diff --git a/codex-rs/app-server/tests/suite/v2/turn_start.rs b/codex-rs/app-server/tests/suite/v2/turn_start.rs index b2b1ac1d83..ec7d37feea 100644 --- a/codex-rs/app-server/tests/suite/v2/turn_start.rs +++ b/codex-rs/app-server/tests/suite/v2/turn_start.rs @@ -50,6 +50,7 @@ use codex_app_server_protocol::UserInput as V2UserInput; use codex_app_server_protocol::WarningNotification; use codex_config::config_toml::ConfigToml; use codex_core::personality_migration::PERSONALITY_MIGRATION_FILENAME; +use codex_core::skills::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; use codex_features::FEATURES; use codex_features::Feature; use codex_protocol::config_types::CollaborationMode; @@ -322,10 +323,7 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills( let warning: WarningNotification = serde_json::from_value(params).expect("deserialize warning notification"); assert_eq!(warning.thread_id.as_deref(), Some(thread.id.as_str())); - assert_eq!( - warning.message, - "Some enabled skills were not included in the model-visible skills list for this session. Mention a skill by name or path if you need it." - ); + assert_eq!(warning.message, SKILL_METADATA_TRUNCATION_WARNING_MESSAGE); timeout( DEFAULT_READ_TIMEOUT, diff --git a/codex-rs/core-skills/src/lib.rs b/codex-rs/core-skills/src/lib.rs index 06ced0d5d4..23f0d4234d 100644 --- a/codex-rs/core-skills/src/lib.rs +++ b/codex-rs/core-skills/src/lib.rs @@ -23,6 +23,7 @@ pub use model::SkillMetadata; pub use model::SkillPolicy; pub use model::filter_skill_load_outcome_for_product; pub use render::AvailableSkills; +pub use render::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; pub use render::SkillMetadataBudget; pub use render::SkillRenderReport; pub use render::build_available_skills; diff --git a/codex-rs/core-skills/src/render.rs b/codex-rs/core-skills/src/render.rs index 6bcd5e4e05..551a767d7d 100644 --- a/codex-rs/core-skills/src/render.rs +++ b/codex-rs/core-skills/src/render.rs @@ -9,6 +9,12 @@ use codex_utils_output_truncation::approx_token_count; const DEFAULT_SKILL_METADATA_CHAR_BUDGET: usize = 8_000; const SKILL_METADATA_CONTEXT_WINDOW_PERCENT: usize = 2; +/// Warning shown when enabled skill metadata exceeds the model-visible budget. +pub const SKILL_METADATA_TRUNCATION_WARNING_MESSAGE: &str = concat!( + "A large number of skills are enabled, so some are excluded from the model-visible skills list ", + "for this session. Mention skills by name or path if explicitly needed." +); + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SkillMetadataBudget { Tokens(usize), diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 6a6ed86a8d..fa08f3e868 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -273,6 +273,7 @@ use crate::rollout::policy::EventPersistenceMode; use crate::session_startup_prewarm::SessionStartupPrewarmHandle; use crate::shell; use crate::shell_snapshot::ShellSnapshot; +use crate::skills::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; use crate::skills_watcher::SkillsWatcher; use crate::skills_watcher::SkillsWatcherEvent; use crate::state::ActiveTurn; @@ -373,8 +374,6 @@ pub struct Codex { pub(crate) type SessionLoopTermination = Shared>; -pub(crate) const THREAD_START_SKILLS_TRIMMED_WARNING_MESSAGE: &str = "Some enabled skills were not included in the model-visible skills list for this session. Mention a skill by name or path if you need it."; - /// Wrapper returned by [`Codex::spawn`] containing the spawned [`Codex`] and /// the unique session id. pub struct CodexSpawnOk { @@ -2507,7 +2506,7 @@ impl Session { self.send_event_raw(Event { id: String::new(), msg: EventMsg::Warning(WarningEvent { - message: THREAD_START_SKILLS_TRIMMED_WARNING_MESSAGE.to_string(), + message: SKILL_METADATA_TRUNCATION_WARNING_MESSAGE.to_string(), }), }) .await; diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index bf0623bcb5..b620db8154 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -14,6 +14,7 @@ use crate::context::TurnAborted; use crate::exec::ExecCapturePolicy; use crate::function_tool::FunctionCallError; use crate::shell::default_user_shell; +use crate::skills::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; use crate::skills::SkillRenderSideEffects; use crate::skills::render::SkillMetadataBudget; use crate::tools::format_exec_output_str; @@ -4817,7 +4818,7 @@ async fn build_initial_context_trims_skill_metadata_from_context_window_budget() assert!( developer_texts .iter() - .all(|text| !text.contains(THREAD_START_SKILLS_TRIMMED_WARNING_MESSAGE)), + .all(|text| !text.contains(SKILL_METADATA_TRUNCATION_WARNING_MESSAGE)), "expected skill budget warning to stay out of the initial context, got {developer_texts:?}" ); assert!( @@ -4899,7 +4900,7 @@ async fn build_initial_context_emits_thread_start_skill_warning_on_repeated_buil assert!(matches!( warning_event.msg, EventMsg::Warning(WarningEvent { message }) - if message == THREAD_START_SKILLS_TRIMMED_WARNING_MESSAGE + if message == SKILL_METADATA_TRUNCATION_WARNING_MESSAGE )); let _ = session.build_initial_context(&turn_context).await; @@ -4910,7 +4911,7 @@ async fn build_initial_context_emits_thread_start_skill_warning_on_repeated_buil assert!(matches!( warning_event.msg, EventMsg::Warning(WarningEvent { message }) - if message == THREAD_START_SKILLS_TRIMMED_WARNING_MESSAGE + if message == SKILL_METADATA_TRUNCATION_WARNING_MESSAGE )); } diff --git a/codex-rs/core/src/skills.rs b/codex-rs/core/src/skills.rs index 0681d09624..e9cf1c04ff 100644 --- a/codex-rs/core/src/skills.rs +++ b/codex-rs/core/src/skills.rs @@ -16,6 +16,7 @@ use codex_protocol::request_user_input::RequestUserInputResponse; use codex_utils_absolute_path::AbsolutePathBuf; use tracing::warn; +pub use codex_core_skills::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; pub use codex_core_skills::SkillDependencyInfo; pub use codex_core_skills::SkillError; pub use codex_core_skills::SkillLoadOutcome; diff --git a/codex-rs/tui/src/chatwidget/tests/app_server.rs b/codex-rs/tui/src/chatwidget/tests/app_server.rs index 702bd08ef9..407f80e506 100644 --- a/codex-rs/tui/src/chatwidget/tests/app_server.rs +++ b/codex-rs/tui/src/chatwidget/tests/app_server.rs @@ -1,4 +1,5 @@ use super::*; +use codex_core_skills::SKILL_METADATA_TRUNCATION_WARNING_MESSAGE; use pretty_assertions::assert_eq; #[tokio::test] @@ -191,7 +192,7 @@ async fn live_app_server_warning_notification_renders_message() { chat.handle_server_notification( ServerNotification::Warning(WarningNotification { thread_id: None, - message: "Some enabled skills were not included in the model-visible skills list for this session. Mention a skill by name or path if you need it.".to_string(), + message: SKILL_METADATA_TRUNCATION_WARNING_MESSAGE.to_string(), }), /*replay_kind*/ None, ); @@ -201,13 +202,11 @@ async fn live_app_server_warning_notification_renders_message() { let rendered = lines_to_single_string(&cells[0]); let normalized = rendered.split_whitespace().collect::>().join(" "); assert!( - normalized.contains( - "Some enabled skills were not included in the model-visible skills list for this session." - ), + normalized.contains("A large number of skills are enabled, so some are excluded"), "expected warning notification message, got {rendered}" ); assert!( - normalized.contains("Mention a skill by name or path if you need it."), + normalized.contains("Mention skills by name or path if explicitly needed."), "expected warning guidance, got {rendered}" ); }