claude-connect 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -6
- package/package.json +1 -1
- package/src/data/catalog-store.js +495 -3
- package/src/gateway/messages.js +152 -7
- package/src/gateway/server.js +206 -63
- package/src/gateway/state.js +52 -0
- package/src/lib/app-paths.js +2 -0
- package/src/lib/claude-settings.js +39 -24
- package/src/lib/profile.js +11 -2
- package/src/lib/secrets.js +48 -0
- package/src/wizard.js +130 -47
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Claude Connect
|
|
2
2
|
|
|
3
|
-
> Conecta `Claude Code` con `Kimi`, `DeepSeek` y `Qwen` desde una interfaz de consola clara, rápida y reversible.
|
|
3
|
+
> Conecta `Claude Code` con `OpenCode Go`, `Zen`, `Kimi`, `DeepSeek`, `OpenRouter` y `Qwen` desde una interfaz de consola clara, rápida y reversible.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/claude-connect)
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
[](./LICENSE)
|
|
8
|
-
[](https://www.npmjs.com/package/claude-connect)
|
|
9
9
|
|
|
10
10
|
## Why Claude Connect
|
|
11
11
|
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
### Highlights
|
|
15
15
|
|
|
16
|
-
- `Kimi`, `DeepSeek` y `Qwen` listos desde el primer arranque
|
|
16
|
+
- `OpenCode Go`, `Zen`, `Kimi`, `DeepSeek`, `OpenRouter` y `Qwen` listos desde el primer arranque
|
|
17
17
|
- soporte para `Token` y `OAuth` cuando el proveedor lo permite
|
|
18
|
+
- API keys compartidas por proveedor para no repetir el mismo token en cada modelo
|
|
18
19
|
- activación reversible sobre la instalación real de `Claude Code`
|
|
19
20
|
- limpieza automática del conflicto entre `claude.ai` y `ANTHROPIC_API_KEY`
|
|
20
21
|
- gateway local Anthropic-compatible para `Qwen`
|
|
@@ -65,6 +66,7 @@ Nueva conexion
|
|
|
65
66
|
-> proveedor
|
|
66
67
|
-> modelo
|
|
67
68
|
-> OAuth o Token
|
|
69
|
+
-> guardar API key una vez por proveedor si aplica
|
|
68
70
|
-> guardar perfil
|
|
69
71
|
-> Activar en Claude
|
|
70
72
|
-> usar claude
|
|
@@ -72,18 +74,35 @@ Nueva conexion
|
|
|
72
74
|
|
|
73
75
|
Al activar:
|
|
74
76
|
|
|
75
|
-
- `
|
|
77
|
+
- `OpenCode Go` usa conexión directa o gateway según el modelo elegido
|
|
78
|
+
- `Zen` usa conexión directa o gateway según el modelo elegido
|
|
79
|
+
- `Kimi` usa gateway local y reenvia al endpoint Anthropic de `https://api.kimi.com/coding/`
|
|
76
80
|
- `DeepSeek` apunta a `https://api.deepseek.com/anthropic`
|
|
81
|
+
- `OpenRouter` usa `openrouter/free` por gateway sobre `https://openrouter.ai/api/v1`
|
|
77
82
|
- `Qwen` apunta al gateway local `http://127.0.0.1:4310/anthropic`
|
|
78
83
|
|
|
79
84
|
## Providers
|
|
80
85
|
|
|
81
86
|
| Proveedor | Modelos | Auth | Integración |
|
|
82
87
|
| --- | --- | --- | --- |
|
|
83
|
-
| `
|
|
88
|
+
| `OpenCode Go` | `glm-5`, `kimi-k2.5`, `minimax-m2.7`, `minimax-m2.5` | `Token` | Mixta |
|
|
89
|
+
| `Zen` | `Claude*` de Zen + modelos `chat/completions` de Zen | `Token` | Mixta |
|
|
90
|
+
| `Kimi` | `kimi-for-coding` | `Token` | Gateway local |
|
|
84
91
|
| `DeepSeek` | `deepseek-chat`, `deepseek-reasoner` | `Token` | Directa |
|
|
92
|
+
| `OpenRouter` | `openrouter/free` | `Token` | Gateway local |
|
|
85
93
|
| `Qwen` | `qwen3-coder-plus` | `OAuth`, `Token` | Gateway local |
|
|
86
94
|
|
|
95
|
+
Nota sobre `OpenCode Go`:
|
|
96
|
+
|
|
97
|
+
- `minimax-m2.7` y `minimax-m2.5` van directos por endpoint `messages`
|
|
98
|
+
- `glm-5` y `kimi-k2.5` van por gateway usando `chat/completions`
|
|
99
|
+
|
|
100
|
+
Nota sobre `Zen`:
|
|
101
|
+
|
|
102
|
+
- los modelos Anthropic de Zen van por conexión directa
|
|
103
|
+
- los modelos de Zen servidos por `chat/completions` van por gateway local
|
|
104
|
+
- esta primera integración no incluye todavía los modelos de Zen expuestos por `responses` ni los de endpoint tipo Google
|
|
105
|
+
|
|
87
106
|
## What It Stores
|
|
88
107
|
|
|
89
108
|
Claude Connect guarda el estado sensible fuera del repo.
|
|
@@ -99,7 +118,7 @@ Ahí viven:
|
|
|
99
118
|
|
|
100
119
|
- perfiles
|
|
101
120
|
- tokens OAuth
|
|
102
|
-
- API keys
|
|
121
|
+
- API keys compartidas por proveedor
|
|
103
122
|
- estado del switch de Claude
|
|
104
123
|
- logs y estado del gateway
|
|
105
124
|
|
package/package.json
CHANGED
|
@@ -27,6 +27,12 @@ CREATE TABLE IF NOT EXISTS models (
|
|
|
27
27
|
category TEXT NOT NULL,
|
|
28
28
|
context_window TEXT NOT NULL,
|
|
29
29
|
summary TEXT NOT NULL,
|
|
30
|
+
upstream_model_id TEXT,
|
|
31
|
+
transport_mode TEXT NOT NULL DEFAULT 'gateway',
|
|
32
|
+
api_style TEXT NOT NULL DEFAULT 'openai-chat',
|
|
33
|
+
api_base_url TEXT,
|
|
34
|
+
api_path TEXT,
|
|
35
|
+
auth_env_mode TEXT NOT NULL DEFAULT 'auth_token',
|
|
30
36
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
31
37
|
is_default INTEGER NOT NULL DEFAULT 0
|
|
32
38
|
);
|
|
@@ -59,11 +65,374 @@ CREATE TABLE IF NOT EXISTS provider_oauth_configs (
|
|
|
59
65
|
`;
|
|
60
66
|
|
|
61
67
|
const seedProviders = [
|
|
68
|
+
{
|
|
69
|
+
id: 'opencode-go',
|
|
70
|
+
name: 'OpenCode Go',
|
|
71
|
+
vendor: 'OpenCode',
|
|
72
|
+
description: 'Suscripcion OpenCode Go con modelos abiertos de programacion. Algunos modelos van directos por messages y otros por gateway en chat/completions.',
|
|
73
|
+
docsUrl: 'https://opencode.ai/docs/es/go/',
|
|
74
|
+
docsVerifiedAt: '2026-04-01',
|
|
75
|
+
baseUrl: 'https://opencode.ai/zen/go',
|
|
76
|
+
defaultModelId: 'minimax-m2.5',
|
|
77
|
+
defaultAuthMethodId: 'token',
|
|
78
|
+
defaultApiKeyEnvVar: 'OPENCODE_API_KEY',
|
|
79
|
+
models: [
|
|
80
|
+
{
|
|
81
|
+
id: 'opencode-go-glm-5',
|
|
82
|
+
name: 'GLM 5',
|
|
83
|
+
category: 'OpenAI-compatible',
|
|
84
|
+
contextWindow: 'Auto',
|
|
85
|
+
summary: 'Modelo de OpenCode Go servido por chat/completions y usado a través del gateway local.',
|
|
86
|
+
upstreamModelId: 'glm-5',
|
|
87
|
+
transportMode: 'gateway',
|
|
88
|
+
apiStyle: 'openai-chat',
|
|
89
|
+
apiBaseUrl: 'https://opencode.ai/zen/go/v1',
|
|
90
|
+
apiPath: '/chat/completions',
|
|
91
|
+
authEnvMode: 'auth_token',
|
|
92
|
+
sortOrder: 1,
|
|
93
|
+
isDefault: 0
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'opencode-go-kimi-k2.5',
|
|
97
|
+
name: 'Kimi K2.5',
|
|
98
|
+
category: 'OpenAI-compatible',
|
|
99
|
+
contextWindow: 'Auto',
|
|
100
|
+
summary: 'Modelo de OpenCode Go servido por chat/completions y usado a través del gateway local.',
|
|
101
|
+
upstreamModelId: 'kimi-k2.5',
|
|
102
|
+
transportMode: 'gateway',
|
|
103
|
+
apiStyle: 'openai-chat',
|
|
104
|
+
apiBaseUrl: 'https://opencode.ai/zen/go/v1',
|
|
105
|
+
apiPath: '/chat/completions',
|
|
106
|
+
authEnvMode: 'auth_token',
|
|
107
|
+
sortOrder: 2,
|
|
108
|
+
isDefault: 0
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'opencode-go-minimax-m2.7',
|
|
112
|
+
name: 'MiniMax M2.7',
|
|
113
|
+
category: 'Anthropic',
|
|
114
|
+
contextWindow: 'Auto',
|
|
115
|
+
summary: 'Modelo de OpenCode Go servido por messages y usado directamente por Claude Code.',
|
|
116
|
+
upstreamModelId: 'minimax-m2.7',
|
|
117
|
+
transportMode: 'direct',
|
|
118
|
+
apiStyle: 'anthropic',
|
|
119
|
+
apiBaseUrl: 'https://opencode.ai/zen/go',
|
|
120
|
+
apiPath: '/v1/messages',
|
|
121
|
+
authEnvMode: 'api_key',
|
|
122
|
+
sortOrder: 3,
|
|
123
|
+
isDefault: 0
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'opencode-go-minimax-m2.5',
|
|
127
|
+
name: 'MiniMax M2.5',
|
|
128
|
+
category: 'Anthropic',
|
|
129
|
+
contextWindow: 'Auto',
|
|
130
|
+
summary: 'Modelo de OpenCode Go servido por messages y usado directamente por Claude Code.',
|
|
131
|
+
upstreamModelId: 'minimax-m2.5',
|
|
132
|
+
transportMode: 'direct',
|
|
133
|
+
apiStyle: 'anthropic',
|
|
134
|
+
apiBaseUrl: 'https://opencode.ai/zen/go',
|
|
135
|
+
apiPath: '/v1/messages',
|
|
136
|
+
authEnvMode: 'api_key',
|
|
137
|
+
sortOrder: 4,
|
|
138
|
+
isDefault: 1
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
authMethods: [
|
|
142
|
+
{
|
|
143
|
+
id: 'token',
|
|
144
|
+
name: 'Token',
|
|
145
|
+
description: 'Conexion por API key de OpenCode para la suscripcion Go.',
|
|
146
|
+
credentialKind: 'env_var',
|
|
147
|
+
sortOrder: 1,
|
|
148
|
+
isDefault: 1
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'zen',
|
|
154
|
+
name: 'OpenCode Zen',
|
|
155
|
+
vendor: 'OpenCode',
|
|
156
|
+
description: 'Zen de OpenCode con modelos curados. Claude va directo para modelos Anthropic y usa gateway para modelos OpenAI-compatible.',
|
|
157
|
+
docsUrl: 'https://opencode.ai/docs/zen',
|
|
158
|
+
docsVerifiedAt: '2026-04-01',
|
|
159
|
+
baseUrl: 'https://opencode.ai/zen',
|
|
160
|
+
defaultModelId: 'claude-sonnet-4-6',
|
|
161
|
+
defaultAuthMethodId: 'token',
|
|
162
|
+
defaultApiKeyEnvVar: 'OPENCODE_API_KEY',
|
|
163
|
+
models: [
|
|
164
|
+
{
|
|
165
|
+
id: 'claude-opus-4-6',
|
|
166
|
+
name: 'Claude Opus 4.6',
|
|
167
|
+
category: 'Anthropic',
|
|
168
|
+
contextWindow: '200K+',
|
|
169
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
170
|
+
upstreamModelId: 'claude-opus-4-6',
|
|
171
|
+
transportMode: 'direct',
|
|
172
|
+
apiStyle: 'anthropic',
|
|
173
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
174
|
+
apiPath: '/v1/messages',
|
|
175
|
+
authEnvMode: 'api_key',
|
|
176
|
+
sortOrder: 1,
|
|
177
|
+
isDefault: 0
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: 'claude-opus-4-5',
|
|
181
|
+
name: 'Claude Opus 4.5',
|
|
182
|
+
category: 'Anthropic',
|
|
183
|
+
contextWindow: '200K+',
|
|
184
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
185
|
+
upstreamModelId: 'claude-opus-4-5',
|
|
186
|
+
transportMode: 'direct',
|
|
187
|
+
apiStyle: 'anthropic',
|
|
188
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
189
|
+
apiPath: '/v1/messages',
|
|
190
|
+
authEnvMode: 'api_key',
|
|
191
|
+
sortOrder: 2,
|
|
192
|
+
isDefault: 0
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: 'claude-opus-4-1',
|
|
196
|
+
name: 'Claude Opus 4.1',
|
|
197
|
+
category: 'Anthropic',
|
|
198
|
+
contextWindow: '200K+',
|
|
199
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
200
|
+
upstreamModelId: 'claude-opus-4-1',
|
|
201
|
+
transportMode: 'direct',
|
|
202
|
+
apiStyle: 'anthropic',
|
|
203
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
204
|
+
apiPath: '/v1/messages',
|
|
205
|
+
authEnvMode: 'api_key',
|
|
206
|
+
sortOrder: 3,
|
|
207
|
+
isDefault: 0
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'claude-sonnet-4-6',
|
|
211
|
+
name: 'Claude Sonnet 4.6',
|
|
212
|
+
category: 'Anthropic',
|
|
213
|
+
contextWindow: '200K+',
|
|
214
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
215
|
+
upstreamModelId: 'claude-sonnet-4-6',
|
|
216
|
+
transportMode: 'direct',
|
|
217
|
+
apiStyle: 'anthropic',
|
|
218
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
219
|
+
apiPath: '/v1/messages',
|
|
220
|
+
authEnvMode: 'api_key',
|
|
221
|
+
sortOrder: 4,
|
|
222
|
+
isDefault: 1
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: 'claude-sonnet-4-5',
|
|
226
|
+
name: 'Claude Sonnet 4.5',
|
|
227
|
+
category: 'Anthropic',
|
|
228
|
+
contextWindow: '200K+',
|
|
229
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
230
|
+
upstreamModelId: 'claude-sonnet-4-5',
|
|
231
|
+
transportMode: 'direct',
|
|
232
|
+
apiStyle: 'anthropic',
|
|
233
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
234
|
+
apiPath: '/v1/messages',
|
|
235
|
+
authEnvMode: 'api_key',
|
|
236
|
+
sortOrder: 5,
|
|
237
|
+
isDefault: 0
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
id: 'claude-sonnet-4',
|
|
241
|
+
name: 'Claude Sonnet 4',
|
|
242
|
+
category: 'Anthropic',
|
|
243
|
+
contextWindow: '200K+',
|
|
244
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
245
|
+
upstreamModelId: 'claude-sonnet-4',
|
|
246
|
+
transportMode: 'direct',
|
|
247
|
+
apiStyle: 'anthropic',
|
|
248
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
249
|
+
apiPath: '/v1/messages',
|
|
250
|
+
authEnvMode: 'api_key',
|
|
251
|
+
sortOrder: 6,
|
|
252
|
+
isDefault: 0
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
id: 'claude-haiku-4-5',
|
|
256
|
+
name: 'Claude Haiku 4.5',
|
|
257
|
+
category: 'Anthropic',
|
|
258
|
+
contextWindow: '200K+',
|
|
259
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
260
|
+
upstreamModelId: 'claude-haiku-4-5',
|
|
261
|
+
transportMode: 'direct',
|
|
262
|
+
apiStyle: 'anthropic',
|
|
263
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
264
|
+
apiPath: '/v1/messages',
|
|
265
|
+
authEnvMode: 'api_key',
|
|
266
|
+
sortOrder: 7,
|
|
267
|
+
isDefault: 0
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: 'claude-3-5-haiku',
|
|
271
|
+
name: 'Claude Haiku 3.5',
|
|
272
|
+
category: 'Anthropic',
|
|
273
|
+
contextWindow: '200K+',
|
|
274
|
+
summary: 'Modelo Anthropic servido por Zen en el endpoint messages.',
|
|
275
|
+
upstreamModelId: 'claude-3-5-haiku',
|
|
276
|
+
transportMode: 'direct',
|
|
277
|
+
apiStyle: 'anthropic',
|
|
278
|
+
apiBaseUrl: 'https://opencode.ai/zen',
|
|
279
|
+
apiPath: '/v1/messages',
|
|
280
|
+
authEnvMode: 'api_key',
|
|
281
|
+
sortOrder: 8,
|
|
282
|
+
isDefault: 0
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
id: 'minimax-m2.5',
|
|
286
|
+
name: 'MiniMax M2.5',
|
|
287
|
+
category: 'OpenAI-compatible',
|
|
288
|
+
contextWindow: 'Auto',
|
|
289
|
+
summary: 'Modelo servido por Zen en chat/completions y usado a través del gateway local.',
|
|
290
|
+
upstreamModelId: 'minimax-m2.5',
|
|
291
|
+
transportMode: 'gateway',
|
|
292
|
+
apiStyle: 'openai-chat',
|
|
293
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
294
|
+
apiPath: '/chat/completions',
|
|
295
|
+
authEnvMode: 'auth_token',
|
|
296
|
+
sortOrder: 9,
|
|
297
|
+
isDefault: 0
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: 'minimax-m2.5-free',
|
|
301
|
+
name: 'MiniMax M2.5 Free',
|
|
302
|
+
category: 'OpenAI-compatible',
|
|
303
|
+
contextWindow: 'Auto',
|
|
304
|
+
summary: 'Modelo gratis servido por Zen en chat/completions y usado a través del gateway local.',
|
|
305
|
+
upstreamModelId: 'minimax-m2.5-free',
|
|
306
|
+
transportMode: 'gateway',
|
|
307
|
+
apiStyle: 'openai-chat',
|
|
308
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
309
|
+
apiPath: '/chat/completions',
|
|
310
|
+
authEnvMode: 'auth_token',
|
|
311
|
+
sortOrder: 10,
|
|
312
|
+
isDefault: 0
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
id: 'glm-5',
|
|
316
|
+
name: 'GLM 5',
|
|
317
|
+
category: 'OpenAI-compatible',
|
|
318
|
+
contextWindow: 'Auto',
|
|
319
|
+
summary: 'Modelo servido por Zen en chat/completions y usado a través del gateway local.',
|
|
320
|
+
upstreamModelId: 'glm-5',
|
|
321
|
+
transportMode: 'gateway',
|
|
322
|
+
apiStyle: 'openai-chat',
|
|
323
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
324
|
+
apiPath: '/chat/completions',
|
|
325
|
+
authEnvMode: 'auth_token',
|
|
326
|
+
sortOrder: 11,
|
|
327
|
+
isDefault: 0
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
id: 'kimi-k2.5',
|
|
331
|
+
name: 'Kimi K2.5',
|
|
332
|
+
category: 'OpenAI-compatible',
|
|
333
|
+
contextWindow: 'Auto',
|
|
334
|
+
summary: 'Modelo servido por Zen en chat/completions y usado a través del gateway local.',
|
|
335
|
+
upstreamModelId: 'kimi-k2.5',
|
|
336
|
+
transportMode: 'gateway',
|
|
337
|
+
apiStyle: 'openai-chat',
|
|
338
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
339
|
+
apiPath: '/chat/completions',
|
|
340
|
+
authEnvMode: 'auth_token',
|
|
341
|
+
sortOrder: 12,
|
|
342
|
+
isDefault: 0
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
id: 'big-pickle',
|
|
346
|
+
name: 'Big Pickle',
|
|
347
|
+
category: 'OpenAI-compatible',
|
|
348
|
+
contextWindow: 'Auto',
|
|
349
|
+
summary: 'Modelo servido por Zen en chat/completions y usado a través del gateway local.',
|
|
350
|
+
upstreamModelId: 'big-pickle',
|
|
351
|
+
transportMode: 'gateway',
|
|
352
|
+
apiStyle: 'openai-chat',
|
|
353
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
354
|
+
apiPath: '/chat/completions',
|
|
355
|
+
authEnvMode: 'auth_token',
|
|
356
|
+
sortOrder: 13,
|
|
357
|
+
isDefault: 0
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: 'mimo-v2-pro-free',
|
|
361
|
+
name: 'MiMo V2 Pro Free',
|
|
362
|
+
category: 'OpenAI-compatible',
|
|
363
|
+
contextWindow: 'Auto',
|
|
364
|
+
summary: 'Modelo gratis servido por Zen en chat/completions y usado a través del gateway local.',
|
|
365
|
+
upstreamModelId: 'mimo-v2-pro-free',
|
|
366
|
+
transportMode: 'gateway',
|
|
367
|
+
apiStyle: 'openai-chat',
|
|
368
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
369
|
+
apiPath: '/chat/completions',
|
|
370
|
+
authEnvMode: 'auth_token',
|
|
371
|
+
sortOrder: 14,
|
|
372
|
+
isDefault: 0
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
id: 'mimo-v2-omni-free',
|
|
376
|
+
name: 'MiMo V2 Omni Free',
|
|
377
|
+
category: 'OpenAI-compatible',
|
|
378
|
+
contextWindow: 'Auto',
|
|
379
|
+
summary: 'Modelo gratis servido por Zen en chat/completions y usado a través del gateway local.',
|
|
380
|
+
upstreamModelId: 'mimo-v2-omni-free',
|
|
381
|
+
transportMode: 'gateway',
|
|
382
|
+
apiStyle: 'openai-chat',
|
|
383
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
384
|
+
apiPath: '/chat/completions',
|
|
385
|
+
authEnvMode: 'auth_token',
|
|
386
|
+
sortOrder: 15,
|
|
387
|
+
isDefault: 0
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
id: 'qwen3.6-plus-free',
|
|
391
|
+
name: 'Qwen 3.6 Plus Free',
|
|
392
|
+
category: 'OpenAI-compatible',
|
|
393
|
+
contextWindow: 'Auto',
|
|
394
|
+
summary: 'Modelo gratis servido por Zen en chat/completions y usado a través del gateway local.',
|
|
395
|
+
upstreamModelId: 'qwen3.6-plus-free',
|
|
396
|
+
transportMode: 'gateway',
|
|
397
|
+
apiStyle: 'openai-chat',
|
|
398
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
399
|
+
apiPath: '/chat/completions',
|
|
400
|
+
authEnvMode: 'auth_token',
|
|
401
|
+
sortOrder: 16,
|
|
402
|
+
isDefault: 0
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
id: 'nemotron-3-super-free',
|
|
406
|
+
name: 'Nemotron 3 Super Free',
|
|
407
|
+
category: 'OpenAI-compatible',
|
|
408
|
+
contextWindow: 'Auto',
|
|
409
|
+
summary: 'Modelo gratis servido por Zen en chat/completions y usado a través del gateway local.',
|
|
410
|
+
upstreamModelId: 'nemotron-3-super-free',
|
|
411
|
+
transportMode: 'gateway',
|
|
412
|
+
apiStyle: 'openai-chat',
|
|
413
|
+
apiBaseUrl: 'https://opencode.ai/zen/v1',
|
|
414
|
+
apiPath: '/chat/completions',
|
|
415
|
+
authEnvMode: 'auth_token',
|
|
416
|
+
sortOrder: 17,
|
|
417
|
+
isDefault: 0
|
|
418
|
+
}
|
|
419
|
+
],
|
|
420
|
+
authMethods: [
|
|
421
|
+
{
|
|
422
|
+
id: 'token',
|
|
423
|
+
name: 'Token',
|
|
424
|
+
description: 'Conexion por API key de OpenCode Zen.',
|
|
425
|
+
credentialKind: 'env_var',
|
|
426
|
+
sortOrder: 1,
|
|
427
|
+
isDefault: 1
|
|
428
|
+
}
|
|
429
|
+
]
|
|
430
|
+
},
|
|
62
431
|
{
|
|
63
432
|
id: 'kimi',
|
|
64
433
|
name: 'Kimi',
|
|
65
434
|
vendor: 'Moonshot AI',
|
|
66
|
-
description: 'Kimi Code para Claude Code usando el endpoint Anthropic oficial de Kimi.',
|
|
435
|
+
description: 'Kimi Code para Claude Code usando el endpoint Anthropic oficial de Kimi a través del gateway local.',
|
|
67
436
|
docsUrl: 'https://www.kimi.com/code/docs/en/more/third-party-agents.html',
|
|
68
437
|
docsVerifiedAt: '2026-04-01',
|
|
69
438
|
baseUrl: 'https://api.kimi.com/coding/',
|
|
@@ -77,6 +446,12 @@ const seedProviders = [
|
|
|
77
446
|
category: 'Coding',
|
|
78
447
|
contextWindow: '262144',
|
|
79
448
|
summary: 'Modelo oficial de Kimi Code para Claude Code. El modo thinking se conmuta con Tab dentro de Claude Code.',
|
|
449
|
+
upstreamModelId: 'kimi-for-coding',
|
|
450
|
+
transportMode: 'gateway',
|
|
451
|
+
apiStyle: 'anthropic',
|
|
452
|
+
apiBaseUrl: 'https://api.kimi.com/coding/',
|
|
453
|
+
apiPath: '/v1/messages',
|
|
454
|
+
authEnvMode: 'api_key',
|
|
80
455
|
sortOrder: 1,
|
|
81
456
|
isDefault: 1
|
|
82
457
|
}
|
|
@@ -110,6 +485,12 @@ const seedProviders = [
|
|
|
110
485
|
category: 'General',
|
|
111
486
|
contextWindow: '128K',
|
|
112
487
|
summary: 'Modo no razonador de DeepSeek V3.2, apto como opcion base para Claude Code.',
|
|
488
|
+
upstreamModelId: 'deepseek-chat',
|
|
489
|
+
transportMode: 'direct',
|
|
490
|
+
apiStyle: 'anthropic',
|
|
491
|
+
apiBaseUrl: 'https://api.deepseek.com/anthropic',
|
|
492
|
+
apiPath: '/v1/messages',
|
|
493
|
+
authEnvMode: 'auth_token',
|
|
113
494
|
sortOrder: 1,
|
|
114
495
|
isDefault: 1
|
|
115
496
|
},
|
|
@@ -119,6 +500,12 @@ const seedProviders = [
|
|
|
119
500
|
category: 'Reasoning',
|
|
120
501
|
contextWindow: '128K',
|
|
121
502
|
summary: 'Modo razonador de DeepSeek V3.2 con soporte de Tool Calls segun la documentacion oficial.',
|
|
503
|
+
upstreamModelId: 'deepseek-reasoner',
|
|
504
|
+
transportMode: 'direct',
|
|
505
|
+
apiStyle: 'anthropic',
|
|
506
|
+
apiBaseUrl: 'https://api.deepseek.com/anthropic',
|
|
507
|
+
apiPath: '/v1/messages',
|
|
508
|
+
authEnvMode: 'auth_token',
|
|
122
509
|
sortOrder: 2,
|
|
123
510
|
isDefault: 0
|
|
124
511
|
}
|
|
@@ -134,6 +521,45 @@ const seedProviders = [
|
|
|
134
521
|
}
|
|
135
522
|
]
|
|
136
523
|
},
|
|
524
|
+
{
|
|
525
|
+
id: 'openrouter',
|
|
526
|
+
name: 'OpenRouter',
|
|
527
|
+
vendor: 'OpenRouter',
|
|
528
|
+
description: 'OpenRouter con el router gratuito openrouter/free para usar inferencia sin costo y dejar que OpenRouter seleccione un modelo free compatible con la solicitud.',
|
|
529
|
+
docsUrl: 'https://openrouter.ai/openrouter/free/activity',
|
|
530
|
+
docsVerifiedAt: '2026-04-01',
|
|
531
|
+
baseUrl: 'https://openrouter.ai/api/v1',
|
|
532
|
+
defaultModelId: 'openrouter-free',
|
|
533
|
+
defaultAuthMethodId: 'token',
|
|
534
|
+
defaultApiKeyEnvVar: 'OPENROUTER_API_KEY',
|
|
535
|
+
models: [
|
|
536
|
+
{
|
|
537
|
+
id: 'openrouter-free',
|
|
538
|
+
name: 'OpenRouter Free Router',
|
|
539
|
+
category: 'Free Router',
|
|
540
|
+
contextWindow: '200K',
|
|
541
|
+
summary: 'Router gratuito de OpenRouter. Usa el modelo upstream openrouter/free y deja que el proveedor elija un modelo free compatible con herramientas, vision u otras capacidades.',
|
|
542
|
+
upstreamModelId: 'openrouter/free',
|
|
543
|
+
transportMode: 'gateway',
|
|
544
|
+
apiStyle: 'openai-chat',
|
|
545
|
+
apiBaseUrl: 'https://openrouter.ai/api/v1',
|
|
546
|
+
apiPath: '/chat/completions',
|
|
547
|
+
authEnvMode: 'auth_token',
|
|
548
|
+
sortOrder: 1,
|
|
549
|
+
isDefault: 1
|
|
550
|
+
}
|
|
551
|
+
],
|
|
552
|
+
authMethods: [
|
|
553
|
+
{
|
|
554
|
+
id: 'token',
|
|
555
|
+
name: 'Token',
|
|
556
|
+
description: 'Conexion por API key contra el endpoint OpenAI-compatible oficial de OpenRouter.',
|
|
557
|
+
credentialKind: 'env_var',
|
|
558
|
+
sortOrder: 1,
|
|
559
|
+
isDefault: 1
|
|
560
|
+
}
|
|
561
|
+
]
|
|
562
|
+
},
|
|
137
563
|
{
|
|
138
564
|
id: 'qwen',
|
|
139
565
|
name: 'Qwen',
|
|
@@ -152,6 +578,12 @@ const seedProviders = [
|
|
|
152
578
|
category: 'Coding',
|
|
153
579
|
contextWindow: 'Auto',
|
|
154
580
|
summary: 'Modelo fijo para esta primera version, siguiendo el flujo de Qwen Code.',
|
|
581
|
+
upstreamModelId: 'qwen3-coder-plus',
|
|
582
|
+
transportMode: 'gateway',
|
|
583
|
+
apiStyle: 'openai-chat',
|
|
584
|
+
apiBaseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
585
|
+
apiPath: '/chat/completions',
|
|
586
|
+
authEnvMode: 'auth_token',
|
|
155
587
|
sortOrder: 1,
|
|
156
588
|
isDefault: 1
|
|
157
589
|
}
|
|
@@ -207,15 +639,24 @@ function seedCatalog(db) {
|
|
|
207
639
|
|
|
208
640
|
const insertModel = db.prepare(`
|
|
209
641
|
INSERT INTO models (
|
|
210
|
-
id, provider_id, name, category, context_window, summary,
|
|
642
|
+
id, provider_id, name, category, context_window, summary,
|
|
643
|
+
upstream_model_id,
|
|
644
|
+
transport_mode, api_style, api_base_url, api_path, auth_env_mode,
|
|
645
|
+
sort_order, is_default
|
|
211
646
|
)
|
|
212
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
647
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
213
648
|
ON CONFLICT(id) DO UPDATE SET
|
|
214
649
|
provider_id = excluded.provider_id,
|
|
215
650
|
name = excluded.name,
|
|
216
651
|
category = excluded.category,
|
|
217
652
|
context_window = excluded.context_window,
|
|
218
653
|
summary = excluded.summary,
|
|
654
|
+
upstream_model_id = excluded.upstream_model_id,
|
|
655
|
+
transport_mode = excluded.transport_mode,
|
|
656
|
+
api_style = excluded.api_style,
|
|
657
|
+
api_base_url = excluded.api_base_url,
|
|
658
|
+
api_path = excluded.api_path,
|
|
659
|
+
auth_env_mode = excluded.auth_env_mode,
|
|
219
660
|
sort_order = excluded.sort_order,
|
|
220
661
|
is_default = excluded.is_default
|
|
221
662
|
`);
|
|
@@ -280,6 +721,12 @@ function seedCatalog(db) {
|
|
|
280
721
|
model.category,
|
|
281
722
|
model.contextWindow,
|
|
282
723
|
model.summary,
|
|
724
|
+
model.upstreamModelId ?? model.id,
|
|
725
|
+
model.transportMode ?? 'gateway',
|
|
726
|
+
model.apiStyle ?? 'openai-chat',
|
|
727
|
+
model.apiBaseUrl ?? null,
|
|
728
|
+
model.apiPath ?? null,
|
|
729
|
+
model.authEnvMode ?? 'auth_token',
|
|
283
730
|
model.sortOrder,
|
|
284
731
|
model.isDefault
|
|
285
732
|
);
|
|
@@ -324,6 +771,44 @@ function seedCatalog(db) {
|
|
|
324
771
|
}
|
|
325
772
|
}
|
|
326
773
|
|
|
774
|
+
function ensureSchemaMigrations(db) {
|
|
775
|
+
const modelColumns = new Set(
|
|
776
|
+
db.prepare('PRAGMA table_info(models)').all().map((column) => column.name)
|
|
777
|
+
);
|
|
778
|
+
|
|
779
|
+
const alterStatements = [];
|
|
780
|
+
|
|
781
|
+
if (!modelColumns.has('transport_mode')) {
|
|
782
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN transport_mode TEXT NOT NULL DEFAULT 'gateway'`);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (!modelColumns.has('api_style')) {
|
|
786
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN api_style TEXT NOT NULL DEFAULT 'openai-chat'`);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
if (!modelColumns.has('api_base_url')) {
|
|
790
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN api_base_url TEXT`);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (!modelColumns.has('api_path')) {
|
|
794
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN api_path TEXT`);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
if (!modelColumns.has('auth_env_mode')) {
|
|
798
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN auth_env_mode TEXT NOT NULL DEFAULT 'auth_token'`);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (!modelColumns.has('upstream_model_id')) {
|
|
802
|
+
alterStatements.push(`ALTER TABLE models ADD COLUMN upstream_model_id TEXT`);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
for (const statement of alterStatements) {
|
|
806
|
+
db.exec(statement);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
db.exec(`UPDATE models SET upstream_model_id = id WHERE upstream_model_id IS NULL OR upstream_model_id = ''`);
|
|
810
|
+
}
|
|
811
|
+
|
|
327
812
|
function mapProviderRow(row) {
|
|
328
813
|
return {
|
|
329
814
|
id: row.id,
|
|
@@ -349,6 +834,12 @@ function mapModelRow(row) {
|
|
|
349
834
|
category: row.category,
|
|
350
835
|
contextWindow: row.context_window,
|
|
351
836
|
summary: row.summary,
|
|
837
|
+
upstreamModelId: row.upstream_model_id ?? row.id,
|
|
838
|
+
transportMode: row.transport_mode,
|
|
839
|
+
apiStyle: row.api_style,
|
|
840
|
+
apiBaseUrl: row.api_base_url,
|
|
841
|
+
apiPath: row.api_path,
|
|
842
|
+
authEnvMode: row.auth_env_mode,
|
|
352
843
|
sortOrder: Number(row.sort_order),
|
|
353
844
|
isDefault: Boolean(row.is_default)
|
|
354
845
|
};
|
|
@@ -385,6 +876,7 @@ export function createCatalogStore({ filename = defaultCatalogDbPath } = {}) {
|
|
|
385
876
|
|
|
386
877
|
const db = new DatabaseSync(filename);
|
|
387
878
|
db.exec(schemaSql);
|
|
879
|
+
ensureSchemaMigrations(db);
|
|
388
880
|
seedCatalog(db);
|
|
389
881
|
|
|
390
882
|
const providerListStatement = db.prepare(`
|