@qadanm/opencode-smart-router 0.0.0-stage → 0.4.0

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/CONTRIBUTING.md +96 -0
  3. package/LICENSE +21 -0
  4. package/README.md +341 -2
  5. package/SECURITY.md +174 -0
  6. package/config.example.json +108 -0
  7. package/dist/allowance.js +487 -0
  8. package/dist/gui-experimental.cjs +1 -0
  9. package/dist/index.js +11111 -0
  10. package/dist/npm/index.js +40 -0
  11. package/dist/tui.js +587 -0
  12. package/docs/ARCHITECTURE.md +104 -0
  13. package/docs/DEBUGGING-GUI.md +70 -0
  14. package/docs/INSTALL.md +120 -0
  15. package/docs/LIMITATIONS.md +213 -0
  16. package/docs/MODELS.md +124 -0
  17. package/docs/OPENDESIGN-INTEGRATION.md +635 -0
  18. package/docs/QA.md +142 -0
  19. package/docs/SHARED-CORE.md +72 -0
  20. package/install +75 -0
  21. package/package.json +92 -4
  22. package/scripts/install.sh +324 -0
  23. package/scripts/uninstall.sh +91 -0
  24. package/src/allowance.ts +135 -0
  25. package/src/core/classify/classifier.ts +305 -0
  26. package/src/core/config-writer.ts +167 -0
  27. package/src/core/config.ts +1030 -0
  28. package/src/core/context/strategy.ts +188 -0
  29. package/src/core/context-health.ts +39 -0
  30. package/src/core/failures.ts +398 -0
  31. package/src/core/history/opencode.ts +173 -0
  32. package/src/core/models/protocol.ts +22 -0
  33. package/src/core/models/registry.ts +203 -0
  34. package/src/core/models/seed.ts +771 -0
  35. package/src/core/offline/mode.ts +321 -0
  36. package/src/core/plan-page.ts +390 -0
  37. package/src/core/plans/catalog.ts +481 -0
  38. package/src/core/policy/calibration.ts +259 -0
  39. package/src/core/policy/eligibility.ts +578 -0
  40. package/src/core/providers/enablement.ts +143 -0
  41. package/src/core/providers/opendesign-credits.ts +206 -0
  42. package/src/core/providers/opendesign-models.ts +628 -0
  43. package/src/core/providers/opendesign.ts +474 -0
  44. package/src/core/quota/calibration.ts +166 -0
  45. package/src/core/quota/commandcode.ts +471 -0
  46. package/src/core/quota/credentials.ts +490 -0
  47. package/src/core/quota/ledger.ts +1273 -0
  48. package/src/core/quota/opencode-go.ts +148 -0
  49. package/src/core/quota/opendesign.ts +1043 -0
  50. package/src/core/quota/reconcile.ts +155 -0
  51. package/src/core/quota/report.ts +261 -0
  52. package/src/core/quota/service.ts +273 -0
  53. package/src/core/reprompt.ts +48 -0
  54. package/src/core/routing/engine.ts +919 -0
  55. package/src/core/types.ts +825 -0
  56. package/src/core/ui.ts +236 -0
  57. package/src/core/util.ts +114 -0
  58. package/src/gui/index.tsx +1670 -0
  59. package/src/gui/viewmodel.ts +456 -0
  60. package/src/index.ts +48 -0
  61. package/src/rpc.ts +204 -0
  62. package/src/server/controller.ts +3281 -0
  63. package/src/server/route-tracker.ts +60 -0
  64. package/src/server/shared-core.ts +671 -0
  65. package/src/tui/index.tsx +168 -0
@@ -0,0 +1,771 @@
1
+ import type { CostTier, ModelRecord, PeakPricing } from "../types.js"
2
+ import { OPENDESIGN_MODELS } from "../providers/opendesign-models.js"
3
+ import { OPENDESIGN_DESIGN_PLAN_MODELS, modelMonthlyAllowanceUsd, resolvePlan } from "../plans/catalog.js"
4
+
5
+ export interface SeedModel {
6
+ key: string
7
+ providerID: string
8
+ modelID: string
9
+ name: string
10
+ context: number
11
+ maxOutput: number
12
+ input: string[]
13
+ tools?: boolean
14
+ cost: CostTier[]
15
+ peakPricing?: PeakPricing
16
+ intelligence: number
17
+ design: number
18
+ designEvidence?: ModelRecord["designEvidence"]
19
+ /** Credit multiplier applied to usage value. One for plain USD billing. */
20
+ creditMultiplier?: number
21
+ /** True when the model is funded from a pool reserved for escalation. */
22
+ escalationOnly?: boolean
23
+ premium?: boolean
24
+ training?: boolean
25
+ free?: boolean
26
+ tier: 1 | 2 | 3
27
+ approved?: boolean
28
+ monthlyAllowanceUsd: number
29
+ protocol?: "anthropic" | "openai-compat"
30
+ notes?: string
31
+ }
32
+
33
+ const cost = (input: number, output: number, read: number, write = 0): CostTier[] => [
34
+ { input, output, cache: { read, write } },
35
+ ]
36
+
37
+ const tieredCost = (
38
+ base: CostTier,
39
+ size: number,
40
+ high: { input: number; output: number; read: number; write: number },
41
+ ): CostTier[] => [
42
+ base,
43
+ {
44
+ input: high.input,
45
+ output: high.output,
46
+ cache: { read: high.read, write: high.write },
47
+ tier: { type: "context", size },
48
+ },
49
+ ]
50
+
51
+ /**
52
+ * Command Code documents these DeepSeek models at off-peak rates and charges
53
+ * 2x from 01:00-04:00 and 06:00-10:00 UTC, Monday-Friday.
54
+ *
55
+ * OpenCode Go publishes the identical peak schedule for DeepSeek V4.1 Flash
56
+ * and V4 Pro, so the same shape is reused rather than duplicated.
57
+ */
58
+ const DEEPSEEK_PEAK_PRICING: PeakPricing = {
59
+ multiplier: 2,
60
+ windowsUtc: [
61
+ { startHour: 1, endHour: 4 },
62
+ { startHour: 6, endHour: 10 },
63
+ ],
64
+ weekdaysOnly: true,
65
+ }
66
+
67
+ const COMMAND_CODE_DEEPSEEK_PEAK = DEEPSEEK_PEAK_PRICING
68
+
69
+ /**
70
+ * Curated seed. Intelligence values come from Command Code's published model
71
+ * cards where available. Models that are new or unscored are deliberately not
72
+ * approved for automatic substantive work.
73
+ *
74
+ * Design scores are curated quality estimates, not benchmark results. They are
75
+ * separate from intelligence and are documented in docs/MODELS.md.
76
+ */
77
+ const BASE_SEED_MODELS: ReadonlyArray<SeedModel> = [
78
+ // ---------------------------------------------------------------------------
79
+ // OpenCode Go: economy
80
+ // ---------------------------------------------------------------------------
81
+ {
82
+ key: "opencode-go/gpt-6-luna",
83
+ providerID: "opencode-go",
84
+ modelID: "gpt-6-luna",
85
+ name: "GPT-6 Luna",
86
+ context: 1_050_000,
87
+ maxOutput: 128_000,
88
+ input: ["text", "image", "pdf"],
89
+ cost: tieredCost(cost(0.1, 0.5, 0.01, 0.125)[0]!, 272_000, { input: 0.2, output: 0.75, read: 0.02, write: 0.25 }),
90
+ intelligence: 38.1,
91
+ design: 55,
92
+ designEvidence: "curated",
93
+ tier: 1,
94
+ monthlyAllowanceUsd: 60,
95
+ notes: "Economy tier. Reliable for narrow mechanical edits, below the standard intelligence floor.",
96
+ },
97
+ {
98
+ key: "opencode-go/mimo-v2.6-flash",
99
+ providerID: "opencode-go",
100
+ modelID: "mimo-v2.6-flash",
101
+ name: "MiMo-V2.6-Flash",
102
+ context: 1_048_576,
103
+ maxOutput: 131_072,
104
+ input: ["text", "image", "audio", "video"],
105
+ cost: cost(0.14, 0.28, 0.0028),
106
+ intelligence: 37.9,
107
+ design: 50,
108
+ designEvidence: "curated",
109
+ tier: 1,
110
+ monthlyAllowanceUsd: 120,
111
+ notes: "Cheap multimodal model. Economy tier only.",
112
+ },
113
+ {
114
+ key: "opencode-go/hy3",
115
+ providerID: "opencode-go",
116
+ modelID: "hy3",
117
+ name: "Hy3",
118
+ context: 256_000,
119
+ maxOutput: 128_000,
120
+ input: ["text"],
121
+ cost: cost(0.14, 0.58, 0.035),
122
+ intelligence: 25.3,
123
+ design: 45,
124
+ designEvidence: "curated",
125
+ tier: 1,
126
+ monthlyAllowanceUsd: 240,
127
+ notes: "Economy tier. Text only. Narrow mechanical work.",
128
+ },
129
+ {
130
+ key: "opencode-go/longcat-2.0",
131
+ providerID: "opencode-go",
132
+ modelID: "longcat-2.0",
133
+ name: "LongCat-2.0",
134
+ context: 1_000_000,
135
+ maxOutput: 131_072,
136
+ input: ["text"],
137
+ cost: cost(0.3, 1.2, 0.006),
138
+ intelligence: 19.1,
139
+ design: 40,
140
+ designEvidence: "curated",
141
+ tier: 1,
142
+ monthlyAllowanceUsd: 240,
143
+ notes: "Economy tier. Very low intelligence; use only with deterministic validation.",
144
+ },
145
+
146
+ // ---------------------------------------------------------------------------
147
+ // OpenCode Go: standard
148
+ // ---------------------------------------------------------------------------
149
+ {
150
+ key: "opencode-go/deepseek-v4.1-flash",
151
+ providerID: "opencode-go",
152
+ modelID: "deepseek-v4.1-flash",
153
+ name: "DeepSeek V4.1 Flash",
154
+ context: 1_000_000,
155
+ maxOutput: 384_000,
156
+ input: ["text", "image"],
157
+ cost: cost(0.15, 0.6, 0.003),
158
+ peakPricing: DEEPSEEK_PEAK_PRICING,
159
+ intelligence: 39.5,
160
+ design: 65,
161
+ designEvidence: "observed",
162
+ tier: 2,
163
+ monthlyAllowanceUsd: 80,
164
+ notes:
165
+ "Approved standard floor. Strong general coding value and native image input. Off-peak list price; 2x during 01-04 and 06-10 UTC Mon-Fri.",
166
+ },
167
+ {
168
+ key: "opencode-go/glm-5.3-flash",
169
+ providerID: "opencode-go",
170
+ modelID: "glm-5.3-flash",
171
+ name: "GLM-5.3-Flash",
172
+ context: 1_000_000,
173
+ maxOutput: 131_072,
174
+ input: ["text", "image", "video"],
175
+ cost: cost(0.15, 0.5, 0.03),
176
+ intelligence: 41.8,
177
+ design: 65,
178
+ designEvidence: "curated",
179
+ tier: 2,
180
+ monthlyAllowanceUsd: 60,
181
+ },
182
+ {
183
+ key: "opencode-go/minimax-m3.1-flash",
184
+ providerID: "opencode-go",
185
+ modelID: "minimax-m3.1-flash",
186
+ name: "MiniMax M3.1 Flash",
187
+ context: 1_000_000,
188
+ maxOutput: 512_000,
189
+ input: ["text", "image", "video"],
190
+ cost: cost(0.15, 0.6, 0.015),
191
+ intelligence: 42.7,
192
+ design: 60,
193
+ designEvidence: "curated",
194
+ tier: 2,
195
+ monthlyAllowanceUsd: 20,
196
+ },
197
+ {
198
+ key: "opencode-go/claude-haiku-5-5",
199
+ providerID: "opencode-go",
200
+ modelID: "claude-haiku-5-5",
201
+ name: "Claude Haiku 5.5",
202
+ context: 1_000_000,
203
+ maxOutput: 128_000,
204
+ input: ["text", "image", "pdf"],
205
+ cost: tieredCost(cost(0.1, 0.5, 0.01, 0.125)[0]!, 100_000, { input: 0.5, output: 2.5, read: 0.05, write: 0.625 }),
206
+ intelligence: 43.4,
207
+ design: 70,
208
+ designEvidence: "curated",
209
+ tier: 2,
210
+ monthlyAllowanceUsd: 15,
211
+ },
212
+ {
213
+ key: "opencode-go/mimo-v2.6-pro",
214
+ providerID: "opencode-go",
215
+ modelID: "mimo-v2.6-pro",
216
+ name: "MiMo-V2.6-Pro",
217
+ context: 1_048_576,
218
+ maxOutput: 131_072,
219
+ input: ["text", "image", "audio", "video"],
220
+ cost: cost(0.435, 0.87, 0.003625),
221
+ intelligence: 46.3,
222
+ design: 62,
223
+ designEvidence: "curated",
224
+ tier: 2,
225
+ monthlyAllowanceUsd: 15,
226
+ notes: "High intelligence for its price. Narrow monthly allowance.",
227
+ },
228
+
229
+ // ---------------------------------------------------------------------------
230
+ // OpenCode Go: premium
231
+ // ---------------------------------------------------------------------------
232
+ {
233
+ key: "opencode-go/glm-5.3",
234
+ providerID: "opencode-go",
235
+ modelID: "glm-5.3",
236
+ name: "GLM-5.3",
237
+ context: 1_000_000,
238
+ maxOutput: 131_072,
239
+ input: ["text"],
240
+ cost: cost(1.4, 4.4, 0.26),
241
+ intelligence: 44.8,
242
+ design: 80,
243
+ designEvidence: "curated",
244
+ premium: true,
245
+ tier: 3,
246
+ monthlyAllowanceUsd: 15,
247
+ notes: "Premium. Text only, so it can never receive screenshots.",
248
+ },
249
+ {
250
+ key: "opencode-go/kimi-k3",
251
+ providerID: "opencode-go",
252
+ modelID: "kimi-k3",
253
+ name: "Kimi K3",
254
+ context: 1_048_576,
255
+ maxOutput: 131_072,
256
+ input: ["text", "image", "video"],
257
+ cost: cost(3, 15, 0.3, 3),
258
+ intelligence: 43.6,
259
+ design: 72,
260
+ designEvidence: "curated",
261
+ premium: true,
262
+ tier: 3,
263
+ monthlyAllowanceUsd: 15,
264
+ },
265
+ {
266
+ key: "opencode-go/grok-4.7",
267
+ providerID: "opencode-go",
268
+ modelID: "grok-4.7",
269
+ name: "Grok 4.7",
270
+ context: 500_000,
271
+ maxOutput: 500_000,
272
+ input: ["text", "image", "pdf"],
273
+ cost: tieredCost(cost(2, 6, 0.5)[0]!, 200_000, { input: 4, output: 12, read: 1, write: 0 }),
274
+ intelligence: 46.4,
275
+ design: 75,
276
+ designEvidence: "curated",
277
+ premium: true,
278
+ tier: 3,
279
+ monthlyAllowanceUsd: 15,
280
+ },
281
+ {
282
+ key: "opencode-go/qwen3.8-max",
283
+ providerID: "opencode-go",
284
+ modelID: "qwen3.8-max",
285
+ name: "Qwen3.8 Max",
286
+ context: 1_000_000,
287
+ maxOutput: 131_072,
288
+ input: ["text", "image", "video"],
289
+ cost: cost(2, 6, 0.25, 2.5),
290
+ intelligence: 40.2,
291
+ design: 70,
292
+ designEvidence: "curated",
293
+ premium: true,
294
+ tier: 3,
295
+ monthlyAllowanceUsd: 15,
296
+ },
297
+ {
298
+ key: "opencode-go/step-5-preview",
299
+ providerID: "opencode-go",
300
+ modelID: "step-5-preview",
301
+ name: "Step 5 Preview",
302
+ context: 1_000_000,
303
+ maxOutput: 65_536,
304
+ input: ["text", "image", "video"],
305
+ cost: cost(1, 2.7, 0.1),
306
+ intelligence: 43.7,
307
+ design: 70,
308
+ designEvidence: "curated",
309
+ premium: true,
310
+ tier: 3,
311
+ monthlyAllowanceUsd: 15,
312
+ },
313
+
314
+ // ---------------------------------------------------------------------------
315
+ // Command Code GOAT: standard
316
+ // ---------------------------------------------------------------------------
317
+ {
318
+ key: "commandcode/deepseek/deepseek-v4.1-flash",
319
+ providerID: "commandcode",
320
+ modelID: "deepseek/deepseek-v4.1-flash",
321
+ name: "DeepSeek V4.1 Flash (GOAT)",
322
+ context: 1_000_000,
323
+ maxOutput: 384_000,
324
+ input: ["text", "image"],
325
+ cost: cost(0.15, 0.6, 0.003),
326
+ peakPricing: COMMAND_CODE_DEEPSEEK_PEAK,
327
+ intelligence: 39.5,
328
+ design: 65,
329
+ designEvidence: "observed",
330
+ tier: 2,
331
+ monthlyAllowanceUsd: 80,
332
+ notes: "Approved standard floor on Command Code. Off-peak list price; 2x during 01-04 and 06-10 UTC Mon-Fri.",
333
+ },
334
+ {
335
+ key: "commandcode/z-ai/glm-5.3-flash",
336
+ providerID: "commandcode",
337
+ modelID: "z-ai/glm-5.3-flash",
338
+ name: "GLM-5.3-Flash",
339
+ context: 1_000_000,
340
+ maxOutput: 131_072,
341
+ input: ["text", "image", "video", "pdf"],
342
+ cost: cost(0.15, 0.5, 0.03),
343
+ intelligence: 41.8,
344
+ design: 65,
345
+ designEvidence: "curated",
346
+ tier: 2,
347
+ monthlyAllowanceUsd: 80,
348
+ },
349
+ {
350
+ key: "commandcode/claude-haiku-5-5",
351
+ providerID: "commandcode",
352
+ modelID: "claude-haiku-5-5",
353
+ name: "Claude Haiku 5.5",
354
+ context: 1_000_000,
355
+ maxOutput: 128_000,
356
+ input: ["text", "image", "pdf"],
357
+ cost: tieredCost(cost(0.1, 0.5, 0.01, 0.125)[0]!, 100_000, { input: 0.5, output: 2.5, read: 0.05, write: 0.625 }),
358
+ intelligence: 43.4,
359
+ design: 70,
360
+ designEvidence: "curated",
361
+ tier: 2,
362
+ monthlyAllowanceUsd: 20,
363
+ },
364
+ {
365
+ key: "commandcode/gpt-6-luna",
366
+ providerID: "commandcode",
367
+ modelID: "gpt-6-luna",
368
+ name: "GPT-6 Luna",
369
+ context: 1_050_000,
370
+ maxOutput: 128_000,
371
+ input: ["text", "image", "pdf"],
372
+ cost: tieredCost(cost(0.1, 0.5, 0.01, 0.125)[0]!, 272_000, { input: 0.2, output: 0.75, read: 0.02, write: 0.25 }),
373
+ intelligence: 38.1,
374
+ design: 55,
375
+ designEvidence: "curated",
376
+ tier: 1,
377
+ monthlyAllowanceUsd: 20,
378
+ },
379
+
380
+ // ---------------------------------------------------------------------------
381
+ // Command Code GOAT: premium
382
+ // ---------------------------------------------------------------------------
383
+ {
384
+ key: "commandcode/claude-sonnet-5-5",
385
+ providerID: "commandcode",
386
+ modelID: "claude-sonnet-5-5",
387
+ name: "Claude Sonnet 5.5",
388
+ context: 1_000_000,
389
+ maxOutput: 128_000,
390
+ input: ["text", "image", "pdf"],
391
+ cost: cost(2, 10, 0.1, 2.5),
392
+ intelligence: 56,
393
+ design: 90,
394
+ designEvidence: "curated",
395
+ premium: true,
396
+ tier: 3,
397
+ monthlyAllowanceUsd: 10,
398
+ notes: "Premium design and architecture candidate. Very small monthly allowance.",
399
+ },
400
+ {
401
+ key: "commandcode/meta/muse-spark-1.3",
402
+ providerID: "commandcode",
403
+ modelID: "meta/muse-spark-1.3",
404
+ name: "Muse Spark 1.3",
405
+ context: 1_048_576,
406
+ maxOutput: 131_072,
407
+ input: ["text", "image", "video", "pdf", "audio"],
408
+ cost: cost(1.25, 4.25, 0.15),
409
+ intelligence: 48.1,
410
+ design: 82,
411
+ designEvidence: "curated",
412
+ premium: true,
413
+ tier: 3,
414
+ monthlyAllowanceUsd: 20,
415
+ },
416
+ {
417
+ key: "commandcode/google/gemini-4-argon",
418
+ providerID: "commandcode",
419
+ modelID: "google/gemini-4-argon",
420
+ name: "Gemini 4 Argon",
421
+ context: 1_000_000,
422
+ maxOutput: 65_536,
423
+ input: ["text", "image", "video", "audio", "pdf"],
424
+ cost: cost(2, 10, 0.1),
425
+ intelligence: 0,
426
+ design: 85,
427
+ designEvidence: "unverified",
428
+ premium: true,
429
+ tier: 3,
430
+ approved: false,
431
+ monthlyAllowanceUsd: 40,
432
+ notes: "Unscored in the current model cards. Excluded from automatic routing until qualified.",
433
+ },
434
+ {
435
+ key: "commandcode/xai/grok-4.7",
436
+ providerID: "commandcode",
437
+ modelID: "xai/grok-4.7",
438
+ name: "Grok 4.7",
439
+ context: 500_000,
440
+ maxOutput: 500_000,
441
+ input: ["text", "image", "pdf"],
442
+ cost: tieredCost(cost(2, 6, 0.5)[0]!, 200_000, { input: 4, output: 12, read: 1, write: 0 }),
443
+ intelligence: 46.4,
444
+ design: 75,
445
+ designEvidence: "curated",
446
+ premium: true,
447
+ tier: 3,
448
+ monthlyAllowanceUsd: 20,
449
+ },
450
+ {
451
+ key: "commandcode/Qwen/Qwen3.8-Max",
452
+ providerID: "commandcode",
453
+ modelID: "Qwen/Qwen3.8-Max",
454
+ name: "Qwen3.8 Max",
455
+ context: 1_000_000,
456
+ maxOutput: 131_072,
457
+ input: ["text", "image", "video", "pdf"],
458
+ cost: cost(2, 6, 0.25, 2.5),
459
+ intelligence: 40.2,
460
+ design: 70,
461
+ designEvidence: "curated",
462
+ premium: true,
463
+ tier: 3,
464
+ monthlyAllowanceUsd: 20,
465
+ },
466
+ {
467
+ key: "commandcode/stepfun/Step-5-Preview",
468
+ providerID: "commandcode",
469
+ modelID: "stepfun/Step-5-Preview",
470
+ name: "Step 5 Preview",
471
+ context: 1_000_000,
472
+ maxOutput: 1_000_000,
473
+ input: ["text", "image", "video"],
474
+ cost: cost(1, 2.7, 0.05),
475
+ intelligence: 43.7,
476
+ design: 70,
477
+ designEvidence: "curated",
478
+ premium: true,
479
+ tier: 3,
480
+ monthlyAllowanceUsd: 20,
481
+ },
482
+
483
+ // ---------------------------------------------------------------------------
484
+ // Known but deliberately unapproved models. They are discovered so the user
485
+ // can qualify them explicitly, but automatic routing never selects them.
486
+ // ---------------------------------------------------------------------------
487
+ {
488
+ key: "commandcode/claude-opus-5-5",
489
+ providerID: "commandcode",
490
+ modelID: "claude-opus-5-5",
491
+ name: "Claude Opus 5.5",
492
+ context: 1_000_000,
493
+ maxOutput: 128_000,
494
+ input: ["text", "image", "pdf"],
495
+ cost: cost(4, 20, 0.2, 5),
496
+ intelligence: 0,
497
+ design: 92,
498
+ designEvidence: "unverified",
499
+ premium: true,
500
+ tier: 3,
501
+ approved: false,
502
+ monthlyAllowanceUsd: 10,
503
+ notes: "Unscored in the current model cards. Explicit approval required.",
504
+ },
505
+ {
506
+ key: "commandcode/gpt-6.1-sol",
507
+ providerID: "commandcode",
508
+ modelID: "gpt-6.1-sol",
509
+ name: "GPT-6.1 Sol",
510
+ context: 1_050_000,
511
+ maxOutput: 128_000,
512
+ input: ["text", "image", "pdf"],
513
+ cost: tieredCost(cost(2, 10, 0.1, 2.5)[0]!, 272_000, { input: 4, output: 15, read: 0.2, write: 5 }),
514
+ intelligence: 0,
515
+ design: 88,
516
+ designEvidence: "unverified",
517
+ premium: true,
518
+ tier: 3,
519
+ approved: false,
520
+ monthlyAllowanceUsd: 20,
521
+ notes: "Unscored in the current model cards. Explicit approval required.",
522
+ },
523
+ {
524
+ key: "commandcode/gpt-6-astra",
525
+ providerID: "commandcode",
526
+ modelID: "gpt-6-astra",
527
+ name: "GPT-6 Astra",
528
+ context: 1_050_000,
529
+ maxOutput: 128_000,
530
+ input: ["text", "image", "pdf"],
531
+ cost: tieredCost(cost(10, 50, 1, 12.5)[0]!, 272_000, { input: 20, output: 75, read: 2, write: 25 }),
532
+ intelligence: 0,
533
+ design: 88,
534
+ designEvidence: "unverified",
535
+ premium: true,
536
+ tier: 3,
537
+ approved: false,
538
+ monthlyAllowanceUsd: 10,
539
+ notes: "Frontier-priced model. Never selected automatically without explicit approval.",
540
+ },
541
+ {
542
+ key: "commandcode/claude-fable-5-1",
543
+ providerID: "commandcode",
544
+ modelID: "claude-fable-5-1",
545
+ name: "Claude Fable 5.1",
546
+ context: 1_000_000,
547
+ maxOutput: 128_000,
548
+ input: ["text", "image", "pdf"],
549
+ cost: cost(10, 50, 0.25, 12.5),
550
+ intelligence: 0,
551
+ design: 90,
552
+ designEvidence: "unverified",
553
+ premium: true,
554
+ tier: 3,
555
+ approved: false,
556
+ monthlyAllowanceUsd: 10,
557
+ notes: "Frontier-priced model. Never selected automatically without explicit approval.",
558
+ },
559
+ {
560
+ key: "opencode-go/gemini-4-argon",
561
+ providerID: "opencode-go",
562
+ modelID: "gemini-4-argon",
563
+ name: "Gemini 4 Argon",
564
+ context: 1_048_576,
565
+ maxOutput: 65_536,
566
+ input: ["text", "image", "video", "audio", "pdf"],
567
+ cost: cost(2, 10, 0.1),
568
+ intelligence: 0,
569
+ design: 85,
570
+ designEvidence: "unverified",
571
+ premium: true,
572
+ tier: 3,
573
+ approved: false,
574
+ monthlyAllowanceUsd: 120,
575
+ notes: "Unscored in the current model cards. Explicit approval required.",
576
+ },
577
+ {
578
+ key: "opencode-go/kimi-k3.1-pro",
579
+ providerID: "opencode-go",
580
+ modelID: "kimi-k3.1-pro",
581
+ name: "Kimi K3.1 Pro",
582
+ context: 1_048_576,
583
+ maxOutput: 131_072,
584
+ input: ["text", "image", "video"],
585
+ cost: cost(2, 10, 0.2, 2),
586
+ intelligence: 0,
587
+ design: 75,
588
+ designEvidence: "unverified",
589
+ premium: true,
590
+ tier: 3,
591
+ approved: false,
592
+ monthlyAllowanceUsd: 60,
593
+ notes: "Unscored in the current model cards. Explicit approval required.",
594
+ },
595
+ {
596
+ key: "commandcode/meta/muse-spark-1.3-contributor",
597
+ providerID: "commandcode",
598
+ modelID: "meta/muse-spark-1.3-contributor",
599
+ name: "Muse Spark 1.3 (Contributor)",
600
+ context: 1_048_576,
601
+ maxOutput: 131_072,
602
+ input: ["text", "image", "video", "pdf", "audio"],
603
+ cost: cost(0.1, 0.2, 0.002),
604
+ intelligence: 0,
605
+ design: 80,
606
+ designEvidence: "unverified",
607
+ training: true,
608
+ tier: 1,
609
+ approved: false,
610
+ monthlyAllowanceUsd: 20,
611
+ notes: "Training-enabled contributor tier. Blocked unless privacy.allowTrainingModels is true.",
612
+ },
613
+ {
614
+ key: "opencode-go/muse-spark-1.3-contributor",
615
+ providerID: "opencode-go",
616
+ modelID: "muse-spark-1.3-contributor",
617
+ name: "Muse Spark 1.3 Contributor",
618
+ context: 1_048_576,
619
+ maxOutput: 131_072,
620
+ input: ["text", "image", "video", "pdf", "audio"],
621
+ cost: cost(0.1, 0.2, 0.002),
622
+ intelligence: 0,
623
+ design: 80,
624
+ designEvidence: "unverified",
625
+ training: true,
626
+ tier: 1,
627
+ approved: false,
628
+ monthlyAllowanceUsd: 120,
629
+ notes: "Training-enabled contributor tier. Blocked unless privacy.allowTrainingModels is true.",
630
+ },
631
+ {
632
+ key: "opencode-go/iceman-contributor-free",
633
+ providerID: "opencode-go",
634
+ modelID: "iceman-contributor-free",
635
+ name: "Iceman Contributor Free",
636
+ context: 262_144,
637
+ maxOutput: 131_072,
638
+ input: ["text"],
639
+ cost: cost(0, 0, 0),
640
+ intelligence: 0,
641
+ design: 0,
642
+ designEvidence: "unverified",
643
+ training: true,
644
+ free: true,
645
+ tier: 1,
646
+ approved: false,
647
+ monthlyAllowanceUsd: 0,
648
+ notes: "Free model that trains on data. Blocked by default.",
649
+ },
650
+ {
651
+ key: "opencode-go/beam-free",
652
+ providerID: "opencode-go",
653
+ modelID: "beam-free",
654
+ name: "Beam Free",
655
+ context: 1_048_576,
656
+ maxOutput: 131_072,
657
+ input: ["text"],
658
+ cost: cost(0, 0, 0),
659
+ intelligence: 0,
660
+ design: 0,
661
+ designEvidence: "unverified",
662
+ free: true,
663
+ tier: 1,
664
+ approved: false,
665
+ monthlyAllowanceUsd: 0,
666
+ notes: "Free promotional model. Not approved for automatic work.",
667
+ },
668
+ {
669
+ key: "opencode-go/deepseek-v4-pro",
670
+ providerID: "opencode-go",
671
+ modelID: "deepseek-v4-pro",
672
+ name: "DeepSeek V4 Pro",
673
+ context: 1_000_000,
674
+ maxOutput: 384_000,
675
+ input: ["text"],
676
+ cost: cost(0.66, 1.98, 0.022),
677
+ intelligence: 36,
678
+ design: 55,
679
+ designEvidence: "curated",
680
+ tier: 2,
681
+ approved: false,
682
+ monthlyAllowanceUsd: 60,
683
+ notes: "Below the current standard floor and text only. Not approved automatically.",
684
+ },
685
+ ]
686
+
687
+ /**
688
+ * OpenDesign: the models served by the OpenDesign gateway.
689
+ *
690
+ * These entries are generated from the provider catalog so the published
691
+ * credit multipliers live in exactly one place. The gateway's `GET /v1/models`
692
+ * response is authoritative for entitlement and for the usable context window,
693
+ * and the discovery adapter merges it over these values at runtime.
694
+ *
695
+ * Which funding pool a model draws from is decided by the plan catalog. A
696
+ * Design Plan model carries its multiplier; a plan model does not, because
697
+ * the multiplier does not follow it into the plan model pool.
698
+ */
699
+ const OPENDESIGN_SEED_MODELS: ReadonlyArray<SeedModel> = OPENDESIGN_MODELS.map((model) => ({
700
+ key: `opendesign/${model.modelID}`,
701
+ providerID: "opendesign",
702
+ modelID: model.modelID,
703
+ name: model.name,
704
+ context: model.context,
705
+ maxOutput: model.maxOutput,
706
+ input: [...model.input],
707
+ tools: true,
708
+ cost: model.cost.map((tier) => ({ ...tier, cache: { ...tier.cache } })),
709
+ // The multiplier only applies to the Design Plan pool. A plan model is
710
+ // billed at plain usage value from the separate plan model pool, so it
711
+ // must not carry a Design Plan multiplier into cost estimation.
712
+ ...(OPENDESIGN_DESIGN_PLAN_MODELS.has(model.modelID) ? { creditMultiplier: model.creditMultiplier } : {}),
713
+ escalationOnly: !OPENDESIGN_DESIGN_PLAN_MODELS.has(model.modelID),
714
+ intelligence: model.intelligence,
715
+ design: model.design,
716
+ designEvidence: model.designEvidence,
717
+ tier: model.tier,
718
+ approved: model.approved,
719
+ // Every OpenDesign allowance is a shared provider-level pool, so no model
720
+ // carries its own monthly allowance.
721
+ monthlyAllowanceUsd: 0,
722
+ notes: model.notes,
723
+ }))
724
+
725
+ /**
726
+ * Local models served by Ollama.
727
+ *
728
+ * These are deliberately *not* approved for automatic online routing. A 4B
729
+ * local model scoring in the high 30s would be competitive with the hosted
730
+ * standard floor on paper, and the router would happily send real work to it,
731
+ * which is not what the owner wants when connected. Offline mode reaches them
732
+ * through the offline allow-list instead, where the choice is explicit.
733
+ *
734
+ * Cost is zero and there is no allowance, because inference runs on hardware
735
+ * the owner already paid for. `free: true` would route them through the
736
+ * privacy guard for promotional models, which is the wrong concept, so it is
737
+ * left unset.
738
+ */
739
+ const LOCAL_SEED_MODELS: ReadonlyArray<SeedModel> = [
740
+ {
741
+ key: "ollama/qwen3.5:4b-q4_K_M",
742
+ providerID: "ollama",
743
+ modelID: "qwen3.5:4b-q4_K_M",
744
+ name: "Qwen3.5 4B (local)",
745
+ // Matches offline.model.contextTokens. A larger declared window would let
746
+ // the router believe it can take a transcript the server is configured to
747
+ // truncate.
748
+ context: 8_192,
749
+ maxOutput: 2_048,
750
+ input: ["text", "image"],
751
+ tools: true,
752
+ cost: [{ input: 0, output: 0, cache: { read: 0, write: 0 } }],
753
+ // Scored below the hosted standard floor on purpose: these numbers describe
754
+ // real capability, and reporting them low keeps the model out of any online
755
+ // automatic decision even if someone approves it later.
756
+ intelligence: 30,
757
+ design: 40,
758
+ designEvidence: "unverified",
759
+ tier: 1,
760
+ approved: false,
761
+ monthlyAllowanceUsd: 0,
762
+ notes:
763
+ "Local Ollama model for offline development. Vision and tool calling. Not for online routing: the intelligence and design scores are deliberately below the hosted floor because a 4B model should not silently replace a hosted standard model when the network is available.",
764
+ },
765
+ ]
766
+
767
+ export const SEED_MODELS: ReadonlyArray<SeedModel> = [
768
+ ...BASE_SEED_MODELS,
769
+ ...OPENDESIGN_SEED_MODELS,
770
+ ...LOCAL_SEED_MODELS,
771
+ ]