mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
chore: extract context fragments into dedicated crate (#26122)
## Why `codex-core` currently owns the generic contextual-fragment trait and several reusable fragment implementations. That makes it harder for other crates to share the same host-owned model-input abstraction without depending on all of `codex-core`. This change extracts the reusable fragment machinery into a small `codex-context-fragments` crate so future extension and skills work can depend on the fragment abstraction directly. ## What Changed - Added the `codex-context-fragments` crate with: - `ContextualUserFragment` - `FragmentRegistration` / `FragmentRegistrationProxy` - additional-context fragment types - Moved `SkillInstructions` into `codex-core-skills`, since skill-specific rendering belongs with skills rather than generic core context machinery. - Kept `codex-core` re-exporting the fragment types it still uses internally, so existing call sites keep the same shape. - Updated Cargo and Bazel workspace metadata for the new crate. ## Verification - `cargo metadata --locked --format-version 1 --no-deps` - `just bazel-lock-update` - `just bazel-lock-check`
This commit is contained in:
Generated
+11
@@ -2506,6 +2506,14 @@ dependencies = [
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-context-fragments"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-protocol",
|
||||
"codex-utils-string",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-core"
|
||||
version = "0.0.0"
|
||||
@@ -2528,6 +2536,7 @@ dependencies = [
|
||||
"codex-code-mode",
|
||||
"codex-config",
|
||||
"codex-connectors",
|
||||
"codex-context-fragments",
|
||||
"codex-core-plugins",
|
||||
"codex-core-skills",
|
||||
"codex-exec-server",
|
||||
@@ -2692,6 +2701,7 @@ dependencies = [
|
||||
"codex-analytics",
|
||||
"codex-app-server-protocol",
|
||||
"codex-config",
|
||||
"codex-context-fragments",
|
||||
"codex-exec-server",
|
||||
"codex-login",
|
||||
"codex-model-provider",
|
||||
@@ -3458,6 +3468,7 @@ name = "codex-prompts"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"codex-context-fragments",
|
||||
"codex-execpolicy",
|
||||
"codex-git-utils",
|
||||
"codex-protocol",
|
||||
|
||||
@@ -29,6 +29,7 @@ members = [
|
||||
"collaboration-mode-templates",
|
||||
"connectors",
|
||||
"config",
|
||||
"context-fragments",
|
||||
"shell-command",
|
||||
"shell-escalation",
|
||||
"skills",
|
||||
@@ -156,6 +157,7 @@ codex-cloud-tasks-mock-client = { path = "cloud-tasks-mock-client" }
|
||||
codex-code-mode = { path = "code-mode" }
|
||||
codex-config = { path = "config" }
|
||||
codex-connectors = { path = "connectors" }
|
||||
codex-context-fragments = { path = "context-fragments" }
|
||||
codex-core = { path = "core" }
|
||||
codex-core-api = { path = "core-api" }
|
||||
codex-core-plugins = { path = "core-plugins" }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
load("//:defs.bzl", "codex_rust_crate")
|
||||
|
||||
codex_rust_crate(
|
||||
name = "context-fragments",
|
||||
crate_name = "codex_context_fragments",
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
name = "codex-context-fragments"
|
||||
version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "codex_context_fragments"
|
||||
path = "src/lib.rs"
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codex-protocol = { workspace = true }
|
||||
codex-utils-string = { workspace = true }
|
||||
+6
-5
@@ -1,18 +1,19 @@
|
||||
use super::ContextualUserFragment;
|
||||
use codex_utils_string::truncate_middle_with_token_budget;
|
||||
|
||||
use crate::ContextualUserFragment;
|
||||
|
||||
const MAX_ADDITIONAL_CONTEXT_VALUE_TOKENS: usize = 1_000;
|
||||
const ADDITIONAL_CONTEXT_END_MARKER_SUFFIX: &str = ">";
|
||||
const ADDITIONAL_CONTEXT_START_MARKER_PREFIX: &str = "<external_";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct AdditionalContextUserFragment {
|
||||
pub struct AdditionalContextUserFragment {
|
||||
key: String,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl AdditionalContextUserFragment {
|
||||
pub(crate) fn new(key: String, value: String) -> Self {
|
||||
pub fn new(key: String, value: String) -> Self {
|
||||
Self { key, value }
|
||||
}
|
||||
}
|
||||
@@ -52,13 +53,13 @@ impl ContextualUserFragment for AdditionalContextUserFragment {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct AdditionalContextDeveloperFragment {
|
||||
pub struct AdditionalContextDeveloperFragment {
|
||||
key: String,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl AdditionalContextDeveloperFragment {
|
||||
pub(crate) fn new(key: String, value: String) -> Self {
|
||||
pub fn new(key: String, value: String) -> Self {
|
||||
Self { key, value }
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,33 @@
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Type-erased registration for a contextual user fragment.
|
||||
///
|
||||
/// Implementations are used by context filtering code to recognize injected
|
||||
/// fragments without constructing the concrete context payload.
|
||||
pub(crate) trait FragmentRegistration: Sync {
|
||||
pub trait FragmentRegistration: Sync {
|
||||
fn matches_text(&self, text: &str) -> bool;
|
||||
}
|
||||
|
||||
pub(crate) struct FragmentRegistrationProxy<T> {
|
||||
_marker: PhantomData<fn() -> T>,
|
||||
pub struct FragmentRegistrationProxy<T> {
|
||||
_marker: std::marker::PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
impl<T> FragmentRegistrationProxy<T> {
|
||||
pub(crate) const fn new() -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
_marker: PhantomData,
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for FragmentRegistrationProxy<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ContextualUserFragment> FragmentRegistration for FragmentRegistrationProxy<T> {
|
||||
fn matches_text(&self, text: &str) -> bool {
|
||||
T::matches_text(text)
|
||||
@@ -97,7 +102,7 @@ pub trait ContextualUserFragment {
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_marked_text(start_marker: &str, end_marker: &str, text: &str) -> bool {
|
||||
pub(crate) fn matches_marked_text(start_marker: &str, end_marker: &str, text: &str) -> bool {
|
||||
if start_marker.is_empty() || end_marker.is_empty() {
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
mod additional_context;
|
||||
mod fragment;
|
||||
|
||||
pub use additional_context::AdditionalContextDeveloperFragment;
|
||||
pub use additional_context::AdditionalContextUserFragment;
|
||||
pub use fragment::ContextualUserFragment;
|
||||
pub use fragment::FragmentRegistration;
|
||||
pub use fragment::FragmentRegistrationProxy;
|
||||
@@ -17,6 +17,7 @@ anyhow = { workspace = true }
|
||||
codex-analytics = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-config = { workspace = true }
|
||||
codex-context-fragments = { workspace = true }
|
||||
codex-exec-server = { workspace = true }
|
||||
codex-login = { workspace = true }
|
||||
codex-model-provider = { workspace = true }
|
||||
|
||||
@@ -7,6 +7,7 @@ mod mention_counts;
|
||||
pub mod model;
|
||||
pub mod remote;
|
||||
pub mod render;
|
||||
mod skill_instructions;
|
||||
pub mod system;
|
||||
|
||||
pub(crate) use invocation_utils::build_implicit_skill_path_indexes;
|
||||
@@ -29,3 +30,4 @@ pub use render::SkillRenderReport;
|
||||
pub use render::build_available_skills;
|
||||
pub use render::default_skill_metadata_budget;
|
||||
pub use render::render_available_skills_body;
|
||||
pub use skill_instructions::SkillInstructions;
|
||||
|
||||
+6
-6
@@ -1,12 +1,12 @@
|
||||
use codex_core_skills::injection::SkillInjection;
|
||||
use codex_context_fragments::ContextualUserFragment;
|
||||
|
||||
use super::ContextualUserFragment;
|
||||
use crate::injection::SkillInjection;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) struct SkillInstructions {
|
||||
pub(crate) name: String,
|
||||
pub(crate) path: String,
|
||||
pub(crate) contents: String,
|
||||
pub struct SkillInstructions {
|
||||
name: String,
|
||||
path: String,
|
||||
contents: String,
|
||||
}
|
||||
|
||||
impl From<&SkillInjection> for SkillInstructions {
|
||||
@@ -31,6 +31,7 @@ codex-apply-patch = { workspace = true }
|
||||
codex-async-utils = { workspace = true }
|
||||
codex-code-mode = { workspace = true }
|
||||
codex-connectors = { workspace = true }
|
||||
codex-context-fragments = { workspace = true }
|
||||
codex-config = { workspace = true }
|
||||
codex-core-plugins = { workspace = true }
|
||||
codex-core-skills = { workspace = true }
|
||||
|
||||
@@ -7,8 +7,6 @@ mod available_skills_instructions;
|
||||
mod collaboration_mode_instructions;
|
||||
mod contextual_user_message;
|
||||
mod environment_context;
|
||||
mod fragment;
|
||||
mod fragments;
|
||||
mod guardian_followup_review_reminder;
|
||||
mod hook_additional_context;
|
||||
mod image_generation_instructions;
|
||||
@@ -24,7 +22,6 @@ mod plugin_instructions;
|
||||
mod realtime_end_instructions;
|
||||
mod realtime_start_instructions;
|
||||
mod realtime_start_with_instructions;
|
||||
mod skill_instructions;
|
||||
mod subagent_notification;
|
||||
mod turn_aborted;
|
||||
mod user_instructions;
|
||||
@@ -34,15 +31,16 @@ pub(crate) use approved_command_prefix_saved::ApprovedCommandPrefixSaved;
|
||||
pub(crate) use apps_instructions::AppsInstructions;
|
||||
pub(crate) use available_plugins_instructions::AvailablePluginsInstructions;
|
||||
pub(crate) use available_skills_instructions::AvailableSkillsInstructions;
|
||||
pub(crate) use codex_context_fragments::AdditionalContextDeveloperFragment;
|
||||
pub(crate) use codex_context_fragments::AdditionalContextUserFragment;
|
||||
pub use codex_context_fragments::ContextualUserFragment;
|
||||
pub(crate) use codex_context_fragments::FragmentRegistration;
|
||||
pub(crate) use codex_context_fragments::FragmentRegistrationProxy;
|
||||
pub(crate) use codex_core_skills::SkillInstructions;
|
||||
pub(crate) use collaboration_mode_instructions::CollaborationModeInstructions;
|
||||
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 fragment::ContextualUserFragment;
|
||||
pub(crate) use fragment::FragmentRegistration;
|
||||
pub(crate) use fragment::FragmentRegistrationProxy;
|
||||
pub(crate) use fragments::AdditionalContextDeveloperFragment;
|
||||
pub(crate) use fragments::AdditionalContextUserFragment;
|
||||
pub(crate) use guardian_followup_review_reminder::GuardianFollowupReviewReminder;
|
||||
pub(crate) use hook_additional_context::HookAdditionalContext;
|
||||
pub(crate) use image_generation_instructions::ImageGenerationInstructions;
|
||||
@@ -60,7 +58,6 @@ pub(crate) use plugin_instructions::PluginInstructions;
|
||||
pub(crate) use realtime_end_instructions::RealtimeEndInstructions;
|
||||
pub(crate) use realtime_start_instructions::RealtimeStartInstructions;
|
||||
pub(crate) use realtime_start_with_instructions::RealtimeStartWithInstructions;
|
||||
pub(crate) use skill_instructions::SkillInstructions;
|
||||
pub(crate) use subagent_notification::SubagentNotification;
|
||||
pub(crate) use turn_aborted::TurnAborted;
|
||||
pub(crate) use user_instructions::UserInstructions;
|
||||
|
||||
@@ -1,21 +1 @@
|
||||
use super::ContextualUserFragment;
|
||||
|
||||
pub use codex_prompts::PermissionsInstructions;
|
||||
|
||||
impl ContextualUserFragment for PermissionsInstructions {
|
||||
fn role() -> &'static str {
|
||||
"developer"
|
||||
}
|
||||
|
||||
fn markers(&self) -> (&'static str, &'static str) {
|
||||
Self::type_markers()
|
||||
}
|
||||
|
||||
fn type_markers() -> (&'static str, &'static str) {
|
||||
("<permissions instructions>", "</permissions instructions>")
|
||||
}
|
||||
|
||||
fn body(&self) -> String {
|
||||
PermissionsInstructions::body(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
codex-context-fragments = { workspace = true }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-execpolicy = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use codex_context_fragments::ContextualUserFragment;
|
||||
use codex_execpolicy::Policy;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
@@ -141,6 +142,24 @@ impl PermissionsInstructions {
|
||||
}
|
||||
}
|
||||
|
||||
impl ContextualUserFragment for PermissionsInstructions {
|
||||
fn role() -> &'static str {
|
||||
"developer"
|
||||
}
|
||||
|
||||
fn markers(&self) -> (&'static str, &'static str) {
|
||||
Self::type_markers()
|
||||
}
|
||||
|
||||
fn type_markers() -> (&'static str, &'static str) {
|
||||
("<permissions instructions>", "</permissions instructions>")
|
||||
}
|
||||
|
||||
fn body(&self) -> String {
|
||||
PermissionsInstructions::body(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn sandbox_prompt_from_policy(
|
||||
file_system_policy: &FileSystemSandboxPolicy,
|
||||
cwd: &Path,
|
||||
|
||||
Reference in New Issue
Block a user