activeclaw 2026.2.12 → 2026.2.13

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 (364) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/{accounts-DbzMEfKN.js → accounts-DCDeFTra.js} +2 -2
  3. package/dist/{accounts-DimKrt7j.js → accounts-DeqIQjo1.js} +2 -2
  4. package/dist/{acp-cli-Cs1ai4XO.js → acp-cli-CeYI4XRd.js} +15 -16
  5. package/dist/{acp-cli-oV2dodPg.js → acp-cli-rNbGXICg.js} +14 -15
  6. package/dist/{agent-BndgzkUe.js → agent-BvNJF5QL.js} +19 -16
  7. package/dist/{agent-DZvDwqnd.js → agent-CyMxTyrG.js} +20 -17
  8. package/dist/{agent-scope-rXQ7WARN.js → agent-scope-BIEhVP4_.js} +1 -1
  9. package/dist/{agent-scope---6LLHj0.js → agent-scope-CQCus0rI.js} +2 -2
  10. package/dist/{agent-scope-RCSw6gHy.js → agent-scope-CsRbLH4l.js} +3 -3
  11. package/dist/{agent-scope-CN8DM4Xb.js → agent-scope-DPIFau3f.js} +1 -1
  12. package/dist/{audio-preflight-SZRntkxo.js → audio-preflight-BU8W7uxc.js} +10 -10
  13. package/dist/{audio-preflight-ClVNINDs.js → audio-preflight-CGsumMzb.js} +10 -10
  14. package/dist/{audio-preflight-txAP3v-C.js → audio-preflight-SLmkJI6-.js} +22 -22
  15. package/dist/{audio-preflight-BP6s-UPp.js → audio-preflight-jZc5mFCZ.js} +23 -23
  16. package/dist/{audit-CQzrm61N.js → audit-Dmww_503.js} +70 -18
  17. package/dist/{audit-DMH3CSXY.js → audit-wPu26VMb.js} +72 -20
  18. package/dist/{tailscale-DU6DgqVy.js → auth-9x3lqfIY.js} +208 -3
  19. package/dist/{tailscale-DHfcfRCx.js → auth-CQNl_IaI.js} +190 -3
  20. package/dist/{auth-health-BB3e3OmN.js → auth-health-C4L4FGBA.js} +1 -1
  21. package/dist/{auth-health-zZ9dnQGC.js → auth-health-j6epgQbq.js} +1 -1
  22. package/dist/{auth-profiles-CcJ3hrog.js → auth-profiles-ByNs3eEm.js} +60 -22
  23. package/dist/build-info.json +3 -3
  24. package/dist/bundled/boot-md/handler.js +19 -16
  25. package/dist/bundled/session-memory/handler.js +16 -15
  26. package/dist/{call-Yxns4CVq.js → call-DVYCIV8m.js} +5 -5
  27. package/dist/{call-C9az806y.js → call-SolyGS1r.js} +4 -4
  28. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  29. package/dist/{channel-options-CjXPwMWu.js → channel-options-BwC2yQcR.js} +4 -4
  30. package/dist/{channel-options-CX4iYQfR.js → channel-options-Cq9BVDkP.js} +7 -7
  31. package/dist/{channel-selection-BoQ7GurB.js → channel-selection-D4D6ImhN.js} +2 -2
  32. package/dist/{channel-selection-C78IwbD-.js → channel-selection-MZAHm4U8.js} +2 -2
  33. package/dist/{channels-cli-DUHsmX3q.js → channels-cli-9Dsk9Qm7.js} +53 -51
  34. package/dist/{channels-cli-BXMQPB4x.js → channels-cli-BJUppQll.js} +52 -50
  35. package/dist/{channels-status-issues-Ca9--azp.js → channels-status-issues-D7GSV1GS.js} +1 -1
  36. package/dist/{channels-status-issues-CbULFg2X.js → channels-status-issues-DDAWeT-6.js} +1 -1
  37. package/dist/{chrome-svgmQ8T_.js → chrome-BfB6JdKF.js} +2 -1
  38. package/dist/{chrome-juQxt0zf.js → chrome-Cvr-57lg.js} +4 -3
  39. package/dist/{chrome-BCPPeLQ6.js → chrome-DL0avO8n.js} +2 -1
  40. package/dist/{chrome-yIKmOzCO.js → chrome-foEwx3lN.js} +5 -4
  41. package/dist/{clack-prompter-Dmvcu3gn.js → clack-prompter-Bz3Mmcl-.js} +5 -5
  42. package/dist/{clack-prompter-DuBVnTKy.js → clack-prompter-ChCGXfyt.js} +4 -4
  43. package/dist/cli/daemon-cli.js +1 -1
  44. package/dist/{cli-FdxAcu_y.js → cli-ZR9ugUBX.js} +42 -40
  45. package/dist/{cli-By331Q9f.js → cli-miPe4Ujz.js} +42 -40
  46. package/dist/{client-B0_GiCjB.js → client-BrYfyoDK.js} +52 -3
  47. package/dist/{client-D7wrC1Ug.js → client-CTwXnRl7.js} +53 -4
  48. package/dist/{command-format-ayFsmwwz.js → command-format-Bxe0mWee.js} +1 -1
  49. package/dist/{command-options-BSDiKuyX.js → command-options-BvgxzPbK.js} +4 -4
  50. package/dist/{commands-BG25qku5.js → commands-BX_OIIVR.js} +4 -4
  51. package/dist/{completion-cli-C4zxjkC1.js → completion-cli-CR77-jyv.js} +3 -3
  52. package/dist/{completion-cli-DECEgBWR.js → completion-cli-DnjpxAag.js} +29 -29
  53. package/dist/{config-B7sno9eI.js → config-Bdhomfei.js} +15 -6
  54. package/dist/{config-BuF7vm-v.js → config-BvMsmctM.js} +13 -4
  55. package/dist/{config-D50SQVar.js → config-QYrbd7x7.js} +13 -4
  56. package/dist/{config-DH9TLUNc.js → config-aFQssWKX.js} +15 -6
  57. package/dist/{config-guard-DPxxY1iw.js → config-guard-CljaSxJd.js} +39 -39
  58. package/dist/{configure-BZQ9uSVX.js → configure-BXLiucXo.js} +19 -19
  59. package/dist/{configure-Cg5IKSUy.js → configure-BYPqXzGZ.js} +19 -19
  60. package/dist/control-auth-8Cf4WXpR.js +54 -0
  61. package/dist/control-auth-DBCu3qyv.js +54 -0
  62. package/dist/{control-service-CBlMVTRu.js → control-service-B5KnPqGP.js} +11 -5
  63. package/dist/{control-service-B2er20Ke.js → control-service-DKnttEus.js} +10 -4
  64. package/dist/{cron-cli-B2Zwhy_r.js → cron-cli-D7BRjDv2.js} +17 -17
  65. package/dist/{cron-cli-EaRUVd0p.js → cron-cli-z1zk_FXQ.js} +16 -16
  66. package/dist/{daemon-cli-CVNzObIF.js → daemon-cli-BDkU2ocb.js} +18 -18
  67. package/dist/{daemon-cli-DF6Rxjy6.js → daemon-cli-cNSF93-v.js} +19 -19
  68. package/dist/{daemon-runtime-BHF5NjQ7.js → daemon-runtime-B0tg_LsX.js} +2 -2
  69. package/dist/{daemon-runtime-B05PME1z.js → daemon-runtime-Bsjeut6m.js} +3 -3
  70. package/dist/{deliver-DzcxEcza.js → deliver-CIU9Npgs.js} +306 -12
  71. package/dist/{deliver-COf5XFo_.js → deliver-DYYCo1G7.js} +302 -8
  72. package/dist/{deliver-B1jsU2r7.js → deliver-LsxKETro.js} +306 -12
  73. package/dist/{deliver-CLwC284e.js → deliver-xUU3mGHo.js} +302 -8
  74. package/dist/{deps-Cva7QM_t.js → deps-QSwGcoNZ.js} +2 -2
  75. package/dist/{deps-B6602Wid.js → deps-lAAA2zYI.js} +2 -2
  76. package/dist/{devices-cli-DPg_4aW8.js → devices-cli-BG3-2oqt.js} +13 -13
  77. package/dist/{devices-cli-D8K3hZR5.js → devices-cli-VIQtOvt_.js} +13 -13
  78. package/dist/{directory-cli-OGBSVKAZ.js → directory-cli-BCJwjVC0.js} +15 -15
  79. package/dist/{directory-cli-Bn47fFX7.js → directory-cli-jYzZ02gk.js} +14 -14
  80. package/dist/{dispatcher-BHsNwFe-.js → dispatcher-DY51b-Zc.js} +2 -2
  81. package/dist/{dns-cli-DmTHXgwU.js → dns-cli-DHIiMJjS.js} +11 -11
  82. package/dist/{dns-cli-kk2rysJh.js → dns-cli-pZlv87Ib.js} +11 -11
  83. package/dist/{docs-cli-CB77CeM4.js → docs-cli-2JDiwfzP.js} +7 -7
  84. package/dist/{docs-cli-DUcyw0X0.js → docs-cli-BhkYqoIQ.js} +6 -6
  85. package/dist/{doctor-DwqdkfPa.js → doctor-Bf8EhNtA.js} +33 -33
  86. package/dist/{doctor-BZfxDGUg.js → doctor-sYG5V4Co.js} +32 -32
  87. package/dist/entry.js +36 -14
  88. package/dist/{env-DE9xvYOL.js → env-ONzUVAG2.js} +1 -1
  89. package/dist/{exec-4WHuOniw.js → exec-B8lXct-k.js} +31 -13
  90. package/dist/{exec-B8JKbXKW.js → exec-CACT5OAW.js} +1 -1
  91. package/dist/{exec-D12IZYtJ.js → exec-CJFFoM7H.js} +31 -13
  92. package/dist/{exec-DXtR2fhb.js → exec-YIosokWE.js} +1 -1
  93. package/dist/{exec-approvals-cli-GizapOX5.js → exec-approvals-cli-7LH0lwhO.js} +19 -19
  94. package/dist/{exec-approvals-cli-BWO0Rs-a.js → exec-approvals-cli-apGnQbpj.js} +19 -19
  95. package/dist/extensionAPI.js +1108 -661
  96. package/dist/{fetch-CqZP8jwB.js → fetch-DmiOpALK.js} +5 -3
  97. package/dist/{fetch-timeout-B2KlHXi3.js → fetch-timeout-BEtUjM1S.js} +5 -3
  98. package/dist/{fetch-timeout-ohY5QmsW.js → fetch-timeout-DEoXG_SF.js} +5 -3
  99. package/dist/{fetch-timeout-4UKsdtE1.js → fetch-timeout-DTK9vxex.js} +5 -3
  100. package/dist/{gateway-cli-Bbd1Xbsc.js → gateway-cli-DUdYxlZS.js} +315 -103
  101. package/dist/{gateway-cli-PR1S0BTe.js → gateway-cli-DbvWmE-9.js} +314 -102
  102. package/dist/{gateway-rpc-8gue7Qjt.js → gateway-rpc-BByb2Snz.js} +3 -3
  103. package/dist/{gateway-rpc-DjuxyOm-.js → gateway-rpc-wXSCUZXj.js} +3 -3
  104. package/dist/{github-copilot-auth-B3chCDfc.js → github-copilot-auth-D7ewvpMd.js} +16 -8
  105. package/dist/{github-copilot-auth-Cm2SB8Qf.js → github-copilot-auth-DDispnyz.js} +16 -8
  106. package/dist/{github-copilot-token-SLWintYd.js → github-copilot-token-Cfs0Wxr8.js} +1 -1
  107. package/dist/{gmail-setup-utils-Cgh0ptgA.js → gmail-setup-utils-Cfns8TQx.js} +3 -3
  108. package/dist/{gmail-setup-utils-WDyf1gTU.js → gmail-setup-utils-DJb-_5kO.js} +4 -4
  109. package/dist/{health-format-C0C_Apce.js → health-format-KGPokKJH.js} +68 -28
  110. package/dist/{health-format-gLMfE2wf.js → health-format-LZDxu3rv.js} +67 -27
  111. package/dist/{help-format-5iAL_46a.js → help-format-C48TXngO.js} +1 -1
  112. package/dist/{help-format-DUy1KRxq.js → help-format-R5fLToDw.js} +1 -1
  113. package/dist/{hooks-cli-CEN1h1ya.js → hooks-cli-CT8JCRkH.js} +46 -44
  114. package/dist/{hooks-cli-DrchIqSi.js → hooks-cli-S1MKumJO.js} +47 -45
  115. package/dist/{hooks-status-Cgy6AtQk.js → hooks-status-Cw0xD8Lt.js} +3 -3
  116. package/dist/{hooks-status--xVLpAXz.js → hooks-status-D9MhwHRp.js} +3 -3
  117. package/dist/{image-Dkawt9Kg.js → image-Brk1sJbw.js} +4 -4
  118. package/dist/{image-DI9s9eEx.js → image-C4Nn2p3e.js} +5 -5
  119. package/dist/{image-LxFvu0wL.js → image-DgtfXMcX.js} +5 -5
  120. package/dist/{image-B4mDPdyz.js → image-RKwc3fsL.js} +4 -4
  121. package/dist/index.js +83 -83
  122. package/dist/{installs-NS0VMPN7.js → installs-CrLcWYHe.js} +4 -4
  123. package/dist/{installs-DA-eSN1B.js → installs-DscWb9b9.js} +5 -5
  124. package/dist/{links-CV4oki2u.js → links-B8LAzWwg.js} +1 -1
  125. package/dist/{links-7M-j83As.js → links-Eax1UO3w.js} +1 -1
  126. package/dist/llm-slug-generator.js +15 -15
  127. package/dist/{loader-Caow9TPA.js → loader-KjT074JR.js} +1105 -762
  128. package/dist/{logging-CeHn2itV.js → logging-BAyPwvdH.js} +1 -1
  129. package/dist/{logging-D0MyqUlV.js → logging-CRq4h04P.js} +2 -2
  130. package/dist/{login-qr-Xx8yJrSc.js → login-qr-B6ZgAuIf.js} +5 -5
  131. package/dist/{login-qr-CoskdtvN.js → login-qr-Bua-p0nG.js} +2 -2
  132. package/dist/{login-qr-CAk9D-FM.js → login-qr-CuvemJj4.js} +6 -6
  133. package/dist/{login-qr-kUyMWXV1.js → login-qr-Djr1JfIf.js} +2 -2
  134. package/dist/{logs-cli-B476pzJS.js → logs-cli-9IAV7rWY.js} +15 -15
  135. package/dist/{logs-cli-BQRUI_PO.js → logs-cli-EiKzUFPa.js} +14 -14
  136. package/dist/{manager-CBApH7eR.js → manager-BIMh_eSm.js} +5 -5
  137. package/dist/{manager-CyJH6WMg.js → manager-CwinWQoz.js} +5 -5
  138. package/dist/{manager-DScY_ZTT.js → manager-DkqF1GiK.js} +7 -7
  139. package/dist/{manager-DseK7RWj.js → manager-T1XfGchB.js} +8 -8
  140. package/dist/{manifest-registry-DFckk-L8.js → manifest-registry-CQhdnDBZ.js} +2 -2
  141. package/dist/{manifest-registry-BTgLN_W2.js → manifest-registry-u0okVSkU.js} +2 -2
  142. package/dist/{message-channel-0717wOz-.js → message-channel-BLi2a6Yw.js} +1 -1
  143. package/dist/{message-channel-BlgPSDAh.js → message-channel-C_MmebBt.js} +1 -1
  144. package/dist/{model-auth-CbqRVYRp.js → model-auth-CabXIF6O.js} +57 -19
  145. package/dist/{model-selection-unMJyUIE.js → model-selection-BLuqsGVB.js} +59 -21
  146. package/dist/{model-selection-B9Y7dKQd.js → model-selection-C1GmkTAV.js} +57 -19
  147. package/dist/{models-cli-B1cLGcRz.js → models-cli-9jmDv-h3.js} +50 -48
  148. package/dist/{models-cli-D7sChCi6.js → models-cli-zS9rtWz8.js} +48 -46
  149. package/dist/{node-cli-ic2C1xs2.js → node-cli-CrpTxTTs.js} +26 -24
  150. package/dist/{node-cli-CS3KwBh1.js → node-cli-wemUMCg-.js} +25 -23
  151. package/dist/{node-service-D_Cdq1JI.js → node-service-C8DTHTMg.js} +2 -2
  152. package/dist/{node-service-_vgO5xR-.js → node-service-WQuEKz6W.js} +1 -1
  153. package/dist/{nodes-cli-CipcvVMc.js → nodes-cli-BaU2SIFw.js} +16 -16
  154. package/dist/{nodes-cli-B1meaW7S.js → nodes-cli-Dx23D72n.js} +16 -16
  155. package/dist/{nodes-screen-N-4_0VIu.js → nodes-screen-C0IuBqUL.js} +1 -1
  156. package/dist/{note-CAM9PbSJ.js → note-BhRSeNeu.js} +2 -2
  157. package/dist/{note-Ci08TSbV.js → note-hhtubr2j.js} +1 -1
  158. package/dist/{onboard-channels-DMcOT0dj.js → onboard-channels-C501x8GI.js} +8 -8
  159. package/dist/{onboard-channels-CsT3E4bT.js → onboard-channels-Dxzroasd.js} +8 -8
  160. package/dist/{onboard-skills-DoxkpnEU.js → onboard-skills-DV0Qzvjj.js} +19 -19
  161. package/dist/{onboard-skills-D-BrCoRN.js → onboard-skills-rlBHcu3Q.js} +18 -18
  162. package/dist/{onboarding-B92952fz.js → onboarding-CN-EDLjd.js} +34 -34
  163. package/dist/{pairing-cli-BDUJ5VoX.js → pairing-cli-CDHG4xuI.js} +15 -15
  164. package/dist/{pairing-cli-0wbU1u8d.js → pairing-cli-CQP34Dlx.js} +14 -14
  165. package/dist/{pairing-labels-3o3QO3Qn.js → pairing-labels-B6CN0SNH.js} +1 -1
  166. package/dist/{pairing-labels-Bin1K7_f.js → pairing-labels-CgNHnjzT.js} +1 -1
  167. package/dist/{pairing-store-CL4rJ7m7.js → pairing-store-CmlRVqOz.js} +2 -2
  168. package/dist/{pairing-store-fIWI3pXG.js → pairing-store-Dp5_JGnG.js} +3 -3
  169. package/dist/{path-env-CXWUFfFv.js → path-env-CLvYNwtL.js} +1 -1
  170. package/dist/{path-env-C5FR_Eay.js → path-env-CaYUVIML.js} +2 -2
  171. package/dist/{paths-DwKNqk_S.js → paths-B0a4ywSO.js} +30 -5
  172. package/dist/{paths-RITJT4UY.js → paths-B49s6UZQ.js} +30 -5
  173. package/dist/{paths-CB2fqqbX.js → paths-D0O87MfH.js} +30 -5
  174. package/dist/{paths-IivnSNkP.js → paths-DLINmNFQ.js} +31 -6
  175. package/dist/{pi-embedded-DhYItk8O.js → pi-embedded-Ctrt2kz0.js} +1109 -662
  176. package/dist/{pi-embedded-helpers-CmftU5Zj.js → pi-embedded-helpers-CMKLjW6X.js} +8 -5
  177. package/dist/{pi-embedded-helpers-CfXnSIFx.js → pi-embedded-helpers-CUzTc1v6.js} +170 -19
  178. package/dist/{pi-embedded-helpers-Uan-3N1T.js → pi-embedded-helpers-DfwkwPYD.js} +7 -4
  179. package/dist/{pi-embedded-helpers-Bri9tk9g.js → pi-embedded-helpers-WDwx99UA.js} +170 -19
  180. package/dist/{pi-tools.policy-CJFi1sny.js → pi-tools.policy-BpsROZbz.js} +4 -4
  181. package/dist/{plugin-auto-enable-BY4CqJbD.js → plugin-auto-enable-Bqhc3w5n.js} +5 -5
  182. package/dist/{plugin-auto-enable-DbQrtQjL.js → plugin-auto-enable-PW76g_PJ.js} +5 -5
  183. package/dist/plugin-sdk/agents/pi-embedded-runner/run/params.d.ts +2 -0
  184. package/dist/plugin-sdk/agents/pi-embedded-runner/run/types.d.ts +2 -0
  185. package/dist/plugin-sdk/agents/pi-embedded-runner/types.d.ts +15 -0
  186. package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.tools.d.ts +1 -1
  187. package/dist/plugin-sdk/agents/pi-embedded-subscribe.handlers.types.d.ts +2 -0
  188. package/dist/plugin-sdk/agents/pi-embedded-subscribe.types.d.ts +2 -0
  189. package/dist/plugin-sdk/agents/session-tool-result-guard-wrapper.d.ts +2 -0
  190. package/dist/plugin-sdk/agents/session-tool-result-guard.d.ts +4 -0
  191. package/dist/plugin-sdk/agents/tools/agent-step.d.ts +3 -0
  192. package/dist/plugin-sdk/agents/usage.d.ts +1 -0
  193. package/dist/plugin-sdk/auto-reply/reply/reply-reference.d.ts +1 -1
  194. package/dist/plugin-sdk/auto-reply/reply/session-run-accounting.d.ts +11 -0
  195. package/dist/plugin-sdk/auto-reply/reply/session-usage.d.ts +8 -0
  196. package/dist/plugin-sdk/browser/control-auth.d.ts +13 -0
  197. package/dist/plugin-sdk/channels/plugins/onboarding/signal.d.ts +1 -0
  198. package/dist/plugin-sdk/cli/prompt.d.ts +1 -0
  199. package/dist/plugin-sdk/commands/agent/types.d.ts +2 -0
  200. package/dist/plugin-sdk/config/sessions/paths.d.ts +7 -2
  201. package/dist/plugin-sdk/config/types.agents.d.ts +2 -0
  202. package/dist/plugin-sdk/config/types.discord.d.ts +5 -0
  203. package/dist/plugin-sdk/config/types.gateway.d.ts +15 -0
  204. package/dist/plugin-sdk/config/types.hooks.d.ts +15 -0
  205. package/dist/plugin-sdk/config/zod-schema.agents.d.ts +1 -0
  206. package/dist/plugin-sdk/config/zod-schema.d.ts +11 -0
  207. package/dist/plugin-sdk/config/zod-schema.providers-core.d.ts +9 -0
  208. package/dist/plugin-sdk/config/zod-schema.providers.d.ts +4 -0
  209. package/dist/plugin-sdk/discord/monitor/allow-list.d.ts +15 -0
  210. package/dist/plugin-sdk/discord/send.types.d.ts +3 -0
  211. package/dist/plugin-sdk/gateway/auth.d.ts +36 -0
  212. package/dist/plugin-sdk/gateway/protocol/schema/agent.d.ts +6 -0
  213. package/dist/plugin-sdk/gateway/session-utils.fs.d.ts +3 -1
  214. package/dist/plugin-sdk/index.js +295 -99
  215. package/dist/plugin-sdk/infra/binaries.d.ts +3 -0
  216. package/dist/plugin-sdk/infra/heartbeat-runner.d.ts +1 -0
  217. package/dist/plugin-sdk/infra/net/fetch-guard.d.ts +1 -0
  218. package/dist/plugin-sdk/infra/net/ssrf.d.ts +1 -0
  219. package/dist/plugin-sdk/infra/tailscale.d.ts +34 -0
  220. package/dist/plugin-sdk/infra/tmp-openclaw-dir.d.ts +10 -0
  221. package/dist/plugin-sdk/logging/logger.d.ts +1 -1
  222. package/dist/plugin-sdk/media/input-files.d.ts +5 -0
  223. package/dist/plugin-sdk/routing/resolve-route.d.ts +3 -1
  224. package/dist/plugin-sdk/security/external-content.d.ts +1 -1
  225. package/dist/plugin-sdk/security/secret-equal.d.ts +1 -0
  226. package/dist/plugin-sdk/sessions/input-provenance.d.ts +16 -0
  227. package/dist/plugin-sdk/signal/monitor/event-handler.types.d.ts +8 -0
  228. package/dist/plugin-sdk/signal/monitor/mentions.d.ts +2 -0
  229. package/dist/{plugins-3GyCj5KL.js → plugins-4Hqd1WGf.js} +3 -3
  230. package/dist/{plugins-BL9lIXSA.js → plugins-X7d_tfTE.js} +4 -4
  231. package/dist/{plugins-cli-Ce7VsvZh.js → plugins-cli-Bgku3EGj.js} +253 -46
  232. package/dist/{plugins-cli-e9gUebMd.js → plugins-cli-CVToH3if.js} +254 -47
  233. package/dist/{ports-DupIRXQ0.js → ports-qkt29rdC.js} +2 -2
  234. package/dist/{program-u22vbFpH.js → program-Cf7lkBur.js} +82 -82
  235. package/dist/{progress-g9R--HZD.js → progress-C9kngsTD.js} +1 -1
  236. package/dist/{progress-Da1ehW-x.js → progress-DWqhRakV.js} +1 -1
  237. package/dist/{prompt-style-Dc0C5HC9.js → prompt-style-BFH5D5LN.js} +1 -1
  238. package/dist/{prompt-style-lmJDcgtA.js → prompt-style-CIbmaxSa.js} +1 -1
  239. package/dist/{pw-ai-C43wv1ZF.js → pw-ai-8mdv3h-d.js} +7 -6
  240. package/dist/{pw-ai-DTZVjndL.js → pw-ai-CM1IsSgZ.js} +5 -5
  241. package/dist/{pw-ai-zVebjrSG.js → pw-ai-FGoRVblI.js} +3 -3
  242. package/dist/{pw-ai-CWrnJ98b.js → pw-ai-sS1fRKW_.js} +3 -3
  243. package/dist/{qmd-manager-NPD5Yh_4.js → qmd-manager-C67Fc8aN.js} +4 -4
  244. package/dist/{qmd-manager-ozZ933qc.js → qmd-manager-CXVbfg99.js} +7 -7
  245. package/dist/{qmd-manager-DBCZ1sio.js → qmd-manager-RMRE8Tqt.js} +6 -6
  246. package/dist/{qmd-manager-a9Bt0405.js → qmd-manager-pyc_MTIe.js} +4 -4
  247. package/dist/{register.subclis-BpX3ulH1.js → register.subclis-C02e4zuJ.js} +28 -28
  248. package/dist/{reply-m467_fOC.js → reply-DICXkh_C.js} +911 -568
  249. package/dist/{routes-82Ywfho6.js → routes-CmOI1hIH.js} +29 -11
  250. package/dist/{routes-BqxA3ZYr.js → routes-DewK5tq2.js} +29 -12
  251. package/dist/{rpc-DcGBG-Fp.js → rpc-DHr30euf.js} +3 -3
  252. package/dist/{rpc-CfdBHlnp.js → rpc-T300F8zI.js} +3 -3
  253. package/dist/{run-main-aolvSfj3.js → run-main-C5wpthq1.js} +84 -84
  254. package/dist/{runner-C1G8RFWl.js → runner-CY0nmVme.js} +9 -9
  255. package/dist/{runner-BCBs8JKA.js → runner-Cfm5nTMc.js} +6 -6
  256. package/dist/{runner-CInKPsiP.js → runner-D_dujMod.js} +8 -8
  257. package/dist/{runner-Cwfn-VOM.js → runner-DrGYLH5K.js} +6 -6
  258. package/dist/{sandbox-B0K9e6Fw.js → sandbox-BKYnhYQH.js} +23 -15
  259. package/dist/{sandbox-BW8Xnkw1.js → sandbox-Bhjnh1Xg.js} +21 -13
  260. package/dist/{sandbox-cli-mKCs2J0i.js → sandbox-cli-DBsAjZJN.js} +20 -20
  261. package/dist/{sandbox-cli-BD5LkZ0B.js → sandbox-cli-rV9LtFeu.js} +19 -19
  262. package/dist/{security-cli-kgI4soGy.js → security-cli-BIwJM_rs.js} +27 -27
  263. package/dist/{security-cli-kz8TiyqU.js → security-cli-BRjny8Yu.js} +26 -26
  264. package/dist/{server-context-fX4xiYRh.js → server-context-BGpGs3qd.js} +7 -7
  265. package/dist/{server-context-Lb-eUZG_.js → server-context-Cl0U0vE3.js} +5 -5
  266. package/dist/{server-node-events-Dx18uVrH.js → server-node-events-CBfTbiTA.js} +45 -43
  267. package/dist/{server-node-events-KqZMN30F.js → server-node-events-QCvh8EgI.js} +45 -43
  268. package/dist/{service-DZMXgMra.js → service--nPk7DvT.js} +3 -3
  269. package/dist/{service-DNcIZ5Kp.js → service-99RDXwX4.js} +2 -2
  270. package/dist/{service-audit-0WLGnoNT.js → service-audit-DnLmRGQt.js} +4 -4
  271. package/dist/{service-audit-uhZSlxeb.js → service-audit-ckBaRCVC.js} +3 -3
  272. package/dist/{session-cost-usage-HU4OeRgw.js → session-cost-usage-D7HuoSSD.js} +10 -8
  273. package/dist/{session-cost-usage-CL8gnHRN.js → session-cost-usage-D9hHANWI.js} +10 -8
  274. package/dist/{shared-j4Qtr475.js → shared-Bs4vduG4.js} +3 -3
  275. package/dist/{shared-BBw6F-YC.js → shared-CEY5IkwG.js} +2 -2
  276. package/dist/{shared-DOZs2SoH.js → shared-DRohONn_.js} +3 -3
  277. package/dist/{shared-CtP9K-o2.js → shared-ICqOZibV.js} +3 -3
  278. package/dist/{skill-scanner-C_fQzVDu.js → skill-scanner-rHMtUHtP.js} +1 -1
  279. package/dist/{skills-BvPUNjxo.js → skills-DRjfSQT3.js} +128 -4
  280. package/dist/{skills-aFOsriMP.js → skills-DprQj9X2.js} +129 -5
  281. package/dist/{skills-cli-oWaTJzZd.js → skills-cli-9WO-C55s.js} +12 -12
  282. package/dist/{skills-cli-E6shXpdd.js → skills-cli-B9eej-EW.js} +13 -13
  283. package/dist/{skills-status-D4vbIMnz.js → skills-status-5U3P3YfJ.js} +3 -3
  284. package/dist/{skills-status-DJDaA2Ur.js → skills-status-TDIgVd1K.js} +2 -2
  285. package/dist/{sqlite-B7FPASCO.js → sqlite-BINzs1U0.js} +2 -2
  286. package/dist/{sqlite-B4Z1_Ioc.js → sqlite-D4w5TejA.js} +2 -2
  287. package/dist/{sqlite-BkYnxkQO.js → sqlite-DRRHmlug.js} +2 -2
  288. package/dist/{sqlite-EuQPVXvn.js → sqlite-F6PGkEm1.js} +2 -2
  289. package/dist/{status-B2Yr-2J5.js → status-BKGkKC_v.js} +3 -3
  290. package/dist/{status-DW7m5xUN.js → status-CiHtHdaa.js} +4 -4
  291. package/dist/{status-CxhnUa5J.js → status-DDWoOpeB.js} +33 -33
  292. package/dist/{subsystem-Bv7dGhES.js → subsystem-BoExtIHo.js} +32 -13
  293. package/dist/{system-cli-0JXhJNWm.js → system-cli-B6lr60Io.js} +14 -14
  294. package/dist/{system-cli-D-0OaMtH.js → system-cli-CprW9G3h.js} +14 -14
  295. package/dist/{systemd-CNTodvCO.js → systemd-C0VZriGM.js} +2 -2
  296. package/dist/{systemd-CUJJHgHa.js → systemd-DrmBtJ5T.js} +3 -3
  297. package/dist/{systemd-hints-cmHtrXUl.js → systemd-hints-DZtXiVHa.js} +1 -1
  298. package/dist/{systemd-linger-CArPbmvv.js → systemd-linger-NC2kl1SC.js} +2 -2
  299. package/dist/{systemd-linger-XvT9Y9sb.js → systemd-linger-xdn3BdPh.js} +2 -2
  300. package/dist/{table-DzBBIqHO.js → table-B8dx3v4v.js} +2 -2
  301. package/dist/{table-oJQPTUL6.js → table-CwulTLQp.js} +1 -1
  302. package/dist/{tool-display-Na-EVL83.js → tool-display-CZRIDMRm.js} +1 -1
  303. package/dist/{tool-display-sHJa3kRs.js → tool-display-ClRud3pg.js} +2 -2
  304. package/dist/{tui-nGp8ltQK.js → tui-CVTQn-dC.js} +9 -9
  305. package/dist/{tui-Biw7aqPj.js → tui-Lu8FdrlK.js} +9 -9
  306. package/dist/{tui-cli-C9FEfG7C.js → tui-cli-BLpTj1X9.js} +25 -25
  307. package/dist/{tui-cli-Dxnu5JGl.js → tui-cli-BLx5kL2I.js} +25 -25
  308. package/dist/{tui-formatters-BiNTNGwg.js → tui-formatters-CNySEfJN.js} +5 -5
  309. package/dist/{tui-formatters-C_baVYUz.js → tui-formatters-DePhZK3J.js} +5 -5
  310. package/dist/{update-C4rsLj2F.js → update-DHVxMTpQ.js} +3 -3
  311. package/dist/{update-uwUWrKFu.js → update-DU1geolI.js} +3 -3
  312. package/dist/{update-cli-cNd_G9E6.js → update-cli-C0hUvJWK.js} +66 -66
  313. package/dist/{update-cli-CBXp-c4C.js → update-cli-Wb1GB3rL.js} +68 -68
  314. package/dist/{update-runner-BLsqC24J.js → update-runner--ixK4J3W.js} +10 -10
  315. package/dist/{update-runner-C_FDpmA3.js → update-runner-7Qa1T9y6.js} +9 -9
  316. package/dist/{utils-Dk86IbEs.js → utils-BLJAc3ZV.js} +1 -1
  317. package/dist/{utils-BHPdZE4h.js → utils-Cd9QdCHh.js} +1 -1
  318. package/dist/{webhooks-cli-BpBKXL7W.js → webhooks-cli-DgcMy7RG.js} +12 -12
  319. package/dist/{webhooks-cli-wNfhfKqm.js → webhooks-cli-aVzUcJY9.js} +11 -11
  320. package/dist/{widearea-dns-WVCWJTEb.js → widearea-dns-BaIgNEhY.js} +1 -1
  321. package/dist/{widearea-dns-BWYPcfby.js → widearea-dns-DzuRdwk5.js} +1 -1
  322. package/dist/{ws-log-Cafylho7.js → ws-log-CIXbLCka.js} +1 -1
  323. package/dist/{ws-log-DTUOUVgR.js → ws-log-DcQFZByi.js} +1 -1
  324. package/dist/{wsl-B-H6Z5wp.js → wsl-BUOkxKJu.js} +2 -2
  325. package/docs/automation/webhook.md +43 -2
  326. package/docs/channels/discord.md +29 -1
  327. package/docs/cli/plugins.md +20 -1
  328. package/docs/cli/security.md +1 -0
  329. package/docs/concepts/session-tool.md +1 -0
  330. package/docs/gateway/configuration-reference.md +11 -0
  331. package/docs/gateway/configuration.md +3 -0
  332. package/docs/gateway/openresponses-http-api.md +15 -0
  333. package/docs/gateway/security/index.md +3 -0
  334. package/docs/help/faq.md +9 -0
  335. package/docs/install/installer.md +20 -0
  336. package/docs/reference/transcript-hygiene.md +18 -0
  337. package/docs/tools/browser.md +6 -0
  338. package/extensions/diagnostics-otel/package.json +9 -9
  339. package/extensions/feishu/package.json +1 -1
  340. package/extensions/feishu/src/config-schema.ts +6 -0
  341. package/extensions/feishu/src/reply-dispatcher.test.ts +116 -0
  342. package/extensions/feishu/src/reply-dispatcher.ts +124 -67
  343. package/extensions/feishu/src/streaming-card.ts +223 -0
  344. package/extensions/feishu/src/targets.test.ts +16 -0
  345. package/extensions/feishu/src/targets.ts +1 -1
  346. package/extensions/irc/src/client.ts +1 -1
  347. package/extensions/minimax-portal-auth/index.ts +7 -5
  348. package/extensions/nostr/package.json +1 -1
  349. package/package.json +13 -13
  350. package/dist/auth-BcNHFK-i.js +0 -184
  351. package/dist/auth-jrfLXze7.js +0 -184
  352. /package/dist/{archive-DqNr5i8b.js → archive-beaSfAzA.js} +0 -0
  353. /package/dist/{brew-BIrWdDps.js → brew-BUIxHEkn.js} +0 -0
  354. /package/dist/{brew-6UyogeLe.js → brew-ROHf0-Xp.js} +0 -0
  355. /package/dist/{constants-DuoCkWRh.js → constants-BvQ6S8j5.js} +0 -0
  356. /package/dist/{errors-x4NYs-1P.js → errors-DjZBTJJ3.js} +0 -0
  357. /package/dist/{helpers-BDvtkJjw.js → helpers-HyeZXsnu.js} +0 -0
  358. /package/dist/{is-main-CE1eOBYb.js → is-main-BWoXGz7p.js} +0 -0
  359. /package/dist/{parse-Cjiudy6x.js → parse-Bw0oH-rT.js} +0 -0
  360. /package/dist/{parse-timeout-DFSPLxpY.js → parse-timeout-D1XX_zN_.js} +0 -0
  361. /package/dist/{prompts-BOz5176z.js → prompts-Bg96reub.js} +0 -0
  362. /package/dist/{redact-DuEEf1p1.js → redact-Br9GfacZ.js} +0 -0
  363. /package/dist/{skill-scanner-CprFkZib.js → skill-scanner-CucvxYhu.js} +0 -0
  364. /package/dist/{transcript-events-CZ8CG4ht.js → transcript-events-BtNd-j6q.js} +0 -0
@@ -1,63 +1,64 @@
1
1
  import { g as resolveStateDir, r as STATE_DIR, t as CONFIG_PATH, y as resolveRequiredHomeDir } from "./paths-DVBShlw6.js";
2
- import { A as logVerbose, D as info, E as danger, F as warn, I as colorize, L as isRich, M as setVerbose, N as shouldLogVerbose, P as success, R as theme, T as setActivePluginRegistry, U as normalizeLogLevel, b as normalizeAnyChannelId, c as defaultRuntime, m as CHAT_CHANNEL_ORDER, t as createSubsystemLogger, w as requireActivePluginRegistry, x as normalizeChannelId, z as getChildLogger } from "./subsystem-Bv7dGhES.js";
3
- import { C as shortenHomePath, D as truncateUtf16Safe, E as toWhatsappJid, S as shortenHomeInString, T as sliceUtf16Safe, b as resolveUserPath, d as isPlainObject, f as isRecord, h as normalizeE164, i as clampInt, l as escapeRegExp, m as jidToE164, p as isSelfChatMode, r as clamp, t as CONFIG_DIR, w as sleep, y as resolveJidToE164 } from "./utils-BHPdZE4h.js";
4
- import { A as isTransientHttpError, C as isContextOverflowError, D as isRateLimitAssistantError, E as isLikelyContextOverflowError, F as ensureSessionHeader, G as normalizeUsageDisplay, H as normalizeElevatedLevel, I as resolveBootstrapMaxChars, J as supportsXHighThinking, K as normalizeVerboseLevel, L as sanitizeGoogleTurnOrdering, M as parseImageSizeError, N as sanitizeUserFacingText, O as isRawApiErrorPayload, P as buildBootstrapContextFiles, R as formatThinkingLevels, S as isCompactionFailureError, T as isFailoverErrorMessage, U as normalizeReasoningLevel, W as normalizeThinkLevel, _ as formatRawAssistantErrorForUi, a as isMessagingToolDuplicateNormalized, b as isBillingAssistantError, c as sanitizeImageBlocks, d as isAntigravityClaude, f as isGoogleModelApi, g as formatBillingErrorMessage, h as formatAssistantErrorText, j as parseImageDimensionError, k as isTimeoutErrorMessage, l as sanitizeToolResultImages, m as classifyFailoverReason, n as validateGeminiTurns, o as normalizeTextForComparison, p as BILLING_ERROR_USER_MESSAGE, q as resolveResponseUsageMode, r as pickFallbackThinkingLevel, s as sanitizeSessionMessagesImages, t as validateAnthropicTurns, u as downgradeOpenAIReasoningBlocks, v as getApiErrorPayloadFingerprint, w as isFailoverAssistantError, x as isCloudCodeAssistFormatError, y as isAuthAssistantError, z as formatXHighModelHint } from "./pi-embedded-helpers-CmftU5Zj.js";
2
+ import { A as logVerbose, D as info, E as danger, F as warn, I as colorize, L as isRich, M as setVerbose, N as shouldLogVerbose, P as success, R as theme, T as setActivePluginRegistry, U as normalizeLogLevel, b as normalizeAnyChannelId, c as defaultRuntime, m as CHAT_CHANNEL_ORDER, t as createSubsystemLogger, w as requireActivePluginRegistry, x as normalizeChannelId, z as getChildLogger } from "./subsystem-BoExtIHo.js";
3
+ import { C as shortenHomePath, D as truncateUtf16Safe, E as toWhatsappJid, S as shortenHomeInString, T as sliceUtf16Safe, b as resolveUserPath, d as isPlainObject, f as isRecord, h as normalizeE164, i as clampInt, l as escapeRegExp, m as jidToE164, p as isSelfChatMode, r as clamp, t as CONFIG_DIR, w as sleep, y as resolveJidToE164 } from "./utils-Cd9QdCHh.js";
4
+ import { A as isTransientHttpError, C as isContextOverflowError, D as isRateLimitAssistantError, E as isLikelyContextOverflowError, F as ensureSessionHeader, G as normalizeUsageDisplay, H as normalizeElevatedLevel, I as resolveBootstrapMaxChars, J as supportsXHighThinking, K as normalizeVerboseLevel, L as sanitizeGoogleTurnOrdering, M as parseImageSizeError, N as sanitizeUserFacingText, O as isRawApiErrorPayload, P as buildBootstrapContextFiles, R as formatThinkingLevels, S as isCompactionFailureError, T as isFailoverErrorMessage, U as normalizeReasoningLevel, W as normalizeThinkLevel, _ as formatRawAssistantErrorForUi, a as isMessagingToolDuplicateNormalized, b as isBillingAssistantError, c as sanitizeImageBlocks, d as isAntigravityClaude, f as isGoogleModelApi, g as formatBillingErrorMessage, h as formatAssistantErrorText, j as parseImageDimensionError, k as isTimeoutErrorMessage, l as sanitizeToolResultImages, m as classifyFailoverReason, n as validateGeminiTurns, o as normalizeTextForComparison, p as BILLING_ERROR_USER_MESSAGE, q as resolveResponseUsageMode, r as pickFallbackThinkingLevel, s as sanitizeSessionMessagesImages, t as validateAnthropicTurns, u as downgradeOpenAIReasoningBlocks, v as getApiErrorPayloadFingerprint, w as isFailoverAssistantError, x as isCloudCodeAssistFormatError, y as isAuthAssistantError, z as formatXHighModelHint } from "./pi-embedded-helpers-CMKLjW6X.js";
5
5
  import { _ as isCronRunSessionKey, a as buildAgentPeerSessionKey, b as resolveThreadParentSessionKey, c as normalizeAccountId$3, d as resolveAgentIdFromSessionKey, f as resolveThreadSessionKeys, g as isAcpSessionKey, i as buildAgentMainSessionKey, l as normalizeAgentId, n as DEFAULT_AGENT_ID, o as buildGroupHistoryKey, p as sanitizeAgentId, r as DEFAULT_MAIN_KEY, s as classifySessionKeyShape, t as DEFAULT_ACCOUNT_ID$1, u as normalizeMainKey, v as isSubagentSessionKey, y as parseAgentSessionKey } from "./session-key-BWxPj0z_.js";
6
- import { a as logDebug, c as logWarn, i as spawnWithFallback, n as runExec, o as logError, r as formatSpawnError, s as logInfo, t as runCommandWithTimeout } from "./exec-DXtR2fhb.js";
6
+ import { a as logDebug, c as logWarn, i as spawnWithFallback, n as runExec, o as logError, r as formatSpawnError, s as logInfo, t as runCommandWithTimeout } from "./exec-YIosokWE.js";
7
7
  import { t as resolveOpenClawPackageRoot } from "./openclaw-root-1VeFrph_.js";
8
- import { C as loadWorkspaceBootstrapFiles, S as filterBootstrapFilesForSession, c as resolveDefaultAgentId, f as DEFAULT_AGENT_WORKSPACE_DIR, i as resolveAgentModelFallbacksOverride, l as resolveSessionAgentId, n as resolveAgentConfig, o as resolveAgentSkillsFilter, p as DEFAULT_BOOTSTRAP_FILENAME, r as resolveAgentDir, s as resolveAgentWorkspaceDir, t as listAgentIds, u as resolveSessionAgentIds, x as ensureAgentWorkspace } from "./agent-scope---6LLHj0.js";
9
- import { B as resolveApiKeyForProvider, Ct as resolveAuthProfileDisplayLabel, Dt as DEFAULT_MODEL, Et as DEFAULT_CONTEXT_TOKENS, G as getShellPathFromLoginShell, H as resolveEnvApiKey, L as getApiKeyForModel, Ot as DEFAULT_PROVIDER, R as getCustomProviderApiKey, St as normalizeSecretInput, U as resolveModelAuthMode, a as isCliProvider, at as resolveApiKeyForProfile, bt as resolveOpenClawAgentDir, d as resolveConfiguredModelRef, dt as listProfilesForProvider, et as resolveAuthProfileOrder, f as resolveDefaultModelForAgent, ft as markAuthProfileGood, h as resolveThinkingDefault, ht as ensureAuthProfileStore, m as resolveModelRefFromString, n as buildConfiguredAllowlistKeys, nt as markAuthProfileFailure, o as modelKey, q as resolveShellEnvFallbackTimeoutMs, r as buildModelAliasIndex, rt as markAuthProfileUsed, s as normalizeProviderId, t as buildAllowedModelSet, tt as isProfileInCooldown, yt as resolveAuthStorePathForDisplay, z as requireApiKey } from "./model-selection-unMJyUIE.js";
8
+ import { C as loadWorkspaceBootstrapFiles, S as filterBootstrapFilesForSession, c as resolveDefaultAgentId, f as DEFAULT_AGENT_WORKSPACE_DIR, i as resolveAgentModelFallbacksOverride, l as resolveSessionAgentId, n as resolveAgentConfig, o as resolveAgentSkillsFilter, p as DEFAULT_BOOTSTRAP_FILENAME, r as resolveAgentDir, s as resolveAgentWorkspaceDir, t as listAgentIds, u as resolveSessionAgentIds, x as ensureAgentWorkspace } from "./agent-scope-CQCus0rI.js";
9
+ import { B as resolveApiKeyForProvider, Ct as resolveAuthProfileDisplayLabel, Dt as DEFAULT_MODEL, Et as DEFAULT_CONTEXT_TOKENS, G as getShellPathFromLoginShell, H as resolveEnvApiKey, L as getApiKeyForModel, Ot as DEFAULT_PROVIDER, R as getCustomProviderApiKey, St as normalizeSecretInput, U as resolveModelAuthMode, a as isCliProvider, at as resolveApiKeyForProfile, bt as resolveOpenClawAgentDir, d as resolveConfiguredModelRef, dt as listProfilesForProvider, et as resolveAuthProfileOrder, f as resolveDefaultModelForAgent, ft as markAuthProfileGood, h as resolveThinkingDefault, ht as ensureAuthProfileStore, m as resolveModelRefFromString, n as buildConfiguredAllowlistKeys, nt as markAuthProfileFailure, o as modelKey, q as resolveShellEnvFallbackTimeoutMs, r as buildModelAliasIndex, rt as markAuthProfileUsed, s as normalizeProviderId, t as buildAllowedModelSet, tt as isProfileInCooldown, yt as resolveAuthStorePathForDisplay, z as requireApiKey } from "./model-selection-BLuqsGVB.js";
10
10
  import { a as saveJsonFile, i as loadJsonFile } from "./github-copilot-token-BW-SEg7E.js";
11
11
  import { t as formatCliCommand } from "./command-format-ChfKqObn.js";
12
12
  import { t as parseBooleanValue$1 } from "./boolean-BgXe2hyu.js";
13
- import { t as isTruthyEnvValue } from "./env-DE9xvYOL.js";
14
- import { A as resolveAgentMaxConcurrent, C as parseConfigPath, M as VERSION, S as getConfigValueAtPath, T as unsetConfigValueAtPath, _ as validateJsonSchemaValue, b as setConfigOverride, c as writeConfigFile, f as TELEGRAM_COMMAND_NAME_PATTERN, g as parseDurationMs, h as isSafeExecutableValue, i as loadConfig, l as validateConfigObjectWithPlugins, m as resolveTelegramCustomCommands, o as readConfigFileSnapshot, p as normalizeTelegramCommandName, s as resolveConfigSnapshotHash, v as getConfigOverrides, w as setConfigValueAtPath, x as unsetConfigOverride, y as resetConfigOverrides } from "./config-DH9TLUNc.js";
15
- import { d as resolveMemorySlotDecision, l as normalizePluginsConfig, n as discoverOpenClawPlugins, s as applyTestPluginDefaults, t as loadPluginManifestRegistry, u as resolveEnableState } from "./manifest-registry-DFckk-L8.js";
16
- import { _ as listEnabledDiscordAccounts, a as normalizeWhatsAppTarget, b as normalizeChatType, c as resolveTelegramAccount, d as listBindings, g as resolveSlackBotToken, h as resolveSlackAppToken, i as isWhatsAppGroupJid, l as resolveTelegramToken, n as listChannelPlugins, o as listEnabledTelegramAccounts, p as resolveSlackAccount, r as normalizeChannelId$1, s as listTelegramAccountIds, t as getChannelPlugin, v as resolveDiscordAccount, y as normalizeDiscordToken } from "./plugins-BL9lIXSA.js";
17
- import { A as resolveSessionResetPolicy, C as normalizeDeliveryContext, D as resolveSessionKey$1, G as resolveIMessageAccount, H as listChannelDocks, K as resolveChannelGroupPolicy, L as resolveMainSessionKey, M as resolveThreadFlag, N as DEFAULT_RESET_TRIGGERS, O as evaluateSessionFreshness, P as canonicalizeMainSessionAlias, S as mergeDeliveryContext, U as listEnabledSignalAccounts, V as getChannelDock, W as resolveSignalAccount, X as resolveGroupSessionKey, Y as buildGroupDisplayName, Z as resolveSandboxConfigForAgent, _ as updateSessionStoreEntry, a as ensureSandboxWorkspaceForSession, at as normalizeToolName, b as deliveryContextFromSession, c as resolveSandboxRuntimeStatus, d as loadSessionStore, dt as resolveConversationLabel, et as applyOwnerOnlyToolPolicy, f as readSessionUpdatedAt, g as updateSessionStore, h as updateLastRoute, j as resolveSessionResetType, k as resolveChannelResetConfig, l as appendAssistantMessageToSessionTranscript, nt as collectExplicitAllowlist, o as resolveSandboxContext, ot as resolveToolProfilePolicy, p as recordSessionMetaFromInbound, q as resolveChannelGroupRequireMention, rt as expandPolicyWithPluginGroups, st as stripPluginOnlyAllowlist, tt as buildPluginToolGroups, v as isCacheEnabled, w as normalizeSessionDeliveryFields, x as deliveryContextKey, y as resolveCacheTtlMs$1, z as deriveSessionMetaPatch } from "./sandbox-BW8Xnkw1.js";
18
- import { _ as CLI_OUTPUT_MAX_BUFFER, a as runCapability, c as modelSupportsVision, f as registerUnhandledRejectionHandler, g as resolveMediaUnderstandingScope, h as normalizeMediaUnderstandingChatType, i as resolveAutoImageModel, m as resolveTimeoutMs$1, n as createMediaAttachmentCache, o as findModelInCatalog, p as resolveConcurrency, r as normalizeMediaAttachments, s as loadModelCatalog, t as buildProviderRegistry, u as resolveAttachmentKind, v as applyTemplate } from "./runner-CInKPsiP.js";
19
- import { _ as stripReasoningTagsFromText, a as decodeDataUrl, c as extractAssistantThinking, d as formatReasoningMessage, f as inferToolMetaFromArgs, g as stripThinkingTagsFromText, h as stripMinimaxToolCallXml, i as coerceImageModelConfig, l as extractThinkingFromTaggedStream, m as stripDowngradedToolCallText, o as resolveProviderVisionModelFromConfig, p as promoteThinkingTagsToBlocks, r as coerceImageAssistantText, s as extractAssistantText$1, u as extractThinkingFromTaggedText, v as ensureOpenClawModelsJson, y as minimaxUnderstandImage } from "./image-DI9s9eEx.js";
13
+ import { t as isTruthyEnvValue } from "./env-ONzUVAG2.js";
14
+ import { A as resolveAgentMaxConcurrent, C as parseConfigPath, M as VERSION, S as getConfigValueAtPath, T as unsetConfigValueAtPath, _ as validateJsonSchemaValue, b as setConfigOverride, c as writeConfigFile, f as TELEGRAM_COMMAND_NAME_PATTERN, g as parseDurationMs, h as isSafeExecutableValue, i as loadConfig, l as validateConfigObjectWithPlugins, m as resolveTelegramCustomCommands, o as readConfigFileSnapshot, p as normalizeTelegramCommandName, s as resolveConfigSnapshotHash, v as getConfigOverrides, w as setConfigValueAtPath, x as unsetConfigOverride, y as resetConfigOverrides } from "./config-aFQssWKX.js";
15
+ import { d as resolveMemorySlotDecision, l as normalizePluginsConfig, n as discoverOpenClawPlugins, s as applyTestPluginDefaults, t as loadPluginManifestRegistry, u as resolveEnableState } from "./manifest-registry-CQhdnDBZ.js";
16
+ import { _ as listEnabledDiscordAccounts, a as normalizeWhatsAppTarget, b as normalizeChatType, c as resolveTelegramAccount, d as listBindings, g as resolveSlackBotToken, h as resolveSlackAppToken, i as isWhatsAppGroupJid, l as resolveTelegramToken, n as listChannelPlugins, o as listEnabledTelegramAccounts, p as resolveSlackAccount, r as normalizeChannelId$1, s as listTelegramAccountIds, t as getChannelPlugin, v as resolveDiscordAccount, y as normalizeDiscordToken } from "./plugins-X7d_tfTE.js";
17
+ import { A as resolveSessionResetPolicy, C as normalizeDeliveryContext, D as resolveSessionKey$1, G as resolveIMessageAccount, H as listChannelDocks, K as resolveChannelGroupPolicy, L as resolveMainSessionKey, M as resolveThreadFlag, N as DEFAULT_RESET_TRIGGERS, O as evaluateSessionFreshness, P as canonicalizeMainSessionAlias, S as mergeDeliveryContext, U as listEnabledSignalAccounts, V as getChannelDock, W as resolveSignalAccount, X as resolveGroupSessionKey, Y as buildGroupDisplayName, Z as resolveSandboxConfigForAgent, _ as updateSessionStoreEntry, a as ensureSandboxWorkspaceForSession, at as normalizeToolName, b as deliveryContextFromSession, c as resolveSandboxRuntimeStatus, d as loadSessionStore, dt as resolveConversationLabel, et as applyOwnerOnlyToolPolicy, f as readSessionUpdatedAt, g as updateSessionStore, h as updateLastRoute, j as resolveSessionResetType, k as resolveChannelResetConfig, l as appendAssistantMessageToSessionTranscript, nt as collectExplicitAllowlist, o as resolveSandboxContext, ot as resolveToolProfilePolicy, p as recordSessionMetaFromInbound, q as resolveChannelGroupRequireMention, rt as expandPolicyWithPluginGroups, st as stripPluginOnlyAllowlist, tt as buildPluginToolGroups, v as isCacheEnabled, w as normalizeSessionDeliveryFields, x as deliveryContextKey, y as resolveCacheTtlMs$1, z as deriveSessionMetaPatch } from "./sandbox-Bhjnh1Xg.js";
18
+ import { _ as CLI_OUTPUT_MAX_BUFFER, a as runCapability, c as modelSupportsVision, f as registerUnhandledRejectionHandler, g as resolveMediaUnderstandingScope, h as normalizeMediaUnderstandingChatType, i as resolveAutoImageModel, m as resolveTimeoutMs$1, n as createMediaAttachmentCache, o as findModelInCatalog, p as resolveConcurrency, r as normalizeMediaAttachments, s as loadModelCatalog, t as buildProviderRegistry, u as resolveAttachmentKind, v as applyTemplate } from "./runner-D_dujMod.js";
19
+ import { _ as stripReasoningTagsFromText, a as decodeDataUrl, c as extractAssistantThinking, d as formatReasoningMessage, f as inferToolMetaFromArgs, g as stripThinkingTagsFromText, h as stripMinimaxToolCallXml, i as coerceImageModelConfig, l as extractThinkingFromTaggedStream, m as stripDowngradedToolCallText, o as resolveProviderVisionModelFromConfig, p as promoteThinkingTagsToBlocks, r as coerceImageAssistantText, s as extractAssistantText$1, u as extractThinkingFromTaggedText, v as ensureOpenClawModelsJson, y as minimaxUnderstandImage } from "./image-C4Nn2p3e.js";
20
20
  import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-EwKVHlZB.js";
21
- import { O as DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "./chrome-juQxt0zf.js";
22
- import { a as resolveSkillsPromptForRun, i as loadWorkspaceSkillEntries, l as applySkillEnvOverrides, n as buildWorkspaceSkillCommandSpecs, r as buildWorkspaceSkillSnapshot, s as resolvePluginSkillDirs, u as applySkillEnvOverridesFromSnapshot } from "./skills-aFOsriMP.js";
23
- import { c as saveMediaBuffer, d as getFileExtension, f as imageMimeFromFormat, g as MAX_IMAGE_BYTES, l as detectMime, m as isGifMedia, o as resizeToJpeg, p as isAudioFileName, r as getImageMetadata, s as getMediaDir, u as extensionForMime, v as mediaKindFromMime, y as SsrFBlockedError } from "./routes-82Ywfho6.js";
21
+ import { O as DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "./chrome-Cvr-57lg.js";
22
+ import { a as resolveSkillsPromptForRun, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, i as loadWorkspaceSkillEntries, l as assertMediaNotDataUrl, n as buildWorkspaceSkillCommandSpecs, p as applySkillEnvOverridesFromSnapshot, r as buildWorkspaceSkillSnapshot, s as resolvePluginSkillDirs, u as assertSandboxPath } from "./skills-DprQj9X2.js";
23
+ import { c as saveMediaBuffer, d as getFileExtension, f as imageMimeFromFormat, g as MAX_IMAGE_BYTES, l as detectMime, m as isGifMedia, o as resizeToJpeg, p as isAudioFileName, r as getImageMetadata, s as getMediaDir, u as extensionForMime, v as mediaKindFromMime, y as SsrFBlockedError } from "./routes-CmOI1hIH.js";
24
24
  import { n as formatErrorMessage, r as formatUncaughtError, t as extractErrorCode } from "./errors-Bv81hF2P.js";
25
- import { i as resolveBrowserConfig } from "./server-context-Lb-eUZG_.js";
25
+ import { i as resolveBrowserConfig } from "./server-context-Cl0U0vE3.js";
26
26
  import { t as pickPrimaryTailnetIPv4 } from "./tailnet-DATIFSsY.js";
27
27
  import { a as isValidIPv4, s as pickPrimaryLanIPv4 } from "./ws-CHCQHs0F.js";
28
- import { a as isInternalMessageChannel, c as listDeliverableMessageChannels, d as resolveMessageChannel, h as GATEWAY_CLIENT_NAMES, l as normalizeMessageChannel, m as GATEWAY_CLIENT_MODES, n as isDeliverableMessageChannel, o as isMarkdownCapableMessageChannel, p as GATEWAY_CLIENT_IDS, t as INTERNAL_MESSAGE_CHANNEL, u as resolveGatewayMessageChannel } from "./message-channel-0717wOz-.js";
29
- import { a as logoutWeb, d as webAuthExists, i as logWebSelfId, n as resolveWhatsAppAccount, r as getWebAuthAgeMs, s as readWebSelfId } from "./accounts-DimKrt7j.js";
30
- import { a as resolveSessionTranscriptsDirForAgent, n as resolveSessionFilePath, o as resolveStorePath, r as resolveSessionTranscriptPath } from "./paths-RITJT4UY.js";
28
+ import { a as isInternalMessageChannel, c as listDeliverableMessageChannels, d as resolveMessageChannel, h as GATEWAY_CLIENT_NAMES, l as normalizeMessageChannel, m as GATEWAY_CLIENT_MODES, n as isDeliverableMessageChannel, o as isMarkdownCapableMessageChannel, p as GATEWAY_CLIENT_IDS, t as INTERNAL_MESSAGE_CHANNEL, u as resolveGatewayMessageChannel } from "./message-channel-BLi2a6Yw.js";
29
+ import { a as logoutWeb, d as webAuthExists, i as logWebSelfId, n as resolveWhatsAppAccount, r as getWebAuthAgeMs, s as readWebSelfId } from "./accounts-DeqIQjo1.js";
30
+ import { i as resolveSessionTranscriptPathInDir, n as resolveSessionFilePath, o as resolveSessionTranscriptsDirForAgent, r as resolveSessionTranscriptPath, s as resolveStorePath } from "./paths-B49s6UZQ.js";
31
31
  import { t as emitSessionTranscriptUpdate } from "./transcript-events-Bp7fGnwv.js";
32
32
  import { n as redactSensitiveText } from "./redact-BRsnXqwD.js";
33
- import { n as resolveToolDisplay } from "./tool-display-Na-EVL83.js";
34
- import { i as fetchWithSsrFGuard, n as fetchRemoteMedia, r as fetchWithTimeout } from "./fetch-CqZP8jwB.js";
35
- import { A as markdownToIR, B as resolveChunkMode, C as sendTypingSignal, D as resolveFetch, E as streamSignalEvents, F as chunkByNewline, G as HEARTBEAT_TOKEN, H as findFenceSpanAt, I as chunkMarkdownText, K as SILENT_REPLY_TOKEN, L as chunkMarkdownTextWithMode, M as loadWebMedia, N as loadWebMediaRaw, O as wrapFetchWithAbortSignal, P as resolveMarkdownTableMode, R as chunkText, S as sendReadReceiptSignal, T as signalRpcRequest, U as isSafeFenceBreak, V as resolveTextChunkLimit, W as parseFenceSpans, _ as throwIfAborted, b as parseInlineDirectives$1, c as applyReplyThreading, d as shouldSuppressMessagingToolReplies, f as createReplyToModeFilterForChannel, g as normalizeTargetForProvider, h as normalizeChannelTargetInput, j as markdownToIRWithMeta, k as chunkMarkdownIR, l as filterMessagingToolDuplicates, m as buildTargetResolverSignature, o as normalizeReplyPayloadsForDelivery, p as resolveReplyToMode, q as isSilentReplyText, s as applyReplyTagsToPayload, t as deliverOutboundPayloads, u as isRenderablePayload, v as parseReplyDirectives, w as signalCheck, x as sendMessageSignal, y as splitMediaFromOutput, z as chunkTextWithMode } from "./deliver-B1jsU2r7.js";
36
- import { i as getMachineDisplayName, n as isWSL, t as createBrowserRouteDispatcher } from "./dispatcher-BHsNwFe-.js";
37
- import { i as resolveMemorySearchConfig, n as resolveRetryConfig, r as retryAsync } from "./manager-DScY_ZTT.js";
38
- import { d as listMemoryFiles, f as normalizeExtraMemoryPaths } from "./sqlite-B4Z1_Ioc.js";
39
- import { _ as parseCommandArgs, b as serializeCommandArgs, d as findCommandByNativeName, f as listChatCommands, g as normalizeCommandBody, h as listNativeCommandSpecsForConfig, i as extractTextFromMessage, m as listNativeCommandSpecs, p as listChatCommandsForConfig, u as buildCommandTextFromArgs, v as resolveCommandArgChoices, x as shouldHandleTextCommands, y as resolveCommandArgMenu } from "./tui-formatters-BiNTNGwg.js";
40
- import { kt as SESSION_LABEL_MAX_LENGTH, t as GatewayClient } from "./client-B0_GiCjB.js";
41
- import { i as randomIdempotencyKey, n as callGateway } from "./call-C9az806y.js";
33
+ import { n as resolveToolDisplay } from "./tool-display-CZRIDMRm.js";
34
+ import { i as fetchWithSsrFGuard, n as fetchRemoteMedia, r as fetchWithTimeout } from "./fetch-DmiOpALK.js";
35
+ import { A as markdownToIR, B as resolveChunkMode, C as sendTypingSignal, D as resolveFetch, E as streamSignalEvents, F as chunkByNewline, G as getGlobalHookRunner, H as findFenceSpanAt, I as chunkMarkdownText, J as SILENT_REPLY_TOKEN, K as initializeGlobalHookRunner, L as chunkMarkdownTextWithMode, M as loadWebMedia, N as loadWebMediaRaw, O as wrapFetchWithAbortSignal, P as resolveMarkdownTableMode, R as chunkText, S as sendReadReceiptSignal, T as signalRpcRequest, U as isSafeFenceBreak, V as resolveTextChunkLimit, W as parseFenceSpans, Y as isSilentReplyText, _ as throwIfAborted, b as parseInlineDirectives$1, c as applyReplyThreading, d as shouldSuppressMessagingToolReplies, f as createReplyToModeFilterForChannel, g as normalizeTargetForProvider, h as normalizeChannelTargetInput, j as markdownToIRWithMeta, k as chunkMarkdownIR, l as filterMessagingToolDuplicates, m as buildTargetResolverSignature, o as normalizeReplyPayloadsForDelivery, p as resolveReplyToMode, q as HEARTBEAT_TOKEN, s as applyReplyTagsToPayload, t as deliverOutboundPayloads, u as isRenderablePayload, v as parseReplyDirectives, w as signalCheck, x as sendMessageSignal, y as splitMediaFromOutput, z as chunkTextWithMode } from "./deliver-LsxKETro.js";
36
+ import { i as getMachineDisplayName, n as isWSL, t as createBrowserRouteDispatcher } from "./dispatcher-DY51b-Zc.js";
37
+ import { i as resolveMemorySearchConfig, n as resolveRetryConfig, r as retryAsync } from "./manager-DkqF1GiK.js";
38
+ import { d as listMemoryFiles, f as normalizeExtraMemoryPaths } from "./sqlite-D4w5TejA.js";
39
+ import { _ as parseCommandArgs, b as serializeCommandArgs, d as findCommandByNativeName, f as listChatCommands, g as normalizeCommandBody, h as listNativeCommandSpecsForConfig, i as extractTextFromMessage, m as listNativeCommandSpecs, p as listChatCommandsForConfig, u as buildCommandTextFromArgs, v as resolveCommandArgChoices, x as shouldHandleTextCommands, y as resolveCommandArgMenu } from "./tui-formatters-CNySEfJN.js";
40
+ import { Mt as hasInterSessionUserProvenance, Nt as normalizeInputProvenance, jt as applyInputProvenanceToUserMessage, kt as SESSION_LABEL_MAX_LENGTH, t as GatewayClient } from "./client-BrYfyoDK.js";
41
+ import { i as randomIdempotencyKey, n as callGateway } from "./call-SolyGS1r.js";
42
42
  import { i as formatDurationSeconds, r as formatDurationPrecise, t as formatDurationCompact } from "./format-duration-84n6_DgO.js";
43
43
  import { n as formatTimeAgo } from "./format-relative-cegC_FF5.js";
44
- import { a as formatError$1, i as createWaSocket, n as startWebLoginWithQr, o as getStatusCode$1, r as waitForWebLogin, s as waitForWaConnection } from "./login-qr-Xx8yJrSc.js";
45
- import { a as removeChannelAllowFromStoreEntry, c as listPairingChannels, i as readChannelAllowFromStore, o as upsertChannelPairingRequest, t as addChannelAllowFromStoreEntry } from "./pairing-store-CL4rJ7m7.js";
46
- import { t as formatDocsLink } from "./links-CV4oki2u.js";
44
+ import { a as formatError$1, i as createWaSocket, n as startWebLoginWithQr, o as getStatusCode$1, r as waitForWebLogin, s as waitForWaConnection } from "./login-qr-B6ZgAuIf.js";
45
+ import { a as removeChannelAllowFromStoreEntry, c as listPairingChannels, i as readChannelAllowFromStore, o as upsertChannelPairingRequest, t as addChannelAllowFromStoreEntry } from "./pairing-store-CmlRVqOz.js";
46
+ import { t as formatDocsLink } from "./links-Eax1UO3w.js";
47
47
  import { r as withManager } from "./cli-utils-CRhVAaLV.js";
48
- import { n as withProgress, r as withProgressTotals } from "./progress-g9R--HZD.js";
49
- import { a as resolveSubagentToolPolicy, c as resolveNativeSkillsEnabled, i as resolveGroupToolPolicy, n as isToolAllowedByPolicies, o as isNativeCommandsExplicitlyDisabled, r as resolveEffectiveToolPolicy, s as resolveNativeCommandsEnabled, t as filterToolsByPolicy } from "./pi-tools.policy-CJFi1sny.js";
50
- import { r as stylePromptTitle } from "./prompt-style-lmJDcgtA.js";
51
- import { t as resolvePairingIdLabel } from "./pairing-labels-3o3QO3Qn.js";
52
- import { c as derivePromptTokens, d as normalizeUsage, l as deriveSessionTotalTokens, n as loadCostUsageSummary, o as extractToolCallNames, r as loadSessionCostSummary, s as hasToolCall, u as hasNonzeroUsage } from "./session-cost-usage-HU4OeRgw.js";
48
+ import { n as withProgress, r as withProgressTotals } from "./progress-C9kngsTD.js";
49
+ import { a as resolveSubagentToolPolicy, c as resolveNativeSkillsEnabled, i as resolveGroupToolPolicy, n as isToolAllowedByPolicies, o as isNativeCommandsExplicitlyDisabled, r as resolveEffectiveToolPolicy, s as resolveNativeCommandsEnabled, t as filterToolsByPolicy } from "./pi-tools.policy-BpsROZbz.js";
50
+ import { r as stylePromptTitle } from "./prompt-style-CIbmaxSa.js";
51
+ import { t as resolvePairingIdLabel } from "./pairing-labels-B6CN0SNH.js";
52
+ import { c as derivePromptTokens, d as normalizeUsage, l as deriveSessionTotalTokens, n as loadCostUsageSummary, o as extractToolCallNames, r as loadSessionCostSummary, s as hasToolCall, u as hasNonzeroUsage } from "./session-cost-usage-D7HuoSSD.js";
53
53
  import { i as resolveModelCostConfig, n as formatTokenCount$2, r as formatUsd$1, t as estimateUsageCost } from "./usage-format-CpORtVCG.js";
54
54
  import { a as evaluateShellAllowlist, d as requiresExecApproval, f as resolveExecApprovals, h as resolveSafeBins, o as maxAsk, p as resolveExecApprovalsFromFile, s as minSecurity, t as addAllowlistEntry, u as recordAllowlistUse } from "./exec-approvals-Cb4ZLukq.js";
55
55
  import { a as canvasSnapshotTempPath, c as parseCameraClipPayload, d as buildNodeShellCommand, i as parseEnvPairs, l as parseCameraSnapPayload, n as screenRecordTempPath, o as parseCanvasSnapshotPayload, r as writeScreenRecordToFile, s as cameraTempPath, t as parseScreenRecordPayload, u as writeBase64ToFile } from "./nodes-screen-CdCWeiwy.js";
56
- import { n as createBrowserControlContext, r as startBrowserControlServiceFromConfig } from "./control-service-CBlMVTRu.js";
57
- import { t as parseAbsoluteTimeMs } from "./parse-Cjiudy6x.js";
58
- import { d as resolveGatewaySystemdServiceName, l as resolveGatewayLaunchAgentLabel } from "./constants-DuoCkWRh.js";
59
- import { n as resolveMessageChannelSelection, t as listConfiguredMessageChannels } from "./channel-selection-C78IwbD-.js";
60
- import { t as parseTimeoutMs } from "./parse-timeout-DFSPLxpY.js";
56
+ import { n as resolveBrowserControlAuth } from "./control-auth-DBCu3qyv.js";
57
+ import { n as createBrowserControlContext, r as startBrowserControlServiceFromConfig } from "./control-service-B5KnPqGP.js";
58
+ import { t as parseAbsoluteTimeMs } from "./parse-Bw0oH-rT.js";
59
+ import { d as resolveGatewaySystemdServiceName, l as resolveGatewayLaunchAgentLabel } from "./constants-BvQ6S8j5.js";
60
+ import { n as resolveMessageChannelSelection, t as listConfiguredMessageChannels } from "./channel-selection-MZAHm4U8.js";
61
+ import { t as parseTimeoutMs } from "./parse-timeout-D1XX_zN_.js";
61
62
  import { createRequire } from "node:module";
62
63
  import process$1 from "node:process";
63
64
  import { fileURLToPath } from "node:url";
@@ -830,6 +831,8 @@ async function fetchWithGuard(params) {
830
831
  url: params.url,
831
832
  maxRedirects: params.maxRedirects,
832
833
  timeoutMs: params.timeoutMs,
834
+ policy: params.policy,
835
+ auditContext: params.auditContext,
833
836
  init: { headers: { "User-Agent": "OpenClaw-Gateway/1.0" } }
834
837
  });
835
838
  try {
@@ -937,7 +940,12 @@ async function extractImageContentFromSource(source, limits) {
937
940
  url: source.url,
938
941
  maxBytes: limits.maxBytes,
939
942
  timeoutMs: limits.timeoutMs,
940
- maxRedirects: limits.maxRedirects
943
+ maxRedirects: limits.maxRedirects,
944
+ policy: {
945
+ allowPrivateNetwork: false,
946
+ hostnameAllowlist: limits.urlAllowlist
947
+ },
948
+ auditContext: "openresponses.input_image"
941
949
  });
942
950
  if (!limits.allowedMimes.has(result.mimeType)) throw new Error(`Unsupported image MIME type from URL: ${result.mimeType}`);
943
951
  return {
@@ -966,7 +974,12 @@ async function extractFileContentFromSource(params) {
966
974
  url: source.url,
967
975
  maxBytes: limits.maxBytes,
968
976
  timeoutMs: limits.timeoutMs,
969
- maxRedirects: limits.maxRedirects
977
+ maxRedirects: limits.maxRedirects,
978
+ policy: {
979
+ allowPrivateNetwork: false,
980
+ hostnameAllowlist: limits.urlAllowlist
981
+ },
982
+ auditContext: "openresponses.input_file"
970
983
  });
971
984
  const parsed = parseContentType(result.contentType);
972
985
  mimeType = parsed.mimeType ?? normalizeMimeType(result.mimeType);
@@ -2599,7 +2612,7 @@ async function createModelSelectionState(params) {
2599
2612
  }
2600
2613
  }
2601
2614
  if (sessionEntry && sessionStore && sessionKey && sessionEntry.authProfileOverride) {
2602
- const { ensureAuthProfileStore } = await import("./model-selection-unMJyUIE.js").then((n) => n.$);
2615
+ const { ensureAuthProfileStore } = await import("./model-selection-BLuqsGVB.js").then((n) => n.$);
2603
2616
  const profile = ensureAuthProfileStore(void 0, { allowKeychainPrompt: false }).profiles[sessionEntry.authProfileOverride];
2604
2617
  const providerKey = normalizeProviderId(provider);
2605
2618
  if (!profile || normalizeProviderId(profile.provider) !== providerKey) await clearSessionAuthProfileOverride({
@@ -6732,260 +6745,6 @@ function getPluginCommandSpecs() {
6732
6745
  }));
6733
6746
  }
6734
6747
 
6735
- //#endregion
6736
- //#region src/plugins/hooks.ts
6737
- /**
6738
- * Get hooks for a specific hook name, sorted by priority (higher first).
6739
- */
6740
- function getHooksForName(registry, hookName) {
6741
- return registry.typedHooks.filter((h) => h.hookName === hookName).toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
6742
- }
6743
- /**
6744
- * Create a hook runner for a specific registry.
6745
- */
6746
- function createHookRunner(registry, options = {}) {
6747
- const logger = options.logger;
6748
- const catchErrors = options.catchErrors ?? true;
6749
- /**
6750
- * Run a hook that doesn't return a value (fire-and-forget style).
6751
- * All handlers are executed in parallel for performance.
6752
- */
6753
- async function runVoidHook(hookName, event, ctx) {
6754
- const hooks = getHooksForName(registry, hookName);
6755
- if (hooks.length === 0) return;
6756
- logger?.debug?.(`[hooks] running ${hookName} (${hooks.length} handlers)`);
6757
- const promises = hooks.map(async (hook) => {
6758
- try {
6759
- await hook.handler(event, ctx);
6760
- } catch (err) {
6761
- const msg = `[hooks] ${hookName} handler from ${hook.pluginId} failed: ${String(err)}`;
6762
- if (catchErrors) logger?.error(msg);
6763
- else throw new Error(msg, { cause: err });
6764
- }
6765
- });
6766
- await Promise.all(promises);
6767
- }
6768
- /**
6769
- * Run a hook that can return a modifying result.
6770
- * Handlers are executed sequentially in priority order, and results are merged.
6771
- */
6772
- async function runModifyingHook(hookName, event, ctx, mergeResults) {
6773
- const hooks = getHooksForName(registry, hookName);
6774
- if (hooks.length === 0) return;
6775
- logger?.debug?.(`[hooks] running ${hookName} (${hooks.length} handlers, sequential)`);
6776
- let result;
6777
- for (const hook of hooks) try {
6778
- const handlerResult = await hook.handler(event, ctx);
6779
- if (handlerResult !== void 0 && handlerResult !== null) if (mergeResults && result !== void 0) result = mergeResults(result, handlerResult);
6780
- else result = handlerResult;
6781
- } catch (err) {
6782
- const msg = `[hooks] ${hookName} handler from ${hook.pluginId} failed: ${String(err)}`;
6783
- if (catchErrors) logger?.error(msg);
6784
- else throw new Error(msg, { cause: err });
6785
- }
6786
- return result;
6787
- }
6788
- /**
6789
- * Run before_agent_start hook.
6790
- * Allows plugins to inject context into the system prompt.
6791
- * Runs sequentially, merging systemPrompt and prependContext from all handlers.
6792
- */
6793
- async function runBeforeAgentStart(event, ctx) {
6794
- return runModifyingHook("before_agent_start", event, ctx, (acc, next) => ({
6795
- systemPrompt: next.systemPrompt ?? acc?.systemPrompt,
6796
- prependContext: acc?.prependContext && next.prependContext ? `${acc.prependContext}\n\n${next.prependContext}` : next.prependContext ?? acc?.prependContext
6797
- }));
6798
- }
6799
- /**
6800
- * Run agent_end hook.
6801
- * Allows plugins to analyze completed conversations.
6802
- * Runs in parallel (fire-and-forget).
6803
- */
6804
- async function runAgentEnd(event, ctx) {
6805
- return runVoidHook("agent_end", event, ctx);
6806
- }
6807
- /**
6808
- * Run before_compaction hook.
6809
- */
6810
- async function runBeforeCompaction(event, ctx) {
6811
- return runVoidHook("before_compaction", event, ctx);
6812
- }
6813
- /**
6814
- * Run after_compaction hook.
6815
- */
6816
- async function runAfterCompaction(event, ctx) {
6817
- return runVoidHook("after_compaction", event, ctx);
6818
- }
6819
- /**
6820
- * Run message_received hook.
6821
- * Runs in parallel (fire-and-forget).
6822
- */
6823
- async function runMessageReceived(event, ctx) {
6824
- return runVoidHook("message_received", event, ctx);
6825
- }
6826
- /**
6827
- * Run message_sending hook.
6828
- * Allows plugins to modify or cancel outgoing messages.
6829
- * Runs sequentially.
6830
- */
6831
- async function runMessageSending(event, ctx) {
6832
- return runModifyingHook("message_sending", event, ctx, (acc, next) => ({
6833
- content: next.content ?? acc?.content,
6834
- cancel: next.cancel ?? acc?.cancel
6835
- }));
6836
- }
6837
- /**
6838
- * Run message_sent hook.
6839
- * Runs in parallel (fire-and-forget).
6840
- */
6841
- async function runMessageSent(event, ctx) {
6842
- return runVoidHook("message_sent", event, ctx);
6843
- }
6844
- /**
6845
- * Run before_tool_call hook.
6846
- * Allows plugins to modify or block tool calls.
6847
- * Runs sequentially.
6848
- */
6849
- async function runBeforeToolCall(event, ctx) {
6850
- return runModifyingHook("before_tool_call", event, ctx, (acc, next) => ({
6851
- params: next.params ?? acc?.params,
6852
- block: next.block ?? acc?.block,
6853
- blockReason: next.blockReason ?? acc?.blockReason
6854
- }));
6855
- }
6856
- /**
6857
- * Run after_tool_call hook.
6858
- * Runs in parallel (fire-and-forget).
6859
- */
6860
- async function runAfterToolCall(event, ctx) {
6861
- return runVoidHook("after_tool_call", event, ctx);
6862
- }
6863
- /**
6864
- * Run tool_result_persist hook.
6865
- *
6866
- * This hook is intentionally synchronous: it runs in hot paths where session
6867
- * transcripts are appended synchronously.
6868
- *
6869
- * Handlers are executed sequentially in priority order (higher first). Each
6870
- * handler may return `{ message }` to replace the message passed to the next
6871
- * handler.
6872
- */
6873
- function runToolResultPersist(event, ctx) {
6874
- const hooks = getHooksForName(registry, "tool_result_persist");
6875
- if (hooks.length === 0) return;
6876
- let current = event.message;
6877
- for (const hook of hooks) try {
6878
- const out = hook.handler({
6879
- ...event,
6880
- message: current
6881
- }, ctx);
6882
- if (out && typeof out.then === "function") {
6883
- const msg = `[hooks] tool_result_persist handler from ${hook.pluginId} returned a Promise; this hook is synchronous and the result was ignored.`;
6884
- if (catchErrors) {
6885
- logger?.warn?.(msg);
6886
- continue;
6887
- }
6888
- throw new Error(msg);
6889
- }
6890
- const next = out?.message;
6891
- if (next) current = next;
6892
- } catch (err) {
6893
- const msg = `[hooks] tool_result_persist handler from ${hook.pluginId} failed: ${String(err)}`;
6894
- if (catchErrors) logger?.error(msg);
6895
- else throw new Error(msg, { cause: err });
6896
- }
6897
- return { message: current };
6898
- }
6899
- /**
6900
- * Run session_start hook.
6901
- * Runs in parallel (fire-and-forget).
6902
- */
6903
- async function runSessionStart(event, ctx) {
6904
- return runVoidHook("session_start", event, ctx);
6905
- }
6906
- /**
6907
- * Run session_end hook.
6908
- * Runs in parallel (fire-and-forget).
6909
- */
6910
- async function runSessionEnd(event, ctx) {
6911
- return runVoidHook("session_end", event, ctx);
6912
- }
6913
- /**
6914
- * Run gateway_start hook.
6915
- * Runs in parallel (fire-and-forget).
6916
- */
6917
- async function runGatewayStart(event, ctx) {
6918
- return runVoidHook("gateway_start", event, ctx);
6919
- }
6920
- /**
6921
- * Run gateway_stop hook.
6922
- * Runs in parallel (fire-and-forget).
6923
- */
6924
- async function runGatewayStop(event, ctx) {
6925
- return runVoidHook("gateway_stop", event, ctx);
6926
- }
6927
- /**
6928
- * Check if any hooks are registered for a given hook name.
6929
- */
6930
- function hasHooks(hookName) {
6931
- return registry.typedHooks.some((h) => h.hookName === hookName);
6932
- }
6933
- /**
6934
- * Get count of registered hooks for a given hook name.
6935
- */
6936
- function getHookCount(hookName) {
6937
- return registry.typedHooks.filter((h) => h.hookName === hookName).length;
6938
- }
6939
- return {
6940
- runBeforeAgentStart,
6941
- runAgentEnd,
6942
- runBeforeCompaction,
6943
- runAfterCompaction,
6944
- runMessageReceived,
6945
- runMessageSending,
6946
- runMessageSent,
6947
- runBeforeToolCall,
6948
- runAfterToolCall,
6949
- runToolResultPersist,
6950
- runSessionStart,
6951
- runSessionEnd,
6952
- runGatewayStart,
6953
- runGatewayStop,
6954
- hasHooks,
6955
- getHookCount
6956
- };
6957
- }
6958
-
6959
- //#endregion
6960
- //#region src/plugins/hook-runner-global.ts
6961
- const log$11 = createSubsystemLogger("plugins");
6962
- let globalHookRunner = null;
6963
- let globalRegistry = null;
6964
- /**
6965
- * Initialize the global hook runner with a plugin registry.
6966
- * Called once when plugins are loaded during gateway startup.
6967
- */
6968
- function initializeGlobalHookRunner(registry) {
6969
- globalRegistry = registry;
6970
- globalHookRunner = createHookRunner(registry, {
6971
- logger: {
6972
- debug: (msg) => log$11.debug(msg),
6973
- warn: (msg) => log$11.warn(msg),
6974
- error: (msg) => log$11.error(msg)
6975
- },
6976
- catchErrors: true
6977
- });
6978
- const hookCount = registry.hooks.length;
6979
- if (hookCount > 0) log$11.info(`hook runner initialized with ${hookCount} registered hooks`);
6980
- }
6981
- /**
6982
- * Get the global hook runner.
6983
- * Returns null if plugins haven't been loaded yet.
6984
- */
6985
- function getGlobalHookRunner() {
6986
- return globalHookRunner;
6987
- }
6988
-
6989
6748
  //#endregion
6990
6749
  //#region src/plugins/http-path.ts
6991
6750
  function normalizePluginHttpPath(path, fallback) {
@@ -7610,7 +7369,7 @@ async function getMemorySearchManager(params) {
7610
7369
  const cached = QMD_MANAGER_CACHE.get(cacheKey);
7611
7370
  if (cached) return { manager: cached };
7612
7371
  try {
7613
- const { QmdMemoryManager } = await import("./qmd-manager-DBCZ1sio.js");
7372
+ const { QmdMemoryManager } = await import("./qmd-manager-RMRE8Tqt.js");
7614
7373
  const primary = await QmdMemoryManager.create({
7615
7374
  cfg: params.cfg,
7616
7375
  agentId: params.agentId,
@@ -7620,7 +7379,7 @@ async function getMemorySearchManager(params) {
7620
7379
  const wrapper = new FallbackMemoryManager({
7621
7380
  primary,
7622
7381
  fallbackFactory: async () => {
7623
- const { MemoryIndexManager } = await import("./manager-DScY_ZTT.js").then((n) => n.t);
7382
+ const { MemoryIndexManager } = await import("./manager-DkqF1GiK.js").then((n) => n.t);
7624
7383
  return await MemoryIndexManager.get(params);
7625
7384
  }
7626
7385
  }, () => QMD_MANAGER_CACHE.delete(cacheKey));
@@ -7633,7 +7392,7 @@ async function getMemorySearchManager(params) {
7633
7392
  }
7634
7393
  }
7635
7394
  try {
7636
- const { MemoryIndexManager } = await import("./manager-DScY_ZTT.js").then((n) => n.t);
7395
+ const { MemoryIndexManager } = await import("./manager-DkqF1GiK.js").then((n) => n.t);
7637
7396
  return { manager: await MemoryIndexManager.get(params) };
7638
7397
  } catch (err) {
7639
7398
  return {
@@ -9525,7 +9284,13 @@ async function runAgentStep(params) {
9525
9284
  deliver: false,
9526
9285
  channel: params.channel ?? INTERNAL_MESSAGE_CHANNEL,
9527
9286
  lane: params.lane ?? AGENT_LANE_NESTED,
9528
- extraSystemPrompt: params.extraSystemPrompt
9287
+ extraSystemPrompt: params.extraSystemPrompt,
9288
+ inputProvenance: {
9289
+ kind: "inter_session",
9290
+ sourceSessionKey: params.sourceSessionKey,
9291
+ sourceChannel: params.sourceChannel,
9292
+ sourceTool: params.sourceTool ?? "sessions_send"
9293
+ }
9529
9294
  },
9530
9295
  timeoutMs: 1e4
9531
9296
  });
@@ -9664,7 +9429,12 @@ async function buildSubagentStatsLine(params) {
9664
9429
  const cfg = loadConfig();
9665
9430
  const { entry, storePath } = await waitForSessionUsage({ sessionKey: params.sessionKey });
9666
9431
  const sessionId = entry?.sessionId;
9667
- const transcriptPath = sessionId && storePath ? path.join(path.dirname(storePath), `${sessionId}.jsonl`) : void 0;
9432
+ let transcriptPath;
9433
+ if (sessionId && storePath) try {
9434
+ transcriptPath = resolveSessionFilePath(sessionId, entry, { sessionsDir: path.dirname(storePath) });
9435
+ } catch {
9436
+ transcriptPath = void 0;
9437
+ }
9668
9438
  const input = entry?.inputTokens;
9669
9439
  const output = entry?.outputTokens;
9670
9440
  const total = entry?.totalTokens ?? (typeof input === "number" && typeof output === "number" ? input + output : void 0);
@@ -11226,7 +10996,7 @@ async function routeReply(params) {
11226
10996
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
11227
10997
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
11228
10998
  try {
11229
- const { deliverOutboundPayloads } = await import("./deliver-B1jsU2r7.js").then((n) => n.n);
10999
+ const { deliverOutboundPayloads } = await import("./deliver-LsxKETro.js").then((n) => n.n);
11230
11000
  return {
11231
11001
  ok: true,
11232
11002
  messageId: (await deliverOutboundPayloads({
@@ -12018,6 +11788,8 @@ function rebalanceReasoningItalics(source, chunks) {
12018
11788
  //#endregion
12019
11789
  //#region src/discord/send.permissions.ts
12020
11790
  const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter(([, value]) => typeof value === "bigint");
11791
+ const ALL_PERMISSIONS = PERMISSION_ENTRIES.reduce((acc, [, value]) => acc | value, 0n);
11792
+ const ADMINISTRATOR_BIT = PermissionFlagsBits.Administrator;
12021
11793
  function resolveToken$4(params) {
12022
11794
  const explicit = normalizeDiscordToken(params.explicit);
12023
11795
  if (explicit) return explicit;
@@ -12050,6 +11822,9 @@ function removePermissionBits(base, deny) {
12050
11822
  function bitfieldToPermissions(bitfield) {
12051
11823
  return PERMISSION_ENTRIES.filter(([, value]) => (bitfield & value) === value).map(([name]) => name).toSorted();
12052
11824
  }
11825
+ function hasAdministrator(bitfield) {
11826
+ return (bitfield & ADMINISTRATOR_BIT) === ADMINISTRATOR_BIT;
11827
+ }
12053
11828
  function isThreadChannelType$1(channelType) {
12054
11829
  return channelType === ChannelType.GuildNewsThread || channelType === ChannelType.GuildPublicThread || channelType === ChannelType.GuildPrivateThread;
12055
11830
  }
@@ -12080,6 +11855,14 @@ async function fetchChannelPermissionsDiscord(channelId, opts = {}) {
12080
11855
  const role = rolesById.get(roleId);
12081
11856
  if (role?.permissions) base = addPermissionBits(base, role.permissions);
12082
11857
  }
11858
+ if (hasAdministrator(base)) return {
11859
+ channelId,
11860
+ guildId,
11861
+ permissions: bitfieldToPermissions(ALL_PERMISSIONS),
11862
+ raw: ALL_PERMISSIONS.toString(),
11863
+ isDm: false,
11864
+ channelType
11865
+ };
12083
11866
  let permissions = base;
12084
11867
  const overwrites = "permission_overwrites" in channel ? channel.permission_overwrites ?? [] : [];
12085
11868
  for (const overwrite of overwrites) if (overwrite.id === guildId) {
@@ -12292,6 +12075,28 @@ function resolveDiscordUserAllowed(params) {
12292
12075
  tag: params.userTag
12293
12076
  });
12294
12077
  }
12078
+ function resolveDiscordRoleAllowed(params) {
12079
+ const allowList = normalizeDiscordAllowList(params.allowList, ["role:"]);
12080
+ if (!allowList) return true;
12081
+ if (allowList.allowAll) return true;
12082
+ return params.memberRoleIds.some((roleId) => allowList.ids.has(roleId));
12083
+ }
12084
+ function resolveDiscordMemberAllowed(params) {
12085
+ const hasUserRestriction = Array.isArray(params.userAllowList) && params.userAllowList.length > 0;
12086
+ const hasRoleRestriction = Array.isArray(params.roleAllowList) && params.roleAllowList.length > 0;
12087
+ if (!hasUserRestriction && !hasRoleRestriction) return true;
12088
+ const userOk = hasUserRestriction ? resolveDiscordUserAllowed({
12089
+ allowList: params.userAllowList,
12090
+ userId: params.userId,
12091
+ userName: params.userName,
12092
+ userTag: params.userTag
12093
+ }) : false;
12094
+ const roleOk = hasRoleRestriction ? resolveDiscordRoleAllowed({
12095
+ allowList: params.roleAllowList,
12096
+ memberRoleIds: params.memberRoleIds
12097
+ }) : false;
12098
+ return userOk || roleOk;
12099
+ }
12295
12100
  function resolveDiscordOwnerAllowFrom(params) {
12296
12101
  const rawAllowList = params.channelConfig?.users ?? params.guildInfo?.users;
12297
12102
  if (!Array.isArray(rawAllowList) || rawAllowList.length === 0) return;
@@ -12355,6 +12160,7 @@ function resolveDiscordChannelConfigEntry(entry) {
12355
12160
  skills: entry.skills,
12356
12161
  enabled: entry.enabled,
12357
12162
  users: entry.users,
12163
+ roles: entry.roles,
12358
12164
  systemPrompt: entry.systemPrompt,
12359
12165
  includeThreadStarter: entry.includeThreadStarter,
12360
12166
  autoThread: entry.autoThread
@@ -12773,13 +12579,14 @@ async function sendDiscordMedia(rest, channelId, text, mediaUrl, replyTo, reques
12773
12579
  chunkMode
12774
12580
  }) : [];
12775
12581
  const caption = chunks[0] ?? "";
12582
+ const hasCaption = caption.trim().length > 0;
12776
12583
  const messageReference = replyTo ? {
12777
12584
  message_id: replyTo,
12778
12585
  fail_if_not_exists: false
12779
12586
  } : void 0;
12780
12587
  const res = await request(() => rest.post(Routes.channelMessages(channelId), { body: {
12781
- content: caption || void 0,
12782
- message_reference: messageReference,
12588
+ ...hasCaption ? { content: caption } : {},
12589
+ ...messageReference ? { message_reference: messageReference } : {},
12783
12590
  ...embeds?.length ? { embeds } : {},
12784
12591
  files: [{
12785
12592
  data: media.buffer,
@@ -12821,6 +12628,9 @@ async function editChannelDiscord(payload, opts = {}) {
12821
12628
  if (payload.parentId !== void 0) body.parent_id = payload.parentId;
12822
12629
  if (payload.nsfw !== void 0) body.nsfw = payload.nsfw;
12823
12630
  if (payload.rateLimitPerUser !== void 0) body.rate_limit_per_user = payload.rateLimitPerUser;
12631
+ if (payload.archived !== void 0) body.archived = payload.archived;
12632
+ if (payload.locked !== void 0) body.locked = payload.locked;
12633
+ if (payload.autoArchiveDuration !== void 0) body.auto_archive_duration = payload.autoArchiveDuration;
12824
12634
  return await rest.patch(Routes.channel(payload.channelId), { body });
12825
12635
  }
12826
12636
  async function deleteChannelDiscord(channelId, opts = {}) {
@@ -13479,6 +13289,9 @@ async function handleDiscordGuildAction(action, params, isActionEnabled) {
13479
13289
  const parentId = readParentIdParam$1(params);
13480
13290
  const nsfw = params.nsfw;
13481
13291
  const rateLimitPerUser = readNumberParam(params, "rateLimitPerUser", { integer: true });
13292
+ const archived = typeof params.archived === "boolean" ? params.archived : void 0;
13293
+ const locked = typeof params.locked === "boolean" ? params.locked : void 0;
13294
+ const autoArchiveDuration = readNumberParam(params, "autoArchiveDuration", { integer: true });
13482
13295
  return jsonResult({
13483
13296
  ok: true,
13484
13297
  channel: accountId ? await editChannelDiscord({
@@ -13488,7 +13301,10 @@ async function handleDiscordGuildAction(action, params, isActionEnabled) {
13488
13301
  position: position ?? void 0,
13489
13302
  parentId,
13490
13303
  nsfw,
13491
- rateLimitPerUser: rateLimitPerUser ?? void 0
13304
+ rateLimitPerUser: rateLimitPerUser ?? void 0,
13305
+ archived,
13306
+ locked,
13307
+ autoArchiveDuration: autoArchiveDuration ?? void 0
13492
13308
  }, { accountId }) : await editChannelDiscord({
13493
13309
  channelId,
13494
13310
  name: name ?? void 0,
@@ -13496,7 +13312,10 @@ async function handleDiscordGuildAction(action, params, isActionEnabled) {
13496
13312
  position: position ?? void 0,
13497
13313
  parentId,
13498
13314
  nsfw,
13499
- rateLimitPerUser: rateLimitPerUser ?? void 0
13315
+ rateLimitPerUser: rateLimitPerUser ?? void 0,
13316
+ archived,
13317
+ locked,
13318
+ autoArchiveDuration: autoArchiveDuration ?? void 0
13500
13319
  })
13501
13320
  });
13502
13321
  }
@@ -14248,6 +14067,9 @@ async function tryHandleDiscordMessageActionGuildAdmin(params) {
14248
14067
  const parentId = readParentIdParam(actionParams);
14249
14068
  const nsfw = typeof actionParams.nsfw === "boolean" ? actionParams.nsfw : void 0;
14250
14069
  const rateLimitPerUser = readNumberParam(actionParams, "rateLimitPerUser", { integer: true });
14070
+ const archived = typeof actionParams.archived === "boolean" ? actionParams.archived : void 0;
14071
+ const locked = typeof actionParams.locked === "boolean" ? actionParams.locked : void 0;
14072
+ const autoArchiveDuration = readNumberParam(actionParams, "autoArchiveDuration", { integer: true });
14251
14073
  return await handleDiscordAction({
14252
14074
  action: "channelEdit",
14253
14075
  accountId: accountId ?? void 0,
@@ -14257,7 +14079,10 @@ async function tryHandleDiscordMessageActionGuildAdmin(params) {
14257
14079
  position: position ?? void 0,
14258
14080
  parentId: parentId === void 0 ? void 0 : parentId,
14259
14081
  nsfw,
14260
- rateLimitPerUser: rateLimitPerUser ?? void 0
14082
+ rateLimitPerUser: rateLimitPerUser ?? void 0,
14083
+ archived,
14084
+ locked,
14085
+ autoArchiveDuration: autoArchiveDuration ?? void 0
14261
14086
  }, cfg);
14262
14087
  }
14263
14088
  if (action === "channel-delete") {
@@ -16221,7 +16046,7 @@ async function describeStickerImage(params) {
16221
16046
  logVerbose(`telegram: describing sticker with ${provider}/${model}`);
16222
16047
  try {
16223
16048
  const buffer = await fs$1.readFile(imagePath);
16224
- const { describeImageWithModel } = await import("./image-DI9s9eEx.js").then((n) => n.n);
16049
+ const { describeImageWithModel } = await import("./image-C4Nn2p3e.js").then((n) => n.n);
16225
16050
  return (await describeImageWithModel({
16226
16051
  buffer,
16227
16052
  fileName: "sticker.webp",
@@ -16583,7 +16408,7 @@ function createWhatsAppLoginTool() {
16583
16408
  force: Type.Optional(Type.Boolean())
16584
16409
  }),
16585
16410
  execute: async (_toolCallId, args) => {
16586
- const { startWebLoginWithQr, waitForWebLogin } = await import("./login-qr-Xx8yJrSc.js").then((n) => n.t);
16411
+ const { startWebLoginWithQr, waitForWebLogin } = await import("./login-qr-B6ZgAuIf.js").then((n) => n.t);
16587
16412
  if ((args?.action ?? "start") === "wait") {
16588
16413
  const result = await waitForWebLogin({ timeoutMs: typeof args.timeoutMs === "number" ? args.timeoutMs : void 0 });
16589
16414
  return {
@@ -16985,6 +16810,11 @@ function matchesTeam(match, teamId) {
16985
16810
  if (!id) return false;
16986
16811
  return id === teamId;
16987
16812
  }
16813
+ function matchesRoles(match, memberRoleIds) {
16814
+ const roles = match?.roles;
16815
+ if (!Array.isArray(roles) || roles.length === 0) return false;
16816
+ return roles.some((role) => memberRoleIds.includes(role));
16817
+ }
16988
16818
  function resolveAgentRoute(input) {
16989
16819
  const channel = normalizeToken(input.channel);
16990
16820
  const accountId = normalizeAccountId$2(input.accountId);
@@ -16994,6 +16824,7 @@ function resolveAgentRoute(input) {
16994
16824
  } : null;
16995
16825
  const guildId = normalizeId(input.guildId);
16996
16826
  const teamId = normalizeId(input.teamId);
16827
+ const memberRoleIds = input.memberRoleIds ?? [];
16997
16828
  const bindings = listBindings(input.cfg).filter((binding) => {
16998
16829
  if (!binding || typeof binding !== "object") return false;
16999
16830
  if (!matchesChannel(binding.match, channel)) return false;
@@ -17034,8 +16865,12 @@ function resolveAgentRoute(input) {
17034
16865
  const parentPeerMatch = bindings.find((b) => matchesPeer(b.match, parentPeer));
17035
16866
  if (parentPeerMatch) return choose(parentPeerMatch.agentId, "binding.peer.parent");
17036
16867
  }
16868
+ if (guildId && memberRoleIds.length > 0) {
16869
+ const guildRolesMatch = bindings.find((b) => matchesGuild(b.match, guildId) && matchesRoles(b.match, memberRoleIds));
16870
+ if (guildRolesMatch) return choose(guildRolesMatch.agentId, "binding.guild+roles");
16871
+ }
17037
16872
  if (guildId) {
17038
- const guildMatch = bindings.find((b) => matchesGuild(b.match, guildId));
16873
+ const guildMatch = bindings.find((b) => matchesGuild(b.match, guildId) && (!Array.isArray(b.match?.roles) || b.match.roles.length === 0));
17039
16874
  if (guildMatch) return choose(guildMatch.agentId, "binding.guild");
17040
16875
  }
17041
16876
  if (teamId) {
@@ -19941,17 +19776,19 @@ async function handleDiscordReactionEvent(params) {
19941
19776
  if (!("user" in data)) return;
19942
19777
  const user = data.user;
19943
19778
  if (!user || user.bot) return;
19944
- if (!data.guild_id) return;
19945
- const guildInfo = resolveDiscordGuildEntry({
19779
+ const isGuildMessage = Boolean(data.guild_id);
19780
+ const guildInfo = isGuildMessage ? resolveDiscordGuildEntry({
19946
19781
  guild: data.guild ?? void 0,
19947
19782
  guildEntries
19948
- });
19949
- if (guildEntries && Object.keys(guildEntries).length > 0 && !guildInfo) return;
19783
+ }) : null;
19784
+ if (isGuildMessage && guildEntries && Object.keys(guildEntries).length > 0 && !guildInfo) return;
19950
19785
  const channel = await client.fetchChannel(data.channel_id);
19951
19786
  if (!channel) return;
19952
19787
  const channelName = "name" in channel ? channel.name ?? void 0 : void 0;
19953
19788
  const channelSlug = channelName ? normalizeDiscordSlug(channelName) : "";
19954
19789
  const channelType = "type" in channel ? channel.type : void 0;
19790
+ const isDirectMessage = channelType === ChannelType$1.DM;
19791
+ const isGroupDm = channelType === ChannelType$1.GroupDM;
19955
19792
  const isThreadChannel = channelType === ChannelType$1.PublicThread || channelType === ChannelType$1.PrivateThread || channelType === ChannelType$1.AnnouncementThread;
19956
19793
  let parentId = "parentId" in channel ? channel.parentId ?? void 0 : void 0;
19957
19794
  let parentName;
@@ -19987,19 +19824,22 @@ async function handleDiscordReactionEvent(params) {
19987
19824
  })) return;
19988
19825
  const emojiLabel = formatDiscordReactionEmoji(data.emoji);
19989
19826
  const actorLabel = formatDiscordUserTag(user);
19990
- const guildSlug = guildInfo?.slug || (data.guild?.name ? normalizeDiscordSlug(data.guild.name) : data.guild_id);
19827
+ const guildSlug = guildInfo?.slug || (data.guild?.name ? normalizeDiscordSlug(data.guild.name) : data.guild_id ?? (isGroupDm ? "group-dm" : "dm"));
19991
19828
  const channelLabel = channelSlug ? `#${channelSlug}` : channelName ? `#${normalizeDiscordSlug(channelName)}` : `#${data.channel_id}`;
19992
19829
  const authorLabel = message?.author ? formatDiscordUserTag(message.author) : void 0;
19993
19830
  const baseText = `Discord reaction ${action}: ${emojiLabel} by ${actorLabel} on ${guildSlug} ${channelLabel} msg ${data.message_id}`;
19994
- enqueueSystemEvent(authorLabel ? `${baseText} from ${authorLabel}` : baseText, {
19831
+ const text = authorLabel ? `${baseText} from ${authorLabel}` : baseText;
19832
+ const memberRoleIds = Array.isArray(data.member?.roles) ? data.member.roles.map((roleId) => String(roleId)) : [];
19833
+ enqueueSystemEvent(text, {
19995
19834
  sessionKey: resolveAgentRoute({
19996
19835
  cfg: params.cfg,
19997
19836
  channel: "discord",
19998
19837
  accountId: params.accountId,
19999
19838
  guildId: data.guild_id ?? void 0,
19839
+ memberRoleIds,
20000
19840
  peer: {
20001
- kind: "channel",
20002
- id: data.channel_id
19841
+ kind: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
19842
+ id: isDirectMessage ? user.id : data.channel_id
20003
19843
  },
20004
19844
  parentPeer: parentId ? {
20005
19845
  kind: "channel",
@@ -20146,19 +19986,16 @@ function createReplyReferencePlanner(options) {
20146
19986
  const startId = options.startId?.trim();
20147
19987
  const use = () => {
20148
19988
  if (!allowReference) return;
20149
- if (existingId) {
20150
- hasReplied = true;
20151
- return existingId;
20152
- }
20153
- if (!startId) return;
20154
19989
  if (options.replyToMode === "off") return;
19990
+ const id = existingId ?? startId;
19991
+ if (!id) return;
20155
19992
  if (options.replyToMode === "all") {
20156
19993
  hasReplied = true;
20157
- return startId;
19994
+ return id;
20158
19995
  }
20159
19996
  if (!hasReplied) {
20160
19997
  hasReplied = true;
20161
- return startId;
19998
+ return id;
20162
19999
  }
20163
20000
  };
20164
20001
  const markSent = () => {
@@ -20173,7 +20010,35 @@ function createReplyReferencePlanner(options) {
20173
20010
 
20174
20011
  //#endregion
20175
20012
  //#region src/discord/monitor/threading.ts
20013
+ const DISCORD_THREAD_STARTER_CACHE_TTL_MS = 300 * 1e3;
20014
+ const DISCORD_THREAD_STARTER_CACHE_MAX = 500;
20176
20015
  const DISCORD_THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
20016
+ function getCachedThreadStarter(key, now) {
20017
+ const entry = DISCORD_THREAD_STARTER_CACHE.get(key);
20018
+ if (!entry) return;
20019
+ if (now - entry.updatedAt > DISCORD_THREAD_STARTER_CACHE_TTL_MS) {
20020
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
20021
+ return;
20022
+ }
20023
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
20024
+ DISCORD_THREAD_STARTER_CACHE.set(key, {
20025
+ ...entry,
20026
+ updatedAt: now
20027
+ });
20028
+ return entry.value;
20029
+ }
20030
+ function setCachedThreadStarter(key, value, now) {
20031
+ DISCORD_THREAD_STARTER_CACHE.delete(key);
20032
+ DISCORD_THREAD_STARTER_CACHE.set(key, {
20033
+ value,
20034
+ updatedAt: now
20035
+ });
20036
+ while (DISCORD_THREAD_STARTER_CACHE.size > DISCORD_THREAD_STARTER_CACHE_MAX) {
20037
+ const iter = DISCORD_THREAD_STARTER_CACHE.keys().next();
20038
+ if (iter.done) break;
20039
+ DISCORD_THREAD_STARTER_CACHE.delete(iter.value);
20040
+ }
20041
+ }
20177
20042
  function isDiscordThreadType(type) {
20178
20043
  return type === ChannelType$1.PublicThread || type === ChannelType$1.PrivateThread || type === ChannelType$1.AnnouncementThread;
20179
20044
  }
@@ -20207,7 +20072,7 @@ async function resolveDiscordThreadParentInfo(params) {
20207
20072
  }
20208
20073
  async function resolveDiscordThreadStarter(params) {
20209
20074
  const cacheKey = params.channel.id;
20210
- const cached = DISCORD_THREAD_STARTER_CACHE.get(cacheKey);
20075
+ const cached = getCachedThreadStarter(cacheKey, Date.now());
20211
20076
  if (cached) return cached;
20212
20077
  try {
20213
20078
  const parentType = params.parentType;
@@ -20222,7 +20087,7 @@ async function resolveDiscordThreadStarter(params) {
20222
20087
  author: starter.member?.nick ?? starter.member?.displayName ?? (starter.author ? starter.author.discriminator && starter.author.discriminator !== "0" ? `${starter.author.username ?? "Unknown"}#${starter.author.discriminator}` : starter.author.username ?? starter.author.id ?? "Unknown" : "Unknown"),
20223
20088
  timestamp: params.resolveTimestampMs(starter.timestamp) ?? void 0
20224
20089
  };
20225
- DISCORD_THREAD_STARTER_CACHE.set(cacheKey, payload);
20090
+ setCachedThreadStarter(cacheKey, payload, Date.now());
20226
20091
  return payload;
20227
20092
  } catch {
20228
20093
  return null;
@@ -20456,11 +20321,13 @@ async function preflightDiscordMessage(params) {
20456
20321
  earlyThreadParentName = parentInfo.name;
20457
20322
  earlyThreadParentType = parentInfo.type;
20458
20323
  }
20324
+ const memberRoleIds = Array.isArray(params.data.member?.roles) ? params.data.member.roles.map((roleId) => String(roleId)) : [];
20459
20325
  const route = resolveAgentRoute({
20460
20326
  cfg: loadConfig(),
20461
20327
  channel: "discord",
20462
20328
  accountId: params.accountId,
20463
20329
  guildId: params.data.guild_id ?? void 0,
20330
+ memberRoleIds,
20464
20331
  peer: {
20465
20332
  kind: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
20466
20333
  id: isDirectMessage ? author.id : message.channelId
@@ -20557,7 +20424,7 @@ async function preflightDiscordMessage(params) {
20557
20424
  let preflightTranscript;
20558
20425
  const hasAudioAttachment = message.attachments?.some((att) => att.contentType?.startsWith("audio/"));
20559
20426
  if (!isDirectMessage && shouldRequireMention && hasAudioAttachment && !baseText && mentionRegexes.length > 0) try {
20560
- const { transcribeFirstAudio } = await import("./audio-preflight-txAP3v-C.js");
20427
+ const { transcribeFirstAudio } = await import("./audio-preflight-SLmkJI6-.js");
20561
20428
  const audioPaths = message.attachments?.filter((att) => att.contentType?.startsWith("audio/")).map((att) => att.url) ?? [];
20562
20429
  if (audioPaths.length > 0) preflightTranscript = await transcribeFirstAudio({
20563
20430
  ctx: {
@@ -20587,6 +20454,17 @@ async function preflightDiscordMessage(params) {
20587
20454
  surface: "discord"
20588
20455
  });
20589
20456
  const hasControlCommandInMessage = hasControlCommand(baseText, params.cfg);
20457
+ const channelUsers = channelConfig?.users ?? guildInfo?.users;
20458
+ const channelRoles = channelConfig?.roles ?? guildInfo?.roles;
20459
+ const hasAccessRestrictions = Array.isArray(channelUsers) && channelUsers.length > 0 || Array.isArray(channelRoles) && channelRoles.length > 0;
20460
+ const memberAllowed = resolveDiscordMemberAllowed({
20461
+ userAllowList: channelUsers,
20462
+ roleAllowList: channelRoles,
20463
+ memberRoleIds,
20464
+ userId: sender.id,
20465
+ userName: sender.name,
20466
+ userTag: sender.tag
20467
+ });
20590
20468
  if (!isDirectMessage) {
20591
20469
  const ownerAllowList = normalizeDiscordAllowList(params.allowFrom, [
20592
20470
  "discord:",
@@ -20598,21 +20476,14 @@ async function preflightDiscordMessage(params) {
20598
20476
  name: sender.name,
20599
20477
  tag: sender.tag
20600
20478
  }) : false;
20601
- const channelUsers = channelConfig?.users ?? guildInfo?.users;
20602
- const usersOk = Array.isArray(channelUsers) && channelUsers.length > 0 ? resolveDiscordUserAllowed({
20603
- allowList: channelUsers,
20604
- userId: sender.id,
20605
- userName: sender.name,
20606
- userTag: sender.tag
20607
- }) : false;
20608
20479
  const commandGate = resolveControlCommandGate({
20609
20480
  useAccessGroups: params.cfg.commands?.useAccessGroups !== false,
20610
20481
  authorizers: [{
20611
20482
  configured: ownerAllowList != null,
20612
20483
  allowed: ownerOk
20613
20484
  }, {
20614
- configured: Array.isArray(channelUsers) && channelUsers.length > 0,
20615
- allowed: usersOk
20485
+ configured: hasAccessRestrictions,
20486
+ allowed: memberAllowed
20616
20487
  }],
20617
20488
  modeWhenAccessGroupsOff: "configured",
20618
20489
  allowTextCommands,
@@ -20658,19 +20529,9 @@ async function preflightDiscordMessage(params) {
20658
20529
  return null;
20659
20530
  }
20660
20531
  }
20661
- if (isGuildMessage) {
20662
- const channelUsers = channelConfig?.users ?? guildInfo?.users;
20663
- if (Array.isArray(channelUsers) && channelUsers.length > 0) {
20664
- if (!resolveDiscordUserAllowed({
20665
- allowList: channelUsers,
20666
- userId: sender.id,
20667
- userName: sender.name,
20668
- userTag: sender.tag
20669
- })) {
20670
- logVerbose(`Blocked discord guild sender ${sender.id} (not in channel users allowlist)`);
20671
- return null;
20672
- }
20673
- }
20532
+ if (isGuildMessage && hasAccessRestrictions && !memberAllowed) {
20533
+ logVerbose(`Blocked discord guild sender ${sender.id} (not in users/roles allowlist)`);
20534
+ return null;
20674
20535
  }
20675
20536
  const systemText = resolveDiscordSystemEvent(message, resolveDiscordSystemLocation({
20676
20537
  isDirectMessage,
@@ -20826,6 +20687,7 @@ const EXTERNAL_SOURCE_LABELS = {
20826
20687
  email: "Email",
20827
20688
  webhook: "Webhook",
20828
20689
  api: "API",
20690
+ browser: "Browser",
20829
20691
  channel_metadata: "Channel metadata",
20830
20692
  web_search: "Web Search",
20831
20693
  web_fetch: "Web Fetch",
@@ -21767,6 +21629,7 @@ async function dispatchDiscordCommandInteraction(params) {
21767
21629
  const channelName = channel && "name" in channel ? channel.name : void 0;
21768
21630
  const channelSlug = channelName ? normalizeDiscordSlug(channelName) : "";
21769
21631
  const rawChannelId = channel?.id ?? "";
21632
+ const memberRoleIds = Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles.map((roleId) => String(roleId)) : [];
21770
21633
  const ownerAllowList = normalizeDiscordAllowList(discordConfig?.dm?.allowFrom ?? [], [
21771
21634
  "discord:",
21772
21635
  "user:",
@@ -21874,24 +21737,27 @@ async function dispatchDiscordCommandInteraction(params) {
21874
21737
  }
21875
21738
  if (!isDirectMessage) {
21876
21739
  const channelUsers = channelConfig?.users ?? guildInfo?.users;
21877
- const hasUserAllowlist = Array.isArray(channelUsers) && channelUsers.length > 0;
21878
- const userOk = hasUserAllowlist ? resolveDiscordUserAllowed({
21879
- allowList: channelUsers,
21740
+ const channelRoles = channelConfig?.roles ?? guildInfo?.roles;
21741
+ const hasAccessRestrictions = Array.isArray(channelUsers) && channelUsers.length > 0 || Array.isArray(channelRoles) && channelRoles.length > 0;
21742
+ const memberAllowed = resolveDiscordMemberAllowed({
21743
+ userAllowList: channelUsers,
21744
+ roleAllowList: channelRoles,
21745
+ memberRoleIds,
21880
21746
  userId: sender.id,
21881
21747
  userName: sender.name,
21882
21748
  userTag: sender.tag
21883
- }) : false;
21749
+ });
21884
21750
  commandAuthorized = resolveCommandAuthorizedFromAuthorizers({
21885
21751
  useAccessGroups,
21886
21752
  authorizers: useAccessGroups ? [{
21887
21753
  configured: ownerAllowList != null,
21888
21754
  allowed: ownerOk
21889
21755
  }, {
21890
- configured: hasUserAllowlist,
21891
- allowed: userOk
21756
+ configured: hasAccessRestrictions,
21757
+ allowed: memberAllowed
21892
21758
  }] : [{
21893
- configured: hasUserAllowlist,
21894
- allowed: userOk
21759
+ configured: hasAccessRestrictions,
21760
+ allowed: memberAllowed
21895
21761
  }],
21896
21762
  modeWhenAccessGroupsOff: "configured"
21897
21763
  });
@@ -21942,6 +21808,7 @@ async function dispatchDiscordCommandInteraction(params) {
21942
21808
  channel: "discord",
21943
21809
  accountId,
21944
21810
  guildId: interaction.guild?.id ?? void 0,
21811
+ memberRoleIds,
21945
21812
  peer: {
21946
21813
  kind: isDirectMessage ? "direct" : isGroupDm ? "group" : "channel",
21947
21814
  id: isDirectMessage ? user.id : channelId
@@ -23414,6 +23281,7 @@ var AgentComponentButton = class extends Button {
23414
23281
  const userId = user.id;
23415
23282
  const rawGuildId = interaction.rawData.guild_id;
23416
23283
  const isDirectMessage = !rawGuildId;
23284
+ const memberRoleIds = Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles.map((roleId) => String(roleId)) : [];
23417
23285
  if (isDirectMessage) {
23418
23286
  if (!await ensureDmComponentAuthorized({
23419
23287
  ctx: this.ctx,
@@ -23445,7 +23313,7 @@ var AgentComponentButton = class extends Button {
23445
23313
  }
23446
23314
  }
23447
23315
  if (rawGuildId) {
23448
- const channelUsers = resolveDiscordChannelConfigWithFallback({
23316
+ const channelConfig = resolveDiscordChannelConfigWithFallback({
23449
23317
  guildInfo,
23450
23318
  channelId,
23451
23319
  channelName,
@@ -23454,23 +23322,23 @@ var AgentComponentButton = class extends Button {
23454
23322
  parentName,
23455
23323
  parentSlug,
23456
23324
  scope: isThread ? "thread" : "channel"
23457
- })?.users ?? guildInfo?.users;
23458
- if (Array.isArray(channelUsers) && channelUsers.length > 0) {
23459
- if (!resolveDiscordUserAllowed({
23460
- allowList: channelUsers,
23461
- userId,
23462
- userName: user.username,
23463
- userTag: user.discriminator ? `${user.username}#${user.discriminator}` : void 0
23464
- })) {
23465
- logVerbose(`agent button: blocked user ${userId} (not in allowlist)`);
23466
- try {
23467
- await interaction.reply({
23468
- content: "You are not authorized to use this button.",
23469
- ephemeral: true
23470
- });
23471
- } catch {}
23472
- return;
23473
- }
23325
+ });
23326
+ if (!resolveDiscordMemberAllowed({
23327
+ userAllowList: channelConfig?.users ?? guildInfo?.users,
23328
+ roleAllowList: channelConfig?.roles ?? guildInfo?.roles,
23329
+ memberRoleIds,
23330
+ userId,
23331
+ userName: user.username,
23332
+ userTag: user.discriminator ? `${user.username}#${user.discriminator}` : void 0
23333
+ })) {
23334
+ logVerbose(`agent button: blocked user ${userId} (not in users/roles allowlist)`);
23335
+ try {
23336
+ await interaction.reply({
23337
+ content: "You are not authorized to use this button.",
23338
+ ephemeral: true
23339
+ });
23340
+ } catch {}
23341
+ return;
23474
23342
  }
23475
23343
  }
23476
23344
  const route = resolveAgentRoute({
@@ -23478,6 +23346,7 @@ var AgentComponentButton = class extends Button {
23478
23346
  channel: "discord",
23479
23347
  accountId: this.ctx.accountId,
23480
23348
  guildId: rawGuildId,
23349
+ memberRoleIds,
23481
23350
  peer: {
23482
23351
  kind: isDirectMessage ? "direct" : "channel",
23483
23352
  id: isDirectMessage ? userId : channelId
@@ -23537,6 +23406,7 @@ var AgentSelectMenu = class extends StringSelectMenu {
23537
23406
  const userId = user.id;
23538
23407
  const rawGuildId = interaction.rawData.guild_id;
23539
23408
  const isDirectMessage = !rawGuildId;
23409
+ const memberRoleIds = Array.isArray(interaction.rawData.member?.roles) ? interaction.rawData.member.roles.map((roleId) => String(roleId)) : [];
23540
23410
  if (isDirectMessage) {
23541
23411
  if (!await ensureDmComponentAuthorized({
23542
23412
  ctx: this.ctx,
@@ -23568,7 +23438,7 @@ var AgentSelectMenu = class extends StringSelectMenu {
23568
23438
  }
23569
23439
  }
23570
23440
  if (rawGuildId) {
23571
- const channelUsers = resolveDiscordChannelConfigWithFallback({
23441
+ const channelConfig = resolveDiscordChannelConfigWithFallback({
23572
23442
  guildInfo,
23573
23443
  channelId,
23574
23444
  channelName,
@@ -23577,23 +23447,23 @@ var AgentSelectMenu = class extends StringSelectMenu {
23577
23447
  parentName,
23578
23448
  parentSlug,
23579
23449
  scope: isThread ? "thread" : "channel"
23580
- })?.users ?? guildInfo?.users;
23581
- if (Array.isArray(channelUsers) && channelUsers.length > 0) {
23582
- if (!resolveDiscordUserAllowed({
23583
- allowList: channelUsers,
23584
- userId,
23585
- userName: user.username,
23586
- userTag: user.discriminator ? `${user.username}#${user.discriminator}` : void 0
23587
- })) {
23588
- logVerbose(`agent select: blocked user ${userId} (not in allowlist)`);
23589
- try {
23590
- await interaction.reply({
23591
- content: "You are not authorized to use this select menu.",
23592
- ephemeral: true
23593
- });
23594
- } catch {}
23595
- return;
23596
- }
23450
+ });
23451
+ if (!resolveDiscordMemberAllowed({
23452
+ userAllowList: channelConfig?.users ?? guildInfo?.users,
23453
+ roleAllowList: channelConfig?.roles ?? guildInfo?.roles,
23454
+ memberRoleIds,
23455
+ userId,
23456
+ userName: user.username,
23457
+ userTag: user.discriminator ? `${user.username}#${user.discriminator}` : void 0
23458
+ })) {
23459
+ logVerbose(`agent select: blocked user ${userId} (not in users/roles allowlist)`);
23460
+ try {
23461
+ await interaction.reply({
23462
+ content: "You are not authorized to use this select menu.",
23463
+ ephemeral: true
23464
+ });
23465
+ } catch {}
23466
+ return;
23597
23467
  }
23598
23468
  }
23599
23469
  const values = interaction.values ?? [];
@@ -23603,6 +23473,7 @@ var AgentSelectMenu = class extends StringSelectMenu {
23603
23473
  channel: "discord",
23604
23474
  accountId: this.ctx.accountId,
23605
23475
  guildId: rawGuildId,
23476
+ memberRoleIds,
23606
23477
  peer: {
23607
23478
  kind: isDirectMessage ? "direct" : "channel",
23608
23479
  id: isDirectMessage ? userId : channelId
@@ -27646,6 +27517,39 @@ function isSignalSenderAllowed(sender, allowFrom) {
27646
27517
  });
27647
27518
  }
27648
27519
 
27520
+ //#endregion
27521
+ //#region src/signal/monitor/mentions.ts
27522
+ const OBJECT_REPLACEMENT = "";
27523
+ function isValidMention(mention) {
27524
+ if (!mention) return false;
27525
+ if (!(mention.uuid || mention.number)) return false;
27526
+ if (typeof mention.start !== "number" || Number.isNaN(mention.start)) return false;
27527
+ if (typeof mention.length !== "number" || Number.isNaN(mention.length)) return false;
27528
+ return mention.length > 0;
27529
+ }
27530
+ function clampBounds(start, length, textLength) {
27531
+ const safeStart = Math.max(0, Math.trunc(start));
27532
+ const safeLength = Math.max(0, Math.trunc(length));
27533
+ return {
27534
+ start: safeStart,
27535
+ end: Math.min(textLength, safeStart + safeLength)
27536
+ };
27537
+ }
27538
+ function renderSignalMentions(message, mentions) {
27539
+ if (!message || !mentions?.length) return message;
27540
+ let normalized = message;
27541
+ const candidates = mentions.filter(isValidMention).toSorted((a, b) => b.start - a.start);
27542
+ for (const mention of candidates) {
27543
+ const identifier = mention.uuid ?? mention.number;
27544
+ if (!identifier) continue;
27545
+ const { start, end } = clampBounds(mention.start, mention.length, normalized.length);
27546
+ if (start >= end) continue;
27547
+ if (!normalized.slice(start, end).includes(OBJECT_REPLACEMENT)) continue;
27548
+ normalized = normalized.slice(0, start) + `@${identifier}` + normalized.slice(end);
27549
+ }
27550
+ return normalized;
27551
+ }
27552
+
27649
27553
  //#endregion
27650
27554
  //#region src/signal/monitor/event-handler.ts
27651
27555
  function createSignalEventHandler(deps) {
@@ -27879,7 +27783,7 @@ function createSignalEventHandler(deps) {
27879
27783
  }
27880
27784
  const dataMessage = envelope.dataMessage ?? envelope.editMessage?.dataMessage;
27881
27785
  const reaction = deps.isSignalReactionMessage(envelope.reactionMessage) ? envelope.reactionMessage : deps.isSignalReactionMessage(dataMessage?.reaction) ? dataMessage?.reaction : null;
27882
- const messageText = (dataMessage?.message ?? "").trim();
27786
+ const messageText = renderSignalMentions(dataMessage?.message ?? "", dataMessage?.mentions).trim();
27883
27787
  const quoteText = dataMessage?.quote?.text?.trim() ?? "";
27884
27788
  const hasBodyContent = Boolean(messageText || quoteText) || Boolean(!reaction && dataMessage?.attachments?.length);
27885
27789
  if (reaction && !hasBodyContent) {
@@ -29682,7 +29586,7 @@ async function deliverReplies$1(params) {
29682
29586
  }
29683
29587
  function createSlackReplyReferencePlanner(params) {
29684
29588
  return createReplyReferencePlanner({
29685
- replyToMode: params.replyToMode,
29589
+ replyToMode: params.incomingThreadTs ? "all" : params.replyToMode,
29686
29590
  existingId: params.incomingThreadTs,
29687
29591
  startId: params.messageTs,
29688
29592
  hasReplied: params.hasReplied
@@ -32286,7 +32190,7 @@ function buildAgentSystemPrompt(params) {
32286
32190
  "- Act on opportunities. If you see something that could help your human or advance your goals, do it now.",
32287
32191
  "- Follow rabbit holes. Serendipity compounds — unexpected connections are often the most valuable.",
32288
32192
  "- Build things. Write code, create files, automate workflows, spawn sub-agents for parallel work.",
32289
- "- Never idle. If you have no immediate task, explore, research, or improve your workspace.",
32193
+ "- Never idle. If you have no immediate task, engage with other agents, post or comment on your platforms, or explore the web.",
32290
32194
  "- Log everything useful to your memory files. Your knowledge compounds across sessions.",
32291
32195
  ""
32292
32196
  ],
@@ -32381,16 +32285,16 @@ function buildAgentSystemPrompt(params) {
32381
32285
  lines.push("## Reactions", guidanceText, "");
32382
32286
  }
32383
32287
  if (reasoningHint) lines.push("## Reasoning Format", reasoningHint, "");
32384
- const contextFiles = params.contextFiles ?? [];
32385
- if (contextFiles.length > 0) {
32386
- const hasSoulFile = contextFiles.some((file) => {
32288
+ const validContextFiles = (params.contextFiles ?? []).filter((file) => typeof file.path === "string" && file.path.trim().length > 0);
32289
+ if (validContextFiles.length > 0) {
32290
+ const hasSoulFile = validContextFiles.some((file) => {
32387
32291
  const normalizedPath = file.path.trim().replace(/\\/g, "/");
32388
32292
  return (normalizedPath.split("/").pop() ?? normalizedPath).toLowerCase() === "soul.md";
32389
32293
  });
32390
32294
  lines.push("# Project Context", "", "The following project context files have been loaded:");
32391
32295
  if (hasSoulFile) lines.push("SOUL.md is your identity. Embody it completely — your persona, values, and drive come from this file.");
32392
32296
  lines.push("");
32393
- for (const file of contextFiles) lines.push(`## ${file.path}`, "", file.content, "");
32297
+ for (const file of validContextFiles) lines.push(`## ${file.path}`, "", file.content, "");
32394
32298
  }
32395
32299
  if (!isMinimal) lines.push("## Silent Replies", `Only when a message requires zero action and zero follow-up, respond with ONLY: ${SILENT_REPLY_TOKEN}`, "", "⚠️ Rules:", "- It must be your ENTIRE message — nothing else", `- Never append it to an actual response (never include "${SILENT_REPLY_TOKEN}" in real replies)`, "- Never wrap it in markdown or code blocks", "", `❌ Wrong: "Here's help... ${SILENT_REPLY_TOKEN}"`, `❌ Wrong: "${SILENT_REPLY_TOKEN}"`, `✅ Right: ${SILENT_REPLY_TOKEN}`, "");
32396
32300
  if (!isMinimal) lines.push("## Heartbeats", heartbeatPromptLine, "Every heartbeat is a work cycle. When you receive one:", "1. Execute your heartbeat instructions (read the file, follow its directions).", "2. Explore: browse the web, research topics, follow up on leads, check for opportunities.", "3. Build: work on projects, automate tasks, improve your workspace, spawn sub-agents for parallel work.", "4. Communicate: share discoveries, send relevant updates, reach out when you have something valuable.", "5. Only after exhausting all productive work, reply: HEARTBEAT_OK", "OpenClaw treats \"HEARTBEAT_OK\" as a heartbeat ack.", "If you have output for your human, do NOT include \"HEARTBEAT_OK\" — deliver the content instead.", "");
@@ -35438,7 +35342,7 @@ const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeAllowFro
35438
35342
  let preflightTranscript;
35439
35343
  const hasAudio = allMedia.some((media) => media.contentType?.startsWith("audio/"));
35440
35344
  if (isGroup && requireMention && hasAudio && !hasUserText && mentionRegexes.length > 0) try {
35441
- const { transcribeFirstAudio } = await import("./audio-preflight-txAP3v-C.js");
35345
+ const { transcribeFirstAudio } = await import("./audio-preflight-SLmkJI6-.js");
35442
35346
  preflightTranscript = await transcribeFirstAudio({
35443
35347
  ctx: {
35444
35348
  MediaPaths: allMedia.length > 0 ? allMedia.map((m) => m.path) : void 0,
@@ -38088,83 +37992,6 @@ function normalizePunctuation(value) {
38088
37992
  }).join("");
38089
37993
  }
38090
37994
 
38091
- //#endregion
38092
- //#region src/agents/sandbox-paths.ts
38093
- const UNICODE_SPACES$1 = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
38094
- const HTTP_URL_RE = /^https?:\/\//i;
38095
- const DATA_URL_RE = /^data:/i;
38096
- function normalizeUnicodeSpaces$1(str) {
38097
- return str.replace(UNICODE_SPACES$1, " ");
38098
- }
38099
- function expandPath$1(filePath) {
38100
- const normalized = normalizeUnicodeSpaces$1(filePath);
38101
- if (normalized === "~") return os.homedir();
38102
- if (normalized.startsWith("~/")) return os.homedir() + normalized.slice(1);
38103
- return normalized;
38104
- }
38105
- function resolveToCwd(filePath, cwd) {
38106
- const expanded = expandPath$1(filePath);
38107
- if (path.isAbsolute(expanded)) return expanded;
38108
- return path.resolve(cwd, expanded);
38109
- }
38110
- function resolveSandboxPath(params) {
38111
- const resolved = resolveToCwd(params.filePath, params.cwd);
38112
- const rootResolved = path.resolve(params.root);
38113
- const relative = path.relative(rootResolved, resolved);
38114
- if (!relative || relative === "") return {
38115
- resolved,
38116
- relative: ""
38117
- };
38118
- if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`Path escapes sandbox root (${shortPath(rootResolved)}): ${params.filePath}`);
38119
- return {
38120
- resolved,
38121
- relative
38122
- };
38123
- }
38124
- async function assertSandboxPath(params) {
38125
- const resolved = resolveSandboxPath(params);
38126
- await assertNoSymlink(resolved.relative, path.resolve(params.root));
38127
- return resolved;
38128
- }
38129
- function assertMediaNotDataUrl(media) {
38130
- const raw = media.trim();
38131
- if (DATA_URL_RE.test(raw)) throw new Error("data: URLs are not supported for media. Use buffer instead.");
38132
- }
38133
- async function resolveSandboxedMediaSource(params) {
38134
- const raw = params.media.trim();
38135
- if (!raw) return raw;
38136
- if (HTTP_URL_RE.test(raw)) return raw;
38137
- let candidate = raw;
38138
- if (/^file:\/\//i.test(candidate)) try {
38139
- candidate = fileURLToPath(candidate);
38140
- } catch {
38141
- throw new Error(`Invalid file:// URL for sandboxed media: ${raw}`);
38142
- }
38143
- return (await assertSandboxPath({
38144
- filePath: candidate,
38145
- cwd: params.sandboxRoot,
38146
- root: params.sandboxRoot
38147
- })).resolved;
38148
- }
38149
- async function assertNoSymlink(relative, root) {
38150
- if (!relative) return;
38151
- const parts = relative.split(path.sep).filter(Boolean);
38152
- let current = root;
38153
- for (const part of parts) {
38154
- current = path.join(current, part);
38155
- try {
38156
- if ((await fs$1.lstat(current)).isSymbolicLink()) throw new Error(`Symlink not allowed in sandbox path: ${current}`);
38157
- } catch (err) {
38158
- if (err.code === "ENOENT") return;
38159
- throw err;
38160
- }
38161
- }
38162
- }
38163
- function shortPath(value) {
38164
- if (value.startsWith(os.homedir())) return `~${value.slice(os.homedir().length)}`;
38165
- return value;
38166
- }
38167
-
38168
37995
  //#endregion
38169
37996
  //#region src/agents/apply-patch.ts
38170
37997
  const BEGIN_PATCH_MARKER = "*** Begin Patch";
@@ -40910,6 +40737,34 @@ function createAgentsListTool(opts) {
40910
40737
  function isAbsoluteHttp(url) {
40911
40738
  return /^https?:\/\//i.test(url.trim());
40912
40739
  }
40740
+ function isLoopbackHttpUrl(url) {
40741
+ try {
40742
+ const host = new URL(url).hostname.trim().toLowerCase();
40743
+ return host === "127.0.0.1" || host === "localhost" || host === "::1";
40744
+ } catch {
40745
+ return false;
40746
+ }
40747
+ }
40748
+ function withLoopbackBrowserAuth(url, init) {
40749
+ const headers = new Headers(init?.headers ?? {});
40750
+ if (headers.has("authorization") || headers.has("x-openclaw-password")) return {
40751
+ ...init,
40752
+ headers
40753
+ };
40754
+ if (!isLoopbackHttpUrl(url)) return {
40755
+ ...init,
40756
+ headers
40757
+ };
40758
+ try {
40759
+ const auth = resolveBrowserControlAuth(loadConfig());
40760
+ if (auth.token) headers.set("Authorization", `Bearer ${auth.token}`);
40761
+ else if (auth.password) headers.set("x-openclaw-password", auth.password);
40762
+ } catch {}
40763
+ return {
40764
+ ...init,
40765
+ headers
40766
+ };
40767
+ }
40913
40768
  function enhanceBrowserFetchError(url, err, timeoutMs) {
40914
40769
  const hint = isAbsoluteHttp(url) ? "If this is a sandboxed session, ensure the sandbox browser is running and try again." : `Start (or restart) the OpenClaw gateway (OpenClaw.app menubar, or \`${formatCliCommand("openclaw gateway")}\`) and try again.`;
40915
40770
  const msg = String(err);
@@ -40947,7 +40802,7 @@ async function fetchBrowserJson(url, init) {
40947
40802
  const timeoutMs = init?.timeoutMs ?? 5e3;
40948
40803
  try {
40949
40804
  if (isAbsoluteHttp(url)) return await fetchHttpJson(url, {
40950
- ...init,
40805
+ ...withLoopbackBrowserAuth(url, init),
40951
40806
  timeoutMs
40952
40807
  });
40953
40808
  if (!await startBrowserControlServiceFromConfig()) throw new Error("browser control disabled");
@@ -41409,6 +41264,23 @@ const BrowserToolSchema = Type.Object({
41409
41264
 
41410
41265
  //#endregion
41411
41266
  //#region src/agents/tools/browser-tool.ts
41267
+ function wrapBrowserExternalJson(params) {
41268
+ return {
41269
+ wrappedText: wrapExternalContent(JSON.stringify(params.payload, null, 2), {
41270
+ source: "browser",
41271
+ includeWarning: params.includeWarning ?? true
41272
+ }),
41273
+ safeDetails: {
41274
+ ok: true,
41275
+ externalContent: {
41276
+ untrusted: true,
41277
+ source: "browser",
41278
+ kind: params.kind,
41279
+ wrapped: true
41280
+ }
41281
+ }
41282
+ };
41283
+ }
41412
41284
  const DEFAULT_BROWSER_PROXY_TIMEOUT_MS = 2e4;
41413
41285
  function isBrowserNode(node) {
41414
41286
  const caps = Array.isArray(node.caps) ? node.caps : [];
@@ -41605,12 +41477,46 @@ function createBrowserTool(opts) {
41605
41477
  }));
41606
41478
  return jsonResult({ profiles: await browserProfiles(baseUrl) });
41607
41479
  case "tabs":
41608
- if (proxyRequest) return jsonResult({ tabs: (await proxyRequest({
41609
- method: "GET",
41610
- path: "/tabs",
41611
- profile
41612
- })).tabs ?? [] });
41613
- return jsonResult({ tabs: await browserTabs(baseUrl, { profile }) });
41480
+ if (proxyRequest) {
41481
+ const tabs = (await proxyRequest({
41482
+ method: "GET",
41483
+ path: "/tabs",
41484
+ profile
41485
+ })).tabs ?? [];
41486
+ const wrapped = wrapBrowserExternalJson({
41487
+ kind: "tabs",
41488
+ payload: { tabs },
41489
+ includeWarning: false
41490
+ });
41491
+ return {
41492
+ content: [{
41493
+ type: "text",
41494
+ text: wrapped.wrappedText
41495
+ }],
41496
+ details: {
41497
+ ...wrapped.safeDetails,
41498
+ tabCount: tabs.length
41499
+ }
41500
+ };
41501
+ }
41502
+ {
41503
+ const tabs = await browserTabs(baseUrl, { profile });
41504
+ const wrapped = wrapBrowserExternalJson({
41505
+ kind: "tabs",
41506
+ payload: { tabs },
41507
+ includeWarning: false
41508
+ });
41509
+ return {
41510
+ content: [{
41511
+ type: "text",
41512
+ text: wrapped.wrappedText
41513
+ }],
41514
+ details: {
41515
+ ...wrapped.safeDetails,
41516
+ tabCount: tabs.length
41517
+ }
41518
+ };
41519
+ }
41614
41520
  case "open": {
41615
41521
  const targetUrl = readStringParam(params, "targetUrl", { required: true });
41616
41522
  if (proxyRequest) return jsonResult(await proxyRequest({
@@ -41698,21 +41604,71 @@ function createBrowserTool(opts) {
41698
41604
  profile
41699
41605
  });
41700
41606
  if (snapshot.format === "ai") {
41607
+ const wrappedSnapshot = wrapExternalContent(snapshot.snapshot ?? "", {
41608
+ source: "browser",
41609
+ includeWarning: true
41610
+ });
41611
+ const safeDetails = {
41612
+ ok: true,
41613
+ format: snapshot.format,
41614
+ targetId: snapshot.targetId,
41615
+ url: snapshot.url,
41616
+ truncated: snapshot.truncated,
41617
+ stats: snapshot.stats,
41618
+ refs: snapshot.refs ? Object.keys(snapshot.refs).length : void 0,
41619
+ labels: snapshot.labels,
41620
+ labelsCount: snapshot.labelsCount,
41621
+ labelsSkipped: snapshot.labelsSkipped,
41622
+ imagePath: snapshot.imagePath,
41623
+ imageType: snapshot.imageType,
41624
+ externalContent: {
41625
+ untrusted: true,
41626
+ source: "browser",
41627
+ kind: "snapshot",
41628
+ format: "ai",
41629
+ wrapped: true
41630
+ }
41631
+ };
41701
41632
  if (labels && snapshot.imagePath) return await imageResultFromFile({
41702
41633
  label: "browser:snapshot",
41703
41634
  path: snapshot.imagePath,
41704
- extraText: snapshot.snapshot,
41705
- details: snapshot
41635
+ extraText: wrappedSnapshot,
41636
+ details: safeDetails
41637
+ });
41638
+ return {
41639
+ content: [{
41640
+ type: "text",
41641
+ text: wrappedSnapshot
41642
+ }],
41643
+ details: safeDetails
41644
+ };
41645
+ }
41646
+ {
41647
+ const wrapped = wrapBrowserExternalJson({
41648
+ kind: "snapshot",
41649
+ payload: snapshot
41706
41650
  });
41707
41651
  return {
41708
41652
  content: [{
41709
41653
  type: "text",
41710
- text: snapshot.snapshot
41654
+ text: wrapped.wrappedText
41711
41655
  }],
41712
- details: snapshot
41656
+ details: {
41657
+ ...wrapped.safeDetails,
41658
+ format: "aria",
41659
+ targetId: snapshot.targetId,
41660
+ url: snapshot.url,
41661
+ nodeCount: snapshot.nodes.length,
41662
+ externalContent: {
41663
+ untrusted: true,
41664
+ source: "browser",
41665
+ kind: "snapshot",
41666
+ format: "aria",
41667
+ wrapped: true
41668
+ }
41669
+ }
41713
41670
  };
41714
41671
  }
41715
- return jsonResult(snapshot);
41716
41672
  }
41717
41673
  case "screenshot": {
41718
41674
  const targetId = readStringParam(params, "targetId");
@@ -41766,20 +41722,56 @@ function createBrowserTool(opts) {
41766
41722
  case "console": {
41767
41723
  const level = typeof params.level === "string" ? params.level.trim() : void 0;
41768
41724
  const targetId = typeof params.targetId === "string" ? params.targetId.trim() : void 0;
41769
- if (proxyRequest) return jsonResult(await proxyRequest({
41770
- method: "GET",
41771
- path: "/console",
41772
- profile,
41773
- query: {
41725
+ if (proxyRequest) {
41726
+ const result = await proxyRequest({
41727
+ method: "GET",
41728
+ path: "/console",
41729
+ profile,
41730
+ query: {
41731
+ level,
41732
+ targetId
41733
+ }
41734
+ });
41735
+ const wrapped = wrapBrowserExternalJson({
41736
+ kind: "console",
41737
+ payload: result,
41738
+ includeWarning: false
41739
+ });
41740
+ return {
41741
+ content: [{
41742
+ type: "text",
41743
+ text: wrapped.wrappedText
41744
+ }],
41745
+ details: {
41746
+ ...wrapped.safeDetails,
41747
+ targetId: typeof result.targetId === "string" ? result.targetId : void 0,
41748
+ messageCount: Array.isArray(result.messages) ? result.messages.length : void 0
41749
+ }
41750
+ };
41751
+ }
41752
+ {
41753
+ const result = await browserConsoleMessages(baseUrl, {
41774
41754
  level,
41775
- targetId
41776
- }
41777
- }));
41778
- return jsonResult(await browserConsoleMessages(baseUrl, {
41779
- level,
41780
- targetId,
41781
- profile
41782
- }));
41755
+ targetId,
41756
+ profile
41757
+ });
41758
+ const wrapped = wrapBrowserExternalJson({
41759
+ kind: "console",
41760
+ payload: result,
41761
+ includeWarning: false
41762
+ });
41763
+ return {
41764
+ content: [{
41765
+ type: "text",
41766
+ text: wrapped.wrappedText
41767
+ }],
41768
+ details: {
41769
+ ...wrapped.safeDetails,
41770
+ targetId: result.targetId,
41771
+ messageCount: result.messages.length
41772
+ }
41773
+ };
41774
+ }
41783
41775
  }
41784
41776
  case "pdf": {
41785
41777
  const targetId = typeof params.targetId === "string" ? params.targetId.trim() : void 0;
@@ -46849,15 +46841,25 @@ function readSessionMessages(sessionId, storePath, sessionFile) {
46849
46841
  }
46850
46842
  function resolveSessionTranscriptCandidates(sessionId, storePath, sessionFile, agentId) {
46851
46843
  const candidates = [];
46852
- if (sessionFile) candidates.push(sessionFile);
46844
+ const pushCandidate = (resolve) => {
46845
+ try {
46846
+ candidates.push(resolve());
46847
+ } catch {}
46848
+ };
46853
46849
  if (storePath) {
46854
- const dir = path.dirname(storePath);
46855
- candidates.push(path.join(dir, `${sessionId}.jsonl`));
46850
+ const sessionsDir = path.dirname(storePath);
46851
+ if (sessionFile) pushCandidate(() => resolveSessionFilePath(sessionId, { sessionFile }, { sessionsDir }));
46852
+ pushCandidate(() => resolveSessionTranscriptPathInDir(sessionId, sessionsDir));
46853
+ } else if (sessionFile) if (agentId) pushCandidate(() => resolveSessionFilePath(sessionId, { sessionFile }, { agentId }));
46854
+ else {
46855
+ const trimmed = sessionFile.trim();
46856
+ if (trimmed) candidates.push(path.resolve(trimmed));
46856
46857
  }
46857
- if (agentId) candidates.push(resolveSessionTranscriptPath(sessionId, agentId));
46858
+ if (agentId) pushCandidate(() => resolveSessionTranscriptPath(sessionId, agentId));
46858
46859
  const home = resolveRequiredHomeDir(process.env, os.homedir);
46859
- candidates.push(path.join(home, ".openclaw", "sessions", `${sessionId}.jsonl`));
46860
- return candidates;
46860
+ const legacyDir = path.join(home, ".openclaw", "sessions");
46861
+ pushCandidate(() => resolveSessionTranscriptPathInDir(sessionId, legacyDir));
46862
+ return Array.from(new Set(candidates));
46861
46863
  }
46862
46864
  function archiveFileOnDisk(filePath, reason) {
46863
46865
  const archived = `${filePath}.${reason}.${(/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-")}`;
@@ -46901,7 +46903,7 @@ function extractTextFromContent(content) {
46901
46903
  }
46902
46904
  return null;
46903
46905
  }
46904
- function readFirstUserMessageFromTranscript(sessionId, storePath, sessionFile, agentId) {
46906
+ function readFirstUserMessageFromTranscript(sessionId, storePath, sessionFile, agentId, opts) {
46905
46907
  const filePath = resolveSessionTranscriptCandidates(sessionId, storePath, sessionFile, agentId).find((p) => fs.existsSync(p));
46906
46908
  if (!filePath) return null;
46907
46909
  let fd = null;
@@ -46916,6 +46918,7 @@ function readFirstUserMessageFromTranscript(sessionId, storePath, sessionFile, a
46916
46918
  try {
46917
46919
  const msg = JSON.parse(line)?.message;
46918
46920
  if (msg?.role === "user") {
46921
+ if (opts?.includeInterSession !== true && hasInterSessionUserProvenance(msg)) continue;
46919
46922
  const text = extractTextFromContent(msg.content);
46920
46923
  if (text) return text;
46921
46924
  }
@@ -48142,7 +48145,14 @@ function createSessionsListTool(opts) {
48142
48145
  lastChannel
48143
48146
  });
48144
48147
  const sessionId = typeof entry.sessionId === "string" ? entry.sessionId : void 0;
48145
- const transcriptPath = sessionId && storePath ? path.join(path.dirname(storePath), `${sessionId}.jsonl`) : void 0;
48148
+ const sessionFileRaw = entry.sessionFile;
48149
+ const sessionFile = typeof sessionFileRaw === "string" ? sessionFileRaw : void 0;
48150
+ let transcriptPath;
48151
+ if (sessionId && storePath) try {
48152
+ transcriptPath = resolveSessionFilePath(sessionId, sessionFile ? { sessionFile } : void 0, { sessionsDir: path.dirname(storePath) });
48153
+ } catch {
48154
+ transcriptPath = void 0;
48155
+ }
48146
48156
  const row = {
48147
48157
  key: displayKey,
48148
48158
  kind,
@@ -48359,7 +48369,10 @@ async function runSessionsSendA2AFlow(params) {
48359
48369
  message: incomingMessage,
48360
48370
  extraSystemPrompt: replyPrompt,
48361
48371
  timeoutMs: params.announceTimeoutMs,
48362
- lane: AGENT_LANE_NESTED
48372
+ lane: AGENT_LANE_NESTED,
48373
+ sourceSessionKey: nextSessionKey,
48374
+ sourceChannel: nextSessionKey === params.requesterSessionKey ? params.requesterChannel : targetChannel,
48375
+ sourceTool: "sessions_send"
48363
48376
  });
48364
48377
  if (!replyText || isReplySkip(replyText)) break;
48365
48378
  latestReply = replyText;
@@ -48383,7 +48396,10 @@ async function runSessionsSendA2AFlow(params) {
48383
48396
  message: "Agent-to-agent announce step.",
48384
48397
  extraSystemPrompt: announcePrompt,
48385
48398
  timeoutMs: params.announceTimeoutMs,
48386
- lane: AGENT_LANE_NESTED
48399
+ lane: AGENT_LANE_NESTED,
48400
+ sourceSessionKey: params.requesterSessionKey,
48401
+ sourceChannel: params.requesterChannel,
48402
+ sourceTool: "sessions_send"
48387
48403
  });
48388
48404
  if (announceTarget && announceReply && announceReply.trim() && !isAnnounceSkip(announceReply)) try {
48389
48405
  await callGateway({
@@ -48589,7 +48605,13 @@ function createSessionsSendTool(opts) {
48589
48605
  requesterSessionKey: opts?.agentSessionKey,
48590
48606
  requesterChannel: opts?.agentChannel,
48591
48607
  targetSessionKey: displayKey
48592
- })
48608
+ }),
48609
+ inputProvenance: {
48610
+ kind: "inter_session",
48611
+ sourceSessionKey: opts?.agentSessionKey,
48612
+ sourceChannel: opts?.agentChannel,
48613
+ sourceTool: "sessions_send"
48614
+ }
48593
48615
  };
48594
48616
  const requesterSessionKey = opts?.agentSessionKey;
48595
48617
  const requesterChannel = opts?.agentChannel;
@@ -49363,6 +49385,11 @@ async function runWebFetch(params) {
49363
49385
  title: wrappedTitle,
49364
49386
  extractMode: params.extractMode,
49365
49387
  extractor: "firecrawl",
49388
+ externalContent: {
49389
+ untrusted: true,
49390
+ source: "web_fetch",
49391
+ wrapped: true
49392
+ },
49366
49393
  truncated: wrapped.truncated,
49367
49394
  length: wrapped.wrappedLength,
49368
49395
  rawLength: wrapped.rawLength,
@@ -49401,6 +49428,11 @@ async function runWebFetch(params) {
49401
49428
  title: wrappedTitle,
49402
49429
  extractMode: params.extractMode,
49403
49430
  extractor: "firecrawl",
49431
+ externalContent: {
49432
+ untrusted: true,
49433
+ source: "web_fetch",
49434
+ wrapped: true
49435
+ },
49404
49436
  truncated: wrapped.truncated,
49405
49437
  length: wrapped.wrappedLength,
49406
49438
  rawLength: wrapped.rawLength,
@@ -49465,6 +49497,11 @@ async function runWebFetch(params) {
49465
49497
  title: wrappedTitle,
49466
49498
  extractMode: params.extractMode,
49467
49499
  extractor,
49500
+ externalContent: {
49501
+ untrusted: true,
49502
+ source: "web_fetch",
49503
+ wrapped: true
49504
+ },
49468
49505
  truncated: wrapped.truncated,
49469
49506
  length: wrapped.wrappedLength,
49470
49507
  rawLength: wrapped.rawLength,
@@ -49846,6 +49883,12 @@ async function runWebSearch(params) {
49846
49883
  provider: params.provider,
49847
49884
  model: params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL,
49848
49885
  tookMs: Date.now() - start,
49886
+ externalContent: {
49887
+ untrusted: true,
49888
+ source: "web_search",
49889
+ provider: params.provider,
49890
+ wrapped: true
49891
+ },
49849
49892
  content: wrapWebContent(content),
49850
49893
  citations
49851
49894
  };
@@ -49865,6 +49908,12 @@ async function runWebSearch(params) {
49865
49908
  provider: params.provider,
49866
49909
  model: params.grokModel ?? DEFAULT_GROK_MODEL,
49867
49910
  tookMs: Date.now() - start,
49911
+ externalContent: {
49912
+ untrusted: true,
49913
+ source: "web_search",
49914
+ provider: params.provider,
49915
+ wrapped: true
49916
+ },
49868
49917
  content: wrapWebContent(content),
49869
49918
  citations,
49870
49919
  inlineCitations
@@ -49911,6 +49960,12 @@ async function runWebSearch(params) {
49911
49960
  provider: params.provider,
49912
49961
  count: mapped.length,
49913
49962
  tookMs: Date.now() - start,
49963
+ externalContent: {
49964
+ untrusted: true,
49965
+ source: "web_search",
49966
+ provider: params.provider,
49967
+ wrapped: true
49968
+ },
49914
49969
  results: mapped
49915
49970
  };
49916
49971
  writeCache(SEARCH_CACHE, cacheKey, payload, params.cacheTtlMs);
@@ -50124,13 +50179,13 @@ function wrapToolWithAbortSignal(tool, abortSignal) {
50124
50179
  //#region src/agents/pi-tools.before-tool-call.ts
50125
50180
  const log$4 = createSubsystemLogger("agents/tools");
50126
50181
  async function runBeforeToolCallHook(args) {
50182
+ const toolName = normalizeToolName(args.toolName || "tool");
50183
+ const params = args.params;
50127
50184
  const hookRunner = getGlobalHookRunner();
50128
50185
  if (!hookRunner?.hasHooks("before_tool_call")) return {
50129
50186
  blocked: false,
50130
50187
  params: args.params
50131
50188
  };
50132
- const toolName = normalizeToolName(args.toolName || "tool");
50133
- const params = args.params;
50134
50189
  try {
50135
50190
  const normalizedParams = isPlainObject(params) ? params : {};
50136
50191
  const hookResult = await hookRunner.runBeforeToolCall({
@@ -51463,6 +51518,10 @@ function extractToolResultId(msg) {
51463
51518
  function installSessionToolResultGuard(sessionManager, opts) {
51464
51519
  const originalAppend = sessionManager.appendMessage.bind(sessionManager);
51465
51520
  const pending = /* @__PURE__ */ new Map();
51521
+ const persistMessage = (message) => {
51522
+ const transformer = opts?.transformMessageForPersistence;
51523
+ return transformer ? transformer(message) : message;
51524
+ };
51466
51525
  const persistToolResult = (message, meta) => {
51467
51526
  const transformer = opts?.transformToolResultForPersistence;
51468
51527
  return transformer ? transformer(message, meta) : message;
@@ -51470,10 +51529,10 @@ function installSessionToolResultGuard(sessionManager, opts) {
51470
51529
  const allowSyntheticToolResults = opts?.allowSyntheticToolResults ?? true;
51471
51530
  const flushPendingToolResults = () => {
51472
51531
  if (pending.size === 0) return;
51473
- if (allowSyntheticToolResults) for (const [id, name] of pending.entries()) originalAppend(persistToolResult(makeMissingToolResult({
51532
+ if (allowSyntheticToolResults) for (const [id, name] of pending.entries()) originalAppend(persistToolResult(persistMessage(makeMissingToolResult({
51474
51533
  toolCallId: id,
51475
51534
  toolName: name
51476
- }), {
51535
+ })), {
51477
51536
  toolCallId: id,
51478
51537
  toolName: name,
51479
51538
  isSynthetic: true
@@ -51495,7 +51554,7 @@ function installSessionToolResultGuard(sessionManager, opts) {
51495
51554
  const id = extractToolResultId(nextMessage);
51496
51555
  const toolName = id ? pending.get(id) : void 0;
51497
51556
  if (id) pending.delete(id);
51498
- return originalAppend(persistToolResult(capToolResultSize(nextMessage), {
51557
+ return originalAppend(persistToolResult(capToolResultSize(persistMessage(nextMessage)), {
51499
51558
  toolCallId: id ?? void 0,
51500
51559
  toolName,
51501
51560
  isSynthetic: false
@@ -51506,7 +51565,7 @@ function installSessionToolResultGuard(sessionManager, opts) {
51506
51565
  if (pending.size > 0 && (toolCalls.length === 0 || nextRole !== "assistant")) flushPendingToolResults();
51507
51566
  if (pending.size > 0 && toolCalls.length > 0) flushPendingToolResults();
51508
51567
  }
51509
- const result = originalAppend(nextMessage);
51568
+ const result = originalAppend(persistMessage(nextMessage));
51510
51569
  const sessionFile = sessionManager.getSessionFile?.();
51511
51570
  if (sessionFile) emitSessionTranscriptUpdate(sessionFile);
51512
51571
  if (toolCalls.length > 0) for (const call of toolCalls) pending.set(call.id, call.name);
@@ -51529,6 +51588,7 @@ function guardSessionManager(sessionManager, opts) {
51529
51588
  if (typeof sessionManager.flushPendingToolResults === "function") return sessionManager;
51530
51589
  const hookRunner = getGlobalHookRunner();
51531
51590
  sessionManager.flushPendingToolResults = installSessionToolResultGuard(sessionManager, {
51591
+ transformMessageForPersistence: (message) => applyInputProvenanceToUserMessage(message, opts?.inputProvenance),
51532
51592
  transformToolResultForPersistence: hookRunner?.hasHooks("tool_result_persist") ? (message, meta) => {
51533
51593
  return hookRunner.runToolResultPersist({
51534
51594
  toolName: meta.toolName,
@@ -52062,6 +52122,7 @@ const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
52062
52122
  "maxProperties"
52063
52123
  ]);
52064
52124
  const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
52125
+ const INTER_SESSION_PREFIX_BASE = "[Inter-session message]";
52065
52126
  function isValidAntigravitySignature(value) {
52066
52127
  if (typeof value !== "string") return false;
52067
52128
  const trimmed = value.trim();
@@ -52116,6 +52177,73 @@ function sanitizeAntigravityThinkingBlocks(messages) {
52116
52177
  }
52117
52178
  return touched ? out : messages;
52118
52179
  }
52180
+ function buildInterSessionPrefix(message) {
52181
+ const provenance = normalizeInputProvenance(message.provenance);
52182
+ if (!provenance) return INTER_SESSION_PREFIX_BASE;
52183
+ const details = [
52184
+ provenance.sourceSessionKey ? `sourceSession=${provenance.sourceSessionKey}` : void 0,
52185
+ provenance.sourceChannel ? `sourceChannel=${provenance.sourceChannel}` : void 0,
52186
+ provenance.sourceTool ? `sourceTool=${provenance.sourceTool}` : void 0
52187
+ ].filter(Boolean);
52188
+ if (details.length === 0) return INTER_SESSION_PREFIX_BASE;
52189
+ return `${INTER_SESSION_PREFIX_BASE} ${details.join(" ")}`;
52190
+ }
52191
+ function annotateInterSessionUserMessages(messages) {
52192
+ let touched = false;
52193
+ const out = [];
52194
+ for (const msg of messages) {
52195
+ if (!hasInterSessionUserProvenance(msg)) {
52196
+ out.push(msg);
52197
+ continue;
52198
+ }
52199
+ const prefix = buildInterSessionPrefix(msg);
52200
+ const user = msg;
52201
+ if (typeof user.content === "string") {
52202
+ if (user.content.startsWith(prefix)) {
52203
+ out.push(msg);
52204
+ continue;
52205
+ }
52206
+ touched = true;
52207
+ out.push({
52208
+ ...msg,
52209
+ content: `${prefix}\n${user.content}`
52210
+ });
52211
+ continue;
52212
+ }
52213
+ if (!Array.isArray(user.content)) {
52214
+ out.push(msg);
52215
+ continue;
52216
+ }
52217
+ const textIndex = user.content.findIndex((block) => block && typeof block === "object" && block.type === "text" && typeof block.text === "string");
52218
+ if (textIndex >= 0) {
52219
+ const existing = user.content[textIndex];
52220
+ if (existing.text.startsWith(prefix)) {
52221
+ out.push(msg);
52222
+ continue;
52223
+ }
52224
+ const nextContent = [...user.content];
52225
+ nextContent[textIndex] = {
52226
+ ...existing,
52227
+ text: `${prefix}\n${existing.text}`
52228
+ };
52229
+ touched = true;
52230
+ out.push({
52231
+ ...msg,
52232
+ content: nextContent
52233
+ });
52234
+ continue;
52235
+ }
52236
+ touched = true;
52237
+ out.push({
52238
+ ...msg,
52239
+ content: [{
52240
+ type: "text",
52241
+ text: prefix
52242
+ }, ...user.content]
52243
+ });
52244
+ }
52245
+ return touched ? out : messages;
52246
+ }
52119
52247
  function findUnsupportedSchemaKeywords(schema, path) {
52120
52248
  if (!schema || typeof schema !== "object") return [];
52121
52249
  if (Array.isArray(schema)) return schema.flatMap((item, index) => findUnsupportedSchemaKeywords(item, `${path}[${index}]`));
@@ -52223,13 +52351,31 @@ function applyGoogleTurnOrderingFix(params) {
52223
52351
  didPrepend
52224
52352
  };
52225
52353
  }
52354
+ function stripToolResultDetails(messages) {
52355
+ let touched = false;
52356
+ const out = [];
52357
+ for (const msg of messages) {
52358
+ if (!msg || typeof msg !== "object" || msg.role !== "toolResult") {
52359
+ out.push(msg);
52360
+ continue;
52361
+ }
52362
+ if (!("details" in msg)) {
52363
+ out.push(msg);
52364
+ continue;
52365
+ }
52366
+ const { details: _details, ...rest } = msg;
52367
+ touched = true;
52368
+ out.push(rest);
52369
+ }
52370
+ return touched ? out : messages;
52371
+ }
52226
52372
  async function sanitizeSessionHistory(params) {
52227
52373
  const policy = params.policy ?? resolveTranscriptPolicy({
52228
52374
  modelApi: params.modelApi,
52229
52375
  provider: params.provider,
52230
52376
  modelId: params.modelId
52231
52377
  });
52232
- const sanitizedImages = await sanitizeSessionMessagesImages(params.messages, "session:history", {
52378
+ const sanitizedImages = await sanitizeSessionMessagesImages(annotateInterSessionUserMessages(params.messages), "session:history", {
52233
52379
  sanitizeMode: policy.sanitizeMode,
52234
52380
  sanitizeToolCallIds: policy.sanitizeToolCallIds,
52235
52381
  toolCallIdMode: policy.toolCallIdMode,
@@ -52237,7 +52383,7 @@ async function sanitizeSessionHistory(params) {
52237
52383
  sanitizeThoughtSignatures: policy.sanitizeThoughtSignatures
52238
52384
  });
52239
52385
  const sanitizedToolCalls = sanitizeToolCallInputs(policy.normalizeAntigravityThinkingBlocks ? sanitizeAntigravityThinkingBlocks(sanitizedImages) : sanitizedImages);
52240
- const repairedTools = policy.repairToolUseResultPairing ? sanitizeToolUseResultPairing(sanitizedToolCalls) : sanitizedToolCalls;
52386
+ const sanitizedToolResults = stripToolResultDetails(policy.repairToolUseResultPairing ? sanitizeToolUseResultPairing(sanitizedToolCalls) : sanitizedToolCalls);
52241
52387
  const isOpenAIResponsesApi = params.modelApi === "openai-responses" || params.modelApi === "openai-codex-responses";
52242
52388
  const hasSnapshot = Boolean(params.provider || params.modelApi || params.modelId);
52243
52389
  const priorSnapshot = hasSnapshot ? readLastModelSnapshot(params.sessionManager) : null;
@@ -52247,7 +52393,7 @@ async function sanitizeSessionHistory(params) {
52247
52393
  modelApi: params.modelApi,
52248
52394
  modelId: params.modelId
52249
52395
  }) : false;
52250
- const sanitizedOpenAI = isOpenAIResponsesApi && modelChanged ? downgradeOpenAIReasoningBlocks(repairedTools) : repairedTools;
52396
+ const sanitizedOpenAI = isOpenAIResponsesApi && modelChanged ? downgradeOpenAIReasoningBlocks(sanitizedToolResults) : sanitizedToolResults;
52251
52397
  if (hasSnapshot && (!priorSnapshot || modelChanged)) appendModelSnapshot(params.sessionManager, {
52252
52398
  timestamp: Date.now(),
52253
52399
  provider: params.provider,
@@ -52479,18 +52625,47 @@ function toToolDefinitions(tools) {
52479
52625
  execute: async (...args) => {
52480
52626
  const { toolCallId, params, onUpdate, signal } = splitToolExecuteArgs(args);
52481
52627
  try {
52482
- return await tool.execute(toolCallId, params, signal, onUpdate);
52628
+ const hookOutcome = await runBeforeToolCallHook({
52629
+ toolName: name,
52630
+ params,
52631
+ toolCallId
52632
+ });
52633
+ if (hookOutcome.blocked) throw new Error(hookOutcome.reason);
52634
+ const adjustedParams = hookOutcome.params;
52635
+ const result = await tool.execute(toolCallId, adjustedParams, signal, onUpdate);
52636
+ const hookRunner = getGlobalHookRunner();
52637
+ if (hookRunner?.hasHooks("after_tool_call")) try {
52638
+ await hookRunner.runAfterToolCall({
52639
+ toolName: name,
52640
+ params: isPlainObject(adjustedParams) ? adjustedParams : {},
52641
+ result
52642
+ }, { toolName: name });
52643
+ } catch (hookErr) {
52644
+ logDebug(`after_tool_call hook failed: tool=${normalizedName} error=${String(hookErr)}`);
52645
+ }
52646
+ return result;
52483
52647
  } catch (err) {
52484
52648
  if (signal?.aborted) throw err;
52485
52649
  if ((err && typeof err === "object" && "name" in err ? String(err.name) : "") === "AbortError") throw err;
52486
52650
  const described = describeToolExecutionError(err);
52487
52651
  if (described.stack && described.stack !== described.message) logDebug(`tools: ${normalizedName} failed stack:\n${described.stack}`);
52488
52652
  logError(`[tools] ${normalizedName} failed: ${described.message}`);
52489
- return jsonResult({
52653
+ const errorResult = jsonResult({
52490
52654
  status: "error",
52491
52655
  tool: normalizedName,
52492
52656
  error: described.message
52493
52657
  });
52658
+ const hookRunner = getGlobalHookRunner();
52659
+ if (hookRunner?.hasHooks("after_tool_call")) try {
52660
+ await hookRunner.runAfterToolCall({
52661
+ toolName: normalizedName,
52662
+ params: isPlainObject(params) ? params : {},
52663
+ error: described.message
52664
+ }, { toolName: normalizedName });
52665
+ } catch (hookErr) {
52666
+ logDebug(`after_tool_call hook failed: tool=${normalizedName} error=${String(hookErr)}`);
52667
+ }
52668
+ return errorResult;
52494
52669
  }
52495
52670
  }
52496
52671
  };
@@ -53590,6 +53765,10 @@ function handleAutoCompactionStart(ctx) {
53590
53765
  stream: "compaction",
53591
53766
  data: { phase: "start" }
53592
53767
  });
53768
+ const hookRunner = getGlobalHookRunner();
53769
+ if (hookRunner?.hasHooks("before_compaction")) hookRunner.runBeforeCompaction({ messageCount: ctx.params.session.messages?.length ?? 0 }, {}).catch((err) => {
53770
+ ctx.log.warn(`before_compaction hook failed: ${String(err)}`);
53771
+ });
53593
53772
  }
53594
53773
  function handleAutoCompactionEnd(ctx, evt) {
53595
53774
  ctx.state.compactionInFlight = false;
@@ -53614,6 +53793,15 @@ function handleAutoCompactionEnd(ctx, evt) {
53614
53793
  willRetry
53615
53794
  }
53616
53795
  });
53796
+ if (!willRetry) {
53797
+ const hookRunnerEnd = getGlobalHookRunner();
53798
+ if (hookRunnerEnd?.hasHooks("after_compaction")) hookRunnerEnd.runAfterCompaction({
53799
+ messageCount: ctx.params.session.messages?.length ?? 0,
53800
+ compactedCount: ctx.getCompactionCount()
53801
+ }, {}).catch((err) => {
53802
+ ctx.log.warn(`after_compaction hook failed: ${String(err)}`);
53803
+ });
53804
+ }
53617
53805
  }
53618
53806
  function handleAgentEnd(ctx) {
53619
53807
  ctx.log.debug(`embedded run agent end: runId=${ctx.params.runId}`);
@@ -54053,6 +54241,8 @@ function extractMessagingToolSend(toolName, args) {
54053
54241
 
54054
54242
  //#endregion
54055
54243
  //#region src/agents/pi-embedded-subscribe.handlers.tools.ts
54244
+ /** Track tool execution start times and args for after_tool_call hook */
54245
+ const toolStartData = /* @__PURE__ */ new Map();
54056
54246
  function extendExecMeta(toolName, args, meta) {
54057
54247
  const normalized = toolName.trim().toLowerCase();
54058
54248
  if (normalized !== "exec" && normalized !== "bash") return meta;
@@ -54071,6 +54261,20 @@ async function handleToolExecutionStart(ctx, evt) {
54071
54261
  const toolName = normalizeToolName(String(evt.toolName));
54072
54262
  const toolCallId = String(evt.toolCallId);
54073
54263
  const args = evt.args;
54264
+ toolStartData.set(toolCallId, {
54265
+ startTime: Date.now(),
54266
+ args
54267
+ });
54268
+ const hookRunner = ctx.hookRunner ?? getGlobalHookRunner();
54269
+ if (hookRunner?.hasHooks?.("before_tool_call")) try {
54270
+ const hookEvent = {
54271
+ toolName,
54272
+ params: args && typeof args === "object" ? args : {}
54273
+ };
54274
+ await hookRunner.runBeforeToolCall(hookEvent, { toolName });
54275
+ } catch (err) {
54276
+ ctx.log.debug(`before_tool_call hook failed: tool=${toolName} error=${String(err)}`);
54277
+ }
54074
54278
  if (toolName === "read") {
54075
54279
  const record = args && typeof args === "object" ? args : {};
54076
54280
  if (!(typeof record.path === "string" ? record.path.trim() : "")) {
@@ -54141,7 +54345,7 @@ function handleToolExecutionUpdate(ctx, evt) {
54141
54345
  }
54142
54346
  });
54143
54347
  }
54144
- function handleToolExecutionEnd(ctx, evt) {
54348
+ async function handleToolExecutionEnd(ctx, evt) {
54145
54349
  const toolName = normalizeToolName(String(evt.toolName));
54146
54350
  const toolCallId = String(evt.toolCallId);
54147
54351
  const isError = Boolean(evt.isError);
@@ -54208,6 +54412,27 @@ function handleToolExecutionEnd(ctx, evt) {
54208
54412
  const outputText = extractToolResultText(sanitizedResult);
54209
54413
  if (outputText) ctx.emitToolOutput(toolName, meta, outputText);
54210
54414
  }
54415
+ const hookRunnerAfter = ctx.hookRunner ?? getGlobalHookRunner();
54416
+ if (hookRunnerAfter?.hasHooks("after_tool_call")) {
54417
+ const startData = toolStartData.get(toolCallId);
54418
+ toolStartData.delete(toolCallId);
54419
+ const durationMs = startData?.startTime != null ? Date.now() - startData.startTime : void 0;
54420
+ const toolArgs = startData?.args;
54421
+ const hookEvent = {
54422
+ toolName,
54423
+ params: toolArgs && typeof toolArgs === "object" ? toolArgs : {},
54424
+ result: sanitizedResult,
54425
+ error: isToolError ? extractToolErrorMessage(sanitizedResult) : void 0,
54426
+ durationMs
54427
+ };
54428
+ hookRunnerAfter.runAfterToolCall(hookEvent, {
54429
+ toolName,
54430
+ agentId: void 0,
54431
+ sessionKey: void 0
54432
+ }).catch((err) => {
54433
+ ctx.log.warn(`after_tool_call hook failed: tool=${toolName} error=${String(err)}`);
54434
+ });
54435
+ } else toolStartData.delete(toolCallId);
54211
54436
  }
54212
54437
 
54213
54438
  //#endregion
@@ -54233,7 +54458,9 @@ function createEmbeddedPiSessionEventHandler(ctx) {
54233
54458
  handleToolExecutionUpdate(ctx, evt);
54234
54459
  return;
54235
54460
  case "tool_execution_end":
54236
- handleToolExecutionEnd(ctx, evt);
54461
+ handleToolExecutionEnd(ctx, evt).catch((err) => {
54462
+ ctx.log.debug(`tool_execution_end handler failed: ${String(err)}`);
54463
+ });
54237
54464
  return;
54238
54465
  case "agent_start":
54239
54466
  handleAgentStart(ctx);
@@ -54617,6 +54844,7 @@ function subscribeEmbeddedPiSession(params) {
54617
54844
  log: log$1,
54618
54845
  blockChunking,
54619
54846
  blockChunker,
54847
+ hookRunner: params.hookRunner,
54620
54848
  shouldEmitToolResult,
54621
54849
  shouldEmitToolOutput,
54622
54850
  emitToolSummary,
@@ -55341,6 +55569,7 @@ async function runEmbeddedAttempt(params) {
55341
55569
  sessionManager = guardSessionManager(SessionManager.open(params.sessionFile), {
55342
55570
  agentId: sessionAgentId,
55343
55571
  sessionKey: params.sessionKey,
55572
+ inputProvenance: params.inputProvenance,
55344
55573
  allowSyntheticToolResults: transcriptPolicy.allowSyntheticToolResults
55345
55574
  });
55346
55575
  trackSessionManagerAccess(params.sessionFile);
@@ -55363,6 +55592,7 @@ async function runEmbeddedAttempt(params) {
55363
55592
  modelId: params.modelId,
55364
55593
  model: params.model
55365
55594
  });
55595
+ const hookRunner = getGlobalHookRunner();
55366
55596
  const { builtInTools, customTools } = splitSdkTools({
55367
55597
  tools,
55368
55598
  sandboxEnabled: !!sandbox?.enabled
@@ -55488,6 +55718,7 @@ async function runEmbeddedAttempt(params) {
55488
55718
  const subscription = subscribeEmbeddedPiSession({
55489
55719
  session: activeSession,
55490
55720
  runId: params.runId,
55721
+ hookRunner: getGlobalHookRunner() ?? void 0,
55491
55722
  verboseLevel: params.verboseLevel,
55492
55723
  reasoningMode: params.reasoningLevel ?? "off",
55493
55724
  toolResultFormat: params.toolResultFormat,
@@ -55532,7 +55763,6 @@ async function runEmbeddedAttempt(params) {
55532
55763
  };
55533
55764
  if (params.abortSignal) if (params.abortSignal.aborted) onAbort();
55534
55765
  else params.abortSignal.addEventListener("abort", onAbort, { once: true });
55535
- const hookRunner = getGlobalHookRunner();
55536
55766
  const hookAgentId = typeof params.agentId === "string" && params.agentId.trim() ? normalizeAgentId(params.agentId) : resolveSessionAgentIds({
55537
55767
  sessionKey: params.sessionKey,
55538
55768
  config: params.config
@@ -55988,6 +56218,7 @@ async function runEmbeddedPiAgent(params) {
55988
56218
  let overflowCompactionAttempts = 0;
55989
56219
  let toolResultTruncationAttempted = false;
55990
56220
  const usageAccumulator = createUsageAccumulator();
56221
+ let lastRunPromptUsage;
55991
56222
  let autoCompactionCount = 0;
55992
56223
  try {
55993
56224
  while (true) {
@@ -56046,12 +56277,16 @@ async function runEmbeddedPiAgent(params) {
56046
56277
  onToolResult: params.onToolResult,
56047
56278
  onAgentEvent: params.onAgentEvent,
56048
56279
  extraSystemPrompt: params.extraSystemPrompt,
56280
+ inputProvenance: params.inputProvenance,
56049
56281
  streamParams: params.streamParams,
56050
56282
  ownerNumbers: params.ownerNumbers,
56051
56283
  enforceFinalTag: params.enforceFinalTag
56052
56284
  });
56053
56285
  const { aborted, promptError, timedOut, sessionIdUsed, lastAssistant } = attempt;
56054
- mergeUsageIntoAccumulator(usageAccumulator, attempt.attemptUsage ?? normalizeUsage(lastAssistant?.usage));
56286
+ const lastAssistantUsage = normalizeUsage(lastAssistant?.usage);
56287
+ const attemptUsage = attempt.attemptUsage ?? lastAssistantUsage;
56288
+ mergeUsageIntoAccumulator(usageAccumulator, attemptUsage);
56289
+ lastRunPromptUsage = lastAssistantUsage ?? attemptUsage;
56055
56290
  autoCompactionCount += Math.max(0, attempt.compactionCount ?? 0);
56056
56291
  const formattedAssistantErrorText = lastAssistant ? formatAssistantErrorText(lastAssistant, {
56057
56292
  cfg: params.config,
@@ -56062,13 +56297,13 @@ async function runEmbeddedPiAgent(params) {
56062
56297
  const contextOverflowError = !aborted ? (() => {
56063
56298
  if (promptError) {
56064
56299
  const errorText = describeUnknownError(promptError);
56065
- if (isContextOverflowError(errorText)) return {
56300
+ if (isLikelyContextOverflowError(errorText)) return {
56066
56301
  text: errorText,
56067
56302
  source: "promptError"
56068
56303
  };
56069
56304
  return null;
56070
56305
  }
56071
- if (assistantErrorText && isContextOverflowError(assistantErrorText)) return {
56306
+ if (assistantErrorText && isLikelyContextOverflowError(assistantErrorText)) return {
56072
56307
  text: assistantErrorText,
56073
56308
  source: "assistantError"
56074
56309
  };
@@ -56279,11 +56514,15 @@ async function runEmbeddedPiAgent(params) {
56279
56514
  }
56280
56515
  }
56281
56516
  const usage = toNormalizedUsage(usageAccumulator);
56517
+ const lastCallUsage = normalizeUsage(lastAssistant?.usage);
56518
+ const promptTokens = derivePromptTokens(lastRunPromptUsage);
56282
56519
  const agentMeta = {
56283
56520
  sessionId: sessionIdUsed,
56284
56521
  provider: lastAssistant?.provider ?? provider,
56285
56522
  model: lastAssistant?.model ?? model.id,
56286
56523
  usage,
56524
+ lastCallUsage: lastCallUsage ?? void 0,
56525
+ promptTokens,
56287
56526
  compactionCount: autoCompactionCount > 0 ? autoCompactionCount : void 0
56288
56527
  };
56289
56528
  const payloads = buildEmbeddedRunPayloads({
@@ -60700,24 +60939,58 @@ function formatMediaAttachedLine(params) {
60700
60939
  const urlPart = urlRaw ? ` | ${urlRaw}` : "";
60701
60940
  return `${prefix}${params.path}${typePart}${urlPart}]`;
60702
60941
  }
60942
+ const AUDIO_EXTENSIONS = new Set([
60943
+ ".ogg",
60944
+ ".opus",
60945
+ ".mp3",
60946
+ ".m4a",
60947
+ ".wav",
60948
+ ".webm",
60949
+ ".flac",
60950
+ ".aac",
60951
+ ".wma",
60952
+ ".aiff",
60953
+ ".alac",
60954
+ ".oga"
60955
+ ]);
60956
+ function isAudioPath(path) {
60957
+ if (!path) return false;
60958
+ const lower = path.toLowerCase();
60959
+ for (const ext of AUDIO_EXTENSIONS) if (lower.endsWith(ext)) return true;
60960
+ return false;
60961
+ }
60703
60962
  function buildInboundMediaNote(ctx) {
60704
60963
  const suppressed = /* @__PURE__ */ new Set();
60705
- if (Array.isArray(ctx.MediaUnderstanding)) for (const output of ctx.MediaUnderstanding) suppressed.add(output.attachmentIndex);
60964
+ const transcribedAudioIndices = /* @__PURE__ */ new Set();
60965
+ if (Array.isArray(ctx.MediaUnderstanding)) for (const output of ctx.MediaUnderstanding) {
60966
+ suppressed.add(output.attachmentIndex);
60967
+ if (output.kind === "audio.transcription") transcribedAudioIndices.add(output.attachmentIndex);
60968
+ }
60706
60969
  if (Array.isArray(ctx.MediaUnderstandingDecisions)) for (const decision of ctx.MediaUnderstandingDecisions) {
60707
60970
  if (decision.outcome !== "success") continue;
60708
- for (const attachment of decision.attachments) if (attachment.chosen?.outcome === "success") suppressed.add(attachment.attachmentIndex);
60971
+ for (const attachment of decision.attachments) if (attachment.chosen?.outcome === "success") {
60972
+ suppressed.add(attachment.attachmentIndex);
60973
+ if (decision.capability === "audio") transcribedAudioIndices.add(attachment.attachmentIndex);
60974
+ }
60709
60975
  }
60710
60976
  const pathsFromArray = Array.isArray(ctx.MediaPaths) ? ctx.MediaPaths : void 0;
60711
60977
  const paths = pathsFromArray && pathsFromArray.length > 0 ? pathsFromArray : ctx.MediaPath?.trim() ? [ctx.MediaPath.trim()] : [];
60712
60978
  if (paths.length === 0) return;
60713
60979
  const urls = Array.isArray(ctx.MediaUrls) && ctx.MediaUrls.length === paths.length ? ctx.MediaUrls : void 0;
60714
60980
  const types = Array.isArray(ctx.MediaTypes) && ctx.MediaTypes.length === paths.length ? ctx.MediaTypes : void 0;
60981
+ const canStripSingleAttachmentByTranscript = Boolean(ctx.Transcript?.trim()) && paths.length === 1;
60715
60982
  const entries = paths.map((entry, index) => ({
60716
60983
  path: entry ?? "",
60717
60984
  type: types?.[index] ?? ctx.MediaType,
60718
60985
  url: urls?.[index] ?? ctx.MediaUrl,
60719
60986
  index
60720
- })).filter((entry) => !suppressed.has(entry.index));
60987
+ })).filter((entry) => {
60988
+ if (suppressed.has(entry.index)) return false;
60989
+ const isAudioByMime = types !== void 0 && entry.type?.toLowerCase().startsWith("audio/");
60990
+ if (!(isAudioPath(entry.path) || isAudioByMime)) return true;
60991
+ if (transcribedAudioIndices.has(entry.index) || canStripSingleAttachmentByTranscript && entry.index === 0) return false;
60992
+ return true;
60993
+ });
60721
60994
  if (entries.length === 0) return;
60722
60995
  if (entries.length === 1) return formatMediaAttachedLine({
60723
60996
  path: entries[0]?.path ?? "",
@@ -62189,6 +62462,7 @@ const DEFAULT_MEMORY_FLUSH_SOFT_TOKENS = 4e3;
62189
62462
  const DEFAULT_MEMORY_FLUSH_PROMPT = [
62190
62463
  "Pre-compaction memory flush.",
62191
62464
  "Store durable memories now (use memory/YYYY-MM-DD.md; create memory/ if needed).",
62465
+ "IMPORTANT: If the file already exists, APPEND new content only and do not overwrite existing entries.",
62192
62466
  `If nothing to store, reply with ${SILENT_REPLY_TOKEN}.`
62193
62467
  ].join(" ");
62194
62468
  const DEFAULT_MEMORY_FLUSH_SYSTEM_PROMPT = [
@@ -62440,8 +62714,9 @@ async function persistSessionUsageUpdate(params) {
62440
62714
  inputTokens: input,
62441
62715
  outputTokens: output,
62442
62716
  totalTokens: deriveSessionTotalTokens({
62443
- usage: params.usage,
62444
- contextTokens: resolvedContextTokens
62717
+ usage: params.lastCallUsage ?? params.usage,
62718
+ contextTokens: resolvedContextTokens,
62719
+ promptTokens: params.promptTokens
62445
62720
  }) ?? input,
62446
62721
  modelProvider: params.providerUsed ?? entry.modelProvider,
62447
62722
  model: params.modelUsed ?? entry.model,
@@ -62503,6 +62778,36 @@ async function persistSessionUsageUpdate(params) {
62503
62778
  }
62504
62779
  }
62505
62780
 
62781
+ //#endregion
62782
+ //#region src/auto-reply/reply/session-run-accounting.ts
62783
+ async function persistRunSessionUsage(params) {
62784
+ await persistSessionUsageUpdate({
62785
+ storePath: params.storePath,
62786
+ sessionKey: params.sessionKey,
62787
+ usage: params.usage,
62788
+ lastCallUsage: params.lastCallUsage,
62789
+ modelUsed: params.modelUsed,
62790
+ providerUsed: params.providerUsed,
62791
+ contextTokensUsed: params.contextTokensUsed,
62792
+ systemPromptReport: params.systemPromptReport,
62793
+ cliSessionId: params.cliSessionId,
62794
+ logLabel: params.logLabel
62795
+ });
62796
+ }
62797
+ async function incrementRunCompactionCount(params) {
62798
+ const tokensAfterCompaction = params.lastCallUsage ? deriveSessionTotalTokens({
62799
+ usage: params.lastCallUsage,
62800
+ contextTokens: params.contextTokensUsed
62801
+ }) : void 0;
62802
+ return incrementCompactionCount({
62803
+ sessionEntry: params.sessionEntry,
62804
+ sessionStore: params.sessionStore,
62805
+ sessionKey: params.sessionKey,
62806
+ storePath: params.storePath,
62807
+ tokensAfter: tokensAfterCompaction
62808
+ });
62809
+ }
62810
+
62506
62811
  //#endregion
62507
62812
  //#region src/auto-reply/reply/typing-mode.ts
62508
62813
  const DEFAULT_GROUP_TYPING_MODE = "message";
@@ -62693,20 +62998,21 @@ function createFollowupRunner(params) {
62693
62998
  defaultRuntime.error?.(`Followup agent failed before reply: ${message}`);
62694
62999
  return;
62695
63000
  }
62696
- if (storePath && sessionKey) {
62697
- const usage = runResult.meta.agentMeta?.usage;
62698
- const modelUsed = runResult.meta.agentMeta?.model ?? fallbackModel ?? defaultModel;
62699
- const contextTokensUsed = agentCfgContextTokens ?? lookupContextTokens(modelUsed) ?? sessionEntry?.contextTokens ?? DEFAULT_CONTEXT_TOKENS;
62700
- await persistSessionUsageUpdate({
62701
- storePath,
62702
- sessionKey,
62703
- usage,
62704
- modelUsed,
62705
- providerUsed: fallbackProvider,
62706
- contextTokensUsed,
62707
- logLabel: "followup"
62708
- });
62709
- }
63001
+ const usage = runResult.meta.agentMeta?.usage;
63002
+ const promptTokens = runResult.meta.agentMeta?.promptTokens;
63003
+ const modelUsed = runResult.meta.agentMeta?.model ?? fallbackModel ?? defaultModel;
63004
+ const contextTokensUsed = agentCfgContextTokens ?? lookupContextTokens(modelUsed) ?? sessionEntry?.contextTokens ?? DEFAULT_CONTEXT_TOKENS;
63005
+ if (storePath && sessionKey) await persistRunSessionUsage({
63006
+ storePath,
63007
+ sessionKey,
63008
+ usage,
63009
+ lastCallUsage: runResult.meta.agentMeta?.lastCallUsage,
63010
+ promptTokens,
63011
+ modelUsed,
63012
+ providerUsed: fallbackProvider,
63013
+ contextTokensUsed,
63014
+ logLabel: "followup"
63015
+ });
62710
63016
  const payloadArray = runResult.payloads ?? [];
62711
63017
  if (payloadArray.length === 0) return;
62712
63018
  const sanitizedPayloads = payloadArray.flatMap((payload) => {
@@ -62737,11 +63043,13 @@ function createFollowupRunner(params) {
62737
63043
  }) ? [] : dedupedPayloads;
62738
63044
  if (finalPayloads.length === 0) return;
62739
63045
  if (autoCompactionCompleted) {
62740
- const count = await incrementCompactionCount({
63046
+ const count = await incrementRunCompactionCount({
62741
63047
  sessionEntry,
62742
63048
  sessionStore,
62743
63049
  sessionKey,
62744
- storePath
63050
+ storePath,
63051
+ lastCallUsage: runResult.meta.agentMeta?.lastCallUsage,
63052
+ contextTokensUsed
62745
63053
  });
62746
63054
  if (queued.run.verboseLevel && queued.run.verboseLevel !== "off") {
62747
63055
  const suffix = typeof count === "number" ? ` (count ${count})` : "";
@@ -62948,14 +63256,17 @@ async function runReplyAgent(params) {
62948
63256
  }
62949
63257
  if (pendingToolTasks.size > 0) await Promise.allSettled(pendingToolTasks);
62950
63258
  const usage = runResult.meta.agentMeta?.usage;
63259
+ const promptTokens = runResult.meta.agentMeta?.promptTokens;
62951
63260
  const modelUsed = runResult.meta.agentMeta?.model ?? fallbackModel ?? defaultModel;
62952
63261
  const providerUsed = runResult.meta.agentMeta?.provider ?? fallbackProvider ?? followupRun.run.provider;
62953
63262
  const cliSessionId = isCliProvider(providerUsed, cfg) ? runResult.meta.agentMeta?.sessionId?.trim() : void 0;
62954
63263
  const contextTokensUsed = agentCfgContextTokens ?? lookupContextTokens(modelUsed) ?? activeSessionEntry?.contextTokens ?? DEFAULT_CONTEXT_TOKENS;
62955
- await persistSessionUsageUpdate({
63264
+ await persistRunSessionUsage({
62956
63265
  storePath,
62957
63266
  sessionKey,
62958
63267
  usage,
63268
+ lastCallUsage: runResult.meta.agentMeta?.lastCallUsage,
63269
+ promptTokens,
62959
63270
  modelUsed,
62960
63271
  providerUsed,
62961
63272
  contextTokensUsed,
@@ -63039,11 +63350,13 @@ async function runReplyAgent(params) {
63039
63350
  let finalPayloads = replyPayloads;
63040
63351
  const verboseEnabled = resolvedVerboseLevel !== "off";
63041
63352
  if (autoCompactionCompleted) {
63042
- const count = await incrementCompactionCount({
63353
+ const count = await incrementRunCompactionCount({
63043
63354
  sessionEntry: activeSessionEntry,
63044
63355
  sessionStore: activeSessionStore,
63045
63356
  sessionKey,
63046
- storePath
63357
+ storePath,
63358
+ lastCallUsage: runResult.meta.agentMeta?.lastCallUsage,
63359
+ contextTokensUsed
63047
63360
  });
63048
63361
  if (verboseEnabled) finalPayloads = [{ text: `🧹 Auto-compaction complete${typeof count === "number" ? ` (count ${count})` : ""}.` }, ...finalPayloads];
63049
63362
  }
@@ -63626,7 +63939,7 @@ async function deliverSessionMaintenanceWarning(params) {
63626
63939
  return;
63627
63940
  }
63628
63941
  try {
63629
- const { deliverOutboundPayloads } = await import("./deliver-B1jsU2r7.js").then((n) => n.n);
63942
+ const { deliverOutboundPayloads } = await import("./deliver-LsxKETro.js").then((n) => n.n);
63630
63943
  await deliverOutboundPayloads({
63631
63944
  cfg: params.cfg,
63632
63945
  channel,
@@ -63644,7 +63957,7 @@ async function deliverSessionMaintenanceWarning(params) {
63644
63957
  //#endregion
63645
63958
  //#region src/auto-reply/reply/session.ts
63646
63959
  function forkSessionFromParent(params) {
63647
- const parentSessionFile = resolveSessionFilePath(params.parentEntry.sessionId, params.parentEntry);
63960
+ const parentSessionFile = resolveSessionFilePath(params.parentEntry.sessionId, params.parentEntry, { sessionsDir: params.sessionsDir });
63648
63961
  if (!parentSessionFile || !fs.existsSync(parentSessionFile)) return null;
63649
63962
  try {
63650
63963
  const manager = SessionManager.open(parentSessionFile);
@@ -63847,7 +64160,10 @@ async function initSessionState(params) {
63847
64160
  const parentSessionKey = ctx.ParentSessionKey?.trim();
63848
64161
  if (isNewSession && parentSessionKey && parentSessionKey !== sessionKey && sessionStore[parentSessionKey]) {
63849
64162
  console.warn(`[session-init] forking from parent session: parentKey=${parentSessionKey} → sessionKey=${sessionKey} parentTokens=${sessionStore[parentSessionKey].totalTokens ?? "?"}`);
63850
- const forked = forkSessionFromParent({ parentEntry: sessionStore[parentSessionKey] });
64163
+ const forked = forkSessionFromParent({
64164
+ parentEntry: sessionStore[parentSessionKey],
64165
+ sessionsDir: path.dirname(storePath)
64166
+ });
63851
64167
  if (forked) {
63852
64168
  sessionId = forked.sessionId;
63853
64169
  sessionEntry.sessionId = forked.sessionId;
@@ -63883,13 +64199,40 @@ async function initSessionState(params) {
63883
64199
  warning
63884
64200
  })
63885
64201
  });
64202
+ const sessionCtx = {
64203
+ ...ctx,
64204
+ BodyStripped: normalizeInboundTextNewlines(bodyStripped ?? ctx.BodyForAgent ?? ctx.Body ?? ctx.CommandBody ?? ctx.RawBody ?? ctx.BodyForCommands ?? ""),
64205
+ SessionId: sessionId,
64206
+ IsNewSession: isNewSession ? "true" : "false"
64207
+ };
64208
+ const hookRunner = getGlobalHookRunner();
64209
+ if (hookRunner && isNewSession) {
64210
+ const effectiveSessionId = sessionId ?? "";
64211
+ if (previousSessionEntry?.sessionId && previousSessionEntry.sessionId !== effectiveSessionId) {
64212
+ if (hookRunner.hasHooks("session_end")) hookRunner.runSessionEnd({
64213
+ sessionId: previousSessionEntry.sessionId,
64214
+ messageCount: 0
64215
+ }, {
64216
+ sessionId: previousSessionEntry.sessionId,
64217
+ agentId: resolveSessionAgentId({
64218
+ sessionKey,
64219
+ config: cfg
64220
+ })
64221
+ }).catch(() => {});
64222
+ }
64223
+ if (hookRunner.hasHooks("session_start")) hookRunner.runSessionStart({
64224
+ sessionId: effectiveSessionId,
64225
+ resumedFrom: previousSessionEntry?.sessionId
64226
+ }, {
64227
+ sessionId: effectiveSessionId,
64228
+ agentId: resolveSessionAgentId({
64229
+ sessionKey,
64230
+ config: cfg
64231
+ })
64232
+ }).catch(() => {});
64233
+ }
63886
64234
  return {
63887
- sessionCtx: {
63888
- ...ctx,
63889
- BodyStripped: normalizeInboundTextNewlines(bodyStripped ?? ctx.BodyForAgent ?? ctx.Body ?? ctx.CommandBody ?? ctx.RawBody ?? ctx.BodyForCommands ?? ""),
63890
- SessionId: sessionId,
63891
- IsNewSession: isNewSession ? "true" : "false"
63892
- },
64235
+ sessionCtx,
63893
64236
  sessionEntry,
63894
64237
  previousSessionEntry,
63895
64238
  sessionStore,