mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] [3/4] Activate endpoint plugin recommendations (#27704)
Summary\n- Await endpoint recommendation selection while constructing each authenticated turn, removing the first-turn cache race.\n- Snapshot and filter endpoint candidates once per turn, then use that same set for the bounded contextual user fragment, tool exposure, and exact install validation.\n- Keep recommendation selection ephemeral: do not persist recommendation state in or gate resumed threads on prior context.\n- Hide the legacy list tool in endpoint mode and preserve legacy discovery unchanged when the endpoint is disabled or unavailable.\n- Keep remote plugin and connector app identities out of model-visible context and attach them only to Codex-owned elicitation metadata.\n\nStack\n- 3/4, based on #28400.\n- Endpoint client and cache: #28399.\n- Generalized suggestion presentation: #28400.\n- Install-schema follow-up: #28403.\n\nValidation\n- \n- \n- \n- \n- Full : 2,649 passed and 88 environment-dependent tests failed because this sandbox cannot write , nest Seatbelt, or locate auxiliary test binaries.
This commit is contained in:
committed by
GitHub
Unverified
parent
587487df9e
commit
a34da3b295
@@ -57,6 +57,8 @@ use codex_config::ConfigLayerStack;
|
||||
use codex_config::clear_user_plugin;
|
||||
use codex_config::set_user_plugin_enabled;
|
||||
use codex_config::types::PluginConfig;
|
||||
use codex_config::types::ToolSuggestDisabledTool;
|
||||
use codex_config::types::ToolSuggestDiscoverableType;
|
||||
use codex_core_skills::SkillMetadata;
|
||||
use codex_core_skills::config_rules::SkillConfigRules;
|
||||
use codex_core_skills::config_rules::skill_config_rules_from_stack;
|
||||
@@ -71,6 +73,9 @@ use codex_plugin::app_connector_ids_from_declarations;
|
||||
use codex_plugin::prompt_safe_plugin_description;
|
||||
use codex_protocol::protocol::HookEventName;
|
||||
use codex_protocol::protocol::Product;
|
||||
use codex_tools::DiscoverablePluginInfo;
|
||||
use codex_tools::DiscoverableTool;
|
||||
use codex_tools::filter_request_plugin_install_discoverable_tools_for_client;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_plugins::PluginSkillRoot;
|
||||
use std::collections::HashMap;
|
||||
@@ -114,6 +119,15 @@ impl PluginsConfigInput {
|
||||
}
|
||||
}
|
||||
|
||||
/// Inputs used to select endpoint-backed plugin install candidates.
|
||||
pub struct RecommendedPluginCandidatesInput<'a> {
|
||||
pub plugins_config: &'a PluginsConfigInput,
|
||||
pub loaded_plugins: &'a PluginLoadOutcome,
|
||||
pub auth: Option<&'a CodexAuth>,
|
||||
pub disabled_tools: &'a [ToolSuggestDisabledTool],
|
||||
pub app_server_client_name: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
struct FeaturedPluginIdsCacheKey {
|
||||
chatgpt_base_url: String,
|
||||
@@ -997,6 +1011,59 @@ impl PluginsManager {
|
||||
mode
|
||||
}
|
||||
|
||||
/// Returns endpoint recommendations eligible for installation in the current client.
|
||||
/// `None` selects the legacy discovery workflow.
|
||||
pub async fn recommended_plugin_candidates_for_config(
|
||||
&self,
|
||||
input: RecommendedPluginCandidatesInput<'_>,
|
||||
) -> Option<Vec<DiscoverableTool>> {
|
||||
let RecommendedPluginsMode::Endpoint { plugins } = self
|
||||
.recommended_plugins_mode_for_config(input.plugins_config, input.auth)
|
||||
.await
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if plugins.is_empty() {
|
||||
return Some(Vec::new());
|
||||
}
|
||||
|
||||
let installed_plugin_ids = input
|
||||
.loaded_plugins
|
||||
.plugins()
|
||||
.iter()
|
||||
.map(|plugin| plugin.config_name.as_str())
|
||||
.collect::<HashSet<_>>();
|
||||
let disabled_plugin_ids = input
|
||||
.disabled_tools
|
||||
.iter()
|
||||
.filter(|tool| tool.kind == ToolSuggestDiscoverableType::Plugin)
|
||||
.map(|tool| tool.id.as_str())
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let candidates = plugins
|
||||
.into_iter()
|
||||
.filter(|plugin| {
|
||||
!installed_plugin_ids.contains(plugin.config_id.as_str())
|
||||
&& !disabled_plugin_ids.contains(plugin.config_id.as_str())
|
||||
})
|
||||
.map(|plugin| {
|
||||
DiscoverableTool::from(DiscoverablePluginInfo {
|
||||
id: plugin.config_id,
|
||||
remote_plugin_id: Some(plugin.remote_plugin_id),
|
||||
name: plugin.display_name,
|
||||
description: None,
|
||||
has_skills: false,
|
||||
mcp_server_names: Vec::new(),
|
||||
app_connector_ids: plugin.app_connector_ids,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Some(filter_request_plugin_install_discoverable_tools_for_client(
|
||||
candidates,
|
||||
input.app_server_client_name,
|
||||
))
|
||||
}
|
||||
|
||||
fn cached_recommended_plugins_mode(
|
||||
&self,
|
||||
cache_key: &RecommendedPluginsCacheKey,
|
||||
|
||||
Reference in New Issue
Block a user