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 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
  [![npm version](https://img.shields.io/npm/v/claude-connect?style=for-the-badge&logo=npm&color=cb3837)](https://www.npmjs.com/package/claude-connect)
6
6
  [![node](https://img.shields.io/badge/node-%3E%3D22-2f7d32?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org/)
7
7
  [![license](https://img.shields.io/badge/license-MIT-0f172a?style=for-the-badge)](./LICENSE)
8
- [![providers](https://img.shields.io/badge/providers-Kimi%20%7C%20DeepSeek%20%7C%20Qwen-0ea5e9?style=for-the-badge)](https://www.npmjs.com/package/claude-connect)
8
+ [![providers](https://img.shields.io/badge/providers-OpenCode%20Go%20%7C%20Zen%20%7C%20Kimi%20%7C%20DeepSeek%20%7C%20OpenRouter%20%7C%20Qwen-0ea5e9?style=for-the-badge)](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
- - `Kimi` apunta a `https://api.kimi.com/coding/`
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
- | `Kimi` | `kimi-for-coding` | `Token` | Directa |
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 gestionadas por la app
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-connect",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "CLI para configurar Claude Code con proveedores de modelos externos",
5
5
  "author": "wmcarlosv",
6
6
  "type": "module",
@@ -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, sort_order, is_default
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(`