Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ In the codex-rs folder where the rust code lives:
- When extracting code from a large module, move the related tests and module/type docs toward
the new implementation so the invariants stay close to the code that owns them.

### Model-visible context fragments

- Model-visible prompt context should go through the shared fragment abstractions described in `docs/model-visible-context.md`.
- Every named fragment type should implement `ModelVisibleContextFragment` and set `type Role`.
- Turn-state model-visible context assembly should produce exactly two envelopes (one developer message + one contextual-user message) via the shared envelope builders.
- Define and register current fragment types in `codex-rs/core/src/model_visible_fragments.rs`. `REGISTERED_MODEL_VISIBLE_FRAGMENTS` is the integration point for contextual-user detection and registry-driven turn-state assembly.
- If a fragment represents durable turn/session state that should be rebuilt correctly across resume/fork/compaction/backtracking, implement `ModelVisibleContextFragment::build(...)`.
- If a fragment is contextual-user, it must provide stable detection: prefer `contextual_user_markers()` when fixed markers are sufficient, and override `matches_contextual_user_text()` only for genuinely custom matching (for example AGENTS.md).
- Use the developer envelope for developer guidance. Custom override text (for example config/app-server `developer_instructions`) should use `CustomDeveloperInstructions`; system-generated developer context should use typed fragments plus the neutral `developer_*_text` helpers rather than reusing the custom override type.
- Use contextual-user fragments for contextual user-role state. Turn-state contextual-user fragments such as custom user instructions, AGENTS instructions, JS REPL guidance, child-agent guidance, and environment context belong in the contextual-user envelope. Runtime contextual-user fragments should still use typed fragments so history parsing treats them as contextual state rather than user intent; examples include skills triggered at runtime, shell-command records, and turn-aborted notices.
- Use `<environment_context>` specifically for environment facts derived from `TurnContext` that may need turn-to-turn diffs (`cwd`, `shell`, optional `current_date`, optional `timezone`, optional network allow/deny domain summaries). Do not put policy text, plugin/skill listings, or other guidance into `<environment_context>`; those should use dedicated fragments.
- Runtime/session-prefix fragments that are not turn-state diffs should usually leave `ModelVisibleContextFragment::build(...)` as `None`.
- Register every current fragment exactly once in `REGISTERED_MODEL_VISIBLE_FRAGMENTS`, in the rough order it should appear in model-visible context.
- Prefer dedicated typed fragments over plain strings. Developer-only one-off text is acceptable only when it is truly isolated, does not need contextual-user detection, and does not participate in turn-state diff reconstruction.
- Do not hand-construct model-visible `ResponseItem::Message` payloads in new turn-state code; use fragment conversion and the shared envelope builders.
- Do not inject raw strings directly into the initial-context or settings-update builders, and do not call fragment wrapping helpers ad hoc from new code.

Run `just fmt` (in `codex-rs` directory) automatically after you have finished making Rust code changes; do not ask for approval to run it. Additionally, run the tests:

1. Run the test for the specific project that was changed. For example, if changes were made in `codex-rs/tui`, run `cargo test -p codex-tui`.
Expand Down
5 changes: 4 additions & 1 deletion codex-rs/app-server-protocol/schema/json/ClientRequest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -2741,7 +2742,7 @@
"type": "object"
},
"ThreadResumeParams": {
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.\n\nWhen resuming a thread that is already loaded/running, override fields are ignored and reported as mismatch warnings rather than being reapplied mid-session.",
"properties": {
"approvalPolicy": {
"anyOf": [
Expand Down Expand Up @@ -2784,6 +2785,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -2962,6 +2964,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11907,6 +11907,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -13086,7 +13087,7 @@
},
"ThreadResumeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.\n\nWhen resuming a thread that is already loaded/running, override fields are ignored and reported as mismatch warnings rather than being reapplied mid-session.",
"properties": {
"approvalPolicy": {
"anyOf": [
Expand Down Expand Up @@ -13129,6 +13130,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -13405,6 +13407,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9667,6 +9667,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -10846,7 +10847,7 @@
},
"ThreadResumeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.\n\nWhen resuming a thread that is already loaded/running, override fields are ignored and reported as mismatch warnings rather than being reapplied mid-session.",
"properties": {
"approvalPolicy": {
"anyOf": [
Expand Down Expand Up @@ -10889,6 +10890,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down Expand Up @@ -11165,6 +11167,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@
"type": "string"
}
},
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.\n\nWhen resuming a thread that is already loaded/running, override fields are ignored and reported as mismatch warnings rather than being reapplied mid-session.",
"properties": {
"approvalPolicy": {
"anyOf": [
Expand Down Expand Up @@ -1024,6 +1024,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
]
},
"developerInstructions": {
"description": "Custom developer override for this thread session. Takes precedence over `~/.codex/config.toml` `developer_instructions`.",
"type": [
"string",
"null"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, /**
* Custom developer override for this thread session.
* Takes precedence over `~/.codex/config.toml` `developer_instructions`.
*/
developerInstructions?: string | null, ephemeral?: boolean, /**
* If true, persist additional rollout EventMsg variants required to
* reconstruct a richer thread history on subsequent resume/fork/read.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import type { SandboxMode } from "./SandboxMode";
* If using history or path, the thread_id param will be ignored.
*
* Prefer using thread_id whenever possible.
*
* When resuming a thread that is already loaded/running, override fields are
* ignored and reported as mismatch warnings rather than being reapplied
* mid-session.
*/
export type ThreadResumeParams = {threadId: string, /**
* [UNSTABLE] FOR CODEX CLOUD - DO NOT USE.
Expand All @@ -36,7 +40,11 @@ model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, /**
* Custom developer override for this thread session.
* Takes precedence over `~/.codex/config.toml` `developer_instructions`.
*/
developerInstructions?: string | null, personality?: Personality | null, /**
* If true, persist additional rollout EventMsg variants required to
* reconstruct a richer thread history on subsequent resume/fork/read.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export type ThreadStartParams = {model?: string | null, modelProvider?: string |
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, /**
* Custom developer override for this thread session.
* Takes precedence over `~/.codex/config.toml` `developer_instructions`.
*/
developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, /**
* If true, opt into emitting raw Responses API items on the event stream.
* This is for internal use only (e.g. Codex Cloud).
*/
Expand Down
10 changes: 10 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2486,6 +2486,8 @@ pub struct ThreadStartParams {
pub service_name: Option<String>,
#[ts(optional = nullable)]
pub base_instructions: Option<String>,
/// Custom developer override for this thread session.
/// Takes precedence over `~/.codex/config.toml` `developer_instructions`.
#[ts(optional = nullable)]
pub developer_instructions: Option<String>,
#[ts(optional = nullable)]
Expand Down Expand Up @@ -2560,6 +2562,10 @@ pub struct ThreadStartResponse {
/// If using history or path, the thread_id param will be ignored.
///
/// Prefer using thread_id whenever possible.
///
/// When resuming a thread that is already loaded/running, override fields are
/// ignored and reported as mismatch warnings rather than being reapplied
/// mid-session.
pub struct ThreadResumeParams {
pub thread_id: String,

Expand Down Expand Up @@ -2604,6 +2610,8 @@ pub struct ThreadResumeParams {
pub config: Option<HashMap<String, serde_json::Value>>,
#[ts(optional = nullable)]
pub base_instructions: Option<String>,
/// Custom developer override for this thread session.
/// Takes precedence over `~/.codex/config.toml` `developer_instructions`.
#[ts(optional = nullable)]
pub developer_instructions: Option<String>,
#[ts(optional = nullable)]
Expand Down Expand Up @@ -2681,6 +2689,8 @@ pub struct ThreadForkParams {
pub config: Option<HashMap<String, serde_json::Value>>,
#[ts(optional = nullable)]
pub base_instructions: Option<String>,
/// Custom developer override for this thread session.
/// Takes precedence over `~/.codex/config.toml` `developer_instructions`.
#[ts(optional = nullable)]
pub developer_instructions: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Example with notification opt-out:
## API Overview

- `thread/start` — create a new thread; emits `thread/started` (including the current `thread.status`) and auto-subscribes you to turn/item events for that thread.
- `thread/resume` — reopen an existing thread by id so subsequent `turn/start` calls append to it.
- `thread/resume` — reopen an existing thread by id so subsequent `turn/start` calls append to it. When calling `thread/resume` against a thread that is already loaded/running, override fields are ignored and logged as mismatch warnings rather than being reapplied mid-session.
- `thread/fork` — fork an existing thread into a new thread id by copying the stored history; accepts `ephemeral: true` for an in-memory temporary fork, emits `thread/started` (including the current `thread.status`), and auto-subscribes you to turn/item events for the new thread.
- `thread/list` — page through stored rollouts; supports cursor-based pagination and optional `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filters. Each returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
- `thread/loaded/list` — list the thread ids currently loaded in memory.
Expand Down
8 changes: 4 additions & 4 deletions codex-rs/core/src/agent/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use crate::error::CodexErr;
use crate::error::Result as CodexResult;
use crate::find_archived_thread_path_by_id_str;
use crate::find_thread_path_by_id_str;
use crate::model_visible_fragments::SubagentNotification;
use crate::model_visible_fragments::format_subagent_context_line;
use crate::rollout::RolloutRecorder;
use crate::session_prefix::format_subagent_context_line;
use crate::session_prefix::format_subagent_notification_message;
use crate::shell_snapshot::ShellSnapshot;
use crate::state_db;
use crate::thread_manager::ThreadManagerState;
Expand Down Expand Up @@ -675,8 +675,8 @@ impl AgentControl {
return;
};
parent_thread
.inject_user_message_without_turn(format_subagent_notification_message(
child_reference.as_str(),
.inject_model_visible_fragment_without_turn(SubagentNotification::new(
&child_reference,
&status,
))
.await;
Expand Down
Loading
Loading