@armadra/agent 0.4.0 → 0.5.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 (432) hide show
  1. package/CHANGELOG.md +184 -1
  2. package/README.md +202 -83
  3. package/THIRD_PARTY_NOTICES.md +34 -0
  4. package/dist/acp.d.ts +18 -0
  5. package/dist/acp.js +19 -0
  6. package/dist/agent/limits.d.ts +38 -0
  7. package/dist/agent/limits.js +127 -0
  8. package/dist/agent/loop-guard.d.ts +38 -0
  9. package/dist/agent/loop-guard.js +95 -0
  10. package/dist/agent/loop.d.ts +4 -0
  11. package/dist/agent/loop.js +7 -0
  12. package/dist/agent/prompt-rules.d.ts +12 -0
  13. package/dist/agent/prompt-rules.js +18 -0
  14. package/dist/agent/reminders.d.ts +59 -0
  15. package/dist/agent/reminders.js +327 -0
  16. package/dist/agent/session-cache.d.ts +5 -0
  17. package/dist/agent/session-cache.js +17 -1
  18. package/dist/agent/session-classifier.d.ts +1 -1
  19. package/dist/agent/session-classifier.js +3 -1
  20. package/dist/agent/session-compaction.d.ts +35 -6
  21. package/dist/agent/session-compaction.js +157 -31
  22. package/dist/agent/session-core.d.ts +27 -1
  23. package/dist/agent/session-extensions.d.ts +61 -0
  24. package/dist/agent/session-extensions.js +129 -0
  25. package/dist/agent/session-images.d.ts +23 -0
  26. package/dist/agent/session-images.js +97 -0
  27. package/dist/agent/session-plan.d.ts +21 -0
  28. package/dist/agent/session-plan.js +524 -0
  29. package/dist/agent/session-rewind.d.ts +81 -0
  30. package/dist/agent/session-rewind.js +354 -0
  31. package/dist/agent/session-run.d.ts +28 -1
  32. package/dist/agent/session-run.js +157 -6
  33. package/dist/agent/session-settings.d.ts +49 -0
  34. package/dist/agent/session-settings.js +95 -0
  35. package/dist/agent/session-subagent.d.ts +36 -24
  36. package/dist/agent/session-subagent.js +259 -129
  37. package/dist/agent/session-sync.d.ts +10 -3
  38. package/dist/agent/session-sync.js +37 -8
  39. package/dist/agent/session-telemetry.d.ts +39 -0
  40. package/dist/agent/session-telemetry.js +231 -0
  41. package/dist/agent/session-tools.js +40 -1
  42. package/dist/agent/session.d.ts +30 -29
  43. package/dist/agent/session.js +79 -123
  44. package/dist/agent/subagent-registry.d.ts +91 -0
  45. package/dist/agent/subagent-registry.js +494 -0
  46. package/dist/agent/system-prompt.d.ts +6 -3
  47. package/dist/agent/system-prompt.js +7 -2
  48. package/dist/agent/tool-runner.d.ts +8 -1
  49. package/dist/agent/tool-runner.js +57 -4
  50. package/dist/agent/types-w5.d.ts +192 -0
  51. package/dist/agent/types-w5.js +10 -0
  52. package/dist/agent/types.d.ts +47 -4
  53. package/dist/agent/types.js +2 -0
  54. package/dist/agent/worktree.d.ts +36 -0
  55. package/dist/agent/worktree.js +86 -0
  56. package/dist/agents/builtin.d.ts +14 -0
  57. package/dist/agents/builtin.js +39 -0
  58. package/dist/agents/catalog.d.ts +43 -0
  59. package/dist/agents/catalog.js +82 -0
  60. package/dist/agents/discover.d.ts +35 -0
  61. package/dist/agents/discover.js +83 -0
  62. package/dist/agents/external.d.ts +82 -0
  63. package/dist/agents/external.js +326 -0
  64. package/dist/agents/parse.d.ts +18 -0
  65. package/dist/agents/parse.js +116 -0
  66. package/dist/agents/result.d.ts +32 -0
  67. package/dist/agents/result.js +67 -0
  68. package/dist/agents/task-control.d.ts +17 -0
  69. package/dist/agents/task-control.js +17 -0
  70. package/dist/agents/task-record.d.ts +78 -0
  71. package/dist/agents/task-record.js +141 -0
  72. package/dist/agents/types.d.ts +46 -0
  73. package/dist/agents/types.js +8 -0
  74. package/dist/ai/apis/anthropic-compat.d.ts +36 -0
  75. package/dist/ai/apis/anthropic-compat.js +92 -0
  76. package/dist/ai/apis/anthropic-request.d.ts +7 -6
  77. package/dist/ai/apis/anthropic-request.js +10 -28
  78. package/dist/ai/apis/cache-params.d.ts +11 -2
  79. package/dist/ai/apis/cache-params.js +25 -6
  80. package/dist/ai/apis/openai-compat.d.ts +4 -1
  81. package/dist/ai/apis/openai-compat.js +8 -1
  82. package/dist/ai/image-limits.d.ts +45 -0
  83. package/dist/ai/image-limits.js +68 -0
  84. package/dist/ai/providers/builtin.d.ts +18 -6
  85. package/dist/ai/providers/builtin.js +135 -6
  86. package/dist/ai/providers/catalog-data.js +17 -13
  87. package/dist/ai/providers/catalog.d.ts +60 -7
  88. package/dist/ai/providers/catalog.js +197 -38
  89. package/dist/ai/providers/channels.d.ts +33 -3
  90. package/dist/ai/providers/channels.js +108 -7
  91. package/dist/ai/providers/enrich.d.ts +6 -3
  92. package/dist/ai/providers/enrich.js +19 -4
  93. package/dist/ai/providers/models-dev-cache.d.ts +28 -24
  94. package/dist/ai/providers/models-dev-cache.js +92 -78
  95. package/dist/ai/providers/models-dev-data.d.ts +7 -0
  96. package/dist/ai/providers/models-dev-data.js +32 -0
  97. package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
  98. package/dist/ai/providers/models-dev-snapshot.js +137 -0
  99. package/dist/ai/providers/models-dev.d.ts +51 -10
  100. package/dist/ai/providers/models-dev.js +132 -39
  101. package/dist/ai/providers/registry.d.ts +20 -10
  102. package/dist/ai/providers/registry.js +82 -43
  103. package/dist/ai/types.d.ts +28 -2
  104. package/dist/ai/types.js +5 -0
  105. package/dist/bundle/ama.cjs +37605 -21619
  106. package/dist/checkpoints/backend.d.ts +61 -0
  107. package/dist/checkpoints/backend.js +135 -0
  108. package/dist/checkpoints/blobs.d.ts +60 -0
  109. package/dist/checkpoints/blobs.js +203 -0
  110. package/dist/checkpoints/gc.d.ts +47 -0
  111. package/dist/checkpoints/gc.js +144 -0
  112. package/dist/checkpoints/git-head.d.ts +15 -0
  113. package/dist/checkpoints/git-head.js +89 -0
  114. package/dist/checkpoints/index.d.ts +17 -0
  115. package/dist/checkpoints/index.js +17 -0
  116. package/dist/checkpoints/replay.d.ts +48 -0
  117. package/dist/checkpoints/replay.js +154 -0
  118. package/dist/checkpoints/restore.d.ts +86 -0
  119. package/dist/checkpoints/restore.js +263 -0
  120. package/dist/checkpoints/settings.d.ts +14 -0
  121. package/dist/checkpoints/settings.js +23 -0
  122. package/dist/checkpoints/shadow-git.d.ts +108 -0
  123. package/dist/checkpoints/shadow-git.js +491 -0
  124. package/dist/checkpoints/shadow-restore.d.ts +25 -0
  125. package/dist/checkpoints/shadow-restore.js +128 -0
  126. package/dist/checkpoints/tracker.d.ts +64 -0
  127. package/dist/checkpoints/tracker.js +192 -0
  128. package/dist/checkpoints/types.d.ts +99 -0
  129. package/dist/checkpoints/types.js +12 -0
  130. package/dist/cli/args.d.ts +8 -4
  131. package/dist/cli/args.js +17 -97
  132. package/dist/cli/bootstrap.js +13 -1
  133. package/dist/cli/choice-prompt.d.ts +58 -0
  134. package/dist/cli/choice-prompt.js +140 -0
  135. package/dist/cli/codemode-notice.d.ts +3 -2
  136. package/dist/cli/codemode-notice.js +3 -2
  137. package/dist/cli/compose-agents.d.ts +27 -0
  138. package/dist/cli/compose-agents.js +111 -0
  139. package/dist/cli/compose-extensions.d.ts +29 -0
  140. package/dist/cli/compose-extensions.js +44 -0
  141. package/dist/cli/compose-session.d.ts +3 -0
  142. package/dist/cli/compose-session.js +47 -4
  143. package/dist/cli/compose.d.ts +3 -0
  144. package/dist/cli/compose.js +33 -6
  145. package/dist/cli/deps.d.ts +6 -0
  146. package/dist/cli/exit-codes.d.ts +10 -0
  147. package/dist/cli/exit-codes.js +12 -0
  148. package/dist/cli/help-text.d.ts +4 -0
  149. package/dist/cli/help-text.js +102 -0
  150. package/dist/cli/startup-screen.js +5 -3
  151. package/dist/cli/startup-steps.js +7 -1
  152. package/dist/cli/subcommands/config.d.ts +4 -1
  153. package/dist/cli/subcommands/config.js +17 -6
  154. package/dist/cli/subcommands/doctor.js +21 -0
  155. package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
  156. package/dist/cli/subcommands/models-cache-probe.js +3 -12
  157. package/dist/cli/subcommands/models-discover.js +5 -6
  158. package/dist/cli/subcommands/models.d.ts +2 -0
  159. package/dist/cli/subcommands/models.js +33 -14
  160. package/dist/cli/subcommands/providers.d.ts +1 -1
  161. package/dist/cli/subcommands/providers.js +8 -15
  162. package/dist/cli/subcommands/sessions.d.ts +3 -1
  163. package/dist/cli/subcommands/sessions.js +36 -2
  164. package/dist/codemode/capability.d.ts +24 -7
  165. package/dist/codemode/capability.js +38 -10
  166. package/dist/codemode/host-side.d.ts +14 -0
  167. package/dist/codemode/host-side.js +24 -1
  168. package/dist/codemode/tool.d.ts +1 -1
  169. package/dist/codemode/tool.js +6 -4
  170. package/dist/compaction/breaker.d.ts +25 -9
  171. package/dist/compaction/breaker.js +47 -17
  172. package/dist/compaction/estimate.d.ts +11 -3
  173. package/dist/compaction/estimate.js +64 -22
  174. package/dist/compaction/image-budget.d.ts +45 -0
  175. package/dist/compaction/image-budget.js +115 -0
  176. package/dist/compaction/post-compact.d.ts +38 -0
  177. package/dist/compaction/post-compact.js +152 -0
  178. package/dist/compaction/protect.d.ts +27 -0
  179. package/dist/compaction/protect.js +56 -0
  180. package/dist/compaction/prune-tier.d.ts +58 -12
  181. package/dist/compaction/prune-tier.js +120 -54
  182. package/dist/compaction/summarize-tier.d.ts +23 -4
  183. package/dist/compaction/summarize-tier.js +100 -29
  184. package/dist/config/checker.d.ts +28 -0
  185. package/dist/config/checker.js +97 -0
  186. package/dist/config/json-schema.js +63 -2
  187. package/dist/config/key-docs.js +72 -3
  188. package/dist/config/merge.d.ts +5 -3
  189. package/dist/config/merge.js +81 -7
  190. package/dist/config/profile.d.ts +2 -0
  191. package/dist/config/profile.js +2 -0
  192. package/dist/config/schema-w5.d.ts +18 -0
  193. package/dist/config/schema-w5.js +109 -0
  194. package/dist/config/schema.d.ts +5 -9
  195. package/dist/config/schema.js +68 -114
  196. package/dist/config/types-w5.d.ts +118 -0
  197. package/dist/config/types-w5.js +20 -0
  198. package/dist/config/types.d.ts +50 -1
  199. package/dist/config/types.js +12 -0
  200. package/dist/drivers/acp/client.d.ts +57 -0
  201. package/dist/drivers/acp/client.js +160 -0
  202. package/dist/drivers/acp/driver.d.ts +31 -0
  203. package/dist/drivers/acp/driver.js +274 -0
  204. package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
  205. package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
  206. package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
  207. package/dist/drivers/acp/testing/fake-agent.js +211 -0
  208. package/dist/drivers/acp/types.d.ts +285 -0
  209. package/dist/drivers/acp/types.js +36 -0
  210. package/dist/drivers/agents.d.ts +58 -0
  211. package/dist/drivers/agents.js +142 -0
  212. package/dist/drivers/base.d.ts +35 -0
  213. package/dist/drivers/base.js +59 -0
  214. package/dist/drivers/catalog.d.ts +46 -0
  215. package/dist/drivers/catalog.js +167 -0
  216. package/dist/drivers/env.d.ts +20 -0
  217. package/dist/drivers/env.js +46 -0
  218. package/dist/drivers/host-runners.d.ts +18 -0
  219. package/dist/drivers/host-runners.js +45 -0
  220. package/dist/drivers/jsonrpc.d.ts +58 -0
  221. package/dist/drivers/jsonrpc.js +180 -0
  222. package/dist/drivers/native/claude-normalize.d.ts +46 -0
  223. package/dist/drivers/native/claude-normalize.js +106 -0
  224. package/dist/drivers/native/claude-stream.d.ts +29 -0
  225. package/dist/drivers/native/claude-stream.js +456 -0
  226. package/dist/drivers/native/codex-app-server.d.ts +26 -0
  227. package/dist/drivers/native/codex-app-server.js +407 -0
  228. package/dist/drivers/native/codex-normalize.d.ts +38 -0
  229. package/dist/drivers/native/codex-normalize.js +124 -0
  230. package/dist/drivers/native/oneshot.d.ts +28 -0
  231. package/dist/drivers/native/oneshot.js +312 -0
  232. package/dist/drivers/permissions.d.ts +40 -0
  233. package/dist/drivers/permissions.js +92 -0
  234. package/dist/drivers/pids.d.ts +32 -0
  235. package/dist/drivers/pids.js +93 -0
  236. package/dist/drivers/pool.d.ts +28 -0
  237. package/dist/drivers/pool.js +96 -0
  238. package/dist/drivers/probe.d.ts +47 -0
  239. package/dist/drivers/probe.js +172 -0
  240. package/dist/drivers/process.d.ts +48 -0
  241. package/dist/drivers/process.js +100 -0
  242. package/dist/drivers/runner.d.ts +61 -0
  243. package/dist/drivers/runner.js +388 -0
  244. package/dist/drivers/store.d.ts +49 -0
  245. package/dist/drivers/store.js +91 -0
  246. package/dist/drivers/turn.d.ts +41 -0
  247. package/dist/drivers/turn.js +99 -0
  248. package/dist/drivers/types.d.ts +122 -0
  249. package/dist/drivers/types.js +11 -0
  250. package/dist/git/info.d.ts +75 -0
  251. package/dist/git/info.js +191 -0
  252. package/dist/hooks/protocol.js +6 -1
  253. package/dist/hooks/types.d.ts +10 -1
  254. package/dist/hooks/types.js +2 -0
  255. package/dist/host/api-impl.d.ts +7 -0
  256. package/dist/host/api-impl.js +15 -0
  257. package/dist/host/types.d.ts +24 -2
  258. package/dist/host/types.js +4 -0
  259. package/dist/index.d.ts +3 -0
  260. package/dist/index.js +1 -0
  261. package/dist/modes/acp/acp-events.d.ts +46 -0
  262. package/dist/modes/acp/acp-events.js +233 -0
  263. package/dist/modes/acp/acp-mode.d.ts +17 -0
  264. package/dist/modes/acp/acp-mode.js +47 -0
  265. package/dist/modes/acp/acp-server.d.ts +79 -0
  266. package/dist/modes/acp/acp-server.js +315 -0
  267. package/dist/modes/commands-core.d.ts +13 -1
  268. package/dist/modes/commands-core.js +64 -0
  269. package/dist/modes/image-input.d.ts +12 -4
  270. package/dist/modes/image-input.js +22 -5
  271. package/dist/modes/interactive/agent-panels.d.ts +14 -0
  272. package/dist/modes/interactive/agent-panels.js +103 -0
  273. package/dist/modes/interactive/agent-ui.d.ts +73 -0
  274. package/dist/modes/interactive/agent-ui.js +234 -0
  275. package/dist/modes/interactive/approval-dialog.d.ts +21 -4
  276. package/dist/modes/interactive/approval-dialog.js +98 -20
  277. package/dist/modes/interactive/approval-merge.d.ts +41 -0
  278. package/dist/modes/interactive/approval-merge.js +89 -0
  279. package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
  280. package/dist/modes/interactive/clipboard-paste.js +28 -0
  281. package/dist/modes/interactive/commands.d.ts +12 -1
  282. package/dist/modes/interactive/commands.js +31 -1
  283. package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
  284. package/dist/modes/interactive/confirm-dialog.js +121 -0
  285. package/dist/modes/interactive/double-esc.d.ts +20 -0
  286. package/dist/modes/interactive/double-esc.js +34 -0
  287. package/dist/modes/interactive/event-notices.d.ts +32 -0
  288. package/dist/modes/interactive/event-notices.js +79 -0
  289. package/dist/modes/interactive/external-editor.d.ts +16 -0
  290. package/dist/modes/interactive/external-editor.js +39 -0
  291. package/dist/modes/interactive/interactive-mode.d.ts +14 -1
  292. package/dist/modes/interactive/interactive-mode.js +140 -136
  293. package/dist/modes/interactive/key-dispatch.d.ts +22 -2
  294. package/dist/modes/interactive/key-dispatch.js +66 -7
  295. package/dist/modes/interactive/line/line-mode.d.ts +4 -1
  296. package/dist/modes/interactive/line/line-mode.js +31 -5
  297. package/dist/modes/interactive/line/line-render.d.ts +2 -1
  298. package/dist/modes/interactive/line/line-render.js +40 -4
  299. package/dist/modes/interactive/message-view.d.ts +1 -1
  300. package/dist/modes/interactive/message-view.js +24 -2
  301. package/dist/modes/interactive/panels.d.ts +18 -1
  302. package/dist/modes/interactive/panels.js +19 -5
  303. package/dist/modes/interactive/plan-command.d.ts +40 -0
  304. package/dist/modes/interactive/plan-command.js +129 -0
  305. package/dist/modes/interactive/plan-dialog.d.ts +98 -0
  306. package/dist/modes/interactive/plan-dialog.js +290 -0
  307. package/dist/modes/interactive/plan-flow.d.ts +34 -0
  308. package/dist/modes/interactive/plan-flow.js +98 -0
  309. package/dist/modes/interactive/rewind-command.d.ts +31 -0
  310. package/dist/modes/interactive/rewind-command.js +106 -0
  311. package/dist/modes/interactive/rewind-flow.d.ts +37 -0
  312. package/dist/modes/interactive/rewind-flow.js +151 -0
  313. package/dist/modes/interactive/rewind-list.d.ts +36 -0
  314. package/dist/modes/interactive/rewind-list.js +123 -0
  315. package/dist/modes/interactive/rewind-panel.d.ts +77 -0
  316. package/dist/modes/interactive/rewind-panel.js +309 -0
  317. package/dist/modes/interactive/rewind-text.d.ts +40 -0
  318. package/dist/modes/interactive/rewind-text.js +139 -0
  319. package/dist/modes/interactive/session-events.d.ts +24 -0
  320. package/dist/modes/interactive/session-events.js +96 -0
  321. package/dist/modes/interactive/startup-ui.js +5 -1
  322. package/dist/modes/interactive/status-area.d.ts +73 -0
  323. package/dist/modes/interactive/status-area.js +190 -0
  324. package/dist/modes/interactive/status-bar.d.ts +99 -11
  325. package/dist/modes/interactive/status-bar.js +273 -90
  326. package/dist/modes/interactive/status-line.d.ts +33 -0
  327. package/dist/modes/interactive/status-line.js +113 -0
  328. package/dist/modes/interactive/subagent-view.d.ts +56 -0
  329. package/dist/modes/interactive/subagent-view.js +154 -0
  330. package/dist/modes/interactive/tasks-report.d.ts +27 -0
  331. package/dist/modes/interactive/tasks-report.js +114 -0
  332. package/dist/modes/interactive/tool-view.d.ts +12 -2
  333. package/dist/modes/interactive/tool-view.js +34 -4
  334. package/dist/modes/print/print-mode.d.ts +13 -4
  335. package/dist/modes/print/print-mode.js +56 -12
  336. package/dist/modes/rpc/commands.d.ts +9 -0
  337. package/dist/modes/rpc/commands.js +44 -0
  338. package/dist/modes/rpc/rpc-mode.js +7 -1
  339. package/dist/modes/session-report.d.ts +11 -0
  340. package/dist/modes/session-report.js +48 -1
  341. package/dist/permissions/auto-safe.d.ts +5 -0
  342. package/dist/permissions/auto-safe.js +18 -0
  343. package/dist/permissions/bypass.d.ts +32 -0
  344. package/dist/permissions/bypass.js +36 -0
  345. package/dist/permissions/classifier.d.ts +4 -0
  346. package/dist/permissions/classifier.js +2 -0
  347. package/dist/permissions/modes.js +1 -1
  348. package/dist/permissions/pipeline.d.ts +43 -4
  349. package/dist/permissions/pipeline.js +114 -9
  350. package/dist/permissions/readonly-bash.d.ts +30 -0
  351. package/dist/permissions/readonly-bash.js +118 -0
  352. package/dist/permissions/types.d.ts +42 -0
  353. package/dist/plan/compose.d.ts +9 -0
  354. package/dist/plan/compose.js +19 -0
  355. package/dist/plan/controller.d.ts +71 -0
  356. package/dist/plan/controller.js +27 -0
  357. package/dist/plan/done-markers.d.ts +17 -0
  358. package/dist/plan/done-markers.js +51 -0
  359. package/dist/plan/extract.d.ts +29 -0
  360. package/dist/plan/extract.js +160 -0
  361. package/dist/plan/prompts.d.ts +36 -0
  362. package/dist/plan/prompts.js +89 -0
  363. package/dist/plan/store.d.ts +37 -0
  364. package/dist/plan/store.js +90 -0
  365. package/dist/rpc.d.ts +58 -2
  366. package/dist/rpc.js +7 -0
  367. package/dist/sandbox/bash.d.ts +74 -0
  368. package/dist/sandbox/bash.js +126 -0
  369. package/dist/sandbox/detect.d.ts +48 -0
  370. package/dist/sandbox/detect.js +149 -0
  371. package/dist/sandbox/index.d.ts +5 -0
  372. package/dist/sandbox/index.js +5 -0
  373. package/dist/sandbox/profile.d.ts +33 -0
  374. package/dist/sandbox/profile.js +76 -0
  375. package/dist/sandbox/wrap.d.ts +29 -0
  376. package/dist/sandbox/wrap.js +117 -0
  377. package/dist/sdk.d.ts +33 -2
  378. package/dist/sdk.js +24 -2
  379. package/dist/session/types.d.ts +3 -1
  380. package/dist/session/types.js +1 -0
  381. package/dist/skills/builtin.d.ts +31 -0
  382. package/dist/skills/builtin.js +109 -0
  383. package/dist/skills/discover.d.ts +2 -1
  384. package/dist/skills/index-prompt.js +5 -8
  385. package/dist/tools/background-jobs.d.ts +71 -0
  386. package/dist/tools/background-jobs.js +198 -0
  387. package/dist/tools/bash.d.ts +53 -1
  388. package/dist/tools/bash.js +158 -7
  389. package/dist/tools/clipboard-image.d.ts +44 -0
  390. package/dist/tools/clipboard-image.js +148 -0
  391. package/dist/tools/edit.d.ts +2 -0
  392. package/dist/tools/edit.js +18 -3
  393. package/dist/tools/image-file.d.ts +38 -3
  394. package/dist/tools/image-file.js +81 -10
  395. package/dist/tools/image-resize.d.ts +58 -0
  396. package/dist/tools/image-resize.js +97 -0
  397. package/dist/tools/presets.d.ts +7 -2
  398. package/dist/tools/presets.js +11 -4
  399. package/dist/tools/read.d.ts +5 -2
  400. package/dist/tools/read.js +13 -10
  401. package/dist/tools/registry.d.ts +7 -1
  402. package/dist/tools/registry.js +27 -4
  403. package/dist/tools/task-ctl.d.ts +22 -0
  404. package/dist/tools/task-ctl.js +116 -0
  405. package/dist/tools/task.d.ts +22 -10
  406. package/dist/tools/task.js +66 -26
  407. package/dist/tools/todo.d.ts +22 -2
  408. package/dist/tools/todo.js +58 -14
  409. package/dist/tools/truncate.d.ts +15 -0
  410. package/dist/tools/truncate.js +25 -0
  411. package/dist/tools/types.d.ts +113 -0
  412. package/dist/tools/types.js +5 -0
  413. package/dist/tools/write.js +3 -0
  414. package/dist/tui/glyphs.d.ts +4 -0
  415. package/dist/tui/glyphs.js +4 -0
  416. package/dist/tui/keybindings.d.ts +6 -1
  417. package/dist/tui/keybindings.js +6 -1
  418. package/docs/acp.md +78 -0
  419. package/docs/agents.md +250 -0
  420. package/docs/codemode.md +12 -8
  421. package/docs/hooks.md +26 -22
  422. package/docs/permissions.md +78 -13
  423. package/docs/plan.md +107 -0
  424. package/docs/providers.md +228 -52
  425. package/docs/rewind-plan.md +181 -0
  426. package/docs/rpc.md +92 -5
  427. package/docs/sandbox.md +215 -0
  428. package/docs/session-format.md +41 -21
  429. package/docs/sessions.md +41 -1
  430. package/docs/tui-design.md +751 -0
  431. package/docs/tui.md +179 -21
  432. package/package.json +13 -2
@@ -0,0 +1,98 @@
1
+ /**
2
+ * 计划审批对话框(docs/wave5-plan.md §6.1、§6.3):底部覆盖层,与权限审批框同一手法。[W5-U]
3
+ *
4
+ * ```
5
+ * ╭─ 计划待审批 ──────────────────────────────────────────────╮
6
+ * │ 计划 v1 · 3 步 · ~/.local/share/ama/plans/3f2a9c1e-v1.md │
7
+ * │ 给 status-bar 加回退模型显示 │
8
+ * │ S1 读 status-bar.ts 与 status-area.ts │
9
+ * │ … │
10
+ * │ │
11
+ * │ › 1. 批准并执行 │
12
+ * │ 2. 批准,在新上下文执行 │
13
+ * │ 3. 继续修改… │
14
+ * │ 4. 放弃,退出 Plan 模式 │
15
+ * │ │
16
+ * │ ↑↓ 选择 · Enter 确认 · e 编辑计划 · Esc 留在 Plan │
17
+ * ╰───────────────────────────────────────────────────────────╯
18
+ * ```
19
+ *
20
+ * - 1 / 2 之后选执行模式:回到进入前的模式(缺省)/ Accept edits / Auto;Esc 回到上一步。
21
+ * - 3「继续修改」:行内写意见(Enter 发送,`Ctrl+E` 改用外部编辑器写),意见作为普通用户消息、留在 plan;
22
+ * Esc 回到上一步。
23
+ * - `e`:在外部编辑器(`$VISUAL` / `$EDITOR`,TUI 挂起)里改计划全文;批准时以改后的版本(version + 1)
24
+ * 交接。
25
+ * - 4「放弃」:计划标 rejected 并退出 Plan 模式(回到进入前的模式);Esc:计划标 rejected、留在 Plan 模式
26
+ * (§6.1)。
27
+ * - 宽 < 56 时紧凑:去掉空行、按键提示缩短。ASCII 字形走 theme.glyphs。
28
+ */
29
+ import type { PlanData } from "../../agent/types.js";
30
+ import type { PermissionMode } from "../../permissions/types.js";
31
+ import { type Component, type Focusable, type Keybindings, type OverlayHandle, type Theme } from "../../tui.js";
32
+ /** 对话框里最多列出的步骤数。 */
33
+ export declare const PLAN_DIALOG_STEPS = 6;
34
+ export type PlanChoice = {
35
+ decision: "approve" | "approve_fresh";
36
+ mode: PermissionMode;
37
+ editedMarkdown?: string;
38
+ } | {
39
+ decision: "revise";
40
+ feedback: string;
41
+ }
42
+ /** `exit`:放弃并退出 Plan 模式(选项 4);Esc 为 false。 */
43
+ | {
44
+ decision: "reject";
45
+ exit: boolean;
46
+ };
47
+ export interface PlanDialogHost {
48
+ theme: Theme;
49
+ keybindings?: Keybindings;
50
+ showOverlay(component: Component): OverlayHandle;
51
+ /** 外部编辑器:返回改后的文本,取消或失败返回 undefined。 */
52
+ editExternal?(text: string, kind: "plan" | "feedback"): Promise<string | undefined>;
53
+ /** 计划文件路径的显示(缩写家目录)。 */
54
+ displayPath?(path: string): string;
55
+ /** 重画(外部编辑器回来之后)。 */
56
+ render?(): void;
57
+ onOpen?(): void;
58
+ onClose?(): void;
59
+ }
60
+ export interface PlanDialogInput {
61
+ plan: PlanData;
62
+ /** 「回到进入前的模式」对应的执行模式。 */
63
+ preMode: PermissionMode;
64
+ }
65
+ export declare class PlanDialog implements Component, Focusable {
66
+ private readonly input;
67
+ private readonly host;
68
+ private readonly done;
69
+ focused: boolean;
70
+ private stage;
71
+ private selected;
72
+ private modeSelected;
73
+ /** 选执行模式时记下的是 1 还是 2。 */
74
+ private fresh;
75
+ private feedback;
76
+ private edited;
77
+ constructor(input: PlanDialogInput, host: PlanDialogHost, done: (choice: PlanChoice) => void);
78
+ private modes;
79
+ handleInput(data: string): void;
80
+ private keys;
81
+ private cancelKey;
82
+ private mainInput;
83
+ private choose;
84
+ private modeInput;
85
+ private approve;
86
+ private reviseInput;
87
+ private editPlan;
88
+ private editFeedback;
89
+ render(width: number): string[];
90
+ /** 版本、步数、文件、标题与前几步。 */
91
+ private summary;
92
+ private optionLines;
93
+ private reviseLines;
94
+ private hint;
95
+ invalidate(): void;
96
+ }
97
+ /** 打开对话框,等用户选择。 */
98
+ export declare function openPlanDialog(host: PlanDialogHost, input: PlanDialogInput): Promise<PlanChoice>;
@@ -0,0 +1,290 @@
1
+ /**
2
+ * 计划审批对话框(docs/wave5-plan.md §6.1、§6.3):底部覆盖层,与权限审批框同一手法。[W5-U]
3
+ *
4
+ * ```
5
+ * ╭─ 计划待审批 ──────────────────────────────────────────────╮
6
+ * │ 计划 v1 · 3 步 · ~/.local/share/ama/plans/3f2a9c1e-v1.md │
7
+ * │ 给 status-bar 加回退模型显示 │
8
+ * │ S1 读 status-bar.ts 与 status-area.ts │
9
+ * │ … │
10
+ * │ │
11
+ * │ › 1. 批准并执行 │
12
+ * │ 2. 批准,在新上下文执行 │
13
+ * │ 3. 继续修改… │
14
+ * │ 4. 放弃,退出 Plan 模式 │
15
+ * │ │
16
+ * │ ↑↓ 选择 · Enter 确认 · e 编辑计划 · Esc 留在 Plan │
17
+ * ╰───────────────────────────────────────────────────────────╯
18
+ * ```
19
+ *
20
+ * - 1 / 2 之后选执行模式:回到进入前的模式(缺省)/ Accept edits / Auto;Esc 回到上一步。
21
+ * - 3「继续修改」:行内写意见(Enter 发送,`Ctrl+E` 改用外部编辑器写),意见作为普通用户消息、留在 plan;
22
+ * Esc 回到上一步。
23
+ * - `e`:在外部编辑器(`$VISUAL` / `$EDITOR`,TUI 挂起)里改计划全文;批准时以改后的版本(version + 1)
24
+ * 交接。
25
+ * - 4「放弃」:计划标 rejected 并退出 Plan 模式(回到进入前的模式);Esc:计划标 rejected、留在 Plan 模式
26
+ * (§6.1)。
27
+ * - 宽 < 56 时紧凑:去掉空行、按键提示缩短。ASCII 字形走 theme.glyphs。
28
+ */
29
+ import { permissionModeLabel } from "../../permissions/modes.js";
30
+ import { Box, defaultKeybindings, isPasteData, isPrintableText, matchesKey, padToWidth, truncateToWidth, unwrapPaste, wrapTextWithAnsi, } from "../../tui.js";
31
+ import { planTitle } from "./plan-command.js";
32
+ /** 对话框里最多列出的步骤数。 */
33
+ export const PLAN_DIALOG_STEPS = 6;
34
+ const COMPACT_WIDTH = 56;
35
+ function mainOptions(ellipsis) {
36
+ return ["批准并执行", "批准,在新上下文执行", `继续修改${ellipsis}`, "放弃,退出 Plan 模式"];
37
+ }
38
+ const MAIN_COUNT = 4;
39
+ export class PlanDialog {
40
+ input;
41
+ host;
42
+ done;
43
+ focused = false;
44
+ stage = "main";
45
+ selected = 0;
46
+ modeSelected = 0;
47
+ /** 选执行模式时记下的是 1 还是 2。 */
48
+ fresh = false;
49
+ feedback = "";
50
+ edited;
51
+ constructor(input, host, done) {
52
+ this.input = input;
53
+ this.host = host;
54
+ this.done = done;
55
+ }
56
+ modes() {
57
+ const pre = this.input.preMode;
58
+ return [
59
+ { mode: pre, label: `回到进入前的模式(${permissionModeLabel(pre)})` },
60
+ { mode: "auto-edit", label: permissionModeLabel("auto-edit") },
61
+ { mode: "auto", label: permissionModeLabel("auto") },
62
+ ];
63
+ }
64
+ handleInput(data) {
65
+ switch (this.stage) {
66
+ case "main":
67
+ return this.mainInput(data);
68
+ case "mode":
69
+ return this.modeInput(data);
70
+ case "revise":
71
+ return this.reviseInput(data);
72
+ case "editing":
73
+ return;
74
+ }
75
+ }
76
+ keys() {
77
+ return this.host.keybindings ?? defaultKeybindings;
78
+ }
79
+ cancelKey(data) {
80
+ const keys = this.keys();
81
+ return (matchesKey(data, "escape") ||
82
+ keys.matches(data, "app.clear") ||
83
+ keys.matches(data, "tui.select.cancel"));
84
+ }
85
+ mainInput(data) {
86
+ const keys = this.keys();
87
+ if (this.cancelKey(data))
88
+ return this.done({ decision: "reject", exit: false });
89
+ if (/^[1-4]$/.test(data))
90
+ return this.choose(Number(data) - 1);
91
+ if (keys.matches(data, "tui.select.up"))
92
+ this.selected = (this.selected + MAIN_COUNT - 1) % MAIN_COUNT;
93
+ else if (keys.matches(data, "tui.select.down"))
94
+ this.selected = (this.selected + 1) % MAIN_COUNT;
95
+ else if (matchesKey(data, "enter"))
96
+ this.choose(this.selected);
97
+ else if (data === "e" || data === "E")
98
+ void this.editPlan();
99
+ }
100
+ choose(index) {
101
+ this.selected = index;
102
+ if (index === 0 || index === 1) {
103
+ this.fresh = index === 1;
104
+ this.modeSelected = 0;
105
+ this.stage = "mode";
106
+ }
107
+ else if (index === 2) {
108
+ this.stage = "revise";
109
+ }
110
+ else
111
+ this.done({ decision: "reject", exit: true });
112
+ }
113
+ modeInput(data) {
114
+ const keys = this.keys();
115
+ const modes = this.modes();
116
+ if (this.cancelKey(data)) {
117
+ this.stage = "main";
118
+ return;
119
+ }
120
+ if (/^[1-3]$/.test(data))
121
+ return this.approve(modes[Number(data) - 1].mode);
122
+ if (keys.matches(data, "tui.select.up"))
123
+ this.modeSelected = (this.modeSelected + modes.length - 1) % modes.length;
124
+ else if (keys.matches(data, "tui.select.down"))
125
+ this.modeSelected = (this.modeSelected + 1) % modes.length;
126
+ else if (matchesKey(data, "enter"))
127
+ this.approve(modes[this.modeSelected].mode);
128
+ }
129
+ approve(mode) {
130
+ this.done({
131
+ decision: this.fresh ? "approve_fresh" : "approve",
132
+ mode,
133
+ ...(this.edited !== undefined ? { editedMarkdown: this.edited } : {}),
134
+ });
135
+ }
136
+ reviseInput(data) {
137
+ if (this.cancelKey(data)) {
138
+ this.stage = "main";
139
+ return;
140
+ }
141
+ if (matchesKey(data, "enter")) {
142
+ if (this.feedback.trim() !== "")
143
+ this.done({ decision: "revise", feedback: this.feedback });
144
+ return;
145
+ }
146
+ if (matchesKey(data, "ctrl+e"))
147
+ return void this.editFeedback();
148
+ if (matchesKey(data, "backspace")) {
149
+ this.feedback = [...this.feedback].slice(0, -1).join("");
150
+ return;
151
+ }
152
+ if (isPasteData(data)) {
153
+ this.feedback += unwrapPaste(data).replace(/\r\n?/g, "\n");
154
+ return;
155
+ }
156
+ if (isPrintableText(data))
157
+ this.feedback += data;
158
+ }
159
+ async editPlan() {
160
+ if (this.host.editExternal === undefined)
161
+ return;
162
+ this.stage = "editing";
163
+ const before = this.edited ?? this.input.plan.markdown;
164
+ const after = await this.host.editExternal(before, "plan").catch(() => undefined);
165
+ if (after !== undefined && after.trim() !== "" && after !== this.input.plan.markdown)
166
+ this.edited = after;
167
+ this.stage = "main";
168
+ this.host.render?.();
169
+ }
170
+ async editFeedback() {
171
+ if (this.host.editExternal === undefined)
172
+ return;
173
+ this.stage = "editing";
174
+ const after = await this.host.editExternal(this.feedback, "feedback").catch(() => undefined);
175
+ this.stage = "revise";
176
+ if (after !== undefined && after.trim() !== "") {
177
+ this.done({ decision: "revise", feedback: after.trim() });
178
+ return;
179
+ }
180
+ this.host.render?.();
181
+ }
182
+ render(width) {
183
+ const compact = width + 4 < COMPACT_WIDTH;
184
+ const lines = [];
185
+ const push = (line) => void lines.push(...wrapTextWithAnsi(line, width));
186
+ const blank = () => {
187
+ if (!compact)
188
+ lines.push("");
189
+ };
190
+ // 摘要(版本、标题、步骤)窄屏截断不折行:续行顶格会和步骤编号对不齐
191
+ lines.push(...this.summary());
192
+ blank();
193
+ switch (this.stage) {
194
+ case "main":
195
+ lines.push(...this.optionLines(mainOptions(this.host.theme.glyphs.ellipsis), this.selected, width));
196
+ break;
197
+ case "mode":
198
+ push(this.host.theme.bold(this.fresh ? "在新上下文执行,执行模式" : "执行模式"));
199
+ lines.push(...this.optionLines(this.modes().map((m) => m.label), this.modeSelected, width));
200
+ break;
201
+ case "revise":
202
+ lines.push(...this.reviseLines(width, compact));
203
+ break;
204
+ case "editing":
205
+ push(this.host.theme.fg("dim", `正在外部编辑器里编辑${this.host.theme.glyphs.ellipsis}`));
206
+ break;
207
+ }
208
+ blank();
209
+ lines.push(this.host.theme.fg("dim", this.hint(compact)));
210
+ return lines.map((line) => truncateToWidth(line, width));
211
+ }
212
+ /** 版本、步数、文件、标题与前几步。 */
213
+ summary() {
214
+ const { theme } = this.host;
215
+ const plan = this.input.plan;
216
+ const sep = theme.fg("dim", " · ");
217
+ const head = [`计划 v${plan.version}`, `${plan.steps.length} 步`];
218
+ if (plan.filePath !== undefined)
219
+ head.push(this.host.displayPath?.(plan.filePath) ?? plan.filePath);
220
+ const out = [theme.fg("muted", head.join(sep))];
221
+ out.push(theme.bold(planTitle({ markdown: this.edited ?? plan.markdown })));
222
+ if (this.edited !== undefined) {
223
+ out.push(theme.fg("warning", "已在编辑器里修改:批准时以修改后的计划执行"));
224
+ return out;
225
+ }
226
+ for (const step of plan.steps.slice(0, PLAN_DIALOG_STEPS))
227
+ out.push(` ${theme.fg("dim", step.id)} ${step.text}`);
228
+ const hidden = plan.steps.length - PLAN_DIALOG_STEPS;
229
+ if (hidden > 0)
230
+ out.push(theme.fg("dim", ` ${theme.glyphs.ellipsis} 另 ${hidden} 步(/plan 查看全部)`));
231
+ return out;
232
+ }
233
+ optionLines(labels, selected, width) {
234
+ const { theme } = this.host;
235
+ const g = theme.glyphs;
236
+ return labels.map((label, i) => {
237
+ const on = i === selected;
238
+ const text = `${on ? g.prompt : " "} ${i + 1}. ${label}`;
239
+ const line = padToWidth(truncateToWidth(on ? theme.fg("accent", theme.bold(text)) : text, width), width);
240
+ return on ? theme.bg("selection", line) : line;
241
+ });
242
+ }
243
+ reviseLines(width, compact) {
244
+ const { theme } = this.host;
245
+ const g = theme.glyphs;
246
+ const out = [theme.bold(compact ? "修改意见" : "修改意见(留在 Plan 模式,模型据此重写计划)")];
247
+ const cursor = "\x1b[7m \x1b[27m";
248
+ const text = this.feedback.replace(/\n/g, " ⏎ ");
249
+ const body = `${theme.fg("user", g.prompt)} ${text}${cursor}`;
250
+ out.push(...wrapTextWithAnsi(body, width));
251
+ return out;
252
+ }
253
+ hint(compact) {
254
+ const g = this.host.theme.glyphs;
255
+ const arrows = g.arrowUp + g.arrowDown;
256
+ const edit = this.host.editExternal !== undefined;
257
+ switch (this.stage) {
258
+ case "main":
259
+ return compact
260
+ ? `${arrows} Enter${edit ? " · e 编辑" : ""} · Esc 留在 Plan`
261
+ : `${arrows} 选择 · Enter 确认${edit ? " · e 编辑计划" : ""} · Esc 留在 Plan`;
262
+ case "mode":
263
+ return compact ? `${arrows} Enter · Esc 返回` : `${arrows} 选择 · Enter 确认 · Esc 返回`;
264
+ case "revise":
265
+ return compact
266
+ ? `Enter 发送${edit ? " · Ctrl+E 编辑器" : ""} · Esc 返回`
267
+ : `Enter 发送${edit ? " · Ctrl+E 外部编辑器" : ""} · Esc 返回`;
268
+ case "editing":
269
+ return "保存并关闭编辑器后回到这里";
270
+ }
271
+ }
272
+ invalidate() { }
273
+ }
274
+ /** 打开对话框,等用户选择。 */
275
+ export function openPlanDialog(host, input) {
276
+ return new Promise((resolve) => {
277
+ let handle;
278
+ let settled = false;
279
+ const dialog = new PlanDialog(input, host, (choice) => {
280
+ if (settled)
281
+ return;
282
+ settled = true;
283
+ handle?.hide();
284
+ host.onClose?.();
285
+ resolve(choice);
286
+ });
287
+ host.onOpen?.();
288
+ handle = host.showOverlay(new Box(dialog, { title: "计划待审批", theme: host.theme }));
289
+ });
290
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 交互界面的计划审批编排(docs/wave5-plan.md §6.1):把会话的计划审批交给对话框。[W5-U]
3
+ *
4
+ * - `attach(session)`:`planController(session).setAttendance("callback", …)`——计划提出后(会话空闲时)
5
+ * 打开审批框;同时关掉 W5-F 的文本回复审批与 `ama.plan_notice` 提示行(两者只在 `text` 时生效)。
6
+ * resume 回来已有待审批的计划时只提示一行(`/plan` 打开审批框)。
7
+ * - 选择 → `controller.respond()`:批准(指定执行模式,编辑过则带 `editedMarkdown`)、继续修改(意见作为
8
+ * 普通用户消息)、放弃(4 退出 Plan 模式;Esc 留在 Plan);「新上下文执行」先新建会话、`adopt(plan)`、
9
+ * 切执行模式,再发 `freshPrompt`。
10
+ */
11
+ import type { AgentSession, PlanData } from "../../agent/types.js";
12
+ import type { SwitchRequest } from "../../cli/compose-session.js";
13
+ import type { NoticeLevel } from "./message-view.js";
14
+ import { openPlanDialog, type PlanChoice, type PlanDialogHost } from "./plan-dialog.js";
15
+ export interface PlanFlowDeps {
16
+ dialog: PlanDialogHost;
17
+ switchSession(request: SwitchRequest): Promise<AgentSession>;
18
+ notice(level: NoticeLevel, text: string): void;
19
+ /** 在当前会话发一条提示(新上下文执行的首条消息)。 */
20
+ prompt(text: string): void;
21
+ /** 测试注入:代替真实对话框。 */
22
+ open?(dialog: PlanDialogHost, input: Parameters<typeof openPlanDialog>[1]): Promise<PlanChoice>;
23
+ }
24
+ export declare class PlanFlow {
25
+ private readonly deps;
26
+ private opened;
27
+ constructor(deps: PlanFlowDeps);
28
+ /** 接管会话的计划审批(每次切换会话后调用)。 */
29
+ attach(session: AgentSession): void;
30
+ get isOpen(): boolean;
31
+ /** 打开审批框并执行选择(同一计划同时只开一个)。 */
32
+ ask(session: AgentSession, plan: PlanData): Promise<void>;
33
+ private apply;
34
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * 交互界面的计划审批编排(docs/wave5-plan.md §6.1):把会话的计划审批交给对话框。[W5-U]
3
+ *
4
+ * - `attach(session)`:`planController(session).setAttendance("callback", …)`——计划提出后(会话空闲时)
5
+ * 打开审批框;同时关掉 W5-F 的文本回复审批与 `ama.plan_notice` 提示行(两者只在 `text` 时生效)。
6
+ * resume 回来已有待审批的计划时只提示一行(`/plan` 打开审批框)。
7
+ * - 选择 → `controller.respond()`:批准(指定执行模式,编辑过则带 `editedMarkdown`)、继续修改(意见作为
8
+ * 普通用户消息)、放弃(4 退出 Plan 模式;Esc 留在 Plan);「新上下文执行」先新建会话、`adopt(plan)`、
9
+ * 切执行模式,再发 `freshPrompt`。
10
+ */
11
+ import { permissionModeLabel } from "../../permissions/modes.js";
12
+ import { planController } from "../../plan/controller.js";
13
+ import { executionMode } from "../../plan/store.js";
14
+ import { approveFresh } from "./plan-command.js";
15
+ import { openPlanDialog } from "./plan-dialog.js";
16
+ export class PlanFlow {
17
+ deps;
18
+ opened;
19
+ constructor(deps) {
20
+ this.deps = deps;
21
+ }
22
+ /** 接管会话的计划审批(每次切换会话后调用)。 */
23
+ attach(session) {
24
+ const controller = planController(session);
25
+ if (controller === undefined)
26
+ return;
27
+ controller.setAttendance("callback", async (plan) => {
28
+ await this.ask(session, plan);
29
+ return undefined;
30
+ });
31
+ const pending = controller.pending();
32
+ if (pending !== undefined)
33
+ this.deps.notice("info", `计划 v${pending.version} 待审批:/plan 打开审批框`);
34
+ }
35
+ get isOpen() {
36
+ return this.opened !== undefined;
37
+ }
38
+ /** 打开审批框并执行选择(同一计划同时只开一个)。 */
39
+ async ask(session, plan) {
40
+ const controller = planController(session);
41
+ if (controller === undefined || this.opened !== undefined)
42
+ return;
43
+ this.opened = plan.id;
44
+ try {
45
+ const input = { plan, preMode: executionMode(undefined, controller.prePlanMode()) };
46
+ const choice = await (this.deps.open ?? openPlanDialog)(this.deps.dialog, input);
47
+ await this.apply(session, plan, choice);
48
+ }
49
+ catch (error) {
50
+ this.deps.notice("error", error instanceof Error ? error.message : String(error));
51
+ }
52
+ finally {
53
+ this.opened = undefined;
54
+ }
55
+ }
56
+ async apply(session, plan, choice) {
57
+ const controller = planController(session);
58
+ if (controller === undefined)
59
+ return;
60
+ switch (choice.decision) {
61
+ case "approve": {
62
+ const result = await controller.respond({
63
+ planId: plan.id,
64
+ decision: "approve",
65
+ mode: choice.mode,
66
+ ...(choice.editedMarkdown !== undefined ? { editedMarkdown: choice.editedMarkdown } : {}),
67
+ });
68
+ const mode = permissionModeLabel(result.mode ?? choice.mode);
69
+ this.deps.notice("info", `已批准计划 v${result.plan.version},以 ${mode} 执行`);
70
+ return;
71
+ }
72
+ case "approve_fresh": {
73
+ const fresh = await approveFresh(controller, plan, choice.mode, { switchSession: (request) => this.deps.switchSession(request) }, choice.editedMarkdown);
74
+ this.deps.notice("info", `已批准计划 v${fresh.plan.version},在新会话 ${fresh.session.state.sessionId.slice(0, 8)} 以 ${permissionModeLabel(choice.mode)} 执行`);
75
+ this.deps.prompt(fresh.prompt);
76
+ return;
77
+ }
78
+ case "revise":
79
+ await controller.respond({
80
+ planId: plan.id,
81
+ decision: "revise",
82
+ feedback: choice.feedback,
83
+ });
84
+ return;
85
+ case "reject": {
86
+ const pre = executionMode(undefined, controller.prePlanMode());
87
+ await controller.respond({ planId: plan.id, decision: "reject" });
88
+ if (choice.exit) {
89
+ session.setPermissionMode(pre);
90
+ this.deps.notice("info", `已放弃计划 v${plan.version},回到 ${permissionModeLabel(pre)}`);
91
+ }
92
+ else
93
+ this.deps.notice("info", `已放弃计划 v${plan.version}(仍在 Plan 模式,/plan 查看)`);
94
+ return;
95
+ }
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `/rewind` 的带参数形式(rewind-plan §4,line 模式与交互模式共用;交互模式无参数时开列表)。[RW-C]
3
+ *
4
+ * - `/rewind`:列出回滚点,编号从旧到新(1 = 最早)。
5
+ * - `/rewind <n> [both|conversation|code] [overwrite]`:缺省 both(没有检查点时 conversation);
6
+ * `overwrite` 覆盖冲突文件(`onConflict: "overwrite"`)。
7
+ * - `/rewind <n> summarize-from|summarize-up-to [说明]`。
8
+ * 错误码换成中文说明后照原 code 抛出。
9
+ */
10
+ import type { AgentSession, RewindDraftText } from "../../agent/types.js";
11
+ import type { RewindPoint } from "../../checkpoints/types.js";
12
+ import type { RewindAction } from "./rewind-panel.js";
13
+ export declare const REWIND_USAGE = "\u7528\u6CD5\uFF1A/rewind\uFF0C/rewind <n> [both|conversation|code] [overwrite]\uFF0C/rewind <n> summarize-from|summarize-up-to [\u8BF4\u660E]";
14
+ export interface RewindArgs {
15
+ /** 1 起的编号。 */
16
+ index: number;
17
+ action?: RewindAction;
18
+ instructions?: string;
19
+ overwrite?: boolean;
20
+ }
21
+ export declare function parseRewindArgs(args: string): RewindArgs;
22
+ export declare function rewindListText(points: readonly RewindPoint[], now: number): string;
23
+ export interface RewindCommandResult {
24
+ message: string;
25
+ /** 对话变了:原消息草稿(界面回填输入框)。 */
26
+ draft?: RewindDraftText;
27
+ /** 消息区要重画。 */
28
+ reload?: boolean;
29
+ }
30
+ /** 执行 `/rewind <args>`;args 为空时只列出回滚点。 */
31
+ export declare function rewindCommand(session: AgentSession, args: string, now?: number): Promise<RewindCommandResult>;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * `/rewind` 的带参数形式(rewind-plan §4,line 模式与交互模式共用;交互模式无参数时开列表)。[RW-C]
3
+ *
4
+ * - `/rewind`:列出回滚点,编号从旧到新(1 = 最早)。
5
+ * - `/rewind <n> [both|conversation|code] [overwrite]`:缺省 both(没有检查点时 conversation);
6
+ * `overwrite` 覆盖冲突文件(`onConflict: "overwrite"`)。
7
+ * - `/rewind <n> summarize-from|summarize-up-to [说明]`。
8
+ * 错误码换成中文说明后照原 code 抛出。
9
+ */
10
+ import { AmaError } from "../../errors.js";
11
+ import { oneLine, rewindErrorText, rewindResultLines } from "./rewind-text.js";
12
+ import { relativeTime } from "./startup-ui.js";
13
+ const FORMS = "/rewind <n> [both|conversation|code] [overwrite],/rewind <n> summarize-from|summarize-up-to [说明]";
14
+ export const REWIND_USAGE = `用法:/rewind,${FORMS}`;
15
+ const ACTIONS = [
16
+ "both",
17
+ "conversation",
18
+ "code",
19
+ "summarize-from",
20
+ "summarize-up-to",
21
+ ];
22
+ export function parseRewindArgs(args) {
23
+ const m = /^(\d+)(?:\s+(\S+))?(?:\s+([\s\S]*))?$/.exec(args.trim());
24
+ const index = m === null ? NaN : Number(m[1]);
25
+ if (m === null || !Number.isInteger(index) || index < 1) {
26
+ throw new AmaError("invalid_arguments", REWIND_USAGE);
27
+ }
28
+ const out = { index };
29
+ const action = m[2];
30
+ const rest = (m[3] ?? "").trim();
31
+ if (action === undefined)
32
+ return out;
33
+ if (!ACTIONS.includes(action)) {
34
+ throw new AmaError("invalid_arguments", REWIND_USAGE);
35
+ }
36
+ out.action = action;
37
+ if (action === "summarize-from" || action === "summarize-up-to") {
38
+ if (rest !== "")
39
+ out.instructions = rest;
40
+ }
41
+ else if (rest === "overwrite" && action !== "conversation")
42
+ out.overwrite = true;
43
+ else if (rest !== "")
44
+ throw new AmaError("invalid_arguments", REWIND_USAGE);
45
+ return out;
46
+ }
47
+ export function rewindListText(points, now) {
48
+ if (points.length === 0)
49
+ return "还没有可回滚的消息";
50
+ const lines = points.map((point, i) => {
51
+ const time = relativeTime(new Date(point.timestamp).toISOString(), now);
52
+ const only = point.hasCheckpoint ? "" : " [仅对话]";
53
+ return ` ${i + 1}. ${time} ${oneLine(point.text, 60) || "(空)"}${only}`;
54
+ });
55
+ return [`回滚点(${FORMS}):`, ...lines].join("\n");
56
+ }
57
+ /** 执行 `/rewind <args>`;args 为空时只列出回滚点。 */
58
+ export async function rewindCommand(session, args, now = Date.now()) {
59
+ const points = session.rewindPoints();
60
+ if (args.trim() === "")
61
+ return { message: rewindListText(points, now) };
62
+ const parsed = parseRewindArgs(args);
63
+ const point = points[parsed.index - 1];
64
+ if (point === undefined) {
65
+ throw new AmaError("invalid_arguments", `没有第 ${parsed.index} 个回滚点(共 ${points.length} 个,/rewind 查看)`);
66
+ }
67
+ const action = parsed.action ?? (point.hasCheckpoint ? "both" : "conversation");
68
+ try {
69
+ if (action === "summarize-from") {
70
+ const result = await session.summarizeFrom(point.entryId, parsed.instructions);
71
+ return {
72
+ message: `已从这里分叉,离开的部分写成了摘要;原消息:${oneLine(result.draft.text, 80)}`,
73
+ draft: result.draft,
74
+ reload: true,
75
+ };
76
+ }
77
+ if (action === "summarize-up-to") {
78
+ const result = await session.summarizeUpTo(point.entryId, parsed.instructions);
79
+ const after = result.tokensAfter !== undefined ? ` → ${result.tokensAfter}` : "";
80
+ return { message: `已摘要到这里:${result.tokensBefore}${after} token` };
81
+ }
82
+ const result = await session.rewind({
83
+ entryId: point.entryId,
84
+ mode: action,
85
+ ...(parsed.overwrite === true ? { onConflict: "overwrite" } : {}),
86
+ });
87
+ if (action === "conversation")
88
+ delete result.gitHint;
89
+ const draft = result.conversation?.draft;
90
+ const lines = rewindResultLines(result, {
91
+ overwrite: parsed.overwrite === true,
92
+ ...(draft !== undefined
93
+ ? { conversation: `对话已回到这条消息之前;原消息:${oneLine(draft.text, 80)}` }
94
+ : {}),
95
+ });
96
+ return draft !== undefined
97
+ ? { message: lines.join("\n"), draft, reload: true }
98
+ : { message: lines.join("\n") };
99
+ }
100
+ catch (error) {
101
+ if (error instanceof AmaError) {
102
+ throw new AmaError(error.code, rewindErrorText(error), { cause: error });
103
+ }
104
+ throw error;
105
+ }
106
+ }