diff --git a/codex-rs/core/src/context/contextual_user_message_tests.rs b/codex-rs/core/src/context/contextual_user_message_tests.rs index 9ff8eb55da..a4ccbbd738 100644 --- a/codex-rs/core/src/context/contextual_user_message_tests.rs +++ b/codex-rs/core/src/context/contextual_user_message_tests.rs @@ -1,6 +1,5 @@ use super::*; use crate::context::ContextualUserFragment; -use crate::context::ExtensionContextTag; use crate::context::SubagentNotification; use codex_protocol::items::HookPromptFragment; use codex_protocol::items::build_hook_prompt_message; @@ -21,15 +20,6 @@ fn detects_extension_context_fragment() { })); } -#[test] -fn detects_goal_extension_context_fragment() { - let text = ExtensionContext::with_tag(ExtensionContextTag::GOAL, "hidden goal prompt").render(); - - assert!(is_contextual_user_fragment(&ContentItem::InputText { - text - })); -} - #[test] fn detects_agents_instructions_fragment() { assert!(is_contextual_user_fragment(&ContentItem::InputText { diff --git a/codex-rs/core/src/context/extension_context.rs b/codex-rs/core/src/context/extension_context.rs index 972f1ffa2b..15e72191a0 100644 --- a/codex-rs/core/src/context/extension_context.rs +++ b/codex-rs/core/src/context/extension_context.rs @@ -1,51 +1,23 @@ //! Hidden user-context wrappers owned by extensions. //! -//! Extensions can use one of these host-recognized tags when they need hidden -//! model-visible context to survive history filtering without teaching core -//! about the extension's domain concepts. +//! Extensions can use this host-recognized tag when they need hidden +//! model-visible context to survive history filtering. use super::ContextualUserFragment; use super::fragment::matches_marked_text; -/// Host-recognized marker pair for extension-owned hidden context. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct ExtensionContextTag { - start_marker: &'static str, - end_marker: &'static str, -} - -impl ExtensionContextTag { - pub const DEFAULT: Self = Self::new("", ""); - pub const GOAL: Self = Self::new("", ""); - - const fn new(start_marker: &'static str, end_marker: &'static str) -> Self { - Self { - start_marker, - end_marker, - } - } -} - -const EXTENSION_CONTEXT_TAGS: &[ExtensionContextTag] = - &[ExtensionContextTag::DEFAULT, ExtensionContextTag::GOAL]; +const START_MARKER: &str = ""; +const END_MARKER: &str = ""; /// Hidden user-context fragment for extension-owned steering prompts. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExtensionContext { - tag: ExtensionContextTag, body: String, } impl ExtensionContext { pub fn new(body: impl Into) -> Self { - Self::with_tag(ExtensionContextTag::DEFAULT, body) - } - - pub fn with_tag(tag: ExtensionContextTag, body: impl Into) -> Self { - Self { - tag, - body: body.into(), - } + Self { body: body.into() } } } @@ -55,20 +27,15 @@ impl ContextualUserFragment for ExtensionContext { } fn markers(&self) -> (&'static str, &'static str) { - (self.tag.start_marker, self.tag.end_marker) + (START_MARKER, END_MARKER) } fn type_markers() -> (&'static str, &'static str) { - ( - ExtensionContextTag::DEFAULT.start_marker, - ExtensionContextTag::DEFAULT.end_marker, - ) + (START_MARKER, END_MARKER) } fn matches_text(text: &str) -> bool { - EXTENSION_CONTEXT_TAGS - .iter() - .any(|tag| matches_marked_text(tag.start_marker, tag.end_marker, text)) + matches_marked_text(START_MARKER, END_MARKER, text) } fn body(&self) -> String { diff --git a/codex-rs/core/src/context/mod.rs b/codex-rs/core/src/context/mod.rs index 70dac08b80..5ad1a8711e 100644 --- a/codex-rs/core/src/context/mod.rs +++ b/codex-rs/core/src/context/mod.rs @@ -39,7 +39,6 @@ pub(crate) use contextual_user_message::is_contextual_user_fragment; pub(crate) use contextual_user_message::parse_visible_hook_prompt_message; pub(crate) use environment_context::EnvironmentContext; pub use extension_context::ExtensionContext; -pub use extension_context::ExtensionContextTag; pub use fragment::ContextualUserFragment; pub(crate) use fragment::FragmentRegistration; pub(crate) use fragment::FragmentRegistrationProxy; diff --git a/codex-rs/core/src/tasks/idle_extension.rs b/codex-rs/core/src/tasks/idle_extension.rs index e570a7fbba..eadc25ae5d 100644 --- a/codex-rs/core/src/tasks/idle_extension.rs +++ b/codex-rs/core/src/tasks/idle_extension.rs @@ -228,8 +228,6 @@ fn idle_extension_input(prompt: String) -> TurnInput { #[cfg(test)] mod tests { - use crate::context::ExtensionContextTag; - use super::*; #[test] @@ -240,7 +238,7 @@ mod tests { ); let original_len = prompt.len(); - let prompt = ExtensionContext::with_tag(ExtensionContextTag::GOAL, prompt).render(); + let prompt = ExtensionContext::new(prompt).render(); let TurnInput::ResponseInputItem(ResponseInputItem::Message { content, .. }) = idle_extension_input(prompt) else { @@ -250,7 +248,7 @@ mod tests { panic!("expected one text content item"); }; - assert!(text.starts_with("")); + assert!(text.starts_with("")); assert!(text.contains("start")); assert!(text.contains("end")); assert!(text.len() < original_len); diff --git a/codex-rs/ext/goal/src/steering.rs b/codex-rs/ext/goal/src/steering.rs index 0e7d493c7f..92a05afb80 100644 --- a/codex-rs/ext/goal/src/steering.rs +++ b/codex-rs/ext/goal/src/steering.rs @@ -1,6 +1,5 @@ use codex_core::context::ContextualUserFragment; use codex_core::context::ExtensionContext; -use codex_core::context::ExtensionContextTag; use codex_extension_api::ThreadIdleRequest; use codex_protocol::models::ResponseInputItem; use codex_protocol::protocol::ThreadGoal; @@ -47,21 +46,19 @@ fn render_embedded_template( } pub(crate) fn budget_limit_steering_item(goal: &ThreadGoal) -> ResponseInputItem { - goal_context_input_item(budget_limit_prompt(goal)) + extension_context_input_item(budget_limit_prompt(goal)) } pub(crate) fn continuation_steering_request(goal: &ThreadGoal) -> ThreadIdleRequest { - ThreadIdleRequest::new( - ExtensionContext::with_tag(ExtensionContextTag::GOAL, continuation_prompt(goal)).render(), - ) + ThreadIdleRequest::new(ExtensionContext::new(continuation_prompt(goal)).render()) } pub(crate) fn objective_updated_steering_item(goal: &ThreadGoal) -> ResponseInputItem { - goal_context_input_item(objective_updated_prompt(goal)) + extension_context_input_item(objective_updated_prompt(goal)) } -fn goal_context_input_item(prompt: String) -> ResponseInputItem { - ExtensionContext::with_tag(ExtensionContextTag::GOAL, prompt).into_response_input_item() +fn extension_context_input_item(prompt: String) -> ResponseInputItem { + ExtensionContext::new(prompt).into_response_input_item() } fn continuation_prompt(goal: &ThreadGoal) -> String { diff --git a/codex-rs/ext/goal/tests/goal_extension_backend.rs b/codex-rs/ext/goal/tests/goal_extension_backend.rs index 438c0d0cfb..c620c94399 100644 --- a/codex-rs/ext/goal/tests/goal_extension_backend.rs +++ b/codex-rs/ext/goal/tests/goal_extension_backend.rs @@ -507,14 +507,14 @@ async fn thread_idle_hook_requests_hidden_goal_continuation() -> anyhow::Result< .ok_or_else(|| anyhow::anyhow!("active goal should request idle continuation"))?; assert!(request.validation_key.is_some()); - assert!(request.prompt.starts_with("")); + assert!(request.prompt.starts_with("")); assert!( request .prompt .contains("Continue working toward the active thread goal.") ); assert!(request.prompt.contains("Completion audit:")); - assert!(request.prompt.ends_with("")); + assert!(request.prompt.ends_with("")); assert!( harness .should_start_idle_turn(ModeKind::Default, &request)