From a81531146609a25847ae8d045f30234e6c7eafd7 Mon Sep 17 00:00:00 2001 From: ningyi-oai Date: Mon, 8 Jun 2026 10:49:59 -0700 Subject: [PATCH] Add HTTP window ID to Responses client metadata (#26923) ## Summary - Keep the existing `x-codex-window-id` HTTP header unchanged. - Also send the same window ID in Responses `client_metadata`, allowing supported backend paths to surface it as `x-client-meta-x-codex-window-id`. - Cover normal HTTP Responses and remote compaction v2 requests without changing window generation or compaction behavior. ## Why In the `2026-06-06T23` production hour, all 28,729 HTTP compaction requests had `window_id` in `x-codex-turn-metadata`, but only 73 retained the direct `x-codex-window-id` header. The request-body `client_metadata` path is already used for installation ID and is preserved through supported Responses API paths. This is additive metadata only. It does not change the direct header, request count, model input, compaction routing, window generation, or user response behavior. Legacy `/v1/responses/compact` is intentionally unchanged. Its current server-side `CompressBody` schema does not accept `client_metadata` and rejects unknown fields, so supporting that path requires a backend schema change before the Codex client can safely send this field. ## Validation - Current head: `219baef3c`, rebased onto `origin/main` at `26d932983`. - The post-rebase diff remains limited to the original five files (`22` insertions, `6` deletions); the legacy experiment remains fully reverted. - `just test -p codex-core responses_stream_includes_subagent_header_on_review`: passed; validates normal HTTP Responses metadata. - `just test -p codex-core remote_compact_v2_reuses_compaction_trigger_for_followups`: passed; validates remote compaction v2. - `just test -p codex-core remote_manual_compact_chatgpt_auth_reuses_service_tier_and_prompt_cache_key`: passed; validates that legacy compact keeps its accepted payload shape. - `just test -p codex-core remote_manual_compact_api_auth_omits_service_tier_and_reuses_prompt_cache_key`: passed; validates the legacy API-key payload as well. - `just fmt`: passed; an unrelated root `justfile` rewrite produced by the formatter was discarded. - `git diff --check origin/main...HEAD`: passed. The focused server pytest could not start in the local monorepo environment because test setup is missing the `dotenv` module. Server source and tests explicitly show that `CompressBody` omits `client_metadata` and `/v1/responses/compact` returns HTTP 400 for unknown body fields. --- codex-rs/core/src/client.rs | 14 ++++++++++---- codex-rs/core/tests/responses_headers.rs | 4 ++++ codex-rs/core/tests/suite/compact_remote.rs | 4 ++++ ...act_api_auth_prompt_cache_key_request_diff.snap | 3 ++- ...service_tier_prompt_cache_key_request_diff.snap | 3 ++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index dd7b9f400..02d231c96 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -802,10 +802,16 @@ impl ModelClient { service_tier, prompt_cache_key, text, - client_metadata: Some(HashMap::from([( - X_CODEX_INSTALLATION_ID_HEADER.to_string(), - self.state.installation_id.clone(), - )])), + client_metadata: Some(HashMap::from([ + ( + X_CODEX_INSTALLATION_ID_HEADER.to_string(), + self.state.installation_id.clone(), + ), + ( + X_CODEX_WINDOW_ID_HEADER.to_string(), + self.current_window_id(), + ), + ])), }; Ok(request) } diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index 75649fa4b..1ba93aec1 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -158,6 +158,10 @@ async fn responses_stream_includes_subagent_header_on_review() { request.body_json()["client_metadata"]["x-codex-installation-id"].as_str(), Some(TEST_INSTALLATION_ID) ); + assert_eq!( + request.body_json()["client_metadata"]["x-codex-window-id"].as_str(), + Some(expected_window_id.as_str()) + ); assert_eq!(request.header("x-codex-sandbox"), None); } diff --git a/codex-rs/core/tests/suite/compact_remote.rs b/codex-rs/core/tests/suite/compact_remote.rs index 2200c7b77..12fd570c5 100644 --- a/codex-rs/core/tests/suite/compact_remote.rs +++ b/codex-rs/core/tests/suite/compact_remote.rs @@ -883,6 +883,10 @@ async fn remote_compact_v2_reuses_compaction_trigger_for_followups() -> Result<( compact_metadata["window_id"].as_str(), compact_request.header("x-codex-window-id").as_deref() ); + assert_eq!( + compact_request.body_json()["client_metadata"]["x-codex-window-id"].as_str(), + compact_metadata["window_id"].as_str() + ); assert_eq!( compact_metadata["compaction"], json!({ diff --git a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_api_auth_prompt_cache_key_request_diff.snap b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_api_auth_prompt_cache_key_request_diff.snap index 750250f86..89796cb91 100644 --- a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_api_auth_prompt_cache_key_request_diff.snap +++ b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_api_auth_prompt_cache_key_request_diff.snap @@ -7,7 +7,8 @@ Scenario: After five varied API-key-auth turns, remote manual compaction omits s --- Last Normal /responses Request +++ Remote /responses/compact Request - "client_metadata": { -- "x-codex-installation-id": "" +- "x-codex-installation-id": "", +- "x-codex-window-id": ":0" - }, - "include": [ - "reasoning.encrypted_content" diff --git a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_chatgpt_auth_service_tier_prompt_cache_key_request_diff.snap b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_chatgpt_auth_service_tier_prompt_cache_key_request_diff.snap index e28ddd30d..ab6c9d1b3 100644 --- a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_chatgpt_auth_service_tier_prompt_cache_key_request_diff.snap +++ b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_manual_compact_chatgpt_auth_service_tier_prompt_cache_key_request_diff.snap @@ -7,7 +7,8 @@ Scenario: After five varied ChatGPT-auth turns, remote manual compaction reuses --- Last Normal /responses Request +++ Remote /responses/compact Request - "client_metadata": { -- "x-codex-installation-id": "" +- "x-codex-installation-id": "", +- "x-codex-window-id": ":0" - }, - "include": [ - "reasoning.encrypted_content"