@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
@@ -7,6 +7,7 @@
7
7
  * - 着色:`✻` accent、标题粗体;键列 dim;模型 accent;已信任 success / 未信任 warning;Bypass 模式 warning;
8
8
  * 按键提示 dim。路径过长时从左截断(`…/armadra-agent`)。宽度变化时按新宽重算是否去框。
9
9
  */
10
+ import { msg } from "../../i18n/index.js";
10
11
  import { permissionModeLabel } from "../../permissions/modes.js";
11
12
  import { Box, KeyValue, padToWidth, truncateToWidth, visibleWidth, } from "../../tui.js";
12
13
  /** 画框的最小宽度;更窄时去框去键列。 */
@@ -58,7 +59,8 @@ export class StartupHeader {
58
59
  }
59
60
  trustText(withSource) {
60
61
  const { trusted, trustSource } = this.info;
61
- const text = `${trusted ? "已信任" : "未信任"}${withSource ? `(${trustSource})` : ""}`;
62
+ const m = msg().interactive.startup.header;
63
+ const text = `${trusted ? m.trusted : m.untrusted}${withSource ? m.trustSource(trustSource) : ""}`;
62
64
  return this.theme.fg(trusted ? "success" : "warning", text);
63
65
  }
64
66
  loadedText() {
@@ -69,7 +71,7 @@ export class StartupHeader {
69
71
  if (skills > 0)
70
72
  parts.push(`${skills} Skill`);
71
73
  if (prompts > 0)
72
- parts.push(`${prompts} 模板`);
74
+ parts.push(msg().interactive.startup.header.templates(prompts));
73
75
  if (hooks > 0)
74
76
  parts.push(`${hooks} Hook`);
75
77
  return parts.length === 0 ? undefined : parts.join(" · ");
@@ -114,51 +116,48 @@ export class StartupHeader {
114
116
  const loaded = this.loadedText();
115
117
  if (loaded !== undefined)
116
118
  lines.push(loaded);
119
+ const m = msg().interactive.startup.header;
117
120
  if (info.host !== undefined)
118
- lines.push(`宿主 ${info.host}`);
121
+ lines.push(m.host(info.host));
119
122
  if (info.warnings > 0)
120
- lines.push(t.fg("warning", `警告 ${info.warnings} 条(ama doctor)`));
121
- lines.push(t.fg("dim", "/help · Shift+Tab 切模式"));
123
+ lines.push(t.fg("warning", m.warnings(info.warnings)));
124
+ lines.push(t.fg("dim", m.hintCompact));
122
125
  return lines.map((line) => truncateToWidth(line, width));
123
126
  }
124
127
  boxLines(width) {
125
128
  const t = this.theme;
126
129
  const sep = t.fg("dim", " · ");
127
130
  const { info } = this;
131
+ const m = msg().interactive.startup.header;
128
132
  const boxWidth = Math.min(width, HEADER_BOX_MAX_WIDTH);
129
- /** 框内文本宽:边框 2 + 内边距 2;键列 6 + 间隔 1。 */
130
- const valueWidth = boxWidth - 4 - 7;
133
+ // 键列至少 6 列(「已加载」的宽度),没有这一行时也对齐;英文键更宽时按最宽的键
134
+ const keyWidth = Math.max(6, ...[m.keyModel, m.keyDir, m.keyMode, m.keyLoaded, m.keyHost, m.keyWarnings].map((k) => visibleWidth(k)));
135
+ /** 框内文本宽:边框 2 + 内边距 2;键列 + 间隔 1。 */
136
+ const valueWidth = boxWidth - 4 - keyWidth - 1;
131
137
  const trust = this.trustText(true);
132
138
  const cwdRoom = Math.max(4, valueWidth - visibleWidth(trust) - 3);
133
139
  const rows = [
134
- { key: "模型", value: t.fg("accent", info.model) + sep + `思考 ${info.thinking}` },
135
- { key: "目录", value: truncateLeft(info.cwd, cwdRoom, t.glyphs.ellipsis) + sep + trust },
140
+ { key: m.keyModel, value: t.fg("accent", info.model) + sep + m.thinking(info.thinking) },
141
+ { key: m.keyDir, value: truncateLeft(info.cwd, cwdRoom, t.glyphs.ellipsis) + sep + trust },
136
142
  {
137
- key: "模式",
138
- value: [this.modeText(), `预设 ${info.preset}`, this.codemodeText()]
143
+ key: m.keyMode,
144
+ value: [this.modeText(), m.preset(info.preset), this.codemodeText()]
139
145
  .filter((p) => p !== undefined)
140
146
  .join(sep),
141
147
  },
142
148
  ];
143
149
  const loaded = this.loadedText();
144
150
  if (loaded !== undefined)
145
- rows.push({ key: "已加载", value: loaded });
151
+ rows.push({ key: m.keyLoaded, value: loaded });
146
152
  if (info.host !== undefined)
147
- rows.push({ key: "宿主", value: info.host });
153
+ rows.push({ key: m.keyHost, value: info.host });
148
154
  if (info.warnings > 0) {
149
- rows.push({ key: "警告", value: t.fg("warning", `${info.warnings} 条(ama doctor 查看)`) });
155
+ rows.push({ key: m.keyWarnings, value: t.fg("warning", m.warningsValue(info.warnings)) });
150
156
  }
151
- // 键列固定 6 列(「已加载」的宽度),没有这一行时也对齐
152
- const padded = rows.map((row) => ({ ...row, key: padToWidth(row.key, 6) }));
157
+ const padded = rows.map((row) => ({ ...row, key: padToWidth(row.key, keyWidth) }));
153
158
  const kv = new KeyValue(padded, { theme: t, gap: 1, maxKeyRatio: 1 });
154
159
  const body = {
155
- render: (inner) => [
156
- this.title(),
157
- "",
158
- ...kv.render(inner),
159
- "",
160
- t.fg("dim", "/help 命令 · Shift+Tab 切模式 · Ctrl+O 展开工具输出"),
161
- ],
160
+ render: (inner) => [this.title(), "", ...kv.render(inner), "", t.fg("dim", m.hint)],
162
161
  invalidate: () => kv.invalidate(),
163
162
  };
164
163
  return new Box(body, { theme: t }).render(boxWidth);
@@ -5,12 +5,13 @@
5
5
  * 选择列表 / 输入框的 `TUI`;答完把问答收成一行再 `stop()`——不清屏,问答留在回滚里。
6
6
  * 取消(Esc / Ctrl+C)按各回调的约定返回 undefined(bootstrap 据此给退出码)。
7
7
  *
8
- * `modelItems` / `sessionItems` 同时供交互模式里的选择器(pickers.ts)使用。
8
+ * `modelItems`(model-items.ts)/ `sessionItems` 同时供交互模式里的选择器(pickers.ts)使用。启动选择器只列
9
+ * 已配置的模型,一个都没有时列全部。
9
10
  */
10
- import type { Model, ProviderRegistryApi } from "../../ai/types.js";
11
11
  import type { InteractiveUi } from "../../cli/deps.js";
12
12
  import type { SessionListItem } from "../../session/types.js";
13
13
  import { type Keybindings, type SelectItem, type Terminal, type Theme } from "../../tui.js";
14
+ export { modelDescription, modelItems } from "./model-items.js";
14
15
  export interface StartupUiOptions {
15
16
  /** 每次问答新建的终端;缺省 `new ProcessTerminal()`。 */
16
17
  terminal?: () => Terminal;
@@ -19,13 +20,6 @@ export interface StartupUiOptions {
19
20
  /** 会话列表的相对时间基准(测试注入)。 */
20
21
  now?: () => number;
21
22
  }
22
- /** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
23
- export declare function modelDescription(model: Model): string | undefined;
24
- /**
25
- * 模型按「供应商 · 渠道」分组;有 key(或本地)的供应商排前,组标题标 key 状态。多渠道供应商的模型在
26
- * 每个挂载的渠道下各出现一次,非首选渠道的值带 `@渠道`。
27
- */
28
- export declare function modelItems(providers: ProviderRegistryApi): Promise<SelectItem[]>;
29
23
  /** `刚刚 / 5 分钟前 / 3 小时前 / 2 天前 / 2026-09-01`。 */
30
24
  export declare function relativeTime(iso: string, now: number): string;
31
25
  /** 会话:标签 = 名字或首条提示,描述 = 相对时间 · 消息数。 */
@@ -5,11 +5,15 @@
5
5
  * 选择列表 / 输入框的 `TUI`;答完把问答收成一行再 `stop()`——不清屏,问答留在回滚里。
6
6
  * 取消(Esc / Ctrl+C)按各回调的约定返回 undefined(bootstrap 据此给退出码)。
7
7
  *
8
- * `modelItems` / `sessionItems` 同时供交互模式里的选择器(pickers.ts)使用。
8
+ * `modelItems`(model-items.ts)/ `sessionItems` 同时供交互模式里的选择器(pickers.ts)使用。启动选择器只列
9
+ * 已配置的模型,一个都没有时列全部。
9
10
  */
11
+ import { msg } from "../../i18n/index.js";
10
12
  import { existsSync, statSync } from "node:fs";
11
13
  import { resolve } from "node:path";
12
14
  import { Container, Editor, ProcessTerminal, SelectList, TUI, Text, createTheme, defaultKeybindings, detectCapabilities, } from "../../tui.js";
15
+ import { loadModelCatalog, catalogItems } from "./model-items.js";
16
+ export { modelDescription, modelItems } from "./model-items.js";
13
17
  function resolveOptions(options) {
14
18
  return {
15
19
  terminal: options.terminal ?? (() => new ProcessTerminal()),
@@ -49,7 +53,7 @@ function askSelect(r, prompt) {
49
53
  done(item);
50
54
  },
51
55
  onCancel: () => {
52
- finish("(已取消)");
56
+ finish(msg().interactive.startup.ui.cancelled);
53
57
  done(undefined);
54
58
  },
55
59
  });
@@ -57,10 +61,10 @@ function askSelect(r, prompt) {
57
61
  list.selectValue(prompt.selected);
58
62
  body.addChild(list);
59
63
  body.addChild(new Text(r.theme.fg("dim", prompt.filterable === true
60
- ? "输入过滤 · ↑↓ 选择 · Enter 确认 · Esc 取消"
64
+ ? msg().interactive.startup.ui.hintFilter("↑↓")
61
65
  : prompt.numberKeys === true
62
- ? `↑↓ 选择 · Enter 确认 · 1-${prompt.items.length} 直接选 · Esc 取消`
63
- : "↑↓ 选择 · Enter 确认 · Esc 取消")));
66
+ ? msg().interactive.startup.ui.hintNumbers("↑↓", prompt.items.length)
67
+ : msg().interactive.startup.ui.hint("↑↓"))));
64
68
  tui.start();
65
69
  tui.setFocus(list);
66
70
  });
@@ -92,7 +96,7 @@ function askText(r, prompt) {
92
96
  body.addChild(error);
93
97
  tui.addInputListener((data) => {
94
98
  if (r.keys.matches(data, "tui.select.cancel") && !editor.isCompletionOpen) {
95
- finish("(已取消)");
99
+ finish(msg().interactive.startup.ui.cancelled);
96
100
  done(undefined);
97
101
  return true;
98
102
  }
@@ -105,80 +109,23 @@ function askText(r, prompt) {
105
109
  // ---------------------------------------------------------------------------
106
110
  // 列表项(选择器共用)
107
111
  // ---------------------------------------------------------------------------
108
- /** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
109
- export function modelDescription(model) {
110
- const ctx = model.contextWindow;
111
- const parts = [
112
- model.name !== "" && model.name !== model.id ? model.name : undefined,
113
- ctx === undefined
114
- ? undefined
115
- : ctx >= 1_000_000
116
- ? `${Math.round(ctx / 100_000) / 10}M`
117
- : `${Math.round(ctx / 1000)}k`,
118
- model.input.includes("image") ? "img" : undefined,
119
- ].filter((x) => x !== undefined);
120
- return parts.length > 0 ? parts.join(" · ") : undefined;
121
- }
122
- /**
123
- * 模型按「供应商 · 渠道」分组;有 key(或本地)的供应商排前,组标题标 key 状态。多渠道供应商的模型在
124
- * 每个挂载的渠道下各出现一次,非首选渠道的值带 `@渠道`。
125
- */
126
- export async function modelItems(providers) {
127
- const groups = [];
128
- for (const provider of providers.list()) {
129
- if (provider.models.length === 0)
130
- continue;
131
- let status;
132
- let ready = true;
133
- if (!provider.requiresApiKey)
134
- status = "本地";
135
- else {
136
- const key = await providers.resolveApiKey(provider.id).catch(() => ({ apiKey: undefined }));
137
- ready = key.apiKey !== undefined;
138
- status = ready ? "key ✓" : "无 key";
139
- }
140
- const item = (model, group, channel) => {
141
- const suffix = channel !== undefined && channel !== model.channel ? `@${channel}` : "";
142
- const out = {
143
- value: `${provider.id}/${model.id}${suffix}`,
144
- label: `${model.id}${suffix}`,
145
- group,
146
- };
147
- const description = modelDescription(model);
148
- if (description !== undefined)
149
- out.description = description;
150
- return out;
151
- };
152
- if (provider.channels === undefined) {
153
- const group = `${provider.id} · ${status}`;
154
- groups.push({ ready, items: provider.models.map((model) => item(model, group)) });
155
- continue;
156
- }
157
- for (const channel of provider.channels) {
158
- const group = `${provider.id} · ${channel.name} · ${status}`;
159
- const models = provider.models.filter((m) => m.channels?.includes(channel.name));
160
- if (models.length > 0)
161
- groups.push({ ready, items: models.map((model) => item(model, group, channel.name)) });
162
- }
163
- }
164
- return [...groups.filter((g) => g.ready), ...groups.filter((g) => !g.ready)].flatMap((g) => g.items);
165
- }
166
112
  /** `刚刚 / 5 分钟前 / 3 小时前 / 2 天前 / 2026-09-01`。 */
167
113
  export function relativeTime(iso, now) {
168
114
  const at = Date.parse(iso);
169
115
  if (!Number.isFinite(at))
170
116
  return "";
117
+ const m = msg().interactive.startup.ui;
171
118
  const minutes = Math.floor((now - at) / 60_000);
172
119
  if (minutes < 1)
173
- return "刚刚";
120
+ return m.justNow;
174
121
  if (minutes < 60)
175
- return `${minutes} 分钟前`;
122
+ return m.minutesAgo(minutes);
176
123
  const hours = Math.floor(minutes / 60);
177
124
  if (hours < 24)
178
- return `${hours} 小时前`;
125
+ return m.hoursAgo(hours);
179
126
  const days = Math.floor(hours / 24);
180
127
  if (days < 30)
181
- return `${days} 天前`;
128
+ return m.daysAgo(days);
182
129
  return iso.slice(0, 10);
183
130
  }
184
131
  function oneLine(text, max = 60) {
@@ -192,18 +139,21 @@ export function sessionItems(items, now) {
192
139
  .map((item) => ({
193
140
  value: item.id,
194
141
  label: oneLine(item.name ?? item.firstPrompt ?? item.id.slice(0, 8)),
195
- description: `${relativeTime(item.modifiedAt, now)} · ${item.messageCount} 条`,
142
+ description: `${relativeTime(item.modifiedAt, now)} · ${msg().interactive.startup.ui.messages(item.messageCount)}`,
196
143
  }));
197
144
  }
198
145
  // ---------------------------------------------------------------------------
199
146
  // InteractiveUi
200
147
  // ---------------------------------------------------------------------------
201
- const TRUST_CHOICES = [
202
- { value: "trust", label: "信任并记住", answer: { trusted: true, remember: true } },
203
- { value: "once", label: "仅本次信任", answer: { trusted: true, remember: false } },
204
- { value: "skip", label: "本次不信任", answer: { trusted: false, remember: false } },
205
- { value: "never", label: "不信任并记住", answer: { trusted: false, remember: true } },
206
- ];
148
+ function trustChoices() {
149
+ const m = msg().interactive.startup.ui;
150
+ return [
151
+ { value: "trust", label: m.trustRemember, answer: { trusted: true, remember: true } },
152
+ { value: "once", label: m.trustOnce, answer: { trusted: true, remember: false } },
153
+ { value: "skip", label: m.trustSkip, answer: { trusted: false, remember: false } },
154
+ { value: "never", label: m.trustNever, answer: { trusted: false, remember: true } },
155
+ ];
156
+ }
207
157
  function isDirectory(path) {
208
158
  try {
209
159
  return statSync(path).isDirectory();
@@ -216,35 +166,40 @@ export function createStartupUi(options = {}) {
216
166
  const r = resolveOptions(options);
217
167
  return {
218
168
  async promptTrust(cwd, resources) {
169
+ const m = msg().interactive.startup.ui;
170
+ const choices = trustChoices();
219
171
  const shown = resources.slice(0, 6).map((p) => ` ${p}`);
220
172
  if (resources.length > shown.length)
221
- shown.push(` …另有 ${resources.length - shown.length} 项`);
173
+ shown.push(m.moreResources(resources.length - shown.length));
222
174
  const picked = await askSelect(r, {
223
- title: "信任这个目录的项目资源?",
175
+ title: m.trustTitle,
224
176
  lines: [cwd, ...shown],
225
- items: TRUST_CHOICES.map(({ value, label }) => ({ value, label })),
177
+ items: choices.map(({ value, label }) => ({ value, label })),
226
178
  selected: "once",
227
179
  numberKeys: true,
228
180
  });
229
- const choice = TRUST_CHOICES.find((c) => c.value === picked?.value);
181
+ const choice = choices.find((c) => c.value === picked?.value);
230
182
  return choice?.answer ?? { trusted: false, remember: false };
231
183
  },
232
184
  async pickSession(items) {
233
185
  if (items.length === 0)
234
186
  return undefined;
235
187
  const picked = await askSelect(r, {
236
- title: "恢复哪个会话?",
188
+ title: msg().interactive.startup.ui.resumeTitle,
237
189
  items: sessionItems(items, r.now()),
238
190
  filterable: true,
239
191
  });
240
192
  return picked?.value;
241
193
  },
242
194
  async pickModel(providers, reason) {
243
- const items = await modelItems(providers);
195
+ const catalog = await loadModelCatalog(providers);
196
+ let items = catalogItems(catalog, { hints: false });
197
+ if (items.length === 0)
198
+ items = catalogItems(catalog, { view: "all", hints: false });
244
199
  if (items.length === 0)
245
200
  return undefined;
246
201
  const picked = await askSelect(r, {
247
- title: "选择模型",
202
+ title: msg().interactive.startup.ui.modelTitle,
248
203
  lines: [reason],
249
204
  items,
250
205
  filterable: true,
@@ -252,18 +207,19 @@ export function createStartupUi(options = {}) {
252
207
  return picked?.value;
253
208
  },
254
209
  askCwd(missing) {
210
+ const m = msg().interactive.startup.ui;
255
211
  return askText(r, {
256
- title: "会话的工作目录不存在",
257
- lines: [missing, "输入替代目录(Enter 确认 · Esc 取消)"],
258
- placeholder: "目录路径",
212
+ title: m.cwdTitle,
213
+ lines: [missing, m.cwdPrompt],
214
+ placeholder: m.cwdPlaceholder,
259
215
  validate: (text) => {
260
216
  if (text === "")
261
- return "请输入目录";
217
+ return m.cwdEmpty;
262
218
  const abs = resolve(text);
263
219
  if (!existsSync(abs))
264
- return `不存在:${abs}`;
220
+ return m.cwdMissing(abs);
265
221
  if (!isDirectory(abs))
266
- return `不是目录:${abs}`;
222
+ return m.cwdNotDir(abs);
267
223
  return undefined;
268
224
  },
269
225
  });
@@ -53,6 +53,8 @@ export declare class StatusArea {
53
53
  private bashSandbox;
54
54
  constructor(deps: StatusAreaDeps);
55
55
  layout(): StatusLineMode;
56
+ /** [W6-A] 界面配置(Agent 栏开关、子 Agent 视图的消息显示选项)。 */
57
+ ui(): NonNullable<Runtime["config"]["ui"]>;
56
58
  setLayout(mode: StatusLineMode): void;
57
59
  toggle(): StatusLineMode;
58
60
  refresh(): void;
@@ -9,6 +9,7 @@
9
9
  * - [W5-U] `model_fallback` 之后状态栏模型项显示 `主模型 → 回退模型`,切回主模型(`model_changed`)后消失。
10
10
  * - `telemetry_tick`(流式中 ≤ 2 Hz)只重取统计并重画(速率行),状态栏的内容这时不变。
11
11
  */
12
+ import { msg } from "../../i18n/index.js";
12
13
  import { basename } from "node:path";
13
14
  import { sandboxCapabilityFor } from "../../codemode/capability.js";
14
15
  import { formatModelRef } from "../../ai/providers/channels.js";
@@ -86,6 +87,10 @@ export class StatusArea {
86
87
  layout() {
87
88
  return this.mode;
88
89
  }
90
+ /** [W6-A] 界面配置(Agent 栏开关、子 Agent 视图的消息显示选项)。 */
91
+ ui() {
92
+ return this.deps.runtime.config.ui ?? {};
93
+ }
89
94
  setLayout(mode) {
90
95
  if (mode === this.mode)
91
96
  return;
@@ -179,12 +184,13 @@ export function statusLineSlash(area, line, notice) {
179
184
  else if (value === "full" || value === "compact")
180
185
  area.setLayout(value);
181
186
  else {
182
- notice("error", "用法:/statusline [full|compact]");
187
+ notice("error", msg().interactive.statusLine.usage);
183
188
  return true;
184
189
  }
185
190
  notice("info", statusLineText(area.layout()));
186
191
  return true;
187
192
  }
188
193
  export function statusLineText(mode) {
189
- return mode === "full" ? "状态栏:完整(两行)" : "状态栏:精简(一行)";
194
+ const m = msg().interactive.statusLine;
195
+ return mode === "full" ? m.full : m.compact;
190
196
  }
@@ -26,6 +26,7 @@
26
26
  * - 宽度不够时按优先级丢弃(数字大的先丢,表见 §1.2);会变的数字按最宽形状占位(`reserve`),
27
27
  * 数字变化不会让某项时有时无(40 列不抖动)。
28
28
  */
29
+ import { msg } from "../../i18n/index.js";
29
30
  import { permissionModeLabel } from "../../permissions/modes.js";
30
31
  import { formatModelRef } from "../../ai/providers/channels.js";
31
32
  import { Meter, levelColor, truncateToWidth, visibleWidth, } from "../../tui.js";
@@ -57,7 +58,7 @@ export function formatDuration(ms) {
57
58
  export function cacheText(cache, warm = "♨") {
58
59
  const rate = cache.lastHitRate ?? cache.hitRate;
59
60
  const value = cache.reporting === "silent"
60
- ? "未报告"
61
+ ? msg().interactive.statusLine.cacheSilent
61
62
  : cache.reporting === "reported" && rate !== undefined
62
63
  ? `${Math.round(rate * 100)}%`
63
64
  : "—";
@@ -178,7 +179,7 @@ export function usageItems(stats, queue, source, theme) {
178
179
  out.codemode = strict ? label : `${label} ${theme.fg("error", "net!")}`;
179
180
  }
180
181
  if (source.bashSandbox?.() === true)
181
- out.sandbox = dim("沙箱");
182
+ out.sandbox = dim(msg().interactive.statusLine.sandbox);
182
183
  const preset = source.preset();
183
184
  if (preset !== "default")
184
185
  out.preset = dim(`preset ${preset}`);
@@ -262,7 +263,7 @@ export class StatusBar {
262
263
  });
263
264
  if (width >= 40) {
264
265
  parts.push({
265
- text: dim("shift+tab 切换"),
266
+ text: dim(msg().interactive.statusLine.cycleHint),
266
267
  priority: full ? FULL_HINT : COMPACT.hint,
267
268
  zone: "left",
268
269
  });
@@ -13,6 +13,7 @@
13
13
  * 完成后父会话收到的 `<task-notification>` 只显示一行(`notificationSummary`),失败 / 停止另有一行提示。
14
14
  * 外部 runner(claude / codex)同一组事件,用量可能缺。
15
15
  */
16
+ import { msg } from "../../i18n/index.js";
16
17
  import { formatElapsed } from "../../tui.js";
17
18
  import { formatTokenCount } from "../session-report.js";
18
19
  import { taskStatusText } from "./tasks-report.js";
@@ -96,10 +97,12 @@ export function subagentLine(state, theme, now) {
96
97
  const g = theme.glyphs;
97
98
  const end = state.endedAt ?? now;
98
99
  const elapsed = formatElapsed(end - state.startedAt);
99
- const status = state.status === "running" ? `运行中 ${elapsed}` : `${taskStatusText(state.status)} ${elapsed}`;
100
+ const status = state.status === "running"
101
+ ? msg().interactive.subagent.running(elapsed)
102
+ : `${taskStatusText(state.status)} ${elapsed}`;
100
103
  const facts = [status];
101
104
  if (state.turns > 0)
102
- facts.push(`${state.turns} 轮`);
105
+ facts.push(msg().panels.tasks.turns(state.turns));
103
106
  if (state.tools.length > 0)
104
107
  facts.push(state.tools.join(" "));
105
108
  const usage = state.usage;
@@ -113,14 +116,13 @@ export function subagentLine(state, theme, now) {
113
116
  ? "error"
114
117
  : "warning";
115
118
  const agent = state.runner !== "ama" && state.runner !== state.agent
116
- ? `${state.agent}(${state.runner})`
119
+ ? msg().panels.tasks.agentRunner(state.agent, state.runner)
117
120
  : state.agent;
118
121
  return theme.fg("tool", agent) + theme.fg("dim", " · ") + theme.fg(color, facts.join(" · "));
119
122
  }
120
123
  /** 后台任务结束的一行提示。 */
121
124
  export function backgroundEndText(state) {
122
- const turns = state.turns > 0 ? ` · ${state.turns} 轮` : "";
123
- return `后台任务 ${state.taskId}(${state.agent})${taskStatusText(state.status)}${turns} · /tasks 查看输出`;
125
+ return msg().interactive.subagent.backgroundEnd(state.taskId, state.agent, taskStatusText(state.status), state.turns);
124
126
  }
125
127
  /**
126
128
  * 父会话收到的 `<task-notification …>`(origin `task` 的用户消息)在消息区只显示一行:
@@ -141,8 +143,8 @@ export function notificationSummary(text) {
141
143
  ];
142
144
  const turns = attrs.get("turns");
143
145
  if (turns !== undefined)
144
- parts.push(`${turns} 轮`);
145
- parts.push("/tasks 查看输出");
146
+ parts.push(msg().interactive.subagent.notificationTurns(turns));
147
+ parts.push(msg().interactive.subagent.viewOutput);
146
148
  return parts.join(" · ");
147
149
  }
148
150
  const STATUS_KEYS = {
@@ -23,5 +23,11 @@ export declare function describeTasks(sessionId: string, now: number): string;
23
23
  export declare function describeTaskOutput(sessionId: string, taskId: string, now: number): string;
24
24
  /** 类型一行的状态:外部 Agent 写安装与版本。 */
25
25
  export declare function agentFacts(agent: AgentInfo): string[];
26
+ /** [W6-C0] 带状态的事实项:界面按 `state` 上色,不按文案判断(文案会随界面语言变)。 */
27
+ export interface AgentFact {
28
+ text: string;
29
+ state?: "missing" | "installed";
30
+ }
31
+ export declare function agentFactItems(agent: AgentInfo): AgentFact[];
26
32
  /** `/agents` 的纯文本(line 模式)。 */
27
33
  export declare function describeAgents(sessionId: string): string;
@@ -7,18 +7,11 @@
7
7
  */
8
8
  import { cachedAgentInfos } from "../../agents/external.js";
9
9
  import { registryOf, sessionAgents, taskRegistryView } from "../../agent/subagent-registry.js";
10
+ import { msg } from "../../i18n/index.js";
10
11
  import { formatTokenCount, formatUsd } from "../session-report.js";
11
12
  import { formatDuration } from "./tool-summary.js";
12
- const STATUS = {
13
- running: "运行中",
14
- completed: "完成",
15
- failed: "失败",
16
- aborted: "已停止",
17
- max_turns: "轮数耗尽",
18
- interrupted: "已中断",
19
- };
20
13
  export function taskStatusText(status) {
21
- return STATUS[status];
14
+ return msg().panels.tasks.status[status];
22
15
  }
23
16
  export function listTasks(sessionId) {
24
17
  return taskRegistryView(sessionId)?.list() ?? [];
@@ -41,7 +34,7 @@ export function taskFacts(task, now) {
41
34
  const end = task.endedAt ?? now;
42
35
  const facts = [taskStatusText(task.status), formatDuration(end - task.startedAt)];
43
36
  if (task.turns !== undefined && task.turns > 0)
44
- facts.push(`${task.turns} 轮`);
37
+ facts.push(msg().panels.tasks.turns(task.turns));
45
38
  const usage = task.usage;
46
39
  if (usage !== undefined && usage.input + usage.output + usage.cacheRead > 0)
47
40
  facts.push(`↑${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ↓${formatTokenCount(usage.output)}`);
@@ -55,60 +48,64 @@ function oneLine(text, max = 60) {
55
48
  }
56
49
  /** `t1 explore · 运行中 · 1m05s · 7 轮 · 描述` */
57
50
  export function taskLine(task, now) {
51
+ const m = msg().panels.tasks;
58
52
  const agent = task.runner !== "ama" && task.runner !== task.agent
59
- ? `${task.agent}(${task.runner})`
53
+ ? m.agentRunner(task.agent, task.runner)
60
54
  : task.agent;
61
55
  const parts = [agent, ...taskFacts(task, now)];
62
56
  if (task.background)
63
- parts.push("后台");
57
+ parts.push(m.background);
64
58
  const description = oneLine(task.description);
65
59
  return `${task.taskId} ${parts.join(" · ")}${description !== "" ? ` ${description}` : ""}`;
66
60
  }
67
61
  /** `/tasks` 的纯文本(line 模式)。 */
68
62
  export function describeTasks(sessionId, now) {
63
+ const m = msg().panels.tasks;
69
64
  const tasks = listTasks(sessionId);
70
65
  if (tasks.length === 0)
71
- return "还没有子 Agent 任务";
66
+ return m.none;
72
67
  return [
73
- `子 Agent 任务(${tasks.length}):`,
68
+ m.heading(tasks.length),
74
69
  ...tasks.map((task) => ` ${taskLine(task, now)}`),
75
- "/tasks <id> 查看输出 · /tasks stop <id> 停止",
70
+ m.footer,
76
71
  ].join("\n");
77
72
  }
78
73
  /** 一个任务的输出全文(line 模式 `/tasks <id>`)。 */
79
74
  export function describeTaskOutput(sessionId, taskId, now) {
75
+ const m = msg().panels.tasks;
80
76
  const task = taskRegistryView(sessionId)?.get(taskId);
81
77
  if (task === undefined)
82
- return `没有任务 ${taskId}`;
78
+ return m.notFound(taskId);
83
79
  const output = taskOutput(sessionId, taskId) ?? "";
84
- const file = task.outputFile !== undefined ? `\n全文:${task.outputFile}` : "";
85
- return `${taskLine(task, now)}${file}\n${output.trim() === "" ? "(还没有输出)" : output.trimEnd()}`;
80
+ const file = task.outputFile !== undefined ? `\n${m.fullOutput(task.outputFile)}` : "";
81
+ return `${taskLine(task, now)}${file}\n${output.trim() === "" ? m.noOutput : output.trimEnd()}`;
82
+ }
83
+ function sourceText(source) {
84
+ const table = msg().panels.agents.source;
85
+ return table[source] ?? source;
86
86
  }
87
- const SOURCE = {
88
- builtin: "内置",
89
- cli: "命令行",
90
- profile: "profile",
91
- user: "用户",
92
- project: "项目",
93
- host: "宿主",
94
- };
95
87
  /** 类型一行的状态:外部 Agent 写安装与版本。 */
96
88
  export function agentFacts(agent) {
97
- const facts = [agent.runner, SOURCE[agent.source] ?? agent.source];
89
+ return agentFactItems(agent).map((fact) => fact.text);
90
+ }
91
+ export function agentFactItems(agent) {
92
+ const m = msg().panels.agents;
93
+ const facts = [{ text: agent.runner }, { text: sourceText(agent.source) }];
98
94
  if (agent.installed === false)
99
- facts.push("未安装");
95
+ facts.push({ text: m.notInstalled, state: "missing" });
100
96
  else if (agent.installed === true)
101
- facts.push(agent.version !== undefined ? `已安装 ${agent.version}` : "已安装");
97
+ facts.push({ text: m.installed(agent.version), state: "installed" });
102
98
  return facts;
103
99
  }
104
100
  /** `/agents` 的纯文本(line 模式)。 */
105
101
  export function describeAgents(sessionId) {
102
+ const m = msg().panels.agents;
106
103
  const agents = listAgents(sessionId);
107
104
  if (agents.length === 0)
108
- return "当前会话没有子 Agent(task 工具未启用)";
105
+ return m.none;
109
106
  const width = Math.max(...agents.map((a) => a.name.length));
110
107
  return [
111
- `子 Agent 类型(${agents.length}):`,
108
+ m.typesHeading(agents.length),
112
109
  ...agents.map((a) => ` ${a.name.padEnd(width)} ${agentFacts(a).join(" · ")} ${oneLine(a.description)}`),
113
110
  ].join("\n");
114
111
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 交互模式装配用到的两个小工具(从 interactive-mode.ts 拆出,控制单文件行数):真实终端与 keybindings.json。
3
+ */
4
+ import type { Runtime } from "../../cli/runtime.js";
5
+ import { Keybindings, type Terminal } from "../../tui.js";
6
+ /** stdin / stdout 都是 TTY 才用真实终端;否则抛 `terminal_init_failed`(调用方降级到行式界面)。 */
7
+ export declare function processTerminal(): Terminal;
8
+ /** 读 `<configDir>/keybindings.json`;问题逐条交给 `warn`。 */
9
+ export declare function loadKeys(runtime: Runtime, warn: (m: string) => void): Keybindings;