zidane 9.1.1 → 9.1.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 (279) hide show
  1. package/dist/{acp-Di9WvMDF.js → acp-Cl4gCZN6.js} +7 -7
  2. package/dist/{acp-Di9WvMDF.js.map → acp-Cl4gCZN6.js.map} +1 -1
  3. package/dist/acp-cli.js +5 -5
  4. package/dist/acp.d.ts +2 -2
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-DJhpTS-B.js → agent-Dh_XZ7fj.js} +74 -19
  7. package/dist/agent-Dh_XZ7fj.js.map +1 -0
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/{auth-store-port-DFgf22oo.js → auth-store-port-DBl2JUC6.js} +2 -2
  11. package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-DBl2JUC6.js.map} +1 -1
  12. package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CF_kjcJd.js} +277 -41
  13. package/dist/auto-update-restart-CF_kjcJd.js.map +1 -0
  14. package/dist/{browser-BcoCCB_n.js → browser-BkdeKnxO.js} +56 -2
  15. package/dist/browser-BkdeKnxO.js.map +1 -0
  16. package/dist/{browser-entry-ypi8CyE-.d.ts → browser-entry-BCwruqNa.d.ts} +10 -10
  17. package/dist/{browser-entry-ypi8CyE-.d.ts.map → browser-entry-BCwruqNa.d.ts.map} +1 -1
  18. package/dist/channels.d.ts +5 -5
  19. package/dist/chat/browser.d.ts +4 -4
  20. package/dist/chat/browser.js +6 -6
  21. package/dist/chat/pure.d.ts +5 -5
  22. package/dist/chat/pure.js +8 -8
  23. package/dist/chat.d.ts +5 -5
  24. package/dist/chat.js +55 -55
  25. package/dist/chat.js.map +1 -1
  26. package/dist/{cli-shared-CabruH8Z.js → cli-shared-DIV9c5Nr.js} +4 -4
  27. package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DIV9c5Nr.js.map} +1 -1
  28. package/dist/cli-style-DBEm6CyT.js +105 -0
  29. package/dist/cli-style-DBEm6CyT.js.map +1 -0
  30. package/dist/{client-core-CIixwznM.d.ts → client-core-C_4m_oL6.d.ts} +4 -4
  31. package/dist/{client-core-CIixwznM.d.ts.map → client-core-C_4m_oL6.d.ts.map} +1 -1
  32. package/dist/{client-CCaIXWue.d.ts → client-ygTASGis.d.ts} +2 -2
  33. package/dist/{client-CCaIXWue.d.ts.map → client-ygTASGis.d.ts.map} +1 -1
  34. package/dist/codemode-worker.js +8 -5
  35. package/dist/codemode-worker.js.map +1 -1
  36. package/dist/codemode.d.ts +16 -0
  37. package/dist/codemode.d.ts.map +1 -1
  38. package/dist/codemode.js +2 -2
  39. package/dist/{connection-loop-QmWL-fJf.d.ts → connection-loop-D_pRONCr.d.ts} +4 -4
  40. package/dist/{connection-loop-QmWL-fJf.d.ts.map → connection-loop-D_pRONCr.d.ts.map} +1 -1
  41. package/dist/contexts/daytona.d.ts +3 -3
  42. package/dist/contexts/docker.d.ts +1 -1
  43. package/dist/contexts/e2b.d.ts +2 -2
  44. package/dist/contexts/sandbox.d.ts +1 -1
  45. package/dist/{contexts-C72b0mMa.js → contexts-DLZTSRHU.js} +17 -106
  46. package/dist/contexts-DLZTSRHU.js.map +1 -0
  47. package/dist/contexts.d.ts +4 -4
  48. package/dist/contexts.js +2 -2
  49. package/dist/{credentials-wwETW8rI.js → credentials-D71duF64.js} +2 -2
  50. package/dist/{credentials-wwETW8rI.js.map → credentials-D71duF64.js.map} +1 -1
  51. package/dist/{cwd-picker-CcekODCt.js → cwd-picker-BsHA6HKv.js} +4 -4
  52. package/dist/{cwd-picker-CcekODCt.js.map → cwd-picker-BsHA6HKv.js.map} +1 -1
  53. package/dist/daemon-cli.js +4 -3
  54. package/dist/daemon-cli.js.map +1 -1
  55. package/dist/{decisions-CXmK0nz9.js → decisions-hsw5XS2g.js} +3 -1
  56. package/dist/decisions-hsw5XS2g.js.map +1 -0
  57. package/dist/{discovery-DycXFxdA.js → discovery-DD4wPWKS.js} +4 -4
  58. package/dist/{discovery-DycXFxdA.js.map → discovery-DD4wPWKS.js.map} +1 -1
  59. package/dist/durable/sqlite.d.ts +2 -2
  60. package/dist/durable.d.ts +1 -1
  61. package/dist/{engine-VQ86XGdG.js → engine-BDmtgr2O.js} +6 -6
  62. package/dist/{engine-VQ86XGdG.js.map → engine-BDmtgr2O.js.map} +1 -1
  63. package/dist/{eval-Bod0I1W_.js → eval-CfGUDAkN.js} +3 -3
  64. package/dist/{eval-Bod0I1W_.js.map → eval-CfGUDAkN.js.map} +1 -1
  65. package/dist/eval.d.ts +1 -1
  66. package/dist/eval.js +1 -1
  67. package/dist/{executor-C7RQrkEq.js → executor-EWOhLyd9.js} +4 -4
  68. package/dist/{executor-C7RQrkEq.js.map → executor-EWOhLyd9.js.map} +1 -1
  69. package/dist/{extension-mark-BqKdEZwF.js → extension-mark-_rhkDWL5.js} +9 -6
  70. package/dist/extension-mark-_rhkDWL5.js.map +1 -0
  71. package/dist/extensions/testing.d.ts +1 -1
  72. package/dist/extensions/testing.js +2 -2
  73. package/dist/{extensions-BCx4QuGB.js → extensions-DklXPjiq.js} +8 -8
  74. package/dist/{extensions-BCx4QuGB.js.map → extensions-DklXPjiq.js.map} +1 -1
  75. package/dist/{extensions-client-D8tEAcMw.d.ts → extensions-client-D4Q2XRKV.d.ts} +31 -5
  76. package/dist/extensions-client-D4Q2XRKV.d.ts.map +1 -0
  77. package/dist/extensions.d.ts +1 -1
  78. package/dist/extensions.js +6 -6
  79. package/dist/{fold-rules-DvLK8pbf.d.ts → fold-rules-1DpDwG9h.d.ts} +2 -2
  80. package/dist/{fold-rules-DvLK8pbf.d.ts.map → fold-rules-1DpDwG9h.d.ts.map} +1 -1
  81. package/dist/{google-Crva32sk.js → google-BtMW9KzL.js} +2 -2
  82. package/dist/{google-Crva32sk.js.map → google-BtMW9KzL.js.map} +1 -1
  83. package/dist/{headless-CCm-jLLT.js → headless-CQm19BL0.js} +4 -4
  84. package/dist/{headless-CCm-jLLT.js.map → headless-CQm19BL0.js.map} +1 -1
  85. package/dist/headless.d.ts +1 -1
  86. package/dist/headless.js +1 -1
  87. package/dist/history-worker.js +1 -1
  88. package/dist/{host-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
  89. package/dist/host-DEoEzQal.js.map +1 -0
  90. package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
  91. package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
  92. package/dist/{host-signals-Jsjd_-4g.js → host-signals-91zyko_i.js} +5 -5
  93. package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-91zyko_i.js.map} +1 -1
  94. package/dist/{host-wO_6GW0y.js → host-uP3t08w8.js} +276 -103
  95. package/dist/host-uP3t08w8.js.map +1 -0
  96. package/dist/{host-version-CNAr9pov.js → host-version-_RHlAB29.js} +2 -2
  97. package/dist/{host-version-CNAr9pov.js.map → host-version-_RHlAB29.js.map} +1 -1
  98. package/dist/{index-C6nnKu32.d.ts → index-B0PLo9jn.d.ts} +4 -4
  99. package/dist/{index-C6nnKu32.d.ts.map → index-B0PLo9jn.d.ts.map} +1 -1
  100. package/dist/{index-Djnc8Peh.d.ts → index-De4x-s76.d.ts} +14 -14
  101. package/dist/{index-Djnc8Peh.d.ts.map → index-De4x-s76.d.ts.map} +1 -1
  102. package/dist/{index-CGbOWa7y.d.ts → index-WlE93Q6d.d.ts} +411 -3
  103. package/dist/index-WlE93Q6d.d.ts.map +1 -0
  104. package/dist/{index-CCf_WeTQ.d.ts → index-f-XWIoYo.d.ts} +2 -2
  105. package/dist/{index-CCf_WeTQ.d.ts.map → index-f-XWIoYo.d.ts.map} +1 -1
  106. package/dist/index.d.ts +5 -5
  107. package/dist/index.js +17 -17
  108. package/dist/ipc/browser-types.d.ts +304 -7
  109. package/dist/ipc/browser-types.d.ts.map +1 -1
  110. package/dist/ipc/browser.d.ts +4 -4
  111. package/dist/ipc/browser.js +2 -2
  112. package/dist/ipc/remote.d.ts +6 -6
  113. package/dist/ipc/remote.js +3 -3
  114. package/dist/{ipc-BzWhIybr.js → ipc-CatnsVEd.js} +4 -4
  115. package/dist/{ipc-BzWhIybr.js.map → ipc-CatnsVEd.js.map} +1 -1
  116. package/dist/ipc.d.ts +10 -10
  117. package/dist/ipc.js +8 -8
  118. package/dist/{json-Dj-YATkZ.js → json-BjClr43H.js} +2 -20
  119. package/dist/json-BjClr43H.js.map +1 -0
  120. package/dist/{links-CJG_rFvf.js → links-a8C9eby4.js} +9 -9
  121. package/dist/{links-CJG_rFvf.js.map → links-a8C9eby4.js.map} +1 -1
  122. package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-D6jzt5HQ.js} +2 -2
  123. package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-D6jzt5HQ.js.map} +1 -1
  124. package/dist/mcp.d.ts +1 -1
  125. package/dist/{media-type-BtA0cbfI.d.ts → media-type-ZSmAGHvg.d.ts} +188 -7
  126. package/dist/media-type-ZSmAGHvg.d.ts.map +1 -0
  127. package/dist/{memory-DuVGrzbl.js → memory-CJy52DNi.js} +132 -31
  128. package/dist/memory-CJy52DNi.js.map +1 -0
  129. package/dist/model-test-CAtJ76kM.js.map +1 -1
  130. package/dist/{move-session-kylExJ5H.js → move-session-D7ILECs-.js} +4 -4
  131. package/dist/{move-session-kylExJ5H.js.map → move-session-D7ILECs-.js.map} +1 -1
  132. package/dist/{nested-call-record-DlzPeTB7.js → nested-call-record-OayszZBQ.js} +4 -3
  133. package/dist/nested-call-record-OayszZBQ.js.map +1 -0
  134. package/dist/output/stream-json.d.ts +1 -1
  135. package/dist/output/terminal.d.ts +1 -1
  136. package/dist/{path-display-COVV71Yu.js → path-display-CAWz-sMq.js} +3 -3
  137. package/dist/{path-display-COVV71Yu.js.map → path-display-CAWz-sMq.js.map} +1 -1
  138. package/dist/plugins.d.ts +1 -1
  139. package/dist/{prelude-CVKoUzV8.js → prelude-BwiSR1uA.js} +16 -5
  140. package/dist/prelude-BwiSR1uA.js.map +1 -0
  141. package/dist/{presets-CBt6rFfS.js → presets-CMY43nUP.js} +3 -3
  142. package/dist/{presets-CBt6rFfS.js.map → presets-CMY43nUP.js.map} +1 -1
  143. package/dist/presets.d.ts +1 -1
  144. package/dist/presets.js +1 -1
  145. package/dist/{protocol-CEVqBO-q.d.ts → protocol-C2lqKuMd.d.ts} +50 -7
  146. package/dist/protocol-C2lqKuMd.d.ts.map +1 -0
  147. package/dist/protocol-DOGyHgLQ.js.map +1 -1
  148. package/dist/protocol-NSllElLw.js.map +1 -1
  149. package/dist/providers/anthropic.d.ts +1 -1
  150. package/dist/providers/arcee.d.ts +1 -1
  151. package/dist/providers/baseten.d.ts +1 -1
  152. package/dist/providers/cerebras.d.ts +1 -1
  153. package/dist/providers/google.d.ts +1 -1
  154. package/dist/providers/google.js +1 -1
  155. package/dist/providers/local.d.ts +1 -1
  156. package/dist/providers/neuralwatt.d.ts +1 -1
  157. package/dist/providers/openai-compat.d.ts +1 -1
  158. package/dist/providers/openai.d.ts +1 -1
  159. package/dist/providers/openrouter.d.ts +1 -1
  160. package/dist/providers/xai.d.ts +1 -1
  161. package/dist/{providers-Z0TaBp1O.js → providers-zVRxiJDv.js} +5 -5
  162. package/dist/providers-zVRxiJDv.js.map +1 -0
  163. package/dist/providers.d.ts +1 -1
  164. package/dist/providers.js +1 -1
  165. package/dist/{readonly-db-D7Z-k0pQ.js → readonly-db-DrbT8tX6.js} +2 -2
  166. package/dist/{readonly-db-D7Z-k0pQ.js.map → readonly-db-DrbT8tX6.js.map} +1 -1
  167. package/dist/{registry-BKjeBnoy.js → registry-CBoYDIND.js} +2 -2
  168. package/dist/{registry-BKjeBnoy.js.map → registry-CBoYDIND.js.map} +1 -1
  169. package/dist/{registry-B6Ww76iW.js → registry-CQOU5jvF.js} +2 -2
  170. package/dist/{registry-B6Ww76iW.js.map → registry-CQOU5jvF.js.map} +1 -1
  171. package/dist/{registry-B9INJwJR.js → registry-YUUqbYGr.js} +324 -39
  172. package/dist/registry-YUUqbYGr.js.map +1 -0
  173. package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-CT8Q95dR.js} +4 -4
  174. package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-CT8Q95dR.js.map} +1 -1
  175. package/dist/{repo-url-D4Dr8NfZ.js → repo-url-DLjjuVk_.js} +169 -2
  176. package/dist/repo-url-DLjjuVk_.js.map +1 -0
  177. package/dist/restate.d.ts +2 -2
  178. package/dist/{sandbox-BwiPGKF7.d.ts → sandbox-B4OW6oNx.d.ts} +2 -2
  179. package/dist/{sandbox-BwiPGKF7.d.ts.map → sandbox-B4OW6oNx.d.ts.map} +1 -1
  180. package/dist/script-progress-CrZ507Qq.js +900 -0
  181. package/dist/script-progress-CrZ507Qq.js.map +1 -0
  182. package/dist/session/sqlite.d.ts +1 -1
  183. package/dist/session.d.ts +1 -1
  184. package/dist/{setting-BQBSyUq0.js → setting-_jh2OtiL.js} +6 -6
  185. package/dist/{setting-BQBSyUq0.js.map → setting-_jh2OtiL.js.map} +1 -1
  186. package/dist/{settings-catalog-4IU2i_jG.js → settings-catalog-DEZlXP51.js} +14 -2
  187. package/dist/settings-catalog-DEZlXP51.js.map +1 -0
  188. package/dist/{settings-keys-iI_Y-7MC.js → settings-keys-BT0_oKjO.js} +3 -3
  189. package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-BT0_oKjO.js.map} +1 -1
  190. package/dist/{skills-CFXRItJ6.js → skills-CEbosUlM.js} +2 -2
  191. package/dist/{skills-CFXRItJ6.js.map → skills-CEbosUlM.js.map} +1 -1
  192. package/dist/skills.d.ts +1 -1
  193. package/dist/skills.js +1 -1
  194. package/dist/{source-Bl1Z501r.js → source-3ZnEPOSa.js} +3 -2
  195. package/dist/source-3ZnEPOSa.js.map +1 -0
  196. package/dist/{sqlite-runtime-BZ2L4RaG.d.ts → sqlite-runtime-CS_LBaAN.d.ts} +2 -2
  197. package/dist/sqlite-runtime-CS_LBaAN.d.ts.map +1 -0
  198. package/dist/{src-BY_ND2xn.js → src-BmTXDta8.js} +2 -2
  199. package/dist/{src-BY_ND2xn.js.map → src-BmTXDta8.js.map} +1 -1
  200. package/dist/{store-C6gI7FfZ.js → store-ByCDaKgJ.js} +14 -3
  201. package/dist/store-ByCDaKgJ.js.map +1 -0
  202. package/dist/{system-freeze-m5o1sGIM.js → system-freeze-DxJ-lRhu.js} +3 -3
  203. package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-DxJ-lRhu.js.map} +1 -1
  204. package/dist/{todo-edits-CbukbjyV.js → todo-edits-Dyj32ds6.js} +4 -3
  205. package/dist/todo-edits-Dyj32ds6.js.map +1 -0
  206. package/dist/tools/fetch-url.d.ts +1 -1
  207. package/dist/tools/web-search.d.ts +1 -1
  208. package/dist/{tools-CVTGhggj.js → tools-BsrGQ8K4.js} +2 -2
  209. package/dist/{tools-CVTGhggj.js.map → tools-BsrGQ8K4.js.map} +1 -1
  210. package/dist/tools.d.ts +1 -1
  211. package/dist/tools.js +3 -3
  212. package/dist/{transcript-anchors-CiSi_UBn.js → transcript-anchors-DMjvyUjk.js} +3 -3
  213. package/dist/{transcript-anchors-CiSi_UBn.js.map → transcript-anchors-DMjvyUjk.js.map} +1 -1
  214. package/dist/{transcript-reconcile-jbSBjLq2.js → transcript-reconcile-DpQO85wl.js} +3 -3
  215. package/dist/{transcript-reconcile-jbSBjLq2.js.map → transcript-reconcile-DpQO85wl.js.map} +1 -1
  216. package/dist/tui.d.ts +9 -9
  217. package/dist/tui.d.ts.map +1 -1
  218. package/dist/tui.js +289 -38
  219. package/dist/tui.js.map +1 -1
  220. package/dist/{types-bDQagoiL.d.ts → types-2HrgolQz.d.ts} +20 -8
  221. package/dist/types-2HrgolQz.d.ts.map +1 -0
  222. package/dist/types-4q1bFG53.js +122 -0
  223. package/dist/types-4q1bFG53.js.map +1 -0
  224. package/dist/{types-DnRd9_cA.d.ts → types-SXqk6hLD.d.ts} +3 -3
  225. package/dist/{types-DnRd9_cA.d.ts.map → types-SXqk6hLD.d.ts.map} +1 -1
  226. package/dist/types-myxheQkw.js.map +1 -1
  227. package/dist/types.d.ts +3 -3
  228. package/dist/{usage-summary-BfcXjiSM.js → usage-summary-BM7B3JdI.js} +2 -2
  229. package/dist/{usage-summary-BfcXjiSM.js.map → usage-summary-BM7B3JdI.js.map} +1 -1
  230. package/dist/{version-DqqqvHDP.js → version-DwQI12WA.js} +2 -2
  231. package/dist/{version-DqqqvHDP.js.map → version-DwQI12WA.js.map} +1 -1
  232. package/dist/{wait-task-BX4NcOOm.js → wait-task-BiI5UaZQ.js} +13 -3
  233. package/dist/wait-task-BiI5UaZQ.js.map +1 -0
  234. package/dist/{wire-CLm2rMK0.js → wire-Dxwxb7QQ.js} +2 -2
  235. package/dist/{wire-CLm2rMK0.js.map → wire-Dxwxb7QQ.js.map} +1 -1
  236. package/dist/{write-file-0E6TUJ9A.js → write-file-Dquu7MzB.js} +5 -3
  237. package/dist/write-file-Dquu7MzB.js.map +1 -0
  238. package/dist/{ws-DfGGYQ4W.js → ws-CA3o2nie.js} +4 -4
  239. package/dist/{ws-DfGGYQ4W.js.map → ws-CA3o2nie.js.map} +1 -1
  240. package/dist/{ws-client-CFMbhsNq.js → ws-client-C0iPAAzc.js} +2 -2
  241. package/dist/{ws-client-CFMbhsNq.js.map → ws-client-C0iPAAzc.js.map} +1 -1
  242. package/docs/CHAT.md +55 -0
  243. package/docs/CODEMODE.md +37 -0
  244. package/docs/EXTENSIONS.md +8 -6
  245. package/docs/RELEASE-NOTES-NEXT.md +48 -1
  246. package/docs/RELEASE.md +9 -1
  247. package/package.json +2 -3
  248. package/dist/agent-DJhpTS-B.js.map +0 -1
  249. package/dist/auto-update-restart-BFB7Ek87.js.map +0 -1
  250. package/dist/browser-BcoCCB_n.js.map +0 -1
  251. package/dist/contexts-C72b0mMa.js.map +0 -1
  252. package/dist/decisions-CXmK0nz9.js.map +0 -1
  253. package/dist/extension-mark-BqKdEZwF.js.map +0 -1
  254. package/dist/extensions-client-D8tEAcMw.d.ts.map +0 -1
  255. package/dist/host-BHMs9jsN.js.map +0 -1
  256. package/dist/host-wO_6GW0y.js.map +0 -1
  257. package/dist/index-CGbOWa7y.d.ts.map +0 -1
  258. package/dist/json-Dj-YATkZ.js.map +0 -1
  259. package/dist/media-type-BtA0cbfI.d.ts.map +0 -1
  260. package/dist/memory-DuVGrzbl.js.map +0 -1
  261. package/dist/nested-call-events-BYk8XvGX.js +0 -182
  262. package/dist/nested-call-events-BYk8XvGX.js.map +0 -1
  263. package/dist/nested-call-record-DlzPeTB7.js.map +0 -1
  264. package/dist/prelude-CVKoUzV8.js.map +0 -1
  265. package/dist/protocol-CEVqBO-q.d.ts.map +0 -1
  266. package/dist/providers-Z0TaBp1O.js.map +0 -1
  267. package/dist/registry-B9INJwJR.js.map +0 -1
  268. package/dist/repo-url-D4Dr8NfZ.js.map +0 -1
  269. package/dist/settings-catalog-4IU2i_jG.js.map +0 -1
  270. package/dist/source-Bl1Z501r.js.map +0 -1
  271. package/dist/sqlite-runtime-BZ2L4RaG.d.ts.map +0 -1
  272. package/dist/store-C6gI7FfZ.js.map +0 -1
  273. package/dist/todo-edits-CbukbjyV.js.map +0 -1
  274. package/dist/types-DTMEhKJO.js +0 -14
  275. package/dist/types-DTMEhKJO.js.map +0 -1
  276. package/dist/types-bDQagoiL.d.ts.map +0 -1
  277. package/dist/wait-task-BX4NcOOm.js.map +0 -1
  278. package/dist/write-file-0E6TUJ9A.js.map +0 -1
  279. package/scripts/eval.ts +0 -179
@@ -1 +0,0 @@
1
- {"version":3,"file":"decisions-CXmK0nz9.js","names":[],"sources":["../src/extensions/hooks/readonly.ts","../src/agent-hooks.ts","../src/decisions/index.ts"],"sourcesContent":["/**\n * Shallow read-only views over hook payloads. Observers and interceptors\n * get a view whose own properties cannot be set or deleted; nested values\n * are returned as they are, so class instances (sessions, providers) keep\n * working. Only plain objects and arrays are wrapped.\n */\n\nconst viewOf = new WeakMap<object, object>()\nconst targetOf = new WeakMap<object, object>()\n\nfunction refuse(prop: string | symbol): never {\n throw new TypeError(`Hook payloads are read-only: cannot change \"${String(prop)}\". Return a new value from an interceptor instead.`)\n}\n\nconst HANDLER: ProxyHandler<object> = {\n set: (_target, prop) => refuse(prop),\n deleteProperty: (_target, prop) => refuse(prop),\n defineProperty: (_target, prop) => refuse(prop),\n setPrototypeOf: () => refuse('__proto__'),\n}\n\nfunction isPlain(value: object): boolean {\n if (Array.isArray(value))\n return true\n const proto = Object.getPrototypeOf(value) as unknown\n return proto === Object.prototype || proto === null\n}\n\n/**\n * Returns a shallow read-only view of `value`. Primitives, class instances\n * and existing views come back unchanged. The same target always yields the\n * same view.\n *\n * @param value - The payload to protect.\n * @returns A proxy that throws on writes to its own properties, or `value`.\n */\nexport function readonlyView<T>(value: T): T {\n if (value === null || typeof value !== 'object' || targetOf.has(value) || !isPlain(value))\n return value\n let view = viewOf.get(value)\n if (!view) {\n view = new Proxy(value, HANDLER)\n viewOf.set(value, view)\n targetOf.set(view, value)\n }\n return view as T\n}\n\n/**\n * Returns the object behind a view made by {@link readonlyView}, or `value`\n * when it is not a view. Interceptors may return the `current` view they\n * were given; the chain unwraps it before handing it back to the caller.\n *\n * @param value - A view or any value.\n * @returns The writable target.\n */\nexport function unwrapReadonly<T>(value: T): T {\n if (value === null || typeof value !== 'object')\n return value\n return (targetOf.get(value) as T | undefined) ?? value\n}\n","/**\n * The agent hook surface: the `AgentHooks` event map, its runtime name\n * registry (kept exhaustive at compile time), and the `AgentHookMap`\n * registration shape.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { CacheBreakInfo, CacheDriftInfo } from './cache-telemetry'\nimport type { ExecutionHandle, TaskExitInfo } from './contexts'\nimport type { AgentDecide, DecisionEndHookContext, DecisionStartHookContext } from './decisions/types'\nimport type { Preset } from './presets'\nimport type { StreamOptions, ToolResult } from './providers'\nimport type { Session, SessionArtifact } from './session'\nimport type { PairingRepair } from './session/messages'\nimport type { ActivationVia, DeactivationReason } from './skills/activation'\nimport type { SkillConfig } from './skills/types'\nimport type { ToolStateOp } from './tool-state'\nimport type { AgentBehavior, AgentRunOptions, AgentStats, ChildRunStats, ChildSpawnHookContext, ChildSpawnIdentity, CompactEndHookContext, CompactProgressHookContext, CompactStartHookContext, HistoryRepairHookContext, InputTransformationsHookContext, JsonValue, McpToolHookContext, McpToolSchema, OAuthRefreshHookContext, ResolveContentRefBlock, SessionEndStatus, SessionHookContext, SessionMessage, SessionTurn, SpawnHookContext, SpawnQueuedContext, StreamHookContext, StreamProgressHookContext, ToolHookContext, ToolOutcome, ToolResultContent, ToolResultMetadata, TurnUsage } from './types'\n\n// ---------------------------------------------------------------------------\n// Hook definitions\n// ---------------------------------------------------------------------------\n\n/** What `tool:gate` carries for a call of a resumed checkpoint run. See `AgentHooks['tool:gate']`. */\nexport interface ToolGateResumeFields {\n /** The call passed the gate in a process that died: restore, don't ask. Its `result` is ignored, and its `block` too unless the call's body runs again (a safe call cut off, or a call with no step of its own). */\n resumed?: true\n /**\n * Per-call state the gate's handlers keep with the call's step record, by\n * handler key: write it on a live call, read it back on a `resumed` one.\n * Set by the loop on every call of a run that records steps, except the\n * calls a replay-mode batch joins. Only a resumed checkpoint run reads it back.\n */\n resumeState?: Record<string, JsonValue>\n}\n\n/** Event map for the agent hook bus. Each key is a hook name and each value is the handler signature. Register handlers with `agent.hooks.hook(name, fn)` or the `hooks` option of {@link createAgent}. */\nexport interface AgentHooks {\n // System\n /**\n * Fires once per run, before the first turn, only when `AgentRunOptions.system` is set. `ctx.system`\n * is that run-level string. Observational: the agent does not read `ctx.system` back, so use\n * `system:transform` to rewrite the system prompt.\n */\n 'system:before': (ctx: { system: string }) => void\n\n // Agent lifecycle (start)\n /**\n * Fires once per `agent.run()` invocation, right after `session:start`\n * (when a session is bound) and before the first `turn:before`. Symmetric\n * with {@link AgentHooks['agent:done']}.\n *\n * `tracingContext` carries opaque parent trace metadata propagated from\n * the spawning agent (typically a W3C `{ traceparent, tracestate }`\n * carrier injected by the parent's tracer on `spawn:before`). Tracers\n * read it on the child run to continue the parent trace; absent on\n * top-level runs.\n */\n 'agent:start': (ctx: {\n runId: string\n parentRunId?: string\n depth: number\n agentName?: string\n /**\n * Provider identity for this run, lower-cased canonical form\n * (`anthropic`, `openai`, `openrouter`, `cerebras`, …). Exposed so\n * observability adapters can stamp `gen_ai.system` (Sentry / OTel\n * Gen AI semantic-convention identifier) on every child span of\n * this run without needing a back-channel to the agent. Absent\n * when the provider declined to identify itself.\n */\n providerName?: string\n startedAt: number\n tracingContext?: Readonly<Record<string, string>>\n }) => void\n\n // Turn lifecycle\n /**\n * Fires immediately before each turn's `provider.stream()` call, after\n * `context:transform` + pairing repair + `system:transform`. The\n * `options` object IS mutable as a last-mile escape hatch (per-turn\n * reminders, dynamic tags, audit wrapping), but prefer\n * {@link AgentHooks['context:transform']} for any mutation that touches\n * `messages` — it runs upstream of the defensive pairing pass and stays\n * cheaper. Loop re-runs `ensureToolResultPairing` + `ensureEndsWithUserMessage`\n * after this hook so a `messages` mutation here can't leak a\n * `tool_result must be preceded by a tool_call` 400 to the wire, but you\n * pay one extra walk for the privilege.\n */\n 'turn:before': (ctx: { turn: number, turnId: string, options: StreamOptions }) => void\n /**\n * Fires when a turn read back materially less cached prefix than the\n * previous turn established — a prompt-cache break. Emitted by\n * `installCacheBreakLogger` (zidane's cache-telemetry module), so like\n * `compact:*` it only fires when that subsystem is installed on this\n * agent's hook bus; the loop itself never emits it.\n *\n * The payload names the request dimensions that changed (`changed`) with\n * human-readable diffs (`details`). An empty `changed` means the request\n * was byte-stable at this wire and the provider still dropped the prefix —\n * TTL expiry, provider eviction, or (behind a format-casting gateway)\n * churn introduced by the cast itself; see {@link CacheBreakInfo} for how\n * to tell them apart. Hosts surface this as UI (TUI footer chip), metrics,\n * or alerts; the text `log` line remains available for grep-based\n * workflows and, unlike this hook, stays silent on unattributable breaks.\n */\n 'cache:break': (info: CacheBreakInfo) => void | Promise<void>\n /**\n * Fires at `turn:before` when the outgoing request DIVERGES from the\n * previous completed turn's — the predictive counterpart of `'cache:break'`.\n * Emitted by `installCacheBreakLogger` from the request bytes alone, so it\n * works on providers that report no cache usage and on format-casting\n * gateways where this wire is the last observable point before the cast.\n *\n * Drift + healthy `cacheRead` afterwards = the provider absorbed the change;\n * drift + a `'cache:break'` on the same turn = the break's attribution.\n * Intentional rewrites (compaction cuts, stale-read stubs) drift by design —\n * `divergedAt` tells them apart; see `CacheDriftInfo`.\n *\n * Delivery is fire-and-forget: `turn:before` rides the loop's PROPAGATING\n * hook timeout, so the emitter does not await consumers. Synchronous\n * handlers complete before the request goes out; async handlers detach and\n * must not assume the turn is still in flight; errors route to the\n * installer's `onEmitError`, never into the run.\n */\n 'cache:drift': (info: CacheDriftInfo) => void | Promise<void>\n /**\n * Fires after each assistant turn (before its tool-result follow-up\n * dispatches; the loop iterates back to a fresh `turn:before` once the\n * tool results are produced).\n *\n * `toolCounts.turn` — calls **emitted** by the model in this assistant\n * turn, keyed by canonical tool name. Reflects what the model asked for,\n * regardless of downstream gate outcome. Most useful for spotting per-turn\n * spikes (\"the model called todowrite 4 times in one turn\").\n *\n * `toolCounts.run` — cumulative running counter of **dispatched** calls\n * scoped to this `runId`, captured at fire time. Excludes calls that were\n * `block`ed by `tool:gate` handlers. Includes calls short-circuited via\n * `tool:gate` `result` substitution (the model still asked, the framework\n * just answered without the tool running). Resumed sessions start a fresh\n * run with empty counts.\n *\n * Both fields are frozen snapshots; mutate-safe.\n *\n * `aborted` — runtime emissions always include this boolean; it is optional\n * on the type only so tests/adapters that manually synthesize `turn:after`\n * payloads do not break (treat absent as `false`). `true` when the run's\n * `AbortController` was already tripped at the moment this `turn:after`\n * fired. This is the case to branch on instead of `usage.finishReason` when\n * emulating Stop-hook semantics: an aborted turn can still carry\n * `finishReason: 'stop'` (e.g. a final text turn the user cancelled\n * mid-stream), so `finishReason` alone cannot distinguish \"model finished\"\n * from \"we killed it\".\n *\n * Covers the streaming-abort path (cancel landed while the turn was\n * streaming) and any abort that landed before this fired. NOTE: a\n * `tool:gate` / `repeat-guard` abort trips DURING the tool batch, which runs\n * after this `turn:after` — so the offending turn reports `aborted: false`\n * here (its `finishReason` is `'tool-calls'`, never `'stop'`, so a\n * `'stop'`-keyed consumer won't misfire). That abort surfaces on the\n * subsequent `agent:abort`. For the post-completion window (host queues a\n * follow-up after a clean `turn:after`, then the run is aborted), rely on\n * {@link Agent.steer}/{@link Agent.followUp} returning `false` once aborted.\n * `false` on every normal turn boundary.\n */\n 'turn:after': (ctx: {\n turn: number\n turnId: string\n usage: TurnUsage\n message: SessionTurn\n aborted?: boolean\n toolCounts: {\n turn: Readonly<Record<string, number>>\n run: Readonly<Record<string, number>>\n }\n /**\n * Run-cumulative token + cost rollup **including this turn**. Computed\n * locally in the loop from `priorUsage + usage`. Lets observability\n * consumers stamp running totals onto turn spans / metrics without\n * re-accumulating across handlers.\n *\n * `turns` is the number of completed parent-loop turns inclusive of this\n * one (1-indexed for the first turn). `cost` is summed from per-turn\n * `TurnUsage.cost` reports; absent when nothing reported a non-zero cost.\n *\n * Children's spend is NOT folded in here — `turn:after` fires on parent\n * turns; child rollup lands on `spawn:complete` / final `agent:done`.\n */\n cumulativeUsage: Readonly<{\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n cost?: number\n turns: number\n }>\n }) => void\n\n /**\n * Fires after a tool-results user turn is pushed onto the conversation,\n * before any byte-budget enforcement or follow-up steering. Symmetric\n * with `turn:after` but for the user-role tool_result turn that closes the\n * round-trip.\n *\n * Why it exists: persistence layers must write tool_use/tool_result turn\n * pairs together — if only the assistant turn (carrying tool_use blocks)\n * is durable, a process death between turns leaves the DB with an orphan\n * tool_use that Anthropic rejects on resume. Subscribe here to persist\n * the tool-results turn before the loop continues.\n */\n 'tool-results:after': (ctx: {\n turn: number\n turnId: string\n message: SessionTurn\n /** Frozen list of tool results that were packed into `message`. */\n results: readonly ToolResult[]\n }) => void\n /**\n * Fires when a durable run resumes a tool batch a previous process left\n * unfinished, before any call of it runs again. `done` calls were rebuilt\n * from their step records (show them finished); `resuming` calls run\n * again or are reported interrupted. Optional for hosts: one that ignores\n * it shows the run as running and fills in the calls when the batch ends.\n *\n * Checkpoint runtimes only: in replay mode the loop cannot tell which calls\n * are done before it issues them, and the hook would fire on every replay.\n */\n 'tool-batch:resumed': (ctx: {\n runId: string\n turn: number\n turnId: string\n /** Call ids answered from their records, in call order. */\n done: readonly string[]\n /** Call ids still to settle, in call order. */\n resuming: readonly string[]\n }) => void\n /**\n * `Agent.resume` refused a run whose stored step records are of another\n * loop turn than the one its saved turns resume at (a history rewrite):\n * asking for keys of the wrong turn would miss a pending unsafe call and\n * run it again. Also fires when the run's saved turns leave a tool call\n * unanswered before their last turn (they were rewritten after the loop\n * saved them). The run is no longer resumable: its records are dropped,\n * its dangling tool calls are reported interrupted (a spawned child's are\n * left to the next top-level run), and `resume()` resolves `null`.\n */\n 'resume:mismatch': (ctx: {\n sessionId: string\n runId: string\n /** The loop turn the saved turns resume at. */\n resumeTurn: number\n /** The loop turns the stored step records are of. */\n storedTurns: readonly number[]\n /** Why the run cannot resume, in words. */\n reason: string\n }) => void\n\n // Streaming\n /**\n * Fires immediately before the loop calls `provider.stream()`. Pairs with\n * `stream:end` / `stream:error`; lets observers timestamp the moment the\n * request leaves the client to compute wait-vs-generate split and TTFT\n * relative to provider dispatch (not run start).\n *\n * `startedAt` is `Date.now()` at fire time. Observational — handlers\n * cannot mutate the in-flight `StreamOptions` (use `turn:before` /\n * `context:transform` / `system:transform` for that).\n */\n 'stream:start': (ctx: StreamHookContext & { startedAt: number }) => void\n /** Fires for each text delta of the model response. `delta` is the new chunk and `text` the accumulated text. */\n 'stream:text': (ctx: StreamHookContext & { delta: string, text: string }) => void\n /** Fires when the model's text stream for the turn ends, with the full text. */\n 'stream:end': (ctx: StreamHookContext & { text: string }) => void\n /** Fires for each thinking delta. `delta` is the new chunk and `thinking` the accumulated thinking text. */\n 'stream:thinking': (ctx: StreamHookContext & { delta: string, thinking: string }) => void\n /**\n * Fires (throttled, ~4/s) while the parent turn streams and once more,\n * unthrottled, right before `stream:end`. Carries the tokens streamed so far\n * (provider-counted when the wire reports mid-stream usage, else chars ÷ 4)\n * and a running USD estimate for the turn. Hosts paint live counters from\n * it; `turn:after` settles the figure. Not bubbled for subagents — their\n * spend lands at `child:turn:after`. Observational and best-effort.\n */\n 'stream:progress': (ctx: StreamProgressHookContext) => void\n /**\n * Fires mid-stream when a provider that executes a tool server-side\n * (currently: Anthropic's `web_search_20250305`) closes the\n * server-tool-invocation content block. Symmetric with `tool:before` for\n * function tools — surface the call into the transcript at the moment the\n * model issued it, without waiting for the assistant message to finalize.\n *\n * Shape is intentionally generic so future server tools reuse the same\n * hook. `id` is the block's tool-use id (echoed back to the provider on\n * follow-up turns); pair with `stream:server_tool_result` via that id.\n *\n * Observational — handlers cannot block or substitute, since the call\n * has already executed server-side by the time we see it.\n */\n 'stream:server_tool_use': (ctx: StreamHookContext & {\n id: string\n name: string\n input: Record<string, unknown>\n }) => void\n /**\n * Pairs with {@link AgentHooks['stream:server_tool_use']} — fires when the\n * provider closes the matching server-tool-result block. `content` is the\n * raw block payload (either an error object or an array of result entries\n * carrying `encrypted_content` / `encrypted_index`); consumers format it\n * for display.\n */\n 'stream:server_tool_result': (ctx: StreamHookContext & {\n toolUseId: string\n toolName: string\n content: unknown\n }) => void\n /**\n * Fires when the provider's stream rejects BEFORE `stream:end` — provider\n * errors, network blips, malformed `tools` payloads (400 invalid_request_error).\n *\n * `err` is the original thrown value, not the typed `AgentProviderError`\n * the loop subsequently constructs; subscribe here to capture the native\n * SDK exception (status codes, request ids) for telemetry without having\n * to walk `cause` chains. Observational — the loop still wraps + throws\n * after this hook resolves, so handlers cannot suppress the failure.\n *\n * Best-effort convenience fields extracted from common SDK shapes\n * (Anthropic, OpenAI, OpenRouter, Cerebras) when present on `err`:\n * - `statusCode` — HTTP status (e.g. 400, 429, 500, 502, 529)\n * - `requestId` — provider request id for grep-the-logs correlation\n *\n * Both absent when the SDK doesn't expose them (network/early rejects,\n * stream-internal protocol errors). Walk `err.cause` chains yourself for\n * deeper diagnostics.\n *\n * Does NOT fire on user-initiated aborts; those land on `agent:abort`\n * instead. Use `err instanceof Error && err.name === 'AbortError'` to\n * distinguish if you also subscribe here for raw error logging.\n */\n 'stream:error': (ctx: StreamHookContext & {\n err: unknown\n statusCode?: number\n requestId?: string\n }) => void\n /**\n * Fires when the loop catches a `retryable` provider error and is about\n * to sleep before re-issuing `provider.stream()`. Does NOT fire on the\n * terminal failure (the attempt the loop gives up on) — that lands on\n * `stream:error` instead.\n *\n * Use this hook to surface \"Anthropic overloaded — retrying in Ns\" in\n * the TUI, count retries in observability, or short-circuit further\n * retry logic from an outer harness.\n *\n * - `attempt` — 1-indexed number of the attempt that just failed.\n * - `nextAttempt` — `attempt + 1`, the attempt that will run after the sleep.\n * - `delayMs` — the wait the loop is about to take. Already accounts for\n * any `retry-after` / `retry-after-ms` header the server returned and\n * the configured `maxDelayMs` cap.\n * - `err` — the raw thrown value (same as `stream:error.err`).\n * - `statusCode` / `requestId` — extracted via the same helper as\n * `stream:error` when available.\n *\n * Observational — handlers cannot cancel the retry. To disable retry,\n * set `behavior.retry.maxAttempts: 1`.\n */\n 'stream:retry': (ctx: StreamHookContext & {\n attempt: number\n nextAttempt: number\n /** The run's retry budget (`behavior.retry.maxAttempts`) — lets UIs render `retry n/max`. */\n maxAttempts: number\n delayMs: number\n err: unknown\n statusCode?: number\n requestId?: string\n /**\n * `true` when the failed attempt streamed reasoning (and nothing else)\n * before it failed. That reasoning is dropped: it is not persisted, and\n * the next attempt's `stream:thinking` `thinking` snapshots start\n * empty. Hosts that showed it live should clear it for this turn.\n */\n discardedThinking?: true\n }) => void\n /**\n * Fires when a stream fails terminally on the active provider+model target\n * and the loop advances to the next entry of the run's fallback chain\n * (`AgentRunOptions.model` array / multi-provider fan-out) instead of\n * surfacing the error. Fires once per advancement; the terminal failure of\n * the LAST target still lands on `stream:error` as usual.\n *\n * Fallback is run-sticky: after this fires, the rest of the run stays on\n * `to` (no ping-pong back to the primary); the next `run()` starts from the\n * primary target again.\n *\n * - `from` / `to` — provider name + model id of the exhausted and newly\n * active targets.\n * - `targetIndex` — 0-based index of `to` in the resolved target list.\n * - `err` — the classified error that exhausted `from` (an\n * `AgentProviderError` whose `limit` says when it was a rate limit, spent\n * quota or overload); the raw provider error is its `cause`.\n * - `discardedThinking` — `true` when the failed attempt streamed\n * reasoning before it failed; same meaning as on `stream:retry`.\n *\n * Observational — handlers cannot cancel the fallback. To disable fallback,\n * configure a single provider+model target.\n *\n * Attribution note: `agent:start`'s `providerName` comes from the PRIMARY\n * target and is not updated when a fallback advances — this hook (and\n * per-turn `TurnUsage.modelId`) is the source of\n * truth for which target actually served a given stretch of the run.\n */\n 'model:fallback': (ctx: StreamHookContext & {\n from: { provider: string, model: string }\n to: { provider: string, model: string }\n targetIndex: number\n err: Error\n /** See {@link AgentHooks['stream:retry']}'s `discardedThinking`. */\n discardedThinking?: true\n }) => void\n /**\n * Fires when the loop catches a `context_exceeded` provider error and, before\n * giving up, performs an emergency in-loop compaction (aggressive tail\n * elision of older `tool_result` bodies) and re-issues `provider.stream()`.\n * Does NOT fire when compaction can't shrink the request any further — that\n * lands on `stream:error` (the terminal failure).\n *\n * Runs independently of `behavior.compactStrategy`: the recovery calls the\n * tail compactor directly, so it protects runs that never opted into\n * client-side compaction. It can only shrink tool-result-heavy histories — a\n * request whose mandatory text alone overflows still surfaces the error.\n *\n * - `attempt` — 1-indexed recovery pass (each pass keeps fewer trailing turns\n * intact and elides more; bounded).\n * - `err` — the raw `context_exceeded` error that triggered recovery.\n *\n * Observational — handlers cannot cancel the recovery.\n */\n 'context:overflow': (ctx: StreamHookContext & {\n attempt: number\n err: unknown\n }) => void\n /**\n * Fires when loop-native auto-compaction (`behavior.autoCompact`) crosses\n * its threshold, or `agent.compact()` starts (`ctx.reason: 'manual'`), and\n * the summary call is about to run, BEFORE the provider round-trip.\n * Distinct from `context:overflow` (the reactive, wire-only\n * `context_exceeded` net) — this is the heavy compaction that summarizes\n * older turns and mutates the session.\n *\n * Use it to surface a \"Compacting…\" banner / footer state. Observational\n * — handlers cannot cancel the compaction. Always paired with exactly one\n * `compact:end`.\n */\n 'compact:start': (ctx: CompactStartHookContext) => void\n /**\n * Fires (throttled) while the compaction summary streams — carries a\n * rough cumulative output-token estimate (`estOutputTokens`, chars ÷ 4)\n * so hosts can paint live progress next to the \"Compacting…\" state.\n * Zero or more per `compact:start`; best-effort and observational.\n */\n 'compact:progress': (ctx: CompactProgressHookContext) => void\n /**\n * Fires exactly once after every `compact:start`, on success and failure\n * (`ctx.status`). On success it carries the replaced/dropped/restored\n * counts and the post-compact `effectiveTokens` estimate so hosts can drop\n * their context indicator immediately. On failure it carries `error`; an\n * auto-compaction's run continues with the un-compacted history (the\n * reactive overflow net still applies) and the circuit breaker counts the\n * failure, while `agent.compact()` rejects with the error (or resolves\n * `compacted: false` when it was aborted).\n */\n 'compact:end': (ctx: CompactEndHookContext) => void\n /**\n * Fires after a provider stream settles when the loop scrubbed\n * provider-rejected reasoning state from canonical history (e.g.\n * Anthropic signature-400 poisoning). In-memory turns and the bound\n * session are already repaired; hosts mirroring turns into an external\n * durable store must heal it using `ctx.turnIds` or the next reload\n * re-poisons the run. Observational. See {@link HistoryRepairHookContext}.\n */\n 'history:repair': (ctx: HistoryRepairHookContext) => void\n /**\n * Fires when the provider dropped replayed thinking blocks server-side\n * before sampling (Anthropic preserved-thinking binding, reported via\n * `input_transformations`). Nothing was mutated on our side — contrast\n * `'history:repair'`. A `prefix_binding_mismatch` entry means this host\n * rewrote system / tools / an earlier message since the block was\n * produced: the same edit `'cache:break'` attributes, now also costing the\n * model its reasoning. Observational. See {@link InputTransformationsHookContext}.\n */\n 'provider:input-transformations': (ctx: InputTransformationsHookContext) => void\n /** Fires when the provider reports a diagnostic event for a turn. */\n 'provider:diagnostic': (ctx: import('./providers/diagnostic').ProviderDiagnostic & { runId: string, turnId: string }) => void\n /** Fires when the provider refreshes its OAuth credentials during a run. */\n 'oauth:refresh': (ctx: OAuthRefreshHookContext) => void\n\n /**\n * Resolves persisted content refs into provider-bound payload bytes.\n *\n * Fires only when wire assembly sees a block carrying `ref`. Handlers set\n * `ctx.data` to the resolved payload. The bytes are wire-only and are never\n * written back to `session.turns`.\n */\n 'content-ref:resolve': (ctx: {\n block: ResolveContentRefBlock\n data?: string\n childId?: string\n depth?: number\n }) => void\n\n // Tool execution\n /**\n * Fires before validation, `tool:before`, and `execute`. Two ways to\n * intercept:\n *\n * - Set `block = true` (with a `reason`) to refuse the call. The model\n * sees a `tool_result` block with `content` = `Blocked: <reason>` and\n * `is_error: true`. `tool:before` / `tool:after` do **not** fire;\n * `tool:dispatched` does (with `outcome: 'gate-block'`) so trace /\n * audit consumers see the refusal. The exact wire payload is:\n *\n * ```jsonc\n * {\n * \"type\": \"tool_result\",\n * \"tool_use_id\": \"<call id>\",\n * \"content\": \"Blocked: <reason>\", // verbatim, no wrapping XML\n * \"is_error\": true\n * }\n * ```\n *\n * The `Blocked: ` prefix is fixed (single space, no colon variations);\n * the `<reason>` is whatever string the gate handler assigned to\n * `ctx.reason` (defaults to `'Tool execution was blocked'` if no\n * handler set it). Pinned by `test/per-run-hooks.test.ts` so SDK\n * consumers can safely string-match for telemetry / eval scoring.\n * - Set `result` to substitute a successful tool_result and skip\n * execution. The model sees the substitute as a normal tool_result;\n * `tool:before` does not fire, but `tool:after` and `tool:transform`\n * do — so byte budgets, telemetry, and post-mutation hooks see the\n * substitute. Useful for cache hits, dedup, idempotency guards,\n * plan-mode synthetic acks.\n *\n * If multiple handlers along the chain set both `block` and `result`,\n * `block` wins — refusal beats substitution, so a policy gate\n * (skills allow-list, custom security) can always override an upstream\n * consumer's cache substitute. Mirrors the writable-`result` shape on\n * `tool:unknown` and `tool:error` so consumers learn one pattern.\n *\n * `runToolCounts` — frozen pre-call snapshot of per-tool dispatched\n * counts in this run. Use it to self-throttle, drive observability, or\n * implement budget guards. Counts every call that passed gate, including\n * dedup substitutes; excludes `block`ed calls.\n *\n * Concurrent fleets see the same pre-batch snapshot on every member's\n * `tool:gate`; the built-in budget / dedup middleware reserves per-call\n * atomically so `behavior.toolBudgets` enforces correctly even when\n * multiple `tool:gate` callbacks fire in the same microtask.\n *\n * Gate a tool call before it runs. Handlers share ONE mutable `ctx` and run\n * sequentially in registration order (the order they were `hook()`-ed). The\n * framework reads the final state once all handlers (including async ones,\n * which are awaited) have run. Built-in behavior gates install during run\n * setup and self-defer when another gate already set `block` / `result`.\n *\n * Precedence across the resolved state:\n * - `block` beats `result`: if any handler left `block === true`, the call\n * is refused (`Blocked: <reason>`, `isError: true`) and any `result`\n * substitute is dropped. Security/refusal beats convenience/substitution.\n * - Among handlers, it is effectively last-writer-wins per field (each just\n * mutates the shared `ctx`). Cooperative built-ins self-defer — e.g.\n * `repeat-guard` early-returns when `ctx.block || ctx.result` is already\n * set, so it never double-penalizes a call another guard already broke.\n * Host handlers composing with the built-ins should do the same\n * (check `ctx.block`/`ctx.result` before acting) to keep precedence\n * predictable.\n *\n * Set `block = true` (+ `reason`) to refuse, or assign `result` to\n * short-circuit with a synthetic successful tool_result (the body never\n * runs; `tool:after` still fires). Mutating `ctx.input` rewrites the args\n * the body and downstream hooks see. `metadata` rides the refused\n * tool_result (read only when the call is blocked).\n *\n * Resumed calls (`resumed`): a checkpoint run resumed after a process\n * death dispatches again the calls whose step was recorded, which passed\n * the gate in the process that died. Their gate runs again so handlers\n * restore what they keep per call, without asking anyone: the framework\n * ignores `result` for them, and `block` too unless the call's body runs\n * again. What a handler writes to\n * `resumeState` (JSON, under a key of its own) is stored with the call's\n * step record and comes back on a resumed call.\n */\n 'tool:gate': (ctx: ToolHookContext & ToolGateResumeFields & {\n block: boolean\n reason: string\n result?: string | ToolResultContent[]\n metadata: ToolResultMetadata\n runToolCounts: Readonly<Record<string, number>>\n }) => void\n /** Fires before a tool body runs. Mutate `ctx.input` to rewrite the arguments the body sees. */\n 'tool:before': (ctx: ToolHookContext & {\n coercions?: readonly string[]\n runToolCounts: Readonly<Record<string, number>>\n /**\n * Pre-write file snapshot — set on a subagent's `tool:before` by the\n * enricher in `spawn-child.ts` when the call is `write_file`, `edit` or\n * `multi_edit` and the target path is readable. Forwarded\n * through to the parent's `child:tool:before` bubble so hosts can\n * render a true `old → new` diff. Absent for every other tool, and\n * for `write_file` on a fresh-create.\n */\n priorContent?: string\n /**\n * `true` when the call's name has no matching registered tool — the\n * model invented it (hallucination) or referenced a tool whose\n * registration is gone (an MCP server dropped, an alias removed).\n *\n * Fires immediately BEFORE the `tool:unknown` substitute path so UI\n * consumers using `tool:before` to render a tool card still see\n * the model's attempt — otherwise the call was silently swallowed\n * and the model's intent never surfaced in the transcript.\n *\n * Pairing contract for `unknown: true` events:\n * - `tool:after` does NOT fire (the body never executed).\n * - `tool:error` fires next (unless the `tool:unknown` handler\n * sets `suppressError`).\n * - `tool:dispatched` fires with `outcome: 'unknown'`.\n *\n * Mutations to `ctx.input` / `ctx.coercions` on this path are\n * observational only — there's no body to dispatch them into.\n */\n unknown?: boolean\n }) => void\n /**\n * Symmetric notification fired ONCE per call the model dispatched,\n * regardless of the path the call ultimately took through the loop.\n * Every call that produces a tool_result closes with exactly one\n * terminal event, so pair `tool:dispatched` with that terminal to\n * reconstruct message history / close per-call spans:\n * - `outcome: 'execute'` → closes with `tool:after` OR, if the call was\n * cancelled in-flight via `agent.cancelTool`, with `tool:cancelled`\n * (NOT `tool:after`). A span keyed on `dispatched(execute)→after`\n * will leak on cancel — also listen for `tool:cancelled`.\n * - `outcome: 'gate-substitute'` → closes with `tool:after`.\n * - `outcome: 'gate-block' | 'invalid-input'` → no `tool:after` (the\n * body never ran); the dispatch event itself carries the result.\n * - `outcome: 'unknown'` → no `tool:after`; closes after\n * `tool:unknown` (+ optional `tool:error`).\n * The strict direction always holds: no `tool:after` fires without a\n * preceding `tool:dispatched`.\n *\n * Distinct from `tool:before`: `tool:before` fires when a tool's body\n * is about to execute (the \"I'm running this tool\" notification)\n * OR — as a special case — once with `unknown: true` for hallucinated\n * tool names, so UI consumers rendering tool cards still see the\n * model's attempt. It still skips gate-block / gate-substitute /\n * validation-reject paths. `tool:dispatched` fires on all five paths\n * with an `outcome` discriminator so live consumers never see a\n * `tool:after` whose matching dispatch event was suppressed.\n *\n * Strict ordering: `tool:dispatched` fires AFTER `tool:gate` /\n * `validation:reject` / `tool:unknown` so the resolved `outcome` is\n * always accurate. Fires BEFORE `tool:before` on the execute path so\n * consumers binding both events see dispatched-then-before.\n *\n * `reason` is set only when `outcome === 'gate-block'` and carries the\n * gate's refusal text (so consumers can render denied-diff badges, etc.\n * without a side channel).\n */\n 'tool:dispatched': (ctx: ToolHookContext & {\n outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'\n reason?: string\n runToolCounts: Readonly<Record<string, number>>\n }) => void\n /**\n * Fires after a tool body produced a result (the execute path) or a\n * `tool:gate` listener substituted one via `ctx.result` (the\n * cache-substitute path). Carries the post-`tool:transform` payload —\n * what the model actually sees on the wire.\n *\n * Does NOT fire on gate-block / unknown-tool / validation-reject\n * paths: the loop synthesizes their `tool_result` text inline and\n * sends it back to the model, but no tool body produced output and\n * no `tool:transform` ran. Consumers wanting symmetric per-call\n * notification across every dispatch path should listen to\n * `tool:dispatched` instead (which fires once per call regardless of\n * path, with an `outcome` discriminator).\n *\n * This narrow contract is deliberate: tracing spans opened in\n * `tool:before` only get closed where they were opened, byte budgets\n * only count real tool output, and chat-layer transcript renderers\n * keep their `tool` ↔ `tool-result` pairing without special-casing\n * the synthesized paths.\n */\n 'tool:after': (ctx: ToolHookContext & {\n result: string | ToolResultContent[]\n /**\n * Final wire error bit for this result, post-`tool:transform` (a\n * transform can flip it in either direction). Middleware that caches\n * or replays results (e.g. `dedupTools`) must consult this: error\n * results are state-dependent verdicts, not stable payloads.\n */\n isError: boolean\n outputBytes: number\n coercions?: readonly string[]\n runToolCounts: Readonly<Record<string, number>>\n /**\n * Structured side-effect outcome for mutating tools that reported one via\n * `ToolContext.reportOutcome` (built-in `write_file` / `edit` /\n * `multi_edit` do). `'noop'` means the call succeeded but changed zero\n * bytes — the signal hosts need to break no-progress loops without\n * string-matching the result text. Absent for read-only tools and any\n * tool that didn't report. See {@link ToolOutcome}.\n */\n outcome?: ToolOutcome\n }) => void\n /**\n * Fires when a tool throws during execution. Mutate `result` to substitute a\n * tool-output payload that gets sent back to the model in place of the\n * default `Tool error: <msg>` string — useful for OSS-model error rewriting\n * (collapse stack traces, hide internal paths, prepend recovery hints).\n *\n * The post-hook value flows through `tool:transform` like a normal output, so\n * downstream byte-budgeting and image-stripping still apply.\n */\n 'tool:error': (ctx: ToolHookContext & { error: Error, result?: string | ToolResultContent[] }) => void\n /** Fires after a tool produces output and before the result goes back to the model. Mutate `ctx.result` to rewrite it. `outputBytes` is the size before any mutation. */\n 'tool:transform': (ctx: ToolHookContext & { result: string | ToolResultContent[], isError: boolean, metadata: ToolResultMetadata, outputBytes: number, coercions?: readonly string[] }) => void\n /**\n * Fires once per artifact the session recorded from a tool result's\n * reserved `metadata.artifacts` namespace (see `session/artifacts.ts`).\n * Observability only — the artifact is already persisted; hosts use it\n * to refresh badges / panels live. Never fires on sessionless runs or\n * stores without artifact support.\n */\n 'artifact:recorded': (ctx: { runId: string, turnId: string, callId: string, name: string, artifact: SessionArtifact }) => void\n /** Bubbled from a subagent's `artifact:recorded` (shared-session children). Same payload + `childId` / `depth`. */\n 'child:artifact:recorded': (ctx: { runId: string, turnId: string, callId: string, name: string, artifact: SessionArtifact, childId: string, depth: number }) => void\n /**\n * Fires when a settled tool call's durable state (`ToolContext.state`) could\n * NOT be committed — the backing {@link AgentOptions.toolState} store\n * rejected the write.\n *\n * The call itself is unaffected: the tool body already ran and its result is\n * already on its way to the model, so failing the run over a bookkeeping\n * write would be worse than losing it. But losing it silently is worse\n * still — a dropped one-shot flag re-arms the exact bug durable tool state\n * exists to prevent — so this is the seam for alerting on it. `ops` is the\n * delta that did NOT land, in the order the tool staged it; replaying it by\n * hand is a legitimate recovery.\n *\n * Without a handler (or with one that leaves `handled` unset) the loop logs\n * to stderr. Set `handled = true` when your handler owns the reporting and\n * you don't want the duplicate log line.\n */\n 'tool-state:commit-failed': (ctx: {\n runId: string\n callId: string\n toolName: string\n ops: readonly ToolStateOp[]\n error: Error\n handled?: boolean\n }) => void\n /**\n * Fires before the generic \"Unknown tool\" error when the model invokes a tool\n * that isn't registered (hallucinated names, dropped MCP servers, dangling\n * aliases). Mutate `result` to substitute a friendly response or set\n * `suppressError: true` to skip the companion `tool:error` emission.\n *\n * Fires for any unknown tool name — including hallucinated MCP-style names\n * (`mcp_<server>_xxx`); branch on `name.startsWith('mcp_')` to differentiate.\n */\n 'tool:unknown': (ctx: ToolHookContext & {\n result?: string | ToolResultContent[]\n suppressError: boolean\n }) => void\n /**\n * Fires when a single in-flight tool call is cancelled mid-flight via\n * `agent.cancelTool(callId)` — typically the TUI's \"cancel this tool\"\n * affordance. Distinguished from `tool:error` (the tool body threw),\n * `agent:abort` (whole run aborted), and the batch-layer\n * `INTERRUPT_MESSAGE_FOR_TOOL_USE` shape (sibling drain on full abort)\n * so consumers can split the four causes.\n *\n * Semantics:\n * - The tool's body has already received an abort signal (via the\n * combined per-call + run signal); whether it actually unwound is\n * up to the body's signal awareness.\n * - The framework returns the canonical\n * {@link TOOL_USE_CANCELLED_MESSAGE} to the model with\n * `isError: true` so the assistant turn closes cleanly and the\n * model can continue with the next batch call.\n * - `tool:after` and `tool:transform` do **not** fire for a cancelled\n * call — there's no real result the loop should account for.\n *\n * `runToolCounts` mirrors the `tool:gate` / `tool:before` snapshot for\n * this call (frozen, pre-increment) so a single per-call observer can\n * subscribe to either hook without re-walking the run.\n */\n 'tool:cancelled': (ctx: ToolHookContext & {\n reason: string\n runToolCounts: Readonly<Record<string, number>>\n }) => void\n /**\n * Fires when `validateToolArgs` rejects an input that could not be auto-coerced\n * to satisfy the tool's `inputSchema`. Observational — the tool call still\n * surfaces a `Validation error: …` string back to the model. Useful for\n * counting validation failures separately from runtime tool errors.\n */\n 'validation:reject': (ctx: ToolHookContext & {\n reason: string\n schema: Record<string, unknown>\n }) => void\n /**\n * Fires when `validateToolArgs` successfully auto-coerced one or more input\n * fields to satisfy the tool's `inputSchema`. **Only fires when at least one\n * coercion happened** — never on perfectly-shaped inputs. Useful for counting\n * model \"wrongness rate\" without re-running validation downstream.\n *\n * `coercions` lists the field names that were coerced. The values landed in\n * the input that the tool actually received; consumers wanting before/after\n * comparison can re-run `validateToolArgs(ctx.input, ctx.schema)`.\n */\n 'validation:coerce': (ctx: ToolHookContext & {\n coercions: readonly string[]\n schema: Record<string, unknown>\n }) => void\n\n // Context\n /** Fires per request with the session messages about to be sent. Mutate `ctx.messages` to rewrite the context for this turn. */\n 'context:transform': (ctx: { messages: SessionMessage[] }) => void\n /**\n * Fires per request, after `context:transform` and before the request goes\n * out. Mutating `ctx.system` updates the system prompt the provider sends\n * for this turn.\n *\n * ## Anything written here must be byte-stable across turns\n *\n * The system prompt sits ABOVE the whole conversation in the provider's cache\n * prefix — Anthropic hashes tools → system → messages, cumulatively — so a\n * one-byte change to `ctx.system` invalidates every message-level breakpoint\n * and re-bills the entire transcript at the cache-write rate. Only `tools` and\n * the static half of the system prompt survive, which is what makes this hard\n * to spot: `cacheRead` stays large and non-zero (it becomes a CONSTANT equal to\n * the scaffold) while cost climbs.\n *\n * The classic way to get this wrong is a live tally: interpolating something\n * like `You have already read ${n} files…` re-renders the prompt on most turns\n * and quietly re-bills the transcript on each one.\n *\n * Constant guidance strings, feature flags and run-stable facts are fine here.\n * Live counters, timestamps, elapsed times, per-turn indices and anything\n * derived from a growing tally are NOT — not even in the dynamic half below\n * `SYSTEM_PROMPT_BOUNDARY`, which carries no `cache_control` of its own but is\n * still inside the prefix that every message breakpoint hashes.\n *\n * Genuinely per-turn state belongs in the transcript, persisted as immutable\n * history so it cannot shift under the prefix on a later turn. A wire-only\n * append to the newest message does NOT work either: that message re-renders\n * without the append next turn and the prefix diverges there instead. Install\n * {@link installCacheBreakLogger} while developing anything that writes here.\n *\n * `messages` is read-only here; use `context:transform` for message\n * surgery. `session` is `undefined` when the run is sessionless.\n */\n 'system:transform': (ctx: { system: string, messages: readonly SessionMessage[], turn: number, turnId: string, session?: Session }) => void\n /** Fires when a queued {@link Agent.steer} message is injected into the conversation as a user turn. */\n 'steer:inject': (ctx: { message: string }) => void\n\n // Spawn\n /**\n * A top-level `spawn` call found every slot taken and waits for one (it\n * starts, with `spawn:before`, once a running child finishes). Never fires\n * for a subagent's spawn: that one is refused at the cap instead.\n */\n 'spawn:queued': (ctx: SpawnQueuedContext) => void\n /** Fires when a spawned subagent is about to start. */\n 'spawn:before': (ctx: SpawnHookContext) => void\n /** Fires when a spawned subagent finishes, with its run stats. */\n 'spawn:complete': (ctx: ChildRunStats) => void\n /** Fires when a spawned subagent fails. */\n 'spawn:error': (ctx: SpawnHookContext & { error: Error }) => void\n /**\n * Nested spawn lifecycle — a SUBAGENT's `spawn:before` / `spawn:complete` /\n * `spawn:error`, re-emitted on its parent's bus (and chained up to the\n * root). Payload is the spawned agent's record plus `parentChildId`, the\n * subagent that spawned it; see {@link ChildSpawnIdentity} for why there is\n * no `childId`. Observational copies: `child:spawn:before` carries no\n * `tracingContext` (the spawner's own tracer owns propagation). The\n * root's own `spawn:*` keeps firing for direct children only.\n */\n 'child:spawn:before': (ctx: ChildSpawnHookContext) => void\n /** Bubbled `spawn:complete` from a subagent. */\n 'child:spawn:complete': (ctx: ChildRunStats & ChildSpawnIdentity) => void\n /** Bubbled `spawn:error` from a subagent. */\n 'child:spawn:error': (ctx: ChildSpawnHookContext & { error: Error }) => void\n\n // Child hook bubbling — re-fires of a subagent's in-turn events on the\n // parent's hook bus. Each context is the original child event payload\n // augmented with `childId` (spawn id) and `depth` (subagent depth). Parents\n // opt in by listening; default behavior is silent. Grandchildren bubble\n // through their immediate parent's spawn tool, so a top-level listener\n // sees the full transitive stream.\n /** Bubbled `stream:text` from a subagent. See the comment above for how child events bubble. */\n 'child:stream:text': (ctx: StreamHookContext & { delta: string, text: string, childId: string, depth: number }) => void\n /** Bubbled `stream:thinking` from a subagent. */\n 'child:stream:thinking': (ctx: StreamHookContext & { delta: string, thinking: string, childId: string, depth: number }) => void\n /** Bubbled `stream:end` from a subagent. */\n 'child:stream:end': (ctx: StreamHookContext & { text: string, childId: string, depth: number }) => void\n /** Bubbled `stream:server_tool_use` from a subagent. See {@link AgentHooks['stream:server_tool_use']}. */\n 'child:stream:server_tool_use': (ctx: StreamHookContext & {\n id: string\n name: string\n input: Record<string, unknown>\n childId: string\n depth: number\n }) => void\n /** Bubbled `stream:server_tool_result` from a subagent. See {@link AgentHooks['stream:server_tool_result']}. */\n 'child:stream:server_tool_result': (ctx: StreamHookContext & {\n toolUseId: string\n toolName: string\n content: unknown\n childId: string\n depth: number\n }) => void\n /** Bubbled `stream:error` from a subagent's turn. See {@link AgentHooks['stream:error']}. */\n 'child:stream:error': (ctx: StreamHookContext & { err: unknown, childId: string, depth: number }) => void\n /** Bubbled {@link AgentHooks['stream:retry']} from a spawned child — lets hosts surface subagent retries. */\n 'child:stream:retry': (ctx: StreamHookContext & {\n attempt: number\n nextAttempt: number\n maxAttempts: number\n delayMs: number\n err: unknown\n statusCode?: number\n requestId?: string\n /** See {@link AgentHooks['stream:retry']}'s `discardedThinking`. */\n discardedThinking?: true\n childId: string\n depth: number\n }) => void\n /**\n * Gate-style child events. Unlike the other `child:*` events, the bubble\n * passes the **same `ctx` reference** the subagent's loop is awaiting on:\n * setting `ctx.block` / `ctx.reason` / `ctx.result` on a parent listener\n * propagates straight back to the child, refusing or substituting the call.\n *\n * Use these to gate subagent tool calls (native + MCP) from the parent\n * without registering listeners on every child agent. The parent's own\n * `tool:gate` / `mcp:tool:gate` listeners are NOT auto-shared with\n * children — that would also share their budgets and dedup state.\n */\n 'child:tool:gate': (ctx: ToolHookContext & ToolGateResumeFields & {\n block: boolean\n reason: string\n result?: string | ToolResultContent[]\n metadata: ToolResultMetadata\n runToolCounts: Readonly<Record<string, number>>\n childId: string\n depth: number\n }) => void\n /** Bubbled `mcp:tool:gate` from a subagent, with `childId` and `depth`. */\n 'child:mcp:tool:gate': (ctx: McpToolHookContext & {\n block: boolean\n reason: string\n result?: string | ToolResultContent[]\n childId: string\n depth: number\n }) => void\n /** Bubbled `tool:before` from a subagent, with `childId` and `depth`. */\n 'child:tool:before': (ctx: ToolHookContext & {\n coercions?: readonly string[]\n runToolCounts: Readonly<Record<string, number>>\n childId: string\n depth: number\n /**\n * Pre-write file snapshot — only set by the enricher in `spawn-child.ts`\n * when `ctx.name` is `write_file`, `edit` or `multi_edit` and the child\n * agent's execution context succeeded in reading the target path.\n * Absent for every other tool, and absent when the file didn't exist\n * (a fresh-create). The TUI's edit-diff renderer treats absence as an\n * empty old buffer to render an all-add view.\n */\n priorContent?: string\n }) => void\n /**\n * Bubbled sibling of {@link AgentHooks['tool:dispatched']} — fires when a\n * subagent dispatches a call. Symmetric with `child:tool:after` so live\n * UI rendering of subagent transcripts stays paired across all five\n * dispatch paths (gate-block/gate-substitute/unknown/invalid-input/execute).\n */\n 'child:tool:dispatched': (ctx: ToolHookContext & {\n outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input'\n reason?: string\n runToolCounts: Readonly<Record<string, number>>\n childId: string\n depth: number\n }) => void\n /** Bubbled `tool:after` from a subagent, with `childId` and `depth`. */\n 'child:tool:after': (ctx: ToolHookContext & {\n result: string | ToolResultContent[]\n /** See `tool:after.isError`. Optional: bridges that synthesize this event (a child run in another invocation) may not know it. */\n isError?: boolean\n outputBytes: number\n coercions?: readonly string[]\n runToolCounts: Readonly<Record<string, number>>\n /** See `tool:after.outcome` — structured side-effect outcome for mutating tools. */\n outcome?: ToolOutcome\n childId: string\n depth: number\n }) => void\n /**\n * Same-ref bubble of a subagent's `tool:transform` hook. Parent\n * listeners may mutate `ctx.result` to rewrite the child tool's\n * output — used by the TUI to append per-edit annotation blocks\n * onto a child agent's `multi_edit` / `edit` / `write_file`\n * results when a parent-level approval gate produced a partial\n * decision.\n */\n 'child:tool:transform': (ctx: ToolHookContext & {\n result: string | ToolResultContent[]\n isError: boolean\n metadata: ToolResultMetadata\n outputBytes: number\n coercions?: readonly string[]\n childId: string\n depth: number\n }) => void\n /** Bubbled `tool:error` from a subagent. */\n 'child:tool:error': (ctx: ToolHookContext & { error: Error, childId: string, depth: number }) => void\n /** Bubbled sibling of {@link AgentHooks['repeat-guard:exceeded']} — a subagent tripped the repeat guard. */\n 'child:repeat-guard:exceeded': (ctx: {\n tool: string\n count: number\n threshold: number\n turnId: string\n action: 'block' | 'steer' | 'abort'\n childId: string\n depth: number\n }) => void\n /** Bubbled sibling of {@link AgentHooks['validation:reject']} — a subagent's call was rejected for invalid input. */\n 'child:validation:reject': (ctx: ToolHookContext & { reason: string, schema: Record<string, unknown>, childId: string, depth: number }) => void\n /**\n * Bubbled sibling of {@link AgentHooks['tool:cancelled']} — fires when a\n * subagent's in-flight tool was cancelled (either directly on the parent\n * via `agent.cancelTool(callId)` reaching a child's call, or by the child\n * agent's own consumers). Symmetric with `child:tool:error` and\n * `child:tool:after` so the TUI's transcript renderer can paint the\n * cancelled badge against the right subagent row.\n */\n 'child:tool:cancelled': (ctx: ToolHookContext & {\n reason: string\n runToolCounts: Readonly<Record<string, number>>\n childId: string\n depth: number\n }) => void\n /** Bubbled from a subagent's `background:start`. Same payload + `childId` / `depth`. */\n 'child:background:start': (ctx: {\n taskId: string\n pid: number\n command: string\n cwd: string\n outputPath: string\n startedAt: number\n childId: string\n depth: number\n }) => void\n /** Bubbled from a subagent's `background:exit`. Same payload + `childId` / `depth`. */\n 'child:background:exit': (ctx: {\n taskId: string\n status: 'exited' | 'killed'\n exitCode: number\n signal?: NodeJS.Signals\n outputPath: string\n durationMs: number\n command: string\n childId: string\n depth: number\n }) => void\n /**\n * Bubbled from a subagent's `background:reassign`. Fires when a\n * grandchild's tasks get promoted to the child's handle on the\n * grandchild's destroy — gives the parent a chance to mirror the\n * ownership change in any UI it maintains.\n */\n 'child:background:reassign': (ctx: {\n taskId: string\n fromHandleId: string\n toHandleId: string\n childId: string\n pid: number\n command: string\n outputPath: string\n startedAt: number\n depth: number\n }) => void\n /** Bubbled `turn:after` from a subagent. */\n 'child:turn:after': (ctx: {\n turn: number\n turnId: string\n usage: TurnUsage\n message: SessionTurn\n /** See `turn:after.aborted` — runtime emissions include it; treat absent as `false`. */\n aborted?: boolean\n toolCounts: { turn: Readonly<Record<string, number>>, run: Readonly<Record<string, number>> }\n childId: string\n depth: number\n }) => void\n\n // MCP server lifecycle\n /**\n * Fires once a server's client is live (transport connected, SDK handshake\n * complete). For servers bootstrapped eagerly, fires right after bootstrap;\n * for servers with `lazyConnect: true`, fires after the first `tools/call`\n * triggers the deferred connect — `lazy: true` lets the host distinguish.\n */\n 'mcp:connect': (ctx: { name: string, transport: string, tools: string[], lazy?: boolean }) => void\n /** Fires when an MCP server fails to connect or errors fatally. */\n 'mcp:error': (ctx: { name: string, error: Error }) => void\n /** Diagnostic line from a server. For fatal failures hook `mcp:error`. */\n 'mcp:warn': (ctx: { name: string, message: string }) => void\n /** Fires when an MCP server connection is closed. */\n 'mcp:close': (ctx: { name: string }) => void\n /**\n * Fires at the start of a per-server bootstrap attempt, before any network I/O.\n * Pairs with `mcp:bootstrap:end` and is always emitted, regardless of outcome.\n */\n 'mcp:bootstrap:start': (ctx: { name: string, transport: string }) => void\n /**\n * Fires at the end of a per-server bootstrap attempt. `durationMs` spans from\n * the matching `mcp:bootstrap:start`. On `ok: false` carries the originating\n * error so consumers can log / trace without relying on a separate `mcp:error`.\n *\n * `lazy: true` on the success arm signals the server registered its tools\n * without opening a connection (see `McpServerConfig.lazyConnect`); the\n * connect cost is deferred to the first `tools/call`. `cached: true` signals\n * the bootstrap skipped `tools/list` because the host provided\n * `cachedTools` — orthogonal to `lazy` (a server can be cached and eager,\n * cached and lazy, or neither).\n *\n * `warnings` (success arm only) collects soft signals that surfaced during\n * bootstrap without aborting it — currently just \"server rejected\n * `notifications/initialized` with 4xx\" from the tolerant client. Hosts\n * can render a \"connected with caveats\" badge from this; consumers that\n * don't care can ignore the field.\n */\n 'mcp:bootstrap:end': (ctx: { name: string, transport: string, durationMs: number } & ({ ok: true, toolCount: number, lazy?: boolean, cached?: boolean, warnings?: string[] } | { ok: false, error: Error })) => void\n /**\n * Fires exactly ONCE per bootstrap batch, after every server's attempt\n * has settled. `results` is sorted by server name — a deterministic\n * aggregate, unlike the per-server `mcp:bootstrap:end` events which\n * fire in network-completion order inside the parallel bootstrap.\n * Durable-execution hosts that journal bootstrap outcomes should hook\n * this instead of buffering + sorting the per-server stream.\n */\n 'mcp:bootstrap:settled': (ctx: {\n results: ReadonlyArray<{ name: string, transport: string, durationMs: number } & (\n | { ok: true, toolCount: number, lazy?: boolean }\n | { ok: false, skipped?: boolean, error?: Error }\n )>\n }) => void\n /**\n * Fires once per successful bootstrap with the **raw, pre-filter** tool\n * schemas the server advertised via `tools/list` (or that the host\n * pre-seeded via `McpServerConfig.cachedTools`). Useful for hosts that\n * want to:\n *\n * - Persist a per-server tool catalog to disk so a settings UI can\n * show every available tool — including ones currently hidden by\n * `disabledTools` — without re-bootstrapping.\n * - Build per-tool toggle UIs that reflect the full server surface.\n * - Diff successive bootstraps to detect newly-added / removed tools.\n *\n * Read-only — handlers must NOT mutate `tools`. Shape the model-facing\n * list via `mcp:tools:filter` instead (which fires immediately after\n * this hook and IS the mutation surface).\n *\n * Does NOT fire when the bootstrap fails. Does NOT fire on lazy-connect\n * servers' deferred first-call (the schemas were already known from\n * `cachedTools` at the agent-construction boundary).\n */\n 'mcp:tools:list': (ctx: { name: string, transport: 'stdio' | 'sse' | 'streamable-http', tools: readonly McpToolSchema[] }) => void\n /**\n * Fires when a server's bootstrap was skipped because it requires OAuth\n * login and no tokens are stored. The host (TUI) surfaces this as a\n * \"needs-auth\" status so the user can opt in to interactive login via\n * `loginMcpServer`. Pairs with `mcp:bootstrap:end ok:false` — both fire,\n * since the bootstrap did fail (just for a recoverable reason).\n *\n * `reason`:\n * - `'no-tokens'` — config has `auth: 'oauth'` set (or normalized from\n * Cursor's `authMethod: 'mcpOAuth'`) and the credential store is empty.\n * - `'auto-promoted'` — server returned 401 + RFC 9728 metadata. No\n * static Authorization header was set, so the server is eligible for\n * OAuth login even though the config didn't explicitly request it.\n */\n 'mcp:auth:required': (ctx: {\n name: string\n transport: 'stdio' | 'sse' | 'streamable-http'\n reason: 'no-tokens' | 'auto-promoted'\n }) => void\n /**\n * Fires during an INTERACTIVE OAuth login flow — when the SDK wants the\n * user agent to navigate to the authorization URL. Hosts open a browser\n * and surface the URL in the TUI (in case the browser auto-open fails).\n * Distinct from `mcp:auth:required` (which fires from bootstrap when\n * tokens are missing); this only fires from `loginMcpServer`.\n */\n 'mcp:auth:url': (ctx: { name: string, url: string }) => void\n /** Interactive login completed and tokens were persisted. */\n 'mcp:auth:success': (ctx: { name: string }) => void\n /** Interactive login failed (browser error, abort, exchange failure). */\n 'mcp:auth:error': (ctx: { name: string, error: Error }) => void\n /**\n * Fires once per server after `listTools()` and after the config-side filters\n * (`enabledTools` / `disabledTools` / `toolFilter`) have applied, but BEFORE\n * tools are registered. Handlers may mutate `ctx.tools` in place — splicing,\n * reordering, or replacing entries — to further narrow what the model sees.\n *\n * Composes with config-side filters: config drops tools the host's static\n * policy excludes; this hook is the runtime escape hatch for per-user, per-\n * environment, or capability-driven decisions that the config can't express.\n *\n * Items are upstream tool descriptors (NOT yet namespaced as `mcp_<server>_<tool>`).\n */\n 'mcp:tools:filter': (ctx: {\n server: string\n transport: 'stdio' | 'sse' | 'streamable-http'\n tools: Array<{ name: string, description?: string | null, inputSchema?: unknown }>\n }) => void\n\n // MCP tool execution\n /**\n * MCP-side counterpart of `tool:gate`. Same shape: set `block` to refuse,\n * set `result` to substitute a successful payload and skip the upstream\n * MCP `callTool`. When both are set across the handler chain, `block` wins.\n *\n * Fires INSIDE the MCP wrapper's `execute`, after the loop's `tool:gate`\n * already ran. Does **not** carry `runToolCounts` — those are loop-level\n * and already exposed on `tool:gate` for MCP tools (which are registered\n * as agent tools under their namespaced name `mcp_<server>_<tool>`). Use\n * `tool:gate` for budget / dedup logic; reserve `mcp:tool:gate` for\n * MCP-specific concerns (per-server routing, transport-aware refusals).\n */\n 'mcp:tool:gate': (ctx: McpToolHookContext & {\n block: boolean\n reason: string\n result?: string | ToolResultContent[]\n }) => void\n /** Fires before an MCP tool call is sent to the server. */\n 'mcp:tool:before': (ctx: McpToolHookContext) => void\n /** Fires after an MCP tool call returns, with the result. */\n 'mcp:tool:after': (ctx: McpToolHookContext & { result: string | ToolResultContent[], outputBytes: number }) => void\n /** Fires before the MCP tool result is returned. Mutate `ctx.result` to rewrite it. `outputBytes` is the size before any mutation. */\n 'mcp:tool:transform': (ctx: McpToolHookContext & { result: string | ToolResultContent[], outputBytes: number }) => void\n /** Fires when an MCP tool call throws. */\n 'mcp:tool:error': (ctx: McpToolHookContext & { error: Error }) => void\n\n // Background tasks\n /**\n * Fires when a background task is spawned via `ExecutionContext.execBackground`.\n * Observational — telemetry consumers can mint a \"task started\" span.\n *\n * `outputPath` is the file the context is streaming stdout+stderr to;\n * the model reads it via `read_file` on demand. `pid` is the OS pid of\n * the spawned shell wrapper (a process-group leader on POSIX, so a\n * `process.kill(-pid)` on cleanup tears down the whole subtree).\n */\n 'background:start': (ctx: {\n taskId: string\n pid: number\n command: string\n cwd: string\n outputPath: string\n startedAt: number\n }) => void\n\n /**\n * Fires exactly once per task when the child process terminates —\n * natural exit, host-issued kill, or `agent.destroy()` teardown. Same\n * payload the agent enqueues into `pendingTaskNotifications` for\n * injection on the next turn; useful for hosts that want to render\n * a \"task done\" toast immediately rather than wait for the model's\n * next prompt.\n */\n 'background:exit': (ctx: {\n taskId: string\n status: 'exited' | 'killed'\n exitCode: number\n signal?: NodeJS.Signals\n outputPath: string\n durationMs: number\n command: string\n }) => void\n\n /**\n * Ownership of a background task was transferred from one execution\n * handle to another — typically the spawn tool reassigning a\n * subagent's still-running tasks up to the parent's handle so they\n * outlive the subagent's `destroy()`.\n *\n * Hosts that listed the task under the source handle should update\n * their view to reflect the new owner. The TUI's `backgroundTasks`\n * registry drops the `childId` tag on the matching entry so the\n * `ctrl+k` picker shows it as parent-level (and `killBackgroundTask`\n * actually finds it).\n *\n * Fires on the new owner's hook bus (the parent's, in the spawn\n * case). The old owner is typically already torn down — wiring the\n * event the other way would deliver it to a destroyed hookable.\n */\n 'background:reassign': (ctx: {\n taskId: string\n /** `ExecutionHandle.id` of the previous owner. */\n fromHandleId: string\n /** `ExecutionHandle.id` of the new owner. */\n toHandleId: string\n /** Subagent label (`child-N`) the task originated under, when known. */\n childId?: string\n pid: number\n command: string\n outputPath: string\n startedAt: number\n }) => void\n\n /**\n * A still-running background task was handed to THIS agent by its host —\n * the agent was built on a host-owned handle that outlived the previous\n * agent (a rebuild after a model swap, settings change, MCP login…; see\n * `chat/execution-cache.ts`). The task's exit/stall callbacks now fire on\n * this bus. Hosts that track running tasks register it exactly like\n * `background:start`; unlike that hook it does not mean \"just spawned\".\n */\n 'background:adopt': (ctx: {\n taskId: string\n pid: number\n command: string\n cwd: string\n outputPath: string\n startedAt: number\n }) => void\n\n /**\n * The stall watchdog ({@link AgentBehavior.backgroundStallWatchdogMs})\n * detected a background task with no output for the configured window.\n * One-shot per quiet period — re-arms after fresh output. The agent\n * queues a `<task-stall>` notification for the model's next turn;\n * hosts can additionally render a \"task may be stuck\" hint.\n */\n 'background:stall': (ctx: {\n taskId: string\n command: string\n outputPath: string\n stalledForMs: number\n bytesWritten: number\n }) => void\n\n /**\n * Fires at the start of an `agent.run()` that has background exits to\n * deliver, BEFORE they are rendered into `<task-notification>`\n * blocks (runs with nothing to deliver skip the hook). `exits` merges\n * the push-fed queue (`background:exit` arrivals since the last run)\n * with a pull-based reconcile against\n * `ExecutionContext.listBackground` — so exits land even when the\n * context never calls `onExit` (remote / durable contexts can't push\n * from a timer into a host journal).\n *\n * This is the journalable seam for durable-execution hosts: the hook\n * runs inside the `run()` await chain, so a handler may replace\n * `ctx.exits` with a recorded copy, making the wall-clock-derived\n * `durationMs`, and so the whole `<task-notification>` block,\n * replay-stable. A replay-mode durable runtime already records the\n * `listBackground` poll as a `reconcile` step.\n *\n * Mutable: handlers may reorder, filter, or substitute entries. The\n * post-hook array is what the model sees.\n */\n 'background:reconcile': (ctx: { exits: TaskExitInfo[] }) => void\n\n /**\n * Fires exactly once per agent, the first time the execution handle is bound\n * — right after the lazy `execution.spawn()` (or immediately on the first run\n * when a handle was injected via {@link AgentOptions.handle}). `spawned` is\n * `true` when the agent minted the handle, `false` for an injected one.\n *\n * The seam durable hosts use to record the minted handle id (e.g. a sandbox\n * id) for re-attach on replay/resume — journal it here, then re-attach via\n * `AgentOptions.handle` + the provider's reconnect option on the next\n * invocation. Observational; the handle is not mutable.\n */\n 'execution:ready': (ctx: { handle: ExecutionHandle, spawned: boolean }) => void\n\n // Skills\n /** Fires once skills have been resolved, with the resolved skill list. */\n 'skills:resolve': (ctx: { skills: SkillConfig[] }) => void\n /** Fires with the rendered skills catalog text and the skills it lists. */\n 'skills:catalog': (ctx: { catalog: string, skills: SkillConfig[] }) => void\n /** Fires when a skill is activated. `via` says what triggered it. */\n 'skills:activate': (ctx: { skill: SkillConfig, via: ActivationVia }) => void\n /** Fires when a skill is deactivated. `reason` says why. */\n 'skills:deactivate': (ctx: { skill: SkillConfig, reason: DeactivationReason }) => void\n\n // Pairing repair\n /**\n * Fires once per repair performed by the pre-send pairing pass\n * ({@link ensureToolResultPairing}). The pass runs immediately before every\n * provider call and patches over the wire-level corruption modes that\n * Anthropic / OpenAI 400 on (orphan `tool_use` / `tool_result`, duplicate\n * ids, compaction-stranded blocks).\n *\n * Observational — handlers can mirror to Sentry/PostHog/etc. for\n * postmortems on new corruption sources but cannot suppress the repair.\n * The companion `behavior.strictToolPairing` flag is the consumer escape\n * hatch for \"throw instead of repair\" (training-data collectors).\n *\n * `turnId` lets handlers correlate a repair burst with the run-loop turn\n * that observed it. Absent on repairs detected from the synthetic\n * fallback path in `agent.run()`'s error catch (the orphan-tool_use\n * fallback for crash recovery), where no turn is in flight.\n */\n 'pairing:repair': (ctx: PairingRepair & { turnId?: string }) => void\n\n // Observability seams\n /**\n * Privacy seam invoked by observability adapters (tracing, metrics,\n * logging, persistence sinks) before attaching potentially-sensitive\n * payloads as span attributes / log lines / external storage.\n *\n * Handlers mutate `ctx.redacted` — the field starts equal to `value` and\n * the final post-hook string is what consumers ship downstream. Default\n * (no handlers) is no redaction. Multiple handlers compose left-to-right;\n * the last writer wins.\n *\n * `kind` lets a single handler do shape-aware scrubbing (system prompts\n * vs. tool args vs. tool output have very different secret surfaces).\n * `meta` carries context-specific identifiers (`toolName`, `server`,\n * `turnId`, `callId`) the adapter knows at the call site — handlers use\n * it for policy decisions (\"skip redaction on internal `read_file`\n * results\"). Adapters that don't fire this hook simply attach raw values.\n *\n * Synchronous-only by design: observability stays on the hot path. Heavy\n * scrubbing (regex over MB of output) belongs in `tool:transform` instead.\n */\n 'tracing:redact': (ctx: {\n kind:\n | 'system'\n | 'prompt'\n | 'tool-input'\n | 'tool-result'\n | 'mcp-tool-input'\n | 'mcp-tool-result'\n | 'stream-text'\n | 'stream-thinking'\n | 'decision-answers'\n value: string\n redacted: string\n meta?: Readonly<Record<string, unknown>>\n }) => void\n\n // Usage and output\n /** Fires after each turn with that turn's token usage and the run's cumulative input and output tokens. */\n 'usage': (ctx: { turn: number, turnId: string, usage: TurnUsage, totalIn: number, totalOut: number }) => void\n /** Fires with the structured output the model produced and the schema it was validated against. */\n 'output': (ctx: { output: Record<string, unknown>, schema: Record<string, unknown> }) => void\n /**\n * Fires when a turn's total tool-output bytes exceed `behavior.toolOutputBudget`.\n * Measured post-`tool:transform`. Loop injects a synthetic user message after\n * the tool-results turn instructing the model to summarize.\n */\n 'budget:exceeded': (ctx: { turn: number, turnId: string, bytes: number, budget: number }) => void\n /**\n * Fires when a per-tool budget configured via `behavior.toolBudgets` is\n * exceeded for a specific tool. `mode` reflects how the framework reacted:\n * `'steer'` lets the call run and queues a post-turn nudge; `'block'`\n * refuses the call outright with `Blocked: <message>`.\n *\n * `count` is the run-cumulative dispatched count just before this call.\n * Use `turnId` to correlate with `turn:after` if you need the integer turn\n * index. Distinct from `budget:exceeded` (byte-level) so consumers can\n * subscribe specifically; both can fire in the same turn.\n */\n 'tool-budget:exceeded': (ctx: {\n tool: string\n count: number\n max: number\n turnId: string\n mode: 'steer' | 'block'\n }) => void\n /**\n * Fires when the consecutive-identical {@link AgentBehavior.repeatGuard}\n * escalates on a tracked tool. In chain mode, `count` is the number of\n * back-to-back identical calls including the offending one; in window mode it\n * is the number of occurrences inside the configured window. `action`\n * reflects the escalation: `'block'` refused this call via `tool:gate`;\n * `'steer'` let it execute and appended a steering message to the result;\n * `'abort'` additionally aborts the run via the agent's `AbortController`\n * (the loop then fires `agent:abort`). The `'abort'` event fires BEFORE the\n * abort so consumers can distinguish a guard abort from a user-driven cancel.\n */\n 'repeat-guard:exceeded': (ctx: {\n tool: string\n count: number\n threshold: number\n turnId: string\n action: 'block' | 'steer' | 'abort'\n }) => void\n\n // Agent lifecycle\n /**\n * The run was aborted — fires exactly once per aborted run, on every abort\n * exit: a between-turn cancel (the loop's `signal.aborted` check), a\n * `repeat-guard` abort, AND a cancel that lands mid-stream (which throws out\n * of the turn and is caught at the run boundary). For a guard abort a\n * `repeat-guard:exceeded` (`action: 'abort'`) event fired first, so consumers\n * can attribute the cause.\n *\n * Does NOT fire on graceful non-cancel terminations that still finalize the\n * session run as `'aborted'`: `maxConsecutivePauseTurns` exhaustion and the\n * `maxCostUsd`/`maxTotalTokens` budget breaker (the latter throws\n * `AgentBudgetExceededError`). Branch on those via their own signals\n * (`finishReason: 'pause'`, the typed error) rather than `agent:abort`.\n *\n * `runId` — the aborted run, for correlating with `turn:after` / telemetry\n * spans. `reason` — the string passed to `AbortController.abort(reason)` when\n * one was supplied (mirrors `signal.reason`); absent for a bare `abort()`.\n */\n 'agent:abort': (ctx: { runId?: string, reason?: string }) => void\n /**\n * Run finished — fires on all exit paths (completion, maxTurns, abort, error).\n *\n * The `AgentStats` carried here is **cumulative** across the\n * parent agent loop and every recursively-spawned sub-agent\n * (`totalIn` / `totalOut` / `cost` / `totalCacheRead` / `totalCacheCreation`).\n * For parent-loop-only counts use `ctx.turnUsage` (parent-only array);\n * for tree-wide turn counts use `flattenTurns(ctx).length`.\n */\n 'agent:done': (ctx: AgentStats) => void\n /**\n * Durable-execution replay finished — the invocation transitioned from\n * journal replay to live execution (the first non-journaled provider\n * stream or tool body just started).\n *\n * The framework core never fires this: it is emitted by durable-runtime\n * adapters (see `createReplayTracker({ hooks })` in `zidane/restate`) once\n * per handler invocation. Hosts that would otherwise infer liveness\n * from side channels (counting live provider calls, watching stream\n * hooks) should key on this instead. Fires at most once per invocation;\n * never fires when the journal replays to completion without going\n * live (nothing left to execute — and nothing left to abort).\n */\n 'replay:done': (ctx: Record<string, never>) => void\n\n // Session\n /** Fires when a run starts on a session, with the run id and prompt label. */\n 'session:start': (ctx: SessionHookContext & { runId: string, prompt: string }) => void\n /** Fires when a run ends, with its status and the range of turn indexes it produced. */\n 'session:end': (ctx: SessionHookContext & { runId: string, status: SessionEndStatus, turnRange: [number, number] }) => void\n /** Fires when new turns are flushed to the session, with the turns and the resulting turn count. */\n 'session:turns': (ctx: SessionHookContext & { turns: SessionTurn[], count: number }) => void\n /** Fires when a session metadata key is set. */\n 'session:meta': (ctx: SessionHookContext & { key: string, value: unknown }) => void\n /** Fires when the session is saved. */\n 'session:save': (ctx: SessionHookContext) => void\n\n // Decisions\n /**\n * Fires when `agent.decide` / `ctx.decide` starts a decision, before\n * validation and the provider call. `provider` / `model` are absent when no\n * decision provider could be resolved. Contexts of `decision:*` hooks carry\n * no `decide`, so a decision can't recursively trigger another.\n */\n 'decision:start': (ctx: DecisionStartHookContext) => void\n /**\n * Fires once per decision, success or failure, after `decision:start`.\n * `ok: false` carries the failure `reason`; `ok: true` carries `answers`\n * and `usage` (decision usage is NOT folded into run totals).\n */\n 'decision:end': (ctx: DecisionEndHookContext) => void\n}\n\n/**\n * Authoritative list of hook event names. Kept in sync with `AgentHooks` at\n * compile time: `satisfies` rejects names not in the interface, and\n * `MissingHookEventNames` below rejects interface keys missing from the list.\n */\nconst HOOK_EVENT_NAMES = [\n 'system:before',\n 'agent:start',\n 'turn:before',\n 'turn:after',\n 'tool-results:after',\n 'tool-batch:resumed',\n 'resume:mismatch',\n 'stream:start',\n 'stream:text',\n 'stream:end',\n 'stream:thinking',\n 'stream:progress',\n 'stream:server_tool_use',\n 'stream:server_tool_result',\n 'stream:error',\n 'stream:retry',\n 'model:fallback',\n 'context:overflow',\n 'cache:break',\n 'cache:drift',\n 'compact:start',\n 'compact:progress',\n 'compact:end',\n 'history:repair',\n 'provider:input-transformations',\n 'oauth:refresh',\n 'provider:diagnostic',\n 'content-ref:resolve',\n 'tool:gate',\n 'tool:dispatched',\n 'tool:before',\n 'tool:after',\n 'tool:error',\n 'tool:cancelled',\n 'tool:transform',\n 'tool:unknown',\n 'tool-state:commit-failed',\n 'artifact:recorded',\n 'child:artifact:recorded',\n 'validation:reject',\n 'validation:coerce',\n 'context:transform',\n 'system:transform',\n 'steer:inject',\n 'spawn:queued',\n 'spawn:before',\n 'spawn:complete',\n 'spawn:error',\n 'child:spawn:before',\n 'child:spawn:complete',\n 'child:spawn:error',\n 'child:stream:text',\n 'child:stream:thinking',\n 'child:stream:end',\n 'child:stream:server_tool_use',\n 'child:stream:server_tool_result',\n 'child:stream:error',\n 'child:stream:retry',\n 'child:tool:gate',\n 'child:mcp:tool:gate',\n 'child:tool:dispatched',\n 'child:tool:before',\n 'child:tool:after',\n 'child:tool:transform',\n 'child:tool:error',\n 'child:validation:reject',\n 'child:repeat-guard:exceeded',\n 'child:tool:cancelled',\n 'child:background:start',\n 'child:background:exit',\n 'child:background:reassign',\n 'child:turn:after',\n 'mcp:connect',\n 'mcp:error',\n 'mcp:warn',\n 'mcp:close',\n 'mcp:bootstrap:start',\n 'mcp:bootstrap:end',\n 'mcp:bootstrap:settled',\n 'mcp:tools:list',\n 'mcp:auth:required',\n 'mcp:auth:url',\n 'mcp:auth:success',\n 'mcp:auth:error',\n 'mcp:tools:filter',\n 'mcp:tool:gate',\n 'mcp:tool:before',\n 'mcp:tool:after',\n 'mcp:tool:transform',\n 'mcp:tool:error',\n 'background:start',\n 'background:exit',\n 'background:reassign',\n 'background:adopt',\n 'background:stall',\n 'background:reconcile',\n 'execution:ready',\n 'skills:resolve',\n 'skills:catalog',\n 'skills:activate',\n 'skills:deactivate',\n 'usage',\n 'output',\n 'budget:exceeded',\n 'tool-budget:exceeded',\n 'repeat-guard:exceeded',\n 'pairing:repair',\n 'tracing:redact',\n 'agent:abort',\n 'agent:done',\n 'replay:done',\n 'session:start',\n 'session:end',\n 'session:turns',\n 'session:meta',\n 'session:save',\n 'decision:start',\n 'decision:end',\n] as const satisfies readonly (keyof AgentHooks)[]\n\ntype MissingHookEventNames = Exclude<keyof AgentHooks, (typeof HOOK_EVENT_NAMES)[number]>\ntype AssertNever<T extends never> = T\n// Fails to compile when an `AgentHooks` key is absent from `HOOK_EVENT_NAMES`.\ntype _HookEventNamesComplete = AssertNever<MissingHookEventNames>\n\nconst HOOK_EVENT_SET: ReadonlySet<string> = new Set(HOOK_EVENT_NAMES)\n\nexport function isKnownHookEvent(event: string): event is keyof AgentHooks {\n return HOOK_EVENT_SET.has(event)\n}\n\n/**\n * Strongly-typed hook registration map accepted on {@link AgentOptions.hooks}\n * (and therefore on any {@link Preset}). Each entry is a single handler or an\n * array of handlers — arrays are what {@link composePresets} produces when\n * multiple presets register handlers for the same event.\n *\n * Handlers registered here live for the **lifetime of the agent**. They fire\n * across every `run()`, mirroring a manual `agent.hooks.hook(event, fn)` call\n * made right after `createAgent` returns. For per-run handlers (auto-detached\n * at run end) use {@link AgentRunOptions.hooks} instead.\n */\nexport type AgentHookMap = Partial<{\n [K in keyof AgentHooks]: AgentHookHandlers[K] | AgentHookHandlers[K][]\n}>\n\n/** Present on every hook context except `decision:*` (see {@link AgentHookHandlers}). */\nexport interface DecideHookContext {\n /**\n * Make a decision request from inside a hook. Bound to the active run: its\n * abort signal cancels the decision and `decision:*` hooks carry its run id.\n * Never throws; see {@link AgentDecide}.\n */\n readonly decide: AgentDecide\n}\n\ntype WithDecide<F> = F extends (ctx: infer C, ...rest: infer R) => infer Ret\n ? (ctx: C extends object ? C & DecideHookContext : C, ...rest: R) => Ret\n : F\n\n/**\n * Handler signatures as consumers see them: identical to {@link AgentHooks}\n * except object contexts also carry {@link DecideHookContext.decide}. The\n * agent attaches it (non-enumerable) right before handlers run, so code that\n * fires hooks builds contexts without it.\n */\nexport type AgentHookHandlers = {\n [K in keyof AgentHooks]: K extends `decision:${string}` ? AgentHooks[K] : WithDecide<AgentHooks[K]>\n}\n\n/** Registration overloads that type handler contexts with `decide`. */\nexport interface AgentHookRegistration {\n hook: <K extends keyof AgentHooks>(name: K, fn: AgentHookHandlers[K], options?: { allowDeprecated?: boolean }) => () => void\n hookOnce: <K extends keyof AgentHooks>(name: K, fn: AgentHookHandlers[K]) => () => void\n removeHook: <K extends keyof AgentHooks>(name: K, fn: AgentHookHandlers[K]) => void\n}\n\n/**\n * `agent.hooks`: the agent's hookable, with registration typed through\n * {@link AgentHookHandlers} (so handlers see `ctx.decide`) while `callHook`\n * keeps the raw {@link AgentHooks} context shapes.\n */\nexport type AgentHookBus = AgentHookRegistration & Hookable<AgentHooks>\n\n/** Events whose contexts never receive `decide`. */\nexport function isDecisionHookEvent(event: string): boolean {\n return event.startsWith('decision:')\n}\n","/**\n * The agent-side decider behind `agent.decide` and `ctx.decide`.\n *\n * Resolves the decision provider + model, validates the request, enforces a\n * wall-clock cap combined with the run's abort signal, fires\n * `decision:start` / `decision:end`, and turns every failure into a\n * `{ ok: false, reason }` outcome. It never throws unless the caller passes\n * `{ throw: true }`.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from '../agent-hooks'\nimport type { Provider, ProviderDecisionRequest, ProviderDecisionResponse, ProviderDecisions } from '../providers'\nimport type { SerializedDecisionError } from './errors'\nimport type {\n AgentDecide,\n AgentDecisionsOptions,\n DecisionAnswers,\n DecisionEndHookContext,\n DecisionFailure,\n DecisionFailureReason,\n DecisionOutcome,\n DecisionQuestions,\n DecisionRequest,\n DecisionStartHookContext,\n} from './types'\nimport { randomUUID } from 'node:crypto'\nimport { createDebugLog } from '../debug-log'\nimport { abortError, classifyDecisionError, DecisionError, DecisionTimeoutError, DecisionUnavailableError, deserializeDecisionError, serializeDecisionError } from './errors'\nimport { decisionInputKind, validateDecisionAnswers, validateDecisionRequest } from './wire'\n\nexport * from './errors'\nexport { currentRunDecide, withRunDecide } from './run-scope'\nexport type * from './types'\nexport { decisionInputKind, scoreLevelDescription, scoreLevelLabel, validateDecisionAnswers, validateDecisionRequest } from './wire'\n\n/** Default wall-clock cap for one decision, in milliseconds. */\nexport const DEFAULT_DECISION_TIMEOUT_MS = 5000\n\nconst debugLog = createDebugLog('decisions')\n\nexport interface DeciderOptions {\n providers: readonly Provider[]\n /** `false` disables decisions; `undefined` auto-detects from `providers`. */\n config: AgentDecisionsOptions | false | undefined\n hooks: Hookable<AgentHooks>\n}\n\nexport interface Decider {\n /**\n * `decide` bound to a run: `runId` is stamped on `decision:*` hooks and\n * `runSignal` (that run's abort signal) cancels its decisions. With a\n * `journal`, pass `newId` too (the run's journaled ids), so a replayed\n * decision keeps its `decisionId`.\n */\n forRun: (runId: string | undefined, runSignal?: AbortSignal, journal?: DecisionJournal, newId?: () => string) => AgentDecide\n}\n\n/**\n * Records a decision's provider call as one step of a replay-mode run: a\n * replay gets the recorded outcome instead of asking the provider again.\n */\nexport type DecisionJournal = <T>(work: () => Promise<T>) => Promise<T>\n\ntype JournaledDecision\n = | { ok: true, response: ProviderDecisionResponse }\n | { ok: false, error: SerializedDecisionError }\n\ninterface Target {\n provider: Provider\n decisions: ProviderDecisions\n}\n\nfunction canDecide(decisions: ProviderDecisions): boolean {\n try {\n return decisions.availability().available\n }\n catch {\n return false\n }\n}\n\nexport function createDecider(options: DeciderOptions): Decider {\n const { providers, config, hooks } = options\n const unavailableModels = new Set<string>()\n let warnedUnavailable = false\n\n function resolveTarget(): Target | string {\n if (config === false)\n return 'Decisions are disabled for this agent'\n // Auto-detect: the first provider that can decide now (credentials), else\n // the first with the capability so its availability error is reported.\n const provider = config?.provider ?? providers.find(p => p.decisions && canDecide(p.decisions)) ?? providers.find(p => p.decisions)\n if (!provider)\n return `No configured provider supports decisions (checked: ${providers.map(p => p.name).join(', ') || 'none'})`\n if (!provider.decisions)\n return `Provider \"${provider.name}\" does not support decisions`\n return { provider, decisions: provider.decisions }\n }\n\n function modelKey(provider: Provider, model: string): string {\n return `${provider.name}/${model}`\n }\n\n function isAvailable(): boolean {\n const target = resolveTarget()\n if (typeof target === 'string')\n return false\n const model = config ? config.model ?? target.decisions.defaultModel : target.decisions.defaultModel\n if (unavailableModels.has(modelKey(target.provider, model)))\n return false\n return canDecide(target.decisions)\n }\n\n async function safeCallHook<K extends 'decision:start' | 'decision:end'>(name: K, ctx: Parameters<AgentHooks[K]>[0]): Promise<void> {\n try {\n await (hooks.callHook as (name: K, ctx: Parameters<AgentHooks[K]>[0]) => Promise<unknown> | void)(name, ctx)\n }\n catch (err) {\n debugLog(`${name} hook threw`, err)\n }\n }\n\n async function run(runId: string | undefined, runSignal: AbortSignal | undefined, request: DecisionRequest, journal: DecisionJournal | undefined, decisionId: string): Promise<DecisionOutcome> {\n const startedAt = Date.now()\n const questionNames = request && typeof request.questions === 'object' && request.questions ? Object.keys(request.questions) : []\n const inputKind = request?.input === undefined ? 'text' : decisionInputKind(request.input)\n const base: DecisionStartHookContext = { decisionId, ...(runId ? { runId } : {}), questionNames, inputKind, startedAt }\n\n const fail = async (reason: DecisionFailureReason, message: string, extra: Partial<DecisionFailure> = {}): Promise<DecisionFailure> => {\n const outcome: DecisionFailure = { ok: false, decisionId, reason, message, ...extra }\n if (reason === 'unavailable' && !warnedUnavailable) {\n warnedUnavailable = true\n debugLog('decisions unavailable', message)\n }\n const end: DecisionEndHookContext = {\n ...base,\n ...(extra.provider ? { provider: extra.provider } : {}),\n ...(extra.model ? { model: extra.model } : {}),\n durationMs: Date.now() - startedAt,\n ok: false,\n reason,\n message,\n }\n await safeCallHook('decision:end', end)\n return outcome\n }\n\n const target = resolveTarget()\n if (typeof target === 'string') {\n await safeCallHook('decision:start', base)\n return fail('unavailable', target)\n }\n const { provider, decisions } = target\n const model = request?.model ?? (config ? config.model : undefined) ?? decisions.defaultModel\n const started: DecisionStartHookContext = { ...base, provider: provider.name, model }\n await safeCallHook('decision:start', started)\n const who = { provider: provider.name, model }\n\n const problem = validateDecisionRequest(request?.input, request?.questions)\n if (problem)\n return fail('invalid', problem, who)\n if (unavailableModels.has(modelKey(provider, model)))\n return fail('unavailable', `Decision model \"${model}\" is unavailable on ${provider.name}`, who)\n // A journaled decision checks availability inside its step, so a replay\n // can't take another branch when a key is missing on replay.\n if (!journal) {\n let availability\n try {\n availability = decisions.availability()\n }\n catch (err) {\n availability = { available: false as const, reason: err instanceof Error ? err.message : String(err) }\n }\n if (!availability.available)\n return fail('unavailable', availability.reason, who)\n }\n\n const timeoutMs = request.timeoutMs ?? (config ? config.timeoutMs : undefined) ?? DEFAULT_DECISION_TIMEOUT_MS\n // setTimeout fires at once for anything outside (0, 2^31-1].\n if (typeof timeoutMs !== 'number' || !Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2 ** 31 - 1)\n return fail('invalid', `timeoutMs must be a number of milliseconds in (0, ${2 ** 31 - 1}]`, who)\n const timeoutController = new AbortController()\n const timer = setTimeout(() => timeoutController.abort(new DecisionTimeoutError(`Decision timed out after ${timeoutMs}ms`)), timeoutMs)\n const signals = [timeoutController.signal, runSignal, request.signal].filter((s): s is AbortSignal => s !== undefined)\n const signal = AbortSignal.any(signals)\n\n let response: ProviderDecisionResponse\n try {\n if (signal.aborted)\n throw abortError(signal)\n const providerRequest = { model, input: request.input, questions: request.questions }\n response = journal\n ? await journaledDecide(journal, decisions, providerRequest, signal)\n : await raceAbort(decisions.decide(providerRequest, signal), signal)\n }\n catch (err) {\n if (timeoutController.signal.aborted)\n return fail('timeout', `Decision timed out after ${timeoutMs}ms`, { ...who, error: asError(err) })\n if (signal.aborted)\n return fail('aborted', 'Decision was cancelled', { ...who, error: asError(err) })\n const classified = classifyDecisionError(err)\n if (classified.modelUnavailable)\n unavailableModels.add(modelKey(provider, model))\n return fail(classified.reason, classified.message, { ...who, error: asError(err) })\n }\n finally {\n clearTimeout(timer)\n }\n\n const answerProblem = validateDecisionAnswers(request.questions, response.answers)\n if (answerProblem)\n return fail('invalid', `Malformed decision response: ${answerProblem}`, who)\n\n const answers = Object.fromEntries(Object.keys(request.questions).map(name => [name, response.answers[name]]))\n const end: DecisionEndHookContext = {\n ...started,\n model: response.model || model,\n durationMs: Date.now() - startedAt,\n ok: true,\n usage: response.usage,\n answers,\n }\n await safeCallHook('decision:end', end)\n return {\n ok: true,\n decisionId,\n answers: answers as DecisionAnswers<DecisionQuestions>,\n usage: response.usage,\n provider: provider.name,\n model: response.model || model,\n ...(response.id ? { id: response.id } : {}),\n }\n }\n\n function forRun(runId: string | undefined, runSignal?: AbortSignal, journal?: DecisionJournal, newId: () => string = randomUUID): AgentDecide {\n const decide = async (request: DecisionRequest, opts?: { throw: true }): Promise<DecisionOutcome> => {\n const decisionId = `dec_${newId()}`\n let outcome: DecisionOutcome\n try {\n outcome = await run(runId, runSignal, request, journal, decisionId)\n }\n catch (err) {\n // Defensive: `run` handles every known failure; anything reaching here is a bug.\n outcome = { ok: false, decisionId, reason: 'error', message: asError(err).message, error: asError(err) }\n }\n if (opts?.throw && !outcome.ok)\n throw new DecisionError(outcome)\n return outcome\n }\n Object.defineProperty(decide, 'available', { get: isAvailable, enumerable: true })\n return decide as unknown as AgentDecide\n }\n\n return { forRun }\n}\n\nfunction asError(err: unknown): Error {\n return err instanceof Error ? err : new Error(String(err))\n}\n\n/** Reject as soon as `signal` aborts, even if the provider ignores it. */\nfunction raceAbort<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const onAbort = (): void => reject(abortError(signal))\n if (signal.aborted)\n return onAbort()\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (v) => {\n signal.removeEventListener('abort', onAbort)\n resolve(v)\n },\n (e) => {\n signal.removeEventListener('abort', onAbort)\n reject(e)\n },\n )\n })\n}\n\n/**\n * The provider call of a journaled decision, failures included: they are\n * recorded as plain JSON and rethrown, so a replayed decision sees the same\n * outcome and takes the same branch. A timeout or abort is recorded as such\n * even when the provider resolved anyway: the caller already gave up.\n */\nasync function journaledDecide(journal: DecisionJournal, decisions: ProviderDecisions, request: ProviderDecisionRequest, signal: AbortSignal): Promise<ProviderDecisionResponse> {\n const entry = await journal<JournaledDecision>(async () => {\n try {\n // Inside the step: a key present live but missing on replay must not change the outcome.\n const availability = decisions.availability()\n if (!availability.available)\n throw new DecisionUnavailableError(availability.reason)\n const response = await raceAbort(decisions.decide(request, signal), signal)\n return signal.aborted\n ? { ok: false, error: serializeDecisionError(abortError(signal)) }\n : { ok: true, response }\n }\n catch (err) {\n return { ok: false, error: serializeDecisionError(signal.aborted ? abortError(signal) : err) }\n }\n })\n if (!entry.ok)\n throw deserializeDecisionError(entry.error)\n return entry.response\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension-mark-BqKdEZwF.js","names":[],"sources":["../src/chat/extension-mark.ts"],"sourcesContent":["/**\n * The one mark of an extension, the same in every app: its own icon, else\n * the logo or icon the native catalog gives it, else the first letter of its\n * name. Pure and browser-safe (`zidane/chat/pure`).\n */\nimport { nativeExtensionByName } from './onboarding/native-extensions'\n\n/** What an app draws for an extension: an icon class, a Simple Icons slug, or a letter. */\nexport type ExtensionMark\n = | { kind: 'icon', gui: string }\n | { kind: 'brand', brand: string }\n | { kind: 'letter', letter: string }\n\n/** What {@link extensionMark} reads. */\nexport interface ExtensionMarkInput {\n /** The extension's id (its folder name). */\n id: string\n /** Its display name. Absent: the native catalog's label, else the id. */\n name?: string\n /** Its own icon (the definition's or the manifest's `icon`). */\n icon?: { gui?: string, tui?: string }\n /** The native catalog entry to read (`NATIVE_EXTENSIONS[].name`). Absent: the id. */\n nativeName?: string\n}\n\n/**\n * The mark of an extension: `icon.gui`, then the native catalog's `brand`,\n * then its `icon.gui`, then the first letter or digit of the display name.\n *\n * @param input - The extension.\n * @returns What to draw.\n * @example\n * ```ts\n * import { extensionMark } from 'zidane/chat/pure'\n *\n * extensionMark({ id: 'linear' }) // { kind: 'brand', brand: 'linear' }\n * extensionMark({ id: 'goal', icon: { gui: 'i-ph-flag' } }) // { kind: 'icon', gui: 'i-ph-flag' }\n * extensionMark({ id: 'my-tool', name: 'My tool' }) // { kind: 'letter', letter: 'M' }\n * ```\n */\nexport function extensionMark(input: ExtensionMarkInput): ExtensionMark {\n const own = input.icon?.gui?.trim()\n if (own)\n return { kind: 'icon', gui: own }\n const native = nativeExtensionByName(input.nativeName ?? input.id)\n if (native?.brand)\n return { kind: 'brand', brand: native.brand }\n const nativeIcon = native?.icon?.gui?.trim()\n if (nativeIcon)\n return { kind: 'icon', gui: nativeIcon }\n const name = input.name?.trim() || native?.label || input.id\n const first = Array.from(name).find(char => /[\\p{L}\\p{N}]/u.test(char))\n return { kind: 'letter', letter: (first ?? '?').toLocaleUpperCase() }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,cAAc,OAA0C;CACtE,MAAM,MAAM,MAAM,MAAM,KAAK,KAAK;CAClC,IAAI,KACF,OAAO;EAAE,MAAM;EAAQ,KAAK;CAAI;CAClC,MAAM,SAAS,sBAAsB,MAAM,cAAc,MAAM,EAAE;CACjE,IAAI,QAAQ,OACV,OAAO;EAAE,MAAM;EAAS,OAAO,OAAO;CAAM;CAC9C,MAAM,aAAa,QAAQ,MAAM,KAAK,KAAK;CAC3C,IAAI,YACF,OAAO;EAAE,MAAM;EAAQ,KAAK;CAAW;CACzC,MAAM,OAAO,MAAM,MAAM,KAAK,KAAK,QAAQ,SAAS,MAAM;CAE1D,OAAO;EAAE,MAAM;EAAU,SADX,MAAM,KAAK,IAAI,CAAC,CAAC,MAAK,SAAQ,gBAAgB,KAAK,IAAI,CAC/B,KAAK,IAAA,CAAK,kBAAkB;CAAE;AACtE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extensions-client-D8tEAcMw.d.ts","names":[],"sources":["../src/ipc/extensions-client.ts"],"mappings":";;;;KAwBK,SAAS,UAAU,sBAAsB,QAAQ;EAAc,MAAM;;;UAGzD;;;;;;;;;EASf,SAAS,SAAS,eAAe;IAAO;IAAkB;IAAqB;IAAoB,QAAQ;IAAa,WAAW,aAAa,mBAAmB;QAA6B;;EAEhM,SAAS,SAAS,8BAA8B;;;UAIjC;;;;;;EAMf,MAAM,aAAa,kBAAkB,gBAAgB,iBAAiB;IAAS;IAAc,SAAS;QAAkB,QAAQ,QAAQ;;EAExI,aAAa,WAAW,OAAO;;EAE/B;IACE,OAAO,gBAAgB,QAAQ;IAC/B,WAAW,WAAW;;;EAGxB;;IAEE,OAAO,gBAAgB,QAAQ;;IAE/B,SAAS,aAAa,SAAS,oBAAoB;;IAEnD,WAAW,WAAW,aAAa,QAAQ;MAAa;;;;;;IAKxD,iBAAiB,WAAW;MAAU;MAAa;MAAqB;MAAiB;;;;EAG3F,WAAW,MAAM,qBAAqB;;EAEtC,QAAQ,QAAQ;;EAEhB;;IAEE,OAAO,aAAa,KAAK,wBAAwB,QAAQ;MAAoB;;;IAE7E,MAAM,aAAa,KAAK,qBAAqB,MAAM,aAAa,aAAa,OAAO,qBAAqB,QAAQ;;IAEjH,WAAW,WAAW,QAAQ;;;EAGhC;;IAEE,MAAM,aAAa,uBAAuB,QAAQ;;IAElD,MAAM,QAAQ,sBAAsB;;;;;;IAMpC,WAAW,WAAW;;;EAGxB;;IAEE,OAAO,aAAa,uBAAuB,QAAQ;;IAEnD,MAAM,aAAa,YAAY;MAAS;MAAe;UAAyB;;IAEhF,WAAW,aAAa,cAAc;MAAS;MAAmB;UAAyB;;IAE3F,UAAU,mBAAmB;;IAE7B,SAAS,aAAa,uBAAuB,QAAQ;;IAErD,WAAW,WAAW,aAAa;MAAW;;;;EAGhD;;IAEE,OAAO,gBAAgB,QAAQ;;IAE/B,aAAa,aAAa,uBAAuB,aAAa,sBAAsB,QAAQ;;IAE5F,QAAQ,aAAa,uBAAuB,kBAAkB,SAAS,MAAM,qBAAqB,4BAA4B,QAAQ;;IAEtI,YAAY,gBAAgB,iBAAiB,8BAA8B;;IAE3E,aAAa,aAAa,uBAAuB,qBAAqB;;IAEtE,aAAa,aAAa,uBAAuB,oBAAoB;;IAErE,WAAW,WAAW;;;EAGxB;;;;;IAKE,OAAO,aAAa,MAAM,KAAK,2BAA2B;MAAU;;;;EAGtE,oBAAoB,aAAa,MAAM,gBAAgB,QAAQ;;EAE/D;;IAEE,SAAS,mBAAmB,QAAQ;;IAEpC,eAAe,QAAQ,yCAAyC,QAAQ;;;;;;;UAQ3D;;EAEf,UAAU,UAAU,eAAe,QAAQ,GAAG,QAAQ,UAAU,OAAO,QAAQ,UAAU;;EAEzF,WAAW,WAAW,QAAQ;;;;;;;;iBAqBhB,uBAAuB,QAAQ,sBAAsB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-BHMs9jsN.js","names":[],"sources":["../src/codemode/runtime/host.ts"],"sourcesContent":["import type {\n CodemodeCall,\n CodemodeCallStatus,\n CodemodeDeterminism,\n CodemodeError,\n CodemodeExecuteOptions,\n CodemodeOutputItem,\n CodemodeResult,\n CodemodeSandboxOptions,\n CodemodeStoreWrites,\n CodemodeTool,\n} from '../types'\nimport type { CodemodeWasmModule } from '../wasm'\nimport type { CallMessage, HostToWorkerMessage, WorkerData, WorkerToHostMessage } from './protocol'\nimport { Worker } from 'node:worker_threads'\nimport { stringArgumentOf } from '../declarations'\nimport { toCodemodeIdentifier } from '../identifier'\nimport { codemodeSandboxPaths } from '../sandbox-paths'\nimport { CodemodeValue } from '../value'\nimport { loadQuickJSWasm } from '../wasm'\nimport { isWorkerToHostMessage } from './protocol'\n\nconst DEFAULT_TIMEOUT_MS = 300_000\nconst IDENTIFIER = /^[A-Z_$][\\w$]*$/i\nconst RESERVED_GLOBALS: ReadonlySet<string> = new Set([\n 'tools',\n 'ALL_TOOLS',\n 'console',\n 'text',\n 'image',\n 'exit',\n 'globalThis',\n 'store',\n 'load',\n])\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction serializeStore(store: Readonly<Record<string, unknown>> | undefined): Record<string, string> {\n const serialized: Record<string, string> = {}\n for (const [key, value] of Object.entries(store ?? {})) {\n const json = JSON.stringify(value)\n if (json !== undefined)\n serialized[key] = json\n }\n return serialized\n}\n\n/**\n * The prelude that serializes values for the host runs in the same VM as the script, so a script\n * that patches built-ins (for example `Array.prototype.toJSON`) can make it send malformed data.\n * Payloads that do not decode throw this error, and the execution fails as a sandbox error.\n */\nclass BridgeError extends Error {}\n\nfunction parseBridgeJson(json: string, what: string): unknown {\n try {\n return JSON.parse(json)\n }\n catch {\n throw new BridgeError(`${what} is not valid JSON`)\n }\n}\n\nfunction parseStoreWrites(json: string): CodemodeStoreWrites {\n const entries = parseBridgeJson(json, 'store writes')\n if (!Array.isArray(entries))\n throw new BridgeError('store writes are not an array')\n const writes: CodemodeStoreWrites = { set: {}, delete: [] }\n for (const entry of entries) {\n if (\n !Array.isArray(entry)\n || typeof entry[0] !== 'string'\n || (entry.length === 2 ? typeof entry[1] !== 'string' : entry.length !== 1)\n ) {\n throw new BridgeError('store writes contain a malformed entry')\n }\n const [key, value] = entry as [string, string?]\n if (value === undefined)\n writes.delete.push(key)\n else\n writes.set[key] = parseBridgeJson(value, `store value for ${JSON.stringify(key)}`)\n }\n return writes\n}\n\nfunction parseScriptError(json: string): CodemodeError {\n const parsed = parseBridgeJson(json, 'script error')\n if (typeof parsed !== 'object' || parsed === null)\n throw new BridgeError('script error is not an object')\n const { name, message, stack } = parsed as Record<string, unknown>\n if (\n typeof message !== 'string'\n || (name !== undefined && typeof name !== 'string')\n || (stack !== undefined && typeof stack !== 'string')\n ) {\n throw new BridgeError('script error is malformed')\n }\n return { kind: 'script', name, message, stack }\n}\n\n/** Characters the worker's wrapper puts before the script on its first line: `(async () => {`. */\nconst WRAPPER_PREFIX_LENGTH = '(async () => {'.length\n\n/**\n * The script line a `codemode.js:<line>:<col>` frame points at, with a caret\n * under the column. The wrapper shares line 1 with the script, so line\n * numbers are exact and line 1's column is shifted by the prefix.\n */\nexport function scriptErrorExcerpt(code: string, stack: string | undefined): string | undefined {\n const match = stack?.match(/codemode\\.js:(\\d+):(\\d+)/)\n if (!match)\n return undefined\n const line = Number(match[1])\n const column = Math.max(1, Number(match[2]) - (line === 1 ? WRAPPER_PREFIX_LENGTH : 0))\n const source = code.split('\\n')[line - 1]\n if (source === undefined)\n return undefined\n const gutter = `${line} | `\n // Long lines: a window around the column, so the caret stays on screen.\n const start = source.length > 160 ? Math.max(0, column - 80) : 0\n const shown = start > 0 ? `…${source.slice(start, start + 160)}` : source.slice(0, 160)\n const caretAt = column - 1 - start + (start > 0 ? 1 : 0)\n return `${gutter}${shown}\\n${' '.repeat(gutter.length + Math.max(0, caretAt))}^`\n}\n\nfunction defaultWorkerUrl(): URL {\n // A compiled executable embeds the worker elsewhere (`sandbox-paths.ts`). Source (tests,\n // `bun run`) sits next to `worker.ts`; the published dist ships it as the sibling entry\n // `codemode-worker.js`.\n const configured = codemodeSandboxPaths().workerUrl\n if (configured)\n return configured\n return new URL(import.meta.url.endsWith('.ts') ? './worker.ts' : './codemode-worker.js', import.meta.url)\n}\n\ninterface PendingCall {\n record: CodemodeCall | undefined\n startedAt: number\n controller: AbortController\n}\n\ninterface ExecutionOptions {\n code: string\n tools: ReadonlyMap<string, CodemodeTool>\n globals: ReadonlyMap<string, CodemodeTool>\n timeoutMs: number\n signal: AbortSignal | undefined\n memoryLimitBytes: number | undefined\n store: Record<string, string>\n wasm: Promise<CodemodeWasmModule>\n workerUrl: string | URL\n determinism: CodemodeDeterminism | undefined\n toolHints: Record<string, string> | undefined\n shortcuts: Record<string, string> | undefined\n}\n\n/**\n * One script run in its own worker and QuickJS VM. A fresh worker per run keeps\n * termination simple: a runaway script, including one that only spins the\n * microtask queue, is killed with `terminate()` and cannot poison a later run.\n */\nclass Execution {\n readonly promise: Promise<CodemodeResult>\n private resolveResult!: (result: CodemodeResult) => void\n private worker: Worker | undefined\n private readonly interrupt = new SharedArrayBuffer(4)\n private readonly tools: ReadonlyMap<string, CodemodeTool>\n private readonly globals: ReadonlyMap<string, CodemodeTool>\n private readonly signal: AbortSignal | undefined\n private readonly timer: ReturnType<typeof setTimeout> | undefined\n private readonly output: CodemodeOutputItem[] = []\n private readonly calls: CodemodeCall[] = []\n private readonly pending = new Map<number, PendingCall>()\n private readonly code: string\n private finished = false\n\n constructor(options: ExecutionOptions) {\n this.promise = new Promise<CodemodeResult>((resolve) => {\n this.resolveResult = resolve\n })\n this.tools = options.tools\n this.globals = options.globals\n this.signal = options.signal\n this.code = options.code\n\n if (Number.isFinite(options.timeoutMs)) {\n this.timer = setTimeout(() => {\n this.finish({ kind: 'timeout', message: `Execution timed out after ${options.timeoutMs} ms` })\n }, options.timeoutMs)\n }\n\n if (options.signal) {\n if (options.signal.aborted)\n this.onAbort()\n else\n options.signal.addEventListener('abort', this.onAbort, { once: true })\n }\n\n options.wasm.then(\n wasm => this.start(options, wasm),\n (error: unknown) => {\n this.finish({ kind: 'sandbox', message: `Failed to load QuickJS: ${errorMessage(error)}` })\n },\n )\n }\n\n abort(message: string): Promise<CodemodeResult> {\n this.finish({ kind: 'aborted', message })\n return this.promise\n }\n\n private start(options: ExecutionOptions, wasm: CodemodeWasmModule): void {\n if (this.finished)\n return\n const workerData: WorkerData = {\n code: options.code,\n tools: [...options.tools.values()].map((tool) => {\n const stringArg = stringArgumentOf(tool.inputSchema)\n return {\n name: tool.name,\n jsName: toCodemodeIdentifier(tool.name),\n description: tool.description ?? '',\n ...(stringArg !== undefined ? { stringArg } : {}),\n }\n }),\n globals: [...options.globals.values()].map(global => ({\n name: global.name,\n spread: global.spread === true,\n })),\n wasm,\n memoryLimitBytes: options.memoryLimitBytes,\n store: options.store,\n interrupt: this.interrupt,\n determinism: options.determinism,\n ...(options.toolHints ? { toolHints: options.toolHints } : {}),\n ...(options.shortcuts ? { shortcuts: options.shortcuts } : {}),\n }\n let worker: Worker\n try {\n worker = new Worker(options.workerUrl, { workerData })\n }\n catch (error) {\n this.finish({ kind: 'sandbox', message: `Failed to start worker: ${errorMessage(error)}` })\n return\n }\n this.worker = worker\n worker.on('message', (message: unknown) => {\n // An exception here would be uncaught in the host process and leave the execution unsettled.\n try {\n this.handleMessage(message)\n }\n catch (error) {\n this.finish({\n kind: 'sandbox',\n message:\n error instanceof BridgeError\n ? `Sandbox bridge broken: ${error.message}. The script may have modified built-ins such as a prototype's toJSON.`\n : `Sandbox host failed: ${errorMessage(error)}`,\n })\n }\n })\n worker.on('error', (error: unknown) => {\n this.finish({\n kind: 'sandbox',\n name: error instanceof Error ? error.name : undefined,\n message: errorMessage(error),\n })\n })\n worker.on('exit', (code) => {\n this.finish({ kind: 'sandbox', message: `Worker exited with code ${code} before the script settled` })\n })\n }\n\n private readonly onAbort = (): void => {\n const reason: unknown = this.signal?.reason\n this.finish({ kind: 'aborted', message: reason instanceof Error ? reason.message : 'Execution aborted' })\n }\n\n private post(message: HostToWorkerMessage): void {\n this.worker?.postMessage(message)\n }\n\n private handleMessage(message: unknown): void {\n if (this.finished)\n return\n if (!isWorkerToHostMessage(message))\n throw new BridgeError('unknown message from the worker')\n switch (message.type) {\n case 'output':\n this.output.push(message.item)\n break\n case 'calls':\n if (!Array.isArray(message.calls))\n throw new BridgeError('calls is not an array')\n // Started synchronously, in issue order: a tool that groups the calls\n // of one turn (a durable host batching them) sees the whole group.\n for (const call of message.calls) {\n if (this.pending.has(call.id))\n throw new BridgeError(`duplicate call id ${call.id}`)\n void this.handleCall(call)\n }\n break\n case 'done':\n this.handleDone(message)\n break\n case 'crash':\n this.finish({ kind: 'sandbox', message: message.message })\n break\n }\n }\n\n private handleDone(message: Extract<WorkerToHostMessage, { type: 'done' }>): void {\n // Decode everything before finish(), which must not throw once it starts.\n if (!message.ok) {\n const error = parseScriptError(message.error)\n const excerpt = scriptErrorExcerpt(this.code, error.stack)\n this.finish(excerpt ? { ...error, excerpt } : error)\n return\n }\n const value = message.value === undefined ? undefined : parseBridgeJson(message.value, 'return value')\n this.finish(undefined, value, parseStoreWrites(message.writes))\n }\n\n private async handleCall(message: CallMessage): Promise<void> {\n const { id, name } = message\n const isTool = message.target === 'tool'\n const record: CodemodeCall | undefined = isTool ? { name, seq: id, status: 'cancelled', durationMs: 0 } : undefined\n if (record)\n this.calls.push(record)\n const pending: PendingCall = { record, startedAt: performance.now(), controller: new AbortController() }\n this.pending.set(id, pending)\n\n let status: CodemodeCallStatus\n let reply: HostToWorkerMessage\n try {\n const tool = (isTool ? this.tools : this.globals).get(name)\n if (!tool)\n throw new Error(`Unknown ${isTool ? 'tool' : 'global'} \"${name}\"`)\n const args: unknown = message.args === undefined ? undefined : JSON.parse(message.args)\n const value = await tool.execute(args, { signal: pending.controller.signal, seq: id })\n reply = CodemodeValue.is(value)\n ? { type: 'result', id, ok: true, payload: value.value === undefined ? undefined : JSON.stringify(value.value), text: value.text }\n : { type: 'result', id, ok: true, payload: value === undefined ? undefined : JSON.stringify(value) }\n status = 'ok'\n }\n catch (error) {\n reply = { type: 'result', id, ok: false, payload: errorMessage(error) }\n status = 'error'\n }\n\n // Already cancelled by finish(): the record keeps \"cancelled\" and the\n // worker is gone or going.\n if (!this.pending.delete(id))\n return\n if (record) {\n record.status = status\n record.durationMs = performance.now() - pending.startedAt\n }\n this.post(reply)\n }\n\n private finish(error: CodemodeError | undefined, value?: unknown, writes?: CodemodeStoreWrites): void {\n if (this.finished)\n return\n this.finished = true\n clearTimeout(this.timer)\n this.signal?.removeEventListener('abort', this.onAbort)\n\n const now = performance.now()\n for (const pending of this.pending.values()) {\n if (pending.record)\n pending.record.durationMs = now - pending.startedAt\n pending.controller.abort()\n }\n this.pending.clear()\n\n const result: CodemodeResult = error\n ? { ok: false, error, output: this.output, calls: this.calls }\n : {\n ok: true,\n value,\n output: this.output,\n calls: this.calls,\n storeWrites: writes ?? { set: {}, delete: [] },\n }\n if (!this.worker) {\n this.resolveResult(result)\n return\n }\n Atomics.store(new Int32Array(this.interrupt), 0, 1)\n this.worker\n .terminate()\n .catch(() => undefined)\n .then(() => this.resolveResult(result))\n }\n}\n\n/**\n * Runs JavaScript in a QuickJS VM (a separate wasm instance) inside a worker\n * thread. The script sees `tools.<name>(args)` for every registered tool, `ALL_TOOLS`,\n * the output helpers `text`, `image`, `exit`, and `console.*`, `store`/`load`, and the\n * configured globals; nothing else (no timers, `fetch`, `process`, `require`, modules).\n *\n * Each `execute()` gets its own worker and VM; the sandbox only holds the tool\n * table and defaults. `close()` aborts in-flight executions.\n *\n * @example\n * ```ts\n * import { CodemodeSandbox } from 'zidane/codemode'\n *\n * const sandbox = new CodemodeSandbox({\n * tools: [{ name: 'add', execute: args => (args as { a: number, b: number }).a + (args as { a: number, b: number }).b }],\n * })\n * const result = await sandbox.execute('return await tools.add({ a: 1, b: 2 })')\n * if (result.ok)\n * console.log(result.value)\n * ```\n */\nexport class CodemodeSandbox {\n private readonly toolsByName = new Map<string, CodemodeTool>()\n private readonly globalsByName = new Map<string, CodemodeTool>()\n private readonly timeoutMs: number\n private readonly memoryLimitBytes: number | undefined\n private readonly wasm: CodemodeWasmModule | Promise<CodemodeWasmModule> | undefined\n private readonly workerUrl: string | URL\n private readonly toolHints: Record<string, string> | undefined\n private readonly shortcuts: Record<string, string> | undefined\n private readonly running = new Set<Execution>()\n private closed = false\n\n /**\n * Creates a sandbox with its tools, globals and defaults. Throws when a global or shortcut name is invalid, reserved or duplicated.\n *\n * @param options - Tools, globals, timeout, memory limit and worker settings.\n */\n constructor(options: CodemodeSandboxOptions = {}) {\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n this.memoryLimitBytes = options.memoryLimitBytes\n this.wasm = options.wasm\n this.workerUrl = options.workerUrl ?? defaultWorkerUrl()\n this.toolHints = options.toolHints\n for (const tool of options.tools ?? [])\n this.registerTool(tool)\n const namespaces = new Set<string>()\n for (const global of options.globals ?? []) {\n const parts = global.name.split('.')\n if (parts.length > 2 || !parts.every(part => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0]!))\n throw new Error(`Invalid global name \"${global.name}\"`)\n if (this.globalsByName.has(global.name))\n throw new Error(`Global \"${global.name}\" is already registered`)\n if (parts.length === 2)\n namespaces.add(parts[0]!)\n this.globalsByName.set(global.name, global)\n }\n for (const name of namespaces) {\n if (this.globalsByName.has(name))\n throw new Error(`Global \"${name}\" conflicts with the namespace \"${name}\"`)\n }\n for (const name of Object.keys(options.shortcuts ?? {})) {\n if (!IDENTIFIER.test(name) || RESERVED_GLOBALS.has(name) || this.globalsByName.has(name) || namespaces.has(name))\n throw new Error(`Invalid shortcut name \"${name}\"`)\n }\n this.shortcuts = options.shortcuts\n }\n\n /**\n * Throws if a tool with the same name is already registered.\n * @param tool - Tool to add to the `tools` table.\n */\n registerTool(tool: CodemodeTool): void {\n if (this.toolsByName.has(tool.name))\n throw new Error(`Tool \"${tool.name}\" is already registered`)\n this.toolsByName.set(tool.name, tool)\n }\n\n /**\n * Removes a tool by name. Returns `true` when it was registered.\n *\n * @param name - Name of the tool to remove.\n */\n unregisterTool(name: string): boolean {\n return this.toolsByName.delete(name)\n }\n\n /** Tools currently registered. */\n get tools(): CodemodeTool[] {\n return [...this.toolsByName.values()]\n }\n\n /** Globals the script can call as top-level functions. */\n get globals(): CodemodeTool[] {\n return [...this.globalsByName.values()]\n }\n\n /**\n * `code` is an async function body: `return` and top-level `await` work.\n * Script failures come back as `{ ok: false }`. The promise rejects only when the sandbox is closed.\n * The script can use `store(key, value)` and `load(key)` on `options.store`.\n *\n * @param code - Script source, run as an async function body.\n * @param options - Per-execution signal, timeout, `store` values and determinism settings.\n */\n execute(code: string, options: CodemodeExecuteOptions = {}): Promise<CodemodeResult> {\n if (this.closed)\n return Promise.reject(new Error('Sandbox is closed'))\n const execution = new Execution({\n code,\n tools: new Map(this.toolsByName),\n globals: this.globalsByName,\n timeoutMs: options.timeoutMs ?? this.timeoutMs,\n signal: options.signal,\n memoryLimitBytes: this.memoryLimitBytes,\n store: serializeStore(options.store),\n wasm: this.wasm === undefined ? loadQuickJSWasm() : Promise.resolve(this.wasm),\n workerUrl: this.workerUrl,\n determinism: options.determinism,\n toolHints: this.toolHints,\n shortcuts: this.shortcuts,\n })\n this.running.add(execution)\n return execution.promise.finally(() => this.running.delete(execution))\n }\n\n /** Aborts in-flight executions (they resolve with `kind: \"aborted\"`) and rejects new ones. */\n async close(): Promise<void> {\n this.closed = true\n await Promise.all([...this.running].map(execution => execution.abort('Sandbox closed')))\n }\n}\n"],"mappings":"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"}