provider.go

v0.7.0
Doc Versions Source
1
package provider
2
3
// StaticModel represents a model available from a provider (no API fetch needed).
4
type StaticModel struct {
5
	ID     string
6
	Name   string
7
	Family string
8
}
9
10
// Plan describes one billing/access plan for a provider with multiple base URLs.
11
type Plan struct {
12
	Key         string // e.g. "api", "coding"
13
	Name        string // display name, e.g. "API (pay per token)"
14
	Description string
15
	BaseURL     string
16
	Compat      string // optional override; when set, switches the provider's Compat mode
17
	AuthEnvVar  string // optional override; when set, switches the auth env var
18
}
19
20
var zaiModels = []StaticModel{
21
	{ID: "glm-5", Name: "GLM-5", Family: "GLM-5"},
22
	{ID: "glm-5-turbo", Name: "GLM-5 Turbo", Family: "GLM-5"},
23
	{ID: "glm-4.7", Name: "GLM-4.7", Family: "GLM-4.7"},
24
	{ID: "glm-4.7-flash", Name: "GLM-4.7 Flash", Family: "GLM-4.7"},
25
	{ID: "glm-4.7-flashx", Name: "GLM-4.7 FlashX", Family: "GLM-4.7"},
26
	{ID: "glm-4.6", Name: "GLM-4.6", Family: "GLM-4.6"},
27
	{ID: "glm-4.5", Name: "GLM-4.5", Family: "GLM-4.5"},
28
	{ID: "glm-4.5-air", Name: "GLM-4.5 Air", Family: "GLM-4.5"},
29
	{ID: "glm-4.5-x", Name: "GLM-4.5 X", Family: "GLM-4.5"},
30
	{ID: "glm-4.5-airx", Name: "GLM-4.5 AirX", Family: "GLM-4.5"},
31
	{ID: "glm-4.5-flash", Name: "GLM-4.5 Flash", Family: "GLM-4.5"},
32
	{ID: "glm-4-32b-0414-128k", Name: "GLM-4 32B", Family: "GLM-4"},
33
}
34
35
var zaiCodingModels = []StaticModel{
36
	{ID: "glm-5.1", Name: "GLM-5.1", Family: "GLM-5"},
37
	{ID: "glm-5", Name: "GLM-5", Family: "GLM-5"},
38
	{ID: "glm-5-turbo", Name: "GLM-5 Turbo", Family: "GLM-5"},
39
	{ID: "glm-4.7", Name: "GLM-4.7", Family: "GLM-4.7"},
40
	{ID: "glm-4.7-flash", Name: "GLM-4.7 Flash", Family: "GLM-4.7"},
41
	{ID: "glm-4.7-flashx", Name: "GLM-4.7 FlashX", Family: "GLM-4.7"},
42
	{ID: "glm-4.5-air", Name: "GLM-4.5 Air", Family: "GLM-4.5"},
43
}
44
45
// Kimi Code exposes an Anthropic-compatible gateway at /coding/ and does not
46
// serve a listable models endpoint there, so we ship a static catalog.
47
var kimiCodeModels = []StaticModel{
48
	{ID: "kimi-k2.6", Name: "Kimi K2.6", Family: "Kimi K2"},
49
	{ID: "kimi-k2.5", Name: "Kimi K2.5", Family: "Kimi K2"},
50
	{ID: "kimi-k2-turbo-preview", Name: "Kimi K2 Turbo (preview)", Family: "Kimi K2"},
51
}
52
53
// StaticModels maps provider keys to their available models.
54
var StaticModels = map[string][]StaticModel{
55
	"zai":        zaiModels,
56
	"zai-coding": zaiCodingModels,
57
	"kimi":       kimiCodeModels,
58
}
59
60
// Provider defines an alternative Claude Code API provider.
61
type Provider struct {
62
	Name        string
63
	Description string
64
	BaseURL     string
65
	Model       string
66
	SmallModel  string
67
	SonnetModel string
68
	OpusModel   string
69
	HaikuModel  string
70
	TimeoutMS   string
71
	// AuthEnvVar is the env var name used for the API key (some use AUTH_TOKEN, some API_KEY).
72
	AuthEnvVar string
73
	// Compat is "anthropic" (default) or "openai". When "openai", a local
74
	// translation proxy is started to convert Anthropic ↔ OpenAI API format.
75
	Compat string
76
	// ContextWindow is the model's context window size in tokens.
77
	// Claude Code assumes 200k by default; when this is smaller,
78
	// CLAUDE_AUTOCOMPACT_PCT_OVERRIDE is set so compaction triggers before
79
	// the real limit is hit.
80
	ContextWindow int
81
	// NoAuth indicates the provider does not require an API key (e.g. local Ollama).
82
	NoAuth bool
83
	// Plans lists alternative billing/access plans with different base URLs.
84
	// When non-empty, the TUI prompts the user to choose a plan.
85
	// BaseURL holds the default plan's URL.
86
	Plans []Plan
87
}
88
89
var Registry = map[string]Provider{
90
	"deepseek": {
91
		Name:          "DeepSeek",
92
		Description:   "DeepSeek Reasoner / V3 via Anthropic-compatible API",
93
		BaseURL:       "https://api.deepseek.com/anthropic",
94
		Model:         "deepseek-reasoner",
95
		SmallModel:    "deepseek-chat",
96
		SonnetModel:   "deepseek-reasoner",
97
		OpusModel:     "deepseek-reasoner",
98
		HaikuModel:    "deepseek-chat",
99
		TimeoutMS:     "600000",
100
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
101
		ContextWindow: 128_000,
102
	},
103
	"zai": {
104
		Name:          "z.AI API",
105
		Description:   "GLM-5 / GLM-4.7 via z.AI (pay-per-token)",
106
		BaseURL:       "https://api.z.ai/api/anthropic",
107
		Model:         "glm-5",
108
		SmallModel:    "glm-4.5-air",
109
		SonnetModel:   "glm-5",
110
		OpusModel:     "glm-5",
111
		HaikuModel:    "glm-4.5-air",
112
		TimeoutMS:     "3000000",
113
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
114
		ContextWindow: 205_000,
115
	},
116
	"zai-coding": {
117
		Name:          "z.AI Coding",
118
		Description:   "GLM-5.1 / GLM-5 via z.AI (subscription)",
119
		BaseURL:       "https://api.z.ai/api/coding/anthropic",
120
		Model:         "glm-5.1",
121
		SmallModel:    "glm-4.5-air",
122
		SonnetModel:   "glm-5.1",
123
		OpusModel:     "glm-5.1",
124
		HaikuModel:    "glm-4.5-air",
125
		TimeoutMS:     "3000000",
126
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
127
		ContextWindow: 205_000,
128
	},
129
	"minimax": {
130
		Name:          "MiniMax",
131
		Description:   "MiniMax-M2.5 via MiniMax Anthropic gateway",
132
		BaseURL:       "https://api.minimax.io/anthropic",
133
		Model:         "MiniMax-M2.5",
134
		SmallModel:    "MiniMax-M2.5",
135
		SonnetModel:   "MiniMax-M2.5",
136
		OpusModel:     "MiniMax-M2.5",
137
		HaikuModel:    "MiniMax-M2.5",
138
		TimeoutMS:     "3000000",
139
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
140
		ContextWindow: 205_000,
141
	},
142
	"kimi": {
143
		Name:          "Kimi Code",
144
		Description:   "Kimi K2.5 / K2 via Kimi Code (International)",
145
		BaseURL:       "https://api.kimi.com/coding/",
146
		Model:         "kimi-k2.5",
147
		SmallModel:    "kimi-k2-turbo-preview",
148
		SonnetModel:   "kimi-k2.5",
149
		OpusModel:     "kimi-k2.5",
150
		HaikuModel:    "kimi-k2-turbo-preview",
151
		TimeoutMS:     "600000",
152
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
153
		ContextWindow: 256_000,
154
	},
155
	"kimi-api-cn": {
156
		Name:          "Kimi API (China)",
157
		Description:   "Kimi via Moonshot Open Platform (api.moonshot.cn)",
158
		BaseURL:       "https://api.moonshot.cn/v1/",
159
		Model:         "kimi-k2.5",
160
		SmallModel:    "kimi-k2-turbo-preview",
161
		SonnetModel:   "kimi-k2.5",
162
		OpusModel:     "kimi-k2.5",
163
		HaikuModel:    "kimi-k2-turbo-preview",
164
		TimeoutMS:     "600000",
165
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
166
		ContextWindow: 256_000,
167
		Compat:        "openai",
168
	},
169
	"kimi-api-intl": {
170
		Name:          "Kimi API (Intl)",
171
		Description:   "Kimi via Moonshot Open Platform (api.moonshot.ai)",
172
		BaseURL:       "https://api.moonshot.ai/v1/",
173
		Model:         "kimi-k2.5",
174
		SmallModel:    "kimi-k2-turbo-preview",
175
		SonnetModel:   "kimi-k2.5",
176
		OpusModel:     "kimi-k2.5",
177
		HaikuModel:    "kimi-k2-turbo-preview",
178
		TimeoutMS:     "600000",
179
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
180
		ContextWindow: 256_000,
181
		Compat:        "openai",
182
	},
183
	"mistral": {
184
		Name:          "Mistral",
185
		Description:   "Devstral / Mistral Large via OpenAI-compatible API",
186
		BaseURL:       "https://api.mistral.ai/v1",
187
		Model:         "devstral-latest",
188
		SmallModel:    "devstral-small-latest",
189
		SonnetModel:   "devstral-latest",
190
		OpusModel:     "devstral-latest",
191
		HaikuModel:    "devstral-small-latest",
192
		TimeoutMS:     "600000",
193
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
194
		Compat:        "openai",
195
		ContextWindow: 256_000,
196
	},
197
	"copilot": {
198
		Name:          "GitHub Copilot",
199
		Description:   "Claude via GitHub Copilot",
200
		BaseURL:       "https://api.githubcopilot.com",
201
		Model:         "claude-sonnet-4.6",
202
		SmallModel:    "claude-haiku-4.5",
203
		SonnetModel:   "claude-sonnet-4.6",
204
		OpusModel:     "claude-opus-4.6",
205
		HaikuModel:    "claude-haiku-4.5",
206
		TimeoutMS:     "600000",
207
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
208
		Compat:        "openai",
209
		ContextWindow: 200_000,
210
	},
211
	"nvidia": {
212
		Name:          "NVIDIA NIM",
213
		Description:   "Access NVIDIA NIM models via OpenAI-compatible API",
214
		BaseURL:       "https://integrate.api.nvidia.com/v1",
215
		Model:         "nvidia/llama-3.1-nemotron-ultra-253b-v1",
216
		SmallModel:    "nvidia/llama-3.3-nemotron-super-49b-v1.5",
217
		SonnetModel:   "nvidia/llama-3.1-nemotron-ultra-253b-v1",
218
		OpusModel:     "nvidia/llama-3.1-nemotron-ultra-253b-v1",
219
		HaikuModel:    "nvidia/llama-3.3-nemotron-super-49b-v1.5",
220
		TimeoutMS:     "600000",
221
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
222
		Compat:        "openai",
223
		ContextWindow: 128_000,
224
	},
225
	"openrouter": {
226
		Name:          "OpenRouter",
227
		Description:   "Access multiple models via OpenRouter",
228
		BaseURL:       "https://openrouter.ai/api/v1",
229
		Model:         "anthropic/claude-sonnet-4.6",
230
		SmallModel:    "anthropic/claude-haiku-4.5",
231
		SonnetModel:   "anthropic/claude-sonnet-4.6",
232
		OpusModel:     "anthropic/claude-opus-4.6",
233
		HaikuModel:    "anthropic/claude-haiku-4.5",
234
		TimeoutMS:     "600000",
235
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
236
		Compat:        "openai",
237
		ContextWindow: 200_000,
238
	},
239
	"vkproxy": {
240
		Name:          "VK LLM Proxy",
241
		Description:   "Import models from claude-code-config.zip",
242
		BaseURL:       "https://llm-proxy.vkteam.ru",
243
		Model:         "deepseek-reasoner",
244
		SmallModel:    "deepseek-reasoner",
245
		SonnetModel:   "deepseek-reasoner",
246
		OpusModel:     "deepseek-reasoner",
247
		HaikuModel:    "deepseek-reasoner",
248
		TimeoutMS:     "600000",
249
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
250
		ContextWindow: 128_000,
251
	},
252
	"ollama": {
253
		Name:          "Ollama (local)",
254
		Description:   "Local Ollama with native Anthropic-compatible API",
255
		BaseURL:       "http://localhost:11434",
256
		Model:         "qwen3-coder",
257
		SmallModel:    "qwen3-coder",
258
		SonnetModel:   "qwen3-coder",
259
		OpusModel:     "qwen3-coder",
260
		HaikuModel:    "qwen3-coder",
261
		TimeoutMS:     "600000",
262
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
263
		ContextWindow: 32_000,
264
		NoAuth:        true,
265
	},
266
	"ollama-cloud": {
267
		Name:          "Ollama Cloud",
268
		Description:   "Cloud models via ollama.com API",
269
		BaseURL:       "https://ollama.com",
270
		Model:         "qwen3.5:397b",
271
		SmallModel:    "devstral-small-2:24b",
272
		SonnetModel:   "devstral-2:123b",
273
		OpusModel:     "qwen3.5:397b",
274
		HaikuModel:    "devstral-small-2:24b",
275
		TimeoutMS:     "600000",
276
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
277
		ContextWindow: 32_000,
278
	},
279
	"lmstudio": {
280
		Name:          "LM Studio",
281
		Description:   "Local LM Studio server with OpenAI-compatible API",
282
		BaseURL:       "http://localhost:1234/v1",
283
		Model:         "local-model",
284
		SmallModel:    "local-model",
285
		SonnetModel:   "local-model",
286
		OpusModel:     "local-model",
287
		HaikuModel:    "local-model",
288
		TimeoutMS:     "600000",
289
		AuthEnvVar:    "ANTHROPIC_AUTH_TOKEN",
290
		ContextWindow: 128_000,
291
		Compat:        "openai",
292
		NoAuth:        true,
293
	},
294
	"claude": {
295
		Name:        "Claude (Anthropic)",
296
		Description: "Native Claude API via Anthropic (passthrough proxy for accounting)",
297
		BaseURL:     "https://api.anthropic.com",
298
		Model:       "claude-sonnet-4-6-20250514",
299
		SmallModel:  "claude-haiku-4-5-20251001",
300
		SonnetModel: "claude-sonnet-4-6-20250514",
301
		OpusModel:   "claude-opus-4-6-20250610",
302
		HaikuModel:  "claude-haiku-4-5-20251001",
303
		TimeoutMS:   "600000",
304
		NoAuth:      true,
305
	},
306
}
307
308
// Order defines the display order of providers.
309
var Order = []string{"claude", "deepseek", "mistral", "zai", "zai-coding", "minimax", "kimi", "kimi-api-cn", "kimi-api-intl", "copilot", "nvidia", "openrouter", "ollama", "ollama-cloud", "lmstudio", "vkproxy"}
310

Source Files