@armadra/agent 0.4.0 → 0.5.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.
Files changed (432) hide show
  1. package/CHANGELOG.md +184 -1
  2. package/README.md +202 -83
  3. package/THIRD_PARTY_NOTICES.md +34 -0
  4. package/dist/acp.d.ts +18 -0
  5. package/dist/acp.js +19 -0
  6. package/dist/agent/limits.d.ts +38 -0
  7. package/dist/agent/limits.js +127 -0
  8. package/dist/agent/loop-guard.d.ts +38 -0
  9. package/dist/agent/loop-guard.js +95 -0
  10. package/dist/agent/loop.d.ts +4 -0
  11. package/dist/agent/loop.js +7 -0
  12. package/dist/agent/prompt-rules.d.ts +12 -0
  13. package/dist/agent/prompt-rules.js +18 -0
  14. package/dist/agent/reminders.d.ts +59 -0
  15. package/dist/agent/reminders.js +327 -0
  16. package/dist/agent/session-cache.d.ts +5 -0
  17. package/dist/agent/session-cache.js +17 -1
  18. package/dist/agent/session-classifier.d.ts +1 -1
  19. package/dist/agent/session-classifier.js +3 -1
  20. package/dist/agent/session-compaction.d.ts +35 -6
  21. package/dist/agent/session-compaction.js +157 -31
  22. package/dist/agent/session-core.d.ts +27 -1
  23. package/dist/agent/session-extensions.d.ts +61 -0
  24. package/dist/agent/session-extensions.js +129 -0
  25. package/dist/agent/session-images.d.ts +23 -0
  26. package/dist/agent/session-images.js +97 -0
  27. package/dist/agent/session-plan.d.ts +21 -0
  28. package/dist/agent/session-plan.js +524 -0
  29. package/dist/agent/session-rewind.d.ts +81 -0
  30. package/dist/agent/session-rewind.js +354 -0
  31. package/dist/agent/session-run.d.ts +28 -1
  32. package/dist/agent/session-run.js +157 -6
  33. package/dist/agent/session-settings.d.ts +49 -0
  34. package/dist/agent/session-settings.js +95 -0
  35. package/dist/agent/session-subagent.d.ts +36 -24
  36. package/dist/agent/session-subagent.js +259 -129
  37. package/dist/agent/session-sync.d.ts +10 -3
  38. package/dist/agent/session-sync.js +37 -8
  39. package/dist/agent/session-telemetry.d.ts +39 -0
  40. package/dist/agent/session-telemetry.js +231 -0
  41. package/dist/agent/session-tools.js +40 -1
  42. package/dist/agent/session.d.ts +30 -29
  43. package/dist/agent/session.js +79 -123
  44. package/dist/agent/subagent-registry.d.ts +91 -0
  45. package/dist/agent/subagent-registry.js +494 -0
  46. package/dist/agent/system-prompt.d.ts +6 -3
  47. package/dist/agent/system-prompt.js +7 -2
  48. package/dist/agent/tool-runner.d.ts +8 -1
  49. package/dist/agent/tool-runner.js +57 -4
  50. package/dist/agent/types-w5.d.ts +192 -0
  51. package/dist/agent/types-w5.js +10 -0
  52. package/dist/agent/types.d.ts +47 -4
  53. package/dist/agent/types.js +2 -0
  54. package/dist/agent/worktree.d.ts +36 -0
  55. package/dist/agent/worktree.js +86 -0
  56. package/dist/agents/builtin.d.ts +14 -0
  57. package/dist/agents/builtin.js +39 -0
  58. package/dist/agents/catalog.d.ts +43 -0
  59. package/dist/agents/catalog.js +82 -0
  60. package/dist/agents/discover.d.ts +35 -0
  61. package/dist/agents/discover.js +83 -0
  62. package/dist/agents/external.d.ts +82 -0
  63. package/dist/agents/external.js +326 -0
  64. package/dist/agents/parse.d.ts +18 -0
  65. package/dist/agents/parse.js +116 -0
  66. package/dist/agents/result.d.ts +32 -0
  67. package/dist/agents/result.js +67 -0
  68. package/dist/agents/task-control.d.ts +17 -0
  69. package/dist/agents/task-control.js +17 -0
  70. package/dist/agents/task-record.d.ts +78 -0
  71. package/dist/agents/task-record.js +141 -0
  72. package/dist/agents/types.d.ts +46 -0
  73. package/dist/agents/types.js +8 -0
  74. package/dist/ai/apis/anthropic-compat.d.ts +36 -0
  75. package/dist/ai/apis/anthropic-compat.js +92 -0
  76. package/dist/ai/apis/anthropic-request.d.ts +7 -6
  77. package/dist/ai/apis/anthropic-request.js +10 -28
  78. package/dist/ai/apis/cache-params.d.ts +11 -2
  79. package/dist/ai/apis/cache-params.js +25 -6
  80. package/dist/ai/apis/openai-compat.d.ts +4 -1
  81. package/dist/ai/apis/openai-compat.js +8 -1
  82. package/dist/ai/image-limits.d.ts +45 -0
  83. package/dist/ai/image-limits.js +68 -0
  84. package/dist/ai/providers/builtin.d.ts +18 -6
  85. package/dist/ai/providers/builtin.js +135 -6
  86. package/dist/ai/providers/catalog-data.js +17 -13
  87. package/dist/ai/providers/catalog.d.ts +60 -7
  88. package/dist/ai/providers/catalog.js +197 -38
  89. package/dist/ai/providers/channels.d.ts +33 -3
  90. package/dist/ai/providers/channels.js +108 -7
  91. package/dist/ai/providers/enrich.d.ts +6 -3
  92. package/dist/ai/providers/enrich.js +19 -4
  93. package/dist/ai/providers/models-dev-cache.d.ts +28 -24
  94. package/dist/ai/providers/models-dev-cache.js +92 -78
  95. package/dist/ai/providers/models-dev-data.d.ts +7 -0
  96. package/dist/ai/providers/models-dev-data.js +32 -0
  97. package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
  98. package/dist/ai/providers/models-dev-snapshot.js +137 -0
  99. package/dist/ai/providers/models-dev.d.ts +51 -10
  100. package/dist/ai/providers/models-dev.js +132 -39
  101. package/dist/ai/providers/registry.d.ts +20 -10
  102. package/dist/ai/providers/registry.js +82 -43
  103. package/dist/ai/types.d.ts +28 -2
  104. package/dist/ai/types.js +5 -0
  105. package/dist/bundle/ama.cjs +37605 -21619
  106. package/dist/checkpoints/backend.d.ts +61 -0
  107. package/dist/checkpoints/backend.js +135 -0
  108. package/dist/checkpoints/blobs.d.ts +60 -0
  109. package/dist/checkpoints/blobs.js +203 -0
  110. package/dist/checkpoints/gc.d.ts +47 -0
  111. package/dist/checkpoints/gc.js +144 -0
  112. package/dist/checkpoints/git-head.d.ts +15 -0
  113. package/dist/checkpoints/git-head.js +89 -0
  114. package/dist/checkpoints/index.d.ts +17 -0
  115. package/dist/checkpoints/index.js +17 -0
  116. package/dist/checkpoints/replay.d.ts +48 -0
  117. package/dist/checkpoints/replay.js +154 -0
  118. package/dist/checkpoints/restore.d.ts +86 -0
  119. package/dist/checkpoints/restore.js +263 -0
  120. package/dist/checkpoints/settings.d.ts +14 -0
  121. package/dist/checkpoints/settings.js +23 -0
  122. package/dist/checkpoints/shadow-git.d.ts +108 -0
  123. package/dist/checkpoints/shadow-git.js +491 -0
  124. package/dist/checkpoints/shadow-restore.d.ts +25 -0
  125. package/dist/checkpoints/shadow-restore.js +128 -0
  126. package/dist/checkpoints/tracker.d.ts +64 -0
  127. package/dist/checkpoints/tracker.js +192 -0
  128. package/dist/checkpoints/types.d.ts +99 -0
  129. package/dist/checkpoints/types.js +12 -0
  130. package/dist/cli/args.d.ts +8 -4
  131. package/dist/cli/args.js +17 -97
  132. package/dist/cli/bootstrap.js +13 -1
  133. package/dist/cli/choice-prompt.d.ts +58 -0
  134. package/dist/cli/choice-prompt.js +140 -0
  135. package/dist/cli/codemode-notice.d.ts +3 -2
  136. package/dist/cli/codemode-notice.js +3 -2
  137. package/dist/cli/compose-agents.d.ts +27 -0
  138. package/dist/cli/compose-agents.js +111 -0
  139. package/dist/cli/compose-extensions.d.ts +29 -0
  140. package/dist/cli/compose-extensions.js +44 -0
  141. package/dist/cli/compose-session.d.ts +3 -0
  142. package/dist/cli/compose-session.js +47 -4
  143. package/dist/cli/compose.d.ts +3 -0
  144. package/dist/cli/compose.js +33 -6
  145. package/dist/cli/deps.d.ts +6 -0
  146. package/dist/cli/exit-codes.d.ts +10 -0
  147. package/dist/cli/exit-codes.js +12 -0
  148. package/dist/cli/help-text.d.ts +4 -0
  149. package/dist/cli/help-text.js +102 -0
  150. package/dist/cli/startup-screen.js +5 -3
  151. package/dist/cli/startup-steps.js +7 -1
  152. package/dist/cli/subcommands/config.d.ts +4 -1
  153. package/dist/cli/subcommands/config.js +17 -6
  154. package/dist/cli/subcommands/doctor.js +21 -0
  155. package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
  156. package/dist/cli/subcommands/models-cache-probe.js +3 -12
  157. package/dist/cli/subcommands/models-discover.js +5 -6
  158. package/dist/cli/subcommands/models.d.ts +2 -0
  159. package/dist/cli/subcommands/models.js +33 -14
  160. package/dist/cli/subcommands/providers.d.ts +1 -1
  161. package/dist/cli/subcommands/providers.js +8 -15
  162. package/dist/cli/subcommands/sessions.d.ts +3 -1
  163. package/dist/cli/subcommands/sessions.js +36 -2
  164. package/dist/codemode/capability.d.ts +24 -7
  165. package/dist/codemode/capability.js +38 -10
  166. package/dist/codemode/host-side.d.ts +14 -0
  167. package/dist/codemode/host-side.js +24 -1
  168. package/dist/codemode/tool.d.ts +1 -1
  169. package/dist/codemode/tool.js +6 -4
  170. package/dist/compaction/breaker.d.ts +25 -9
  171. package/dist/compaction/breaker.js +47 -17
  172. package/dist/compaction/estimate.d.ts +11 -3
  173. package/dist/compaction/estimate.js +64 -22
  174. package/dist/compaction/image-budget.d.ts +45 -0
  175. package/dist/compaction/image-budget.js +115 -0
  176. package/dist/compaction/post-compact.d.ts +38 -0
  177. package/dist/compaction/post-compact.js +152 -0
  178. package/dist/compaction/protect.d.ts +27 -0
  179. package/dist/compaction/protect.js +56 -0
  180. package/dist/compaction/prune-tier.d.ts +58 -12
  181. package/dist/compaction/prune-tier.js +120 -54
  182. package/dist/compaction/summarize-tier.d.ts +23 -4
  183. package/dist/compaction/summarize-tier.js +100 -29
  184. package/dist/config/checker.d.ts +28 -0
  185. package/dist/config/checker.js +97 -0
  186. package/dist/config/json-schema.js +63 -2
  187. package/dist/config/key-docs.js +72 -3
  188. package/dist/config/merge.d.ts +5 -3
  189. package/dist/config/merge.js +81 -7
  190. package/dist/config/profile.d.ts +2 -0
  191. package/dist/config/profile.js +2 -0
  192. package/dist/config/schema-w5.d.ts +18 -0
  193. package/dist/config/schema-w5.js +109 -0
  194. package/dist/config/schema.d.ts +5 -9
  195. package/dist/config/schema.js +68 -114
  196. package/dist/config/types-w5.d.ts +118 -0
  197. package/dist/config/types-w5.js +20 -0
  198. package/dist/config/types.d.ts +50 -1
  199. package/dist/config/types.js +12 -0
  200. package/dist/drivers/acp/client.d.ts +57 -0
  201. package/dist/drivers/acp/client.js +160 -0
  202. package/dist/drivers/acp/driver.d.ts +31 -0
  203. package/dist/drivers/acp/driver.js +274 -0
  204. package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
  205. package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
  206. package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
  207. package/dist/drivers/acp/testing/fake-agent.js +211 -0
  208. package/dist/drivers/acp/types.d.ts +285 -0
  209. package/dist/drivers/acp/types.js +36 -0
  210. package/dist/drivers/agents.d.ts +58 -0
  211. package/dist/drivers/agents.js +142 -0
  212. package/dist/drivers/base.d.ts +35 -0
  213. package/dist/drivers/base.js +59 -0
  214. package/dist/drivers/catalog.d.ts +46 -0
  215. package/dist/drivers/catalog.js +167 -0
  216. package/dist/drivers/env.d.ts +20 -0
  217. package/dist/drivers/env.js +46 -0
  218. package/dist/drivers/host-runners.d.ts +18 -0
  219. package/dist/drivers/host-runners.js +45 -0
  220. package/dist/drivers/jsonrpc.d.ts +58 -0
  221. package/dist/drivers/jsonrpc.js +180 -0
  222. package/dist/drivers/native/claude-normalize.d.ts +46 -0
  223. package/dist/drivers/native/claude-normalize.js +106 -0
  224. package/dist/drivers/native/claude-stream.d.ts +29 -0
  225. package/dist/drivers/native/claude-stream.js +456 -0
  226. package/dist/drivers/native/codex-app-server.d.ts +26 -0
  227. package/dist/drivers/native/codex-app-server.js +407 -0
  228. package/dist/drivers/native/codex-normalize.d.ts +38 -0
  229. package/dist/drivers/native/codex-normalize.js +124 -0
  230. package/dist/drivers/native/oneshot.d.ts +28 -0
  231. package/dist/drivers/native/oneshot.js +312 -0
  232. package/dist/drivers/permissions.d.ts +40 -0
  233. package/dist/drivers/permissions.js +92 -0
  234. package/dist/drivers/pids.d.ts +32 -0
  235. package/dist/drivers/pids.js +93 -0
  236. package/dist/drivers/pool.d.ts +28 -0
  237. package/dist/drivers/pool.js +96 -0
  238. package/dist/drivers/probe.d.ts +47 -0
  239. package/dist/drivers/probe.js +172 -0
  240. package/dist/drivers/process.d.ts +48 -0
  241. package/dist/drivers/process.js +100 -0
  242. package/dist/drivers/runner.d.ts +61 -0
  243. package/dist/drivers/runner.js +388 -0
  244. package/dist/drivers/store.d.ts +49 -0
  245. package/dist/drivers/store.js +91 -0
  246. package/dist/drivers/turn.d.ts +41 -0
  247. package/dist/drivers/turn.js +99 -0
  248. package/dist/drivers/types.d.ts +122 -0
  249. package/dist/drivers/types.js +11 -0
  250. package/dist/git/info.d.ts +75 -0
  251. package/dist/git/info.js +191 -0
  252. package/dist/hooks/protocol.js +6 -1
  253. package/dist/hooks/types.d.ts +10 -1
  254. package/dist/hooks/types.js +2 -0
  255. package/dist/host/api-impl.d.ts +7 -0
  256. package/dist/host/api-impl.js +15 -0
  257. package/dist/host/types.d.ts +24 -2
  258. package/dist/host/types.js +4 -0
  259. package/dist/index.d.ts +3 -0
  260. package/dist/index.js +1 -0
  261. package/dist/modes/acp/acp-events.d.ts +46 -0
  262. package/dist/modes/acp/acp-events.js +233 -0
  263. package/dist/modes/acp/acp-mode.d.ts +17 -0
  264. package/dist/modes/acp/acp-mode.js +47 -0
  265. package/dist/modes/acp/acp-server.d.ts +79 -0
  266. package/dist/modes/acp/acp-server.js +315 -0
  267. package/dist/modes/commands-core.d.ts +13 -1
  268. package/dist/modes/commands-core.js +64 -0
  269. package/dist/modes/image-input.d.ts +12 -4
  270. package/dist/modes/image-input.js +22 -5
  271. package/dist/modes/interactive/agent-panels.d.ts +14 -0
  272. package/dist/modes/interactive/agent-panels.js +103 -0
  273. package/dist/modes/interactive/agent-ui.d.ts +73 -0
  274. package/dist/modes/interactive/agent-ui.js +234 -0
  275. package/dist/modes/interactive/approval-dialog.d.ts +21 -4
  276. package/dist/modes/interactive/approval-dialog.js +98 -20
  277. package/dist/modes/interactive/approval-merge.d.ts +41 -0
  278. package/dist/modes/interactive/approval-merge.js +89 -0
  279. package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
  280. package/dist/modes/interactive/clipboard-paste.js +28 -0
  281. package/dist/modes/interactive/commands.d.ts +12 -1
  282. package/dist/modes/interactive/commands.js +31 -1
  283. package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
  284. package/dist/modes/interactive/confirm-dialog.js +121 -0
  285. package/dist/modes/interactive/double-esc.d.ts +20 -0
  286. package/dist/modes/interactive/double-esc.js +34 -0
  287. package/dist/modes/interactive/event-notices.d.ts +32 -0
  288. package/dist/modes/interactive/event-notices.js +79 -0
  289. package/dist/modes/interactive/external-editor.d.ts +16 -0
  290. package/dist/modes/interactive/external-editor.js +39 -0
  291. package/dist/modes/interactive/interactive-mode.d.ts +14 -1
  292. package/dist/modes/interactive/interactive-mode.js +140 -136
  293. package/dist/modes/interactive/key-dispatch.d.ts +22 -2
  294. package/dist/modes/interactive/key-dispatch.js +66 -7
  295. package/dist/modes/interactive/line/line-mode.d.ts +4 -1
  296. package/dist/modes/interactive/line/line-mode.js +31 -5
  297. package/dist/modes/interactive/line/line-render.d.ts +2 -1
  298. package/dist/modes/interactive/line/line-render.js +40 -4
  299. package/dist/modes/interactive/message-view.d.ts +1 -1
  300. package/dist/modes/interactive/message-view.js +24 -2
  301. package/dist/modes/interactive/panels.d.ts +18 -1
  302. package/dist/modes/interactive/panels.js +19 -5
  303. package/dist/modes/interactive/plan-command.d.ts +40 -0
  304. package/dist/modes/interactive/plan-command.js +129 -0
  305. package/dist/modes/interactive/plan-dialog.d.ts +98 -0
  306. package/dist/modes/interactive/plan-dialog.js +290 -0
  307. package/dist/modes/interactive/plan-flow.d.ts +34 -0
  308. package/dist/modes/interactive/plan-flow.js +98 -0
  309. package/dist/modes/interactive/rewind-command.d.ts +31 -0
  310. package/dist/modes/interactive/rewind-command.js +106 -0
  311. package/dist/modes/interactive/rewind-flow.d.ts +37 -0
  312. package/dist/modes/interactive/rewind-flow.js +151 -0
  313. package/dist/modes/interactive/rewind-list.d.ts +36 -0
  314. package/dist/modes/interactive/rewind-list.js +123 -0
  315. package/dist/modes/interactive/rewind-panel.d.ts +77 -0
  316. package/dist/modes/interactive/rewind-panel.js +309 -0
  317. package/dist/modes/interactive/rewind-text.d.ts +40 -0
  318. package/dist/modes/interactive/rewind-text.js +139 -0
  319. package/dist/modes/interactive/session-events.d.ts +24 -0
  320. package/dist/modes/interactive/session-events.js +96 -0
  321. package/dist/modes/interactive/startup-ui.js +5 -1
  322. package/dist/modes/interactive/status-area.d.ts +73 -0
  323. package/dist/modes/interactive/status-area.js +190 -0
  324. package/dist/modes/interactive/status-bar.d.ts +99 -11
  325. package/dist/modes/interactive/status-bar.js +273 -90
  326. package/dist/modes/interactive/status-line.d.ts +33 -0
  327. package/dist/modes/interactive/status-line.js +113 -0
  328. package/dist/modes/interactive/subagent-view.d.ts +56 -0
  329. package/dist/modes/interactive/subagent-view.js +154 -0
  330. package/dist/modes/interactive/tasks-report.d.ts +27 -0
  331. package/dist/modes/interactive/tasks-report.js +114 -0
  332. package/dist/modes/interactive/tool-view.d.ts +12 -2
  333. package/dist/modes/interactive/tool-view.js +34 -4
  334. package/dist/modes/print/print-mode.d.ts +13 -4
  335. package/dist/modes/print/print-mode.js +56 -12
  336. package/dist/modes/rpc/commands.d.ts +9 -0
  337. package/dist/modes/rpc/commands.js +44 -0
  338. package/dist/modes/rpc/rpc-mode.js +7 -1
  339. package/dist/modes/session-report.d.ts +11 -0
  340. package/dist/modes/session-report.js +48 -1
  341. package/dist/permissions/auto-safe.d.ts +5 -0
  342. package/dist/permissions/auto-safe.js +18 -0
  343. package/dist/permissions/bypass.d.ts +32 -0
  344. package/dist/permissions/bypass.js +36 -0
  345. package/dist/permissions/classifier.d.ts +4 -0
  346. package/dist/permissions/classifier.js +2 -0
  347. package/dist/permissions/modes.js +1 -1
  348. package/dist/permissions/pipeline.d.ts +43 -4
  349. package/dist/permissions/pipeline.js +114 -9
  350. package/dist/permissions/readonly-bash.d.ts +30 -0
  351. package/dist/permissions/readonly-bash.js +118 -0
  352. package/dist/permissions/types.d.ts +42 -0
  353. package/dist/plan/compose.d.ts +9 -0
  354. package/dist/plan/compose.js +19 -0
  355. package/dist/plan/controller.d.ts +71 -0
  356. package/dist/plan/controller.js +27 -0
  357. package/dist/plan/done-markers.d.ts +17 -0
  358. package/dist/plan/done-markers.js +51 -0
  359. package/dist/plan/extract.d.ts +29 -0
  360. package/dist/plan/extract.js +160 -0
  361. package/dist/plan/prompts.d.ts +36 -0
  362. package/dist/plan/prompts.js +89 -0
  363. package/dist/plan/store.d.ts +37 -0
  364. package/dist/plan/store.js +90 -0
  365. package/dist/rpc.d.ts +58 -2
  366. package/dist/rpc.js +7 -0
  367. package/dist/sandbox/bash.d.ts +74 -0
  368. package/dist/sandbox/bash.js +126 -0
  369. package/dist/sandbox/detect.d.ts +48 -0
  370. package/dist/sandbox/detect.js +149 -0
  371. package/dist/sandbox/index.d.ts +5 -0
  372. package/dist/sandbox/index.js +5 -0
  373. package/dist/sandbox/profile.d.ts +33 -0
  374. package/dist/sandbox/profile.js +76 -0
  375. package/dist/sandbox/wrap.d.ts +29 -0
  376. package/dist/sandbox/wrap.js +117 -0
  377. package/dist/sdk.d.ts +33 -2
  378. package/dist/sdk.js +24 -2
  379. package/dist/session/types.d.ts +3 -1
  380. package/dist/session/types.js +1 -0
  381. package/dist/skills/builtin.d.ts +31 -0
  382. package/dist/skills/builtin.js +109 -0
  383. package/dist/skills/discover.d.ts +2 -1
  384. package/dist/skills/index-prompt.js +5 -8
  385. package/dist/tools/background-jobs.d.ts +71 -0
  386. package/dist/tools/background-jobs.js +198 -0
  387. package/dist/tools/bash.d.ts +53 -1
  388. package/dist/tools/bash.js +158 -7
  389. package/dist/tools/clipboard-image.d.ts +44 -0
  390. package/dist/tools/clipboard-image.js +148 -0
  391. package/dist/tools/edit.d.ts +2 -0
  392. package/dist/tools/edit.js +18 -3
  393. package/dist/tools/image-file.d.ts +38 -3
  394. package/dist/tools/image-file.js +81 -10
  395. package/dist/tools/image-resize.d.ts +58 -0
  396. package/dist/tools/image-resize.js +97 -0
  397. package/dist/tools/presets.d.ts +7 -2
  398. package/dist/tools/presets.js +11 -4
  399. package/dist/tools/read.d.ts +5 -2
  400. package/dist/tools/read.js +13 -10
  401. package/dist/tools/registry.d.ts +7 -1
  402. package/dist/tools/registry.js +27 -4
  403. package/dist/tools/task-ctl.d.ts +22 -0
  404. package/dist/tools/task-ctl.js +116 -0
  405. package/dist/tools/task.d.ts +22 -10
  406. package/dist/tools/task.js +66 -26
  407. package/dist/tools/todo.d.ts +22 -2
  408. package/dist/tools/todo.js +58 -14
  409. package/dist/tools/truncate.d.ts +15 -0
  410. package/dist/tools/truncate.js +25 -0
  411. package/dist/tools/types.d.ts +113 -0
  412. package/dist/tools/types.js +5 -0
  413. package/dist/tools/write.js +3 -0
  414. package/dist/tui/glyphs.d.ts +4 -0
  415. package/dist/tui/glyphs.js +4 -0
  416. package/dist/tui/keybindings.d.ts +6 -1
  417. package/dist/tui/keybindings.js +6 -1
  418. package/docs/acp.md +78 -0
  419. package/docs/agents.md +250 -0
  420. package/docs/codemode.md +12 -8
  421. package/docs/hooks.md +26 -22
  422. package/docs/permissions.md +78 -13
  423. package/docs/plan.md +107 -0
  424. package/docs/providers.md +228 -52
  425. package/docs/rewind-plan.md +181 -0
  426. package/docs/rpc.md +92 -5
  427. package/docs/sandbox.md +215 -0
  428. package/docs/session-format.md +41 -21
  429. package/docs/sessions.md +41 -1
  430. package/docs/tui-design.md +751 -0
  431. package/docs/tui.md +179 -21
  432. package/package.json +13 -2
@@ -3,17 +3,21 @@
3
3
  * UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts
4
4
  */
5
5
  export const CATALOG_SOURCES = {
6
- anthropic: '{"version":1,"provider":"anthropic","models":[{"id":"claude-fable-5-1","name":"Claude Fable 5.1","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":0.25,"cacheWrite":12.5},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-fable-5","name":"Claude Fable 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5-5","name":"Claude Opus 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.2,"cacheWrite":5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5","name":"Claude Opus 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-8","name":"Claude Opus 4.8","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-7","name":"Claude Opus 4.7","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":2048},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-6","name":"Claude Opus 4.6","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"promptCache":{"short":300,"long":3600,"minTokens":4096},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5-5","name":"Claude Sonnet 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5","name":"Claude Sonnet 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-6","name":"Claude Sonnet 4.6","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":3.75},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5 (latest)","contextWindow":1000000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":3.75},"promptCache":{"short":300,"long":3600,"minTokens":1024}},{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5 (latest)","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":1,"output":5,"cacheRead":0.1,"cacheWrite":1.25},"promptCache":{"short":300,"long":3600,"minTokens":4096}},{"id":"claude-opus-4-5","name":"Claude Opus 4.5 (latest)","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"promptCache":{"short":300,"long":3600,"minTokens":4096}}]}',
7
- dashscope: '{"version":1,"provider":"dashscope","models":[{"id":"qwen3.8-max","name":"Qwen3.8 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.8-flash","name":"Qwen3.8 Flash","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.7-max","name":"Qwen3.7 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-flash","name":"Qwen3.6 Flash","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}}]}',
8
- deepseek: '{"version":1,"provider":"deepseek","models":[{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro","contextWindow":1000000,"maxTokens":384000,"reasoning":true,"input":["text"],"cost":{"input":1.32,"output":3.96,"cacheRead":0.044,"cacheWrite":0},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"}},{"id":"deepseek-flash","name":"DeepSeek V4.1 Flash","contextWindow":1000000,"maxTokens":384000,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.006,"cacheWrite":0},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"}}]}',
9
- google: '{"version":1,"provider":"google","models":[{"id":"gemini-3.8-flash","name":"Gemini 3.8 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.7-flash","name":"Gemini 3.7 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash","name":"Gemini 3.5 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":1.5,"output":9,"cacheRead":0.15,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash-lite","name":"Gemini 3.5 Flash Lite","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":2.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.1-pro-preview","name":"Gemini 3.1 Pro Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3-flash-preview","name":"Gemini 3 Flash Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.5,"output":3,"cacheRead":0.05,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-2.5-pro","name":"Gemini 2.5 Pro","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":128,"low":2048,"medium":8192,"high":32768}},{"id":"gemini-2.5-flash","name":"Gemini 2.5 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":2.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"minimal":128,"low":2048,"medium":8192,"high":24576}},{"id":"gemini-2.5-flash-lite","name":"Gemini 2.5 Flash-Lite","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.4,"cacheRead":0.01,"cacheWrite":0},"thinkingLevelMap":{"minimal":512,"low":2048,"medium":8192,"high":24576}}]}',
10
- groq: '{"version":1,"provider":"groq","models":[{"id":"openai/gpt-oss-120b","name":"GPT OSS 120B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-20b","name":"GPT OSS 20B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.075,"output":0.3,"cacheRead":0.0375,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-safeguard-20b","name":"Safety GPT OSS 20B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.075,"output":0.3,"cacheRead":0,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.8-27b","name":"Qwen3.8 27B","contextWindow":131042,"maxTokens":16384,"reasoning":true,"input":["text","image"],"cost":{"input":0.8,"output":4,"cacheRead":0,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.6-27b","name":"Qwen3.6 27B","contextWindow":131072,"maxTokens":16384,"reasoning":true,"input":["text","image"],"cost":{"input":0.6,"output":3,"cacheRead":0.3,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"default","xhigh":null}},{"id":"llama-3.3-70b-versatile","name":"Llama 3.3 70B","contextWindow":131072,"maxTokens":32768,"reasoning":false,"input":["text"],"cost":{"input":0.59,"output":0.79,"cacheRead":0,"cacheWrite":0}},{"id":"llama-3.1-8b-instant","name":"Llama 3.1 8B","contextWindow":131072,"maxTokens":131072,"reasoning":false,"input":["text"],"cost":{"input":0.05,"output":0.08,"cacheRead":0,"cacheWrite":0}}]}',
11
- lmstudio: '{"version":1,"provider":"lmstudio","models":[]}',
12
- mistral: '{"version":1,"provider":"mistral","models":[{"id":"mistral-large-latest","name":"Mistral Large (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text","image"],"cost":{"input":0.5,"output":1.5,"cacheRead":0.05,"cacheWrite":0}},{"id":"mistral-medium-latest","name":"Mistral Medium (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":1.5,"output":7.5,"cacheRead":0.15,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"mistral-small-latest","name":"Mistral Small (latest)","contextWindow":256000,"maxTokens":256000,"reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.015,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"magistral-medium-latest","name":"Magistral Medium (latest)","contextWindow":128000,"maxTokens":16384,"reasoning":true,"input":["text"],"cost":{"input":2,"output":5,"cacheRead":0.2,"cacheWrite":0}},{"id":"codestral-latest","name":"Codestral (latest)","contextWindow":256000,"maxTokens":4096,"reasoning":false,"input":["text"],"cost":{"input":0.3,"output":0.9,"cacheRead":0.03,"cacheWrite":0}},{"id":"devstral-latest","name":"Devstral 2","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"devstral-medium-latest","name":"Devstral 2 (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"ministral-8b-latest","name":"Ministral 8B (latest)","contextWindow":128000,"maxTokens":128000,"reasoning":false,"input":["text"],"cost":{"input":0.1,"output":0.1,"cacheRead":0.01,"cacheWrite":0}},{"id":"pixtral-large-latest","name":"Pixtral Large (latest)","contextWindow":128000,"maxTokens":128000,"reasoning":false,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.2,"cacheWrite":0}}]}',
13
- moonshot: '{"version":1,"provider":"moonshot","models":[{"id":"kimi-k3","name":"Kimi K3","contextWindow":1048576,"maxTokens":1048576,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":true}},{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.19,"cacheWrite":0},"thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.7-code-highspeed","name":"Kimi K2.7 Code HighSpeed","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":1.9,"output":8,"cacheRead":0.38,"cacheWrite":0},"thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.6","name":"Kimi K2.6","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.16,"cacheWrite":0},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}}]}',
14
- ollama: '{"version":1,"provider":"ollama","models":[]}',
15
- openai: '{"version":1,"provider":"openai","models":[{"id":"gpt-6.1-sol","name":"GPT-6.1 Sol","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.1,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":15,"cacheRead":0.2,"cacheWrite":5}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-sol","name":"GPT-6 Sol","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":15,"cacheRead":0.4,"cacheWrite":5}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-luna","name":"GPT-6 Luna","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.5,"cacheRead":0.01,"cacheWrite":0.125,"tiers":[{"inputTokensAbove":272000,"input":0.2,"output":0.75,"cacheRead":0.02,"cacheWrite":0.25}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-astra","name":"GPT-6 Astra","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5,"tiers":[{"inputTokensAbove":272000,"input":20,"output":75,"cacheRead":2,"cacheWrite":25}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-nano","name":"GPT-5.4 nano","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.25,"cacheRead":0.02,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5","name":"GPT-5","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5-mini","name":"GPT-5 Mini","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.25,"output":2,"cacheRead":0.025,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4.1","name":"GPT-4.1","contextWindow":1047576,"maxTokens":32768,"reasoning":false,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o","name":"GPT-4o","contextWindow":128000,"maxTokens":16384,"reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o-mini","name":"GPT-4o mini","contextWindow":128000,"maxTokens":16384,"reasoning":false,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o4-mini","name":"o4-mini","api":"openai-responses","contextWindow":200000,"maxTokens":100000,"reasoning":true,"input":["text","image"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.275,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o3","name":"o3","api":"openai-responses","contextWindow":200000,"maxTokens":100000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}}]}',
16
- openrouter: '{"version":1,"provider":"openrouter","models":[{"id":"anthropic/claude-opus-5.5","name":"Anthropic: Claude Opus 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.2,"cacheWrite":5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-sonnet-5.5","name":"Anthropic: Claude Sonnet 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-haiku-4.5","name":"Anthropic: Claude Haiku 4.5","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":1,"output":5,"cacheRead":0.1,"cacheWrite":1.25}},{"id":"openai/gpt-6-sol","name":"OpenAI: GPT-6 Sol","contextWindow":1050000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.5","name":"OpenAI: GPT-5.5","contextWindow":1050000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.4-mini","name":"OpenAI: GPT-5.4 Mini","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"google/gemini-3.8-flash","name":"Google: Gemini 3.8 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0.041667},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"google/gemini-3.1-pro-preview","name":"Google: Gemini 3.1 Pro Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":0.375},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"deepseek/deepseek-v4-pro","name":"DeepSeek: DeepSeek V4 Pro 0423","contextWindow":1024000,"maxTokens":384000,"reasoning":true,"input":["text"],"cost":{"input":0.2088,"output":0.4176,"cacheRead":0.0174,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":"xhigh"},"compat":{"requiresReasoningContentOnAssistantMessages":true}},{"id":"moonshotai/kimi-k3","name":"MoonshotAI: Kimi K3","contextWindow":1048576,"maxTokens":131072,"reasoning":true,"input":["text","image"],"cost":{"input":0.6635,"output":10,"cacheRead":0.6635,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"qwen/qwen3.7-max","name":"Qwen: Qwen3.7 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.475,"output":4.425,"cacheRead":0.295,"cacheWrite":1.84375}},{"id":"z-ai/glm-5.3","name":"Z.ai: GLM 5.3","contextWindow":1048576,"maxTokens":943718,"reasoning":true,"input":["text"],"cost":{"input":0.2219,"output":3.39,"cacheRead":0.1775,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"x-ai/grok-4.7","name":"SpaceXAI: Grok 4.7","contextWindow":500000,"maxTokens":450000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}}]}',
17
- xai: '{"version":1,"provider":"xai","models":[{"id":"grok-4.7","name":"Grok 4.7","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.6","name":"Grok 4.6","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.5","name":"Grok 4.5","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.3,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":0.6,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"grok-4.3","name":"Grok 4.3","api":"openai-responses","contextWindow":1000000,"maxTokens":30000,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":2.5,"cacheRead":0.2,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":2.5,"output":5,"cacheRead":0.4,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}}]}',
18
- zhipu: '{"version":1,"provider":"zhipu","models":[{"id":"glm-5.3","name":"GLM-5.3","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.3-flash","name":"GLM-5.3-Flash","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.2","name":"GLM-5.2","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5-turbo","name":"GLM-5-Turbo","contextWindow":200000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsReasoningEffort":false}},{"id":"glm-4.7","name":"GLM-4.7","contextWindow":204800,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":0.6,"output":2.2,"cacheRead":0.11,"cacheWrite":0},"compat":{"supportsReasoningEffort":false}}]}',
6
+ anthropic: '{"version":1,"provider":"anthropic","modelsDev":"anthropic","models":[{"id":"claude-fable-5-1","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-fable-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-8","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-7","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":2048},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-6","promptCache":{"short":300,"long":3600,"minTokens":4096},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-6","promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-5","promptCache":{"short":300,"long":3600,"minTokens":1024}},{"id":"claude-haiku-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}},{"id":"claude-opus-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}}]}',
7
+ dashscope: '{"version":1,"provider":"dashscope","modelsDev":"alibaba-cn","models":[{"id":"qwen3.8-max","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.7-max","maxTokens":131072,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.7-plus","maxTokens":65536,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-plus","compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-flash","compat":{"supportsReasoningEffort":false}}]}',
8
+ deepseek: '{"version":1,"provider":"deepseek","modelsDev":"deepseek","models":[{"id":"deepseek-v4-pro","maxTokens":384000,"cost":{"input":1.32,"output":3.96,"cacheRead":0.044},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"},{"id":"deepseek-flash","maxTokens":384000,"cost":{"input":0.3,"output":1.2,"cacheRead":0.006},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"}]}',
9
+ google: '{"version":1,"provider":"google","modelsDev":"google","models":[{"id":"gemini-3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.7-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash-lite","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.1-pro-preview","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3-flash-preview","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-2.5-pro","thinkingLevelMap":{"off":null,"minimal":128,"low":2048,"medium":8192,"high":32768}},{"id":"gemini-2.5-flash","thinkingLevelMap":{"minimal":128,"low":2048,"medium":8192,"high":24576}},{"id":"gemini-2.5-flash-lite","thinkingLevelMap":{"minimal":512,"low":2048,"medium":8192,"high":24576}}]}',
10
+ groq: '{"version":1,"provider":"groq","modelsDev":"groq","models":[{"id":"openai/gpt-oss-120b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-safeguard-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.8-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.6-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"default","xhigh":null}},{"id":"llama-3.3-70b-versatile"},{"id":"llama-3.1-8b-instant"}]}',
11
+ lmstudio: '{"version":1,"provider":"lmstudio","modelsDev":false,"models":[]}',
12
+ minimax: '{"version":1,"provider":"minimax","modelsDev":"minimax-cn","models":[{"id":"MiniMax-M3"},{"id":"MiniMax-M2.7","channels":["messages","chat","messages-intl","chat-intl"],"thinkingLevelMap":{"off":null},"promptCache":{"short":300}},{"id":"MiniMax-M2.7-highspeed","channels":["messages","chat","messages-intl","chat-intl"],"thinkingLevelMap":{"off":null},"promptCache":{"short":300}},{"id":"MiniMax-M2.5","channels":["messages","chat","messages-intl","chat-intl"],"thinkingLevelMap":{"off":null},"promptCache":{"short":300}}]}',
13
+ mistral: '{"version":1,"provider":"mistral","modelsDev":"mistral","models":[{"id":"mistral-large-latest"},{"id":"mistral-medium-latest","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"mistral-small-latest","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"magistral-medium-latest","cost":{"cacheRead":0.2}},{"id":"codestral-latest"},{"id":"devstral-latest","name":"Devstral 2","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"devstral-medium-latest","name":"Devstral 2 (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"ministral-8b-latest","cost":{"cacheRead":0.01}},{"id":"pixtral-large-latest","cost":{"cacheRead":0.2}}]}',
14
+ moonshot: '{"version":1,"provider":"moonshot","modelsDev":"moonshotai-cn","models":[{"id":"kimi-k3","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":true}},{"id":"kimi-k2.7-code","thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.7-code-highspeed","thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.6","promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}}]}',
15
+ ollama: '{"version":1,"provider":"ollama","modelsDev":false,"models":[]}',
16
+ openai: '{"version":1,"provider":"openai","modelsDev":"openai","models":[{"id":"gpt-6.1-sol","contextWindow":272000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-sol","contextWindow":272000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-luna","contextWindow":272000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-astra","contextWindow":272000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.5","contextWindow":272000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4","contextWindow":272000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-mini","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-nano","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5-mini","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4.1","promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o","promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o-mini","promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o4-mini","name":"o4-mini","contextWindow":200000,"maxTokens":100000,"reasoning":true,"input":["text","image"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.275,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o3","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}}]}',
17
+ openrouter: '{"version":1,"provider":"openrouter","modelsDev":"openrouter","models":[{"id":"anthropic/claude-opus-5.5","name":"Anthropic: Claude Opus 5.5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-sonnet-5.5","name":"Anthropic: Claude Sonnet 5.5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-haiku-4.5","name":"Anthropic: Claude Haiku 4.5"},{"id":"openai/gpt-6-sol","name":"OpenAI: GPT-6 Sol","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.5","name":"OpenAI: GPT-5.5","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.4-mini","name":"OpenAI: GPT-5.4 Mini","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"google/gemini-3.8-flash","name":"Google: Gemini 3.8 Flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"google/gemini-3.1-pro-preview","name":"Google: Gemini 3.1 Pro Preview","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"deepseek/deepseek-v4-pro","name":"DeepSeek: DeepSeek V4 Pro 0423","contextWindow":1024000,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":"xhigh"},"compat":{"requiresReasoningContentOnAssistantMessages":true}},{"id":"moonshotai/kimi-k3","name":"MoonshotAI: Kimi K3","maxTokens":131072,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"qwen/qwen3.7-max","name":"Qwen: Qwen3.7 Max"},{"id":"z-ai/glm-5.3","name":"Z.ai: GLM 5.3","maxTokens":943718,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"x-ai/grok-4.7","name":"SpaceXAI: Grok 4.7","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}}]}',
18
+ stepfun: '{"version":1,"provider":"stepfun","modelsDev":"stepfun","models":[{"id":"step-5-preview"},{"id":"step-3.7-flash","channels":["messages","chat","messages-intl","chat-intl"]},{"id":"step-3.5-flash","channels":["messages","chat","messages-intl","chat-intl"]}]}',
19
+ tencent: '{"version":1,"provider":"tencent","modelsDev":"tencent-tokenhub","models":[{"id":"hy4-preview","promptCache":{"short":300,"long":3600}},{"id":"hy3","cost":{"input":0.139,"output":0.556,"cacheRead":0.0348,"cacheWrite":0},"_reason":"快照价为 0;官方价格页(2026-10)1 / 4 / 0.25 元每百万 token,按快照同一汇率(约 0.139)折算","promptCache":{"short":300,"long":3600}}]}',
20
+ volcengine: '{"version":1,"provider":"volcengine","modelsDev":"volcengine","models":[{"id":"doubao-seed-2-1-pro-260628"},{"id":"doubao-seed-2-1-turbo-260628"},{"id":"doubao-seed-2-0-code-preview-260215"},{"id":"doubao-seed-2-0-lite-260428"},{"id":"deepseek-v4-pro-ga-260813"},{"id":"glm-5-3-flash-260828"}]}',
21
+ xai: '{"version":1,"provider":"xai","modelsDev":"xai","models":[{"id":"grok-4.7","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.6","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"grok-4.3","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}}]}',
22
+ zhipu: '{"version":1,"provider":"zhipu","modelsDev":"zhipuai","models":[{"id":"glm-5.3","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.3-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.2","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5-turbo","name":"GLM-5-Turbo","contextWindow":200000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsReasoningEffort":false}},{"id":"glm-4.7","compat":{"supportsReasoningEffort":false}}]}',
19
23
  };
@@ -5,17 +5,70 @@
5
5
  * 的字符串表(`UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts` 重新生成,
6
6
  * 测试守住两者一致)。本模块解析并校验它,另提供覆盖合并。
7
7
  *
8
- * 必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——数据源里
9
- * 不确定的就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
8
+ * [W5-M1] 「快照 ⊕ 覆盖」格式(docs/wave5-plan.md §2.2、D6):文件级 `modelsDev` 指向 models.dev
9
+ * 快照里的供应商 id(`false` = 没有对应),条目按 `<modelsDev>/<id>`(或条目自己的 `modelsDev:
10
+ * "provider/model"`)从快照继承数值事实——name、reasoning、contextWindow、maxTokens、input、cost、
11
+ * family / knowledge / releaseDate / inputLimit / status;目录只写覆盖项与 ama 特有字段(`api`、
12
+ * `thinkingLevelMap`、`promptCache`、`compat`、有意调小的 `maxTokens` 等)。`cost` 可只写要覆盖的键。
13
+ * `_reason` 是注释字段(运行时忽略;写了它的条目不做冗余检查,用来有意钉住与快照相同的值)。
14
+ *
15
+ * 合并后的必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——快照与目录
16
+ * 都没有就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
10
17
  * (TTL 秒数与最小可缓存长度)同样只写有公开依据的值(第三波 §1.4),留空 = 不承诺。
11
18
  */
12
- import type { Model, ModelCatalogFile } from "../types.js";
19
+ import type { Api, Model, ModelCatalogFile } from "../types.js";
20
+ import { type ModelsDevIndex } from "./models-dev.js";
13
21
  export type CatalogModel = ModelCatalogFile["models"][number];
14
- /** 校验一个模型条目,返回问题列表(空 = 合法)。 */
22
+ /** 目录文件里的一条(覆盖格式):除 id 外都可省,省掉的从快照继承。 */
23
+ export type CatalogEntry = Partial<Omit<CatalogModel, "cost">> & {
24
+ id: string;
25
+ cost?: Partial<NonNullable<CatalogModel["cost"]>>;
26
+ /** 显式快照条目 `provider/model`;false = 不继承。 */
27
+ modelsDev?: string | false;
28
+ /** 注释:有意保留的覆盖(不做冗余检查)。 */
29
+ _reason?: string;
30
+ /** 模型级协议(OpenAI 推理模型走 responses 等)。 */
31
+ api?: Api;
32
+ };
33
+ /** `catalog/*.json` 的文件形状(覆盖格式)。 */
34
+ export interface CatalogSourceFile {
35
+ version: 1;
36
+ provider: string;
37
+ /** 快照里对应的 models.dev 供应商 id;false = 没有(本地服务)。 */
38
+ modelsDev?: string | false;
39
+ models: CatalogEntry[];
40
+ }
41
+ /** 从快照继承的字段(顺序即冗余检查与来源展示的顺序)。 */
42
+ export declare const INHERITED_FIELDS: readonly ["name", "reasoning", "contextWindow", "maxTokens", "input", "cost", "family", "knowledge", "releaseDate", "inputLimit", "status"];
43
+ /** 校验合并后的模型(必填齐全、cost 四个价都在),返回问题列表(空 = 合法)。 */
15
44
  export declare function checkCatalogModel(value: unknown, path: string): string[];
16
- export declare function parseCatalogFile(value: unknown, source: string): ModelCatalogFile;
17
- /** 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。 */
18
- export declare function loadBuiltinCatalog(): Map<string, CatalogModel[]>;
45
+ /** 校验目录里的一条(覆盖格式:只查写了的字段),返回问题列表(空 = 合法)。 */
46
+ export declare function checkCatalogEntry(value: unknown, path: string): string[];
47
+ /** 一条目录条目对应的快照条目 `provider/model`(没有返回 undefined)。 */
48
+ export declare function snapshotRefOf(file: Pick<CatalogSourceFile, "modelsDev">, entry: Pick<CatalogEntry, "id" | "modelsDev">): string | undefined;
49
+ /** 快照能给这条目录条目的字段(catalog 口径:不封顶、缺缓存价记 0)。 */
50
+ export declare function inheritedFields(file: Pick<CatalogSourceFile, "modelsDev">, entry: Pick<CatalogEntry, "id" | "modelsDev">, index?: ModelsDevIndex): Partial<CatalogModel>;
51
+ /** 合并:快照 ⊕ 目录条目(`cost` 按键合并);返回模型与从快照继承的字段名。 */
52
+ export declare function resolveCatalogEntry(entry: CatalogEntry, inherited: Partial<CatalogModel>): {
53
+ model: CatalogModel;
54
+ inherited: string[];
55
+ };
56
+ /**
57
+ * 与快照取值相同的覆盖项(冗余,测试报错;`UPDATE_CATALOG=1` 时自动删):`name`、`cost.input` 一类路径。
58
+ * 写了 `_reason` 的条目不查。
59
+ */
60
+ export declare function redundantFields(entry: CatalogEntry, inherited: Partial<CatalogModel>): string[];
61
+ /** 校验文件形状(覆盖格式),不合并。 */
62
+ export declare function parseCatalogSource(value: unknown, source: string): CatalogSourceFile;
63
+ /** 校验并合并(快照 ⊕ 目录)一个目录文件;`index` 缺省用内置快照。 */
64
+ export declare function parseCatalogFile(value: unknown, source: string, index?: ModelsDevIndex): ModelCatalogFile;
65
+ /**
66
+ * 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。`index` 缺省用内置快照;传入
67
+ * 「快照 ⊕ 用户刷新」的索引时目录也吃刷新后的数值(缺字段的条目退回内置快照)。
68
+ */
69
+ export declare function loadBuiltinCatalog(index?: ModelsDevIndex): Map<string, CatalogModel[]>;
70
+ /** 最近一次 `loadBuiltinCatalog()` 里,该目录模型从快照继承的字段(来源展示用)。 */
71
+ export declare function catalogInherited(provider: string, modelId: string): readonly string[];
19
72
  /** 目录条目 → Model(补 provider / api 与缺省 input)。 */
20
73
  export declare function toModel(entry: CatalogModel, provider: string, api: Model["api"]): Model;
21
74
  /** 自定义模型缺省:maxTokens 8192、reasoning false、input ["text"]、name = id;不猜 contextWindow。 */
@@ -5,31 +5,81 @@
5
5
  * 的字符串表(`UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts` 重新生成,
6
6
  * 测试守住两者一致)。本模块解析并校验它,另提供覆盖合并。
7
7
  *
8
- * 必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——数据源里
9
- * 不确定的就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
8
+ * [W5-M1] 「快照 ⊕ 覆盖」格式(docs/wave5-plan.md §2.2、D6):文件级 `modelsDev` 指向 models.dev
9
+ * 快照里的供应商 id(`false` = 没有对应),条目按 `<modelsDev>/<id>`(或条目自己的 `modelsDev:
10
+ * "provider/model"`)从快照继承数值事实——name、reasoning、contextWindow、maxTokens、input、cost、
11
+ * family / knowledge / releaseDate / inputLimit / status;目录只写覆盖项与 ama 特有字段(`api`、
12
+ * `thinkingLevelMap`、`promptCache`、`compat`、有意调小的 `maxTokens` 等)。`cost` 可只写要覆盖的键。
13
+ * `_reason` 是注释字段(运行时忽略;写了它的条目不做冗余检查,用来有意钉住与快照相同的值)。
14
+ *
15
+ * 合并后的必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——快照与目录
16
+ * 都没有就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
10
17
  * (TTL 秒数与最小可缓存长度)同样只写有公开依据的值(第三波 §1.4),留空 = 不承诺。
11
18
  */
19
+ import { isDeepStrictEqual } from "node:util";
12
20
  import { AmaError } from "../../errors.js";
13
21
  import { CATALOG_SOURCES } from "./catalog-data.js";
14
22
  import { THINKING_LEVELS } from "../thinking.js";
23
+ import { modelsDevFields } from "./models-dev.js";
24
+ import { builtinSnapshotIndex } from "./models-dev-snapshot.js";
25
+ /** 从快照继承的字段(顺序即冗余检查与来源展示的顺序)。 */
26
+ export const INHERITED_FIELDS = [
27
+ "name",
28
+ "reasoning",
29
+ "contextWindow",
30
+ "maxTokens",
31
+ "input",
32
+ "cost",
33
+ "family",
34
+ "knowledge",
35
+ "releaseDate",
36
+ "inputLimit",
37
+ "status",
38
+ ];
15
39
  function isRecord(value) {
16
40
  return typeof value === "object" && value !== null && !Array.isArray(value);
17
41
  }
18
42
  function isNonNegative(value) {
19
43
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
20
44
  }
21
- /** 校验一个模型条目,返回问题列表(空 = 合法)。 */
45
+ /** 校验合并后的模型(必填齐全、cost 四个价都在),返回问题列表(空 = 合法)。 */
22
46
  export function checkCatalogModel(value, path) {
47
+ if (!isRecord(value))
48
+ return [`${path}: must be an object`];
49
+ const problems = [];
50
+ if (typeof value["name"] !== "string")
51
+ problems.push(`${path}.name`);
52
+ if (typeof value["reasoning"] !== "boolean")
53
+ problems.push(`${path}.reasoning`);
54
+ if (value["maxTokens"] === undefined)
55
+ problems.push(`${path}.maxTokens`);
56
+ const cost = value["cost"];
57
+ if (isRecord(cost)) {
58
+ for (const key of ["input", "output", "cacheRead", "cacheWrite"]) {
59
+ if (cost[key] === undefined)
60
+ problems.push(`${path}.cost.${key}`);
61
+ }
62
+ }
63
+ return [...new Set([...problems, ...checkCatalogEntry(value, path)])];
64
+ }
65
+ /** 校验目录里的一条(覆盖格式:只查写了的字段),返回问题列表(空 = 合法)。 */
66
+ export function checkCatalogEntry(value, path) {
23
67
  const problems = [];
24
68
  if (!isRecord(value))
25
69
  return [`${path}: must be an object`];
26
70
  if (typeof value["id"] !== "string" || value["id"].length === 0)
27
71
  problems.push(`${path}.id`);
28
- if (typeof value["name"] !== "string")
72
+ if (value["name"] !== undefined && typeof value["name"] !== "string")
29
73
  problems.push(`${path}.name`);
30
- if (typeof value["reasoning"] !== "boolean")
74
+ if (value["reasoning"] !== undefined && typeof value["reasoning"] !== "boolean")
31
75
  problems.push(`${path}.reasoning`);
32
- if (!isNonNegative(value["maxTokens"]) || value["maxTokens"] === 0) {
76
+ const modelsDev = value["modelsDev"];
77
+ if (modelsDev !== undefined && modelsDev !== false && typeof modelsDev !== "string")
78
+ problems.push(`${path}.modelsDev`);
79
+ if (value["_reason"] !== undefined && typeof value["_reason"] !== "string")
80
+ problems.push(`${path}._reason`);
81
+ if (value["maxTokens"] !== undefined &&
82
+ (!isNonNegative(value["maxTokens"]) || value["maxTokens"] === 0)) {
33
83
  problems.push(`${path}.maxTokens`);
34
84
  }
35
85
  if (value["contextWindow"] !== undefined && !isNonNegative(value["contextWindow"])) {
@@ -46,7 +96,7 @@ export function checkCatalogModel(value, path) {
46
96
  problems.push(`${path}.cost`);
47
97
  else {
48
98
  for (const key of ["input", "output", "cacheRead", "cacheWrite"]) {
49
- if (!isNonNegative(cost[key]))
99
+ if (cost[key] !== undefined && !isNonNegative(cost[key]))
50
100
  problems.push(`${path}.cost.${key}`);
51
101
  }
52
102
  if (cost["tiers"] !== undefined && !Array.isArray(cost["tiers"])) {
@@ -86,50 +136,159 @@ export function checkCatalogModel(value, path) {
86
136
  }
87
137
  return problems;
88
138
  }
89
- export function parseCatalogFile(value, source) {
139
+ /** 一条目录条目对应的快照条目 `provider/model`(没有返回 undefined)。 */
140
+ export function snapshotRefOf(file, entry) {
141
+ if (entry.modelsDev === false)
142
+ return undefined;
143
+ if (typeof entry.modelsDev === "string")
144
+ return entry.modelsDev;
145
+ return typeof file.modelsDev === "string" ? `${file.modelsDev}/${entry.id}` : undefined;
146
+ }
147
+ /** 快照能给这条目录条目的字段(catalog 口径:不封顶、缺缓存价记 0)。 */
148
+ export function inheritedFields(file, entry, index = builtinSnapshotIndex()) {
149
+ const ref = snapshotRefOf(file, entry);
150
+ const model = ref !== undefined ? index.get(ref) : undefined;
151
+ if (model === undefined)
152
+ return {};
153
+ const fields = modelsDevFields(model, "catalog");
154
+ const out = {};
155
+ for (const key of INHERITED_FIELDS) {
156
+ if (fields[key] !== undefined)
157
+ out[key] = fields[key];
158
+ }
159
+ return out;
160
+ }
161
+ /** 合并:快照 ⊕ 目录条目(`cost` 按键合并);返回模型与从快照继承的字段名。 */
162
+ export function resolveCatalogEntry(entry, inherited) {
163
+ const { modelsDev: _modelsDev, _reason: _r, ...own } = structuredClone(entry);
164
+ const model = { ...structuredClone(inherited), ...own };
165
+ if (own.cost !== undefined && inherited.cost !== undefined)
166
+ model.cost = { ...structuredClone(inherited.cost), ...own.cost };
167
+ // 目录有意把窗口调小(如 272k 计价档)时,继承来的更大的输入上限没有意义
168
+ if (own.inputLimit === undefined &&
169
+ model.inputLimit !== undefined &&
170
+ model.contextWindow !== undefined &&
171
+ model.inputLimit >= model.contextWindow)
172
+ delete model.inputLimit;
173
+ const from = INHERITED_FIELDS.filter((k) => own[k] === undefined && model[k] !== undefined);
174
+ return { model, inherited: from };
175
+ }
176
+ /**
177
+ * 与快照取值相同的覆盖项(冗余,测试报错;`UPDATE_CATALOG=1` 时自动删):`name`、`cost.input` 一类路径。
178
+ * 写了 `_reason` 的条目不查。
179
+ */
180
+ export function redundantFields(entry, inherited) {
181
+ if (entry._reason !== undefined)
182
+ return [];
183
+ const out = [];
184
+ for (const key of INHERITED_FIELDS) {
185
+ const own = entry[key];
186
+ const base = inherited[key];
187
+ if (own === undefined || base === undefined)
188
+ continue;
189
+ if (key === "cost" && isRecord(own) && isRecord(base)) {
190
+ for (const [k, v] of Object.entries(own))
191
+ if (isDeepStrictEqual(v, base[k]))
192
+ out.push(`cost.${k}`);
193
+ }
194
+ else if (isDeepStrictEqual(own, base))
195
+ out.push(key);
196
+ }
197
+ return out;
198
+ }
199
+ function fileProblems(value) {
90
200
  const problems = [];
91
201
  if (!isRecord(value))
92
- problems.push("$: must be an object");
202
+ return ["$: must be an object"];
203
+ if (value["version"] !== 1)
204
+ problems.push("$.version must be 1");
205
+ if (typeof value["provider"] !== "string")
206
+ problems.push("$.provider");
207
+ const modelsDev = value["modelsDev"];
208
+ if (modelsDev !== undefined && modelsDev !== false && typeof modelsDev !== "string")
209
+ problems.push("$.modelsDev");
210
+ if (!Array.isArray(value["models"]))
211
+ problems.push("$.models must be an array");
93
212
  else {
94
- if (value["version"] !== 1)
95
- problems.push("$.version must be 1");
96
- if (typeof value["provider"] !== "string")
97
- problems.push("$.provider");
98
- if (!Array.isArray(value["models"]))
99
- problems.push("$.models must be an array");
100
- else {
101
- const seen = new Set();
102
- value["models"].forEach((model, i) => {
103
- problems.push(...checkCatalogModel(model, `$.models[${i}]`));
104
- const id = isRecord(model) ? model["id"] : undefined;
105
- if (typeof id === "string") {
106
- if (seen.has(id))
107
- problems.push(`$.models[${i}].id duplicated: ${id}`);
108
- seen.add(id);
109
- }
110
- });
111
- }
112
- }
113
- if (problems.length > 0) {
114
- throw new AmaError("config_invalid", `model catalog ${source} is invalid: ${problems.join(", ")}`);
213
+ const seen = new Set();
214
+ value["models"].forEach((model, i) => {
215
+ problems.push(...checkCatalogEntry(model, `$.models[${i}]`));
216
+ const id = isRecord(model) ? model["id"] : undefined;
217
+ if (typeof id === "string") {
218
+ if (seen.has(id))
219
+ problems.push(`$.models[${i}].id duplicated: ${id}`);
220
+ seen.add(id);
221
+ }
222
+ });
115
223
  }
224
+ return problems;
225
+ }
226
+ function invalid(source, problems) {
227
+ return new AmaError("config_invalid", `model catalog ${source} is invalid: ${problems.join(", ")}`);
228
+ }
229
+ /** 校验文件形状(覆盖格式),不合并。 */
230
+ export function parseCatalogSource(value, source) {
231
+ const problems = fileProblems(value);
232
+ if (problems.length > 0)
233
+ throw invalid(source, problems);
116
234
  return value;
117
235
  }
118
- let cache;
119
- /** 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。 */
120
- export function loadBuiltinCatalog() {
121
- if (!cache) {
236
+ function resolveFile(file, source, index) {
237
+ const problems = [];
238
+ const inherited = new Map();
239
+ const builtin = builtinSnapshotIndex();
240
+ const models = file.models.map((entry, i) => {
241
+ const path = `$.models[${i}]`;
242
+ let resolved = resolveCatalogEntry(entry, inheritedFields(file, entry, index ?? builtin));
243
+ let found = checkCatalogModel(resolved.model, path);
244
+ if (found.length > 0 && index !== undefined && index !== builtin) {
245
+ // 用户刷新的数据缺字段(上游改版):这一条退回内置快照,不让启动失败。
246
+ resolved = resolveCatalogEntry(entry, inheritedFields(file, entry, builtin));
247
+ found = checkCatalogModel(resolved.model, path);
248
+ }
249
+ problems.push(...found);
250
+ inherited.set(entry.id, resolved.inherited);
251
+ return resolved.model;
252
+ });
253
+ if (problems.length > 0)
254
+ throw invalid(source, problems);
255
+ return { file: { version: 1, provider: file.provider, models }, inherited };
256
+ }
257
+ /** 校验并合并(快照 ⊕ 目录)一个目录文件;`index` 缺省用内置快照。 */
258
+ export function parseCatalogFile(value, source, index) {
259
+ return resolveFile(parseCatalogSource(value, source), source, index).file;
260
+ }
261
+ const caches = new WeakMap();
262
+ let lastInherited = new Map();
263
+ /**
264
+ * 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。`index` 缺省用内置快照;传入
265
+ * 「快照 ⊕ 用户刷新」的索引时目录也吃刷新后的数值(缺字段的条目退回内置快照)。
266
+ */
267
+ export function loadBuiltinCatalog(index) {
268
+ const key = index ?? builtinSnapshotIndex();
269
+ let cache = caches.get(key);
270
+ if (cache === undefined) {
122
271
  cache = new Map();
123
272
  for (const [provider, raw] of Object.entries(CATALOG_SOURCES)) {
124
- const file = parseCatalogFile(JSON.parse(raw), `catalog/${provider}.json`);
125
- cache.set(file.provider, file.models);
273
+ const source = `catalog/${provider}.json`;
274
+ const resolved = resolveFile(parseCatalogSource(JSON.parse(raw), source), source, index);
275
+ cache.set(resolved.file.provider, resolved);
126
276
  }
277
+ caches.set(key, cache);
127
278
  }
128
279
  const copy = new Map();
129
- for (const [provider, models] of cache)
130
- copy.set(provider, structuredClone(models));
280
+ lastInherited = new Map();
281
+ for (const [provider, resolved] of cache) {
282
+ copy.set(provider, structuredClone(resolved.file.models));
283
+ for (const [id, fields] of resolved.inherited)
284
+ lastInherited.set(`${provider}/${id}`, fields);
285
+ }
131
286
  return copy;
132
287
  }
288
+ /** 最近一次 `loadBuiltinCatalog()` 里,该目录模型从快照继承的字段(来源展示用)。 */
289
+ export function catalogInherited(provider, modelId) {
290
+ return lastInherited.get(`${provider}/${modelId}`) ?? [];
291
+ }
133
292
  /** 目录条目 → Model(补 provider / api 与缺省 input)。 */
134
293
  export function toModel(entry, provider, api) {
135
294
  return { ...structuredClone(entry), input: entry.input ?? ["text"], provider, api };