mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
app-server: treat null mode developer instructions as built-in defaults (#10983)
## Summary - make `turn/start` normalize `collaborationMode.settings.developer_instructions: null` to the built-in instructions for the selected mode - prevent app-server clients from accidentally clearing mode-switch developer instructions by sending `null` - document this behavior in the v2 protocol and app-server docs ## What changed - `codex-rs/app-server/src/codex_message_processor.rs` - added a small `normalize_turn_start_collaboration_mode` helper - in `turn_start`, apply normalization before `OverrideTurnContext` - `codex-rs/app-server/tests/suite/v2/turn_start.rs` - extended `turn_start_accepts_collaboration_mode_override_v2` to assert the outgoing request includes default-mode instruction text when the client sends `developer_instructions: null` - `codex-rs/app-server-protocol/src/protocol/v2.rs` - clarified `TurnStartParams.collaboration_mode` docs: `settings.developer_instructions: null` means use built-in mode instructions - regenerated schema fixture: - `codex-rs/app-server-protocol/schema/typescript/v2/TurnStartParams.ts` - docs: - `codex-rs/app-server/README.md` - `codex-rs/docs/codex_mcp_interface.md`
This commit is contained in:
committed by
GitHub
Unverified
parent
739908a12c
commit
e6662d6387
@@ -37,5 +37,8 @@ personality?: Personality | null, /**
|
||||
outputSchema?: JsonValue | null, /**
|
||||
* EXPERIMENTAL - Set a pre-set collaboration mode.
|
||||
* Takes precedence over model, reasoning_effort, and developer instructions if set.
|
||||
*
|
||||
* For `collaboration_mode.settings.developer_instructions`, `null` means
|
||||
* "use the built-in instructions for the selected mode".
|
||||
*/
|
||||
collaborationMode?: CollaborationMode | null};
|
||||
|
||||
@@ -2089,6 +2089,9 @@ pub struct TurnStartParams {
|
||||
|
||||
/// EXPERIMENTAL - Set a pre-set collaboration mode.
|
||||
/// Takes precedence over model, reasoning_effort, and developer instructions if set.
|
||||
///
|
||||
/// For `collaboration_mode.settings.developer_instructions`, `null` means
|
||||
/// "use the built-in instructions for the selected mode".
|
||||
#[experimental("turn/start.collaborationMode")]
|
||||
#[ts(optional = nullable)]
|
||||
pub collaboration_mode: Option<CollaborationMode>,
|
||||
|
||||
@@ -94,7 +94,7 @@ Example (from OpenAI's official VSCode extension):
|
||||
- `thread/unarchive` — move an archived rollout file back into the sessions directory; returns the restored `thread` on success.
|
||||
- `thread/compact/start` — trigger conversation history compaction for a thread; returns `{}` immediately while progress streams through standard turn/item notifications.
|
||||
- `thread/rollback` — drop the last N turns from the agent’s in-memory context and persist a rollback marker in the rollout so future resumes see the pruned history; returns the updated `thread` (with `turns` populated) on success.
|
||||
- `turn/start` — add user input to a thread and begin Codex generation; responds with the initial `turn` object and streams `turn/started`, `item/*`, and `turn/completed` notifications.
|
||||
- `turn/start` — add user input to a thread and begin Codex generation; responds with the initial `turn` object and streams `turn/started`, `item/*`, and `turn/completed` notifications. For `collaborationMode`, `settings.developer_instructions: null` means "use built-in instructions for the selected mode".
|
||||
- `turn/steer` — add user input to an already in-flight turn without starting a new turn; returns the active `turnId` that accepted the input.
|
||||
- `turn/interrupt` — request cancellation of an in-flight turn by `(thread_id, turn_id)`; success is an empty `{}` response and the turn finishes with `status: "interrupted"`.
|
||||
- `review/start` — kick off Codex’s automated reviewer for a thread; responds like `turn/start` and emits `item/started`/`item/completed` notifications with `enteredReviewMode` and `exitedReviewMode` items, plus a final assistant `agentMessage` containing the review.
|
||||
|
||||
@@ -206,6 +206,7 @@ use codex_login::ServerOptions as LoginServerOptions;
|
||||
use codex_login::ShutdownHandle;
|
||||
use codex_login::run_login_server;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::CollaborationMode;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
@@ -397,6 +398,27 @@ impl CodexMessageProcessor {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// If a client sends `developer_instructions: null` during a mode switch,
|
||||
/// use the built-in instructions for that mode.
|
||||
fn normalize_turn_start_collaboration_mode(
|
||||
&self,
|
||||
mut collaboration_mode: CollaborationMode,
|
||||
) -> CollaborationMode {
|
||||
if collaboration_mode.settings.developer_instructions.is_none()
|
||||
&& let Some(instructions) = self
|
||||
.thread_manager
|
||||
.list_collaboration_modes()
|
||||
.into_iter()
|
||||
.find(|preset| preset.mode == Some(collaboration_mode.mode))
|
||||
.and_then(|preset| preset.developer_instructions.flatten())
|
||||
.filter(|instructions| !instructions.is_empty())
|
||||
{
|
||||
collaboration_mode.settings.developer_instructions = Some(instructions);
|
||||
}
|
||||
|
||||
collaboration_mode
|
||||
}
|
||||
|
||||
fn review_request_from_target(
|
||||
target: ApiReviewTarget,
|
||||
) -> Result<(ReviewRequest, String), JSONRPCErrorError> {
|
||||
@@ -4554,6 +4576,10 @@ impl CodexMessageProcessor {
|
||||
}
|
||||
};
|
||||
|
||||
let collaboration_mode = params
|
||||
.collaboration_mode
|
||||
.map(|mode| self.normalize_turn_start_collaboration_mode(mode));
|
||||
|
||||
// Map v2 input items to core input items.
|
||||
let mapped_items: Vec<CoreInputItem> = params
|
||||
.input
|
||||
@@ -4567,7 +4593,7 @@ impl CodexMessageProcessor {
|
||||
|| params.model.is_some()
|
||||
|| params.effort.is_some()
|
||||
|| params.summary.is_some()
|
||||
|| params.collaboration_mode.is_some()
|
||||
|| collaboration_mode.is_some()
|
||||
|| params.personality.is_some();
|
||||
|
||||
// If any overrides are provided, update the session turn context first.
|
||||
@@ -4581,7 +4607,7 @@ impl CodexMessageProcessor {
|
||||
model: params.model,
|
||||
effort: params.effort.map(Some),
|
||||
summary: params.summary,
|
||||
collaboration_mode: params.collaboration_mode,
|
||||
collaboration_mode,
|
||||
personality: params.personality,
|
||||
})
|
||||
.await;
|
||||
|
||||
@@ -408,6 +408,8 @@ async fn turn_start_accepts_collaboration_mode_override_v2() -> Result<()> {
|
||||
let request = response_mock.single_request();
|
||||
let payload = request.body_json();
|
||||
assert_eq!(payload["model"].as_str(), Some("mock-model-collab"));
|
||||
let payload_text = payload.to_string();
|
||||
assert!(payload_text.contains("The `request_user_input` tool is unavailable in Default mode."));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@ Fetch the built-in collaboration mode presets with `collaborationMode/list`. Thi
|
||||
- `data` – ordered list of collaboration mode masks (partial settings to apply on top of the base mode)
|
||||
- For tri-state fields like `reasoning_effort` and `developer_instructions`, omit the field to keep the current value, set it to `null` to clear it, or set a concrete value to update it.
|
||||
|
||||
When sending `turn/start` with `collaborationMode`, `settings.developer_instructions: null` means "use built-in instructions for the selected mode".
|
||||
|
||||
## Event stream
|
||||
|
||||
While a conversation runs, the server sends notifications:
|
||||
|
||||
Reference in New Issue
Block a user