shadow-claw 1.40.0 → 1.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/.well-known/mcp/server-card.json +2 -2
  2. package/.well-known/mcp/servers.json +1 -1
  3. package/.well-known/mcp.json +2 -2
  4. package/README.md +1 -0
  5. package/dist/cli/build/build.js +1 -1
  6. package/dist/cli/{chunk-Bfz2NYgD.js → chunk-0IeC97mU.js} +7 -7
  7. package/dist/cli/chunk-3oLxlxPn.js +1 -0
  8. package/dist/cli/{chunk-BXg4-9Rq2.js → chunk-8CrZyP1b2.js} +1 -1
  9. package/dist/cli/{chunk-BP5Hg6CM.js → chunk-B--ueArB.js} +1 -1
  10. package/dist/cli/chunk-BIh7rXlJ2.js +1 -0
  11. package/dist/cli/{chunk-Drr0VSGA2.js → chunk-BKnTOLLS2.js} +1 -1
  12. package/dist/cli/{chunk-C5PuRV08.js → chunk-BLMC1Bxv.js} +1 -1
  13. package/dist/cli/{chunk-B2tNSlFy2.js → chunk-BOigzz2U2.js} +1 -1
  14. package/dist/cli/{chunk-DOf3DZdR.js → chunk-BOzn335y.js} +1 -1
  15. package/dist/cli/chunk-BjOeVLb42.js +1 -0
  16. package/dist/cli/{chunk-DqTx0rRp2.js → chunk-Bjqh5_SU2.js} +1 -1
  17. package/dist/cli/chunk-BqWBd_jF2.js +1 -0
  18. package/dist/cli/{chunk-Bc9nRNyN.js → chunk-BvVUnHTq.js} +12 -9
  19. package/dist/cli/{chunk-DIbSoQmd2.js → chunk-C6FFByBU2.js} +2 -2
  20. package/dist/cli/{chunk-Drq18VZe.js → chunk-C9-aL3rF.js} +1 -1
  21. package/dist/cli/{chunk-BUhqHeEA2.js → chunk-C9czddEh2.js} +2 -2
  22. package/dist/cli/chunk-CCx8WOwz2.js +1 -0
  23. package/dist/cli/{chunk-BkMSjVJb.js → chunk-CK6ejMig.js} +1 -1
  24. package/dist/cli/chunk-CUUERioR2.js +1 -0
  25. package/dist/cli/chunk-CXAobnJd.js +1 -0
  26. package/dist/cli/chunk-CY1X0pOF2.js +1 -0
  27. package/dist/cli/chunk-CZvvgLVv.js +1 -0
  28. package/dist/cli/chunk-CbcwbfJB.js +1 -0
  29. package/dist/cli/{chunk-quilB3TV2.js → chunk-Ci9OJGcd2.js} +1 -1
  30. package/dist/cli/chunk-Cj9wl0qx.js +1 -0
  31. package/dist/cli/{chunk-3gRhOmGo2.js → chunk-CjJsVrKI2.js} +1 -1
  32. package/dist/cli/{chunk-CmEfzm-_.js → chunk-ClPZ4Rea.js} +1 -1
  33. package/dist/cli/{chunk-WMPAfIvV2.js → chunk-DHJCGRuG2.js} +1 -1
  34. package/dist/cli/{chunk-C7Y2xIk4.js → chunk-DKVkYTV9.js} +1 -1
  35. package/dist/cli/chunk-DR2XtWRo.js +1 -0
  36. package/dist/cli/{chunk-DID5VvOG.js → chunk-DTES-dE6.js} +3 -3
  37. package/dist/cli/{chunk-BiVJVh_S.js → chunk-DUlIqkaX.js} +7 -7
  38. package/dist/cli/{chunk-CkpueGaZ2.js → chunk-DjWle8FF2.js} +1 -1
  39. package/dist/cli/{chunk-CSvHmNOk.js → chunk-DmRXVLfy.js} +1 -1
  40. package/dist/cli/{chunk-BT1xXZn72.js → chunk-HlSiTC-u2.js} +1 -1
  41. package/dist/cli/{chunk-da0bsiOn.js → chunk-P4JSeFBI.js} +1 -1
  42. package/dist/cli/chunk-UcNbHaRQ.js +1 -0
  43. package/dist/cli/{chunk-BXFHFbEd.js → chunk-UweLmfQS.js} +1 -1
  44. package/dist/cli/chunk-bQQkVCw-.js +94 -0
  45. package/dist/cli/{chunk-CGiXWHTi2.js → chunk-gwpxl-0W2.js} +1 -1
  46. package/dist/cli/{chunk-NH8koEis2.js → chunk-nmDhxXH_2.js} +1 -1
  47. package/dist/cli/chunk-p0n_c-I2.js +1 -0
  48. package/dist/cli/{chunk-D7xP72La.js → chunk-q7r4FosZ.js} +1 -1
  49. package/dist/cli/cli.js +3 -3
  50. package/dist/cli/prerender/dsd-shell/prerender-dsd-shell.js +1 -1
  51. package/dist/electron/main.cjs +1 -1
  52. package/dist/headless-agent.js +1 -1
  53. package/dist/lib/{app-routes-BAEMLu9g.js → app-routes-CKkiX12g.js} +7 -2
  54. package/dist/lib/app-routes-CKkiX12g.js.map +1 -0
  55. package/dist/lib/components/index.js +26 -26
  56. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  57. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  58. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  59. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  60. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  61. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  62. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  63. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  64. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  65. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  66. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  67. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  68. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  69. package/dist/lib/components/shadow-claw/utils/syncSlottedSidebarActiveLinks.d.ts +10 -0
  70. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  71. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  72. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  73. package/dist/lib/components/shadow-claw-channels.js +1 -1
  74. package/dist/lib/components/shadow-claw-chat.js +1 -1
  75. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  76. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  77. package/dist/lib/components/shadow-claw-file-viewer/shadow-claw-file-viewer.d.ts +1 -1
  78. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  79. package/dist/lib/components/shadow-claw-files.js +1 -1
  80. package/dist/lib/components/shadow-claw-git.js +1 -1
  81. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  82. package/dist/lib/components/shadow-claw-llm.js +1 -1
  83. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  84. package/dist/lib/components/shadow-claw-networking.js +1 -1
  85. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  86. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  87. package/dist/lib/components/shadow-claw-pages.js +1 -1
  88. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  89. package/dist/lib/components/shadow-claw-settings.js +1 -1
  90. package/dist/lib/components/shadow-claw-storage.js +1 -1
  91. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  92. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  93. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  94. package/dist/lib/components/shadow-claw-tools.js +1 -1
  95. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  96. package/dist/lib/components/shadow-claw.js +1 -1
  97. package/dist/lib/{config-CPHDmyTx.js → config-DZkF9LiO.js} +2 -2
  98. package/dist/lib/{config-CPHDmyTx.js.map → config-DZkF9LiO.js.map} +1 -1
  99. package/dist/lib/{configurePeerJs-BsJoycQd.js → configurePeerJs-B3IE9BY2.js} +3 -3
  100. package/dist/lib/{configurePeerJs-BsJoycQd.js.map → configurePeerJs-B3IE9BY2.js.map} +1 -1
  101. package/dist/lib/{connections-BdIru7bF.js → connections-CalJGWvZ.js} +2 -2
  102. package/dist/lib/{connections-BdIru7bF.js.map → connections-CalJGWvZ.js.map} +1 -1
  103. package/dist/lib/core/orchestrator/orchestrator-state.d.ts +2 -1
  104. package/dist/lib/core/orchestrator/orchestrator.d.ts +2 -1
  105. package/dist/lib/core/orchestrator/utils/operations/task.d.ts +1 -0
  106. package/dist/lib/{downloadGroupFile-Dn0KsMlV.js → downloadGroupFile-DDE1fIhJ.js} +2 -2
  107. package/dist/lib/{downloadGroupFile-Dn0KsMlV.js.map → downloadGroupFile-DDE1fIhJ.js.map} +1 -1
  108. package/dist/lib/{file-viewer-BYrXXu-X.js → file-viewer-Bll2EoGc.js} +5 -5
  109. package/dist/lib/{file-viewer-BYrXXu-X.js.map → file-viewer-Bll2EoGc.js.map} +1 -1
  110. package/dist/lib/{getGroupDir-DF-RZO8X.js → getGroupDir-MHv7Lvmp.js} +4 -4
  111. package/dist/lib/{getGroupDir-DF-RZO8X.js.map → getGroupDir-MHv7Lvmp.js.map} +1 -1
  112. package/dist/lib/{git-s_0cgKm1.js → git-Bv_M3dgw.js} +3 -3
  113. package/dist/lib/{git-s_0cgKm1.js.map → git-Bv_M3dgw.js.map} +1 -1
  114. package/dist/lib/{iframe-sanitizer-DFdda1jJ.js → iframe-sanitizer-C7ZGDjEI.js} +2 -2
  115. package/dist/lib/{iframe-sanitizer-DFdda1jJ.js.map → iframe-sanitizer-C7ZGDjEI.js.map} +1 -1
  116. package/dist/lib/{iframe-storage-proxy-qrhZmQyO.js → iframe-storage-proxy-CR8ZYHPd.js} +2 -2
  117. package/dist/lib/{iframe-storage-proxy-qrhZmQyO.js.map → iframe-storage-proxy-CR8ZYHPd.js.map} +1 -1
  118. package/dist/lib/index.js +27 -27
  119. package/dist/lib/{initChatSplitResize-DuNlwCuI.js → initChatSplitResize-DiKTI-wk.js} +2 -2
  120. package/dist/lib/{initChatSplitResize-DuNlwCuI.js.map → initChatSplitResize-DiKTI-wk.js.map} +1 -1
  121. package/dist/lib/{initControlPlane-D4UZ4EhV.js → initControlPlane-CzjtQ4aM.js} +15 -15
  122. package/dist/lib/{initControlPlane-D4UZ4EhV.js.map → initControlPlane-CzjtQ4aM.js.map} +1 -1
  123. package/dist/lib/{markdown-CRRwbN9h.js → markdown-k8wA9LKy.js} +4 -4
  124. package/dist/lib/{markdown-CRRwbN9h.js.map → markdown-k8wA9LKy.js.map} +1 -1
  125. package/dist/lib/{mcp-reconnect-COdZ-cea.js → mcp-reconnect-CGIdfZnS.js} +2 -2
  126. package/dist/lib/{mcp-reconnect-COdZ-cea.js.map → mcp-reconnect-CGIdfZnS.js.map} +1 -1
  127. package/dist/lib/{memoryStorage-BsMe2FOQ.js → memoryStorage-DL-Bo3dh.js} +2 -2
  128. package/dist/lib/{memoryStorage-BsMe2FOQ.js.map → memoryStorage-DL-Bo3dh.js.map} +1 -1
  129. package/dist/lib/{orchestrator-D9f5fDCb.js → orchestrator-DKHCoikY.js} +11 -11
  130. package/dist/lib/{orchestrator-D9f5fDCb.js.map → orchestrator-DKHCoikY.js.map} +1 -1
  131. package/dist/lib/{orchestrator-Bq9ft3uG.js → orchestrator-Dn1ZOz9B.js} +20 -24
  132. package/dist/lib/orchestrator-Dn1ZOz9B.js.map +1 -0
  133. package/dist/lib/{peerjs-6u8KtenE.js → peerjs-BK41iBvP.js} +7 -7
  134. package/dist/lib/{peerjs-6u8KtenE.js.map → peerjs-BK41iBvP.js.map} +1 -1
  135. package/dist/lib/{push-client-DCnB2-OU.js → push-client-DKgVFD2Z.js} +3 -3
  136. package/dist/lib/{push-client-DCnB2-OU.js.map → push-client-DKgVFD2Z.js.map} +1 -1
  137. package/dist/lib/{readGroupFileBytes-nKNJ6sbl.js → readGroupFileBytes-CgU_UfGv.js} +2 -2
  138. package/dist/lib/{readGroupFileBytes-nKNJ6sbl.js.map → readGroupFileBytes-CgU_UfGv.js.map} +1 -1
  139. package/dist/lib/{shadow-claw-MumteAJy.js → shadow-claw-CtCj5Rn_.js} +121 -16
  140. package/dist/lib/shadow-claw-CtCj5Rn_.js.map +1 -0
  141. package/dist/lib/{shadow-claw-a2ui-Dipe8nY2.js → shadow-claw-a2ui-CvK5w940.js} +2 -2
  142. package/dist/lib/{shadow-claw-a2ui-Dipe8nY2.js.map → shadow-claw-a2ui-CvK5w940.js.map} +1 -1
  143. package/dist/lib/{shadow-claw-accounts-BgCkz3Zv.js → shadow-claw-accounts-Br3XdHro.js} +3 -3
  144. package/dist/lib/{shadow-claw-accounts-BgCkz3Zv.js.map → shadow-claw-accounts-Br3XdHro.js.map} +1 -1
  145. package/dist/lib/{shadow-claw-channel-config-CIm_Bxd2.js → shadow-claw-channel-config-Da2dN19M.js} +3 -3
  146. package/dist/lib/{shadow-claw-channel-config-CIm_Bxd2.js.map → shadow-claw-channel-config-Da2dN19M.js.map} +1 -1
  147. package/dist/lib/{shadow-claw-channels-CaceK52s.js → shadow-claw-channels-BofYHgz8.js} +3 -3
  148. package/dist/lib/{shadow-claw-channels-CaceK52s.js.map → shadow-claw-channels-BofYHgz8.js.map} +1 -1
  149. package/dist/lib/{shadow-claw-chat-BD18-mAR.js → shadow-claw-chat-Dw32DPV2.js} +12 -12
  150. package/dist/lib/{shadow-claw-chat-BD18-mAR.js.map → shadow-claw-chat-Dw32DPV2.js.map} +1 -1
  151. package/dist/lib/{shadow-claw-control-plane-U6LsfRPm.js → shadow-claw-control-plane-CwFotFDh.js} +7 -7
  152. package/dist/lib/{shadow-claw-control-plane-U6LsfRPm.js.map → shadow-claw-control-plane-CwFotFDh.js.map} +1 -1
  153. package/dist/lib/{shadow-claw-conversations-CDsza_oB.js → shadow-claw-conversations-0UXge23k.js} +5 -5
  154. package/dist/lib/{shadow-claw-conversations-CDsza_oB.js.map → shadow-claw-conversations-0UXge23k.js.map} +1 -1
  155. package/dist/lib/{shadow-claw-file-viewer-CMOnFmcP.js → shadow-claw-file-viewer-CAsn9NxH.js} +30 -30
  156. package/dist/lib/{shadow-claw-file-viewer-CMOnFmcP.js.map → shadow-claw-file-viewer-CAsn9NxH.js.map} +1 -1
  157. package/dist/lib/{shadow-claw-files-BI0P3m8a.js → shadow-claw-files-xGGhsHNH.js} +9 -9
  158. package/dist/lib/{shadow-claw-files-BI0P3m8a.js.map → shadow-claw-files-xGGhsHNH.js.map} +1 -1
  159. package/dist/lib/{shadow-claw-git-xRApLEMN.js → shadow-claw-git-B606hcMU.js} +6 -6
  160. package/dist/lib/{shadow-claw-git-xRApLEMN.js.map → shadow-claw-git-B606hcMU.js.map} +1 -1
  161. package/dist/lib/{shadow-claw-integrations-B2e1Nfg1.js → shadow-claw-integrations-Bwq5cba1.js} +4 -4
  162. package/dist/lib/{shadow-claw-integrations-B2e1Nfg1.js.map → shadow-claw-integrations-Bwq5cba1.js.map} +1 -1
  163. package/dist/lib/{shadow-claw-llm-Bc2mWuGb.js → shadow-claw-llm-BgpcMBIy.js} +6 -6
  164. package/dist/lib/{shadow-claw-llm-Bc2mWuGb.js.map → shadow-claw-llm-BgpcMBIy.js.map} +1 -1
  165. package/dist/lib/{shadow-claw-mcp-remote-D_Bh3aeC.js → shadow-claw-mcp-remote-DvQCA-Bk.js} +4 -4
  166. package/dist/lib/{shadow-claw-mcp-remote-D_Bh3aeC.js.map → shadow-claw-mcp-remote-DvQCA-Bk.js.map} +1 -1
  167. package/dist/lib/{shadow-claw-networking-F5W3n5ci.js → shadow-claw-networking-Cxvf9c7E.js} +2 -2
  168. package/dist/lib/{shadow-claw-networking-F5W3n5ci.js.map → shadow-claw-networking-Cxvf9c7E.js.map} +1 -1
  169. package/dist/lib/{shadow-claw-notifications-lvMt9WJ1.js → shadow-claw-notifications-CGVcFYBy.js} +3 -3
  170. package/dist/lib/{shadow-claw-notifications-lvMt9WJ1.js.map → shadow-claw-notifications-CGVcFYBy.js.map} +1 -1
  171. package/dist/lib/{shadow-claw-page-header-6gq6EMqX.js → shadow-claw-page-header-DAYz3I_o.js} +2 -2
  172. package/dist/lib/{shadow-claw-page-header-6gq6EMqX.js.map → shadow-claw-page-header-DAYz3I_o.js.map} +1 -1
  173. package/dist/lib/{shadow-claw-pages-Bo8_z2S-.js → shadow-claw-pages-BLeEZb9k.js} +24 -12
  174. package/dist/lib/shadow-claw-pages-BLeEZb9k.js.map +1 -0
  175. package/dist/lib/{shadow-claw-peerjs-DRTLCVDQ.js → shadow-claw-peerjs-BcFnbK74.js} +3 -3
  176. package/dist/lib/{shadow-claw-peerjs-DRTLCVDQ.js.map → shadow-claw-peerjs-BcFnbK74.js.map} +1 -1
  177. package/dist/lib/{shadow-claw-settings-D00B4p4L.js → shadow-claw-settings-B7o0Z4hu.js} +9 -9
  178. package/dist/lib/{shadow-claw-settings-D00B4p4L.js.map → shadow-claw-settings-B7o0Z4hu.js.map} +1 -1
  179. package/dist/lib/{shadow-claw-storage-DgMe7-Zo.js → shadow-claw-storage-afMVqB7E.js} +5 -5
  180. package/dist/lib/{shadow-claw-storage-DgMe7-Zo.js.map → shadow-claw-storage-afMVqB7E.js.map} +1 -1
  181. package/dist/lib/{shadow-claw-task-server-D103YOuI.js → shadow-claw-task-server-B9-MQjl6.js} +2 -2
  182. package/dist/lib/{shadow-claw-task-server-D103YOuI.js.map → shadow-claw-task-server-B9-MQjl6.js.map} +1 -1
  183. package/dist/lib/{shadow-claw-tasks-6OhALkq1.js → shadow-claw-tasks-Dc4BC-t-.js} +8 -8
  184. package/dist/lib/{shadow-claw-tasks-6OhALkq1.js.map → shadow-claw-tasks-Dc4BC-t-.js.map} +1 -1
  185. package/dist/lib/{shadow-claw-terminal-BGtxA1qD.js → shadow-claw-terminal-BINcTdsk.js} +2 -2
  186. package/dist/lib/{shadow-claw-terminal-BGtxA1qD.js.map → shadow-claw-terminal-BINcTdsk.js.map} +1 -1
  187. package/dist/lib/{shadow-claw-tools-OeIwAnnd.js → shadow-claw-tools-BjFgXNLR.js} +7 -7
  188. package/dist/lib/{shadow-claw-tools-OeIwAnnd.js.map → shadow-claw-tools-BjFgXNLR.js.map} +1 -1
  189. package/dist/lib/{shadow-claw-webvm-gVFZ197u.js → shadow-claw-webvm-Xe3ByMDw.js} +3 -3
  190. package/dist/lib/{shadow-claw-webvm-gVFZ197u.js.map → shadow-claw-webvm-Xe3ByMDw.js.map} +1 -1
  191. package/dist/lib/subsystems/mcp/webmcp.d.ts +64 -0
  192. package/dist/lib/{syncWebMcpRegistration-Bbph0XZl.js → syncWebMcpRegistration-D7alChz0.js} +21 -6
  193. package/dist/lib/syncWebMcpRegistration-D7alChz0.js.map +1 -0
  194. package/dist/lib/{tools-D0OlSzMD.js → tools-Cmhpk3X8.js} +4 -4
  195. package/dist/lib/{tools-D0OlSzMD.js.map → tools-Cmhpk3X8.js.map} +1 -1
  196. package/dist/lib/utils/index.js +1 -1
  197. package/dist/lib/utils/namespacedStorage.js +1 -1
  198. package/dist/lib/utils/utils.js +1 -1
  199. package/dist/lib/{utils-DYdrO2KI.js → utils-CzgKe_XZ.js} +4 -4
  200. package/dist/lib/{utils-DYdrO2KI.js.map → utils-CzgKe_XZ.js.map} +1 -1
  201. package/dist/lib/{webmcp-D2bocsgh.js → webmcp-oEP9YpR2.js} +119 -3
  202. package/dist/lib/{webmcp-D2bocsgh.js.map → webmcp-oEP9YpR2.js.map} +1 -1
  203. package/dist/public/.well-known/mcp/server-card.json +2 -2
  204. package/dist/public/.well-known/mcp/servers.json +1 -1
  205. package/dist/public/.well-known/mcp.json +2 -2
  206. package/dist/public/AGENTS.md +2 -1
  207. package/dist/public/README.md +1 -0
  208. package/dist/public/agent.worker.js +1 -1
  209. package/dist/public/app-routes-C6-H2zPH.js +1 -0
  210. package/dist/public/components/shadow-claw/shadow-claw.css +1 -1
  211. package/dist/public/components/shadow-claw/shadow-claw.html +1 -1
  212. package/dist/public/components/shadow-claw-pages/shadow-claw-pages.css +1 -1
  213. package/dist/public/{config-D4lVqMs8.js → config-Dewnqegf.js} +1 -1
  214. package/dist/public/{configurePeerJs-DDOAVSaH.js → configurePeerJs-CaPU2sN5.js} +1 -1
  215. package/dist/public/{connections-CiukjGiH.js → connections-CwE7jE9l.js} +1 -1
  216. package/dist/public/{custom-element-security-piU2U-Ec.js → custom-element-security-DLgHMf5R.js} +1 -1
  217. package/dist/public/docs/decisions/native-web-components-and-signals.md +1 -1
  218. package/dist/public/docs/example/article/index.html +5 -5
  219. package/dist/public/docs/guides/publishing-to-github-pages.md +49 -6
  220. package/dist/public/docs/publishing/index.html +5 -5
  221. package/dist/public/docs/skill-creator/index.html +5 -5
  222. package/dist/public/docs/subsystems/pages.md +10 -3
  223. package/dist/public/docs/subsystems/webmcp.md +89 -1
  224. package/dist/public/{downloadGroupFile-BiZQYY-O.js → downloadGroupFile-ChWHuap_.js} +1 -1
  225. package/dist/public/e2e/README.md +2 -2
  226. package/dist/public/{e2e-bridge-CybB810Q.js → e2e-bridge-BkaldjV2.js} +1 -1
  227. package/dist/public/{file-viewer-DLUBvOVD.js → file-viewer-Df4qUJCn.js} +1 -1
  228. package/dist/public/{getGroupDir-CLz5c8cg.js → getGroupDir-CeSr4fzS.js} +1 -1
  229. package/dist/public/{git-Ba8AeviI.js → git-Bscc1tK-.js} +2 -2
  230. package/dist/public/{iframe-sanitizer-CKOO7cxp.js → iframe-sanitizer-BVdkQsor.js} +1 -1
  231. package/dist/public/{iframe-storage-proxy-BvRiccH0.js → iframe-storage-proxy-Cg8aFw7o.js} +1 -1
  232. package/dist/public/index.css +1 -1
  233. package/dist/public/index.html +5 -5
  234. package/dist/public/index.js +1 -1
  235. package/dist/public/{initChatSplitResize-osJXM2gu.js → initChatSplitResize-C3Rp1LeZ.js} +1 -1
  236. package/dist/public/{initControlPlane-CNggzsRw.js → initControlPlane-C1pnzG16.js} +1 -1
  237. package/dist/public/llms.txt +1 -1
  238. package/dist/public/main/index.html +5 -5
  239. package/dist/public/main/memory/index.html +5 -5
  240. package/dist/public/{markdown-CZA-Ye2Q.js → markdown-D3A902nT.js} +1 -1
  241. package/dist/public/{mcp-reconnect-BK1bYBdC.js → mcp-reconnect-BJWxQBm_.js} +1 -1
  242. package/dist/public/{memoryStorage-Bew1X8Uy.js → memoryStorage-ykv-Ri-y.js} +1 -1
  243. package/dist/public/{orchestrator-D6tel2Zp.js → orchestrator-BVnC4Vtt.js} +2 -2
  244. package/dist/public/{orchestrator-BLkS_jpm.js → orchestrator-CQcc7OFA.js} +2 -2
  245. package/dist/public/{peerjs-CYs1F7sq.js → peerjs-CYC2cI1Y.js} +1 -1
  246. package/dist/public/{push-client-_HUyJlFJ.js → push-client-BJrnOULM.js} +1 -1
  247. package/dist/public/service-worker/fetch-proxy.js +1 -1
  248. package/dist/public/service-worker.js +1 -1
  249. package/dist/public/{shadow-claw-DmrxnX3Q.js → shadow-claw-WwfOu-tu.js} +33 -3
  250. package/dist/public/{shadow-claw-accounts-BqGrm47Z.js → shadow-claw-accounts-BFZxrPsH.js} +1 -1
  251. package/dist/public/{shadow-claw-channels-Ci2UPaaA.js → shadow-claw-channels-C0w0c1EF.js} +1 -1
  252. package/dist/public/{shadow-claw-chat-BxR6cBYQ.js → shadow-claw-chat-DIJ0A-QN.js} +1 -1
  253. package/dist/public/{shadow-claw-control-plane-C1A-CZ9H.js → shadow-claw-control-plane-DZoxUd-1.js} +2 -2
  254. package/dist/public/{shadow-claw-conversations-DcwG05-H.js → shadow-claw-conversations-DMyG_5zj.js} +1 -1
  255. package/dist/public/{shadow-claw-file-viewer-a_uRA30F.js → shadow-claw-file-viewer-DYgZjZb9.js} +2 -2
  256. package/dist/public/{shadow-claw-files-B774Xz1d.js → shadow-claw-files-DIOUdKJr.js} +1 -1
  257. package/dist/public/{shadow-claw-git-CTIPP0vs.js → shadow-claw-git-if5S0QJr.js} +2 -2
  258. package/dist/public/{shadow-claw-integrations-CjtkA6l0.js → shadow-claw-integrations-BQt4hcWe.js} +1 -1
  259. package/dist/public/{shadow-claw-llm-DfmITHde.js → shadow-claw-llm-9uf1KFA0.js} +2 -2
  260. package/dist/public/{shadow-claw-mcp-remote-BPuV22So.js → shadow-claw-mcp-remote-COpNIzJd.js} +1 -1
  261. package/dist/public/{shadow-claw-networking-DEMMygy0.js → shadow-claw-networking-AOVRUn6B.js} +1 -1
  262. package/dist/public/{shadow-claw-notifications-B9Xhcj1P.js → shadow-claw-notifications-CKB-W1TA.js} +1 -1
  263. package/dist/public/{shadow-claw-page-header-CAXokjQy.js → shadow-claw-page-header-D4LmUigA.js} +1 -1
  264. package/dist/public/{shadow-claw-pages-BRQw8bTm.js → shadow-claw-pages-BpHRY4vH.js} +12 -3
  265. package/dist/public/{shadow-claw-settings-BGrDNyqh.js → shadow-claw-settings-CE-aUo_J.js} +3 -3
  266. package/dist/public/{shadow-claw-storage-DK3pf11w.js → shadow-claw-storage-CFKC-Y3V.js} +1 -1
  267. package/dist/public/{shadow-claw-task-server-CMp5Vjza.js → shadow-claw-task-server-B_ZjqK4B.js} +1 -1
  268. package/dist/public/{shadow-claw-tasks-BO8aXM2B.js → shadow-claw-tasks-CGsEv48K.js} +1 -1
  269. package/dist/public/{shadow-claw-terminal-BSeTuyDa.js → shadow-claw-terminal-DcaS7cPH.js} +1 -1
  270. package/dist/public/{shadow-claw-tools-Bj6DLZ-2.js → shadow-claw-tools-Cnu9hKy0.js} +1 -1
  271. package/dist/public/{shadow-claw-webvm-M7d5RH8H.js → shadow-claw-webvm-BB8SFvJ8.js} +1 -1
  272. package/dist/public/syncWebMcpRegistration-D2Zx4oA1.js +1 -0
  273. package/dist/public/theme-init.js +1 -1
  274. package/dist/public/{tools-nysPKnGT.js → tools-sOLCHTj8.js} +1 -1
  275. package/dist/public/{webmcp-Bo3KTgRb.js → webmcp-YFt6vM1_.js} +1 -1
  276. package/dist/server.js +189 -189
  277. package/package.json +1 -1
  278. package/src/cli/cli.ts +2 -2
  279. package/src/cli/prerender/dsd-shell/prerender-dsd-shell.test.ts +4 -1
  280. package/src/cli/prerender/dsd-shell/prerender-dsd-shell.ts +7 -1
  281. package/src/cli/prerender/utils/insert-before-closing-head.test.ts +12 -0
  282. package/src/cli/prerender/utils/insert-before-closing-head.ts +4 -6
  283. package/src/cli/site-config/apply.test.ts +90 -0
  284. package/src/cli/site-config/apply.ts +181 -13
  285. package/src/components/shadow-claw/shadow-claw.css +26 -0
  286. package/src/components/shadow-claw/shadow-claw.html +4 -0
  287. package/src/components/shadow-claw/utils/applyRoute.ts +3 -0
  288. package/src/components/shadow-claw/utils/bindEventListeners.test.ts +6 -0
  289. package/src/components/shadow-claw/utils/bindEventListeners.ts +30 -1
  290. package/src/components/shadow-claw/utils/getRoute.test.ts +52 -0
  291. package/src/components/shadow-claw/utils/getRoute.ts +18 -0
  292. package/src/components/shadow-claw/utils/navigateToRoute.test.ts +21 -0
  293. package/src/components/shadow-claw/utils/navigateToRoute.ts +10 -0
  294. package/src/components/shadow-claw/utils/sidebarVisibility.ts +12 -4
  295. package/src/components/shadow-claw/utils/syncSlottedSidebarActiveLinks.test.ts +93 -0
  296. package/src/components/shadow-claw/utils/syncSlottedSidebarActiveLinks.ts +100 -0
  297. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +31 -31
  298. package/src/components/shadow-claw-pages/shadow-claw-pages.css +10 -1
  299. package/src/components/shadow-claw-pages/utils/removePreviewIframe.ts +3 -0
  300. package/src/core/effect.test.ts +19 -0
  301. package/src/core/orchestrator/orchestrator-state.ts +2 -1
  302. package/src/core/orchestrator/orchestrator.test.ts +686 -5
  303. package/src/core/orchestrator/orchestrator.ts +3 -10
  304. package/src/core/orchestrator/utils/compactContext.test.ts +423 -121
  305. package/src/core/orchestrator/utils/configurePeerJs.test.ts +27 -0
  306. package/src/core/orchestrator/utils/deliverResponse.test.ts +127 -0
  307. package/src/core/orchestrator/utils/dispatchSubagentInvoke.test.ts +23 -0
  308. package/src/core/orchestrator/utils/enqueue.test.ts +520 -86
  309. package/src/core/orchestrator/utils/handleWorkerMessage.test.ts +664 -144
  310. package/src/core/orchestrator/utils/initTasks.node.test.ts +147 -0
  311. package/src/core/orchestrator/utils/initTasks.test.ts +926 -191
  312. package/src/core/orchestrator/utils/initTasks.ts +5 -4
  313. package/src/core/orchestrator/utils/invokeAgent.test.ts +563 -110
  314. package/src/core/orchestrator/utils/invokeAgent.ts +8 -10
  315. package/src/core/orchestrator/utils/loadChannelConfigurations.test.ts +50 -0
  316. package/src/core/orchestrator/utils/operations/channel.test.ts +377 -170
  317. package/src/core/orchestrator/utils/operations/provider.test.ts +663 -85
  318. package/src/core/orchestrator/utils/operations/room.test.ts +74 -11
  319. package/src/core/orchestrator/utils/operations/task.test.ts +452 -56
  320. package/src/core/orchestrator/utils/operations/task.ts +1 -1
  321. package/src/core/orchestrator/utils/operations/vm.test.ts +66 -7
  322. package/src/core/orchestrator/utils/parseDirectToolCommand.test.ts +6 -0
  323. package/src/core/orchestrator/utils/settings.test.ts +248 -81
  324. package/src/core/orchestrator/utils/setupPushTaskListener.test.ts +58 -0
  325. package/src/core/orchestrator/utils/syncWebMcpRegistration.test.ts +392 -64
  326. package/src/core/orchestrator/utils/syncWebMcpRegistration.ts +32 -3
  327. package/src/server/middleware/static-files.test.ts +36 -0
  328. package/src/server/middleware/static-files.ts +14 -6
  329. package/src/server/routes/mcp.ts +2 -2
  330. package/src/storage/staticRouting.test.ts +36 -0
  331. package/src/storage/staticRouting.ts +31 -3
  332. package/src/stores/file-viewer.test.ts +11 -0
  333. package/src/stores/theme.test.ts +41 -2
  334. package/src/stores/toast.test.ts +25 -0
  335. package/src/subsystems/mcp/webmcp.test.ts +255 -0
  336. package/src/subsystems/mcp/webmcp.ts +253 -0
  337. package/src/worker/tools/bash/native-bash-executor.test.ts +31 -1
  338. package/src/worker/tools/git/utils/extractConflictPaths.test.ts +24 -0
  339. package/src/worker/tools/git/utils/parseConflictRegions.test.ts +46 -0
  340. package/src/worker/tools/git/utils/resolveCorsProxy.test.ts +26 -5
  341. package/src/worker/tools/git/utils/truncateSnippet.test.ts +16 -0
  342. package/src/worker/tools/node-transformers-executor.test.ts +105 -6
  343. package/src/worker/tools/remote-mcp/remote-mcp.test.ts +172 -47
  344. package/src/worker/tools/remote-mcp/utils/formatListToolsOutput.test.ts +19 -0
  345. package/src/worker/tools/remote-mcp/utils/isMcpReauthError.test.ts +45 -0
  346. package/src/worker/tools/remote-mcp/utils/resolveMcpReauth.test.ts +48 -0
  347. package/src/worker/tools/rooms/list-room-members.test.ts +24 -10
  348. package/src/worker/tools/tasks/list-tasks.test.ts +39 -8
  349. package/src/worker/tools/tasks/update-task.test.ts +78 -14
  350. package/src/worker/tools/ui/javascript.test.ts +70 -17
  351. package/src/worker/tools/ui/list-tool-profiles.test.ts +31 -9
  352. package/dist/cli/chunk-00GAzVPl2.js +0 -1
  353. package/dist/cli/chunk-2hnFoNNC.js +0 -1
  354. package/dist/cli/chunk-BKQL4nzF2.js +0 -1
  355. package/dist/cli/chunk-BQ4K3fqj2.js +0 -1
  356. package/dist/cli/chunk-BVCGo6uf2.js +0 -1
  357. package/dist/cli/chunk-BcTH_-FL.js +0 -1
  358. package/dist/cli/chunk-BmD_sPRt.js +0 -1
  359. package/dist/cli/chunk-BsxNqqer.js +0 -1
  360. package/dist/cli/chunk-CCcF5T-c.js +0 -1
  361. package/dist/cli/chunk-CFhvwUeL.js +0 -91
  362. package/dist/cli/chunk-CwWtvULn.js +0 -1
  363. package/dist/cli/chunk-Drf-hXIR2.js +0 -1
  364. package/dist/cli/chunk-Dt5HNYVi.js +0 -1
  365. package/dist/cli/chunk-DwZQi9Ax.js +0 -1
  366. package/dist/cli/chunk-m9ZX7TyF2.js +0 -1
  367. package/dist/lib/app-routes-BAEMLu9g.js.map +0 -1
  368. package/dist/lib/orchestrator-Bq9ft3uG.js.map +0 -1
  369. package/dist/lib/shadow-claw-MumteAJy.js.map +0 -1
  370. package/dist/lib/shadow-claw-pages-Bo8_z2S-.js.map +0 -1
  371. package/dist/lib/syncWebMcpRegistration-Bbph0XZl.js.map +0 -1
  372. package/dist/public/app-routes-BMQ4HFaM.js +0 -1
  373. package/dist/public/syncWebMcpRegistration-4bT0YUyZ.js +0 -1
@@ -1,7 +1,7 @@
1
1
  import { n as __exportAll } from "../rolldown-runtime-DZ8SGSJo.js";
2
2
  import { IMAGE_MIME_TYPES, MIME_TYPES, getImageMimeType, getMimeType, guessMimeTypeFromFilename, inferAttachmentMimeType, isImagePath, isMimeType, mime } from "./mime.js";
3
3
  import { ulid } from "./ulid.js";
4
- import { a as formatTimestamp, c as toArrayBuffer, i as formatDateForFilename, n as computeSha256, o as handleSpecialLinkNavigation, r as escapeHtml, s as sanitizeHtml, t as bufferToHex } from "../utils-DYdrO2KI.js";
4
+ import { a as formatTimestamp, c as toArrayBuffer, i as formatDateForFilename, n as computeSha256, o as handleSpecialLinkNavigation, r as escapeHtml, s as sanitizeHtml, t as bufferToHex } from "../utils-CzgKe_XZ.js";
5
5
  import { isTruthyConfigValue, parseBooleanConfig } from "./parseBooleanConfig.js";
6
6
  import { asNumber, asStringArray, asUidArray, coerce, coerceArray, coerceNumber, coerceStringArray, coerceUidArray } from "./coerce.js";
7
7
  import { base64, base64ToBytes, bytesToBase64 } from "./base64.js";
@@ -1,4 +1,4 @@
1
- import { a as getDeploymentNamespace } from "../app-routes-BAEMLu9g.js";
1
+ import { a as getDeploymentNamespace } from "../app-routes-CKkiX12g.js";
2
2
 
3
3
  //#region src/utils/namespacedStorage.ts
4
4
  /**
@@ -1,3 +1,3 @@
1
- import { a as formatTimestamp, c as toArrayBuffer, i as formatDateForFilename, n as computeSha256, o as handleSpecialLinkNavigation, r as escapeHtml, s as sanitizeHtml, t as bufferToHex } from "../utils-DYdrO2KI.js";
1
+ import { a as formatTimestamp, c as toArrayBuffer, i as formatDateForFilename, n as computeSha256, o as handleSpecialLinkNavigation, r as escapeHtml, s as sanitizeHtml, t as bufferToHex } from "../utils-CzgKe_XZ.js";
2
2
 
3
3
  export { bufferToHex, computeSha256, escapeHtml, formatDateForFilename, formatTimestamp, handleSpecialLinkNavigation, sanitizeHtml, toArrayBuffer };
@@ -1,10 +1,10 @@
1
1
  import { i as __toESM } from "./rolldown-runtime-DZ8SGSJo.js";
2
2
  import { r as getDb } from "./txPromise-DdeRXi7G.js";
3
- import { r as CONFIG_KEYS } from "./config-CPHDmyTx.js";
4
- import { l as parseRouteFromUrl } from "./app-routes-BAEMLu9g.js";
3
+ import { r as CONFIG_KEYS } from "./config-DZkF9LiO.js";
4
+ import { l as parseRouteFromUrl } from "./app-routes-CKkiX12g.js";
5
5
  import { t as getConfig } from "./getConfig-B7JdRqIY.js";
6
6
  import { t as require_browser } from "./browser-FvTfy_Ym.js";
7
- import { i as parseHostPatternMatch, n as getDOMPurify, t as ensureIframeSanitizerHook } from "./iframe-sanitizer-DFdda1jJ.js";
7
+ import { i as parseHostPatternMatch, n as getDOMPurify, t as ensureIframeSanitizerHook } from "./iframe-sanitizer-C7ZGDjEI.js";
8
8
 
9
9
  //#region src/security/trusted-types.ts
10
10
  const APP_TRUSTED_TYPES_POLICY_NAME = "shadowclaw";
@@ -574,4 +574,4 @@ async function computeSha256(input) {
574
574
 
575
575
  //#endregion
576
576
  export { toTrustedScriptUrl as S, loadCustomElementSecurityFromDb as _, formatTimestamp as a, setTrustedSrcdoc as b, toArrayBuffer as c, getIframeCsp as d, getIframeSandboxPolicy as f, isAllowedCustomElement as g, installCustomElementsRegistryGuard as h, formatDateForFilename as i, configureCustomElementSecurity as l, installCustomElementDomGuard as m, computeSha256 as n, handleSpecialLinkNavigation as o, hasApprovedCustomElement as p, escapeHtml as r, sanitizeHtml as s, bufferToHex as t, getApprovedCustomElementScriptDescriptors as u, sanitizeSrcdocHtml as v, toTrustedHtmlPresanitized as x, setSanitizedHtml as y };
577
- //# sourceMappingURL=utils-DYdrO2KI.js.map
577
+ //# sourceMappingURL=utils-CzgKe_XZ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils-DYdrO2KI.js","names":["process"],"sources":["../../src/security/trusted-types.ts","../../src/security/custom-element-security.ts","../../src/utils/utils.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\nimport type { Config } from \"dompurify\";\n\nimport { escapeHtml, sanitizeHtml } from \"../utils/utils.js\";\n\ntype TrustedMarkup = string | { toString: () => string };\n\ntype TrustedTypesPolicyLike = {\n createHTML: (input: string) => TrustedMarkup;\n createScriptURL?: (input: string) => TrustedMarkup;\n};\n\ntype TrustedTypesFactoryLike = {\n createPolicy: (\n name: string,\n rules: {\n createHTML?: (input: string) => string;\n createScriptURL?: (input: string) => string;\n },\n ) => TrustedTypesPolicyLike;\n getPolicy?: (name: string) => TrustedTypesPolicyLike | null;\n};\n\nconst APP_TRUSTED_TYPES_POLICY_NAME = \"shadowclaw\";\n\nlet cachedPolicy: TrustedTypesPolicyLike | null | undefined;\n\nfunction getTrustedTypesFactory(): TrustedTypesFactoryLike | null {\n const factory = globalThis.trustedTypes;\n if (!factory || typeof factory.createPolicy !== \"function\") {\n return null;\n }\n\n return factory as TrustedTypesFactoryLike;\n}\n\nfunction getTrustedTypesPolicy(): TrustedTypesPolicyLike | null {\n if (cachedPolicy !== undefined) {\n return cachedPolicy;\n }\n\n const factory = getTrustedTypesFactory();\n if (!factory) {\n cachedPolicy = null;\n\n return cachedPolicy;\n }\n\n if (typeof factory.getPolicy === \"function\") {\n const existingPolicy = factory.getPolicy(APP_TRUSTED_TYPES_POLICY_NAME);\n if (existingPolicy) {\n cachedPolicy = existingPolicy;\n\n return cachedPolicy;\n }\n }\n\n try {\n cachedPolicy = factory.createPolicy(APP_TRUSTED_TYPES_POLICY_NAME, {\n // Input is already sanitized by sanitizeToTrustedHtml before policy use.\n // Keep this an identity transform so caller-provided sanitize options\n // (for example blob URL allowlists) are not lost.\n createHTML: (input: string) => input,\n createScriptURL: (input: string) => input,\n });\n } catch {\n if (typeof factory.getPolicy === \"function\") {\n cachedPolicy = factory.getPolicy(APP_TRUSTED_TYPES_POLICY_NAME) ?? null;\n } else {\n cachedPolicy = null;\n }\n }\n\n return cachedPolicy;\n}\n\nexport function getTrustedTypesPolicyName(): string {\n return APP_TRUSTED_TYPES_POLICY_NAME;\n}\n\nexport function sanitizeToTrustedHtml(\n dirty: string | Node = \"\",\n options: Config = {},\n): TrustedMarkup {\n const sanitized = sanitizeHtml(dirty, options);\n const policy = getTrustedTypesPolicy();\n\n if (!policy) {\n return sanitized;\n }\n\n return policy.createHTML(sanitized);\n}\n\nexport function escapeToTrustedHtml(text: string): TrustedMarkup {\n return sanitizeToTrustedHtml(escapeHtml(text));\n}\n\nexport function sanitizeSrcdocHtml(html: string, options: Config = {}): string {\n return sanitizeHtml(html, options);\n}\n\nexport function toTrustedHtmlPresanitized(html: string): TrustedMarkup {\n const policy = getTrustedTypesPolicy();\n\n if (!policy) {\n return html;\n }\n\n return policy.createHTML(html);\n}\n\nexport function setSanitizedHtml(\n element: Element,\n dirty: string | Node = \"\",\n options: Config = {},\n): TrustedMarkup {\n const trustedHtml = sanitizeToTrustedHtml(dirty, options);\n\n element.innerHTML = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setEscapedHtml(element: Element, text: string): TrustedMarkup {\n const trustedHtml = escapeToTrustedHtml(text);\n\n element.innerHTML = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setSanitizedSrcdoc(\n iframe: HTMLIFrameElement,\n dirty: string,\n options: Config = {},\n): TrustedMarkup {\n const trustedHtml = sanitizeToTrustedHtml(dirty, options);\n\n iframe.srcdoc = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setTrustedSrcdoc(\n iframe: HTMLIFrameElement,\n html: string,\n): TrustedMarkup {\n const trustedHtml = toTrustedHtmlPresanitized(html);\n\n iframe.srcdoc = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function toTrustedScriptUrl(url: string): TrustedMarkup {\n const policy = getTrustedTypesPolicy();\n\n if (!policy || typeof policy.createScriptURL !== \"function\") {\n return url;\n }\n\n return policy.createScriptURL(url);\n}\n","import { CONFIG_KEYS } from \"../config/config.js\";\nimport { getDb } from \"../db/db.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { getDOMPurify, parseHostPatternMatch } from \"./iframe-sanitizer.js\";\nimport { toTrustedScriptUrl } from \"./trusted-types.js\";\n\nimport type { Config } from \"dompurify\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/** Default allowed custom elements: none by default */\nexport const DEFAULT_ALLOWED_CUSTOM_ELEMENTS: string[] = [];\n\n/** Default allowed custom element host patterns: none by default */\nexport const DEFAULT_ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS: string[] = [];\n\nlet activeAllowedElements: Set<string> = new Set(\n DEFAULT_ALLOWED_CUSTOM_ELEMENTS.map((el) => el.toLowerCase().trim()),\n);\n\nlet activeHostPatterns: string[] = [\n ...DEFAULT_ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS,\n];\nlet activeHostMatchers: Array<(hostname: string) => boolean> = [];\n\nfunction rebuildHostMatchers(patterns: string[]): void {\n activeHostMatchers = patterns\n .map((p) => parseHostPatternMatch(p))\n .filter(Boolean);\n}\n\nrebuildHostMatchers(activeHostPatterns);\n\n/**\n * Normalizes an element tag name or list into an array of lowercase strings.\n */\nfunction normalizeElementList(elements: string[] | string): string[] {\n if (Array.isArray(elements)) {\n return elements\n .map((s) => (typeof s === \"string\" ? s.toLowerCase().trim() : \"\"))\n .filter(Boolean);\n }\n if (typeof elements === \"string\") {\n return elements\n .split(/[\\n,]+/)\n .map((s) => s.toLowerCase().trim())\n .filter(Boolean);\n }\n return [];\n}\n\n/**\n * Normalizes a list of host patterns into an array of trimmed strings.\n */\nfunction normalizePatternList(patterns: string[] | string): string[] {\n if (Array.isArray(patterns)) {\n return patterns\n .map((s) => (typeof s === \"string\" ? s.trim() : \"\"))\n .filter(Boolean);\n }\n if (typeof patterns === \"string\") {\n return patterns\n .split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n }\n return [];\n}\n\n/**\n * Set the allowed custom elements in memory.\n */\nexport function setAllowedCustomElements(elements: string[] | string): void {\n const list = normalizeElementList(elements);\n activeAllowedElements = new Set(list);\n}\n\n/**\n * Get the current list of allowed custom elements.\n */\nexport function getAllowedCustomElements(): string[] {\n return Array.from(activeAllowedElements);\n}\n\n/**\n * Set the allowed custom element host patterns in memory.\n */\nexport function setAllowedCustomElementHostPatterns(\n patterns: string[] | string,\n): void {\n const list = normalizePatternList(patterns);\n activeHostPatterns = list;\n rebuildHostMatchers(list);\n}\n\n/**\n * Get the current list of allowed custom element host patterns.\n */\nexport function getAllowedCustomElementHostPatterns(): string[] {\n return [...activeHostPatterns];\n}\n\n/**\n * Check if a custom element tag name is approved.\n * Built-in ShadowClaw elements (\"shadow-claw\" and \"shadow-claw-*\") are always allowed.\n * Standard non-hyphenated HTML elements pass tag name check.\n */\nexport function isAllowedCustomElement(tagName: string): boolean {\n if (!tagName || typeof tagName !== \"string\") {\n return false;\n }\n\n const lower = tagName.trim().toLowerCase();\n\n // If not a custom element (no hyphen), allow standard HTML tag handling\n if (!lower.includes(\"-\")) {\n return true;\n }\n\n // ShadowClaw core elements are built-in and always permitted\n if (lower === \"shadow-claw\" || lower.startsWith(\"shadow-claw-\")) {\n return true;\n }\n\n // Check against explicit allowlist\n return activeAllowedElements.has(lower);\n}\n\n/**\n * Check if a script URL source is from an approved domain or same-origin.\n */\nexport function isSafeCustomElementSource(urlStr: string): boolean {\n if (!urlStr || typeof urlStr !== \"string\") {\n return false;\n }\n\n const trimmed = urlStr.trim();\n if (!trimmed) {\n return false;\n }\n\n // Reject dangerous pseudo-protocols\n if (/^(?:javascript|data|vbscript):/i.test(trimmed)) {\n return false;\n }\n\n // Allow blob: URLs (used by internal web workers)\n if (/^blob:/i.test(trimmed)) {\n return true;\n }\n\n try {\n const base =\n typeof globalThis !== \"undefined\" &&\n globalThis.location?.origin &&\n globalThis.location.origin !== \"null\"\n ? globalThis.location.origin\n : \"http://localhost\";\n const url = new URL(trimmed, base);\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return false;\n }\n\n // Same-origin is trusted\n if (\n typeof globalThis !== \"undefined\" &&\n globalThis.location?.origin &&\n globalThis.location.origin !== \"null\" &&\n url.origin === globalThis.location.origin\n ) {\n return true;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n return activeHostMatchers.some((matcher) => matcher(hostname));\n } catch {\n return false;\n }\n}\n\nexport const DEFAULT_IFRAME_SANDBOX_POLICY =\n \"allow-modals allow-scripts allow-popups allow-popups-to-escape-sandbox\";\n\nexport const DEFAULT_WORKER_SRC = [\"'self'\", \"blob:\", \"data:\"];\nexport const DEFAULT_CONNECT_SRC = [\"'self'\", \"blob:\", \"data:\"];\nexport const DEFAULT_STYLE_SRC = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"https:\",\n \"http:\",\n];\nexport const DEFAULT_IMG_SRC = [\"'self'\", \"blob:\", \"data:\", \"https:\", \"http:\"];\n\nlet activeIframeSandboxPolicy: string = DEFAULT_IFRAME_SANDBOX_POLICY;\nlet activeWorkerSrc: string[] = [...DEFAULT_WORKER_SRC];\nlet activeConnectSrc: string[] = [...DEFAULT_CONNECT_SRC];\nlet activeScriptSrc: string[] = [];\nlet activeStyleSrc: string[] = [...DEFAULT_STYLE_SRC];\nlet activeImgSrc: string[] = [...DEFAULT_IMG_SRC];\n\n/**\n * Get the active iframe sandbox policy string.\n */\nexport function getIframeSandboxPolicy(): string {\n return activeIframeSandboxPolicy;\n}\n\n/**\n * Set the iframe sandbox policy.\n */\nexport function setIframeSandboxPolicy(policy: string[] | string): void {\n if (Array.isArray(policy)) {\n activeIframeSandboxPolicy = policy\n .map((s) => (typeof s === \"string\" ? s.trim() : \"\"))\n .filter(Boolean)\n .join(\" \");\n } else if (typeof policy === \"string\" && policy.trim()) {\n activeIframeSandboxPolicy = policy.trim();\n } else {\n activeIframeSandboxPolicy = DEFAULT_IFRAME_SANDBOX_POLICY;\n }\n}\n\n/**\n * Generate CSP header string for the sandboxed preview iframe.\n */\nexport function getIframeCsp(nonce: string): string {\n const allowedPatterns = getAllowedCustomElementHostPatterns();\n const approvedScripts = getApprovedCustomElementScripts();\n\n const allowedScriptHosts = new Set<string>();\n for (const pattern of allowedPatterns) {\n if (pattern && /^(\\*\\.)?[a-zA-Z0-9.-]+(?::[0-9]+)?$/.test(pattern)) {\n allowedScriptHosts.add(`https://${pattern}`);\n allowedScriptHosts.add(`http://${pattern}`);\n }\n }\n for (const scriptUrl of approvedScripts) {\n try {\n const parsed = new URL(\n scriptUrl,\n typeof globalThis !== \"undefined\" && globalThis.location?.origin\n ? globalThis.location.origin\n : \"http://localhost\",\n );\n allowedScriptHosts.add(parsed.origin);\n } catch {}\n }\n\n const scriptSources = [\n `'nonce-${nonce}'`,\n ...Array.from(allowedScriptHosts),\n ...activeScriptSrc,\n ];\n\n const connectSources = [\n ...activeConnectSrc,\n ...Array.from(allowedScriptHosts),\n ];\n\n const directives: string[] = [\n `script-src ${Array.from(new Set(scriptSources)).join(\" \")}`,\n `worker-src ${Array.from(new Set(activeWorkerSrc)).join(\" \")}`,\n `connect-src ${Array.from(new Set(connectSources)).join(\" \")}`,\n `style-src ${Array.from(new Set(activeStyleSrc)).join(\" \")}`,\n `img-src ${Array.from(new Set(activeImgSrc)).join(\" \")}`,\n ];\n\n return directives.join(\"; \");\n}\n\n/**\n * Configure custom element security and iframe sandbox policy from a site config object or options.\n */\nexport function configureCustomElementSecurity(config: {\n allowedCustomElements?: string[] | string;\n allowedCustomElementDomains?: string[] | string;\n customElements?:\n | {\n allowedElements?: string[] | string;\n allowedDomains?: string[] | string;\n scripts?: Array<string | { src: string }>;\n }\n | Array<string | { src: string }>;\n security?: {\n iframeSandbox?: string[] | string;\n allowSameOrigin?: boolean;\n allowIframeSameOrigin?: boolean;\n workerSrc?: string[] | string;\n connectSrc?: string[] | string;\n scriptSrc?: string[] | string;\n styleSrc?: string[] | string;\n imgSrc?: string[] | string;\n };\n}): void {\n if (!config || typeof config !== \"object\") {\n return;\n }\n\n // Extract allowed elements\n const elements =\n config.allowedCustomElements ||\n (typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.allowedElements\n : undefined);\n\n if (elements !== undefined) {\n setAllowedCustomElements(elements);\n }\n\n // Extract allowed domains\n const domains =\n config.allowedCustomElementDomains ||\n (typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.allowedDomains\n : undefined);\n\n if (domains !== undefined) {\n setAllowedCustomElementHostPatterns(domains);\n }\n\n // Extract security iframe sandbox settings\n if (config.security?.iframeSandbox !== undefined) {\n setIframeSandboxPolicy(config.security.iframeSandbox);\n } else if (\n config.security?.allowSameOrigin === true ||\n config.security?.allowIframeSameOrigin === true\n ) {\n if (!activeIframeSandboxPolicy.includes(\"allow-same-origin\")) {\n activeIframeSandboxPolicy =\n `${activeIframeSandboxPolicy} allow-same-origin`.trim();\n }\n }\n\n // Extract CSP overrides if configured\n if (config.security?.workerSrc !== undefined) {\n activeWorkerSrc = normalizePatternList(config.security.workerSrc);\n }\n if (config.security?.connectSrc !== undefined) {\n activeConnectSrc = normalizePatternList(config.security.connectSrc);\n }\n if (config.security?.scriptSrc !== undefined) {\n activeScriptSrc = normalizePatternList(config.security.scriptSrc);\n }\n if (config.security?.styleSrc !== undefined) {\n activeStyleSrc = normalizePatternList(config.security.styleSrc);\n }\n if (config.security?.imgSrc !== undefined) {\n activeImgSrc = normalizePatternList(config.security.imgSrc);\n }\n}\n\n/**\n * Initializes custom element security synchronously from embedded site-config script in the DOM if available.\n */\nexport function initCustomElementSecurityFromEmbeddedConfig(): void {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const configScript = document.getElementById(\"shadow-claw-site-config\");\n if (configScript && configScript.textContent) {\n try {\n const config = JSON.parse(configScript.textContent);\n configureCustomElementSecurity(config);\n } catch {\n // ignore JSON parse error\n }\n }\n}\n\nexport interface CustomElementScriptDescriptor {\n src: string;\n hasInit: boolean;\n}\n\n/**\n * Retrieve approved custom element script descriptors from the embedded site config.\n */\nexport function getApprovedCustomElementScriptDescriptors(): CustomElementScriptDescriptor[] {\n if (typeof document === \"undefined\") {\n return [];\n }\n\n const configScript = document.getElementById(\"shadow-claw-site-config\");\n if (!configScript || !configScript.textContent) {\n return [];\n }\n\n try {\n const config = JSON.parse(configScript.textContent);\n const scripts =\n typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.scripts\n : undefined;\n\n if (Array.isArray(scripts)) {\n return scripts\n .map((s: any) => {\n const src = typeof s === \"string\" ? s : s?.src;\n const hasInit =\n typeof s === \"object\" && s !== null ? Boolean(s.hasInit) : false;\n return { src, hasInit };\n })\n .filter(\n (entry): entry is CustomElementScriptDescriptor =>\n typeof entry.src === \"string\" &&\n isSafeCustomElementSource(entry.src),\n );\n }\n } catch {}\n\n return [];\n}\n\n/**\n * Retrieve approved custom element script URLs from the embedded site config.\n */\nexport function getApprovedCustomElementScripts(): string[] {\n return getApprovedCustomElementScriptDescriptors().map((d) => d.src);\n}\n\n/**\n * Check if HTML content contains any approved custom element tags.\n */\nexport function hasApprovedCustomElement(html: string): boolean {\n if (!html || typeof html !== \"string\") {\n return false;\n }\n const allowed = getAllowedCustomElements();\n if (allowed.length > 0) {\n return allowed.some((tag) => {\n const escaped = tag.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`<${escaped}[\\\\s>/]`, \"i\");\n return regex.test(html);\n });\n }\n\n // If no explicit allowed elements are set, check for any non-shadow-claw custom element\n const customTagRegex = /<([a-z][a-z0-9_]*-[a-z0-9_-]*)[\\\\s>/]/gi;\n let match: RegExpExecArray | null;\n while ((match = customTagRegex.exec(html)) !== null) {\n const tagName = match[1].toLowerCase();\n if (!tagName.startsWith(\"shadow-claw\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Load allowed custom elements and host patterns from IndexedDB.\n */\nexport async function loadCustomElementSecurityFromDb(\n db?: ShadowClawDatabase | null,\n): Promise<void> {\n try {\n const database = db ?? (await getDb());\n if (!database) {\n return;\n }\n\n const [elementsVal, hostsVal] = await Promise.all([\n getConfig(database, CONFIG_KEYS.ALLOWED_CUSTOM_ELEMENTS),\n getConfig(database, CONFIG_KEYS.ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS),\n ]);\n\n if (typeof elementsVal === \"string\" && elementsVal.trim()) {\n try {\n const parsed = JSON.parse(elementsVal);\n setAllowedCustomElements(parsed);\n } catch {\n setAllowedCustomElements(elementsVal);\n }\n }\n\n if (typeof hostsVal === \"string\" && hostsVal.trim()) {\n try {\n const parsed = JSON.parse(hostsVal);\n setAllowedCustomElementHostPatterns(parsed);\n } catch {\n setAllowedCustomElementHostPatterns(hostsVal);\n }\n }\n } catch (err) {\n console.warn(\"Failed to load custom element security from db:\", err);\n }\n}\n\nlet originalCustomElementsDefine: typeof customElements.define | null = null;\nlet isRegistryGuardInstalled = false;\n\n/**\n * Monkey-patches customElements.define to prevent registration of unapproved custom elements.\n */\nexport function installCustomElementsRegistryGuard(): void {\n initCustomElementSecurityFromEmbeddedConfig();\n\n if (\n isRegistryGuardInstalled ||\n typeof customElements === \"undefined\" ||\n typeof customElements.define !== \"function\"\n ) {\n return;\n }\n\n originalCustomElementsDefine = customElements.define.bind(customElements);\n\n customElements.define = function (\n name: string,\n constructor: CustomElementConstructor,\n options?: ElementDefinitionOptions,\n ) {\n const lowerName = (name || \"\").toLowerCase().trim();\n if (!isAllowedCustomElement(lowerName)) {\n const errorMsg = `[Security] Registration blocked: <${name}> is not an approved custom element.`;\n console.error(errorMsg);\n throw new Error(errorMsg);\n }\n\n return originalCustomElementsDefine!(name, constructor, options);\n };\n\n isRegistryGuardInstalled = true;\n}\n\n/**\n * Restores the original customElements.define (useful for testing).\n */\nexport function uninstallCustomElementsRegistryGuard(): void {\n if (!isRegistryGuardInstalled || !originalCustomElementsDefine) {\n return;\n }\n\n customElements.define = originalCustomElementsDefine;\n originalCustomElementsDefine = null;\n isRegistryGuardInstalled = false;\n}\n\n/**\n * Installs a MutationObserver on a DOM tree to detect and strip unapproved custom elements.\n */\nexport function installCustomElementDomGuard(\n root: Node = typeof document !== \"undefined\"\n ? document.documentElement\n : (null as any),\n): MutationObserver | null {\n if (typeof MutationObserver === \"undefined\" || !root) {\n return null;\n }\n\n // Sweep existing unapproved custom elements already present in root\n if (typeof (root as any).querySelectorAll === \"function\") {\n try {\n const existing = (root as Element).querySelectorAll(\"*\");\n existing.forEach((el) => {\n const tagName = el.tagName ? el.tagName.toLowerCase() : \"\";\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n console.warn(\n `[Security] Removing existing unapproved custom element: <${tagName}>`,\n );\n el.remove();\n }\n });\n } catch {}\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n const el = node as Element;\n const tagName = el.tagName ? el.tagName.toLowerCase() : \"\";\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n console.warn(\n `[Security] Removing unapproved custom element: <${tagName}>`,\n );\n el.remove();\n }\n }\n });\n }\n });\n\n observer.observe(root, { childList: true, subtree: true });\n\n return observer;\n}\n\n/**\n * Load an approved custom element script module dynamically.\n * Enforces domain validation and Trusted Types.\n */\nexport async function loadApprovedCustomElementScript(\n src: string,\n options: {\n type?: string;\n async?: boolean;\n defer?: boolean;\n } = {},\n): Promise<HTMLScriptElement> {\n if (!isSafeCustomElementSource(src)) {\n throw new Error(\n `[Security] Refused to load script from unapproved host: ${src}`,\n );\n }\n\n if (typeof document === \"undefined\") {\n throw new Error(\"Cannot load script outside browser document environment.\");\n }\n\n const existingScript = document.querySelector(`script[src=\"${src}\"]`);\n if (existingScript instanceof HTMLScriptElement) {\n return existingScript;\n }\n\n const trustedUrl = toTrustedScriptUrl(src) as string;\n\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.type = options.type || \"module\";\n if (options.async) script.async = true;\n if (options.defer) script.defer = true;\n script.src = trustedUrl;\n\n script.onload = () => resolve(script);\n script.onerror = (err) =>\n reject(\n new Error(`Failed to load custom element script: ${src} (${err})`),\n );\n\n document.head.appendChild(script);\n });\n}\n\nlet purifyHookRegistered = false;\n\n/**\n * Ensures DOMPurify has the custom element sanitization hook registered.\n */\nexport function ensureCustomElementSanitizerHook(): void {\n if (purifyHookRegistered) {\n return;\n }\n\n const purify = getDOMPurify();\n\n if (purify && typeof purify.addHook === \"function\") {\n const sanitizeCustomElementNode = (node: Node) => {\n if (node && node.nodeType === 1 /* ELEMENT_NODE */) {\n const el = node as Element;\n const tagName = (el.tagName || \"\").toLowerCase();\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n if (typeof el.remove === \"function\") {\n el.remove();\n }\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n }\n }\n };\n\n purify.addHook(\"uponSanitizeElement\", sanitizeCustomElementNode);\n purify.addHook(\"afterSanitizeElements\", sanitizeCustomElementNode);\n purifyHookRegistered = true;\n }\n}\n\n/**\n * Get DOMPurify configuration for custom element handling.\n */\nexport function getCustomElementPurifyConfig(): Config {\n ensureCustomElementSanitizerHook();\n\n return {\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: (tagName: string) => isAllowedCustomElement(tagName),\n attributeNameCheck: () => true,\n allowCustomizedBuiltInElements: false,\n },\n };\n}\n","/// <reference lib=\"dom\" />\nimport type { Config } from \"dompurify\";\nimport { parseRouteFromUrl } from \"../core/app-routes.js\";\nimport {\n ensureIframeSanitizerHook,\n getDOMPurify,\n} from \"../security/iframe-sanitizer.js\";\nimport {\n ensureCustomElementSanitizerHook,\n isAllowedCustomElement,\n} from \"../security/custom-element-security.js\";\n\nexport type HashInput = File | Blob | ArrayBuffer | ArrayBufferView;\n\n/**\n * Format a date for use in a filename: yyyy-mm-dd_hh-mm-ss\n */\nexport function formatDateForFilename(date = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n\n const yyyy = date.getFullYear();\n const mm = pad(date.getMonth() + 1);\n const dd = pad(date.getDate());\n\n const hh = pad(date.getHours());\n const min = pad(date.getMinutes());\n const ss = pad(date.getSeconds());\n\n return `${yyyy}-${mm}-${dd}_${hh}-${min}-${ss}`;\n}\n\n/**\n * Format a timestamp for display: e.g. \"Sun, Mar 1, 1:25 PM\"\n */\nexport function formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp);\n\n return new Intl.DateTimeFormat(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n }).format(date);\n}\n\n/**\n * Escape HTML special characters in a string.\n */\nexport function escapeHtml(str: string): string {\n const div = document.createElement(\"div\");\n div.textContent = str;\n\n return div.innerHTML;\n}\n\n/**\n * Sanitize HTML content using DOMPurify, allowing custom element tags.\n */\nexport function sanitizeHtml(\n dirty: string | Node = \"\",\n options: Config = {},\n): string {\n ensureIframeSanitizerHook();\n ensureCustomElementSanitizerHook();\n\n return getDOMPurify().sanitize(dirty, {\n ADD_TAGS: [\"iframe\", \"figure\", \"figcaption\"],\n ADD_ATTR: [\n \"allow\",\n \"allowfullscreen\",\n \"frameborder\",\n \"scrolling\",\n \"referrerpolicy\",\n \"loading\",\n ],\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: (tagName: string) => isAllowedCustomElement(tagName),\n attributeNameCheck: () => true,\n allowCustomizedBuiltInElements: false,\n },\n ...options,\n });\n}\n\n/**\n * Interface representing the detailed internal navigation parameters\n */\nexport interface ShadowClawNavigateDetail {\n page: string;\n groupId?: string;\n path?: string;\n anchor?: string;\n}\n\n/**\n * Parses a special or relative link and dispatches the 'shadow-claw-navigate' custom event on document.\n * Returns true if the link was handled/intercepted, false otherwise.\n */\nexport function handleSpecialLinkNavigation(\n href: string,\n basePath: string = \"\",\n currentGroupId?: string,\n): boolean {\n let trimmed = href.trim();\n if (!trimmed) {\n return false;\n }\n\n // Handle malformed query strings where '?' is used instead of '&' (e.g. #Page?param1=val1?param2=val2)\n const firstQuestion = trimmed.indexOf(\"?\");\n if (firstQuestion !== -1) {\n const before = trimmed.slice(0, firstQuestion + 1);\n const after = trimmed.slice(firstQuestion + 1);\n trimmed = before + after.replace(/\\?/g, \"&\");\n }\n\n // 1. Check if it is a case-insensitive special link starting with \"/#\" or \"#\" matching standard pages\n if (trimmed.startsWith(\"/#\") || trimmed.startsWith(\"#\")) {\n const withoutHash = trimmed.startsWith(\"/#\")\n ? trimmed.slice(2)\n : trimmed.slice(1);\n\n // Parse parts: Page?query#anchor\n const pagePart = withoutHash.split(/[?#]/, 1)[0];\n const pageName = pagePart.toLowerCase();\n\n // Valid pages\n const validPages = [\"chat\", \"files\", \"tasks\", \"pages\", \"settings\"];\n if (validPages.includes(pageName)) {\n // Create a dummy absolute URL to parse searchParams easily\n const fakeUrl = trimmed.startsWith(\"/#\")\n ? trimmed.replace(/^\\/#/, \"http://local/\")\n : trimmed.replace(/^#/, \"http://local/\");\n const urlLike = new URL(fakeUrl, \"http://local/\");\n\n const groupId =\n urlLike.searchParams.get(\"groupId\") ||\n urlLike.searchParams.get(\"conversationId\") ||\n currentGroupId;\n const path =\n urlLike.searchParams.get(\"file\") ||\n urlLike.searchParams.get(\"path\") ||\n undefined;\n // Support: ?anchor=some-heading, ?anchor=L10-L20, or #fragment\n const anchorParam = urlLike.searchParams.get(\"anchor\");\n const anchor = anchorParam\n ? anchorParam\n : urlLike.hash\n ? urlLike.hash.slice(1)\n : undefined;\n\n const detail: ShadowClawNavigateDetail = {\n page: pageName,\n groupId: groupId || undefined,\n path: path || undefined,\n anchor: anchor || undefined,\n };\n\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail,\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n }\n\n // 1.5. Check if it is an absolute application route (e.g., /files/room:123/path, /chat/...)\n if (trimmed.startsWith(\"/\")) {\n try {\n const urlLike = new URL(trimmed, window.location.origin);\n const route = parseRouteFromUrl(urlLike, currentGroupId);\n if (route) {\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail: {\n page: route.page,\n groupId: route.groupId,\n path: route.path,\n anchor:\n route.anchor ||\n (urlLike.hash ? urlLike.hash.slice(1) : undefined),\n },\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n } catch {\n // Fallback to relative workspace path resolution below\n }\n }\n\n // 2. Relative or absolute workspace paths, e.g., \"docs/README.md\"\n // If it does not have a scheme (http, https, mailto, etc.) and is not external:\n const hasScheme = /^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed);\n if (\n !hasScheme &&\n !trimmed.startsWith(\"//\") &&\n !trimmed.startsWith(\"javascript:\")\n ) {\n // Resolve absolute vs relative\n let resolvedPath = trimmed.split(/[?#]/, 1)[0].replace(/\\\\/g, \"/\");\n const isAbsolute = resolvedPath.startsWith(\"/\");\n resolvedPath = resolvedPath.replace(/^\\/+/, \"\");\n\n const urlLike = new URL(trimmed, \"http://local/\");\n const anchor = urlLike.hash ? urlLike.hash.slice(1) : undefined;\n\n let finalPath = resolvedPath;\n if (!isAbsolute && basePath) {\n const baseParts = basePath\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .split(\"/\")\n .filter(Boolean);\n baseParts.pop(); // Remove the filename of base path\n\n const pathParts = resolvedPath.split(\"/\");\n const stack = [...baseParts];\n for (const part of pathParts) {\n if (!part || part === \".\") {\n continue;\n }\n\n if (part === \"..\") {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n\n finalPath = stack.join(\"/\");\n }\n\n if (finalPath) {\n const detail: ShadowClawNavigateDetail = {\n page: \"files\",\n groupId: currentGroupId || undefined,\n path: finalPath,\n anchor: anchor || undefined,\n };\n\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail,\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Convert various input types to an ArrayBuffer for hashing.\n */\nexport function toArrayBuffer(input: HashInput): Promise<ArrayBuffer> {\n if (input instanceof Blob) {\n return input.arrayBuffer();\n }\n\n if (input instanceof ArrayBuffer) {\n return Promise.resolve(input.slice(0) as ArrayBuffer);\n }\n\n const { buffer, byteOffset, byteLength } = input;\n\n return Promise.resolve(\n buffer.slice(byteOffset, byteOffset + byteLength) as ArrayBuffer,\n );\n}\n\n/**\n * Convert an ArrayBuffer to a hex string.\n */\nexport function bufferToHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Compute the SHA-256 hash and return it as a hex string.\n */\nexport async function computeSha256(input: HashInput): Promise<string> {\n const data = await toArrayBuffer(input);\n const subtle =\n globalThis.crypto?.subtle ??\n (globalThis as any).window?.crypto?.subtle ??\n (typeof process !== \"undefined\"\n ? (await import(\"node:crypto\")).webcrypto?.subtle\n : undefined);\n\n if (!subtle) {\n throw new Error(\"crypto.subtle is not available in current environment\");\n }\n\n const hashBuffer = await subtle.digest(\"SHA-256\", data);\n\n return bufferToHex(hashBuffer);\n}\n"],"mappings":";;;;;;;;;AAuBA,MAAM,gCAAgC;AAEtC,IAAI;AAEJ,SAAS,yBAAyD;CAChE,MAAM,UAAU,WAAW;CAC3B,IAAI,CAAC,WAAW,OAAO,QAAQ,iBAAiB,YAC9C,OAAO;CAGT,OAAO;AACT;AAEA,SAAS,wBAAuD;CAC9D,IAAI,iBAAiB,QACnB,OAAO;CAGT,MAAM,UAAU,uBAAuB;CACvC,IAAI,CAAC,SAAS;EACZ,eAAe;EAEf,OAAO;CACT;CAEA,IAAI,OAAO,QAAQ,cAAc,YAAY;EAC3C,MAAM,iBAAiB,QAAQ,UAAU,6BAA6B;EACtE,IAAI,gBAAgB;GAClB,eAAe;GAEf,OAAO;EACT;CACF;CAEA,IAAI;EACF,eAAe,QAAQ,aAAa,+BAA+B;GAIjE,aAAa,UAAkB;GAC/B,kBAAkB,UAAkB;EACtC,CAAC;CACH,QAAQ;EACN,IAAI,OAAO,QAAQ,cAAc,YAC/B,eAAe,QAAQ,UAAU,6BAA6B,KAAK;OAEnE,eAAe;CAEnB;CAEA,OAAO;AACT;AAMA,SAAgB,sBACd,QAAuB,IACvB,UAAkB,CAAC,GACJ;CACf,MAAM,YAAY,aAAa,OAAO,OAAO;CAC7C,MAAM,SAAS,sBAAsB;CAErC,IAAI,CAAC,QACH,OAAO;CAGT,OAAO,OAAO,WAAW,SAAS;AACpC;AAMA,SAAgB,mBAAmB,MAAc,UAAkB,CAAC,GAAW;CAC7E,OAAO,aAAa,MAAM,OAAO;AACnC;AAEA,SAAgB,0BAA0B,MAA6B;CACrE,MAAM,SAAS,sBAAsB;CAErC,IAAI,CAAC,QACH,OAAO;CAGT,OAAO,OAAO,WAAW,IAAI;AAC/B;AAEA,SAAgB,iBACd,SACA,QAAuB,IACvB,UAAkB,CAAC,GACJ;CACf,MAAM,cAAc,sBAAsB,OAAO,OAAO;CAExD,QAAQ,YAAY;CAEpB,OAAO;AACT;AAsBA,SAAgB,iBACd,QACA,MACe;CACf,MAAM,cAAc,0BAA0B,IAAI;CAElD,OAAO,SAAS;CAEhB,OAAO;AACT;AAEA,SAAgB,mBAAmB,KAA4B;CAC7D,MAAM,SAAS,sBAAsB;CAErC,IAAI,CAAC,UAAU,OAAO,OAAO,oBAAoB,YAC/C,OAAO;CAGT,OAAO,OAAO,gBAAgB,GAAG;AACnC;;;;;ACzJA,MAAa,kCAA4C,CAAC;;AAG1D,MAAa,+CAAyD,CAAC;AAEvE,IAAI,wBAAqC,IAAI,IAC3C,gCAAgC,KAAK,OAAO,GAAG,YAAY,CAAC,CAAC,KAAK,CAAC,CACrE;AAEA,IAAI,qBAA+B,CACjC,GAAG,4CACL;AACA,IAAI,qBAA2D,CAAC;AAEhE,SAAS,oBAAoB,UAA0B;CACrD,qBAAqB,SAClB,KAAK,MAAM,sBAAsB,CAAC,CAAC,CAAC,CACpC,OAAO,OAAO;AACnB;AAEA,oBAAoB,kBAAkB;;;;AAKtC,SAAS,qBAAqB,UAAuC;CACnE,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SACJ,KAAK,MAAO,OAAO,MAAM,WAAW,EAAE,YAAY,CAAC,CAAC,KAAK,IAAI,EAAG,CAAC,CACjE,OAAO,OAAO;CAEnB,IAAI,OAAO,aAAa,UACtB,OAAO,SACJ,MAAM,QAAQ,CAAC,CACf,KAAK,MAAM,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAClC,OAAO,OAAO;CAEnB,OAAO,CAAC;AACV;;;;AAKA,SAAS,qBAAqB,UAAuC;CACnE,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SACJ,KAAK,MAAO,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI,EAAG,CAAC,CACnD,OAAO,OAAO;CAEnB,IAAI,OAAO,aAAa,UACtB,OAAO,SACJ,MAAM,QAAQ,CAAC,CACf,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,OAAO,OAAO;CAEnB,OAAO,CAAC;AACV;;;;AAKA,SAAgB,yBAAyB,UAAmC;CAC1E,MAAM,OAAO,qBAAqB,QAAQ;CAC1C,wBAAwB,IAAI,IAAI,IAAI;AACtC;;;;AAKA,SAAgB,2BAAqC;CACnD,OAAO,MAAM,KAAK,qBAAqB;AACzC;;;;AAKA,SAAgB,oCACd,UACM;CACN,MAAM,OAAO,qBAAqB,QAAQ;CAC1C,qBAAqB;CACrB,oBAAoB,IAAI;AAC1B;;;;AAKA,SAAgB,sCAAgD;CAC9D,OAAO,CAAC,GAAG,kBAAkB;AAC/B;;;;;;AAOA,SAAgB,uBAAuB,SAA0B;CAC/D,IAAI,CAAC,WAAW,OAAO,YAAY,UACjC,OAAO;CAGT,MAAM,QAAQ,QAAQ,KAAK,CAAC,CAAC,YAAY;CAGzC,IAAI,CAAC,MAAM,SAAS,GAAG,GACrB,OAAO;CAIT,IAAI,UAAU,iBAAiB,MAAM,WAAW,cAAc,GAC5D,OAAO;CAIT,OAAO,sBAAsB,IAAI,KAAK;AACxC;;;;AAKA,SAAgB,0BAA0B,QAAyB;CACjE,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,OAAO;CAGT,MAAM,UAAU,OAAO,KAAK;CAC5B,IAAI,CAAC,SACH,OAAO;CAIT,IAAI,kCAAkC,KAAK,OAAO,GAChD,OAAO;CAIT,IAAI,UAAU,KAAK,OAAO,GACxB,OAAO;CAGT,IAAI;EACF,MAAM,OACJ,OAAO,eAAe,eACtB,WAAW,UAAU,UACrB,WAAW,SAAS,WAAW,SAC3B,WAAW,SAAS,SACpB;EACN,MAAM,MAAM,IAAI,IAAI,SAAS,IAAI;EAEjC,IAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAC/C,OAAO;EAIT,IACE,OAAO,eAAe,eACtB,WAAW,UAAU,UACrB,WAAW,SAAS,WAAW,UAC/B,IAAI,WAAW,WAAW,SAAS,QAEnC,OAAO;EAGT,MAAM,WAAW,IAAI,SAAS,YAAY;EAE1C,OAAO,mBAAmB,MAAM,YAAY,QAAQ,QAAQ,CAAC;CAC/D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAa,gCACX;AAEF,MAAa,qBAAqB;CAAC;CAAU;CAAS;AAAO;AAC7D,MAAa,sBAAsB;CAAC;CAAU;CAAS;AAAO;AAC9D,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;AACF;AACA,MAAa,kBAAkB;CAAC;CAAU;CAAS;CAAS;CAAU;AAAO;AAE7E,IAAI,4BAAoC;AACxC,IAAI,kBAA4B,CAAC,GAAG,kBAAkB;AACtD,IAAI,mBAA6B,CAAC,GAAG,mBAAmB;AACxD,IAAI,kBAA4B,CAAC;AACjC,IAAI,iBAA2B,CAAC,GAAG,iBAAiB;AACpD,IAAI,eAAyB,CAAC,GAAG,eAAe;;;;AAKhD,SAAgB,yBAAiC;CAC/C,OAAO;AACT;;;;AAKA,SAAgB,uBAAuB,QAAiC;CACtE,IAAI,MAAM,QAAQ,MAAM,GACtB,4BAA4B,OACzB,KAAK,MAAO,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI,EAAG,CAAC,CACnD,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;MACN,IAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GACnD,4BAA4B,OAAO,KAAK;MAExC,4BAA4B;AAEhC;;;;AAKA,SAAgB,aAAa,OAAuB;CAClD,MAAM,kBAAkB,oCAAoC;CAC5D,MAAM,kBAAkB,gCAAgC;CAExD,MAAM,qCAAqB,IAAI,IAAY;CAC3C,KAAK,MAAM,WAAW,iBACpB,IAAI,WAAW,sCAAsC,KAAK,OAAO,GAAG;EAClE,mBAAmB,IAAI,WAAW,SAAS;EAC3C,mBAAmB,IAAI,UAAU,SAAS;CAC5C;CAEF,KAAK,MAAM,aAAa,iBACtB,IAAI;EACF,MAAM,SAAS,IAAI,IACjB,WACA,OAAO,eAAe,eAAe,WAAW,UAAU,SACtD,WAAW,SAAS,SACpB,kBACN;EACA,mBAAmB,IAAI,OAAO,MAAM;CACtC,QAAQ,CAAC;CAGX,MAAM,gBAAgB;EACpB,UAAU,MAAM;EAChB,GAAG,MAAM,KAAK,kBAAkB;EAChC,GAAG;CACL;CAEA,MAAM,iBAAiB,CACrB,GAAG,kBACH,GAAG,MAAM,KAAK,kBAAkB,CAClC;CAUA,OAAO;EAPL,cAAc,MAAM,KAAK,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC,KAAK,GAAG;EACzD,cAAc,MAAM,KAAK,IAAI,IAAI,eAAe,CAAC,CAAC,CAAC,KAAK,GAAG;EAC3D,eAAe,MAAM,KAAK,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,KAAK,GAAG;EAC3D,aAAa,MAAM,KAAK,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC,KAAK,GAAG;EACzD,WAAW,MAAM,KAAK,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,GAAG;CAGvC,CAAC,CAAC,KAAK,IAAI;AAC7B;;;;AAKA,SAAgB,+BAA+B,QAoBtC;CACP,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B;CAIF,MAAM,WACJ,OAAO,0BACN,OAAO,OAAO,mBAAmB,YAClC,CAAC,MAAM,QAAQ,OAAO,cAAc,IAChC,OAAO,gBAAgB,kBACvB;CAEN,IAAI,aAAa,QACf,yBAAyB,QAAQ;CAInC,MAAM,UACJ,OAAO,gCACN,OAAO,OAAO,mBAAmB,YAClC,CAAC,MAAM,QAAQ,OAAO,cAAc,IAChC,OAAO,gBAAgB,iBACvB;CAEN,IAAI,YAAY,QACd,oCAAoC,OAAO;CAI7C,IAAI,OAAO,UAAU,kBAAkB,QACrC,uBAAuB,OAAO,SAAS,aAAa;MAC/C,IACL,OAAO,UAAU,oBAAoB,QACrC,OAAO,UAAU,0BAA0B,MAE3C;MAAI,CAAC,0BAA0B,SAAS,mBAAmB,GACzD,4BACE,GAAG,0BAA0B,oBAAoB,KAAK;CAC1D;CAIF,IAAI,OAAO,UAAU,cAAc,QACjC,kBAAkB,qBAAqB,OAAO,SAAS,SAAS;CAElE,IAAI,OAAO,UAAU,eAAe,QAClC,mBAAmB,qBAAqB,OAAO,SAAS,UAAU;CAEpE,IAAI,OAAO,UAAU,cAAc,QACjC,kBAAkB,qBAAqB,OAAO,SAAS,SAAS;CAElE,IAAI,OAAO,UAAU,aAAa,QAChC,iBAAiB,qBAAqB,OAAO,SAAS,QAAQ;CAEhE,IAAI,OAAO,UAAU,WAAW,QAC9B,eAAe,qBAAqB,OAAO,SAAS,MAAM;AAE9D;;;;AAKA,SAAgB,8CAAoD;CAClE,IAAI,OAAO,aAAa,aACtB;CAGF,MAAM,eAAe,SAAS,eAAe,yBAAyB;CACtE,IAAI,gBAAgB,aAAa,aAC/B,IAAI;EAEF,+BADe,KAAK,MAAM,aAAa,WACH,CAAC;CACvC,QAAQ,CAER;AAEJ;;;;AAUA,SAAgB,4CAA6E;CAC3F,IAAI,OAAO,aAAa,aACtB,OAAO,CAAC;CAGV,MAAM,eAAe,SAAS,eAAe,yBAAyB;CACtE,IAAI,CAAC,gBAAgB,CAAC,aAAa,aACjC,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,WAAW;EAClD,MAAM,UACJ,OAAO,OAAO,mBAAmB,YACjC,CAAC,MAAM,QAAQ,OAAO,cAAc,IAChC,OAAO,gBAAgB,UACvB;EAEN,IAAI,MAAM,QAAQ,OAAO,GACvB,OAAO,QACJ,KAAK,MAAW;GAIf,OAAO;IAAE,KAHG,OAAO,MAAM,WAAW,IAAI,GAAG;IAG7B,SADZ,OAAO,MAAM,YAAY,MAAM,OAAO,QAAQ,EAAE,OAAO,IAAI;GACvC;EACxB,CAAC,CAAC,CACD,QACE,UACC,OAAO,MAAM,QAAQ,YACrB,0BAA0B,MAAM,GAAG,CACvC;CAEN,QAAQ,CAAC;CAET,OAAO,CAAC;AACV;;;;AAKA,SAAgB,kCAA4C;CAC1D,OAAO,0CAA0C,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG;AACrE;;;;AAKA,SAAgB,yBAAyB,MAAuB;CAC9D,IAAI,CAAC,QAAQ,OAAO,SAAS,UAC3B,OAAO;CAET,MAAM,UAAU,yBAAyB;CACzC,IAAI,QAAQ,SAAS,GACnB,OAAO,QAAQ,MAAM,QAAQ;EAC3B,MAAM,UAAU,IAAI,QAAQ,uBAAuB,MAAM;EAEzD,OAAO,IADW,OAAO,IAAI,QAAQ,UAAU,GACpC,CAAC,CAAC,KAAK,IAAI;CACxB,CAAC;CAIH,MAAM,iBAAiB;CACvB,IAAI;CACJ,QAAQ,QAAQ,eAAe,KAAK,IAAI,OAAO,MAE7C,IAAI,CADY,MAAM,EAAE,CAAC,YACd,CAAC,CAAC,WAAW,aAAa,GACnC,OAAO;CAGX,OAAO;AACT;;;;AAKA,eAAsB,gCACpB,IACe;CACf,IAAI;EACF,MAAM,WAAW,MAAO,MAAM,MAAM;EACpC,IAAI,CAAC,UACH;EAGF,MAAM,CAAC,aAAa,YAAY,MAAM,QAAQ,IAAI,CAChD,UAAU,UAAU,YAAY,uBAAuB,GACvD,UAAU,UAAU,YAAY,oCAAoC,CACtE,CAAC;EAED,IAAI,OAAO,gBAAgB,YAAY,YAAY,KAAK,GACtD,IAAI;GAEF,yBADe,KAAK,MAAM,WACI,CAAC;EACjC,QAAQ;GACN,yBAAyB,WAAW;EACtC;EAGF,IAAI,OAAO,aAAa,YAAY,SAAS,KAAK,GAChD,IAAI;GAEF,oCADe,KAAK,MAAM,QACe,CAAC;EAC5C,QAAQ;GACN,oCAAoC,QAAQ;EAC9C;CAEJ,SAAS,KAAK;EACZ,QAAQ,KAAK,mDAAmD,GAAG;CACrE;AACF;AAEA,IAAI,+BAAoE;AACxE,IAAI,2BAA2B;;;;AAK/B,SAAgB,qCAA2C;CACzD,4CAA4C;CAE5C,IACE,4BACA,OAAO,mBAAmB,eAC1B,OAAO,eAAe,WAAW,YAEjC;CAGF,+BAA+B,eAAe,OAAO,KAAK,cAAc;CAExE,eAAe,SAAS,SACtB,MACA,aACA,SACA;EAEA,IAAI,CAAC,wBADc,QAAQ,GAAE,CAAE,YAAY,CAAC,CAAC,KACT,CAAC,GAAG;GACtC,MAAM,WAAW,qCAAqC,KAAK;GAC3D,QAAQ,MAAM,QAAQ;GACtB,MAAM,IAAI,MAAM,QAAQ;EAC1B;EAEA,OAAO,6BAA8B,MAAM,aAAa,OAAO;CACjE;CAEA,2BAA2B;AAC7B;;;;AAkBA,SAAgB,6BACd,OAAa,OAAO,aAAa,cAC7B,SAAS,kBACR,MACoB;CACzB,IAAI,OAAO,qBAAqB,eAAe,CAAC,MAC9C,OAAO;CAIT,IAAI,OAAQ,KAAa,qBAAqB,YAC5C,IAAI;EAEF,AADkB,KAAiB,iBAAiB,GAC7C,CAAC,CAAC,SAAS,OAAO;GACvB,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,YAAY,IAAI;GACxD,IAAI,QAAQ,SAAS,GAAG,KAAK,CAAC,uBAAuB,OAAO,GAAG;IAC7D,QAAQ,KACN,4DAA4D,QAAQ,EACtE;IACA,GAAG,OAAO;GACZ;EACF,CAAC;CACH,QAAQ,CAAC;CAGX,MAAM,WAAW,IAAI,kBAAkB,cAAc;EACnD,KAAK,MAAM,YAAY,WACrB,SAAS,WAAW,SAAS,SAAS;GACpC,IAAI,KAAK,aAAa,GAA2B;IAC/C,MAAM,KAAK;IACX,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,YAAY,IAAI;IACxD,IAAI,QAAQ,SAAS,GAAG,KAAK,CAAC,uBAAuB,OAAO,GAAG;KAC7D,QAAQ,KACN,mDAAmD,QAAQ,EAC7D;KACA,GAAG,OAAO;IACZ;GACF;EACF,CAAC;CAEL,CAAC;CAED,SAAS,QAAQ,MAAM;EAAE,WAAW;EAAM,SAAS;CAAK,CAAC;CAEzD,OAAO;AACT;AAgDA,IAAI,uBAAuB;;;;AAK3B,SAAgB,mCAAyC;CACvD,IAAI,sBACF;CAGF,MAAM,SAAS,aAAa;CAE5B,IAAI,UAAU,OAAO,OAAO,YAAY,YAAY;EAClD,MAAM,6BAA6B,SAAe;GAChD,IAAI,QAAQ,KAAK,aAAa,GAAsB;IAClD,MAAM,KAAK;IACX,MAAM,WAAW,GAAG,WAAW,GAAE,CAAE,YAAY;IAC/C,IAAI,QAAQ,SAAS,GAAG,KAAK,CAAC,uBAAuB,OAAO,GAAG;KAC7D,IAAI,OAAO,GAAG,WAAW,YACvB,GAAG,OAAO;KAEZ,IAAI,GAAG,YACL,GAAG,WAAW,YAAY,EAAE;IAEhC;GACF;EACF;EAEA,OAAO,QAAQ,uBAAuB,yBAAyB;EAC/D,OAAO,QAAQ,yBAAyB,yBAAyB;EACjE,uBAAuB;CACzB;AACF;;;;;;;;AC9oBA,SAAgB,sBAAsB,uBAAO,IAAI,KAAK,GAAW;CAC/D,MAAM,OAAO,MAAc,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CAUpD,OAAO,GARM,KAAK,YAQL,EAAE,GAPJ,IAAI,KAAK,SAAS,IAAI,CAOd,EAAE,GANV,IAAI,KAAK,QAAQ,CAMH,EAAE,GAJhB,IAAI,KAAK,SAAS,CAIE,EAAE,GAHrB,IAAI,KAAK,WAAW,CAGM,EAAE,GAF7B,IAAI,KAAK,WAAW,CAEa;AAC9C;;;;AAKA,SAAgB,gBAAgB,WAA2B;CACzD,MAAM,OAAO,IAAI,KAAK,SAAS;CAE/B,OAAO,IAAI,KAAK,eAAe,SAAS;EACtC,SAAS;EACT,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;CACV,CAAC,CAAC,CAAC,OAAO,IAAI;AAChB;;;;AAKA,SAAgB,WAAW,KAAqB;CAC9C,MAAM,MAAM,SAAS,cAAc,KAAK;CACxC,IAAI,cAAc;CAElB,OAAO,IAAI;AACb;;;;AAKA,SAAgB,aACd,QAAuB,IACvB,UAAkB,CAAC,GACX;CACR,0BAA0B;CAC1B,iCAAiC;CAEjC,OAAO,aAAa,CAAC,CAAC,SAAS,OAAO;EACpC,UAAU;GAAC;GAAU;GAAU;EAAY;EAC3C,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;EACF;EACA,yBAAyB;GACvB,eAAe,YAAoB,uBAAuB,OAAO;GACjE,0BAA0B;GAC1B,gCAAgC;EAClC;EACA,GAAG;CACL,CAAC;AACH;;;;;AAgBA,SAAgB,4BACd,MACA,WAAmB,IACnB,gBACS;CACT,IAAI,UAAU,KAAK,KAAK;CACxB,IAAI,CAAC,SACH,OAAO;CAIT,MAAM,gBAAgB,QAAQ,QAAQ,GAAG;CACzC,IAAI,kBAAkB,IAGpB,UAFe,QAAQ,MAAM,GAAG,gBAAgB,CAEjC,IADD,QAAQ,MAAM,gBAAgB,CACrB,CAAC,CAAC,QAAQ,OAAO,GAAG;CAI7C,IAAI,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,GAAG,GAAG;EAOvD,MAAM,YANc,QAAQ,WAAW,IAAI,IACvC,QAAQ,MAAM,CAAC,IACf,QAAQ,MAAM,CAAC,EAGS,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC,YAAY;EAItC,IAAI;GADgB;GAAQ;GAAS;GAAS;GAAS;EAC1C,CAAC,CAAC,SAAS,QAAQ,GAAG;GAEjC,MAAM,UAAU,QAAQ,WAAW,IAAI,IACnC,QAAQ,QAAQ,QAAQ,eAAe,IACvC,QAAQ,QAAQ,MAAM,eAAe;GACzC,MAAM,UAAU,IAAI,IAAI,SAAS,eAAe;GAEhD,MAAM,UACJ,QAAQ,aAAa,IAAI,SAAS,KAClC,QAAQ,aAAa,IAAI,gBAAgB,KACzC;GACF,MAAM,OACJ,QAAQ,aAAa,IAAI,MAAM,KAC/B,QAAQ,aAAa,IAAI,MAAM,KAC/B;GAEF,MAAM,cAAc,QAAQ,aAAa,IAAI,QAAQ;GACrD,MAAM,SAAS,cACX,cACA,QAAQ,OACN,QAAQ,KAAK,MAAM,CAAC,IACpB;GAEN,MAAM,SAAmC;IACvC,MAAM;IACN,SAAS,WAAW;IACpB,MAAM,QAAQ;IACd,QAAQ,UAAU;GACpB;GAEA,SAAS,cACP,IAAI,YAAY,wBAAwB;IACtC;IACA,SAAS;IACT,UAAU;GACZ,CAAC,CACH;GAEA,OAAO;EACT;CACF;CAGA,IAAI,QAAQ,WAAW,GAAG,GACxB,IAAI;EACF,MAAM,UAAU,IAAI,IAAI,SAAS,OAAO,SAAS,MAAM;EACvD,MAAM,QAAQ,kBAAkB,SAAS,cAAc;EACvD,IAAI,OAAO;GACT,SAAS,cACP,IAAI,YAAY,wBAAwB;IACtC,QAAQ;KACN,MAAM,MAAM;KACZ,SAAS,MAAM;KACf,MAAM,MAAM;KACZ,QACE,MAAM,WACL,QAAQ,OAAO,QAAQ,KAAK,MAAM,CAAC,IAAI;IAC5C;IACA,SAAS;IACT,UAAU;GACZ,CAAC,CACH;GAEA,OAAO;EACT;CACF,QAAQ,CAER;CAMF,IACE,CAFgB,2BAA2B,KAAK,OAEvC,KACT,CAAC,QAAQ,WAAW,IAAI,KACxB,CAAC,QAAQ,WAAW,aAAa,GACjC;EAEA,IAAI,eAAe,QAAQ,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,OAAO,GAAG;EACjE,MAAM,aAAa,aAAa,WAAW,GAAG;EAC9C,eAAe,aAAa,QAAQ,QAAQ,EAAE;EAE9C,MAAM,UAAU,IAAI,IAAI,SAAS,eAAe;EAChD,MAAM,SAAS,QAAQ,OAAO,QAAQ,KAAK,MAAM,CAAC,IAAI;EAEtD,IAAI,YAAY;EAChB,IAAI,CAAC,cAAc,UAAU;GAC3B,MAAM,YAAY,SACf,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,QAAQ,EAAE,CAAC,CACnB,MAAM,GAAG,CAAC,CACV,OAAO,OAAO;GACjB,UAAU,IAAI;GAEd,MAAM,YAAY,aAAa,MAAM,GAAG;GACxC,MAAM,QAAQ,CAAC,GAAG,SAAS;GAC3B,KAAK,MAAM,QAAQ,WAAW;IAC5B,IAAI,CAAC,QAAQ,SAAS,KACpB;IAGF,IAAI,SAAS,MACX,MAAM,IAAI;SAEV,MAAM,KAAK,IAAI;GAEnB;GAEA,YAAY,MAAM,KAAK,GAAG;EAC5B;EAEA,IAAI,WAAW;GACb,MAAM,SAAmC;IACvC,MAAM;IACN,SAAS,kBAAkB;IAC3B,MAAM;IACN,QAAQ,UAAU;GACpB;GAEA,SAAS,cACP,IAAI,YAAY,wBAAwB;IACtC;IACA,SAAS;IACT,UAAU;GACZ,CAAC,CACH;GAEA,OAAO;EACT;CACF;CAEA,OAAO;AACT;;;;AAKA,SAAgB,cAAc,OAAwC;CACpE,IAAI,iBAAiB,MACnB,OAAO,MAAM,YAAY;CAG3B,IAAI,iBAAiB,aACnB,OAAO,QAAQ,QAAQ,MAAM,MAAM,CAAC,CAAgB;CAGtD,MAAM,EAAE,QAAQ,YAAY,eAAe;CAE3C,OAAO,QAAQ,QACb,OAAO,MAAM,YAAY,aAAa,UAAU,CAClD;AACF;;;;AAKA,SAAgB,YAAY,QAA6B;CACvD,OAAO,MAAM,KAAK,IAAI,WAAW,MAAM,CAAC,CAAC,CACtC,KAAK,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAC3C,KAAK,EAAE;AACZ;;;;AAKA,eAAsB,cAAc,OAAmC;CACrE,MAAM,OAAO,MAAM,cAAc,KAAK;CACtC,MAAM,SACJ,WAAW,QAAQ,UAClB,WAAmB,QAAQ,QAAQ,WACnC,OAAOA,2BAAY,eACf,MAAM,OAAO,kCAAc,iDAAE,WAAW,SACzC;CAEN,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,uDAAuD;CAKzE,OAAO,YAAY,MAFM,OAAO,OAAO,WAAW,IAAI,CAEzB;AAC/B"}
1
+ {"version":3,"file":"utils-CzgKe_XZ.js","names":["process"],"sources":["../../src/security/trusted-types.ts","../../src/security/custom-element-security.ts","../../src/utils/utils.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\nimport type { Config } from \"dompurify\";\n\nimport { escapeHtml, sanitizeHtml } from \"../utils/utils.js\";\n\ntype TrustedMarkup = string | { toString: () => string };\n\ntype TrustedTypesPolicyLike = {\n createHTML: (input: string) => TrustedMarkup;\n createScriptURL?: (input: string) => TrustedMarkup;\n};\n\ntype TrustedTypesFactoryLike = {\n createPolicy: (\n name: string,\n rules: {\n createHTML?: (input: string) => string;\n createScriptURL?: (input: string) => string;\n },\n ) => TrustedTypesPolicyLike;\n getPolicy?: (name: string) => TrustedTypesPolicyLike | null;\n};\n\nconst APP_TRUSTED_TYPES_POLICY_NAME = \"shadowclaw\";\n\nlet cachedPolicy: TrustedTypesPolicyLike | null | undefined;\n\nfunction getTrustedTypesFactory(): TrustedTypesFactoryLike | null {\n const factory = globalThis.trustedTypes;\n if (!factory || typeof factory.createPolicy !== \"function\") {\n return null;\n }\n\n return factory as TrustedTypesFactoryLike;\n}\n\nfunction getTrustedTypesPolicy(): TrustedTypesPolicyLike | null {\n if (cachedPolicy !== undefined) {\n return cachedPolicy;\n }\n\n const factory = getTrustedTypesFactory();\n if (!factory) {\n cachedPolicy = null;\n\n return cachedPolicy;\n }\n\n if (typeof factory.getPolicy === \"function\") {\n const existingPolicy = factory.getPolicy(APP_TRUSTED_TYPES_POLICY_NAME);\n if (existingPolicy) {\n cachedPolicy = existingPolicy;\n\n return cachedPolicy;\n }\n }\n\n try {\n cachedPolicy = factory.createPolicy(APP_TRUSTED_TYPES_POLICY_NAME, {\n // Input is already sanitized by sanitizeToTrustedHtml before policy use.\n // Keep this an identity transform so caller-provided sanitize options\n // (for example blob URL allowlists) are not lost.\n createHTML: (input: string) => input,\n createScriptURL: (input: string) => input,\n });\n } catch {\n if (typeof factory.getPolicy === \"function\") {\n cachedPolicy = factory.getPolicy(APP_TRUSTED_TYPES_POLICY_NAME) ?? null;\n } else {\n cachedPolicy = null;\n }\n }\n\n return cachedPolicy;\n}\n\nexport function getTrustedTypesPolicyName(): string {\n return APP_TRUSTED_TYPES_POLICY_NAME;\n}\n\nexport function sanitizeToTrustedHtml(\n dirty: string | Node = \"\",\n options: Config = {},\n): TrustedMarkup {\n const sanitized = sanitizeHtml(dirty, options);\n const policy = getTrustedTypesPolicy();\n\n if (!policy) {\n return sanitized;\n }\n\n return policy.createHTML(sanitized);\n}\n\nexport function escapeToTrustedHtml(text: string): TrustedMarkup {\n return sanitizeToTrustedHtml(escapeHtml(text));\n}\n\nexport function sanitizeSrcdocHtml(html: string, options: Config = {}): string {\n return sanitizeHtml(html, options);\n}\n\nexport function toTrustedHtmlPresanitized(html: string): TrustedMarkup {\n const policy = getTrustedTypesPolicy();\n\n if (!policy) {\n return html;\n }\n\n return policy.createHTML(html);\n}\n\nexport function setSanitizedHtml(\n element: Element,\n dirty: string | Node = \"\",\n options: Config = {},\n): TrustedMarkup {\n const trustedHtml = sanitizeToTrustedHtml(dirty, options);\n\n element.innerHTML = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setEscapedHtml(element: Element, text: string): TrustedMarkup {\n const trustedHtml = escapeToTrustedHtml(text);\n\n element.innerHTML = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setSanitizedSrcdoc(\n iframe: HTMLIFrameElement,\n dirty: string,\n options: Config = {},\n): TrustedMarkup {\n const trustedHtml = sanitizeToTrustedHtml(dirty, options);\n\n iframe.srcdoc = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function setTrustedSrcdoc(\n iframe: HTMLIFrameElement,\n html: string,\n): TrustedMarkup {\n const trustedHtml = toTrustedHtmlPresanitized(html);\n\n iframe.srcdoc = trustedHtml as string;\n\n return trustedHtml;\n}\n\nexport function toTrustedScriptUrl(url: string): TrustedMarkup {\n const policy = getTrustedTypesPolicy();\n\n if (!policy || typeof policy.createScriptURL !== \"function\") {\n return url;\n }\n\n return policy.createScriptURL(url);\n}\n","import { CONFIG_KEYS } from \"../config/config.js\";\nimport { getDb } from \"../db/db.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { getDOMPurify, parseHostPatternMatch } from \"./iframe-sanitizer.js\";\nimport { toTrustedScriptUrl } from \"./trusted-types.js\";\n\nimport type { Config } from \"dompurify\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/** Default allowed custom elements: none by default */\nexport const DEFAULT_ALLOWED_CUSTOM_ELEMENTS: string[] = [];\n\n/** Default allowed custom element host patterns: none by default */\nexport const DEFAULT_ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS: string[] = [];\n\nlet activeAllowedElements: Set<string> = new Set(\n DEFAULT_ALLOWED_CUSTOM_ELEMENTS.map((el) => el.toLowerCase().trim()),\n);\n\nlet activeHostPatterns: string[] = [\n ...DEFAULT_ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS,\n];\nlet activeHostMatchers: Array<(hostname: string) => boolean> = [];\n\nfunction rebuildHostMatchers(patterns: string[]): void {\n activeHostMatchers = patterns\n .map((p) => parseHostPatternMatch(p))\n .filter(Boolean);\n}\n\nrebuildHostMatchers(activeHostPatterns);\n\n/**\n * Normalizes an element tag name or list into an array of lowercase strings.\n */\nfunction normalizeElementList(elements: string[] | string): string[] {\n if (Array.isArray(elements)) {\n return elements\n .map((s) => (typeof s === \"string\" ? s.toLowerCase().trim() : \"\"))\n .filter(Boolean);\n }\n if (typeof elements === \"string\") {\n return elements\n .split(/[\\n,]+/)\n .map((s) => s.toLowerCase().trim())\n .filter(Boolean);\n }\n return [];\n}\n\n/**\n * Normalizes a list of host patterns into an array of trimmed strings.\n */\nfunction normalizePatternList(patterns: string[] | string): string[] {\n if (Array.isArray(patterns)) {\n return patterns\n .map((s) => (typeof s === \"string\" ? s.trim() : \"\"))\n .filter(Boolean);\n }\n if (typeof patterns === \"string\") {\n return patterns\n .split(/[\\n,]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n }\n return [];\n}\n\n/**\n * Set the allowed custom elements in memory.\n */\nexport function setAllowedCustomElements(elements: string[] | string): void {\n const list = normalizeElementList(elements);\n activeAllowedElements = new Set(list);\n}\n\n/**\n * Get the current list of allowed custom elements.\n */\nexport function getAllowedCustomElements(): string[] {\n return Array.from(activeAllowedElements);\n}\n\n/**\n * Set the allowed custom element host patterns in memory.\n */\nexport function setAllowedCustomElementHostPatterns(\n patterns: string[] | string,\n): void {\n const list = normalizePatternList(patterns);\n activeHostPatterns = list;\n rebuildHostMatchers(list);\n}\n\n/**\n * Get the current list of allowed custom element host patterns.\n */\nexport function getAllowedCustomElementHostPatterns(): string[] {\n return [...activeHostPatterns];\n}\n\n/**\n * Check if a custom element tag name is approved.\n * Built-in ShadowClaw elements (\"shadow-claw\" and \"shadow-claw-*\") are always allowed.\n * Standard non-hyphenated HTML elements pass tag name check.\n */\nexport function isAllowedCustomElement(tagName: string): boolean {\n if (!tagName || typeof tagName !== \"string\") {\n return false;\n }\n\n const lower = tagName.trim().toLowerCase();\n\n // If not a custom element (no hyphen), allow standard HTML tag handling\n if (!lower.includes(\"-\")) {\n return true;\n }\n\n // ShadowClaw core elements are built-in and always permitted\n if (lower === \"shadow-claw\" || lower.startsWith(\"shadow-claw-\")) {\n return true;\n }\n\n // Check against explicit allowlist\n return activeAllowedElements.has(lower);\n}\n\n/**\n * Check if a script URL source is from an approved domain or same-origin.\n */\nexport function isSafeCustomElementSource(urlStr: string): boolean {\n if (!urlStr || typeof urlStr !== \"string\") {\n return false;\n }\n\n const trimmed = urlStr.trim();\n if (!trimmed) {\n return false;\n }\n\n // Reject dangerous pseudo-protocols\n if (/^(?:javascript|data|vbscript):/i.test(trimmed)) {\n return false;\n }\n\n // Allow blob: URLs (used by internal web workers)\n if (/^blob:/i.test(trimmed)) {\n return true;\n }\n\n try {\n const base =\n typeof globalThis !== \"undefined\" &&\n globalThis.location?.origin &&\n globalThis.location.origin !== \"null\"\n ? globalThis.location.origin\n : \"http://localhost\";\n const url = new URL(trimmed, base);\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return false;\n }\n\n // Same-origin is trusted\n if (\n typeof globalThis !== \"undefined\" &&\n globalThis.location?.origin &&\n globalThis.location.origin !== \"null\" &&\n url.origin === globalThis.location.origin\n ) {\n return true;\n }\n\n const hostname = url.hostname.toLowerCase();\n\n return activeHostMatchers.some((matcher) => matcher(hostname));\n } catch {\n return false;\n }\n}\n\nexport const DEFAULT_IFRAME_SANDBOX_POLICY =\n \"allow-modals allow-scripts allow-popups allow-popups-to-escape-sandbox\";\n\nexport const DEFAULT_WORKER_SRC = [\"'self'\", \"blob:\", \"data:\"];\nexport const DEFAULT_CONNECT_SRC = [\"'self'\", \"blob:\", \"data:\"];\nexport const DEFAULT_STYLE_SRC = [\n \"'self'\",\n \"'unsafe-inline'\",\n \"https:\",\n \"http:\",\n];\nexport const DEFAULT_IMG_SRC = [\"'self'\", \"blob:\", \"data:\", \"https:\", \"http:\"];\n\nlet activeIframeSandboxPolicy: string = DEFAULT_IFRAME_SANDBOX_POLICY;\nlet activeWorkerSrc: string[] = [...DEFAULT_WORKER_SRC];\nlet activeConnectSrc: string[] = [...DEFAULT_CONNECT_SRC];\nlet activeScriptSrc: string[] = [];\nlet activeStyleSrc: string[] = [...DEFAULT_STYLE_SRC];\nlet activeImgSrc: string[] = [...DEFAULT_IMG_SRC];\n\n/**\n * Get the active iframe sandbox policy string.\n */\nexport function getIframeSandboxPolicy(): string {\n return activeIframeSandboxPolicy;\n}\n\n/**\n * Set the iframe sandbox policy.\n */\nexport function setIframeSandboxPolicy(policy: string[] | string): void {\n if (Array.isArray(policy)) {\n activeIframeSandboxPolicy = policy\n .map((s) => (typeof s === \"string\" ? s.trim() : \"\"))\n .filter(Boolean)\n .join(\" \");\n } else if (typeof policy === \"string\" && policy.trim()) {\n activeIframeSandboxPolicy = policy.trim();\n } else {\n activeIframeSandboxPolicy = DEFAULT_IFRAME_SANDBOX_POLICY;\n }\n}\n\n/**\n * Generate CSP header string for the sandboxed preview iframe.\n */\nexport function getIframeCsp(nonce: string): string {\n const allowedPatterns = getAllowedCustomElementHostPatterns();\n const approvedScripts = getApprovedCustomElementScripts();\n\n const allowedScriptHosts = new Set<string>();\n for (const pattern of allowedPatterns) {\n if (pattern && /^(\\*\\.)?[a-zA-Z0-9.-]+(?::[0-9]+)?$/.test(pattern)) {\n allowedScriptHosts.add(`https://${pattern}`);\n allowedScriptHosts.add(`http://${pattern}`);\n }\n }\n for (const scriptUrl of approvedScripts) {\n try {\n const parsed = new URL(\n scriptUrl,\n typeof globalThis !== \"undefined\" && globalThis.location?.origin\n ? globalThis.location.origin\n : \"http://localhost\",\n );\n allowedScriptHosts.add(parsed.origin);\n } catch {}\n }\n\n const scriptSources = [\n `'nonce-${nonce}'`,\n ...Array.from(allowedScriptHosts),\n ...activeScriptSrc,\n ];\n\n const connectSources = [\n ...activeConnectSrc,\n ...Array.from(allowedScriptHosts),\n ];\n\n const directives: string[] = [\n `script-src ${Array.from(new Set(scriptSources)).join(\" \")}`,\n `worker-src ${Array.from(new Set(activeWorkerSrc)).join(\" \")}`,\n `connect-src ${Array.from(new Set(connectSources)).join(\" \")}`,\n `style-src ${Array.from(new Set(activeStyleSrc)).join(\" \")}`,\n `img-src ${Array.from(new Set(activeImgSrc)).join(\" \")}`,\n ];\n\n return directives.join(\"; \");\n}\n\n/**\n * Configure custom element security and iframe sandbox policy from a site config object or options.\n */\nexport function configureCustomElementSecurity(config: {\n allowedCustomElements?: string[] | string;\n allowedCustomElementDomains?: string[] | string;\n customElements?:\n | {\n allowedElements?: string[] | string;\n allowedDomains?: string[] | string;\n scripts?: Array<string | { src: string }>;\n }\n | Array<string | { src: string }>;\n security?: {\n iframeSandbox?: string[] | string;\n allowSameOrigin?: boolean;\n allowIframeSameOrigin?: boolean;\n workerSrc?: string[] | string;\n connectSrc?: string[] | string;\n scriptSrc?: string[] | string;\n styleSrc?: string[] | string;\n imgSrc?: string[] | string;\n };\n}): void {\n if (!config || typeof config !== \"object\") {\n return;\n }\n\n // Extract allowed elements\n const elements =\n config.allowedCustomElements ||\n (typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.allowedElements\n : undefined);\n\n if (elements !== undefined) {\n setAllowedCustomElements(elements);\n }\n\n // Extract allowed domains\n const domains =\n config.allowedCustomElementDomains ||\n (typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.allowedDomains\n : undefined);\n\n if (domains !== undefined) {\n setAllowedCustomElementHostPatterns(domains);\n }\n\n // Extract security iframe sandbox settings\n if (config.security?.iframeSandbox !== undefined) {\n setIframeSandboxPolicy(config.security.iframeSandbox);\n } else if (\n config.security?.allowSameOrigin === true ||\n config.security?.allowIframeSameOrigin === true\n ) {\n if (!activeIframeSandboxPolicy.includes(\"allow-same-origin\")) {\n activeIframeSandboxPolicy =\n `${activeIframeSandboxPolicy} allow-same-origin`.trim();\n }\n }\n\n // Extract CSP overrides if configured\n if (config.security?.workerSrc !== undefined) {\n activeWorkerSrc = normalizePatternList(config.security.workerSrc);\n }\n if (config.security?.connectSrc !== undefined) {\n activeConnectSrc = normalizePatternList(config.security.connectSrc);\n }\n if (config.security?.scriptSrc !== undefined) {\n activeScriptSrc = normalizePatternList(config.security.scriptSrc);\n }\n if (config.security?.styleSrc !== undefined) {\n activeStyleSrc = normalizePatternList(config.security.styleSrc);\n }\n if (config.security?.imgSrc !== undefined) {\n activeImgSrc = normalizePatternList(config.security.imgSrc);\n }\n}\n\n/**\n * Initializes custom element security synchronously from embedded site-config script in the DOM if available.\n */\nexport function initCustomElementSecurityFromEmbeddedConfig(): void {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const configScript = document.getElementById(\"shadow-claw-site-config\");\n if (configScript && configScript.textContent) {\n try {\n const config = JSON.parse(configScript.textContent);\n configureCustomElementSecurity(config);\n } catch {\n // ignore JSON parse error\n }\n }\n}\n\nexport interface CustomElementScriptDescriptor {\n src: string;\n hasInit: boolean;\n}\n\n/**\n * Retrieve approved custom element script descriptors from the embedded site config.\n */\nexport function getApprovedCustomElementScriptDescriptors(): CustomElementScriptDescriptor[] {\n if (typeof document === \"undefined\") {\n return [];\n }\n\n const configScript = document.getElementById(\"shadow-claw-site-config\");\n if (!configScript || !configScript.textContent) {\n return [];\n }\n\n try {\n const config = JSON.parse(configScript.textContent);\n const scripts =\n typeof config.customElements === \"object\" &&\n !Array.isArray(config.customElements)\n ? config.customElements?.scripts\n : undefined;\n\n if (Array.isArray(scripts)) {\n return scripts\n .map((s: any) => {\n const src = typeof s === \"string\" ? s : s?.src;\n const hasInit =\n typeof s === \"object\" && s !== null ? Boolean(s.hasInit) : false;\n return { src, hasInit };\n })\n .filter(\n (entry): entry is CustomElementScriptDescriptor =>\n typeof entry.src === \"string\" &&\n isSafeCustomElementSource(entry.src),\n );\n }\n } catch {}\n\n return [];\n}\n\n/**\n * Retrieve approved custom element script URLs from the embedded site config.\n */\nexport function getApprovedCustomElementScripts(): string[] {\n return getApprovedCustomElementScriptDescriptors().map((d) => d.src);\n}\n\n/**\n * Check if HTML content contains any approved custom element tags.\n */\nexport function hasApprovedCustomElement(html: string): boolean {\n if (!html || typeof html !== \"string\") {\n return false;\n }\n const allowed = getAllowedCustomElements();\n if (allowed.length > 0) {\n return allowed.some((tag) => {\n const escaped = tag.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`<${escaped}[\\\\s>/]`, \"i\");\n return regex.test(html);\n });\n }\n\n // If no explicit allowed elements are set, check for any non-shadow-claw custom element\n const customTagRegex = /<([a-z][a-z0-9_]*-[a-z0-9_-]*)[\\\\s>/]/gi;\n let match: RegExpExecArray | null;\n while ((match = customTagRegex.exec(html)) !== null) {\n const tagName = match[1].toLowerCase();\n if (!tagName.startsWith(\"shadow-claw\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Load allowed custom elements and host patterns from IndexedDB.\n */\nexport async function loadCustomElementSecurityFromDb(\n db?: ShadowClawDatabase | null,\n): Promise<void> {\n try {\n const database = db ?? (await getDb());\n if (!database) {\n return;\n }\n\n const [elementsVal, hostsVal] = await Promise.all([\n getConfig(database, CONFIG_KEYS.ALLOWED_CUSTOM_ELEMENTS),\n getConfig(database, CONFIG_KEYS.ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS),\n ]);\n\n if (typeof elementsVal === \"string\" && elementsVal.trim()) {\n try {\n const parsed = JSON.parse(elementsVal);\n setAllowedCustomElements(parsed);\n } catch {\n setAllowedCustomElements(elementsVal);\n }\n }\n\n if (typeof hostsVal === \"string\" && hostsVal.trim()) {\n try {\n const parsed = JSON.parse(hostsVal);\n setAllowedCustomElementHostPatterns(parsed);\n } catch {\n setAllowedCustomElementHostPatterns(hostsVal);\n }\n }\n } catch (err) {\n console.warn(\"Failed to load custom element security from db:\", err);\n }\n}\n\nlet originalCustomElementsDefine: typeof customElements.define | null = null;\nlet isRegistryGuardInstalled = false;\n\n/**\n * Monkey-patches customElements.define to prevent registration of unapproved custom elements.\n */\nexport function installCustomElementsRegistryGuard(): void {\n initCustomElementSecurityFromEmbeddedConfig();\n\n if (\n isRegistryGuardInstalled ||\n typeof customElements === \"undefined\" ||\n typeof customElements.define !== \"function\"\n ) {\n return;\n }\n\n originalCustomElementsDefine = customElements.define.bind(customElements);\n\n customElements.define = function (\n name: string,\n constructor: CustomElementConstructor,\n options?: ElementDefinitionOptions,\n ) {\n const lowerName = (name || \"\").toLowerCase().trim();\n if (!isAllowedCustomElement(lowerName)) {\n const errorMsg = `[Security] Registration blocked: <${name}> is not an approved custom element.`;\n console.error(errorMsg);\n throw new Error(errorMsg);\n }\n\n return originalCustomElementsDefine!(name, constructor, options);\n };\n\n isRegistryGuardInstalled = true;\n}\n\n/**\n * Restores the original customElements.define (useful for testing).\n */\nexport function uninstallCustomElementsRegistryGuard(): void {\n if (!isRegistryGuardInstalled || !originalCustomElementsDefine) {\n return;\n }\n\n customElements.define = originalCustomElementsDefine;\n originalCustomElementsDefine = null;\n isRegistryGuardInstalled = false;\n}\n\n/**\n * Installs a MutationObserver on a DOM tree to detect and strip unapproved custom elements.\n */\nexport function installCustomElementDomGuard(\n root: Node = typeof document !== \"undefined\"\n ? document.documentElement\n : (null as any),\n): MutationObserver | null {\n if (typeof MutationObserver === \"undefined\" || !root) {\n return null;\n }\n\n // Sweep existing unapproved custom elements already present in root\n if (typeof (root as any).querySelectorAll === \"function\") {\n try {\n const existing = (root as Element).querySelectorAll(\"*\");\n existing.forEach((el) => {\n const tagName = el.tagName ? el.tagName.toLowerCase() : \"\";\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n console.warn(\n `[Security] Removing existing unapproved custom element: <${tagName}>`,\n );\n el.remove();\n }\n });\n } catch {}\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n const el = node as Element;\n const tagName = el.tagName ? el.tagName.toLowerCase() : \"\";\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n console.warn(\n `[Security] Removing unapproved custom element: <${tagName}>`,\n );\n el.remove();\n }\n }\n });\n }\n });\n\n observer.observe(root, { childList: true, subtree: true });\n\n return observer;\n}\n\n/**\n * Load an approved custom element script module dynamically.\n * Enforces domain validation and Trusted Types.\n */\nexport async function loadApprovedCustomElementScript(\n src: string,\n options: {\n type?: string;\n async?: boolean;\n defer?: boolean;\n } = {},\n): Promise<HTMLScriptElement> {\n if (!isSafeCustomElementSource(src)) {\n throw new Error(\n `[Security] Refused to load script from unapproved host: ${src}`,\n );\n }\n\n if (typeof document === \"undefined\") {\n throw new Error(\"Cannot load script outside browser document environment.\");\n }\n\n const existingScript = document.querySelector(`script[src=\"${src}\"]`);\n if (existingScript instanceof HTMLScriptElement) {\n return existingScript;\n }\n\n const trustedUrl = toTrustedScriptUrl(src) as string;\n\n return new Promise((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.type = options.type || \"module\";\n if (options.async) script.async = true;\n if (options.defer) script.defer = true;\n script.src = trustedUrl;\n\n script.onload = () => resolve(script);\n script.onerror = (err) =>\n reject(\n new Error(`Failed to load custom element script: ${src} (${err})`),\n );\n\n document.head.appendChild(script);\n });\n}\n\nlet purifyHookRegistered = false;\n\n/**\n * Ensures DOMPurify has the custom element sanitization hook registered.\n */\nexport function ensureCustomElementSanitizerHook(): void {\n if (purifyHookRegistered) {\n return;\n }\n\n const purify = getDOMPurify();\n\n if (purify && typeof purify.addHook === \"function\") {\n const sanitizeCustomElementNode = (node: Node) => {\n if (node && node.nodeType === 1 /* ELEMENT_NODE */) {\n const el = node as Element;\n const tagName = (el.tagName || \"\").toLowerCase();\n if (tagName.includes(\"-\") && !isAllowedCustomElement(tagName)) {\n if (typeof el.remove === \"function\") {\n el.remove();\n }\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n }\n }\n }\n };\n\n purify.addHook(\"uponSanitizeElement\", sanitizeCustomElementNode);\n purify.addHook(\"afterSanitizeElements\", sanitizeCustomElementNode);\n purifyHookRegistered = true;\n }\n}\n\n/**\n * Get DOMPurify configuration for custom element handling.\n */\nexport function getCustomElementPurifyConfig(): Config {\n ensureCustomElementSanitizerHook();\n\n return {\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: (tagName: string) => isAllowedCustomElement(tagName),\n attributeNameCheck: () => true,\n allowCustomizedBuiltInElements: false,\n },\n };\n}\n","/// <reference lib=\"dom\" />\nimport type { Config } from \"dompurify\";\nimport { parseRouteFromUrl } from \"../core/app-routes.js\";\nimport {\n ensureIframeSanitizerHook,\n getDOMPurify,\n} from \"../security/iframe-sanitizer.js\";\nimport {\n ensureCustomElementSanitizerHook,\n isAllowedCustomElement,\n} from \"../security/custom-element-security.js\";\n\nexport type HashInput = File | Blob | ArrayBuffer | ArrayBufferView;\n\n/**\n * Format a date for use in a filename: yyyy-mm-dd_hh-mm-ss\n */\nexport function formatDateForFilename(date = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n\n const yyyy = date.getFullYear();\n const mm = pad(date.getMonth() + 1);\n const dd = pad(date.getDate());\n\n const hh = pad(date.getHours());\n const min = pad(date.getMinutes());\n const ss = pad(date.getSeconds());\n\n return `${yyyy}-${mm}-${dd}_${hh}-${min}-${ss}`;\n}\n\n/**\n * Format a timestamp for display: e.g. \"Sun, Mar 1, 1:25 PM\"\n */\nexport function formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp);\n\n return new Intl.DateTimeFormat(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n }).format(date);\n}\n\n/**\n * Escape HTML special characters in a string.\n */\nexport function escapeHtml(str: string): string {\n const div = document.createElement(\"div\");\n div.textContent = str;\n\n return div.innerHTML;\n}\n\n/**\n * Sanitize HTML content using DOMPurify, allowing custom element tags.\n */\nexport function sanitizeHtml(\n dirty: string | Node = \"\",\n options: Config = {},\n): string {\n ensureIframeSanitizerHook();\n ensureCustomElementSanitizerHook();\n\n return getDOMPurify().sanitize(dirty, {\n ADD_TAGS: [\"iframe\", \"figure\", \"figcaption\"],\n ADD_ATTR: [\n \"allow\",\n \"allowfullscreen\",\n \"frameborder\",\n \"scrolling\",\n \"referrerpolicy\",\n \"loading\",\n ],\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: (tagName: string) => isAllowedCustomElement(tagName),\n attributeNameCheck: () => true,\n allowCustomizedBuiltInElements: false,\n },\n ...options,\n });\n}\n\n/**\n * Interface representing the detailed internal navigation parameters\n */\nexport interface ShadowClawNavigateDetail {\n page: string;\n groupId?: string;\n path?: string;\n anchor?: string;\n}\n\n/**\n * Parses a special or relative link and dispatches the 'shadow-claw-navigate' custom event on document.\n * Returns true if the link was handled/intercepted, false otherwise.\n */\nexport function handleSpecialLinkNavigation(\n href: string,\n basePath: string = \"\",\n currentGroupId?: string,\n): boolean {\n let trimmed = href.trim();\n if (!trimmed) {\n return false;\n }\n\n // Handle malformed query strings where '?' is used instead of '&' (e.g. #Page?param1=val1?param2=val2)\n const firstQuestion = trimmed.indexOf(\"?\");\n if (firstQuestion !== -1) {\n const before = trimmed.slice(0, firstQuestion + 1);\n const after = trimmed.slice(firstQuestion + 1);\n trimmed = before + after.replace(/\\?/g, \"&\");\n }\n\n // 1. Check if it is a case-insensitive special link starting with \"/#\" or \"#\" matching standard pages\n if (trimmed.startsWith(\"/#\") || trimmed.startsWith(\"#\")) {\n const withoutHash = trimmed.startsWith(\"/#\")\n ? trimmed.slice(2)\n : trimmed.slice(1);\n\n // Parse parts: Page?query#anchor\n const pagePart = withoutHash.split(/[?#]/, 1)[0];\n const pageName = pagePart.toLowerCase();\n\n // Valid pages\n const validPages = [\"chat\", \"files\", \"tasks\", \"pages\", \"settings\"];\n if (validPages.includes(pageName)) {\n // Create a dummy absolute URL to parse searchParams easily\n const fakeUrl = trimmed.startsWith(\"/#\")\n ? trimmed.replace(/^\\/#/, \"http://local/\")\n : trimmed.replace(/^#/, \"http://local/\");\n const urlLike = new URL(fakeUrl, \"http://local/\");\n\n const groupId =\n urlLike.searchParams.get(\"groupId\") ||\n urlLike.searchParams.get(\"conversationId\") ||\n currentGroupId;\n const path =\n urlLike.searchParams.get(\"file\") ||\n urlLike.searchParams.get(\"path\") ||\n undefined;\n // Support: ?anchor=some-heading, ?anchor=L10-L20, or #fragment\n const anchorParam = urlLike.searchParams.get(\"anchor\");\n const anchor = anchorParam\n ? anchorParam\n : urlLike.hash\n ? urlLike.hash.slice(1)\n : undefined;\n\n const detail: ShadowClawNavigateDetail = {\n page: pageName,\n groupId: groupId || undefined,\n path: path || undefined,\n anchor: anchor || undefined,\n };\n\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail,\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n }\n\n // 1.5. Check if it is an absolute application route (e.g., /files/room:123/path, /chat/...)\n if (trimmed.startsWith(\"/\")) {\n try {\n const urlLike = new URL(trimmed, window.location.origin);\n const route = parseRouteFromUrl(urlLike, currentGroupId);\n if (route) {\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail: {\n page: route.page,\n groupId: route.groupId,\n path: route.path,\n anchor:\n route.anchor ||\n (urlLike.hash ? urlLike.hash.slice(1) : undefined),\n },\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n } catch {\n // Fallback to relative workspace path resolution below\n }\n }\n\n // 2. Relative or absolute workspace paths, e.g., \"docs/README.md\"\n // If it does not have a scheme (http, https, mailto, etc.) and is not external:\n const hasScheme = /^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed);\n if (\n !hasScheme &&\n !trimmed.startsWith(\"//\") &&\n !trimmed.startsWith(\"javascript:\")\n ) {\n // Resolve absolute vs relative\n let resolvedPath = trimmed.split(/[?#]/, 1)[0].replace(/\\\\/g, \"/\");\n const isAbsolute = resolvedPath.startsWith(\"/\");\n resolvedPath = resolvedPath.replace(/^\\/+/, \"\");\n\n const urlLike = new URL(trimmed, \"http://local/\");\n const anchor = urlLike.hash ? urlLike.hash.slice(1) : undefined;\n\n let finalPath = resolvedPath;\n if (!isAbsolute && basePath) {\n const baseParts = basePath\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .split(\"/\")\n .filter(Boolean);\n baseParts.pop(); // Remove the filename of base path\n\n const pathParts = resolvedPath.split(\"/\");\n const stack = [...baseParts];\n for (const part of pathParts) {\n if (!part || part === \".\") {\n continue;\n }\n\n if (part === \"..\") {\n stack.pop();\n } else {\n stack.push(part);\n }\n }\n\n finalPath = stack.join(\"/\");\n }\n\n if (finalPath) {\n const detail: ShadowClawNavigateDetail = {\n page: \"files\",\n groupId: currentGroupId || undefined,\n path: finalPath,\n anchor: anchor || undefined,\n };\n\n document.dispatchEvent(\n new CustomEvent(\"shadow-claw-navigate\", {\n detail,\n bubbles: true,\n composed: true,\n }),\n );\n\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Convert various input types to an ArrayBuffer for hashing.\n */\nexport function toArrayBuffer(input: HashInput): Promise<ArrayBuffer> {\n if (input instanceof Blob) {\n return input.arrayBuffer();\n }\n\n if (input instanceof ArrayBuffer) {\n return Promise.resolve(input.slice(0) as ArrayBuffer);\n }\n\n const { buffer, byteOffset, byteLength } = input;\n\n return Promise.resolve(\n buffer.slice(byteOffset, byteOffset + byteLength) as ArrayBuffer,\n );\n}\n\n/**\n * Convert an ArrayBuffer to a hex string.\n */\nexport function bufferToHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Compute the SHA-256 hash and return it as a hex string.\n */\nexport async function computeSha256(input: HashInput): Promise<string> {\n const data = await toArrayBuffer(input);\n const subtle =\n globalThis.crypto?.subtle ??\n (globalThis as any).window?.crypto?.subtle ??\n (typeof process !== \"undefined\"\n ? (await import(\"node:crypto\")).webcrypto?.subtle\n : undefined);\n\n if (!subtle) {\n throw new Error(\"crypto.subtle is not available in current environment\");\n }\n\n const hashBuffer = await subtle.digest(\"SHA-256\", data);\n\n return bufferToHex(hashBuffer);\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-DZ8SGSJo.js";
2
- import { o as DEFAULT_GROUP_ID } from "./config-CPHDmyTx.js";
2
+ import { o as DEFAULT_GROUP_ID } from "./config-DZkF9LiO.js";
3
3
  import { t as TOOL_DEFINITIONS } from "./tools-BQpz4Hkp.js";
4
4
  import "./tools-d8Wgmt5f.js";
5
5
 
@@ -1184,10 +1184,14 @@ function cleanupWebMCPPolyfill() {
1184
1184
  var webmcp_exports = /* @__PURE__ */ __exportAll({
1185
1185
  CONSEQUENTIAL_TOOL_NAMES: () => CONSEQUENTIAL_TOOL_NAMES,
1186
1186
  READ_ONLY_TOOL_NAMES: () => READ_ONLY_TOOL_NAMES,
1187
+ addWebMcpEventListener: () => addWebMcpEventListener,
1187
1188
  executeWebMcpTool: () => executeWebMcpTool,
1188
1189
  extractAbortSignal: () => extractAbortSignal,
1190
+ getWebMcpEventTarget: () => getWebMcpEventTarget,
1189
1191
  getWebMcpMode: () => getWebMcpMode,
1190
1192
  getWebMcpTools: () => getWebMcpTools,
1193
+ onWebMcpToolActivated: () => onWebMcpToolActivated,
1194
+ onWebMcpToolCancel: () => onWebMcpToolCancel,
1191
1195
  parseWebMcpInputSchema: () => parseWebMcpInputSchema,
1192
1196
  registerWebMcpTools: () => registerWebMcpTools,
1193
1197
  resolveWebMcpToolAnnotations: () => resolveWebMcpToolAnnotations,
@@ -1391,6 +1395,118 @@ async function executeWebMcpTool(modelContext, tool, input, options) {
1391
1395
  }
1392
1396
  }
1393
1397
  /**
1398
+ * Resolves the appropriate EventTarget for WebMCP lifecycle events
1399
+ * (`toolactivated` and `toolcancel`) with backwards compatibility.
1400
+ *
1401
+ * Starting in Chrome 156.0.8076.0 (PR #245), `ontoolactivated` and `ontoolcancel`
1402
+ * event handler properties and lifecycle events moved from `window` to `document.modelContext`.
1403
+ * In Chrome < 156, these events were fired on `window`.
1404
+ *
1405
+ * This function practices robust feature detection and graceful degradation:
1406
+ * 1. Safely checks for existence of `document` and `window` to avoid ReferenceErrors
1407
+ * in non-DOM / headless / Node.js environments.
1408
+ * 2. Checks if `on${type}` is present in `document.modelContext` (or `navigator.modelContext`).
1409
+ * If present and it supports `addEventListener`, `modelContext` is returned.
1410
+ * 3. Checks if `on${type}` is present in `window`. If present and `window` supports
1411
+ * `addEventListener`, `window` is returned (legacy Chrome < 156 path).
1412
+ * 4. Fallback: If neither has `on${type}` (e.g. polyfill, synthetic mock, or uninitialized prototype),
1413
+ * prefers `modelContext` if it supports `addEventListener`, otherwise falls back to `window`.
1414
+ * 5. Returns `null` if no valid EventTarget is found.
1415
+ */
1416
+ function getWebMcpEventTarget(type) {
1417
+ const doc = typeof document !== "undefined" ? document : void 0;
1418
+ const win = typeof window !== "undefined" ? window : void 0;
1419
+ const nav = typeof navigator !== "undefined" ? navigator : void 0;
1420
+ const modelContext = doc?.modelContext ?? nav?.modelContext;
1421
+ const hasModelContextListener = modelContext && typeof modelContext.addEventListener === "function";
1422
+ const hasWindowListener = win && typeof win.addEventListener === "function";
1423
+ if (type) {
1424
+ const handlerKey = `on${type}`;
1425
+ if (modelContext && handlerKey in modelContext && hasModelContextListener) return modelContext;
1426
+ if (win && handlerKey in win && hasWindowListener) return win;
1427
+ }
1428
+ if (hasModelContextListener) return modelContext;
1429
+ if (hasWindowListener) return win;
1430
+ return null;
1431
+ }
1432
+ /**
1433
+ * Safely registers a listener for WebMCP lifecycle events (`toolactivated`, `toolcancel`)
1434
+ * with graceful degradation, event payload normalization, and automatic unsubscription.
1435
+ *
1436
+ * Returns an idempotent unsubscribe cleanup function.
1437
+ */
1438
+ function addWebMcpEventListener(type, listener, options) {
1439
+ const target = getWebMcpEventTarget(type);
1440
+ const opts = typeof options === "object" ? options : void 0;
1441
+ const listenBoth = opts?.listenBoth ?? false;
1442
+ const win = typeof window !== "undefined" && typeof window.addEventListener === "function" ? window : null;
1443
+ const doc = typeof document !== "undefined" ? document : null;
1444
+ const nav = typeof navigator !== "undefined" ? navigator : null;
1445
+ const modelContext = doc?.modelContext ?? nav?.modelContext;
1446
+ const hasMc = modelContext && typeof modelContext.addEventListener === "function";
1447
+ const secondaryTarget = listenBoth ? target === modelContext ? win !== target ? win : null : hasMc ? modelContext : null : null;
1448
+ if (!target && !secondaryTarget) return () => {};
1449
+ let recentToolNames = null;
1450
+ let clearTimer = null;
1451
+ const wrapHandler = (evt) => {
1452
+ let toolName = evt.toolName;
1453
+ if (typeof toolName !== "string" && "detail" in evt && typeof evt.detail === "object") toolName = evt.detail?.toolName;
1454
+ if (typeof toolName !== "string") toolName = "";
1455
+ if (!("toolName" in evt) || evt.toolName !== toolName) try {
1456
+ Object.defineProperty(evt, "toolName", {
1457
+ value: toolName,
1458
+ configurable: true,
1459
+ enumerable: true
1460
+ });
1461
+ } catch {}
1462
+ if (listenBoth && toolName) {
1463
+ if (!recentToolNames) recentToolNames = /* @__PURE__ */ new Set();
1464
+ if (recentToolNames.has(toolName)) return;
1465
+ recentToolNames.add(toolName);
1466
+ if (!clearTimer) clearTimer = setTimeout(() => {
1467
+ recentToolNames?.clear();
1468
+ clearTimer = null;
1469
+ }, 100);
1470
+ }
1471
+ listener(evt);
1472
+ };
1473
+ if (target) target.addEventListener(type, wrapHandler, options);
1474
+ if (secondaryTarget) secondaryTarget.addEventListener(type, wrapHandler, options);
1475
+ let unsubscribed = false;
1476
+ const unsubscribe = () => {
1477
+ if (unsubscribed) return;
1478
+ unsubscribed = true;
1479
+ if (clearTimer) {
1480
+ clearTimeout(clearTimer);
1481
+ clearTimer = null;
1482
+ }
1483
+ if (target) target.removeEventListener(type, wrapHandler, options);
1484
+ if (secondaryTarget) secondaryTarget.removeEventListener(type, wrapHandler, options);
1485
+ };
1486
+ if (opts?.signal) {
1487
+ if (opts.signal.aborted) {
1488
+ unsubscribe();
1489
+ return () => {};
1490
+ }
1491
+ opts.signal.addEventListener("abort", () => unsubscribe(), { once: true });
1492
+ }
1493
+ return unsubscribe;
1494
+ }
1495
+ /**
1496
+ * Convenience helper to subscribe to tool execution start events (`toolactivated`).
1497
+ * Returns an unsubscribe cleanup function.
1498
+ */
1499
+ function onWebMcpToolActivated(listener, options) {
1500
+ return addWebMcpEventListener("toolactivated", listener, options);
1501
+ }
1502
+ /**
1503
+ * Convenience helper to subscribe to tool execution cancel events (`toolcancel`).
1504
+ * Returns an unsubscribe cleanup function.
1505
+ */
1506
+ function onWebMcpToolCancel(listener, options) {
1507
+ return addWebMcpEventListener("toolcancel", listener, options);
1508
+ }
1509
+ /**
1394
1510
  * Consequential tools that perform high-stakes, irreversible, or external real-world actions
1395
1511
  * (such as deleting data, executing arbitrary system commands, or transmitting live communications).
1396
1512
  * Signals consuming agents to require explicit user confirmation prior to execution (Chrome 154.0.8017.0+).
@@ -1567,5 +1683,5 @@ function unregisterWebMcpTools() {
1567
1683
  }
1568
1684
 
1569
1685
  //#endregion
1570
- export { webmcp_exports as a, unregisterWebMcpTools as i, registerWebMcpTools as n, setWebMcpMode as r, getWebMcpMode as t };
1571
- //# sourceMappingURL=webmcp-D2bocsgh.js.map
1686
+ export { setWebMcpMode as a, registerWebMcpTools as i, onWebMcpToolActivated as n, unregisterWebMcpTools as o, onWebMcpToolCancel as r, webmcp_exports as s, getWebMcpMode as t };
1687
+ //# sourceMappingURL=webmcp-oEP9YpR2.js.map