From 9afd3d0bea603d6d7fa188dae01fcff2ac48fa10 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Mon, 8 Jun 2026 10:12:03 +0200 Subject: [PATCH] feat: track OpenCode sessions (#26128) This follows #26098 by teaching AI Bridge to read OpenCode session IDs from the X-OpenCode-Session header, so OpenCode requests are grouped consistently in interception logs. Adds unit and integration test coverage for the new header.
Coder Agents generated This pull request was generated with Coder Agents assistance.
--- .../integrationtest/bridge_internal_test.go | 10 ++++++++++ aibridge/session.go | 2 ++ aibridge/session_test.go | 17 +++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/aibridge/internal/integrationtest/bridge_internal_test.go b/aibridge/internal/integrationtest/bridge_internal_test.go index 7a8ae1116f..8c6804c247 100644 --- a/aibridge/internal/integrationtest/bridge_internal_test.go +++ b/aibridge/internal/integrationtest/bridge_internal_test.go @@ -1049,6 +1049,16 @@ func TestSessionIDTracking(t *testing.T) { "User-Agent": []string{"Zed/0.219.4+stable.119.abc123 (macos; aarch64)"}, }, }, + { + name: "opencode", + fixture: fixtures.AntSimple, + expectedClient: aibridge.ClientOpenCode, + expectSessionID: "ses_15a48edefffe7oY0YcIHRv29dD", + header: http.Header{ + "User-Agent": []string{"opencode/1.16.0 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14"}, + "X-OpenCode-Session": []string{"ses_15a48edefffe7oY0YcIHRv29dD"}, + }, + }, } for _, tc := range testCases { diff --git a/aibridge/session.go b/aibridge/session.go index a97fdaef2a..759a2e69f1 100644 --- a/aibridge/session.go +++ b/aibridge/session.go @@ -75,6 +75,8 @@ func GuessSessionID(client Client, r *http.Request) *string { return cleanRef(r.Header.Get("X-KILOCODE-TASKID")) case ClientCoderAgents: return cleanRef(r.Header.Get("X-Coder-Chat-Id")) + case ClientOpenCode: + return cleanRef(r.Header.Get("X-OpenCode-Session")) case ClientCrush: return nil // Crush does not send a session ID header. case ClientRoo: diff --git a/aibridge/session_test.go b/aibridge/session_test.go index 90b27ce705..f1fb7614f4 100644 --- a/aibridge/session_test.go +++ b/aibridge/session_test.go @@ -182,6 +182,23 @@ func TestGuessSessionID(t *testing.T) { name: "coder_agents_without_chat_id", client: aibridge.ClientCoderAgents, }, + // OpenCode. + { + name: "opencode_with_session_header", + client: aibridge.ClientOpenCode, + headers: map[string]string{"X-OpenCode-Session": "ses_15a48edefffe7oY0YcIHRv29dD"}, + sessionID: utils.PtrTo("ses_15a48edefffe7oY0YcIHRv29dD"), + }, + { + name: "opencode_with_whitespace_in_header", + client: aibridge.ClientOpenCode, + headers: map[string]string{"X-OpenCode-Session": " ses_15a48edefffe7oY0YcIHRv29dD "}, + sessionID: utils.PtrTo("ses_15a48edefffe7oY0YcIHRv29dD"), + }, + { + name: "opencode_without_session_header", + client: aibridge.ClientOpenCode, + }, // Crush. { name: "crush_returns_empty",