mirror of
https://github.com/openai/codex.git
synced 2026-10-26 07:58:43 +00:00
Unify plugin skill loading with the host skill service (#37444)
## What changed - Inject the host skill loader into `PluginsManager` so plugin discovery and agent turns use the same loading and product-policy behavior. - Share plugin skill snapshots across those paths, preserving a consistent view of skills across workspaces. - Apply migrated-command precedence after product filtering, allowing an eligible migrated command to replace a filtered native skill with the same name. ## Testing - Add coverage for product-restricted plugin skills, native-versus-migrated command precedence, and the skills exposed to agent turns. GitOrigin-RevId: f5ef0d0766ebeeb30d73ffaf044d003c2906ea4d
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use super::*;
|
||||
use crate::HostSkillsService;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::skills_load_input_from_config;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_utils_absolute_path::test_support::PathExt;
|
||||
@@ -398,7 +398,7 @@ enabled = false
|
||||
.await
|
||||
.expect("custom role should apply");
|
||||
|
||||
let plugins_manager = Arc::new(PluginsManager::new(home.path().to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let skills_service =
|
||||
HostSkillsService::new(home.path().abs(), /*bundled_skills_enabled*/ true);
|
||||
let plugins_input = config.plugins_config_input();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::config::edit::ConfigEdit;
|
||||
use crate::config::edit::ConfigEditsBuilder;
|
||||
use crate::config::edit::apply_blocking;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use assert_matches::assert_matches;
|
||||
use codex_config::CONFIG_TOML_FILE;
|
||||
use codex_config::ConfigLayerEntry;
|
||||
@@ -67,7 +68,6 @@ use codex_config::types::TuiNotificationSettings;
|
||||
use codex_config::types::TuiPetAnchor;
|
||||
use codex_config::types::WindowsSandboxModeToml;
|
||||
use codex_config::types::WindowsToml;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_exec_server::LOCAL_FS;
|
||||
use codex_features::Feature;
|
||||
use codex_features::FeaturesToml;
|
||||
@@ -499,7 +499,7 @@ async fn load_config_resolves_non_prefixed_mcp_tool_servers() -> std::io::Result
|
||||
|
||||
assert_eq!(config.non_prefixed_mcp_tool_servers, expected_servers);
|
||||
assert_eq!(config.prefix_mcp_tool_names(), expected_prefix);
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(mcp_config.prefix_mcp_tool_names, expected_prefix);
|
||||
assert_eq!(
|
||||
@@ -5214,7 +5214,7 @@ async fn rebuild_preserving_session_layers_refreshes_plugin_derived_mcp_config()
|
||||
let config = thread_config
|
||||
.rebuild_preserving_session_layers(&refreshed_config)
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
let configured_servers = mcp_config.mcp_server_catalog.configured_servers();
|
||||
|
||||
@@ -5276,7 +5276,7 @@ enabled = true
|
||||
.codex_home(codex_home.path().to_path_buf())
|
||||
.build()
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
let configured_servers = mcp_config.mcp_server_catalog.configured_servers();
|
||||
|
||||
@@ -5344,7 +5344,7 @@ url = "https://sample.example/mcp"
|
||||
)
|
||||
.build()
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
let configured_servers = mcp_config.mcp_server_catalog.configured_servers();
|
||||
|
||||
@@ -5446,7 +5446,7 @@ enabled = true
|
||||
)
|
||||
.build()
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
let configured_servers = mcp_config.mcp_server_catalog.configured_servers();
|
||||
|
||||
@@ -6463,7 +6463,7 @@ async fn to_mcp_config_preserves_apps_feature_from_config() -> std::io::Result<(
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
config.apps_mcp_product_sku = Some("tpp".to_string());
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
@@ -6490,7 +6490,7 @@ async fn to_mcp_config_flows_mcp_tool_prefix_from_feature() -> std::io::Result<(
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert!(mcp_config.prefix_mcp_tool_names);
|
||||
@@ -6526,7 +6526,7 @@ async fn to_mcp_config_flows_mcp_2026_feature_from_config() -> std::io::Result<(
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(mcp_config.protocol_mode, codex_mcp::McpProtocolMode::Legacy);
|
||||
@@ -6550,7 +6550,7 @@ async fn to_mcp_config_preserves_auth_elicitation_feature_from_config() -> std::
|
||||
codex_home.abs(),
|
||||
)
|
||||
.await?;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
let mcp_config = config.to_mcp_config(&plugins_manager).await;
|
||||
assert_eq!(
|
||||
|
||||
@@ -22,6 +22,7 @@ use tracing::warn;
|
||||
use crate::config::Config;
|
||||
use crate::mcp::McpManager;
|
||||
use crate::plugins::list_tool_suggest_discoverable_plugins;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::session::INITIAL_SUBMIT_ID;
|
||||
use codex_config::types::ApprovalsReviewer;
|
||||
use codex_config::types::ToolSuggestDiscoverableType;
|
||||
@@ -186,7 +187,7 @@ pub async fn list_accessible_connectors_from_mcp_tools_with_environment_manager(
|
||||
force_refetch: bool,
|
||||
environment_manager: Arc<EnvironmentManager>,
|
||||
) -> anyhow::Result<AccessibleConnectorsStatus> {
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(config));
|
||||
let mcp_manager = Arc::new(McpManager::new(plugins_manager));
|
||||
list_accessible_connectors_from_mcp_tools_with_mcp_manager(
|
||||
config,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::*;
|
||||
use crate::config::CONFIG_TOML_FILE;
|
||||
use crate::config::ConfigBuilder;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use codex_config::test_support::CloudConfigBundleFixture;
|
||||
use codex_config::types::ApprovalsReviewer;
|
||||
use codex_connectors::merge::plugin_connector_to_app_info;
|
||||
@@ -504,7 +505,7 @@ discoverables = [
|
||||
.await
|
||||
.expect("config should load");
|
||||
let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
|
||||
let plugins_manager = PluginsManager::new(config.codex_home.to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
let discoverable_tools = list_tool_suggest_discoverable_tools_with_auth(
|
||||
&config,
|
||||
@@ -542,7 +543,7 @@ apps = true
|
||||
.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 plugins_manager = PluginsManager::new(config.codex_home.to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
let discoverable_tools = list_tool_suggest_discoverable_tools_with_auth(
|
||||
&config,
|
||||
|
||||
@@ -74,6 +74,7 @@ pub use mention_syntax::PLUGIN_TEXT_MENTION_SIGIL;
|
||||
pub use mention_syntax::TOOL_MENTION_SIGIL;
|
||||
pub use utils::path_utils;
|
||||
pub(crate) mod plugins;
|
||||
pub use plugins::plugins_manager_for_config;
|
||||
#[doc(hidden)]
|
||||
pub(crate) mod prompt_debug;
|
||||
#[doc(hidden)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::plugins::test_support::load_plugins_config;
|
||||
use crate::plugins::test_support::write_file;
|
||||
use crate::plugins::test_support::write_openai_curated_marketplace;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_core_plugins::startup_sync::curated_plugins_repo_path;
|
||||
use codex_tools::DiscoverablePluginInfo;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -11,7 +11,7 @@ async fn list_discoverable_plugins(
|
||||
config: &crate::config::Config,
|
||||
loaded_plugin_app_connector_ids: &[String],
|
||||
) -> anyhow::Result<Vec<DiscoverablePluginInfo>> {
|
||||
let plugins_manager = PluginsManager::new(config.codex_home.to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(config);
|
||||
super::list_tool_suggest_discoverable_plugins(
|
||||
config,
|
||||
&plugins_manager,
|
||||
|
||||
@@ -8,6 +8,11 @@ mod skill_snapshot_tests;
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test_support;
|
||||
|
||||
use crate::config::Config;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_skills_extension::HostSkillsService;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) use codex_plugin::PluginCapabilitySummary;
|
||||
|
||||
pub(crate) use discoverable::list_tool_suggest_discoverable_plugins;
|
||||
@@ -19,3 +24,14 @@ pub(crate) use mentions::build_skill_name_counts;
|
||||
pub(crate) use mentions::collect_explicit_app_ids;
|
||||
pub(crate) use mentions::collect_explicit_plugin_mentions;
|
||||
pub(crate) use mentions::collect_tool_mentions_from_messages;
|
||||
|
||||
/// Constructs a standalone plugin manager with extension-owned plugin skill loading.
|
||||
///
|
||||
/// Callers that already own a host skills service should inject that existing service instead.
|
||||
pub fn plugins_manager_for_config(config: &Config) -> PluginsManager {
|
||||
let skill_root_loader = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
/*bundled_skills_enabled*/ false,
|
||||
));
|
||||
PluginsManager::new(config.codex_home.to_path_buf(), skill_root_loader)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ use codex_protocol::auth::AuthMode;
|
||||
use codex_protocol::protocol::Product;
|
||||
use codex_skills_extension::HostSkillsLoadInput;
|
||||
use codex_skills_extension::HostSkillsService;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::test_support::load_plugins_config;
|
||||
use super::test_support::write_file;
|
||||
@@ -43,44 +45,53 @@ enabled = true
|
||||
.expect("persist remote plugin id");
|
||||
let config = load_plugins_config(codex_home.path()).await;
|
||||
let plugins_input = config.plugins_config_input();
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
/*bundled_skills_enabled*/ false,
|
||||
));
|
||||
let plugins_manager = PluginsManager::new_with_options(
|
||||
codex_home.path().to_path_buf(),
|
||||
Some(Product::Codex),
|
||||
Some(AuthMode::Chatgpt),
|
||||
skills_service.clone(),
|
||||
);
|
||||
let plugin_outcome = plugins_manager.plugins_for_config(&plugins_input).await;
|
||||
|
||||
write_file(&skill_path, "---\nname: search\ndescription: second\n---\n");
|
||||
|
||||
let skills_input = HostSkillsLoadInput::new(
|
||||
config.cwd.clone(),
|
||||
plugin_outcome.effective_plugin_skill_roots(),
|
||||
config.config_layer_stack.clone(),
|
||||
/*bundled_skills_enabled*/ false,
|
||||
)
|
||||
.with_plugin_skill_snapshots(plugins_manager.plugin_skill_snapshots_for_config(&plugins_input));
|
||||
let skills_service = HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
/*bundled_skills_enabled*/ false,
|
||||
);
|
||||
let snapshot = skills_service
|
||||
.snapshot_for_config(&skills_input, /*fs*/ None)
|
||||
.await;
|
||||
let other_cwd = codex_home.path().join("other-workspace");
|
||||
std::fs::create_dir_all(&other_cwd).expect("create second workspace");
|
||||
let other_cwd = AbsolutePathBuf::from_absolute_path(other_cwd).expect("absolute workspace");
|
||||
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.outcome()
|
||||
.skills
|
||||
.iter()
|
||||
.filter(|skill| skill.plugin_id.as_deref() == Some(PLUGIN_CONFIG_NAME))
|
||||
.map(|skill| {
|
||||
(
|
||||
skill.description.as_str(),
|
||||
skill.plugin_id.as_deref(),
|
||||
skill.remote_plugin_id.as_deref(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
vec![("first", Some(PLUGIN_CONFIG_NAME), Some(REMOTE_PLUGIN_ID),)]
|
||||
);
|
||||
for cwd in [config.cwd.clone(), other_cwd] {
|
||||
let skills_input = HostSkillsLoadInput::new(
|
||||
cwd,
|
||||
plugin_outcome.effective_plugin_skill_roots(),
|
||||
config.config_layer_stack.clone(),
|
||||
/*bundled_skills_enabled*/ false,
|
||||
)
|
||||
.with_plugin_skill_snapshots(
|
||||
plugins_manager.plugin_skill_snapshots_for_config(&plugins_input),
|
||||
);
|
||||
let snapshot = skills_service
|
||||
.snapshot_for_config(&skills_input, /*fs*/ None)
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.outcome()
|
||||
.skills
|
||||
.iter()
|
||||
.filter(|skill| skill.plugin_id.as_deref() == Some(PLUGIN_CONFIG_NAME))
|
||||
.map(|skill| {
|
||||
(
|
||||
skill.description.as_str(),
|
||||
skill.plugin_id.as_deref(),
|
||||
skill.remote_plugin_id.as_deref(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
vec![("first", Some(PLUGIN_CONFIG_NAME), Some(REMOTE_PLUGIN_ID),)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::context::TurnAborted;
|
||||
use crate::environment_selection::ThreadEnvironments;
|
||||
use crate::environment_selection::TurnEnvironmentState;
|
||||
use crate::function_tool::FunctionCallError;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::shell::default_user_shell;
|
||||
use crate::shell_snapshot::ShellSnapshot;
|
||||
@@ -5567,7 +5568,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_packaged_zsh() {
|
||||
|
||||
let (tx_event, _rx_event) = async_channel::unbounded();
|
||||
let (agent_status_tx, _agent_status_rx) = watch::channel(AgentStatus::PendingInit);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
@@ -5736,7 +5737,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
.expect("primary environment")
|
||||
.environment,
|
||||
);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
@@ -5982,7 +5983,7 @@ async fn make_session_with_config_and_rx(
|
||||
|
||||
let (tx_event, rx_event) = async_channel::unbounded();
|
||||
let (agent_status_tx, _agent_status_rx) = watch::channel(AgentStatus::PendingInit);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
@@ -6096,7 +6097,7 @@ async fn make_session_with_history_source_and_agent_control_and_rx(
|
||||
|
||||
let (tx_event, rx_event) = async_channel::unbounded();
|
||||
let (agent_status_tx, _agent_status_rx) = watch::channel(AgentStatus::PendingInit);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
@@ -7955,7 +7956,7 @@ where
|
||||
.expect("primary environment")
|
||||
.environment,
|
||||
);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
|
||||
@@ -2,6 +2,7 @@ use super::*;
|
||||
use crate::compact::InitialContextInjection;
|
||||
use crate::exec_policy::ExecPolicyManager;
|
||||
use crate::guardian::GUARDIAN_REVIEWER_NAME;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use crate::session::step_context::StepContext;
|
||||
use crate::test_support::models_manager_with_provider;
|
||||
@@ -738,7 +739,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
|
||||
auth_manager.clone(),
|
||||
config.model_provider.clone(),
|
||||
);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.to_path_buf()));
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(&config));
|
||||
let skills_service = Arc::new(HostSkillsService::new(
|
||||
config.codex_home.clone(),
|
||||
/*bundled_skills_enabled*/ true,
|
||||
|
||||
@@ -416,21 +416,22 @@ impl ThreadManager {
|
||||
let codex_home = config.codex_home.clone();
|
||||
let restriction_product = session_source.restriction_product();
|
||||
let (thread_created_tx, _) = broadcast::channel(THREAD_CREATED_CHANNEL_CAPACITY);
|
||||
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
|
||||
codex_home.clone(),
|
||||
config.bundled_skills_enabled(),
|
||||
restriction_product,
|
||||
));
|
||||
let plugins_manager = Arc::new(PluginsManager::new_with_options(
|
||||
codex_home.to_path_buf(),
|
||||
restriction_product,
|
||||
auth_manager.get_api_auth_mode(),
|
||||
skills_service.clone(),
|
||||
));
|
||||
let mcp_manager = Arc::new(McpManager::new_with_extensions(
|
||||
Arc::clone(&plugins_manager),
|
||||
Arc::clone(&extensions),
|
||||
codex_apps_tools_cache,
|
||||
));
|
||||
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
|
||||
codex_home,
|
||||
config.bundled_skills_enabled(),
|
||||
restriction_product,
|
||||
));
|
||||
let code_mode_session_provider: Arc<dyn CodeModeSessionProvider> =
|
||||
if config.features.enabled(Feature::CodeModeHost)
|
||||
|| config.code_mode.disable_in_process_fallback
|
||||
@@ -562,17 +563,18 @@ impl ThreadManager {
|
||||
};
|
||||
let (thread_created_tx, _) = broadcast::channel(THREAD_CREATED_CHANNEL_CAPACITY);
|
||||
let restriction_product = SessionSource::Exec.restriction_product();
|
||||
let plugins_manager = Arc::new(PluginsManager::new_with_options(
|
||||
codex_home.clone(),
|
||||
restriction_product,
|
||||
auth_manager.get_api_auth_mode(),
|
||||
));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
|
||||
absolute_codex_home.clone(),
|
||||
/*bundled_skills_enabled*/ true,
|
||||
restriction_product,
|
||||
));
|
||||
let plugins_manager = Arc::new(PluginsManager::new_with_options(
|
||||
codex_home.clone(),
|
||||
restriction_product,
|
||||
auth_manager.get_api_auth_mode(),
|
||||
skills_service.clone(),
|
||||
));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
// This test constructor has no Config input. Tests that need a non-local
|
||||
// process store should construct ThreadManager::new with an explicit store.
|
||||
let thread_store: Arc<dyn ThreadStore> = Arc::new(LocalThreadStore::new(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use crate::plugins::plugins_manager_for_config;
|
||||
use crate::plugins::test_support::load_plugins_config;
|
||||
use crate::plugins::test_support::write_curated_plugin_sha;
|
||||
use crate::plugins::test_support::write_openai_curated_marketplace;
|
||||
@@ -10,7 +11,6 @@ use codex_config::types::ToolSuggestDisabledTool;
|
||||
use codex_config::types::ToolSuggestDiscoverable;
|
||||
use codex_config::types::ToolSuggestDiscoverableType;
|
||||
use codex_core_plugins::PluginInstallRequest;
|
||||
use codex_core_plugins::PluginsManager;
|
||||
use codex_core_plugins::startup_sync::curated_plugins_repo_path;
|
||||
use codex_rmcp_client::ElicitationResponse;
|
||||
use codex_tools::DiscoverablePluginInfo;
|
||||
@@ -40,7 +40,7 @@ async fn verified_plugin_install_completed_requires_installed_plugin() {
|
||||
write_plugins_feature_config(codex_home.path());
|
||||
|
||||
let config = load_plugins_config(codex_home.path()).await;
|
||||
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
|
||||
let plugins_manager = plugins_manager_for_config(&config);
|
||||
|
||||
assert!(!verified_plugin_install_completed(
|
||||
"sample@openai-curated",
|
||||
|
||||
Reference in New Issue
Block a user