mirror of
https://github.com/openai/codex.git
synced 2026-11-13 21:30:47 +00:00
fix
This commit is contained in:
@@ -202,6 +202,8 @@ use codex_core::config::types::McpServerTransportConfig;
|
||||
use codex_core::config_loader::CloudRequirementsLoadError;
|
||||
use codex_core::config_loader::CloudRequirementsLoadErrorCode;
|
||||
use codex_core::config_loader::CloudRequirementsLoader;
|
||||
use codex_core::config_loader::LoaderOverrides;
|
||||
use codex_core::config_loader::load_config_layers_state;
|
||||
use codex_core::default_client::set_default_client_residency_requirement;
|
||||
use codex_core::error::CodexErr;
|
||||
use codex_core::error::Result as CodexResult;
|
||||
@@ -281,6 +283,7 @@ use codex_state::StateRuntime;
|
||||
use codex_state::ThreadMetadata;
|
||||
use codex_state::ThreadMetadataBuilder;
|
||||
use codex_state::log_db::LogDbLayer;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_json_to_toml::json_to_toml;
|
||||
use codex_utils_pty::DEFAULT_OUTPUT_BYTES_CAP;
|
||||
use std::collections::HashMap;
|
||||
@@ -5479,15 +5482,31 @@ impl CodexMessageProcessor {
|
||||
}
|
||||
};
|
||||
let skills_manager = self.thread_manager.skills_manager();
|
||||
let plugins_manager = self.thread_manager.plugins_manager();
|
||||
let cli_overrides = self.cli_overrides.as_slice();
|
||||
let mut data = Vec::new();
|
||||
for cwd in cwds {
|
||||
let extra_roots = extra_roots_by_cwd
|
||||
.get(&cwd)
|
||||
.map_or(&[][..], std::vec::Vec::as_slice);
|
||||
let cwd_abs = match AbsolutePathBuf::try_from(cwd.as_path()) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
data.push(codex_app_server_protocol::SkillsListEntry {
|
||||
cwd,
|
||||
skills: Vec::new(),
|
||||
errors: errors_to_info(&[codex_core::skills::SkillError {
|
||||
path: cwd.clone(),
|
||||
message: err.to_string(),
|
||||
}]),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let config_layer_stack = match load_config_layers_state(
|
||||
&self.codex_home,
|
||||
Some(cwd_abs),
|
||||
&cli_overrides,
|
||||
cli_overrides,
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
)
|
||||
@@ -5495,16 +5514,21 @@ impl CodexMessageProcessor {
|
||||
{
|
||||
Ok(config_layer_stack) => config_layer_stack,
|
||||
Err(err) => {
|
||||
return SkillLoadOutcome {
|
||||
errors: vec![crate::skills::model::SkillError {
|
||||
path: cwd.to_path_buf(),
|
||||
data.push(codex_app_server_protocol::SkillsListEntry {
|
||||
cwd,
|
||||
skills: Vec::new(),
|
||||
errors: errors_to_info(&[codex_core::skills::SkillError {
|
||||
path: cwd.clone(),
|
||||
message: err.to_string(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
}]),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let effective_skill_roots = skills_manager.effective_skill_roots(&config_layer_stack);
|
||||
let effective_skill_roots = plugins_manager.effective_skill_roots_for_layer_stack(
|
||||
&config_layer_stack,
|
||||
config.features.enabled(Feature::Plugins),
|
||||
);
|
||||
let outcome = skills_manager
|
||||
.skills_for_cwd_with_extra_user_roots(
|
||||
&cwd,
|
||||
|
||||
@@ -12,23 +12,23 @@ use tracing::warn;
|
||||
use crate::skills::SkillMetadata;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub(crate) enum SkillConfigRuleSelector {
|
||||
pub enum SkillConfigRuleSelector {
|
||||
Name(String),
|
||||
Path(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct SkillConfigRule {
|
||||
pub struct SkillConfigRule {
|
||||
pub selector: SkillConfigRuleSelector,
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct SkillConfigRules {
|
||||
pub struct SkillConfigRules {
|
||||
pub entries: Vec<SkillConfigRule>,
|
||||
}
|
||||
|
||||
pub(crate) fn skill_config_rules_from_stack(
|
||||
pub fn skill_config_rules_from_stack(
|
||||
config_layer_stack: &ConfigLayerStack,
|
||||
) -> SkillConfigRules {
|
||||
let mut entries = Vec::new();
|
||||
@@ -71,7 +71,7 @@ pub(crate) fn skill_config_rules_from_stack(
|
||||
SkillConfigRules { entries }
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_disabled_skill_paths(
|
||||
pub fn resolve_disabled_skill_paths(
|
||||
skills: &[SkillMetadata],
|
||||
rules: &SkillConfigRules,
|
||||
) -> HashSet<PathBuf> {
|
||||
|
||||
@@ -16,12 +16,12 @@ use codex_protocol::user_input::UserInput;
|
||||
use tokio::fs;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct SkillInjections {
|
||||
pub(crate) items: Vec<ResponseItem>,
|
||||
pub(crate) warnings: Vec<String>,
|
||||
pub struct SkillInjections {
|
||||
pub items: Vec<ResponseItem>,
|
||||
pub warnings: Vec<String>,
|
||||
}
|
||||
|
||||
pub(crate) async fn build_skill_injections(
|
||||
pub async fn build_skill_injections(
|
||||
mentioned_skills: &[SkillMetadata],
|
||||
otel: Option<&SessionTelemetry>,
|
||||
analytics_client: &AnalyticsEventsClient,
|
||||
@@ -97,7 +97,7 @@ fn emit_skill_injected_metric(
|
||||
/// Complexity: `O(T + (N_s + N_t) * S)` time, `O(S + M)` space, where:
|
||||
/// `S` = number of skills, `T` = total text length, `N_s` = number of structured skill inputs,
|
||||
/// `N_t` = number of text inputs, `M` = max mentions parsed from a single text input.
|
||||
pub(crate) fn collect_explicit_skill_mentions(
|
||||
pub fn collect_explicit_skill_mentions(
|
||||
inputs: &[UserInput],
|
||||
skills: &[SkillMetadata],
|
||||
disabled_paths: &HashSet<PathBuf>,
|
||||
@@ -159,7 +159,7 @@ struct SkillSelectionContext<'a> {
|
||||
connector_slug_counts: &'a HashMap<String, usize>,
|
||||
}
|
||||
|
||||
pub(crate) struct ToolMentions<'a> {
|
||||
pub struct ToolMentions<'a> {
|
||||
names: HashSet<&'a str>,
|
||||
paths: HashSet<&'a str>,
|
||||
plain_names: HashSet<&'a str>,
|
||||
@@ -170,17 +170,17 @@ impl<'a> ToolMentions<'a> {
|
||||
self.names.is_empty() && self.paths.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn plain_names(&self) -> impl Iterator<Item = &'a str> + '_ {
|
||||
pub fn plain_names(&self) -> impl Iterator<Item = &'a str> + '_ {
|
||||
self.plain_names.iter().copied()
|
||||
}
|
||||
|
||||
pub(crate) fn paths(&self) -> impl Iterator<Item = &'a str> + '_ {
|
||||
pub fn paths(&self) -> impl Iterator<Item = &'a str> + '_ {
|
||||
self.paths.iter().copied()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum ToolMentionKind {
|
||||
pub enum ToolMentionKind {
|
||||
App,
|
||||
Mcp,
|
||||
Plugin,
|
||||
@@ -194,7 +194,7 @@ const PLUGIN_PATH_PREFIX: &str = "plugin://";
|
||||
const SKILL_PATH_PREFIX: &str = "skill://";
|
||||
const SKILL_FILENAME: &str = "SKILL.md";
|
||||
|
||||
pub(crate) fn tool_kind_for_path(path: &str) -> ToolMentionKind {
|
||||
pub fn tool_kind_for_path(path: &str) -> ToolMentionKind {
|
||||
if path.starts_with(APP_PATH_PREFIX) {
|
||||
ToolMentionKind::App
|
||||
} else if path.starts_with(MCP_PATH_PREFIX) {
|
||||
@@ -213,12 +213,12 @@ fn is_skill_filename(path: &str) -> bool {
|
||||
file_name.eq_ignore_ascii_case(SKILL_FILENAME)
|
||||
}
|
||||
|
||||
pub(crate) fn app_id_from_path(path: &str) -> Option<&str> {
|
||||
pub fn app_id_from_path(path: &str) -> Option<&str> {
|
||||
path.strip_prefix(APP_PATH_PREFIX)
|
||||
.filter(|value| !value.is_empty())
|
||||
}
|
||||
|
||||
pub(crate) fn plugin_config_name_from_path(path: &str) -> Option<&str> {
|
||||
pub fn plugin_config_name_from_path(path: &str) -> Option<&str> {
|
||||
path.strip_prefix(PLUGIN_PATH_PREFIX)
|
||||
.filter(|value| !value.is_empty())
|
||||
}
|
||||
@@ -232,11 +232,11 @@ pub(crate) fn normalize_skill_path(path: &str) -> &str {
|
||||
/// Supports explicit resource links in the form `[$tool-name](resource path)`. When a
|
||||
/// resource path is present, it is captured for exact path matching while also tracking
|
||||
/// the name for fallback matching.
|
||||
pub(crate) fn extract_tool_mentions(text: &str) -> ToolMentions<'_> {
|
||||
pub fn extract_tool_mentions(text: &str) -> ToolMentions<'_> {
|
||||
extract_tool_mentions_with_sigil(text, TOOL_MENTION_SIGIL)
|
||||
}
|
||||
|
||||
pub(crate) fn extract_tool_mentions_with_sigil(text: &str, sigil: char) -> ToolMentions<'_> {
|
||||
pub fn extract_tool_mentions_with_sigil(text: &str, sigil: char) -> ToolMentions<'_> {
|
||||
let text_bytes = text.as_bytes();
|
||||
let mut mentioned_names: HashSet<&str> = HashSet::new();
|
||||
let mut mentioned_paths: HashSet<&str> = HashSet::new();
|
||||
|
||||
@@ -173,12 +173,12 @@ impl fmt::Display for SkillParseError {
|
||||
|
||||
impl Error for SkillParseError {}
|
||||
|
||||
pub(crate) struct SkillRoot {
|
||||
pub(crate) path: PathBuf,
|
||||
pub(crate) scope: SkillScope,
|
||||
pub struct SkillRoot {
|
||||
pub path: PathBuf,
|
||||
pub scope: SkillScope,
|
||||
}
|
||||
|
||||
pub(crate) fn load_skills_from_roots<I>(roots: I) -> SkillLoadOutcome
|
||||
pub fn load_skills_from_roots<I>(roots: I) -> SkillLoadOutcome
|
||||
where
|
||||
I: IntoIterator<Item = SkillRoot>,
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ impl SkillsManager {
|
||||
outcome
|
||||
}
|
||||
|
||||
pub(crate) fn skill_roots_for_config(
|
||||
pub fn skill_roots_for_config(
|
||||
&self,
|
||||
cwd: &Path,
|
||||
effective_skill_roots: &[PathBuf],
|
||||
@@ -221,7 +221,7 @@ struct ConfigSkillsCacheKey {
|
||||
skill_config_rules: SkillConfigRules,
|
||||
}
|
||||
|
||||
pub(crate) fn bundled_skills_enabled_from_stack(
|
||||
pub fn bundled_skills_enabled_from_stack(
|
||||
config_layer_stack: &codex_config::ConfigLayerStack,
|
||||
) -> bool {
|
||||
let effective_config = config_layer_stack.effective_config();
|
||||
|
||||
@@ -629,8 +629,15 @@ enabled = false
|
||||
.expect("custom role should apply");
|
||||
|
||||
let plugins_manager = Arc::new(PluginsManager::new(home.path().to_path_buf()));
|
||||
let skills_manager = SkillsManager::new(home.path().to_path_buf(), plugins_manager, true);
|
||||
let outcome = skills_manager.skills_for_config(&config);
|
||||
let skills_manager = SkillsManager::new(home.path().to_path_buf(), true);
|
||||
let plugin_outcome = plugins_manager.plugins_for_config(&config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let outcome = skills_manager.skills_for_config(
|
||||
config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&config.config_layer_stack,
|
||||
config.bundled_skills_enabled(),
|
||||
);
|
||||
let skill = outcome
|
||||
.skills
|
||||
.iter()
|
||||
|
||||
+61
-12
@@ -471,7 +471,14 @@ impl Codex {
|
||||
let (tx_sub, rx_sub) = async_channel::bounded(SUBMISSION_CHANNEL_CAPACITY);
|
||||
let (tx_event, rx_event) = async_channel::unbounded();
|
||||
|
||||
let loaded_skills = skills_manager.skills_for_config(&config);
|
||||
let plugin_outcome = plugins_manager.plugins_for_config(&config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let loaded_skills = skills_manager.skills_for_config(
|
||||
config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&config.config_layer_stack,
|
||||
config.bundled_skills_enabled(),
|
||||
);
|
||||
|
||||
for err in &loaded_skills.errors {
|
||||
error!(
|
||||
@@ -2440,10 +2447,20 @@ impl Session {
|
||||
&per_turn_config,
|
||||
)
|
||||
.await;
|
||||
let plugin_outcome = self
|
||||
.services
|
||||
.plugins_manager
|
||||
.plugins_for_config(&per_turn_config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let skills_outcome = Arc::new(
|
||||
self.services
|
||||
.skills_manager
|
||||
.skills_for_config(&per_turn_config),
|
||||
.skills_for_config(
|
||||
per_turn_config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&per_turn_config.config_layer_stack,
|
||||
per_turn_config.bundled_skills_enabled(),
|
||||
),
|
||||
);
|
||||
let mut turn_context: TurnContext = Self::make_turn_context(
|
||||
self.conversation_id,
|
||||
@@ -4500,6 +4517,12 @@ mod handlers {
|
||||
|
||||
use crate::codex::spawn_review_thread;
|
||||
use crate::config::Config;
|
||||
use crate::config_loader::CloudRequirementsLoader;
|
||||
use crate::config_loader::LoaderOverrides;
|
||||
use crate::config_loader::load_config_layers_state;
|
||||
use crate::skills::SkillError;
|
||||
use codex_features::Feature;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
|
||||
use crate::mcp::auth::compute_auth_statuses;
|
||||
use crate::mcp::collect_mcp_snapshot_from_manager;
|
||||
@@ -4935,13 +4958,32 @@ mod handlers {
|
||||
};
|
||||
|
||||
let skills_manager = &sess.services.skills_manager;
|
||||
let plugins_manager = &sess.services.plugins_manager;
|
||||
let config = sess.get_config().await;
|
||||
let codex_home = sess.codex_home().await;
|
||||
let mut skills = Vec::new();
|
||||
let empty_cli_overrides: &[(String, toml::Value)] = &[];
|
||||
for cwd in cwds {
|
||||
let cwd_abs = match AbsolutePathBuf::try_from(cwd.as_path()) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
let message = err.to_string();
|
||||
let cwd_for_entry = cwd.clone();
|
||||
skills.push(SkillsListEntry {
|
||||
cwd: cwd_for_entry.clone(),
|
||||
skills: Vec::new(),
|
||||
errors: super::errors_to_info(&[SkillError {
|
||||
path: cwd_for_entry,
|
||||
message,
|
||||
}]),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let config_layer_stack = match load_config_layers_state(
|
||||
&self.codex_home,
|
||||
&codex_home,
|
||||
Some(cwd_abs),
|
||||
&cli_overrides,
|
||||
empty_cli_overrides,
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
)
|
||||
@@ -4949,16 +4991,23 @@ mod handlers {
|
||||
{
|
||||
Ok(config_layer_stack) => config_layer_stack,
|
||||
Err(err) => {
|
||||
return SkillLoadOutcome {
|
||||
errors: vec![crate::skills::model::SkillError {
|
||||
path: cwd.to_path_buf(),
|
||||
message: err.to_string(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
let message = err.to_string();
|
||||
let cwd_for_entry = cwd.clone();
|
||||
skills.push(SkillsListEntry {
|
||||
cwd: cwd_for_entry.clone(),
|
||||
skills: Vec::new(),
|
||||
errors: super::errors_to_info(&[SkillError {
|
||||
path: cwd_for_entry,
|
||||
message,
|
||||
}]),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let effective_skill_roots = skills_manager.effective_skill_roots(&config_layer_stack);
|
||||
let effective_skill_roots = plugins_manager.effective_skill_roots_for_layer_stack(
|
||||
&config_layer_stack,
|
||||
config.features.enabled(Feature::Plugins),
|
||||
);
|
||||
let outcome = skills_manager
|
||||
.skills_for_cwd(
|
||||
&cwd,
|
||||
|
||||
@@ -2506,11 +2506,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() {
|
||||
let (agent_status_tx, _agent_status_rx) = watch::channel(AgentStatus::PendingInit);
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone()));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_manager = Arc::new(SkillsManager::new(
|
||||
config.codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
true,
|
||||
));
|
||||
let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true));
|
||||
let result = Session::new(
|
||||
session_configuration,
|
||||
Arc::clone(&config),
|
||||
@@ -2611,11 +2607,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
let state = SessionState::new(session_configuration.clone());
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone()));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_manager = Arc::new(SkillsManager::new(
|
||||
config.codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
true,
|
||||
));
|
||||
let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true));
|
||||
let network_approval = Arc::new(NetworkApprovalService::default());
|
||||
let environment = Arc::new(
|
||||
codex_exec_server::Environment::create(None)
|
||||
@@ -2683,7 +2675,14 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
|
||||
config.js_repl_node_module_dirs.clone(),
|
||||
));
|
||||
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(&per_turn_config));
|
||||
let plugin_outcome = services.plugins_manager.plugins_for_config(&per_turn_config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(
|
||||
per_turn_config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&per_turn_config.config_layer_stack,
|
||||
per_turn_config.bundled_skills_enabled(),
|
||||
));
|
||||
let turn_context = Session::make_turn_context(
|
||||
conversation_id,
|
||||
Some(Arc::clone(&auth_manager)),
|
||||
@@ -3447,11 +3446,7 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx(
|
||||
let state = SessionState::new(session_configuration.clone());
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone()));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_manager = Arc::new(SkillsManager::new(
|
||||
config.codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
true,
|
||||
));
|
||||
let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true));
|
||||
let network_approval = Arc::new(NetworkApprovalService::default());
|
||||
let environment = Arc::new(
|
||||
codex_exec_server::Environment::create(None)
|
||||
@@ -3519,7 +3514,14 @@ pub(crate) async fn make_session_and_context_with_dynamic_tools_and_rx(
|
||||
config.js_repl_node_module_dirs.clone(),
|
||||
));
|
||||
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(&per_turn_config));
|
||||
let plugin_outcome = services.plugins_manager.plugins_for_config(&per_turn_config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let skills_outcome = Arc::new(services.skills_manager.skills_for_config(
|
||||
per_turn_config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&per_turn_config.config_layer_stack,
|
||||
per_turn_config.bundled_skills_enabled(),
|
||||
));
|
||||
let turn_context = Arc::new(Session::make_turn_context(
|
||||
conversation_id,
|
||||
Some(Arc::clone(&auth_manager)),
|
||||
|
||||
@@ -429,11 +429,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {
|
||||
CollaborationModesConfig::default(),
|
||||
));
|
||||
let plugins_manager = Arc::new(PluginsManager::new(config.codex_home.clone()));
|
||||
let skills_manager = Arc::new(SkillsManager::new(
|
||||
config.codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
true,
|
||||
));
|
||||
let skills_manager = Arc::new(SkillsManager::new(config.codex_home.clone(), true));
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_watcher = Arc::new(SkillsWatcher::noop());
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ use codex_instructions::SKILL_FRAGMENT;
|
||||
use codex_protocol::items::HookPromptItem;
|
||||
use codex_protocol::items::parse_hook_prompt_fragment;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::protocol::ENVIRONMENT_CONTEXT_CLOSE_TAG;
|
||||
use codex_protocol::protocol::ENVIRONMENT_CONTEXT_OPEN_TAG;
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
pub(crate) use codex_instructions::SkillInstructions;
|
||||
pub use codex_instructions::USER_INSTRUCTIONS_PREFIX;
|
||||
pub(crate) use codex_instructions::UserInstructions;
|
||||
|
||||
@@ -68,12 +68,11 @@ pub use utils::path_utils;
|
||||
pub mod personality_migration;
|
||||
pub mod plugins;
|
||||
pub(crate) mod mentions {
|
||||
pub use crate::plugins::CollectedToolMentions;
|
||||
pub use crate::plugins::build_connector_slug_counts;
|
||||
pub use crate::plugins::build_skill_name_counts;
|
||||
pub use crate::plugins::collect_explicit_app_ids;
|
||||
pub use crate::plugins::collect_explicit_plugin_mentions;
|
||||
pub use crate::plugins::collect_tool_mentions_from_messages;
|
||||
pub(crate) use crate::plugins::build_connector_slug_counts;
|
||||
pub(crate) use crate::plugins::build_skill_name_counts;
|
||||
pub(crate) use crate::plugins::collect_explicit_app_ids;
|
||||
pub(crate) use crate::plugins::collect_explicit_plugin_mentions;
|
||||
pub(crate) use crate::plugins::collect_tool_mentions_from_messages;
|
||||
}
|
||||
mod sandbox_tags;
|
||||
pub mod sandboxing;
|
||||
|
||||
@@ -405,6 +405,23 @@ impl PluginsManager {
|
||||
*cached_enabled_outcome = None;
|
||||
}
|
||||
|
||||
/// Resolve plugin skill roots for a config layer stack without touching the plugins cache.
|
||||
pub fn effective_skill_roots_for_layer_stack(
|
||||
&self,
|
||||
config_layer_stack: &ConfigLayerStack,
|
||||
plugins_feature_enabled: bool,
|
||||
) -> Vec<PathBuf> {
|
||||
if !plugins_feature_enabled {
|
||||
return Vec::new();
|
||||
}
|
||||
load_plugins_from_layer_stack(
|
||||
config_layer_stack,
|
||||
&self.store,
|
||||
self.restriction_product,
|
||||
)
|
||||
.effective_skill_roots()
|
||||
}
|
||||
|
||||
fn cached_enabled_outcome(&self) -> Option<PluginLoadOutcome> {
|
||||
match self.cached_enabled_outcome.read() {
|
||||
Ok(cache) => cache.clone(),
|
||||
@@ -1171,7 +1188,7 @@ impl PluginUninstallError {
|
||||
|
||||
fn log_plugin_load_errors(outcome: &PluginLoadOutcome) {
|
||||
for plugin in outcome
|
||||
.plugins
|
||||
.plugins()
|
||||
.iter()
|
||||
.filter(|plugin| plugin.error.is_some())
|
||||
{
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_protocol::user_input::UserInput;
|
||||
|
||||
use crate::connectors;
|
||||
use crate::mention_syntax::PLUGIN_TEXT_MENTION_SIGIL;
|
||||
use crate::mention_syntax::TOOL_MENTION_SIGIL;
|
||||
use crate::skills::SkillMetadata;
|
||||
use crate::skills::injection::ToolMentionKind;
|
||||
use crate::skills::injection::app_id_from_path;
|
||||
use crate::skills::injection::extract_tool_mentions_with_sigil;
|
||||
|
||||
@@ -62,7 +62,6 @@ pub(crate) use startup_sync::read_curated_plugins_sha;
|
||||
pub(crate) use startup_sync::sync_openai_plugins_repo;
|
||||
pub use toggles::collect_plugin_enabled_candidates;
|
||||
|
||||
pub(crate) use mentions::CollectedToolMentions;
|
||||
pub(crate) use mentions::build_connector_slug_counts;
|
||||
pub(crate) use mentions::build_skill_name_counts;
|
||||
pub(crate) use mentions::collect_explicit_app_ids;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use super::load_plugin_manifest;
|
||||
use codex_plugin::PLUGIN_MANIFEST_PATH;
|
||||
use codex_plugin::PluginId;
|
||||
use codex_plugin::PluginIdError;
|
||||
use codex_plugin::validate_plugin_segment;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use std::fs;
|
||||
|
||||
@@ -27,6 +27,9 @@ pub use codex_core_skills::skills::config_rules;
|
||||
pub use codex_core_skills::skills::detect_implicit_skill_invocation_for_command;
|
||||
pub use codex_core_skills::skills::filter_skill_load_outcome_for_product;
|
||||
pub use codex_core_skills::skills::injection;
|
||||
pub use codex_core_skills::skills::injection::SkillInjections;
|
||||
pub use codex_core_skills::skills::injection::build_skill_injections;
|
||||
pub use codex_core_skills::skills::injection::collect_explicit_skill_mentions;
|
||||
pub use codex_core_skills::skills::loader;
|
||||
pub use codex_core_skills::skills::manager;
|
||||
pub use codex_core_skills::skills::model;
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::file_watcher::Receiver;
|
||||
use crate::file_watcher::ThrottledWatchReceiver;
|
||||
use crate::file_watcher::WatchPath;
|
||||
use crate::file_watcher::WatchRegistration;
|
||||
use crate::plugins::PluginsManager;
|
||||
use crate::skills::SkillsManager;
|
||||
|
||||
#[cfg(not(test))]
|
||||
@@ -56,9 +57,17 @@ impl SkillsWatcher {
|
||||
&self,
|
||||
config: &Config,
|
||||
skills_manager: &SkillsManager,
|
||||
plugins_manager: &PluginsManager,
|
||||
) -> WatchRegistration {
|
||||
let plugin_outcome = plugins_manager.plugins_for_config(config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let roots = skills_manager
|
||||
.skill_roots_for_config(config)
|
||||
.skill_roots_for_config(
|
||||
config.cwd.as_path(),
|
||||
&effective_skill_roots,
|
||||
&config.config_layer_stack,
|
||||
config.bundled_skills_enabled(),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|root| WatchPath {
|
||||
path: root.path,
|
||||
|
||||
@@ -231,7 +231,6 @@ impl ThreadManager {
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_manager = Arc::new(SkillsManager::new_with_restriction_product(
|
||||
codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
config.bundled_skills_enabled(),
|
||||
restriction_product,
|
||||
));
|
||||
@@ -297,7 +296,6 @@ impl ThreadManager {
|
||||
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
|
||||
let skills_manager = Arc::new(SkillsManager::new_with_restriction_product(
|
||||
codex_home.clone(),
|
||||
Arc::clone(&plugins_manager),
|
||||
/*bundled_skills_enabled*/ true,
|
||||
restriction_product,
|
||||
));
|
||||
@@ -835,9 +833,11 @@ impl ThreadManagerState {
|
||||
parent_trace: Option<W3cTraceContext>,
|
||||
user_shell_override: Option<crate::shell::Shell>,
|
||||
) -> CodexResult<NewThread> {
|
||||
let watch_registration = self
|
||||
.skills_watcher
|
||||
.register_config(&config, self.skills_manager.as_ref());
|
||||
let watch_registration = self.skills_watcher.register_config(
|
||||
&config,
|
||||
self.skills_manager.as_ref(),
|
||||
self.plugins_manager.as_ref(),
|
||||
);
|
||||
let CodexSpawnOk {
|
||||
codex, thread_id, ..
|
||||
} = Codex::spawn(CodexSpawnArgs {
|
||||
|
||||
@@ -486,27 +486,13 @@ impl CoreShellActionProvider {
|
||||
/// any skills.
|
||||
async fn find_skill(&self, program: &AbsolutePathBuf) -> Option<SkillMetadata> {
|
||||
let force_reload = false;
|
||||
let config_layer_stack = match load_config_layers_state(
|
||||
&self.codex_home,
|
||||
Some(cwd_abs),
|
||||
&cli_overrides,
|
||||
LoaderOverrides::default(),
|
||||
CloudRequirementsLoader::default(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(config_layer_stack) => config_layer_stack,
|
||||
Err(err) => {
|
||||
return SkillLoadOutcome {
|
||||
errors: vec![crate::skills::model::SkillError {
|
||||
path: cwd.to_path_buf(),
|
||||
message: err.to_string(),
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
}
|
||||
};
|
||||
let effective_skill_roots = skills_manager.effective_skill_roots(&config_layer_stack);
|
||||
let turn_config = self.turn.config.as_ref();
|
||||
let plugin_outcome = self
|
||||
.session
|
||||
.services
|
||||
.plugins_manager
|
||||
.plugins_for_config(turn_config);
|
||||
let effective_skill_roots = plugin_outcome.effective_skill_roots();
|
||||
let skills_outcome = self
|
||||
.session
|
||||
.services
|
||||
@@ -515,7 +501,7 @@ impl CoreShellActionProvider {
|
||||
&self.turn.cwd,
|
||||
&effective_skill_roots,
|
||||
force_reload,
|
||||
&config_layer_stack,
|
||||
&turn_config.config_layer_stack,
|
||||
)
|
||||
.await;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user