-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathclient_test.go
More file actions
125 lines (116 loc) · 3.13 KB
/
client_test.go
File metadata and controls
125 lines (116 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package aibridge_test
import (
"net/http"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/aibridge"
)
func TestGuessClient(t *testing.T) {
t.Parallel()
tests := []struct {
name string
userAgent string
headers map[string]string
wantClient aibridge.Client
}{
{
name: "mux",
userAgent: "mux/0.19.0-next.2.gcceff159 ai-sdk/openai/3.0.36 ai-sdk/provider-utils/4.0.15 runtime/node.js/22",
wantClient: aibridge.ClientMux,
},
{
name: "claude_code",
userAgent: "claude-cli/2.0.67 (external, cli)",
wantClient: aibridge.ClientClaudeCode,
},
{
name: "codex_cli",
userAgent: "codex_cli_rs/0.87.0 (Mac OS 26.2.0; arm64) ghostty/1.3.0-main_250877ef",
wantClient: aibridge.ClientCodex,
},
{
name: "zed",
userAgent: "Zed/0.219.4+stable.119.abc123 (macos; aarch64)",
wantClient: aibridge.ClientZed,
},
{
name: "github_copilot_vsc",
userAgent: "GitHubCopilotChat/0.37.2026011603",
wantClient: aibridge.ClientCopilotVSC,
},
{
name: "github_copilot_cli",
userAgent: "copilot/0.0.403 (client/cli linux v24.11.1)",
wantClient: aibridge.ClientCopilotCLI,
},
{
name: "kilo_code_user_agent",
userAgent: "kilo-code/5.1.0 (darwin 25.2.0; arm64) node/22.21.1",
wantClient: aibridge.ClientKilo,
},
{
name: "kilo_code_originator",
headers: map[string]string{"Originator": "kilo-code"},
wantClient: aibridge.ClientKilo,
},
{
name: "roo_code_user_agent",
userAgent: "roo-code/3.45.0 (darwin 25.2.0; arm64) node/22.21.1",
wantClient: aibridge.ClientRoo,
},
{
name: "roo_code_originator",
headers: map[string]string{"Originator": "roo-code"},
wantClient: aibridge.ClientRoo,
},
{
name: "coder_agents",
userAgent: "coder-agents/v2.24.0 (linux/amd64)",
wantClient: aibridge.ClientCoderAgents,
},
{
name: "coder_agents_dev",
userAgent: "coder-agents/v0.0.0-devel (darwin/arm64)",
wantClient: aibridge.ClientCoderAgents,
},
{
name: "charm_crush",
userAgent: "Charm Crush/0.1.11",
wantClient: aibridge.ClientCrush,
},
{
name: "cursor_x_cursor_client_version",
userAgent: "connect-es/1.6.1",
headers: map[string]string{"X-Cursor-client-version": "0.50.0"},
wantClient: aibridge.ClientCursor,
},
{
name: "cursor_x_cursor_some_other_header",
headers: map[string]string{"x-cursor-client-version": "abc123"},
wantClient: aibridge.ClientCursor,
},
{
name: "unknown_client",
userAgent: "ccclaude-cli/calude-with-wrong-prefix",
wantClient: aibridge.ClientUnknown,
},
{
name: "empty_user_agent",
userAgent: "",
wantClient: aibridge.ClientUnknown,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, "", nil)
require.NoError(t, err)
req.Header.Set("User-Agent", tt.userAgent)
for key, value := range tt.headers {
req.Header.Set(key, value)
}
got := aibridge.GuessClient(req)
require.Equal(t, tt.wantClient, got)
})
}
}