@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,388 @@
1
+ /**
2
+ * ProcessRunner:把 AgentDriver 适配成 SubagentRunner(docs/wave5-plan.md §7.6、§5.3–§5.4)。[W5-E]
3
+ *
4
+ * 外部 CLI Agent 由此与 ama 子 Agent 共用 `task(agent=…)` 入口(D13)。`start()`:
5
+ * 1. 只在已信任目录里起(§5.4 信任;`claude -p` 会跳过目录信任对话框并执行项目 hooks);
6
+ * 2. 模式夹到父会话当前模式(`agents.<id>.maxMode` 例外),再取驱动支持的不更宽的模式;
7
+ * 按候选顺序选第一个已安装且支持该模式的驱动(D14 优先级;oneshot 只在只读下可选);
8
+ * 3. 会话级美元预算 `agents.sessionBudgetUsd` 用尽则不再起;
9
+ * 4. 子进程环境按 D16 清理;并发池(总 3 / claude 2)每回合取一个名额,排队可被 abort;
10
+ * 5. 权限请求只交给人({@link askHuman});中断 / stop / 超时时挂起的请求回 cancelled;
11
+ * 6. 每回合写 `custom{ama.agent-usage}`,会话建立写 `custom{ama.agent-session}`;
12
+ * 只回 finalText + 工具摘要(原始事件不落盘,§5.4 敏感数据);
13
+ * 7. 看门狗:单回合缺省 30 min;空闲 10 min 关进程(能续接的下次 `send` 以 resume 重开)。
14
+ */
15
+ import { agentEntry } from "../config/types-w5.js";
16
+ import { AmaError } from "../errors.js";
17
+ import { defaultSetTimer } from "./base.js";
18
+ import { buildChildEnv } from "./env.js";
19
+ import { askHuman, clampMode, supportedMode } from "./permissions.js";
20
+ export const RUN_TIMEOUT_MS = 30 * 60 * 1000;
21
+ export const IDLE_CLOSE_MS = 10 * 60 * 1000;
22
+ function toUsage(turn) {
23
+ const u = turn.usage ?? {};
24
+ const input = u.input ?? 0;
25
+ const output = u.output ?? 0;
26
+ const cacheRead = u.cacheRead ?? 0;
27
+ const usage = {
28
+ input,
29
+ output,
30
+ cacheRead,
31
+ cacheWrite: 0,
32
+ totalTokens: input + output + cacheRead,
33
+ };
34
+ if (u.costUsd !== undefined)
35
+ usage.cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: u.costUsd };
36
+ return usage;
37
+ }
38
+ function statusOf(turn, timedOut, stopped) {
39
+ if (timedOut)
40
+ return "failed";
41
+ switch (turn.stopReason) {
42
+ case "end_turn":
43
+ case "max_tokens":
44
+ return "completed";
45
+ case "max_turn_requests":
46
+ return "max_turns";
47
+ case "cancelled":
48
+ return stopped ? "aborted" : "failed";
49
+ case "refusal":
50
+ return "failed";
51
+ }
52
+ }
53
+ /** 最终报告:最终文本 + 工具摘要 / 触及文件(给协调者当资料,不是指令)。 */
54
+ export function reportText(turn) {
55
+ const parts = [turn.finalText.trim()];
56
+ if (turn.toolSummary.length > 0)
57
+ parts.push(`工具调用:\n${turn.toolSummary.map((l) => `- ${l}`).join("\n")}`);
58
+ if (turn.filesTouched.length > 0)
59
+ parts.push(`修改的文件:\n${turn.filesTouched.map((f) => `- ${f}`).join("\n")}`);
60
+ return parts.filter((p) => p !== "").join("\n\n");
61
+ }
62
+ function failed(text, sessionId, runner) {
63
+ return {
64
+ text,
65
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0 },
66
+ stopReason: "error",
67
+ isError: true,
68
+ status: "failed",
69
+ ...(sessionId !== "" ? { sessionRef: { runner, sessionId } } : {}),
70
+ };
71
+ }
72
+ export class ProcessRunner {
73
+ deps;
74
+ id;
75
+ drivers;
76
+ constructor(driver, deps) {
77
+ this.deps = deps;
78
+ this.drivers = Array.isArray(driver) ? driver : [driver];
79
+ if (this.drivers.length === 0)
80
+ throw new AmaError("invalid_arguments", "ProcessRunner 需要至少一个驱动");
81
+ this.id = deps.id ?? this.drivers[0].agentId;
82
+ }
83
+ get agentId() {
84
+ return this.drivers[0].agentId;
85
+ }
86
+ unattended() {
87
+ const u = this.deps.unattended;
88
+ return typeof u === "function" ? u() : u === true;
89
+ }
90
+ /** 选驱动:第一个已安装、且支持(不宽于)目标模式的候选。 */
91
+ async choose(mode) {
92
+ const reasons = [];
93
+ for (const driver of this.drivers) {
94
+ const probe = await driver.probe();
95
+ if (!probe.installed) {
96
+ reasons.push(`${driver.kind} 未安装`);
97
+ continue;
98
+ }
99
+ const usable = supportedMode(mode, probe.capabilities.modes);
100
+ if (usable === undefined) {
101
+ reasons.push(`${driver.kind} 不支持「${mode}」`);
102
+ continue;
103
+ }
104
+ const warning = probe.warning;
105
+ return {
106
+ driver,
107
+ mode: usable,
108
+ capabilities: probe.capabilities,
109
+ ...(warning !== undefined ? { warning } : {}),
110
+ };
111
+ }
112
+ throw new AmaError("agent_unavailable", `外部 Agent ${this.id} 不可用(${reasons.join(";")})`);
113
+ }
114
+ async start(request) {
115
+ if (!this.deps.trusted(request.cwd))
116
+ throw new AmaError("agent_untrusted", `目录 ${request.cwd} 尚未被 ama 信任,不能在这里启动外部 Agent(它会执行项目里的 hooks 与配置);先运行 ama trust`);
117
+ const budget = this.deps.config?.sessionBudgetUsd;
118
+ if (budget !== undefined && (this.deps.store?.totalUsd() ?? 0) >= budget)
119
+ throw new AmaError("budget_exhausted", `本会话外部 Agent 预算 $${budget} 已用尽`);
120
+ const entry = agentEntry(this.deps.config, this.agentId);
121
+ const mode = clampMode(request.mode, this.deps.parentMode?.(), entry?.maxMode);
122
+ const chosen = await this.choose(mode);
123
+ const handle = new ProcessHandle(this, chosen, request, {
124
+ ...this.deps,
125
+ model: request.model ?? entry?.model,
126
+ unattended: this.unattended(),
127
+ });
128
+ await handle.open(request.resume);
129
+ handle.begin();
130
+ return handle;
131
+ }
132
+ /** ProcessHandle 用。 */
133
+ get options() {
134
+ return this.deps;
135
+ }
136
+ }
137
+ class ProcessHandle {
138
+ runner;
139
+ chosen;
140
+ request;
141
+ deps;
142
+ session;
143
+ sessionId = "";
144
+ chain = Promise.resolve(failed("尚未运行", "", ""));
145
+ busy = false;
146
+ turns = 0;
147
+ stopped = false;
148
+ lifetime = new AbortController();
149
+ clearIdle;
150
+ agent;
151
+ constructor(runner, chosen, request, deps) {
152
+ this.runner = runner;
153
+ this.chosen = chosen;
154
+ this.request = request;
155
+ this.deps = deps;
156
+ this.agent = runner.agentId;
157
+ const onAbort = () => void this.stop();
158
+ if (request.signal.aborted)
159
+ this.lifetime.abort();
160
+ else
161
+ request.signal.addEventListener("abort", onAbort, { once: true });
162
+ if (chosen.warning !== undefined)
163
+ request.onEvent({ type: "notice", level: "warn", text: chosen.warning });
164
+ if (chosen.mode !== request.mode)
165
+ request.onEvent({
166
+ type: "notice",
167
+ level: "info",
168
+ text: `${this.agent} 以「${chosen.mode}」模式运行(请求的是「${request.mode}」,外部 Agent 不得比 ama 当前模式宽)`,
169
+ });
170
+ }
171
+ get id() {
172
+ return this.sessionId;
173
+ }
174
+ async open(resume) {
175
+ const env = buildChildEnv(this.deps.env, this.agent, this.deps.config);
176
+ const session = await this.chosen.driver.open({
177
+ cwd: this.request.cwd,
178
+ mode: this.chosen.mode,
179
+ env,
180
+ signal: this.lifetime.signal,
181
+ unattended: this.deps.unattended,
182
+ ...(this.deps.model !== undefined ? { model: this.deps.model } : {}),
183
+ ...(resume !== undefined ? { resume } : {}),
184
+ ...(this.request.budgetUsd !== undefined ? { budgetUsd: this.request.budgetUsd } : {}),
185
+ });
186
+ this.session = session;
187
+ this.sessionId = session.sessionId;
188
+ this.deps.store?.recordSession({
189
+ agent: this.agent,
190
+ runner: this.chosen.driver.kind,
191
+ sessionId: session.sessionId,
192
+ cwd: this.request.cwd,
193
+ ...(this.request.taskId !== undefined ? { taskId: this.request.taskId } : {}),
194
+ });
195
+ }
196
+ /** 第一回合。 */
197
+ begin() {
198
+ this.chain = this.runTurn(this.request.prompt);
199
+ }
200
+ async send(text) {
201
+ if (this.stopped)
202
+ throw new AmaError("agent_closed", `${this.agent} 已停止`);
203
+ if (this.busy && this.session?.steer !== undefined && this.chosen.capabilities.steer) {
204
+ await this.session.steer([{ type: "text", text }]);
205
+ return;
206
+ }
207
+ this.chain = this.chain.then(() => this.runTurn(text));
208
+ }
209
+ wait() {
210
+ return this.chain;
211
+ }
212
+ async stop() {
213
+ if (this.stopped)
214
+ return;
215
+ this.stopped = true;
216
+ this.lifetime.abort();
217
+ this.clearIdle?.();
218
+ const session = this.session;
219
+ this.session = undefined;
220
+ if (session !== undefined) {
221
+ await session.cancel().catch(() => undefined);
222
+ await session.close().catch(() => undefined);
223
+ }
224
+ }
225
+ emit(event) {
226
+ try {
227
+ this.request.onEvent(event);
228
+ }
229
+ catch (error) {
230
+ this.deps.log?.("warn", `subagent onEvent failed: ${String(error)}`);
231
+ }
232
+ }
233
+ onDriverEvent(event, turnCost, cancel) {
234
+ switch (event.type) {
235
+ case "message_delta":
236
+ this.emit({ type: "text", delta: event.text });
237
+ return;
238
+ case "thought_delta":
239
+ this.emit({ type: "thought", delta: event.text });
240
+ return;
241
+ case "tool_call":
242
+ if (event.status === "pending")
243
+ return;
244
+ this.emit({
245
+ type: "tool",
246
+ toolName: event.title,
247
+ status: event.status === "in_progress"
248
+ ? "started"
249
+ : event.status === "failed"
250
+ ? "failed"
251
+ : "completed",
252
+ });
253
+ return;
254
+ case "notice":
255
+ this.emit({ type: "notice", level: event.level, text: event.text });
256
+ return;
257
+ case "usage":
258
+ if (event.costUsd !== undefined) {
259
+ turnCost.usd = event.costUsd;
260
+ const budget = this.request.budgetUsd;
261
+ const session = this.deps.config?.sessionBudgetUsd;
262
+ const spent = this.deps.store?.totalUsd() ?? 0;
263
+ if ((budget !== undefined && turnCost.usd > budget) ||
264
+ (session !== undefined && spent + turnCost.usd > session)) {
265
+ this.emit({
266
+ type: "notice",
267
+ level: "warn",
268
+ text: `${this.agent} 超出美元预算,已中断`,
269
+ });
270
+ cancel();
271
+ }
272
+ }
273
+ return;
274
+ default:
275
+ return;
276
+ }
277
+ }
278
+ /** 关掉空闲进程后再续聊:能续接的以 resume 重开。 */
279
+ async ensureSession() {
280
+ if (this.session !== undefined)
281
+ return this.session;
282
+ if (this.chosen.capabilities.resume === "none" || this.sessionId === "")
283
+ throw new AmaError("agent_closed", `${this.agent} 会话已因空闲关闭且不支持续接`);
284
+ await this.open(this.sessionId);
285
+ return this.session;
286
+ }
287
+ async runTurn(text) {
288
+ if (this.stopped)
289
+ return failed(`${this.agent} 已停止`, this.sessionId, this.runner.id);
290
+ this.clearIdle?.();
291
+ let release;
292
+ const setTimer = this.deps.setTimer ?? defaultSetTimer;
293
+ let timedOut = false;
294
+ try {
295
+ release = await this.deps.pool.acquire(this.agent, this.lifetime.signal);
296
+ const session = this.session ?? (await this.ensureSession());
297
+ this.busy = true;
298
+ this.turns += 1;
299
+ this.emit({ type: "turn", turn: this.turns });
300
+ const turnCost = { usd: 0 };
301
+ const cancel = () => void session.cancel();
302
+ const clearTimeout = setTimer(() => {
303
+ timedOut = true;
304
+ this.emit({ type: "notice", level: "warn", text: `${this.agent} 运行超时,已中断` });
305
+ cancel();
306
+ }, this.deps.timeoutMs ?? RUN_TIMEOUT_MS);
307
+ const onAbort = () => cancel();
308
+ this.lifetime.signal.addEventListener("abort", onAbort, { once: true });
309
+ let turn;
310
+ try {
311
+ turn = await session.prompt([{ type: "text", text }], {
312
+ onEvent: (e) => this.onDriverEvent(e, turnCost, cancel),
313
+ onPermission: (req, signal) => askHuman(req, {
314
+ agent: this.agent,
315
+ sessionId: session.sessionId,
316
+ unattended: this.deps.unattended,
317
+ approve: this.deps.approve,
318
+ signal: AbortSignal.any([signal, this.lifetime.signal]),
319
+ ...(this.request.taskId !== undefined ? { taskId: this.request.taskId } : {}),
320
+ }),
321
+ });
322
+ }
323
+ finally {
324
+ clearTimeout();
325
+ this.lifetime.signal.removeEventListener("abort", onAbort);
326
+ this.busy = false;
327
+ }
328
+ this.sessionId = session.sessionId;
329
+ const usage = toUsage(turn);
330
+ const unit = this.chosen.capabilities.usage;
331
+ if (unit !== "none") {
332
+ const amount = unit === "usd"
333
+ ? (turn.usage?.costUsd ?? turnCost.usd)
334
+ : unit === "tokens"
335
+ ? usage.input + usage.output
336
+ : 1;
337
+ this.deps.store?.recordUsage({
338
+ agent: this.agent,
339
+ sessionId: this.sessionId,
340
+ unit,
341
+ amount,
342
+ ...(usage.totalTokens > 0 ? { tokens: usage.totalTokens } : {}),
343
+ });
344
+ this.emit({ type: "usage", usage, unit, amount });
345
+ }
346
+ const status = statusOf(turn, timedOut, this.stopped);
347
+ this.armIdle();
348
+ return {
349
+ text: timedOut
350
+ ? `${this.agent} 运行超时被中断。${turn.finalText !== "" ? `\n\n${reportText(turn)}` : ""}`
351
+ : reportText(turn),
352
+ usage,
353
+ stopReason: timedOut ? "timeout" : turn.stopReason,
354
+ isError: status === "failed",
355
+ status,
356
+ sessionRef: { runner: this.runner.id, sessionId: this.sessionId },
357
+ };
358
+ }
359
+ catch (error) {
360
+ if (this.stopped)
361
+ return {
362
+ ...failed(`${this.agent} 已停止`, this.sessionId, this.runner.id),
363
+ status: "aborted",
364
+ };
365
+ return failed(`${this.agent} 失败:${error.message}`, this.sessionId, this.runner.id);
366
+ }
367
+ finally {
368
+ release?.();
369
+ }
370
+ }
371
+ /** 空闲一段时间关进程(不占资源);能续接的下次 send 再起。 */
372
+ armIdle() {
373
+ if (this.chosen.capabilities.resume === "none")
374
+ return;
375
+ const setTimer = this.deps.setTimer ?? defaultSetTimer;
376
+ this.clearIdle = setTimer(() => {
377
+ if (this.busy || this.stopped)
378
+ return;
379
+ const session = this.session;
380
+ this.session = undefined;
381
+ void session?.close().catch(() => undefined);
382
+ }, this.deps.idleMs ?? IDLE_CLOSE_MS);
383
+ }
384
+ }
385
+ /** §10.2 的签名:`createProcessRunner(driver, { approve, pool, store, … })`。 */
386
+ export function createProcessRunner(driver, deps) {
387
+ return new ProcessRunner(driver, deps);
388
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 外部 Agent 的会话引用与记账(docs/wave5-plan.md §5.4 记账 / 敏感数据,session-format 登记)。[W5-E]
3
+ *
4
+ * - `custom{ama.agent-session}`:`{ agent, runner, sessionId, cwd?, taskId? }`——外部 CLI 自己的
5
+ * 会话 id,续聊(`taskId` / resume)用;不含原始事件与转录。
6
+ * - `custom{ama.agent-usage}`:每个回合结束一条 `{ agent, sessionId, unit, amount, tokens? }`;
7
+ * 无美元单位的按各自单位记,不换算。
8
+ * - `SessionStats.external` 由 {@link createExternalStatsExtension} 从活动分支汇总(扩展点
9
+ * `contributeStats`,主会话才装)。
10
+ */
11
+ import type { SessionExtension } from "../agent/session-extensions.js";
12
+ import type { ExternalAgentStats, ExternalUsageUnit } from "../agent/types-w5.js";
13
+ import type { SessionEntry } from "../session/types.js";
14
+ export declare const AGENT_SESSION_CUSTOM = "ama.agent-session";
15
+ export declare const AGENT_USAGE_CUSTOM = "ama.agent-usage";
16
+ export interface AgentSessionRecord {
17
+ agent: string;
18
+ /** 驱动种类(`claude-stream` / `codex-app-server` / `acp` …)或宿主 runner id。 */
19
+ runner: string;
20
+ sessionId: string;
21
+ cwd?: string;
22
+ taskId?: string;
23
+ }
24
+ export interface AgentUsageRecord {
25
+ agent: string;
26
+ sessionId: string;
27
+ unit: ExternalUsageUnit;
28
+ amount: number;
29
+ tokens?: number;
30
+ }
31
+ /** 会话一侧的最小接口(`ToolContext.session` 或 SessionCore 都能提供)。 */
32
+ export interface AgentStoreBackend {
33
+ appendCustom(customType: string, data: unknown): void;
34
+ /** 活动分支上的条目(求会话级美元合计;不给则只算本进程记下的)。 */
35
+ entries?(): readonly SessionEntry[];
36
+ }
37
+ export interface AgentStore {
38
+ recordSession(record: AgentSessionRecord): void;
39
+ recordUsage(record: AgentUsageRecord): void;
40
+ /** 本会话外部 Agent 的美元合计(`agents.sessionBudgetUsd`)。 */
41
+ totalUsd(): number;
42
+ /** 最近一条该 Agent(可按 taskId 过滤)的会话引用。 */
43
+ lastSession(agent: string, taskId?: string): AgentSessionRecord | undefined;
44
+ }
45
+ export declare function createAgentStore(backend: AgentStoreBackend): AgentStore;
46
+ /** 活动分支上的 `ama.agent-usage` → `SessionStats.external`;没有外部运行时 undefined。 */
47
+ export declare function aggregateExternal(entries: readonly SessionEntry[]): ExternalAgentStats | undefined;
48
+ /** 会话扩展:`getStats()` 时补 `external`(只装在主会话)。 */
49
+ export declare function createExternalStatsExtension(entries: () => readonly SessionEntry[]): SessionExtension;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * 外部 Agent 的会话引用与记账(docs/wave5-plan.md §5.4 记账 / 敏感数据,session-format 登记)。[W5-E]
3
+ *
4
+ * - `custom{ama.agent-session}`:`{ agent, runner, sessionId, cwd?, taskId? }`——外部 CLI 自己的
5
+ * 会话 id,续聊(`taskId` / resume)用;不含原始事件与转录。
6
+ * - `custom{ama.agent-usage}`:每个回合结束一条 `{ agent, sessionId, unit, amount, tokens? }`;
7
+ * 无美元单位的按各自单位记,不换算。
8
+ * - `SessionStats.external` 由 {@link createExternalStatsExtension} 从活动分支汇总(扩展点
9
+ * `contributeStats`,主会话才装)。
10
+ */
11
+ export const AGENT_SESSION_CUSTOM = "ama.agent-session";
12
+ export const AGENT_USAGE_CUSTOM = "ama.agent-usage";
13
+ function customs(entries, type) {
14
+ const out = [];
15
+ for (const entry of entries)
16
+ if (entry.type === "custom" && entry.customType === type && typeof entry.data === "object")
17
+ out.push(entry.data);
18
+ return out;
19
+ }
20
+ export function createAgentStore(backend) {
21
+ const sessions = [];
22
+ let usd = 0;
23
+ const all = () => {
24
+ const entries = backend.entries?.();
25
+ if (entries === undefined)
26
+ return undefined;
27
+ return {
28
+ sessions: customs(entries, AGENT_SESSION_CUSTOM),
29
+ usage: customs(entries, AGENT_USAGE_CUSTOM),
30
+ };
31
+ };
32
+ return {
33
+ recordSession(record) {
34
+ sessions.push(record);
35
+ backend.appendCustom(AGENT_SESSION_CUSTOM, record);
36
+ },
37
+ recordUsage(record) {
38
+ if (record.unit === "usd")
39
+ usd += record.amount;
40
+ backend.appendCustom(AGENT_USAGE_CUSTOM, record);
41
+ },
42
+ totalUsd() {
43
+ const persisted = all();
44
+ if (persisted === undefined)
45
+ return usd;
46
+ return persisted.usage.reduce((sum, u) => (u.unit === "usd" ? sum + u.amount : sum), 0);
47
+ },
48
+ lastSession(agent, taskId) {
49
+ const list = all()?.sessions ?? sessions;
50
+ for (let i = list.length - 1; i >= 0; i--) {
51
+ const r = list[i];
52
+ if (r.agent === agent && (taskId === undefined || r.taskId === taskId))
53
+ return r;
54
+ }
55
+ return undefined;
56
+ },
57
+ };
58
+ }
59
+ /** 活动分支上的 `ama.agent-usage` → `SessionStats.external`;没有外部运行时 undefined。 */
60
+ export function aggregateExternal(entries) {
61
+ const usage = customs(entries, AGENT_USAGE_CUSTOM);
62
+ if (usage.length === 0)
63
+ return undefined;
64
+ const byAgent = {};
65
+ for (const u of usage) {
66
+ if (typeof u.agent !== "string" || typeof u.amount !== "number")
67
+ continue;
68
+ const row = (byAgent[u.agent] ??= { runs: 0, unit: u.unit, amount: 0 });
69
+ row.runs += 1;
70
+ // 同一 Agent 换了单位(换了驱动)时以最新单位重新计
71
+ if (row.unit !== u.unit) {
72
+ row.unit = u.unit;
73
+ row.amount = 0;
74
+ }
75
+ row.amount += u.amount;
76
+ if (typeof u.tokens === "number")
77
+ row.tokens = (row.tokens ?? 0) + u.tokens;
78
+ }
79
+ return { byAgent };
80
+ }
81
+ /** 会话扩展:`getStats()` 时补 `external`(只装在主会话)。 */
82
+ export function createExternalStatsExtension(entries) {
83
+ return {
84
+ id: "external-agents",
85
+ contributeStats(stats) {
86
+ const external = aggregateExternal(entries());
87
+ if (external !== undefined)
88
+ stats.external = external;
89
+ },
90
+ };
91
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * 一个回合的结果汇总(各驱动共用)。[W5-E]
3
+ *
4
+ * 驱动把归一化后的 {@link DriverEvent} 交给收集器:它转发给 `onEvent`,同时累计最终文本、
5
+ * 工具摘要(≤ 20 行,§5.2)、触及的文件(edit / delete / move 类工具的 locations)与用量。
6
+ * 原始事件只在内存里流过,不落盘(§5.4 敏感数据)。
7
+ */
8
+ import type { AcpToolKind, DriverEvent, DriverTurnResult } from "./types.js";
9
+ export declare const TOOL_SUMMARY_LINES = 20;
10
+ interface ToolState {
11
+ title: string;
12
+ kind: AcpToolKind;
13
+ status: "pending" | "in_progress" | "completed" | "failed";
14
+ locations: string[];
15
+ }
16
+ export declare class TurnCollector {
17
+ private readonly onEvent;
18
+ private text;
19
+ private readonly tools;
20
+ private readonly order;
21
+ private usage;
22
+ constructor(onEvent: (event: DriverEvent) => void);
23
+ /** 归一化事件:累计后转发给 onEvent。 */
24
+ push(event: DriverEvent): void;
25
+ /** 工具调用的最近状态(驱动做 tool_call_update 时补全标题与种类)。 */
26
+ tool(id: string): Readonly<ToolState> | undefined;
27
+ /** 回合结束时的累计用量合并(`result.usage` 等)。 */
28
+ mergeUsage(usage: {
29
+ input?: number;
30
+ output?: number;
31
+ cacheRead?: number;
32
+ costUsd?: number;
33
+ }): void;
34
+ get finalText(): string;
35
+ /** 原生协议以整条消息给出最终文本时覆盖(流式增量与整条只取其一)。 */
36
+ setFinalText(text: string): void;
37
+ result(stopReason: DriverTurnResult["stopReason"]): DriverTurnResult;
38
+ }
39
+ /** 单行、截断(标题与摘要用)。 */
40
+ export declare function oneLine(text: string, max?: number): string;
41
+ export {};
@@ -0,0 +1,99 @@
1
+ /**
2
+ * 一个回合的结果汇总(各驱动共用)。[W5-E]
3
+ *
4
+ * 驱动把归一化后的 {@link DriverEvent} 交给收集器:它转发给 `onEvent`,同时累计最终文本、
5
+ * 工具摘要(≤ 20 行,§5.2)、触及的文件(edit / delete / move 类工具的 locations)与用量。
6
+ * 原始事件只在内存里流过,不落盘(§5.4 敏感数据)。
7
+ */
8
+ export const TOOL_SUMMARY_LINES = 20;
9
+ const WRITE_KINDS = new Set(["edit", "delete", "move"]);
10
+ export class TurnCollector {
11
+ onEvent;
12
+ text = "";
13
+ tools = new Map();
14
+ order = [];
15
+ usage = {};
16
+ constructor(onEvent) {
17
+ this.onEvent = onEvent;
18
+ }
19
+ /** 归一化事件:累计后转发给 onEvent。 */
20
+ push(event) {
21
+ switch (event.type) {
22
+ case "message_delta":
23
+ this.text += event.text;
24
+ break;
25
+ case "tool_call": {
26
+ const known = this.tools.get(event.id);
27
+ const next = {
28
+ title: event.title !== "" ? event.title : (known?.title ?? event.id),
29
+ kind: event.kind,
30
+ status: event.status,
31
+ locations: event.locations ?? known?.locations ?? [],
32
+ };
33
+ if (known === undefined)
34
+ this.order.push(event.id);
35
+ this.tools.set(event.id, next);
36
+ break;
37
+ }
38
+ case "usage":
39
+ this.mergeUsage(event);
40
+ break;
41
+ default:
42
+ break;
43
+ }
44
+ this.onEvent(event);
45
+ }
46
+ /** 工具调用的最近状态(驱动做 tool_call_update 时补全标题与种类)。 */
47
+ tool(id) {
48
+ return this.tools.get(id);
49
+ }
50
+ /** 回合结束时的累计用量合并(`result.usage` 等)。 */
51
+ mergeUsage(usage) {
52
+ if (usage.input !== undefined)
53
+ this.usage.input = usage.input;
54
+ if (usage.output !== undefined)
55
+ this.usage.output = usage.output;
56
+ if (usage.cacheRead !== undefined)
57
+ this.usage.cacheRead = usage.cacheRead;
58
+ if (usage.costUsd !== undefined)
59
+ this.usage.costUsd = usage.costUsd;
60
+ }
61
+ get finalText() {
62
+ return this.text;
63
+ }
64
+ /** 原生协议以整条消息给出最终文本时覆盖(流式增量与整条只取其一)。 */
65
+ setFinalText(text) {
66
+ this.text = text;
67
+ }
68
+ result(stopReason) {
69
+ const files = new Set();
70
+ for (const tool of this.tools.values())
71
+ if (WRITE_KINDS.has(tool.kind) && tool.status === "completed")
72
+ for (const path of tool.locations)
73
+ files.add(path);
74
+ const lines = this.order.map((id) => {
75
+ const tool = this.tools.get(id);
76
+ return `${tool.status === "failed" ? "✗" : tool.status === "completed" ? "✓" : "…"} ${tool.kind} ${tool.title}`;
77
+ });
78
+ const summary = lines.length > TOOL_SUMMARY_LINES
79
+ ? [
80
+ ...lines.slice(0, TOOL_SUMMARY_LINES - 1),
81
+ `… 另有 ${lines.length - TOOL_SUMMARY_LINES + 1} 次工具调用`,
82
+ ]
83
+ : lines;
84
+ const result = {
85
+ stopReason,
86
+ finalText: this.text,
87
+ filesTouched: [...files],
88
+ toolSummary: summary,
89
+ };
90
+ if (Object.keys(this.usage).length > 0)
91
+ result.usage = { ...this.usage };
92
+ return result;
93
+ }
94
+ }
95
+ /** 单行、截断(标题与摘要用)。 */
96
+ export function oneLine(text, max = 120) {
97
+ const flat = text.replace(/\s+/g, " ").trim();
98
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
99
+ }