@armadra/agent 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/CHANGELOG.md +177 -304
  2. package/CHANGELOG.zh-CN.md +442 -0
  3. package/README.md +408 -364
  4. package/README.zh-CN.md +705 -0
  5. package/dist/agent/session-plan.js +2 -2
  6. package/dist/agent/session-state.d.ts +3 -0
  7. package/dist/agent/session-state.js +20 -0
  8. package/dist/agent/session-subagent.d.ts +15 -1
  9. package/dist/agent/session-subagent.js +26 -3
  10. package/dist/agent/session-telemetry.d.ts +16 -2
  11. package/dist/agent/session-telemetry.js +29 -7
  12. package/dist/agent/session-tools.js +5 -2
  13. package/dist/agent/session-trace-writer.d.ts +27 -0
  14. package/dist/agent/session-trace-writer.js +253 -0
  15. package/dist/agent/session.d.ts +2 -0
  16. package/dist/agent/session.js +12 -0
  17. package/dist/agent/subagent-direct.d.ts +20 -0
  18. package/dist/agent/subagent-direct.js +76 -0
  19. package/dist/agent/subagent-registry.d.ts +8 -1
  20. package/dist/agent/subagent-registry.js +28 -1
  21. package/dist/agent/system-prompt.d.ts +3 -1
  22. package/dist/agent/system-prompt.js +3 -0
  23. package/dist/agent/tool-runner.d.ts +2 -1
  24. package/dist/agent/tool-runner.js +5 -4
  25. package/dist/agent/types-w6.d.ts +39 -0
  26. package/dist/agent/types-w6.js +4 -0
  27. package/dist/agent/types.d.ts +5 -2
  28. package/dist/agents/external.js +1 -1
  29. package/dist/agents/task-record.d.ts +74 -1
  30. package/dist/agents/task-record.js +100 -0
  31. package/dist/ai/apis/cache-params.js +2 -1
  32. package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
  33. package/dist/ai/apis/chatgpt-backend.js +224 -0
  34. package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
  35. package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
  36. package/dist/ai/apis/openai-responses-request.d.ts +2 -1
  37. package/dist/ai/apis/openai-responses-request.js +8 -2
  38. package/dist/ai/apis/openai-responses.d.ts +2 -0
  39. package/dist/ai/apis/openai-responses.js +51 -16
  40. package/dist/ai/overflow.d.ts +1 -1
  41. package/dist/ai/overflow.js +10 -7
  42. package/dist/ai/providers/auth.d.ts +15 -2
  43. package/dist/ai/providers/auth.js +69 -2
  44. package/dist/ai/providers/builtin.js +27 -0
  45. package/dist/ai/providers/catalog-data.js +1 -0
  46. package/dist/ai/providers/enrich.js +2 -7
  47. package/dist/ai/providers/models-dev-cache.js +15 -19
  48. package/dist/ai/providers/models-dev-snapshot.js +8 -7
  49. package/dist/ai/providers/models-dev.js +5 -15
  50. package/dist/ai/providers/suggest.js +2 -16
  51. package/dist/ai/types.d.ts +27 -1
  52. package/dist/auth/chatgpt/backend-client.d.ts +26 -0
  53. package/dist/auth/chatgpt/backend-client.js +74 -0
  54. package/dist/auth/chatgpt/claims.d.ts +17 -0
  55. package/dist/auth/chatgpt/claims.js +46 -0
  56. package/dist/auth/chatgpt/cli.d.ts +33 -0
  57. package/dist/auth/chatgpt/cli.js +252 -0
  58. package/dist/auth/chatgpt/doctor.d.ts +17 -0
  59. package/dist/auth/chatgpt/doctor.js +36 -0
  60. package/dist/auth/chatgpt/host-id.d.ts +7 -0
  61. package/dist/auth/chatgpt/host-id.js +26 -0
  62. package/dist/auth/chatgpt/login.d.ts +30 -0
  63. package/dist/auth/chatgpt/login.js +130 -0
  64. package/dist/auth/chatgpt/presets.d.ts +66 -0
  65. package/dist/auth/chatgpt/presets.js +120 -0
  66. package/dist/auth/chatgpt/quota-text.d.ts +13 -0
  67. package/dist/auth/chatgpt/quota-text.js +36 -0
  68. package/dist/auth/oauth/browser.d.ts +12 -0
  69. package/dist/auth/oauth/browser.js +27 -0
  70. package/dist/auth/oauth/callback-server.d.ts +47 -0
  71. package/dist/auth/oauth/callback-server.js +147 -0
  72. package/dist/auth/oauth/flows.d.ts +62 -0
  73. package/dist/auth/oauth/flows.js +113 -0
  74. package/dist/auth/oauth/jwt.d.ts +24 -0
  75. package/dist/auth/oauth/jwt.js +81 -0
  76. package/dist/auth/oauth/live.d.ts +21 -0
  77. package/dist/auth/oauth/live.js +25 -0
  78. package/dist/auth/oauth/oidc.d.ts +26 -0
  79. package/dist/auth/oauth/oidc.js +72 -0
  80. package/dist/auth/oauth/pkce.d.ts +15 -0
  81. package/dist/auth/oauth/pkce.js +20 -0
  82. package/dist/auth/oauth/refresh.d.ts +35 -0
  83. package/dist/auth/oauth/refresh.js +129 -0
  84. package/dist/auth/oauth/token-client.d.ts +33 -0
  85. package/dist/auth/oauth/token-client.js +121 -0
  86. package/dist/auth/oauth/token-store.d.ts +23 -0
  87. package/dist/auth/oauth/token-store.js +125 -0
  88. package/dist/auth/testing/fake-oauth.d.ts +73 -0
  89. package/dist/auth/testing/fake-oauth.js +271 -0
  90. package/dist/auth/testing/refresh-child.d.ts +5 -0
  91. package/dist/auth/testing/refresh-child.js +16 -0
  92. package/dist/bundle/ama.cjs +25928 -11144
  93. package/dist/checkpoints/backend.js +6 -5
  94. package/dist/checkpoints/restore.js +3 -2
  95. package/dist/checkpoints/settings.js +2 -1
  96. package/dist/checkpoints/shadow-git.js +7 -6
  97. package/dist/checkpoints/shadow-restore.js +3 -2
  98. package/dist/checkpoints/tracker.js +4 -3
  99. package/dist/cli/args.d.ts +9 -2
  100. package/dist/cli/args.js +74 -27
  101. package/dist/cli/bootstrap.js +53 -31
  102. package/dist/cli/choice-prompt.js +8 -6
  103. package/dist/cli/codemode-notice.js +2 -2
  104. package/dist/cli/compose-agents.js +2 -1
  105. package/dist/cli/compose-extensions.js +2 -0
  106. package/dist/cli/compose-memory.d.ts +53 -0
  107. package/dist/cli/compose-memory.js +127 -0
  108. package/dist/cli/compose-providers.d.ts +5 -0
  109. package/dist/cli/compose-providers.js +32 -2
  110. package/dist/cli/compose-session.d.ts +5 -0
  111. package/dist/cli/compose-session.js +27 -13
  112. package/dist/cli/compose-store.d.ts +2 -0
  113. package/dist/cli/compose-store.js +9 -5
  114. package/dist/cli/compose.d.ts +2 -0
  115. package/dist/cli/compose.js +13 -5
  116. package/dist/cli/default-model.d.ts +0 -2
  117. package/dist/cli/default-model.js +5 -8
  118. package/dist/cli/deps.d.ts +5 -1
  119. package/dist/cli/exit-codes.d.ts +1 -1
  120. package/dist/cli/exit-codes.js +7 -16
  121. package/dist/cli/from-prompt.js +3 -2
  122. package/dist/cli/help-text.d.ts +2 -1
  123. package/dist/cli/help-text.js +5 -99
  124. package/dist/cli/main.d.ts +5 -0
  125. package/dist/cli/main.js +21 -2
  126. package/dist/cli/proxy.js +14 -9
  127. package/dist/cli/runtime.d.ts +5 -0
  128. package/dist/cli/startup-screen.js +20 -27
  129. package/dist/cli/startup-steps.js +6 -8
  130. package/dist/cli/subcommands/auth.d.ts +6 -3
  131. package/dist/cli/subcommands/auth.js +52 -22
  132. package/dist/cli/subcommands/config-set.d.ts +21 -0
  133. package/dist/cli/subcommands/config-set.js +137 -0
  134. package/dist/cli/subcommands/config.d.ts +2 -1
  135. package/dist/cli/subcommands/config.js +51 -37
  136. package/dist/cli/subcommands/doctor.d.ts +2 -1
  137. package/dist/cli/subcommands/doctor.js +97 -58
  138. package/dist/cli/subcommands/init.d.ts +1 -1
  139. package/dist/cli/subcommands/init.js +8 -7
  140. package/dist/cli/subcommands/memory.d.ts +18 -0
  141. package/dist/cli/subcommands/memory.js +189 -0
  142. package/dist/cli/subcommands/model-meta.js +11 -9
  143. package/dist/cli/subcommands/models-cache-probe.js +23 -20
  144. package/dist/cli/subcommands/models-discover.d.ts +3 -0
  145. package/dist/cli/subcommands/models-discover.js +44 -21
  146. package/dist/cli/subcommands/models.d.ts +1 -1
  147. package/dist/cli/subcommands/models.js +29 -22
  148. package/dist/cli/subcommands/probe-runner.js +8 -7
  149. package/dist/cli/subcommands/providers-list.js +32 -21
  150. package/dist/cli/subcommands/providers-plan.js +24 -25
  151. package/dist/cli/subcommands/providers-probe.js +5 -6
  152. package/dist/cli/subcommands/providers.d.ts +1 -1
  153. package/dist/cli/subcommands/providers.js +45 -50
  154. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  155. package/dist/cli/subcommands/sessions-export.js +10 -9
  156. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  157. package/dist/cli/subcommands/sessions-search.js +11 -10
  158. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  159. package/dist/cli/subcommands/sessions-trace.js +156 -0
  160. package/dist/cli/subcommands/sessions.d.ts +4 -3
  161. package/dist/cli/subcommands/sessions.js +40 -37
  162. package/dist/cli/subcommands/stats.d.ts +1 -1
  163. package/dist/cli/subcommands/stats.js +49 -30
  164. package/dist/cli/system-prompt-arg.js +3 -2
  165. package/dist/codemode/capability.js +3 -2
  166. package/dist/compaction/post-compact.d.ts +1 -0
  167. package/dist/compaction/post-compact.js +15 -1
  168. package/dist/compaction/prune-tier.d.ts +1 -1
  169. package/dist/compaction/prune-tier.js +3 -3
  170. package/dist/compaction/serialize.js +2 -1
  171. package/dist/config/auth-file.d.ts +12 -2
  172. package/dist/config/auth-file.js +32 -10
  173. package/dist/config/checker.js +12 -11
  174. package/dist/config/context-files.js +3 -2
  175. package/dist/config/edit.d.ts +106 -0
  176. package/dist/config/edit.js +350 -0
  177. package/dist/config/init.d.ts +4 -3
  178. package/dist/config/init.js +10 -18
  179. package/dist/config/json-schema.d.ts +2 -1
  180. package/dist/config/json-schema.js +101 -68
  181. package/dist/config/key-docs.d.ts +18 -7
  182. package/dist/config/key-docs.js +43 -128
  183. package/dist/config/load.js +7 -6
  184. package/dist/config/merge.d.ts +4 -1
  185. package/dist/config/merge.js +42 -22
  186. package/dist/config/paths.js +6 -5
  187. package/dist/config/profile.d.ts +5 -1
  188. package/dist/config/profile.js +7 -2
  189. package/dist/config/schema-w5.js +3 -2
  190. package/dist/config/schema-w6.d.ts +19 -0
  191. package/dist/config/schema-w6.js +115 -0
  192. package/dist/config/schema.js +34 -20
  193. package/dist/config/settings-registry.d.ts +78 -0
  194. package/dist/config/settings-registry.js +184 -0
  195. package/dist/config/types-w6.d.ts +109 -0
  196. package/dist/config/types-w6.js +19 -0
  197. package/dist/config/types.d.ts +11 -8
  198. package/dist/config/types.js +1 -0
  199. package/dist/drivers/acp/client.js +1 -1
  200. package/dist/drivers/acp/driver.js +13 -8
  201. package/dist/drivers/agents.js +4 -3
  202. package/dist/drivers/base.js +3 -2
  203. package/dist/drivers/host-runners.js +2 -1
  204. package/dist/drivers/native/claude-stream.js +12 -11
  205. package/dist/drivers/native/codex-app-server.js +17 -12
  206. package/dist/drivers/native/oneshot.js +8 -7
  207. package/dist/drivers/pool.js +1 -1
  208. package/dist/drivers/runner.d.ts +3 -1
  209. package/dist/drivers/runner.js +68 -20
  210. package/dist/drivers/turn.js +1 -1
  211. package/dist/hooks/config.js +3 -2
  212. package/dist/hooks/protocol.js +18 -12
  213. package/dist/host/api-impl.js +11 -10
  214. package/dist/host/loader.js +9 -8
  215. package/dist/host/types.d.ts +3 -0
  216. package/dist/i18n/catalog.d.ts +2169 -0
  217. package/dist/i18n/catalog.js +72 -0
  218. package/dist/i18n/format.d.ts +21 -0
  219. package/dist/i18n/format.js +58 -0
  220. package/dist/i18n/index.d.ts +58 -0
  221. package/dist/i18n/index.js +72 -0
  222. package/dist/i18n/messages/agents.d.ts +84 -0
  223. package/dist/i18n/messages/agents.js +85 -0
  224. package/dist/i18n/messages/approval.d.ts +99 -0
  225. package/dist/i18n/messages/approval.js +100 -0
  226. package/dist/i18n/messages/auth.d.ts +187 -0
  227. package/dist/i18n/messages/auth.js +189 -0
  228. package/dist/i18n/messages/cli-args.d.ts +46 -0
  229. package/dist/i18n/messages/cli-args.js +46 -0
  230. package/dist/i18n/messages/cli-help.d.ts +12 -0
  231. package/dist/i18n/messages/cli-help.js +244 -0
  232. package/dist/i18n/messages/cli.d.ts +336 -0
  233. package/dist/i18n/messages/cli.js +311 -0
  234. package/dist/i18n/messages/config-keys.d.ts +289 -0
  235. package/dist/i18n/messages/config-keys.js +292 -0
  236. package/dist/i18n/messages/config.d.ts +502 -0
  237. package/dist/i18n/messages/config.js +239 -0
  238. package/dist/i18n/messages/drivers.d.ts +123 -0
  239. package/dist/i18n/messages/drivers.js +124 -0
  240. package/dist/i18n/messages/errors.d.ts +83 -0
  241. package/dist/i18n/messages/errors.js +171 -0
  242. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  243. package/dist/i18n/messages/interactive-line.js +69 -0
  244. package/dist/i18n/messages/interactive-startup.d.ts +103 -0
  245. package/dist/i18n/messages/interactive-startup.js +104 -0
  246. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  247. package/dist/i18n/messages/interactive-view.js +141 -0
  248. package/dist/i18n/messages/interactive.d.ts +493 -0
  249. package/dist/i18n/messages/interactive.js +248 -0
  250. package/dist/i18n/messages/memory.d.ts +123 -0
  251. package/dist/i18n/messages/memory.js +128 -0
  252. package/dist/i18n/messages/panels.d.ts +190 -0
  253. package/dist/i18n/messages/panels.js +189 -0
  254. package/dist/i18n/messages/permissions.d.ts +126 -0
  255. package/dist/i18n/messages/permissions.js +151 -0
  256. package/dist/i18n/messages/plan.d.ts +123 -0
  257. package/dist/i18n/messages/plan.js +124 -0
  258. package/dist/i18n/messages/print.d.ts +86 -0
  259. package/dist/i18n/messages/print.js +91 -0
  260. package/dist/i18n/messages/report.d.ts +391 -0
  261. package/dist/i18n/messages/report.js +490 -0
  262. package/dist/i18n/messages/rewind.d.ts +198 -0
  263. package/dist/i18n/messages/rewind.js +217 -0
  264. package/dist/i18n/messages/session.d.ts +230 -0
  265. package/dist/i18n/messages/session.js +258 -0
  266. package/dist/i18n/messages/settings.d.ts +348 -0
  267. package/dist/i18n/messages/settings.js +336 -0
  268. package/dist/i18n/messages/subcommands-config.d.ts +111 -0
  269. package/dist/i18n/messages/subcommands-config.js +127 -0
  270. package/dist/i18n/messages/subcommands.d.ts +548 -0
  271. package/dist/i18n/messages/subcommands.js +474 -0
  272. package/dist/i18n/messages/trace.d.ts +243 -0
  273. package/dist/i18n/messages/trace.js +238 -0
  274. package/dist/i18n/types.d.ts +15 -0
  275. package/dist/i18n/types.js +7 -0
  276. package/dist/index.d.ts +6 -0
  277. package/dist/index.js +2 -0
  278. package/dist/memory/edit.d.ts +24 -0
  279. package/dist/memory/edit.js +63 -0
  280. package/dist/memory/frontmatter.d.ts +37 -0
  281. package/dist/memory/frontmatter.js +79 -0
  282. package/dist/memory/index.d.ts +28 -0
  283. package/dist/memory/index.js +126 -0
  284. package/dist/memory/lock.d.ts +17 -0
  285. package/dist/memory/lock.js +62 -0
  286. package/dist/memory/paths.d.ts +57 -0
  287. package/dist/memory/paths.js +175 -0
  288. package/dist/memory/report.d.ts +36 -0
  289. package/dist/memory/report.js +86 -0
  290. package/dist/memory/runtime.d.ts +42 -0
  291. package/dist/memory/runtime.js +36 -0
  292. package/dist/memory/secrets.d.ts +8 -0
  293. package/dist/memory/secrets.js +27 -0
  294. package/dist/memory/section.d.ts +28 -0
  295. package/dist/memory/section.js +59 -0
  296. package/dist/memory/store.d.ts +70 -0
  297. package/dist/memory/store.js +284 -0
  298. package/dist/memory/tool.d.ts +31 -0
  299. package/dist/memory/tool.js +94 -0
  300. package/dist/modes/acp/acp-events.js +2 -1
  301. package/dist/modes/acp/acp-server.js +13 -12
  302. package/dist/modes/commands-core.d.ts +11 -0
  303. package/dist/modes/commands-core.js +93 -62
  304. package/dist/modes/image-input.js +20 -6
  305. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  306. package/dist/modes/interactive/agent-bar.js +248 -0
  307. package/dist/modes/interactive/agent-panels.js +27 -26
  308. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  309. package/dist/modes/interactive/agent-transcript.js +191 -0
  310. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  311. package/dist/modes/interactive/agent-ui.js +180 -14
  312. package/dist/modes/interactive/agent-view.d.ts +72 -0
  313. package/dist/modes/interactive/agent-view.js +281 -0
  314. package/dist/modes/interactive/approval-dialog.js +46 -34
  315. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  316. package/dist/modes/interactive/clipboard-paste.js +9 -4
  317. package/dist/modes/interactive/commands.d.ts +19 -1
  318. package/dist/modes/interactive/commands.js +84 -40
  319. package/dist/modes/interactive/completion.js +2 -1
  320. package/dist/modes/interactive/config-panel.d.ts +70 -0
  321. package/dist/modes/interactive/config-panel.js +319 -0
  322. package/dist/modes/interactive/config-ui.d.ts +96 -0
  323. package/dist/modes/interactive/config-ui.js +397 -0
  324. package/dist/modes/interactive/confirm-dialog.js +6 -7
  325. package/dist/modes/interactive/event-notices.js +11 -9
  326. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  327. package/dist/modes/interactive/interactive-mode.js +19 -22
  328. package/dist/modes/interactive/key-dispatch.d.ts +12 -0
  329. package/dist/modes/interactive/key-dispatch.js +24 -9
  330. package/dist/modes/interactive/line/line-editor.js +2 -1
  331. package/dist/modes/interactive/line/line-mode.js +18 -7
  332. package/dist/modes/interactive/line/line-render.js +25 -24
  333. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  334. package/dist/modes/interactive/memory-panel.js +221 -0
  335. package/dist/modes/interactive/message-view.d.ts +4 -2
  336. package/dist/modes/interactive/message-view.js +42 -33
  337. package/dist/modes/interactive/panels.js +39 -31
  338. package/dist/modes/interactive/pickers.d.ts +2 -1
  339. package/dist/modes/interactive/pickers.js +10 -6
  340. package/dist/modes/interactive/plan-command.d.ts +1 -1
  341. package/dist/modes/interactive/plan-command.js +24 -27
  342. package/dist/modes/interactive/plan-dialog.js +18 -17
  343. package/dist/modes/interactive/plan-flow.js +6 -5
  344. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  345. package/dist/modes/interactive/rewind-command.js +18 -16
  346. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  347. package/dist/modes/interactive/rewind-flow.js +13 -14
  348. package/dist/modes/interactive/rewind-list.js +7 -6
  349. package/dist/modes/interactive/rewind-panel.js +40 -40
  350. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  351. package/dist/modes/interactive/rewind-text.js +48 -38
  352. package/dist/modes/interactive/run-indicator.js +15 -12
  353. package/dist/modes/interactive/session-events.js +3 -2
  354. package/dist/modes/interactive/startup-header.js +22 -23
  355. package/dist/modes/interactive/startup-ui.js +38 -30
  356. package/dist/modes/interactive/status-area.d.ts +2 -0
  357. package/dist/modes/interactive/status-area.js +8 -2
  358. package/dist/modes/interactive/status-bar.js +4 -3
  359. package/dist/modes/interactive/subagent-view.js +9 -7
  360. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  361. package/dist/modes/interactive/tasks-report.js +28 -31
  362. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  363. package/dist/modes/interactive/terminal-setup.js +23 -0
  364. package/dist/modes/interactive/tool-summary.js +19 -17
  365. package/dist/modes/interactive/tool-view.js +7 -4
  366. package/dist/modes/interactive/trace-view.d.ts +89 -0
  367. package/dist/modes/interactive/trace-view.js +332 -0
  368. package/dist/modes/print/print-mode.js +14 -15
  369. package/dist/modes/rpc/commands.js +7 -3
  370. package/dist/modes/rpc/rpc-mode.js +9 -3
  371. package/dist/modes/session-report.d.ts +2 -0
  372. package/dist/modes/session-report.js +101 -105
  373. package/dist/modes/startup-ui-text.js +11 -6
  374. package/dist/permissions/bypass.d.ts +8 -10
  375. package/dist/permissions/bypass.js +19 -10
  376. package/dist/permissions/memory-class.d.ts +23 -0
  377. package/dist/permissions/memory-class.js +54 -0
  378. package/dist/permissions/modes.d.ts +3 -3
  379. package/dist/permissions/modes.js +21 -16
  380. package/dist/permissions/pipeline.d.ts +1 -1
  381. package/dist/permissions/pipeline.js +9 -2
  382. package/dist/permissions/preview.js +49 -42
  383. package/dist/permissions/rules.js +5 -2
  384. package/dist/permissions/types.d.ts +4 -0
  385. package/dist/plan/store.js +2 -1
  386. package/dist/rpc.d.ts +39 -1
  387. package/dist/rpc.js +3 -0
  388. package/dist/sandbox/bash.js +11 -8
  389. package/dist/sandbox/detect.js +14 -11
  390. package/dist/sdk.d.ts +17 -1
  391. package/dist/sdk.js +29 -7
  392. package/dist/session/export.js +31 -30
  393. package/dist/session/manager.d.ts +1 -1
  394. package/dist/session/manager.js +5 -3
  395. package/dist/session/reuse.js +5 -4
  396. package/dist/session/scan.js +3 -2
  397. package/dist/session/stats-aggregate.d.ts +3 -1
  398. package/dist/session/stats-aggregate.js +5 -1
  399. package/dist/session/stats-index.js +2 -1
  400. package/dist/session/stats-scan.d.ts +4 -1
  401. package/dist/session/stats-scan.js +6 -2
  402. package/dist/session/store.d.ts +11 -0
  403. package/dist/session/store.js +48 -1
  404. package/dist/session/types.d.ts +2 -0
  405. package/dist/skills/builtin.js +2 -1
  406. package/dist/tools/image-file.d.ts +26 -1
  407. package/dist/tools/image-file.js +55 -13
  408. package/dist/tools/presets.d.ts +14 -1
  409. package/dist/tools/presets.js +3 -3
  410. package/dist/tools/registry.js +1 -1
  411. package/dist/tools/truncate.d.ts +1 -1
  412. package/dist/tools/truncate.js +2 -2
  413. package/dist/tools/types.d.ts +17 -1
  414. package/dist/trace/build-index.d.ts +91 -0
  415. package/dist/trace/build-index.js +127 -0
  416. package/dist/trace/build-nodes.d.ts +24 -0
  417. package/dist/trace/build-nodes.js +279 -0
  418. package/dist/trace/build-util.d.ts +43 -0
  419. package/dist/trace/build-util.js +120 -0
  420. package/dist/trace/build.d.ts +82 -0
  421. package/dist/trace/build.js +382 -0
  422. package/dist/trace/detail.d.ts +35 -0
  423. package/dist/trace/detail.js +205 -0
  424. package/dist/trace/flatten.d.ts +69 -0
  425. package/dist/trace/flatten.js +173 -0
  426. package/dist/trace/format.d.ts +47 -0
  427. package/dist/trace/format.js +329 -0
  428. package/dist/trace/html-template.d.ts +19 -0
  429. package/dist/trace/html-template.js +150 -0
  430. package/dist/trace/html.d.ts +104 -0
  431. package/dist/trace/html.js +292 -0
  432. package/dist/trace/preview.d.ts +29 -0
  433. package/dist/trace/preview.js +59 -0
  434. package/dist/trace/query-session.d.ts +14 -0
  435. package/dist/trace/query-session.js +38 -0
  436. package/dist/trace/query.d.ts +55 -0
  437. package/dist/trace/query.js +188 -0
  438. package/dist/trace/session.d.ts +40 -0
  439. package/dist/trace/session.js +168 -0
  440. package/dist/trace/types.d.ts +243 -0
  441. package/dist/trace/types.js +13 -0
  442. package/dist/tui/components/editor-paste.d.ts +2 -0
  443. package/dist/tui/components/editor-paste.js +6 -3
  444. package/dist/tui/components/editor.js +2 -2
  445. package/dist/tui/components/loader.d.ts +3 -0
  446. package/dist/tui/components/loader.js +14 -0
  447. package/dist/tui/components/settings-list.d.ts +61 -0
  448. package/dist/tui/components/settings-list.js +135 -0
  449. package/dist/tui/keybindings.d.ts +5 -0
  450. package/dist/tui/keybindings.js +17 -5
  451. package/dist/tui.d.ts +1 -0
  452. package/dist/tui.js +2 -0
  453. package/docs/en/host-api.md +167 -0
  454. package/docs/en/permissions.md +214 -0
  455. package/docs/en/providers.md +625 -0
  456. package/docs/en/rpc.md +361 -0
  457. package/docs/en/sessions.md +219 -0
  458. package/docs/en/tui.md +527 -0
  459. package/docs/host-api.md +18 -17
  460. package/docs/memory.md +172 -0
  461. package/docs/permissions.md +2 -2
  462. package/docs/providers.md +67 -1
  463. package/docs/rpc.md +31 -3
  464. package/docs/session-format.md +8 -2
  465. package/docs/sessions.md +29 -1
  466. package/docs/tui.md +132 -3
  467. package/package.json +8 -3
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * `modelItems` / `sessionItems` 同时供交互模式里的选择器(pickers.ts)使用。
9
9
  */
10
+ import { msg } from "../../i18n/index.js";
10
11
  import { existsSync, statSync } from "node:fs";
11
12
  import { resolve } from "node:path";
12
13
  import { Container, Editor, ProcessTerminal, SelectList, TUI, Text, createTheme, defaultKeybindings, detectCapabilities, } from "../../tui.js";
@@ -49,7 +50,7 @@ function askSelect(r, prompt) {
49
50
  done(item);
50
51
  },
51
52
  onCancel: () => {
52
- finish("(已取消)");
53
+ finish(msg().interactive.startup.ui.cancelled);
53
54
  done(undefined);
54
55
  },
55
56
  });
@@ -57,10 +58,10 @@ function askSelect(r, prompt) {
57
58
  list.selectValue(prompt.selected);
58
59
  body.addChild(list);
59
60
  body.addChild(new Text(r.theme.fg("dim", prompt.filterable === true
60
- ? "输入过滤 · ↑↓ 选择 · Enter 确认 · Esc 取消"
61
+ ? msg().interactive.startup.ui.hintFilter("↑↓")
61
62
  : prompt.numberKeys === true
62
- ? `↑↓ 选择 · Enter 确认 · 1-${prompt.items.length} 直接选 · Esc 取消`
63
- : "↑↓ 选择 · Enter 确认 · Esc 取消")));
63
+ ? msg().interactive.startup.ui.hintNumbers("↑↓", prompt.items.length)
64
+ : msg().interactive.startup.ui.hint("↑↓"))));
64
65
  tui.start();
65
66
  tui.setFocus(list);
66
67
  });
@@ -92,7 +93,7 @@ function askText(r, prompt) {
92
93
  body.addChild(error);
93
94
  tui.addInputListener((data) => {
94
95
  if (r.keys.matches(data, "tui.select.cancel") && !editor.isCompletionOpen) {
95
- finish("(已取消)");
96
+ finish(msg().interactive.startup.ui.cancelled);
96
97
  done(undefined);
97
98
  return true;
98
99
  }
@@ -131,11 +132,11 @@ export async function modelItems(providers) {
131
132
  let status;
132
133
  let ready = true;
133
134
  if (!provider.requiresApiKey)
134
- status = "本地";
135
+ status = msg().interactive.startup.ui.local;
135
136
  else {
136
137
  const key = await providers.resolveApiKey(provider.id).catch(() => ({ apiKey: undefined }));
137
138
  ready = key.apiKey !== undefined;
138
- status = ready ? "key ✓" : "无 key";
139
+ status = ready ? "key ✓" : msg().interactive.startup.ui.noKey;
139
140
  }
140
141
  const item = (model, group, channel) => {
141
142
  const suffix = channel !== undefined && channel !== model.channel ? `@${channel}` : "";
@@ -168,17 +169,18 @@ export function relativeTime(iso, now) {
168
169
  const at = Date.parse(iso);
169
170
  if (!Number.isFinite(at))
170
171
  return "";
172
+ const m = msg().interactive.startup.ui;
171
173
  const minutes = Math.floor((now - at) / 60_000);
172
174
  if (minutes < 1)
173
- return "刚刚";
175
+ return m.justNow;
174
176
  if (minutes < 60)
175
- return `${minutes} 分钟前`;
177
+ return m.minutesAgo(minutes);
176
178
  const hours = Math.floor(minutes / 60);
177
179
  if (hours < 24)
178
- return `${hours} 小时前`;
180
+ return m.hoursAgo(hours);
179
181
  const days = Math.floor(hours / 24);
180
182
  if (days < 30)
181
- return `${days} 天前`;
183
+ return m.daysAgo(days);
182
184
  return iso.slice(0, 10);
183
185
  }
184
186
  function oneLine(text, max = 60) {
@@ -192,18 +194,21 @@ export function sessionItems(items, now) {
192
194
  .map((item) => ({
193
195
  value: item.id,
194
196
  label: oneLine(item.name ?? item.firstPrompt ?? item.id.slice(0, 8)),
195
- description: `${relativeTime(item.modifiedAt, now)} · ${item.messageCount} 条`,
197
+ description: `${relativeTime(item.modifiedAt, now)} · ${msg().interactive.startup.ui.messages(item.messageCount)}`,
196
198
  }));
197
199
  }
198
200
  // ---------------------------------------------------------------------------
199
201
  // InteractiveUi
200
202
  // ---------------------------------------------------------------------------
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
- ];
203
+ function trustChoices() {
204
+ const m = msg().interactive.startup.ui;
205
+ return [
206
+ { value: "trust", label: m.trustRemember, answer: { trusted: true, remember: true } },
207
+ { value: "once", label: m.trustOnce, answer: { trusted: true, remember: false } },
208
+ { value: "skip", label: m.trustSkip, answer: { trusted: false, remember: false } },
209
+ { value: "never", label: m.trustNever, answer: { trusted: false, remember: true } },
210
+ ];
211
+ }
207
212
  function isDirectory(path) {
208
213
  try {
209
214
  return statSync(path).isDirectory();
@@ -216,24 +221,26 @@ export function createStartupUi(options = {}) {
216
221
  const r = resolveOptions(options);
217
222
  return {
218
223
  async promptTrust(cwd, resources) {
224
+ const m = msg().interactive.startup.ui;
225
+ const choices = trustChoices();
219
226
  const shown = resources.slice(0, 6).map((p) => ` ${p}`);
220
227
  if (resources.length > shown.length)
221
- shown.push(` …另有 ${resources.length - shown.length} 项`);
228
+ shown.push(m.moreResources(resources.length - shown.length));
222
229
  const picked = await askSelect(r, {
223
- title: "信任这个目录的项目资源?",
230
+ title: m.trustTitle,
224
231
  lines: [cwd, ...shown],
225
- items: TRUST_CHOICES.map(({ value, label }) => ({ value, label })),
232
+ items: choices.map(({ value, label }) => ({ value, label })),
226
233
  selected: "once",
227
234
  numberKeys: true,
228
235
  });
229
- const choice = TRUST_CHOICES.find((c) => c.value === picked?.value);
236
+ const choice = choices.find((c) => c.value === picked?.value);
230
237
  return choice?.answer ?? { trusted: false, remember: false };
231
238
  },
232
239
  async pickSession(items) {
233
240
  if (items.length === 0)
234
241
  return undefined;
235
242
  const picked = await askSelect(r, {
236
- title: "恢复哪个会话?",
243
+ title: msg().interactive.startup.ui.resumeTitle,
237
244
  items: sessionItems(items, r.now()),
238
245
  filterable: true,
239
246
  });
@@ -244,7 +251,7 @@ export function createStartupUi(options = {}) {
244
251
  if (items.length === 0)
245
252
  return undefined;
246
253
  const picked = await askSelect(r, {
247
- title: "选择模型",
254
+ title: msg().interactive.startup.ui.modelTitle,
248
255
  lines: [reason],
249
256
  items,
250
257
  filterable: true,
@@ -252,18 +259,19 @@ export function createStartupUi(options = {}) {
252
259
  return picked?.value;
253
260
  },
254
261
  askCwd(missing) {
262
+ const m = msg().interactive.startup.ui;
255
263
  return askText(r, {
256
- title: "会话的工作目录不存在",
257
- lines: [missing, "输入替代目录(Enter 确认 · Esc 取消)"],
258
- placeholder: "目录路径",
264
+ title: m.cwdTitle,
265
+ lines: [missing, m.cwdPrompt],
266
+ placeholder: m.cwdPlaceholder,
259
267
  validate: (text) => {
260
268
  if (text === "")
261
- return "请输入目录";
269
+ return m.cwdEmpty;
262
270
  const abs = resolve(text);
263
271
  if (!existsSync(abs))
264
- return `不存在:${abs}`;
272
+ return m.cwdMissing(abs);
265
273
  if (!isDirectory(abs))
266
- return `不是目录:${abs}`;
274
+ return m.cwdNotDir(abs);
267
275
  return undefined;
268
276
  },
269
277
  });
@@ -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;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 交互模式装配用到的两个小工具(从 interactive-mode.ts 拆出,控制单文件行数):真实终端与 keybindings.json。
3
+ */
4
+ import { join } from "node:path";
5
+ import { KEYBINDINGS_FILE } from "../../config/paths.js";
6
+ import { AmaError } from "../../errors.js";
7
+ import { msg } from "../../i18n/index.js";
8
+ import { Keybindings, ProcessTerminal, loadKeybindingsFile } from "../../tui.js";
9
+ /** stdin / stdout 都是 TTY 才用真实终端;否则抛 `terminal_init_failed`(调用方降级到行式界面)。 */
10
+ export function processTerminal() {
11
+ const stdin = process.stdin;
12
+ if (stdin.isTTY !== true || typeof stdin.setRawMode !== "function" || !process.stdout.isTTY) {
13
+ throw new AmaError("terminal_init_failed", msg().interactive.app.notTty);
14
+ }
15
+ return new ProcessTerminal();
16
+ }
17
+ /** 读 `<configDir>/keybindings.json`;问题逐条交给 `warn`。 */
18
+ export function loadKeys(runtime, warn) {
19
+ const parsed = loadKeybindingsFile(join(runtime.paths.configDir, KEYBINDINGS_FILE));
20
+ for (const w of parsed.warnings)
21
+ warn(msg().interactive.app.keybindingsWarning(w));
22
+ return new Keybindings(parsed.overrides);
23
+ }
@@ -8,6 +8,7 @@
8
8
  * - grep `N 处匹配 · M 个文件`;glob `N 个文件`;codemode `N 个内层调用 · 脚本输出 M 行`;
9
9
  * - task `完成 · 耗时 · ↑in ↓out`;其它 `N 行输出`;失败(非 bash)取错误首行。
10
10
  */
11
+ import { msg } from "../../i18n/index.js";
11
12
  import { isAbsolute, relative } from "node:path";
12
13
  import { stripAnsi } from "../../tui.js";
13
14
  import { formatTokens } from "./status-bar.js";
@@ -135,6 +136,7 @@ export function bashOutput(result) {
135
136
  /** 完成后的一行结果摘要(已着色,不含 `⎿`)。 */
136
137
  export function resultSummary(input, theme) {
137
138
  const { name, result, isError, lines } = input;
139
+ const m = msg().interactive.view.tool;
138
140
  const details = record(result.details);
139
141
  const muted = (s) => theme.fg("muted", s);
140
142
  const sep = theme.fg("dim", " · ");
@@ -146,27 +148,27 @@ export function resultSummary(input, theme) {
146
148
  const code = num(details["exit_code"]) ?? (isError ? 1 : 0);
147
149
  const total = num(details["totalLines"]) ?? count;
148
150
  const head = details["aborted"] === true
149
- ? "已中断"
151
+ ? m.interrupted
150
152
  : details["timedOut"] === true
151
- ? "超时"
152
- : `退出 ${code}`;
153
- const parts = [head, duration, ...(total > 0 ? [`${total} 行`] : [])];
153
+ ? m.timedOut
154
+ : m.exit(code);
155
+ const parts = [head, duration, ...(total > 0 ? [m.lines(total)] : [])];
154
156
  const text = parts.join(" · ");
155
157
  return isError || code !== 0 ? theme.fg("error", text) : parts.map(muted).join(sep);
156
158
  }
157
159
  if (isError)
158
- return theme.fg("error", `${theme.glyphs.fail} ${lines[0] ?? "失败"}`);
160
+ return theme.fg("error", `${theme.glyphs.fail} ${lines[0] ?? m.failed}`);
159
161
  switch (name) {
160
162
  case "read": {
161
163
  const mime = details["mimeType"];
162
164
  if (typeof mime === "string")
163
- return muted(`图片 ${mime}`);
165
+ return muted(m.image(mime));
164
166
  const first = num(details["firstLine"]);
165
167
  const last = num(details["lastLine"]);
166
168
  if (num(details["totalLines"]) === 0)
167
- return muted("空文件");
169
+ return muted(m.emptyFile);
168
170
  const n = first !== undefined && last !== undefined ? last - first + 1 : count;
169
- return muted(`读取 ${n} 行`);
171
+ return muted(m.read(n));
170
172
  }
171
173
  case "edit": {
172
174
  const rows = parseDiff(diffOf(result) ?? "");
@@ -174,7 +176,7 @@ export function resultSummary(input, theme) {
174
176
  const del = rows.filter((r) => r.kind === "del").length;
175
177
  const edits = record(input.args)["edits"];
176
178
  const n = num(details["replacements"]) ?? (Array.isArray(edits) ? edits.length : 1);
177
- return (muted(`${n} 处修改`) +
179
+ return (muted(m.edits(n)) +
178
180
  sep +
179
181
  theme.fg("success", `+${add}`) +
180
182
  " " +
@@ -183,23 +185,23 @@ export function resultSummary(input, theme) {
183
185
  case "write": {
184
186
  const content = record(input.args)["content"];
185
187
  const n = typeof content === "string" ? cleanLines(content).length : 0;
186
- return muted(`${details["created"] === true ? "新建" : "覆盖"} · ${n} 行`);
188
+ return muted(m.write(details["created"] === true, n));
187
189
  }
188
190
  case "grep": {
189
191
  const matches = num(details["matches"]);
190
192
  if (matches === 0)
191
- return muted("无匹配");
193
+ return muted(m.noMatch);
192
194
  if (matches === undefined)
193
- return muted(`${count} 行`);
194
- return muted(`${matches} 处匹配 · ${num(details["files"]) ?? "?"} 个文件`);
195
+ return muted(m.lines(count));
196
+ return muted(m.matches(matches, num(details["files"])));
195
197
  }
196
198
  case "glob": {
197
199
  const n = num(details["count"]);
198
- return muted(n === 0 ? "无匹配" : `${n ?? count} 个文件`);
200
+ return muted(n === 0 ? m.noMatch : m.files(n ?? count));
199
201
  }
200
202
  case "codemode": {
201
203
  const calls = num(details["toolCalls"]) ?? input.nestedCount ?? 0;
202
- return muted(`${calls} 个内层调用 · 脚本输出 ${count} 行`);
204
+ return muted(m.codemode(calls, count));
203
205
  }
204
206
  case "task": {
205
207
  const usage = record(details["usage"]);
@@ -210,9 +212,9 @@ export function resultSummary(input, theme) {
210
212
  `${theme.glyphs.arrowUp}${formatTokens(input_)} ${theme.glyphs.arrowDown}${formatTokens(output)}`,
211
213
  ]
212
214
  : [];
213
- return muted(["完成", duration, ...tokens].join(" · "));
215
+ return muted([m.done, duration, ...tokens].join(" · "));
214
216
  }
215
217
  default:
216
- return muted(count === 0 ? "完成" : `${count} 行输出`);
218
+ return muted(count === 0 ? m.done : m.outputLines(count));
217
219
  }
218
220
  }
@@ -20,6 +20,7 @@
20
20
  * - 自定义渲染(`ToolDefinition.renderCall / renderResult`):标题摘要优先取 `renderCall` 第一行;成功的结果
21
21
  * 正文优先用 `renderResult`;抛错或返回空时回到缺省显示;错误结果始终用缺省显示。
22
22
  */
23
+ import { msg } from "../../i18n/index.js";
23
24
  import { formatElapsed, truncateToWidth, wrapTextWithAnsi, } from "../../tui.js";
24
25
  import { contentText } from "./message-view.js";
25
26
  import { subagentLine } from "./subagent-view.js";
@@ -159,7 +160,7 @@ export class ToolView {
159
160
  const g = theme.glyphs;
160
161
  const lead = " " + theme.fg("border", g.result) + " ";
161
162
  if (this.state === "running" && this.awaiting) {
162
- return truncateToWidth(lead + theme.fg("dim", `${g.spinnerStatic} 等待确认`), width);
163
+ return truncateToWidth(lead + theme.fg("dim", msg().interactive.view.tool.awaiting(g.spinnerStatic)), width);
163
164
  }
164
165
  const sub = this.subagentState();
165
166
  if (this.state === "running" && sub !== undefined) {
@@ -170,7 +171,8 @@ export class ToolView {
170
171
  if (this.state === "running") {
171
172
  const frame = this.options.spinner?.() ?? g.spinnerStatic;
172
173
  const elapsed = formatElapsed(this.now() - this.startedAt);
173
- const what = this.toolName === "task" ? `子 Agent · 运行中 ${elapsed}` : `运行中 · ${elapsed}`;
174
+ const m = msg().interactive.view.tool;
175
+ const what = this.toolName === "task" ? m.subagentRunning(elapsed) : m.running(elapsed);
174
176
  return truncateToWidth(lead + theme.fg("accent", frame) + " " + theme.fg("muted", what), width);
175
177
  }
176
178
  const result = this.result;
@@ -251,7 +253,7 @@ export class ToolView {
251
253
  }
252
254
  more(hidden) {
253
255
  const { theme } = this.options;
254
- return BODY + theme.fg("dim", `${theme.glyphs.ellipsis} 另 ${hidden} 行(Ctrl+O 展开)`);
256
+ return (BODY + theme.fg("dim", msg().interactive.view.tool.moreLines(theme.glyphs.ellipsis, hidden)));
255
257
  }
256
258
  nestedLines(width) {
257
259
  const { theme } = this.options;
@@ -269,7 +271,8 @@ export class ToolView {
269
271
  const shown = this.nested.slice(-COLLAPSED_CHILDREN);
270
272
  if (this.nested.length > shown.length) {
271
273
  const hidden = this.nested.length - shown.length;
272
- out.push(BODY + theme.fg("dim", `${theme.glyphs.ellipsis} 前 ${hidden} 个调用`));
274
+ out.push(BODY +
275
+ theme.fg("dim", msg().interactive.view.tool.earlierCalls(theme.glyphs.ellipsis, hidden)));
273
276
  }
274
277
  for (const child of shown) {
275
278
  out.push(BODY + child.header(inner));