@namzu/zen 4.0.2 → 5.0.1

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.
@@ -114,10 +114,30 @@ export const ROUTES: readonly {
114
114
  readonly protocol: ZenProtocol
115
115
  readonly kind: 'path' | 'model'
116
116
  }[] = Object.freeze([
117
- { npm: '@ai-sdk/openai-compatible', path: '/chat/completions', protocol: 'chat', kind: 'path' },
118
- { npm: '@ai-sdk/openai', path: '/responses', protocol: 'responses', kind: 'path' },
119
- { npm: '@ai-sdk/anthropic', path: '/messages', protocol: 'messages', kind: 'path' },
120
- { npm: '@ai-sdk/google', path: '/models/', protocol: 'google', kind: 'model' },
117
+ {
118
+ npm: '@ai-sdk/openai-compatible',
119
+ path: '/chat/completions',
120
+ protocol: 'chat',
121
+ kind: 'path',
122
+ },
123
+ {
124
+ npm: '@ai-sdk/openai',
125
+ path: '/responses',
126
+ protocol: 'responses',
127
+ kind: 'path',
128
+ },
129
+ {
130
+ npm: '@ai-sdk/anthropic',
131
+ path: '/messages',
132
+ protocol: 'messages',
133
+ kind: 'path',
134
+ },
135
+ {
136
+ npm: '@ai-sdk/google',
137
+ path: '/models/',
138
+ protocol: 'google',
139
+ kind: 'model',
140
+ },
121
141
  ])
122
142
 
123
143
  /** The Google route's tail: `models/<id>`, and nothing else. */
@@ -141,14 +161,28 @@ export const SERVICE_PREFIX: Readonly<Record<ZenService, string>> = Object.freez
141
161
 
142
162
  /**
143
163
  * The path prefixes a documentation page may state an endpoint on, per
144
- * service. The gateway answers on both: `/zen/v1/…` is what the client and
145
- * this package call, and `/inference/v1/…` is the alias the documentation
146
- * pages now publish. Both resolve to the same service, so a row on either is
147
- * a route on that service.
164
+ * service. The gateway answers on all of these: `/zen/v1/…` is what the client
165
+ * and this package call, and the pages have published aliases across the
166
+ * gateway's history — a flat `/inference/v1/…`, then per-wire
167
+ * `/inference/<wire>/…` paths, where each wire's documentation names its own
168
+ * version segment (`openai/v1`, `google/v1beta`). Every one resolves to the
169
+ * same service, so a row on any of them is a route on that service.
148
170
  */
149
171
  export const DOCUMENTED_PREFIXES: Readonly<Record<ZenService, readonly string[]>> = Object.freeze({
150
- zen: Object.freeze(['/zen/v1/', '/inference/v1/']),
151
- go: Object.freeze(['/zen/go/v1/', '/inference/go/v1/']),
172
+ zen: Object.freeze([
173
+ '/zen/v1/',
174
+ '/inference/v1/',
175
+ '/inference/openai/v1/',
176
+ '/inference/anthropic/v1/',
177
+ '/inference/google/v1beta/',
178
+ ]),
179
+ go: Object.freeze([
180
+ '/zen/go/v1/',
181
+ '/inference/go/v1/',
182
+ '/inference/go/openai/v1/',
183
+ '/inference/go/anthropic/v1/',
184
+ '/inference/go/google/v1beta/',
185
+ ]),
152
186
  })
153
187
 
154
188
  /** One route-table row. `npm` is undefined when the page states no wire. */
@@ -389,47 +423,101 @@ export function priceRowFor(rows: readonly ZenPriceRow[], name: string): ZenPric
389
423
  }
390
424
 
391
425
  /**
392
- * The protocol a (package, endpoint) pair is, refusing anything unrecognised.
426
+ * The verdict on one route row's (package, endpoint) pair: the protocol to
427
+ * route it with, or the reason no wire follows from it, and whether the
428
+ * refusal indicts the run or merely the row.
429
+ *
430
+ * A pair that names an endpoint OUTSIDE the service's host is tamper-shaped —
431
+ * the whole point of the per-part checks — so its refusal is fatal and must
432
+ * stop the run no matter how derivable the rest of the page is. Everything
433
+ * else this classifier cannot read is upstream having grown a wire this
434
+ * driver does not speak (a new endpoint family on the service's own host, an
435
+ * AI SDK package not implemented yet): the refusal is per-row, and the
436
+ * derivation decides what to do with it.
393
437
  *
394
438
  * The pair is checked against the URL's own parts rather than by substring: a
395
439
  * cell reading `https://evil.example/messages` contains the path a Messages
396
440
  * route has, and a routing decision that accepts it is a routing decision made
397
441
  * on the wrong string. Host, service prefix, path and package must all agree.
398
442
  */
399
- export function protocolFor(
400
- { id, endpoint, npm }: Pick<ZenRouteRow, 'id' | 'endpoint' | 'npm'>,
443
+ export function routeFor(
444
+ { endpoint, npm }: Pick<ZenRouteRow, 'id' | 'endpoint' | 'npm'>,
401
445
  service: string,
402
- ): ZenProtocol {
403
- const refuse = (why: string): never =>
404
- unusable(
405
- `"${id}" is documented as ${npm} on ${endpoint}, ${why}. A model whose wire is not\n known cannot be routed, so the run stops rather than picking one.`,
406
- )
446
+ ): { readonly protocol: ZenProtocol } | { readonly refusal: string; readonly fatal: boolean } {
407
447
  if (npm === undefined) {
408
- unusable(
409
- `"${id}" is documented on ${endpoint} with no AI SDK package stated, so no wire is\n known. A model whose wire is not known cannot be routed, so the run stops\n rather than picking one.`,
410
- )
448
+ return {
449
+ refusal: 'the page states no AI SDK package for it, so no wire is known',
450
+ fatal: false,
451
+ }
411
452
  }
412
453
  let url: URL
413
454
  try {
414
455
  url = new URL(endpoint)
415
456
  } catch {
416
- return refuse('which is not a URL')
457
+ return {
458
+ refusal: 'the endpoint cell is not a URL, so no wire can be read',
459
+ fatal: true,
460
+ }
461
+ }
462
+ if (url.host !== 'opencode.ai') {
463
+ return { refusal: "whose host is not the service's", fatal: true }
417
464
  }
418
- if (url.host !== 'opencode.ai') refuse("whose host is not the service's")
419
465
  const prefixes = (DOCUMENTED_PREFIXES as Record<string, readonly string[] | undefined>)[service]
420
- if (prefixes === undefined) return refuse('on a service this script does not know')
466
+ if (prefixes === undefined) {
467
+ return { refusal: 'on a service this script does not know', fatal: true }
468
+ }
421
469
  const prefix = prefixes.find((candidate) => url.pathname.startsWith(candidate))
422
- if (prefix === undefined) return refuse(`which is not on the ${service} service's own path`)
470
+ if (prefix === undefined) {
471
+ return {
472
+ refusal: `which is not on the ${service} service's own path`,
473
+ fatal: false,
474
+ }
475
+ }
423
476
  const route = ROUTES.find((candidate) => candidate.npm === npm)
424
477
  if (!route) {
425
- return refuse(
426
- `with a package that is not one of the ${ROUTES.length} routes this driver implements`,
427
- )
478
+ return {
479
+ refusal: `with a package that is not one of the ${ROUTES.length} routes this driver implements`,
480
+ fatal: false,
481
+ }
428
482
  }
429
483
  const tail = url.pathname.slice(prefix.length)
430
484
  const matches = route.kind === 'path' ? tail === route.path.slice(1) : MODEL_PATH.test(tail)
431
- if (!matches) refuse(`which does not address ${route.path} on the ${service} service`)
432
- return route.protocol
485
+ if (!matches) {
486
+ return {
487
+ refusal: `which does not address ${route.path} on the ${service} service`,
488
+ fatal: false,
489
+ }
490
+ }
491
+ return { protocol: route.protocol }
492
+ }
493
+
494
+ /** The message the run-wide refusal of a pair carries, in both surfaces. */
495
+ function refusalMessage(
496
+ { id, npm }: Pick<ZenRouteRow, 'id' | 'npm'>,
497
+ { endpoint }: Pick<ZenRouteRow, 'endpoint'>,
498
+ refusal: string,
499
+ ): string {
500
+ return `"${id}" is documented as ${npm} on ${endpoint}, ${refusal}. A model whose wire is not\n known cannot be routed, so the run stops rather than picking one.`
501
+ }
502
+
503
+ /**
504
+ * The protocol a (package, endpoint) pair is, refusing anything unrecognised.
505
+ *
506
+ * The derivation goes through `routeFor` instead, where an unrouteable row
507
+ * splits off into the undecided count and the rest of the roster carries on;
508
+ * here a caller that asks for the pair's protocol gets stopped immediately.
509
+ * Either way nothing is guessed: a model whose wire is unknown is never routed
510
+ * by picking a protocol for it.
511
+ */
512
+ export function protocolFor(
513
+ { id, endpoint, npm }: Pick<ZenRouteRow, 'id' | 'endpoint' | 'npm'>,
514
+ service: string,
515
+ ): ZenProtocol {
516
+ const verdict = routeFor({ id, endpoint, npm }, service)
517
+ if ('refusal' in verdict) {
518
+ unusable(refusalMessage({ id, npm }, { endpoint }, verdict.refusal))
519
+ }
520
+ return verdict.protocol
433
521
  }
434
522
 
435
523
  /**
@@ -465,18 +553,27 @@ export function pinnedProtocolForGo(id: string): ZenProtocol | undefined {
465
553
  return GO_REFERENCE_ROUTES[id]?.gateway
466
554
  }
467
555
 
468
- function pinnedProtocolFor(row: ZenRouteRow, service: string): ZenProtocol {
469
- const documented = protocolFor(row, service)
470
- if (service !== 'go') return documented
556
+ /**
557
+ * The row's routed protocol, or its refusal — the Go pinning decides the same
558
+ * way `routeFor` does, then names the reference client's wire for the ids the
559
+ * published page and the reference client disagree on.
560
+ */
561
+ function pinnedRouteFor(
562
+ row: ZenRouteRow,
563
+ service: string,
564
+ ): { readonly protocol: ZenProtocol } | { readonly refusal: string; readonly fatal: boolean } {
565
+ const verdict = routeFor(row, service)
566
+ if ('refusal' in verdict) return verdict
567
+ if (service !== 'go') return verdict
471
568
  const exception = GO_REFERENCE_ROUTES[row.id]
472
- if (!exception) return documented
473
- if (documented === exception.gateway) return documented
474
- if (documented !== exception.documented) {
569
+ if (!exception) return verdict
570
+ if (verdict.protocol === exception.gateway) return verdict
571
+ if (verdict.protocol !== exception.documented) {
475
572
  unusable(
476
- `go.mdx changed the route for "${row.id}" to ${documented}; its reference-client route exception must be reviewed.`,
573
+ `go.mdx changed the route for "${row.id}" to ${verdict.protocol}; its reference-client route exception must be reviewed.`,
477
574
  )
478
575
  }
479
- return exception.gateway
576
+ return { protocol: exception.gateway }
480
577
  }
481
578
 
482
579
  /** A models.dev model entry, as far as these rules read it. */
@@ -484,7 +581,10 @@ interface ModelsDevEntry {
484
581
  readonly limit?: { readonly context?: number; readonly output?: number }
485
582
  readonly modalities?: { readonly input?: readonly string[] }
486
583
  readonly tool_call?: boolean
487
- readonly reasoning_options?: readonly { readonly type?: string; readonly values?: unknown }[]
584
+ readonly reasoning_options?: readonly {
585
+ readonly type?: string
586
+ readonly values?: unknown
587
+ }[]
488
588
  }
489
589
 
490
590
  /** A models.dev provider entry: its models, keyed by id. */
@@ -602,6 +702,22 @@ export function derive(
602
702
  continue
603
703
  }
604
704
  considered += 1
705
+ // The wire a row names is decided before anything else is asked about
706
+ // it, because every carried form needs it. A pair no routing follows
707
+ // from — upstream naming a model on a wire this driver does not speak
708
+ // — splits off into the undecided count here instead of stopping the
709
+ // run: the rest of the roster is exactly as derivable as it was before
710
+ // the row arrived, and one new wire upstream should not hold every
711
+ // other model back either. Nothing is guessed for the row.
712
+ const routed = pinnedRouteFor(row, service)
713
+ if ('refusal' in routed) {
714
+ if (routed.fatal) {
715
+ unusable(refusalMessage(row, row, routed.refusal))
716
+ }
717
+ undecided.push([`${service}/${row.id}`, routed.refusal])
718
+ continue
719
+ }
720
+ const protocol = routed.protocol
605
721
  const metadata = provider.models[row.id] as ModelsDevEntry | undefined
606
722
  if (!metadata || typeof metadata !== 'object') {
607
723
  // The route and the price are stated and the limits are not, yet: carry it
@@ -613,7 +729,7 @@ export function derive(
613
729
  unverified.push({
614
730
  id: row.id,
615
731
  name: row.name,
616
- protocol: pinnedProtocolFor(row, service),
732
+ protocol,
617
733
  ...CONSERVATIVE_LIMITS,
618
734
  inputModalities: ['text'],
619
735
  inputPrice: statedPrice ? statedPrice.input : 0,
@@ -668,7 +784,7 @@ export function derive(
668
784
  models.push({
669
785
  id: row.id,
670
786
  name: row.name,
671
- protocol: pinnedProtocolFor(row, service),
787
+ protocol,
672
788
  contextWindow,
673
789
  maxOutputTokens,
674
790
  inputModalities,
package/src/client.ts CHANGED
@@ -900,6 +900,7 @@ export class ZenProvider implements LLMProvider {
900
900
  status: error.statusCode,
901
901
  body: scrub(error.responseBody ?? error.message),
902
902
  retryAfter: error.responseHeaders?.['retry-after'],
903
+ shouldRetry: error.responseHeaders?.['x-should-retry'],
903
904
  }),
904
905
  )
905
906
  if (APICallError.isInstance(error))
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "omissions": {
3
- "go/deepseek-flash": "Served by the Go service and named by no route row on either page; models.dev carries no entry for it either, so neither a wire nor its limits can be derived.",
4
3
  "go/glm-5.1": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
4
+ "go/kimi-k2.6": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
5
+ "go/minimax-m2.7": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
6
+ "go/grok-4.6": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
5
7
  "go/minimax-m2.5": "Superseded on Go by MiniMax M2.7 and M3, which are both carried. The page still lists it.",
6
8
  "go/omen-alpha": "Served by Go and no longer routed by the Go page, which is why this release dropped it from the catalogue. No source states a wire for it any more, so a caller that needs it must name the protocol itself.",
7
9
  "go/qwen3.6-plus": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, and the old bundled Messages route conflicts with the reference client's Chat route, so it is not carried by guessing.",
8
10
  "go/qwen3.7-max": "Still served by Go, but the current Go page states neither a route nor a price for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
9
11
  "zen/claude-opus-5-5-backup": "Served by the Zen /models answer as a failover twin of a routed model and named by no route row on either page. A backup id carries no route of its own, so no wire can be derived and a caller that needs it must name the protocol explicitly.",
12
+ "zen/deepseek-v4-flash": "Still served by Zen, but the current Zen page states no route for it. The /models answer states no wire, so the old bundled route is not carried without current evidence.",
10
13
  "zen/gemini-4-argon": "Routed by the Zen page, which states neither a price row nor a free-list entry for it. A price that cannot be read is never defaulted to zero, so it is not carried — least of all anonymously.",
11
14
  "zen/glm-5": "Superseded by GLM 5.1, 5.2 and 5.3, which are all carried. The page still lists it.",
12
15
  "zen/gpt-5-codex": "Superseded Codex generation; gpt-5.3-codex and gpt-5.3-codex-spark are carried.",
package/src/models.ts CHANGED
@@ -37,7 +37,7 @@ export interface ZenModel {
37
37
  * derived is an edit to src/catalogue/derive.ts. Both survive regeneration; a
38
38
  * hand edit here does not.
39
39
  *
40
- * Refreshed: 2026-10-13
40
+ * Refreshed: 2026-10-16
41
41
  *
42
42
  * This is the BUNDLED snapshot: what the driver knows with no network. A host
43
43
  * can derive a fresher roster at run time from the same sources, by the same
@@ -768,32 +768,6 @@ const ZEN_MODELS = freezeModels([
768
768
  supportsStreaming: true,
769
769
  effortLevels: ['high', 'max'],
770
770
  },
771
- {
772
- id: 'deepseek-v4-flash',
773
- name: 'DeepSeek V4 Flash',
774
- protocol: 'chat',
775
- contextWindow: 1000000,
776
- maxOutputTokens: 384000,
777
- inputModalities: ['text'],
778
- inputPrice: 0.14,
779
- outputPrice: 0.28,
780
- supportsToolUse: true,
781
- supportsStreaming: true,
782
- effortLevels: ['low', 'high', 'max'],
783
- },
784
- {
785
- id: 'deepseek-v4-flash-vision-exp',
786
- name: 'DeepSeek V4 Flash Vision Exp',
787
- protocol: 'chat',
788
- contextWindow: 1000000,
789
- maxOutputTokens: 384000,
790
- inputModalities: ['text', 'image'],
791
- inputPrice: 0.14,
792
- outputPrice: 0.28,
793
- supportsToolUse: true,
794
- supportsStreaming: true,
795
- effortLevels: ['low', 'high', 'max'],
796
- },
797
771
  {
798
772
  id: 'minimax-m3',
799
773
  name: 'MiniMax M3',
@@ -924,6 +898,32 @@ const ZEN_MODELS = freezeModels([
924
898
  supportsStreaming: true,
925
899
  effortLevels: [],
926
900
  },
901
+ {
902
+ id: 'glm-5.3-flash-free',
903
+ name: 'GLM-5.3-Flash Free',
904
+ protocol: 'chat',
905
+ contextWindow: 200000,
906
+ maxOutputTokens: 32000,
907
+ inputModalities: ['text', 'image', 'document'],
908
+ inputPrice: 0,
909
+ outputPrice: 0,
910
+ supportsToolUse: true,
911
+ supportsStreaming: true,
912
+ effortLevels: ['low', 'high', 'max'],
913
+ },
914
+ {
915
+ id: 'deepseek-v4.1-flash-free',
916
+ name: 'DeepSeek V4.1 Flash Free',
917
+ protocol: 'chat',
918
+ contextWindow: 200000,
919
+ maxOutputTokens: 32000,
920
+ inputModalities: ['text', 'image'],
921
+ inputPrice: 0,
922
+ outputPrice: 0,
923
+ supportsToolUse: true,
924
+ supportsStreaming: true,
925
+ effortLevels: ['low', 'high', 'max'],
926
+ },
927
927
  {
928
928
  id: 'space-bunny-free',
929
929
  supportsAnonymousAccess: true,
@@ -939,10 +939,10 @@ const ZEN_MODELS = freezeModels([
939
939
  effortLevels: ['low', 'medium', 'high', 'xhigh', 'max'],
940
940
  },
941
941
  {
942
- id: 'cat-jam-free',
943
- name: 'Cat Jam Free',
942
+ id: 'beam-free',
943
+ name: 'Beam Free',
944
944
  protocol: 'chat',
945
- contextWindow: 262144,
945
+ contextWindow: 1048576,
946
946
  maxOutputTokens: 131072,
947
947
  inputModalities: ['text'],
948
948
  inputPrice: 0,
@@ -952,30 +952,30 @@ const ZEN_MODELS = freezeModels([
952
952
  effortLevels: ['low', 'medium', 'high', 'xhigh', 'max'],
953
953
  },
954
954
  {
955
- id: 'longcat-2.5-preview-free',
956
- name: 'LongCat 2.5 Preview Free',
955
+ id: 'll-alpha-free',
956
+ name: 'LL Alpha Free',
957
957
  protocol: 'chat',
958
- contextWindow: 1000000,
959
- maxOutputTokens: 131072,
960
- inputModalities: ['text', 'image'],
958
+ contextWindow: 262144,
959
+ maxOutputTokens: 65536,
960
+ inputModalities: ['text'],
961
961
  inputPrice: 0,
962
962
  outputPrice: 0,
963
963
  supportsToolUse: true,
964
964
  supportsStreaming: true,
965
- effortLevels: [],
965
+ effortLevels: ['low', 'medium', 'high', 'xhigh', 'max'],
966
966
  },
967
967
  {
968
- id: 'step-5-preview-free',
969
- name: 'Step 5 Preview Free',
968
+ id: 'longcat-2.5-preview-free',
969
+ name: 'LongCat 2.5 Preview Free',
970
970
  protocol: 'chat',
971
971
  contextWindow: 1000000,
972
- maxOutputTokens: 65536,
972
+ maxOutputTokens: 131072,
973
973
  inputModalities: ['text', 'image'],
974
974
  inputPrice: 0,
975
975
  outputPrice: 0,
976
976
  supportsToolUse: true,
977
977
  supportsStreaming: true,
978
- effortLevels: ['low', 'medium', 'high'],
978
+ effortLevels: [],
979
979
  },
980
980
  {
981
981
  id: 'exo-free',
@@ -1016,32 +1016,6 @@ const ZEN_MODELS = freezeModels([
1016
1016
  supportsStreaming: true,
1017
1017
  effortLevels: [],
1018
1018
  },
1019
- {
1020
- id: 'ling-3.1-flash-free',
1021
- name: 'Ling 3.1 Flash Free',
1022
- protocol: 'chat',
1023
- contextWindow: 262144,
1024
- maxOutputTokens: 32768,
1025
- inputModalities: ['text'],
1026
- inputPrice: 0,
1027
- outputPrice: 0,
1028
- supportsToolUse: true,
1029
- supportsStreaming: true,
1030
- effortLevels: [],
1031
- },
1032
- {
1033
- id: 'ling-3.0-flash-fin-free',
1034
- name: 'Ling 3.0 Flash Fin Free',
1035
- protocol: 'chat',
1036
- contextWindow: 262144,
1037
- maxOutputTokens: 32768,
1038
- inputModalities: ['text'],
1039
- inputPrice: 0,
1040
- outputPrice: 0,
1041
- supportsToolUse: true,
1042
- supportsStreaming: true,
1043
- effortLevels: [],
1044
- },
1045
1019
  {
1046
1020
  id: 'nemotron-3-ultra-free',
1047
1021
  name: 'Nemotron 3 Ultra Free',
@@ -1068,6 +1042,19 @@ const ZEN_MODELS = freezeModels([
1068
1042
  supportsStreaming: true,
1069
1043
  effortLevels: [],
1070
1044
  },
1045
+ {
1046
+ id: 'nemotron-3.5-super-vl-free',
1047
+ name: 'Nemotron 3.5 Super VL Free',
1048
+ protocol: 'chat',
1049
+ contextWindow: 1048576,
1050
+ maxOutputTokens: 131072,
1051
+ inputModalities: ['text', 'image'],
1052
+ inputPrice: 0,
1053
+ outputPrice: 0,
1054
+ supportsToolUse: true,
1055
+ supportsStreaming: true,
1056
+ effortLevels: ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'],
1057
+ },
1071
1058
  {
1072
1059
  id: 'muse-spark-1.3-contributor-free',
1073
1060
  name: 'Muse Spark 1.3 Contributor Free',
@@ -1097,19 +1084,6 @@ const GO_MODELS = freezeModels([
1097
1084
  supportsStreaming: true,
1098
1085
  effortLevels: ['low', 'medium', 'high', 'xhigh'],
1099
1086
  },
1100
- {
1101
- id: 'grok-4.6',
1102
- name: 'Grok 4.6',
1103
- protocol: 'responses',
1104
- contextWindow: 500000,
1105
- maxOutputTokens: 500000,
1106
- inputModalities: ['text', 'image'],
1107
- inputPrice: 2.0,
1108
- outputPrice: 6.0,
1109
- supportsToolUse: true,
1110
- supportsStreaming: true,
1111
- effortLevels: ['low', 'medium', 'high', 'xhigh'],
1112
- },
1113
1087
  {
1114
1088
  id: 'gpt-6-luna',
1115
1089
  name: 'GPT 6 Luna',
@@ -1149,6 +1123,19 @@ const GO_MODELS = freezeModels([
1149
1123
  supportsStreaming: true,
1150
1124
  effortLevels: ['low', 'medium', 'high', 'xhigh', 'max'],
1151
1125
  },
1126
+ {
1127
+ id: 'gemini-4-argon-contributor',
1128
+ name: 'Gemini 4 Argon Contributor',
1129
+ protocol: 'google',
1130
+ contextWindow: 1048576,
1131
+ maxOutputTokens: 65536,
1132
+ inputModalities: ['text', 'image', 'document'],
1133
+ inputPrice: 4.0,
1134
+ outputPrice: 20.0,
1135
+ supportsToolUse: true,
1136
+ supportsStreaming: true,
1137
+ effortLevels: ['low', 'medium', 'high'],
1138
+ },
1152
1139
  {
1153
1140
  id: 'glm-5.3-flash',
1154
1141
  name: 'GLM-5.3-Flash',
@@ -1214,19 +1201,6 @@ const GO_MODELS = freezeModels([
1214
1201
  supportsStreaming: true,
1215
1202
  effortLevels: [],
1216
1203
  },
1217
- {
1218
- id: 'kimi-k2.6',
1219
- name: 'Kimi K2.6',
1220
- protocol: 'chat',
1221
- contextWindow: 262144,
1222
- maxOutputTokens: 65536,
1223
- inputModalities: ['text', 'image'],
1224
- inputPrice: 0.95,
1225
- outputPrice: 4.0,
1226
- supportsToolUse: true,
1227
- supportsStreaming: true,
1228
- effortLevels: [],
1229
- },
1230
1204
  {
1231
1205
  id: 'longcat-2.0',
1232
1206
  name: 'LongCat-2.0',
@@ -1266,32 +1240,6 @@ const GO_MODELS = freezeModels([
1266
1240
  supportsStreaming: true,
1267
1241
  effortLevels: ['high', 'max'],
1268
1242
  },
1269
- {
1270
- id: 'deepseek-v4-flash',
1271
- name: 'DeepSeek V4 Flash',
1272
- protocol: 'responses',
1273
- contextWindow: 1000000,
1274
- maxOutputTokens: 384000,
1275
- inputModalities: ['text'],
1276
- inputPrice: 0.15,
1277
- outputPrice: 0.6,
1278
- supportsToolUse: true,
1279
- supportsStreaming: true,
1280
- effortLevels: ['low', 'high', 'max'],
1281
- },
1282
- {
1283
- id: 'deepseek-v4-flash-vision-exp',
1284
- name: 'DeepSeek V4 Flash Vision Exp',
1285
- protocol: 'chat',
1286
- contextWindow: 1000000,
1287
- maxOutputTokens: 384000,
1288
- inputModalities: ['text', 'image'],
1289
- inputPrice: 0.15,
1290
- outputPrice: 0.6,
1291
- supportsToolUse: true,
1292
- supportsStreaming: true,
1293
- effortLevels: ['low', 'high', 'max'],
1294
- },
1295
1243
  {
1296
1244
  id: 'mimo-v2.6-flash',
1297
1245
  name: 'MiMo-V2.6-Flash',
@@ -1357,19 +1305,6 @@ const GO_MODELS = freezeModels([
1357
1305
  supportsStreaming: true,
1358
1306
  effortLevels: [],
1359
1307
  },
1360
- {
1361
- id: 'minimax-m2.7',
1362
- name: 'MiniMax M2.7',
1363
- protocol: 'chat',
1364
- contextWindow: 204800,
1365
- maxOutputTokens: 131072,
1366
- inputModalities: ['text'],
1367
- inputPrice: 0.3,
1368
- outputPrice: 1.2,
1369
- supportsToolUse: true,
1370
- supportsStreaming: true,
1371
- effortLevels: [],
1372
- },
1373
1308
  {
1374
1309
  id: 'muse-spark-1.3-contributor',
1375
1310
  name: 'Muse Spark 1.3 Contributor',
@@ -1488,23 +1423,23 @@ const GO_MODELS = freezeModels([
1488
1423
  effortLevels: [],
1489
1424
  },
1490
1425
  {
1491
- id: 'step-5-preview-free',
1492
- name: 'Step 5 Preview Free',
1426
+ id: 'step-5-preview',
1427
+ name: 'Step 5 Preview',
1493
1428
  protocol: 'chat',
1494
1429
  contextWindow: 1000000,
1495
1430
  maxOutputTokens: 65536,
1496
1431
  inputModalities: ['text', 'image'],
1497
- inputPrice: 0,
1498
- outputPrice: 0,
1432
+ inputPrice: 1.0,
1433
+ outputPrice: 2.7,
1499
1434
  supportsToolUse: true,
1500
1435
  supportsStreaming: true,
1501
1436
  effortLevels: ['low', 'medium', 'high'],
1502
1437
  },
1503
1438
  {
1504
- id: 'cat-jam-free',
1505
- name: 'Cat Jam Free',
1439
+ id: 'beam-free',
1440
+ name: 'Beam Free',
1506
1441
  protocol: 'chat',
1507
- contextWindow: 262144,
1442
+ contextWindow: 1048576,
1508
1443
  maxOutputTokens: 131072,
1509
1444
  inputModalities: ['text'],
1510
1445
  inputPrice: 0,
@@ -1521,13 +1456,16 @@ const GO_MODELS = freezeModels([
1521
1456
  * `@namzu/zen/catalogue` honours the same decisions by default.
1522
1457
  */
1523
1458
  export const ZEN_OMITTED_MODELS: readonly string[] = Object.freeze([
1524
- 'go/deepseek-flash',
1525
1459
  'go/glm-5.1',
1460
+ 'go/grok-4.6',
1461
+ 'go/kimi-k2.6',
1526
1462
  'go/minimax-m2.5',
1463
+ 'go/minimax-m2.7',
1527
1464
  'go/omen-alpha',
1528
1465
  'go/qwen3.6-plus',
1529
1466
  'go/qwen3.7-max',
1530
1467
  'zen/claude-opus-5-5-backup',
1468
+ 'zen/deepseek-v4-flash',
1531
1469
  'zen/gemini-4-argon',
1532
1470
  'zen/glm-5',
1533
1471
  'zen/gpt-5-codex',