Skip to content

Commit e86601f

Browse files
committed
feat: session detection for all supported clients
Signed-off-by: Danny Kopping <danny@coder.com>
1 parent 1afa42e commit e86601f

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

session.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ func guessSessionID(client Client, r *http.Request) string {
4949
return strings.TrimSpace(headers.Get("session_id"))
5050
case ClientMux:
5151
return strings.TrimSpace(headers.Get("X-Mux-Workspace-Id"))
52+
case ClientZed:
53+
return "" // Zed does not send a session ID from Zed Agent or Text Thread.
54+
case ClientCopilotVSC:
55+
// This does not map precisely to what we consider a session, but it's close enough.
56+
// Most other providers' equivalent of this would persist for the duration of a
57+
// conversation; it does seem to persist across an agentic loop though, which is
58+
// all we really need.
59+
//
60+
// There's also `vscode-sessionid` but that's persistent for the duration of the
61+
// VS Code window.
62+
return strings.TrimSpace(headers.Get("x-interaction-id"))
63+
case ClientCopilotCLI:
64+
return strings.TrimSpace(headers.Get("X-Client-Session-Id"))
65+
case ClientKilo:
66+
return strings.TrimSpace(headers.Get("X-KILOCODE-TASKID"))
67+
case ClientRoo:
68+
return "" // RooCode doesn't send a session ID.
69+
case ClientCursor:
70+
return "" // Cursor is not currently supported.
5271
default:
5372
return ""
5473
}

session_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,66 @@ func TestGuessSessionID(t *testing.T) {
8888
body: `{"metadata":{"user_id":"user_abc_account_456_session_some-id"}}`,
8989
sessionID: "",
9090
},
91+
// Mux.
92+
{
93+
name: "mux_with_workspace_header",
94+
client: ClientMux,
95+
headers: map[string]string{"X-Mux-Workspace-Id": "ws-abc-123"},
96+
sessionID: "ws-abc-123",
97+
},
98+
{
99+
name: "mux_without_workspace_header",
100+
client: ClientMux,
101+
sessionID: "",
102+
},
103+
// Copilot VS Code.
104+
{
105+
name: "copilot_vsc_with_interaction_id",
106+
client: ClientCopilotVSC,
107+
headers: map[string]string{"x-interaction-id": "interaction-xyz"},
108+
sessionID: "interaction-xyz",
109+
},
110+
{
111+
name: "copilot_vsc_without_interaction_id",
112+
client: ClientCopilotVSC,
113+
sessionID: "",
114+
},
115+
// Copilot CLI.
116+
{
117+
name: "copilot_cli_with_session_header",
118+
client: ClientCopilotCLI,
119+
headers: map[string]string{"X-Client-Session-Id": "cli-sess-456"},
120+
sessionID: "cli-sess-456",
121+
},
122+
{
123+
name: "copilot_cli_without_session_header",
124+
client: ClientCopilotCLI,
125+
sessionID: "",
126+
},
127+
// Kilo.
128+
{
129+
name: "kilo_with_task_id",
130+
client: ClientKilo,
131+
headers: map[string]string{"X-KILOCODE-TASKID": "task-789"},
132+
sessionID: "task-789",
133+
},
134+
{
135+
name: "kilo_without_task_id",
136+
client: ClientKilo,
137+
sessionID: "",
138+
},
139+
// Roo.
140+
{
141+
name: "roo_returns_empty",
142+
client: ClientRoo,
143+
sessionID: "",
144+
},
145+
// Cursor.
146+
{
147+
name: "cursor_returns_empty",
148+
client: ClientCursor,
149+
sessionID: "",
150+
},
91151
}
92152

93153
for _, tc := range cases {

0 commit comments

Comments
 (0)