@armadra/agent 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. package/CHANGELOG.md +203 -304
  2. package/CHANGELOG.zh-CN.md +462 -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/discovered-cache.d.ts +48 -0
  47. package/dist/ai/providers/discovered-cache.js +102 -0
  48. package/dist/ai/providers/enrich.js +2 -7
  49. package/dist/ai/providers/model-visibility.d.ts +33 -0
  50. package/dist/ai/providers/model-visibility.js +70 -0
  51. package/dist/ai/providers/models-dev-cache.js +15 -19
  52. package/dist/ai/providers/models-dev-snapshot.js +8 -7
  53. package/dist/ai/providers/models-dev.js +5 -15
  54. package/dist/ai/providers/registry.d.ts +2 -0
  55. package/dist/ai/providers/registry.js +6 -1
  56. package/dist/ai/providers/suggest.js +2 -16
  57. package/dist/ai/types.d.ts +27 -1
  58. package/dist/auth/chatgpt/backend-client.d.ts +26 -0
  59. package/dist/auth/chatgpt/backend-client.js +74 -0
  60. package/dist/auth/chatgpt/claims.d.ts +17 -0
  61. package/dist/auth/chatgpt/claims.js +46 -0
  62. package/dist/auth/chatgpt/cli.d.ts +35 -0
  63. package/dist/auth/chatgpt/cli.js +279 -0
  64. package/dist/auth/chatgpt/doctor.d.ts +17 -0
  65. package/dist/auth/chatgpt/doctor.js +36 -0
  66. package/dist/auth/chatgpt/host-id.d.ts +7 -0
  67. package/dist/auth/chatgpt/host-id.js +26 -0
  68. package/dist/auth/chatgpt/login.d.ts +30 -0
  69. package/dist/auth/chatgpt/login.js +130 -0
  70. package/dist/auth/chatgpt/presets.d.ts +66 -0
  71. package/dist/auth/chatgpt/presets.js +120 -0
  72. package/dist/auth/chatgpt/quota-text.d.ts +13 -0
  73. package/dist/auth/chatgpt/quota-text.js +36 -0
  74. package/dist/auth/oauth/browser.d.ts +12 -0
  75. package/dist/auth/oauth/browser.js +27 -0
  76. package/dist/auth/oauth/callback-server.d.ts +47 -0
  77. package/dist/auth/oauth/callback-server.js +147 -0
  78. package/dist/auth/oauth/flows.d.ts +62 -0
  79. package/dist/auth/oauth/flows.js +113 -0
  80. package/dist/auth/oauth/jwt.d.ts +24 -0
  81. package/dist/auth/oauth/jwt.js +81 -0
  82. package/dist/auth/oauth/live.d.ts +21 -0
  83. package/dist/auth/oauth/live.js +25 -0
  84. package/dist/auth/oauth/oidc.d.ts +26 -0
  85. package/dist/auth/oauth/oidc.js +72 -0
  86. package/dist/auth/oauth/pkce.d.ts +15 -0
  87. package/dist/auth/oauth/pkce.js +20 -0
  88. package/dist/auth/oauth/refresh.d.ts +35 -0
  89. package/dist/auth/oauth/refresh.js +129 -0
  90. package/dist/auth/oauth/token-client.d.ts +33 -0
  91. package/dist/auth/oauth/token-client.js +121 -0
  92. package/dist/auth/oauth/token-store.d.ts +23 -0
  93. package/dist/auth/oauth/token-store.js +125 -0
  94. package/dist/auth/testing/fake-oauth.d.ts +73 -0
  95. package/dist/auth/testing/fake-oauth.js +271 -0
  96. package/dist/auth/testing/refresh-child.d.ts +5 -0
  97. package/dist/auth/testing/refresh-child.js +16 -0
  98. package/dist/bundle/ama.cjs +26532 -11045
  99. package/dist/checkpoints/backend.js +6 -5
  100. package/dist/checkpoints/restore.js +3 -2
  101. package/dist/checkpoints/settings.js +2 -1
  102. package/dist/checkpoints/shadow-git.js +7 -6
  103. package/dist/checkpoints/shadow-restore.js +3 -2
  104. package/dist/checkpoints/tracker.js +4 -3
  105. package/dist/cli/args.d.ts +9 -2
  106. package/dist/cli/args.js +74 -27
  107. package/dist/cli/bootstrap.js +53 -31
  108. package/dist/cli/choice-prompt.js +8 -6
  109. package/dist/cli/codemode-notice.js +2 -2
  110. package/dist/cli/compose-agents.js +2 -1
  111. package/dist/cli/compose-extensions.js +2 -0
  112. package/dist/cli/compose-memory.d.ts +53 -0
  113. package/dist/cli/compose-memory.js +127 -0
  114. package/dist/cli/compose-providers.d.ts +6 -0
  115. package/dist/cli/compose-providers.js +38 -2
  116. package/dist/cli/compose-session.d.ts +5 -0
  117. package/dist/cli/compose-session.js +27 -13
  118. package/dist/cli/compose-store.d.ts +2 -0
  119. package/dist/cli/compose-store.js +9 -5
  120. package/dist/cli/compose.d.ts +2 -0
  121. package/dist/cli/compose.js +13 -5
  122. package/dist/cli/default-model.d.ts +0 -2
  123. package/dist/cli/default-model.js +5 -8
  124. package/dist/cli/deps.d.ts +5 -1
  125. package/dist/cli/exit-codes.d.ts +1 -1
  126. package/dist/cli/exit-codes.js +7 -16
  127. package/dist/cli/from-prompt.js +3 -2
  128. package/dist/cli/help-text.d.ts +2 -1
  129. package/dist/cli/help-text.js +5 -99
  130. package/dist/cli/main.d.ts +5 -0
  131. package/dist/cli/main.js +21 -2
  132. package/dist/cli/proxy.js +14 -9
  133. package/dist/cli/runtime.d.ts +5 -0
  134. package/dist/cli/startup-screen.js +20 -27
  135. package/dist/cli/startup-steps.js +6 -8
  136. package/dist/cli/subcommands/auth.d.ts +6 -3
  137. package/dist/cli/subcommands/auth.js +52 -22
  138. package/dist/cli/subcommands/config-set.d.ts +21 -0
  139. package/dist/cli/subcommands/config-set.js +145 -0
  140. package/dist/cli/subcommands/config.d.ts +2 -1
  141. package/dist/cli/subcommands/config.js +51 -37
  142. package/dist/cli/subcommands/doctor.d.ts +2 -1
  143. package/dist/cli/subcommands/doctor.js +97 -58
  144. package/dist/cli/subcommands/init.d.ts +1 -1
  145. package/dist/cli/subcommands/init.js +8 -7
  146. package/dist/cli/subcommands/memory.d.ts +18 -0
  147. package/dist/cli/subcommands/memory.js +189 -0
  148. package/dist/cli/subcommands/model-meta.js +11 -9
  149. package/dist/cli/subcommands/models-cache-probe.js +23 -20
  150. package/dist/cli/subcommands/models-discover.d.ts +4 -0
  151. package/dist/cli/subcommands/models-discover.js +60 -21
  152. package/dist/cli/subcommands/models-enable.d.ts +13 -0
  153. package/dist/cli/subcommands/models-enable.js +145 -0
  154. package/dist/cli/subcommands/models.d.ts +3 -1
  155. package/dist/cli/subcommands/models.js +39 -24
  156. package/dist/cli/subcommands/probe-runner.js +8 -7
  157. package/dist/cli/subcommands/providers-list.js +32 -21
  158. package/dist/cli/subcommands/providers-plan.js +24 -25
  159. package/dist/cli/subcommands/providers-probe.js +5 -6
  160. package/dist/cli/subcommands/providers.d.ts +1 -1
  161. package/dist/cli/subcommands/providers.js +45 -50
  162. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  163. package/dist/cli/subcommands/sessions-export.js +10 -9
  164. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  165. package/dist/cli/subcommands/sessions-search.js +11 -10
  166. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  167. package/dist/cli/subcommands/sessions-trace.js +156 -0
  168. package/dist/cli/subcommands/sessions.d.ts +4 -3
  169. package/dist/cli/subcommands/sessions.js +40 -37
  170. package/dist/cli/subcommands/stats.d.ts +1 -1
  171. package/dist/cli/subcommands/stats.js +49 -30
  172. package/dist/cli/system-prompt-arg.js +3 -2
  173. package/dist/codemode/capability.js +3 -2
  174. package/dist/compaction/post-compact.d.ts +1 -0
  175. package/dist/compaction/post-compact.js +15 -1
  176. package/dist/compaction/prune-tier.d.ts +1 -1
  177. package/dist/compaction/prune-tier.js +3 -3
  178. package/dist/compaction/serialize.js +2 -1
  179. package/dist/config/auth-file.d.ts +12 -2
  180. package/dist/config/auth-file.js +32 -10
  181. package/dist/config/checker.js +12 -11
  182. package/dist/config/context-files.js +3 -2
  183. package/dist/config/edit.d.ts +106 -0
  184. package/dist/config/edit.js +350 -0
  185. package/dist/config/init.d.ts +4 -3
  186. package/dist/config/init.js +10 -18
  187. package/dist/config/json-schema.d.ts +2 -1
  188. package/dist/config/json-schema.js +102 -69
  189. package/dist/config/key-docs.d.ts +18 -7
  190. package/dist/config/key-docs.js +43 -128
  191. package/dist/config/load.js +7 -6
  192. package/dist/config/merge.d.ts +4 -1
  193. package/dist/config/merge.js +42 -22
  194. package/dist/config/paths.js +6 -5
  195. package/dist/config/profile.d.ts +5 -1
  196. package/dist/config/profile.js +7 -2
  197. package/dist/config/schema-w5.js +12 -4
  198. package/dist/config/schema-w6.d.ts +19 -0
  199. package/dist/config/schema-w6.js +115 -0
  200. package/dist/config/schema.js +34 -20
  201. package/dist/config/settings-registry.d.ts +81 -0
  202. package/dist/config/settings-registry.js +185 -0
  203. package/dist/config/types-w5.d.ts +7 -0
  204. package/dist/config/types-w5.js +2 -0
  205. package/dist/config/types-w6.d.ts +109 -0
  206. package/dist/config/types-w6.js +19 -0
  207. package/dist/config/types.d.ts +11 -8
  208. package/dist/config/types.js +1 -0
  209. package/dist/drivers/acp/client.js +1 -1
  210. package/dist/drivers/acp/driver.js +13 -8
  211. package/dist/drivers/agents.js +4 -3
  212. package/dist/drivers/base.js +3 -2
  213. package/dist/drivers/host-runners.js +2 -1
  214. package/dist/drivers/native/claude-stream.js +12 -11
  215. package/dist/drivers/native/codex-app-server.js +17 -12
  216. package/dist/drivers/native/oneshot.js +8 -7
  217. package/dist/drivers/pool.js +1 -1
  218. package/dist/drivers/runner.d.ts +3 -1
  219. package/dist/drivers/runner.js +68 -20
  220. package/dist/drivers/turn.js +1 -1
  221. package/dist/hooks/config.js +3 -2
  222. package/dist/hooks/protocol.js +18 -12
  223. package/dist/host/api-impl.js +11 -10
  224. package/dist/host/loader.js +9 -8
  225. package/dist/host/types.d.ts +3 -0
  226. package/dist/i18n/catalog.d.ts +2209 -0
  227. package/dist/i18n/catalog.js +72 -0
  228. package/dist/i18n/format.d.ts +21 -0
  229. package/dist/i18n/format.js +58 -0
  230. package/dist/i18n/index.d.ts +58 -0
  231. package/dist/i18n/index.js +72 -0
  232. package/dist/i18n/messages/agents.d.ts +84 -0
  233. package/dist/i18n/messages/agents.js +85 -0
  234. package/dist/i18n/messages/approval.d.ts +99 -0
  235. package/dist/i18n/messages/approval.js +100 -0
  236. package/dist/i18n/messages/auth.d.ts +189 -0
  237. package/dist/i18n/messages/auth.js +201 -0
  238. package/dist/i18n/messages/cli-args.d.ts +46 -0
  239. package/dist/i18n/messages/cli-args.js +46 -0
  240. package/dist/i18n/messages/cli-help.d.ts +12 -0
  241. package/dist/i18n/messages/cli-help.js +248 -0
  242. package/dist/i18n/messages/cli.d.ts +336 -0
  243. package/dist/i18n/messages/cli.js +311 -0
  244. package/dist/i18n/messages/config-keys.d.ts +293 -0
  245. package/dist/i18n/messages/config-keys.js +296 -0
  246. package/dist/i18n/messages/config.d.ts +508 -0
  247. package/dist/i18n/messages/config.js +241 -0
  248. package/dist/i18n/messages/drivers.d.ts +123 -0
  249. package/dist/i18n/messages/drivers.js +124 -0
  250. package/dist/i18n/messages/errors.d.ts +83 -0
  251. package/dist/i18n/messages/errors.js +171 -0
  252. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  253. package/dist/i18n/messages/interactive-line.js +69 -0
  254. package/dist/i18n/messages/interactive-startup.d.ts +99 -0
  255. package/dist/i18n/messages/interactive-startup.js +100 -0
  256. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  257. package/dist/i18n/messages/interactive-view.js +141 -0
  258. package/dist/i18n/messages/interactive.d.ts +489 -0
  259. package/dist/i18n/messages/interactive.js +248 -0
  260. package/dist/i18n/messages/memory.d.ts +123 -0
  261. package/dist/i18n/messages/memory.js +128 -0
  262. package/dist/i18n/messages/panels.d.ts +233 -0
  263. package/dist/i18n/messages/panels.js +232 -0
  264. package/dist/i18n/messages/permissions.d.ts +126 -0
  265. package/dist/i18n/messages/permissions.js +151 -0
  266. package/dist/i18n/messages/plan.d.ts +123 -0
  267. package/dist/i18n/messages/plan.js +124 -0
  268. package/dist/i18n/messages/print.d.ts +86 -0
  269. package/dist/i18n/messages/print.js +91 -0
  270. package/dist/i18n/messages/report.d.ts +391 -0
  271. package/dist/i18n/messages/report.js +490 -0
  272. package/dist/i18n/messages/rewind.d.ts +198 -0
  273. package/dist/i18n/messages/rewind.js +217 -0
  274. package/dist/i18n/messages/session.d.ts +230 -0
  275. package/dist/i18n/messages/session.js +258 -0
  276. package/dist/i18n/messages/settings.d.ts +355 -0
  277. package/dist/i18n/messages/settings.js +343 -0
  278. package/dist/i18n/messages/subcommands-config.d.ts +113 -0
  279. package/dist/i18n/messages/subcommands-config.js +129 -0
  280. package/dist/i18n/messages/subcommands-models.d.ts +34 -0
  281. package/dist/i18n/messages/subcommands-models.js +34 -0
  282. package/dist/i18n/messages/subcommands.d.ts +576 -0
  283. package/dist/i18n/messages/subcommands.js +477 -0
  284. package/dist/i18n/messages/trace.d.ts +243 -0
  285. package/dist/i18n/messages/trace.js +238 -0
  286. package/dist/i18n/types.d.ts +15 -0
  287. package/dist/i18n/types.js +7 -0
  288. package/dist/index.d.ts +6 -0
  289. package/dist/index.js +2 -0
  290. package/dist/memory/edit.d.ts +24 -0
  291. package/dist/memory/edit.js +63 -0
  292. package/dist/memory/frontmatter.d.ts +37 -0
  293. package/dist/memory/frontmatter.js +79 -0
  294. package/dist/memory/index.d.ts +28 -0
  295. package/dist/memory/index.js +126 -0
  296. package/dist/memory/lock.d.ts +17 -0
  297. package/dist/memory/lock.js +62 -0
  298. package/dist/memory/paths.d.ts +57 -0
  299. package/dist/memory/paths.js +175 -0
  300. package/dist/memory/report.d.ts +36 -0
  301. package/dist/memory/report.js +86 -0
  302. package/dist/memory/runtime.d.ts +42 -0
  303. package/dist/memory/runtime.js +36 -0
  304. package/dist/memory/secrets.d.ts +8 -0
  305. package/dist/memory/secrets.js +27 -0
  306. package/dist/memory/section.d.ts +28 -0
  307. package/dist/memory/section.js +59 -0
  308. package/dist/memory/store.d.ts +70 -0
  309. package/dist/memory/store.js +284 -0
  310. package/dist/memory/tool.d.ts +31 -0
  311. package/dist/memory/tool.js +94 -0
  312. package/dist/modes/acp/acp-events.js +2 -1
  313. package/dist/modes/acp/acp-server.js +13 -12
  314. package/dist/modes/commands-core.d.ts +11 -0
  315. package/dist/modes/commands-core.js +93 -62
  316. package/dist/modes/image-input.js +20 -6
  317. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  318. package/dist/modes/interactive/agent-bar.js +248 -0
  319. package/dist/modes/interactive/agent-panels.js +27 -26
  320. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  321. package/dist/modes/interactive/agent-transcript.js +191 -0
  322. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  323. package/dist/modes/interactive/agent-ui.js +180 -14
  324. package/dist/modes/interactive/agent-view.d.ts +72 -0
  325. package/dist/modes/interactive/agent-view.js +281 -0
  326. package/dist/modes/interactive/approval-dialog.js +46 -34
  327. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  328. package/dist/modes/interactive/clipboard-paste.js +9 -4
  329. package/dist/modes/interactive/commands.d.ts +22 -1
  330. package/dist/modes/interactive/commands.js +100 -49
  331. package/dist/modes/interactive/completion.js +2 -1
  332. package/dist/modes/interactive/config-panel.d.ts +70 -0
  333. package/dist/modes/interactive/config-panel.js +319 -0
  334. package/dist/modes/interactive/config-ui.d.ts +96 -0
  335. package/dist/modes/interactive/config-ui.js +397 -0
  336. package/dist/modes/interactive/confirm-dialog.js +6 -7
  337. package/dist/modes/interactive/event-notices.js +11 -9
  338. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  339. package/dist/modes/interactive/interactive-mode.js +21 -22
  340. package/dist/modes/interactive/key-dispatch.d.ts +12 -0
  341. package/dist/modes/interactive/key-dispatch.js +24 -9
  342. package/dist/modes/interactive/line/line-editor.js +2 -1
  343. package/dist/modes/interactive/line/line-mode.js +18 -7
  344. package/dist/modes/interactive/line/line-render.js +25 -24
  345. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  346. package/dist/modes/interactive/memory-panel.js +221 -0
  347. package/dist/modes/interactive/message-view.d.ts +4 -2
  348. package/dist/modes/interactive/message-view.js +42 -33
  349. package/dist/modes/interactive/model-items.d.ts +45 -0
  350. package/dist/modes/interactive/model-items.js +134 -0
  351. package/dist/modes/interactive/model-picker.d.ts +57 -0
  352. package/dist/modes/interactive/model-picker.js +191 -0
  353. package/dist/modes/interactive/panels.js +39 -31
  354. package/dist/modes/interactive/pickers.d.ts +2 -1
  355. package/dist/modes/interactive/pickers.js +10 -6
  356. package/dist/modes/interactive/plan-command.d.ts +1 -1
  357. package/dist/modes/interactive/plan-command.js +24 -27
  358. package/dist/modes/interactive/plan-dialog.js +18 -17
  359. package/dist/modes/interactive/plan-flow.js +6 -5
  360. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  361. package/dist/modes/interactive/rewind-command.js +18 -16
  362. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  363. package/dist/modes/interactive/rewind-flow.js +13 -14
  364. package/dist/modes/interactive/rewind-list.js +7 -6
  365. package/dist/modes/interactive/rewind-panel.js +40 -40
  366. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  367. package/dist/modes/interactive/rewind-text.js +48 -38
  368. package/dist/modes/interactive/run-indicator.js +15 -12
  369. package/dist/modes/interactive/session-events.js +3 -2
  370. package/dist/modes/interactive/startup-header.js +22 -23
  371. package/dist/modes/interactive/startup-ui.d.ts +3 -9
  372. package/dist/modes/interactive/startup-ui.js +44 -88
  373. package/dist/modes/interactive/status-area.d.ts +2 -0
  374. package/dist/modes/interactive/status-area.js +8 -2
  375. package/dist/modes/interactive/status-bar.js +4 -3
  376. package/dist/modes/interactive/subagent-view.js +9 -7
  377. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  378. package/dist/modes/interactive/tasks-report.js +28 -31
  379. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  380. package/dist/modes/interactive/terminal-setup.js +23 -0
  381. package/dist/modes/interactive/tool-summary.js +19 -17
  382. package/dist/modes/interactive/tool-view.js +7 -4
  383. package/dist/modes/interactive/trace-view.d.ts +89 -0
  384. package/dist/modes/interactive/trace-view.js +332 -0
  385. package/dist/modes/print/print-mode.js +14 -15
  386. package/dist/modes/rpc/commands.js +7 -3
  387. package/dist/modes/rpc/rpc-mode.js +9 -3
  388. package/dist/modes/session-report.d.ts +2 -0
  389. package/dist/modes/session-report.js +101 -105
  390. package/dist/modes/startup-ui-text.js +11 -6
  391. package/dist/permissions/bypass.d.ts +8 -10
  392. package/dist/permissions/bypass.js +19 -10
  393. package/dist/permissions/memory-class.d.ts +23 -0
  394. package/dist/permissions/memory-class.js +54 -0
  395. package/dist/permissions/modes.d.ts +3 -3
  396. package/dist/permissions/modes.js +21 -16
  397. package/dist/permissions/pipeline.d.ts +1 -1
  398. package/dist/permissions/pipeline.js +9 -2
  399. package/dist/permissions/preview.js +49 -42
  400. package/dist/permissions/rules.js +5 -2
  401. package/dist/permissions/types.d.ts +4 -0
  402. package/dist/plan/store.js +2 -1
  403. package/dist/rpc.d.ts +39 -1
  404. package/dist/rpc.js +3 -0
  405. package/dist/sandbox/bash.js +11 -8
  406. package/dist/sandbox/detect.js +14 -11
  407. package/dist/sdk.d.ts +17 -1
  408. package/dist/sdk.js +29 -7
  409. package/dist/session/export.js +31 -30
  410. package/dist/session/manager.d.ts +1 -1
  411. package/dist/session/manager.js +5 -3
  412. package/dist/session/reuse.js +5 -4
  413. package/dist/session/scan.js +3 -2
  414. package/dist/session/stats-aggregate.d.ts +3 -1
  415. package/dist/session/stats-aggregate.js +5 -1
  416. package/dist/session/stats-index.js +2 -1
  417. package/dist/session/stats-scan.d.ts +4 -1
  418. package/dist/session/stats-scan.js +6 -2
  419. package/dist/session/store.d.ts +11 -0
  420. package/dist/session/store.js +48 -1
  421. package/dist/session/types.d.ts +2 -0
  422. package/dist/skills/builtin.js +2 -1
  423. package/dist/tools/image-file.d.ts +26 -1
  424. package/dist/tools/image-file.js +55 -13
  425. package/dist/tools/presets.d.ts +14 -1
  426. package/dist/tools/presets.js +3 -3
  427. package/dist/tools/registry.js +1 -1
  428. package/dist/tools/truncate.d.ts +1 -1
  429. package/dist/tools/truncate.js +2 -2
  430. package/dist/tools/types.d.ts +17 -1
  431. package/dist/trace/build-index.d.ts +91 -0
  432. package/dist/trace/build-index.js +127 -0
  433. package/dist/trace/build-nodes.d.ts +24 -0
  434. package/dist/trace/build-nodes.js +279 -0
  435. package/dist/trace/build-util.d.ts +43 -0
  436. package/dist/trace/build-util.js +120 -0
  437. package/dist/trace/build.d.ts +82 -0
  438. package/dist/trace/build.js +382 -0
  439. package/dist/trace/detail.d.ts +35 -0
  440. package/dist/trace/detail.js +205 -0
  441. package/dist/trace/flatten.d.ts +69 -0
  442. package/dist/trace/flatten.js +173 -0
  443. package/dist/trace/format.d.ts +47 -0
  444. package/dist/trace/format.js +329 -0
  445. package/dist/trace/html-template.d.ts +19 -0
  446. package/dist/trace/html-template.js +150 -0
  447. package/dist/trace/html.d.ts +104 -0
  448. package/dist/trace/html.js +292 -0
  449. package/dist/trace/preview.d.ts +29 -0
  450. package/dist/trace/preview.js +59 -0
  451. package/dist/trace/query-session.d.ts +14 -0
  452. package/dist/trace/query-session.js +38 -0
  453. package/dist/trace/query.d.ts +55 -0
  454. package/dist/trace/query.js +188 -0
  455. package/dist/trace/session.d.ts +40 -0
  456. package/dist/trace/session.js +168 -0
  457. package/dist/trace/types.d.ts +243 -0
  458. package/dist/trace/types.js +13 -0
  459. package/dist/tui/components/editor-paste.d.ts +2 -0
  460. package/dist/tui/components/editor-paste.js +6 -3
  461. package/dist/tui/components/editor.js +2 -2
  462. package/dist/tui/components/loader.d.ts +3 -0
  463. package/dist/tui/components/loader.js +14 -0
  464. package/dist/tui/components/select-list.d.ts +2 -0
  465. package/dist/tui/components/select-list.js +7 -0
  466. package/dist/tui/components/settings-list.d.ts +61 -0
  467. package/dist/tui/components/settings-list.js +135 -0
  468. package/dist/tui/keybindings.d.ts +5 -0
  469. package/dist/tui/keybindings.js +17 -5
  470. package/dist/tui.d.ts +1 -0
  471. package/dist/tui.js +2 -0
  472. package/docs/en/host-api.md +167 -0
  473. package/docs/en/permissions.md +214 -0
  474. package/docs/en/providers.md +627 -0
  475. package/docs/en/rpc.md +361 -0
  476. package/docs/en/sessions.md +219 -0
  477. package/docs/en/tui.md +534 -0
  478. package/docs/host-api.md +18 -17
  479. package/docs/memory.md +172 -0
  480. package/docs/permissions.md +2 -2
  481. package/docs/providers.md +73 -1
  482. package/docs/rpc.md +31 -3
  483. package/docs/session-format.md +8 -2
  484. package/docs/sessions.md +29 -1
  485. package/docs/tui.md +140 -4
  486. package/package.json +8 -3
@@ -14,27 +14,28 @@
14
14
  *
15
15
  * 滚动交给终端回滚:消息区只追加,切换会话时整体清空重画。
16
16
  */
17
+ import { msg } from "../../i18n/index.js";
17
18
  import { Card, Container, Markdown, Spacer, Text, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
18
19
  import { formatCost, formatTokens } from "./status-bar.js";
19
20
  import { notificationSummary } from "./subagent-view.js";
20
21
  import { PLAN_APPROVED_PROMPT } from "../../plan/prompts.js";
21
22
  /** 退出摘要的时长:不足 1 分钟按秒,否则按分钟。 */
22
23
  function sessionDuration(ms) {
23
- const seconds = Math.max(0, Math.round(ms / 1000));
24
- return seconds < 60 ? `${seconds} 秒` : `${Math.round(seconds / 60)} 分钟`;
24
+ return msg().interactive.view.message.duration(Math.max(0, Math.round(ms / 1000)));
25
25
  }
26
26
  /**
27
27
  * 退出摘要(§3.14):`─ 会话 <id> · 时长 · N 回合 · ↑in ↓out · cache x% · $y(重计费 $z)` 与
28
28
  * ` 恢复:ama --resume <id>`。整体 dim,会话 id 与恢复命令正文色;0 回合只到「回合」;会话没落盘不给恢复行。
29
29
  */
30
30
  export function exitSummaryLines(stats, elapsedMs, theme) {
31
+ const m = msg().interactive.view.message;
31
32
  const g = theme.glyphs;
32
33
  const dim = (s) => theme.fg("dim", s);
33
34
  const id = stats.sessionId.slice(0, 8);
34
35
  const parts = [
35
- dim(`${g.rule} 会话 `) + theme.fg("text", id),
36
+ dim(m.sessionPrefix(g.rule)) + theme.fg("text", id),
36
37
  dim(sessionDuration(elapsedMs)),
37
- dim(`${stats.userMessages} 回合`),
38
+ dim(m.turns(stats.userMessages)),
38
39
  ];
39
40
  const t = stats.tokens;
40
41
  const prompt = t.input + t.cacheRead + t.cacheWrite;
@@ -45,28 +46,23 @@ export function exitSummaryLines(stats, elapsedMs, theme) {
45
46
  parts.push(dim(`cache ${Math.round(rate * 100)}%`));
46
47
  if (stats.cost !== undefined && stats.cost > 0) {
47
48
  const rebill = stats.cache?.reBilledUsd;
48
- const extra = rebill !== undefined && rebill > 0 ? `(重计费 ${formatCost(rebill)})` : "";
49
+ const extra = rebill !== undefined && rebill > 0 ? m.rebill(formatCost(rebill)) : "";
49
50
  parts.push(dim(formatCost(stats.cost) + extra));
50
51
  }
51
52
  }
52
53
  const lines = [parts.join(dim(" · "))];
53
54
  if (stats.userMessages > 0 && stats.sessionFile !== undefined) {
54
- lines.push(dim(" 恢复:") + theme.fg("text", `ama --resume ${id}`));
55
+ lines.push(dim(m.resume) + theme.fg("text", `ama --resume ${id}`));
55
56
  }
56
57
  return lines;
57
58
  }
58
59
  /** 思考块展开时的正文行数上限(`full` 不限)。 */
59
60
  export const THINKING_EXPANDED_LINES = 60;
60
- /** origin → 中文标签(未知 origin 原样显示)。 */
61
- export const ORIGIN_LABELS = {
62
- steer: "插话",
63
- followUp: "之后",
64
- host: "宿主",
65
- task: "子 Agent 通知",
66
- plan: "计划",
67
- };
68
- /** [W5-U] origin 为 plan 的交接消息(给模型的英文开场)在消息区的说法。 */
69
- const PLAN_HANDOFF_TEXT = "按批准的计划开始执行";
61
+ /** origin → 界面语言的标签(未知 origin 原样显示)。 */
62
+ export function originLabel(origin) {
63
+ const labels = msg().interactive.view.message.origin;
64
+ return labels[origin] ?? origin;
65
+ }
70
66
  /** 首行带前缀、续行按 `indent` 缩进的文本(用户消息、排队消息)。 */
71
67
  export class PrefixedText {
72
68
  prefix;
@@ -135,9 +131,10 @@ class ThinkingView {
135
131
  const t = this.theme;
136
132
  const g = t.glyphs;
137
133
  const style = (s) => t.fg("dim", t.italic(s));
134
+ const m = msg().interactive.view.message;
138
135
  const title = this.streaming
139
- ? `${g.thinking} 思考中${g.ellipsis}`
140
- : `${g.thinking} 思考 · ${formatTokens(this.tokens)} token`;
136
+ ? m.thinkingStreaming(g.thinking, g.ellipsis)
137
+ : m.thinking(g.thinking, formatTokens(this.tokens));
141
138
  const lines = [
142
139
  style(title) + (this.open && !this.streaming ? " " + t.fg("dim", g.collapse) : ""),
143
140
  ];
@@ -150,7 +147,7 @@ class ThinkingView {
150
147
  for (const line of all.slice(0, limit))
151
148
  lines.push(" " + t.fg("muted", t.italic(line)));
152
149
  if (all.length > limit) {
153
- lines.push(" " + t.fg("dim", `${g.ellipsis} 另 ${all.length - limit} 行`));
150
+ lines.push(" " + t.fg("dim", m.moreLines(g.ellipsis, all.length - limit)));
154
151
  }
155
152
  }
156
153
  this.cache = { width, lines };
@@ -173,7 +170,11 @@ export function contentText(content) {
173
170
  if (typeof content === "string")
174
171
  return content;
175
172
  return content
176
- .map((block) => (block.type === "text" ? block.text : block.type === "image" ? "[图片]" : ""))
173
+ .map((block) => block.type === "text"
174
+ ? block.text
175
+ : block.type === "image"
176
+ ? msg().interactive.view.message.image
177
+ : "")
177
178
  .join("");
178
179
  }
179
180
  /** 一条助手消息:按内容块(思考 / 文本)同步子组件;工具调用块由 tool-view 单独显示。 */
@@ -247,14 +248,15 @@ export class AssistantView extends Container {
247
248
  finish(message) {
248
249
  this.streaming = false;
249
250
  const { theme } = this.options;
251
+ const m = msg().interactive.view.message;
250
252
  if (message.stopReason === "error") {
251
- this.status.setText(theme.fg("error", `${theme.glyphs.fail} ${message.errorMessage ?? "模型调用失败"}`));
253
+ this.status.setText(theme.fg("error", `${theme.glyphs.fail} ${message.errorMessage ?? m.modelError}`));
252
254
  }
253
255
  else if (message.stopReason === "aborted") {
254
- this.status.setText(theme.fg("dim", "已中断"));
256
+ this.status.setText(theme.fg("dim", m.interrupted));
255
257
  }
256
258
  else if (message.stopReason === "length") {
257
- this.status.setText(theme.fg("warning", "输出达到长度上限"));
259
+ this.status.setText(theme.fg("warning", m.lengthLimit));
258
260
  }
259
261
  this.update(message);
260
262
  }
@@ -285,6 +287,10 @@ export class MessageView extends Container {
285
287
  get theme() {
286
288
  return this.options.theme;
287
289
  }
290
+ /** [W6-S] `/config` 热应用:之后渲染的块按新选项(共享同一个 options 对象)。 */
291
+ setOptions(options) {
292
+ Object.assign(this.options, options);
293
+ }
288
294
  /** 追加一块(与上一块之间空一行;`compact` 不空行)。 */
289
295
  add(component) {
290
296
  this.push(component, this.options.compact !== true);
@@ -350,12 +356,12 @@ export class MessageView extends Container {
350
356
  this.add(new PrefixedText(t.fg("user", t.bold(t.glyphs.prompt)) + " ", text));
351
357
  return;
352
358
  }
353
- const label = ORIGIN_LABELS[origin] ?? origin;
359
+ const label = originLabel(origin);
354
360
  // [W5-U] 后台子 Agent 的 <task-notification> 是给模型的全文,消息区只留一行
355
361
  const summary = origin === "task"
356
362
  ? notificationSummary(text)
357
363
  : origin === "plan" && text === PLAN_APPROVED_PROMPT
358
- ? PLAN_HANDOFF_TEXT
364
+ ? msg().interactive.view.message.planHandoff
359
365
  : undefined;
360
366
  if (summary !== undefined) {
361
367
  this.add(new PrefixedText(t.fg("dim", t.glyphs.queued) + " " + t.fg("muted", `${label} `), t.fg("muted", summary)));
@@ -398,23 +404,24 @@ export class MessageView extends Container {
398
404
  }
399
405
  addHookBlocked(reason) {
400
406
  const glyph = this.theme.glyphs.blocked;
401
- this.add(new Text(this.theme.fg("warning", `${glyph} Hook 阻止:${reason}`)));
407
+ this.add(new Text(this.theme.fg("warning", msg().interactive.view.message.hookBlocked(glyph, reason))));
402
408
  }
403
409
  addRetry(attempt, maxAttempts, delayMs, error) {
404
410
  const seconds = Math.max(1, Math.round(delayMs / 1000));
405
411
  const glyph = this.theme.glyphs.retry;
406
- this.add(new Text(this.theme.fg("warning", `${glyph} 重试 ${attempt}/${maxAttempts}(${seconds}s 后):${error}`)));
412
+ this.add(new Text(this.theme.fg("warning", msg().interactive.view.message.retry(glyph, attempt, maxAttempts, seconds, error))));
407
413
  }
408
414
  /** 退出前追加的会话摘要(留在终端回滚里)。 */
409
415
  addExitSummary(lines) {
410
416
  this.add(new Text(lines.join("\n")));
411
417
  }
412
418
  addRetryFailed(error) {
413
- this.addNotice("error", `重试失败${error !== undefined ? `:${error}` : ""}`);
419
+ this.addNotice("error", msg().interactive.view.message.retryFailed(error));
414
420
  }
415
421
  /** 压缩 / 分支摘要卡(左竖条):标题 + token 变化(有则显示)+ 摘要前 3 行。 */
416
422
  addSummaryCard(summary, options = {}) {
417
423
  const t = this.theme;
424
+ const m = msg().interactive.view.message;
418
425
  const lines = summary
419
426
  .trim()
420
427
  .split("\n")
@@ -422,16 +429,16 @@ export class MessageView extends Container {
422
429
  const head = lines.slice(0, 3);
423
430
  const body = head.map((l) => t.fg("muted", l));
424
431
  if (lines.length > head.length) {
425
- body.push(t.fg("dim", `${t.glyphs.ellipsis} 另 ${lines.length - head.length} 行`));
432
+ body.push(t.fg("dim", m.moreLines(t.glyphs.ellipsis, lines.length - head.length)));
426
433
  }
427
434
  let subtitle;
428
435
  if (options.tokensBefore !== undefined) {
429
- const after = options.tokensAfter !== undefined ? ` → ${formatTokens(options.tokensAfter)}` : "";
430
- subtitle = `${formatTokens(options.tokensBefore)}${after} token`;
436
+ const after = options.tokensAfter !== undefined ? formatTokens(options.tokensAfter) : undefined;
437
+ subtitle = m.summaryTokens(formatTokens(options.tokensBefore), after);
431
438
  }
432
439
  this.add(new Card(new Text(body.join("\n")), {
433
440
  theme: t,
434
- title: options.title ?? "上下文已压缩",
441
+ title: options.title ?? m.compacted,
435
442
  ...(subtitle !== undefined ? { subtitle } : {}),
436
443
  }));
437
444
  }
@@ -471,7 +478,9 @@ export class MessageView extends Container {
471
478
  this.addSummaryCard(message.summary, { tokensBefore: message.tokensBefore });
472
479
  break;
473
480
  case "branchSummary":
474
- this.addSummaryCard(message.summary, { title: "分支摘要" });
481
+ this.addSummaryCard(message.summary, {
482
+ title: msg().interactive.view.message.branchSummary,
483
+ });
475
484
  break;
476
485
  case "custom":
477
486
  if (message.display)
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 模型选择器的列表项(`/model`、启动选择器、`/config` 的模型项共用)。
3
+ *
4
+ * - 缺省视图「已配置」:只列有 key、OAuth 已登录或本地的供应商;设置了 `models.enabled` 时只列清单内的
5
+ * (`provider/*` 整个供应商)。「全部」视图(`/model` 里 Tab)另列没配置的供应商,组标题标「未配置 key」。
6
+ * - 当前会话的模型不在视图里时置顶一行,组标题「当前」。
7
+ * - 多渠道供应商每个模型一行(首选渠道),说明里列出其它渠道;`channels`(筛选文本含 `@`)时再列出
8
+ * `model@渠道` 行。清单里逐字写了 `provider/model@渠道` 的渠道行总是列出。
9
+ * - 模型表为空的供应商(ChatGPT 订阅,未缓存发现结果)给一行提示(value 以 `HINT_PREFIX` 开头,不是模型)。
10
+ *
11
+ * 先 `loadModelCatalog`(解析 key,异步)再 `catalogItems`(同步):选择器切视图、改清单时不必重查 key。
12
+ */
13
+ import type { Model, ProviderData, ProviderRegistryApi } from "../../ai/types.js";
14
+ import { type ProviderAccess } from "../../ai/providers/model-visibility.js";
15
+ import type { SelectItem } from "../../tui.js";
16
+ /** 提示行的 value 前缀(`ama:hint:<供应商>`);选中时不是模型。 */
17
+ export declare const HINT_PREFIX = "ama:hint:";
18
+ export declare function isHintValue(value: string): boolean;
19
+ export interface CatalogProvider {
20
+ provider: ProviderData;
21
+ access: ProviderAccess;
22
+ }
23
+ export interface ModelCatalog {
24
+ providers: readonly CatalogProvider[];
25
+ }
26
+ export interface ModelItemOptions {
27
+ /** `configured`(缺省)或 `all`。 */
28
+ view?: "configured" | "all";
29
+ /** `models.enabled`;undefined / 空表示不限。 */
30
+ enabled?: readonly string[] | undefined;
31
+ /** 当前模型 `provider/model[@channel]`。 */
32
+ current?: string | undefined;
33
+ /** 列出 `model@渠道` 行。 */
34
+ channels?: boolean;
35
+ /** 列提示行(缺省 true;启动选择器与 `/config` 关掉)。 */
36
+ hints?: boolean;
37
+ }
38
+ /** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
39
+ export declare function modelDescription(model: Model): string | undefined;
40
+ export declare function loadModelCatalog(registry: ProviderRegistryApi): Promise<ModelCatalog>;
41
+ export declare function accessLabel(access: ProviderAccess): string;
42
+ /** 目录 → 列表项(规则见文件头)。 */
43
+ export declare function catalogItems(catalog: ModelCatalog, options?: ModelItemOptions): SelectItem[];
44
+ /** 一步到位:解析 key 再生成列表项。 */
45
+ export declare function modelItems(registry: ProviderRegistryApi, options?: ModelItemOptions): Promise<SelectItem[]>;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * 模型选择器的列表项(`/model`、启动选择器、`/config` 的模型项共用)。
3
+ *
4
+ * - 缺省视图「已配置」:只列有 key、OAuth 已登录或本地的供应商;设置了 `models.enabled` 时只列清单内的
5
+ * (`provider/*` 整个供应商)。「全部」视图(`/model` 里 Tab)另列没配置的供应商,组标题标「未配置 key」。
6
+ * - 当前会话的模型不在视图里时置顶一行,组标题「当前」。
7
+ * - 多渠道供应商每个模型一行(首选渠道),说明里列出其它渠道;`channels`(筛选文本含 `@`)时再列出
8
+ * `model@渠道` 行。清单里逐字写了 `provider/model@渠道` 的渠道行总是列出。
9
+ * - 模型表为空的供应商(ChatGPT 订阅,未缓存发现结果)给一行提示(value 以 `HINT_PREFIX` 开头,不是模型)。
10
+ *
11
+ * 先 `loadModelCatalog`(解析 key,异步)再 `catalogItems`(同步):选择器切视图、改清单时不必重查 key。
12
+ */
13
+ import { accessReady, enabledMatch, providerAccess, } from "../../ai/providers/model-visibility.js";
14
+ import { CHATGPT_PROVIDER_ID } from "../../auth/chatgpt/presets.js";
15
+ import { msg } from "../../i18n/index.js";
16
+ /** 提示行的 value 前缀(`ama:hint:<供应商>`);选中时不是模型。 */
17
+ export const HINT_PREFIX = "ama:hint:";
18
+ export function isHintValue(value) {
19
+ return value.startsWith(HINT_PREFIX);
20
+ }
21
+ /** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
22
+ export function modelDescription(model) {
23
+ const ctx = model.contextWindow;
24
+ const parts = [
25
+ model.name !== "" && model.name !== model.id ? model.name : undefined,
26
+ ctx === undefined
27
+ ? undefined
28
+ : ctx >= 1_000_000
29
+ ? `${Math.round(ctx / 100_000) / 10}M`
30
+ : `${Math.round(ctx / 1000)}k`,
31
+ model.input.includes("image") ? "img" : undefined,
32
+ ].filter((x) => x !== undefined);
33
+ return parts.length > 0 ? parts.join(" · ") : undefined;
34
+ }
35
+ export async function loadModelCatalog(registry) {
36
+ const providers = [];
37
+ for (const provider of registry.list())
38
+ providers.push({ provider, access: await providerAccess(registry, provider) });
39
+ return { providers };
40
+ }
41
+ export function accessLabel(access) {
42
+ const m = msg().panels.model;
43
+ return access === "none" ? m.noKey : m[access];
44
+ }
45
+ /** 模型的其它渠道(首选渠道之外)。 */
46
+ function otherChannels(model) {
47
+ return (model.channels ?? []).filter((c) => c !== "" && c !== model.channel);
48
+ }
49
+ function row(model, group, channel) {
50
+ const suffix = channel === undefined ? "" : `@${channel}`;
51
+ const item = {
52
+ value: `${model.provider}/${model.id}${suffix}`,
53
+ label: `${model.id}${suffix}`,
54
+ group,
55
+ };
56
+ const others = channel === undefined ? otherChannels(model) : [];
57
+ const parts = [
58
+ modelDescription(model),
59
+ others.length > 0
60
+ ? msg().panels.model.otherChannels(others.map((c) => `@${c}`).join(" "))
61
+ : undefined,
62
+ ].filter((x) => x !== undefined);
63
+ if (parts.length > 0)
64
+ item.description = parts.join(" · ");
65
+ return item;
66
+ }
67
+ function hintRow(entry, group) {
68
+ const { provider, access } = entry;
69
+ if (provider.models.length > 0 || !provider.requiresApiKey)
70
+ return undefined;
71
+ const m = msg().panels.model;
72
+ if (access === "key" || access === "oauth")
73
+ return { value: `${HINT_PREFIX}${provider.id}`, label: m.discoverHint(provider.id), group };
74
+ if (provider.id === CHATGPT_PROVIDER_ID)
75
+ return { value: `${HINT_PREFIX}${provider.id}`, label: m.loginHint(provider.id), group };
76
+ return undefined;
77
+ }
78
+ /** 目录 → 列表项(规则见文件头)。 */
79
+ export function catalogItems(catalog, options = {}) {
80
+ const all = options.view === "all";
81
+ const list = options.enabled !== undefined && options.enabled.length > 0 ? options.enabled : undefined;
82
+ const ready = [];
83
+ const rest = [];
84
+ for (const entry of catalog.providers) {
85
+ const { provider, access } = entry;
86
+ const isReady = accessReady(access);
87
+ const group = `${provider.id} · ${accessLabel(access)}`;
88
+ const items = [];
89
+ const listedProvider = list?.includes(`${provider.id}/*`) === true;
90
+ for (const model of provider.models) {
91
+ const main = row(model, group);
92
+ const listed = list !== undefined && enabledMatch(list, main.value) !== undefined;
93
+ const shown = all || (list !== undefined ? listed : isReady);
94
+ if (shown) {
95
+ if (all && listed)
96
+ main.badge = msg().panels.model.listed;
97
+ if (all && listed)
98
+ main.badgeColor = "dim";
99
+ items.push(main);
100
+ }
101
+ for (const channel of otherChannels(model)) {
102
+ const extra = row(model, group, channel);
103
+ const exact = list?.includes(extra.value) === true;
104
+ if (exact || (shown && options.channels === true))
105
+ items.push(extra);
106
+ }
107
+ }
108
+ const hint = options.hints === false ? undefined : hintRow(entry, group);
109
+ if (hint !== undefined && (all || (list !== undefined ? listedProvider : isReady)))
110
+ items.push(hint);
111
+ (isReady ? ready : rest).push(...items);
112
+ }
113
+ return pinCurrent(catalog, [...ready, ...rest], options.current);
114
+ }
115
+ /** 当前模型不在列表里时置顶一行。 */
116
+ function pinCurrent(catalog, items, current) {
117
+ if (current === undefined || current === "" || items.some((i) => i.value === current))
118
+ return items;
119
+ const slash = current.indexOf("/");
120
+ const at = current.lastIndexOf("@");
121
+ const base = at > slash ? current.slice(0, at) : current;
122
+ const model = catalog.providers
123
+ .find((p) => p.provider.id === current.slice(0, slash))
124
+ ?.provider.models.find((m) => `${m.provider}/${m.id}` === base);
125
+ const item = { value: current, label: current, group: msg().panels.model.current };
126
+ const description = model === undefined ? undefined : modelDescription(model);
127
+ if (description !== undefined)
128
+ item.description = description;
129
+ return [item, ...items];
130
+ }
131
+ /** 一步到位:解析 key 再生成列表项。 */
132
+ export async function modelItems(registry, options = {}) {
133
+ return catalogItems(await loadModelCatalog(registry), options);
134
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 交互模式的 `/model` 选择器:居中覆盖层,列表项见 model-items.ts。
3
+ *
4
+ * - `Tab` 在「已配置 / 全部」两个视图间切换(过滤文本保留);全部视图里没配置的供应商标「未配置 key」,
5
+ * 选中它的模型不切换,选择器底部提示 `ama auth set` / `ama providers add`;
6
+ * - `Space` 把高亮的模型加入 / 移出用户级 `models.enabled`(经 config/edit.ts 写回);只经 `provider/*`
7
+ * 列入的不能单独移出,提示改用 `ama models disable`;
8
+ * - 筛选文本含 `@` 时列出各模型的 `@渠道` 行;
9
+ * - 已在用清单时,从全部视图选中清单外的模型会先把它加入清单再切换;
10
+ * - 提示行(模型表为空的供应商)选中时只在底部显示命令。
11
+ */
12
+ import type { ProviderRegistryApi } from "../../ai/types.js";
13
+ import type { ModeContext } from "../../cli/deps.js";
14
+ import type { Runtime } from "../../cli/runtime.js";
15
+ import { SelectList, type Component, type Focusable } from "../../tui.js";
16
+ import { type ModelCatalog } from "./model-items.js";
17
+ import type { PickerHost } from "./pickers.js";
18
+ export interface ModelPickerOptions {
19
+ title: string;
20
+ providers: ProviderRegistryApi;
21
+ /** 当前模型 `provider/model[@channel]`。 */
22
+ current?: string | undefined;
23
+ /** 打开时的 `models.enabled`。 */
24
+ enabled?: readonly string[] | undefined;
25
+ /** 写回用户级 `models.enabled`(undefined 删除该键);抛错时错误显示在选择器底部。 */
26
+ saveEnabled(next: string[] | undefined): void;
27
+ }
28
+ type View = "configured" | "all";
29
+ /** 选择器本体(可单独测试):`done` 收到选中的模型引用或 undefined(取消)。 */
30
+ export declare class ModelPickerView implements Component, Focusable {
31
+ private readonly host;
32
+ private readonly catalog;
33
+ private readonly options;
34
+ private readonly done;
35
+ private view;
36
+ private enabled;
37
+ private notice;
38
+ private channels;
39
+ readonly list: SelectList;
40
+ constructor(host: PickerHost, catalog: ModelCatalog, options: ModelPickerOptions, done: (ref: string | undefined) => void);
41
+ get focused(): boolean;
42
+ set focused(value: boolean);
43
+ get currentView(): View;
44
+ private rebuild;
45
+ handleInput(data: string): void;
46
+ private providerOf;
47
+ private save;
48
+ private toggle;
49
+ private select;
50
+ render(width: number): string[];
51
+ invalidate(): void;
52
+ }
53
+ /** 打开 `/model` 选择器;返回选中的模型引用,取消返回 undefined。 */
54
+ export declare function openModelPicker(host: PickerHost, options: ModelPickerOptions): Promise<string | undefined>;
55
+ /** 交互模式装配:清单读 `runtime.config`,写用户级 config.json 并换上新配置。 */
56
+ export declare function modelPickerFor(host: PickerHost, runtime: Runtime, context: ModeContext): (providers: ProviderRegistryApi, current: string | undefined) => Promise<string | undefined>;
57
+ export {};
@@ -0,0 +1,191 @@
1
+ /**
2
+ * 交互模式的 `/model` 选择器:居中覆盖层,列表项见 model-items.ts。
3
+ *
4
+ * - `Tab` 在「已配置 / 全部」两个视图间切换(过滤文本保留);全部视图里没配置的供应商标「未配置 key」,
5
+ * 选中它的模型不切换,选择器底部提示 `ama auth set` / `ama providers add`;
6
+ * - `Space` 把高亮的模型加入 / 移出用户级 `models.enabled`(经 config/edit.ts 写回);只经 `provider/*`
7
+ * 列入的不能单独移出,提示改用 `ama models disable`;
8
+ * - 筛选文本含 `@` 时列出各模型的 `@渠道` 行;
9
+ * - 已在用清单时,从全部视图选中清单外的模型会先把它加入清单再切换;
10
+ * - 提示行(模型表为空的供应商)选中时只在底部显示命令。
11
+ */
12
+ import { accessReady, addEnabled, enabledList, enabledMatch, removeEnabled, } from "../../ai/providers/model-visibility.js";
13
+ import { setConfigValue } from "../../config/edit.js";
14
+ import { msg } from "../../i18n/index.js";
15
+ import { Box, SelectList, matchesKey, wrapTextWithAnsi, } from "../../tui.js";
16
+ import { layerInputFor } from "./config-ui.js";
17
+ import { catalogItems, isHintValue, loadModelCatalog } from "./model-items.js";
18
+ /** 选择器本体(可单独测试):`done` 收到选中的模型引用或 undefined(取消)。 */
19
+ export class ModelPickerView {
20
+ host;
21
+ catalog;
22
+ options;
23
+ done;
24
+ view = "configured";
25
+ enabled;
26
+ notice;
27
+ channels = false;
28
+ list;
29
+ constructor(host, catalog, options, done) {
30
+ this.host = host;
31
+ this.catalog = catalog;
32
+ this.options = options;
33
+ this.done = done;
34
+ this.enabled = enabledList(options.enabled);
35
+ this.list = new SelectList([], {
36
+ theme: host.theme,
37
+ maxVisible: 12,
38
+ filterable: true,
39
+ showCount: true,
40
+ ...(host.keybindings !== undefined ? { keybindings: host.keybindings } : {}),
41
+ ...(options.current !== undefined ? { currentValue: options.current } : {}),
42
+ emptyText: msg().panels.model.emptyConfigured,
43
+ onSelect: (item) => this.select(item),
44
+ onCancel: () => this.done(undefined),
45
+ });
46
+ this.rebuild();
47
+ if (options.current !== undefined)
48
+ this.list.selectValue(options.current);
49
+ }
50
+ get focused() {
51
+ return this.list.focused;
52
+ }
53
+ set focused(value) {
54
+ this.list.focused = value;
55
+ }
56
+ get currentView() {
57
+ return this.view;
58
+ }
59
+ rebuild() {
60
+ const m = msg().panels.model;
61
+ this.list.setFooter(this.view === "all" ? m.footerAll : m.footerConfigured);
62
+ this.list.setItems(catalogItems(this.catalog, {
63
+ view: this.view,
64
+ enabled: this.enabled,
65
+ current: this.options.current,
66
+ channels: this.channels,
67
+ }));
68
+ }
69
+ handleInput(data) {
70
+ if (matchesKey(data, "tab")) {
71
+ this.view = this.view === "all" ? "configured" : "all";
72
+ this.notice = undefined;
73
+ this.rebuild();
74
+ return;
75
+ }
76
+ if (data === " ") {
77
+ this.toggle();
78
+ return;
79
+ }
80
+ this.list.handleInput(data);
81
+ const channels = this.list.getFilter().includes("@");
82
+ if (channels !== this.channels) {
83
+ this.channels = channels;
84
+ this.rebuild();
85
+ }
86
+ }
87
+ providerOf(value) {
88
+ const id = value.slice(0, value.indexOf("/"));
89
+ return this.catalog.providers.find((p) => p.provider.id === id);
90
+ }
91
+ save(next) {
92
+ try {
93
+ this.options.saveEnabled(next);
94
+ this.enabled = next;
95
+ return true;
96
+ }
97
+ catch (error) {
98
+ this.notice = {
99
+ text: error instanceof Error ? error.message : String(error),
100
+ level: "error",
101
+ };
102
+ return false;
103
+ }
104
+ }
105
+ toggle() {
106
+ const item = this.list.getSelected();
107
+ if (item === undefined || isHintValue(item.value))
108
+ return;
109
+ const m = msg().panels.model;
110
+ const ref = item.value;
111
+ const match = this.enabled === undefined ? undefined : enabledMatch(this.enabled, ref);
112
+ if (match?.kind === "wildcard") {
113
+ this.notice = { text: m.wildcard(ref, match.pattern), level: "warning" };
114
+ }
115
+ else if (match !== undefined) {
116
+ if (this.save(removeEnabled(this.enabled, [ref])))
117
+ this.notice = { text: m.removed(ref), level: "info" };
118
+ }
119
+ else {
120
+ const first = this.enabled === undefined;
121
+ if (this.save(addEnabled(this.enabled, [ref])))
122
+ this.notice = { text: first ? m.addedFirst(ref) : m.added(ref), level: "info" };
123
+ }
124
+ this.rebuild();
125
+ }
126
+ select(item) {
127
+ const m = msg().panels.model;
128
+ const id = item.value.slice(0, item.value.indexOf("/"));
129
+ if (isHintValue(item.value)) {
130
+ this.notice = { text: item.label, level: "info" };
131
+ return;
132
+ }
133
+ const entry = this.providerOf(item.value);
134
+ if (item.value !== this.options.current && entry !== undefined && !accessReady(entry.access)) {
135
+ const text = entry.access === "needsLogin" ? m.needsLoginHint(id) : m.noKeyHint(id);
136
+ this.notice = { text, level: "warning" };
137
+ return;
138
+ }
139
+ if (this.enabled !== undefined &&
140
+ item.value !== this.options.current &&
141
+ enabledMatch(this.enabled, item.value) === undefined &&
142
+ !this.save(addEnabled(this.enabled, [item.value])))
143
+ return;
144
+ this.done(item.value);
145
+ }
146
+ render(width) {
147
+ const lines = this.list.render(width);
148
+ if (this.notice === undefined)
149
+ return lines;
150
+ const theme = this.host.theme;
151
+ const color = this.notice.level === "info" ? "dim" : this.notice.level;
152
+ return [...lines, ...wrapTextWithAnsi(theme.fg(color, this.notice.text), width)];
153
+ }
154
+ invalidate() {
155
+ this.list.invalidate();
156
+ }
157
+ }
158
+ /** 打开 `/model` 选择器;返回选中的模型引用,取消返回 undefined。 */
159
+ export async function openModelPicker(host, options) {
160
+ const catalog = await loadModelCatalog(options.providers);
161
+ return new Promise((resolve) => {
162
+ let handle;
163
+ const view = new ModelPickerView(host, catalog, options, (ref) => {
164
+ handle?.hide();
165
+ resolve(ref);
166
+ });
167
+ const width = Math.max(20, Math.min(host.columns() - 2, 72));
168
+ handle = host.showOverlay(new Box(view, { title: options.title, theme: host.theme }), {
169
+ anchor: "center",
170
+ width,
171
+ });
172
+ });
173
+ }
174
+ /** 交互模式装配:清单读 `runtime.config`,写用户级 config.json 并换上新配置。 */
175
+ export function modelPickerFor(host, runtime, context) {
176
+ return (providers, current) => openModelPicker(host, {
177
+ title: msg().interactive.commands.modelTitle,
178
+ providers,
179
+ current,
180
+ enabled: runtime.config.models?.enabled,
181
+ saveEnabled: (next) => {
182
+ const result = setConfigValue({
183
+ ...layerInputFor(runtime, context),
184
+ scope: "user",
185
+ key: "models.enabled",
186
+ value: next,
187
+ });
188
+ runtime.replaceConfig?.(result.snapshot.config);
189
+ },
190
+ });
191
+ }