diff --git a/codex-rs/app-server-protocol/schema/json/ModelCompactParams.json b/codex-rs/app-server-protocol/schema/json/ModelCompactParams.json index 75826430fc..5f7d04239c 100644 --- a/codex-rs/app-server-protocol/schema/json/ModelCompactParams.json +++ b/codex-rs/app-server-protocol/schema/json/ModelCompactParams.json @@ -649,6 +649,12 @@ "call_id": { "type": "string" }, + "name": { + "type": [ + "string", + "null" + ] + }, "output": { "$ref": "#/definitions/FunctionCallOutputBody" }, diff --git a/codex-rs/app-server-protocol/schema/json/ModelCompactResponse.json b/codex-rs/app-server-protocol/schema/json/ModelCompactResponse.json index d830d585f4..a51228e55e 100644 --- a/codex-rs/app-server-protocol/schema/json/ModelCompactResponse.json +++ b/codex-rs/app-server-protocol/schema/json/ModelCompactResponse.json @@ -607,6 +607,12 @@ "call_id": { "type": "string" }, + "name": { + "type": [ + "string", + "null" + ] + }, "output": { "$ref": "#/definitions/FunctionCallOutputBody" }, diff --git a/codex-rs/app-server-protocol/schema/json/ModelRequestParams.json b/codex-rs/app-server-protocol/schema/json/ModelRequestParams.json index 9d3b1afea7..a052c3d70c 100644 --- a/codex-rs/app-server-protocol/schema/json/ModelRequestParams.json +++ b/codex-rs/app-server-protocol/schema/json/ModelRequestParams.json @@ -680,6 +680,12 @@ "call_id": { "type": "string" }, + "name": { + "type": [ + "string", + "null" + ] + }, "output": { "$ref": "#/definitions/FunctionCallOutputBody" }, diff --git a/codex-rs/app-server-protocol/schema/json/ServerRequest.json b/codex-rs/app-server-protocol/schema/json/ServerRequest.json index 70c20a59a4..377dcc2309 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ServerRequest.json @@ -2276,6 +2276,12 @@ "call_id": { "type": "string" }, + "name": { + "type": [ + "string", + "null" + ] + }, "output": { "$ref": "#/definitions/FunctionCallOutputBody" }, diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 48a5f23147..93259c0d36 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -421,6 +421,10 @@ impl CodexMessageProcessor { self.thread_state_manager.clone() } + pub(crate) fn clear_runtime_references(&self) { + self.thread_manager.set_delegated_model_transport(None); + } + pub(crate) fn clear_plugin_related_caches(&self) { self.thread_manager.plugins_manager().clear_cache(); self.thread_manager.skills_manager().clear_cache(); diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index 18298d1a44..f4094786bb 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -279,6 +279,7 @@ impl MessageProcessor { } pub(crate) fn clear_runtime_references(&self) { + self.codex_message_processor.clear_runtime_references(); self.auth_manager.clear_external_auth_refresher(); } diff --git a/codex-rs/app-server/tests/suite/v2/command_exec.rs b/codex-rs/app-server/tests/suite/v2/command_exec.rs index ecd897eb84..abf51f7c0c 100644 --- a/codex-rs/app-server/tests/suite/v2/command_exec.rs +++ b/codex-rs/app-server/tests/suite/v2/command_exec.rs @@ -744,11 +744,14 @@ async fn command_exec_process_ids_are_connection_scoped_and_disconnect_terminate ) .await?; - let delta = read_command_exec_delta_ws(&mut ws1).await?; - assert_eq!(delta.process_id, "shared-process"); - assert_eq!(delta.stream, CommandExecOutputStream::Stdout); - let delta_text = String::from_utf8(STANDARD.decode(&delta.delta_base64)?)?; - assert!(delta_text.contains("ready")); + let stdout = read_command_exec_output_ws_until_contains( + &mut ws1, + "shared-process", + CommandExecOutputStream::Stdout, + "ready", + ) + .await?; + assert!(stdout.contains("ready")); wait_for_process_marker(&marker, true).await?; send_request( @@ -839,6 +842,37 @@ async fn read_command_exec_delta_ws( } } +async fn read_command_exec_output_ws_until_contains( + stream: &mut super::connection_handling_websocket::WsClient, + process_id: &str, + expected_stream: CommandExecOutputStream, + expected: &str, +) -> Result { + let deadline = Instant::now() + DEFAULT_READ_TIMEOUT; + let mut collected = String::new(); + + loop { + let remaining = deadline.saturating_duration_since(Instant::now()); + let delta = timeout(remaining, read_command_exec_delta_ws(stream)) + .await + .with_context(|| { + format!( + "timed out waiting for {expected:?} in websocket command/exec output for {process_id}; collected {collected:?}" + ) + })??; + assert_eq!(delta.process_id, process_id); + if delta.stream != expected_stream { + continue; + } + + let delta_text = String::from_utf8(STANDARD.decode(&delta.delta_base64)?)?; + collected.push_str(&delta_text.replace('\r', "")); + if collected.contains(expected) { + return Ok(collected); + } + } +} + fn decode_delta_notification( notification: JSONRPCNotification, ) -> Result {