zidane 7.2.4 → 8.0.4

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 (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -6
  3. package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
  4. package/dist/acp-DQDhi2dj.js.map +1 -0
  5. package/dist/acp-cli.d.ts +1 -1
  6. package/dist/acp-cli.js +9 -66
  7. package/dist/acp-cli.js.map +1 -1
  8. package/dist/acp.d.ts +10 -590
  9. package/dist/acp.d.ts.map +1 -1
  10. package/dist/acp.js +3 -3
  11. package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
  12. package/dist/agent-DSLNmBp0.js.map +1 -0
  13. package/dist/agent.d.ts +1 -1
  14. package/dist/agent.js +3 -2
  15. package/dist/aliasing-lVFbm81n.js +217 -0
  16. package/dist/aliasing-lVFbm81n.js.map +1 -0
  17. package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
  18. package/dist/anthropic-CD00LhUP.js.map +1 -0
  19. package/dist/artifacts-CV2hUKnL.js.map +1 -1
  20. package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
  21. package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
  22. package/dist/call-tool-dHlbGOIY.js +70 -0
  23. package/dist/call-tool-dHlbGOIY.js.map +1 -0
  24. package/dist/chat/pure.d.ts +372 -6
  25. package/dist/chat/pure.d.ts.map +1 -1
  26. package/dist/chat/pure.js +35 -244
  27. package/dist/chat/pure.js.map +1 -1
  28. package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
  29. package/dist/chat-JPJJ8uu5.js.map +1 -0
  30. package/dist/chat.d.ts +4 -6
  31. package/dist/chat.js +23 -12
  32. package/dist/cli-shared-C-YCaglL.js +159 -0
  33. package/dist/cli-shared-C-YCaglL.js.map +1 -0
  34. package/dist/client-core-BQSyDALT.d.ts +2115 -0
  35. package/dist/client-core-BQSyDALT.d.ts.map +1 -0
  36. package/dist/codemode-worker.d.ts +1 -0
  37. package/dist/codemode-worker.js +155 -0
  38. package/dist/codemode-worker.js.map +1 -0
  39. package/dist/codemode.d.ts +352 -0
  40. package/dist/codemode.d.ts.map +1 -0
  41. package/dist/codemode.js +5 -0
  42. package/dist/connection-Dr-Js4yZ.d.ts +28 -0
  43. package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
  44. package/dist/connection-loop-gdh22LTI.js +112 -0
  45. package/dist/connection-loop-gdh22LTI.js.map +1 -0
  46. package/dist/context-segments-BHKlagL6.js +1016 -0
  47. package/dist/context-segments-BHKlagL6.js.map +1 -0
  48. package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
  49. package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
  50. package/dist/contexts/daytona.d.ts +19 -8
  51. package/dist/contexts/daytona.d.ts.map +1 -1
  52. package/dist/contexts/daytona.js +1 -440
  53. package/dist/contexts/docker.d.ts +36 -7
  54. package/dist/contexts/docker.d.ts.map +1 -1
  55. package/dist/contexts/docker.js +1 -456
  56. package/dist/contexts/e2b.d.ts +68 -13
  57. package/dist/contexts/e2b.d.ts.map +1 -1
  58. package/dist/contexts/e2b.js +1 -382
  59. package/dist/contexts/sandbox.d.ts +1 -1
  60. package/dist/contexts/sandbox.js +5 -0
  61. package/dist/contexts/sandbox.js.map +1 -1
  62. package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
  63. package/dist/contexts-d7UolYot.js.map +1 -0
  64. package/dist/contexts.d.ts +3 -3
  65. package/dist/contexts.js +1 -1
  66. package/dist/cred-keys-GpBg71cP.js +105 -0
  67. package/dist/cred-keys-GpBg71cP.js.map +1 -0
  68. package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
  69. package/dist/credentials-JttEuRON.js.map +1 -0
  70. package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
  71. package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
  72. package/dist/daemon-cli.d.ts +1 -1
  73. package/dist/daemon-cli.js +3 -2
  74. package/dist/daemon-cli.js.map +1 -1
  75. package/dist/daytona-DG3omipZ.js +513 -0
  76. package/dist/daytona-DG3omipZ.js.map +1 -0
  77. package/dist/defaults-Cx3zvDOV.js +23 -0
  78. package/dist/defaults-Cx3zvDOV.js.map +1 -0
  79. package/dist/dispatcher-BMlu2BmZ.js +4941 -0
  80. package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
  81. package/dist/docker-BZhMMJUp.js +727 -0
  82. package/dist/docker-BZhMMJUp.js.map +1 -0
  83. package/dist/e2b-CEVOdRib.js +480 -0
  84. package/dist/e2b-CEVOdRib.js.map +1 -0
  85. package/dist/edit-utils-EGosADZq.js +234 -0
  86. package/dist/edit-utils-EGosADZq.js.map +1 -0
  87. package/dist/environment-8wsKE2Ln.js +214 -0
  88. package/dist/environment-8wsKE2Ln.js.map +1 -0
  89. package/dist/eval-BNcvle_J.js +1595 -0
  90. package/dist/eval-BNcvle_J.js.map +1 -0
  91. package/dist/eval.d.ts +2 -2
  92. package/dist/eval.js +1 -1489
  93. package/dist/executor-Cx5-8yqi.js +621 -0
  94. package/dist/executor-Cx5-8yqi.js.map +1 -0
  95. package/dist/extension-authoring-DyGGmq9V.js +385 -0
  96. package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
  97. package/dist/extensions.d.ts +2 -2
  98. package/dist/extensions.js +3 -3
  99. package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
  100. package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
  101. package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
  102. package/dist/format-C2NQEVUH.js.map +1 -0
  103. package/dist/format-bytes-C7tfc3Zm.js +55 -0
  104. package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
  105. package/dist/headless-C_rNUuYC.js +960 -0
  106. package/dist/headless-C_rNUuYC.js.map +1 -0
  107. package/dist/headless.d.ts +1 -1
  108. package/dist/headless.js +1 -413
  109. package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
  110. package/dist/history-search-CcYzF8-0.js.map +1 -0
  111. package/dist/history-search-worker.d.ts +1 -1
  112. package/dist/history-search-worker.js +1 -1
  113. package/dist/host-D7NrI03V.js +378 -0
  114. package/dist/host-D7NrI03V.js.map +1 -0
  115. package/dist/host-signals-BcP5QKUD.js +118 -0
  116. package/dist/host-signals-BcP5QKUD.js.map +1 -0
  117. package/dist/identity-CwfO8K-t.js +26 -0
  118. package/dist/identity-CwfO8K-t.js.map +1 -0
  119. package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
  120. package/dist/index-BGe1fQT7.d.ts.map +1 -0
  121. package/dist/index-BVQsIKGn.d.ts +448 -0
  122. package/dist/index-BVQsIKGn.d.ts.map +1 -0
  123. package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
  124. package/dist/index-CHABJd-L.d.ts.map +1 -0
  125. package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
  126. package/dist/index-D6a7qXpg.d.ts.map +1 -0
  127. package/dist/index.d.ts +6 -6
  128. package/dist/index.js +27 -23
  129. package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
  130. package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
  131. package/dist/ipc/remote.d.ts +313 -0
  132. package/dist/ipc/remote.d.ts.map +1 -0
  133. package/dist/ipc/remote.js +4 -0
  134. package/dist/ipc.d.ts +6 -964
  135. package/dist/ipc.js +403 -4
  136. package/dist/ipc.js.map +1 -0
  137. package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
  138. package/dist/isolation-D9L650W5.d.ts.map +1 -0
  139. package/dist/json-rpc--HXQti1E.js +350 -0
  140. package/dist/json-rpc--HXQti1E.js.map +1 -0
  141. package/dist/links-j8rED1sR.js +603 -0
  142. package/dist/links-j8rED1sR.js.map +1 -0
  143. package/dist/local-terminal-D8QThwo_.js +252 -0
  144. package/dist/local-terminal-D8QThwo_.js.map +1 -0
  145. package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
  146. package/dist/logger-Gtqlayx8.js.map +1 -0
  147. package/dist/logs-view-CWG8aUAG.js.map +1 -1
  148. package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
  149. package/dist/mcp-_wecH9Qe.js.map +1 -0
  150. package/dist/mcp.d.ts +2 -2
  151. package/dist/mcp.js +2 -2
  152. package/dist/media-sniff-UKijEaiQ.js.map +1 -1
  153. package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
  154. package/dist/messages-BqiwcD2Q.js.map +1 -0
  155. package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
  156. package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
  157. package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
  158. package/dist/openai-compat-CFrpH7uq.js.map +1 -0
  159. package/dist/orchestration-BCGmB8Ps.js +511 -0
  160. package/dist/orchestration-BCGmB8Ps.js.map +1 -0
  161. package/dist/output/stream-json.d.ts +1 -2
  162. package/dist/output/stream-json.d.ts.map +1 -1
  163. package/dist/output/stream-json.js +1 -1
  164. package/dist/output/terminal.d.ts +1 -2
  165. package/dist/output/terminal.d.ts.map +1 -1
  166. package/dist/output/terminal.js +13 -7
  167. package/dist/output/terminal.js.map +1 -1
  168. package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
  169. package/dist/plugins-DS7mahzZ.js.map +1 -0
  170. package/dist/plugins.d.ts +1 -1
  171. package/dist/plugins.js +1 -2
  172. package/dist/prelude-Cxo4t74B.js +517 -0
  173. package/dist/prelude-Cxo4t74B.js.map +1 -0
  174. package/dist/presets.d.ts +1 -1
  175. package/dist/presets.js +1 -2
  176. package/dist/project-root-B8zADr4o.js +167 -0
  177. package/dist/project-root-B8zADr4o.js.map +1 -0
  178. package/dist/project-user-paths-BSgtrRxl.js +58 -0
  179. package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
  180. package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
  181. package/dist/prompts-DYcvqShf.d.ts.map +1 -0
  182. package/dist/protocol-DnhqqSmE.js +13 -0
  183. package/dist/protocol-DnhqqSmE.js.map +1 -0
  184. package/dist/providers/anthropic.d.ts +2 -2
  185. package/dist/providers/anthropic.js +1 -2
  186. package/dist/providers/arcee.d.ts +1 -1
  187. package/dist/providers/arcee.js +1 -1
  188. package/dist/providers/baseten.d.ts +1 -1
  189. package/dist/providers/baseten.js +1 -1
  190. package/dist/providers/cerebras.d.ts +1 -1
  191. package/dist/providers/cerebras.js +3 -2
  192. package/dist/providers/cerebras.js.map +1 -1
  193. package/dist/providers/local.d.ts +1 -1
  194. package/dist/providers/local.js +1 -1
  195. package/dist/providers/openai-compat.d.ts +1 -1
  196. package/dist/providers/openai-compat.js +1 -2
  197. package/dist/providers/openai.d.ts +1 -1
  198. package/dist/providers/openai.js +15 -12
  199. package/dist/providers/openai.js.map +1 -1
  200. package/dist/providers/openrouter.d.ts +1 -1
  201. package/dist/providers/openrouter.js +3 -2
  202. package/dist/providers/openrouter.js.map +1 -1
  203. package/dist/providers/xai.d.ts +1 -1
  204. package/dist/providers/xai.js +3 -3
  205. package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
  206. package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
  207. package/dist/providers.d.ts +1 -1
  208. package/dist/providers.js +4 -4
  209. package/dist/registry-D6ShBWJU.js +5234 -0
  210. package/dist/registry-D6ShBWJU.js.map +1 -0
  211. package/dist/remote-hosts-BtA_9ZGp.js +97 -0
  212. package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
  213. package/dist/restate.d.ts +2 -3
  214. package/dist/restate.d.ts.map +1 -1
  215. package/dist/restate.js +631 -572
  216. package/dist/restate.js.map +1 -1
  217. package/dist/run-summary-CklLiZ4y.js +288 -0
  218. package/dist/run-summary-CklLiZ4y.js.map +1 -0
  219. package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
  220. package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
  221. package/dist/session/sqlite.d.ts +1 -2
  222. package/dist/session/sqlite.d.ts.map +1 -1
  223. package/dist/session/sqlite.js +1 -616
  224. package/dist/session-factory-BUGY5P40.js +1576 -0
  225. package/dist/session-factory-BUGY5P40.js.map +1 -0
  226. package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
  227. package/dist/session-xh9JXu6i.js.map +1 -0
  228. package/dist/session.d.ts +1 -1
  229. package/dist/session.js +2 -2
  230. package/dist/settings-keys-Ckf29NeM.js +677 -0
  231. package/dist/settings-keys-Ckf29NeM.js.map +1 -0
  232. package/dist/shell-path-Dqaoow2J.js +412 -0
  233. package/dist/shell-path-Dqaoow2J.js.map +1 -0
  234. package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
  235. package/dist/skills-DKqZJm4X.js.map +1 -0
  236. package/dist/skills.d.ts +2 -2
  237. package/dist/skills.js +1 -2
  238. package/dist/source-mPExaUm8.js +381 -0
  239. package/dist/source-mPExaUm8.js.map +1 -0
  240. package/dist/sqlite-DV1DQzN2.js +698 -0
  241. package/dist/sqlite-DV1DQzN2.js.map +1 -0
  242. package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
  243. package/dist/src-BRMYRJib.js.map +1 -0
  244. package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
  245. package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
  246. package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
  247. package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
  248. package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
  249. package/dist/timeout-DEaqslLO.d.ts.map +1 -1
  250. package/dist/todo-edits-Dn251YUP.js +1790 -0
  251. package/dist/todo-edits-Dn251YUP.js.map +1 -0
  252. package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
  253. package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
  254. package/dist/tool-state-Dku6YqAB.js +989 -0
  255. package/dist/tool-state-Dku6YqAB.js.map +1 -0
  256. package/dist/tools/fetch-url.d.ts +1 -2
  257. package/dist/tools/fetch-url.d.ts.map +1 -1
  258. package/dist/tools/fetch-url.js +1 -2
  259. package/dist/tools/prompts.d.ts +1 -1
  260. package/dist/tools/prompts.js +7 -7
  261. package/dist/tools/prompts.js.map +1 -1
  262. package/dist/tools/web-search.d.ts +1 -2
  263. package/dist/tools/web-search.d.ts.map +1 -1
  264. package/dist/tools/web-search.js +2 -2
  265. package/dist/tools/web-search.js.map +1 -1
  266. package/dist/tools-_DnT3AGM.js +578 -0
  267. package/dist/tools-_DnT3AGM.js.map +1 -0
  268. package/dist/tools.d.ts +3 -3
  269. package/dist/tools.js +4 -2
  270. package/dist/tui.d.ts +534 -517
  271. package/dist/tui.d.ts.map +1 -1
  272. package/dist/tui.js +34933 -27242
  273. package/dist/tui.js.map +1 -1
  274. package/dist/turn-operations-B8sokwi5.js +333 -0
  275. package/dist/turn-operations-B8sokwi5.js.map +1 -0
  276. package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
  277. package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
  278. package/dist/types-C7ZFOztE.d.ts +132 -0
  279. package/dist/types-C7ZFOztE.d.ts.map +1 -0
  280. package/dist/types-CH5XpIHw.js +114 -0
  281. package/dist/types-CH5XpIHw.js.map +1 -0
  282. package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
  283. package/dist/types-Cu0ZGDu9.js.map +1 -0
  284. package/dist/types-IqegbJEE.d.ts +624 -0
  285. package/dist/types-IqegbJEE.d.ts.map +1 -0
  286. package/dist/types.d.ts +4 -4
  287. package/dist/types.js +1 -1
  288. package/dist/url-D8HCl65b.js +1259 -0
  289. package/dist/url-D8HCl65b.js.map +1 -0
  290. package/dist/wasm-BVT-j5cl.js +33 -0
  291. package/dist/wasm-BVT-j5cl.js.map +1 -0
  292. package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
  293. package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
  294. package/dist/ws-CIHMvlSh.js +952 -0
  295. package/dist/ws-CIHMvlSh.js.map +1 -0
  296. package/dist/ws-client-N7NxzvQp.js +230 -0
  297. package/dist/ws-client-N7NxzvQp.js.map +1 -0
  298. package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
  299. package/dist/xai-CvJTeLrI.js.map +1 -0
  300. package/dist/xdg-zweed0-t.js +117 -0
  301. package/dist/xdg-zweed0-t.js.map +1 -0
  302. package/docs/ACP.md +52 -0
  303. package/docs/ARCHITECTURE.md +103 -6
  304. package/docs/ARTIFACTS.md +8 -4
  305. package/docs/CHAT.md +165 -14
  306. package/docs/EXECUTION_CONTEXT.md +8 -0
  307. package/docs/EXTENSIONS.md +123 -2
  308. package/docs/HEADLESS.md +2 -0
  309. package/docs/IPC.md +775 -64
  310. package/docs/MACHINES.md +456 -0
  311. package/docs/PANELS.md +3 -0
  312. package/docs/README.md +4 -0
  313. package/docs/RESTATE.md +3 -2
  314. package/docs/RUN_IN_BACKGROUND.md +10 -2
  315. package/docs/SERVER.md +1085 -0
  316. package/docs/SKILL.md +6 -1
  317. package/docs/TERMINAL.md +75 -0
  318. package/docs/TUI.md +65 -14
  319. package/package.json +58 -26
  320. package/scripts/eval.ts +4 -0
  321. package/dist/acp-D-tVyUjw.js.map +0 -1
  322. package/dist/agent-D0zZnGbt.js.map +0 -1
  323. package/dist/anthropic-C2aole0G.js.map +0 -1
  324. package/dist/approvals-DKaJZYlm.js.map +0 -1
  325. package/dist/atomic-write-B7zr1ddF.js.map +0 -1
  326. package/dist/auth-BG2rVKSt.js.map +0 -1
  327. package/dist/completion-core-BRo86R_L.js.map +0 -1
  328. package/dist/contexts/daytona.js.map +0 -1
  329. package/dist/contexts/docker.js.map +0 -1
  330. package/dist/contexts/e2b.js.map +0 -1
  331. package/dist/contexts-CRE9pw07.js.map +0 -1
  332. package/dist/eval.js.map +0 -1
  333. package/dist/format-BF745pLL.js.map +0 -1
  334. package/dist/glob-DluQFSw1.js +0 -270
  335. package/dist/glob-DluQFSw1.js.map +0 -1
  336. package/dist/headless.js.map +0 -1
  337. package/dist/history-search-C4bk1Wz_.js.map +0 -1
  338. package/dist/index-BgN1T3lk.d.ts.map +0 -1
  339. package/dist/index-C37_ppWv.d.ts.map +0 -1
  340. package/dist/index-C6NEd5y_.d.ts.map +0 -1
  341. package/dist/ipc-zVSyo6K1.js +0 -331
  342. package/dist/ipc-zVSyo6K1.js.map +0 -1
  343. package/dist/ipc.d.ts.map +0 -1
  344. package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
  345. package/dist/json-rpc-rSWMUh9b.js +0 -192
  346. package/dist/json-rpc-rSWMUh9b.js.map +0 -1
  347. package/dist/logger--C1VQjwJ.js.map +0 -1
  348. package/dist/mcp-CgNd-f3F.js.map +0 -1
  349. package/dist/messages-2jcOA_5R.js.map +0 -1
  350. package/dist/openai-compat-Dy56weK8.js.map +0 -1
  351. package/dist/output-cap-C9zukcCj.js +0 -100
  352. package/dist/output-cap-C9zukcCj.js.map +0 -1
  353. package/dist/panels-B6gRk4bf.js +0 -789
  354. package/dist/panels-B6gRk4bf.js.map +0 -1
  355. package/dist/plugins-gbI7SBA6.js.map +0 -1
  356. package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
  357. package/dist/run-summary-BU_NgwUT.js +0 -269
  358. package/dist/run-summary-BU_NgwUT.js.map +0 -1
  359. package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
  360. package/dist/session/sqlite.js.map +0 -1
  361. package/dist/session-BqRP1hS7.js.map +0 -1
  362. package/dist/shell-path-h5czzllR.js +0 -1549
  363. package/dist/shell-path-h5czzllR.js.map +0 -1
  364. package/dist/skills-BC3dodWp.js.map +0 -1
  365. package/dist/src-CkNQKFKr.js.map +0 -1
  366. package/dist/todo-edits-UOwgxGKu.js +0 -528
  367. package/dist/todo-edits-UOwgxGKu.js.map +0 -1
  368. package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
  369. package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
  370. package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
  371. package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
  372. package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
  373. package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
  374. package/dist/turn-operations-DrbJlpq9.js.map +0 -1
  375. package/dist/types-CWgENVLY.js.map +0 -1
  376. package/dist/xai-CazjStOK.js.map +0 -1
@@ -0,0 +1,989 @@
1
+ import { d as toolResultToText } from "./types-Cu0ZGDu9.js";
2
+ import { n as deriveMcpToolMeta, r as nonOwningMcpView } from "./mcp-_wecH9Qe.js";
3
+ import { toolPrompts } from "./tools/prompts.js";
4
+ import { i as styleReplacementForVia, n as resolveOldString } from "./edit-utils-EGosADZq.js";
5
+ import { o as toCanonicalName } from "./aliasing-lVFbm81n.js";
6
+ import { a as readFileTargets, r as readFileBatchHeader, t as formatBytes } from "./format-bytes-C7tfc3Zm.js";
7
+ import { Buffer } from "node:buffer";
8
+ import { resolve } from "node:path";
9
+ //#region src/tools/read-state.ts
10
+ const STATE = /* @__PURE__ */ new WeakMap();
11
+ /**
12
+ * Get or lazily create the per-session read-state map. Returns `undefined`
13
+ * when no session is provided.
14
+ *
15
+ * Most tool callers should prefer {@link resolveReadStateMap}, which
16
+ * additionally honors an explicit `ctx.readState` (the path
17
+ * `spawn`'s `shareReadState: true` uses to forward the parent's map
18
+ * into a sessionless child). Use this helper directly only when the
19
+ * Session-keyed map is exactly what you want and you don't need to
20
+ * accept an override.
21
+ */
22
+ function getReadState(session) {
23
+ if (!session) return void 0;
24
+ let map = STATE.get(session);
25
+ if (!map) {
26
+ map = /* @__PURE__ */ new Map();
27
+ STATE.set(session, map);
28
+ }
29
+ return map;
30
+ }
31
+ /**
32
+ * Resolve the active read-state map from a tool context. An explicit
33
+ * `ctx.readState` wins (used by `spawn`'s `shareReadState` opt-in to
34
+ * forward the parent's map into a sessionless child); otherwise the
35
+ * usual `Session`-keyed lookup applies.
36
+ *
37
+ * Tools should call this helper instead of `getReadState(ctx.session)`
38
+ * directly so the `shareReadState` plumbing is honored uniformly.
39
+ */
40
+ function resolveReadStateMap(ctx) {
41
+ return ctx.readState ?? getReadState(ctx.session);
42
+ }
43
+ /**
44
+ * Mark a read-state entry as elided from the on-wire history WITHOUT
45
+ * un-registering it.
46
+ *
47
+ * Used by the loop's `elideStaleReads` pass. The entry must survive —
48
+ * deleting it made the `requireReadBeforeEdit` gate reject the very next
49
+ * edit on a file the model had demonstrably read and just edited (the
50
+ * gate's failure mode then defeats the gate: models degrade to raw shell
51
+ * edits that bypass the guard entirely). The `elided` flag instead
52
+ * defeats only the dedup stub: the next identical re-read returns the
53
+ * full body again, and `rememberRead` clears the flag.
54
+ *
55
+ * No-op when the path has no entry in the resolved map(s).
56
+ */
57
+ function markReadStateElided(ctx, cwd, path) {
58
+ const key = readStateKey(cwd, path);
59
+ for (const map of [ctx.readState, ctx.session ? STATE.get(ctx.session) : void 0]) {
60
+ const entry = map?.get(key);
61
+ if (entry && entry.elided !== true) map.set(key, {
62
+ ...entry,
63
+ elided: true
64
+ });
65
+ }
66
+ }
67
+ /**
68
+ * Record one `requireReadBeforeEdit` drift refusal against `entry` and
69
+ * return the consecutive count (1 for the first). The caller composes the
70
+ * refusal message with {@link staleRefusalHint}.
71
+ */
72
+ function noteStaleRejection(map, key, entry) {
73
+ const count = (entry.staleRejections ?? 0) + 1;
74
+ map.set(key, {
75
+ ...entry,
76
+ staleRejections: count
77
+ });
78
+ return count;
79
+ }
80
+ /**
81
+ * Escalating suffix for a drift refusal. Empty on the first refusal — the
82
+ * base "re-read the file" advice is correct and sufficient. From the second
83
+ * consecutive refusal on, the model has demonstrably re-read and been
84
+ * refused again, so repeating the same advice reads as a broken tool;
85
+ * name the real hypothesis (an external writer) instead.
86
+ */
87
+ function staleRefusalHint(count) {
88
+ if (count < 2) return "";
89
+ return ` This is refusal #${count} since your last read — a process outside this session (editor auto-save, formatter, codegen watcher) may be rewriting the file between your reads.`;
90
+ }
91
+ /**
92
+ * Canonical read-state key for a `(cwd, path)` pair.
93
+ *
94
+ * `ctx.execution.readFile(handle, path)` resolves the model-provided
95
+ * path against `handle.cwd` before touching disk — so `src/App.tsx`,
96
+ * `./src/App.tsx`, and `/abs/cwd/src/App.tsx` all read the **same**
97
+ * bytes. The read-state map MUST mirror that resolution: without it,
98
+ * a model that reads `src/App.tsx` and then edits `./src/App.tsx`
99
+ * trips the `requireReadBeforeEdit` gate for a file it demonstrably
100
+ * already saw (the gate's "has not been read in this session" message
101
+ * fires on a stale key).
102
+ *
103
+ * `node:path`'s `resolve(cwd, path)` short-circuits when `path` is
104
+ * already absolute, so absolute and relative shapes converge on the
105
+ * same canonical form. We don't `realpath()` symlinks — the file IS
106
+ * the path the model addressed, not the realpath behind it; the host's
107
+ * execution context decides how to dereference.
108
+ */
109
+ function readStateKey(cwd, path) {
110
+ return resolve(cwd, path);
111
+ }
112
+ /**
113
+ * 64-bit content hash: two independent 32-bit FNV-1a-style lanes (different
114
+ * offset bases + multipliers) concatenated as 16 hex chars. Fast,
115
+ * non-cryptographic — but wide enough that the `requireReadBeforeEdit`
116
+ * drift gate, which silently corrupts a file on a false "unchanged"
117
+ * verdict, isn't betting on a 32-bit birthday bound (~1 in 4 billion per
118
+ * pair; uncomfortably reachable over many files × many sessions). Entries
119
+ * live only in per-session in-memory maps, so widening needs no
120
+ * stored-format migration. Still cheaper than allocating a Buffer and
121
+ * pulling in `crypto`.
122
+ */
123
+ function hashContent(text) {
124
+ let h1 = 2166136261;
125
+ let h2 = 2128831031;
126
+ for (let i = 0; i < text.length; i++) {
127
+ const c = text.charCodeAt(i);
128
+ h1 = Math.imul(h1 ^ c, 16777619) >>> 0;
129
+ h2 = Math.imul(h2 ^ c, 2246822507) >>> 0;
130
+ }
131
+ return h1.toString(16).padStart(8, "0") + h2.toString(16).padStart(8, "0");
132
+ }
133
+ const READ_FILE_DEFAULT_OFFSET = 1;
134
+ const READ_FILE_DEFAULT_LIMIT = 2e3;
135
+ const READ_FILE_DEFAULT_MAX_BYTES = 262144;
136
+ const READ_FILE_FOOTER_RE = /\n\n…(?:read lines|truncated)/;
137
+ const READ_FILE_LINE_RE = /^\d{1,9}\t(.*)$/;
138
+ /**
139
+ * Rebuild the per-session read-state map from durable session turns.
140
+ *
141
+ * Durable replay runtimes may return recorded tool results without re-running
142
+ * the tool body, so in-memory side effects like `readState.set(...)` can be
143
+ * missing even though the transcript contains the successful `read_file`.
144
+ * This helper is intentionally opt-in: live hosts keep the normal side-effect
145
+ * behavior unless they call it themselves.
146
+ *
147
+ * Hydration only fills missing keys. Live in-memory state may already reflect a
148
+ * newer read or edit from the current run, and durable history cannot prove it
149
+ * is fresher. Relative paths are resolved against the current execution cwd,
150
+ * matching replay hosts that run sessions from a stable workspace.
151
+ */
152
+ function hydrateReadStateFromSession(session, cwd, options = {}) {
153
+ if (!session) return 0;
154
+ const readState = getReadState(session);
155
+ if (!readState) return 0;
156
+ const normalized = normalizeHydrateReadStateOptions(options);
157
+ const pending = /* @__PURE__ */ new Map();
158
+ const known = /* @__PURE__ */ new Map();
159
+ const preexistingKeys = new Set(readState.keys());
160
+ let hydrated = 0;
161
+ for (const turn of session.turns) for (const block of turn.content) {
162
+ if (block.type === "tool_call") {
163
+ const canonicalName = canonicalToolCallName(block.name, normalized);
164
+ if (canonicalName === normalized.readFileToolName || canonicalName === normalized.writeFileToolName || canonicalName === normalized.editToolName || canonicalName === normalized.multiEditToolName) pending.set(block.id, {
165
+ name: canonicalName,
166
+ input: block.input
167
+ });
168
+ continue;
169
+ }
170
+ if (block.type !== "tool_result") continue;
171
+ const call = pending.get(block.callId);
172
+ if (!call) continue;
173
+ pending.delete(block.callId);
174
+ if (block.isError === true) continue;
175
+ const output = toolResultToText(block.output);
176
+ for (const next of stateFromToolResult(call, output, turn, cwd, normalized, known)) {
177
+ if (!preexistingKeys.has(next.key)) {
178
+ readState.set(next.key, next.file.entry);
179
+ hydrated += 1;
180
+ }
181
+ known.set(next.key, next.file);
182
+ }
183
+ }
184
+ return hydrated;
185
+ }
186
+ /**
187
+ * Async replay hydrator for durable hosts that can cheaply read the current
188
+ * full file through their execution context. Transcript-only reconstruction is
189
+ * still preferred for full reads; partial/truncated read_file entries fall back
190
+ * to `readFileForHash` and hash those full current bytes.
191
+ */
192
+ async function hydrateReadStateFromSessionAsync(session, cwd, options = {}) {
193
+ if (!session) return 0;
194
+ const readState = getReadState(session);
195
+ if (!readState) return 0;
196
+ const normalized = normalizeHydrateReadStateOptions(options);
197
+ const pending = /* @__PURE__ */ new Map();
198
+ const known = /* @__PURE__ */ new Map();
199
+ const preexistingKeys = new Set(readState.keys());
200
+ let hydrated = 0;
201
+ for (const turn of session.turns) for (const block of turn.content) {
202
+ if (block.type === "tool_call") {
203
+ const canonicalName = canonicalToolCallName(block.name, normalized);
204
+ if (canonicalName === normalized.readFileToolName || canonicalName === normalized.writeFileToolName || canonicalName === normalized.editToolName || canonicalName === normalized.multiEditToolName) pending.set(block.id, {
205
+ name: canonicalName,
206
+ input: block.input
207
+ });
208
+ continue;
209
+ }
210
+ if (block.type !== "tool_result") continue;
211
+ const call = pending.get(block.callId);
212
+ if (!call) continue;
213
+ pending.delete(block.callId);
214
+ if (block.isError === true) continue;
215
+ const output = toolResultToText(block.output);
216
+ for (const next of await stateFromToolResultAsync(call, output, turn, cwd, normalized, known)) {
217
+ if (!preexistingKeys.has(next.key)) {
218
+ readState.set(next.key, next.file.entry);
219
+ hydrated += 1;
220
+ }
221
+ known.set(next.key, next.file);
222
+ }
223
+ }
224
+ return hydrated;
225
+ }
226
+ function normalizeHydrateReadStateOptions(options) {
227
+ return {
228
+ readFileToolName: options.readFileToolName ?? "read_file",
229
+ writeFileToolName: options.writeFileToolName ?? "write_file",
230
+ editToolName: options.editToolName ?? "edit",
231
+ multiEditToolName: options.multiEditToolName ?? "multi_edit",
232
+ defaultLineNumbers: options.defaultLineNumbers ?? true,
233
+ ...options.readFileForHash ? { readFileForHash: options.readFileForHash } : {},
234
+ ...options.aliasMaps ? { aliasMaps: options.aliasMaps } : {}
235
+ };
236
+ }
237
+ /**
238
+ * Resolve a transcript tool-call name to its canonical form for matching.
239
+ * Honors `aliasMaps` (wire → canonical) when present; otherwise the name is
240
+ * already canonical (zidane persists canonical names) and passes through.
241
+ */
242
+ function canonicalToolCallName(name, options) {
243
+ return options.aliasMaps ? toCanonicalName(name, options.aliasMaps) : name;
244
+ }
245
+ function stateFromToolResult(call, output, resultTurn, cwd, options, known) {
246
+ let next;
247
+ if (call.name === options.readFileToolName) return readFileSections(call.input, output).flatMap(({ input, output }) => {
248
+ const state = readFileStateFromResult(input, output, resultTurn, cwd, options.defaultLineNumbers);
249
+ return state ? [state] : [];
250
+ });
251
+ if (call.name === options.writeFileToolName) next = writeFileStateFromResult(call.input, output, resultTurn, cwd);
252
+ else if (call.name === options.editToolName) next = editStateFromResult(call.input, output, resultTurn, cwd, known);
253
+ else if (call.name === options.multiEditToolName) next = multiEditStateFromResult(call.input, output, resultTurn, cwd, known);
254
+ return next ? [next] : [];
255
+ }
256
+ /**
257
+ * A `read_file` call as single-path reads: the call itself, or, for a
258
+ * `paths` batch, one per `==> path <==` section (each with that entry's
259
+ * offset / limit). Sections are found in call order; hydration stops at the
260
+ * first header it can't locate.
261
+ */
262
+ function readFileSections(input, output) {
263
+ if (!Array.isArray(input.paths)) return [{
264
+ input,
265
+ output
266
+ }];
267
+ const targets = readFileTargets(input);
268
+ const out = [];
269
+ let cursor = 0;
270
+ for (let i = 0; i < targets.length; i++) {
271
+ const header = `${readFileBatchHeader(targets[i].path)}\n`;
272
+ if (!output.startsWith(header, cursor)) break;
273
+ const start = cursor + header.length;
274
+ const nextHeader = i + 1 < targets.length ? `\n\n${readFileBatchHeader(targets[i + 1].path)}\n` : void 0;
275
+ const end = nextHeader ? output.indexOf(nextHeader, start) : output.length;
276
+ if (end === -1) break;
277
+ const { path, offset, limit } = targets[i];
278
+ out.push({
279
+ input: {
280
+ path,
281
+ offset,
282
+ limit,
283
+ ...typeof input.lineNumbers === "boolean" ? { lineNumbers: input.lineNumbers } : {}
284
+ },
285
+ output: output.slice(start, end)
286
+ });
287
+ cursor = end + 2;
288
+ }
289
+ return out;
290
+ }
291
+ async function stateFromToolResultAsync(call, output, resultTurn, cwd, options, known) {
292
+ if (call.name === options.readFileToolName) {
293
+ const out = [];
294
+ for (const section of readFileSections(call.input, output)) {
295
+ const state = await readFileStateFromResultAsync(section.input, section.output, resultTurn, cwd, {
296
+ defaultLineNumbers: options.defaultLineNumbers,
297
+ readFileForHash: options.readFileForHash
298
+ });
299
+ if (state) out.push(state);
300
+ }
301
+ return out;
302
+ }
303
+ return stateFromToolResult(call, output, resultTurn, cwd, options, known);
304
+ }
305
+ function readFileStateFromResult(input, output, resultTurn, cwd, defaultLineNumbers) {
306
+ const path = typeof input.path === "string" ? input.path : void 0;
307
+ if (!path || !isSuccessfulFullReadOutput(output)) return void 0;
308
+ const lineNumbers = typeof input.lineNumbers === "boolean" ? input.lineNumbers : defaultLineNumbers;
309
+ const content = lineNumbers ? stripReadFileLineNumbers(output) : output;
310
+ if (content === void 0) return void 0;
311
+ const entry = {
312
+ contentHash: hashContent(content),
313
+ offset: normalizeReadInteger(input.offset, READ_FILE_DEFAULT_OFFSET),
314
+ limit: normalizeReadInteger(input.limit, READ_FILE_DEFAULT_LIMIT),
315
+ maxBytes: normalizeReadInteger(input.maxBytes, READ_FILE_DEFAULT_MAX_BYTES),
316
+ lineNumbers,
317
+ mtimeMs: resultTurn.createdAt
318
+ };
319
+ return {
320
+ key: readStateKey(cwd, path),
321
+ file: {
322
+ content,
323
+ entry
324
+ }
325
+ };
326
+ }
327
+ async function readFileStateFromResultAsync(input, output, resultTurn, cwd, options) {
328
+ const reconstructed = readFileStateFromResult(input, output, resultTurn, cwd, options.defaultLineNumbers);
329
+ if (reconstructed) return reconstructed;
330
+ const path = typeof input.path === "string" ? input.path : void 0;
331
+ if (!path || !options.readFileForHash || !isSuccessfulReadOutput(output)) return void 0;
332
+ let content;
333
+ try {
334
+ content = await options.readFileForHash(path);
335
+ } catch {
336
+ return;
337
+ }
338
+ if (typeof content !== "string") return void 0;
339
+ const lineNumbers = typeof input.lineNumbers === "boolean" ? input.lineNumbers : options.defaultLineNumbers;
340
+ const entry = {
341
+ contentHash: hashContent(content),
342
+ offset: normalizeReadInteger(input.offset, READ_FILE_DEFAULT_OFFSET),
343
+ limit: normalizeReadInteger(input.limit, READ_FILE_DEFAULT_LIMIT),
344
+ maxBytes: normalizeReadInteger(input.maxBytes, READ_FILE_DEFAULT_MAX_BYTES),
345
+ lineNumbers,
346
+ mtimeMs: resultTurn.createdAt
347
+ };
348
+ return {
349
+ key: readStateKey(cwd, path),
350
+ file: {
351
+ content,
352
+ entry
353
+ }
354
+ };
355
+ }
356
+ function writeFileStateFromResult(input, output, resultTurn, cwd) {
357
+ const path = typeof input.path === "string" ? input.path : void 0;
358
+ const content = typeof input.content === "string" ? input.content : void 0;
359
+ if (!path || content === void 0) return void 0;
360
+ if (!output.startsWith(`Created ${path} (`) && !output.startsWith(`Updated ${path} (`)) return void 0;
361
+ return {
362
+ key: readStateKey(cwd, path),
363
+ file: {
364
+ content,
365
+ entry: {
366
+ contentHash: hashContent(content),
367
+ offset: 0,
368
+ limit: Number.POSITIVE_INFINITY,
369
+ maxBytes: Number.POSITIVE_INFINITY,
370
+ mtimeMs: resultTurn.createdAt,
371
+ elided: true
372
+ }
373
+ }
374
+ };
375
+ }
376
+ function editStateFromResult(input, output, resultTurn, cwd, known) {
377
+ const path = typeof input.path === "string" ? input.path : void 0;
378
+ const oldString = typeof input.old_string === "string" ? input.old_string : void 0;
379
+ const newString = typeof input.new_string === "string" ? input.new_string : void 0;
380
+ if (!path || oldString === void 0 || newString === void 0) return void 0;
381
+ if (!output.startsWith(`Edited ${path}: replaced `)) return void 0;
382
+ const key = readStateKey(cwd, path);
383
+ const prior = known.get(key);
384
+ if (!prior) return void 0;
385
+ const nextContent = applyEdit(prior.content, oldString, newString, input.replace_all === true);
386
+ if (nextContent === void 0) return void 0;
387
+ return {
388
+ key,
389
+ file: {
390
+ content: nextContent,
391
+ entry: {
392
+ ...prior.entry,
393
+ contentHash: hashContent(nextContent),
394
+ mtimeMs: resultTurn.createdAt,
395
+ elided: true
396
+ }
397
+ }
398
+ };
399
+ }
400
+ function multiEditStateFromResult(input, output, resultTurn, cwd, known) {
401
+ const path = typeof input.path === "string" ? input.path : void 0;
402
+ const edits = Array.isArray(input.edits) ? input.edits : void 0;
403
+ if (!path || !edits) return void 0;
404
+ if (!output.startsWith(`Edited ${path}: applied `)) return void 0;
405
+ const key = readStateKey(cwd, path);
406
+ const prior = known.get(key);
407
+ if (!prior) return void 0;
408
+ const applied = parseMultiEditAppliedSteps(output, edits.length);
409
+ let current = prior.content;
410
+ for (let i = 0; i < edits.length; i++) {
411
+ if (!applied.has(i)) continue;
412
+ const step = edits[i];
413
+ if (typeof step.old_string !== "string" || typeof step.new_string !== "string") return void 0;
414
+ const next = applyEdit(current, step.old_string, step.new_string, step.replace_all === true);
415
+ if (next === void 0) return void 0;
416
+ current = next;
417
+ }
418
+ return {
419
+ key,
420
+ file: {
421
+ content: current,
422
+ entry: {
423
+ ...prior.entry,
424
+ contentHash: hashContent(current),
425
+ mtimeMs: resultTurn.createdAt,
426
+ elided: true
427
+ }
428
+ }
429
+ };
430
+ }
431
+ function applyEdit(content, oldString, newString, replaceAll) {
432
+ const match = resolveOldString(content, oldString);
433
+ if (!match) return void 0;
434
+ if (match.occurrences > 1 && !replaceAll) return void 0;
435
+ const styledReplacement = styleReplacementForVia(newString, match.via, match.actual);
436
+ return replaceAll ? content.split(match.actual).join(styledReplacement) : content.replace(match.actual, styledReplacement);
437
+ }
438
+ function parseMultiEditAppliedSteps(output, editCount) {
439
+ const annotationMatch = /<edit-outcomes>\n([\s\S]*?)\n<\/edit-outcomes>/.exec(output);
440
+ if (!annotationMatch) return new Set(Array.from({ length: editCount }, (_, i) => i));
441
+ const applied = /* @__PURE__ */ new Set();
442
+ for (const line of annotationMatch[1].split("\n")) {
443
+ const match = /^#(\d+) applied$/.exec(line.trim());
444
+ if (!match) continue;
445
+ const index = Number(match[1]) - 1;
446
+ if (index >= 0 && index < editCount) applied.add(index);
447
+ }
448
+ return applied;
449
+ }
450
+ function isSuccessfulFullReadOutput(output) {
451
+ if (!isSuccessfulReadOutput(output) || READ_FILE_FOOTER_RE.test(output)) return false;
452
+ return true;
453
+ }
454
+ function isSuccessfulReadOutput(output) {
455
+ if (output.length === 0) return true;
456
+ if (output.startsWith("File not found:") || output.startsWith("[binary file:") || output.startsWith("Image:") || output.startsWith("Document:") || output.startsWith("[image too large to inline:") || output.startsWith("[document:") || output.startsWith("[document too large to attach:") || output.startsWith("Image read failed:") || output.startsWith("Document read failed:") || output.startsWith("[skipped:") || output.includes(" unchanged since the previous read in this session ")) return false;
457
+ return true;
458
+ }
459
+ function stripReadFileLineNumbers(output) {
460
+ const lines = output.split("\n");
461
+ const stripped = [];
462
+ for (const line of lines) {
463
+ const match = READ_FILE_LINE_RE.exec(line);
464
+ if (!match) return void 0;
465
+ stripped.push(match[1]);
466
+ }
467
+ return stripped.join("\n");
468
+ }
469
+ function normalizeReadInteger(value, fallback) {
470
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return fallback;
471
+ return Math.floor(value);
472
+ }
473
+ const TOOL_DEDUP_STATE = /* @__PURE__ */ new WeakMap();
474
+ /**
475
+ * Get or lazily create the per-session tool-dedup map. Returns `undefined`
476
+ * when no session is provided — middleware should treat that as "no dedup".
477
+ */
478
+ function getToolDedupState(session) {
479
+ if (!session) return void 0;
480
+ let map = TOOL_DEDUP_STATE.get(session);
481
+ if (!map) {
482
+ map = /* @__PURE__ */ new Map();
483
+ TOOL_DEDUP_STATE.set(session, map);
484
+ }
485
+ return map;
486
+ }
487
+ //#endregion
488
+ //#region src/tools/model-search.ts
489
+ /**
490
+ * One display line per model: id, provider, real pricing, context
491
+ * window, reasoning flag. The single source of truth for how models
492
+ * render in BOTH the spawn schema's embedded catalog and `model_search`
493
+ * output, so the model never sees two spellings of the same entry.
494
+ */
495
+ function formatModelLine(entry) {
496
+ const { model } = entry;
497
+ const parts = [`${model.id} (${entry.provider})`];
498
+ if (model.cost) parts.push(`$${model.cost.input}/$${model.cost.output} per Mtok`);
499
+ if (typeof model.contextWindow === "number" && model.contextWindow > 0) parts.push(`${Math.round(model.contextWindow / 1e3)}k ctx`);
500
+ if (model.reasoning) parts.push("reasoning");
501
+ if (model.name && model.name !== model.id) parts.push(model.name);
502
+ return parts.join(" · ");
503
+ }
504
+ /**
505
+ * Case-insensitive multi-term filter across id, display name, and
506
+ * provider. Every whitespace-separated term must match somewhere
507
+ * (mirrors the TUI picker's `filterModelCatalog` semantics). Empty /
508
+ * whitespace queries pass everything through.
509
+ */
510
+ function matchModelEntries(entries, query) {
511
+ const trimmed = query.trim().toLowerCase();
512
+ if (!trimmed) return [...entries];
513
+ const terms = trimmed.split(/\s+/);
514
+ return entries.filter((entry) => {
515
+ const corpus = `${entry.model.id} ${entry.model.name ?? ""} ${entry.provider}`.toLowerCase();
516
+ return terms.every((t) => corpus.includes(t));
517
+ });
518
+ }
519
+ /**
520
+ * Build the `model_search` tool over a spawn model catalog. Register it
521
+ * alongside `createSpawnTool({ models })` — typically only when the
522
+ * catalog is too large to embed in the spawn schema, though it is
523
+ * harmless (and occasionally useful) alongside an embedded catalog too.
524
+ */
525
+ function createModelSearchTool(models) {
526
+ return {
527
+ spec: {
528
+ name: "model_search",
529
+ description: toolPrompts.model_search,
530
+ inputSchema: {
531
+ type: "object",
532
+ properties: { query: {
533
+ type: "string",
534
+ description: "Optional filter: space-separated terms, ALL must match (e.g. \"haiku\" or \"openrouter qwen\")."
535
+ } },
536
+ additionalProperties: false
537
+ }
538
+ },
539
+ async execute(input) {
540
+ const query = typeof input.query === "string" ? input.query : "";
541
+ const matches = matchModelEntries(models, query);
542
+ if (matches.length === 0) return query.trim() === "" ? "No models are configured for subagent use." : `No models match "${query.trim()}". Call model_search without a query to list all ${models.length}.`;
543
+ return [query.trim() === "" ? `${matches.length} model${matches.length === 1 ? "" : "s"} available for spawned subagents:` : `${matches.length} of ${models.length} model${models.length === 1 ? "" : "s"} match:`, ...matches.map((m) => `- ${formatModelLine(m)}`)].join("\n");
544
+ }
545
+ };
546
+ }
547
+ //#endregion
548
+ //#region src/tools/spawn-helpers.ts
549
+ const sessionChildCounters = /* @__PURE__ */ new WeakMap();
550
+ /** Chronological child runs (depth > 0) — index + 1 is the `child-N` label. */
551
+ function childRunsOf(session) {
552
+ return session.runs.filter((r) => (r.depth ?? 0) > 0);
553
+ }
554
+ /**
555
+ * Human/model-facing list of this session's child runs. Prefers the label
556
+ * persisted at `startRun` (`SessionRun.label`) and falls back to positional
557
+ * numbering for legacy sessions recorded before labels were stored.
558
+ * Rendered into resume-rejection messages so the model can self-correct
559
+ * with a valid label.
560
+ */
561
+ function describeChildRuns(session) {
562
+ const childRuns = childRunsOf(session);
563
+ if (childRuns.length === 0) return "No child runs exist in this session.";
564
+ return childRuns.map((r, i) => `- ${r.label ?? `child-${i + 1}`} · ${r.status} · ${r.prompt.slice(0, 80)}`).join("\n");
565
+ }
566
+ /**
567
+ * Reserve the next `child-N` label for this session. Exported so the durable
568
+ * (child-as-invocation) spawn tool in `src/restate/spawn.ts` allocates labels
569
+ * from the same session-anchored counter — otherwise the two tools would number
570
+ * children independently and a session that used both would collide.
571
+ */
572
+ function reserveChildLabel(session) {
573
+ let counter = sessionChildCounters.get(session);
574
+ if (counter === void 0) {
575
+ const childRuns = childRunsOf(session);
576
+ counter = childRuns.length;
577
+ for (const r of childRuns) {
578
+ const m = r.label ? /^child-(\d+)$/.exec(r.label) : null;
579
+ if (m) counter = Math.max(counter, Number(m[1]));
580
+ }
581
+ }
582
+ counter += 1;
583
+ sessionChildCounters.set(session, counter);
584
+ return `child-${counter}`;
585
+ }
586
+ function extractText(message) {
587
+ if (!message || typeof message !== "object") return "";
588
+ const msg = message;
589
+ if (typeof msg.content === "string") return msg.content;
590
+ if (Array.isArray(msg.content)) return msg.content.filter((block) => !!block && typeof block === "object" && block.type === "text").map((block) => block.text).join("\n");
591
+ return "";
592
+ }
593
+ /**
594
+ * Read-only tool whitelist applied when a subagent preset has
595
+ * `readonly: true` and no explicit `tools` list. Intentionally narrow —
596
+ * only obviously non-mutating built-ins. Hosts wanting a different
597
+ * read-only profile (e.g. include `glob` for a code-search agent) should
598
+ * pass an explicit `tools` array on the subagent def.
599
+ */
600
+ const READONLY_TOOL_DEFAULTS = [
601
+ "read_file",
602
+ "grep",
603
+ "glob",
604
+ "list_files"
605
+ ];
606
+ /**
607
+ * Apply a subagent preset's tool filter to the parent's tool registry.
608
+ * Always a strict subset of the input — the child agent never gains
609
+ * tools the parent doesn't have. Names that don't match a parent tool
610
+ * are silently dropped (matches MCP's lenient `enabledTools` behavior).
611
+ *
612
+ * Precedence: `def.tools` (explicit list) > `def.readonly: true`
613
+ * (built-in read-only set) > unfiltered.
614
+ */
615
+ function filterToolsForSubagent(parentTools, def) {
616
+ if (!parentTools) return parentTools;
617
+ const explicit = def.tools;
618
+ if (explicit && explicit.length > 0) {
619
+ const wanted = new Set(explicit);
620
+ const filtered = {};
621
+ for (const [registryKey, t] of Object.entries(parentTools)) if (wanted.has(t.spec.name)) filtered[registryKey] = t;
622
+ return filtered;
623
+ }
624
+ if (def.readonly) {
625
+ const wanted = new Set(READONLY_TOOL_DEFAULTS);
626
+ const filtered = {};
627
+ for (const [registryKey, t] of Object.entries(parentTools)) if (wanted.has(t.spec.name)) filtered[registryKey] = t;
628
+ return filtered;
629
+ }
630
+ return parentTools;
631
+ }
632
+ /**
633
+ * Wrap the parent's live MCP connection as a child `mcpConnector`. The
634
+ * child agent gets the SAME already-connected, already-wrapped tool defs
635
+ * (and instructions) — no re-bootstrap, no re-auth, so servers connected
636
+ * through a custom parent connector (e.g. the TUI's OAuth-aware one) stay
637
+ * reachable from subagents. `close` is a no-op: the parent owns the
638
+ * transports and closes them on its own destroy; a child's destroy must
639
+ * never tear down connections the parent is still using.
640
+ *
641
+ * Shared tool defs keep the hook bus they were built with, so
642
+ * `mcp:tool:gate` / `mcp:tool:transform` fire on the parent's hooks —
643
+ * child MCP calls are governed by the same gate policy as the session
644
+ * that spawned them.
645
+ */
646
+ function nonOwningMcpConnector(connection) {
647
+ return async () => nonOwningMcpView(connection);
648
+ }
649
+ /**
650
+ * Decide what MCP state a child inherits, honoring the subagent tool
651
+ * policy. `filterToolsForSubagent` only sees the parent's native registry
652
+ * — MCP tools arrive later via the child's connector — so without this
653
+ * gate a `readonly` or allowlisted subagent would inherit the parent's
654
+ * FULL MCP toolset on top of its filtered natives.
655
+ *
656
+ * Policy mirror of {@link filterToolsForSubagent}:
657
+ * - no def / unrestricted def → full inheritance (config + shared live
658
+ * connection when present).
659
+ * - `readonly: true` → nothing. MCP tools carry unknown mutation risk;
660
+ * the read-only whitelist is intentionally native-only. Subagents that
661
+ * need specific MCP reads should use an explicit `tools` list.
662
+ * - explicit `tools` list → only MCP tools named in the list, and only
663
+ * through the shared live connection — forwarding configs without one
664
+ * would re-bootstrap every server and reopen the bypass this exists
665
+ * to close. Instructions are trimmed to servers that still contribute
666
+ * a tool.
667
+ *
668
+ * CONTRACT CAVEAT — configless parents: the child only invokes its
669
+ * connector when its own `mcpServers` list is non-empty (`agent.ts` gates
670
+ * every connect path on config count; pinned by `test/mcp.test.ts`
671
+ * "connector + zero configs → no connect"). So a parent with a live
672
+ * `ctx.mcpConnection` but an absent/empty `ctx.mcpServers` hands down a
673
+ * connector that never fires — the child gets NO MCP tools, allowlisted
674
+ * or not. Hosts sharing a connection must pass the matching transformed
675
+ * config list alongside it (`agent.mcpServers` — see the command-spawn
676
+ * seam in the TUI).
677
+ */
678
+ function inheritedMcpForSubagent(ctx, def) {
679
+ const explicit = def?.tools;
680
+ if (!(def !== void 0 && (def.readonly === true || explicit !== void 0 && explicit.length > 0))) return {
681
+ ...ctx.mcpServers !== void 0 ? { mcpServers: ctx.mcpServers } : {},
682
+ ...ctx.mcpConnection !== void 0 ? { mcpConnector: nonOwningMcpConnector(ctx.mcpConnection) } : {}
683
+ };
684
+ if (!explicit || explicit.length === 0) return {};
685
+ if (ctx.mcpConnection === void 0) return {};
686
+ const wanted = new Set(explicit);
687
+ const tools = {};
688
+ for (const [key, t] of Object.entries(ctx.mcpConnection.tools)) if (wanted.has(t.spec.name)) tools[key] = t;
689
+ const surviving = Object.keys(tools);
690
+ if (surviving.length === 0) return {};
691
+ const servers = ctx.mcpServers ?? [];
692
+ const keepServers = new Set(surviving.map((name) => deriveMcpToolMeta(name, servers).server));
693
+ const instructions = ctx.mcpConnection.instructions;
694
+ const filteredInstructions = instructions ? new Map([...instructions].filter(([name]) => keepServers.has(name))) : void 0;
695
+ return {
696
+ ...ctx.mcpServers !== void 0 ? { mcpServers: ctx.mcpServers } : {},
697
+ mcpConnector: nonOwningMcpConnector({
698
+ tools,
699
+ ...filteredInstructions !== void 0 && filteredInstructions.size > 0 ? { instructions: filteredInstructions } : {}
700
+ })
701
+ };
702
+ }
703
+ /**
704
+ * Render the per-type descriptions into a single schema-field
705
+ * description string the model reads when choosing a `subagent_type`.
706
+ * Falls back to a generic line when the host didn't supply any per-type
707
+ * descriptions.
708
+ */
709
+ function buildSubagentTypeDescription(registry) {
710
+ const lines = [];
711
+ let hasAny = false;
712
+ for (const [key, def] of Object.entries(registry)) if (def.description) {
713
+ lines.push(`- "${key}": ${def.description}`);
714
+ hasAny = true;
715
+ } else lines.push(`- "${key}"`);
716
+ lines.push("- \"general-purpose\": no specialization; uses the spawn tool's default config.");
717
+ if (!hasAny) return `Optional subagent preset. One of: ${lines.map((l) => l.replace(/^- /, "").replace(/:.*$/, "")).join(", ")}.`;
718
+ return `Optional subagent preset that overlays the spawn tool's defaults.\n${lines.join("\n")}`;
719
+ }
720
+ /**
721
+ * Build the `model` field's description: delegation doctrine plus either
722
+ * the embedded catalog (small) or a pointer at `model_search` (large).
723
+ */
724
+ function buildModelFieldDescription(catalog) {
725
+ const doctrine = "Optional model id to run the child on. Cost-tier your delegation: mechanical, parallelizable, or high-volume search work suits cheaper/faster models; keep synthesis and final judgment on your own model. Omit to inherit your model.";
726
+ if (catalog.length <= 8) return `${doctrine}\nAvailable:\n${catalog.map((e) => `- ${formatModelLine(e)}`).join("\n")}`;
727
+ return `${doctrine}\n${catalog.length} models are available: call \`model_search\` to browse ids, pricing, and context windows.`;
728
+ }
729
+ /**
730
+ * Resolve a catalog entry's `Provider.name` against the run's provider
731
+ * list: the active provider first, then the fallback-chain providers
732
+ * (`ToolContext.providers`, populated by the loop for multi-provider
733
+ * runs). `undefined` when no instance with that name serves this run.
734
+ */
735
+ function resolveProviderByName(name, ctx) {
736
+ if (ctx.provider.name === name) return ctx.provider;
737
+ return ctx.providers?.find((p) => p.name === name);
738
+ }
739
+ /**
740
+ * Race `task` (an already-running child `agent.run()` promise) against a
741
+ * timer. Does NOT race against the parent abort signal — the child agent
742
+ * already observes the same signal internally and handles its own aborted
743
+ * bookkeeping, so racing here would detach the spawn from the child's
744
+ * session-persisting finally block.
745
+ *
746
+ * On timeout: rejects with `SpawnTimeoutError`; caller is expected to call
747
+ * `agent.abort()` and subsequently `await` the original `task` so the
748
+ * child's session state (runs, turns, status) gets flushed before the
749
+ * parent moves on.
750
+ */
751
+ async function raceWithTimeout(task, timeoutMs) {
752
+ if (!timeoutMs || timeoutMs <= 0) return task;
753
+ let timer;
754
+ try {
755
+ return await new Promise((resolve, reject) => {
756
+ timer = setTimeout(() => reject(new SpawnTimeoutError(timeoutMs)), timeoutMs);
757
+ task.then(resolve, reject);
758
+ });
759
+ } finally {
760
+ if (timer) clearTimeout(timer);
761
+ }
762
+ }
763
+ var SpawnTimeoutError = class extends Error {
764
+ timeoutMs;
765
+ constructor(timeoutMs) {
766
+ super(`Child agent timed out after ${timeoutMs}ms`);
767
+ this.name = "SpawnTimeoutError";
768
+ this.timeoutMs = timeoutMs;
769
+ }
770
+ };
771
+ //#endregion
772
+ //#region src/tool-state.ts
773
+ /**
774
+ * Durable key/value state for tools.
775
+ *
776
+ * A tool reaches this through {@link ToolContext.state} — a plain,
777
+ * SYNCHRONOUS map view. Synchronous is not a convenience choice: under a
778
+ * durable-execution runtime the tool body runs inside a journaled action
779
+ * (Restate's `ctx.run`), and a durable read (`ctx.get`) is illegal in
780
+ * there. So the flow is split into three phases the runtime can journal
781
+ * independently:
782
+ *
783
+ * 1. **hydrate** — load the snapshot ONCE per agent, outside any
784
+ * journaled action, before the first tool dispatch.
785
+ * 2. **stage** — the tool mutates its per-call view. Mutations are
786
+ * recorded as an ordered {@link ToolStateOp} list, NOT written
787
+ * through: they're plain data, so a durable adapter can journal them
788
+ * alongside the tool result.
789
+ * 3. **commit** — the loop applies the staged ops through
790
+ * {@link ToolStateStore.commit} after the call settles, outside the
791
+ * journaled action.
792
+ *
793
+ * The invariant that makes this replay-safe:
794
+ *
795
+ * > A staged mutation is committed only if it came back OUT of a journal
796
+ * > entry.
797
+ *
798
+ * A durable adapter (see `restateTool`) reads {@link StagedToolState.pending}
799
+ * from inside its journaled closure, ships the ops out as part of the
800
+ * journaled value, and calls {@link StagedToolState.restore} outside it. On
801
+ * replay the tool body never runs, so nothing is staged live — `restore`
802
+ * re-seeds the exact same ops from the journal and the commit re-issues an
803
+ * identical write. Paths that produced no journal entry (a fatal error, a
804
+ * control abort, a dead attempt) call {@link StagedToolState.clear} so live
805
+ * mutations from an attempt nobody recorded can never reach the store.
806
+ *
807
+ * The store seam is deliberately runtime-agnostic: `zidane/restate` ships
808
+ * `restateToolStateStore`, but a Redis / Postgres / file-backed
809
+ * implementation is the same two methods. With no store configured the
810
+ * controller is in-memory only — `ctx.state` still works everywhere
811
+ * (local CLI, tests, subagents), it just doesn't outlive the process.
812
+ */
813
+ /**
814
+ * Default per-value size budget: 64 KiB of JSON.
815
+ *
816
+ * Deliberately far below any backend's hard ceiling (Restate's journal-entry
817
+ * limit is 32 MiB) because this is a design guard, not a protocol limit.
818
+ * Durable tool state is for flags, ids, counters, and cursors; a value that
819
+ * doesn't fit in 64 KiB is a payload, and payloads belong in the tool result
820
+ * or in storage the tool owns. Raise it on the store if you disagree — but
821
+ * know that everything here is rewritten on every commit.
822
+ */
823
+ const DEFAULT_MAX_VALUE_BYTES = 65536;
824
+ /** Brand so {@link stagedToolState} can recognise views this module made. */
825
+ const STAGED = Symbol("zidane.toolState.staged");
826
+ /**
827
+ * Resolve the staging handle behind a view. Returns `undefined` for a
828
+ * missing view or a foreign implementation (a host that supplied its own
829
+ * `ToolStateView`), which lets adapters degrade to "no durable staging"
830
+ * instead of throwing.
831
+ */
832
+ function stagedToolState(view) {
833
+ if (!view) return void 0;
834
+ return view[STAGED] ?? void 0;
835
+ }
836
+ function createToolStateController(store) {
837
+ const snapshot = /* @__PURE__ */ new Map();
838
+ const views = /* @__PURE__ */ new Map();
839
+ const maxValueBytes = store?.maxValueBytes ?? 65536;
840
+ let hydrated;
841
+ const hydrate = () => {
842
+ if (hydrated) return hydrated;
843
+ hydrated = (async () => {
844
+ if (!store) return;
845
+ const loaded = await store.load();
846
+ for (const [key, value] of Object.entries(loaded ?? {})) if (!snapshot.has(key)) snapshot.set(key, value);
847
+ })().catch((err) => {
848
+ hydrated = void 0;
849
+ throw err;
850
+ });
851
+ return hydrated;
852
+ };
853
+ const begin = (callId) => {
854
+ const existing = views.get(callId);
855
+ if (existing) return existing;
856
+ const view = createStagingView(snapshot, maxValueBytes);
857
+ views.set(callId, view);
858
+ return view;
859
+ };
860
+ const commit = async (callId) => {
861
+ const view = views.get(callId);
862
+ if (!view) return;
863
+ views.delete(callId);
864
+ const ops = view[STAGED].pending();
865
+ if (ops.length === 0) return;
866
+ await store?.commit(ops);
867
+ applyOps(snapshot, ops);
868
+ };
869
+ return {
870
+ hydrate,
871
+ begin,
872
+ commit,
873
+ discard: (callId) => {
874
+ views.delete(callId);
875
+ },
876
+ pending: (callId) => views.get(callId)?.[STAGED].pending() ?? [],
877
+ snapshot: () => Object.fromEntries(snapshot),
878
+ committed: {
879
+ get: (key) => snapshot.get(key),
880
+ has: (key) => snapshot.has(key),
881
+ keys: () => [...snapshot.keys()].sort()
882
+ }
883
+ };
884
+ }
885
+ /**
886
+ * Build a view over `snapshot` that records writes instead of applying
887
+ * them. Reads layer staged ops on top of the snapshot so a tool sees its
888
+ * own writes back — including deletions, which read as absent.
889
+ */
890
+ function createStagingView(snapshot, maxValueBytes) {
891
+ let ops = [];
892
+ const latest = /* @__PURE__ */ new Map();
893
+ const stage = (op) => {
894
+ ops.push(op);
895
+ latest.set(op.key, op);
896
+ };
897
+ const resolve = (key) => {
898
+ const staged = latest.get(key);
899
+ if (staged) return staged.delete === true ? { present: false } : {
900
+ present: true,
901
+ value: staged.value
902
+ };
903
+ return snapshot.has(key) ? {
904
+ present: true,
905
+ value: snapshot.get(key)
906
+ } : { present: false };
907
+ };
908
+ const view = {
909
+ get: (key) => {
910
+ const resolved = resolve(key);
911
+ return resolved.present ? resolved.value : void 0;
912
+ },
913
+ set: (key, value) => {
914
+ assertStorable(key, value, maxValueBytes);
915
+ if (value === void 0) stage({
916
+ key,
917
+ delete: true
918
+ });
919
+ else stage({
920
+ key,
921
+ value
922
+ });
923
+ },
924
+ delete: (key) => {
925
+ stage({
926
+ key,
927
+ delete: true
928
+ });
929
+ },
930
+ has: (key) => resolve(key).present,
931
+ keys: () => {
932
+ const keys = new Set(snapshot.keys());
933
+ for (const [key, op] of latest) if (op.delete === true) keys.delete(key);
934
+ else keys.add(key);
935
+ return [...keys].sort();
936
+ },
937
+ [STAGED]: {
938
+ pending: () => [...ops],
939
+ restore: (restored) => {
940
+ ops = [...restored];
941
+ latest.clear();
942
+ for (const op of ops) latest.set(op.key, op);
943
+ },
944
+ clear: () => {
945
+ ops = [];
946
+ latest.clear();
947
+ }
948
+ }
949
+ };
950
+ Object.defineProperty(view, STAGED, {
951
+ value: view[STAGED],
952
+ enumerable: false
953
+ });
954
+ return view;
955
+ }
956
+ /**
957
+ * Reject a value that can't survive the trip to the store, at the moment the
958
+ * tool stages it.
959
+ *
960
+ * Scalars are skipped: they're bounded, and paying a `JSON.stringify` per
961
+ * `set` on a hot tool would be a real cost for no signal. Strings and objects
962
+ * are measured in UTF-8 bytes, which is what both the journal and the store
963
+ * actually spend.
964
+ */
965
+ function assertStorable(key, value, maxValueBytes) {
966
+ if (value === void 0 || value === null || typeof value === "boolean" || typeof value === "number") return;
967
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") throw new TypeError(`tool state value for "${key}" is a ${typeof value}, which a durable store can't hold. Use a JSON-serializable value.`);
968
+ let json;
969
+ try {
970
+ json = typeof value === "string" ? value : JSON.stringify(value) ?? "";
971
+ } catch (err) {
972
+ throw new TypeError(`tool state value for "${key}" is not JSON-serializable (${err instanceof Error ? err.message : String(err)}). Durable tool state crosses a journal, so cycles and exotic values can't be stored.`);
973
+ }
974
+ const bytes = Buffer.byteLength(json, "utf8");
975
+ if (bytes > maxValueBytes) throw new RangeError(`tool state value for "${key}" is ${formatBytes(bytes)}, over the ${formatBytes(maxValueBytes)} limit. Durable tool state is for flags, ids, counters, and cursors. It is rewritten on every commit and crosses a journal entry. Keep the payload in the tool result or in storage the tool owns, and store a reference here.`);
976
+ }
977
+ /** Apply ops to a snapshot map in order — last write per key wins. */
978
+ function applyOps(snapshot, ops) {
979
+ for (const op of ops) if (op.delete === true) snapshot.delete(op.key);
980
+ else snapshot.set(op.key, op.value);
981
+ }
982
+ /** Runtime guard for a journaled op list — adapters validate before restoring. */
983
+ function isToolStateOps(value) {
984
+ return Array.isArray(value) && value.every((op) => typeof op === "object" && op !== null && typeof op.key === "string" && (op.delete === true || "value" in op));
985
+ }
986
+ //#endregion
987
+ export { hydrateReadStateFromSessionAsync as C, resolveReadStateMap as D, readStateKey as E, staleRefusalHint as O, hydrateReadStateFromSession as S, noteStaleRejection as T, formatModelLine as _, SpawnTimeoutError as a, getToolDedupState as b, childRunsOf as c, filterToolsForSubagent as d, inheritedMcpForSubagent as f, createModelSearchTool as g, resolveProviderByName as h, stagedToolState as i, describeChildRuns as l, reserveChildLabel as m, createToolStateController as n, buildModelFieldDescription as o, raceWithTimeout as p, isToolStateOps as r, buildSubagentTypeDescription as s, DEFAULT_MAX_VALUE_BYTES as t, extractText as u, matchModelEntries as v, markReadStateElided as w, hashContent as x, getReadState as y };
988
+
989
+ //# sourceMappingURL=tool-state-Dku6YqAB.js.map