@armadra/agent 0.3.0 → 0.5.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 (527) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/README.md +263 -95
  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/retry.d.ts +1 -1
  17. package/dist/agent/retry.js +2 -1
  18. package/dist/agent/session-cache.d.ts +5 -0
  19. package/dist/agent/session-cache.js +18 -2
  20. package/dist/agent/session-classifier.d.ts +18 -0
  21. package/dist/agent/session-classifier.js +105 -0
  22. package/dist/agent/session-compaction.d.ts +35 -6
  23. package/dist/agent/session-compaction.js +157 -31
  24. package/dist/agent/session-core.d.ts +40 -1
  25. package/dist/agent/session-extensions.d.ts +61 -0
  26. package/dist/agent/session-extensions.js +129 -0
  27. package/dist/agent/session-images.d.ts +23 -0
  28. package/dist/agent/session-images.js +97 -0
  29. package/dist/agent/session-plan.d.ts +21 -0
  30. package/dist/agent/session-plan.js +524 -0
  31. package/dist/agent/session-rewind.d.ts +81 -0
  32. package/dist/agent/session-rewind.js +354 -0
  33. package/dist/agent/session-run.d.ts +28 -1
  34. package/dist/agent/session-run.js +157 -6
  35. package/dist/agent/session-settings.d.ts +49 -0
  36. package/dist/agent/session-settings.js +95 -0
  37. package/dist/agent/session-subagent.d.ts +36 -24
  38. package/dist/agent/session-subagent.js +259 -129
  39. package/dist/agent/session-sync.d.ts +10 -3
  40. package/dist/agent/session-sync.js +37 -8
  41. package/dist/agent/session-telemetry.d.ts +39 -0
  42. package/dist/agent/session-telemetry.js +231 -0
  43. package/dist/agent/session-tools.js +63 -3
  44. package/dist/agent/session.d.ts +33 -29
  45. package/dist/agent/session.js +91 -126
  46. package/dist/agent/subagent-registry.d.ts +91 -0
  47. package/dist/agent/subagent-registry.js +494 -0
  48. package/dist/agent/system-prompt.d.ts +6 -3
  49. package/dist/agent/system-prompt.js +7 -2
  50. package/dist/agent/tool-runner.d.ts +8 -1
  51. package/dist/agent/tool-runner.js +72 -6
  52. package/dist/agent/types-w5.d.ts +192 -0
  53. package/dist/agent/types-w5.js +10 -0
  54. package/dist/agent/types.d.ts +55 -4
  55. package/dist/agent/types.js +2 -0
  56. package/dist/agent/worktree.d.ts +36 -0
  57. package/dist/agent/worktree.js +86 -0
  58. package/dist/agents/builtin.d.ts +14 -0
  59. package/dist/agents/builtin.js +39 -0
  60. package/dist/agents/catalog.d.ts +43 -0
  61. package/dist/agents/catalog.js +82 -0
  62. package/dist/agents/discover.d.ts +35 -0
  63. package/dist/agents/discover.js +83 -0
  64. package/dist/agents/external.d.ts +82 -0
  65. package/dist/agents/external.js +326 -0
  66. package/dist/agents/parse.d.ts +18 -0
  67. package/dist/agents/parse.js +116 -0
  68. package/dist/agents/result.d.ts +32 -0
  69. package/dist/agents/result.js +67 -0
  70. package/dist/agents/task-control.d.ts +17 -0
  71. package/dist/agents/task-control.js +17 -0
  72. package/dist/agents/task-record.d.ts +78 -0
  73. package/dist/agents/task-record.js +141 -0
  74. package/dist/agents/types.d.ts +46 -0
  75. package/dist/agents/types.js +8 -0
  76. package/dist/ai/apis/anthropic-compat.d.ts +36 -0
  77. package/dist/ai/apis/anthropic-compat.js +92 -0
  78. package/dist/ai/apis/anthropic-messages.js +3 -2
  79. package/dist/ai/apis/anthropic-request.d.ts +7 -6
  80. package/dist/ai/apis/anthropic-request.js +10 -28
  81. package/dist/ai/apis/cache-params.d.ts +11 -2
  82. package/dist/ai/apis/cache-params.js +25 -6
  83. package/dist/ai/apis/google-generative-ai.js +3 -2
  84. package/dist/ai/apis/openai-compat.d.ts +4 -1
  85. package/dist/ai/apis/openai-compat.js +8 -1
  86. package/dist/ai/apis/openai-completions.js +3 -2
  87. package/dist/ai/apis/openai-responses.js +3 -2
  88. package/dist/ai/http.d.ts +28 -6
  89. package/dist/ai/http.js +41 -8
  90. package/dist/ai/image-limits.d.ts +45 -0
  91. package/dist/ai/image-limits.js +68 -0
  92. package/dist/ai/providers/builtin.d.ts +18 -6
  93. package/dist/ai/providers/builtin.js +135 -6
  94. package/dist/ai/providers/catalog-data.js +17 -13
  95. package/dist/ai/providers/catalog.d.ts +60 -7
  96. package/dist/ai/providers/catalog.js +197 -38
  97. package/dist/ai/providers/channels.d.ts +33 -3
  98. package/dist/ai/providers/channels.js +108 -7
  99. package/dist/ai/providers/enrich.d.ts +6 -3
  100. package/dist/ai/providers/enrich.js +19 -4
  101. package/dist/ai/providers/models-dev-cache.d.ts +28 -24
  102. package/dist/ai/providers/models-dev-cache.js +92 -78
  103. package/dist/ai/providers/models-dev-data.d.ts +7 -0
  104. package/dist/ai/providers/models-dev-data.js +32 -0
  105. package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
  106. package/dist/ai/providers/models-dev-snapshot.js +137 -0
  107. package/dist/ai/providers/models-dev.d.ts +51 -10
  108. package/dist/ai/providers/models-dev.js +132 -39
  109. package/dist/ai/providers/registry.d.ts +28 -11
  110. package/dist/ai/providers/registry.js +112 -65
  111. package/dist/ai/providers/suggest.d.ts +18 -0
  112. package/dist/ai/providers/suggest.js +72 -0
  113. package/dist/ai/sse.d.ts +6 -2
  114. package/dist/ai/sse.js +22 -2
  115. package/dist/ai/types.d.ts +37 -4
  116. package/dist/ai/types.js +5 -0
  117. package/dist/bundle/ama.cjs +41979 -21147
  118. package/dist/checkpoints/backend.d.ts +61 -0
  119. package/dist/checkpoints/backend.js +135 -0
  120. package/dist/checkpoints/blobs.d.ts +60 -0
  121. package/dist/checkpoints/blobs.js +203 -0
  122. package/dist/checkpoints/gc.d.ts +47 -0
  123. package/dist/checkpoints/gc.js +144 -0
  124. package/dist/checkpoints/git-head.d.ts +15 -0
  125. package/dist/checkpoints/git-head.js +89 -0
  126. package/dist/checkpoints/index.d.ts +17 -0
  127. package/dist/checkpoints/index.js +17 -0
  128. package/dist/checkpoints/replay.d.ts +48 -0
  129. package/dist/checkpoints/replay.js +154 -0
  130. package/dist/checkpoints/restore.d.ts +86 -0
  131. package/dist/checkpoints/restore.js +263 -0
  132. package/dist/checkpoints/settings.d.ts +14 -0
  133. package/dist/checkpoints/settings.js +23 -0
  134. package/dist/checkpoints/shadow-git.d.ts +108 -0
  135. package/dist/checkpoints/shadow-git.js +491 -0
  136. package/dist/checkpoints/shadow-restore.d.ts +25 -0
  137. package/dist/checkpoints/shadow-restore.js +128 -0
  138. package/dist/checkpoints/tracker.d.ts +64 -0
  139. package/dist/checkpoints/tracker.js +192 -0
  140. package/dist/checkpoints/types.d.ts +99 -0
  141. package/dist/checkpoints/types.js +12 -0
  142. package/dist/cli/args.d.ts +26 -7
  143. package/dist/cli/args.js +75 -82
  144. package/dist/cli/bootstrap.js +40 -4
  145. package/dist/cli/codemode-notice.d.ts +21 -0
  146. package/dist/cli/codemode-notice.js +56 -0
  147. package/dist/cli/compose-agents.d.ts +27 -0
  148. package/dist/cli/compose-agents.js +111 -0
  149. package/dist/cli/compose-extensions.d.ts +29 -0
  150. package/dist/cli/compose-extensions.js +44 -0
  151. package/dist/cli/compose-session.d.ts +8 -0
  152. package/dist/cli/compose-session.js +76 -2
  153. package/dist/cli/compose-store.d.ts +1 -1
  154. package/dist/cli/compose-store.js +3 -1
  155. package/dist/cli/compose.d.ts +17 -4
  156. package/dist/cli/compose.js +60 -14
  157. package/dist/cli/default-model.d.ts +38 -1
  158. package/dist/cli/default-model.js +96 -9
  159. package/dist/cli/deps.d.ts +42 -0
  160. package/dist/cli/exit-codes.d.ts +12 -0
  161. package/dist/cli/exit-codes.js +15 -0
  162. package/dist/cli/fake-visibility.d.ts +13 -0
  163. package/dist/cli/fake-visibility.js +26 -0
  164. package/dist/cli/from-prompt.d.ts +18 -0
  165. package/dist/cli/from-prompt.js +49 -0
  166. package/dist/cli/help-text.d.ts +4 -0
  167. package/dist/cli/help-text.js +102 -0
  168. package/dist/cli/main.d.ts +9 -2
  169. package/dist/cli/main.js +77 -3
  170. package/dist/cli/proxy.d.ts +51 -0
  171. package/dist/cli/proxy.js +135 -0
  172. package/dist/cli/startup-screen.d.ts +29 -0
  173. package/dist/cli/startup-screen.js +51 -2
  174. package/dist/cli/startup-steps.d.ts +1 -1
  175. package/dist/cli/startup-steps.js +21 -13
  176. package/dist/cli/subcommands/config.d.ts +22 -3
  177. package/dist/cli/subcommands/config.js +119 -21
  178. package/dist/cli/subcommands/context.js +4 -1
  179. package/dist/cli/subcommands/doctor.js +33 -1
  180. package/dist/cli/subcommands/init.js +2 -1
  181. package/dist/cli/subcommands/models-discover.d.ts +15 -9
  182. package/dist/cli/subcommands/models-discover.js +58 -52
  183. package/dist/cli/subcommands/models.d.ts +2 -0
  184. package/dist/cli/subcommands/models.js +33 -14
  185. package/dist/cli/subcommands/probe-runner.d.ts +96 -0
  186. package/dist/cli/subcommands/probe-runner.js +264 -0
  187. package/dist/cli/subcommands/providers-probe.d.ts +34 -0
  188. package/dist/cli/subcommands/providers-probe.js +87 -0
  189. package/dist/cli/subcommands/providers.d.ts +3 -2
  190. package/dist/cli/subcommands/providers.js +53 -51
  191. package/dist/cli/subcommands/sessions-export.d.ts +10 -0
  192. package/dist/cli/subcommands/sessions-export.js +59 -0
  193. package/dist/cli/subcommands/sessions-search.d.ts +13 -0
  194. package/dist/cli/subcommands/sessions-search.js +103 -0
  195. package/dist/cli/subcommands/sessions.d.ts +6 -3
  196. package/dist/cli/subcommands/sessions.js +58 -3
  197. package/dist/cli/subcommands/stats.d.ts +17 -0
  198. package/dist/cli/subcommands/stats.js +198 -0
  199. package/dist/cli/system-prompt-arg.d.ts +11 -0
  200. package/dist/cli/system-prompt-arg.js +34 -0
  201. package/dist/codemode/capability.d.ts +24 -7
  202. package/dist/codemode/capability.js +38 -10
  203. package/dist/codemode/host-side.d.ts +14 -0
  204. package/dist/codemode/host-side.js +24 -1
  205. package/dist/codemode/modes.d.ts +4 -11
  206. package/dist/codemode/modes.js +5 -27
  207. package/dist/codemode/tool.d.ts +18 -14
  208. package/dist/codemode/tool.js +76 -31
  209. package/dist/compaction/breaker.d.ts +25 -9
  210. package/dist/compaction/breaker.js +47 -17
  211. package/dist/compaction/estimate.d.ts +11 -3
  212. package/dist/compaction/estimate.js +64 -22
  213. package/dist/compaction/image-budget.d.ts +45 -0
  214. package/dist/compaction/image-budget.js +115 -0
  215. package/dist/compaction/post-compact.d.ts +38 -0
  216. package/dist/compaction/post-compact.js +152 -0
  217. package/dist/compaction/protect.d.ts +27 -0
  218. package/dist/compaction/protect.js +56 -0
  219. package/dist/compaction/prune-tier.d.ts +58 -12
  220. package/dist/compaction/prune-tier.js +120 -54
  221. package/dist/compaction/summarize-tier.d.ts +23 -4
  222. package/dist/compaction/summarize-tier.js +100 -29
  223. package/dist/config/checker.d.ts +28 -0
  224. package/dist/config/checker.js +97 -0
  225. package/dist/config/init.d.ts +6 -2
  226. package/dist/config/init.js +12 -5
  227. package/dist/config/json-schema.d.ts +1 -0
  228. package/dist/config/json-schema.js +98 -4
  229. package/dist/config/key-docs.d.ts +22 -0
  230. package/dist/config/key-docs.js +174 -0
  231. package/dist/config/merge.d.ts +12 -9
  232. package/dist/config/merge.js +102 -13
  233. package/dist/config/profile.d.ts +2 -0
  234. package/dist/config/profile.js +2 -0
  235. package/dist/config/schema-w5.d.ts +18 -0
  236. package/dist/config/schema-w5.js +109 -0
  237. package/dist/config/schema.d.ts +5 -9
  238. package/dist/config/schema.js +91 -118
  239. package/dist/config/types-w5.d.ts +118 -0
  240. package/dist/config/types-w5.js +20 -0
  241. package/dist/config/types.d.ts +84 -7
  242. package/dist/config/types.js +29 -1
  243. package/dist/drivers/acp/client.d.ts +57 -0
  244. package/dist/drivers/acp/client.js +160 -0
  245. package/dist/drivers/acp/driver.d.ts +31 -0
  246. package/dist/drivers/acp/driver.js +274 -0
  247. package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
  248. package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
  249. package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
  250. package/dist/drivers/acp/testing/fake-agent.js +211 -0
  251. package/dist/drivers/acp/types.d.ts +285 -0
  252. package/dist/drivers/acp/types.js +36 -0
  253. package/dist/drivers/agents.d.ts +58 -0
  254. package/dist/drivers/agents.js +142 -0
  255. package/dist/drivers/base.d.ts +35 -0
  256. package/dist/drivers/base.js +59 -0
  257. package/dist/drivers/catalog.d.ts +46 -0
  258. package/dist/drivers/catalog.js +167 -0
  259. package/dist/drivers/env.d.ts +20 -0
  260. package/dist/drivers/env.js +46 -0
  261. package/dist/drivers/host-runners.d.ts +18 -0
  262. package/dist/drivers/host-runners.js +45 -0
  263. package/dist/drivers/jsonrpc.d.ts +58 -0
  264. package/dist/drivers/jsonrpc.js +180 -0
  265. package/dist/drivers/native/claude-normalize.d.ts +46 -0
  266. package/dist/drivers/native/claude-normalize.js +106 -0
  267. package/dist/drivers/native/claude-stream.d.ts +29 -0
  268. package/dist/drivers/native/claude-stream.js +456 -0
  269. package/dist/drivers/native/codex-app-server.d.ts +26 -0
  270. package/dist/drivers/native/codex-app-server.js +407 -0
  271. package/dist/drivers/native/codex-normalize.d.ts +38 -0
  272. package/dist/drivers/native/codex-normalize.js +124 -0
  273. package/dist/drivers/native/oneshot.d.ts +28 -0
  274. package/dist/drivers/native/oneshot.js +312 -0
  275. package/dist/drivers/permissions.d.ts +40 -0
  276. package/dist/drivers/permissions.js +92 -0
  277. package/dist/drivers/pids.d.ts +32 -0
  278. package/dist/drivers/pids.js +93 -0
  279. package/dist/drivers/pool.d.ts +28 -0
  280. package/dist/drivers/pool.js +96 -0
  281. package/dist/drivers/probe.d.ts +47 -0
  282. package/dist/drivers/probe.js +172 -0
  283. package/dist/drivers/process.d.ts +48 -0
  284. package/dist/drivers/process.js +100 -0
  285. package/dist/drivers/runner.d.ts +61 -0
  286. package/dist/drivers/runner.js +388 -0
  287. package/dist/drivers/store.d.ts +49 -0
  288. package/dist/drivers/store.js +91 -0
  289. package/dist/drivers/turn.d.ts +41 -0
  290. package/dist/drivers/turn.js +99 -0
  291. package/dist/drivers/types.d.ts +122 -0
  292. package/dist/drivers/types.js +11 -0
  293. package/dist/git/info.d.ts +75 -0
  294. package/dist/git/info.js +191 -0
  295. package/dist/hooks/protocol.js +6 -1
  296. package/dist/hooks/types.d.ts +10 -1
  297. package/dist/hooks/types.js +2 -0
  298. package/dist/host/api-impl.d.ts +7 -0
  299. package/dist/host/api-impl.js +15 -0
  300. package/dist/host/types.d.ts +24 -2
  301. package/dist/host/types.js +4 -0
  302. package/dist/index.d.ts +3 -0
  303. package/dist/index.js +1 -0
  304. package/dist/modes/acp/acp-events.d.ts +46 -0
  305. package/dist/modes/acp/acp-events.js +233 -0
  306. package/dist/modes/acp/acp-mode.d.ts +17 -0
  307. package/dist/modes/acp/acp-mode.js +47 -0
  308. package/dist/modes/acp/acp-server.d.ts +79 -0
  309. package/dist/modes/acp/acp-server.js +315 -0
  310. package/dist/modes/commands-core.d.ts +7 -1
  311. package/dist/modes/commands-core.js +61 -5
  312. package/dist/modes/image-input.d.ts +12 -4
  313. package/dist/modes/image-input.js +22 -5
  314. package/dist/modes/interactive/agent-panels.d.ts +14 -0
  315. package/dist/modes/interactive/agent-panels.js +103 -0
  316. package/dist/modes/interactive/agent-ui.d.ts +73 -0
  317. package/dist/modes/interactive/agent-ui.js +234 -0
  318. package/dist/modes/interactive/approval-dialog.d.ts +40 -7
  319. package/dist/modes/interactive/approval-dialog.js +192 -35
  320. package/dist/modes/interactive/approval-merge.d.ts +41 -0
  321. package/dist/modes/interactive/approval-merge.js +89 -0
  322. package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
  323. package/dist/modes/interactive/clipboard-paste.js +28 -0
  324. package/dist/modes/interactive/commands.d.ts +20 -3
  325. package/dist/modes/interactive/commands.js +75 -16
  326. package/dist/modes/interactive/double-esc.d.ts +20 -0
  327. package/dist/modes/interactive/double-esc.js +34 -0
  328. package/dist/modes/interactive/event-notices.d.ts +32 -0
  329. package/dist/modes/interactive/event-notices.js +79 -0
  330. package/dist/modes/interactive/external-editor.d.ts +16 -0
  331. package/dist/modes/interactive/external-editor.js +39 -0
  332. package/dist/modes/interactive/interactive-mode.d.ts +16 -2
  333. package/dist/modes/interactive/interactive-mode.js +184 -202
  334. package/dist/modes/interactive/key-dispatch.d.ts +18 -2
  335. package/dist/modes/interactive/key-dispatch.js +53 -6
  336. package/dist/modes/interactive/line/line-mode.d.ts +3 -1
  337. package/dist/modes/interactive/line/line-mode.js +28 -9
  338. package/dist/modes/interactive/line/line-render.d.ts +6 -1
  339. package/dist/modes/interactive/line/line-render.js +66 -8
  340. package/dist/modes/interactive/message-view.d.ts +49 -10
  341. package/dist/modes/interactive/message-view.js +262 -46
  342. package/dist/modes/interactive/panels.d.ts +35 -0
  343. package/dist/modes/interactive/panels.js +157 -0
  344. package/dist/modes/interactive/pickers.d.ts +23 -2
  345. package/dist/modes/interactive/pickers.js +48 -15
  346. package/dist/modes/interactive/plan-command.d.ts +40 -0
  347. package/dist/modes/interactive/plan-command.js +129 -0
  348. package/dist/modes/interactive/plan-dialog.d.ts +98 -0
  349. package/dist/modes/interactive/plan-dialog.js +290 -0
  350. package/dist/modes/interactive/plan-flow.d.ts +34 -0
  351. package/dist/modes/interactive/plan-flow.js +98 -0
  352. package/dist/modes/interactive/rewind-command.d.ts +31 -0
  353. package/dist/modes/interactive/rewind-command.js +106 -0
  354. package/dist/modes/interactive/rewind-flow.d.ts +37 -0
  355. package/dist/modes/interactive/rewind-flow.js +151 -0
  356. package/dist/modes/interactive/rewind-list.d.ts +36 -0
  357. package/dist/modes/interactive/rewind-list.js +123 -0
  358. package/dist/modes/interactive/rewind-panel.d.ts +77 -0
  359. package/dist/modes/interactive/rewind-panel.js +309 -0
  360. package/dist/modes/interactive/rewind-text.d.ts +40 -0
  361. package/dist/modes/interactive/rewind-text.js +139 -0
  362. package/dist/modes/interactive/run-indicator.d.ts +51 -0
  363. package/dist/modes/interactive/run-indicator.js +189 -0
  364. package/dist/modes/interactive/session-events.d.ts +24 -0
  365. package/dist/modes/interactive/session-events.js +96 -0
  366. package/dist/modes/interactive/startup-header.d.ts +40 -0
  367. package/dist/modes/interactive/startup-header.js +169 -0
  368. package/dist/modes/interactive/status-area.d.ts +73 -0
  369. package/dist/modes/interactive/status-area.js +190 -0
  370. package/dist/modes/interactive/status-bar.d.ts +107 -16
  371. package/dist/modes/interactive/status-bar.js +306 -81
  372. package/dist/modes/interactive/status-line.d.ts +33 -0
  373. package/dist/modes/interactive/status-line.js +113 -0
  374. package/dist/modes/interactive/subagent-view.d.ts +56 -0
  375. package/dist/modes/interactive/subagent-view.js +154 -0
  376. package/dist/modes/interactive/tasks-report.d.ts +27 -0
  377. package/dist/modes/interactive/tasks-report.js +114 -0
  378. package/dist/modes/interactive/tool-summary.d.ts +46 -0
  379. package/dist/modes/interactive/tool-summary.js +218 -0
  380. package/dist/modes/interactive/tool-view.d.ts +58 -15
  381. package/dist/modes/interactive/tool-view.js +233 -145
  382. package/dist/modes/print/print-mode.d.ts +40 -4
  383. package/dist/modes/print/print-mode.js +161 -8
  384. package/dist/modes/rpc/commands.d.ts +9 -0
  385. package/dist/modes/rpc/commands.js +49 -0
  386. package/dist/modes/rpc/rpc-mode.js +7 -1
  387. package/dist/modes/session-report.d.ts +11 -0
  388. package/dist/modes/session-report.js +48 -1
  389. package/dist/permissions/auto-safe.d.ts +65 -0
  390. package/dist/permissions/auto-safe.js +547 -0
  391. package/dist/permissions/classifier.d.ts +68 -0
  392. package/dist/permissions/classifier.js +186 -0
  393. package/dist/permissions/dangerous.d.ts +5 -0
  394. package/dist/permissions/dangerous.js +1 -1
  395. package/dist/permissions/modes.d.ts +30 -0
  396. package/dist/permissions/modes.js +78 -0
  397. package/dist/permissions/pipeline.d.ts +72 -6
  398. package/dist/permissions/pipeline.js +306 -11
  399. package/dist/permissions/protected.d.ts +19 -0
  400. package/dist/permissions/protected.js +74 -0
  401. package/dist/permissions/readonly-bash.d.ts +30 -0
  402. package/dist/permissions/readonly-bash.js +118 -0
  403. package/dist/permissions/rules.js +3 -0
  404. package/dist/permissions/types.d.ts +92 -3
  405. package/dist/permissions/types.js +3 -0
  406. package/dist/plan/compose.d.ts +9 -0
  407. package/dist/plan/compose.js +19 -0
  408. package/dist/plan/controller.d.ts +71 -0
  409. package/dist/plan/controller.js +27 -0
  410. package/dist/plan/done-markers.d.ts +17 -0
  411. package/dist/plan/done-markers.js +51 -0
  412. package/dist/plan/extract.d.ts +29 -0
  413. package/dist/plan/extract.js +160 -0
  414. package/dist/plan/prompts.d.ts +36 -0
  415. package/dist/plan/prompts.js +89 -0
  416. package/dist/plan/store.d.ts +37 -0
  417. package/dist/plan/store.js +90 -0
  418. package/dist/rpc.d.ts +58 -2
  419. package/dist/rpc.js +7 -0
  420. package/dist/sandbox/bash.d.ts +74 -0
  421. package/dist/sandbox/bash.js +126 -0
  422. package/dist/sandbox/detect.d.ts +48 -0
  423. package/dist/sandbox/detect.js +149 -0
  424. package/dist/sandbox/index.d.ts +5 -0
  425. package/dist/sandbox/index.js +5 -0
  426. package/dist/sandbox/profile.d.ts +33 -0
  427. package/dist/sandbox/profile.js +76 -0
  428. package/dist/sandbox/wrap.d.ts +29 -0
  429. package/dist/sandbox/wrap.js +117 -0
  430. package/dist/sdk.d.ts +42 -5
  431. package/dist/sdk.js +34 -4
  432. package/dist/session/export.d.ts +32 -0
  433. package/dist/session/export.js +187 -0
  434. package/dist/session/redact.d.ts +15 -0
  435. package/dist/session/redact.js +55 -0
  436. package/dist/session/reuse.d.ts +33 -0
  437. package/dist/session/reuse.js +86 -0
  438. package/dist/session/scan.d.ts +34 -0
  439. package/dist/session/scan.js +140 -0
  440. package/dist/session/search.d.ts +52 -0
  441. package/dist/session/search.js +211 -0
  442. package/dist/session/stats-aggregate.d.ts +63 -0
  443. package/dist/session/stats-aggregate.js +163 -0
  444. package/dist/session/stats-index.d.ts +26 -0
  445. package/dist/session/stats-index.js +91 -0
  446. package/dist/session/stats-scan.d.ts +54 -0
  447. package/dist/session/stats-scan.js +236 -0
  448. package/dist/session/types.d.ts +3 -1
  449. package/dist/session/types.js +1 -0
  450. package/dist/skills/builtin.d.ts +31 -0
  451. package/dist/skills/builtin.js +109 -0
  452. package/dist/skills/discover.d.ts +2 -1
  453. package/dist/skills/index-prompt.js +5 -8
  454. package/dist/tools/background-jobs.d.ts +71 -0
  455. package/dist/tools/background-jobs.js +198 -0
  456. package/dist/tools/bash.d.ts +53 -1
  457. package/dist/tools/bash.js +158 -7
  458. package/dist/tools/clipboard-image.d.ts +44 -0
  459. package/dist/tools/clipboard-image.js +148 -0
  460. package/dist/tools/edit.d.ts +2 -0
  461. package/dist/tools/edit.js +18 -3
  462. package/dist/tools/image-file.d.ts +38 -3
  463. package/dist/tools/image-file.js +81 -10
  464. package/dist/tools/image-resize.d.ts +58 -0
  465. package/dist/tools/image-resize.js +97 -0
  466. package/dist/tools/presets.d.ts +40 -8
  467. package/dist/tools/presets.js +65 -19
  468. package/dist/tools/read.d.ts +5 -2
  469. package/dist/tools/read.js +13 -10
  470. package/dist/tools/registry.d.ts +7 -1
  471. package/dist/tools/registry.js +27 -4
  472. package/dist/tools/task-ctl.d.ts +22 -0
  473. package/dist/tools/task-ctl.js +116 -0
  474. package/dist/tools/task.d.ts +22 -10
  475. package/dist/tools/task.js +66 -26
  476. package/dist/tools/todo.d.ts +22 -2
  477. package/dist/tools/todo.js +58 -14
  478. package/dist/tools/truncate.d.ts +15 -0
  479. package/dist/tools/truncate.js +25 -0
  480. package/dist/tools/types.d.ts +113 -0
  481. package/dist/tools/types.js +5 -0
  482. package/dist/tools/write.js +3 -0
  483. package/dist/tui/component.d.ts +8 -2
  484. package/dist/tui/component.js +3 -1
  485. package/dist/tui/components/box.d.ts +6 -1
  486. package/dist/tui/components/box.js +16 -6
  487. package/dist/tui/components/card.d.ts +23 -0
  488. package/dist/tui/components/card.js +37 -0
  489. package/dist/tui/components/editor-history.d.ts +6 -0
  490. package/dist/tui/components/editor-history.js +45 -0
  491. package/dist/tui/components/editor-paste.d.ts +1 -1
  492. package/dist/tui/components/editor-paste.js +4 -4
  493. package/dist/tui/components/editor.d.ts +11 -5
  494. package/dist/tui/components/editor.js +52 -58
  495. package/dist/tui/components/key-value.d.ts +3 -0
  496. package/dist/tui/components/key-value.js +16 -6
  497. package/dist/tui/components/loader.d.ts +37 -7
  498. package/dist/tui/components/loader.js +84 -21
  499. package/dist/tui/components/markdown.d.ts +5 -1
  500. package/dist/tui/components/markdown.js +45 -21
  501. package/dist/tui/components/meter.d.ts +3 -3
  502. package/dist/tui/components/meter.js +13 -11
  503. package/dist/tui/components/select-list.d.ts +23 -1
  504. package/dist/tui/components/select-list.js +76 -13
  505. package/dist/tui/glyphs.d.ts +72 -0
  506. package/dist/tui/glyphs.js +118 -0
  507. package/dist/tui/keybindings.d.ts +5 -0
  508. package/dist/tui/keybindings.js +5 -0
  509. package/dist/tui/theme.d.ts +30 -6
  510. package/dist/tui/theme.js +103 -17
  511. package/dist/tui.d.ts +4 -2
  512. package/dist/tui.js +3 -1
  513. package/docs/acp.md +78 -0
  514. package/docs/agents.md +250 -0
  515. package/docs/codemode.md +28 -10
  516. package/docs/hooks.md +36 -32
  517. package/docs/permissions.md +212 -0
  518. package/docs/plan.md +107 -0
  519. package/docs/providers.md +261 -62
  520. package/docs/rewind-plan.md +181 -0
  521. package/docs/rpc.md +127 -40
  522. package/docs/sandbox.md +215 -0
  523. package/docs/session-format.md +43 -22
  524. package/docs/sessions.md +174 -0
  525. package/docs/tui-design.md +751 -0
  526. package/docs/tui.md +260 -64
  527. package/package.json +15 -2
@@ -0,0 +1,181 @@
1
+ # 检查点与回滚:设计与实施计划
2
+
3
+ > 状态:实施设计(2026-10-02)。基线:`main` = `95c0435`(0.4.0)。
4
+ > 设计依据:`docs/design.md` §8 会话树、§9 压缩、§9.1 缓存保证、§13 SDK / RPC;对照同类终端 Agent 的检查点实现(只借鉴行为与边界,不复制代码)。
5
+ > 路径相对仓库根;`[RW-x]` 为本计划的批次编号(§6)。
6
+
7
+ ## §0 结论
8
+
9
+ | # | 决定 | 理由 |
10
+ | --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
11
+ | D1 | 回滚 = 「对话」与「代码」两件事,入口 `/rewind` 与空闲时双击 Esc;选项:对话 + 代码 / 仅对话 / 仅代码 / 从这里摘要 / 摘要到这里 / 取消 | 两者独立才能覆盖「代码写坏了但对话想留」「对话跑偏了但代码要留」 |
12
+ | D2 | 检查点粒度 = 开启新回合的用户消息;运行中插话(steer)与排队消息并入当前回合,不单独建 | 回合是用户能理解的最小单位 |
13
+ | D3 | 代码跟踪 edit / write(含 codemode 内层调用、task 子会话)改过的文件;每次发新回合按**当前磁盘状态**重拍已跟踪文件,所以 bash 或手动对已跟踪文件的改动也会被收进下一个检查点 | bash 任意改动不可完整追踪;已跟踪文件这样处理就不会漏 |
14
+ | D4 | 备份按内容 sha256 存全局目录,多会话、多检查点共用;会话文件只记哈希 | 同内容只存一份;fork 不用迁移备份 |
15
+ | D5 | 恢复前做冲突检测:磁盘内容既不等于 ama 最后写入的、也不等于最近检查点的 → 冲突,缺省跳过并列出,`onConflict: "overwrite"` 才覆盖 | 不冲掉用户在回合外的手动修改 |
16
+ | D6 | git 状态不动;检查点记 HEAD,回滚时 HEAD 变了只提示并给命令 | `reset` 类操作风险高,交给用户 |
17
+ | D7 | 对话回滚复用会话树(`navigate` 换叶子),被离开的分支留在文件里 | 现有能力,零迁移 |
18
+ | D8 | 回滚后上下文只发新路径,前缀逐字节不变,缓存照常命中;需要告诉模型的事(文件与对话不一致)以 `custom_message` 追加在末尾 | §9.1 前缀稳定 |
19
+ | D9 | `影子 git` 模式(能覆盖 bash 改动)作为可选 `checkpoints.mode: "shadow-git"`,缺省关,最后一批做 | 大仓库慢、依赖 git,不适合作缺省 |
20
+
21
+ ## §1 数据模型
22
+
23
+ ### §1.1 备份存储
24
+
25
+ - 目录:`<dataDir>/file-history/blobs/<sha256 前 2 位>/<sha256 全长>`,内容为文件原字节(不压缩、不改换行与 BOM);先写 `<name>.tmp-<pid>` 再 rename,已存在即跳过。
26
+ - 不备份:超过 `checkpoints.maxFileBytes`(缺省 5 MiB)的文件、非普通文件。记录里标 `skipped: "too_large" | "not_regular"`,回滚时报告「无法恢复」。
27
+ - 内存会话(无会话文件)不建检查点,`/rewind` 只提供「仅对话」。
28
+
29
+ ### §1.2 会话条目(均为 `custom`,不进上下文,不影响前缀)
30
+
31
+ ```ts
32
+ // customType "ama.checkpoint":新回合的用户消息条目追加之后立即追加
33
+ interface CheckpointData {
34
+ v: 1;
35
+ userEntryId: string; // 这个检查点属于哪条用户消息(「这条消息发出前」的状态)
36
+ files: Record<string, FileRecord>; // 全部已跟踪文件;键 = cwd 内相对路径(/ 分隔),cwd 外为绝对路径
37
+ git?: { head: string; branch?: string }; // 直接读 .git/HEAD(含 worktree 的 gitdir 文件),不起 git 进程
38
+ }
39
+
40
+ // customType "ama.checkpoint-track":回合中途第一次碰某文件时追加,补进本回合的检查点
41
+ interface CheckpointTrackData {
42
+ v: 1;
43
+ userEntryId: string;
44
+ path: string;
45
+ record: FileRecord;
46
+ }
47
+
48
+ interface FileRecord {
49
+ blob: string | null; // sha256;null = 当时文件不存在(回滚时删除)
50
+ mode?: number; // 普通文件的权限位
51
+ size?: number;
52
+ realParentDir?: string; // 记录时父目录的 realpath(恢复时校验没被移动)
53
+ skipped?: "too_large" | "not_regular";
54
+ }
55
+ ```
56
+
57
+ - 读取:按文件顺序重放全会话(不限活动分支)的两类条目,得到 `Map<userEntryId, CheckpointData>`;`checkpoint-track` 并入对应检查点。
58
+ - 每个文件的第一条记录(最早的 `blob`)永久保留,作为「找不到更近记录时」的回退。
59
+
60
+ ### §1.3 运行时状态(`src/checkpoints/tracker.ts`)
61
+
62
+ - `trackedFiles: Set<string>`、最近检查点、`lastWritten: Map<路径, sha256>`(ama 最后一次写入后的内容哈希,用于冲突检测;只在内存,恢复会话后以最近检查点为准)。
63
+ - 检查点上限 `checkpoints.keep`(缺省 100):超出时较早检查点不再列为回滚点;备份由 GC 清理(§1.4)。
64
+
65
+ ### §1.4 清理
66
+
67
+ - `ama sessions prune` 与删除会话时:标记 —— 扫描所有会话文件里的 `ama.checkpoint*` 引用;清除 —— 删除未被引用且 mtime 超过 1 天的 blob。
68
+ - `ama doctor` 显示 file-history 占用。
69
+
70
+ ## §2 时机
71
+
72
+ | 时机 | 动作 |
73
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
+ | 新回合用户消息落盘后(`runPrompt`,steer / 排队并入的不算) | 对每个已跟踪文件:lstat → 不存在记 `null`;size / mode 与上一条记录一致且 mtime 不晚于记录时间 → 沿用;否则读内容算 sha256,等于上一条则沿用,不等则写 blob。追加 `ama.checkpoint` |
75
+ | edit / write 写文件**之前**(`ctx.checkpoint?.beforeWrite(abs)`) | 文件在任何检查点里都没出现过 → 备份当前内容(不存在记 `null`),追加 `ama.checkpoint-track`,加入 `trackedFiles`;出现过则什么都不做 |
76
+ | edit / write 写文件**之后**(`ctx.checkpoint?.afterWrite(abs, bytes)`) | 记 `lastWritten` |
77
+ | task 子会话 | 子会话的 `ctx.checkpoint` 指向父会话的 tracker,记到父会话当前回合 |
78
+ | codemode 内层调用 | 走同一工具上下文,天然覆盖 |
79
+
80
+ `beforeWrite` 失败(磁盘满、权限)只记 warn,不阻止写入(与对照实现一致:检查点是辅助,不能让编辑失败)。
81
+
82
+ ## §3 回滚
83
+
84
+ ### §3.1 API(`AgentSession`,SDK 同名,RPC 见 §5)
85
+
86
+ 类型见 `src/checkpoints/types.ts`(`RewindPoint`、`RewindRequest`、`RewindResult`、`CodeRestoreResult`):
87
+
88
+ ```ts
89
+ rewindPoints(): RewindPoint[]; // 活动路径上的新回合用户消息,从旧到新
90
+ rewind(request: RewindRequest): Promise<RewindResult>;
91
+ ```
92
+
93
+ `dryRun` 的 `code` 字段给出将恢复的文件与 `insertions / deletions`,界面的每行统计与确认预览都用它(懒计算,只对选中项)。
94
+
95
+ - 运行中调用抛 `AmaError("busy")`。全部失败且无一恢复 → `AmaError("rewind_failed", "没有文件被恢复…")`。
96
+
97
+ ### §3.2 恢复代码(`src/checkpoints/restore.ts`)
98
+
99
+ 对每个已跟踪文件,取目标检查点里的记录,没有则取该文件最早的记录:
100
+
101
+ 1. 记录 `skipped` → 报告 `too_large` / `not_regular`。
102
+ 2. 当前内容与记录相同 → 跳过(不计入)。
103
+ 3. 冲突检测:当前 sha256 ∉ {`lastWritten`,最近检查点的记录} → 冲突;`skip` 时列入 `conflicts` 不动。
104
+ 4. 安全检查(不通过 → `skipped`):目标是符号链接 / 非普通文件 / `nlink > 1`;父目录 realpath ≠ `realParentDir`。
105
+ 5. `blob: null` → 删除文件(只删普通文件)。
106
+ 6. 否则写回:Windows 以外用 `O_NOFOLLOW` 打开目标,`fstat` 与路径 `lstat` 的 dev / ino 一致才写;清空后写入 blob 内容,恢复 `mode`;目标不存在时按需创建父目录(再次校验父目录)。
107
+ 7. 被恢复 / 删除的文件从 `readFiles` 移除(模型再改前必须重新 read)。
108
+
109
+ `dryRun` 只做 1–4 并用行级 diff 计 `insertions / deletions`(复用 `tools/edit` 的 diff 实现)。
110
+
111
+ ### §3.3 回滚对话(`src/agent/session-rewind.ts`)
112
+
113
+ 1. `navigate(userEntry.parentId)`(已有:换叶子、重载消息、`cache.onContextChanged()`)。
114
+ 2. `readFiles` 按新路径重算:路径上成功的 read 工具调用的绝对路径(不跨分支保留)。
115
+ 3. 返回 `draft`:原消息文本与图片,交互界面回填输入框。
116
+ 4. 模型、思考级别、权限模式保持当前(文档写明)。
117
+
118
+ ### §3.4 文件与对话不一致时告诉模型
119
+
120
+ - 仅对话:若有已跟踪文件当前内容 ≠ 目标检查点 → 下一次提示前追加 `custom_message{customType:"ama.rewind-note"}`:「回滚到较早的对话,但以下文件保留了之后的修改:…(最多 20 个,其余计数)」。
121
+ - 仅代码:追加「以下文件已恢复到第 N 条消息之前的状态:…」。
122
+ - 对话 + 代码:两边一致,不追加。
123
+ - 该条目在回滚落点之后、下一条用户消息之前,只追加在末尾,不改前缀。
124
+
125
+ ### §3.5 摘要两项
126
+
127
+ - 「从这里摘要」= `navigate(parentId, { summarize: true })`(已有 `branch_summary`,走会话前缀续写),并回填原消息。
128
+ - 「摘要到这里」= 以所选用户消息为切点做一次档二压缩(`compaction` 条目的 `firstKeptEntryId` = 该消息),之后的消息原样保留,停在末尾。可附说明(`instructions`)。
129
+
130
+ ### §3.6 中断即撤回
131
+
132
+ 运行中 Esc 中断,且本回合还没有任何 assistant 文本 / 工具调用、输入框为空 → 自动 `rewind(当前回合, "conversation")` 并回填原消息(配置 `ui.restoreOnCancel`,缺省 true)。
133
+
134
+ ## §4 交互
135
+
136
+ - 空闲且输入框为空:双击 Esc(间隔 ≤ 800 ms,第一次提示「再按 Esc 回滚」)打开回滚列表;输入框有字:双击 Esc 清空输入并存进输入历史(↑ 可取回),第一次提示「再按 Esc 清空」。运行中 Esc 仍为中断。
137
+ - 列表:活动路径上的用户消息,最近在下、缺省选中最后一条;高亮行右侧显示 `N 文件 +x −y` / `无代码改动`(对高亮项做 dryRun,结果缓存)。
138
+ - 选中后:确认面板(左竖条样式,复用 `/session` 面板),显示消息原文与时间、选项(有代码改动才出现两个「恢复代码」项;两个摘要项可在行内输入说明)、预览(「将恢复 N 个文件 +x −y」/「代码不变」/ 冲突与跳过清单)、git HEAD 变化提示(附 `git log --oneline <记录>..HEAD` 与 `git reset --soft <记录>` 两条命令,不执行)。
139
+ - 结果通知:`已恢复 N 个文件,跳过 M 个(原因…)`。
140
+ - line 模式:`/rewind` 列编号;`/rewind <n> [both|conversation|code]`。
141
+ - 文案进 i18n 风格的现有中文常量;字形走主题 glyphs(ASCII 可用)。
142
+
143
+ ## §5 RPC / SDK / Hook / 配置
144
+
145
+ - RPC:`get_rewind_points` → `{ points }`;`rewind { entryId, mode, dryRun?, onConflict? }` → `RewindResult`;事件 `session_rewound { entryId, mode, restored, deleted, conflicts, skipped }`。写进 `docs/rpc.md`。
146
+ - SDK:`session.rewindPoints()`、`session.rewind()`。
147
+ - Hook:新增命令式事件 `PostRewind`(payload `{ entryId, mode, files }`,不可阻止);`docs/hooks.md` 同步。
148
+ - 配置(`key-docs.ts` 每项要说明与缺省值):
149
+ - `checkpoints.mode`: `"tools"`(缺省)/ `"shadow-git"` / `"off"`;`AMA_CHECKPOINTS=off` 覆盖。
150
+ - `checkpoints.maxFileBytes`: 5 242 880。
151
+ - `checkpoints.keep`: 100。
152
+ - `ui.restoreOnCancel`: true。
153
+
154
+ ## §6 影子 git(`checkpoints.mode: "shadow-git"`)[RW-D]
155
+
156
+ - 仓库:`<dataDir>/file-history/shadow/<sha256(cwd) 前 16>/`(`--git-dir`),`--work-tree=cwd`;尊重 cwd 的 `.gitignore` 与 `info/exclude`,额外排除 `.git`。
157
+ - 每个新回合:`git add -A` + `write-tree` + `commit-tree`,提交 id 记进 `CheckpointData.shadowCommit`(契约里预留可选字段)。
158
+ - 护栏:cwd 下文件数 > 20 000 或单次快照 > 3 s → 本会话降级为 `tools` 并提示;需要 `git` 在 PATH。
159
+ - 恢复:只处理目标提交与「当前工作区快照」之间的差异文件,逐个按 §3.2 的冲突与安全检查写回或删除;不碰 `.gitignore` 掉的文件。
160
+ - 与 `tools` 模式并存:edit / write 的跟踪照常(冲突检测仍以它为准)。
161
+
162
+ ## §7 缓存与上下文
163
+
164
+ - 回滚后第一次请求:system + tools + 落点之前的消息与回滚前发过的请求逐字节相同 → 有效期内命中;`onContextChanged()` 使这次请求成为重置点(不做未命中归因、保温作废),与现状一致。
165
+ - `ama.checkpoint*` 是 `custom`,不进上下文;`ama.rewind-note` 是 `custom_message`,只出现在新落点之后。
166
+ - 测试:回滚前后请求体前缀逐字节比较(`src/agent/session-rewind.test.ts`)。
167
+
168
+ ## §8 批次与文件所有权
169
+
170
+ 契约 PR(本计划所在 PR)先合入:`src/checkpoints/types.ts`、`ToolContext.checkpoint?`。配置 `checkpoints.*` 归 RW-A,`ui.restoreOnCancel` 与 `PostRewind` 归 RW-B(各自同步 `config/{types,schema,json-schema,key-docs}.ts` 与 `hooks/types.ts`)。之后:
171
+
172
+ | 批次 | 内容 | 文件所有权 | 依赖 | 验收 |
173
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
174
+ | RW-A 检查点核心 | blob 存储、tracker、条目重放、恢复与安全检查、冲突检测、dry-run diff、GC、doctor 占用;edit / write 调 `ctx.checkpoint` | `src/checkpoints/**`(除 types.ts)、`src/tools/{edit,write}.ts` 的两处调用、`src/cli/subcommands/{sessions,doctor}.ts` 的 GC / 占用 | 契约 | 单测覆盖 §3.2 每条分支(符号链接、硬链接、父目录移动、删除、新建、冲突 skip / overwrite、too_large);三平台 CI 绿(Windows 无 O_NOFOLLOW 分支) |
175
+ | RW-B 会话与接口 | `session-rewind.ts`(编排、readFiles 重算、rewind-note、摘要两项、中断即撤回)、检查点接线(runPrompt 后建检查点、子会话指向父 tracker)、RPC / SDK / `PostRewind` / 文档 | `src/agent/session-rewind.ts`(新)、`src/agent/{session,session-run,session-tools,session-subagent}.ts` 的接线、`src/modes/rpc/**`、`src/sdk.ts`、`src/hooks/**` 的事件、`docs/{rpc,hooks,sessions}.md` | 契约;RW-A 的实现可先用内存桩,合入顺序 A → B | fake 供应商端到端:edit 两个文件 → rewind both → 文件与对话都回到之前、readFiles 不含被恢复文件、下一请求前缀逐字节不变;仅对话 / 仅代码各自的 note;子会话编辑可回滚;中断即撤回 |
176
+ | RW-C 交互界面 | 双击 Esc、回滚列表、确认面板、预览、git 提示、结果通知、line 模式 `/rewind` | `src/modes/interactive/**`、`src/modes/commands-core.ts`、`docs/tui.md` | RW-B | 帧黄金:列表、面板(有 / 无代码改动、冲突、git 提示)、ASCII;tmux 手测双击 Esc 两种行为 |
177
+ | RW-D 影子 git | §6 | `src/checkpoints/shadow-git.ts`(新)及其测试 | RW-A | 临时 git 仓库里 bash 改动可回滚;护栏降级;无 git 时提示 |
178
+
179
+ - A 与 B 并行开发(B 用桩),A 先合;C 与 D 在 B / A 合入后并行。
180
+ - 每个文件 ≤ 600 行(`src/agent/session.ts` 已 600 行,新逻辑放 `session-rewind.ts`)。
181
+ - 每批次细粒度提交、一个 PR、CI 绿后由主会话合并(merge commit);不发版。
package/docs/rpc.md CHANGED
@@ -13,7 +13,7 @@
13
13
  启动后先发 `hello`,再发当前会话的 `session_start`:
14
14
 
15
15
  ```json
16
- {"type":"hello","protocolVersion":1,"agent":"ama","version":"0.1.0","capabilities":["approvals","images","hooks"]}
16
+ {"type":"hello","protocolVersion":1,"agent":"ama","version":"0.1.0","capabilities":["approvals","images","hooks","plans"]}
17
17
  {"type":"session_start","sessionId":"…","cwd":"/work","reason":"startup"}
18
18
  ```
19
19
 
@@ -90,65 +90,136 @@
90
90
  | `set_session_name` † | `name: string` | `{ name }` |
91
91
  | `get_fork_messages` † | — | `{ messages: { entryId, text }[] }`(活动分支上的用户消息,`fork` 的候选) |
92
92
 
93
+ ### 回滚
94
+
95
+ 详见 [rewind-plan.md](rewind-plan.md) §3。回滚点是活动路径上开启新回合的用户消息(运行中插话、排队消息并入当前回合,不单列)。运行中调用回 `busy`。
96
+
97
+ | 命令 | 参数 | `data` |
98
+ | ------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
99
+ | `get_rewind_points` | — | `{ points: { entryId, text, timestamp, hasCheckpoint }[] }`,从旧到新;`hasCheckpoint: false`(内存会话、检查点关闭、超出保留数)时只能仅对话 |
100
+ | `rewind` | `entryId`、`mode: both \| conversation \| code`、`dryRun?: boolean`、`onConflict?: "skip" \| "overwrite"` | `RewindResult`:`conversation?: { leafId, draft: { text, images? } }`、`code?: CodeRestoreResult`、`gitHint?: { recordedHead, currentHead }`;`dryRun` 只返回预览,不改任何东西 |
101
+ | `summarize_from` | `entryId`、`instructions?: string` | `{ leafId, draft, summary? }`:回到该消息之前,为离开的分支写 `branch_summary`,并回填原消息 |
102
+ | `summarize_up_to` | `entryId`、`instructions?: string` | `CompactionResult`:以该消息为切点压缩之前的上下文(`firstKeptEntryId` = 该消息),停在末尾 |
103
+
104
+ `CodeRestoreResult`:`restored` / `deleted` / `conflicts`(`skip` 时未动,`overwrite` 时已覆盖)/ `skipped: { path, reason }[]`(`symlink` / `hardlink` / `not_regular` / `parent_moved` / `too_large` / `backup_missing`)/ `failed: { path, message }[]` / `insertions` / `deletions`;路径在 cwd 内为相对路径(`/` 分隔)。错误码:没有检查点却要恢复代码 → `no_checkpoint`;全部失败且无一恢复 → `rewind_failed`(对话不动);条目不是活动路径上的回滚点 → `invalid_arguments`。仅对话或仅代码时,下一次提示前会在上下文末尾追加一条 `custom_message{customType: "ama.rewind-note"}` 告诉模型哪些文件与对话不一致。
105
+
93
106
  换会话后服务端重新订阅事件,并为新会话发 `session_start`(`reason` 为 `new` / `resume` / `fork`)。`new_session` 目前不使用 `parentSession` 参数。条目形状见 [session-format.md](session-format.md)。
94
107
 
95
108
  ### 审批
96
109
 
97
110
  | 命令 | 参数 | `data` |
98
111
  | ------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
99
- | `set_client_capabilities` | `capabilities: ("approvals" \| "images" \| "hooks")[]` | `{ capabilities }` |
112
+ | `set_client_capabilities` | `capabilities: ("approvals" \| "images" \| "hooks" \| "plans")[]` | `{ capabilities }` |
100
113
  | `permission_response` | `requestId: string`、`decision: "allow" \| "deny" \| "allow_session"` | `{ accepted: boolean }`(false = 当前没在等这个 id,已暂存,稍后被问到时生效) |
101
114
 
102
115
  ### 工具、权限、发现
103
116
 
104
- | 命令 | 参数 | `data` |
105
- | --------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
106
- | `get_tools` | — | `{ tools: { name, description, parameters, permission, active }[] }`(注册表全部工具,`active` 表示模型当前能看到) |
107
- | `set_active_tools` | `names: string[]` | `{ names }`(生效后的活动工具名) |
108
- | `set_permission_mode` | `mode: plan \| default \| auto-edit \| full-auto` | `{ mode }` |
109
- | `get_commands` | — | `{ commands: { name, description?, source: "builtin" \| "template" \| "skill" }[] }`;Skill 名写作 `skill:<名>` |
110
- | `get_skills` | — | `{ skills: { name, description, location, … }[] }`(已发现的 Skill;`location` 是 SKILL.md 路径) |
117
+ | 命令 | 参数 | `data` |
118
+ | --------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
119
+ | `get_tools` | — | `{ tools: { name, description, parameters, permission, active }[] }`(注册表全部工具,`active` 表示模型当前能看到) |
120
+ | `set_active_tools` | `names: string[]` | `{ names }`(生效后的活动工具名) |
121
+ | `set_permission_mode` | `mode: plan \| allowlist \| default \| auto-edit \| auto \| full-auto` | `{ mode }`(未知模式 → `invalid_arguments`) |
122
+ | `get_commands` | — | `{ commands: { name, description?, source: "builtin" \| "template" \| "skill" }[] }`;Skill 名写作 `skill:<名>` |
123
+ | `get_skills` | — | `{ skills: { name, description, location, … }[] }`(已发现的 Skill;`location` 是 SKILL.md 路径) |
124
+
125
+ ### 计划与任务(第五波)
126
+
127
+ | 命令 | 参数 | `data` |
128
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
129
+ | `plan_response` | `planId`、`decision: approve \| approve_fresh \| revise \| reject`、`mode?`(批准后的执行模式)、`feedback?`(revise 的意见)、`editedMarkdown?` | `{ planId, decision }`;`planId` 不是待审批的计划 → `plan_not_found`。见「计划审批」 |
130
+ | `get_plan` | `planId?` | `PlanData \| null`:`{ id, version, status, markdown, steps, sourceEntryId, filePath? }`,缺省取最近一份 |
131
+ | `get_todos` | — | `{ items: { id, text, status: pending \| in_progress \| done, planStep? }[] }` |
132
+ | `get_tasks` | — | `{ tasks: TaskInfo[] }`(子 Agent 任务注册表的只读视图;未装配时为空表) |
133
+ | `get_agents` | — | `{ agents: AgentInfo[] }`(可用的子 Agent 类型与外部 Agent;未装配时为空表) |
111
134
 
112
- 合计 33 条命令,名字即 `RpcCommandMap` 的键。
135
+ 合计 42 条命令,名字即 `RpcCommandMap` 的键。
113
136
 
114
137
  ## 事件
115
138
 
116
139
  事件就是进程内 `SessionEvent`(`src/agent/types.ts`),只有 `message_update` 在线上换成纯增量。按出现场景分组:
117
140
 
118
- | 事件 | 字段 |
119
- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
120
- | `session_start` | `sessionId`、`sessionFile?`、`cwd`、`reason: startup \| resume \| new \| fork` |
121
- | `session_changed` | `sessionId`、`sessionFile?` |
122
- | `before_agent_start` | `prompt`(经 UserPromptSubmit Hook 与模板展开之后) |
123
- | `agent_start` / `turn_start` / `agent_before_settle` | — |
124
- | `turn_end` | `message`(助手消息)、`toolResults` |
125
- | `agent_end` | `stopReason`、`willRetry` |
126
- | `agent_settled` | `warning?`(运行彻底结束,含重试与 followUp) |
127
- | `message_start` / `message_end` | `message`(`AgentMessage`) |
128
- | `message_update` | `assistantMessageEvent`、`usage?`(见下) |
129
- | `tool_execution_start` | `toolCallId`、`toolName`、`args`、`parentToolCallId?` |
130
- | `tool_execution_update` | `toolCallId`、`toolName`、`partial`(运行中的输出文本)、`parentToolCallId?` |
131
- | `tool_execution_end` | `toolCallId`、`toolName`、`result`、`isError`、`parentToolCallId?` |
132
- | `queue_update` | `steering: string[]`、`followUp: string[]` |
133
- | `compaction_start` | `trigger: threshold \| overflow \| manual` |
134
- | `compaction_end` | `trigger`、`result?`、`aborted`、`willRetry`、`error?` |
135
- | `auto_retry_start` | `attempt`、`maxAttempts`、`delayMs`、`errorMessage` |
136
- | `auto_retry_end` | `success`、`attempt`、`finalError?` |
137
- | `permission_request` | `requestId`、`toolName`、`input`、`reason: mode \| dangerous \| hook`、`hookReason?`、`timeoutMs`、`preview?` |
138
- | `permission_resolved` | `requestId`、`decision` |
139
- | `permission_mode_changed` | `mode` |
140
- | `model_changed` | `model: { provider, id, channel? }` |
141
- | `thinking_level_changed` | `level` |
142
- | `entry_appended` | `entry`(刚落盘的会话条目) |
143
- | `hook_executed` | `event`、`command`、`exitCode`(超时或被信号杀死为 null)、`durationMs` |
144
- | `cache_miss` | `missedTokens`、`missedCost?`、`reason`、`detail?`、`idleMs` |
145
- | `cache_warm` | `phase: scheduled \| sent \| stopped`、`nextWarmAt?`、`usage?`、`cost?`、`reason?` |
146
- | `context_pressure` | `percent`、`threshold: 70 \| 90`、`remainingTokens?`、`estimatedTurnsLeft?` |
141
+ | 事件 | 字段 |
142
+ | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
143
+ | `session_start` | `sessionId`、`sessionFile?`、`cwd`、`reason: startup \| resume \| new \| fork` |
144
+ | `session_changed` | `sessionId`、`sessionFile?` |
145
+ | `session_rewound` | `entryId`、`mode`、`restored`、`deleted`、`conflicts`、`skipped`(回滚完成;`dryRun` 不发,仅对话时文件清单为空) |
146
+ | `before_agent_start` | `prompt`(经 UserPromptSubmit Hook 与模板展开之后) |
147
+ | `agent_start` / `turn_start` / `agent_before_settle` | — |
148
+ | `turn_end` | `message`(助手消息)、`toolResults` |
149
+ | `agent_end` | `stopReason`、`willRetry` |
150
+ | `agent_settled` | `warning?`(运行彻底结束,含重试与 followUp) |
151
+ | `message_start` / `message_end` | `message`(`AgentMessage`) |
152
+ | `message_update` | `assistantMessageEvent`、`usage?`(见下) |
153
+ | `tool_execution_start` | `toolCallId`、`toolName`、`args`、`parentToolCallId?` |
154
+ | `tool_execution_update` | `toolCallId`、`toolName`、`partial`(运行中的输出文本)、`parentToolCallId?` |
155
+ | `tool_execution_end` | `toolCallId`、`toolName`、`result`、`isError`、`parentToolCallId?`、`autoDecision?`(auto 模式:`{ layer: rule \| static \| classifier, decision, reason, cached? }`)、`denied?`(`true`:被权限 / Hook / 审批拒绝而没有执行,原因见 `result`) |
156
+ | `queue_update` | `steering: string[]`、`followUp: string[]` |
157
+ | `compaction_start` | `trigger: threshold \| overflow \| manual` |
158
+ | `compaction_end` | `trigger`、`result?`、`aborted`、`willRetry`、`error?` |
159
+ | `auto_retry_start` | `attempt`、`maxAttempts`、`delayMs`、`errorMessage` |
160
+ | `auto_retry_end` | `success`、`attempt`、`finalError?` |
161
+ | `permission_request` | `requestId`、`toolName`、`input`、`reason: mode \| dangerous \| hook`、`hookReason?`、`timeoutMs`、`preview?`、`autoDecision?`(auto 模式下为什么询问)、`context?`(来源,见「子 Agent 事件」) |
162
+ | `permission_resolved` | `requestId`、`decision` |
163
+ | `permission_mode_changed` | `mode` |
164
+ | `model_changed` | `model: { provider, id, channel? }` |
165
+ | `thinking_level_changed` | `level` |
166
+ | `entry_appended` | `entry`(刚落盘的会话条目) |
167
+ | `hook_executed` | `event`、`command`、`exitCode`(超时或被信号杀死为 null)、`durationMs` |
168
+ | `cache_miss` | `missedTokens`、`missedCost?`、`reason`、`detail?`、`idleMs` |
169
+ | `cache_warm` | `phase: scheduled \| sent \| stopped`、`nextWarmAt?`、`usage?`、`cost?`、`reason?` |
170
+ | `context_pressure` | `percent`、`threshold: 70 \| 90`、`remainingTokens?`、`estimatedTurnsLeft?` |
147
171
 
148
172
  另有非会话事件 `{"type":"notification","level":"info"|"warn"|"error","message":…}`:宿主 `ui.notify` 与应答之后的运行失败。
149
173
 
150
174
  `parentToolCallId` 只出现在 codemode 脚本里经 `tools.*` 发起的内层调用上,值是外层 `codemode` 调用的 id;客户端据此折叠显示。内层调用不进转录。
151
175
 
176
+ ### 子 Agent 事件(第五波)
177
+
178
+ `task` / `task_ctl` 起的子 Agent(ama 子会话与外部 Agent 同一组事件,见 [agents.md](agents.md)「子 Agent」):
179
+
180
+ | 事件 | 字段 |
181
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
182
+ | `subagent_start` | `taskId`、`parentToolCallId`、`agent`、`runner`(`ama` / `claude` / `codex` / `acp:<程序>`)、`description`、`background`、`model?`、`sessionFile?`、`cwd`;同一 `taskId` 续聊时再发一次 |
183
+ | `subagent_update` | `taskId`、`kind: tool \| text \| turn`、`toolName?`、`textDelta?`(≥ 250 ms 合并)、`turn`、`usage?` |
184
+ | `subagent_end` | `taskId`、`status: completed \| failed \| aborted \| max_turns \| interrupted`、`usage?`、`cache?`、`outputFile?`、`worktree?: { branch, changed }` |
185
+
186
+ 子会话与外部 Agent 的审批照常以 `permission_request` 发给本连接,`context`(可选,只在不是主会话自己的调用时出现)标出来源:
187
+ `depth`(1 = 来自 task 子 Agent)、`taskId`(来源任务)、`origin`(外部 Agent 发来的权限请求:`agent`、`sessionId`(外部 CLI
188
+ 自己的会话 id)、`toolCall: { title, kind, locations?, inputSummary? }`、`options`)。对话框据此标 `[task:<agent>]` 或
189
+ `[claude · 会话 abc1]`。外部 Agent 的请求 `toolName` 是 `agent:<id>`,回答只影响这一次(「本会话允许」交给外部 Agent 自己记);
190
+ 首次在会话里以某个外部 Agent 运行时还有一次 `toolName: "task"`、`input: { agent, mode, note }` 的确认(`context.taskId`)。
191
+ `test/fixtures/rpc/external.out.jsonl` 是 `task(agent="acp:ama")` 的三次审批(task 工具、首次运行、子 ama 的 bash)的黄金记录,
192
+ 由 `src/agents/external-rpc.test.ts` 用 `UPDATE_GOLDEN=1` 更新。后台任务完成后父会话收到一条
193
+ `origin: "task"` 的 user 消息(`<task-notification …>…</task-notification>`),随后照常开新回合。任务列表与类型列表由
194
+ `get_tasks` / `get_agents` 返回(形状 `TaskInfo` / `AgentInfo`;没有 task 工具时为空表),数据来自当前会话的
195
+ `taskRegistryView(sessionId)` / `sessionAgents(sessionId)`(`src/agent/subagent-registry.ts`)。`get_agents` 另含外部 Agent
196
+ (`installed` / `version` 来自 PATH 与 `--version` 探测,会话建立时异步缓存、外部任务结束与宿主注入变化时刷新;缓存就绪前
197
+ 只有类型目录,见 `cachedAgentInfos`,`src/agents/external.ts`)。
198
+ `test/fixtures/rpc/subagent.out.jsonl` 是一次前台 `task(agent="explore")` 加 `get_tasks` / `get_agents` 的黄金记录(只保留
199
+ 响应、`tool_execution_*`、`subagent_*` 与 `agent_settled`),由
200
+ `src/agent/subagent-rpc.test.ts` 用 `UPDATE_GOLDEN=1` 更新。
201
+
202
+ ### 速率遥测(第五波)
203
+
204
+ 主会话装有遥测扩展(`src/agent/session-telemetry.ts`),只统计对话请求(`purpose: "turn"`;压缩摘要、保温、探测、分类器不计):
205
+
206
+ - 事件 `{"type":"telemetry_tick"}`:流式中首 token 之后约每 500 ms 一次(≤ 2 Hz,由增量驱动;瞬时完成的短回复不发),
207
+ `ui.animation: false` 时不发;没有载荷,数据从 `get_session_stats` 的 `telemetry` 取。
208
+ - `SessionStats.telemetry`:`{ sessionStartedAt, last?, live?, avgTps? }`。`last` 是最近一次请求(`requestAt`、`firstTokenAt?`、
209
+ `ttftMs?`、`doneAt?`、`outputTokens?`、`tps?`;进行中的请求出首 token 后即为 `last`,结束后补齐 `doneAt` 等);
210
+ `live` 只在流式中(`tps` 为最近 2 s 窗口的估算、`outputTokens` 按增量字符估算、`elapsedMs` 自首 token 起);
211
+ `avgTps` = Σ输出 / Σ(结束 − 首 token),生成不足 250 ms 的请求不计(`tps` 也留空)。时间都是毫秒时间戳。
212
+
213
+ ### 预算、回退与后台命令事件(第五波 W5-H2)
214
+
215
+ | 事件 | 字段 |
216
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
217
+ | `limit_reached` | `kind: turns \| cost`、`value`(本次运行的回合数 / 美元)、`limit`;`limits.*`(config,`-p` 另有 `--max-turns` / `--max-cost`)到限时每次运行每类一次,随后 `agent_settled{warning:"limit_reached"}` |
218
+ | `model_fallback` | `from`、`to`(`{ provider, id, channel? }`)、`reason`(触发的错误文本);可重试错误在 overloaded 时或重试用尽后切到 `fallbackModel` 重试一次,回复后切回(另有两次 `model_changed`) |
219
+ | `background_job` | `jobId`、`phase: started \| exited \| stopped`、`command`、`pid?`、`outputPath?`、`exitCode?`;`bash{background:true}` 启动的后台命令 |
220
+
221
+ 重复调用检测(同 run 同名同参第 5 次)结束 run 时 `agent_settled{warning:"repeated_tool_call"}`。
222
+
152
223
  ### `message_update` 与消息重建
153
224
 
154
225
  线上的 `message_update` 去掉了累计消息与 `partial`,只有增量:
@@ -236,6 +307,22 @@
236
307
  4. 回答者顺序:宿主 broker(`HostApi.approvals.setBroker`)→ RPC 客户端 → 无人作答 deny。审批串行,同一时刻只有一个在等。
237
308
  5. 超时:`timeoutMs`(缺省 600 000,即 10 分钟;环境变量 `AMA_APPROVAL_TIMEOUT_MS` 可改)内没有回答 → 服务端按 deny 处理并发 `permission_resolved`。运行被中断时同样 deny,即使客户端已经放行。
238
309
 
310
+ ## 计划审批
311
+
312
+ plan 模式与计划的格式见 [plan.md](plan.md)。
313
+
314
+ 1. 回合在 plan 模式下以纯文本结束、回复里有 `<proposed_plan>` 块时,服务端落盘计划并发 `plan_proposed{ planId, version, markdown, steps, filePath? }`(`steps[]`:`{ id, text, dependsOn?, agent? }`),随后照常 `agent_settled`。
315
+ 2. 客户端声明过 `set_client_capabilities{capabilities:["plans"]}` 才由它回答;没声明时按配置 `plan.unattended`:缺省 `stop`(计划留在 proposed,不切模式、不执行,客户端之后仍可用 `plan_response` 作答),`approve` 时同一次运行里自动批准并执行。
316
+ 3. `plan_response`:
317
+ - `approve`:计划标 approved,步骤写成 todo(首项 in_progress,发 `todo_updated`),发 `plan_resolved{ planId, decision, mode }`,权限模式切到 `mode`(缺省进入 plan 前的模式;进入前就是 plan 时用 `default`),随后自动开一个新回合:用户消息 `The plan is approved. Go ahead.`(`origin: "plan"`)+ `custom_message{ama.plan_approved}`(计划全文、文件路径、进度记法:有 todo 工具时按 todo 推进,没有时请模型每完成一步写一行 `[DONE:<步骤>]`,ama 据此推进待办并发 `todo_updated`)。
318
+ - `approve_fresh`:同上标 approved、切模式,然后新建会话(发 `session_start{reason:"new"}`),在新会话里写 todo,并以计划全文为首条用户消息开回合。
319
+ - `revise`:留在 plan;`feedback` 非空时作为普通用户消息开回合,模型重写计划后出新版本(旧版标 superseded)。
320
+ - `reject`:计划标 rejected,留在 plan。
321
+ - `editedMarkdown`:客户端改过的全文;与原文不同则先落一份新版本(`plan_proposed` 再发一次)再按 `decision` 处理。
322
+ 4. `todo_updated{ items }`:todo 清单每次变化(`todo` 工具的 set / update、批准时生成)都发,形状同 `get_todos`。
323
+
324
+ `test/fixtures/rpc/plan.out.jsonl` 是一次完整审批往返的黄金文件(不含 `entry_appended` 与 `message_update`):声明 `plans` → `set_permission_mode plan` → 提示 → `ama.plan_mode` 说明 → 带计划块的回复 → `plan_proposed` → `agent_settled` → `get_plan` → `plan_response approve` → `todo_updated`、`plan_resolved`、`permission_mode_changed` → 执行回合(`ama.plan_approved`)→ `get_todos`。由 `src/modes/rpc/rpc-plan.test.ts` 用 `UPDATE_GOLDEN=1` 更新。
325
+
239
326
  ## 退出
240
327
 
241
328
  - stdin 关闭:不再接收命令,撤下审批(之后的 ask 按无人作答 deny),等在途命令与已开始的运行结束、响应写完,退出码 0。所以 `printf '{"type":"prompt","message":"hi"}\n' | ama --mode rpc` 能拿到完整回复;要提前停止,先发 `abort`。
@@ -244,7 +331,7 @@
244
331
 
245
332
  ## 示例
246
333
 
247
- `test/fixtures/rpc/prompt.out.jsonl` 是一次完整往返的黄金文件(fake 供应商;`prompt` → `get_last_assistant_text`,会话 id、时间戳与路径已归一化):`hello` → `session_start` → `entry_appended`(模型、思考级别、首条 system 消息)→ `before_agent_start` → `agent_start` → `turn_start` → `prompt` 的响应 → 用户消息 → 助手消息的 `message_update` 增量 → `turn_end` → `agent_end` → `agent_before_settle` → `agent_settled` → 第二条命令的响应。改协议后由 `src/modes/rpc/rpc-mode.test.ts` 用 `UPDATE_GOLDEN=1` 更新并审阅差异。
334
+ `test/fixtures/rpc/prompt.out.jsonl` 是一次完整往返的黄金文件(fake 供应商;`prompt` → `get_last_assistant_text`,会话 id、时间戳与路径已归一化):`hello` → `session_start` → `entry_appended`(模型、思考级别、首条 system 消息)→ `before_agent_start` → `agent_start` → `turn_start` → `prompt` 的响应 → 用户消息 → 助手消息的 `message_update` 增量 → `turn_end` → `agent_end` → `agent_before_settle` → `agent_settled` → 第二条命令的响应。改协议后由 `src/modes/rpc/rpc-mode.test.ts` 用 `UPDATE_GOLDEN=1` 更新并审阅差异。`test/fixtures/rpc/rewind.out.jsonl` 记回滚的往返(不含 `entry_appended`;第二回合用 write 新建了 `c.txt`):`get_rewind_points` → `rewind{mode:"both", dryRun:true}` 只回预览 → `rewind{mode:"both"}` 先发 `session_rewound` 再回 `RewindResult`(`c.txt` 被删除、对话回到第二条消息之前)→ 非回滚点的 `summarize_up_to` 回 `invalid_arguments` → 回滚后的 `get_rewind_points`。
248
335
 
249
336
  最小会话(stdin 关闭即撤下审批,所以管道方式只适合不需要审批的提示;要回答审批,保持 stdin 打开并先发 `set_client_capabilities`):
250
337