@armadra/agent 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +470 -2
  4. package/dist/agent/agent.d.ts +56 -0
  5. package/dist/agent/agent.js +129 -0
  6. package/dist/agent/loop.d.ts +51 -0
  7. package/dist/agent/loop.js +158 -0
  8. package/dist/agent/queue.d.ts +25 -0
  9. package/dist/agent/queue.js +55 -0
  10. package/dist/agent/retry.d.ts +22 -0
  11. package/dist/agent/retry.js +92 -0
  12. package/dist/agent/schema.d.ts +27 -0
  13. package/dist/agent/schema.js +186 -0
  14. package/dist/agent/session-cache.d.ts +100 -0
  15. package/dist/agent/session-cache.js +514 -0
  16. package/dist/agent/session-compaction.d.ts +49 -0
  17. package/dist/agent/session-compaction.js +251 -0
  18. package/dist/agent/session-core.d.ts +103 -0
  19. package/dist/agent/session-core.js +7 -0
  20. package/dist/agent/session-run.d.ts +55 -0
  21. package/dist/agent/session-run.js +246 -0
  22. package/dist/agent/session-state.d.ts +39 -0
  23. package/dist/agent/session-state.js +119 -0
  24. package/dist/agent/session-subagent.d.ts +54 -0
  25. package/dist/agent/session-subagent.js +157 -0
  26. package/dist/agent/session-sync.d.ts +20 -0
  27. package/dist/agent/session-sync.js +111 -0
  28. package/dist/agent/session-tools.d.ts +24 -0
  29. package/dist/agent/session-tools.js +277 -0
  30. package/dist/agent/session.d.ts +117 -0
  31. package/dist/agent/session.js +485 -0
  32. package/dist/agent/system-prompt.d.ts +49 -0
  33. package/dist/agent/system-prompt.js +121 -0
  34. package/dist/agent/tool-runner.d.ts +64 -0
  35. package/dist/agent/tool-runner.js +309 -0
  36. package/dist/agent/transform.d.ts +26 -0
  37. package/dist/agent/transform.js +171 -0
  38. package/dist/agent/types.d.ts +378 -0
  39. package/dist/agent/types.js +21 -0
  40. package/dist/ai/apis/anthropic-messages.d.ts +26 -0
  41. package/dist/ai/apis/anthropic-messages.js +214 -0
  42. package/dist/ai/apis/anthropic-request.d.ts +42 -0
  43. package/dist/ai/apis/anthropic-request.js +282 -0
  44. package/dist/ai/apis/api.d.ts +28 -0
  45. package/dist/ai/apis/api.js +102 -0
  46. package/dist/ai/apis/cache-params.d.ts +48 -0
  47. package/dist/ai/apis/cache-params.js +163 -0
  48. package/dist/ai/apis/google-generative-ai.d.ts +32 -0
  49. package/dist/ai/apis/google-generative-ai.js +249 -0
  50. package/dist/ai/apis/google-request.d.ts +40 -0
  51. package/dist/ai/apis/google-request.js +255 -0
  52. package/dist/ai/apis/openai-compat.d.ts +35 -0
  53. package/dist/ai/apis/openai-compat.js +142 -0
  54. package/dist/ai/apis/openai-completions.d.ts +28 -0
  55. package/dist/ai/apis/openai-completions.js +246 -0
  56. package/dist/ai/apis/openai-request.d.ts +35 -0
  57. package/dist/ai/apis/openai-request.js +303 -0
  58. package/dist/ai/apis/openai-responses-request.d.ts +52 -0
  59. package/dist/ai/apis/openai-responses-request.js +266 -0
  60. package/dist/ai/apis/openai-responses.d.ts +28 -0
  61. package/dist/ai/apis/openai-responses.js +304 -0
  62. package/dist/ai/apis/shared.d.ts +56 -0
  63. package/dist/ai/apis/shared.js +179 -0
  64. package/dist/ai/cache/economics.d.ts +24 -0
  65. package/dist/ai/cache/economics.js +69 -0
  66. package/dist/ai/cache/fingerprint.d.ts +17 -0
  67. package/dist/ai/cache/fingerprint.js +39 -0
  68. package/dist/ai/cache/miss.d.ts +49 -0
  69. package/dist/ai/cache/miss.js +96 -0
  70. package/dist/ai/cache/reporting.d.ts +39 -0
  71. package/dist/ai/cache/reporting.js +103 -0
  72. package/dist/ai/cache/types.d.ts +94 -0
  73. package/dist/ai/cache/types.js +19 -0
  74. package/dist/ai/cache/warmer.d.ts +94 -0
  75. package/dist/ai/cache/warmer.js +224 -0
  76. package/dist/ai/context.d.ts +35 -0
  77. package/dist/ai/context.js +114 -0
  78. package/dist/ai/cost.d.ts +21 -0
  79. package/dist/ai/cost.js +60 -0
  80. package/dist/ai/event-stream.d.ts +33 -0
  81. package/dist/ai/event-stream.js +101 -0
  82. package/dist/ai/fake/fake-provider.d.ts +68 -0
  83. package/dist/ai/fake/fake-provider.js +278 -0
  84. package/dist/ai/fake/fake-script.d.ts +69 -0
  85. package/dist/ai/fake/fake-script.js +142 -0
  86. package/dist/ai/http.d.ts +54 -0
  87. package/dist/ai/http.js +212 -0
  88. package/dist/ai/json-partial.d.ts +17 -0
  89. package/dist/ai/json-partial.js +243 -0
  90. package/dist/ai/overflow.d.ts +22 -0
  91. package/dist/ai/overflow.js +61 -0
  92. package/dist/ai/providers/auth.d.ts +71 -0
  93. package/dist/ai/providers/auth.js +202 -0
  94. package/dist/ai/providers/builtin.d.ts +23 -0
  95. package/dist/ai/providers/builtin.js +148 -0
  96. package/dist/ai/providers/catalog-data.d.ts +5 -0
  97. package/dist/ai/providers/catalog-data.js +19 -0
  98. package/dist/ai/providers/catalog.d.ts +28 -0
  99. package/dist/ai/providers/catalog.js +166 -0
  100. package/dist/ai/providers/channels.d.ts +51 -0
  101. package/dist/ai/providers/channels.js +96 -0
  102. package/dist/ai/providers/enrich.d.ts +34 -0
  103. package/dist/ai/providers/enrich.js +86 -0
  104. package/dist/ai/providers/models-dev-cache.d.ts +53 -0
  105. package/dist/ai/providers/models-dev-cache.js +147 -0
  106. package/dist/ai/providers/models-dev.d.ts +99 -0
  107. package/dist/ai/providers/models-dev.js +315 -0
  108. package/dist/ai/providers/registry.d.ts +114 -0
  109. package/dist/ai/providers/registry.js +458 -0
  110. package/dist/ai/sse.d.ts +32 -0
  111. package/dist/ai/sse.js +140 -0
  112. package/dist/ai/thinking.d.ts +42 -0
  113. package/dist/ai/thinking.js +101 -0
  114. package/dist/ai/types.d.ts +448 -0
  115. package/dist/ai/types.js +19 -0
  116. package/dist/bundle/ama-sandbox.cjs +324 -0
  117. package/dist/bundle/ama.cjs +27837 -0
  118. package/dist/bundle.d.ts +9 -0
  119. package/dist/bundle.js +15 -0
  120. package/dist/cli/args.d.ts +85 -0
  121. package/dist/cli/args.js +408 -0
  122. package/dist/cli/bootstrap.d.ts +18 -0
  123. package/dist/cli/bootstrap.js +399 -0
  124. package/dist/cli/compose-providers.d.ts +37 -0
  125. package/dist/cli/compose-providers.js +107 -0
  126. package/dist/cli/compose-session.d.ts +72 -0
  127. package/dist/cli/compose-session.js +370 -0
  128. package/dist/cli/compose-store.d.ts +24 -0
  129. package/dist/cli/compose-store.js +125 -0
  130. package/dist/cli/compose.d.ts +108 -0
  131. package/dist/cli/compose.js +221 -0
  132. package/dist/cli/default-model.d.ts +16 -0
  133. package/dist/cli/default-model.js +24 -0
  134. package/dist/cli/deps.d.ts +207 -0
  135. package/dist/cli/deps.js +12 -0
  136. package/dist/cli/exit-codes.d.ts +29 -0
  137. package/dist/cli/exit-codes.js +40 -0
  138. package/dist/cli/main.d.ts +27 -0
  139. package/dist/cli/main.js +177 -0
  140. package/dist/cli/runtime.d.ts +90 -0
  141. package/dist/cli/runtime.js +8 -0
  142. package/dist/cli/startup-screen.d.ts +15 -0
  143. package/dist/cli/startup-screen.js +56 -0
  144. package/dist/cli/startup-steps.d.ts +35 -0
  145. package/dist/cli/startup-steps.js +202 -0
  146. package/dist/cli/subcommands/auth.d.ts +12 -0
  147. package/dist/cli/subcommands/auth.js +91 -0
  148. package/dist/cli/subcommands/config.d.ts +53 -0
  149. package/dist/cli/subcommands/config.js +277 -0
  150. package/dist/cli/subcommands/context.d.ts +21 -0
  151. package/dist/cli/subcommands/context.js +42 -0
  152. package/dist/cli/subcommands/doctor.d.ts +11 -0
  153. package/dist/cli/subcommands/doctor.js +246 -0
  154. package/dist/cli/subcommands/init.d.ts +6 -0
  155. package/dist/cli/subcommands/init.js +22 -0
  156. package/dist/cli/subcommands/model-meta.d.ts +16 -0
  157. package/dist/cli/subcommands/model-meta.js +54 -0
  158. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  159. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  160. package/dist/cli/subcommands/models-discover.d.ts +46 -0
  161. package/dist/cli/subcommands/models-discover.js +232 -0
  162. package/dist/cli/subcommands/models.d.ts +40 -0
  163. package/dist/cli/subcommands/models.js +152 -0
  164. package/dist/cli/subcommands/providers-list.d.ts +8 -0
  165. package/dist/cli/subcommands/providers-list.js +97 -0
  166. package/dist/cli/subcommands/providers-plan.d.ts +79 -0
  167. package/dist/cli/subcommands/providers-plan.js +215 -0
  168. package/dist/cli/subcommands/providers.d.ts +27 -0
  169. package/dist/cli/subcommands/providers.js +433 -0
  170. package/dist/cli/subcommands/sessions.d.ts +11 -0
  171. package/dist/cli/subcommands/sessions.js +100 -0
  172. package/dist/codemode/capability.d.ts +37 -0
  173. package/dist/codemode/capability.js +55 -0
  174. package/dist/codemode/declarations.d.ts +44 -0
  175. package/dist/codemode/declarations.js +111 -0
  176. package/dist/codemode/host-side.d.ts +59 -0
  177. package/dist/codemode/host-side.js +253 -0
  178. package/dist/codemode/modes.d.ts +23 -0
  179. package/dist/codemode/modes.js +40 -0
  180. package/dist/codemode/protocol.d.ts +91 -0
  181. package/dist/codemode/protocol.js +114 -0
  182. package/dist/codemode/sandbox-entry.d.ts +25 -0
  183. package/dist/codemode/sandbox-entry.js +323 -0
  184. package/dist/codemode/store.d.ts +26 -0
  185. package/dist/codemode/store.js +53 -0
  186. package/dist/codemode/tool.d.ts +105 -0
  187. package/dist/codemode/tool.js +283 -0
  188. package/dist/compaction/branch-summary.d.ts +30 -0
  189. package/dist/compaction/branch-summary.js +79 -0
  190. package/dist/compaction/breaker.d.ts +32 -0
  191. package/dist/compaction/breaker.js +65 -0
  192. package/dist/compaction/cut-point.d.ts +23 -0
  193. package/dist/compaction/cut-point.js +70 -0
  194. package/dist/compaction/estimate.d.ts +30 -0
  195. package/dist/compaction/estimate.js +114 -0
  196. package/dist/compaction/prune-tier.d.ts +31 -0
  197. package/dist/compaction/prune-tier.js +83 -0
  198. package/dist/compaction/serialize.d.ts +20 -0
  199. package/dist/compaction/serialize.js +115 -0
  200. package/dist/compaction/summarize-tier.d.ts +111 -0
  201. package/dist/compaction/summarize-tier.js +305 -0
  202. package/dist/config/auth-file.d.ts +39 -0
  203. package/dist/config/auth-file.js +92 -0
  204. package/dist/config/context-files.d.ts +30 -0
  205. package/dist/config/context-files.js +77 -0
  206. package/dist/config/init.d.ts +30 -0
  207. package/dist/config/init.js +92 -0
  208. package/dist/config/json-schema.d.ts +14 -0
  209. package/dist/config/json-schema.js +182 -0
  210. package/dist/config/load.d.ts +45 -0
  211. package/dist/config/load.js +97 -0
  212. package/dist/config/merge.d.ts +73 -0
  213. package/dist/config/merge.js +248 -0
  214. package/dist/config/paths.d.ts +38 -0
  215. package/dist/config/paths.js +108 -0
  216. package/dist/config/profile.d.ts +27 -0
  217. package/dist/config/profile.js +65 -0
  218. package/dist/config/schema.d.ts +34 -0
  219. package/dist/config/schema.js +476 -0
  220. package/dist/config/trust.d.ts +42 -0
  221. package/dist/config/trust.js +122 -0
  222. package/dist/config/types.d.ts +190 -0
  223. package/dist/config/types.js +29 -0
  224. package/dist/config/write.d.ts +10 -0
  225. package/dist/config/write.js +25 -0
  226. package/dist/errors.d.ts +28 -0
  227. package/dist/errors.js +30 -0
  228. package/dist/hooks/config.d.ts +49 -0
  229. package/dist/hooks/config.js +102 -0
  230. package/dist/hooks/dispatcher.d.ts +41 -0
  231. package/dist/hooks/dispatcher.js +104 -0
  232. package/dist/hooks/matcher.d.ts +22 -0
  233. package/dist/hooks/matcher.js +108 -0
  234. package/dist/hooks/protocol.d.ts +33 -0
  235. package/dist/hooks/protocol.js +240 -0
  236. package/dist/hooks/runner.d.ts +30 -0
  237. package/dist/hooks/runner.js +143 -0
  238. package/dist/hooks/types.d.ts +147 -0
  239. package/dist/hooks/types.js +20 -0
  240. package/dist/host/api-impl.d.ts +75 -0
  241. package/dist/host/api-impl.js +173 -0
  242. package/dist/host/loader.d.ts +31 -0
  243. package/dist/host/loader.js +147 -0
  244. package/dist/host/types.d.ts +169 -0
  245. package/dist/host/types.js +14 -0
  246. package/dist/host.d.ts +5 -0
  247. package/dist/host.js +4 -0
  248. package/dist/index.d.ts +41 -0
  249. package/dist/index.js +28 -0
  250. package/dist/modes/commands-core.d.ts +44 -0
  251. package/dist/modes/commands-core.js +171 -0
  252. package/dist/modes/image-input.d.ts +27 -0
  253. package/dist/modes/image-input.js +78 -0
  254. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  255. package/dist/modes/interactive/approval-dialog.js +202 -0
  256. package/dist/modes/interactive/commands.d.ts +41 -0
  257. package/dist/modes/interactive/commands.js +201 -0
  258. package/dist/modes/interactive/completion.d.ts +53 -0
  259. package/dist/modes/interactive/completion.js +157 -0
  260. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  261. package/dist/modes/interactive/interactive-mode.js +491 -0
  262. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  263. package/dist/modes/interactive/key-dispatch.js +107 -0
  264. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  265. package/dist/modes/interactive/line/line-editor.js +232 -0
  266. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  267. package/dist/modes/interactive/line/line-mode.js +218 -0
  268. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  269. package/dist/modes/interactive/line/line-render.js +171 -0
  270. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  271. package/dist/modes/interactive/line/paste-state.js +72 -0
  272. package/dist/modes/interactive/message-view.d.ts +77 -0
  273. package/dist/modes/interactive/message-view.js +269 -0
  274. package/dist/modes/interactive/pickers.d.ts +42 -0
  275. package/dist/modes/interactive/pickers.js +115 -0
  276. package/dist/modes/interactive/startup-ui.d.ts +33 -0
  277. package/dist/modes/interactive/startup-ui.js +268 -0
  278. package/dist/modes/interactive/status-bar.d.ts +48 -0
  279. package/dist/modes/interactive/status-bar.js +139 -0
  280. package/dist/modes/interactive/tool-view.d.ts +95 -0
  281. package/dist/modes/interactive/tool-view.js +344 -0
  282. package/dist/modes/print/json-event.d.ts +15 -0
  283. package/dist/modes/print/json-event.js +39 -0
  284. package/dist/modes/print/print-mode.d.ts +17 -0
  285. package/dist/modes/print/print-mode.js +107 -0
  286. package/dist/modes/rpc/commands.d.ts +40 -0
  287. package/dist/modes/rpc/commands.js +263 -0
  288. package/dist/modes/rpc/jsonl.d.ts +16 -0
  289. package/dist/modes/rpc/jsonl.js +55 -0
  290. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  291. package/dist/modes/rpc/rpc-mode.js +153 -0
  292. package/dist/modes/session-report.d.ts +55 -0
  293. package/dist/modes/session-report.js +278 -0
  294. package/dist/modes/shared.d.ts +13 -0
  295. package/dist/modes/shared.js +52 -0
  296. package/dist/modes/startup-ui-text.d.ts +16 -0
  297. package/dist/modes/startup-ui-text.js +103 -0
  298. package/dist/permissions/broker.d.ts +47 -0
  299. package/dist/permissions/broker.js +107 -0
  300. package/dist/permissions/dangerous.d.ts +47 -0
  301. package/dist/permissions/dangerous.js +370 -0
  302. package/dist/permissions/pipeline.d.ts +51 -0
  303. package/dist/permissions/pipeline.js +181 -0
  304. package/dist/permissions/preview.d.ts +43 -0
  305. package/dist/permissions/preview.js +463 -0
  306. package/dist/permissions/rules.d.ts +58 -0
  307. package/dist/permissions/rules.js +249 -0
  308. package/dist/permissions/types.d.ts +100 -0
  309. package/dist/permissions/types.js +18 -0
  310. package/dist/rpc.d.ts +173 -0
  311. package/dist/rpc.js +13 -0
  312. package/dist/sdk.d.ts +98 -0
  313. package/dist/sdk.js +195 -0
  314. package/dist/session/manager.d.ts +70 -0
  315. package/dist/session/manager.js +278 -0
  316. package/dist/session/migrate.d.ts +19 -0
  317. package/dist/session/migrate.js +53 -0
  318. package/dist/session/projection.d.ts +50 -0
  319. package/dist/session/projection.js +184 -0
  320. package/dist/session/store.d.ts +47 -0
  321. package/dist/session/store.js +210 -0
  322. package/dist/session/tree.d.ts +21 -0
  323. package/dist/session/tree.js +88 -0
  324. package/dist/session/types.d.ts +201 -0
  325. package/dist/session/types.js +18 -0
  326. package/dist/skills/discover.d.ts +60 -0
  327. package/dist/skills/discover.js +160 -0
  328. package/dist/skills/expand.d.ts +35 -0
  329. package/dist/skills/expand.js +46 -0
  330. package/dist/skills/frontmatter.d.ts +27 -0
  331. package/dist/skills/frontmatter.js +157 -0
  332. package/dist/skills/index-prompt.d.ts +13 -0
  333. package/dist/skills/index-prompt.js +42 -0
  334. package/dist/skills/templates.d.ts +52 -0
  335. package/dist/skills/templates.js +177 -0
  336. package/dist/tools/bash.d.ts +49 -0
  337. package/dist/tools/bash.js +222 -0
  338. package/dist/tools/edit-fuzzy.d.ts +36 -0
  339. package/dist/tools/edit-fuzzy.js +129 -0
  340. package/dist/tools/edit.d.ts +38 -0
  341. package/dist/tools/edit.js +241 -0
  342. package/dist/tools/file-mutex.d.ts +8 -0
  343. package/dist/tools/file-mutex.js +29 -0
  344. package/dist/tools/glob.d.ts +44 -0
  345. package/dist/tools/glob.js +217 -0
  346. package/dist/tools/grep.d.ts +39 -0
  347. package/dist/tools/grep.js +179 -0
  348. package/dist/tools/ignore.d.ts +40 -0
  349. package/dist/tools/ignore.js +174 -0
  350. package/dist/tools/image-file.d.ts +31 -0
  351. package/dist/tools/image-file.js +114 -0
  352. package/dist/tools/ls.d.ts +21 -0
  353. package/dist/tools/ls.js +96 -0
  354. package/dist/tools/output-accumulator.d.ts +48 -0
  355. package/dist/tools/output-accumulator.js +106 -0
  356. package/dist/tools/paths.d.ts +20 -0
  357. package/dist/tools/paths.js +58 -0
  358. package/dist/tools/presets.d.ts +71 -0
  359. package/dist/tools/presets.js +128 -0
  360. package/dist/tools/process-tree.d.ts +35 -0
  361. package/dist/tools/process-tree.js +125 -0
  362. package/dist/tools/read.d.ts +24 -0
  363. package/dist/tools/read.js +132 -0
  364. package/dist/tools/registry.d.ts +43 -0
  365. package/dist/tools/registry.js +106 -0
  366. package/dist/tools/shell.d.ts +38 -0
  367. package/dist/tools/shell.js +91 -0
  368. package/dist/tools/task.d.ts +29 -0
  369. package/dist/tools/task.js +107 -0
  370. package/dist/tools/todo.d.ts +28 -0
  371. package/dist/tools/todo.js +107 -0
  372. package/dist/tools/truncate.d.ts +44 -0
  373. package/dist/tools/truncate.js +175 -0
  374. package/dist/tools/types.d.ts +135 -0
  375. package/dist/tools/types.js +19 -0
  376. package/dist/tools/write.d.ts +20 -0
  377. package/dist/tools/write.js +84 -0
  378. package/dist/tui/ansi.d.ts +29 -0
  379. package/dist/tui/ansi.js +420 -0
  380. package/dist/tui/component.d.ts +38 -0
  381. package/dist/tui/component.js +13 -0
  382. package/dist/tui/components/box.d.ts +26 -0
  383. package/dist/tui/components/box.js +65 -0
  384. package/dist/tui/components/container.d.ts +14 -0
  385. package/dist/tui/components/container.js +39 -0
  386. package/dist/tui/components/editor-buffer.d.ts +67 -0
  387. package/dist/tui/components/editor-buffer.js +300 -0
  388. package/dist/tui/components/editor-paste.d.ts +29 -0
  389. package/dist/tui/components/editor-paste.js +64 -0
  390. package/dist/tui/components/editor.d.ts +114 -0
  391. package/dist/tui/components/editor.js +530 -0
  392. package/dist/tui/components/key-value.d.ts +29 -0
  393. package/dist/tui/components/key-value.js +48 -0
  394. package/dist/tui/components/loader.d.ts +35 -0
  395. package/dist/tui/components/loader.js +71 -0
  396. package/dist/tui/components/markdown.d.ts +90 -0
  397. package/dist/tui/components/markdown.js +462 -0
  398. package/dist/tui/components/meter.d.ts +29 -0
  399. package/dist/tui/components/meter.js +47 -0
  400. package/dist/tui/components/overlay.d.ts +24 -0
  401. package/dist/tui/components/overlay.js +52 -0
  402. package/dist/tui/components/select-list.d.ts +57 -0
  403. package/dist/tui/components/select-list.js +179 -0
  404. package/dist/tui/components/spacer.d.ts +11 -0
  405. package/dist/tui/components/spacer.js +16 -0
  406. package/dist/tui/components/text.d.ts +30 -0
  407. package/dist/tui/components/text.js +65 -0
  408. package/dist/tui/keybindings.d.ts +66 -0
  409. package/dist/tui/keybindings.js +120 -0
  410. package/dist/tui/keys.d.ts +38 -0
  411. package/dist/tui/keys.js +275 -0
  412. package/dist/tui/stdin-buffer.d.ts +41 -0
  413. package/dist/tui/stdin-buffer.js +206 -0
  414. package/dist/tui/terminal.d.ts +79 -0
  415. package/dist/tui/terminal.js +153 -0
  416. package/dist/tui/theme.d.ts +31 -0
  417. package/dist/tui/theme.js +199 -0
  418. package/dist/tui/tui.d.ts +103 -0
  419. package/dist/tui/tui.js +363 -0
  420. package/dist/tui/vt-screen.d.ts +46 -0
  421. package/dist/tui/vt-screen.js +251 -0
  422. package/dist/tui.d.ts +30 -0
  423. package/dist/tui.js +31 -0
  424. package/dist/version.d.ts +8 -0
  425. package/dist/version.js +24 -0
  426. package/docs/codemode.md +102 -0
  427. package/docs/hooks.md +196 -0
  428. package/docs/host-api.md +161 -0
  429. package/docs/providers.md +531 -0
  430. package/docs/rpc.md +253 -0
  431. package/docs/session-format.md +119 -0
  432. package/docs/tui.md +170 -0
  433. package/package.json +101 -4
@@ -0,0 +1,53 @@
1
+ /**
2
+ * codemode 的跨次存储(设计 §5.5 `store / load`)。[B10]
3
+ *
4
+ * - 存成 `custom{customType:"ama.codemode-store", data:{ entries }}` 条目(不进上下文);每次成功
5
+ * 的脚本写过 store 就追加一条**完整快照**,读取取活动分支上最近一条——随会话分支走,fork /
6
+ * 切分支后只看本分支写过的值;
7
+ * - 单值 JSON ≤ 262 144 字符、合计 ≤ 1 048 576 字符(子进程里 store() 先检查一次,这里提交前
8
+ * 再检查一次,防止子进程被绕过);
9
+ * - 脚本失败不提交(由 tool.ts 保证:只在 `done.ok` 时调用 commitStore)。
10
+ */
11
+ export const STORE_CUSTOM_TYPE = "ama.codemode-store";
12
+ export const MAX_STORE_VALUE_CHARS = 262_144;
13
+ export const MAX_STORE_TOTAL_CHARS = 1_048_576;
14
+ /** 活动分支上最近一次提交的快照;没有或形状不对 → 空。 */
15
+ export function readStore(session) {
16
+ const data = session.lastCustom(STORE_CUSTOM_TYPE);
17
+ const entries = data?.entries;
18
+ if (typeof entries !== "object" || entries === null || Array.isArray(entries))
19
+ return {};
20
+ return { ...entries };
21
+ }
22
+ /** 超限 / 非法 → 说明文字;合法 → undefined。 */
23
+ export function validateStore(entries) {
24
+ let total = 0;
25
+ for (const [key, value] of Object.entries(entries)) {
26
+ let json;
27
+ try {
28
+ json = JSON.stringify(value);
29
+ }
30
+ catch {
31
+ json = undefined;
32
+ }
33
+ if (json === undefined)
34
+ return `store value "${key}" is not JSON-serializable`;
35
+ if (json.length > MAX_STORE_VALUE_CHARS) {
36
+ return `store value "${key}" is ${json.length} characters of JSON (limit ${MAX_STORE_VALUE_CHARS})`;
37
+ }
38
+ total += json.length;
39
+ }
40
+ if (total > MAX_STORE_TOTAL_CHARS) {
41
+ return `store holds ${total} characters of JSON (limit ${MAX_STORE_TOTAL_CHARS})`;
42
+ }
43
+ return undefined;
44
+ }
45
+ /** 校验并追加快照条目;超限不写,返回说明。 */
46
+ export function commitStore(session, entries) {
47
+ const problem = validateStore(entries);
48
+ if (problem !== undefined)
49
+ return problem;
50
+ const data = { entries };
51
+ session.appendCustom(STORE_CUSTOM_TYPE, data);
52
+ return undefined;
53
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `codemode` 工具(设计 §5.5):模型写一段 JavaScript,脚本里经 `tools.*` 编排多次工具调用,只有
3
+ * 脚本输出回到模型。[B10]
4
+ *
5
+ * - 权限类:网络隔离时 `read`,否则 `execute`;`sequential`;脚本里的每次 `tools.*` 经 `ToolContext.tools.executeTool`
6
+ * 走完整门禁(schema → PreToolUse → 权限管线 → 审批 → 执行 → PostToolUse),Hook 输入带
7
+ * `viaCodemode: true` 与父 toolCallId,事件带 `parentToolCallId`(agent/tool-runner.ts);
8
+ * - 返回值:`bash` 解析为 `{ output, truncated, fullOutputPath?, exitCode, wallTimeMs }`(非零退出码
9
+ * 也解析),其它工具解析为 `structured` 或文本;失败、被拒、参数非法 → 以 Error reject;
10
+ * - 结果:`Script completed` / `Script failed` + 用时 + 输出;超过 `max_output_tokens`(以及会话的
11
+ * 单条结果上限)保留首尾,全文写 `<outputDir>/<toolCallId>.txt`;失败时保留已产出输出;
12
+ * - store 只在脚本成功时提交(store.ts);
13
+ * - 描述(含工具声明)在第一次读取时确定并冻结:同一会话内字节稳定(设计 §9.1),之后注册的宿主
14
+ * 工具仍可在脚本里调用(`ALL_TOOLS` / `describeTool` 是执行时的清单)。
15
+ */
16
+ import type { ToolDefinition, ToolResult } from "../tools/types.js";
17
+ import { type SandboxCapability } from "./capability.js";
18
+ import { type DeclarableTool } from "./declarations.js";
19
+ import { type SandboxRunResult } from "./host-side.js";
20
+ export declare const CODEMODE_TOOL_NAME = "codemode";
21
+ export interface CodemodeInput {
22
+ script: string;
23
+ }
24
+ export interface CallableTool {
25
+ tool: DeclarableTool;
26
+ /** 内置工具(非 bash)解析为文本;宿主 / SDK 工具可能返回结构化值。 */
27
+ textResult: boolean;
28
+ }
29
+ export interface CodemodeToolOptions {
30
+ /** 脚本里可调用的工具(不含 codemode 本身);描述冻结时与每次执行时各调用一次。 */
31
+ listTools(): CallableTool[];
32
+ /** 描述里内联声明的预算(估算 token),缺省 3000。 */
33
+ inlineBudget?: number;
34
+ /** 缺省 detectSandboxCapability()。 */
35
+ capability?: SandboxCapability;
36
+ /** 会话的单条工具结果上限(runner 会再截一次;这里先按它收紧,避免二次截断丢掉尾部)。 */
37
+ maxResultChars?: number;
38
+ /** `only` 模式:其它工具不直接暴露,系统提示的工具行与规则写明只能在脚本里调用。 */
39
+ exclusive?: boolean;
40
+ /** 子进程入口(测试 / 嵌入方覆盖)。 */
41
+ entry?: string;
42
+ nodePath?: string;
43
+ }
44
+ export interface CodemodeDetails {
45
+ ok: boolean;
46
+ elapsedMs: number;
47
+ toolCalls: number;
48
+ timedOut: boolean;
49
+ aborted: boolean;
50
+ strict: boolean;
51
+ fullOutputPath?: string;
52
+ error?: string;
53
+ }
54
+ /** 脚本里拿到的 bash 结果。 */
55
+ export interface ScriptBashResult {
56
+ output: string;
57
+ truncated: boolean;
58
+ fullOutputPath?: string;
59
+ exitCode: number;
60
+ wallTimeMs: number;
61
+ }
62
+ /** 内层工具结果 → 脚本拿到的值;失败抛 Error。 */
63
+ export declare function toScriptValue(name: string, result: ToolResult): unknown;
64
+ /** 描述里的示例脚本(6 行):并发两个 read、过滤、return。 */
65
+ export declare const CODEMODE_EXAMPLE: readonly string[];
66
+ /**
67
+ * 脚本失败原因后补一句正确写法:用了 require / import / process 等,或把工具名当函数直接调用
68
+ * (实测模型常见的两种错误)。其它错误原样返回。
69
+ */
70
+ export declare function scriptErrorHint(error: string, toolNames: readonly string[]): string;
71
+ export declare function buildCodemodeDescription(tools: readonly CallableTool[], inlineBudget: number, capability: SandboxCapability): string;
72
+ /** 结果文本:状态行 + 输出(超限保留首尾)+ 失败原因。 */
73
+ export declare function formatCodemodeResult(run: Pick<SandboxRunResult, "ok" | "error" | "outputs" | "elapsedMs" | "droppedChars">, limitChars: number, saveFull: (text: string) => string | undefined): {
74
+ text: string;
75
+ fullOutputPath?: string;
76
+ };
77
+ /** `only` 模式的系统提示规则(实测模型仍会先直接调用 read / edit / bash)。 */
78
+ export declare const CODEMODE_ONLY_GUIDELINE = "read, edit, write, bash and the other tools are not callable directly here: every tool call goes inside a codemode script as tools.<name>(args); batch related calls in one script.";
79
+ export declare function createCodemodeTool(options: CodemodeToolOptions): ToolDefinition<CodemodeInput>;
80
+ /** 组装根用:从 ToolFactoryContext 的形状取所需(避免 codemode → cli 的依赖)。 */
81
+ export interface CodemodeFactoryContext {
82
+ config: {
83
+ codemode?: {
84
+ mode?: "off" | "on" | "only";
85
+ inlineBudget?: number;
86
+ requireStrict?: boolean;
87
+ };
88
+ tools?: {
89
+ preset?: string;
90
+ maxToolResultChars?: number;
91
+ };
92
+ };
93
+ registry: {
94
+ list(): readonly string[];
95
+ get(name: string): ToolDefinition | undefined;
96
+ } & {
97
+ sourceOf?(name: string): string | undefined;
98
+ };
99
+ warn(message: string): void;
100
+ }
101
+ /**
102
+ * codemode 工具工厂:`codemode.mode` 生效值为 off → 不注册;`requireStrict` 而运行时不隔离网络
103
+ * → 不注册并 warning(预设随之回退到 default)。
104
+ */
105
+ export declare function codemodeToolFactory(overrides?: Partial<Pick<CodemodeToolOptions, "capability" | "entry" | "nodePath">>): (ctx: CodemodeFactoryContext) => ToolDefinition | undefined;
@@ -0,0 +1,283 @@
1
+ /**
2
+ * `codemode` 工具(设计 §5.5):模型写一段 JavaScript,脚本里经 `tools.*` 编排多次工具调用,只有
3
+ * 脚本输出回到模型。[B10]
4
+ *
5
+ * - 权限类:网络隔离时 `read`,否则 `execute`;`sequential`;脚本里的每次 `tools.*` 经 `ToolContext.tools.executeTool`
6
+ * 走完整门禁(schema → PreToolUse → 权限管线 → 审批 → 执行 → PostToolUse),Hook 输入带
7
+ * `viaCodemode: true` 与父 toolCallId,事件带 `parentToolCallId`(agent/tool-runner.ts);
8
+ * - 返回值:`bash` 解析为 `{ output, truncated, fullOutputPath?, exitCode, wallTimeMs }`(非零退出码
9
+ * 也解析),其它工具解析为 `structured` 或文本;失败、被拒、参数非法 → 以 Error reject;
10
+ * - 结果:`Script completed` / `Script failed` + 用时 + 输出;超过 `max_output_tokens`(以及会话的
11
+ * 单条结果上限)保留首尾,全文写 `<outputDir>/<toolCallId>.txt`;失败时保留已产出输出;
12
+ * - store 只在脚本成功时提交(store.ts);
13
+ * - 描述(含工具声明)在第一次读取时确定并冻结:同一会话内字节稳定(设计 §9.1),之后注册的宿主
14
+ * 工具仍可在脚本里调用(`ALL_TOOLS` / `describeTool` 是执行时的清单)。
15
+ */
16
+ import { mkdirSync, writeFileSync } from "node:fs";
17
+ import { tmpdir } from "node:os";
18
+ import { join } from "node:path";
19
+ import { codemodeAvailability, detectSandboxCapability, } from "./capability.js";
20
+ import { DEFAULT_INLINE_BUDGET, buildDeclarationBlock, toolDeclaration, } from "./declarations.js";
21
+ import { runSandbox } from "./host-side.js";
22
+ import { codemodeHint } from "./modes.js";
23
+ import { parseOptionsLine } from "./protocol.js";
24
+ import { commitStore, readStore } from "./store.js";
25
+ export const CODEMODE_TOOL_NAME = "codemode";
26
+ /** 与 agent/tool-runner.ts 的 DEFAULT_MAX_TOOL_RESULT_CHARS 一致(codemode 与 tools 同层,不 import agent)。 */
27
+ const DEFAULT_MAX_TOOL_RESULT_CHARS = 30_000;
28
+ function textOf(content) {
29
+ if (typeof content === "string")
30
+ return content;
31
+ return content.map((block) => (block.type === "text" ? block.text : "")).join("");
32
+ }
33
+ function isBashStructured(value) {
34
+ return (typeof value === "object" &&
35
+ value !== null &&
36
+ typeof value.output === "string" &&
37
+ typeof value.exit_code === "number");
38
+ }
39
+ /** 内层工具结果 → 脚本拿到的值;失败抛 Error。 */
40
+ export function toScriptValue(name, result) {
41
+ if (name === "bash" && isBashStructured(result.structured)) {
42
+ const s = result.structured;
43
+ const value = {
44
+ output: s.output,
45
+ truncated: s.truncated,
46
+ exitCode: s.exit_code,
47
+ wallTimeMs: Math.round(s.wall_time_seconds * 1000),
48
+ };
49
+ if (s.full_output_path !== undefined)
50
+ value.fullOutputPath = s.full_output_path;
51
+ return value;
52
+ }
53
+ if (result.isError === true)
54
+ throw new Error(textOf(result.content) || `Tool ${name} failed`);
55
+ return result.structured !== undefined ? result.structured : textOf(result.content);
56
+ }
57
+ /** on 模式下其它工具描述末尾的提示不进声明。 */
58
+ function declarable(tool) {
59
+ const suffix = `\n${codemodeHint(tool.name)}`;
60
+ if (!tool.description.endsWith(suffix))
61
+ return tool;
62
+ return { ...tool, description: tool.description.slice(0, -suffix.length) };
63
+ }
64
+ /** 描述里的示例脚本(6 行):并发两个 read、过滤、return。 */
65
+ export const CODEMODE_EXAMPLE = [
66
+ "const [a, b] = await Promise.all([",
67
+ ' tools.read({ path: "src/a.ts" }),',
68
+ ' tools.read({ path: "src/b.ts" }),',
69
+ "]);",
70
+ 'const hits = (a + "\\n" + b).split("\\n").filter((line) => line.includes("TODO"));',
71
+ 'return hits.join("\\n");',
72
+ ];
73
+ const SCRIPT_ONLY_GLOBALS = /\b(require|process|fetch|setTimeout|setInterval|setImmediate) is not defined/;
74
+ /**
75
+ * 脚本失败原因后补一句正确写法:用了 require / import / process 等,或把工具名当函数直接调用
76
+ * (实测模型常见的两种错误)。其它错误原样返回。
77
+ */
78
+ export function scriptErrorHint(error, toolNames) {
79
+ if (/Cannot use import statement|dynamic import callback/.test(error) ||
80
+ SCRIPT_ONLY_GLOBALS.test(error)) {
81
+ return `${error}\nOnly tools.<name>(args) is available in codemode scripts (no require, import, process, fetch or timers).`;
82
+ }
83
+ const called = /ReferenceError: ([A-Za-z_$][\w$]*) is not defined/.exec(error)?.[1];
84
+ if (called !== undefined && toolNames.includes(called)) {
85
+ return `${error}\nCall tools as tools.${called}({...}), not ${called}(...).`;
86
+ }
87
+ return error;
88
+ }
89
+ export function buildCodemodeDescription(tools, inlineBudget, capability) {
90
+ const lines = [
91
+ "Run a JavaScript script that calls tools; only the script's output comes back to you. Use it to batch many tool calls (Promise.all), filter or summarize large results, or loop, in one step.",
92
+ "Only tools.<name>(args) is available. There is no require, import, process, fetch or timers; do not call tools directly as functions.",
93
+ 'The input is raw JavaScript (not JSON, no code fence), run as the body of an async function: top-level await and return work. Optional first line: // @options: {"max_output_tokens": 10000, "timeout_ms": 300000}',
94
+ "Example:",
95
+ ...CODEMODE_EXAMPLE,
96
+ "Globals: tools.<name>(args) returns a Promise and rejects with an Error when the call fails or is denied (use Promise.allSettled to keep the rest); text(v) and console.log(...) append output (non-strings as JSON); return v is text(v); store(key, v) / load(key) keep small JSON values across scripts (saved only when the script succeeds); ALL_TOOLS lists callable tools; describeTool(name) returns a declaration. At most 8 tool calls run at once; codemode cannot call itself. Every call goes through the normal hooks, permissions and approvals.",
97
+ ];
98
+ if (!capability.strict) {
99
+ lines.push(`Sandbox: ${capability.reason}.`);
100
+ }
101
+ const block = buildDeclarationBlock(tools.map(({ tool, textResult }) => ({ tool: declarable(tool), textResult })), inlineBudget);
102
+ if (block.text !== "")
103
+ lines.push(block.text);
104
+ return lines.join("\n");
105
+ }
106
+ /** 结果文本:状态行 + 输出(超限保留首尾)+ 失败原因。 */
107
+ export function formatCodemodeResult(run, limitChars, saveFull) {
108
+ const seconds = (run.elapsedMs / 1000).toFixed(2);
109
+ const header = `${run.ok ? "Script completed" : "Script failed"} in ${seconds}s`;
110
+ let output = run.outputs.join("\n");
111
+ if (run.droppedChars > 0) {
112
+ output += `\n[${run.droppedChars} more characters of output were discarded]`;
113
+ }
114
+ let fullOutputPath;
115
+ if (output.length > limitChars) {
116
+ fullOutputPath = saveFull(output);
117
+ const half = Math.max(1, Math.floor(limitChars / 2));
118
+ const omitted = output.length - half * 2;
119
+ const where = fullOutputPath === undefined ? "" : `; full output: ${fullOutputPath}`;
120
+ output = `${output.slice(0, half)}\n[... ${omitted} characters omitted${where} ...]\n${output.slice(-half)}`;
121
+ }
122
+ const parts = [header, output === "" ? "(no output)" : output];
123
+ if (!run.ok && run.error !== undefined)
124
+ parts.push(`Script error: ${run.error}`);
125
+ const result = { text: parts.join("\n\n") };
126
+ if (fullOutputPath !== undefined)
127
+ result.fullOutputPath = fullOutputPath;
128
+ return result;
129
+ }
130
+ function saveFullOutput(ctx, text) {
131
+ try {
132
+ const dir = ctx.outputDir ?? join(tmpdir(), "ama-codemode");
133
+ mkdirSync(dir, { recursive: true });
134
+ const file = join(dir, `${ctx.toolCallId.replace(/[^A-Za-z0-9_-]/g, "_")}.txt`);
135
+ writeFileSync(file, text, "utf8");
136
+ return file;
137
+ }
138
+ catch {
139
+ return undefined;
140
+ }
141
+ }
142
+ const TAIL_CHARS = 4000;
143
+ /** `only` 模式的系统提示规则(实测模型仍会先直接调用 read / edit / bash)。 */
144
+ export const CODEMODE_ONLY_GUIDELINE = "read, edit, write, bash and the other tools are not callable directly here: every tool call goes inside a codemode script as tools.<name>(args); batch related calls in one script.";
145
+ export function createCodemodeTool(options) {
146
+ const capability = options.capability ?? detectSandboxCapability();
147
+ const inlineBudget = options.inlineBudget ?? DEFAULT_INLINE_BUDGET;
148
+ const maxResultChars = options.maxResultChars ?? DEFAULT_MAX_TOOL_RESULT_CHARS;
149
+ let frozenDescription;
150
+ const tool = {
151
+ name: CODEMODE_TOOL_NAME,
152
+ label: "Codemode",
153
+ get description() {
154
+ frozenDescription ??= buildCodemodeDescription(options.listTools(), inlineBudget, capability);
155
+ return frozenDescription;
156
+ },
157
+ parameters: {
158
+ type: "object",
159
+ properties: {
160
+ script: { type: "string", description: "Raw JavaScript (async function body)" },
161
+ },
162
+ required: ["script"],
163
+ },
164
+ // 网络隔离(Node ≥ 25)时脚本只能经 tools.* 做事,每次内层调用各自过权限:codemode 本身按 read
165
+ // 类(default 模式免审批);不隔离网络时脚本逃出 vm 就能联网,仍按 execute。
166
+ permission: capability.strict ? "read" : "execute",
167
+ executionMode: "sequential",
168
+ promptSnippet: options.exclusive === true
169
+ ? "codemode: your only tool; run a JavaScript script that calls the other tools as tools.<name>(args); only its output returns"
170
+ : "codemode: run a JavaScript script that calls tools; only its output returns",
171
+ ...(options.exclusive === true ? { promptGuidelines: [CODEMODE_ONLY_GUIDELINE] } : {}),
172
+ async execute(input, ctx) {
173
+ let scriptOptions;
174
+ try {
175
+ scriptOptions = parseOptionsLine(input.script);
176
+ }
177
+ catch (error) {
178
+ return { content: error.message, isError: true };
179
+ }
180
+ const tools = options.listTools().map(({ tool: t, textResult }) => ({
181
+ name: t.name,
182
+ declaration: toolDeclaration(declarable(t), textResult ? {} : { textResult: false }),
183
+ }));
184
+ let tail = "";
185
+ const run = await runSandbox({
186
+ script: input.script,
187
+ options: scriptOptions,
188
+ tools,
189
+ store: readStore(ctx.session),
190
+ signal: ctx.signal,
191
+ ...(options.entry !== undefined ? { entry: options.entry } : {}),
192
+ ...(options.nodePath !== undefined ? { nodePath: options.nodePath } : {}),
193
+ callTool: async (name, args, signal) => toScriptValue(name, await ctx.tools.executeTool(name, args, { signal })),
194
+ onOutput: (text) => {
195
+ tail = `${tail}${tail === "" ? "" : "\n"}${text}`.slice(-TAIL_CHARS);
196
+ ctx.onUpdate(tail);
197
+ },
198
+ });
199
+ if (run.error !== undefined) {
200
+ run.error = scriptErrorHint(run.error, tools.map((t) => t.name));
201
+ }
202
+ if (run.ok && run.store !== undefined) {
203
+ const problem = commitStore(ctx.session, run.store);
204
+ if (problem !== undefined) {
205
+ run.ok = false;
206
+ run.error = `store was not saved: ${problem}`;
207
+ }
208
+ }
209
+ const limitChars = Math.max(1000, Math.min(scriptOptions.maxOutputTokens * 4, maxResultChars - 500));
210
+ const formatted = formatCodemodeResult(run, limitChars, (text) => saveFullOutput(ctx, text));
211
+ const details = {
212
+ ok: run.ok,
213
+ elapsedMs: run.elapsedMs,
214
+ toolCalls: run.toolCalls,
215
+ timedOut: run.timedOut,
216
+ aborted: run.aborted,
217
+ strict: capability.strict,
218
+ };
219
+ if (formatted.fullOutputPath !== undefined)
220
+ details.fullOutputPath = formatted.fullOutputPath;
221
+ if (run.error !== undefined)
222
+ details.error = run.error;
223
+ return { content: formatted.text, isError: !run.ok, details };
224
+ },
225
+ renderCall(input, width) {
226
+ const lines = input.script.split("\n");
227
+ const shown = lines.slice(0, 6).map((line) => line.slice(0, Math.max(10, width)));
228
+ if (lines.length > shown.length)
229
+ shown.push(`… ${lines.length - shown.length} more lines`);
230
+ return shown;
231
+ },
232
+ renderResult(result, width, expanded) {
233
+ const lines = textOf(result.content).split("\n");
234
+ const clip = (line) => line.slice(0, Math.max(10, width));
235
+ if (expanded || lines.length <= 8)
236
+ return lines.map(clip);
237
+ return [clip(lines[0] ?? ""), `… ${lines.length - 6} lines`, ...lines.slice(-5).map(clip)];
238
+ },
239
+ };
240
+ return tool;
241
+ }
242
+ /**
243
+ * codemode 工具工厂:`codemode.mode` 生效值为 off → 不注册;`requireStrict` 而运行时不隔离网络
244
+ * → 不注册并 warning(预设随之回退到 default)。
245
+ */
246
+ export function codemodeToolFactory(overrides = {}) {
247
+ return (ctx) => {
248
+ const explicit = ctx.config.codemode?.mode;
249
+ const mode = explicit ?? (ctx.config.tools?.preset === "codemode" ? "only" : "off");
250
+ if (mode === "off")
251
+ return undefined;
252
+ const availability = codemodeAvailability(ctx.config.codemode?.requireStrict, overrides.capability ?? detectSandboxCapability());
253
+ if (!availability.available) {
254
+ ctx.warn(availability.warning);
255
+ return undefined;
256
+ }
257
+ const registry = ctx.registry;
258
+ const options = {
259
+ capability: availability.capability,
260
+ exclusive: mode === "only",
261
+ listTools: () => registry
262
+ .list()
263
+ .filter((name) => name !== CODEMODE_TOOL_NAME)
264
+ .map((name) => registry.get(name))
265
+ .filter((t) => t !== undefined)
266
+ .map((t) => ({
267
+ tool: t,
268
+ textResult: (registry.sourceOf?.(t.name) ?? "builtin") === "builtin",
269
+ })),
270
+ };
271
+ const budget = ctx.config.codemode?.inlineBudget;
272
+ if (budget !== undefined)
273
+ options.inlineBudget = budget;
274
+ const maxChars = ctx.config.tools?.maxToolResultChars;
275
+ if (maxChars !== undefined)
276
+ options.maxResultChars = maxChars;
277
+ if (overrides.entry !== undefined)
278
+ options.entry = overrides.entry;
279
+ if (overrides.nodePath !== undefined)
280
+ options.nodePath = overrides.nodePath;
281
+ return createCodemodeTool(options);
282
+ };
283
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 分支摘要(设计 §8「branch_summary」、§1.2 branch-summary.ts):`/tree` 离开分支时总结被离开的那段。[B2]
3
+ *
4
+ * 找新旧叶子的最深公共祖先 → 收集旧叶子到祖先之间(不含祖先)的上下文消息 → 从新到旧按预算截取 →
5
+ * 用同一模板(止于 Next Steps)生成摘要。调用方把结果作为 `branch_summary` 追加在新位置
6
+ * (parentId = 新叶子,fromId = 旧叶子)。
7
+ *
8
+ * [W3-C1b] 调用方给出续写前缀(离开前的完整转录)时同压缩一样走会话前缀续写:「只摘要最后 K 条」,
9
+ * 失败回落独立请求(第三波 §1.8)。
10
+ */
11
+ import type { Usage } from "../ai/types.js";
12
+ import { type EntryIndex } from "../session/tree.js";
13
+ import type { AgentMessage, FileOpsDetails } from "../session/types.js";
14
+ import { type SummarizerOptions } from "./summarize-tier.js";
15
+ export declare const BRANCH_SUMMARY_BUDGET_TOKENS = 20000;
16
+ export declare const BRANCH_SUMMARY_TEMPLATE = "The record above is a branch of the session that the user is now leaving to continue from an earlier point. Summarize what was tried on this branch so the agent can benefit from it, using EXACTLY this format:\n\n## Goal\n## Constraints & Preferences\n## Progress\n### Done\n### In Progress\n### Blocked\n## Key Decisions\n## Next Steps\n\nKeep it concise; preserve exact file paths and error messages.";
17
+ export interface BranchSummaryPlan {
18
+ fromId: string;
19
+ commonAncestorId: string | null;
20
+ messages: AgentMessage[];
21
+ }
22
+ export interface BranchSummaryDraft {
23
+ fromId: string;
24
+ summary: string;
25
+ usage: Usage;
26
+ details: FileOpsDetails;
27
+ }
28
+ /** 旧叶子与新叶子在同一路径上(无被离开的内容)时返回 undefined。 */
29
+ export declare function prepareBranchSummary(index: EntryIndex, oldLeafId: string | null, newLeafId: string | null, budgetTokens?: number): BranchSummaryPlan | undefined;
30
+ export declare function runBranchSummary(plan: BranchSummaryPlan, options: SummarizerOptions): Promise<BranchSummaryDraft>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * 分支摘要(设计 §8「branch_summary」、§1.2 branch-summary.ts):`/tree` 离开分支时总结被离开的那段。[B2]
3
+ *
4
+ * 找新旧叶子的最深公共祖先 → 收集旧叶子到祖先之间(不含祖先)的上下文消息 → 从新到旧按预算截取 →
5
+ * 用同一模板(止于 Next Steps)生成摘要。调用方把结果作为 `branch_summary` 追加在新位置
6
+ * (parentId = 新叶子,fromId = 旧叶子)。
7
+ *
8
+ * [W3-C1b] 调用方给出续写前缀(离开前的完整转录)时同压缩一样走会话前缀续写:「只摘要最后 K 条」,
9
+ * 失败回落独立请求(第三波 §1.8)。
10
+ */
11
+ import { entryToMessage } from "../session/projection.js";
12
+ import { commonAncestor, entriesBetween } from "../session/tree.js";
13
+ import { estimateMessageTokens } from "./estimate.js";
14
+ import { collectFileOps, createFileOps, fileOpsDetails, formatFileOps, serializeConversation, } from "./serialize.js";
15
+ import { countLlmMessages, summarizeWithFallback, } from "./summarize-tier.js";
16
+ export const BRANCH_SUMMARY_BUDGET_TOKENS = 20_000;
17
+ export const BRANCH_SUMMARY_TEMPLATE = `The record above is a branch of the session that the user is now leaving to continue from an earlier point. Summarize what was tried on this branch so the agent can benefit from it, using EXACTLY this format:
18
+
19
+ ## Goal
20
+ ## Constraints & Preferences
21
+ ## Progress
22
+ ### Done
23
+ ### In Progress
24
+ ### Blocked
25
+ ## Key Decisions
26
+ ## Next Steps
27
+
28
+ Keep it concise; preserve exact file paths and error messages.`;
29
+ /** 旧叶子与新叶子在同一路径上(无被离开的内容)时返回 undefined。 */
30
+ export function prepareBranchSummary(index, oldLeafId, newLeafId, budgetTokens = BRANCH_SUMMARY_BUDGET_TOKENS) {
31
+ if (oldLeafId === null)
32
+ return undefined;
33
+ const ancestor = commonAncestor(index, oldLeafId, newLeafId);
34
+ const abandoned = entriesBetween(index, ancestor, oldLeafId);
35
+ const all = [];
36
+ for (const entry of abandoned) {
37
+ const message = entryToMessage(entry);
38
+ if (message !== undefined && message.role !== "system")
39
+ all.push(message);
40
+ }
41
+ if (all.length === 0)
42
+ return undefined;
43
+ const picked = [];
44
+ let used = 0;
45
+ for (let i = all.length - 1; i >= 0; i--) {
46
+ const message = all[i];
47
+ const cost = estimateMessageTokens(message);
48
+ if (picked.length > 0 && used + cost > budgetTokens)
49
+ break;
50
+ picked.unshift(message);
51
+ used += cost;
52
+ }
53
+ return { fromId: oldLeafId, commonAncestorId: ancestor, messages: picked };
54
+ }
55
+ export async function runBranchSummary(plan, options) {
56
+ const prefix = options.continuation?.prefix;
57
+ const total = prefix === undefined ? 0 : prefix.messages.filter((m) => m.role !== "system").length;
58
+ const from = Math.max(0, total - countLlmMessages(plan.messages));
59
+ const { text, usage } = await summarizeWithFallback(options, {
60
+ from,
61
+ keepFrom: { index: total, excerpt: "" },
62
+ instruction: `Messages ${from + 1}–${total} are the branch being left.\n\n${BRANCH_SUMMARY_TEMPLATE}`,
63
+ }, () => {
64
+ const parts = [`<conversation>\n${serializeConversation(plan.messages)}\n</conversation>`];
65
+ parts.push(BRANCH_SUMMARY_TEMPLATE);
66
+ if (options.customInstructions !== undefined && options.customInstructions.trim() !== "") {
67
+ parts.push(`Additional instructions:\n${options.customInstructions.trim()}`);
68
+ }
69
+ return parts.join("\n\n");
70
+ });
71
+ const details = fileOpsDetails(collectFileOps(plan.messages, createFileOps()));
72
+ const files = formatFileOps(details);
73
+ return {
74
+ fromId: plan.fromId,
75
+ summary: files === "" ? text : `${text}\n\n${files}`,
76
+ usage,
77
+ details,
78
+ };
79
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 压缩熔断(设计 §9「熔断」)。[B2]
3
+ *
4
+ * - 无 `contextWindow` 或配置关闭 → 自动压缩关闭(手动 /compact 仍可用)。
5
+ * - 同一 run 内档二(摘要)≤ 1 次(`startRun()` 重置计数)。
6
+ * - 连续两次摘要失败 → 跳闸,关闭自动压缩直到 `reset()`(例如用户手动压缩成功)。
7
+ * - 溢出恢复:压缩后估算仍 > 0.8 × window → 不重试。
8
+ */
9
+ export declare const MAX_SUMMARIES_PER_RUN = 1;
10
+ export declare const MAX_CONSECUTIVE_FAILURES = 2;
11
+ export declare const RETRY_AFTER_COMPACTION_RATIO = 0.8;
12
+ export type BreakerBlockReason = "disabled" | "no_window" | "tripped" | "run_limit";
13
+ export declare class CompactionBreaker {
14
+ private summariesThisRun;
15
+ private consecutiveFailures;
16
+ private enabled;
17
+ private contextWindow;
18
+ constructor(enabled: boolean, contextWindow: number | undefined);
19
+ configure(enabled: boolean, contextWindow: number | undefined): void;
20
+ get tripped(): boolean;
21
+ /** 自动压缩整体是否开启(不看本 run 计数)。 */
22
+ get autoEnabled(): boolean;
23
+ startRun(): void;
24
+ /** 自动档二能否执行;不能则给出原因。 */
25
+ blockReason(): BreakerBlockReason | undefined;
26
+ canSummarize(): boolean;
27
+ recordSummary(success: boolean): void;
28
+ /** 手动压缩成功等场景:清零失败计数。 */
29
+ reset(): void;
30
+ /** 溢出恢复后是否值得重试。 */
31
+ shouldRetryAfterCompaction(tokensAfter: number): boolean;
32
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 压缩熔断(设计 §9「熔断」)。[B2]
3
+ *
4
+ * - 无 `contextWindow` 或配置关闭 → 自动压缩关闭(手动 /compact 仍可用)。
5
+ * - 同一 run 内档二(摘要)≤ 1 次(`startRun()` 重置计数)。
6
+ * - 连续两次摘要失败 → 跳闸,关闭自动压缩直到 `reset()`(例如用户手动压缩成功)。
7
+ * - 溢出恢复:压缩后估算仍 > 0.8 × window → 不重试。
8
+ */
9
+ export const MAX_SUMMARIES_PER_RUN = 1;
10
+ export const MAX_CONSECUTIVE_FAILURES = 2;
11
+ export const RETRY_AFTER_COMPACTION_RATIO = 0.8;
12
+ export class CompactionBreaker {
13
+ summariesThisRun = 0;
14
+ consecutiveFailures = 0;
15
+ enabled;
16
+ contextWindow;
17
+ constructor(enabled, contextWindow) {
18
+ this.enabled = enabled;
19
+ this.contextWindow = contextWindow;
20
+ }
21
+ configure(enabled, contextWindow) {
22
+ this.enabled = enabled;
23
+ this.contextWindow = contextWindow;
24
+ }
25
+ get tripped() {
26
+ return this.consecutiveFailures >= MAX_CONSECUTIVE_FAILURES;
27
+ }
28
+ /** 自动压缩整体是否开启(不看本 run 计数)。 */
29
+ get autoEnabled() {
30
+ return this.enabled && this.contextWindow !== undefined && !this.tripped;
31
+ }
32
+ startRun() {
33
+ this.summariesThisRun = 0;
34
+ }
35
+ /** 自动档二能否执行;不能则给出原因。 */
36
+ blockReason() {
37
+ if (!this.enabled)
38
+ return "disabled";
39
+ if (this.contextWindow === undefined)
40
+ return "no_window";
41
+ if (this.tripped)
42
+ return "tripped";
43
+ if (this.summariesThisRun >= MAX_SUMMARIES_PER_RUN)
44
+ return "run_limit";
45
+ return undefined;
46
+ }
47
+ canSummarize() {
48
+ return this.blockReason() === undefined;
49
+ }
50
+ recordSummary(success) {
51
+ this.summariesThisRun++;
52
+ this.consecutiveFailures = success ? 0 : this.consecutiveFailures + 1;
53
+ }
54
+ /** 手动压缩成功等场景:清零失败计数。 */
55
+ reset() {
56
+ this.consecutiveFailures = 0;
57
+ this.summariesThisRun = 0;
58
+ }
59
+ /** 溢出恢复后是否值得重试。 */
60
+ shouldRetryAfterCompaction(tokensAfter) {
61
+ if (this.contextWindow === undefined)
62
+ return false;
63
+ return tokensAfter <= RETRY_AFTER_COMPACTION_RATIO * this.contextWindow;
64
+ }
65
+ }