From 94d47608ac0f91a90eb429fdaee3028d67e8a224 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 14 May 2026 15:34:46 -0700 Subject: [PATCH] Simplify turn context update plumbing --- .../src/protocol/common.rs | 27 +------- codex-rs/app-server/src/in_process.rs | 35 ----------- .../src/request_processors/turn_processor.rs | 62 +++++++++---------- 3 files changed, 29 insertions(+), 95 deletions(-) diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index b330f877fb..4afab97a91 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -2453,6 +2453,7 @@ mod tests { fn serialize_thread_turn_context_response_and_notification() -> Result<()> { let cwd = absolute_path("/tmp"); let turn_context = sample_thread_turn_context(cwd); + let turn_context_json = serde_json::to_value(&turn_context)?; let response = ClientResponse::ThreadTurnContextUpdate { request_id: RequestId::Integer(11), response: v2::ThreadTurnContextUpdateResponse { @@ -2465,32 +2466,6 @@ mod tests { turn_context, }, ); - let turn_context_json = json!({ - "model": "gpt-5", - "modelProvider": "openai", - "serviceTier": null, - "cwd": absolute_path_string("tmp"), - "approvalPolicy": "on-failure", - "approvalsReviewer": "user", - "sandboxPolicy": { - "type": "dangerFullAccess" - }, - "permissionProfile": { - "type": "disabled" - }, - "activePermissionProfile": null, - "effort": null, - "summary": null, - "personality": null, - "collaborationMode": { - "mode": "default", - "settings": { - "model": "gpt-5", - "reasoning_effort": null, - "developer_instructions": null - } - } - }); assert_eq!( json!({ diff --git a/codex-rs/app-server/src/in_process.rs b/codex-rs/app-server/src/in_process.rs index e4996d7921..a00bb62b29 100644 --- a/codex-rs/app-server/src/in_process.rs +++ b/codex-rs/app-server/src/in_process.rs @@ -732,19 +732,11 @@ mod tests { use codex_app_server_protocol::SessionSource as ApiSessionSource; use codex_app_server_protocol::ThreadStartParams; use codex_app_server_protocol::ThreadStartResponse; - use codex_app_server_protocol::ThreadTurnContext; - use codex_app_server_protocol::ThreadTurnContextUpdatedNotification; use codex_app_server_protocol::Turn; use codex_app_server_protocol::TurnCompletedNotification; use codex_app_server_protocol::TurnItemsView; use codex_app_server_protocol::TurnStatus; use codex_core::config::ConfigBuilder; - use codex_protocol::config_types::CollaborationMode; - use codex_protocol::config_types::ModeKind; - use codex_protocol::config_types::Settings; - use codex_protocol::models::PermissionProfile; - use codex_utils_absolute_path::test_support::PathBufExt; - use codex_utils_absolute_path::test_support::test_path_buf; use pretty_assertions::assert_eq; use std::path::Path; use tempfile::TempDir; @@ -901,32 +893,5 @@ mod tests { }, }) )); - assert!(server_notification_requires_delivery( - &ServerNotification::ThreadTurnContextUpdated(ThreadTurnContextUpdatedNotification { - thread_id: "thread-1".to_string(), - turn_context: ThreadTurnContext { - model: "gpt-5".to_string(), - model_provider: "openai".to_string(), - service_tier: None, - cwd: test_path_buf("/tmp/project").abs(), - approval_policy: codex_app_server_protocol::AskForApproval::Never, - approvals_reviewer: codex_app_server_protocol::ApprovalsReviewer::User, - sandbox_policy: codex_app_server_protocol::SandboxPolicy::DangerFullAccess, - permission_profile: PermissionProfile::read_only().into(), - active_permission_profile: None, - effort: None, - summary: None, - personality: None, - collaboration_mode: CollaborationMode { - mode: ModeKind::Default, - settings: Settings { - model: "gpt-5".to_string(), - reasoning_effort: None, - developer_instructions: None, - }, - }, - }, - }) - )); } } diff --git a/codex-rs/app-server/src/request_processors/turn_processor.rs b/codex-rs/app-server/src/request_processors/turn_processor.rs index 61bda506c2..abd21a4a7b 100644 --- a/codex-rs/app-server/src/request_processors/turn_processor.rs +++ b/codex-rs/app-server/src/request_processors/turn_processor.rs @@ -47,11 +47,6 @@ impl TurnContextOverrideRequest { } } -struct ResolvedTurnContextOverrides { - has_any_overrides: bool, - overrides: CodexThreadTurnContextOverrides, -} - const TURN_STARTED_ACK_TIMEOUT: Duration = Duration::from_secs(5); impl TurnRequestProcessor { @@ -364,14 +359,17 @@ impl TurnRequestProcessor { &self, base_snapshot: &ThreadConfigSnapshot, request: TurnContextOverrideRequest, - ) -> Result { + ) -> Result, JSONRPCErrorError> { if request.sandbox_policy.is_some() && request.permissions.is_some() { return Err(invalid_request( "`permissions` cannot be combined with `sandboxPolicy`", )); } - let has_any_overrides = request.has_any_overrides(); + if !request.has_any_overrides() { + return Ok(None); + } + let cwd = request.cwd; let approval_policy = request.approval_policy.map(AskForApproval::to_core); let approvals_reviewer = request @@ -417,26 +415,23 @@ impl TurnRequestProcessor { (None, None) }; - Ok(ResolvedTurnContextOverrides { - has_any_overrides, - overrides: CodexThreadTurnContextOverrides { - cwd, - approval_policy, - approvals_reviewer, - sandbox_policy, - permission_profile, - active_permission_profile, - windows_sandbox_level: None, - model: request.model, - effort: request.effort, - summary: request.summary, - service_tier: request.service_tier, - collaboration_mode: request - .collaboration_mode - .map(|mode| self.normalize_turn_start_collaboration_mode(mode)), - personality: request.personality, - }, - }) + Ok(Some(CodexThreadTurnContextOverrides { + cwd, + approval_policy, + approvals_reviewer, + sandbox_policy, + permission_profile, + active_permission_profile, + windows_sandbox_level: None, + model: request.model, + effort: request.effort, + summary: request.summary, + service_tier: request.service_tier, + collaboration_mode: request + .collaboration_mode + .map(|mode| self.normalize_turn_start_collaboration_mode(mode)), + personality: request.personality, + })) } async fn maybe_emit_turn_context_updated( @@ -519,17 +514,16 @@ impl TurnRequestProcessor { }, ) .await?; - let has_turn_context_overrides = resolved_overrides.has_any_overrides; - if has_turn_context_overrides { + let has_turn_context_overrides = resolved_overrides.is_some(); + if let Some(overrides) = resolved_overrides.as_ref() { thread - .preview_turn_context_overrides(resolved_overrides.overrides.clone()) + .preview_turn_context_overrides(overrides.clone()) .await .map_err(|err| invalid_request(format!("invalid turn context override: {err}")))?; } // Start the turn by submitting the user input. Return its submission id as turn_id. - let turn_op = if has_turn_context_overrides { - let overrides = resolved_overrides.overrides; + let turn_op = if let Some(overrides) = resolved_overrides { Op::UserInputWithTurnContext { items: mapped_items, environments: environment_selections, @@ -656,9 +650,9 @@ impl TurnRequestProcessor { ) .await?; - let after_snapshot = if resolved_overrides.has_any_overrides { + let after_snapshot = if let Some(overrides) = resolved_overrides { thread - .update_turn_context_overrides(resolved_overrides.overrides) + .update_turn_context_overrides(overrides) .await .map_err(|err| invalid_request(format!("invalid turn context override: {err}")))? } else {