feat(analytics): generate an installation_id and pass it in responsesapi client_metadata (#16912)

## Summary

This adds a stable Codex installation ID and includes it on Responses
API requests via `x-codex-installation-id` passed in via the
`client_metadata` field for analytics/debugging.

The main pieces are:
- persist a UUID in `$CODEX_HOME/installation_id`
- thread the installation ID into `ModelClient`
- send it in `client_metadata` on Responses requests so it works
consistently across HTTP and WebSocket transports
This commit is contained in:
Owen Lin
2026-04-07 09:52:17 -07:00
committed by GitHub
parent 2b9bf5d3d4
commit 5d1671ca70
12 changed files with 219 additions and 2 deletions

View File

@@ -55,6 +55,7 @@ const MODEL: &str = "gpt-5.2-codex";
const OPENAI_BETA_HEADER: &str = "OpenAI-Beta";
const WS_V2_BETA_HEADER_VALUE: &str = "responses_websockets=2026-02-06";
const X_CLIENT_REQUEST_ID_HEADER: &str = "x-client-request-id";
const TEST_INSTALLATION_ID: &str = "11111111-1111-4111-8111-111111111111";
fn assert_request_trace_matches(body: &serde_json::Value, expected_trace: &W3cTraceContext) {
let client_metadata = body["client_metadata"]
@@ -125,6 +126,10 @@ async fn responses_websocket_streams_request() {
handshake.header(X_CLIENT_REQUEST_ID_HEADER),
Some(harness.conversation_id.to_string())
);
assert_eq!(
body["client_metadata"]["x-codex-installation-id"].as_str(),
Some(TEST_INSTALLATION_ID)
);
server.shutdown().await;
}
@@ -1756,6 +1761,7 @@ async fn websocket_harness_with_provider_options(
let client = ModelClient::new(
/*auth_manager*/ None,
conversation_id,
/*installation_id*/ TEST_INSTALLATION_ID.to_string(),
provider.clone(),
SessionSource::Exec,
config.model_verbosity,