@visual-z/xeno 0.8.4 → 0.9.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 (350) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +31 -746
  3. package/bin/xeno.exe +26 -0
  4. package/install.cjs +88 -0
  5. package/package.json +18 -48
  6. package/docs/app-server.md +0 -115
  7. package/docs/foundations.md +0 -88
  8. package/docs/install.md +0 -244
  9. package/docs/providers.md +0 -172
  10. package/docs/research/foundation-clients-2026-10-09.md +0 -27
  11. package/docs/research/foundation-editing-2026-10-09.md +0 -56
  12. package/docs/research/foundation-network-2026-10-09.md +0 -37
  13. package/docs/research/foundation-workflow-2026-10-09.md +0 -37
  14. package/src/apps/acp-server.ts +0 -41
  15. package/src/apps/agent-profiles.ts +0 -19
  16. package/src/apps/app-server.ts +0 -30
  17. package/src/apps/approve.ts +0 -49
  18. package/src/apps/cli.ts +0 -99
  19. package/src/apps/commands.ts +0 -319
  20. package/src/apps/completions.ts +0 -87
  21. package/src/apps/control-transport.ts +0 -90
  22. package/src/apps/export-cli.ts +0 -24
  23. package/src/apps/goal-flow.ts +0 -70
  24. package/src/apps/image-draft.ts +0 -46
  25. package/src/apps/input.ts +0 -312
  26. package/src/apps/model-catalog.ts +0 -69
  27. package/src/apps/preferences.ts +0 -20
  28. package/src/apps/project-trust.ts +0 -9
  29. package/src/apps/provider-connect.ts +0 -346
  30. package/src/apps/question-ui.ts +0 -27
  31. package/src/apps/render.ts +0 -181
  32. package/src/apps/resources.ts +0 -66
  33. package/src/apps/review.ts +0 -109
  34. package/src/apps/session-hub.ts +0 -96
  35. package/src/apps/session-lifecycle.ts +0 -64
  36. package/src/apps/shell.ts +0 -2071
  37. package/src/apps/startup-input.ts +0 -135
  38. package/src/apps/startup.ts +0 -1677
  39. package/src/apps/ui/app.ts +0 -1818
  40. package/src/apps/ui/control-model.ts +0 -43
  41. package/src/apps/ui/extension-host.ts +0 -194
  42. package/src/apps/ui/image-cache.ts +0 -121
  43. package/src/apps/ui/palette.ts +0 -88
  44. package/src/apps/ui/project.ts +0 -127
  45. package/src/apps/ui/standalone.ts +0 -148
  46. package/src/apps/ui/status-model.ts +0 -68
  47. package/src/apps/ui/surface.ts +0 -91
  48. package/src/apps/ui/theme.ts +0 -86
  49. package/src/apps/update-check.ts +0 -112
  50. package/src/apps/workflow.ts +0 -58
  51. package/src/core/acceptance.ts +0 -139
  52. package/src/core/action-defaults.ts +0 -58
  53. package/src/core/activity-status.ts +0 -52
  54. package/src/core/agent-profile.ts +0 -130
  55. package/src/core/attachment-input.ts +0 -17
  56. package/src/core/blind-checks.ts +0 -72
  57. package/src/core/boundary.ts +0 -174
  58. package/src/core/branch-receipt.ts +0 -26
  59. package/src/core/catalog-merge.ts +0 -19
  60. package/src/core/checkpoints.ts +0 -85
  61. package/src/core/churn.ts +0 -61
  62. package/src/core/command-artifacts.ts +0 -94
  63. package/src/core/command-contract.ts +0 -151
  64. package/src/core/completion-action.ts +0 -20
  65. package/src/core/completion-review.ts +0 -98
  66. package/src/core/context-detail.ts +0 -37
  67. package/src/core/context-policy.ts +0 -133
  68. package/src/core/context-window.ts +0 -54
  69. package/src/core/continuation.ts +0 -130
  70. package/src/core/control-protocol.ts +0 -69
  71. package/src/core/control-view.ts +0 -39
  72. package/src/core/cycle.ts +0 -17
  73. package/src/core/data-query.ts +0 -201
  74. package/src/core/deadline.ts +0 -40
  75. package/src/core/derive.ts +0 -516
  76. package/src/core/draft-images.ts +0 -56
  77. package/src/core/edit-plan.ts +0 -200
  78. package/src/core/environment.ts +0 -181
  79. package/src/core/event-validation.ts +0 -220
  80. package/src/core/events.ts +0 -670
  81. package/src/core/evidence-ladder.ts +0 -62
  82. package/src/core/evidence-links.ts +0 -68
  83. package/src/core/evidence.ts +0 -240
  84. package/src/core/execution.ts +0 -18
  85. package/src/core/exhaustive.ts +0 -18
  86. package/src/core/export.ts +0 -179
  87. package/src/core/extension-flags.ts +0 -14
  88. package/src/core/external-effects.ts +0 -488
  89. package/src/core/failure-recovery.ts +0 -173
  90. package/src/core/file-precondition.ts +0 -78
  91. package/src/core/file-references.ts +0 -35
  92. package/src/core/frontmatter.ts +0 -213
  93. package/src/core/git-status.ts +0 -29
  94. package/src/core/goal-view.ts +0 -64
  95. package/src/core/goal.ts +0 -200
  96. package/src/core/handoff.ts +0 -479
  97. package/src/core/history-query.ts +0 -139
  98. package/src/core/history.ts +0 -237
  99. package/src/core/image-limits.ts +0 -72
  100. package/src/core/images.ts +0 -46
  101. package/src/core/integration-health.ts +0 -34
  102. package/src/core/json-event.ts +0 -131
  103. package/src/core/json-pointer.ts +0 -46
  104. package/src/core/keymap.ts +0 -153
  105. package/src/core/lsp-framing.ts +0 -34
  106. package/src/core/mcp-config.ts +0 -68
  107. package/src/core/model-picker.ts +0 -64
  108. package/src/core/model-preferences.ts +0 -28
  109. package/src/core/model-replay.ts +0 -22
  110. package/src/core/model-scope.ts +0 -53
  111. package/src/core/note-guidance.ts +0 -34
  112. package/src/core/oauth-fields.ts +0 -44
  113. package/src/core/observation-view.ts +0 -152
  114. package/src/core/outcome.ts +0 -44
  115. package/src/core/overflow.ts +0 -59
  116. package/src/core/packages.ts +0 -47
  117. package/src/core/patch.ts +0 -130
  118. package/src/core/path-suggestions.ts +0 -59
  119. package/src/core/permissions.ts +0 -410
  120. package/src/core/process-receipt.ts +0 -105
  121. package/src/core/process-state.ts +0 -37
  122. package/src/core/program-status.ts +0 -40
  123. package/src/core/progress.ts +0 -150
  124. package/src/core/project.ts +0 -431
  125. package/src/core/prompt-policy.ts +0 -46
  126. package/src/core/prompts.ts +0 -111
  127. package/src/core/question.ts +0 -94
  128. package/src/core/queue.ts +0 -78
  129. package/src/core/read-bounds.ts +0 -24
  130. package/src/core/read-observation.ts +0 -106
  131. package/src/core/recovery-sources.ts +0 -74
  132. package/src/core/regex-dialect.ts +0 -25
  133. package/src/core/request-budget.ts +0 -23
  134. package/src/core/request-progress.ts +0 -87
  135. package/src/core/request-state.ts +0 -273
  136. package/src/core/resource-selection.ts +0 -36
  137. package/src/core/response-recovery.ts +0 -59
  138. package/src/core/resume.ts +0 -59
  139. package/src/core/review.ts +0 -68
  140. package/src/core/ripgrep-release.ts +0 -64
  141. package/src/core/runtime-target.ts +0 -94
  142. package/src/core/scheduling.ts +0 -8
  143. package/src/core/search-observation.ts +0 -97
  144. package/src/core/secrets.ts +0 -188
  145. package/src/core/session-archive.ts +0 -4
  146. package/src/core/session-browser.ts +0 -82
  147. package/src/core/session-entry.ts +0 -61
  148. package/src/core/session-exit.ts +0 -42
  149. package/src/core/session-format.ts +0 -169
  150. package/src/core/session-position.ts +0 -26
  151. package/src/core/session-tree.ts +0 -147
  152. package/src/core/settings.ts +0 -192
  153. package/src/core/skills.ts +0 -165
  154. package/src/core/sql-query.ts +0 -211
  155. package/src/core/stall.ts +0 -128
  156. package/src/core/stop-report.ts +0 -68
  157. package/src/core/text-normalize.ts +0 -81
  158. package/src/core/theme.ts +0 -166
  159. package/src/core/thinking.ts +0 -26
  160. package/src/core/tokens.ts +0 -151
  161. package/src/core/tool-contract.ts +0 -153
  162. package/src/core/tool-discovery.ts +0 -87
  163. package/src/core/tool-failure.ts +0 -81
  164. package/src/core/tool-input.ts +0 -44
  165. package/src/core/transcript.ts +0 -108
  166. package/src/core/tui-mode.ts +0 -29
  167. package/src/core/update-check.ts +0 -157
  168. package/src/core/version.ts +0 -55
  169. package/src/core/web-content.ts +0 -80
  170. package/src/core/work-state.ts +0 -154
  171. package/src/core/workflow-mode.ts +0 -34
  172. package/src/core/working-set.ts +0 -119
  173. package/src/core/yaml.ts +0 -282
  174. package/src/runtime/acp-agent.ts +0 -289
  175. package/src/runtime/agent-profiles.ts +0 -21
  176. package/src/runtime/auth.ts +0 -367
  177. package/src/runtime/blind-check.ts +0 -36
  178. package/src/runtime/branch-jobs.ts +0 -36
  179. package/src/runtime/catalog.ts +0 -285
  180. package/src/runtime/clipboard.ts +0 -125
  181. package/src/runtime/command-artifacts.ts +0 -64
  182. package/src/runtime/connection-reuse.ts +0 -40
  183. package/src/runtime/control-client.ts +0 -149
  184. package/src/runtime/control-connection.ts +0 -139
  185. package/src/runtime/counter-check.ts +0 -74
  186. package/src/runtime/environment-tools.ts +0 -60
  187. package/src/runtime/evidence-notes.ts +0 -35
  188. package/src/runtime/exec-sessions.ts +0 -456
  189. package/src/runtime/execution-control.ts +0 -40
  190. package/src/runtime/extension-loader.ts +0 -37
  191. package/src/runtime/extension-ui.ts +0 -47
  192. package/src/runtime/extensions.ts +0 -370
  193. package/src/runtime/formatter-tool.ts +0 -38
  194. package/src/runtime/formatter.ts +0 -50
  195. package/src/runtime/foundation.ts +0 -116
  196. package/src/runtime/history-cache.ts +0 -57
  197. package/src/runtime/history-tools.ts +0 -168
  198. package/src/runtime/images.ts +0 -80
  199. package/src/runtime/integrations.ts +0 -216
  200. package/src/runtime/loop.ts +0 -3108
  201. package/src/runtime/lsp-client.ts +0 -201
  202. package/src/runtime/mcp-client.ts +0 -264
  203. package/src/runtime/mcp-oauth.ts +0 -168
  204. package/src/runtime/mcp-schema.ts +0 -51
  205. package/src/runtime/model-config.ts +0 -232
  206. package/src/runtime/model-data.LICENSE +0 -27
  207. package/src/runtime/model-data.ts +0 -21
  208. package/src/runtime/model-discovery.ts +0 -208
  209. package/src/runtime/model-replay.ts +0 -10
  210. package/src/runtime/model-scope.ts +0 -20
  211. package/src/runtime/model-sources.ts +0 -151
  212. package/src/runtime/model.ts +0 -686
  213. package/src/runtime/models-fetch.ts +0 -57
  214. package/src/runtime/oauth-device.ts +0 -86
  215. package/src/runtime/oauth.ts +0 -853
  216. package/src/runtime/open-image.ts +0 -42
  217. package/src/runtime/openai-responses.ts +0 -304
  218. package/src/runtime/openai.ts +0 -697
  219. package/src/runtime/output-schema.ts +0 -26
  220. package/src/runtime/package-manager.ts +0 -125
  221. package/src/runtime/patch-tool.ts +0 -38
  222. package/src/runtime/permission-resources.ts +0 -18
  223. package/src/runtime/pi-provider.ts +0 -423
  224. package/src/runtime/program-status.ts +0 -38
  225. package/src/runtime/progress.ts +0 -26
  226. package/src/runtime/provider-access.ts +0 -21
  227. package/src/runtime/provider-connect.ts +0 -109
  228. package/src/runtime/provider-presets.ts +0 -98
  229. package/src/runtime/provider-protocols.ts +0 -29
  230. package/src/runtime/provider-request.ts +0 -87
  231. package/src/runtime/provider-tool-policy.ts +0 -33
  232. package/src/runtime/provider.ts +0 -580
  233. package/src/runtime/question-tool.ts +0 -62
  234. package/src/runtime/retry.ts +0 -447
  235. package/src/runtime/review-tool.ts +0 -48
  236. package/src/runtime/rich-text.ts +0 -36
  237. package/src/runtime/runtime-target.ts +0 -149
  238. package/src/runtime/secrets.ts +0 -79
  239. package/src/runtime/self-update.ts +0 -74
  240. package/src/runtime/session-control.ts +0 -265
  241. package/src/runtime/session-hub.ts +0 -85
  242. package/src/runtime/stream-idle.ts +0 -80
  243. package/src/runtime/tool-broker.ts +0 -137
  244. package/src/runtime/tool-discovery.ts +0 -58
  245. package/src/runtime/tool-queue.ts +0 -77
  246. package/src/runtime/tools.ts +0 -1820
  247. package/src/runtime/turn-effects.ts +0 -31
  248. package/src/runtime/update-check.ts +0 -48
  249. package/src/runtime/usage.ts +0 -253
  250. package/src/runtime/version.ts +0 -12
  251. package/src/runtime/web-http.ts +0 -56
  252. package/src/runtime/web-tools.ts +0 -88
  253. package/src/runtime/working-notes.ts +0 -60
  254. package/src/runtime/workspace-lifecycle.ts +0 -141
  255. package/src/store/acceptance.ts +0 -15
  256. package/src/store/agent-profile-files.ts +0 -13
  257. package/src/store/atomic.ts +0 -31
  258. package/src/store/auth-store.ts +0 -50
  259. package/src/store/blind-checks.ts +0 -32
  260. package/src/store/blobs.ts +0 -143
  261. package/src/store/checkpoint-history.ts +0 -32
  262. package/src/store/command-artifacts.ts +0 -96
  263. package/src/store/command.ts +0 -111
  264. package/src/store/config.ts +0 -69
  265. package/src/store/context-files.ts +0 -436
  266. package/src/store/file-checkpoints.ts +0 -108
  267. package/src/store/file-index.ts +0 -174
  268. package/src/store/foundation-config.ts +0 -24
  269. package/src/store/git-checkpoints.ts +0 -67
  270. package/src/store/git-status.ts +0 -15
  271. package/src/store/history-search.ts +0 -19
  272. package/src/store/log.ts +0 -725
  273. package/src/store/lsp-document.ts +0 -30
  274. package/src/store/mcp-credentials.ts +0 -85
  275. package/src/store/models.ts +0 -60
  276. package/src/store/observations.ts +0 -224
  277. package/src/store/packages.ts +0 -98
  278. package/src/store/patch.ts +0 -92
  279. package/src/store/permission-paths.ts +0 -34
  280. package/src/store/process-receipts.ts +0 -34
  281. package/src/store/query-source.ts +0 -49
  282. package/src/store/recovery.ts +0 -44
  283. package/src/store/replay.ts +0 -76
  284. package/src/store/resource-index.ts +0 -170
  285. package/src/store/resources.ts +0 -285
  286. package/src/store/restore.ts +0 -110
  287. package/src/store/review.ts +0 -109
  288. package/src/store/runtime-target.ts +0 -64
  289. package/src/store/search.ts +0 -728
  290. package/src/store/secrets.ts +0 -44
  291. package/src/store/serial.ts +0 -13
  292. package/src/store/session-archive.ts +0 -165
  293. package/src/store/session-browser.ts +0 -68
  294. package/src/store/session-position.ts +0 -27
  295. package/src/store/sessions.ts +0 -525
  296. package/src/store/source-cancellation.ts +0 -6
  297. package/src/store/tool-binaries.ts +0 -90
  298. package/src/store/trust.ts +0 -82
  299. package/src/store/update-cache.ts +0 -36
  300. package/src/store/user-settings.ts +0 -30
  301. package/src/store/workspace-clone.ts +0 -42
  302. package/src/store/workspace-observation.ts +0 -113
  303. package/src/store/workspace.ts +0 -115
  304. package/src/store/worktree.ts +0 -278
  305. package/src/tui/ansi-spans.ts +0 -126
  306. package/src/tui/diff.ts +0 -160
  307. package/src/tui/exhaustive.ts +0 -14
  308. package/src/tui/fuzzy.ts +0 -75
  309. package/src/tui/style.ts +0 -208
  310. package/src/tui/ui/atomic-draft.ts +0 -121
  311. package/src/tui/ui/branch-panel.ts +0 -47
  312. package/src/tui/ui/canvas.ts +0 -96
  313. package/src/tui/ui/colors.ts +0 -70
  314. package/src/tui/ui/composer.ts +0 -199
  315. package/src/tui/ui/control-panel.ts +0 -25
  316. package/src/tui/ui/control-sidebar.ts +0 -49
  317. package/src/tui/ui/dialog.ts +0 -398
  318. package/src/tui/ui/draft.ts +0 -23
  319. package/src/tui/ui/duration.ts +0 -16
  320. package/src/tui/ui/edge.ts +0 -186
  321. package/src/tui/ui/image-size.ts +0 -44
  322. package/src/tui/ui/ink.ts +0 -210
  323. package/src/tui/ui/items.ts +0 -42
  324. package/src/tui/ui/keys.ts +0 -40
  325. package/src/tui/ui/layout.ts +0 -74
  326. package/src/tui/ui/list-model.ts +0 -86
  327. package/src/tui/ui/list-view.ts +0 -172
  328. package/src/tui/ui/mascot.ts +0 -67
  329. package/src/tui/ui/messages.ts +0 -518
  330. package/src/tui/ui/motion.ts +0 -28
  331. package/src/tui/ui/paths.ts +0 -10
  332. package/src/tui/ui/pictures.ts +0 -108
  333. package/src/tui/ui/prompt-history.ts +0 -60
  334. package/src/tui/ui/screen.ts +0 -579
  335. package/src/tui/ui/status.ts +0 -403
  336. package/src/tui/ui/styled.ts +0 -85
  337. package/src/tui/ui/tool-card.ts +0 -150
  338. package/src/tui/width.ts +0 -567
  339. package/src/vendor/pi-rich/LICENSE.upstream +0 -21
  340. package/src/vendor/pi-rich/UPSTREAM.json +0 -17
  341. package/src/vendor/pi-rich/clipboard-command.ts +0 -44
  342. package/src/vendor/pi-rich/exif-orientation.ts +0 -182
  343. package/src/vendor/pi-rich/html.ts +0 -51
  344. package/src/vendor/pi-rich/image-convert.ts +0 -49
  345. package/src/vendor/pi-rich/image-resize-core.ts +0 -164
  346. package/src/vendor/pi-rich/image-resize-worker.ts +0 -42
  347. package/src/vendor/pi-rich/image-resize.ts +0 -123
  348. package/src/vendor/pi-rich/mime.ts +0 -116
  349. package/src/vendor/pi-rich/photon.ts +0 -139
  350. package/src/vendor/pi-rich/syntax-highlight.ts +0 -214
@@ -1,686 +0,0 @@
1
- /**
2
- * What the runtime needs to know about a model: how to talk to it, and how to
3
- * price what it did.
4
- *
5
- * This exists because the two facts turned out to be inseparable. The obvious
6
- * shape is "an adapter per wire format" and nothing else, but pricing is not a
7
- * property of the wire format -- two providers speaking the same OpenAI
8
- * Completions dialect bill caching on completely different terms. So the model,
9
- * not the adapter, is what carries the rates.
10
- *
11
- * Deliberately not a class and deliberately inert: a spec is data the catalog
12
- * hands to an adapter, and anything that can reach the network belongs in the
13
- * adapter instead.
14
- */
15
-
16
- /**
17
- * The protocol vocabulary is local even when the runtime delegates wire IO to Pi.
18
- */
19
- import type { ProviderApi } from "./provider-protocols.ts";
20
- import { SOURCE_MODELS } from "./model-data.ts";
21
- import { mergeCatalogs } from "../core/catalog-merge.ts";
22
- import { GROK_PROVIDER, GROK_BASE_URL } from "./oauth.ts";
23
- export type Api = ProviderApi;
24
-
25
- /** How hard the model should think. Capability and wire vocabulary are mapped per model. */
26
- import type { ThinkingLevel } from "../core/thinking.ts";
27
- export type Effort = ThinkingLevel;
28
-
29
- /**
30
- * Who decides what gets cached.
31
- *
32
- * explicit -- the caller places breakpoints and the provider bills for the
33
- * write. Hits are predictable because you chose the boundary.
34
- * (Anthropic)
35
- * automatic -- the provider caches prefixes by itself, bills nothing for the
36
- * write, and guarantees no hit rate. Writes land in seconds, so
37
- * an early miss is normal rather than a symptom. (DeepSeek)
38
- *
39
- * A named pair rather than two booleans: both the cost path and the diagnosis
40
- * path fork on this, and a discriminant can be closed with `assertNever`.
41
- */
42
- export type CacheKind = "explicit" | "automatic";
43
-
44
- /**
45
- * Cache prices as multiples of base input.
46
- *
47
- * Multiples rather than dollars because that is the unit `equivalentCost`
48
- * reports in, and for the reason stated there: dollar prices go stale, ratios
49
- * survive a price change. A provider that bills nothing for cache writes sets
50
- * `write: 0`, which is not a placeholder -- it is the actual term.
51
- */
52
- export interface CacheRates {
53
- read: number;
54
- write: number;
55
- }
56
-
57
- /**
58
- * USD per million tokens.
59
- *
60
- * Optional on the model, and filled in only where the number was read off
61
- * a source we trust. An unverified price is worse than an absent one: it
62
- * looks authoritative and silently misreports every session.
63
- *
64
- * Cache fields are optional because most providers publish input/output
65
- * and nothing else. Requiring all four packed a partial fact into a total
66
- * unknown — the catalog then had the groq rate and /usage still said
67
- * "unknown". Filling the missing cache slot with 0 is still forbidden:
68
- * `write: 0` is DeepSeek's and Z.AI's actual term, not a default.
69
- */
70
- export interface Price {
71
- input: number;
72
- output: number;
73
- cacheRead?: number;
74
- cacheWrite?: number;
75
- }
76
-
77
- /**
78
- * Which dialect of "OpenAI-compatible" a model speaks.
79
- *
80
- * Every field here is a difference that costs a 400 or a wrong number, and
81
- * every one was found the same way: a provider quietly disagreeing with the
82
- * spec. Carried as data because the alternative -- branching on the provider's
83
- * name inside the adapter -- becomes an unextendable chain of `||` by the
84
- * third provider.
85
- *
86
- * Only relevant to `openai-completions`. The Anthropic adapter has one dialect
87
- * by construction: its own.
88
- */
89
- export interface Compat {
90
- /**
91
- * Whether the system prompt may be sent with the `developer` role, which
92
- * reasoning-capable OpenAI models expect. Servers that predate it (Ollama,
93
- * vLLM, DeepSeek) reject the role outright, so they get `system`.
94
- */
95
- supportsDeveloperRole: boolean;
96
- /**
97
- * OpenAI renamed this for reasoning models and most of the family did not
98
- * follow. Sending the wrong one is not an error -- it is silently ignored,
99
- * and the response runs to the model's own default length.
100
- */
101
- maxTokensField: "max_tokens" | "max_completion_tokens";
102
- /** Whether `reasoning_effort` is understood. Some servers 400 on an unknown field. */
103
- supportsReasoningEffort: boolean;
104
- /**
105
- * Whether the server accepts `stream_options: { include_usage: true }`.
106
- * Default on: an OpenAI-dialect stream that is not asked for usage reports
107
- * none, the loop would park a zero-token anchor, and shouldCut never fires.
108
- * Some servers 400 on the unknown field, which is why this is a bit rather
109
- * than assumed of every Completions accent.
110
- */
111
- supportsUsageInStreaming: boolean;
112
- /**
113
- * DeepSeek requires `reasoning_content` on every assistant message once
114
- * `tools` is in the request -- including turns that did no thinking -- and
115
- * returns 400 without it.
116
- */
117
- requiresReasoningContentOnAssistantMessages: boolean;
118
- /** How thinking is switched on. `deepseek` adds `thinking: {type}`; `openai` uses effort alone. */
119
- thinkingFormat: "openai" | "deepseek";
120
- }
121
-
122
- /**
123
- * Standard OpenAI. A model that says nothing about its accent is assumed to
124
- * speak the documented one -- and will be corrected by a 400 if it does not,
125
- * which is the cheapest way to find out.
126
- */
127
- /**
128
- * Kimi K3, from Moonshot's own agent guide (platform.kimi.ai, "Build an Agent
129
- * with Kimi K3" and the Reasoning Effort page): it always reasons, takes no
130
- * `thinking` field, accepts only low / high / max effort (default max), and
131
- * every example uses the `system` role. The complete assistant message --
132
- * reasoning included -- must be sent back, which the thinking block's raw
133
- * already does; turns without reasoning get none, since "unmodified" rules
134
- * out inventing an empty one.
135
- */
136
- export const KIMI_K3_COMPAT: Compat = {
137
- supportsDeveloperRole: false,
138
- maxTokensField: "max_completion_tokens",
139
- supportsReasoningEffort: true,
140
- supportsUsageInStreaming: true,
141
- requiresReasoningContentOnAssistantMessages: false,
142
- thinkingFormat: "openai",
143
- };
144
- export const KIMI_K3_EFFORT: Partial<Record<Effort, string | null>> = {
145
- off: null, minimal: "low",
146
- low: "low", medium: "high", high: "high", xhigh: "max", max: "max",
147
- };
148
-
149
- /**
150
- * Gemini's OpenAI-compatible endpoint (ai.google.dev/gemini-api/docs/openai).
151
- * It 400s on any effort outside none / low / medium / high -- reported
152
- * verbatim on Google's developer forum -- and Gemini 3 cannot turn reasoning
153
- * off, so the top of our scale maps to high. `max_tokens` is the documented
154
- * field; `max_completion_tokens` has been reported ignored. Every official
155
- * example uses `system`. Thought signatures ride on each tool call's `wire`.
156
- */
157
- export const GEMINI_COMPAT: Compat = {
158
- supportsDeveloperRole: false,
159
- maxTokensField: "max_tokens",
160
- supportsReasoningEffort: true,
161
- supportsUsageInStreaming: true,
162
- requiresReasoningContentOnAssistantMessages: false,
163
- thinkingFormat: "openai",
164
- };
165
- export const GEMINI_EFFORT: Partial<Record<Effort, string | null>> = {
166
- off: null, minimal: "low",
167
- low: "low", medium: "medium", high: "high", xhigh: "high", max: "high",
168
- };
169
-
170
- export const DEFAULT_COMPAT: Compat = {
171
- supportsDeveloperRole: true,
172
- maxTokensField: "max_completion_tokens",
173
- supportsReasoningEffort: true,
174
- supportsUsageInStreaming: true,
175
- requiresReasoningContentOnAssistantMessages: false,
176
- thinkingFormat: "openai",
177
- };
178
-
179
- export interface ModelSpec {
180
- /** Public variable names from the source directory, never their values. */
181
- credentialEnv?: readonly string[];
182
- /** Native Pi transport is runtime-only. Existing models retain their verified adapter. */
183
- driver?: "pi";
184
- /** Public catalog metadata only. User credentials/headers live in provider-access's sidecar. */
185
- nativeCompat?: Record<string, unknown>;
186
- samplingParams?: Record<string, unknown>;
187
- defaultHeaders?: Record<string, string>;
188
- /** The id sent on the wire. */
189
- id: string;
190
- /** Optional upstream deployment/model id when a user gives it a local catalog alias. */
191
- wireId?: string;
192
- /** For humans, in `/model` listings. */
193
- name: string;
194
- api: Api;
195
- /** Catalog/auth key -- the name under which a credential is stored. */
196
- provider: string;
197
- /**
198
- * Optional: the Anthropic SDK resolves its own default, and a custom
199
- * endpoint overrides it. Required in practice for `openai-completions`,
200
- * where there is no default worth guessing.
201
- */
202
- baseUrl?: string;
203
- reasoning: boolean;
204
- /** Explicit capability from the model catalog. Unknown input capability is text-only. */
205
- input?: readonly ("text" | "image")[];
206
- /**
207
- * Absent when the provider's caching terms are not in the source we
208
- * trust. Filling `automatic` + `write: 0` here would be DeepSeek's
209
- * contract, not a default, and `/usage` would then report a fake zero.
210
- */
211
- cache?: CacheKind;
212
- rates?: CacheRates;
213
- price?: Price;
214
- /**
215
- * Both optional because an unverified number here would be a fabrication,
216
- * and nothing reads them yet -- they are descriptive, for `/model` and for
217
- * a future context-window check. Fill them from the provider's own docs or
218
- * leave them out.
219
- */
220
- contextWindow?: number;
221
- maxTokens?: number;
222
- /** Only meaningful for `openai-completions`. Absent means `DEFAULT_COMPAT`. */
223
- compat?: Compat;
224
- /**
225
- * Pi's effort names onto the wire vocabulary. `null` disables a level.
226
- * Unmapped xhigh/max are unsupported; other missing names pass through.
227
- */
228
- thinkingLevelMap?: Partial<Record<Effort, string | null>>;
229
- }
230
-
231
- /**
232
- * 5-minute ephemeral caching: reads bill at 0.1x base input, writes at 1.25x.
233
- * If Anthropic changes these, every cost number in the session report is
234
- * wrong by that factor and nothing will raise an error -- so they live here,
235
- * next to the model they describe, rather than as loose module constants.
236
- */
237
- export const ANTHROPIC_RATES: CacheRates = { read: 0.1, write: 1.25 };
238
-
239
- export const CLAUDE_OPUS_5: ModelSpec = {
240
- id: "claude-opus-5",
241
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
242
- input: ["text","image"],
243
- name: "Claude Opus 5",
244
- api: "anthropic-messages",
245
- provider: "anthropic",
246
- reasoning: true,
247
- // Preserve the built-in request vocabulary while the generic capability policy becomes explicit.
248
- thinkingLevelMap: { minimal: "low", xhigh: "xhigh", max: "max" },
249
- cache: "explicit",
250
- rates: ANTHROPIC_RATES,
251
- // Cost from models.dev on 2026-09-21. Ratios match ANTHROPIC_RATES.
252
- price: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
253
- contextWindow: 1_000_000,
254
- maxTokens: 128_000,
255
- };
256
-
257
- /**
258
- * DeepSeek's accent, verified against its own docs rather than inferred:
259
- * `max_tokens` (not the renamed field), no `developer` role, `thinking`
260
- * toggled explicitly, and reasoning echoed back on every assistant message
261
- * or the request is rejected once tools are present.
262
- */
263
- const DEEPSEEK_COMPAT: Compat = {
264
- supportsDeveloperRole: false,
265
- maxTokensField: "max_tokens",
266
- supportsReasoningEffort: true,
267
- supportsUsageInStreaming: true,
268
- requiresReasoningContentOnAssistantMessages: true,
269
- thinkingFormat: "deepseek",
270
- };
271
-
272
- /**
273
- * Effort levels DeepSeek accepts: low, high, max. The docs say a request's
274
- * level is remapped internally (minimal/low -> low, medium/high/xhigh ->
275
- * high, max -> max), so this map does the same thing explicitly rather than
276
- * sending a level the API has to guess about.
277
- */
278
- const DEEPSEEK_EFFORT: Partial<Record<Effort, string | null>> = {
279
- minimal: "low",
280
- low: "low",
281
- medium: "high",
282
- high: "high",
283
- xhigh: "high",
284
- max: "max",
285
- };
286
-
287
- /**
288
- * Prices read off DeepSeek's own price page (peak rates, USD per 1M tokens).
289
- * Off-peak is half of these, which changes the absolute cost but not the
290
- * ratios below, and the ratios are what `equivalentCost` reports in.
291
- *
292
- * Cache creation has no separate billing line; misses are ordinary input.
293
- * A zero creation rate does not make a rebuilt prefix free: those tokens
294
- * still pay the cold input rate and evidence recovery may need more requests.
295
- */
296
- export const DEEPSEEK_V4_PRO: ModelSpec = {
297
- id: "deepseek-v4-pro",
298
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
299
- input: ["text"],
300
- name: "DeepSeek V4 Pro",
301
- api: "openai-completions",
302
- provider: "deepseek",
303
- baseUrl: "https://api.deepseek.com",
304
- reasoning: true,
305
- cache: "automatic",
306
- rates: { read: 0.044 / 1.32, write: 0 },
307
- price: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0 },
308
- contextWindow: 1_000_000,
309
- maxTokens: 384_000,
310
- compat: DEEPSEEK_COMPAT,
311
- thinkingLevelMap: DEEPSEEK_EFFORT,
312
- };
313
-
314
- export const DEEPSEEK_FLASH: ModelSpec = {
315
- id: "deepseek-flash",
316
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
317
- input: ["text","image"],
318
- name: "DeepSeek V4.1 Flash",
319
- api: "openai-completions",
320
- provider: "deepseek",
321
- baseUrl: "https://api.deepseek.com",
322
- reasoning: true,
323
- cache: "automatic",
324
- rates: { read: 0.006 / 0.3, write: 0 },
325
- price: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0 },
326
- contextWindow: 1_000_000,
327
- maxTokens: 384_000,
328
- compat: DEEPSEEK_COMPAT,
329
- thinkingLevelMap: DEEPSEEK_EFFORT,
330
- };
331
-
332
- /**
333
- * How we talk to a provider. A third `api` is another card, not a row here.
334
- *
335
- * Google is listed as Completions because it publishes an OpenAI-compatible
336
- * endpoint at this URL; we are not pretending Gemini's native protocol is
337
- * Chat Completions. xAI, Mistral, and OpenAI likewise have a Completions
338
- * surface we already speak. Pi uses other adapters for some of these;
339
- * bending ours to match would be the thing the card forbids.
340
- */
341
- export const PROVIDER_WIRE: Readonly<Record<string, { api: Api; baseUrl?: string }>> = {
342
- anthropic: { api: "anthropic-messages" },
343
- openai: { api: "openai-completions", baseUrl: "https://api.openai.com/v1" },
344
- google: { api: "openai-completions", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai" },
345
- deepseek: { api: "openai-completions", baseUrl: "https://api.deepseek.com" },
346
- xai: { api: "openai-completions", baseUrl: "https://api.x.ai/v1" },
347
- groq: { api: "openai-completions", baseUrl: "https://api.groq.com/openai/v1" },
348
- cerebras: { api: "openai-completions", baseUrl: "https://api.cerebras.ai/v1" },
349
- mistral: { api: "openai-completions", baseUrl: "https://api.mistral.ai/v1" },
350
- openrouter: { api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1" },
351
- zai: { api: "openai-completions", baseUrl: "https://api.z.ai/api/paas/v4" },
352
- moonshotai: { api: "openai-completions", baseUrl: "https://api.moonshot.ai/v1" },
353
- together: { api: "openai-completions", baseUrl: "https://api.together.xyz/v1" },
354
- // models.dev's id; we store the catalog key as `together`.
355
- togetherai: { api: "openai-completions", baseUrl: "https://api.together.xyz/v1" },
356
- };
357
-
358
- function anthropicModel(spec: Omit<ModelSpec, "api" | "provider">): ModelSpec {
359
- return { api: "anthropic-messages", provider: "anthropic", ...spec };
360
- }
361
-
362
- function completionsModel(spec: Omit<ModelSpec, "api">): ModelSpec {
363
- return { api: "openai-completions", ...spec };
364
- }
365
-
366
- /**
367
- * OpenAI's own endpoint for its reasoning models: Chat Completions would drop
368
- * their reasoning between turns (feat-openai-responses). OpenRouter's GPT
369
- * entries stay on Completions, which is the API OpenRouter serves.
370
- */
371
- function responsesModel(spec: Omit<ModelSpec, "api">): ModelSpec {
372
- return { api: "openai-responses", ...spec };
373
- }
374
-
375
- /**
376
- * Built-in catalog. Numbers from models.dev on 2026-09-21 unless a comment
377
- * says otherwise. Price is omitted only when input or output is missing —
378
- * a zero there would look like "this is free". cacheRead / cacheWrite are
379
- * filled when the source has them and left off when it does not. Cache
380
- * *rates* (multiples) stay omitted unless both cache dollars are present,
381
- * except DeepSeek (verified against its own page).
382
- */
383
- export const CURATED_CATALOG: readonly ModelSpec[] = [
384
- CLAUDE_OPUS_5,
385
- anthropicModel({
386
- id: "claude-fable-5-1",
387
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
388
- input: ["text","image"],
389
- name: "Claude Fable 5.1",
390
- reasoning: true,
391
- cache: "explicit",
392
- rates: { read: 0.25 / 10, write: 12.5 / 10 },
393
- price: { input: 10, output: 50, cacheRead: 0.25, cacheWrite: 12.5 },
394
- contextWindow: 1_000_000,
395
- maxTokens: 128_000,
396
- }),
397
-
398
- responsesModel({
399
- id: "gpt-5.5-pro",
400
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
401
- input: ["text","image"],
402
- name: "GPT-5.5 Pro",
403
- provider: "openai",
404
- baseUrl: "https://api.openai.com/v1",
405
- reasoning: true,
406
- contextWindow: 1_050_000,
407
- maxTokens: 128_000,
408
- // Base rate. models.dev also lists a context_over_200k tier at 60/270.
409
- price: { input: 30, output: 180 },
410
- }),
411
- responsesModel({
412
- id: "gpt-5.4-pro",
413
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
414
- input: ["text","image"],
415
- name: "GPT-5.4 Pro",
416
- provider: "openai",
417
- baseUrl: "https://api.openai.com/v1",
418
- reasoning: true,
419
- contextWindow: 1_050_000,
420
- maxTokens: 128_000,
421
- // Base rate. models.dev also lists a context_over_200k tier at 60/270.
422
- price: { input: 30, output: 180 },
423
- }),
424
-
425
- completionsModel({
426
- id: "gemini-3.1-pro-preview",
427
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
428
- input: ["text","image"],
429
- name: "Gemini 3.1 Pro Preview",
430
- provider: "google",
431
- baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
432
- reasoning: true,
433
- contextWindow: 1_048_576,
434
- maxTokens: 65_536,
435
- // Base rate. models.dev also lists a context_over_200k tier (4/18/0.4).
436
- price: { input: 2, output: 12, cacheRead: 0.2 },
437
- compat: GEMINI_COMPAT,
438
- thinkingLevelMap: GEMINI_EFFORT,
439
- }),
440
-
441
- DEEPSEEK_V4_PRO,
442
- DEEPSEEK_FLASH,
443
-
444
- {
445
- id: "grok-build", name: "Grok Build", provider: GROK_PROVIDER, baseUrl: GROK_BASE_URL,
446
- api: "openai-completions", driver: "pi", input: ["text"],
447
- // The official proxy alias has no published effort/price contract. Do not copy API model rates.
448
- reasoning: false,
449
- nativeCompat: { supportsDeveloperRole: false, supportsReasoningEffort: false, maxTokensField: "max_tokens" },
450
- },
451
-
452
- completionsModel({
453
- id: "grok-4.6",
454
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
455
- input: ["text","image"],
456
- name: "Grok 4.6",
457
- provider: "xai",
458
- baseUrl: "https://api.x.ai/v1",
459
- reasoning: true,
460
- contextWindow: 500_000,
461
- maxTokens: 500_000,
462
- // Base rate. models.dev also lists a context_over_200k tier (4/12/1).
463
- price: { input: 2, output: 6, cacheRead: 0.5 },
464
- }),
465
- completionsModel({
466
- id: "grok-4.5",
467
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
468
- input: ["text","image"],
469
- name: "Grok 4.5",
470
- provider: "xai",
471
- baseUrl: "https://api.x.ai/v1",
472
- reasoning: true,
473
- contextWindow: 500_000,
474
- maxTokens: 500_000,
475
- // Base rate. models.dev also lists a context_over_200k tier (4/12/0.6).
476
- price: { input: 2, output: 6, cacheRead: 0.3 },
477
- }),
478
-
479
- completionsModel({
480
- id: "llama-3.3-70b-versatile",
481
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
482
- input: ["text"],
483
- name: "Llama 3.3 70B",
484
- provider: "groq",
485
- baseUrl: "https://api.groq.com/openai/v1",
486
- reasoning: false,
487
- contextWindow: 131_072,
488
- maxTokens: 32_768,
489
- price: { input: 0.59, output: 0.79 },
490
- }),
491
- completionsModel({
492
- id: "qwen/qwen3.6-27b",
493
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
494
- input: ["text","image"],
495
- name: "Qwen3.6 27B",
496
- provider: "groq",
497
- baseUrl: "https://api.groq.com/openai/v1",
498
- reasoning: true,
499
- contextWindow: 131_072,
500
- maxTokens: 16_384,
501
- price: { input: 0.6, output: 3, cacheRead: 0.3 },
502
- }),
503
-
504
- completionsModel({
505
- id: "gpt-oss-120b",
506
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
507
- input: ["text"],
508
- name: "GPT OSS 120B",
509
- provider: "cerebras",
510
- baseUrl: "https://api.cerebras.ai/v1",
511
- reasoning: true,
512
- contextWindow: 131_072,
513
- maxTokens: 40_960,
514
- price: { input: 0.35, output: 0.75 },
515
- }),
516
- completionsModel({
517
- id: "qwen-3.8-27b",
518
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
519
- input: ["text","image"],
520
- name: "Qwen3.8 27B",
521
- provider: "cerebras",
522
- baseUrl: "https://api.cerebras.ai/v1",
523
- reasoning: true,
524
- contextWindow: 65_536,
525
- maxTokens: 32_768,
526
- price: { input: 0.99, output: 1.49 },
527
- }),
528
-
529
- completionsModel({
530
- id: "magistral-medium-latest",
531
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
532
- input: ["text"],
533
- name: "Magistral Medium (latest)",
534
- provider: "mistral",
535
- baseUrl: "https://api.mistral.ai/v1",
536
- reasoning: true,
537
- contextWindow: 128_000,
538
- maxTokens: 16_384,
539
- price: { input: 2, output: 5 },
540
- }),
541
- completionsModel({
542
- id: "mistral-large-2411",
543
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
544
- input: ["text"],
545
- name: "Mistral Large 2.1",
546
- provider: "mistral",
547
- baseUrl: "https://api.mistral.ai/v1",
548
- reasoning: false,
549
- contextWindow: 131_072,
550
- maxTokens: 16_384,
551
- price: { input: 2, output: 6 },
552
- }),
553
-
554
- completionsModel({
555
- id: "openai/gpt-5.5-pro",
556
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
557
- input: ["text","image"],
558
- name: "GPT-5.5 Pro",
559
- provider: "openrouter",
560
- baseUrl: "https://openrouter.ai/api/v1",
561
- reasoning: true,
562
- contextWindow: 1_050_000,
563
- maxTokens: 128_000,
564
- // Base rate. Same context_over_200k tier as the OpenAI row (60/270).
565
- price: { input: 30, output: 180 },
566
- }),
567
- completionsModel({
568
- id: "openai/gpt-5.4-pro",
569
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
570
- input: ["text","image"],
571
- name: "GPT-5.4 Pro",
572
- provider: "openrouter",
573
- baseUrl: "https://openrouter.ai/api/v1",
574
- reasoning: true,
575
- contextWindow: 1_050_000,
576
- maxTokens: 128_000,
577
- // Base rate. Same context_over_200k tier as the OpenAI row (60/270).
578
- price: { input: 30, output: 180 },
579
- }),
580
-
581
- completionsModel({
582
- id: "glm-5.3",
583
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
584
- input: ["text"],
585
- name: "GLM-5.3",
586
- provider: "zai",
587
- baseUrl: "https://api.z.ai/api/paas/v4",
588
- reasoning: true,
589
- cache: "automatic",
590
- rates: { read: 0.26 / 1.4, write: 0 },
591
- price: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
592
- contextWindow: 1_000_000,
593
- maxTokens: 131_072,
594
- }),
595
- completionsModel({
596
- id: "glm-5.2",
597
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
598
- input: ["text"],
599
- name: "GLM-5.2",
600
- provider: "zai",
601
- baseUrl: "https://api.z.ai/api/paas/v4",
602
- reasoning: true,
603
- cache: "automatic",
604
- rates: { read: 0.26 / 1.4, write: 0 },
605
- price: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
606
- contextWindow: 1_000_000,
607
- maxTokens: 131_072,
608
- }),
609
-
610
- completionsModel({
611
- id: "kimi-k3",
612
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
613
- input: ["text","image"],
614
- name: "Kimi K3",
615
- provider: "moonshotai",
616
- baseUrl: "https://api.moonshot.ai/v1",
617
- reasoning: true,
618
- contextWindow: 1_048_576,
619
- maxTokens: 131_072,
620
- price: { input: 3, output: 15, cacheRead: 0.3 },
621
- compat: KIMI_K3_COMPAT,
622
- thinkingLevelMap: KIMI_K3_EFFORT,
623
- }),
624
- completionsModel({
625
- id: "kimi-k2.6",
626
- // Input modalities from the existing models.dev catalog source, 2026-09-30.
627
- input: ["text","image"],
628
- name: "Kimi K2.6",
629
- provider: "moonshotai",
630
- baseUrl: "https://api.moonshot.ai/v1",
631
- reasoning: true,
632
- contextWindow: 262_144,
633
- maxTokens: 262_144,
634
- price: { input: 0.95, output: 4, cacheRead: 0.16 },
635
- }),
636
-
637
- completionsModel({
638
- id: "moonshotai/Kimi-K3",
639
- name: "Kimi K3",
640
- provider: "together",
641
- baseUrl: "https://api.together.xyz/v1",
642
- reasoning: true,
643
- contextWindow: 1_048_576,
644
- maxTokens: 131_072,
645
- price: { input: 3, output: 15, cacheRead: 0.3 },
646
- compat: KIMI_K3_COMPAT,
647
- thinkingLevelMap: KIMI_K3_EFFORT,
648
- }),
649
- completionsModel({
650
- id: "Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8",
651
- name: "Qwen3 Coder 480B A35B Instruct",
652
- provider: "together",
653
- baseUrl: "https://api.together.xyz/v1",
654
- reasoning: false,
655
- contextWindow: 262_144,
656
- maxTokens: 262_144,
657
- // models.dev has input 2 / output 2. Left unpriced so the catalog
658
- // still contains a model whose price was not filled in — the existing
659
- // "unknown cost instead of zero" assertion is a living fixture, not
660
- // a gap we are allowed to close by inventing a reason to skip a rate.
661
- // Filling every other row that has numbers already exceeds 20.
662
- }),
663
- ];
664
-
665
- // Keep existing default/provider order and verified wire dialects; add the source union once.
666
- export const CATALOG: readonly ModelSpec[] = mergeCatalogs(CURATED_CATALOG,
667
- SOURCE_MODELS.filter(model => !CURATED_CATALOG.some(curated => curated.provider === model.provider && curated.id === model.id)));
668
-
669
- /**
670
- * Output tokens to request, which is also the output reserve every window
671
- * budget subtracts.
672
- *
673
- * Three bounds, smallest wins. The model's own limit, because asking for more
674
- * is a 400. A default -- 32000 for reasoning models, whose thinking is billed
675
- * as output and truncated at 16000 often enough to trigger output recovery;
676
- * 16000 otherwise, the previous fixed value. A quarter of the window, so a
677
- * 64k model does not hand a quarter of its context to a reply that is usually
678
- * a few hundred tokens. The defaults are operational choices (32000 is also
679
- * Claude Code's default), not measurements.
680
- */
681
- export function outputTokenBudget(spec: ModelSpec): number {
682
- const bounds = [spec.reasoning ? 32_000 : 16_000];
683
- if (spec.maxTokens !== undefined) bounds.push(spec.maxTokens);
684
- if (spec.contextWindow !== undefined) bounds.push(Math.floor(spec.contextWindow / 4));
685
- return Math.max(1, Math.min(...bounds));
686
- }