@armadra/agent 0.5.0 → 0.6.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 (471) hide show
  1. package/CHANGELOG.md +177 -294
  2. package/CHANGELOG.zh-CN.md +442 -0
  3. package/README.md +408 -364
  4. package/README.zh-CN.md +705 -0
  5. package/dist/agent/session-plan.js +2 -2
  6. package/dist/agent/session-state.d.ts +3 -0
  7. package/dist/agent/session-state.js +20 -0
  8. package/dist/agent/session-subagent.d.ts +15 -1
  9. package/dist/agent/session-subagent.js +26 -3
  10. package/dist/agent/session-telemetry.d.ts +16 -2
  11. package/dist/agent/session-telemetry.js +29 -7
  12. package/dist/agent/session-tools.js +5 -2
  13. package/dist/agent/session-trace-writer.d.ts +27 -0
  14. package/dist/agent/session-trace-writer.js +253 -0
  15. package/dist/agent/session.d.ts +2 -0
  16. package/dist/agent/session.js +12 -0
  17. package/dist/agent/subagent-direct.d.ts +20 -0
  18. package/dist/agent/subagent-direct.js +76 -0
  19. package/dist/agent/subagent-registry.d.ts +8 -1
  20. package/dist/agent/subagent-registry.js +28 -1
  21. package/dist/agent/system-prompt.d.ts +3 -1
  22. package/dist/agent/system-prompt.js +3 -0
  23. package/dist/agent/tool-runner.d.ts +2 -1
  24. package/dist/agent/tool-runner.js +5 -4
  25. package/dist/agent/types-w6.d.ts +39 -0
  26. package/dist/agent/types-w6.js +4 -0
  27. package/dist/agent/types.d.ts +5 -2
  28. package/dist/agents/external.js +1 -1
  29. package/dist/agents/task-record.d.ts +74 -1
  30. package/dist/agents/task-record.js +100 -0
  31. package/dist/ai/apis/cache-params.js +2 -1
  32. package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
  33. package/dist/ai/apis/chatgpt-backend.js +224 -0
  34. package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
  35. package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
  36. package/dist/ai/apis/openai-responses-request.d.ts +2 -1
  37. package/dist/ai/apis/openai-responses-request.js +8 -2
  38. package/dist/ai/apis/openai-responses.d.ts +2 -0
  39. package/dist/ai/apis/openai-responses.js +51 -16
  40. package/dist/ai/overflow.d.ts +1 -1
  41. package/dist/ai/overflow.js +10 -7
  42. package/dist/ai/providers/auth.d.ts +15 -2
  43. package/dist/ai/providers/auth.js +69 -2
  44. package/dist/ai/providers/builtin.js +27 -0
  45. package/dist/ai/providers/catalog-data.js +1 -0
  46. package/dist/ai/providers/enrich.js +2 -7
  47. package/dist/ai/providers/models-dev-cache.js +15 -19
  48. package/dist/ai/providers/models-dev-snapshot.js +8 -7
  49. package/dist/ai/providers/models-dev.js +5 -15
  50. package/dist/ai/providers/suggest.js +2 -16
  51. package/dist/ai/types.d.ts +27 -1
  52. package/dist/auth/chatgpt/backend-client.d.ts +26 -0
  53. package/dist/auth/chatgpt/backend-client.js +74 -0
  54. package/dist/auth/chatgpt/claims.d.ts +17 -0
  55. package/dist/auth/chatgpt/claims.js +46 -0
  56. package/dist/auth/chatgpt/cli.d.ts +33 -0
  57. package/dist/auth/chatgpt/cli.js +252 -0
  58. package/dist/auth/chatgpt/doctor.d.ts +17 -0
  59. package/dist/auth/chatgpt/doctor.js +36 -0
  60. package/dist/auth/chatgpt/host-id.d.ts +7 -0
  61. package/dist/auth/chatgpt/host-id.js +26 -0
  62. package/dist/auth/chatgpt/login.d.ts +30 -0
  63. package/dist/auth/chatgpt/login.js +130 -0
  64. package/dist/auth/chatgpt/presets.d.ts +66 -0
  65. package/dist/auth/chatgpt/presets.js +120 -0
  66. package/dist/auth/chatgpt/quota-text.d.ts +13 -0
  67. package/dist/auth/chatgpt/quota-text.js +36 -0
  68. package/dist/auth/oauth/browser.d.ts +12 -0
  69. package/dist/auth/oauth/browser.js +27 -0
  70. package/dist/auth/oauth/callback-server.d.ts +47 -0
  71. package/dist/auth/oauth/callback-server.js +147 -0
  72. package/dist/auth/oauth/flows.d.ts +62 -0
  73. package/dist/auth/oauth/flows.js +113 -0
  74. package/dist/auth/oauth/jwt.d.ts +24 -0
  75. package/dist/auth/oauth/jwt.js +81 -0
  76. package/dist/auth/oauth/live.d.ts +21 -0
  77. package/dist/auth/oauth/live.js +25 -0
  78. package/dist/auth/oauth/oidc.d.ts +26 -0
  79. package/dist/auth/oauth/oidc.js +72 -0
  80. package/dist/auth/oauth/pkce.d.ts +15 -0
  81. package/dist/auth/oauth/pkce.js +20 -0
  82. package/dist/auth/oauth/refresh.d.ts +35 -0
  83. package/dist/auth/oauth/refresh.js +129 -0
  84. package/dist/auth/oauth/token-client.d.ts +33 -0
  85. package/dist/auth/oauth/token-client.js +121 -0
  86. package/dist/auth/oauth/token-store.d.ts +23 -0
  87. package/dist/auth/oauth/token-store.js +125 -0
  88. package/dist/auth/testing/fake-oauth.d.ts +73 -0
  89. package/dist/auth/testing/fake-oauth.js +271 -0
  90. package/dist/auth/testing/refresh-child.d.ts +5 -0
  91. package/dist/auth/testing/refresh-child.js +16 -0
  92. package/dist/bundle/ama.cjs +28307 -13241
  93. package/dist/checkpoints/backend.js +6 -5
  94. package/dist/checkpoints/restore.js +3 -2
  95. package/dist/checkpoints/settings.js +2 -1
  96. package/dist/checkpoints/shadow-git.js +7 -6
  97. package/dist/checkpoints/shadow-restore.js +3 -2
  98. package/dist/checkpoints/tracker.js +4 -3
  99. package/dist/cli/args.d.ts +9 -2
  100. package/dist/cli/args.js +74 -27
  101. package/dist/cli/bootstrap.js +53 -31
  102. package/dist/cli/choice-prompt.d.ts +58 -0
  103. package/dist/cli/choice-prompt.js +142 -0
  104. package/dist/cli/codemode-notice.js +2 -2
  105. package/dist/cli/compose-agents.js +2 -1
  106. package/dist/cli/compose-extensions.js +2 -0
  107. package/dist/cli/compose-memory.d.ts +53 -0
  108. package/dist/cli/compose-memory.js +127 -0
  109. package/dist/cli/compose-providers.d.ts +5 -0
  110. package/dist/cli/compose-providers.js +32 -2
  111. package/dist/cli/compose-session.d.ts +5 -0
  112. package/dist/cli/compose-session.js +27 -13
  113. package/dist/cli/compose-store.d.ts +2 -0
  114. package/dist/cli/compose-store.js +9 -5
  115. package/dist/cli/compose.d.ts +2 -0
  116. package/dist/cli/compose.js +13 -5
  117. package/dist/cli/default-model.d.ts +0 -2
  118. package/dist/cli/default-model.js +5 -8
  119. package/dist/cli/deps.d.ts +5 -1
  120. package/dist/cli/exit-codes.d.ts +1 -1
  121. package/dist/cli/exit-codes.js +7 -16
  122. package/dist/cli/from-prompt.js +3 -2
  123. package/dist/cli/help-text.d.ts +2 -1
  124. package/dist/cli/help-text.js +5 -99
  125. package/dist/cli/main.d.ts +5 -0
  126. package/dist/cli/main.js +21 -2
  127. package/dist/cli/proxy.js +14 -9
  128. package/dist/cli/runtime.d.ts +5 -0
  129. package/dist/cli/startup-screen.js +20 -27
  130. package/dist/cli/startup-steps.js +6 -8
  131. package/dist/cli/subcommands/auth.d.ts +6 -3
  132. package/dist/cli/subcommands/auth.js +52 -22
  133. package/dist/cli/subcommands/config-set.d.ts +21 -0
  134. package/dist/cli/subcommands/config-set.js +137 -0
  135. package/dist/cli/subcommands/config.d.ts +2 -1
  136. package/dist/cli/subcommands/config.js +51 -37
  137. package/dist/cli/subcommands/doctor.d.ts +2 -1
  138. package/dist/cli/subcommands/doctor.js +97 -58
  139. package/dist/cli/subcommands/init.d.ts +1 -1
  140. package/dist/cli/subcommands/init.js +8 -7
  141. package/dist/cli/subcommands/memory.d.ts +18 -0
  142. package/dist/cli/subcommands/memory.js +189 -0
  143. package/dist/cli/subcommands/model-meta.js +11 -9
  144. package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
  145. package/dist/cli/subcommands/models-cache-probe.js +26 -32
  146. package/dist/cli/subcommands/models-discover.d.ts +3 -0
  147. package/dist/cli/subcommands/models-discover.js +44 -21
  148. package/dist/cli/subcommands/models.d.ts +1 -1
  149. package/dist/cli/subcommands/models.js +29 -22
  150. package/dist/cli/subcommands/probe-runner.js +8 -7
  151. package/dist/cli/subcommands/providers-list.js +32 -21
  152. package/dist/cli/subcommands/providers-plan.js +24 -25
  153. package/dist/cli/subcommands/providers-probe.js +5 -6
  154. package/dist/cli/subcommands/providers.d.ts +2 -2
  155. package/dist/cli/subcommands/providers.js +48 -59
  156. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  157. package/dist/cli/subcommands/sessions-export.js +10 -9
  158. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  159. package/dist/cli/subcommands/sessions-search.js +11 -10
  160. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  161. package/dist/cli/subcommands/sessions-trace.js +156 -0
  162. package/dist/cli/subcommands/sessions.d.ts +4 -3
  163. package/dist/cli/subcommands/sessions.js +40 -37
  164. package/dist/cli/subcommands/stats.d.ts +1 -1
  165. package/dist/cli/subcommands/stats.js +49 -30
  166. package/dist/cli/system-prompt-arg.js +3 -2
  167. package/dist/codemode/capability.js +3 -2
  168. package/dist/compaction/post-compact.d.ts +1 -0
  169. package/dist/compaction/post-compact.js +15 -1
  170. package/dist/compaction/prune-tier.d.ts +1 -1
  171. package/dist/compaction/prune-tier.js +3 -3
  172. package/dist/compaction/serialize.js +2 -1
  173. package/dist/config/auth-file.d.ts +12 -2
  174. package/dist/config/auth-file.js +32 -10
  175. package/dist/config/checker.js +12 -11
  176. package/dist/config/context-files.js +3 -2
  177. package/dist/config/edit.d.ts +106 -0
  178. package/dist/config/edit.js +350 -0
  179. package/dist/config/init.d.ts +4 -3
  180. package/dist/config/init.js +10 -18
  181. package/dist/config/json-schema.d.ts +2 -1
  182. package/dist/config/json-schema.js +101 -68
  183. package/dist/config/key-docs.d.ts +18 -7
  184. package/dist/config/key-docs.js +43 -128
  185. package/dist/config/load.js +7 -6
  186. package/dist/config/merge.d.ts +4 -1
  187. package/dist/config/merge.js +42 -22
  188. package/dist/config/paths.js +6 -5
  189. package/dist/config/profile.d.ts +5 -1
  190. package/dist/config/profile.js +7 -2
  191. package/dist/config/schema-w5.js +3 -2
  192. package/dist/config/schema-w6.d.ts +19 -0
  193. package/dist/config/schema-w6.js +115 -0
  194. package/dist/config/schema.js +34 -20
  195. package/dist/config/settings-registry.d.ts +78 -0
  196. package/dist/config/settings-registry.js +184 -0
  197. package/dist/config/types-w6.d.ts +109 -0
  198. package/dist/config/types-w6.js +19 -0
  199. package/dist/config/types.d.ts +11 -8
  200. package/dist/config/types.js +1 -0
  201. package/dist/drivers/acp/client.js +1 -1
  202. package/dist/drivers/acp/driver.js +13 -8
  203. package/dist/drivers/agents.js +4 -3
  204. package/dist/drivers/base.js +3 -2
  205. package/dist/drivers/host-runners.js +2 -1
  206. package/dist/drivers/native/claude-stream.js +12 -11
  207. package/dist/drivers/native/codex-app-server.js +17 -12
  208. package/dist/drivers/native/oneshot.js +8 -7
  209. package/dist/drivers/pool.js +1 -1
  210. package/dist/drivers/runner.d.ts +3 -1
  211. package/dist/drivers/runner.js +68 -20
  212. package/dist/drivers/turn.js +1 -1
  213. package/dist/hooks/config.js +3 -2
  214. package/dist/hooks/protocol.js +18 -12
  215. package/dist/host/api-impl.js +11 -10
  216. package/dist/host/loader.js +9 -8
  217. package/dist/host/types.d.ts +3 -0
  218. package/dist/i18n/catalog.d.ts +2169 -0
  219. package/dist/i18n/catalog.js +72 -0
  220. package/dist/i18n/format.d.ts +21 -0
  221. package/dist/i18n/format.js +58 -0
  222. package/dist/i18n/index.d.ts +58 -0
  223. package/dist/i18n/index.js +72 -0
  224. package/dist/i18n/messages/agents.d.ts +84 -0
  225. package/dist/i18n/messages/agents.js +85 -0
  226. package/dist/i18n/messages/approval.d.ts +99 -0
  227. package/dist/i18n/messages/approval.js +100 -0
  228. package/dist/i18n/messages/auth.d.ts +187 -0
  229. package/dist/i18n/messages/auth.js +189 -0
  230. package/dist/i18n/messages/cli-args.d.ts +46 -0
  231. package/dist/i18n/messages/cli-args.js +46 -0
  232. package/dist/i18n/messages/cli-help.d.ts +12 -0
  233. package/dist/i18n/messages/cli-help.js +244 -0
  234. package/dist/i18n/messages/cli.d.ts +336 -0
  235. package/dist/i18n/messages/cli.js +311 -0
  236. package/dist/i18n/messages/config-keys.d.ts +289 -0
  237. package/dist/i18n/messages/config-keys.js +292 -0
  238. package/dist/i18n/messages/config.d.ts +502 -0
  239. package/dist/i18n/messages/config.js +239 -0
  240. package/dist/i18n/messages/drivers.d.ts +123 -0
  241. package/dist/i18n/messages/drivers.js +124 -0
  242. package/dist/i18n/messages/errors.d.ts +83 -0
  243. package/dist/i18n/messages/errors.js +171 -0
  244. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  245. package/dist/i18n/messages/interactive-line.js +69 -0
  246. package/dist/i18n/messages/interactive-startup.d.ts +103 -0
  247. package/dist/i18n/messages/interactive-startup.js +104 -0
  248. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  249. package/dist/i18n/messages/interactive-view.js +141 -0
  250. package/dist/i18n/messages/interactive.d.ts +493 -0
  251. package/dist/i18n/messages/interactive.js +248 -0
  252. package/dist/i18n/messages/memory.d.ts +123 -0
  253. package/dist/i18n/messages/memory.js +128 -0
  254. package/dist/i18n/messages/panels.d.ts +190 -0
  255. package/dist/i18n/messages/panels.js +189 -0
  256. package/dist/i18n/messages/permissions.d.ts +126 -0
  257. package/dist/i18n/messages/permissions.js +151 -0
  258. package/dist/i18n/messages/plan.d.ts +123 -0
  259. package/dist/i18n/messages/plan.js +124 -0
  260. package/dist/i18n/messages/print.d.ts +86 -0
  261. package/dist/i18n/messages/print.js +91 -0
  262. package/dist/i18n/messages/report.d.ts +391 -0
  263. package/dist/i18n/messages/report.js +490 -0
  264. package/dist/i18n/messages/rewind.d.ts +198 -0
  265. package/dist/i18n/messages/rewind.js +217 -0
  266. package/dist/i18n/messages/session.d.ts +230 -0
  267. package/dist/i18n/messages/session.js +258 -0
  268. package/dist/i18n/messages/settings.d.ts +348 -0
  269. package/dist/i18n/messages/settings.js +336 -0
  270. package/dist/i18n/messages/subcommands-config.d.ts +111 -0
  271. package/dist/i18n/messages/subcommands-config.js +127 -0
  272. package/dist/i18n/messages/subcommands.d.ts +548 -0
  273. package/dist/i18n/messages/subcommands.js +474 -0
  274. package/dist/i18n/messages/trace.d.ts +243 -0
  275. package/dist/i18n/messages/trace.js +238 -0
  276. package/dist/i18n/types.d.ts +15 -0
  277. package/dist/i18n/types.js +7 -0
  278. package/dist/index.d.ts +6 -0
  279. package/dist/index.js +2 -0
  280. package/dist/memory/edit.d.ts +24 -0
  281. package/dist/memory/edit.js +63 -0
  282. package/dist/memory/frontmatter.d.ts +37 -0
  283. package/dist/memory/frontmatter.js +79 -0
  284. package/dist/memory/index.d.ts +28 -0
  285. package/dist/memory/index.js +126 -0
  286. package/dist/memory/lock.d.ts +17 -0
  287. package/dist/memory/lock.js +62 -0
  288. package/dist/memory/paths.d.ts +57 -0
  289. package/dist/memory/paths.js +175 -0
  290. package/dist/memory/report.d.ts +36 -0
  291. package/dist/memory/report.js +86 -0
  292. package/dist/memory/runtime.d.ts +42 -0
  293. package/dist/memory/runtime.js +36 -0
  294. package/dist/memory/secrets.d.ts +8 -0
  295. package/dist/memory/secrets.js +27 -0
  296. package/dist/memory/section.d.ts +28 -0
  297. package/dist/memory/section.js +59 -0
  298. package/dist/memory/store.d.ts +70 -0
  299. package/dist/memory/store.js +284 -0
  300. package/dist/memory/tool.d.ts +31 -0
  301. package/dist/memory/tool.js +94 -0
  302. package/dist/modes/acp/acp-events.js +2 -1
  303. package/dist/modes/acp/acp-server.js +13 -12
  304. package/dist/modes/commands-core.d.ts +17 -0
  305. package/dist/modes/commands-core.js +101 -61
  306. package/dist/modes/image-input.js +20 -6
  307. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  308. package/dist/modes/interactive/agent-bar.js +248 -0
  309. package/dist/modes/interactive/agent-panels.js +27 -26
  310. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  311. package/dist/modes/interactive/agent-transcript.js +191 -0
  312. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  313. package/dist/modes/interactive/agent-ui.js +180 -14
  314. package/dist/modes/interactive/agent-view.d.ts +72 -0
  315. package/dist/modes/interactive/agent-view.js +281 -0
  316. package/dist/modes/interactive/approval-dialog.js +46 -34
  317. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  318. package/dist/modes/interactive/clipboard-paste.js +9 -4
  319. package/dist/modes/interactive/commands.d.ts +22 -1
  320. package/dist/modes/interactive/commands.js +93 -38
  321. package/dist/modes/interactive/completion.js +2 -1
  322. package/dist/modes/interactive/config-panel.d.ts +70 -0
  323. package/dist/modes/interactive/config-panel.js +319 -0
  324. package/dist/modes/interactive/config-ui.d.ts +96 -0
  325. package/dist/modes/interactive/config-ui.js +397 -0
  326. package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
  327. package/dist/modes/interactive/confirm-dialog.js +120 -0
  328. package/dist/modes/interactive/event-notices.js +11 -9
  329. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  330. package/dist/modes/interactive/interactive-mode.js +25 -22
  331. package/dist/modes/interactive/key-dispatch.d.ts +18 -0
  332. package/dist/modes/interactive/key-dispatch.js +39 -13
  333. package/dist/modes/interactive/line/line-editor.js +2 -1
  334. package/dist/modes/interactive/line/line-mode.d.ts +2 -0
  335. package/dist/modes/interactive/line/line-mode.js +24 -4
  336. package/dist/modes/interactive/line/line-render.js +25 -24
  337. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  338. package/dist/modes/interactive/memory-panel.js +221 -0
  339. package/dist/modes/interactive/message-view.d.ts +4 -2
  340. package/dist/modes/interactive/message-view.js +42 -33
  341. package/dist/modes/interactive/panels.js +39 -31
  342. package/dist/modes/interactive/pickers.d.ts +2 -1
  343. package/dist/modes/interactive/pickers.js +10 -6
  344. package/dist/modes/interactive/plan-command.d.ts +1 -1
  345. package/dist/modes/interactive/plan-command.js +24 -27
  346. package/dist/modes/interactive/plan-dialog.js +18 -17
  347. package/dist/modes/interactive/plan-flow.js +6 -5
  348. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  349. package/dist/modes/interactive/rewind-command.js +18 -16
  350. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  351. package/dist/modes/interactive/rewind-flow.js +13 -14
  352. package/dist/modes/interactive/rewind-list.js +7 -6
  353. package/dist/modes/interactive/rewind-panel.js +40 -40
  354. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  355. package/dist/modes/interactive/rewind-text.js +48 -38
  356. package/dist/modes/interactive/run-indicator.js +15 -12
  357. package/dist/modes/interactive/session-events.js +3 -2
  358. package/dist/modes/interactive/startup-header.js +22 -23
  359. package/dist/modes/interactive/startup-ui.js +41 -29
  360. package/dist/modes/interactive/status-area.d.ts +2 -0
  361. package/dist/modes/interactive/status-area.js +8 -2
  362. package/dist/modes/interactive/status-bar.js +4 -3
  363. package/dist/modes/interactive/subagent-view.js +9 -7
  364. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  365. package/dist/modes/interactive/tasks-report.js +28 -31
  366. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  367. package/dist/modes/interactive/terminal-setup.js +23 -0
  368. package/dist/modes/interactive/tool-summary.js +19 -17
  369. package/dist/modes/interactive/tool-view.js +7 -4
  370. package/dist/modes/interactive/trace-view.d.ts +89 -0
  371. package/dist/modes/interactive/trace-view.js +332 -0
  372. package/dist/modes/print/print-mode.js +14 -15
  373. package/dist/modes/rpc/commands.js +7 -3
  374. package/dist/modes/rpc/rpc-mode.js +9 -3
  375. package/dist/modes/session-report.d.ts +2 -0
  376. package/dist/modes/session-report.js +101 -105
  377. package/dist/modes/startup-ui-text.js +11 -6
  378. package/dist/permissions/bypass.d.ts +30 -0
  379. package/dist/permissions/bypass.js +45 -0
  380. package/dist/permissions/memory-class.d.ts +23 -0
  381. package/dist/permissions/memory-class.js +54 -0
  382. package/dist/permissions/modes.d.ts +3 -3
  383. package/dist/permissions/modes.js +21 -16
  384. package/dist/permissions/pipeline.d.ts +1 -1
  385. package/dist/permissions/pipeline.js +9 -2
  386. package/dist/permissions/preview.js +49 -42
  387. package/dist/permissions/rules.js +5 -2
  388. package/dist/permissions/types.d.ts +4 -0
  389. package/dist/plan/store.js +2 -1
  390. package/dist/rpc.d.ts +39 -1
  391. package/dist/rpc.js +3 -0
  392. package/dist/sandbox/bash.js +11 -8
  393. package/dist/sandbox/detect.js +14 -11
  394. package/dist/sdk.d.ts +17 -1
  395. package/dist/sdk.js +29 -7
  396. package/dist/session/export.js +31 -30
  397. package/dist/session/manager.d.ts +1 -1
  398. package/dist/session/manager.js +5 -3
  399. package/dist/session/reuse.js +5 -4
  400. package/dist/session/scan.js +3 -2
  401. package/dist/session/stats-aggregate.d.ts +3 -1
  402. package/dist/session/stats-aggregate.js +5 -1
  403. package/dist/session/stats-index.js +2 -1
  404. package/dist/session/stats-scan.d.ts +4 -1
  405. package/dist/session/stats-scan.js +6 -2
  406. package/dist/session/store.d.ts +11 -0
  407. package/dist/session/store.js +48 -1
  408. package/dist/session/types.d.ts +2 -0
  409. package/dist/skills/builtin.js +2 -1
  410. package/dist/tools/image-file.d.ts +26 -1
  411. package/dist/tools/image-file.js +55 -13
  412. package/dist/tools/presets.d.ts +14 -1
  413. package/dist/tools/presets.js +3 -3
  414. package/dist/tools/registry.js +1 -1
  415. package/dist/tools/truncate.d.ts +1 -1
  416. package/dist/tools/truncate.js +2 -2
  417. package/dist/tools/types.d.ts +17 -1
  418. package/dist/trace/build-index.d.ts +91 -0
  419. package/dist/trace/build-index.js +127 -0
  420. package/dist/trace/build-nodes.d.ts +24 -0
  421. package/dist/trace/build-nodes.js +279 -0
  422. package/dist/trace/build-util.d.ts +43 -0
  423. package/dist/trace/build-util.js +120 -0
  424. package/dist/trace/build.d.ts +82 -0
  425. package/dist/trace/build.js +382 -0
  426. package/dist/trace/detail.d.ts +35 -0
  427. package/dist/trace/detail.js +205 -0
  428. package/dist/trace/flatten.d.ts +69 -0
  429. package/dist/trace/flatten.js +173 -0
  430. package/dist/trace/format.d.ts +47 -0
  431. package/dist/trace/format.js +329 -0
  432. package/dist/trace/html-template.d.ts +19 -0
  433. package/dist/trace/html-template.js +150 -0
  434. package/dist/trace/html.d.ts +104 -0
  435. package/dist/trace/html.js +292 -0
  436. package/dist/trace/preview.d.ts +29 -0
  437. package/dist/trace/preview.js +59 -0
  438. package/dist/trace/query-session.d.ts +14 -0
  439. package/dist/trace/query-session.js +38 -0
  440. package/dist/trace/query.d.ts +55 -0
  441. package/dist/trace/query.js +188 -0
  442. package/dist/trace/session.d.ts +40 -0
  443. package/dist/trace/session.js +168 -0
  444. package/dist/trace/types.d.ts +243 -0
  445. package/dist/trace/types.js +13 -0
  446. package/dist/tui/components/editor-paste.d.ts +2 -0
  447. package/dist/tui/components/editor-paste.js +6 -3
  448. package/dist/tui/components/editor.js +2 -2
  449. package/dist/tui/components/loader.d.ts +3 -0
  450. package/dist/tui/components/loader.js +14 -0
  451. package/dist/tui/components/settings-list.d.ts +61 -0
  452. package/dist/tui/components/settings-list.js +135 -0
  453. package/dist/tui/keybindings.d.ts +6 -1
  454. package/dist/tui/keybindings.js +18 -6
  455. package/dist/tui.d.ts +1 -0
  456. package/dist/tui.js +2 -0
  457. package/docs/en/host-api.md +167 -0
  458. package/docs/en/permissions.md +214 -0
  459. package/docs/en/providers.md +625 -0
  460. package/docs/en/rpc.md +361 -0
  461. package/docs/en/sessions.md +219 -0
  462. package/docs/en/tui.md +527 -0
  463. package/docs/host-api.md +18 -17
  464. package/docs/memory.md +172 -0
  465. package/docs/permissions.md +3 -2
  466. package/docs/providers.md +67 -1
  467. package/docs/rpc.md +31 -3
  468. package/docs/session-format.md +8 -2
  469. package/docs/sessions.md +29 -1
  470. package/docs/tui.md +189 -21
  471. package/package.json +8 -3
@@ -7,13 +7,14 @@
7
7
  * (字段缺失或恒 0);其余(读到一点、只有写入)→ `inconclusive`(粒度或 TTL 问题)。
8
8
  *
9
9
  * 计费动作:执行前打印预估(两次 × `--tokens` × 目录输入价,无价 `$?`);非 TTY 必须 `--yes`
10
- * (否则退出 2),TTY 下问一次 y/N。`--json` 时预估写 stderr,stdout 只有一个结果对象。
10
+ * (否则退出 2),TTY 下方向键选一次「继续 / 取消」(choice-prompt.ts)。`--json` 时预估写 stderr,stdout 只有一个结果对象。
11
11
  * 协议层不保留原始响应,「usage 字段」列的是该协议解析时读取的字段名。
12
12
  */
13
- import { createInterface } from "node:readline/promises";
14
13
  import { priceTokens } from "../../ai/cost.js";
15
14
  import { UsageError } from "../args.js";
15
+ import { confirmContinue } from "../choice-prompt.js";
16
16
  import { ExitCode } from "../exit-codes.js";
17
+ import { msg } from "../../i18n/index.js";
17
18
  export const PROBE_DEFAULT_TOKENS = 2048;
18
19
  export const PROBE_DEFAULT_GAP_MS = 3000;
19
20
  export const PROBE_REQUEST_TIMEOUT_MS = 60_000;
@@ -56,17 +57,16 @@ export function judgeProbe(first, second) {
56
57
  return any === 0 ? "silent" : "inconclusive";
57
58
  }
58
59
  export function probeAdvice(verdict, model, samples = []) {
60
+ const t = msg().subcommands.cacheProbe;
59
61
  if (verdict === "silent") {
60
62
  // 实测:同一中转的 Kimi 间隔 3 s 两次都是 0、间隔更久才命中——字段存在时提示写入延迟的可能
61
- const present = samples.some((s) => s.cacheReported === true)
62
- ? "(响应里有缓存字段但恒为 0;也可能是缓存写入有延迟,可加大 --gap-ms 再测一次)"
63
- : "";
64
- return `可在 config 里设 providers.${model.provider}.compat.cacheReporting: "silent",状态栏将显示未报告${present}`;
63
+ const present = samples.some((s) => s.cacheReported === true);
64
+ return t.adviceSilent(model.provider, present);
65
65
  }
66
66
  if (verdict === "inconclusive")
67
- return "第二次只读到少量缓存或只有写入:可能是缓存粒度或 TTL 问题,可加大 --tokens 或缩短 --gap-ms 重试";
67
+ return t.adviceInconclusive;
68
68
  if (model.promptCache === undefined)
69
- return `可自填 promptCache.short 以启用保温(providers.${model.provider}.modelOverrides: [{ "id": "${model.id}", "promptCache": { "short": 300 } }])`;
69
+ return t.advicePromptCache(model.provider, model.id);
70
70
  return undefined;
71
71
  }
72
72
  function intOption(ctx, name, fallback, min) {
@@ -75,21 +75,13 @@ function intOption(ctx, name, fallback, min) {
75
75
  return fallback;
76
76
  const value = Number(raw);
77
77
  if (!Number.isInteger(value) || value < min)
78
- throw new UsageError(`--${name} 应为不小于 ${min} 的整数`);
78
+ throw new UsageError(msg().subcommands.cacheProbe.intAtLeast(name, min));
79
79
  return value;
80
80
  }
81
- async function confirm() {
82
- const rl = createInterface({ input: process.stdin, output: process.stderr });
83
- try {
84
- return /^y(es)?$/i.test((await rl.question("继续?[y/N] ")).trim());
85
- }
86
- finally {
87
- rl.close();
88
- }
89
- }
90
81
  function sampleLine(index, s) {
91
- const field = s.cacheReported === undefined ? "?" : s.cacheReported ? "有" : "无";
92
- return `#${index} input ${s.input} · cacheRead ${s.cacheRead} · cacheWrite ${s.cacheWrite} · 缓存字段 ${field}`;
82
+ const t = msg().subcommands.cacheProbe;
83
+ const field = s.cacheReported === undefined ? "?" : s.cacheReported ? t.yes : t.no;
84
+ return t.sample(index, s.input, s.cacheRead, s.cacheWrite, field);
93
85
  }
94
86
  async function run(ctx) {
95
87
  const { io, registry } = ctx;
@@ -99,31 +91,33 @@ async function run(ctx) {
99
91
  const json = ctx.flags.has("json");
100
92
  const found = registry.findModel(ref);
101
93
  if (!found.ok) {
102
- io.stderr(`ama: 模型不存在:${ref}\n`);
94
+ io.stderr(msg().subcommands.common.modelNotFound(ref));
103
95
  return ExitCode.NoModel;
104
96
  }
105
97
  const { model, provider } = found;
106
98
  const key = await registry.resolveApiKey(provider.id, model.channel);
107
99
  if (key.apiKey === undefined && provider.requiresApiKey) {
108
- io.stderr(`ama: ${provider.id} 没有 API key(ama auth set ${provider.id})\n`);
100
+ io.stderr(msg().subcommands.common.noApiKey(provider.id));
109
101
  return ExitCode.NoModel;
110
102
  }
111
103
  const api = registry.getApi(model.api);
112
104
  if (api === undefined) {
113
- io.stderr(`ama: 协议 ${model.api} 尚未实现\n`);
105
+ io.stderr(msg().subcommands.common.apiNotImplemented(model.api));
114
106
  return ExitCode.RuntimeError;
115
107
  }
116
108
  const estimate = priceTokens(model, { input: tokens * 2, output: 32 });
117
109
  const name = `${provider.id}/${model.id}`;
118
- const head = `cache-probe ${name}(${model.api})· 前缀约 ${tokens} token · 间隔 ${gapMs} ms\n预估花费:${estimate === undefined ? "$?" : `$${estimate.toFixed(4)}`}(两次 × ${tokens} token × 目录价)\n`;
110
+ const t = msg().subcommands.cacheProbe;
111
+ const cost = estimate === undefined ? "$?" : `$${estimate.toFixed(4)}`;
112
+ const head = t.head(name, model.api, tokens, gapMs, cost);
119
113
  (json ? io.stderr : io.stdout)(head);
120
114
  if (!ctx.flags.has("yes")) {
121
115
  if (!io.stdinIsTTY) {
122
- io.stderr("ama: cache-probe 会发两次计费请求,非交互环境需加 --yes\n");
116
+ io.stderr(t.needsYes);
123
117
  return ExitCode.Usage;
124
118
  }
125
- if (!(await confirm())) {
126
- io.stderr("ama: 已取消\n");
119
+ if (!(await confirmContinue({ env: io.env }))) {
120
+ io.stderr(msg().subcommands.common.cancelled);
127
121
  return ExitCode.Ok;
128
122
  }
129
123
  }
@@ -145,7 +139,7 @@ async function run(ctx) {
145
139
  })
146
140
  .result();
147
141
  if (message.stopReason === "error" || message.stopReason === "aborted") {
148
- io.stderr(`ama: 第 ${i + 1} 次请求失败:${message.errorMessage ?? message.stopReason}\n`);
142
+ io.stderr(t.requestFailed(i + 1, message.errorMessage ?? message.stopReason));
149
143
  return ExitCode.RuntimeError;
150
144
  }
151
145
  samples.push(sampleOf(message.usage));
@@ -170,14 +164,14 @@ async function run(ctx) {
170
164
  return ExitCode.Ok;
171
165
  }
172
166
  const share = first.promptTokens > 0
173
- ? `(第二次读到前缀的 ${Math.round((second.cacheRead / first.promptTokens) * 100)}%)`
167
+ ? t.share(Math.round((second.cacheRead / first.promptTokens) * 100))
174
168
  : "";
175
169
  io.stdout([
176
170
  sampleLine(1, first),
177
171
  sampleLine(2, second),
178
- ...(fields.length > 0 ? [`usage 字段(${model.api} 读取):${fields.join(" / ")}`] : []),
179
- `判定:${verdict}${share}`,
180
- ...(advice !== undefined ? [`建议:${advice}`] : []),
172
+ ...(fields.length > 0 ? [t.usageFields(model.api, fields)] : []),
173
+ t.verdict(verdict, share),
174
+ ...(advice !== undefined ? [t.advice(advice)] : []),
181
175
  ].join("\n") + "\n");
182
176
  return ExitCode.Ok;
183
177
  }
@@ -16,6 +16,9 @@
16
16
  *
17
17
  * models.dev:列表之后按需刷新缓存(24 小时内不重拉),每个模型标出上下文、输出、图片、工具调用与
18
18
  * 匹配结果;`--write` 跳过 models.dev 标明不支持工具调用的模型。元数据不写进配置——运行时从缓存补。
19
+ *
20
+ * [W6-O] `chatgpt`:按登录的 flavor 调对应后端的模型列表(SIWC `GET /v1/models` 筛 `visibility: list`;codex
21
+ * `GET /models?client_version=…`),只取 slug 与显示名;`--probe` 不适用(订阅后端只有一种协议)。
19
22
  */
20
23
  import type { Api, Model, ProviderData, ProviderRegistryApi } from "../../ai/types.js";
21
24
  import type { ModelsAction } from "./models.js";
@@ -16,8 +16,14 @@
16
16
  *
17
17
  * models.dev:列表之后按需刷新缓存(24 小时内不重拉),每个模型标出上下文、输出、图片、工具调用与
18
18
  * 匹配结果;`--write` 跳过 models.dev 标明不支持工具调用的模型。元数据不写进配置——运行时从缓存补。
19
+ *
20
+ * [W6-O] `chatgpt`:按登录的 flavor 调对应后端的模型列表(SIWC `GET /v1/models` 筛 `visibility: list`;codex
21
+ * `GET /models?client_version=…`),只取 slug 与显示名;`--probe` 不适用(订阅后端只有一种协议)。
19
22
  */
20
23
  import { authHeaders, mergeHeaders } from "../../ai/http.js";
24
+ import { listChatGptModels } from "../../auth/chatgpt/backend-client.js";
25
+ import { CHATGPT_PROVIDER_ID } from "../../auth/chatgpt/presets.js";
26
+ import { liveToken } from "../../auth/oauth/live.js";
21
27
  import { discoverLocalModels, materializeModel } from "../../ai/providers/registry.js";
22
28
  import { withCustomDefaults } from "../../ai/providers/catalog.js";
23
29
  import { describeModelsDev, loadModelsDevIndex } from "../../ai/providers/models-dev-cache.js";
@@ -26,6 +32,7 @@ import { existsSync } from "node:fs";
26
32
  import { loadConfigFile } from "../../config/load.js";
27
33
  import { writeConfigFile } from "../../config/write.js";
28
34
  import { UsageError } from "../args.js";
35
+ import { msg } from "../../i18n/index.js";
29
36
  import { ExitCode } from "../exit-codes.js";
30
37
  import { compactTokens } from "./model-meta.js";
31
38
  import { describeProbePlan, parseProbeTuning, ProbeProgress, ProbeScheduler, } from "./probe-runner.js";
@@ -47,6 +54,23 @@ export function modelsUrl(provider) {
47
54
  }
48
55
  export async function discoverModels(provider, apiKey, options = {}) {
49
56
  const timeoutMs = options.timeoutMs ?? DISCOVER_TIMEOUT_MS;
57
+ if (provider.id === CHATGPT_PROVIDER_ID && apiKey !== undefined) {
58
+ const live = liveToken(apiKey);
59
+ const flavor = live?.flavor ?? (provider.defaultChannel === "codex" ? "codex" : "siwc");
60
+ const channel = provider.channels?.find((c) => c.name === flavor);
61
+ const models = await listChatGptModels(fetch, channel?.baseUrl ?? provider.baseUrl, {
62
+ flavor,
63
+ accessToken: apiKey,
64
+ accountId: live?.accountId,
65
+ originator: channel?.headers?.["originator"],
66
+ });
67
+ return models.map((m) => {
68
+ const model = withCustomDefaults({ id: m.id }, provider.id, provider.api);
69
+ if (m.name !== undefined)
70
+ model.name = m.name;
71
+ return model;
72
+ });
73
+ }
50
74
  if (!provider.requiresApiKey && apiKey === undefined)
51
75
  return discoverLocalModels(provider, { timeoutMs });
52
76
  const anthropic = provider.api === "anthropic-messages";
@@ -114,17 +138,18 @@ function parseLimit(raw) {
114
138
  return DEFAULT_PROBE_LIMIT;
115
139
  const n = Number(raw);
116
140
  if (!Number.isInteger(n) || n < 1)
117
- throw new UsageError(`--limit 需要正整数:${raw}`);
141
+ throw new UsageError(msg().subcommands.discover.limitPositive(raw));
118
142
  return n;
119
143
  }
120
144
  /** 把新条目合并进用户级 config.json;返回写入条数。 */
121
145
  function writeEntries(ctx, provider, entries, notes) {
122
146
  const { io } = ctx;
147
+ const m = msg().subcommands.discover;
123
148
  const path = ctx.level.userConfigPath;
124
149
  const config = structuredClone(loadConfigFile("config", path)?.value ?? { version: 1 });
125
150
  const providers = (config.providers ??= {});
126
151
  if (providers[provider.id] === undefined && !provider.builtin) {
127
- io.stderr(`ama: ${provider.id} 不在用户级配置(${path})里,未写入\n`);
152
+ io.stderr(m.notInUserConfig(provider.id, path));
128
153
  return 0;
129
154
  }
130
155
  const target = (providers[provider.id] ??= {});
@@ -133,34 +158,33 @@ function writeEntries(ctx, provider, entries, notes) {
133
158
  const added = entries.filter((entry) => !existing.has(entry.id));
134
159
  const kept = entries.length - added.length;
135
160
  if (added.length === 0) {
136
- io.stdout(`\n没有新模型要写入${kept > 0 ? `(${kept} 个已存在,未覆盖)` : ""}\n`);
161
+ io.stdout(m.nothingToWrite(kept));
137
162
  return 0;
138
163
  }
139
164
  models.push(...added);
140
165
  const backup = existsSync(path);
141
166
  writeConfigFile(path, config, { backup: true });
142
- io.stdout(`\n已写入 ${path}:${provider.id} 新增 ${added.length} 个模型` +
143
- `${kept > 0 ? `,${kept} 个已存在未覆盖` : ""}${backup ? `(原文件备份为 ${path}.bak)` : ""}\n`);
167
+ io.stdout(m.written(path, provider.id, added.length, kept, backup));
144
168
  if (notes.noTools.size > 0)
145
- io.stdout(`跳过不支持工具调用的模型(models.dev):${[...notes.noTools].join(", ")}\n`);
169
+ io.stdout(m.skippedNoTools([...notes.noTools].join(", ")));
146
170
  const blind = added.filter((entry) => notes.unmatched.has(entry.id)).map((entry) => entry.id);
147
171
  if (blind.length > 0)
148
- io.stderr(`ama: 警告:${blind.join(", ")} 在 models.dev 未匹配,没有 contextWindow,自动压缩关闭;` +
149
- `需要时在 config.json 里补上或写 modelsDev\n`);
172
+ io.stderr(m.unmatchedWarning(blind.join(", ")));
150
173
  return added.length;
151
174
  }
152
175
  async function run(ctx) {
153
176
  const { io, registry } = ctx;
177
+ const m = msg().subcommands.discover;
154
178
  const id = ctx.args[0] ?? "";
155
179
  const limit = parseLimit(ctx.values.get("limit"));
156
180
  const provider = registry.get(id);
157
181
  if (provider === undefined) {
158
- io.stderr(`ama: 供应商不存在:${id}\n`);
182
+ io.stderr(msg().subcommands.common.providerNotFound(id));
159
183
  return ExitCode.NoModel;
160
184
  }
161
185
  const key = await registry.resolveApiKey(provider.id);
162
186
  if (key.apiKey === undefined && provider.requiresApiKey) {
163
- io.stderr(`ama: ${provider.id} 没有 API key(ama auth set ${provider.id})\n`);
187
+ io.stderr(msg().subcommands.common.noApiKey(provider.id));
164
188
  return ExitCode.NoModel;
165
189
  }
166
190
  let found;
@@ -168,11 +192,11 @@ async function run(ctx) {
168
192
  found = await discoverModels(provider, key.apiKey);
169
193
  }
170
194
  catch (error) {
171
- io.stderr(`ama: ${provider.id} 模型列表获取失败:${error.message}\n`);
195
+ io.stderr(m.listFailed(provider.id, error.message));
172
196
  return ExitCode.RuntimeError;
173
197
  }
174
198
  const configured = new Map(provider.models.map((m) => [m.id, m]));
175
- io.stdout(`${provider.id}:发现 ${found.length} 个模型(${modelsUrl(provider)})\n`);
199
+ io.stdout(m.found(provider.id, found.length, modelsUrl(provider)));
176
200
  // models.dev 只读本地(快照 ⊕ `ama models refresh` 的覆盖),不联网。
177
201
  const mdIndex = loadModelsDevIndex(ctx.level.dataDir);
178
202
  io.stdout(`${describeModelsDev(ctx.level.dataDir)}\n`);
@@ -187,14 +211,14 @@ async function run(ctx) {
187
211
  if (match === undefined)
188
212
  unmatched.add(model.id);
189
213
  const meta = fields === undefined
190
- ? " models.dev 未匹配"
214
+ ? m.unmatched
191
215
  : ` 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`);
216
+ `${fields.input?.includes("image") ? m.image : ""}${fields.reasoning ? m.reasoning : ""}` +
217
+ `${fields.toolCall === false ? m.noTools : ""} · ${matchLabel(match)}`;
218
+ io.stdout(` ${model.id}${known !== undefined ? m.configured(known.api) : ""}${meta}\n`);
195
219
  }
196
220
  const write = ctx.flags.has("write");
197
- if (!ctx.flags.has("probe")) {
221
+ if (!ctx.flags.has("probe") || provider.id === CHATGPT_PROVIDER_ID) {
198
222
  if (write)
199
223
  writeEntries(ctx, provider, found.filter((m) => !noTools.has(m.id)).map((m) => ({ id: m.id })), { noTools, unmatched });
200
224
  return ExitCode.Ok;
@@ -203,15 +227,14 @@ async function run(ctx) {
203
227
  const count = Math.min(limit, ids.length);
204
228
  const order = probeOrder(provider);
205
229
  const tuning = parseProbeTuning(ctx.values);
206
- io.stdout(`\n探测协议:${count} 个模型(${order.join(" → ")}),最多 ${count * order.length} 次请求` +
207
- `${ids.length > count ? `;另有 ${ids.length - count} 个超出 --limit ${limit},未探测` : ""}\n` +
230
+ io.stdout(m.probeHeader(count, order.join(" → "), count * order.length, ids.length - count, limit) +
208
231
  `${describeProbePlan(count * order.length, tuning.concurrency, tuning.timeoutMs)}\n`);
209
232
  let stopped;
210
233
  const progress = new ProbeProgress(io.stdout, io.stdoutIsTTY, count);
211
234
  const probed = await probeModelApis(registry, provider, ids, limit, {
212
235
  ...tuning,
213
236
  onSettled: () => progress.tick(),
214
- onResult: (modelId, api) => progress.line(` ${modelId} ${api ?? "不可用(三种协议均失败)"}\n`),
237
+ onResult: (modelId, api) => progress.line(` ${modelId} ${api ?? m.unavailable}\n`),
215
238
  onStop: (reason) => (stopped = reason),
216
239
  });
217
240
  progress.finish();
@@ -224,7 +247,7 @@ async function run(ctx) {
224
247
  writeEntries(ctx, provider, entries, { noTools, unmatched });
225
248
  }
226
249
  if (stopped !== undefined) {
227
- io.stderr(`ama: 探测提前停止(${stopped})\n`);
250
+ io.stderr(m.probeStopped(stopped));
228
251
  return ExitCode.RuntimeError;
229
252
  }
230
253
  return ExitCode.Ok;
@@ -38,5 +38,5 @@ export interface ModelsAction {
38
38
  export declare const CHECK_TIMEOUT_MS = 30000;
39
39
  /** 动作表:键是子命令名,顺序即用法文本顺序。 */
40
40
  export declare const MODELS_ACTIONS: Readonly<Record<string, ModelsAction>>;
41
- export declare const MODELS_USAGE: string;
41
+ export declare function modelsUsage(): string;
42
42
  export declare function runModels(argv: readonly string[], io: CliIo, deps: Pick<RuntimeDeps, "providers"> | undefined): Promise<number>;
@@ -19,21 +19,23 @@ import { buildRegistry, loadUserLevel } from "./context.js";
19
19
  import { CACHE_PROBE_ACTION } from "./models-cache-probe.js";
20
20
  import { DISCOVER_ACTION } from "./models-discover.js";
21
21
  import { metadataOf, modelFlags, sourcesLine } from "./model-meta.js";
22
+ import { msg } from "../../i18n/index.js";
22
23
  const COMMON_VALUE_OPTIONS = ["profile", "auth-file"];
23
24
  export const CHECK_TIMEOUT_MS = 30_000;
24
25
  async function list(io, registry, only) {
25
26
  const providers = registry.list().filter((p) => only === undefined || p.id === only);
26
27
  if (only !== undefined && providers.length === 0) {
27
- io.stderr(`ama: 供应商不存在:${only}\n`);
28
+ io.stderr(msg().subcommands.common.providerNotFound(only));
28
29
  return ExitCode.NoModel;
29
30
  }
30
31
  for (const provider of providers) {
31
32
  const key = await registry.resolveApiKey(provider.id);
33
+ const t = msg().subcommands.models;
32
34
  const keyText = key.apiKey !== undefined
33
- ? `key:${key.source}${key.origin !== undefined ? `(${key.origin})` : ""}`
35
+ ? t.keyFrom(key.source, key.origin)
34
36
  : provider.requiresApiKey
35
- ? "无 key"
36
- : "无需 key";
37
+ ? t.noKey
38
+ : t.keyNotNeeded;
37
39
  io.stdout(`${provider.id} ${provider.api} ${keyText}\n`);
38
40
  for (const channel of provider.channels ?? [])
39
41
  io.stdout(` @${channel.name} ${channel.api} ${channel.baseUrl}\n`);
@@ -49,19 +51,18 @@ async function list(io, registry, only) {
49
51
  async function check(io, registry, ref) {
50
52
  const found = registry.findModel(ref);
51
53
  if (!found.ok) {
52
- const hint = found.candidates.length > 0 ? `;候选:${found.candidates.slice(0, 10).join(", ")}` : "";
53
- io.stderr(`ama: 模型不存在:${ref}${hint}\n`);
54
+ io.stderr(msg().subcommands.common.modelNotFound(ref, found.candidates.slice(0, 10)));
54
55
  return ExitCode.NoModel;
55
56
  }
56
57
  const { model, provider } = found;
57
58
  const key = await registry.resolveApiKey(provider.id, model.channel);
58
59
  if (key.apiKey === undefined && provider.requiresApiKey) {
59
- io.stderr(`ama: ${provider.id} 没有 API key(ama auth set ${provider.id})\n`);
60
+ io.stderr(msg().subcommands.common.noApiKey(provider.id));
60
61
  return ExitCode.NoModel;
61
62
  }
62
63
  const api = registry.getApi(model.api);
63
64
  if (api === undefined) {
64
- io.stderr(`ama: 协议 ${model.api} 尚未实现\n`);
65
+ io.stderr(msg().subcommands.common.apiNotImplemented(model.api));
65
66
  return ExitCode.RuntimeError;
66
67
  }
67
68
  const started = Date.now();
@@ -74,11 +75,11 @@ async function check(io, registry, ref) {
74
75
  const message = await stream.result();
75
76
  const ms = Date.now() - started;
76
77
  if (message.stopReason === "error" || message.stopReason === "aborted") {
77
- io.stderr(`ama: ${provider.id}/${model.id} 失败(${ms} ms):${message.errorMessage ?? message.stopReason}\n`);
78
+ io.stderr(msg().subcommands.models.checkFailed(`${provider.id}/${model.id}`, ms, message.errorMessage ?? message.stopReason));
78
79
  return ExitCode.RuntimeError;
79
80
  }
80
81
  const shown = formatModelRef(modelRefOf(model));
81
- io.stdout(`${shown} 可用(${model.api},${ms} ms,stopReason ${message.stopReason})\n`);
82
+ io.stdout(msg().subcommands.models.checkOk(shown, model.api, ms, message.stopReason));
82
83
  return ExitCode.Ok;
83
84
  }
84
85
  /**
@@ -94,7 +95,7 @@ const REFRESH_ACTION = {
94
95
  ?.split(",")
95
96
  .map((p) => p.trim())
96
97
  .filter(Boolean);
97
- ctx.io.stdout(`内置快照:${snapshotMeta().fetchedAt};正在拉取 models.dev…\n`);
98
+ ctx.io.stdout(msg().subcommands.models.refreshing(snapshotMeta().fetchedAt));
98
99
  const result = await refreshModelsDev({
99
100
  dataDir: ctx.level.dataDir,
100
101
  env: ctx.io.env,
@@ -105,7 +106,7 @@ const REFRESH_ACTION = {
105
106
  ctx.io.stdout(`${describeRefresh(result)}\n`);
106
107
  if (result.status === "failed")
107
108
  return ExitCode.RuntimeError;
108
- ctx.io.stdout(`已写入 ${modelsDevCachePath(ctx.level.dataDir)}\n`);
109
+ ctx.io.stdout(msg().subcommands.models.written(modelsDevCachePath(ctx.level.dataDir)));
109
110
  return ExitCode.Ok;
110
111
  },
111
112
  };
@@ -124,11 +125,17 @@ export const MODELS_ACTIONS = Object.freeze({
124
125
  discover: DISCOVER_ACTION,
125
126
  "cache-probe": CACHE_PROBE_ACTION,
126
127
  refresh: REFRESH_ACTION,
127
- "refresh-catalog": { ...REFRESH_ACTION, usage: "ama models refresh-catalog(refresh 的旧名)" },
128
+ // 用法行按界面语言取,用 getter(模块级求值会按 import 时的语言定死)
129
+ "refresh-catalog": {
130
+ ...REFRESH_ACTION,
131
+ get usage() {
132
+ return msg().subcommands.models.refreshCatalogUsage;
133
+ },
134
+ },
128
135
  });
129
- export const MODELS_USAGE = `用法:${Object.values(MODELS_ACTIONS)
130
- .map((a) => a.usage)
131
- .join("\n ")}\n`;
136
+ export function modelsUsage() {
137
+ return msg().subcommands.models.usage(Object.values(MODELS_ACTIONS).map((a) => a.usage));
138
+ }
132
139
  function unique(lists) {
133
140
  return [...new Set(lists.flatMap((l) => l ?? []))];
134
141
  }
@@ -137,12 +144,12 @@ export async function runModels(argv, io, deps) {
137
144
  const { positionals, values, flags } = parseSubArgs(argv, unique([...actions.map((a) => a.valueOptions), COMMON_VALUE_OPTIONS]), unique(actions.map((a) => a.flagOptions)));
138
145
  const name = positionals[0];
139
146
  if (flags.has("help") || name === undefined) {
140
- io.stdout(MODELS_USAGE);
147
+ io.stdout(modelsUsage());
141
148
  return flags.has("help") ? ExitCode.Ok : ExitCode.Usage;
142
149
  }
143
150
  const action = Object.hasOwn(MODELS_ACTIONS, name) ? MODELS_ACTIONS[name] : undefined;
144
151
  if (action === undefined)
145
- throw new UsageError(`未知的 models 子命令:${name}`);
152
+ throw new UsageError(msg().subcommands.common.unknownSubcommand("models", name));
146
153
  // 选项按全部动作的并集解析;这里再拒绝不属于本动作的(如 `list --json`)。
147
154
  for (const option of [...values.keys(), ...flags]) {
148
155
  const own = [
@@ -151,13 +158,13 @@ export async function runModels(argv, io, deps) {
151
158
  ...(action.flagOptions ?? []),
152
159
  ];
153
160
  if (!own.includes(option))
154
- throw new UsageError(`未知选项:--${option}`);
161
+ throw new UsageError(msg().subcommands.common.unknownOption(option));
155
162
  }
156
163
  const args = positionals.slice(1);
157
164
  if (action.required !== undefined && args[0] === undefined)
158
- throw new UsageError(`ama models ${name} 需要 ${action.required}`);
165
+ throw new UsageError(msg().subcommands.common.needsArg(`ama models ${name}`, action.required));
159
166
  if (deps === undefined) {
160
- io.stderr("ama: models 尚未装配(供应商注册表由集成批次注入)\n");
167
+ io.stderr(msg().subcommands.common.notAssembled("models"));
161
168
  return ExitCode.RuntimeError;
162
169
  }
163
170
  const level = loadUserLevel(io, {
@@ -165,7 +172,7 @@ export async function runModels(argv, io, deps) {
165
172
  authFile: values.get("auth-file"),
166
173
  });
167
174
  for (const warning of level.warnings)
168
- io.stderr(`ama: 警告:${warning}\n`);
175
+ io.stderr(msg().subcommands.common.warning(warning));
169
176
  const registry = await buildRegistry(level, io, deps);
170
177
  return action.run({ io, registry, level, args, values, flags });
171
178
  }
@@ -13,6 +13,7 @@
13
13
  * `ama models check` 不走这里:它只发一次,要看到完整回复与耗时。
14
14
  */
15
15
  import { UsageError } from "../args.js";
16
+ import { msg } from "../../i18n/index.js";
16
17
  export const PROBE_TIMEOUT_MS = 15_000;
17
18
  export const DEFAULT_PROBE_CONCURRENCY = 6;
18
19
  export const MAX_PROBE_CONCURRENCY = 16;
@@ -36,7 +37,7 @@ const sleep = (ms, signal) => new Promise((resolve) => {
36
37
  export async function probeOnce(registry, model, apiKey, tuning = {}, signal) {
37
38
  const impl = registry.getApi(model.api);
38
39
  if (impl === undefined)
39
- return { error: `协议 ${model.api} 尚未实现` };
40
+ return { error: msg().subcommands.probe.apiNotImplemented(model.api) };
40
41
  if (signal?.aborted)
41
42
  return { aborted: true };
42
43
  const timeoutMs = tuning.timeoutMs ?? PROBE_TIMEOUT_MS;
@@ -53,7 +54,7 @@ export async function probeOnce(registry, model, apiKey, tuning = {}, signal) {
53
54
  if (signal?.aborted)
54
55
  return { aborted: true };
55
56
  if (timedOut)
56
- return { error: `超时(${Math.round(timeoutMs / 1000)} s 内没有响应)` };
57
+ return { error: msg().subcommands.probe.timeout(Math.round(timeoutMs / 1000)) };
57
58
  return outcome;
58
59
  };
59
60
  try {
@@ -147,7 +148,7 @@ export class ProbeScheduler {
147
148
  return { aborted: true };
148
149
  outcome = await probeOnce(this.registry, model, this.apiKey, this.options, this.signal);
149
150
  if (outcome.error !== undefined && RATE_LIMITED.test(outcome.error)) {
150
- this.stop(`连续 429 限流:${outcome.error}`);
151
+ this.stop(msg().subcommands.probe.rateLimitedStop(outcome.error));
151
152
  return outcome;
152
153
  }
153
154
  }
@@ -208,7 +209,7 @@ export function parseProbeTuning(values) {
208
209
  return fallback;
209
210
  const n = Number(raw);
210
211
  if (!Number.isInteger(n) || n < min || n > max)
211
- throw new UsageError(`--${name} 需要 ${min}–${max} 的整数:${raw}`);
212
+ throw new UsageError(msg().subcommands.probe.intRange(name, min, max, raw));
212
213
  return n;
213
214
  };
214
215
  return {
@@ -219,7 +220,7 @@ export function parseProbeTuning(values) {
219
220
  /** 预估文案:`并发 6,单次最长 15 s,预计不超过 150 s`。 */
220
221
  export function describeProbePlan(requests, concurrency, timeoutMs) {
221
222
  const worst = Math.ceil(requests / concurrency) * Math.ceil(timeoutMs / 1000);
222
- return `并发 ${concurrency},单次最长 ${Math.round(timeoutMs / 1000)} s,预计不超过 ${worst} s`;
223
+ return msg().subcommands.probe.plan(concurrency, Math.round(timeoutMs / 1000), worst);
223
224
  }
224
225
  /** 进度:TTY 下单行刷新「探测 18/60」;非 TTY 只在结束时打印一行汇总。 */
225
226
  export class ProbeProgress {
@@ -247,12 +248,12 @@ export class ProbeProgress {
247
248
  finish() {
248
249
  this.clear();
249
250
  const seconds = ((Date.now() - this.started) / 1000).toFixed(1);
250
- this.write(`探测完成 ${this.done}/${this.total},用时 ${seconds} s\n`);
251
+ this.write(msg().subcommands.probe.done(this.done, this.total, seconds));
251
252
  }
252
253
  draw() {
253
254
  if (!this.tty)
254
255
  return;
255
- this.write(`\r\x1b[2K探测 ${this.done}/${this.total}`);
256
+ this.write(`\r\x1b[2K${msg().subcommands.probe.progress(this.done, this.total)}`);
256
257
  this.shown = true;
257
258
  }
258
259
  clear() {
@@ -8,23 +8,21 @@ import { writeConfigFile } from "../../config/write.js";
8
8
  import { ExitCode } from "../exit-codes.js";
9
9
  import { buildRegistry } from "./context.js";
10
10
  import { userConfig } from "./providers.js";
11
+ import { msg } from "../../i18n/index.js";
11
12
  async function keySource(registry, config, id, channel) {
13
+ const m = msg().subcommands.providersList;
12
14
  const raw = channel !== undefined ? config?.channels?.[channel]?.apiKey : config?.apiKey;
13
15
  if (raw !== undefined) {
14
16
  const kind = classifyKeyValue(raw);
15
- return kind === "env-ref"
16
- ? raw
17
- : kind === "command"
18
- ? "!命令(config.json)"
19
- : "字面量(config.json)";
17
+ return kind === "env-ref" ? raw : kind === "command" ? m.keyCommand : m.keyLiteral;
20
18
  }
21
19
  const resolved = await registry.resolveApiKey(id, channel);
22
20
  if (resolved.apiKey === undefined)
23
- return channel !== undefined ? "同供应商" : "无";
21
+ return channel !== undefined ? m.keySameProvider : m.keyNone;
24
22
  if (channel !== undefined && resolved.source !== "auth-file")
25
- return "同供应商";
23
+ return m.keySameProvider;
26
24
  return resolved.source === "env"
27
- ? `环境变量 ${resolved.origin ?? ""}`
25
+ ? m.keyEnv(resolved.origin ?? "")
28
26
  : resolved.source === "auth-file"
29
27
  ? "auth.json"
30
28
  : resolved.source;
@@ -41,36 +39,49 @@ export async function listProviders(ctx) {
41
39
  (await registry.resolveApiKey(provider.id)).apiKey !== undefined))
42
40
  continue;
43
41
  shown++;
44
- const kind = provider.builtin ? "内置" : "自定义";
45
42
  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`);
43
+ const t = msg().subcommands.providersList;
44
+ ctx.io.stdout(t.providerLine({
45
+ id: provider.id,
46
+ builtin: provider.builtin,
47
+ channels: channels.length,
48
+ endpoint: `${provider.api} ${provider.baseUrl}`,
49
+ models: provider.models.length,
50
+ key: await keySource(registry, own, provider.id),
51
+ }));
48
52
  for (const c of channels) {
49
53
  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`);
54
+ const key = await keySource(registry, own, provider.id, c.name);
55
+ ctx.io.stdout(t.channelLine(c.name, c.api, c.baseUrl, count, key));
51
56
  }
52
57
  }
53
58
  if (shown === 0)
54
- ctx.io.stdout(`没有配置供应商(ama providers add <id> --base-url <url>)\n`);
59
+ ctx.io.stdout(msg().subcommands.providersList.noProviders);
55
60
  return ExitCode.Ok;
56
61
  }
57
62
  export async function listChannels(ctx, id) {
58
63
  const registry = await buildRegistry(ctx.level, ctx.io, ctx.deps);
59
64
  const provider = registry.get(id);
60
65
  if (provider === undefined) {
61
- ctx.io.stderr(`ama: 供应商不存在:${id}\n`);
66
+ ctx.io.stderr(msg().subcommands.common.providerNotFound(id));
62
67
  return ExitCode.NoModel;
63
68
  }
64
69
  const own = userConfig(ctx.level).providers?.[id];
65
70
  if (provider.channels === undefined) {
66
- ctx.io.stdout(`${id}:单渠道(${provider.api} ${provider.baseUrl}),${provider.models.length} 模型\n`);
71
+ ctx.io.stdout(msg().subcommands.providersList.singleChannel(id, provider.api, provider.baseUrl, provider.models.length));
67
72
  return ExitCode.Ok;
68
73
  }
69
74
  for (const c of provider.channels) {
70
75
  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`);
76
+ ctx.io.stdout(msg().subcommands.providersList.channelDetail({
77
+ name: c.name,
78
+ isDefault: c.name === provider.defaultChannel,
79
+ short: apiShortName(c.api),
80
+ api: c.api,
81
+ url: c.baseUrl,
82
+ key: await keySource(registry, own, id, c.name),
83
+ models: models.map((m) => m.id),
84
+ }));
74
85
  }
75
86
  return ExitCode.Ok;
76
87
  }
@@ -80,7 +91,7 @@ export function removeProvider(ctx, id) {
80
91
  if (had) {
81
92
  delete config.providers?.[id];
82
93
  writeConfigFile(ctx.level.userConfigPath, config, { backup: true });
83
- ctx.io.stdout(`已从 ${ctx.level.userConfigPath} 删除 ${id}(原文件备份为 config.json.bak)\n`);
94
+ ctx.io.stdout(msg().subcommands.providersList.removed(ctx.level.userConfigPath, id));
84
95
  }
85
96
  const auth = readAuthFile(ctx.level.authFile).file;
86
97
  let keys = 0;
@@ -88,9 +99,9 @@ export function removeProvider(ctx, id) {
88
99
  if (name === id || name.startsWith(`${id}@`))
89
100
  keys += removeAuthKey(ctx.level.authFile, name) ? 1 : 0;
90
101
  if (keys > 0)
91
- ctx.io.stdout(`已删除 ${ctx.level.authFile} 里 ${id} 的 ${keys} 个 key\n`);
102
+ ctx.io.stdout(msg().subcommands.providersList.keysRemoved(ctx.level.authFile, id, keys));
92
103
  if (!had && keys === 0) {
93
- ctx.io.stderr(`ama: 没有供应商 ${id}\n`);
104
+ ctx.io.stderr(msg().subcommands.providersList.noSuchProvider(id));
94
105
  return ExitCode.RuntimeError;
95
106
  }
96
107
  return ExitCode.Ok;