core/src/context/contextual_user_message.rs
102 lines
use codex_protocol::items::HookPromptItem;use codex_protocol::items::parse_hook_prompt_fragment;use codex_protocol::models::ContentItem;use super::AdditionalContextUserFragment;use super::EnvironmentContext;use super::FragmentRegistration;use super::FragmentRegistrationProxy;use super::InternalModelContextFragment;use super::LegacyApplyPatchExecCommandWarning;use super::LegacyModelMismatchWarning;use super::LegacyUnifiedExecProcessLimitWarning;use super::SkillInstructions;use super::SubagentNotification;use super::TurnAborted;use super::UserInstructions;use super::UserShellCommand;static USER_INSTRUCTIONS_REGISTRATION: FragmentRegistrationProxy<UserInstructions> = FragmentRegistrationProxy::new();static ENVIRONMENT_CONTEXT_REGISTRATION: FragmentRegistrationProxy<EnvironmentContext> = FragmentRegistrationProxy::new();static ADDITIONAL_CONTEXT_REGISTRATION: FragmentRegistrationProxy<AdditionalContextUserFragment> = FragmentRegistrationProxy::new();static SKILL_INSTRUCTIONS_REGISTRATION: FragmentRegistrationProxy<SkillInstructions> = FragmentRegistrationProxy::new();static USER_SHELL_COMMAND_REGISTRATION: FragmentRegistrationProxy<UserShellCommand> = FragmentRegistrationProxy::new();static TURN_ABORTED_REGISTRATION: FragmentRegistrationProxy<TurnAborted> = FragmentRegistrationProxy::new();static SUBAGENT_NOTIFICATION_REGISTRATION: FragmentRegistrationProxy<SubagentNotification> = FragmentRegistrationProxy::new();static INTERNAL_MODEL_CONTEXT_REGISTRATION: FragmentRegistrationProxy< InternalModelContextFragment,> = FragmentRegistrationProxy::new();static LEGACY_UNIFIED_EXEC_PROCESS_LIMIT_WARNING_REGISTRATION: FragmentRegistrationProxy< LegacyUnifiedExecProcessLimitWarning,> = FragmentRegistrationProxy::new();static LEGACY_APPLY_PATCH_EXEC_COMMAND_WARNING_REGISTRATION: FragmentRegistrationProxy< LegacyApplyPatchExecCommandWarning,> = FragmentRegistrationProxy::new();static LEGACY_MODEL_MISMATCH_WARNING_REGISTRATION: FragmentRegistrationProxy< LegacyModelMismatchWarning,> = FragmentRegistrationProxy::new();static CONTEXTUAL_USER_FRAGMENTS: &[&dyn FragmentRegistration] = &[ &USER_INSTRUCTIONS_REGISTRATION, &ENVIRONMENT_CONTEXT_REGISTRATION, &ADDITIONAL_CONTEXT_REGISTRATION, &SKILL_INSTRUCTIONS_REGISTRATION, &USER_SHELL_COMMAND_REGISTRATION, &TURN_ABORTED_REGISTRATION, &SUBAGENT_NOTIFICATION_REGISTRATION, &INTERNAL_MODEL_CONTEXT_REGISTRATION, &LEGACY_UNIFIED_EXEC_PROCESS_LIMIT_WARNING_REGISTRATION, &LEGACY_APPLY_PATCH_EXEC_COMMAND_WARNING_REGISTRATION, &LEGACY_MODEL_MISMATCH_WARNING_REGISTRATION,];fn is_standard_contextual_user_text(text: &str) -> bool { CONTEXTUAL_USER_FRAGMENTS .iter() .any(|fragment| fragment.matches_text(text))}pub(crate) fn is_contextual_user_fragment(content_item: &ContentItem) -> bool { let ContentItem::InputText { text } = content_item else { return false; }; parse_hook_prompt_fragment(text).is_some() || is_standard_contextual_user_text(text)}pub(crate) fn parse_visible_hook_prompt_message( id: Option<&String>, content: &[ContentItem],) -> Option<HookPromptItem> { let mut fragments = Vec::new(); for content_item in content { let ContentItem::InputText { text } = content_item else { return None; }; if let Some(fragment) = parse_hook_prompt_fragment(text) { fragments.push(fragment); continue; } if is_standard_contextual_user_text(text) { continue; } return None; } if fragments.is_empty() { return None; } Some(HookPromptItem::from_fragments(id, fragments))}#[cfg(test)]#[path = "contextual_user_message_tests.rs"]mod tests;