@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,116 @@
1
+ /**
2
+ * 子 Agent 定义文件解析(docs/wave5-plan.md §7.1,D22)。[W5-G]
3
+ *
4
+ * 一个 `*.md` = 一个类型:frontmatter 与 Skill 同一套 YAML 子集(skills/frontmatter.ts),字段名
5
+ * kebab-case;正文 = 追加到子会话系统提示末尾的角色说明。不合格的文件不加载并给出 warning(拼错的
6
+ * 字段比静默按缺省运行更容易发现)。不支持的字段(`hooks`、`mcpServers`、`memory`、`color`、
7
+ * `initialPrompt`、`skills`)与未知字段忽略。
8
+ */
9
+ import { basename } from "node:path";
10
+ import { parseFrontmatter } from "../skills/frontmatter.js";
11
+ export const AGENT_NAME_RE = /^[a-z0-9-]{1,64}$/;
12
+ export const MAX_AGENT_DESCRIPTION = 1024;
13
+ export const DEFAULT_AGENT_MAX_TURNS = 30;
14
+ const THINKING = [
15
+ "off",
16
+ "minimal",
17
+ "low",
18
+ "medium",
19
+ "high",
20
+ "xhigh",
21
+ ];
22
+ /** 字符串或数组 → 名字列表(`read, grep` / `[read, grep]` / 块数组)。 */
23
+ function nameList(value) {
24
+ if (value === undefined || value === null)
25
+ return undefined;
26
+ const items = Array.isArray(value) ? value.map(String) : String(value).split(/[\s,]+/);
27
+ return items.map((item) => item.trim()).filter((item) => item !== "");
28
+ }
29
+ function isRunner(value) {
30
+ return value === "ama" || value === "claude" || value === "codex" || /^acp:[^\s]+$/.test(value);
31
+ }
32
+ function permissionModeOf(value) {
33
+ if (value === undefined || value === null)
34
+ return "inherit";
35
+ const text = String(value).trim();
36
+ if (text === "inherit")
37
+ return "inherit";
38
+ // R4 草案写作 read-only;与 plan 同义(D22:只读复用 plan 模式)
39
+ if (text === "plan" || text === "read-only" || text === "readonly")
40
+ return "plan";
41
+ return undefined;
42
+ }
43
+ /** 解析一份定义文件;`filePath` 用于缺省名与 warning。 */
44
+ export function parseAgentDefinition(text, filePath, source) {
45
+ const warnings = [];
46
+ const fail = (message) => {
47
+ warnings.push(`${filePath}: ${message}`);
48
+ return { warnings };
49
+ };
50
+ const fm = parseFrontmatter(text);
51
+ for (const error of fm.errors)
52
+ warnings.push(`${filePath}: ${error}`);
53
+ const data = fm.data;
54
+ const rawName = data["name"];
55
+ const name = typeof rawName === "string" && rawName !== "" ? rawName : basename(filePath, ".md");
56
+ if (!AGENT_NAME_RE.test(name))
57
+ return fail(`invalid agent name "${name}" (lowercase letters, digits, -; at most 64)`);
58
+ const description = data["description"];
59
+ if (typeof description !== "string" || description.trim() === "")
60
+ return fail(`missing description; agent "${name}" not loaded`);
61
+ if (description.length > MAX_AGENT_DESCRIPTION)
62
+ return fail(`description longer than ${MAX_AGENT_DESCRIPTION} characters`);
63
+ const runnerRaw = data["runner"] ?? "ama";
64
+ const runner = String(runnerRaw).trim();
65
+ if (!isRunner(runner))
66
+ return fail(`unknown runner "${runner}" (ama | claude | codex | acp:<program>)`);
67
+ const tools = nameList(data["tools"]);
68
+ const disallowedTools = nameList(data["disallowed-tools"]);
69
+ if (tools !== undefined && disallowedTools !== undefined)
70
+ return fail("tools and disallowed-tools are mutually exclusive");
71
+ const permissionMode = permissionModeOf(data["permission-mode"]);
72
+ if (permissionMode === undefined)
73
+ return fail(`permission-mode must be plan or inherit (got "${String(data["permission-mode"])}")`);
74
+ const model = data["model"] === undefined || data["model"] === null ? "inherit" : data["model"];
75
+ if (typeof model !== "string" || model.trim() === "")
76
+ return fail("model must be a string");
77
+ const thinking = data["thinking"];
78
+ if (thinking !== undefined &&
79
+ thinking !== null &&
80
+ !THINKING.includes(thinking))
81
+ return fail(`thinking must be one of ${THINKING.join(", ")}`);
82
+ const maxTurns = data["max-turns"] ?? DEFAULT_AGENT_MAX_TURNS;
83
+ if (typeof maxTurns !== "number" || !Number.isInteger(maxTurns) || maxTurns < 1)
84
+ return fail("max-turns must be an integer ≥ 1");
85
+ const isolation = data["isolation"] ?? "none";
86
+ if (isolation !== "none" && isolation !== "worktree")
87
+ return fail("isolation must be none or worktree");
88
+ const background = data["background"] ?? false;
89
+ if (typeof background !== "boolean")
90
+ return fail("background must be true or false");
91
+ if (runner !== "ama") {
92
+ const ignored = ["tools", "disallowed-tools", "permission-mode"].filter((key) => data[key] !== undefined);
93
+ if (ignored.length > 0)
94
+ warnings.push(`${filePath}: ${ignored.join(", ")} ignored for external runner ${runner} (it keeps its own policy)`);
95
+ }
96
+ const agent = {
97
+ name,
98
+ description: description.trim(),
99
+ permissionMode,
100
+ model: model.trim(),
101
+ maxTurns,
102
+ isolation,
103
+ background,
104
+ runner,
105
+ prompt: fm.body.trim(),
106
+ source,
107
+ filePath,
108
+ };
109
+ if (tools !== undefined)
110
+ agent.tools = tools;
111
+ if (disallowedTools !== undefined)
112
+ agent.disallowedTools = disallowedTools;
113
+ if (typeof thinking === "string")
114
+ agent.thinking = thinking;
115
+ return { agent, warnings };
116
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 子 Agent 结果的上限、落盘与通知文本(docs/wave5-plan.md §7.4,D23–D24)。[W5-G]
3
+ *
4
+ * - 结果 > 50 KB(UTF-8 字节)保留头 70% + 尾 30%,中间一行说明省略了多少、全文在哪;
5
+ * - 后台任务完成后以 `<task-notification>` 作为 followUp 投递给父会话(系统提示 rules 里由 task
6
+ * 工具的 guideline 说明这不是用户发言)。
7
+ */
8
+ import type { Usage } from "../ai/types.js";
9
+ import type { SubagentStatus } from "../tools/types.js";
10
+ export declare const TASK_RESULT_LIMIT_BYTES: number;
11
+ export declare const MAX_TURNS_NOTE = "[Turn limit reached; the sub-agent's last output follows.]";
12
+ /** 超过上限时保留头尾;返回 `truncated` 供调用方决定是否落盘。 */
13
+ export declare function capTaskText(text: string, outputFile: string | undefined, limit?: number): {
14
+ text: string;
15
+ truncated: boolean;
16
+ };
17
+ /** 全文写到 `<dir>/<name>`;失败返回 undefined(结果仍按截断返回)。 */
18
+ export declare function writeTaskOutput(dir: string, name: string, text: string): string | undefined;
19
+ export declare function formatTokens(count: number): string;
20
+ export interface NotificationInput {
21
+ taskId: string;
22
+ agent: string;
23
+ status: SubagentStatus;
24
+ turns?: number;
25
+ usage?: Usage;
26
+ outputFile?: string;
27
+ /** 已按上限截断的最终报告。 */
28
+ report: string;
29
+ }
30
+ export declare function taskNotification(input: NotificationInput): string;
31
+ /** 系统提示 rules 节的一句(task 工具的 promptGuidelines;会话开始即固定)。 */
32
+ export declare const TASK_NOTIFICATION_RULE = "A <task-notification> message is a background task's report, not the user speaking.";
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 子 Agent 结果的上限、落盘与通知文本(docs/wave5-plan.md §7.4,D23–D24)。[W5-G]
3
+ *
4
+ * - 结果 > 50 KB(UTF-8 字节)保留头 70% + 尾 30%,中间一行说明省略了多少、全文在哪;
5
+ * - 后台任务完成后以 `<task-notification>` 作为 followUp 投递给父会话(系统提示 rules 里由 task
6
+ * 工具的 guideline 说明这不是用户发言)。
7
+ */
8
+ import { mkdirSync, writeFileSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ export const TASK_RESULT_LIMIT_BYTES = 50 * 1024;
11
+ const HEAD_SHARE = 0.7;
12
+ export const MAX_TURNS_NOTE = "[Turn limit reached; the sub-agent's last output follows.]";
13
+ /** 去掉按字节切开时残留的半个字符(U+FFFD)。 */
14
+ function trimReplacement(text, side) {
15
+ return side === "end" ? text.replace(/�+$/, "") : text.replace(/^�+/, "");
16
+ }
17
+ /** 超过上限时保留头尾;返回 `truncated` 供调用方决定是否落盘。 */
18
+ export function capTaskText(text, outputFile, limit = TASK_RESULT_LIMIT_BYTES) {
19
+ const bytes = Buffer.from(text, "utf8");
20
+ if (bytes.length <= limit)
21
+ return { text, truncated: false };
22
+ const headBytes = Math.floor(limit * HEAD_SHARE);
23
+ const tailBytes = limit - headBytes;
24
+ const head = trimReplacement(bytes.subarray(0, headBytes).toString("utf8"), "end");
25
+ const tail = trimReplacement(bytes.subarray(bytes.length - tailBytes).toString("utf8"), "start");
26
+ const omitted = bytes.length - headBytes - tailBytes;
27
+ const where = outputFile === undefined ? "" : `; full output: ${outputFile}`;
28
+ return { text: `${head}\n\n[… ${omitted} bytes omitted${where} …]\n\n${tail}`, truncated: true };
29
+ }
30
+ /** 全文写到 `<dir>/<name>`;失败返回 undefined(结果仍按截断返回)。 */
31
+ export function writeTaskOutput(dir, name, text) {
32
+ try {
33
+ mkdirSync(dir, { recursive: true });
34
+ const file = join(dir, name);
35
+ writeFileSync(file, text);
36
+ return file;
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ export function formatTokens(count) {
43
+ if (count < 1000)
44
+ return String(count);
45
+ if (count < 1_000_000)
46
+ return `${(count / 1000).toFixed(1).replace(/\.0$/, "")}k`;
47
+ return `${(count / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`;
48
+ }
49
+ function attr(value) {
50
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
51
+ }
52
+ export function taskNotification(input) {
53
+ const attrs = [
54
+ `taskId="${attr(input.taskId)}"`,
55
+ `agent="${attr(input.agent)}"`,
56
+ `status="${input.status}"`,
57
+ ];
58
+ if (input.turns !== undefined)
59
+ attrs.push(`turns="${input.turns}"`);
60
+ if (input.usage !== undefined)
61
+ attrs.push(`tokens="${formatTokens(input.usage.totalTokens)}"`);
62
+ if (input.outputFile !== undefined)
63
+ attrs.push(`outputFile="${attr(input.outputFile)}"`);
64
+ return `<task-notification ${attrs.join(" ")}>\n${input.report}\n</task-notification>`;
65
+ }
66
+ /** 系统提示 rules 节的一句(task 工具的 promptGuidelines;会话开始即固定)。 */
67
+ export const TASK_NOTIFICATION_RULE = "A <task-notification> message is a background task's report, not the user speaking.";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 会话 id → 任务控制面(`task_ctl` 工具、RPC `get_tasks`、`/tasks` 用)。[W5-G]
3
+ *
4
+ * 注册表(agent/subagent-registry.ts)建好后登记、会话 dispose 时注销。单独成文件是为了让
5
+ * tools/task-ctl.ts 不 import agent/ 的实现(agent/tool-runner → tools/registry → task-ctl 会成环)。
6
+ */
7
+ import type { SubagentResult, TaskRegistryView } from "../tools/types.js";
8
+ export interface TaskControl extends TaskRegistryView {
9
+ /** 运行中是已有输出,结束后是最终文本。 */
10
+ output(taskId: string): string | undefined;
11
+ /** 等结束或超时(超时返回 undefined);未知 taskId 抛 `task_not_found`。 */
12
+ wait(taskId: string, timeoutMs: number): Promise<SubagentResult | undefined>;
13
+ stop(taskId: string): Promise<SubagentResult | undefined>;
14
+ }
15
+ export declare function registerTaskControl(sessionId: string, control: TaskControl): void;
16
+ export declare function unregisterTaskControl(sessionId: string, control: TaskControl): void;
17
+ export declare function taskControl(sessionId: string): TaskControl | undefined;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 会话 id → 任务控制面(`task_ctl` 工具、RPC `get_tasks`、`/tasks` 用)。[W5-G]
3
+ *
4
+ * 注册表(agent/subagent-registry.ts)建好后登记、会话 dispose 时注销。单独成文件是为了让
5
+ * tools/task-ctl.ts 不 import agent/ 的实现(agent/tool-runner → tools/registry → task-ctl 会成环)。
6
+ */
7
+ const controls = new Map();
8
+ export function registerTaskControl(sessionId, control) {
9
+ controls.set(sessionId, control);
10
+ }
11
+ export function unregisterTaskControl(sessionId, control) {
12
+ if (controls.get(sessionId) === control)
13
+ controls.delete(sessionId);
14
+ }
15
+ export function taskControl(sessionId) {
16
+ return controls.get(sessionId);
17
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 子 Agent 任务记录:并发池、单条任务的状态、runner 进度 → `subagent_update`、父会话
3
+ * `custom{ama.task}` 快照的写入形状与 resume 重建(docs/wave5-plan.md §7.4–§7.5)。[W5-G]
4
+ * 编排在 agent/subagent-registry.ts。
5
+ */
6
+ import type { SubagentUpdateEvent } from "../agent/types-w5.js";
7
+ import type { Worktree, WorktreeOutcome } from "../agent/worktree.js";
8
+ import type { SessionEntry } from "../session/types.js";
9
+ import type { RunnerHandle, SubagentEvent, SubagentRequest, SubagentResult, TaskInfo } from "../tools/types.js";
10
+ import type { AgentCatalog } from "./catalog.js";
11
+ import type { AgentDefinition } from "./types.js";
12
+ export declare const TASK_CUSTOM_TYPE = "ama.task";
13
+ /** `subagent_update{kind:"text"}` 的合并间隔。 */
14
+ export declare const TEXT_THROTTLE_MS = 250;
15
+ /** 计数信号量;`waiting` 供排队上限判断;排队中 abort → 抛 aborted 并让出位置。 */
16
+ export declare class SubagentPool {
17
+ private readonly limit;
18
+ private running;
19
+ private readonly waiters;
20
+ constructor(limit: number);
21
+ get waiting(): number;
22
+ acquire(signal: AbortSignal): Promise<void>;
23
+ release(): void;
24
+ }
25
+ /** ama runner 的创建参数(registry → session-subagent.ts)。 */
26
+ export interface AmaRunnerSpec {
27
+ taskId: string;
28
+ agent: AgentDefinition;
29
+ request: SubagentRequest;
30
+ /** `provider/model`;undefined = 继承父。 */
31
+ modelRef?: string;
32
+ cwd: string;
33
+ /** 续聊被释放 / resume 后的任务:重开这个子会话文件。 */
34
+ resumeFile?: string;
35
+ /** worktree 里运行:不记父会话检查点。 */
36
+ isolated: boolean;
37
+ }
38
+ /** runner 句柄的可选扩展(ama 子会话提供)。 */
39
+ export type TaskHandle = RunnerHandle & {
40
+ readonly sessionFile?: string;
41
+ readonly model?: string;
42
+ dispose?(): Promise<void>;
43
+ };
44
+ export interface TaskRecord {
45
+ info: TaskInfo;
46
+ agent: AgentDefinition;
47
+ parentToolCallId: string;
48
+ isolation: "none" | "worktree";
49
+ cwd: string;
50
+ modelRef?: string;
51
+ handle?: TaskHandle;
52
+ running?: Promise<SubagentResult>;
53
+ controller?: AbortController;
54
+ /** 本次运行的文本(运行中是已有输出,结束后是最终文本)。 */
55
+ text: string;
56
+ pendingText: string;
57
+ lastFlush: number;
58
+ worktree?: Worktree;
59
+ worktreeOutcome?: WorktreeOutcome;
60
+ last?: SubagentResult;
61
+ onUpdate?: (partial: string) => void;
62
+ }
63
+ export declare function newRecord(info: TaskInfo, agent: AgentDefinition, parentToolCallId: string, cwd: string, isolation?: "none" | "worktree"): TaskRecord;
64
+ export interface ProgressSink {
65
+ emit(event: SubagentUpdateEvent): void;
66
+ log(level: "info" | "warn", message: string): void;
67
+ now(): number;
68
+ }
69
+ export declare function flushText(record: TaskRecord, sink: ProgressSink): void;
70
+ /** runner 进度 → 记录与 `subagent_update`(文本 ≥ 250 ms 合并,轮次与结束时冲刷)。 */
71
+ export declare function applyRunnerEvent(record: TaskRecord, event: SubagentEvent, sink: ProgressSink): void;
72
+ /** 父会话 `custom{ama.task}` 的 data:TaskInfo + 父 toolCallId + 运行目录(带 `status`)。 */
73
+ export declare function recordData(record: TaskRecord): Record<string, unknown>;
74
+ /** 从父会话分支重建(同一 taskId 取最后一条;未结束的标 interrupted);返回最大序号。 */
75
+ export declare function rebuildRecords(branch: readonly SessionEntry[], catalog: AgentCatalog, cwd: string): {
76
+ records: Map<string, TaskRecord>;
77
+ seq: number;
78
+ };
@@ -0,0 +1,141 @@
1
+ /**
2
+ * 子 Agent 任务记录:并发池、单条任务的状态、runner 进度 → `subagent_update`、父会话
3
+ * `custom{ama.task}` 快照的写入形状与 resume 重建(docs/wave5-plan.md §7.4–§7.5)。[W5-G]
4
+ * 编排在 agent/subagent-registry.ts。
5
+ */
6
+ import { AmaError } from "../errors.js";
7
+ import { DEFAULT_AGENT } from "./builtin.js";
8
+ export const TASK_CUSTOM_TYPE = "ama.task";
9
+ /** `subagent_update{kind:"text"}` 的合并间隔。 */
10
+ export const TEXT_THROTTLE_MS = 250;
11
+ /** 计数信号量;`waiting` 供排队上限判断;排队中 abort → 抛 aborted 并让出位置。 */
12
+ export class SubagentPool {
13
+ limit;
14
+ running = 0;
15
+ waiters = [];
16
+ constructor(limit) {
17
+ this.limit = limit;
18
+ }
19
+ get waiting() {
20
+ return this.waiters.length;
21
+ }
22
+ async acquire(signal) {
23
+ while (this.running >= this.limit) {
24
+ if (signal.aborted)
25
+ throw new AmaError("aborted", "aborted");
26
+ await new Promise((resolve) => {
27
+ const wake = () => {
28
+ signal.removeEventListener("abort", wake);
29
+ const at = this.waiters.indexOf(wake);
30
+ if (at >= 0)
31
+ this.waiters.splice(at, 1);
32
+ resolve();
33
+ };
34
+ this.waiters.push(wake);
35
+ signal.addEventListener("abort", wake, { once: true });
36
+ });
37
+ }
38
+ if (signal.aborted)
39
+ throw new AmaError("aborted", "aborted");
40
+ this.running++;
41
+ }
42
+ release() {
43
+ this.running--;
44
+ this.waiters[0]?.();
45
+ }
46
+ }
47
+ export function newRecord(info, agent, parentToolCallId, cwd, isolation = "none") {
48
+ return { info, agent, parentToolCallId, isolation, cwd, text: "", pendingText: "", lastFlush: 0 };
49
+ }
50
+ export function flushText(record, sink) {
51
+ if (record.pendingText === "")
52
+ return;
53
+ sink.emit({
54
+ type: "subagent_update",
55
+ taskId: record.info.taskId,
56
+ kind: "text",
57
+ textDelta: record.pendingText,
58
+ turn: record.info.turns ?? 0,
59
+ });
60
+ record.pendingText = "";
61
+ record.lastFlush = sink.now();
62
+ }
63
+ /** runner 进度 → 记录与 `subagent_update`(文本 ≥ 250 ms 合并,轮次与结束时冲刷)。 */
64
+ export function applyRunnerEvent(record, event, sink) {
65
+ const taskId = record.info.taskId;
66
+ switch (event.type) {
67
+ case "text":
68
+ record.text += event.delta;
69
+ record.pendingText += event.delta;
70
+ if (sink.now() - record.lastFlush >= TEXT_THROTTLE_MS)
71
+ flushText(record, sink);
72
+ return;
73
+ case "tool":
74
+ if (event.status !== "started")
75
+ return;
76
+ record.onUpdate?.(`[task] ${event.toolName}`);
77
+ sink.emit({
78
+ type: "subagent_update",
79
+ taskId,
80
+ kind: "tool",
81
+ toolName: event.toolName,
82
+ turn: record.info.turns ?? 0,
83
+ });
84
+ return;
85
+ case "turn": {
86
+ flushText(record, sink);
87
+ record.info.turns = event.turn;
88
+ const update = {
89
+ type: "subagent_update",
90
+ taskId,
91
+ kind: "turn",
92
+ turn: event.turn,
93
+ };
94
+ if (record.info.usage !== undefined)
95
+ update.usage = record.info.usage;
96
+ sink.emit(update);
97
+ return;
98
+ }
99
+ case "usage":
100
+ if (event.usage !== undefined)
101
+ record.info.usage = event.usage;
102
+ if (event.unit === "usd" && event.amount !== undefined)
103
+ record.info.costUsd = event.amount;
104
+ return;
105
+ case "notice":
106
+ sink.log(event.level, `[task ${taskId}] ${event.text}`);
107
+ return;
108
+ default:
109
+ return;
110
+ }
111
+ }
112
+ /** 父会话 `custom{ama.task}` 的 data:TaskInfo + 父 toolCallId + 运行目录(带 `status`)。 */
113
+ export function recordData(record) {
114
+ return { ...record.info, parentToolCallId: record.parentToolCallId, cwd: record.cwd };
115
+ }
116
+ /** 从父会话分支重建(同一 taskId 取最后一条;未结束的标 interrupted);返回最大序号。 */
117
+ export function rebuildRecords(branch, catalog, cwd) {
118
+ const records = new Map();
119
+ let seq = 0;
120
+ for (const entry of branch) {
121
+ if (entry.type !== "custom" || entry.customType !== TASK_CUSTOM_TYPE)
122
+ continue;
123
+ // 子会话自己的首条 ama.task 没有 status,跳过
124
+ const data = entry.data;
125
+ if (typeof data.taskId !== "string" || data.status === undefined)
126
+ continue;
127
+ const { parentToolCallId = "", cwd: runCwd = cwd, ...rest } = data;
128
+ const info = { ...rest };
129
+ if (info.status === "running")
130
+ info.status = "interrupted";
131
+ const agent = catalog.get(info.agent) ?? {
132
+ ...catalog.get(DEFAULT_AGENT),
133
+ name: info.agent,
134
+ };
135
+ records.set(info.taskId, newRecord(info, agent, parentToolCallId, runCwd));
136
+ const n = /^t(\d+)$/.exec(info.taskId);
137
+ if (n !== null)
138
+ seq = Math.max(seq, Number(n[1]));
139
+ }
140
+ return { records, seq };
141
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * 子 Agent 定义契约(docs/wave5-plan.md §7.1–§7.2,D22)。[W5-C0] 契约文件,发现与解析归 W5-G。
3
+ *
4
+ * 定义文件:`--agent-dir`(可重复)→ profile `agentDirs` → `~/.config/ama/agents/*.md` →
5
+ * `<cwd>/.ama/agents/*.md`(需信任);frontmatter 与 Skill 同风格(kebab-case),正文追加到子会话
6
+ * 系统提示末尾。这里是解析后(缺省已补齐)的形状。
7
+ */
8
+ import type { ModelThinkingLevel } from "../ai/types.js";
9
+ /** `ama`(缺省)| `claude` | `codex` | `acp:<program>`。 */
10
+ export type AgentRunnerSpec = "ama" | "claude" | "codex" | `acp:${string}`;
11
+ export type AgentSource = "builtin" | "cli" | "profile" | "user" | "project" | "host";
12
+ export interface AgentDefinition {
13
+ /** `^[a-z0-9-]{1,64}$`,缺省取文件名。 */
14
+ name: string;
15
+ /** ≤ 1024 字符,进 task 工具描述。 */
16
+ description: string;
17
+ /** 工具白名单(与 `disallowedTools` 二选一);缺省 = 父活动集。 */
18
+ tools?: string[];
19
+ disallowedTools?: string[];
20
+ /** `plan` 强制只读;`inherit` = 父当前模式(只能更严)。 */
21
+ permissionMode: "plan" | "inherit";
22
+ /** `inherit` | `fast` | `strong`(`models.aliases`)| `provider/model[@channel]`。 */
23
+ model: string;
24
+ thinking?: ModelThinkingLevel;
25
+ /** 缺省 30。 */
26
+ maxTurns: number;
27
+ isolation: "none" | "worktree";
28
+ background: boolean;
29
+ runner: AgentRunnerSpec;
30
+ /** 正文:追加到子会话系统提示末尾的角色说明。 */
31
+ prompt: string;
32
+ source: AgentSource;
33
+ /** 定义文件路径(内置与宿主类型没有)。 */
34
+ filePath?: string;
35
+ }
36
+ /** RPC `get_agents` / `/agents` 的一行。 */
37
+ export interface AgentInfo {
38
+ name: string;
39
+ description: string;
40
+ runner: AgentRunnerSpec | (string & {});
41
+ source: AgentSource;
42
+ filePath?: string;
43
+ /** 外部 Agent:探测到的版本与是否已安装。 */
44
+ installed?: boolean;
45
+ version?: string;
46
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 子 Agent 定义契约(docs/wave5-plan.md §7.1–§7.2,D22)。[W5-C0] 契约文件,发现与解析归 W5-G。
3
+ *
4
+ * 定义文件:`--agent-dir`(可重复)→ profile `agentDirs` → `~/.config/ama/agents/*.md` →
5
+ * `<cwd>/.ama/agents/*.md`(需信任);frontmatter 与 Skill 同风格(kebab-case),正文追加到子会话
6
+ * 系统提示末尾。这里是解析后(缺省已补齐)的形状。
7
+ */
8
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * anthropic-messages 的 compat 推断([W5-M2],docs/wave5-plan.md §3.1、D10):按请求主机给缺省。
3
+ *
4
+ * 顺序:保守缺省 ← 主机表(`model.baseUrl` 的主机名子串,先命中先用)← `provider.compat` ←
5
+ * `model.compat`(字段级覆盖,undefined 不覆盖)。registry 物化后的模型已把供应商 / 渠道 compat 合进
6
+ * `model.compat`,所以显式配置永远胜过推断。
7
+ *
8
+ * - `sendInterleavedThinkingBeta`:官方端点开;表里的第三方端点关(DeepSeek 文档写明忽略 beta 头,其余
9
+ * 未写明接受,不发未知 beta 头最稳);不在表里的主机(中转)只对 `claude*` 模型开——中转转发 Claude
10
+ * 时仍需要交错思考。
11
+ * - `sendCacheControl`:缺省开;DeepSeek 文档写明 `cache_control` 被忽略,关掉以减小请求体。
12
+ * - `adaptiveThinking` 只由目录 / 配置给(官方模型逐条写在 catalog/anthropic.json),表里不推断。
13
+ * - 缓存保留层级(1h TTL)等缓存能力在 cache-params.ts 的 `HOST_CACHE_CAPABILITIES`,不在这里。
14
+ * - OpenRouter:流式 usage 只出现在 `message_delta`,`applyAnthropicUsage` 本就按非 null 字段合并,
15
+ * 不需要开关(anthropic-compat.test.ts 核对)。
16
+ *
17
+ * 表里每一项都对应厂商文档或实测(docs/research/R1-models-protocols.md §2.1、docs/providers.md「渠道实测」)。
18
+ */
19
+ import type { AnthropicMessagesCompat, Model, ProviderData } from "../types.js";
20
+ export type ResolvedAnthropicCompat = Required<AnthropicMessagesCompat>;
21
+ export declare const ANTHROPIC_COMPAT_KEYS: readonly ["supportsCacheControlOnTools", "supportsTemperatureWithThinking", "adaptiveThinking", "maxCacheBreakpoints", "sendInterleavedThinkingBeta", "sendCacheControl"];
22
+ /** 未知主机的保守缺省(`sendInterleavedThinkingBeta` 另按模型 id 定,见 `hostDefaults`)。 */
23
+ export declare const DEFAULT_ANTHROPIC_COMPAT: Readonly<ResolvedAnthropicCompat>;
24
+ export interface AnthropicHostRule {
25
+ /** 主机名子串(小写)。 */
26
+ host: string;
27
+ patch: Partial<AnthropicMessagesCompat>;
28
+ }
29
+ /** 主机表:先命中先用。 */
30
+ export declare const ANTHROPIC_HOST_RULES: readonly AnthropicHostRule[];
31
+ /** 命中的主机规则(没有返回 undefined)。 */
32
+ export declare function findAnthropicHostRule(baseUrl: string | undefined): AnthropicHostRule | undefined;
33
+ /** 主机推断(不含显式配置)。未知主机:`claude*` 模型发交错思考 beta(中转转发 Claude)。 */
34
+ export declare function hostDefaults(baseUrl: string | undefined, modelId: string): ResolvedAnthropicCompat;
35
+ /** 完整 compat:主机推断 ← provider.compat ← model.compat。 */
36
+ export declare function detectAnthropicCompat(model: Model, provider?: ProviderData): ResolvedAnthropicCompat;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * anthropic-messages 的 compat 推断([W5-M2],docs/wave5-plan.md §3.1、D10):按请求主机给缺省。
3
+ *
4
+ * 顺序:保守缺省 ← 主机表(`model.baseUrl` 的主机名子串,先命中先用)← `provider.compat` ←
5
+ * `model.compat`(字段级覆盖,undefined 不覆盖)。registry 物化后的模型已把供应商 / 渠道 compat 合进
6
+ * `model.compat`,所以显式配置永远胜过推断。
7
+ *
8
+ * - `sendInterleavedThinkingBeta`:官方端点开;表里的第三方端点关(DeepSeek 文档写明忽略 beta 头,其余
9
+ * 未写明接受,不发未知 beta 头最稳);不在表里的主机(中转)只对 `claude*` 模型开——中转转发 Claude
10
+ * 时仍需要交错思考。
11
+ * - `sendCacheControl`:缺省开;DeepSeek 文档写明 `cache_control` 被忽略,关掉以减小请求体。
12
+ * - `adaptiveThinking` 只由目录 / 配置给(官方模型逐条写在 catalog/anthropic.json),表里不推断。
13
+ * - 缓存保留层级(1h TTL)等缓存能力在 cache-params.ts 的 `HOST_CACHE_CAPABILITIES`,不在这里。
14
+ * - OpenRouter:流式 usage 只出现在 `message_delta`,`applyAnthropicUsage` 本就按非 null 字段合并,
15
+ * 不需要开关(anthropic-compat.test.ts 核对)。
16
+ *
17
+ * 表里每一项都对应厂商文档或实测(docs/research/R1-models-protocols.md §2.1、docs/providers.md「渠道实测」)。
18
+ */
19
+ export const ANTHROPIC_COMPAT_KEYS = [
20
+ "supportsCacheControlOnTools",
21
+ "supportsTemperatureWithThinking",
22
+ "adaptiveThinking",
23
+ "maxCacheBreakpoints",
24
+ "sendInterleavedThinkingBeta",
25
+ "sendCacheControl",
26
+ ];
27
+ /** 未知主机的保守缺省(`sendInterleavedThinkingBeta` 另按模型 id 定,见 `hostDefaults`)。 */
28
+ export const DEFAULT_ANTHROPIC_COMPAT = {
29
+ supportsCacheControlOnTools: true,
30
+ supportsTemperatureWithThinking: false,
31
+ adaptiveThinking: false,
32
+ maxCacheBreakpoints: 4,
33
+ sendInterleavedThinkingBeta: false,
34
+ sendCacheControl: true,
35
+ };
36
+ const THIRD_PARTY = { sendInterleavedThinkingBeta: false };
37
+ /** 主机表:先命中先用。 */
38
+ export const ANTHROPIC_HOST_RULES = [
39
+ { host: "api.anthropic.com", patch: { sendInterleavedThinkingBeta: true } },
40
+ {
41
+ host: "api.deepseek.com",
42
+ patch: { sendCacheControl: false, sendInterleavedThinkingBeta: false, adaptiveThinking: false },
43
+ },
44
+ { host: "open.bigmodel.cn", patch: THIRD_PARTY },
45
+ { host: "api.z.ai", patch: THIRD_PARTY },
46
+ { host: "api.moonshot.", patch: THIRD_PARTY },
47
+ { host: "dashscope", patch: THIRD_PARTY },
48
+ { host: "maas.aliyuncs.com", patch: THIRD_PARTY },
49
+ { host: "api.minimax", patch: THIRD_PARTY },
50
+ { host: "api.stepfun.", patch: THIRD_PARTY },
51
+ { host: "tokenhub.tencentmaas.com", patch: THIRD_PARTY },
52
+ { host: "volces.com", patch: THIRD_PARTY },
53
+ // openrouter.ai 不进表:按未知主机处理(anthropic/claude-* 带交错思考 beta)
54
+ ];
55
+ function hostOf(baseUrl) {
56
+ try {
57
+ return new URL(baseUrl ?? "https://api.anthropic.com").hostname.toLowerCase();
58
+ }
59
+ catch {
60
+ return "";
61
+ }
62
+ }
63
+ /** 命中的主机规则(没有返回 undefined)。 */
64
+ export function findAnthropicHostRule(baseUrl) {
65
+ const host = hostOf(baseUrl);
66
+ return host === "" ? undefined : ANTHROPIC_HOST_RULES.find((rule) => host.includes(rule.host));
67
+ }
68
+ /** 主机推断(不含显式配置)。未知主机:`claude*` 模型发交错思考 beta(中转转发 Claude)。 */
69
+ export function hostDefaults(baseUrl, modelId) {
70
+ const rule = findAnthropicHostRule(baseUrl);
71
+ if (rule !== undefined)
72
+ return { ...DEFAULT_ANTHROPIC_COMPAT, ...rule.patch };
73
+ const claude = /(^|\/)claude/i.test(modelId);
74
+ return { ...DEFAULT_ANTHROPIC_COMPAT, sendInterleavedThinkingBeta: claude };
75
+ }
76
+ function pick(compat) {
77
+ const out = {};
78
+ for (const key of ANTHROPIC_COMPAT_KEYS) {
79
+ const value = compat?.[key];
80
+ if (value !== undefined)
81
+ out[key] = value;
82
+ }
83
+ return out;
84
+ }
85
+ /** 完整 compat:主机推断 ← provider.compat ← model.compat。 */
86
+ export function detectAnthropicCompat(model, provider) {
87
+ return {
88
+ ...hostDefaults(model.baseUrl ?? provider?.baseUrl, model.id),
89
+ ...pick(provider?.compat),
90
+ ...pick(model.compat),
91
+ };
92
+ }