@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,81 @@
1
+ /**
2
+ * 会话回滚编排(docs/rewind-plan.md §2、§3.1、§3.3–§3.6)。[RW-B]
3
+ *
4
+ * - 回合起点:`runPrompt` 开启新回合的那条用户消息(steer / followUp 并入当前回合、Stop Hook 续跑
5
+ * 的 `hook` 消息都不算)。本进程内落盘的按记录判断;恢复的会话以 `ama.checkpoint` 条目为准,
6
+ * 没有检查点时退回「origin 为空的用户消息」。
7
+ * - 检查点:回合起点落盘后调后端 `snapshot()`,首个模型请求前等它完成;ToolContext 的
8
+ * `checkpoint` 钩子指向后端(子会话指向父会话的后端,记到父会话当前回合)。内存会话不建。
9
+ * - `rewind()`:代码(后端恢复)与对话(`navigate(parentId)`);`readFiles` 按新路径上成功的
10
+ * read / write 调用重算,再去掉被恢复、删除或与目标检查点不一致的文件。
11
+ * - 仅对话 / 仅代码时的一致性提示 `ama.rewind-note` 留到下一次提示前追加在末尾(§3.4、§7)。
12
+ * - 「从这里摘要」= navigate(parentId, summarize);「摘要到这里」= 以该消息为切点的档二压缩。
13
+ * - 中断即撤回(§3.6):本回合被 abort 且没有任何助手文本 / 工具调用 → 可撤回并回填原消息。
14
+ */
15
+ import type { UserMessage } from "../ai/types.js";
16
+ import type { CheckpointBackend } from "../checkpoints/index.js";
17
+ import { type CheckpointHooks, type RewindPoint, type RewindRequest, type RewindResult } from "../checkpoints/types.js";
18
+ import type { BranchSummaryEntry, SessionEntry } from "../session/types.js";
19
+ import type { SessionCore } from "./session-core.js";
20
+ import type { CompactionResult, RewindDraftText } from "./types.js";
21
+ /** 提示里最多列出的文件数(§3.4)。 */
22
+ export declare const REWIND_NOTE_MAX_FILES = 20;
23
+ export type RewindDraft = RewindDraftText;
24
+ /** 「从这里摘要」的结果。 */
25
+ export interface SummarizeFromResult {
26
+ leafId: string | null;
27
+ draft: RewindDraft;
28
+ summary?: BranchSummaryEntry;
29
+ }
30
+ /** 会话交给回滚控制器的能力(避免与 session.ts 循环 import)。 */
31
+ export interface RewindHost {
32
+ readonly core: SessionCore;
33
+ running(): boolean;
34
+ navigate(targetId: string | null, options?: {
35
+ summarize?: boolean;
36
+ instructions?: string;
37
+ }): Promise<BranchSummaryEntry | undefined>;
38
+ /** 以 entryId 为切点的档二压缩(运行中 → busy)。 */
39
+ compactAt(entryId: string, instructions: string | undefined): Promise<CompactionResult>;
40
+ }
41
+ /** 文件清单:最多 20 个,其余计数。 */
42
+ export declare function listFiles(files: readonly string[]): string;
43
+ export declare function conversationNote(files: readonly string[]): string;
44
+ export declare function codeNote(files: readonly string[], index: number): string;
45
+ export declare class RewindController {
46
+ readonly backend: CheckpointBackend | undefined;
47
+ private readonly host;
48
+ /** 本进程内落盘的回合起点。 */
49
+ private readonly turnStarts;
50
+ /** 本进程内落盘的全部用户消息(回合起点之外的不用回退规则判断)。 */
51
+ private readonly seenUsers;
52
+ private expected;
53
+ private turn;
54
+ private pendingSnapshot;
55
+ private pendingNote;
56
+ constructor(host: RewindHost);
57
+ /** ToolContext.checkpoint:自己的后端,或子会话继承的父会话钩子。 */
58
+ hooks(): CheckpointHooks | undefined;
59
+ /** runPrompt 构造了开启新回合的用户消息;同时把待发的一致性提示追加在它之前。 */
60
+ beginTurn(message: UserMessage): void;
61
+ /** 每条落盘的消息。 */
62
+ onPersisted(entry: SessionEntry | undefined): void;
63
+ /** 首个模型请求前(beforeRequest):等检查点拍完,工具才可能写文件。 */
64
+ ready(): Promise<void>;
65
+ private checkpointIds;
66
+ private turnEntries;
67
+ points(): RewindPoint[];
68
+ private target;
69
+ private assertIdle;
70
+ rewind(request: RewindRequest): Promise<RewindResult>;
71
+ private absolute;
72
+ private announce;
73
+ /** 新路径上成功的 read / write 调用(与 markRead 的语义一致,不跨分支保留)。 */
74
+ recomputeReadFiles(): void;
75
+ summarizeFrom(entryId: string, instructions?: string): Promise<SummarizeFromResult>;
76
+ summarizeUpTo(entryId: string, instructions?: string): Promise<CompactionResult>;
77
+ /** 空闲、开关开、最近一个回合被中断且还没有任何助手文本 / 工具调用。 */
78
+ canUndoAbortedTurn(): boolean;
79
+ /** 撤回被中断的回合并返回原消息;不满足条件时 undefined。 */
80
+ undoAbortedTurn(): Promise<RewindDraft | undefined>;
81
+ }
@@ -0,0 +1,354 @@
1
+ /**
2
+ * 会话回滚编排(docs/rewind-plan.md §2、§3.1、§3.3–§3.6)。[RW-B]
3
+ *
4
+ * - 回合起点:`runPrompt` 开启新回合的那条用户消息(steer / followUp 并入当前回合、Stop Hook 续跑
5
+ * 的 `hook` 消息都不算)。本进程内落盘的按记录判断;恢复的会话以 `ama.checkpoint` 条目为准,
6
+ * 没有检查点时退回「origin 为空的用户消息」。
7
+ * - 检查点:回合起点落盘后调后端 `snapshot()`,首个模型请求前等它完成;ToolContext 的
8
+ * `checkpoint` 钩子指向后端(子会话指向父会话的后端,记到父会话当前回合)。内存会话不建。
9
+ * - `rewind()`:代码(后端恢复)与对话(`navigate(parentId)`);`readFiles` 按新路径上成功的
10
+ * read / write 调用重算,再去掉被恢复、删除或与目标检查点不一致的文件。
11
+ * - 仅对话 / 仅代码时的一致性提示 `ama.rewind-note` 留到下一次提示前追加在末尾(§3.4、§7)。
12
+ * - 「从这里摘要」= navigate(parentId, summarize);「摘要到这里」= 以该消息为切点的档二压缩。
13
+ * - 中断即撤回(§3.6):本回合被 abort 且没有任何助手文本 / 工具调用 → 可撤回并回填原消息。
14
+ */
15
+ import { isAbsolute, resolve } from "node:path";
16
+ import { CHECKPOINT_CUSTOM_TYPE, REWIND_NOTE_CUSTOM_TYPE, } from "../checkpoints/types.js";
17
+ import { AmaError } from "../errors.js";
18
+ import { resolvePath } from "../tools/paths.js";
19
+ import { ABORTED_CUSTOM_TYPE } from "./session-run.js";
20
+ /** 提示里最多列出的文件数(§3.4)。 */
21
+ export const REWIND_NOTE_MAX_FILES = 20;
22
+ function textOf(content) {
23
+ if (typeof content === "string")
24
+ return content;
25
+ return content.map((block) => (block.type === "text" ? block.text : "")).join("");
26
+ }
27
+ function draftOf(message) {
28
+ const draft = { text: textOf(message.content) };
29
+ if (typeof message.content !== "string") {
30
+ const images = message.content.filter((block) => block.type === "image");
31
+ if (images.length > 0)
32
+ draft.images = images;
33
+ }
34
+ return draft;
35
+ }
36
+ function userMessageOf(entry) {
37
+ return entry?.type === "message" && entry.message.role === "user" ? entry.message : undefined;
38
+ }
39
+ /** 文件清单:最多 20 个,其余计数。 */
40
+ export function listFiles(files) {
41
+ const shown = files.slice(0, REWIND_NOTE_MAX_FILES).map((file) => `- ${file}`);
42
+ const rest = files.length - REWIND_NOTE_MAX_FILES;
43
+ if (rest > 0)
44
+ shown.push(`- … and ${rest} more`);
45
+ return shown.join("\n");
46
+ }
47
+ export function conversationNote(files) {
48
+ return ("The conversation was rewound to an earlier point, but these files keep the changes made " +
49
+ `after that point (their content may differ from what you saw earlier):\n${listFiles(files)}`);
50
+ }
51
+ export function codeNote(files, index) {
52
+ return (`These files were restored to their state before user message #${index} of this ` +
53
+ `conversation (read them again before editing):\n${listFiles(files)}`);
54
+ }
55
+ function changedFiles(result) {
56
+ return [...new Set([...result.restored, ...result.deleted, ...result.conflicts])];
57
+ }
58
+ /** 本回合有没有任何助手文本或工具调用。 */
59
+ function hasOutput(entry) {
60
+ if (entry.type !== "message")
61
+ return false;
62
+ const message = entry.message;
63
+ if (message.role === "toolResult" || message.role === "user")
64
+ return true;
65
+ if (message.role !== "assistant")
66
+ return false;
67
+ return message.content.some((block) => block.type === "toolCall" || (block.type === "text" && block.text.trim().length > 0));
68
+ }
69
+ export class RewindController {
70
+ backend;
71
+ host;
72
+ /** 本进程内落盘的回合起点。 */
73
+ turnStarts = new Set();
74
+ /** 本进程内落盘的全部用户消息(回合起点之外的不用回退规则判断)。 */
75
+ seenUsers = new Set();
76
+ expected;
77
+ turn;
78
+ pendingSnapshot;
79
+ pendingNote;
80
+ constructor(host) {
81
+ this.host = host;
82
+ const core = host.core;
83
+ const factory = core.options.checkpoints;
84
+ const persisted = core.manager.directory() !== undefined;
85
+ this.backend =
86
+ factory !== undefined && core.depth === 0 && persisted
87
+ ? factory({
88
+ cwd: core.cwd,
89
+ entries: () => core.manager.entries(),
90
+ appendCustom: (customType, data) => {
91
+ core.appendEntry({ type: "custom", customType, data });
92
+ },
93
+ currentTurn: () => this.turn,
94
+ log: (level, message) => core.log(level, message),
95
+ })
96
+ : undefined;
97
+ }
98
+ /** ToolContext.checkpoint:自己的后端,或子会话继承的父会话钩子。 */
99
+ hooks() {
100
+ return this.backend?.hooks ?? this.host.core.options.checkpointHooks;
101
+ }
102
+ // -------------------------------------------------------------------------
103
+ // 接线:runPrompt → 落盘 → snapshot → 首个请求前等待
104
+ // -------------------------------------------------------------------------
105
+ /** runPrompt 构造了开启新回合的用户消息;同时把待发的一致性提示追加在它之前。 */
106
+ beginTurn(message) {
107
+ this.expected = message;
108
+ if (this.pendingNote !== undefined) {
109
+ const content = this.pendingNote;
110
+ this.pendingNote = undefined;
111
+ this.host.core.appendEntry({
112
+ type: "custom_message",
113
+ customType: REWIND_NOTE_CUSTOM_TYPE,
114
+ content,
115
+ display: false,
116
+ });
117
+ this.host.core.reloadMessages();
118
+ }
119
+ }
120
+ /** 每条落盘的消息。 */
121
+ onPersisted(entry) {
122
+ const message = userMessageOf(entry);
123
+ if (entry === undefined || message === undefined)
124
+ return;
125
+ this.seenUsers.add(entry.id);
126
+ if (message !== this.expected)
127
+ return;
128
+ this.expected = undefined;
129
+ this.turnStarts.add(entry.id);
130
+ this.turn = entry.id;
131
+ const backend = this.backend;
132
+ if (backend === undefined)
133
+ return;
134
+ this.pendingSnapshot = backend.snapshot(entry.id).catch((error) => {
135
+ this.host.core.log("warn", `checkpoint snapshot failed: ${String(error)}`);
136
+ });
137
+ }
138
+ /** 首个模型请求前(beforeRequest):等检查点拍完,工具才可能写文件。 */
139
+ async ready() {
140
+ const pending = this.pendingSnapshot;
141
+ this.pendingSnapshot = undefined;
142
+ if (pending !== undefined)
143
+ await pending;
144
+ }
145
+ // -------------------------------------------------------------------------
146
+ // 回滚点
147
+ // -------------------------------------------------------------------------
148
+ checkpointIds() {
149
+ const ids = new Set();
150
+ for (const entry of this.host.core.manager.entries()) {
151
+ if (entry.type !== "custom" || entry.customType !== CHECKPOINT_CUSTOM_TYPE)
152
+ continue;
153
+ const data = entry.data;
154
+ if (typeof data?.userEntryId === "string")
155
+ ids.add(data.userEntryId);
156
+ }
157
+ return ids;
158
+ }
159
+ turnEntries() {
160
+ const recorded = this.checkpointIds();
161
+ const out = [];
162
+ for (const entry of this.host.core.manager.branch()) {
163
+ const message = userMessageOf(entry);
164
+ if (message === undefined)
165
+ continue;
166
+ const start = this.seenUsers.has(entry.id)
167
+ ? this.turnStarts.has(entry.id)
168
+ : recorded.has(entry.id) || message.origin === undefined;
169
+ if (start)
170
+ out.push({ entry, message });
171
+ }
172
+ return out;
173
+ }
174
+ points() {
175
+ return this.turnEntries().map(({ entry, message }) => ({
176
+ entryId: entry.id,
177
+ text: textOf(message.content),
178
+ timestamp: message.timestamp,
179
+ hasCheckpoint: this.backend?.hasCheckpoint(entry.id) ?? false,
180
+ }));
181
+ }
182
+ target(entryId) {
183
+ const turns = this.turnEntries();
184
+ const index = turns.findIndex((turn) => turn.entry.id === entryId);
185
+ const found = turns[index];
186
+ if (found === undefined) {
187
+ throw new AmaError("invalid_arguments", `entry ${entryId} is not a rewind point on the active branch`);
188
+ }
189
+ return { ...found, index: index + 1 };
190
+ }
191
+ // -------------------------------------------------------------------------
192
+ // 回滚
193
+ // -------------------------------------------------------------------------
194
+ assertIdle() {
195
+ if (this.host.running())
196
+ throw new AmaError("busy", "cannot rewind while running");
197
+ }
198
+ async rewind(request) {
199
+ this.assertIdle();
200
+ const { entry, message, index } = this.target(request.entryId);
201
+ const mode = request.mode;
202
+ const withCode = mode !== "conversation";
203
+ const withConversation = mode !== "code";
204
+ const backend = this.backend;
205
+ const checkpointed = backend?.hasCheckpoint(entry.id) === true;
206
+ if (withCode && (backend === undefined || !checkpointed)) {
207
+ throw new AmaError("no_checkpoint", "this message has no checkpoint; rewind the conversation only");
208
+ }
209
+ const onConflict = request.onConflict ?? "skip";
210
+ const result = {};
211
+ if (checkpointed && backend !== undefined) {
212
+ const hint = await backend.gitHint(entry.id);
213
+ if (hint !== undefined)
214
+ result.gitHint = hint;
215
+ }
216
+ if (request.dryRun === true) {
217
+ if (checkpointed && backend !== undefined) {
218
+ result.code = (await backend.restore(entry.id, { dryRun: true, onConflict })).result;
219
+ }
220
+ return result;
221
+ }
222
+ let touched = [];
223
+ let divergent = [];
224
+ if (withCode && backend !== undefined) {
225
+ const restored = await backend.restore(entry.id, { dryRun: false, onConflict });
226
+ const code = restored.result;
227
+ if (code.failed.length > 0 && code.restored.length === 0 && code.deleted.length === 0) {
228
+ throw new AmaError("rewind_failed", `no files were restored: ${code.failed.map((f) => `${f.path}: ${f.message}`).join("; ")}`, { detail: code });
229
+ }
230
+ result.code = code;
231
+ touched = restored.touched;
232
+ }
233
+ else if (checkpointed && backend !== undefined) {
234
+ // 仅对话:与目标检查点不一致的文件要告诉模型,并从 readFiles 去掉
235
+ const preview = await backend.restore(entry.id, { dryRun: true, onConflict: "skip" });
236
+ divergent = changedFiles(preview.result);
237
+ }
238
+ if (withConversation) {
239
+ await this.host.navigate(entry.parentId);
240
+ result.conversation = { leafId: entry.parentId, draft: draftOf(message) };
241
+ this.recomputeReadFiles();
242
+ }
243
+ const core = this.host.core;
244
+ for (const path of [...touched, ...divergent.map((file) => this.absolute(file))]) {
245
+ core.readFiles.delete(path);
246
+ }
247
+ if (mode === "conversation") {
248
+ this.pendingNote = divergent.length > 0 ? conversationNote(divergent) : undefined;
249
+ }
250
+ else if (mode === "code") {
251
+ const files = result.code === undefined ? [] : [...result.code.restored, ...result.code.deleted];
252
+ this.pendingNote = files.length > 0 ? codeNote(files, index) : undefined;
253
+ }
254
+ else
255
+ this.pendingNote = undefined;
256
+ this.announce(entry.id, mode, result.code);
257
+ return result;
258
+ }
259
+ absolute(file) {
260
+ return isAbsolute(file) ? file : resolve(this.host.core.cwd, file);
261
+ }
262
+ announce(entryId, mode, code) {
263
+ const core = this.host.core;
264
+ const restored = code?.restored ?? [];
265
+ const deleted = code?.deleted ?? [];
266
+ core.emit({
267
+ type: "session_rewound",
268
+ entryId,
269
+ mode,
270
+ restored,
271
+ deleted,
272
+ conflicts: code?.conflicts ?? [],
273
+ skipped: code?.skipped ?? [],
274
+ });
275
+ void core.runHook("PostRewind", { entryId, mode, files: [...restored, ...deleted] });
276
+ }
277
+ /** 新路径上成功的 read / write 调用(与 markRead 的语义一致,不跨分支保留)。 */
278
+ recomputeReadFiles() {
279
+ const core = this.host.core;
280
+ const calls = new Map();
281
+ const next = new Set();
282
+ for (const entry of core.manager.branch()) {
283
+ if (entry.type !== "message")
284
+ continue;
285
+ const message = entry.message;
286
+ if (message.role === "assistant") {
287
+ for (const block of message.content) {
288
+ if (block.type !== "toolCall" || (block.name !== "read" && block.name !== "write"))
289
+ continue;
290
+ const path = block.arguments["path"];
291
+ if (typeof path === "string")
292
+ calls.set(block.id, resolvePath(path, core.cwd));
293
+ }
294
+ }
295
+ else if (message.role === "toolResult" && message.isError !== true) {
296
+ const path = calls.get(message.toolCallId);
297
+ if (path !== undefined)
298
+ next.add(path);
299
+ }
300
+ }
301
+ core.readFiles.clear();
302
+ for (const path of next)
303
+ core.readFiles.add(path);
304
+ }
305
+ // -------------------------------------------------------------------------
306
+ // 摘要两项(§3.5)
307
+ // -------------------------------------------------------------------------
308
+ async summarizeFrom(entryId, instructions) {
309
+ this.assertIdle();
310
+ const { entry, message } = this.target(entryId);
311
+ const options = { summarize: true };
312
+ if (instructions !== undefined)
313
+ options.instructions = instructions;
314
+ const summary = await this.host.navigate(entry.parentId, options);
315
+ this.recomputeReadFiles();
316
+ this.pendingNote = undefined;
317
+ this.announce(entry.id, "conversation", undefined);
318
+ const result = { leafId: entry.parentId, draft: draftOf(message) };
319
+ if (summary !== undefined)
320
+ result.summary = summary;
321
+ return result;
322
+ }
323
+ async summarizeUpTo(entryId, instructions) {
324
+ this.assertIdle();
325
+ const { entry } = this.target(entryId);
326
+ return this.host.compactAt(entry.id, instructions);
327
+ }
328
+ // -------------------------------------------------------------------------
329
+ // 中断即撤回(§3.6)
330
+ // -------------------------------------------------------------------------
331
+ /** 空闲、开关开、最近一个回合被中断且还没有任何助手文本 / 工具调用。 */
332
+ canUndoAbortedTurn() {
333
+ if (this.host.running() || this.host.core.options.restoreOnCancel === false)
334
+ return false;
335
+ const last = this.turnEntries().at(-1);
336
+ if (last === undefined)
337
+ return false;
338
+ const branch = this.host.core.manager.branch();
339
+ const after = branch.slice(branch.findIndex((entry) => entry.id === last.entry.id) + 1);
340
+ if (after.some(hasOutput))
341
+ return false;
342
+ return after.some((entry) => entry.type === "custom_message" && entry.customType === ABORTED_CUSTOM_TYPE);
343
+ }
344
+ /** 撤回被中断的回合并返回原消息;不满足条件时 undefined。 */
345
+ async undoAbortedTurn() {
346
+ if (!this.canUndoAbortedTurn())
347
+ return undefined;
348
+ const last = this.turnEntries().at(-1);
349
+ if (last === undefined)
350
+ return undefined;
351
+ const result = await this.rewind({ entryId: last.entry.id, mode: "conversation" });
352
+ return result.conversation?.draft;
353
+ }
354
+ }
@@ -10,6 +10,11 @@
10
10
  * - 将要停下时发 agent_before_settle 并跑 Stop(子 Agent 为 SubagentStop)Hook:block + reason →
11
11
  * 以 reason 作为新 user 消息再跑一轮(上限 3 次,stopHookActive 传给 Hook)。
12
12
  * - 最终失败后若 followUp 队列非空,照常投递。
13
+ * - [W5-H2] 模型回退:可重试错误在 overloaded 时、或重试用尽后,若配置了 `fallbackModel` 就切过去
14
+ * 重试一次本请求(`model_fallback` 事件),回退模型回复后切回主模型;每个周期最多一次。
15
+ * - [W5-H2] 扩展经 `noteSettleWarning` 登记的 warning(预算到限 `limit_reached`)写进本周期的 agent_settled;
16
+ * `limit_reached:` 开头的错误回复(预算拦下请求)不重试。
17
+ * - [W5-H2] run 带 `warning`(重复调用检测 `repeated_tool_call`):不跑 Stop Hook,agent_settled 带该 warning。
13
18
  */
14
19
  import type { AssistantMessage, ImageBlock, UserMessage } from "../ai/types.js";
15
20
  import type { AgentMessage } from "../session/types.js";
@@ -19,6 +24,9 @@ import type { CompactionController } from "./session-compaction.js";
19
24
  import type { PromptDisposition, RetrySettings } from "./types.js";
20
25
  export declare const MAX_STOP_HOOK_CONTINUATIONS = 3;
21
26
  export declare const ABORTED_CUSTOM_TYPE = "ama.aborted";
27
+ /** [W5-H2] 预算拦下请求时错误回复的前缀(limits.ts):判为最终失败,不重试、不回退。 */
28
+ export declare const LIMIT_ERROR_PREFIX = "limit_reached:";
29
+ export declare function noteSettleWarning(core: SessionCore, warning: string): void;
22
30
  export type RunDecision = {
23
31
  kind: "done";
24
32
  } | {
@@ -31,6 +39,11 @@ export type RunDecision = {
31
39
  } | {
32
40
  kind: "failed";
33
41
  errorMessage: string;
42
+ }
43
+ /** [W5-H2] 切到 `fallbackModel` 重试一次本请求(overloaded,或可重试错误的重试已用尽)。 */
44
+ | {
45
+ kind: "fallback";
46
+ errorMessage: string;
34
47
  };
35
48
  export interface RunCycleDeps {
36
49
  core: SessionCore;
@@ -40,12 +53,26 @@ export interface RunCycleDeps {
40
53
  stopRequested(): boolean;
41
54
  setRetrying(value: boolean): void;
42
55
  lastAssistantText(): string | null;
56
+ /** [RW-B] 开启新回合的用户消息已构造、尚未落盘(建检查点、追加回滚提示)。 */
57
+ beginTurn?(message: UserMessage): void;
58
+ /** [W5-C0] 扩展点 beforePrompts:返回追加在 prompts 之后的消息(session-extensions.ts)。 */
59
+ beforePrompts?(prompts: readonly AgentMessage[]): Promise<AgentMessage[]>;
60
+ /** [W5-C0] 扩展点 onAgentSettled:agent_settled 之后、周期结束之前。 */
61
+ afterSettled?(): Promise<void>;
43
62
  }
44
- export declare function decideAfterRun(deps: RunCycleDeps, outcome: RunOutcome, retryAttempt: number, overflowRecovered: boolean): RunDecision;
63
+ export declare function decideAfterRun(deps: RunCycleDeps, outcome: RunOutcome, retryAttempt: number, overflowRecovered: boolean, fallbackUsed?: boolean): RunDecision;
45
64
  /** 用 context_edit 把失败尝试(助手消息与其后补的结果)从上下文剔除。 */
46
65
  export declare function excludeFailedAttempt(core: SessionCore, failed: AssistantMessage | undefined, reason: "retry" | "overflow"): void;
47
66
  export declare function recordAbort(core: SessionCore): void;
67
+ /**
68
+ * 会话周期:跑完一轮(到 agent_settled 与 onAgentSettled)后,若期间(Stop Hook、agent_settled 监听器、
69
+ * onAgentSettled 扩展)又有 steer / followUp 入队——宿主 `sendUser`、子 Agent 后台通知等在周期收尾
70
+ * 阶段调用时会话仍算忙,只能入队——就在同一周期里再开一轮投递它们([W5-H2],W5-G 发现的竞态)。
71
+ * abort 或已请求停止(Hook continue:false、预算到限)时不续投,消息留在队列。
72
+ */
48
73
  export declare function runCycle(deps: RunCycleDeps, prompts: AgentMessage[], signal: AbortSignal): Promise<void>;
74
+ /** `"user"` = 普通用户输入,不写 origin。 */
75
+ export declare function normalizeOrigin(origin: string | undefined): string | undefined;
49
76
  export declare function makeUserMessage(text: string, images?: readonly ImageBlock[], origin?: string): UserMessage;
50
77
  /**
51
78
  * 一次提示:展开(expandPrompt)→ UserPromptSubmit Hook(block 拒绝;updatedPrompt 替换;