feat(api): expand Coding-Agent detection list
Description
Expands DetectCodingAgent (internal/api/coding_agent.go) so the Coding-Agent/<name> token in glab's User-Agent attributes traffic from three additional sources.
What changed
| Signal | Env condition | Returned name |
|---|---|---|
| Roo Code CLI | ROO_CLI_RUNTIME == "1" |
roo-code |
| GitLab Duo Agent Platform | AGENT_PLATFORM_GITLAB_VERSION != "" |
duo-agent-platform |
| Cursor terminal (fallback) | TERM_PROGRAM == "cursor" |
cursor-terminal |
| Windsurf terminal (fallback) | TERM_PROGRAM == "windsurf" (case-insensitive) |
windsurf-terminal |
| Zed terminal (fallback) | TERM_PROGRAM == "zed" |
zed-terminal |
Naming convention: the -terminal suffix
Explicit "agent invoked glab" signals (e.g. CLAUDECODE=1, CURSOR_AGENT=1) keep their plain names. TERM_PROGRAM-based signals get the -terminal suffix because they can fire for human-typed commands inside those IDE terminals as well as agent-driven invocations — analytics can then split true agent calls from "ran in an IDE terminal" context.
Precedence preserved
DetectCodingAgent still returns the first match. AI_AGENT wins, then the explicit per-agent env vars (alphabetical, existing behaviour), then the TERM_PROGRAM fallback. So CURSOR_AGENT=1 plus TERM_PROGRAM=cursor still resolves to cursor, not cursor-terminal.
Related Issues
Resolves #8318 (closed)
How has this been tested?
go test ./internal/api/ -run TestDetectCodingAgent -v— all 20 cases pass (8 new).go test ./internal/api/...— passes (no regression).gofmt -dandgo vet ./internal/api/...— clean.golangci-lint run ./internal/api/...—0 issues.- Local end-to-end build, then
GLAB_DEBUG_HTTP=1 glab auth statuswith each env var set; the User-Agent emits the expected token for each:ROO_CLI_RUNTIME=1→Coding-Agent/roo-codeAGENT_PLATFORM_GITLAB_VERSION=18.0.0→Coding-Agent/duo-agent-platformTERM_PROGRAM=Windsurf→Coding-Agent/windsurf-terminalCURSOR_AGENT=1+TERM_PROGRAM=cursor→Coding-Agent/cursor(precedence sanity)
Coordination
- A separate branch
add_gemini_cli_detectionis in flight, adding Gemini CLI (GEMINI_CLI=1→gemini). It doesn't overlap functionally; whichever lands first wins, and the other rebases. Any conflict is adjacent-line and trivial. - For
duo-agent-platform,AGENT_PLATFORM_GITLAB_VERSIONis documented as Duo Agent Platform-specific in the execution-variables docs. Happy to swap to a more explicit flag (e.g. a dedicatedDUO_AGENT=1) if the Duo team prefers.
Non-goals
- No agent version capture — keeping the existing name-only format.
- No separate HTTP header — staying with the existing
Coding-Agent/<name>UA token. - No Snowplow / product-analytics instrumentation — only the UA header is changed.