From 034b4377f7fc9b99fa1ebcbd85fa7126c38ab2b7 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 May 2026 13:31:44 +0200 Subject: [PATCH 1/3] Detect VS Code agent via VSCODE_AGENT, remove COPILOT_MODEL heuristic VS Code 1.121+ sets VSCODE_AGENT for agent-initiated terminal commands. Detect it as `vscode-agent` in the User-Agent header. The previous COPILOT_MODEL heuristic reported `copilot-vscode` but COPILOT_MODEL is set by Copilot CLI BYOK users, not specifically by VS Code. The BYOK collapse logic (drop copilot-vscode when COPILOT_CLI is also set) is removed alongside the heuristic; VSCODE_AGENT can legitimately stack with COPILOT_CLI, which now correctly reports `multiple`. See: https://code.visualstudio.com/updates/v1_121 Signed-off-by: simon --- NEXT_CHANGELOG.md | 2 ++ useragent/agent.go | 30 +----------------------------- useragent/agent_test.go | 23 +++++++++++------------ 3 files changed, 14 insertions(+), 41 deletions(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index c17546bd3..ffc7c815b 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -6,6 +6,8 @@ ### New Features and Improvements +* Detect VS Code agent-initiated terminal commands via the `VSCODE_AGENT` environment variable (VS Code 1.121+). The User-Agent header now reports `agent/vscode-agent` when set. The previous `COPILOT_MODEL` heuristic (which reported `agent/copilot-vscode`) has been removed; it produced false positives for Copilot CLI BYOK users and never reliably identified VS Code. + ### Bug Fixes ### Documentation diff --git a/useragent/agent.go b/useragent/agent.go index 2b1163700..da84ac01a 100644 --- a/useragent/agent.go +++ b/useragent/agent.go @@ -41,13 +41,13 @@ func listKnownAgents() []knownAgent { {envVar: "CLINE_ACTIVE", product: "cline"}, // https://github.com/cline/cline (v3.24.0+) {envVar: "CODEX_CI", product: "codex"}, // https://github.com/openai/codex {envVar: "COPILOT_CLI", product: "copilot-cli"}, // https://github.com/features/copilot - {envVar: "COPILOT_MODEL", product: "copilot-vscode"}, // VS Code Copilot terminal, best-effort heuristic, not officially identified {envVar: "CURSOR_AGENT", product: "cursor"}, // Closed source {envVar: "GEMINI_CLI", product: "gemini-cli"}, // https://google-gemini.github.io/gemini-cli {envVar: "GOOSE_TERMINAL", product: "goose"}, // https://block.github.io/goose/ (also sets AGENT=goose, handled by the central fallback in lookupAgentProvider) {envVar: "KIRO", product: "kiro"}, // https://kiro.dev/ (Amazon) {envVar: "OPENCLAW_SHELL", product: "openclaw"}, // https://github.com/anthropics/openclaw {envVar: "OPENCODE", product: "opencode"}, // https://github.com/opencode-ai/opencode + {envVar: "VSCODE_AGENT", product: "vscode-agent"}, // Set by VS Code 1.121+ for agent-initiated terminal commands (https://code.visualstudio.com/updates/v1_121) {envVar: "WINDSURF_AGENT", product: "windsurf"}, // https://codeium.com/windsurf (Codeium) } } @@ -75,11 +75,6 @@ func lookupAgentProvider() string { } } - // Known BYOK false positive: Copilot CLI users often set COPILOT_MODEL - // alongside COPILOT_CLI. That is a single copilot-cli signal, not a - // stacked multi-agent setup, so drop the copilot-vscode match. - matches = collapseCopilotBYOK(matches) - switch len(matches) { case 1: return matches[0] @@ -90,29 +85,6 @@ func lookupAgentProvider() string { } } -func collapseCopilotBYOK(matches []string) []string { - hasCLI, hasVSCode := false, false - for _, m := range matches { - if m == "copilot-cli" { - hasCLI = true - } - if m == "copilot-vscode" { - hasVSCode = true - } - } - if !hasCLI || !hasVSCode { - return matches - } - filtered := make([]string, 0, len(matches)-1) - for _, m := range matches { - if m == "copilot-vscode" { - continue - } - filtered = append(filtered, m) - } - return filtered -} - // agentEnvFallback returns a sanitized, length-capped name from AGENT // or AI_AGENT, preferring AGENT when both are non-empty. The value is // passed through rather than categorized so that new names are propagated diff --git a/useragent/agent_test.go b/useragent/agent_test.go index 6c2f13706..fc8fc374f 100644 --- a/useragent/agent_test.go +++ b/useragent/agent_test.go @@ -115,9 +115,14 @@ func TestLookupAgentProvider(t *testing.T) { expect: "augment", }, { - name: "copilot vscode", + name: "vscode-agent", + envs: map[string]string{"VSCODE_AGENT": "1"}, + expect: "vscode-agent", + }, + { + name: "COPILOT_MODEL alone is no longer detected", envs: map[string]string{"COPILOT_MODEL": "gpt-4"}, - expect: "copilot-vscode", + expect: "", }, { name: "kiro", @@ -176,17 +181,11 @@ func TestLookupAgentProvider(t *testing.T) { envs: map[string]string{"GOOSE_TERMINAL": "1", "AGENT": "cursor"}, expect: "goose", }, - // Known BYOK false positive: Copilot CLI users often set COPILOT_MODEL - // alongside COPILOT_CLI. The pair is treated as a single copilot-cli - // signal rather than a stacked multi-agent setup. - { - name: "COPILOT_CLI + COPILOT_MODEL collapses to copilot-cli (BYOK)", - envs: map[string]string{"COPILOT_CLI": "1", "COPILOT_MODEL": "gpt-4"}, - expect: "copilot-cli", - }, + // VSCODE_AGENT can legitimately stack with other agents (e.g. running + // Copilot CLI from a VS Code agent terminal). { - name: "COPILOT_CLI + COPILOT_MODEL + CLAUDECODE still reports multiple after BYOK collapse", - envs: map[string]string{"COPILOT_CLI": "1", "COPILOT_MODEL": "gpt-4", "CLAUDECODE": "1"}, + name: "VSCODE_AGENT + COPILOT_CLI reports multiple", + envs: map[string]string{"VSCODE_AGENT": "1", "COPILOT_CLI": "1"}, expect: "multiple", }, // AI_AGENT fallback (Vercel @vercel/detect-agent convention). From a2ce8efc856fe07caa8964af0bc1cd51f4d367c3 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 May 2026 13:39:49 +0200 Subject: [PATCH 2/3] Drop the residual COPILOT_MODEL test case Signed-off-by: simon --- useragent/agent_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/useragent/agent_test.go b/useragent/agent_test.go index fc8fc374f..096d08e3b 100644 --- a/useragent/agent_test.go +++ b/useragent/agent_test.go @@ -119,11 +119,6 @@ func TestLookupAgentProvider(t *testing.T) { envs: map[string]string{"VSCODE_AGENT": "1"}, expect: "vscode-agent", }, - { - name: "COPILOT_MODEL alone is no longer detected", - envs: map[string]string{"COPILOT_MODEL": "gpt-4"}, - expect: "", - }, { name: "kiro", envs: map[string]string{"KIRO": "1"}, From 101a3c7c94d09e12d9b0caa2a02ceff98b819c51 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 26 May 2026 13:50:57 +0200 Subject: [PATCH 3/3] Drop NEXT_CHANGELOG entry (NO_CHANGELOG=true) Signed-off-by: simon --- NEXT_CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index ffc7c815b..c17546bd3 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -6,8 +6,6 @@ ### New Features and Improvements -* Detect VS Code agent-initiated terminal commands via the `VSCODE_AGENT` environment variable (VS Code 1.121+). The User-Agent header now reports `agent/vscode-agent` when set. The previous `COPILOT_MODEL` heuristic (which reported `agent/copilot-vscode`) has been removed; it produced false positives for Copilot CLI BYOK users and never reliably identified VS Code. - ### Bug Fixes ### Documentation