@armadra/agent 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +470 -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 +514 -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 +119 -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 +111 -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 +485 -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 +304 -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 +103 -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/channels.d.ts +51 -0
  101. package/dist/ai/providers/channels.js +96 -0
  102. package/dist/ai/providers/enrich.d.ts +34 -0
  103. package/dist/ai/providers/enrich.js +86 -0
  104. package/dist/ai/providers/models-dev-cache.d.ts +53 -0
  105. package/dist/ai/providers/models-dev-cache.js +147 -0
  106. package/dist/ai/providers/models-dev.d.ts +99 -0
  107. package/dist/ai/providers/models-dev.js +315 -0
  108. package/dist/ai/providers/registry.d.ts +114 -0
  109. package/dist/ai/providers/registry.js +458 -0
  110. package/dist/ai/sse.d.ts +32 -0
  111. package/dist/ai/sse.js +140 -0
  112. package/dist/ai/thinking.d.ts +42 -0
  113. package/dist/ai/thinking.js +101 -0
  114. package/dist/ai/types.d.ts +448 -0
  115. package/dist/ai/types.js +19 -0
  116. package/dist/bundle/ama-sandbox.cjs +324 -0
  117. package/dist/bundle/ama.cjs +27837 -0
  118. package/dist/bundle.d.ts +9 -0
  119. package/dist/bundle.js +15 -0
  120. package/dist/cli/args.d.ts +85 -0
  121. package/dist/cli/args.js +408 -0
  122. package/dist/cli/bootstrap.d.ts +18 -0
  123. package/dist/cli/bootstrap.js +399 -0
  124. package/dist/cli/compose-providers.d.ts +37 -0
  125. package/dist/cli/compose-providers.js +107 -0
  126. package/dist/cli/compose-session.d.ts +72 -0
  127. package/dist/cli/compose-session.js +370 -0
  128. package/dist/cli/compose-store.d.ts +24 -0
  129. package/dist/cli/compose-store.js +125 -0
  130. package/dist/cli/compose.d.ts +108 -0
  131. package/dist/cli/compose.js +221 -0
  132. package/dist/cli/default-model.d.ts +16 -0
  133. package/dist/cli/default-model.js +24 -0
  134. package/dist/cli/deps.d.ts +207 -0
  135. package/dist/cli/deps.js +12 -0
  136. package/dist/cli/exit-codes.d.ts +29 -0
  137. package/dist/cli/exit-codes.js +40 -0
  138. package/dist/cli/main.d.ts +27 -0
  139. package/dist/cli/main.js +177 -0
  140. package/dist/cli/runtime.d.ts +90 -0
  141. package/dist/cli/runtime.js +8 -0
  142. package/dist/cli/startup-screen.d.ts +15 -0
  143. package/dist/cli/startup-screen.js +56 -0
  144. package/dist/cli/startup-steps.d.ts +35 -0
  145. package/dist/cli/startup-steps.js +202 -0
  146. package/dist/cli/subcommands/auth.d.ts +12 -0
  147. package/dist/cli/subcommands/auth.js +91 -0
  148. package/dist/cli/subcommands/config.d.ts +53 -0
  149. package/dist/cli/subcommands/config.js +277 -0
  150. package/dist/cli/subcommands/context.d.ts +21 -0
  151. package/dist/cli/subcommands/context.js +42 -0
  152. package/dist/cli/subcommands/doctor.d.ts +11 -0
  153. package/dist/cli/subcommands/doctor.js +246 -0
  154. package/dist/cli/subcommands/init.d.ts +6 -0
  155. package/dist/cli/subcommands/init.js +22 -0
  156. package/dist/cli/subcommands/model-meta.d.ts +16 -0
  157. package/dist/cli/subcommands/model-meta.js +54 -0
  158. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  159. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  160. package/dist/cli/subcommands/models-discover.d.ts +46 -0
  161. package/dist/cli/subcommands/models-discover.js +232 -0
  162. package/dist/cli/subcommands/models.d.ts +40 -0
  163. package/dist/cli/subcommands/models.js +152 -0
  164. package/dist/cli/subcommands/providers-list.d.ts +8 -0
  165. package/dist/cli/subcommands/providers-list.js +97 -0
  166. package/dist/cli/subcommands/providers-plan.d.ts +79 -0
  167. package/dist/cli/subcommands/providers-plan.js +215 -0
  168. package/dist/cli/subcommands/providers.d.ts +27 -0
  169. package/dist/cli/subcommands/providers.js +433 -0
  170. package/dist/cli/subcommands/sessions.d.ts +11 -0
  171. package/dist/cli/subcommands/sessions.js +100 -0
  172. package/dist/codemode/capability.d.ts +37 -0
  173. package/dist/codemode/capability.js +55 -0
  174. package/dist/codemode/declarations.d.ts +44 -0
  175. package/dist/codemode/declarations.js +111 -0
  176. package/dist/codemode/host-side.d.ts +59 -0
  177. package/dist/codemode/host-side.js +253 -0
  178. package/dist/codemode/modes.d.ts +23 -0
  179. package/dist/codemode/modes.js +40 -0
  180. package/dist/codemode/protocol.d.ts +91 -0
  181. package/dist/codemode/protocol.js +114 -0
  182. package/dist/codemode/sandbox-entry.d.ts +25 -0
  183. package/dist/codemode/sandbox-entry.js +323 -0
  184. package/dist/codemode/store.d.ts +26 -0
  185. package/dist/codemode/store.js +53 -0
  186. package/dist/codemode/tool.d.ts +105 -0
  187. package/dist/codemode/tool.js +283 -0
  188. package/dist/compaction/branch-summary.d.ts +30 -0
  189. package/dist/compaction/branch-summary.js +79 -0
  190. package/dist/compaction/breaker.d.ts +32 -0
  191. package/dist/compaction/breaker.js +65 -0
  192. package/dist/compaction/cut-point.d.ts +23 -0
  193. package/dist/compaction/cut-point.js +70 -0
  194. package/dist/compaction/estimate.d.ts +30 -0
  195. package/dist/compaction/estimate.js +114 -0
  196. package/dist/compaction/prune-tier.d.ts +31 -0
  197. package/dist/compaction/prune-tier.js +83 -0
  198. package/dist/compaction/serialize.d.ts +20 -0
  199. package/dist/compaction/serialize.js +115 -0
  200. package/dist/compaction/summarize-tier.d.ts +111 -0
  201. package/dist/compaction/summarize-tier.js +305 -0
  202. package/dist/config/auth-file.d.ts +39 -0
  203. package/dist/config/auth-file.js +92 -0
  204. package/dist/config/context-files.d.ts +30 -0
  205. package/dist/config/context-files.js +77 -0
  206. package/dist/config/init.d.ts +30 -0
  207. package/dist/config/init.js +92 -0
  208. package/dist/config/json-schema.d.ts +14 -0
  209. package/dist/config/json-schema.js +182 -0
  210. package/dist/config/load.d.ts +45 -0
  211. package/dist/config/load.js +97 -0
  212. package/dist/config/merge.d.ts +73 -0
  213. package/dist/config/merge.js +248 -0
  214. package/dist/config/paths.d.ts +38 -0
  215. package/dist/config/paths.js +108 -0
  216. package/dist/config/profile.d.ts +27 -0
  217. package/dist/config/profile.js +65 -0
  218. package/dist/config/schema.d.ts +34 -0
  219. package/dist/config/schema.js +476 -0
  220. package/dist/config/trust.d.ts +42 -0
  221. package/dist/config/trust.js +122 -0
  222. package/dist/config/types.d.ts +190 -0
  223. package/dist/config/types.js +29 -0
  224. package/dist/config/write.d.ts +10 -0
  225. package/dist/config/write.js +25 -0
  226. package/dist/errors.d.ts +28 -0
  227. package/dist/errors.js +30 -0
  228. package/dist/hooks/config.d.ts +49 -0
  229. package/dist/hooks/config.js +102 -0
  230. package/dist/hooks/dispatcher.d.ts +41 -0
  231. package/dist/hooks/dispatcher.js +104 -0
  232. package/dist/hooks/matcher.d.ts +22 -0
  233. package/dist/hooks/matcher.js +108 -0
  234. package/dist/hooks/protocol.d.ts +33 -0
  235. package/dist/hooks/protocol.js +240 -0
  236. package/dist/hooks/runner.d.ts +30 -0
  237. package/dist/hooks/runner.js +143 -0
  238. package/dist/hooks/types.d.ts +147 -0
  239. package/dist/hooks/types.js +20 -0
  240. package/dist/host/api-impl.d.ts +75 -0
  241. package/dist/host/api-impl.js +173 -0
  242. package/dist/host/loader.d.ts +31 -0
  243. package/dist/host/loader.js +147 -0
  244. package/dist/host/types.d.ts +169 -0
  245. package/dist/host/types.js +14 -0
  246. package/dist/host.d.ts +5 -0
  247. package/dist/host.js +4 -0
  248. package/dist/index.d.ts +41 -0
  249. package/dist/index.js +28 -0
  250. package/dist/modes/commands-core.d.ts +44 -0
  251. package/dist/modes/commands-core.js +171 -0
  252. package/dist/modes/image-input.d.ts +27 -0
  253. package/dist/modes/image-input.js +78 -0
  254. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  255. package/dist/modes/interactive/approval-dialog.js +202 -0
  256. package/dist/modes/interactive/commands.d.ts +41 -0
  257. package/dist/modes/interactive/commands.js +201 -0
  258. package/dist/modes/interactive/completion.d.ts +53 -0
  259. package/dist/modes/interactive/completion.js +157 -0
  260. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  261. package/dist/modes/interactive/interactive-mode.js +491 -0
  262. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  263. package/dist/modes/interactive/key-dispatch.js +107 -0
  264. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  265. package/dist/modes/interactive/line/line-editor.js +232 -0
  266. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  267. package/dist/modes/interactive/line/line-mode.js +218 -0
  268. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  269. package/dist/modes/interactive/line/line-render.js +171 -0
  270. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  271. package/dist/modes/interactive/line/paste-state.js +72 -0
  272. package/dist/modes/interactive/message-view.d.ts +77 -0
  273. package/dist/modes/interactive/message-view.js +269 -0
  274. package/dist/modes/interactive/pickers.d.ts +42 -0
  275. package/dist/modes/interactive/pickers.js +115 -0
  276. package/dist/modes/interactive/startup-ui.d.ts +33 -0
  277. package/dist/modes/interactive/startup-ui.js +268 -0
  278. package/dist/modes/interactive/status-bar.d.ts +48 -0
  279. package/dist/modes/interactive/status-bar.js +139 -0
  280. package/dist/modes/interactive/tool-view.d.ts +95 -0
  281. package/dist/modes/interactive/tool-view.js +344 -0
  282. package/dist/modes/print/json-event.d.ts +15 -0
  283. package/dist/modes/print/json-event.js +39 -0
  284. package/dist/modes/print/print-mode.d.ts +17 -0
  285. package/dist/modes/print/print-mode.js +107 -0
  286. package/dist/modes/rpc/commands.d.ts +40 -0
  287. package/dist/modes/rpc/commands.js +263 -0
  288. package/dist/modes/rpc/jsonl.d.ts +16 -0
  289. package/dist/modes/rpc/jsonl.js +55 -0
  290. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  291. package/dist/modes/rpc/rpc-mode.js +153 -0
  292. package/dist/modes/session-report.d.ts +55 -0
  293. package/dist/modes/session-report.js +278 -0
  294. package/dist/modes/shared.d.ts +13 -0
  295. package/dist/modes/shared.js +52 -0
  296. package/dist/modes/startup-ui-text.d.ts +16 -0
  297. package/dist/modes/startup-ui-text.js +103 -0
  298. package/dist/permissions/broker.d.ts +47 -0
  299. package/dist/permissions/broker.js +107 -0
  300. package/dist/permissions/dangerous.d.ts +47 -0
  301. package/dist/permissions/dangerous.js +370 -0
  302. package/dist/permissions/pipeline.d.ts +51 -0
  303. package/dist/permissions/pipeline.js +181 -0
  304. package/dist/permissions/preview.d.ts +43 -0
  305. package/dist/permissions/preview.js +463 -0
  306. package/dist/permissions/rules.d.ts +58 -0
  307. package/dist/permissions/rules.js +249 -0
  308. package/dist/permissions/types.d.ts +100 -0
  309. package/dist/permissions/types.js +18 -0
  310. package/dist/rpc.d.ts +173 -0
  311. package/dist/rpc.js +13 -0
  312. package/dist/sdk.d.ts +98 -0
  313. package/dist/sdk.js +195 -0
  314. package/dist/session/manager.d.ts +70 -0
  315. package/dist/session/manager.js +278 -0
  316. package/dist/session/migrate.d.ts +19 -0
  317. package/dist/session/migrate.js +53 -0
  318. package/dist/session/projection.d.ts +50 -0
  319. package/dist/session/projection.js +184 -0
  320. package/dist/session/store.d.ts +47 -0
  321. package/dist/session/store.js +210 -0
  322. package/dist/session/tree.d.ts +21 -0
  323. package/dist/session/tree.js +88 -0
  324. package/dist/session/types.d.ts +201 -0
  325. package/dist/session/types.js +18 -0
  326. package/dist/skills/discover.d.ts +60 -0
  327. package/dist/skills/discover.js +160 -0
  328. package/dist/skills/expand.d.ts +35 -0
  329. package/dist/skills/expand.js +46 -0
  330. package/dist/skills/frontmatter.d.ts +27 -0
  331. package/dist/skills/frontmatter.js +157 -0
  332. package/dist/skills/index-prompt.d.ts +13 -0
  333. package/dist/skills/index-prompt.js +42 -0
  334. package/dist/skills/templates.d.ts +52 -0
  335. package/dist/skills/templates.js +177 -0
  336. package/dist/tools/bash.d.ts +49 -0
  337. package/dist/tools/bash.js +222 -0
  338. package/dist/tools/edit-fuzzy.d.ts +36 -0
  339. package/dist/tools/edit-fuzzy.js +129 -0
  340. package/dist/tools/edit.d.ts +38 -0
  341. package/dist/tools/edit.js +241 -0
  342. package/dist/tools/file-mutex.d.ts +8 -0
  343. package/dist/tools/file-mutex.js +29 -0
  344. package/dist/tools/glob.d.ts +44 -0
  345. package/dist/tools/glob.js +217 -0
  346. package/dist/tools/grep.d.ts +39 -0
  347. package/dist/tools/grep.js +179 -0
  348. package/dist/tools/ignore.d.ts +40 -0
  349. package/dist/tools/ignore.js +174 -0
  350. package/dist/tools/image-file.d.ts +31 -0
  351. package/dist/tools/image-file.js +114 -0
  352. package/dist/tools/ls.d.ts +21 -0
  353. package/dist/tools/ls.js +96 -0
  354. package/dist/tools/output-accumulator.d.ts +48 -0
  355. package/dist/tools/output-accumulator.js +106 -0
  356. package/dist/tools/paths.d.ts +20 -0
  357. package/dist/tools/paths.js +58 -0
  358. package/dist/tools/presets.d.ts +71 -0
  359. package/dist/tools/presets.js +128 -0
  360. package/dist/tools/process-tree.d.ts +35 -0
  361. package/dist/tools/process-tree.js +125 -0
  362. package/dist/tools/read.d.ts +24 -0
  363. package/dist/tools/read.js +132 -0
  364. package/dist/tools/registry.d.ts +43 -0
  365. package/dist/tools/registry.js +106 -0
  366. package/dist/tools/shell.d.ts +38 -0
  367. package/dist/tools/shell.js +91 -0
  368. package/dist/tools/task.d.ts +29 -0
  369. package/dist/tools/task.js +107 -0
  370. package/dist/tools/todo.d.ts +28 -0
  371. package/dist/tools/todo.js +107 -0
  372. package/dist/tools/truncate.d.ts +44 -0
  373. package/dist/tools/truncate.js +175 -0
  374. package/dist/tools/types.d.ts +135 -0
  375. package/dist/tools/types.js +19 -0
  376. package/dist/tools/write.d.ts +20 -0
  377. package/dist/tools/write.js +84 -0
  378. package/dist/tui/ansi.d.ts +29 -0
  379. package/dist/tui/ansi.js +420 -0
  380. package/dist/tui/component.d.ts +38 -0
  381. package/dist/tui/component.js +13 -0
  382. package/dist/tui/components/box.d.ts +26 -0
  383. package/dist/tui/components/box.js +65 -0
  384. package/dist/tui/components/container.d.ts +14 -0
  385. package/dist/tui/components/container.js +39 -0
  386. package/dist/tui/components/editor-buffer.d.ts +67 -0
  387. package/dist/tui/components/editor-buffer.js +300 -0
  388. package/dist/tui/components/editor-paste.d.ts +29 -0
  389. package/dist/tui/components/editor-paste.js +64 -0
  390. package/dist/tui/components/editor.d.ts +114 -0
  391. package/dist/tui/components/editor.js +530 -0
  392. package/dist/tui/components/key-value.d.ts +29 -0
  393. package/dist/tui/components/key-value.js +48 -0
  394. package/dist/tui/components/loader.d.ts +35 -0
  395. package/dist/tui/components/loader.js +71 -0
  396. package/dist/tui/components/markdown.d.ts +90 -0
  397. package/dist/tui/components/markdown.js +462 -0
  398. package/dist/tui/components/meter.d.ts +29 -0
  399. package/dist/tui/components/meter.js +47 -0
  400. package/dist/tui/components/overlay.d.ts +24 -0
  401. package/dist/tui/components/overlay.js +52 -0
  402. package/dist/tui/components/select-list.d.ts +57 -0
  403. package/dist/tui/components/select-list.js +179 -0
  404. package/dist/tui/components/spacer.d.ts +11 -0
  405. package/dist/tui/components/spacer.js +16 -0
  406. package/dist/tui/components/text.d.ts +30 -0
  407. package/dist/tui/components/text.js +65 -0
  408. package/dist/tui/keybindings.d.ts +66 -0
  409. package/dist/tui/keybindings.js +120 -0
  410. package/dist/tui/keys.d.ts +38 -0
  411. package/dist/tui/keys.js +275 -0
  412. package/dist/tui/stdin-buffer.d.ts +41 -0
  413. package/dist/tui/stdin-buffer.js +206 -0
  414. package/dist/tui/terminal.d.ts +79 -0
  415. package/dist/tui/terminal.js +153 -0
  416. package/dist/tui/theme.d.ts +31 -0
  417. package/dist/tui/theme.js +199 -0
  418. package/dist/tui/tui.d.ts +103 -0
  419. package/dist/tui/tui.js +363 -0
  420. package/dist/tui/vt-screen.d.ts +46 -0
  421. package/dist/tui/vt-screen.js +251 -0
  422. package/dist/tui.d.ts +30 -0
  423. package/dist/tui.js +31 -0
  424. package/dist/version.d.ts +8 -0
  425. package/dist/version.js +24 -0
  426. package/docs/codemode.md +102 -0
  427. package/docs/hooks.md +196 -0
  428. package/docs/host-api.md +161 -0
  429. package/docs/providers.md +531 -0
  430. package/docs/rpc.md +253 -0
  431. package/docs/session-format.md +119 -0
  432. package/docs/tui.md +170 -0
  433. package/package.json +101 -4
@@ -0,0 +1,232 @@
1
+ /**
2
+ * `ama models discover <provider>`(第三波 §2.3):问中转站有哪些模型。[W3-B12]
3
+ *
4
+ * GET `{baseUrl}/models`(anthropic-messages 且 baseUrl 不以 `/v1` 结尾时为 `{baseUrl}/v1/models`),
5
+ * 带供应商的鉴权头,打印 id 列表并标出已配置的条目。
6
+ *
7
+ * `--probe`:同一中转下不同模型支持的协议不同,对每个 id 依次试供应商协议 → completions →
8
+ * responses → messages(去重),各发一次最小请求(`ama models check` 同款,maxTokens 16),
9
+ * 记第一个成功的协议;每模型最多 3 次请求,`--limit`(缺省 30)限制探测的模型数,执行前打印
10
+ * 预估;401 / 403 / 429 立即停止(key 无效或被限流,继续只会浪费请求)。
11
+ *
12
+ * `--write`:新条目合并进用户级 config.json 的 `providers.<id>.models`——已有同 id 不覆盖;只写
13
+ * `id` 与探到的 `api`(与供应商协议相同时省略);带 `--probe` 时只写探测成功的模型。不猜
14
+ * `contextWindow`(自动压缩随之关闭,输出 warning)。写前备份为 `config.json.bak`。
15
+ *
16
+ * models.dev:列表之后按需刷新缓存(24 小时内不重拉),每个模型标出上下文、输出、图片、工具调用与
17
+ * 匹配结果;`--write` 跳过 models.dev 标明不支持工具调用的模型。元数据不写进配置——运行时从缓存补。
18
+ */
19
+ import { authHeaders, mergeHeaders } from "../../ai/http.js";
20
+ import { discoverLocalModels, materializeModel } from "../../ai/providers/registry.js";
21
+ import { withCustomDefaults } from "../../ai/providers/catalog.js";
22
+ import { describeRefresh, refreshModelsDev } from "../../ai/providers/models-dev-cache.js";
23
+ import { matchLabel, modelsDevFields } from "../../ai/providers/models-dev.js";
24
+ import { existsSync } from "node:fs";
25
+ import { loadConfigFile } from "../../config/load.js";
26
+ import { writeConfigFile } from "../../config/write.js";
27
+ import { UsageError } from "../args.js";
28
+ import { ExitCode } from "../exit-codes.js";
29
+ import { compactTokens } from "./model-meta.js";
30
+ export const DISCOVER_TIMEOUT_MS = 15_000;
31
+ export const PROBE_TIMEOUT_MS = 30_000;
32
+ export const DEFAULT_PROBE_LIMIT = 30;
33
+ const ANTHROPIC_VERSION = "2023-06-01";
34
+ /** 中转常见的三种协议,按此顺序探测(供应商协议排最前)。 */
35
+ export const PROBE_APIS = [
36
+ "openai-completions",
37
+ "openai-responses",
38
+ "anthropic-messages",
39
+ ];
40
+ /** 模型列表的 URL:OpenAI 系是 `{baseUrl}/models`;Anthropic 官方形状的 baseUrl 不带 `/v1`。 */
41
+ export function modelsUrl(provider) {
42
+ const base = provider.baseUrl.replace(/\/+$/, "");
43
+ if (provider.api === "anthropic-messages" && !/\/v1$/.test(base))
44
+ return `${base}/v1/models`;
45
+ return `${base}/models`;
46
+ }
47
+ export async function discoverModels(provider, apiKey, options = {}) {
48
+ const timeoutMs = options.timeoutMs ?? DISCOVER_TIMEOUT_MS;
49
+ if (!provider.requiresApiKey && apiKey === undefined)
50
+ return discoverLocalModels(provider, { timeoutMs });
51
+ const anthropic = provider.api === "anthropic-messages";
52
+ const headers = mergeHeaders(provider.headers, anthropic ? { "anthropic-version": ANTHROPIC_VERSION } : {}, authHeaders(apiKey, provider.authHeader, anthropic ? "x-api-key" : "authorization-bearer"));
53
+ return discoverLocalModels(provider, { timeoutMs, url: modelsUrl(provider), headers });
54
+ }
55
+ export function probeOrder(provider) {
56
+ return PROBE_APIS.includes(provider.api)
57
+ ? [provider.api, ...PROBE_APIS.filter((api) => api !== provider.api)]
58
+ : [...PROBE_APIS];
59
+ }
60
+ export const FATAL_STATUS = /^(?:HTTP )?(?:401|403|429)\b/;
61
+ /** 返回已探测模型 → 第一个成功的协议(都失败为 undefined);超出 `limit` 或提前停止的不在表里。 */
62
+ export async function probeModelApis(registry, provider, ids, limit, options = {}) {
63
+ const result = new Map();
64
+ const key = await registry.resolveApiKey(provider.id);
65
+ const order = probeOrder(provider).filter((api) => registry.getApi(api) !== undefined);
66
+ for (const id of ids.slice(0, Math.max(0, limit))) {
67
+ const known = provider.models.find((m) => m.id === id);
68
+ let found;
69
+ for (const api of order) {
70
+ const model = known !== undefined
71
+ ? { ...known, api }
72
+ : materializeModel(withCustomDefaults({ id }, provider.id, api), provider);
73
+ const error = await attempt(registry, model, key.apiKey, options.timeoutMs);
74
+ options.onAttempt?.(id, api, error);
75
+ if (error === undefined) {
76
+ found = api;
77
+ break;
78
+ }
79
+ if (FATAL_STATUS.test(error)) {
80
+ options.onStop?.(error);
81
+ return result;
82
+ }
83
+ }
84
+ result.set(id, found);
85
+ options.onResult?.(id, found);
86
+ }
87
+ return result;
88
+ }
89
+ /** 一次最小请求;成功返回 undefined,失败返回错误文本(`ama providers add --probe` 也用)。 */
90
+ export async function attempt(registry, model, apiKey, timeoutMs = PROBE_TIMEOUT_MS) {
91
+ const impl = registry.getApi(model.api);
92
+ if (impl === undefined)
93
+ return `协议 ${model.api} 尚未实现`;
94
+ try {
95
+ const message = await impl
96
+ .stream(model, { messages: [{ role: "user", content: "Reply with: ok", timestamp: Date.now() }] }, {
97
+ signal: AbortSignal.timeout(timeoutMs),
98
+ ...(apiKey !== undefined ? { apiKey } : {}),
99
+ maxTokens: 16,
100
+ cacheRetention: "none",
101
+ })
102
+ .result();
103
+ if (message.stopReason === "error" || message.stopReason === "aborted")
104
+ return message.errorMessage ?? message.stopReason;
105
+ return undefined;
106
+ }
107
+ catch (error) {
108
+ return error instanceof Error ? error.message : String(error);
109
+ }
110
+ }
111
+ function parseLimit(raw) {
112
+ if (raw === undefined)
113
+ return DEFAULT_PROBE_LIMIT;
114
+ const n = Number(raw);
115
+ if (!Number.isInteger(n) || n < 1)
116
+ throw new UsageError(`--limit 需要正整数:${raw}`);
117
+ return n;
118
+ }
119
+ /** 把新条目合并进用户级 config.json;返回写入条数。 */
120
+ function writeEntries(ctx, provider, entries, notes) {
121
+ const { io } = ctx;
122
+ const path = ctx.level.userConfigPath;
123
+ const config = structuredClone(loadConfigFile("config", path)?.value ?? { version: 1 });
124
+ const providers = (config.providers ??= {});
125
+ if (providers[provider.id] === undefined && !provider.builtin) {
126
+ io.stderr(`ama: ${provider.id} 不在用户级配置(${path})里,未写入\n`);
127
+ return 0;
128
+ }
129
+ const target = (providers[provider.id] ??= {});
130
+ const models = (target.models ??= []);
131
+ const existing = new Set([...models.map((m) => m.id), ...provider.models.map((m) => m.id)]);
132
+ const added = entries.filter((entry) => !existing.has(entry.id));
133
+ const kept = entries.length - added.length;
134
+ if (added.length === 0) {
135
+ io.stdout(`\n没有新模型要写入${kept > 0 ? `(${kept} 个已存在,未覆盖)` : ""}\n`);
136
+ return 0;
137
+ }
138
+ models.push(...added);
139
+ const backup = existsSync(path);
140
+ writeConfigFile(path, config, { backup: true });
141
+ io.stdout(`\n已写入 ${path}:${provider.id} 新增 ${added.length} 个模型` +
142
+ `${kept > 0 ? `,${kept} 个已存在未覆盖` : ""}${backup ? `(原文件备份为 ${path}.bak)` : ""}\n`);
143
+ if (notes.noTools.size > 0)
144
+ io.stdout(`跳过不支持工具调用的模型(models.dev):${[...notes.noTools].join(", ")}\n`);
145
+ const blind = added.filter((entry) => notes.unmatched.has(entry.id)).map((entry) => entry.id);
146
+ if (blind.length > 0)
147
+ io.stderr(`ama: 警告:${blind.join(", ")} 在 models.dev 未匹配,没有 contextWindow,自动压缩关闭;` +
148
+ `需要时在 config.json 里补上或写 modelsDev\n`);
149
+ return added.length;
150
+ }
151
+ async function run(ctx) {
152
+ const { io, registry } = ctx;
153
+ const id = ctx.args[0] ?? "";
154
+ const limit = parseLimit(ctx.values.get("limit"));
155
+ const provider = registry.get(id);
156
+ if (provider === undefined) {
157
+ io.stderr(`ama: 供应商不存在:${id}\n`);
158
+ return ExitCode.NoModel;
159
+ }
160
+ const key = await registry.resolveApiKey(provider.id);
161
+ if (key.apiKey === undefined && provider.requiresApiKey) {
162
+ io.stderr(`ama: ${provider.id} 没有 API key(ama auth set ${provider.id})\n`);
163
+ return ExitCode.NoModel;
164
+ }
165
+ let found;
166
+ try {
167
+ found = await discoverModels(provider, key.apiKey);
168
+ }
169
+ catch (error) {
170
+ io.stderr(`ama: ${provider.id} 模型列表获取失败:${error.message}\n`);
171
+ return ExitCode.RuntimeError;
172
+ }
173
+ const configured = new Map(provider.models.map((m) => [m.id, m]));
174
+ io.stdout(`${provider.id}:发现 ${found.length} 个模型(${modelsUrl(provider)})\n`);
175
+ const md = await refreshModelsDev({ dataDir: ctx.level.dataDir, env: io.env });
176
+ io.stdout(`${describeRefresh(md)}\n`);
177
+ if (md.warning !== undefined)
178
+ io.stderr(`ama: 警告:${md.warning}\n`);
179
+ const noTools = new Set();
180
+ const unmatched = new Set();
181
+ for (const model of found) {
182
+ const known = configured.get(model.id);
183
+ const match = md.index?.match(model.id);
184
+ const fields = match !== undefined ? modelsDevFields(match.model) : undefined;
185
+ if (fields?.toolCall === false)
186
+ noTools.add(model.id);
187
+ if (match === undefined)
188
+ unmatched.add(model.id);
189
+ const meta = fields === undefined
190
+ ? " models.dev 未匹配"
191
+ : ` ctx ${compactTokens(fields.contextWindow)} · out ${compactTokens(fields.maxTokens)}` +
192
+ `${fields.input?.includes("image") ? " · 图片" : ""}${fields.reasoning ? " · 思考" : ""}` +
193
+ `${fields.toolCall === false ? " · 不支持工具调用" : ""} · ${matchLabel(match)}`;
194
+ io.stdout(` ${model.id}${known !== undefined ? ` 已配置(${known.api})` : ""}${meta}\n`);
195
+ }
196
+ const write = ctx.flags.has("write");
197
+ if (!ctx.flags.has("probe")) {
198
+ if (write)
199
+ writeEntries(ctx, provider, found.filter((m) => !noTools.has(m.id)).map((m) => ({ id: m.id })), { noTools, unmatched });
200
+ return ExitCode.Ok;
201
+ }
202
+ const ids = found.map((m) => m.id);
203
+ const count = Math.min(limit, ids.length);
204
+ const order = probeOrder(provider);
205
+ io.stdout(`\n探测协议:${count} 个模型(${order.join(" → ")}),最多 ${count * order.length} 次请求` +
206
+ `${ids.length > count ? `;另有 ${ids.length - count} 个超出 --limit ${limit},未探测` : ""}\n`);
207
+ let stopped;
208
+ const probed = await probeModelApis(registry, provider, ids, limit, {
209
+ onResult: (modelId, api) => io.stdout(` ${modelId} ${api ?? "不可用(三种协议均失败)"}\n`),
210
+ onStop: (reason) => (stopped = reason),
211
+ });
212
+ if (write) {
213
+ const entries = [];
214
+ for (const [modelId, api] of probed) {
215
+ if (api !== undefined && !noTools.has(modelId))
216
+ entries.push(api === provider.api ? { id: modelId } : { id: modelId, api });
217
+ }
218
+ writeEntries(ctx, provider, entries, { noTools, unmatched });
219
+ }
220
+ if (stopped !== undefined) {
221
+ io.stderr(`ama: 探测提前停止(${stopped})\n`);
222
+ return ExitCode.RuntimeError;
223
+ }
224
+ return ExitCode.Ok;
225
+ }
226
+ export const DISCOVER_ACTION = {
227
+ usage: "ama models discover <provider> [--probe] [--write] [--limit <n>]",
228
+ required: "<provider>",
229
+ valueOptions: ["limit"],
230
+ flagOptions: ["probe", "write"],
231
+ run,
232
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `ama models list [--provider <id>]`、`ama models check <provider/id>`(设计 §1.2、R6)。[B5]
3
+ *
4
+ * 注册表经 RuntimeDeps.providers 注入(B1)。check 发一次最小调用(一条 user 消息、
5
+ * maxTokens 16、超时 30 s),只报告成败与 stopReason,不输出 key。
6
+ *
7
+ * [W3-C0] 子命令分派改为动作表 `MODELS_ACTIONS`(第三波 §1.11 / §2.3):新动作(C2 的
8
+ * `cache-probe`、B12 的 `discover`)各写在自己的文件里,这里只加一行表项;用法文本、
9
+ * 选项表与必填位置参数都从表里来。
10
+ */
11
+ import type { ProviderRegistryApi } from "../../ai/types.js";
12
+ import type { CliIo, RuntimeDeps } from "../deps.js";
13
+ import { type UserLevel } from "./context.js";
14
+ /** 动作执行时拿到的上下文(参数已按表解析、注册表已构造)。 */
15
+ export interface ModelsActionContext {
16
+ io: CliIo;
17
+ registry: ProviderRegistryApi;
18
+ /** 用户级(+ profile)配置;写配置的动作(`discover --write`)要用 `userConfigPath`。 */
19
+ level: UserLevel;
20
+ /** 动作名之后的位置参数。 */
21
+ args: readonly string[];
22
+ values: ReadonlyMap<string, string>;
23
+ flags: ReadonlySet<string>;
24
+ }
25
+ export interface ModelsAction {
26
+ /** 用法行(不含「ama models 」前缀之前的「用法:」)。 */
27
+ usage: string;
28
+ /** 带值选项(不含共用的 --profile / --auth-file)。 */
29
+ valueOptions?: readonly string[];
30
+ /** 布尔选项。 */
31
+ flagOptions?: readonly string[];
32
+ /** 必填的第一个位置参数,缺失时报「ama models <动作> 需要 <required>」。 */
33
+ required?: string;
34
+ run(ctx: ModelsActionContext): Promise<number>;
35
+ }
36
+ export declare const CHECK_TIMEOUT_MS = 30000;
37
+ /** 动作表:键是子命令名,顺序即用法文本顺序。 */
38
+ export declare const MODELS_ACTIONS: Readonly<Record<string, ModelsAction>>;
39
+ export declare const MODELS_USAGE: string;
40
+ export declare function runModels(argv: readonly string[], io: CliIo, deps: Pick<RuntimeDeps, "providers"> | undefined): Promise<number>;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * `ama models list [--provider <id>]`、`ama models check <provider/id>`(设计 §1.2、R6)。[B5]
3
+ *
4
+ * 注册表经 RuntimeDeps.providers 注入(B1)。check 发一次最小调用(一条 user 消息、
5
+ * maxTokens 16、超时 30 s),只报告成败与 stopReason,不输出 key。
6
+ *
7
+ * [W3-C0] 子命令分派改为动作表 `MODELS_ACTIONS`(第三波 §1.11 / §2.3):新动作(C2 的
8
+ * `cache-probe`、B12 的 `discover`)各写在自己的文件里,这里只加一行表项;用法文本、
9
+ * 选项表与必填位置参数都从表里来。
10
+ */
11
+ import { formatModelRef, modelRefOf } from "../../ai/providers/channels.js";
12
+ import { describeRefresh, modelsDevCachePath, refreshModelsDev, } from "../../ai/providers/models-dev-cache.js";
13
+ import { parseSubArgs, UsageError } from "../args.js";
14
+ import { ExitCode } from "../exit-codes.js";
15
+ import { buildRegistry, loadUserLevel } from "./context.js";
16
+ import { CACHE_PROBE_ACTION } from "./models-cache-probe.js";
17
+ import { DISCOVER_ACTION } from "./models-discover.js";
18
+ import { metadataOf, modelFlags, sourcesLine } from "./model-meta.js";
19
+ const COMMON_VALUE_OPTIONS = ["profile", "auth-file"];
20
+ export const CHECK_TIMEOUT_MS = 30_000;
21
+ async function list(io, registry, only) {
22
+ const providers = registry.list().filter((p) => only === undefined || p.id === only);
23
+ if (only !== undefined && providers.length === 0) {
24
+ io.stderr(`ama: 供应商不存在:${only}\n`);
25
+ return ExitCode.NoModel;
26
+ }
27
+ for (const provider of providers) {
28
+ const key = await registry.resolveApiKey(provider.id);
29
+ const keyText = key.apiKey !== undefined
30
+ ? `key:${key.source}${key.origin !== undefined ? `(${key.origin})` : ""}`
31
+ : provider.requiresApiKey
32
+ ? "无 key"
33
+ : "无需 key";
34
+ io.stdout(`${provider.id} ${provider.api} ${keyText}\n`);
35
+ for (const channel of provider.channels ?? [])
36
+ io.stdout(` @${channel.name} ${channel.api} ${channel.baseUrl}\n`);
37
+ for (const model of provider.models) {
38
+ io.stdout(` ${provider.id}/${model.id} ${modelFlags(model)}\n`);
39
+ const sources = sourcesLine(metadataOf(registry, provider.id, model.id));
40
+ if (sources !== undefined)
41
+ io.stdout(` ${sources}\n`);
42
+ }
43
+ }
44
+ return ExitCode.Ok;
45
+ }
46
+ async function check(io, registry, ref) {
47
+ const found = registry.findModel(ref);
48
+ if (!found.ok) {
49
+ const hint = found.candidates.length > 0 ? `;候选:${found.candidates.slice(0, 10).join(", ")}` : "";
50
+ io.stderr(`ama: 模型不存在:${ref}${hint}\n`);
51
+ return ExitCode.NoModel;
52
+ }
53
+ const { model, provider } = found;
54
+ const key = await registry.resolveApiKey(provider.id, model.channel);
55
+ if (key.apiKey === undefined && provider.requiresApiKey) {
56
+ io.stderr(`ama: ${provider.id} 没有 API key(ama auth set ${provider.id})\n`);
57
+ return ExitCode.NoModel;
58
+ }
59
+ const api = registry.getApi(model.api);
60
+ if (api === undefined) {
61
+ io.stderr(`ama: 协议 ${model.api} 尚未实现\n`);
62
+ return ExitCode.RuntimeError;
63
+ }
64
+ const started = Date.now();
65
+ const stream = api.stream(model, { messages: [{ role: "user", content: "Reply with: ok", timestamp: Date.now() }] }, {
66
+ signal: AbortSignal.timeout(CHECK_TIMEOUT_MS),
67
+ ...(key.apiKey !== undefined ? { apiKey: key.apiKey } : {}),
68
+ maxTokens: 16,
69
+ cacheRetention: "none",
70
+ });
71
+ const message = await stream.result();
72
+ const ms = Date.now() - started;
73
+ if (message.stopReason === "error" || message.stopReason === "aborted") {
74
+ io.stderr(`ama: ${provider.id}/${model.id} 失败(${ms} ms):${message.errorMessage ?? message.stopReason}\n`);
75
+ return ExitCode.RuntimeError;
76
+ }
77
+ const shown = formatModelRef(modelRefOf(model));
78
+ io.stdout(`${shown} 可用(${model.api},${ms} ms,stopReason ${message.stopReason})\n`);
79
+ return ExitCode.Ok;
80
+ }
81
+ /** 动作表:键是子命令名,顺序即用法文本顺序。 */
82
+ export const MODELS_ACTIONS = Object.freeze({
83
+ list: {
84
+ usage: "ama models list [--provider <id>]",
85
+ valueOptions: ["provider"],
86
+ run: (ctx) => list(ctx.io, ctx.registry, ctx.values.get("provider")),
87
+ },
88
+ check: {
89
+ usage: "ama models check <provider/id>",
90
+ required: "<provider/id>",
91
+ run: (ctx) => check(ctx.io, ctx.registry, ctx.args[0] ?? ""),
92
+ },
93
+ discover: DISCOVER_ACTION,
94
+ "cache-probe": CACHE_PROBE_ACTION,
95
+ "refresh-catalog": {
96
+ usage: "ama models refresh-catalog",
97
+ run: async (ctx) => {
98
+ const result = await refreshModelsDev({
99
+ dataDir: ctx.level.dataDir,
100
+ env: ctx.io.env,
101
+ force: true,
102
+ });
103
+ ctx.io.stdout(`${describeRefresh(result)}\n${modelsDevCachePath(ctx.level.dataDir)}\n`);
104
+ if (result.warning !== undefined)
105
+ ctx.io.stderr(`ama: 警告:${result.warning}\n`);
106
+ return result.status === "unavailable" ? ExitCode.RuntimeError : ExitCode.Ok;
107
+ },
108
+ },
109
+ });
110
+ export const MODELS_USAGE = `用法:${Object.values(MODELS_ACTIONS)
111
+ .map((a) => a.usage)
112
+ .join("\n ")}\n`;
113
+ function unique(lists) {
114
+ return [...new Set(lists.flatMap((l) => l ?? []))];
115
+ }
116
+ export async function runModels(argv, io, deps) {
117
+ const actions = Object.values(MODELS_ACTIONS);
118
+ const { positionals, values, flags } = parseSubArgs(argv, unique([...actions.map((a) => a.valueOptions), COMMON_VALUE_OPTIONS]), unique(actions.map((a) => a.flagOptions)));
119
+ const name = positionals[0];
120
+ if (flags.has("help") || name === undefined) {
121
+ io.stdout(MODELS_USAGE);
122
+ return flags.has("help") ? ExitCode.Ok : ExitCode.Usage;
123
+ }
124
+ const action = Object.hasOwn(MODELS_ACTIONS, name) ? MODELS_ACTIONS[name] : undefined;
125
+ if (action === undefined)
126
+ throw new UsageError(`未知的 models 子命令:${name}`);
127
+ // 选项按全部动作的并集解析;这里再拒绝不属于本动作的(如 `list --json`)。
128
+ for (const option of [...values.keys(), ...flags]) {
129
+ const own = [
130
+ ...COMMON_VALUE_OPTIONS,
131
+ ...(action.valueOptions ?? []),
132
+ ...(action.flagOptions ?? []),
133
+ ];
134
+ if (!own.includes(option))
135
+ throw new UsageError(`未知选项:--${option}`);
136
+ }
137
+ const args = positionals.slice(1);
138
+ if (action.required !== undefined && args[0] === undefined)
139
+ throw new UsageError(`ama models ${name} 需要 ${action.required}`);
140
+ if (deps === undefined) {
141
+ io.stderr("ama: models 尚未装配(供应商注册表由集成批次注入)\n");
142
+ return ExitCode.RuntimeError;
143
+ }
144
+ const level = loadUserLevel(io, {
145
+ profile: values.get("profile"),
146
+ authFile: values.get("auth-file"),
147
+ });
148
+ for (const warning of level.warnings)
149
+ io.stderr(`ama: 警告:${warning}\n`);
150
+ const registry = await buildRegistry(level, io, deps);
151
+ return action.run({ io, registry, level, args, values, flags });
152
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `ama providers list|channels|remove`(docs/providers.md「一键接入」):供应商 → 渠道 → 模型数与 key 来源
3
+ * (从不显示 key);remove 删配置条目(先备份)与 auth.json 里该供应商及其渠道的 key。
4
+ */
5
+ import { type Ctx } from "./providers.js";
6
+ export declare function listProviders(ctx: Ctx): Promise<number>;
7
+ export declare function listChannels(ctx: Ctx, id: string): Promise<number>;
8
+ export declare function removeProvider(ctx: Ctx, id: string): number;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * `ama providers list|channels|remove`(docs/providers.md「一键接入」):供应商 → 渠道 → 模型数与 key 来源
3
+ * (从不显示 key);remove 删配置条目(先备份)与 auth.json 里该供应商及其渠道的 key。
4
+ */
5
+ import { apiShortName } from "../../ai/providers/channels.js";
6
+ import { classifyKeyValue, readAuthFile, removeAuthKey } from "../../config/auth-file.js";
7
+ import { writeConfigFile } from "../../config/write.js";
8
+ import { ExitCode } from "../exit-codes.js";
9
+ import { buildRegistry } from "./context.js";
10
+ import { userConfig } from "./providers.js";
11
+ async function keySource(registry, config, id, channel) {
12
+ const raw = channel !== undefined ? config?.channels?.[channel]?.apiKey : config?.apiKey;
13
+ if (raw !== undefined) {
14
+ const kind = classifyKeyValue(raw);
15
+ return kind === "env-ref"
16
+ ? raw
17
+ : kind === "command"
18
+ ? "!命令(config.json)"
19
+ : "字面量(config.json)";
20
+ }
21
+ const resolved = await registry.resolveApiKey(id, channel);
22
+ if (resolved.apiKey === undefined)
23
+ return channel !== undefined ? "同供应商" : "无";
24
+ if (channel !== undefined && resolved.source !== "auth-file")
25
+ return "同供应商";
26
+ return resolved.source === "env"
27
+ ? `环境变量 ${resolved.origin ?? ""}`
28
+ : resolved.source === "auth-file"
29
+ ? "auth.json"
30
+ : resolved.source;
31
+ }
32
+ export async function listProviders(ctx) {
33
+ const registry = await buildRegistry(ctx.level, ctx.io, ctx.deps);
34
+ const config = userConfig(ctx.level);
35
+ let shown = 0;
36
+ for (const provider of registry.list()) {
37
+ const own = config.providers?.[provider.id];
38
+ if (own === undefined &&
39
+ !(provider.builtin &&
40
+ provider.requiresApiKey &&
41
+ (await registry.resolveApiKey(provider.id)).apiKey !== undefined))
42
+ continue;
43
+ shown++;
44
+ const kind = provider.builtin ? "内置" : "自定义";
45
+ const channels = provider.channels ?? [];
46
+ ctx.io.stdout(`${provider.id} ${kind} · ${channels.length > 0 ? `${channels.length} 渠道` : `${provider.api} ${provider.baseUrl}`} · ` +
47
+ `${provider.models.length} 模型 · key ${await keySource(registry, own, provider.id)}\n`);
48
+ for (const c of channels) {
49
+ const count = provider.models.filter((m) => m.channels?.includes(c.name)).length;
50
+ ctx.io.stdout(` @${c.name} ${c.api} ${c.baseUrl} ${count} 模型 · key ${await keySource(registry, own, provider.id, c.name)}\n`);
51
+ }
52
+ }
53
+ if (shown === 0)
54
+ ctx.io.stdout(`没有配置供应商(ama providers add <id> --base-url <url>)\n`);
55
+ return ExitCode.Ok;
56
+ }
57
+ export async function listChannels(ctx, id) {
58
+ const registry = await buildRegistry(ctx.level, ctx.io, ctx.deps);
59
+ const provider = registry.get(id);
60
+ if (provider === undefined) {
61
+ ctx.io.stderr(`ama: 供应商不存在:${id}\n`);
62
+ return ExitCode.NoModel;
63
+ }
64
+ const own = userConfig(ctx.level).providers?.[id];
65
+ if (provider.channels === undefined) {
66
+ ctx.io.stdout(`${id}:单渠道(${provider.api} ${provider.baseUrl}),${provider.models.length} 模型\n`);
67
+ return ExitCode.Ok;
68
+ }
69
+ for (const c of provider.channels) {
70
+ const models = provider.models.filter((m) => m.channels?.includes(c.name));
71
+ const mark = c.name === provider.defaultChannel ? "(缺省)" : "";
72
+ ctx.io.stdout(`@${c.name}${mark} ${apiShortName(c.api)} ${c.api} ${c.baseUrl} key ${await keySource(registry, own, id, c.name)}\n` +
73
+ ` ${models.length} 模型${models.length > 0 ? `:${models.map((m) => m.id).join(", ")}` : ""}\n`);
74
+ }
75
+ return ExitCode.Ok;
76
+ }
77
+ export function removeProvider(ctx, id) {
78
+ const config = userConfig(ctx.level);
79
+ const had = config.providers?.[id] !== undefined;
80
+ if (had) {
81
+ delete config.providers?.[id];
82
+ writeConfigFile(ctx.level.userConfigPath, config, { backup: true });
83
+ ctx.io.stdout(`已从 ${ctx.level.userConfigPath} 删除 ${id}(原文件备份为 config.json.bak)\n`);
84
+ }
85
+ const auth = readAuthFile(ctx.level.authFile).file;
86
+ let keys = 0;
87
+ for (const name of Object.keys(auth.providers))
88
+ if (name === id || name.startsWith(`${id}@`))
89
+ keys += removeAuthKey(ctx.level.authFile, name) ? 1 : 0;
90
+ if (keys > 0)
91
+ ctx.io.stdout(`已删除 ${ctx.level.authFile} 里 ${id} 的 ${keys} 个 key\n`);
92
+ if (!had && keys === 0) {
93
+ ctx.io.stderr(`ama: 没有供应商 ${id}\n`);
94
+ return ExitCode.RuntimeError;
95
+ }
96
+ return ExitCode.Ok;
97
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `ama providers add|refresh` 的纯计算部分(docs/providers.md「一键接入」):候选渠道、模型列表的
3
+ * 协议提示、探测结果 → 模型渠道、渠道收敛、追加式合并进配置、表格。
4
+ *
5
+ * 不读写文件、不联网(`fetchModelList` 除外,它只是一次 GET);命令流程在 providers.ts。
6
+ */
7
+ import { type ModelsDevFields, type ModelsDevMatch } from "../../ai/providers/models-dev.js";
8
+ import type { Api } from "../../ai/types.js";
9
+ import type { ProviderConfig } from "../../config/types.js";
10
+ export declare const PROBE_APIS: readonly Api[];
11
+ export declare const DEFAULT_PREFER: readonly string[];
12
+ export interface CandidateChannel {
13
+ name: string;
14
+ api: Api;
15
+ baseUrl: string;
16
+ }
17
+ /** `--channel name=api@baseUrl`。 */
18
+ export declare function parseChannelSpec(spec: string): CandidateChannel;
19
+ /** 从 `--base-url` 推出候选渠道;`api` 给定(非 auto)时只留对应的一个。 */
20
+ export declare function defaultChannels(baseUrl: string, api?: string): CandidateChannel[];
21
+ export interface ListedModel {
22
+ id: string;
23
+ /** new-api 一类中转的 `supported_endpoint_types`。 */
24
+ endpoints?: string[];
25
+ }
26
+ /**
27
+ * 模型列表的提示 → 候选渠道名。没有提示(或提示里没有认识的协议)返回 undefined;有提示但候选渠道
28
+ * 一个都不支持返回 [](该模型在这些渠道上不可用)。
29
+ */
30
+ export declare function hintedChannels(listed: ListedModel, candidates: readonly CandidateChannel[]): string[] | undefined;
31
+ /** 按 `prefer` 排序(不在 prefer 里的保持原顺序排在后面)。 */
32
+ export declare function orderChannels(names: readonly string[], prefer: readonly string[]): string[];
33
+ /** 解析 `GET /models` 的响应体。 */
34
+ export declare function parseModelList(body: unknown): ListedModel[];
35
+ /** 列模型用的渠道与 URL:第一个 OpenAI 系渠道 `{baseUrl}/models`;只有 Messages 时 `/v1/models`。 */
36
+ export declare function listingTarget(candidates: readonly CandidateChannel[]): {
37
+ channel: CandidateChannel;
38
+ url: string;
39
+ } | undefined;
40
+ export type ModelStatus = "ok" | "unprobed" | "failed" | "no-tools" | "no-channel" | "existing";
41
+ export interface ModelPlan {
42
+ id: string;
43
+ channels: string[];
44
+ status: ModelStatus;
45
+ fields: ModelsDevFields;
46
+ match: ModelsDevMatch | undefined;
47
+ /** 探测失败的原因(最后一次)。 */
48
+ error?: string;
49
+ }
50
+ /** 要探测的模型:`--probe-models` 给出的(保持顺序),否则按 id 字母序(不分大小写)取前 limit 个。 */
51
+ export declare function probeSelection(ids: readonly string[], limit: number, only: readonly string[] | undefined): string[];
52
+ /**
53
+ * 按请求上限截断:每个模型要试的渠道数相加超过 `max` 时丢掉后面的模型。返回保留的模型与请求数。
54
+ */
55
+ export declare function capRequests(selected: readonly string[], channelsFor: (id: string) => readonly string[], max: number): {
56
+ ids: string[];
57
+ requests: number;
58
+ dropped: number;
59
+ };
60
+ /**
61
+ * 合并进已有的供应商配置(追加式):已有渠道定义与模型条目一字不改,只加新渠道与新模型;
62
+ * 新模型只写 `id` 与 `channels`。返回新的配置与新增数。
63
+ */
64
+ export declare function mergeProvider(existing: ProviderConfig | undefined, input: {
65
+ name?: string;
66
+ apiKey?: string;
67
+ channels: readonly CandidateChannel[];
68
+ models: readonly {
69
+ id: string;
70
+ channels: readonly string[];
71
+ }[];
72
+ prefer: readonly string[];
73
+ }): {
74
+ config: ProviderConfig;
75
+ addedChannels: string[];
76
+ addedModels: string[];
77
+ };
78
+ /** 表格:id、渠道、上下文、输出、图像、推理、工具、价格($/M 入/出)、状态、models.dev 匹配。 */
79
+ export declare function renderTable(plans: readonly ModelPlan[]): string;