mirror of
https://github.com/openai/codex.git
synced 2026-06-02 19:31:59 +00:00
[codex] Update remote connector suggestions (#25172)
## Summary - Use the session-loaded plugin app IDs as the source of connector suggestion candidates. - Remove the redundant plugin reload from `tool_suggest_connector_ids()`. - Add regression coverage for connectors declared by a loaded remote plugin, using the Databricks app case. ## Context Loaded remote plugins can declare app connector IDs in `.app.json`. The session-owned `PluginsManager` already loads those plugins and exposes their effective app IDs. The connector suggestion path was creating a separate `PluginsManager` and recomputing plugin app IDs. That new manager does not share the session manager’s remote installed plugin cache, so app IDs from loaded remote plugins were missing from connector suggestions. ## Fix Pass the already-loaded effective app IDs into connector suggestion generation and use them directly as the plugin-derived connector candidate set. Connector candidates are now built from: - App IDs declared by loaded plugins - Explicitly configured connector discoverables - Existing disabled-suggestion filtering This avoids a second plugin-manager lookup and keeps connector suggestions aligned with the plugins actually loaded for the turn. ## Behavior For example, when a plugin is loaded and its `.app.json` declares data apps, `list_available_plugins_to_install` can now return those data connectors. This does not create plugin suggestions from the plugin itself. Plugin suggestions still come from eligible uninstalled entries in the marketplace catalog and require existing matching/filtering rules. ## Validation - `just fmt` - Added regression coverage for a loaded-plugin connector ID appearing in discoverable tools - Attempted `just test -p codex-core`; the command exited unsuccessfully in the local test environment without useful failure detail captured in the run output
This commit is contained in:
@@ -115,7 +115,7 @@ pub(crate) async fn list_tool_suggest_discoverable_tools_with_auth(
|
||||
accessible_connectors: &[AppInfo],
|
||||
loaded_plugin_app_connector_ids: &[String],
|
||||
) -> anyhow::Result<Vec<DiscoverableTool>> {
|
||||
let connector_ids = tool_suggest_connector_ids(config).await;
|
||||
let connector_ids = tool_suggest_connector_ids(config, loaded_plugin_app_connector_ids);
|
||||
let directory_connectors = codex_connectors::merge::merge_plugin_connectors(
|
||||
cached_directory_connectors_for_tool_suggest_with_auth(config, auth).await,
|
||||
connector_ids.iter().cloned(),
|
||||
@@ -406,15 +406,13 @@ fn write_cached_accessible_connectors(
|
||||
});
|
||||
}
|
||||
|
||||
async fn tool_suggest_connector_ids(config: &Config) -> HashSet<String> {
|
||||
let plugins_input = config.plugins_config_input();
|
||||
let mut connector_ids = PluginsManager::new(config.codex_home.to_path_buf())
|
||||
.plugins_for_config(&plugins_input)
|
||||
.await
|
||||
.capability_summaries()
|
||||
fn tool_suggest_connector_ids(
|
||||
config: &Config,
|
||||
loaded_plugin_app_connector_ids: &[String],
|
||||
) -> HashSet<String> {
|
||||
let mut connector_ids = loaded_plugin_app_connector_ids
|
||||
.iter()
|
||||
.flat_map(|plugin| plugin.app_connector_ids.iter())
|
||||
.map(|connector_id| connector_id.0.clone())
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
connector_ids.extend(
|
||||
config
|
||||
|
||||
@@ -1180,7 +1180,7 @@ discoverables = [
|
||||
.expect("config should load");
|
||||
|
||||
assert_eq!(
|
||||
tool_suggest_connector_ids(&config).await,
|
||||
tool_suggest_connector_ids(&config, &[]),
|
||||
HashSet::from(["connector_2128aebfecb84f64a069897515042a44".to_string()])
|
||||
);
|
||||
}
|
||||
@@ -1209,7 +1209,7 @@ disabled_tools = [
|
||||
.expect("config should load");
|
||||
|
||||
assert_eq!(
|
||||
tool_suggest_connector_ids(&config).await,
|
||||
tool_suggest_connector_ids(&config, &[]),
|
||||
HashSet::from(["connector_gmail".to_string()])
|
||||
);
|
||||
}
|
||||
@@ -1249,3 +1249,39 @@ discoverables = [
|
||||
))]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tool_suggest_includes_connectors_from_loaded_plugin_apps() {
|
||||
let codex_home = tempdir().expect("tempdir should succeed");
|
||||
std::fs::write(
|
||||
codex_home.path().join(CONFIG_TOML_FILE),
|
||||
r#"
|
||||
[features]
|
||||
apps = true
|
||||
"#,
|
||||
)
|
||||
.expect("write config");
|
||||
let config = ConfigBuilder::default()
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await
|
||||
.expect("config should load");
|
||||
let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
|
||||
let loaded_plugin_app_connector_ids = vec!["asdk_app_databricks_workspace".to_string()];
|
||||
|
||||
let discoverable_tools = list_tool_suggest_discoverable_tools_with_auth(
|
||||
&config,
|
||||
Some(&auth),
|
||||
&[],
|
||||
&loaded_plugin_app_connector_ids,
|
||||
)
|
||||
.await
|
||||
.expect("discoverable tools should load");
|
||||
|
||||
assert_eq!(
|
||||
discoverable_tools,
|
||||
vec![DiscoverableTool::from(plugin_connector_to_app_info(
|
||||
"asdk_app_databricks_workspace".to_string(),
|
||||
))]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user