@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
@@ -0,0 +1,397 @@
1
+ /**
2
+ * `/config` controller (docs/wave6-plan.md §6.3, D24-D26). [W6-S]
3
+ *
4
+ * - `open("")` shows the panel (config-panel.ts); `open("key=value")` / `open("key value")` sets one key
5
+ * in the user config without the panel (same path as `ama config set`).
6
+ * - Every change is written at once (config/edit.ts) and then applied: keys of the "now" tier go to the
7
+ * running session / view (`applySetting`), and `runtime.replaceConfig()` hands the re-merged config to
8
+ * `/new`. `defaultModel`, `thinkingLevel` and `permission.mode` also switch the current session.
9
+ * - `permission.mode: full-auto` in the user config always asks the Bypass confirmation first.
10
+ * - The first change of a cache-prefix key in a conversation that already has replies shows a notice once
11
+ * per panel; closing the panel posts one summary (`from → to (scope)`, plus restart / new-session lists).
12
+ * - `configCommand()` is the line mode `/config` (`CommandContext.extra.config`).
13
+ */
14
+ import { AgentSessionImpl } from "../../agent/session.js";
15
+ import { currentSession } from "../../cli/compose-session.js";
16
+ import { hideFakeProvider } from "../../cli/fake-visibility.js";
17
+ import { tildePath } from "../../cli/startup-screen.js";
18
+ import { ConfigEditError, formatSettingValue, getConfigValue, parseValue, readSnapshot, setConfigValue, } from "../../config/edit.js";
19
+ import { loadProfile } from "../../config/profile.js";
20
+ import { settingSpec, settingsRegistry } from "../../config/settings-registry.js";
21
+ import { msg } from "../../i18n/index.js";
22
+ import { ConfigPanel, blockedReason } from "./config-panel.js";
23
+ import { bypassChoiceSpec, openChoice } from "./confirm-dialog.js";
24
+ import { modelItems, openPicker, permissionItems, thinkingItems, } from "./pickers.js";
25
+ /** Apply one "now" key to the running session / view; returns false when nothing applies. */
26
+ export async function applySetting(key, value, targets) {
27
+ const session = targets.session();
28
+ const impl = session instanceof AgentSessionImpl ? session : undefined;
29
+ switch (key) {
30
+ case "ui.markdown":
31
+ targets.view?.setOptions({ markdown: value !== false });
32
+ break;
33
+ case "ui.showThinking":
34
+ targets.view?.setOptions({ showThinking: (value ?? "collapsed") });
35
+ break;
36
+ case "ui.compact":
37
+ targets.view?.setOptions({ compact: value === true });
38
+ break;
39
+ case "ui.animation":
40
+ targets.loader?.setAnimation(value !== false);
41
+ break;
42
+ case "ui.statusLine":
43
+ targets.area?.setLayout((value ?? "full"));
44
+ break;
45
+ case "thinkingLevel":
46
+ session.setThinkingLevel((value ?? "medium"));
47
+ return true;
48
+ case "permission.mode":
49
+ session.setPermissionMode((value ?? "default"));
50
+ return true;
51
+ case "defaultModel":
52
+ if (typeof value !== "string")
53
+ return false;
54
+ await session.setModel(value);
55
+ return true;
56
+ case "compaction.enabled":
57
+ impl?.setAutoCompaction(value !== false);
58
+ return impl !== undefined;
59
+ case "retry.enabled":
60
+ impl?.setAutoRetry(value !== false);
61
+ return impl !== undefined;
62
+ case "cache.warming":
63
+ if (typeof value === "string")
64
+ impl?.cache.setWarming(value);
65
+ return impl !== undefined;
66
+ default:
67
+ return false;
68
+ }
69
+ targets.redraw?.();
70
+ return true;
71
+ }
72
+ /** Layer inputs of this process: user / project files, the profile and the command line flags. */
73
+ export function layerInputFor(runtime, context) {
74
+ const { args, io } = context;
75
+ const cli = {};
76
+ if (args.thinking !== undefined)
77
+ cli.thinkingLevel = args.thinking;
78
+ if (args.permissionMode !== undefined)
79
+ cli.permissionMode = args.permissionMode;
80
+ if (args.allow.length > 0)
81
+ cli.allow = args.allow;
82
+ if (args.deny.length > 0)
83
+ cli.deny = args.deny;
84
+ if (args.quietStartup !== undefined)
85
+ cli.quietStartup = args.quietStartup;
86
+ if (args.tuiMode !== undefined)
87
+ cli.tuiMode = args.tuiMode;
88
+ if (args.toolsPreset !== undefined)
89
+ cli.toolsPreset = args.toolsPreset;
90
+ if (args.codemode !== undefined)
91
+ cli.codemode = args.codemode;
92
+ if (args.memory !== undefined)
93
+ cli.memory = args.memory;
94
+ const input = {
95
+ configDir: runtime.paths.configDir,
96
+ cwd: runtime.paths.cwd,
97
+ env: io.env,
98
+ cli,
99
+ };
100
+ if (args.profile !== undefined) {
101
+ input.profile = { config: loadProfile(args.profile, io.cwd).config };
102
+ input.hasProfile = true;
103
+ }
104
+ return input;
105
+ }
106
+ /** `key=value` / `key value` → [key, raw]. */
107
+ export function splitAssignment(args) {
108
+ const text = args.trim();
109
+ const eq = text.indexOf("=");
110
+ const space = text.search(/\s/);
111
+ const at = eq !== -1 && (space === -1 || eq < space) ? eq : space;
112
+ if (at <= 0)
113
+ return undefined;
114
+ return [text.slice(0, at).trim(), text.slice(at + 1).trim()];
115
+ }
116
+ const PROJECT_FILE = ".ama/config.json";
117
+ const labelOf = (key) => msg().settings.labels[key] ?? key;
118
+ const hasReplies = (session) => session.messages.some((m) => m.role === "assistant");
119
+ export class ConfigUi {
120
+ deps;
121
+ panel;
122
+ handle;
123
+ changes = new Map();
124
+ prefixNoticeShown = false;
125
+ constructor(deps) {
126
+ this.deps = deps;
127
+ }
128
+ input() {
129
+ return layerInputFor(this.deps.runtime, this.deps.context);
130
+ }
131
+ /** `/config [key=value]`. */
132
+ async open(args) {
133
+ if (args.trim() !== "")
134
+ return this.direct(args);
135
+ if (this.panel !== undefined)
136
+ return;
137
+ const snapshot = readSnapshot(this.input());
138
+ const home = this.deps.home;
139
+ this.changes = new Map();
140
+ this.prefixNoticeShown = false;
141
+ const panel = new ConfigPanel(snapshot, {
142
+ theme: this.deps.theme,
143
+ ...(this.deps.keybindings !== undefined ? { keybindings: this.deps.keybindings } : {}),
144
+ rows: () => this.deps.rows(),
145
+ // project file is always <cwd>/.ama/config.json; forward slashes on every platform
146
+ paths: {
147
+ user: tildePath(snapshot.userPath, home).replace(/\\/g, "/"),
148
+ project: PROJECT_FILE,
149
+ },
150
+ embedded: this.input().hasProfile === true,
151
+ activate: (key, scope) => this.activate(key, scope),
152
+ unset: (key, scope) => this.write(key, undefined, scope).then(() => undefined),
153
+ commit: (key, text, scope) => this.commitText(key, text, scope),
154
+ close: () => this.close(),
155
+ requestRender: () => this.deps.render(),
156
+ });
157
+ this.panel = panel;
158
+ this.handle = this.deps.showOverlay(panel, { anchor: "bottom" });
159
+ this.deps.render();
160
+ }
161
+ close() {
162
+ this.handle?.hide();
163
+ this.handle = undefined;
164
+ this.panel = undefined;
165
+ const summary = this.summary();
166
+ if (summary !== undefined)
167
+ this.deps.notice("info", summary);
168
+ this.deps.render();
169
+ }
170
+ /** Closing summary (undefined when nothing changed). */
171
+ summary() {
172
+ const s = msg().settings;
173
+ const changed = [...this.changes.values()].filter((c) => c.from !== c.to);
174
+ if (changed.length === 0)
175
+ return undefined;
176
+ const lines = [s.summaryTitle];
177
+ for (const c of changed)
178
+ lines.push(` ${s.summaryLine(labelOf(c.key), c.from, c.to, s.scope[c.scope])}`);
179
+ const tier = (apply) => changed
180
+ .filter((c) => c.spec?.apply === apply)
181
+ .map((c) => labelOf(c.key))
182
+ .join(", ");
183
+ if (tier("restart") !== "")
184
+ lines.push(s.summaryRestart(tier("restart")));
185
+ if (tier("nextSession") !== "")
186
+ lines.push(s.summaryNextSession(tier("nextSession")));
187
+ return lines.join("\n");
188
+ }
189
+ async activate(key, scope) {
190
+ const panel = this.panel;
191
+ const spec = settingSpec(key);
192
+ if (panel === undefined || spec === undefined)
193
+ return;
194
+ const current = getConfigValue(readSnapshot(this.input()), key);
195
+ const blocked = blockedReason(spec, current, scope);
196
+ if (blocked !== undefined)
197
+ return panel.setNotice(blocked, "warning");
198
+ const value = current.value;
199
+ switch (spec.kind) {
200
+ case "bool":
201
+ await this.write(key, value !== true, scope);
202
+ return;
203
+ case "enum": {
204
+ const options = spec.options ?? [];
205
+ if (options.length <= 4) {
206
+ const next = options[(options.indexOf(String(value)) + 1) % options.length];
207
+ await this.write(key, next, scope);
208
+ return;
209
+ }
210
+ const picked = await this.pick(spec, value);
211
+ if (picked !== undefined)
212
+ await this.write(key, picked === "" ? undefined : picked, scope);
213
+ return;
214
+ }
215
+ case "model": {
216
+ const picked = await this.pick(spec, value);
217
+ if (picked !== undefined)
218
+ await this.write(key, picked === "" ? undefined : picked, scope);
219
+ return;
220
+ }
221
+ default:
222
+ panel.startEdit(key, value === undefined ? "" : formatSettingValue(value));
223
+ }
224
+ }
225
+ async pick(spec, value) {
226
+ const s = msg().settings;
227
+ const current = typeof value === "string" ? value : undefined;
228
+ let items;
229
+ if (spec.key === "permission.mode")
230
+ items = permissionItems((current ?? "default"));
231
+ else if (spec.key.endsWith("thinkingLevel"))
232
+ items = thinkingItems(true);
233
+ else if (spec.kind === "model")
234
+ items = [
235
+ ...(await modelItems(hideFakeProvider(this.deps.runtime.providers, this.deps.context.io.env), { current, enabled: this.deps.runtime.config.models?.enabled, hints: false })),
236
+ { value: "", label: s.defaultChoice },
237
+ ];
238
+ else
239
+ items = (spec.options ?? []).map((o) => ({ value: o, label: o }));
240
+ const picked = await openPicker(this.deps, {
241
+ title: s.pickTitle(labelOf(spec.key)),
242
+ items,
243
+ filterable: spec.kind === "model",
244
+ ...(current !== undefined ? { selected: current, currentValue: current } : {}),
245
+ ...(spec.key === "permission.mode" ? { stacked: true } : {}),
246
+ });
247
+ return picked?.value;
248
+ }
249
+ async commitText(key, text, scope) {
250
+ try {
251
+ await this.write(key, parseValue(key, text), scope, true);
252
+ return undefined;
253
+ }
254
+ catch (error) {
255
+ return error instanceof Error ? error.message : String(error);
256
+ }
257
+ }
258
+ /**
259
+ * Write one key and apply it. Errors become panel notices (or are rethrown with `rethrow`, for the
260
+ * inline editor). Returns the edit result, undefined when refused / cancelled.
261
+ */
262
+ async write(key, value, scope, rethrow = false) {
263
+ const s = msg().settings;
264
+ if (key === "permission.mode" && value === "full-auto" && scope === "user") {
265
+ const spec = bypassChoiceSpec(this.deps.theme);
266
+ const body = [...spec.body, this.deps.theme.fg("warning", s.bypassPersist)];
267
+ if ((await openChoice(this.deps, { ...spec, body })) !== 0)
268
+ return undefined;
269
+ }
270
+ let result;
271
+ try {
272
+ result = setConfigValue({ ...this.input(), scope, key, value });
273
+ }
274
+ catch (error) {
275
+ if (rethrow)
276
+ throw error;
277
+ const text = error instanceof Error ? error.message : String(error);
278
+ if (this.panel !== undefined)
279
+ this.panel.setNotice(text, "error");
280
+ else
281
+ this.deps.notice("error", text);
282
+ return undefined;
283
+ }
284
+ await this.afterWrite(result);
285
+ return result;
286
+ }
287
+ async afterWrite(result) {
288
+ const s = msg().settings;
289
+ const spec = settingSpec(result.key);
290
+ const from = formatSettingValue(result.before.value);
291
+ const to = formatSettingValue(result.after.value);
292
+ const previous = this.changes.get(result.key);
293
+ this.changes.set(result.key, {
294
+ key: result.key,
295
+ from: previous?.from ?? from,
296
+ to,
297
+ scope: result.scope,
298
+ spec,
299
+ });
300
+ this.deps.runtime.replaceConfig?.(result.snapshot.config);
301
+ let warning;
302
+ if (result.apply === "now" && result.before.value !== result.after.value)
303
+ await applySetting(result.key, result.after.value, this.deps).catch((error) => {
304
+ warning = error instanceof Error ? error.message : String(error);
305
+ });
306
+ if (result.overriddenBy !== undefined)
307
+ warning ??= s.stillOverridden(result.key, result.after.envName ?? result.overriddenBy);
308
+ if (result.prefixChanged && !this.prefixNoticeShown && hasReplies(this.deps.session())) {
309
+ this.prefixNoticeShown = true;
310
+ warning ??= s.prefixNotice;
311
+ }
312
+ if (this.panel !== undefined) {
313
+ this.panel.refresh(result.snapshot);
314
+ this.panel.setNotice(warning, "warning");
315
+ }
316
+ else {
317
+ const line = s.setDone(result.key, to, s.scope[result.scope]);
318
+ this.deps.notice(warning === undefined ? "info" : "warn", warning === undefined ? line : `${line}\n${warning}`);
319
+ }
320
+ this.deps.render();
321
+ }
322
+ /** `/config key=value`: user scope, no panel. */
323
+ async direct(args) {
324
+ const s = msg().settings;
325
+ const parts = splitAssignment(args);
326
+ if (parts === undefined || parts[1] === "")
327
+ return this.deps.notice("warn", s.slashUsage);
328
+ try {
329
+ const value = parseValue(parts[0], parts[1]);
330
+ await this.write(parts[0], value, "user", true);
331
+ }
332
+ catch (error) {
333
+ const text = error instanceof Error ? error.message : String(error);
334
+ this.deps.notice(error instanceof ConfigEditError ? "warn" : "error", text);
335
+ }
336
+ }
337
+ }
338
+ /** Line mode `/config`: no args lists the settings, `key=value` sets one (user scope). */
339
+ export function configCommand(runtime, context) {
340
+ return async (args, ctx) => {
341
+ const s = msg().settings;
342
+ const input = layerInputFor(runtime, context);
343
+ if (args.trim() === "") {
344
+ const snapshot = readSnapshot(input);
345
+ const lines = settingsRegistry().map((spec) => {
346
+ const value = getConfigValue(snapshot, spec.key);
347
+ return ` ${spec.key} = ${formatSettingValue(value.value)} ${value.envName ?? value.source}`;
348
+ });
349
+ return { kind: "handled", message: [s.cli.listHeader, ...lines].join("\n") };
350
+ }
351
+ const parts = splitAssignment(args);
352
+ if (parts === undefined || parts[1] === "")
353
+ return { kind: "handled", message: s.slashUsage };
354
+ try {
355
+ const value = parseValue(parts[0], parts[1]);
356
+ if (parts[0] === "permission.mode" && value === "full-auto") {
357
+ const confirmed = ctx.confirmPermissionMode === undefined
358
+ ? false
359
+ : await ctx.confirmPermissionMode("full-auto");
360
+ if (!confirmed)
361
+ return { kind: "handled", message: s.cli.needYes };
362
+ }
363
+ const result = setConfigValue({ ...input, scope: "user", key: parts[0], value });
364
+ runtime.replaceConfig?.(result.snapshot.config);
365
+ if (result.apply === "now" && result.before.value !== result.after.value)
366
+ await applySetting(result.key, result.after.value, { session: () => ctx.session() });
367
+ const lines = [s.setDone(result.key, formatSettingValue(result.after.value), s.scope.user)];
368
+ if (result.overriddenBy !== undefined)
369
+ lines.push(s.stillOverridden(result.key, result.after.envName ?? result.overriddenBy));
370
+ return { kind: "handled", message: lines.join("\n") };
371
+ }
372
+ catch (error) {
373
+ if (error instanceof ConfigEditError)
374
+ return { kind: "handled", message: error.message };
375
+ throw error;
376
+ }
377
+ };
378
+ }
379
+ /** Wiring for interactive-mode.ts (one line there): the session follows `/new` `/resume` `/fork`. */
380
+ export function configUiFor(host, parts) {
381
+ const { runtime, context, tui } = parts;
382
+ const env = context.io.env;
383
+ const home = env["HOME"] ?? env["USERPROFILE"];
384
+ return new ConfigUi({
385
+ ...host,
386
+ runtime,
387
+ context,
388
+ view: parts.view,
389
+ loader: parts.loader,
390
+ area: parts.area,
391
+ session: () => currentSession(runtime),
392
+ notice: parts.notice,
393
+ render: () => tui.requestRender(),
394
+ redraw: () => tui.forceFullRedraw(),
395
+ ...(home !== undefined ? { home } : {}),
396
+ });
397
+ }
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * 用途:进入 Bypass permissions 前的确认(`confirmBypass`,permissions/bypass.ts)。
10
10
  */
11
- import { BYPASS_CHOICES, BYPASS_CONFIRM_TITLE, BYPASS_DEFAULT_CHOICE, BYPASS_RISK_LINES, } from "../../permissions/bypass.js";
11
+ import { msg } from "../../i18n/index.js";
12
+ import { BYPASS_DEFAULT_CHOICE, bypassChoices, bypassConfirmTitle, bypassRiskLines, } from "../../permissions/bypass.js";
12
13
  import { Box, defaultKeybindings, matchesKey, padToWidth, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
13
14
  /** 宽度低于它(Box 外宽)时用紧凑布局。 */
14
15
  const COMPACT_WIDTH = 56;
@@ -64,9 +65,7 @@ export class ChoiceDialog {
64
65
  const g = theme.glyphs;
65
66
  const arrows = g.arrowUp + g.arrowDown;
66
67
  const n = this.spec.options.length;
67
- lines.push(theme.fg("dim", compact
68
- ? `${arrows} Enter · 1-${n} · Esc`
69
- : `${arrows} 选择 · Enter 确认 · 1-${n} 直接选 · Esc 取消`));
68
+ lines.push(theme.fg("dim", compact ? `${arrows} Enter · 1-${n} · Esc` : msg().approval.choiceHint(arrows, n)));
70
69
  return lines.map((l) => truncateToWidth(l, width));
71
70
  }
72
71
  optionLines(width, compact) {
@@ -108,9 +107,9 @@ export function openChoice(host, spec) {
108
107
  /** Bypass 确认框的内容(缺省选中「取消」,边框 warning)。 */
109
108
  export function bypassChoiceSpec(theme) {
110
109
  return {
111
- title: BYPASS_CONFIRM_TITLE,
112
- body: BYPASS_RISK_LINES.map((line, i) => (i === 0 ? theme.fg("warning", line) : line)),
113
- options: BYPASS_CHOICES,
110
+ title: bypassConfirmTitle(),
111
+ body: bypassRiskLines().map((line, i) => (i === 0 ? theme.fg("warning", line) : line)),
112
+ options: bypassChoices(),
114
113
  selected: BYPASS_DEFAULT_CHOICE,
115
114
  borderColor: "warning",
116
115
  };
@@ -5,11 +5,12 @@
5
5
  * 合并成一条「已省略 N 张早期图片以符合请求上限」,N 按占位文本数;
6
6
  * - W5-H1:`compaction_end.error` 的「compaction did not shrink」换成中文说明(其余错误原样)。
7
7
  */
8
+ import { msg } from "../../i18n/index.js";
8
9
  import { IMAGE_OMITTED_FOR_BUDGET, IMAGE_OMITTED_TOO_LARGE, } from "../../compaction/image-budget.js";
9
10
  /** `compaction_end.error` 的显示文本。 */
10
11
  export function compactionErrorText(error) {
11
12
  if (/compaction did not shrink/i.test(error)) {
12
- return "压缩后上下文没有变小,已保留原对话(不写摘要)";
13
+ return msg().interactive.events.compactionNoShrink;
13
14
  }
14
15
  return error;
15
16
  }
@@ -43,7 +44,7 @@ export class ImageBudgetNotices {
43
44
  const n = this.pending;
44
45
  this.pending = 0;
45
46
  this.scheduled = false;
46
- this.notify(`已省略 ${n} 张早期图片以符合请求上限`);
47
+ this.notify(msg().interactive.events.imagesOmitted(n));
47
48
  });
48
49
  }
49
50
  }
@@ -54,26 +55,27 @@ export class ImageBudgetNotices {
54
55
  export const LIMIT_WARNING = "limit_reached";
55
56
  /** `limit_reached`:回合 / 费用到限(每次运行每类一次)。 */
56
57
  export function limitReachedText(event) {
58
+ const m = msg().interactive.events;
57
59
  if (event.kind === "turns")
58
- return `已到回合上限(${event.limit} 回合),本次运行停止;发新消息继续(--max-turns / limits.maxTurns)`;
59
- const spent = `$${event.value.toFixed(2)}`;
60
- return `已到费用上限 $${event.limit.toFixed(2)}(本次运行已用 ${spent}),本次运行停止;发新消息继续(--max-cost / limits.maxCostUsd)`;
60
+ return m.limitTurns(event.limit);
61
+ return m.limitCost(`$${event.limit.toFixed(2)}`, `$${event.value.toFixed(2)}`);
61
62
  }
62
63
  /** `model_fallback`:主模型失败后改用回退模型重试一次。 */
63
64
  export function modelFallbackText(event) {
64
65
  const ref = (m) => `${m.provider}/${m.id}`;
65
- return `${ref(event.from)} 不可用(${event.reason}),本次请求改用 ${ref(event.to)},回复后切回`;
66
+ return msg().interactive.events.modelFallback(ref(event.from), event.reason, ref(event.to));
66
67
  }
67
68
  /** `background_job`:后台命令启动 / 退出 / 停止。 */
68
69
  export function backgroundJobText(event) {
69
70
  const command = event.command.replace(/\s+/g, " ").trim();
70
71
  const short = command.length > 60 ? `${command.slice(0, 59)}…` : command;
72
+ const m = msg().interactive.events;
71
73
  switch (event.phase) {
72
74
  case "started":
73
- return `后台命令 ${event.jobId} 已启动:${short}`;
75
+ return m.backgroundStarted(event.jobId, short);
74
76
  case "exited":
75
- return `后台命令 ${event.jobId} 已退出(码 ${event.exitCode ?? "?"}):${short}`;
77
+ return m.backgroundExited(event.jobId, String(event.exitCode ?? "?"), short);
76
78
  case "stopped":
77
- return `后台命令 ${event.jobId} 已停止:${short}`;
79
+ return m.backgroundStopped(event.jobId, short);
78
80
  }
79
81
  }
@@ -24,7 +24,7 @@ import type { ModeContext } from "../../cli/deps.js";
24
24
  import type { Runtime } from "../../cli/runtime.js";
25
25
  import type { StatusLineMode } from "../../config/types.js";
26
26
  import type { ClipboardDeps } from "../../tools/clipboard-image.js";
27
- import { Editor, Keybindings, TUI, type Terminal, type Theme } from "../../tui.js";
27
+ import { Editor, TUI, type Keybindings, type Terminal, type Theme } from "../../tui.js";
28
28
  import { MessageView } from "./message-view.js";
29
29
  import { StatusArea } from "./status-area.js";
30
30
  import type { StatusBar } from "./status-bar.js";
@@ -25,42 +25,33 @@ import { AgentSessionImpl } from "../../agent/session.js";
25
25
  import { taskRegistryView } from "../../agent/subagent-registry.js";
26
26
  import { currentSession, switchSession } from "../../cli/compose-session.js";
27
27
  import { startupInfo, startupScreenLevel, tildePath } from "../../cli/startup-screen.js";
28
- import { KEYBINDINGS_FILE } from "../../config/paths.js";
29
28
  import { AmaError, isAmaError } from "../../errors.js";
30
- import { Container, Editor, Keybindings, Loader, ProcessTerminal, Spacer, TUI, Text, createTheme, detectCapabilities, resolveAscii, resolveThemeName, loadKeybindingsFile, } from "../../tui.js";
29
+ import { msg } from "../../i18n/index.js";
30
+ import { Container, Editor, Loader, Spacer, TUI, Text, createTheme, detectCapabilities, resolveAscii, resolveThemeName, } from "../../tui.js";
31
31
  import { BYPASS_MODE, createBypassGate } from "../../permissions/bypass.js";
32
32
  import { onTerminationSignals } from "../shared.js";
33
- import { AgentUi } from "./agent-ui.js";
33
+ import { AgentUi, agentCommandHooks } from "./agent-ui.js";
34
34
  import { ApprovalDialogBroker, approvalOutcomeText } from "./approval-dialog.js";
35
35
  import { mergingBroker } from "./approval-merge.js";
36
36
  import { ALL_COMMANDS, runInteractiveCommand } from "./commands.js";
37
+ import { memoryPanelFor } from "./memory-panel.js";
37
38
  import { InteractiveCompletion } from "./completion.js";
38
39
  import { confirmBypass } from "./confirm-dialog.js";
40
+ import { configUiFor } from "./config-ui.js";
39
41
  import { createKeyDispatch } from "./key-dispatch.js";
40
42
  import { MessageView, exitSummaryLines } from "./message-view.js";
41
43
  import { openPicker } from "./pickers.js";
44
+ import { modelPickerFor } from "./model-picker.js";
42
45
  import { createRewindFlow } from "./rewind-flow.js";
46
+ import { openTraceView } from "./trace-view.js";
43
47
  import { StartupHeader } from "./startup-header.js";
44
48
  import { QueueView, RunIndicator } from "./run-indicator.js";
45
49
  import { StatusArea, statusLineSlash } from "./status-area.js";
46
50
  import { createSessionEventHandler } from "./session-events.js";
47
51
  import { SubagentTracker } from "./subagent-view.js";
52
+ import { loadKeys, processTerminal } from "./terminal-setup.js";
48
53
  import { ToolTracker } from "./tool-view.js";
49
54
  const HINT_MS = 2500;
50
- const EDITOR_PLACEHOLDER = "输入消息,/ 命令,@ 文件,Shift+Enter 换行";
51
- function processTerminal() {
52
- const stdin = process.stdin;
53
- if (stdin.isTTY !== true || typeof stdin.setRawMode !== "function" || !process.stdout.isTTY) {
54
- throw new AmaError("terminal_init_failed", "stdin / stdout 不是终端");
55
- }
56
- return new ProcessTerminal();
57
- }
58
- function loadKeys(runtime, warn) {
59
- const parsed = loadKeybindingsFile(join(runtime.paths.configDir, KEYBINDINGS_FILE));
60
- for (const w of parsed.warnings)
61
- warn(`keybindings.json:${w}`);
62
- return new Keybindings(parsed.overrides);
63
- }
64
55
  export function runInteractiveMode(runtime, context, options = {}) {
65
56
  const terminal = options.terminal ?? processTerminal();
66
57
  const ui = runtime.config.ui ?? {};
@@ -95,7 +86,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
95
86
  const loaderSlot = new Container();
96
87
  const loader = new Loader(() => tui.requestRender(), {
97
88
  theme,
98
- message: "思考中",
89
+ message: msg().interactive.view.run.thinking,
99
90
  now,
100
91
  ...(ui.animation === false ? { animation: false } : {}),
101
92
  ...(options.spinnerIntervalMs !== undefined ? { intervalMs: options.spinnerIntervalMs } : {}),
@@ -126,7 +117,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
126
117
  theme,
127
118
  keybindings: keys,
128
119
  maxVisibleLines: 8,
129
- placeholder: EDITOR_PLACEHOLDER,
120
+ placeholder: msg().interactive.app.placeholder,
130
121
  autocomplete: completion,
131
122
  requestRender: () => tui.requestRender(),
132
123
  ...(historyFile !== undefined ? { historyFile } : {}),
@@ -196,7 +187,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
196
187
  const replay = () => {
197
188
  view.replay(session.messages, {
198
189
  tool: (call, result) => tools.completed(call.id, call.name, call.arguments, result === undefined
199
- ? { content: "(没有结果)", isError: true }
190
+ ? { content: msg().interactive.app.noResult, isError: true }
200
191
  : {
201
192
  content: result.content,
202
193
  isError: result.isError,
@@ -285,6 +276,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
285
276
  setDraft,
286
277
  editorEmpty: () => editor.isEmpty(),
287
278
  });
279
+ const configUi = configUiFor(pickerHost, { runtime, context, view, loader, area, tui, notice });
288
280
  const commandUi = {
289
281
  runtime,
290
282
  session: () => session,
@@ -294,6 +286,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
294
286
  return next;
295
287
  },
296
288
  pick: (spec) => openPicker(pickerHost, spec),
289
+ pickModel: modelPickerFor(pickerHost, runtime, context),
297
290
  confirmMode,
298
291
  rewind: () => rewind.open(),
299
292
  setDraft,
@@ -314,6 +307,10 @@ export function runInteractiveMode(runtime, context, options = {}) {
314
307
  exit: (code) => exit(code),
315
308
  now,
316
309
  extra: (name, args) => agentUi.command(name, args),
310
+ ...agentCommandHooks(() => agentUi),
311
+ configPanel: (args) => configUi.open(args),
312
+ traceView: (id) => openTraceView({ ...pickerHost, session: () => session, now, notice, render }, id),
313
+ memoryPanel: memoryPanelFor(() => commandUi, pickerHost, tui, env), // [W6-M]
317
314
  };
318
315
  const runCommand = (line) => (statusLineSlash(area, line, notice)
319
316
  ? Promise.resolve(true)
@@ -360,6 +357,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
360
357
  runCommand: (line) => void runCommand(line),
361
358
  exit: (code) => exit(code),
362
359
  onInterrupted: (empty) => void rewind.afterInterrupt(empty),
360
+ agents: () => agentUi.keys,
363
361
  }));
364
362
  // ---- 晚绑定 ---------------------------------------------------------------
365
363
  const overlayHooks = {
@@ -395,6 +393,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
395
393
  dialog: { theme, keybindings: keys, ...overlayHooks },
396
394
  displayPath: (path) => tildePath(path, home),
397
395
  ...(options.clipboard !== undefined ? { clipboard: options.clipboard } : {}),
396
+ area,
398
397
  });
399
398
  const taskAgent = (taskId) => taskRegistryView(session.state.sessionId)?.get(taskId)?.agent;
400
399
  const broker = mergingBroker(new ApprovalDialogBroker({
@@ -411,7 +410,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
411
410
  notice(outcome === "deny" ? "info" : "warn", text);
412
411
  }
413
412
  },
414
- }), agentUi.merge, (request) => notice("info", `${approvalOutcomeText(request, "allow", taskAgent)}(随上一次确认)`));
413
+ }), agentUi.merge, (request) => notice("info", msg().interactive.app.followed(approvalOutcomeText(request, "allow", taskAgent))));
415
414
  // ---- 启动与退出 -----------------------------------------------------------
416
415
  let offSignals = () => undefined;
417
416
  function exit(code) {
@@ -453,7 +452,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
453
452
  }
454
453
  catch (error) {
455
454
  unsubscribe();
456
- reject(new AmaError("terminal_init_failed", `终端初始化失败:${error instanceof Error ? error.message : String(error)}`, { cause: error }));
455
+ reject(new AmaError("terminal_init_failed", msg().interactive.app.terminalInitFailed(error instanceof Error ? error.message : String(error)), { cause: error }));
457
456
  return;
458
457
  }
459
458
  runtime.approvals.setUiBroker(broker);
@@ -9,12 +9,22 @@
9
9
  *
10
10
  * [RW-C] 空闲时双击 Esc(`app.rewind`,double-esc.ts):输入框为空打开回滚列表,有字则清空并存进
11
11
  * 输入历史;运行中 Esc 仍为中断,中断后交给 `onInterrupted`(中断即撤回)。
12
+ *
13
+ * [W6-A] Agent 栏(agent-ui.ts):栏聚焦时它先收键(Esc 是「返回」,不中断、不回滚);输入为空、补全没开时
14
+ * `app.agents.focus`(缺省 `Ctrl+B` / `↓`)先问它要不要进栏,不要就照常交给编辑器(光标左移、历史下一条)。
12
15
  */
13
16
  import type { AgentSession } from "../../agent/types.js";
14
17
  import type { PermissionMode } from "../../permissions/types.js";
15
18
  import type { Editor, Keybindings } from "../../tui.js";
16
19
  import type { StatusBar } from "./status-bar.js";
17
20
  import type { ToolTracker } from "./tool-view.js";
21
+ /** [W6-A] Agent 栏的按键入口。 */
22
+ export interface AgentKeys {
23
+ /** 栏聚焦时先消费按键;返回 true 已处理。 */
24
+ handleKey(data: string): boolean;
25
+ /** `app.agents.focus`(输入为空):进栏返回 true,否则交给编辑器。 */
26
+ focus(data: string): boolean;
27
+ }
18
28
  export interface KeyDispatchDeps {
19
29
  keys: Keybindings;
20
30
  editor: Editor;
@@ -46,6 +56,8 @@ export interface KeyDispatchDeps {
46
56
  onInterrupted?(editorWasEmpty: boolean): void;
47
57
  /** 双击 Esc 的间隔(测试注入)。 */
48
58
  doubleEscMs?: number;
59
+ /** [W6-A] Agent 栏(晚绑定)。 */
60
+ agents?(): AgentKeys | undefined;
49
61
  }
50
62
  /** 返回输入监听器:已处理返回 true,交给编辑器返回 false。 */
51
63
  export declare function createKeyDispatch(deps: KeyDispatchDeps): (data: string) => boolean;