@armadra/agent 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/CHANGELOG.md +177 -294
  2. package/CHANGELOG.zh-CN.md +442 -0
  3. package/README.md +408 -364
  4. package/README.zh-CN.md +705 -0
  5. package/dist/agent/session-plan.js +2 -2
  6. package/dist/agent/session-state.d.ts +3 -0
  7. package/dist/agent/session-state.js +20 -0
  8. package/dist/agent/session-subagent.d.ts +15 -1
  9. package/dist/agent/session-subagent.js +26 -3
  10. package/dist/agent/session-telemetry.d.ts +16 -2
  11. package/dist/agent/session-telemetry.js +29 -7
  12. package/dist/agent/session-tools.js +5 -2
  13. package/dist/agent/session-trace-writer.d.ts +27 -0
  14. package/dist/agent/session-trace-writer.js +253 -0
  15. package/dist/agent/session.d.ts +2 -0
  16. package/dist/agent/session.js +12 -0
  17. package/dist/agent/subagent-direct.d.ts +20 -0
  18. package/dist/agent/subagent-direct.js +76 -0
  19. package/dist/agent/subagent-registry.d.ts +8 -1
  20. package/dist/agent/subagent-registry.js +28 -1
  21. package/dist/agent/system-prompt.d.ts +3 -1
  22. package/dist/agent/system-prompt.js +3 -0
  23. package/dist/agent/tool-runner.d.ts +2 -1
  24. package/dist/agent/tool-runner.js +5 -4
  25. package/dist/agent/types-w6.d.ts +39 -0
  26. package/dist/agent/types-w6.js +4 -0
  27. package/dist/agent/types.d.ts +5 -2
  28. package/dist/agents/external.js +1 -1
  29. package/dist/agents/task-record.d.ts +74 -1
  30. package/dist/agents/task-record.js +100 -0
  31. package/dist/ai/apis/cache-params.js +2 -1
  32. package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
  33. package/dist/ai/apis/chatgpt-backend.js +224 -0
  34. package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
  35. package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
  36. package/dist/ai/apis/openai-responses-request.d.ts +2 -1
  37. package/dist/ai/apis/openai-responses-request.js +8 -2
  38. package/dist/ai/apis/openai-responses.d.ts +2 -0
  39. package/dist/ai/apis/openai-responses.js +51 -16
  40. package/dist/ai/overflow.d.ts +1 -1
  41. package/dist/ai/overflow.js +10 -7
  42. package/dist/ai/providers/auth.d.ts +15 -2
  43. package/dist/ai/providers/auth.js +69 -2
  44. package/dist/ai/providers/builtin.js +27 -0
  45. package/dist/ai/providers/catalog-data.js +1 -0
  46. package/dist/ai/providers/enrich.js +2 -7
  47. package/dist/ai/providers/models-dev-cache.js +15 -19
  48. package/dist/ai/providers/models-dev-snapshot.js +8 -7
  49. package/dist/ai/providers/models-dev.js +5 -15
  50. package/dist/ai/providers/suggest.js +2 -16
  51. package/dist/ai/types.d.ts +27 -1
  52. package/dist/auth/chatgpt/backend-client.d.ts +26 -0
  53. package/dist/auth/chatgpt/backend-client.js +74 -0
  54. package/dist/auth/chatgpt/claims.d.ts +17 -0
  55. package/dist/auth/chatgpt/claims.js +46 -0
  56. package/dist/auth/chatgpt/cli.d.ts +33 -0
  57. package/dist/auth/chatgpt/cli.js +252 -0
  58. package/dist/auth/chatgpt/doctor.d.ts +17 -0
  59. package/dist/auth/chatgpt/doctor.js +36 -0
  60. package/dist/auth/chatgpt/host-id.d.ts +7 -0
  61. package/dist/auth/chatgpt/host-id.js +26 -0
  62. package/dist/auth/chatgpt/login.d.ts +30 -0
  63. package/dist/auth/chatgpt/login.js +130 -0
  64. package/dist/auth/chatgpt/presets.d.ts +66 -0
  65. package/dist/auth/chatgpt/presets.js +120 -0
  66. package/dist/auth/chatgpt/quota-text.d.ts +13 -0
  67. package/dist/auth/chatgpt/quota-text.js +36 -0
  68. package/dist/auth/oauth/browser.d.ts +12 -0
  69. package/dist/auth/oauth/browser.js +27 -0
  70. package/dist/auth/oauth/callback-server.d.ts +47 -0
  71. package/dist/auth/oauth/callback-server.js +147 -0
  72. package/dist/auth/oauth/flows.d.ts +62 -0
  73. package/dist/auth/oauth/flows.js +113 -0
  74. package/dist/auth/oauth/jwt.d.ts +24 -0
  75. package/dist/auth/oauth/jwt.js +81 -0
  76. package/dist/auth/oauth/live.d.ts +21 -0
  77. package/dist/auth/oauth/live.js +25 -0
  78. package/dist/auth/oauth/oidc.d.ts +26 -0
  79. package/dist/auth/oauth/oidc.js +72 -0
  80. package/dist/auth/oauth/pkce.d.ts +15 -0
  81. package/dist/auth/oauth/pkce.js +20 -0
  82. package/dist/auth/oauth/refresh.d.ts +35 -0
  83. package/dist/auth/oauth/refresh.js +129 -0
  84. package/dist/auth/oauth/token-client.d.ts +33 -0
  85. package/dist/auth/oauth/token-client.js +121 -0
  86. package/dist/auth/oauth/token-store.d.ts +23 -0
  87. package/dist/auth/oauth/token-store.js +125 -0
  88. package/dist/auth/testing/fake-oauth.d.ts +73 -0
  89. package/dist/auth/testing/fake-oauth.js +271 -0
  90. package/dist/auth/testing/refresh-child.d.ts +5 -0
  91. package/dist/auth/testing/refresh-child.js +16 -0
  92. package/dist/bundle/ama.cjs +28307 -13241
  93. package/dist/checkpoints/backend.js +6 -5
  94. package/dist/checkpoints/restore.js +3 -2
  95. package/dist/checkpoints/settings.js +2 -1
  96. package/dist/checkpoints/shadow-git.js +7 -6
  97. package/dist/checkpoints/shadow-restore.js +3 -2
  98. package/dist/checkpoints/tracker.js +4 -3
  99. package/dist/cli/args.d.ts +9 -2
  100. package/dist/cli/args.js +74 -27
  101. package/dist/cli/bootstrap.js +53 -31
  102. package/dist/cli/choice-prompt.d.ts +58 -0
  103. package/dist/cli/choice-prompt.js +142 -0
  104. package/dist/cli/codemode-notice.js +2 -2
  105. package/dist/cli/compose-agents.js +2 -1
  106. package/dist/cli/compose-extensions.js +2 -0
  107. package/dist/cli/compose-memory.d.ts +53 -0
  108. package/dist/cli/compose-memory.js +127 -0
  109. package/dist/cli/compose-providers.d.ts +5 -0
  110. package/dist/cli/compose-providers.js +32 -2
  111. package/dist/cli/compose-session.d.ts +5 -0
  112. package/dist/cli/compose-session.js +27 -13
  113. package/dist/cli/compose-store.d.ts +2 -0
  114. package/dist/cli/compose-store.js +9 -5
  115. package/dist/cli/compose.d.ts +2 -0
  116. package/dist/cli/compose.js +13 -5
  117. package/dist/cli/default-model.d.ts +0 -2
  118. package/dist/cli/default-model.js +5 -8
  119. package/dist/cli/deps.d.ts +5 -1
  120. package/dist/cli/exit-codes.d.ts +1 -1
  121. package/dist/cli/exit-codes.js +7 -16
  122. package/dist/cli/from-prompt.js +3 -2
  123. package/dist/cli/help-text.d.ts +2 -1
  124. package/dist/cli/help-text.js +5 -99
  125. package/dist/cli/main.d.ts +5 -0
  126. package/dist/cli/main.js +21 -2
  127. package/dist/cli/proxy.js +14 -9
  128. package/dist/cli/runtime.d.ts +5 -0
  129. package/dist/cli/startup-screen.js +20 -27
  130. package/dist/cli/startup-steps.js +6 -8
  131. package/dist/cli/subcommands/auth.d.ts +6 -3
  132. package/dist/cli/subcommands/auth.js +52 -22
  133. package/dist/cli/subcommands/config-set.d.ts +21 -0
  134. package/dist/cli/subcommands/config-set.js +137 -0
  135. package/dist/cli/subcommands/config.d.ts +2 -1
  136. package/dist/cli/subcommands/config.js +51 -37
  137. package/dist/cli/subcommands/doctor.d.ts +2 -1
  138. package/dist/cli/subcommands/doctor.js +97 -58
  139. package/dist/cli/subcommands/init.d.ts +1 -1
  140. package/dist/cli/subcommands/init.js +8 -7
  141. package/dist/cli/subcommands/memory.d.ts +18 -0
  142. package/dist/cli/subcommands/memory.js +189 -0
  143. package/dist/cli/subcommands/model-meta.js +11 -9
  144. package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
  145. package/dist/cli/subcommands/models-cache-probe.js +26 -32
  146. package/dist/cli/subcommands/models-discover.d.ts +3 -0
  147. package/dist/cli/subcommands/models-discover.js +44 -21
  148. package/dist/cli/subcommands/models.d.ts +1 -1
  149. package/dist/cli/subcommands/models.js +29 -22
  150. package/dist/cli/subcommands/probe-runner.js +8 -7
  151. package/dist/cli/subcommands/providers-list.js +32 -21
  152. package/dist/cli/subcommands/providers-plan.js +24 -25
  153. package/dist/cli/subcommands/providers-probe.js +5 -6
  154. package/dist/cli/subcommands/providers.d.ts +2 -2
  155. package/dist/cli/subcommands/providers.js +48 -59
  156. package/dist/cli/subcommands/sessions-export.d.ts +1 -1
  157. package/dist/cli/subcommands/sessions-export.js +10 -9
  158. package/dist/cli/subcommands/sessions-search.d.ts +1 -1
  159. package/dist/cli/subcommands/sessions-search.js +11 -10
  160. package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
  161. package/dist/cli/subcommands/sessions-trace.js +156 -0
  162. package/dist/cli/subcommands/sessions.d.ts +4 -3
  163. package/dist/cli/subcommands/sessions.js +40 -37
  164. package/dist/cli/subcommands/stats.d.ts +1 -1
  165. package/dist/cli/subcommands/stats.js +49 -30
  166. package/dist/cli/system-prompt-arg.js +3 -2
  167. package/dist/codemode/capability.js +3 -2
  168. package/dist/compaction/post-compact.d.ts +1 -0
  169. package/dist/compaction/post-compact.js +15 -1
  170. package/dist/compaction/prune-tier.d.ts +1 -1
  171. package/dist/compaction/prune-tier.js +3 -3
  172. package/dist/compaction/serialize.js +2 -1
  173. package/dist/config/auth-file.d.ts +12 -2
  174. package/dist/config/auth-file.js +32 -10
  175. package/dist/config/checker.js +12 -11
  176. package/dist/config/context-files.js +3 -2
  177. package/dist/config/edit.d.ts +106 -0
  178. package/dist/config/edit.js +350 -0
  179. package/dist/config/init.d.ts +4 -3
  180. package/dist/config/init.js +10 -18
  181. package/dist/config/json-schema.d.ts +2 -1
  182. package/dist/config/json-schema.js +101 -68
  183. package/dist/config/key-docs.d.ts +18 -7
  184. package/dist/config/key-docs.js +43 -128
  185. package/dist/config/load.js +7 -6
  186. package/dist/config/merge.d.ts +4 -1
  187. package/dist/config/merge.js +42 -22
  188. package/dist/config/paths.js +6 -5
  189. package/dist/config/profile.d.ts +5 -1
  190. package/dist/config/profile.js +7 -2
  191. package/dist/config/schema-w5.js +3 -2
  192. package/dist/config/schema-w6.d.ts +19 -0
  193. package/dist/config/schema-w6.js +115 -0
  194. package/dist/config/schema.js +34 -20
  195. package/dist/config/settings-registry.d.ts +78 -0
  196. package/dist/config/settings-registry.js +184 -0
  197. package/dist/config/types-w6.d.ts +109 -0
  198. package/dist/config/types-w6.js +19 -0
  199. package/dist/config/types.d.ts +11 -8
  200. package/dist/config/types.js +1 -0
  201. package/dist/drivers/acp/client.js +1 -1
  202. package/dist/drivers/acp/driver.js +13 -8
  203. package/dist/drivers/agents.js +4 -3
  204. package/dist/drivers/base.js +3 -2
  205. package/dist/drivers/host-runners.js +2 -1
  206. package/dist/drivers/native/claude-stream.js +12 -11
  207. package/dist/drivers/native/codex-app-server.js +17 -12
  208. package/dist/drivers/native/oneshot.js +8 -7
  209. package/dist/drivers/pool.js +1 -1
  210. package/dist/drivers/runner.d.ts +3 -1
  211. package/dist/drivers/runner.js +68 -20
  212. package/dist/drivers/turn.js +1 -1
  213. package/dist/hooks/config.js +3 -2
  214. package/dist/hooks/protocol.js +18 -12
  215. package/dist/host/api-impl.js +11 -10
  216. package/dist/host/loader.js +9 -8
  217. package/dist/host/types.d.ts +3 -0
  218. package/dist/i18n/catalog.d.ts +2169 -0
  219. package/dist/i18n/catalog.js +72 -0
  220. package/dist/i18n/format.d.ts +21 -0
  221. package/dist/i18n/format.js +58 -0
  222. package/dist/i18n/index.d.ts +58 -0
  223. package/dist/i18n/index.js +72 -0
  224. package/dist/i18n/messages/agents.d.ts +84 -0
  225. package/dist/i18n/messages/agents.js +85 -0
  226. package/dist/i18n/messages/approval.d.ts +99 -0
  227. package/dist/i18n/messages/approval.js +100 -0
  228. package/dist/i18n/messages/auth.d.ts +187 -0
  229. package/dist/i18n/messages/auth.js +189 -0
  230. package/dist/i18n/messages/cli-args.d.ts +46 -0
  231. package/dist/i18n/messages/cli-args.js +46 -0
  232. package/dist/i18n/messages/cli-help.d.ts +12 -0
  233. package/dist/i18n/messages/cli-help.js +244 -0
  234. package/dist/i18n/messages/cli.d.ts +336 -0
  235. package/dist/i18n/messages/cli.js +311 -0
  236. package/dist/i18n/messages/config-keys.d.ts +289 -0
  237. package/dist/i18n/messages/config-keys.js +292 -0
  238. package/dist/i18n/messages/config.d.ts +502 -0
  239. package/dist/i18n/messages/config.js +239 -0
  240. package/dist/i18n/messages/drivers.d.ts +123 -0
  241. package/dist/i18n/messages/drivers.js +124 -0
  242. package/dist/i18n/messages/errors.d.ts +83 -0
  243. package/dist/i18n/messages/errors.js +171 -0
  244. package/dist/i18n/messages/interactive-line.d.ts +61 -0
  245. package/dist/i18n/messages/interactive-line.js +69 -0
  246. package/dist/i18n/messages/interactive-startup.d.ts +103 -0
  247. package/dist/i18n/messages/interactive-startup.js +104 -0
  248. package/dist/i18n/messages/interactive-view.d.ts +140 -0
  249. package/dist/i18n/messages/interactive-view.js +141 -0
  250. package/dist/i18n/messages/interactive.d.ts +493 -0
  251. package/dist/i18n/messages/interactive.js +248 -0
  252. package/dist/i18n/messages/memory.d.ts +123 -0
  253. package/dist/i18n/messages/memory.js +128 -0
  254. package/dist/i18n/messages/panels.d.ts +190 -0
  255. package/dist/i18n/messages/panels.js +189 -0
  256. package/dist/i18n/messages/permissions.d.ts +126 -0
  257. package/dist/i18n/messages/permissions.js +151 -0
  258. package/dist/i18n/messages/plan.d.ts +123 -0
  259. package/dist/i18n/messages/plan.js +124 -0
  260. package/dist/i18n/messages/print.d.ts +86 -0
  261. package/dist/i18n/messages/print.js +91 -0
  262. package/dist/i18n/messages/report.d.ts +391 -0
  263. package/dist/i18n/messages/report.js +490 -0
  264. package/dist/i18n/messages/rewind.d.ts +198 -0
  265. package/dist/i18n/messages/rewind.js +217 -0
  266. package/dist/i18n/messages/session.d.ts +230 -0
  267. package/dist/i18n/messages/session.js +258 -0
  268. package/dist/i18n/messages/settings.d.ts +348 -0
  269. package/dist/i18n/messages/settings.js +336 -0
  270. package/dist/i18n/messages/subcommands-config.d.ts +111 -0
  271. package/dist/i18n/messages/subcommands-config.js +127 -0
  272. package/dist/i18n/messages/subcommands.d.ts +548 -0
  273. package/dist/i18n/messages/subcommands.js +474 -0
  274. package/dist/i18n/messages/trace.d.ts +243 -0
  275. package/dist/i18n/messages/trace.js +238 -0
  276. package/dist/i18n/types.d.ts +15 -0
  277. package/dist/i18n/types.js +7 -0
  278. package/dist/index.d.ts +6 -0
  279. package/dist/index.js +2 -0
  280. package/dist/memory/edit.d.ts +24 -0
  281. package/dist/memory/edit.js +63 -0
  282. package/dist/memory/frontmatter.d.ts +37 -0
  283. package/dist/memory/frontmatter.js +79 -0
  284. package/dist/memory/index.d.ts +28 -0
  285. package/dist/memory/index.js +126 -0
  286. package/dist/memory/lock.d.ts +17 -0
  287. package/dist/memory/lock.js +62 -0
  288. package/dist/memory/paths.d.ts +57 -0
  289. package/dist/memory/paths.js +175 -0
  290. package/dist/memory/report.d.ts +36 -0
  291. package/dist/memory/report.js +86 -0
  292. package/dist/memory/runtime.d.ts +42 -0
  293. package/dist/memory/runtime.js +36 -0
  294. package/dist/memory/secrets.d.ts +8 -0
  295. package/dist/memory/secrets.js +27 -0
  296. package/dist/memory/section.d.ts +28 -0
  297. package/dist/memory/section.js +59 -0
  298. package/dist/memory/store.d.ts +70 -0
  299. package/dist/memory/store.js +284 -0
  300. package/dist/memory/tool.d.ts +31 -0
  301. package/dist/memory/tool.js +94 -0
  302. package/dist/modes/acp/acp-events.js +2 -1
  303. package/dist/modes/acp/acp-server.js +13 -12
  304. package/dist/modes/commands-core.d.ts +17 -0
  305. package/dist/modes/commands-core.js +101 -61
  306. package/dist/modes/image-input.js +20 -6
  307. package/dist/modes/interactive/agent-bar.d.ts +95 -0
  308. package/dist/modes/interactive/agent-bar.js +248 -0
  309. package/dist/modes/interactive/agent-panels.js +27 -26
  310. package/dist/modes/interactive/agent-transcript.d.ts +47 -0
  311. package/dist/modes/interactive/agent-transcript.js +191 -0
  312. package/dist/modes/interactive/agent-ui.d.ts +36 -1
  313. package/dist/modes/interactive/agent-ui.js +180 -14
  314. package/dist/modes/interactive/agent-view.d.ts +72 -0
  315. package/dist/modes/interactive/agent-view.js +281 -0
  316. package/dist/modes/interactive/approval-dialog.js +46 -34
  317. package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
  318. package/dist/modes/interactive/clipboard-paste.js +9 -4
  319. package/dist/modes/interactive/commands.d.ts +22 -1
  320. package/dist/modes/interactive/commands.js +93 -38
  321. package/dist/modes/interactive/completion.js +2 -1
  322. package/dist/modes/interactive/config-panel.d.ts +70 -0
  323. package/dist/modes/interactive/config-panel.js +319 -0
  324. package/dist/modes/interactive/config-ui.d.ts +96 -0
  325. package/dist/modes/interactive/config-ui.js +397 -0
  326. package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
  327. package/dist/modes/interactive/confirm-dialog.js +120 -0
  328. package/dist/modes/interactive/event-notices.js +11 -9
  329. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  330. package/dist/modes/interactive/interactive-mode.js +25 -22
  331. package/dist/modes/interactive/key-dispatch.d.ts +18 -0
  332. package/dist/modes/interactive/key-dispatch.js +39 -13
  333. package/dist/modes/interactive/line/line-editor.js +2 -1
  334. package/dist/modes/interactive/line/line-mode.d.ts +2 -0
  335. package/dist/modes/interactive/line/line-mode.js +24 -4
  336. package/dist/modes/interactive/line/line-render.js +25 -24
  337. package/dist/modes/interactive/memory-panel.d.ts +64 -0
  338. package/dist/modes/interactive/memory-panel.js +221 -0
  339. package/dist/modes/interactive/message-view.d.ts +4 -2
  340. package/dist/modes/interactive/message-view.js +42 -33
  341. package/dist/modes/interactive/panels.js +39 -31
  342. package/dist/modes/interactive/pickers.d.ts +2 -1
  343. package/dist/modes/interactive/pickers.js +10 -6
  344. package/dist/modes/interactive/plan-command.d.ts +1 -1
  345. package/dist/modes/interactive/plan-command.js +24 -27
  346. package/dist/modes/interactive/plan-dialog.js +18 -17
  347. package/dist/modes/interactive/plan-flow.js +6 -5
  348. package/dist/modes/interactive/rewind-command.d.ts +1 -1
  349. package/dist/modes/interactive/rewind-command.js +18 -16
  350. package/dist/modes/interactive/rewind-flow.d.ts +0 -1
  351. package/dist/modes/interactive/rewind-flow.js +13 -14
  352. package/dist/modes/interactive/rewind-list.js +7 -6
  353. package/dist/modes/interactive/rewind-panel.js +40 -40
  354. package/dist/modes/interactive/rewind-text.d.ts +5 -3
  355. package/dist/modes/interactive/rewind-text.js +48 -38
  356. package/dist/modes/interactive/run-indicator.js +15 -12
  357. package/dist/modes/interactive/session-events.js +3 -2
  358. package/dist/modes/interactive/startup-header.js +22 -23
  359. package/dist/modes/interactive/startup-ui.js +41 -29
  360. package/dist/modes/interactive/status-area.d.ts +2 -0
  361. package/dist/modes/interactive/status-area.js +8 -2
  362. package/dist/modes/interactive/status-bar.js +4 -3
  363. package/dist/modes/interactive/subagent-view.js +9 -7
  364. package/dist/modes/interactive/tasks-report.d.ts +6 -0
  365. package/dist/modes/interactive/tasks-report.js +28 -31
  366. package/dist/modes/interactive/terminal-setup.d.ts +9 -0
  367. package/dist/modes/interactive/terminal-setup.js +23 -0
  368. package/dist/modes/interactive/tool-summary.js +19 -17
  369. package/dist/modes/interactive/tool-view.js +7 -4
  370. package/dist/modes/interactive/trace-view.d.ts +89 -0
  371. package/dist/modes/interactive/trace-view.js +332 -0
  372. package/dist/modes/print/print-mode.js +14 -15
  373. package/dist/modes/rpc/commands.js +7 -3
  374. package/dist/modes/rpc/rpc-mode.js +9 -3
  375. package/dist/modes/session-report.d.ts +2 -0
  376. package/dist/modes/session-report.js +101 -105
  377. package/dist/modes/startup-ui-text.js +11 -6
  378. package/dist/permissions/bypass.d.ts +30 -0
  379. package/dist/permissions/bypass.js +45 -0
  380. package/dist/permissions/memory-class.d.ts +23 -0
  381. package/dist/permissions/memory-class.js +54 -0
  382. package/dist/permissions/modes.d.ts +3 -3
  383. package/dist/permissions/modes.js +21 -16
  384. package/dist/permissions/pipeline.d.ts +1 -1
  385. package/dist/permissions/pipeline.js +9 -2
  386. package/dist/permissions/preview.js +49 -42
  387. package/dist/permissions/rules.js +5 -2
  388. package/dist/permissions/types.d.ts +4 -0
  389. package/dist/plan/store.js +2 -1
  390. package/dist/rpc.d.ts +39 -1
  391. package/dist/rpc.js +3 -0
  392. package/dist/sandbox/bash.js +11 -8
  393. package/dist/sandbox/detect.js +14 -11
  394. package/dist/sdk.d.ts +17 -1
  395. package/dist/sdk.js +29 -7
  396. package/dist/session/export.js +31 -30
  397. package/dist/session/manager.d.ts +1 -1
  398. package/dist/session/manager.js +5 -3
  399. package/dist/session/reuse.js +5 -4
  400. package/dist/session/scan.js +3 -2
  401. package/dist/session/stats-aggregate.d.ts +3 -1
  402. package/dist/session/stats-aggregate.js +5 -1
  403. package/dist/session/stats-index.js +2 -1
  404. package/dist/session/stats-scan.d.ts +4 -1
  405. package/dist/session/stats-scan.js +6 -2
  406. package/dist/session/store.d.ts +11 -0
  407. package/dist/session/store.js +48 -1
  408. package/dist/session/types.d.ts +2 -0
  409. package/dist/skills/builtin.js +2 -1
  410. package/dist/tools/image-file.d.ts +26 -1
  411. package/dist/tools/image-file.js +55 -13
  412. package/dist/tools/presets.d.ts +14 -1
  413. package/dist/tools/presets.js +3 -3
  414. package/dist/tools/registry.js +1 -1
  415. package/dist/tools/truncate.d.ts +1 -1
  416. package/dist/tools/truncate.js +2 -2
  417. package/dist/tools/types.d.ts +17 -1
  418. package/dist/trace/build-index.d.ts +91 -0
  419. package/dist/trace/build-index.js +127 -0
  420. package/dist/trace/build-nodes.d.ts +24 -0
  421. package/dist/trace/build-nodes.js +279 -0
  422. package/dist/trace/build-util.d.ts +43 -0
  423. package/dist/trace/build-util.js +120 -0
  424. package/dist/trace/build.d.ts +82 -0
  425. package/dist/trace/build.js +382 -0
  426. package/dist/trace/detail.d.ts +35 -0
  427. package/dist/trace/detail.js +205 -0
  428. package/dist/trace/flatten.d.ts +69 -0
  429. package/dist/trace/flatten.js +173 -0
  430. package/dist/trace/format.d.ts +47 -0
  431. package/dist/trace/format.js +329 -0
  432. package/dist/trace/html-template.d.ts +19 -0
  433. package/dist/trace/html-template.js +150 -0
  434. package/dist/trace/html.d.ts +104 -0
  435. package/dist/trace/html.js +292 -0
  436. package/dist/trace/preview.d.ts +29 -0
  437. package/dist/trace/preview.js +59 -0
  438. package/dist/trace/query-session.d.ts +14 -0
  439. package/dist/trace/query-session.js +38 -0
  440. package/dist/trace/query.d.ts +55 -0
  441. package/dist/trace/query.js +188 -0
  442. package/dist/trace/session.d.ts +40 -0
  443. package/dist/trace/session.js +168 -0
  444. package/dist/trace/types.d.ts +243 -0
  445. package/dist/trace/types.js +13 -0
  446. package/dist/tui/components/editor-paste.d.ts +2 -0
  447. package/dist/tui/components/editor-paste.js +6 -3
  448. package/dist/tui/components/editor.js +2 -2
  449. package/dist/tui/components/loader.d.ts +3 -0
  450. package/dist/tui/components/loader.js +14 -0
  451. package/dist/tui/components/settings-list.d.ts +61 -0
  452. package/dist/tui/components/settings-list.js +135 -0
  453. package/dist/tui/keybindings.d.ts +6 -1
  454. package/dist/tui/keybindings.js +18 -6
  455. package/dist/tui.d.ts +1 -0
  456. package/dist/tui.js +2 -0
  457. package/docs/en/host-api.md +167 -0
  458. package/docs/en/permissions.md +214 -0
  459. package/docs/en/providers.md +625 -0
  460. package/docs/en/rpc.md +361 -0
  461. package/docs/en/sessions.md +219 -0
  462. package/docs/en/tui.md +527 -0
  463. package/docs/host-api.md +18 -17
  464. package/docs/memory.md +172 -0
  465. package/docs/permissions.md +3 -2
  466. package/docs/providers.md +67 -1
  467. package/docs/rpc.md +31 -3
  468. package/docs/session-format.md +8 -2
  469. package/docs/sessions.md +29 -1
  470. package/docs/tui.md +189 -21
  471. package/package.json +8 -3
@@ -0,0 +1,96 @@
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 type { AgentSession } from "../../agent/types.js";
15
+ import type { ModeContext } from "../../cli/deps.js";
16
+ import type { Runtime } from "../../cli/runtime.js";
17
+ import { type ConfigLayerInput } from "../../config/edit.js";
18
+ import type { StatusLineMode } from "../../config/types.js";
19
+ import type { CommandContext, CommandResult } from "../commands-core.js";
20
+ import type { NoticeLevel, ThinkingDisplay } from "./message-view.js";
21
+ import { type PickerHost } from "./pickers.js";
22
+ /** Where "now" settings land in the running UI (every target optional). */
23
+ export interface ConfigApplyTargets {
24
+ session(): AgentSession;
25
+ view?: {
26
+ setOptions(options: {
27
+ showThinking?: ThinkingDisplay;
28
+ markdown?: boolean;
29
+ compact?: boolean;
30
+ }): void;
31
+ };
32
+ loader?: {
33
+ setAnimation(on: boolean): void;
34
+ };
35
+ area?: {
36
+ setLayout(mode: StatusLineMode): void;
37
+ };
38
+ redraw?(): void;
39
+ }
40
+ /** Apply one "now" key to the running session / view; returns false when nothing applies. */
41
+ export declare function applySetting(key: string, value: unknown, targets: ConfigApplyTargets): Promise<boolean>;
42
+ /** Layer inputs of this process: user / project files, the profile and the command line flags. */
43
+ export declare function layerInputFor(runtime: Runtime, context: ModeContext): ConfigLayerInput;
44
+ /** `key=value` / `key value` → [key, raw]. */
45
+ export declare function splitAssignment(args: string): [string, string] | undefined;
46
+ export interface ConfigUiDeps extends PickerHost, ConfigApplyTargets {
47
+ runtime: Runtime;
48
+ context: ModeContext;
49
+ rows(): number;
50
+ notice(level: NoticeLevel, text: string): void;
51
+ render(): void;
52
+ /** Home directory for ~ in paths. */
53
+ home?: string;
54
+ }
55
+ export declare class ConfigUi {
56
+ private readonly deps;
57
+ private panel;
58
+ private handle;
59
+ private changes;
60
+ private prefixNoticeShown;
61
+ constructor(deps: ConfigUiDeps);
62
+ private input;
63
+ /** `/config [key=value]`. */
64
+ open(args: string): Promise<void>;
65
+ private close;
66
+ /** Closing summary (undefined when nothing changed). */
67
+ summary(): string | undefined;
68
+ private activate;
69
+ private pick;
70
+ private commitText;
71
+ /**
72
+ * Write one key and apply it. Errors become panel notices (or are rethrown with `rethrow`, for the
73
+ * inline editor). Returns the edit result, undefined when refused / cancelled.
74
+ */
75
+ private write;
76
+ private afterWrite;
77
+ /** `/config key=value`: user scope, no panel. */
78
+ private direct;
79
+ }
80
+ /** Line mode `/config`: no args lists the settings, `key=value` sets one (user scope). */
81
+ export declare function configCommand(runtime: Runtime, context: ModeContext): (args: string, ctx: CommandContext) => Promise<CommandResult>;
82
+ /** Wiring for interactive-mode.ts (one line there): the session follows `/new` `/resume` `/fork`. */
83
+ export declare function configUiFor(host: PickerHost & {
84
+ rows(): number;
85
+ }, parts: {
86
+ runtime: Runtime;
87
+ context: ModeContext;
88
+ view: NonNullable<ConfigApplyTargets["view"]>;
89
+ loader: NonNullable<ConfigApplyTargets["loader"]>;
90
+ area: NonNullable<ConfigApplyTargets["area"]>;
91
+ tui: {
92
+ forceFullRedraw(): void;
93
+ requestRender(): void;
94
+ };
95
+ notice(level: NoticeLevel, text: string): void;
96
+ }): ConfigUi;
@@ -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))),
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
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 通用确认框:底部覆盖层 + `Box`,选项样式与审批对话框一致(终端界面视觉设计 v1 §3.11)。
3
+ *
4
+ * - 编号选项 `› 1. 进入 Bypass y`,选中行 `›` + `selection` 底色,右侧按键提示 `dim`;
5
+ * - 按键:↑↓ 移动(循环)、Enter 确认、数字直选、选项按键提示里的单个字母直选(如 `y` / `n`);
6
+ * Esc / Ctrl+C / `tui.select.cancel` 取消(返回 undefined);
7
+ * - 宽 < 56 列紧凑:去掉空行、按键提示只留第一个、底部提示缩短。字形取 `theme.glyphs`(ASCII 回退)。
8
+ *
9
+ * 用途:进入 Bypass permissions 前的确认(`confirmBypass`,permissions/bypass.ts)。
10
+ */
11
+ import { type Component, type Focusable, type Keybindings, type OverlayHandle, type OverlayOptions, type SemanticColor, type Theme } from "../../tui.js";
12
+ export interface ChoiceOption {
13
+ label: string;
14
+ /** 右侧按键提示(空格分隔);其中的单个字母同时是直选键。 */
15
+ keys: string;
16
+ }
17
+ export interface ChoiceSpec {
18
+ title: string;
19
+ /** 正文(已着色),选项之上。 */
20
+ body: readonly string[];
21
+ options: readonly ChoiceOption[];
22
+ /** 缺省选中的下标。 */
23
+ selected?: number;
24
+ borderColor?: SemanticColor;
25
+ }
26
+ export interface ChoiceHost {
27
+ theme: Theme;
28
+ keybindings?: Keybindings;
29
+ showOverlay(component: Component, options: OverlayOptions): OverlayHandle;
30
+ }
31
+ export declare class ChoiceDialog implements Component, Focusable {
32
+ private readonly spec;
33
+ private readonly host;
34
+ private readonly done;
35
+ focused: boolean;
36
+ private selected;
37
+ constructor(spec: ChoiceSpec, host: Omit<ChoiceHost, "showOverlay">, done: (index: number | undefined) => void);
38
+ get selectedIndex(): number;
39
+ handleInput(data: string): void;
40
+ render(width: number): string[];
41
+ private optionLines;
42
+ invalidate(): void;
43
+ }
44
+ /** 打开确认框(底部覆盖层):返回选中的下标,取消返回 undefined。 */
45
+ export declare function openChoice(host: ChoiceHost, spec: ChoiceSpec): Promise<number | undefined>;
46
+ /** Bypass 确认框的内容(缺省选中「取消」,边框 warning)。 */
47
+ export declare function bypassChoiceSpec(theme: Theme): ChoiceSpec;
48
+ /** 进入 Bypass 前问一次:选「进入 Bypass」返回 true,取消 / 选「取消」返回 false。 */
49
+ export declare function confirmBypass(host: ChoiceHost): Promise<boolean>;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * 通用确认框:底部覆盖层 + `Box`,选项样式与审批对话框一致(终端界面视觉设计 v1 §3.11)。
3
+ *
4
+ * - 编号选项 `› 1. 进入 Bypass y`,选中行 `›` + `selection` 底色,右侧按键提示 `dim`;
5
+ * - 按键:↑↓ 移动(循环)、Enter 确认、数字直选、选项按键提示里的单个字母直选(如 `y` / `n`);
6
+ * Esc / Ctrl+C / `tui.select.cancel` 取消(返回 undefined);
7
+ * - 宽 < 56 列紧凑:去掉空行、按键提示只留第一个、底部提示缩短。字形取 `theme.glyphs`(ASCII 回退)。
8
+ *
9
+ * 用途:进入 Bypass permissions 前的确认(`confirmBypass`,permissions/bypass.ts)。
10
+ */
11
+ import { msg } from "../../i18n/index.js";
12
+ import { BYPASS_DEFAULT_CHOICE, bypassChoices, bypassConfirmTitle, bypassRiskLines, } from "../../permissions/bypass.js";
13
+ import { Box, defaultKeybindings, matchesKey, padToWidth, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
14
+ /** 宽度低于它(Box 外宽)时用紧凑布局。 */
15
+ const COMPACT_WIDTH = 56;
16
+ export class ChoiceDialog {
17
+ spec;
18
+ host;
19
+ done;
20
+ focused = false;
21
+ selected;
22
+ constructor(spec, host, done) {
23
+ this.spec = spec;
24
+ this.host = host;
25
+ this.done = done;
26
+ this.selected = Math.max(0, Math.min(spec.options.length - 1, spec.selected ?? 0));
27
+ }
28
+ get selectedIndex() {
29
+ return this.selected;
30
+ }
31
+ handleInput(data) {
32
+ const keys = this.host.keybindings ?? defaultKeybindings;
33
+ const n = this.spec.options.length;
34
+ const letter = data.length === 1 ? data.toLowerCase() : "";
35
+ const byLetter = letter === "" || !/^[a-z]$/.test(letter)
36
+ ? -1
37
+ : this.spec.options.findIndex((o) => o.keys.split(/\s+/).includes(letter));
38
+ if (byLetter !== -1)
39
+ this.done(byLetter);
40
+ else if (matchesKey(data, "escape") ||
41
+ keys.matches(data, "app.clear") ||
42
+ keys.matches(data, "tui.select.cancel")) {
43
+ this.done(undefined);
44
+ }
45
+ else if (/^[1-9]$/.test(data) && Number(data) <= n)
46
+ this.done(Number(data) - 1);
47
+ else if (keys.matches(data, "tui.select.up"))
48
+ this.selected = (this.selected + n - 1) % n;
49
+ else if (keys.matches(data, "tui.select.down"))
50
+ this.selected = (this.selected + 1) % n;
51
+ else if (matchesKey(data, "enter"))
52
+ this.done(this.selected);
53
+ }
54
+ render(width) {
55
+ const { theme } = this.host;
56
+ const compact = width + 4 < COMPACT_WIDTH;
57
+ const lines = [];
58
+ for (const line of this.spec.body)
59
+ lines.push(...wrapTextWithAnsi(line, width));
60
+ if (!compact)
61
+ lines.push("");
62
+ lines.push(...this.optionLines(width, compact));
63
+ if (!compact)
64
+ lines.push("");
65
+ const g = theme.glyphs;
66
+ const arrows = g.arrowUp + g.arrowDown;
67
+ const n = this.spec.options.length;
68
+ lines.push(theme.fg("dim", compact ? `${arrows} Enter · 1-${n} · Esc` : msg().approval.choiceHint(arrows, n)));
69
+ return lines.map((l) => truncateToWidth(l, width));
70
+ }
71
+ optionLines(width, compact) {
72
+ const { theme } = this.host;
73
+ const g = theme.glyphs;
74
+ const shown = this.spec.options.map((o) => (compact ? o.keys.split(/\s+/)[0] : o.keys));
75
+ const keyWidth = Math.max(...shown.map((k) => visibleWidth(k)));
76
+ return this.spec.options.map((option, i) => {
77
+ const selected = i === this.selected;
78
+ const left = `${selected ? g.prompt : " "} ${i + 1}. ${option.label}`;
79
+ const right = padToWidth(shown[i], keyWidth);
80
+ const room = Math.max(1, width - keyWidth - 1);
81
+ const label = selected ? theme.fg("accent", theme.bold(left)) : left;
82
+ const line = padToWidth(truncateToWidth(label, room), room) + " " + theme.fg("dim", right);
83
+ return selected ? theme.bg("selection", line) : line;
84
+ });
85
+ }
86
+ invalidate() { }
87
+ }
88
+ /** 打开确认框(底部覆盖层):返回选中的下标,取消返回 undefined。 */
89
+ export function openChoice(host, spec) {
90
+ return new Promise((resolve) => {
91
+ let handle;
92
+ let settled = false;
93
+ const dialog = new ChoiceDialog(spec, host, (index) => {
94
+ if (settled)
95
+ return;
96
+ settled = true;
97
+ handle?.hide();
98
+ resolve(index);
99
+ });
100
+ handle = host.showOverlay(new Box(dialog, {
101
+ title: spec.title,
102
+ theme: host.theme,
103
+ ...(spec.borderColor !== undefined ? { borderColor: spec.borderColor } : {}),
104
+ }), { anchor: "bottom" });
105
+ });
106
+ }
107
+ /** Bypass 确认框的内容(缺省选中「取消」,边框 warning)。 */
108
+ export function bypassChoiceSpec(theme) {
109
+ return {
110
+ title: bypassConfirmTitle(),
111
+ body: bypassRiskLines().map((line, i) => (i === 0 ? theme.fg("warning", line) : line)),
112
+ options: bypassChoices(),
113
+ selected: BYPASS_DEFAULT_CHOICE,
114
+ borderColor: "warning",
115
+ };
116
+ }
117
+ /** 进入 Bypass 前问一次:选「进入 Bypass」返回 true,取消 / 选「取消」返回 false。 */
118
+ export async function confirmBypass(host) {
119
+ return (await openChoice(host, bypassChoiceSpec(host.theme))) === 0;
120
+ }