Skip to content

Commit 484fe95

Browse files
authored
Detect VS Code agent via VSCODE_AGENT, remove COPILOT_MODEL heuristic (#1697)
## Why [VS Code 1.121](https://code.visualstudio.com/updates/v1_121) introduced the `VSCODE_AGENT` environment variable, set for any agent-initiated terminal command (Copilot Chat agent mode and other agent extensions). This is the official signal for VS Code agent usage. The previous heuristic detected `COPILOT_MODEL` and reported `copilot-vscode`, but `COPILOT_MODEL` is actually set by Copilot CLI users who bring their own key, not specifically by VS Code. This produced false positives and required a BYOK collapse workaround (drop `copilot-vscode` whenever `COPILOT_CLI` was also set). Over the last 13 weeks, the heuristic identified 3 users / 52 events; `copilot-cli` saw 539 users / 175k events. The signal was effectively dead. ## Changes - Add `VSCODE_AGENT` to the known agents list, reported as `agent/vscode-agent`. - Remove the `COPILOT_MODEL` to `copilot-vscode` mapping. - Remove the `collapseCopilotBYOK` function. `VSCODE_AGENT` can legitimately stack with `COPILOT_CLI` (e.g. running Copilot CLI from a VS Code agent terminal), so the multi-agent path covers it without special handling. ## Tests - [x] Updated `agent_test.go`: new `vscode-agent` case, `VSCODE_AGENT + COPILOT_CLI` stacks to `multiple`. - [x] `make test` passes. - [x] `make fmt lint` clean. This PR mirrors parallel changes in [databricks-sdk-py](databricks/databricks-sdk-py#1444), [databricks-sdk-java](databricks/databricks-sdk-java#810), and [sdk-js](databricks/sdk-js#152). NO_CHANGELOG=true --------- Signed-off-by: simon <simon.faltum@databricks.com>
1 parent 85511e2 commit 484fe95

2 files changed

Lines changed: 8 additions & 42 deletions

File tree

useragent/agent.go

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ func listKnownAgents() []knownAgent {
4141
{envVar: "CLINE_ACTIVE", product: "cline"}, // https://github.com/cline/cline (v3.24.0+)
4242
{envVar: "CODEX_CI", product: "codex"}, // https://github.com/openai/codex
4343
{envVar: "COPILOT_CLI", product: "copilot-cli"}, // https://github.com/features/copilot
44-
{envVar: "COPILOT_MODEL", product: "copilot-vscode"}, // VS Code Copilot terminal, best-effort heuristic, not officially identified
4544
{envVar: "CURSOR_AGENT", product: "cursor"}, // Closed source
4645
{envVar: "GEMINI_CLI", product: "gemini-cli"}, // https://google-gemini.github.io/gemini-cli
4746
{envVar: "GOOSE_TERMINAL", product: "goose"}, // https://block.github.io/goose/ (also sets AGENT=goose, handled by the central fallback in lookupAgentProvider)
4847
{envVar: "KIRO", product: "kiro"}, // https://kiro.dev/ (Amazon)
4948
{envVar: "OPENCLAW_SHELL", product: "openclaw"}, // https://github.com/anthropics/openclaw
5049
{envVar: "OPENCODE", product: "opencode"}, // https://github.com/opencode-ai/opencode
50+
{envVar: "VSCODE_AGENT", product: "vscode-agent"}, // Set by VS Code 1.121+ for agent-initiated terminal commands (https://code.visualstudio.com/updates/v1_121)
5151
{envVar: "WINDSURF_AGENT", product: "windsurf"}, // https://codeium.com/windsurf (Codeium)
5252
}
5353
}
@@ -75,11 +75,6 @@ func lookupAgentProvider() string {
7575
}
7676
}
7777

78-
// Known BYOK false positive: Copilot CLI users often set COPILOT_MODEL
79-
// alongside COPILOT_CLI. That is a single copilot-cli signal, not a
80-
// stacked multi-agent setup, so drop the copilot-vscode match.
81-
matches = collapseCopilotBYOK(matches)
82-
8378
switch len(matches) {
8479
case 1:
8580
return matches[0]
@@ -90,29 +85,6 @@ func lookupAgentProvider() string {
9085
}
9186
}
9287

93-
func collapseCopilotBYOK(matches []string) []string {
94-
hasCLI, hasVSCode := false, false
95-
for _, m := range matches {
96-
if m == "copilot-cli" {
97-
hasCLI = true
98-
}
99-
if m == "copilot-vscode" {
100-
hasVSCode = true
101-
}
102-
}
103-
if !hasCLI || !hasVSCode {
104-
return matches
105-
}
106-
filtered := make([]string, 0, len(matches)-1)
107-
for _, m := range matches {
108-
if m == "copilot-vscode" {
109-
continue
110-
}
111-
filtered = append(filtered, m)
112-
}
113-
return filtered
114-
}
115-
11688
// agentEnvFallback returns a sanitized, length-capped name from AGENT
11789
// or AI_AGENT, preferring AGENT when both are non-empty. The value is
11890
// passed through rather than categorized so that new names are propagated

useragent/agent_test.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,9 @@ func TestLookupAgentProvider(t *testing.T) {
115115
expect: "augment",
116116
},
117117
{
118-
name: "copilot vscode",
119-
envs: map[string]string{"COPILOT_MODEL": "gpt-4"},
120-
expect: "copilot-vscode",
118+
name: "vscode-agent",
119+
envs: map[string]string{"VSCODE_AGENT": "1"},
120+
expect: "vscode-agent",
121121
},
122122
{
123123
name: "kiro",
@@ -176,17 +176,11 @@ func TestLookupAgentProvider(t *testing.T) {
176176
envs: map[string]string{"GOOSE_TERMINAL": "1", "AGENT": "cursor"},
177177
expect: "goose",
178178
},
179-
// Known BYOK false positive: Copilot CLI users often set COPILOT_MODEL
180-
// alongside COPILOT_CLI. The pair is treated as a single copilot-cli
181-
// signal rather than a stacked multi-agent setup.
179+
// VSCODE_AGENT can legitimately stack with other agents (e.g. running
180+
// Copilot CLI from a VS Code agent terminal).
182181
{
183-
name: "COPILOT_CLI + COPILOT_MODEL collapses to copilot-cli (BYOK)",
184-
envs: map[string]string{"COPILOT_CLI": "1", "COPILOT_MODEL": "gpt-4"},
185-
expect: "copilot-cli",
186-
},
187-
{
188-
name: "COPILOT_CLI + COPILOT_MODEL + CLAUDECODE still reports multiple after BYOK collapse",
189-
envs: map[string]string{"COPILOT_CLI": "1", "COPILOT_MODEL": "gpt-4", "CLAUDECODE": "1"},
182+
name: "VSCODE_AGENT + COPILOT_CLI reports multiple",
183+
envs: map[string]string{"VSCODE_AGENT": "1", "COPILOT_CLI": "1"},
190184
expect: "multiple",
191185
},
192186
// AI_AGENT fallback (Vercel @vercel/detect-agent convention).

0 commit comments

Comments
 (0)