@armadra/agent 0.0.0-stage → 0.2.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 (407) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +426 -2
  4. package/dist/agent/agent.d.ts +56 -0
  5. package/dist/agent/agent.js +129 -0
  6. package/dist/agent/loop.d.ts +51 -0
  7. package/dist/agent/loop.js +158 -0
  8. package/dist/agent/queue.d.ts +25 -0
  9. package/dist/agent/queue.js +55 -0
  10. package/dist/agent/retry.d.ts +22 -0
  11. package/dist/agent/retry.js +92 -0
  12. package/dist/agent/schema.d.ts +27 -0
  13. package/dist/agent/schema.js +186 -0
  14. package/dist/agent/session-cache.d.ts +100 -0
  15. package/dist/agent/session-cache.js +511 -0
  16. package/dist/agent/session-compaction.d.ts +49 -0
  17. package/dist/agent/session-compaction.js +251 -0
  18. package/dist/agent/session-core.d.ts +103 -0
  19. package/dist/agent/session-core.js +7 -0
  20. package/dist/agent/session-run.d.ts +55 -0
  21. package/dist/agent/session-run.js +246 -0
  22. package/dist/agent/session-state.d.ts +39 -0
  23. package/dist/agent/session-state.js +118 -0
  24. package/dist/agent/session-subagent.d.ts +54 -0
  25. package/dist/agent/session-subagent.js +157 -0
  26. package/dist/agent/session-sync.d.ts +20 -0
  27. package/dist/agent/session-sync.js +104 -0
  28. package/dist/agent/session-tools.d.ts +24 -0
  29. package/dist/agent/session-tools.js +277 -0
  30. package/dist/agent/session.d.ts +117 -0
  31. package/dist/agent/session.js +484 -0
  32. package/dist/agent/system-prompt.d.ts +49 -0
  33. package/dist/agent/system-prompt.js +121 -0
  34. package/dist/agent/tool-runner.d.ts +64 -0
  35. package/dist/agent/tool-runner.js +309 -0
  36. package/dist/agent/transform.d.ts +26 -0
  37. package/dist/agent/transform.js +171 -0
  38. package/dist/agent/types.d.ts +378 -0
  39. package/dist/agent/types.js +21 -0
  40. package/dist/ai/apis/anthropic-messages.d.ts +26 -0
  41. package/dist/ai/apis/anthropic-messages.js +214 -0
  42. package/dist/ai/apis/anthropic-request.d.ts +42 -0
  43. package/dist/ai/apis/anthropic-request.js +282 -0
  44. package/dist/ai/apis/api.d.ts +28 -0
  45. package/dist/ai/apis/api.js +102 -0
  46. package/dist/ai/apis/cache-params.d.ts +48 -0
  47. package/dist/ai/apis/cache-params.js +163 -0
  48. package/dist/ai/apis/google-generative-ai.d.ts +32 -0
  49. package/dist/ai/apis/google-generative-ai.js +249 -0
  50. package/dist/ai/apis/google-request.d.ts +40 -0
  51. package/dist/ai/apis/google-request.js +255 -0
  52. package/dist/ai/apis/openai-compat.d.ts +35 -0
  53. package/dist/ai/apis/openai-compat.js +142 -0
  54. package/dist/ai/apis/openai-completions.d.ts +28 -0
  55. package/dist/ai/apis/openai-completions.js +246 -0
  56. package/dist/ai/apis/openai-request.d.ts +35 -0
  57. package/dist/ai/apis/openai-request.js +303 -0
  58. package/dist/ai/apis/openai-responses-request.d.ts +52 -0
  59. package/dist/ai/apis/openai-responses-request.js +266 -0
  60. package/dist/ai/apis/openai-responses.d.ts +28 -0
  61. package/dist/ai/apis/openai-responses.js +303 -0
  62. package/dist/ai/apis/shared.d.ts +56 -0
  63. package/dist/ai/apis/shared.js +179 -0
  64. package/dist/ai/cache/economics.d.ts +24 -0
  65. package/dist/ai/cache/economics.js +69 -0
  66. package/dist/ai/cache/fingerprint.d.ts +17 -0
  67. package/dist/ai/cache/fingerprint.js +39 -0
  68. package/dist/ai/cache/miss.d.ts +49 -0
  69. package/dist/ai/cache/miss.js +96 -0
  70. package/dist/ai/cache/reporting.d.ts +39 -0
  71. package/dist/ai/cache/reporting.js +102 -0
  72. package/dist/ai/cache/types.d.ts +94 -0
  73. package/dist/ai/cache/types.js +19 -0
  74. package/dist/ai/cache/warmer.d.ts +94 -0
  75. package/dist/ai/cache/warmer.js +224 -0
  76. package/dist/ai/context.d.ts +35 -0
  77. package/dist/ai/context.js +114 -0
  78. package/dist/ai/cost.d.ts +21 -0
  79. package/dist/ai/cost.js +60 -0
  80. package/dist/ai/event-stream.d.ts +33 -0
  81. package/dist/ai/event-stream.js +101 -0
  82. package/dist/ai/fake/fake-provider.d.ts +68 -0
  83. package/dist/ai/fake/fake-provider.js +278 -0
  84. package/dist/ai/fake/fake-script.d.ts +69 -0
  85. package/dist/ai/fake/fake-script.js +142 -0
  86. package/dist/ai/http.d.ts +54 -0
  87. package/dist/ai/http.js +212 -0
  88. package/dist/ai/json-partial.d.ts +17 -0
  89. package/dist/ai/json-partial.js +243 -0
  90. package/dist/ai/overflow.d.ts +22 -0
  91. package/dist/ai/overflow.js +61 -0
  92. package/dist/ai/providers/auth.d.ts +71 -0
  93. package/dist/ai/providers/auth.js +202 -0
  94. package/dist/ai/providers/builtin.d.ts +23 -0
  95. package/dist/ai/providers/builtin.js +148 -0
  96. package/dist/ai/providers/catalog-data.d.ts +5 -0
  97. package/dist/ai/providers/catalog-data.js +19 -0
  98. package/dist/ai/providers/catalog.d.ts +28 -0
  99. package/dist/ai/providers/catalog.js +166 -0
  100. package/dist/ai/providers/registry.d.ts +83 -0
  101. package/dist/ai/providers/registry.js +305 -0
  102. package/dist/ai/sse.d.ts +32 -0
  103. package/dist/ai/sse.js +140 -0
  104. package/dist/ai/thinking.d.ts +42 -0
  105. package/dist/ai/thinking.js +101 -0
  106. package/dist/ai/types.d.ts +428 -0
  107. package/dist/ai/types.js +19 -0
  108. package/dist/bundle/ama-sandbox.cjs +324 -0
  109. package/dist/bundle/ama.cjs +25770 -0
  110. package/dist/bundle.d.ts +9 -0
  111. package/dist/bundle.js +15 -0
  112. package/dist/cli/args.d.ts +82 -0
  113. package/dist/cli/args.js +381 -0
  114. package/dist/cli/bootstrap.d.ts +18 -0
  115. package/dist/cli/bootstrap.js +398 -0
  116. package/dist/cli/compose-providers.d.ts +37 -0
  117. package/dist/cli/compose-providers.js +104 -0
  118. package/dist/cli/compose-session.d.ts +69 -0
  119. package/dist/cli/compose-session.js +370 -0
  120. package/dist/cli/compose-store.d.ts +24 -0
  121. package/dist/cli/compose-store.js +125 -0
  122. package/dist/cli/compose.d.ts +106 -0
  123. package/dist/cli/compose.js +206 -0
  124. package/dist/cli/default-model.d.ts +16 -0
  125. package/dist/cli/default-model.js +24 -0
  126. package/dist/cli/deps.d.ts +205 -0
  127. package/dist/cli/deps.js +12 -0
  128. package/dist/cli/exit-codes.d.ts +29 -0
  129. package/dist/cli/exit-codes.js +40 -0
  130. package/dist/cli/main.d.ts +26 -0
  131. package/dist/cli/main.js +165 -0
  132. package/dist/cli/runtime.d.ts +90 -0
  133. package/dist/cli/runtime.js +8 -0
  134. package/dist/cli/startup-screen.d.ts +15 -0
  135. package/dist/cli/startup-screen.js +56 -0
  136. package/dist/cli/startup-steps.d.ts +35 -0
  137. package/dist/cli/startup-steps.js +197 -0
  138. package/dist/cli/subcommands/auth.d.ts +12 -0
  139. package/dist/cli/subcommands/auth.js +91 -0
  140. package/dist/cli/subcommands/config.d.ts +44 -0
  141. package/dist/cli/subcommands/config.js +201 -0
  142. package/dist/cli/subcommands/context.d.ts +21 -0
  143. package/dist/cli/subcommands/context.js +41 -0
  144. package/dist/cli/subcommands/doctor.d.ts +11 -0
  145. package/dist/cli/subcommands/doctor.js +246 -0
  146. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  147. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  148. package/dist/cli/subcommands/models-discover.d.ts +40 -0
  149. package/dist/cli/subcommands/models-discover.js +204 -0
  150. package/dist/cli/subcommands/models.d.ts +40 -0
  151. package/dist/cli/subcommands/models.js +144 -0
  152. package/dist/cli/subcommands/sessions.d.ts +11 -0
  153. package/dist/cli/subcommands/sessions.js +100 -0
  154. package/dist/codemode/capability.d.ts +37 -0
  155. package/dist/codemode/capability.js +55 -0
  156. package/dist/codemode/declarations.d.ts +44 -0
  157. package/dist/codemode/declarations.js +111 -0
  158. package/dist/codemode/host-side.d.ts +59 -0
  159. package/dist/codemode/host-side.js +253 -0
  160. package/dist/codemode/modes.d.ts +23 -0
  161. package/dist/codemode/modes.js +40 -0
  162. package/dist/codemode/protocol.d.ts +91 -0
  163. package/dist/codemode/protocol.js +114 -0
  164. package/dist/codemode/sandbox-entry.d.ts +25 -0
  165. package/dist/codemode/sandbox-entry.js +323 -0
  166. package/dist/codemode/store.d.ts +26 -0
  167. package/dist/codemode/store.js +53 -0
  168. package/dist/codemode/tool.d.ts +105 -0
  169. package/dist/codemode/tool.js +283 -0
  170. package/dist/compaction/branch-summary.d.ts +30 -0
  171. package/dist/compaction/branch-summary.js +79 -0
  172. package/dist/compaction/breaker.d.ts +32 -0
  173. package/dist/compaction/breaker.js +65 -0
  174. package/dist/compaction/cut-point.d.ts +23 -0
  175. package/dist/compaction/cut-point.js +70 -0
  176. package/dist/compaction/estimate.d.ts +30 -0
  177. package/dist/compaction/estimate.js +114 -0
  178. package/dist/compaction/prune-tier.d.ts +31 -0
  179. package/dist/compaction/prune-tier.js +83 -0
  180. package/dist/compaction/serialize.d.ts +20 -0
  181. package/dist/compaction/serialize.js +115 -0
  182. package/dist/compaction/summarize-tier.d.ts +111 -0
  183. package/dist/compaction/summarize-tier.js +305 -0
  184. package/dist/config/auth-file.d.ts +39 -0
  185. package/dist/config/auth-file.js +92 -0
  186. package/dist/config/context-files.d.ts +30 -0
  187. package/dist/config/context-files.js +77 -0
  188. package/dist/config/load.d.ts +45 -0
  189. package/dist/config/load.js +97 -0
  190. package/dist/config/merge.d.ts +73 -0
  191. package/dist/config/merge.js +248 -0
  192. package/dist/config/paths.d.ts +38 -0
  193. package/dist/config/paths.js +108 -0
  194. package/dist/config/profile.d.ts +27 -0
  195. package/dist/config/profile.js +65 -0
  196. package/dist/config/schema.d.ts +34 -0
  197. package/dist/config/schema.js +413 -0
  198. package/dist/config/trust.d.ts +42 -0
  199. package/dist/config/trust.js +122 -0
  200. package/dist/config/types.d.ts +172 -0
  201. package/dist/config/types.js +27 -0
  202. package/dist/config/write.d.ts +10 -0
  203. package/dist/config/write.js +25 -0
  204. package/dist/errors.d.ts +28 -0
  205. package/dist/errors.js +30 -0
  206. package/dist/hooks/config.d.ts +49 -0
  207. package/dist/hooks/config.js +102 -0
  208. package/dist/hooks/dispatcher.d.ts +41 -0
  209. package/dist/hooks/dispatcher.js +104 -0
  210. package/dist/hooks/matcher.d.ts +22 -0
  211. package/dist/hooks/matcher.js +108 -0
  212. package/dist/hooks/protocol.d.ts +33 -0
  213. package/dist/hooks/protocol.js +240 -0
  214. package/dist/hooks/runner.d.ts +30 -0
  215. package/dist/hooks/runner.js +143 -0
  216. package/dist/hooks/types.d.ts +147 -0
  217. package/dist/hooks/types.js +20 -0
  218. package/dist/host/api-impl.d.ts +75 -0
  219. package/dist/host/api-impl.js +173 -0
  220. package/dist/host/loader.d.ts +31 -0
  221. package/dist/host/loader.js +147 -0
  222. package/dist/host/types.d.ts +169 -0
  223. package/dist/host/types.js +14 -0
  224. package/dist/host.d.ts +5 -0
  225. package/dist/host.js +4 -0
  226. package/dist/index.d.ts +41 -0
  227. package/dist/index.js +28 -0
  228. package/dist/modes/commands-core.d.ts +44 -0
  229. package/dist/modes/commands-core.js +171 -0
  230. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  231. package/dist/modes/interactive/approval-dialog.js +202 -0
  232. package/dist/modes/interactive/commands.d.ts +41 -0
  233. package/dist/modes/interactive/commands.js +202 -0
  234. package/dist/modes/interactive/completion.d.ts +53 -0
  235. package/dist/modes/interactive/completion.js +157 -0
  236. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  237. package/dist/modes/interactive/interactive-mode.js +487 -0
  238. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  239. package/dist/modes/interactive/key-dispatch.js +107 -0
  240. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  241. package/dist/modes/interactive/line/line-editor.js +232 -0
  242. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  243. package/dist/modes/interactive/line/line-mode.js +216 -0
  244. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  245. package/dist/modes/interactive/line/line-render.js +171 -0
  246. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  247. package/dist/modes/interactive/line/paste-state.js +72 -0
  248. package/dist/modes/interactive/message-view.d.ts +77 -0
  249. package/dist/modes/interactive/message-view.js +269 -0
  250. package/dist/modes/interactive/pickers.d.ts +42 -0
  251. package/dist/modes/interactive/pickers.js +115 -0
  252. package/dist/modes/interactive/startup-ui.d.ts +28 -0
  253. package/dist/modes/interactive/startup-ui.js +238 -0
  254. package/dist/modes/interactive/status-bar.d.ts +48 -0
  255. package/dist/modes/interactive/status-bar.js +139 -0
  256. package/dist/modes/interactive/tool-view.d.ts +95 -0
  257. package/dist/modes/interactive/tool-view.js +344 -0
  258. package/dist/modes/print/json-event.d.ts +15 -0
  259. package/dist/modes/print/json-event.js +39 -0
  260. package/dist/modes/print/print-mode.d.ts +15 -0
  261. package/dist/modes/print/print-mode.js +96 -0
  262. package/dist/modes/rpc/commands.d.ts +40 -0
  263. package/dist/modes/rpc/commands.js +258 -0
  264. package/dist/modes/rpc/jsonl.d.ts +16 -0
  265. package/dist/modes/rpc/jsonl.js +55 -0
  266. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  267. package/dist/modes/rpc/rpc-mode.js +153 -0
  268. package/dist/modes/session-report.d.ts +55 -0
  269. package/dist/modes/session-report.js +278 -0
  270. package/dist/modes/shared.d.ts +13 -0
  271. package/dist/modes/shared.js +52 -0
  272. package/dist/modes/startup-ui-text.d.ts +16 -0
  273. package/dist/modes/startup-ui-text.js +103 -0
  274. package/dist/permissions/broker.d.ts +47 -0
  275. package/dist/permissions/broker.js +107 -0
  276. package/dist/permissions/dangerous.d.ts +47 -0
  277. package/dist/permissions/dangerous.js +370 -0
  278. package/dist/permissions/pipeline.d.ts +51 -0
  279. package/dist/permissions/pipeline.js +181 -0
  280. package/dist/permissions/preview.d.ts +43 -0
  281. package/dist/permissions/preview.js +463 -0
  282. package/dist/permissions/rules.d.ts +58 -0
  283. package/dist/permissions/rules.js +249 -0
  284. package/dist/permissions/types.d.ts +100 -0
  285. package/dist/permissions/types.js +18 -0
  286. package/dist/rpc.d.ts +171 -0
  287. package/dist/rpc.js +13 -0
  288. package/dist/sdk.d.ts +98 -0
  289. package/dist/sdk.js +195 -0
  290. package/dist/session/manager.d.ts +70 -0
  291. package/dist/session/manager.js +278 -0
  292. package/dist/session/migrate.d.ts +19 -0
  293. package/dist/session/migrate.js +53 -0
  294. package/dist/session/projection.d.ts +50 -0
  295. package/dist/session/projection.js +180 -0
  296. package/dist/session/store.d.ts +47 -0
  297. package/dist/session/store.js +210 -0
  298. package/dist/session/tree.d.ts +21 -0
  299. package/dist/session/tree.js +88 -0
  300. package/dist/session/types.d.ts +199 -0
  301. package/dist/session/types.js +18 -0
  302. package/dist/skills/discover.d.ts +60 -0
  303. package/dist/skills/discover.js +160 -0
  304. package/dist/skills/expand.d.ts +35 -0
  305. package/dist/skills/expand.js +46 -0
  306. package/dist/skills/frontmatter.d.ts +27 -0
  307. package/dist/skills/frontmatter.js +157 -0
  308. package/dist/skills/index-prompt.d.ts +13 -0
  309. package/dist/skills/index-prompt.js +42 -0
  310. package/dist/skills/templates.d.ts +52 -0
  311. package/dist/skills/templates.js +177 -0
  312. package/dist/tools/bash.d.ts +49 -0
  313. package/dist/tools/bash.js +222 -0
  314. package/dist/tools/edit-fuzzy.d.ts +36 -0
  315. package/dist/tools/edit-fuzzy.js +129 -0
  316. package/dist/tools/edit.d.ts +38 -0
  317. package/dist/tools/edit.js +241 -0
  318. package/dist/tools/file-mutex.d.ts +8 -0
  319. package/dist/tools/file-mutex.js +29 -0
  320. package/dist/tools/glob.d.ts +44 -0
  321. package/dist/tools/glob.js +217 -0
  322. package/dist/tools/grep.d.ts +39 -0
  323. package/dist/tools/grep.js +179 -0
  324. package/dist/tools/ignore.d.ts +40 -0
  325. package/dist/tools/ignore.js +174 -0
  326. package/dist/tools/ls.d.ts +21 -0
  327. package/dist/tools/ls.js +96 -0
  328. package/dist/tools/output-accumulator.d.ts +48 -0
  329. package/dist/tools/output-accumulator.js +106 -0
  330. package/dist/tools/paths.d.ts +20 -0
  331. package/dist/tools/paths.js +58 -0
  332. package/dist/tools/presets.d.ts +71 -0
  333. package/dist/tools/presets.js +128 -0
  334. package/dist/tools/process-tree.d.ts +35 -0
  335. package/dist/tools/process-tree.js +125 -0
  336. package/dist/tools/read.d.ts +28 -0
  337. package/dist/tools/read.js +181 -0
  338. package/dist/tools/registry.d.ts +43 -0
  339. package/dist/tools/registry.js +106 -0
  340. package/dist/tools/shell.d.ts +38 -0
  341. package/dist/tools/shell.js +91 -0
  342. package/dist/tools/task.d.ts +29 -0
  343. package/dist/tools/task.js +107 -0
  344. package/dist/tools/todo.d.ts +28 -0
  345. package/dist/tools/todo.js +107 -0
  346. package/dist/tools/truncate.d.ts +44 -0
  347. package/dist/tools/truncate.js +175 -0
  348. package/dist/tools/types.d.ts +135 -0
  349. package/dist/tools/types.js +19 -0
  350. package/dist/tools/write.d.ts +20 -0
  351. package/dist/tools/write.js +84 -0
  352. package/dist/tui/ansi.d.ts +29 -0
  353. package/dist/tui/ansi.js +420 -0
  354. package/dist/tui/component.d.ts +38 -0
  355. package/dist/tui/component.js +13 -0
  356. package/dist/tui/components/box.d.ts +26 -0
  357. package/dist/tui/components/box.js +65 -0
  358. package/dist/tui/components/container.d.ts +14 -0
  359. package/dist/tui/components/container.js +39 -0
  360. package/dist/tui/components/editor-buffer.d.ts +67 -0
  361. package/dist/tui/components/editor-buffer.js +300 -0
  362. package/dist/tui/components/editor-paste.d.ts +29 -0
  363. package/dist/tui/components/editor-paste.js +64 -0
  364. package/dist/tui/components/editor.d.ts +114 -0
  365. package/dist/tui/components/editor.js +530 -0
  366. package/dist/tui/components/key-value.d.ts +29 -0
  367. package/dist/tui/components/key-value.js +48 -0
  368. package/dist/tui/components/loader.d.ts +35 -0
  369. package/dist/tui/components/loader.js +71 -0
  370. package/dist/tui/components/markdown.d.ts +90 -0
  371. package/dist/tui/components/markdown.js +462 -0
  372. package/dist/tui/components/meter.d.ts +29 -0
  373. package/dist/tui/components/meter.js +47 -0
  374. package/dist/tui/components/overlay.d.ts +24 -0
  375. package/dist/tui/components/overlay.js +52 -0
  376. package/dist/tui/components/select-list.d.ts +57 -0
  377. package/dist/tui/components/select-list.js +179 -0
  378. package/dist/tui/components/spacer.d.ts +11 -0
  379. package/dist/tui/components/spacer.js +16 -0
  380. package/dist/tui/components/text.d.ts +30 -0
  381. package/dist/tui/components/text.js +65 -0
  382. package/dist/tui/keybindings.d.ts +66 -0
  383. package/dist/tui/keybindings.js +120 -0
  384. package/dist/tui/keys.d.ts +38 -0
  385. package/dist/tui/keys.js +275 -0
  386. package/dist/tui/stdin-buffer.d.ts +41 -0
  387. package/dist/tui/stdin-buffer.js +206 -0
  388. package/dist/tui/terminal.d.ts +79 -0
  389. package/dist/tui/terminal.js +153 -0
  390. package/dist/tui/theme.d.ts +31 -0
  391. package/dist/tui/theme.js +199 -0
  392. package/dist/tui/tui.d.ts +103 -0
  393. package/dist/tui/tui.js +363 -0
  394. package/dist/tui/vt-screen.d.ts +46 -0
  395. package/dist/tui/vt-screen.js +251 -0
  396. package/dist/tui.d.ts +30 -0
  397. package/dist/tui.js +31 -0
  398. package/dist/version.d.ts +8 -0
  399. package/dist/version.js +24 -0
  400. package/docs/codemode.md +102 -0
  401. package/docs/hooks.md +196 -0
  402. package/docs/host-api.md +161 -0
  403. package/docs/providers.md +316 -0
  404. package/docs/rpc.md +253 -0
  405. package/docs/session-format.md +119 -0
  406. package/docs/tui.md +168 -0
  407. package/package.json +101 -4
@@ -0,0 +1,202 @@
1
+ /**
2
+ * API Key 发现(设计 §3.5)。顺序:
3
+ * ① `--api-key`(只对 `--model` 指定的那家供应商)
4
+ * ② `--auth-file` / profile.authFile 指向的 auth.json
5
+ * ③ 用户级 `<configDir>/auth.json`(不是 0600 → warning 并照用)
6
+ * ④ config.json 的 `providers.<id>.apiKey`(`$ENV_NAME`、`${ENV_NAME}`、`!command`;`$$` 转义)
7
+ * ⑤ 环境变量:`provider.envKeys` 顺序(profile.authEnv=false 时跳过)
8
+ * ⑥ `requiresApiKey: false` 的供应商:无 key 也放行(source "none")
9
+ *
10
+ * auth.json 的 `apiKey` 以 `!` 开头 = 执行命令取值(stdout 去首尾空白;超时 10 s;空输出或
11
+ * 非零退出视为未配置,继续找下一来源);同一命令进程内只执行一次。
12
+ * 密钥只出现在 `resolve()` 的返回值里:warning 文案不含密钥与命令输出。
13
+ */
14
+ import { exec } from "node:child_process";
15
+ import { readFileSync, statSync } from "node:fs";
16
+ import { homedir } from "node:os";
17
+ import { join } from "node:path";
18
+ /** 用户级配置目录:AMA_CONFIG_DIR > %APPDATA%\ama > $XDG_CONFIG_HOME/ama > ~/.config/ama。 */
19
+ export function defaultConfigDir(env = process.env) {
20
+ if (env["AMA_CONFIG_DIR"])
21
+ return env["AMA_CONFIG_DIR"];
22
+ if (process.platform === "win32" && env["APPDATA"])
23
+ return join(env["APPDATA"], "ama");
24
+ if (env["XDG_CONFIG_HOME"])
25
+ return join(env["XDG_CONFIG_HOME"], "ama");
26
+ return join(env["HOME"] ?? homedir(), ".config", "ama");
27
+ }
28
+ /** 读 auth.json;不存在返回 undefined;格式错误 / 权限过宽记 warning。 */
29
+ export function readAuthFile(path, onWarning) {
30
+ let raw;
31
+ try {
32
+ raw = readFileSync(path, "utf8");
33
+ }
34
+ catch (error) {
35
+ const code = error.code;
36
+ if (code !== "ENOENT")
37
+ onWarning?.(`cannot read auth file ${path}`);
38
+ return undefined;
39
+ }
40
+ if (process.platform !== "win32") {
41
+ try {
42
+ const mode = statSync(path).mode & 0o777;
43
+ if ((mode & 0o077) !== 0) {
44
+ onWarning?.(`auth file ${path} has permissions ${mode.toString(8).padStart(4, "0")}; expected 0600`);
45
+ }
46
+ }
47
+ catch {
48
+ // 读得到就不必再纠结 stat
49
+ }
50
+ }
51
+ try {
52
+ const value = JSON.parse(raw);
53
+ if (typeof value !== "object" || value === null)
54
+ throw new Error("not an object");
55
+ const providers = value.providers;
56
+ if (typeof providers !== "object" || providers === null)
57
+ throw new Error("no providers");
58
+ return value;
59
+ }
60
+ catch {
61
+ onWarning?.(`auth file ${path} is not a valid auth.json; ignored`);
62
+ return undefined;
63
+ }
64
+ }
65
+ /**
66
+ * 展开 config.json 的 `$NAME` / `${NAME}`(`$$` → `$`)。引用的变量未设置或为空 →
67
+ * undefined(视为未配置)。
68
+ */
69
+ export function expandEnvRefs(value, env) {
70
+ let missing = false;
71
+ const out = value.replace(/\$\$|\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (match, braced, bare) => {
72
+ if (match === "$$")
73
+ return "$";
74
+ const name = braced ?? bare ?? "";
75
+ const resolved = env[name];
76
+ if (resolved === undefined || resolved === "")
77
+ missing = true;
78
+ return resolved ?? "";
79
+ });
80
+ return missing || out.length === 0 ? undefined : out;
81
+ }
82
+ export class ApiKeyResolver {
83
+ options;
84
+ env;
85
+ commandCache = new Map();
86
+ fileCache = new Map();
87
+ constructor(options = {}) {
88
+ this.options = options;
89
+ this.env = options.env ?? process.env;
90
+ }
91
+ warn(message) {
92
+ this.options.onWarning?.(message);
93
+ }
94
+ authFiles() {
95
+ const files = [];
96
+ if (this.options.authFile)
97
+ files.push(this.options.authFile);
98
+ const user = this.options.userAuthFile === undefined
99
+ ? join(defaultConfigDir(this.env), "auth.json")
100
+ : this.options.userAuthFile;
101
+ if (user && !files.includes(user))
102
+ files.push(user);
103
+ return files;
104
+ }
105
+ loadFile(path) {
106
+ if (!this.fileCache.has(path))
107
+ this.fileCache.set(path, readAuthFile(path, (m) => this.warn(m)));
108
+ return this.fileCache.get(path);
109
+ }
110
+ /** auth.json 里该供应商的条目(按 ② ③ 顺序第一个)。 */
111
+ authEntry(providerId) {
112
+ for (const path of this.authFiles()) {
113
+ const entry = this.loadFile(path)?.providers[providerId];
114
+ if (entry && typeof entry.apiKey === "string")
115
+ return { entry, path };
116
+ }
117
+ return undefined;
118
+ }
119
+ runCommand(command, extraEnv) {
120
+ const key = `${command}\0${JSON.stringify(extraEnv ?? {})}`;
121
+ let pending = this.commandCache.get(key);
122
+ if (!pending) {
123
+ const timeout = this.options.commandTimeoutMs ?? 10_000;
124
+ pending = new Promise((resolve) => {
125
+ exec(command, { timeout, windowsHide: true, env: { ...this.env, ...extraEnv }, maxBuffer: 1 << 20 }, (error, stdout) => {
126
+ const value = String(stdout).trim();
127
+ if (error || value.length === 0) {
128
+ this.warn(`api key command failed or printed nothing: ${command.split(/\s+/)[0]}`);
129
+ resolve(undefined);
130
+ }
131
+ else
132
+ resolve(value);
133
+ });
134
+ });
135
+ this.commandCache.set(key, pending);
136
+ }
137
+ return pending;
138
+ }
139
+ async fromAuthFiles(providerId) {
140
+ for (const path of this.authFiles()) {
141
+ const entry = this.loadFile(path)?.providers[providerId];
142
+ if (!entry || typeof entry.apiKey !== "string" || entry.apiKey.length === 0)
143
+ continue;
144
+ const value = entry.apiKey.startsWith("!")
145
+ ? await this.runCommand(entry.apiKey.slice(1), entry.env)
146
+ : entry.apiKey;
147
+ if (value)
148
+ return { apiKey: value, source: "auth-file", origin: path };
149
+ }
150
+ return undefined;
151
+ }
152
+ async fromConfig(providerId) {
153
+ const raw = this.options.configKeys?.[providerId];
154
+ if (!raw)
155
+ return undefined;
156
+ if (raw.startsWith("!"))
157
+ return this.runCommand(raw.slice(1));
158
+ return expandEnvRefs(raw, this.env);
159
+ }
160
+ fromEnv(provider) {
161
+ if (this.options.useEnv === false)
162
+ return undefined;
163
+ for (const name of provider.envKeys) {
164
+ const value = this.env[name];
165
+ if (value && value.trim().length > 0) {
166
+ return { apiKey: value.trim(), source: "env", origin: name };
167
+ }
168
+ }
169
+ return undefined;
170
+ }
171
+ async resolve(provider) {
172
+ const cli = this.options.cliApiKey;
173
+ if (cli && cli.provider === provider.id && cli.apiKey) {
174
+ return { apiKey: cli.apiKey, source: "cli" };
175
+ }
176
+ const fromFile = await this.fromAuthFiles(provider.id);
177
+ if (fromFile)
178
+ return fromFile;
179
+ const fromConfig = await this.fromConfig(provider.id);
180
+ if (fromConfig)
181
+ return { apiKey: fromConfig, source: "config" };
182
+ const fromEnv = this.fromEnv(provider);
183
+ if (fromEnv)
184
+ return fromEnv;
185
+ return { apiKey: undefined, source: "none" };
186
+ }
187
+ /**
188
+ * 同步判断「看起来配置了 key」(不执行 `!command`,只看配置是否存在;env 引用需已设置)。
189
+ * 供 `findModel()` 在无斜杠引用时过滤候选。
190
+ */
191
+ hasConfiguredKey(provider) {
192
+ const cli = this.options.cliApiKey;
193
+ if (cli && cli.provider === provider.id && cli.apiKey)
194
+ return true;
195
+ if (this.authEntry(provider.id)?.entry.apiKey)
196
+ return true;
197
+ const raw = this.options.configKeys?.[provider.id];
198
+ if (raw && (raw.startsWith("!") || expandEnvRefs(raw, this.env) !== undefined))
199
+ return true;
200
+ return this.fromEnv(provider) !== undefined;
201
+ }
202
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 13 家内置供应商(设计 §3.3)。这里只放供应商级数据;模型来自 catalog/*.json,compat 由
3
+ * 各协议的 detectCompat 推断(openai-compat.ts 的推断表),这里只写推断不出来的东西。
4
+ *
5
+ * 这里的 `api` 是供应商级缺省;目录条目可用 `api` 覆盖(openai 推理模型与 xai 目录模型走
6
+ * openai-responses,见 catalog/*.json)。
7
+ *
8
+ * `baseUrlEnv`(第三波 §2.3):通行约定的 baseUrl 环境变量(OpenAI SDK 的 `OPENAI_BASE_URL`、
9
+ * Claude Code 的 `ANTHROPIC_BASE_URL`),设了就把内置供应商指向中转站,零配置可用;优先级低于
10
+ * config.json 与 auth.json 的 baseUrl。
11
+ */
12
+ import type { ProviderData } from "../types.js";
13
+ export type BuiltinProvider = Omit<ProviderData, "models" | "builtin"> & {
14
+ baseUrlEnv?: string;
15
+ };
16
+ export declare const BUILTIN_PROVIDERS: readonly BuiltinProvider[];
17
+ /**
18
+ * 内置供应商的 baseUrl 是否被改到了非官方主机(中转站):此时目录外的 model id 也接受,
19
+ * compat 走保守缺省。非内置供应商返回 false。
20
+ */
21
+ export declare function isRelayedBaseUrl(providerId: string, baseUrl: string): boolean;
22
+ /** 自定义供应商的兜底环境变量名:`AMA_API_KEY_<ID>`(非字母数字转下划线、大写)。 */
23
+ export declare function fallbackEnvKey(providerId: string): string;
@@ -0,0 +1,148 @@
1
+ /**
2
+ * 13 家内置供应商(设计 §3.3)。这里只放供应商级数据;模型来自 catalog/*.json,compat 由
3
+ * 各协议的 detectCompat 推断(openai-compat.ts 的推断表),这里只写推断不出来的东西。
4
+ *
5
+ * 这里的 `api` 是供应商级缺省;目录条目可用 `api` 覆盖(openai 推理模型与 xai 目录模型走
6
+ * openai-responses,见 catalog/*.json)。
7
+ *
8
+ * `baseUrlEnv`(第三波 §2.3):通行约定的 baseUrl 环境变量(OpenAI SDK 的 `OPENAI_BASE_URL`、
9
+ * Claude Code 的 `ANTHROPIC_BASE_URL`),设了就把内置供应商指向中转站,零配置可用;优先级低于
10
+ * config.json 与 auth.json 的 baseUrl。
11
+ */
12
+ export const BUILTIN_PROVIDERS = [
13
+ {
14
+ id: "anthropic",
15
+ name: "Anthropic",
16
+ api: "anthropic-messages",
17
+ baseUrl: "https://api.anthropic.com",
18
+ baseUrlEnv: "ANTHROPIC_BASE_URL",
19
+ envKeys: ["ANTHROPIC_API_KEY", "AMA_API_KEY_ANTHROPIC"],
20
+ authHeader: "x-api-key",
21
+ requiresApiKey: true,
22
+ },
23
+ {
24
+ id: "openai",
25
+ name: "OpenAI",
26
+ api: "openai-completions",
27
+ baseUrl: "https://api.openai.com/v1",
28
+ baseUrlEnv: "OPENAI_BASE_URL",
29
+ envKeys: ["OPENAI_API_KEY", "AMA_API_KEY_OPENAI"],
30
+ requiresApiKey: true,
31
+ },
32
+ {
33
+ id: "google",
34
+ name: "Google Gemini",
35
+ api: "google-generative-ai",
36
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
37
+ envKeys: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "AMA_API_KEY_GOOGLE"],
38
+ authHeader: "x-goog-api-key",
39
+ requiresApiKey: true,
40
+ },
41
+ {
42
+ id: "deepseek",
43
+ name: "DeepSeek",
44
+ api: "openai-completions",
45
+ baseUrl: "https://api.deepseek.com",
46
+ envKeys: ["DEEPSEEK_API_KEY", "AMA_API_KEY_DEEPSEEK"],
47
+ requiresApiKey: true,
48
+ },
49
+ {
50
+ id: "moonshot",
51
+ name: "Moonshot (Kimi)",
52
+ api: "openai-completions",
53
+ baseUrl: "https://api.moonshot.cn/v1",
54
+ envKeys: ["MOONSHOT_API_KEY", "KIMI_API_KEY", "AMA_API_KEY_MOONSHOT"],
55
+ requiresApiKey: true,
56
+ },
57
+ {
58
+ id: "zhipu",
59
+ name: "Zhipu GLM",
60
+ api: "openai-completions",
61
+ baseUrl: "https://open.bigmodel.cn/api/paas/v4",
62
+ envKeys: ["ZHIPU_API_KEY", "ZAI_API_KEY", "AMA_API_KEY_ZHIPU"],
63
+ requiresApiKey: true,
64
+ },
65
+ {
66
+ id: "dashscope",
67
+ name: "Alibaba DashScope (Qwen)",
68
+ api: "openai-completions",
69
+ baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
70
+ envKeys: ["DASHSCOPE_API_KEY", "QWEN_API_KEY", "AMA_API_KEY_DASHSCOPE"],
71
+ requiresApiKey: true,
72
+ },
73
+ {
74
+ id: "openrouter",
75
+ name: "OpenRouter",
76
+ api: "openai-completions",
77
+ baseUrl: "https://openrouter.ai/api/v1",
78
+ envKeys: ["OPENROUTER_API_KEY", "AMA_API_KEY_OPENROUTER"],
79
+ headers: {
80
+ "HTTP-Referer": "https://github.com/Owlbay/armadra-agent",
81
+ "X-Title": "ama",
82
+ },
83
+ requiresApiKey: true,
84
+ },
85
+ {
86
+ id: "groq",
87
+ name: "Groq",
88
+ api: "openai-completions",
89
+ baseUrl: "https://api.groq.com/openai/v1",
90
+ envKeys: ["GROQ_API_KEY", "AMA_API_KEY_GROQ"],
91
+ requiresApiKey: true,
92
+ },
93
+ {
94
+ id: "xai",
95
+ name: "xAI",
96
+ api: "openai-completions",
97
+ baseUrl: "https://api.x.ai/v1",
98
+ envKeys: ["XAI_API_KEY", "AMA_API_KEY_XAI"],
99
+ requiresApiKey: true,
100
+ },
101
+ {
102
+ id: "mistral",
103
+ name: "Mistral",
104
+ api: "openai-completions",
105
+ baseUrl: "https://api.mistral.ai/v1",
106
+ envKeys: ["MISTRAL_API_KEY", "AMA_API_KEY_MISTRAL"],
107
+ requiresApiKey: true,
108
+ },
109
+ {
110
+ id: "ollama",
111
+ name: "Ollama (local)",
112
+ api: "openai-completions",
113
+ baseUrl: "http://127.0.0.1:11434/v1",
114
+ envKeys: ["OLLAMA_API_KEY", "AMA_API_KEY_OLLAMA"],
115
+ requiresApiKey: false,
116
+ },
117
+ {
118
+ id: "lmstudio",
119
+ name: "LM Studio (local)",
120
+ api: "openai-completions",
121
+ baseUrl: "http://127.0.0.1:1234/v1",
122
+ envKeys: ["AMA_API_KEY_LMSTUDIO"],
123
+ requiresApiKey: false,
124
+ },
125
+ ];
126
+ /** 主机名(不含端口);无法解析时返回 undefined。 */
127
+ function hostOf(url) {
128
+ try {
129
+ return new URL(url).hostname.toLowerCase();
130
+ }
131
+ catch {
132
+ return undefined;
133
+ }
134
+ }
135
+ /**
136
+ * 内置供应商的 baseUrl 是否被改到了非官方主机(中转站):此时目录外的 model id 也接受,
137
+ * compat 走保守缺省。非内置供应商返回 false。
138
+ */
139
+ export function isRelayedBaseUrl(providerId, baseUrl) {
140
+ const builtin = BUILTIN_PROVIDERS.find((p) => p.id === providerId);
141
+ if (builtin === undefined || builtin.requiresApiKey === false)
142
+ return false;
143
+ return hostOf(baseUrl) !== hostOf(builtin.baseUrl);
144
+ }
145
+ /** 自定义供应商的兜底环境变量名:`AMA_API_KEY_<ID>`(非字母数字转下划线、大写)。 */
146
+ export function fallbackEnvKey(providerId) {
147
+ return `AMA_API_KEY_${providerId.replace(/[^a-zA-Z0-9]/g, "_").toUpperCase()}`;
148
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 由 catalog/*.json 生成,勿手改。重新生成:
3
+ * UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts
4
+ */
5
+ export declare const CATALOG_SOURCES: Readonly<Record<string, string>>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 由 catalog/*.json 生成,勿手改。重新生成:
3
+ * UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts
4
+ */
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}}]}',
19
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 模型目录(设计 §3.4):`catalog/*.json` 是数据源(人工校对、PR 更新),随包携带。
3
+ *
4
+ * 运行时零依赖、bundle 为单文件,不能在运行时读 JSON 文件;`catalog-data.ts` 是由 JSON 生成
5
+ * 的字符串表(`UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts` 重新生成,
6
+ * 测试守住两者一致)。本模块解析并校验它,另提供覆盖合并。
7
+ *
8
+ * 必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——数据源里
9
+ * 不确定的就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
10
+ * (TTL 秒数与最小可缓存长度)同样只写有公开依据的值(第三波 §1.4),留空 = 不承诺。
11
+ */
12
+ import type { Model, ModelCatalogFile } from "../types.js";
13
+ export type CatalogModel = ModelCatalogFile["models"][number];
14
+ /** 校验一个模型条目,返回问题列表(空 = 合法)。 */
15
+ 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[]>;
19
+ /** 目录条目 → Model(补 provider / api 与缺省 input)。 */
20
+ export declare function toModel(entry: CatalogModel, provider: string, api: Model["api"]): Model;
21
+ /** 自定义模型缺省:maxTokens 8192、reasoning false、input ["text"]、name = id;不猜 contextWindow。 */
22
+ export declare function withCustomDefaults(entry: Partial<Omit<Model, "provider" | "api">> & {
23
+ id: string;
24
+ }, provider: string, api: Model["api"]): Model;
25
+ /** 只改元数据:浅合并,`compat` / `cost` / `thinkingLevelMap` / `headers` 再合并一层。 */
26
+ export declare function applyModelOverride(model: Model, override: Partial<Omit<Model, "provider" | "api">> & {
27
+ id: string;
28
+ }): Model;