@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,407 @@
1
+ /**
2
+ * Codex 原生驱动:`codex app-server`(stdio JSON-RPC,docs/wave5-plan.md §5.1,R2 §1.3)。[W5-E]
3
+ *
4
+ * - `initialize{clientInfo}` → `initialized` 通知 → `thread/start`(或 `thread/resume`,带
5
+ * `excludeTurns` 不回放)→ 每回合 `turn/start`,以对应 turn 的 `turn/completed` 结束;
6
+ * 运行中追加用 `turn/steer{expectedTurnId}`;中断 `turn/interrupt`(15 s 看门狗)。
7
+ * - 审批(服务端请求,只交给人):`item/commandExecution/requestApproval`、
8
+ * `item/fileChange/requestApproval` → accept / acceptForSession / decline(回合取消 → cancel;
9
+ * execpolicy 与网络策略修订会改持久配置,不提供);`item/permissions/requestApproval` →
10
+ * 按人的选择授予本回合 / 本会话或不授予;`item/tool/requestUserInput` 与
11
+ * `mcpServer/elicitation/request` 不代答(错误 / cancel,并发提示)。
12
+ * - 用量:`thread/tokenUsage/updated` 的 `total` 差值记本回合(订阅 token,不换算美元)。
13
+ * - 每个会话一个子进程,不连共享 daemon(隔离清楚)。
14
+ */
15
+ import { AmaError } from "../../errors.js";
16
+ import { AMA_VERSION } from "../../version.js";
17
+ import { armCancelWatchdog, probeCandidate, spawnOf } from "../base.js";
18
+ import { JsonRpcPeer, RpcError } from "../jsonrpc.js";
19
+ import { stderrHint } from "../process.js";
20
+ import { TurnCollector, oneLine } from "../turn.js";
21
+ import { codexDecision, codexPlan, codexPolicy, codexToolEvent, grantedProfile, readTokens, } from "./codex-normalize.js";
22
+ const DECISION_OPTIONS = [
23
+ { optionId: "accept", kind: "allow_once" },
24
+ { optionId: "acceptForSession", kind: "allow_always" },
25
+ { optionId: "decline", kind: "reject_once" },
26
+ ];
27
+ function textInput(content) {
28
+ return content.flatMap((b) => b.type === "text" ? [{ type: "text", text: b.text, text_elements: [] }] : []);
29
+ }
30
+ export class CodexAppServerDriver {
31
+ agentId;
32
+ candidate;
33
+ deps;
34
+ kind = "codex-app-server";
35
+ constructor(agentId, candidate, deps = {}) {
36
+ this.agentId = agentId;
37
+ this.candidate = candidate;
38
+ this.deps = deps;
39
+ }
40
+ probe() {
41
+ return probeCandidate(this.candidate, this.deps);
42
+ }
43
+ async open(options) {
44
+ const probed = await probeCandidate(this.candidate, this.deps);
45
+ const transport = spawnOf(this.deps)({
46
+ program: probed.path ?? this.candidate.program,
47
+ args: this.candidate.args,
48
+ cwd: options.cwd,
49
+ env: options.env,
50
+ });
51
+ const session = new CodexSession(this.agentId, transport, this.deps);
52
+ if (probed.warning !== undefined)
53
+ session.notices.push(probed.warning);
54
+ try {
55
+ await session.start(options);
56
+ }
57
+ catch (error) {
58
+ await session.close();
59
+ if (error instanceof AmaError)
60
+ throw error;
61
+ throw new AmaError("agent_start_failed", `${this.agentId}:app-server 启动失败(${error.message})${stderrHint(transport) !== "" ? `:${stderrHint(transport)}` : ""}`, { cause: error });
62
+ }
63
+ return session;
64
+ }
65
+ }
66
+ class CodexSession {
67
+ agentId;
68
+ transport;
69
+ deps;
70
+ notices = [];
71
+ peer;
72
+ threadId = "";
73
+ turnId;
74
+ turn;
75
+ hooks;
76
+ finishTurn;
77
+ running;
78
+ permissions = new Set();
79
+ /** fileChange 条目的路径(审批请求只带 itemId)。 */
80
+ itemPaths = new Map();
81
+ messages = new Map();
82
+ tokensTotal;
83
+ tokensAtStart;
84
+ contextWindow;
85
+ closed = false;
86
+ interruptRequested = false;
87
+ constructor(agentId, transport, deps) {
88
+ this.agentId = agentId;
89
+ this.transport = transport;
90
+ this.deps = deps;
91
+ this.peer = new JsonRpcPeer({
92
+ input: transport.stdout,
93
+ output: transport.stdin,
94
+ jsonrpcField: false,
95
+ onRequest: (method, params) => this.onServerRequest(method, (params ?? {})),
96
+ onNotification: (method, params) => this.onNotification(method, (params ?? {})),
97
+ onClose: () => {
98
+ for (const c of this.permissions)
99
+ c.abort();
100
+ },
101
+ });
102
+ }
103
+ get sessionId() {
104
+ return this.threadId;
105
+ }
106
+ async start(options) {
107
+ const signal = options.signal;
108
+ await this.peer.request("initialize", {
109
+ clientInfo: { name: "ama", title: "ama", version: AMA_VERSION },
110
+ capabilities: { experimentalApi: false, requestAttestation: false },
111
+ }, signal);
112
+ await this.peer.notify("initialized");
113
+ const policy = codexPolicy(options.mode, options.unattended === true);
114
+ const common = {
115
+ cwd: options.cwd,
116
+ ...policy,
117
+ ...(options.model !== undefined ? { model: options.model } : {}),
118
+ };
119
+ if (options.resume !== undefined) {
120
+ try {
121
+ const resumed = await this.peer.request("thread/resume", { threadId: options.resume, excludeTurns: true, ...common }, signal);
122
+ this.threadId = resumed.thread?.id ?? options.resume;
123
+ return;
124
+ }
125
+ catch (error) {
126
+ if (signal.aborted || !(error instanceof RpcError))
127
+ throw error;
128
+ this.notices.push(`${this.agentId} 找不到会话 ${options.resume},已新开`);
129
+ }
130
+ }
131
+ const started = await this.peer.request("thread/start", common, signal);
132
+ const id = started.thread?.id;
133
+ if (typeof id !== "string" || id === "")
134
+ throw new Error("thread/start 没有返回 thread.id");
135
+ this.threadId = id;
136
+ }
137
+ async prompt(content, hooks) {
138
+ if (this.closed || !this.peer.isOpen)
139
+ throw new AmaError("agent_closed", `${this.agentId} 会话已关闭`);
140
+ if (this.running !== undefined)
141
+ throw new AmaError("busy", `${this.agentId} 正在运行`);
142
+ const turn = new TurnCollector((e) => hooks.onEvent(e));
143
+ for (const text of this.notices.splice(0))
144
+ turn.push({ type: "notice", level: "info", text });
145
+ if (content.some((b) => b.type === "image"))
146
+ turn.push({ type: "notice", level: "warn", text: `${this.agentId} 驱动暂不传图片,已省略` });
147
+ this.turn = turn;
148
+ this.hooks = hooks;
149
+ this.messages.clear();
150
+ this.tokensAtStart = this.tokensTotal;
151
+ this.interruptRequested = false;
152
+ const completed = new Promise((resolve) => (this.finishTurn = resolve));
153
+ const closed = this.peer.closed.then(() => {
154
+ throw new AmaError("agent_exited", `${this.agentId} 进程已退出${stderrHint(this.transport) !== "" ? `:${stderrHint(this.transport)}` : ""}`);
155
+ });
156
+ void closed.catch(() => undefined);
157
+ this.running = (async () => {
158
+ const response = await Promise.race([
159
+ this.peer.request("turn/start", {
160
+ threadId: this.threadId,
161
+ input: textInput(content),
162
+ }),
163
+ closed,
164
+ ]);
165
+ if (typeof response.turn?.id === "string")
166
+ this.setTurnId(response.turn.id);
167
+ const done = await Promise.race([completed, closed]);
168
+ return this.complete(done, turn);
169
+ })();
170
+ try {
171
+ return await this.running;
172
+ }
173
+ finally {
174
+ this.running = undefined;
175
+ this.turn = undefined;
176
+ this.hooks = undefined;
177
+ this.turnId = undefined;
178
+ this.finishTurn = undefined;
179
+ }
180
+ }
181
+ async steer(content) {
182
+ if (this.turnId === undefined)
183
+ throw new AmaError("not_running", `${this.agentId} 没有进行中的回合`);
184
+ await this.peer.request("turn/steer", {
185
+ threadId: this.threadId,
186
+ input: textInput(content),
187
+ expectedTurnId: this.turnId,
188
+ });
189
+ }
190
+ async cancel() {
191
+ const running = this.running;
192
+ if (running === undefined || this.closed)
193
+ return;
194
+ for (const c of this.permissions)
195
+ c.abort();
196
+ this.interruptRequested = true;
197
+ if (this.turnId !== undefined)
198
+ this.sendInterrupt(this.turnId);
199
+ armCancelWatchdog(this.transport, running.catch(() => undefined), this.deps);
200
+ }
201
+ async close() {
202
+ if (this.closed)
203
+ return;
204
+ this.closed = true;
205
+ for (const c of this.permissions)
206
+ c.abort();
207
+ this.peer.close();
208
+ await this.transport.terminate();
209
+ }
210
+ /** turn id 可能先从通知 / 服务端请求里知道(早于 turn/start 的响应被处理)。 */
211
+ setTurnId(id) {
212
+ if (this.running === undefined || this.turnId !== undefined)
213
+ return;
214
+ this.turnId = id;
215
+ if (this.interruptRequested)
216
+ this.sendInterrupt(id);
217
+ }
218
+ sendInterrupt(turnId) {
219
+ void this.peer
220
+ .request("turn/interrupt", { threadId: this.threadId, turnId })
221
+ .catch(() => undefined);
222
+ }
223
+ complete(turnInfo, turn) {
224
+ const start = this.tokensAtStart;
225
+ const end = this.tokensTotal;
226
+ if (end !== undefined) {
227
+ turn.push({
228
+ type: "usage",
229
+ input: end.inputTokens - (start?.inputTokens ?? 0),
230
+ output: end.outputTokens - (start?.outputTokens ?? 0),
231
+ cacheRead: end.cachedInputTokens - (start?.cachedInputTokens ?? 0),
232
+ ...(this.contextWindow !== undefined ? { contextWindow: this.contextWindow } : {}),
233
+ });
234
+ }
235
+ const last = [...this.messages.values()].at(-1);
236
+ if (last !== undefined)
237
+ turn.setFinalText(last);
238
+ const status = turnInfo["status"];
239
+ if (status === "interrupted")
240
+ return turn.result("cancelled");
241
+ if (status === "failed") {
242
+ const error = (turnInfo["error"] ?? {});
243
+ throw new AmaError("agent_failed", `${this.agentId} 回合失败:${oneLine(String(error["message"] ?? "unknown"), 300)}`);
244
+ }
245
+ return turn.result("end_turn");
246
+ }
247
+ onNotification(method, params) {
248
+ const turn = this.turn;
249
+ switch (method) {
250
+ case "thread/tokenUsage/updated": {
251
+ const usage = (params["tokenUsage"] ?? {});
252
+ const total = readTokens(usage["total"]);
253
+ if (total !== undefined)
254
+ this.tokensTotal = total;
255
+ if (typeof usage["modelContextWindow"] === "number")
256
+ this.contextWindow = usage["modelContextWindow"];
257
+ return;
258
+ }
259
+ case "turn/started": {
260
+ const id = (params["turn"] ?? {})["id"];
261
+ if (typeof id === "string")
262
+ this.setTurnId(id);
263
+ return;
264
+ }
265
+ case "turn/completed": {
266
+ const info = (params["turn"] ?? {});
267
+ if (this.turnId === undefined || info["id"] === this.turnId)
268
+ this.finishTurn?.(info);
269
+ return;
270
+ }
271
+ default:
272
+ break;
273
+ }
274
+ if (turn === undefined)
275
+ return;
276
+ switch (method) {
277
+ case "item/agentMessage/delta": {
278
+ const delta = String(params["delta"] ?? "");
279
+ const id = String(params["itemId"] ?? "");
280
+ this.messages.set(id, (this.messages.get(id) ?? "") + delta);
281
+ turn.push({ type: "message_delta", text: delta });
282
+ return;
283
+ }
284
+ case "item/reasoning/summaryTextDelta":
285
+ case "item/reasoning/textDelta":
286
+ turn.push({ type: "thought_delta", text: String(params["delta"] ?? "") });
287
+ return;
288
+ case "item/started":
289
+ case "item/completed": {
290
+ const item = (params["item"] ?? {});
291
+ if (item["type"] === "agentMessage" && method === "item/completed") {
292
+ this.messages.set(String(item["id"]), String(item["text"] ?? ""));
293
+ return;
294
+ }
295
+ const event = codexToolEvent(item, method === "item/started" ? "started" : "completed");
296
+ if (event === undefined)
297
+ return;
298
+ if (event.locations !== undefined)
299
+ this.itemPaths.set(event.id, event.locations);
300
+ turn.push(event);
301
+ return;
302
+ }
303
+ case "turn/plan/updated": {
304
+ const plan = codexPlan(params);
305
+ if (plan !== undefined)
306
+ turn.push(plan);
307
+ return;
308
+ }
309
+ case "error": {
310
+ const error = (params["error"] ?? {});
311
+ turn.push({
312
+ type: "notice",
313
+ level: "warn",
314
+ text: `${this.agentId}:${oneLine(String(error["message"] ?? "error"), 200)}${params["willRetry"] === true ? "(重试中)" : ""}`,
315
+ });
316
+ return;
317
+ }
318
+ default:
319
+ return;
320
+ }
321
+ }
322
+ async ask(request) {
323
+ const hooks = this.hooks;
324
+ if (hooks === undefined || this.closed)
325
+ return undefined;
326
+ const controller = new AbortController();
327
+ this.permissions.add(controller);
328
+ try {
329
+ const outcome = await hooks.onPermission(request, controller.signal);
330
+ return outcome.outcome === "selected" && !controller.signal.aborted
331
+ ? outcome.optionId
332
+ : undefined;
333
+ }
334
+ finally {
335
+ this.permissions.delete(controller);
336
+ }
337
+ }
338
+ async onServerRequest(method, params) {
339
+ if (typeof params["turnId"] === "string")
340
+ this.setTurnId(params["turnId"]);
341
+ switch (method) {
342
+ case "item/commandExecution/requestApproval": {
343
+ const command = String(params["command"] ?? "");
344
+ const reason = typeof params["reason"] === "string" ? ` — ${params["reason"]}` : "";
345
+ const cwd = typeof params["cwd"] === "string" ? [params["cwd"]] : undefined;
346
+ const answer = await this.ask({
347
+ toolCall: {
348
+ title: `$ ${oneLine(command, 100)}`,
349
+ kind: "execute",
350
+ ...(cwd !== undefined ? { locations: cwd } : {}),
351
+ inputSummary: oneLine(`${command}${reason}`, 300),
352
+ },
353
+ options: DECISION_OPTIONS,
354
+ });
355
+ return { decision: codexDecision(answer) };
356
+ }
357
+ case "item/fileChange/requestApproval": {
358
+ const paths = this.itemPaths.get(String(params["itemId"] ?? "")) ?? [];
359
+ const reason = typeof params["reason"] === "string" ? params["reason"] : "";
360
+ const answer = await this.ask({
361
+ toolCall: {
362
+ title: paths.length > 0 ? `edit ${paths.join(", ")}` : "edit files",
363
+ kind: "edit",
364
+ ...(paths.length > 0 ? { locations: paths } : {}),
365
+ ...(reason !== "" ? { inputSummary: oneLine(reason, 300) } : {}),
366
+ },
367
+ options: DECISION_OPTIONS,
368
+ });
369
+ return { decision: codexDecision(answer) };
370
+ }
371
+ case "item/permissions/requestApproval": {
372
+ const reason = typeof params["reason"] === "string" ? params["reason"] : "";
373
+ const answer = await this.ask({
374
+ toolCall: {
375
+ title: "request additional permissions",
376
+ kind: "other",
377
+ inputSummary: oneLine(`${JSON.stringify(params["permissions"] ?? {})} ${reason}`, 300),
378
+ },
379
+ options: [
380
+ { optionId: "turn", kind: "allow_once" },
381
+ { optionId: "session", kind: "allow_always" },
382
+ { optionId: "deny", kind: "reject_once" },
383
+ ],
384
+ });
385
+ if (answer === "turn" || answer === "session")
386
+ return { permissions: grantedProfile(params["permissions"]), scope: answer };
387
+ return { permissions: {}, scope: "turn" };
388
+ }
389
+ case "item/tool/requestUserInput":
390
+ this.turn?.push({
391
+ type: "notice",
392
+ level: "warn",
393
+ text: `${this.agentId} 想向你提问;ama 不代答,请让它把问题写进最终回复`,
394
+ });
395
+ throw new RpcError(-32601, "The coordinator cannot relay interactive questions");
396
+ case "mcpServer/elicitation/request":
397
+ this.turn?.push({
398
+ type: "notice",
399
+ level: "warn",
400
+ text: `${this.agentId} 的 MCP 服务器请求输入;ama 不代答,已取消`,
401
+ });
402
+ return { action: "cancel", content: null, _meta: null };
403
+ default:
404
+ throw new RpcError(-32601, `ama does not handle ${method}`);
405
+ }
406
+ }
407
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Codex app-server(0.160.x,`[experimental]`)↔ ama 的映射(docs/wave5-plan.md §5.1 normalize,
3
+ * R2 §1.3)。[W5-E]
4
+ *
5
+ * 只依赖 `test/fixtures/drivers/codex-schema/shapes.json` 锁住的方法与字段(12 个方法 + 5 类审批
6
+ * 请求);线上不写 `"jsonrpc"` 字段。
7
+ */
8
+ import type { PermissionMode } from "../../permissions/types.js";
9
+ import type { DriverEvent } from "../types.js";
10
+ export type CodexApprovalPolicy = "untrusted" | "on-request" | "never";
11
+ export type CodexSandbox = "read-only" | "workspace-write" | "danger-full-access";
12
+ /**
13
+ * ama 模式 → Codex `approvalPolicy` + `sandbox`。从不给 `danger-full-access`;
14
+ * 无人值守一律 `never`(不发审批请求,越权的操作由沙箱拒绝后交回模型)。
15
+ */
16
+ export declare function codexPolicy(mode: PermissionMode, unattended: boolean): {
17
+ approvalPolicy: CodexApprovalPolicy;
18
+ sandbox: CodexSandbox;
19
+ };
20
+ type Json = Record<string, unknown>;
21
+ /** ThreadItem → tool_call(非工具类条目返回 undefined)。 */
22
+ export declare function codexToolEvent(item: Json, phase: "started" | "completed"): Extract<DriverEvent, {
23
+ type: "tool_call";
24
+ }> | undefined;
25
+ /** turn/plan/updated → plan。 */
26
+ export declare function codexPlan(params: Json): DriverEvent | undefined;
27
+ export interface CodexTokens {
28
+ totalTokens: number;
29
+ inputTokens: number;
30
+ cachedInputTokens: number;
31
+ outputTokens: number;
32
+ }
33
+ export declare function readTokens(value: unknown): CodexTokens | undefined;
34
+ /** 审批决定(ACP 词汇 → Codex);execpolicy 修订是持久配置变更,不提供。 */
35
+ export declare function codexDecision(optionId: string | undefined): "accept" | "acceptForSession" | "decline" | "cancel";
36
+ /** 去掉 null 字段(`RequestPermissionProfile` → `GrantedPermissionProfile`)。 */
37
+ export declare function grantedProfile(permissions: unknown): Json;
38
+ export {};
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Codex app-server(0.160.x,`[experimental]`)↔ ama 的映射(docs/wave5-plan.md §5.1 normalize,
3
+ * R2 §1.3)。[W5-E]
4
+ *
5
+ * 只依赖 `test/fixtures/drivers/codex-schema/shapes.json` 锁住的方法与字段(12 个方法 + 5 类审批
6
+ * 请求);线上不写 `"jsonrpc"` 字段。
7
+ */
8
+ import { oneLine } from "../turn.js";
9
+ /**
10
+ * ama 模式 → Codex `approvalPolicy` + `sandbox`。从不给 `danger-full-access`;
11
+ * 无人值守一律 `never`(不发审批请求,越权的操作由沙箱拒绝后交回模型)。
12
+ */
13
+ export function codexPolicy(mode, unattended) {
14
+ const base = (() => {
15
+ switch (mode) {
16
+ case "plan":
17
+ case "allowlist":
18
+ return { approvalPolicy: "never", sandbox: "read-only" };
19
+ case "default":
20
+ // 写文件 / 越过只读沙箱都要先问人(≈ ama default 的「写与执行要问」)
21
+ return { approvalPolicy: "on-request", sandbox: "read-only" };
22
+ case "auto-edit":
23
+ return { approvalPolicy: "untrusted", sandbox: "workspace-write" };
24
+ case "auto":
25
+ return { approvalPolicy: "on-request", sandbox: "workspace-write" };
26
+ case "full-auto":
27
+ return { approvalPolicy: "never", sandbox: "workspace-write" };
28
+ }
29
+ })();
30
+ return unattended ? { ...base, approvalPolicy: "never" } : base;
31
+ }
32
+ /** ThreadItem → tool_call(非工具类条目返回 undefined)。 */
33
+ export function codexToolEvent(item, phase) {
34
+ const id = String(item["id"] ?? "");
35
+ const type = item["type"];
36
+ let kind;
37
+ let title;
38
+ let locations;
39
+ switch (type) {
40
+ case "commandExecution":
41
+ kind = "execute";
42
+ title = `$ ${oneLine(String(item["command"] ?? ""), 100)}`;
43
+ break;
44
+ case "fileChange": {
45
+ kind = "edit";
46
+ const changes = Array.isArray(item["changes"]) ? item["changes"] : [];
47
+ locations = changes.map((c) => String(c["path"] ?? "")).filter((p) => p !== "");
48
+ title = locations.length > 0 ? `edit ${locations.join(", ")}` : "edit";
49
+ break;
50
+ }
51
+ case "mcpToolCall":
52
+ kind = "other";
53
+ title = `${String(item["server"] ?? "mcp")}.${String(item["tool"] ?? "tool")}`;
54
+ break;
55
+ case "dynamicToolCall":
56
+ kind = "other";
57
+ title = String(item["tool"] ?? "tool");
58
+ break;
59
+ case "webSearch":
60
+ kind = "fetch";
61
+ title = `search ${oneLine(String(item["query"] ?? ""), 80)}`;
62
+ break;
63
+ default:
64
+ return undefined;
65
+ }
66
+ const status = String(item["status"] ?? "");
67
+ const failed = status === "failed" || status === "declined";
68
+ return {
69
+ type: "tool_call",
70
+ id,
71
+ title,
72
+ kind,
73
+ status: phase === "started" ? "in_progress" : failed ? "failed" : "completed",
74
+ ...(locations !== undefined && locations.length > 0 ? { locations } : {}),
75
+ };
76
+ }
77
+ /** turn/plan/updated → plan。 */
78
+ export function codexPlan(params) {
79
+ const plan = params["plan"];
80
+ if (!Array.isArray(plan))
81
+ return undefined;
82
+ return {
83
+ type: "plan",
84
+ entries: plan.map((s) => ({
85
+ content: String(s["step"] ?? ""),
86
+ status: String(s["status"] ?? "pending"),
87
+ })),
88
+ };
89
+ }
90
+ export function readTokens(value) {
91
+ if (value === null || typeof value !== "object")
92
+ return undefined;
93
+ const v = value;
94
+ const num = (k) => (typeof v[k] === "number" ? v[k] : 0);
95
+ return {
96
+ totalTokens: num("totalTokens"),
97
+ inputTokens: num("inputTokens"),
98
+ cachedInputTokens: num("cachedInputTokens"),
99
+ outputTokens: num("outputTokens"),
100
+ };
101
+ }
102
+ /** 审批决定(ACP 词汇 → Codex);execpolicy 修订是持久配置变更,不提供。 */
103
+ export function codexDecision(optionId) {
104
+ switch (optionId) {
105
+ case "accept":
106
+ return "accept";
107
+ case "acceptForSession":
108
+ return "acceptForSession";
109
+ case "decline":
110
+ return "decline";
111
+ default:
112
+ return "cancel";
113
+ }
114
+ }
115
+ /** 去掉 null 字段(`RequestPermissionProfile` → `GrantedPermissionProfile`)。 */
116
+ export function grantedProfile(permissions) {
117
+ if (permissions === null || typeof permissions !== "object")
118
+ return {};
119
+ const out = {};
120
+ for (const [k, v] of Object.entries(permissions))
121
+ if (v !== null && v !== undefined)
122
+ out[k] = v;
123
+ return out;
124
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 一次性打印模式兜底(docs/wave5-plan.md §5.1 oneshot.ts)。[W5-E]
3
+ *
4
+ * `claude -p --output-format json`、`codex exec --json`、`gemini -p --output-format stream-json`:
5
+ * **不能审批**(能力 `permissions: "none"`),所以只在只读任务下用——open 时模式不是
6
+ * plan / allowlist 直接拒绝;子进程一律以只读方式启动(Claude `--permission-mode plan
7
+ * --permission-prompts none`,Codex `sandbox_mode="read-only"` + `approval_policy="never"`,
8
+ * Gemini `--approval-mode default`,无头时需要批准的工具不可用;未实测)。每回合起一个进程,提示从 stdin 给(Gemini 走 `-p` 参数);
9
+ * 续聊用各 CLI 自己的 resume。中断 = 结束进程树。
10
+ */
11
+ import { type DriverDeps } from "../base.js";
12
+ import type { CatalogCandidate } from "../catalog.js";
13
+ import type { AgentDriver, DriverOpenOptions, DriverProbe, DriverSession } from "../types.js";
14
+ type Dialect = NonNullable<CatalogCandidate["oneshot"]>;
15
+ export declare function oneshotArgs(dialect: Dialect, options: Pick<DriverOpenOptions, "model" | "budgetUsd">, session: {
16
+ id: string;
17
+ resume: boolean;
18
+ }, prompt: string): string[];
19
+ export declare class OneshotDriver implements AgentDriver {
20
+ readonly agentId: string;
21
+ private readonly candidate;
22
+ private readonly deps;
23
+ readonly kind: "oneshot";
24
+ constructor(agentId: string, candidate: CatalogCandidate, deps?: DriverDeps);
25
+ probe(): Promise<DriverProbe>;
26
+ open(options: DriverOpenOptions): Promise<DriverSession>;
27
+ }
28
+ export {};