shadow-claw 1.29.0 → 1.30.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.
- package/.agents/skills/main/skill-creator/SKILL.md +3 -2
- package/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
- package/.well-known/agent-skills/index.json +1 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/.well-known/mcp.json +1 -1
- package/dist/lib/{app-routes-CqBOeA5q.js → app-routes-BAEMLu9g.js} +3 -2
- package/dist/lib/app-routes-BAEMLu9g.js.map +1 -0
- package/dist/lib/{bundler-8JNIKwOs.js → bundler-CsL7hHMq.js} +4 -9
- package/dist/lib/{bundler-8JNIKwOs.js.map → bundler-CsL7hHMq.js.map} +1 -1
- package/dist/lib/components/index.js +26 -26
- package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/settings/shadow-claw-git.js +1 -1
- package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
- package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
- package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
- package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw-a2ui.js +1 -1
- package/dist/lib/components/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/shadow-claw-channels.js +1 -1
- package/dist/lib/components/shadow-claw-chat.js +1 -1
- package/dist/lib/components/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/shadow-claw-conversations.js +1 -1
- package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
- package/dist/lib/components/shadow-claw-files.js +1 -1
- package/dist/lib/components/shadow-claw-git.js +1 -1
- package/dist/lib/components/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/shadow-claw-llm.js +1 -1
- package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/shadow-claw-networking.js +1 -1
- package/dist/lib/components/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/shadow-claw-page-header.js +1 -1
- package/dist/lib/components/shadow-claw-pages.js +1 -1
- package/dist/lib/components/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/shadow-claw-settings.js +1 -1
- package/dist/lib/components/shadow-claw-storage.js +1 -1
- package/dist/lib/components/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/shadow-claw-tasks.js +1 -1
- package/dist/lib/components/shadow-claw-terminal.js +1 -1
- package/dist/lib/components/shadow-claw-tools.js +1 -1
- package/dist/lib/components/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw.js +1 -1
- package/dist/lib/{config--CFrw3J3.js → config-DjZ9QWc4.js} +2 -2
- package/dist/lib/{config--CFrw3J3.js.map → config-DjZ9QWc4.js.map} +1 -1
- package/dist/lib/{configurePeerJs-DG4hliKp.js → configurePeerJs-H0WaoT0w.js} +3 -3
- package/dist/lib/{configurePeerJs-DG4hliKp.js.map → configurePeerJs-H0WaoT0w.js.map} +1 -1
- package/dist/lib/{connections-DwjzwVz0.js → connections-BURqMIUv.js} +2 -2
- package/dist/lib/{connections-DwjzwVz0.js.map → connections-BURqMIUv.js.map} +1 -1
- package/dist/lib/content/markdown-links.d.ts +19 -0
- package/dist/lib/core/app-routes.d.ts +1 -0
- package/dist/lib/{downloadGroupFile-DmcBQU1n.js → downloadGroupFile-B8J4up2a.js} +2 -2
- package/dist/lib/{downloadGroupFile-DmcBQU1n.js.map → downloadGroupFile-B8J4up2a.js.map} +1 -1
- package/dist/lib/{file-viewer-C3YKnq_-.js → file-viewer-CwvhxAAG.js} +5 -5
- package/dist/lib/{file-viewer-C3YKnq_-.js.map → file-viewer-CwvhxAAG.js.map} +1 -1
- package/dist/lib/{getGroupDir-m0f-ekgX.js → getGroupDir-QrN2aTo8.js} +4 -4
- package/dist/lib/{getGroupDir-m0f-ekgX.js.map → getGroupDir-QrN2aTo8.js.map} +1 -1
- package/dist/lib/{git-C-Q6-IVe.js → git-DhZoe1SE.js} +3 -3
- package/dist/lib/{git-C-Q6-IVe.js.map → git-DhZoe1SE.js.map} +1 -1
- package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js → iframe-sanitizer-Bujgq14T.js} +2 -2
- package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js.map → iframe-sanitizer-Bujgq14T.js.map} +1 -1
- package/dist/lib/index.js +27 -27
- package/dist/lib/{initChatSplitResize-yyBTU6h9.js → initChatSplitResize-BjiWoqC_.js} +2 -2
- package/dist/lib/{initChatSplitResize-yyBTU6h9.js.map → initChatSplitResize-BjiWoqC_.js.map} +1 -1
- package/dist/lib/{initControlPlane-DnpAzphg.js → initControlPlane-C9JxQCDh.js} +16 -16
- package/dist/lib/{initControlPlane-DnpAzphg.js.map → initControlPlane-C9JxQCDh.js.map} +1 -1
- package/dist/lib/{markdown-DgdSt2GD.js → markdown-DYHmNjC4.js} +126 -5
- package/dist/lib/markdown-DYHmNjC4.js.map +1 -0
- package/dist/lib/{mcp-reconnect-C86MR3z8.js → mcp-reconnect-BxJ77WSb.js} +2 -2
- package/dist/lib/{mcp-reconnect-C86MR3z8.js.map → mcp-reconnect-BxJ77WSb.js.map} +1 -1
- package/dist/lib/{memoryStorage-UR8E8K-H.js → memoryStorage-D3FBwO9T.js} +2 -2
- package/dist/lib/{memoryStorage-UR8E8K-H.js.map → memoryStorage-D3FBwO9T.js.map} +1 -1
- package/dist/lib/{orchestrator-ClXbJ4Mb.js → orchestrator-C6dc-2OQ.js} +130 -27
- package/dist/lib/{orchestrator-ClXbJ4Mb.js.map → orchestrator-C6dc-2OQ.js.map} +1 -1
- package/dist/lib/{orchestrator-CjEau_RG.js → orchestrator-DVkyd8K9.js} +27 -17
- package/dist/lib/orchestrator-DVkyd8K9.js.map +1 -0
- package/dist/lib/{peerjs-BdfpltIe.js → peerjs-BUS9O04I.js} +274 -60
- package/dist/lib/peerjs-BUS9O04I.js.map +1 -0
- package/dist/lib/{push-client-DjwKknNg.js → push-client-4JsQGmQa.js} +3 -3
- package/dist/lib/{push-client-DjwKknNg.js.map → push-client-4JsQGmQa.js.map} +1 -1
- package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js → readGroupFileBytes-CSA7u-nJ.js} +2 -2
- package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js.map → readGroupFileBytes-CSA7u-nJ.js.map} +1 -1
- package/dist/lib/{shadow-claw-DcPGKenn.js → shadow-claw-BMoF8Auf.js} +11 -11
- package/dist/lib/{shadow-claw-DcPGKenn.js.map → shadow-claw-BMoF8Auf.js.map} +1 -1
- package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js → shadow-claw-a2ui-2I5nffIn.js} +2 -2
- package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js.map → shadow-claw-a2ui-2I5nffIn.js.map} +1 -1
- package/dist/lib/{shadow-claw-accounts-03oJ__XC.js → shadow-claw-accounts-BCjlgvzy.js} +3 -3
- package/dist/lib/{shadow-claw-accounts-03oJ__XC.js.map → shadow-claw-accounts-BCjlgvzy.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js → shadow-claw-channel-config-CxQAmlDE.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js.map → shadow-claw-channel-config-CxQAmlDE.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-BgaJiPdE.js → shadow-claw-channels-CuYMUVAG.js} +3 -3
- package/dist/lib/{shadow-claw-channels-BgaJiPdE.js.map → shadow-claw-channels-CuYMUVAG.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-mXPQZbwT.js → shadow-claw-chat-RFtPmmyl.js} +13 -12
- package/dist/lib/shadow-claw-chat-RFtPmmyl.js.map +1 -0
- package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js → shadow-claw-control-plane-siqmRzR1.js} +7 -7
- package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js.map → shadow-claw-control-plane-siqmRzR1.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js → shadow-claw-conversations-DygK5y1e.js} +7 -7
- package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js.map → shadow-claw-conversations-DygK5y1e.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-BSbZvSl-.js → shadow-claw-file-viewer-DGMA7d7H.js} +11 -11
- package/dist/lib/shadow-claw-file-viewer-DGMA7d7H.js.map +1 -0
- package/dist/lib/{shadow-claw-files-BLVr9Pua.js → shadow-claw-files-CgD1B9J7.js} +8 -8
- package/dist/lib/{shadow-claw-files-BLVr9Pua.js.map → shadow-claw-files-CgD1B9J7.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-CHC1H86J.js → shadow-claw-git-Bw1jGRrf.js} +6 -6
- package/dist/lib/{shadow-claw-git-CHC1H86J.js.map → shadow-claw-git-Bw1jGRrf.js.map} +1 -1
- package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js → shadow-claw-integrations-ChaXtvsg.js} +4 -4
- package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js.map → shadow-claw-integrations-ChaXtvsg.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-CKXfxd3D.js → shadow-claw-llm-CDM4Akjc.js} +6 -6
- package/dist/lib/{shadow-claw-llm-CKXfxd3D.js.map → shadow-claw-llm-CDM4Akjc.js.map} +1 -1
- package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js → shadow-claw-mcp-remote-BLxs_Z4I.js} +4 -4
- package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js.map → shadow-claw-mcp-remote-BLxs_Z4I.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-dpYvfchh.js → shadow-claw-networking-BYt-kMSI.js} +2 -2
- package/dist/lib/{shadow-claw-networking-dpYvfchh.js.map → shadow-claw-networking-BYt-kMSI.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-_YeAVPga.js → shadow-claw-notifications-Dpe4EtZI.js} +3 -3
- package/dist/lib/{shadow-claw-notifications-_YeAVPga.js.map → shadow-claw-notifications-Dpe4EtZI.js.map} +1 -1
- package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js → shadow-claw-page-header-P4EvWyUr.js} +2 -2
- package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js.map → shadow-claw-page-header-P4EvWyUr.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-DVzZriZ7.js → shadow-claw-pages-DWd_c4d6.js} +10 -10
- package/dist/lib/{shadow-claw-pages-DVzZriZ7.js.map → shadow-claw-pages-DWd_c4d6.js.map} +1 -1
- package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js → shadow-claw-peerjs-D928817m.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js.map → shadow-claw-peerjs-D928817m.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js → shadow-claw-settings-C8OPrSqs.js} +8 -8
- package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js.map → shadow-claw-settings-C8OPrSqs.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-Bv__kXG6.js → shadow-claw-storage-CZ2uZJNw.js} +5 -5
- package/dist/lib/{shadow-claw-storage-Bv__kXG6.js.map → shadow-claw-storage-CZ2uZJNw.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js → shadow-claw-task-server-CLT018BX.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js.map → shadow-claw-task-server-CLT018BX.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-qmcDT4PU.js → shadow-claw-tasks-D5h-lGmq.js} +9 -8
- package/dist/lib/shadow-claw-tasks-D5h-lGmq.js.map +1 -0
- package/dist/lib/{shadow-claw-terminal-0QUWP8of.js → shadow-claw-terminal-Cy1O6KVM.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-0QUWP8of.js.map → shadow-claw-terminal-Cy1O6KVM.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js → shadow-claw-tools-CVD06bCR.js} +9 -9
- package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js.map → shadow-claw-tools-CVD06bCR.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js → shadow-claw-webvm-DoGl5ZSJ.js} +3 -3
- package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js.map → shadow-claw-webvm-DoGl5ZSJ.js.map} +1 -1
- package/dist/lib/subsystems/channels/peerjs.d.ts +37 -4
- package/dist/lib/subsystems/channels/room.d.ts +4 -0
- package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js → syncWebMcpRegistration-BeYkQEvj.js} +5 -5
- package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js.map → syncWebMcpRegistration-BeYkQEvj.js.map} +1 -1
- package/dist/lib/tools-C3Kft940.js +1 -0
- package/dist/lib/{tools-DBaMRiEu.js → tools-DKzPWc0q.js} +2 -2
- package/dist/lib/{tools-DBaMRiEu.js.map → tools-DKzPWc0q.js.map} +1 -1
- package/dist/lib/{tools-DwwB9RBa.js → tools-DqcJe8LS.js} +5 -5
- package/dist/lib/{tools-DwwB9RBa.js.map → tools-DqcJe8LS.js.map} +1 -1
- package/dist/lib/{trusted-types-Dx0RZlrd.js → trusted-types-Oz7xXJAY.js} +4 -4
- package/dist/lib/{trusted-types-Dx0RZlrd.js.map → trusted-types-Oz7xXJAY.js.map} +1 -1
- package/dist/lib/utils/index.js +1 -1
- package/dist/lib/utils/namespacedStorage.js +1 -1
- package/dist/lib/utils/utils.js +1 -1
- package/dist/lib/{webmcp-j_1_T3wf.js → webmcp-BC8_WafM.js} +4 -4
- package/dist/lib/{webmcp-j_1_T3wf.js.map → webmcp-BC8_WafM.js.map} +1 -1
- package/dist/lib/worker/utils/system-prompt.d.ts +4 -1
- package/dist/public/.agents/skills/main/skill-creator/SKILL.md +3 -2
- package/dist/public/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
- package/dist/public/.well-known/agent-skills/index.json +1 -1
- package/dist/public/.well-known/mcp/server-card.json +1 -1
- package/dist/public/.well-known/mcp.json +1 -1
- package/dist/public/agent.worker.js +18 -17
- package/dist/public/app-routes-BMQ4HFaM.js +1 -0
- package/dist/public/{bundler-Ca-Xwln8.js → bundler-0if-QelV.js} +4 -4
- package/dist/public/{config-CrHchneq.js → config-Bnwx4EfS.js} +1 -1
- package/dist/public/{configurePeerJs-B470pdeU.js → configurePeerJs-DkyGvwk_.js} +1 -1
- package/dist/public/{connections-DvbgdkaB.js → connections-6575KDGE.js} +1 -1
- package/dist/public/{custom-element-security-FU04Cq05.js → custom-element-security-BQJQ_oKz.js} +1 -1
- package/dist/public/docs/example/article/index.html +2 -2
- package/dist/public/docs/publishing/index.html +2 -2
- package/dist/public/docs/skill-creator/index.html +2 -2
- package/dist/public/docs/subsystems/skills.md +3 -1
- package/dist/public/{downloadGroupFile-D8KRJGGL.js → downloadGroupFile-Wo1Sxdhr.js} +1 -1
- package/dist/public/{e2e-bridge-CSW0S5Yz.js → e2e-bridge-CvLCUU2O.js} +1 -1
- package/dist/public/{file-viewer-Cs-riNvy.js → file-viewer-CIjqAvNF.js} +1 -1
- package/dist/public/{getGroupDir-P1h9wl6S.js → getGroupDir-BwprrdrQ.js} +1 -1
- package/dist/public/{git-7Vq_SJSp.js → git-BSnY2D-A.js} +2 -2
- package/dist/public/{iframe-sanitizer-y2Z1pPwY.js → iframe-sanitizer-viROQkRn.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/public/index.js +1 -1
- package/dist/public/{initChatSplitResize-CzV2E7Ul.js → initChatSplitResize-BA18wLQQ.js} +1 -1
- package/dist/public/{initControlPlane-BqCY0NQy.js → initControlPlane-L96uJkRA.js} +1 -1
- package/dist/public/main/index.html +2 -2
- package/dist/public/main/memory/index.html +2 -2
- package/dist/public/{markdown-Cw7vCtTg.js → markdown-DGjZAm_w.js} +17 -14
- package/dist/public/{mcp-reconnect-9emsqGRe.js → mcp-reconnect-CBHuaYdF.js} +1 -1
- package/dist/public/{memoryStorage-C0KvLNUp.js → memoryStorage-C1llaYus.js} +1 -1
- package/dist/public/orchestrator-C0VOoTiK.js +15 -0
- package/dist/public/{orchestrator-DpkkeD6T.js → orchestrator-DMWi--Dc.js} +20 -19
- package/dist/public/peerjs-Bf6ZxfbA.js +1 -0
- package/dist/public/{push-client-CHjSbrWs.js → push-client-BD4YalBa.js} +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-BBPV_9X8.js → shadow-claw-DRy-D4Qi.js} +2 -2
- package/dist/public/{shadow-claw-accounts-xUOLBsQZ.js → shadow-claw-accounts-DnfmA8cb.js} +1 -1
- package/dist/public/{shadow-claw-channels-BJvrKQjg.js → shadow-claw-channels-8UkycZAa.js} +1 -1
- package/dist/public/{shadow-claw-chat-BG2EaRaw.js → shadow-claw-chat-Cf5LUiul.js} +9 -9
- package/dist/public/{shadow-claw-control-plane-BBa7WbTg.js → shadow-claw-control-plane-UsBF-Nvd.js} +2 -2
- package/dist/public/{shadow-claw-conversations-CFaWFmkm.js → shadow-claw-conversations-Aoe61Y21.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-Z-GIKaE9.js → shadow-claw-file-viewer-D28dSSEn.js} +6 -6
- package/dist/public/{shadow-claw-files-BBx4iMsk.js → shadow-claw-files-CaDUlPEU.js} +1 -1
- package/dist/public/{shadow-claw-git-vTOKatwd.js → shadow-claw-git-DYNcZMWA.js} +2 -2
- package/dist/public/{shadow-claw-integrations-BBVnO0Fc.js → shadow-claw-integrations-BJf_hQVv.js} +1 -1
- package/dist/public/{shadow-claw-llm-Ce1Ax6-x.js → shadow-claw-llm-BqK2SIRf.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-Bkx0gsmF.js → shadow-claw-mcp-remote-B_dDG990.js} +1 -1
- package/dist/public/{shadow-claw-networking-q4XIzdB5.js → shadow-claw-networking-D8LxOofv.js} +1 -1
- package/dist/public/{shadow-claw-notifications-D2cz0gmm.js → shadow-claw-notifications-DpVyiNG_.js} +1 -1
- package/dist/public/{shadow-claw-page-header-BccSHItx.js → shadow-claw-page-header-DdC7bJuW.js} +1 -1
- package/dist/public/{shadow-claw-pages-3335lmSC.js → shadow-claw-pages-CYMl4J-6.js} +3 -3
- package/dist/public/{shadow-claw-settings-4ptYuJwO.js → shadow-claw-settings-Da_8Oy3O.js} +3 -3
- package/dist/public/{shadow-claw-storage-bIrPKFhF.js → shadow-claw-storage-DXIm86_-.js} +1 -1
- package/dist/public/{shadow-claw-task-server-5yqVBxy1.js → shadow-claw-task-server-BCceBD0G.js} +1 -1
- package/dist/public/{shadow-claw-tasks-DcqYHPLZ.js → shadow-claw-tasks-BW1QZ5L3.js} +19 -19
- package/dist/public/{shadow-claw-terminal-fARaDONr.js → shadow-claw-terminal-vqfsxhcK.js} +1 -1
- package/dist/public/{shadow-claw-tools-paEAhcJr.js → shadow-claw-tools-l0Jsa7UJ.js} +1 -1
- package/dist/public/{shadow-claw-webvm-CbzH_vyX.js → shadow-claw-webvm-CDPOWZm7.js} +1 -1
- package/dist/public/skills/main/skill-creator/SKILL.md +3 -2
- package/dist/public/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
- package/dist/public/static-main-manifest.json +2 -2
- package/dist/public/{syncWebMcpRegistration-CWSYaHex.js → syncWebMcpRegistration-5b5FkP9_.js} +1 -1
- package/dist/public/tools-B-PzsLc2.js +1 -0
- package/dist/public/{tools-C8x3nmo4.js → tools-CcgG5XuA.js} +1 -1
- package/dist/public/{tools-DvckJZG2.js → tools-VSOY66vs.js} +1 -1
- package/dist/public/{webmcp-DAjmliCx.js → webmcp-DBONjQWd.js} +1 -1
- package/dist/server.js +2 -2
- package/package.json +2 -2
- package/src/__mocks__/marked.cjs +14 -0
- package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +17 -0
- package/src/components/shadow-claw-chat/shadow-claw-chat.ts +5 -1
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +78 -0
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +6 -2
- package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +56 -0
- package/src/components/shadow-claw-tasks/shadow-claw-tasks.test.ts +22 -0
- package/src/components/shadow-claw-tasks/shadow-claw-tasks.ts +5 -1
- package/src/content/markdown-links.test.ts +109 -0
- package/src/content/markdown-links.ts +187 -0
- package/src/content/markdown.test.ts +33 -0
- package/src/content/markdown.ts +6 -1
- package/src/core/app-routes.test.ts +65 -0
- package/src/core/app-routes.ts +1 -1
- package/src/core/orchestrator/orchestrator.ts +3 -0
- package/src/core/orchestrator/utils/compactContext.ts +2 -0
- package/src/core/orchestrator/utils/invokeAgent.ts +1 -0
- package/src/subsystems/accounts/service-accounts.test.ts +0 -1
- package/src/subsystems/channels/peerjs.test.ts +479 -1
- package/src/subsystems/channels/peerjs.ts +420 -75
- package/src/subsystems/channels/room.test.ts +35 -0
- package/src/subsystems/channels/room.ts +15 -0
- package/src/subsystems/skills/activateSkill.test.ts +38 -5
- package/src/subsystems/skills/activateSkill.ts +25 -3
- package/src/subsystems/skills/parseSkill.test.ts +71 -0
- package/src/subsystems/skills/parseSkill.ts +185 -25
- package/src/subsystems/tools/files.ts +4 -4
- package/src/worker/tools/spawn-subagent/spawn-subagent.test.ts +22 -23
- package/src/worker/tools/workspace/send-file.test.ts +24 -1
- package/src/worker/tools/workspace/send-file.ts +6 -3
- package/src/worker/utils/handleCompact.test.ts +3 -4
- package/src/worker/utils/handleInvoke.test.ts +13 -11
- package/src/worker/utils/handleInvoke.ts +3 -0
- package/src/worker/utils/handleMessage.test.ts +0 -1
- package/src/worker/utils/post.test.ts +3 -4
- package/src/worker/utils/sandboxedEval.test.ts +1 -2
- package/src/worker/utils/system-prompt.test.ts +59 -0
- package/src/worker/utils/system-prompt.ts +21 -1
- package/src/worker/utils/withRetry.test.ts +3 -16
- package/dist/lib/app-routes-CqBOeA5q.js.map +0 -1
- package/dist/lib/markdown-DgdSt2GD.js.map +0 -1
- package/dist/lib/orchestrator-CjEau_RG.js.map +0 -1
- package/dist/lib/peerjs-BdfpltIe.js.map +0 -1
- package/dist/lib/shadow-claw-chat-mXPQZbwT.js.map +0 -1
- package/dist/lib/shadow-claw-file-viewer-BSbZvSl-.js.map +0 -1
- package/dist/lib/shadow-claw-tasks-qmcDT4PU.js.map +0 -1
- package/dist/lib/tools-D4Pp-nUw.js +0 -1
- package/dist/public/app-routes-Bs-riIvr.js +0 -1
- package/dist/public/orchestrator-BWkHHO9Y.js +0 -15
- package/dist/public/peerjs-tf2EmWjB.js +0 -1
- package/dist/public/tools-COduyYJ0.js +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-DZ8SGSJo.js";
|
|
2
2
|
import { t as Signal } from "./dist-Bxg3C_zy.js";
|
|
3
|
-
import { t as getGroupDir } from "./getGroupDir-
|
|
4
|
-
import { o as DEFAULT_GROUP_ID, r as CONFIG_KEYS } from "./config
|
|
3
|
+
import { t as getGroupDir } from "./getGroupDir-QrN2aTo8.js";
|
|
4
|
+
import { o as DEFAULT_GROUP_ID, r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
|
|
5
5
|
import { t as getConfig } from "./getConfig-BxxXMyuM.js";
|
|
6
6
|
import { t as parsePath } from "./parsePath-DwC_YZjw.js";
|
|
7
7
|
import { t as setConfig } from "./setConfig-BFED5CXn.js";
|
|
8
|
-
import { t as TOOL_DEFINITIONS } from "./tools-
|
|
9
|
-
import "./tools-
|
|
8
|
+
import { t as TOOL_DEFINITIONS } from "./tools-DKzPWc0q.js";
|
|
9
|
+
import "./tools-C3Kft940.js";
|
|
10
10
|
|
|
11
11
|
//#region src/storage/readGroupFile.ts
|
|
12
12
|
/**
|
|
@@ -543,4 +543,4 @@ const toolsStore = new ToolsStore();
|
|
|
543
543
|
|
|
544
544
|
//#endregion
|
|
545
545
|
export { DEFAULT_BUILTIN_PROFILE as a, loadDeclarativeTools as i, tools_exports as n, readGroupFile as o, findDeclarativeTool as r, toolsStore as t };
|
|
546
|
-
//# sourceMappingURL=tools-
|
|
546
|
+
//# sourceMappingURL=tools-DqcJe8LS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-DwwB9RBa.js","names":[],"sources":["../../src/storage/readGroupFile.ts","../../src/subsystems/tools/builtin-profiles.ts","../../src/subsystems/tools/declarative.ts","../../src/stores/tools.ts"],"sourcesContent":["import { getGroupDir } from \"./getGroupDir.js\";\nimport { parsePath } from \"./parsePath.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Read a file from a group's workspace.\n */\nexport async function readGroupFile(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<string> {\n const groupDir = await getGroupDir(db, groupId);\n const { dirs, filename } = parsePath(filePath);\n\n let dir = groupDir;\n for (const seg of dirs) {\n dir = await dir.getDirectoryHandle(seg);\n }\n\n // Re-acquire file handle and file object to force filesystem re-stat\n const fileHandle = await dir.getFileHandle(filename);\n\n try {\n const syncHandle = await (fileHandle as any).createSyncAccessHandle();\n const size = syncHandle.getSize();\n const buf = new Uint8Array(size);\n\n syncHandle.read(buf, { at: 0 });\n syncHandle.close();\n\n return new TextDecoder(\"utf-8\").decode(buf);\n } catch {\n // Not OPFS or not in a Worker — use File System Access API path\n const file = await fileHandle.getFile();\n\n return file.text();\n }\n}\n","import { ToolProfile } from \"./types.js\";\n\n/**\n * Built-in profile optimized for Gemini Nano (Prompt API).\n * Minimizes context consumption so Nano has maximum tokens for generation.\n */\nexport const DEFAULT_BUILTIN_PROFILE: ToolProfile = {\n id: \"__builtin_default\",\n name: \"Default\",\n providerId: \"prompt_api\",\n enabledToolNames: [\n \"javascript\",\n \"list_files\",\n \"open_file\",\n \"read_file\",\n \"write_file\",\n ],\n customTools: [],\n systemPromptOverride:\n \"You are a helpful coding assistant.\\n\" +\n \"Content intended to be rendered as a `Page` (HTML or Markdown) SHOULD include frontmatter (title, created, updated, and slug).\\n\" +\n \"HTML content intended to be rendered as a `Page` SHOULD USE `<article><h2>${subTitle}</h2>...</article>` for its main body content.\",\n};\n","import { CONFIG_KEYS, DEFAULT_GROUP_ID } from \"../../config/config.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { getGroupDir } from \"../../storage/getGroupDir.js\";\nimport { readGroupFile } from \"../../storage/readGroupFile.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/types.js\";\nimport type {\n DeclarativeToolDefinition,\n DeclarativeToolExecution,\n ToolDefinition,\n} from \"./types.js\";\n\nexport type { DeclarativeToolDefinition };\n\nconst TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;\n\nexport function parseDeclarativeTool(\n path: string,\n value: unknown,\n): DeclarativeToolDefinition {\n if (!value || typeof value !== \"object\") {\n throw new Error(`Tool at ${path} must be a JSON object`);\n }\n\n const candidate = value as Record<string, unknown>;\n const name = typeof candidate.name === \"string\" ? candidate.name.trim() : \"\";\n const description =\n typeof candidate.description === \"string\"\n ? candidate.description.trim()\n : \"\";\n const inputSchema = candidate.input_schema ?? candidate.parameters;\n const execution = candidate.execution ?? candidate.evaluation;\n\n if (!TOOL_NAME_PATTERN.test(name)) {\n throw new Error(`Tool name is invalid: ${name || \"(missing)\"}`);\n }\n if (!description) {\n throw new Error(`Tool ${name} requires a description`);\n }\n if (!inputSchema || typeof inputSchema !== \"object\") {\n throw new Error(`Tool ${name} requires input_schema`);\n }\n if (!execution || typeof execution !== \"object\") {\n throw new Error(`Tool ${name} requires execution`);\n }\n\n const parsedExecution = execution as Record<string, unknown>;\n const type = parsedExecution.type;\n if (type !== \"bash\" && type !== \"javascript\" && type !== \"tool\") {\n throw new Error(\n `Tool ${name} execution type must be bash, javascript, or tool`,\n );\n }\n if (type === \"tool\") {\n if (\n typeof parsedExecution.name !== \"string\" ||\n !TOOL_NAME_PATTERN.test(parsedExecution.name)\n ) {\n throw new Error(`Tool ${name} execution requires a valid tool name`);\n }\n\n return {\n name,\n description,\n input_schema: inputSchema as ToolDefinition[\"input_schema\"],\n execution: {\n type,\n name: parsedExecution.name,\n ...(parsedExecution.input && typeof parsedExecution.input === \"object\"\n ? { input: parsedExecution.input as Record<string, unknown> }\n : {}),\n },\n path,\n };\n }\n const sourceKey = type === \"bash\" ? \"command\" : \"code\";\n const source = parsedExecution[sourceKey] ?? parsedExecution.expression;\n if (typeof source !== \"string\" || source.trim() === \"\") {\n throw new Error(`Tool ${name} execution requires ${sourceKey}`);\n }\n\n return {\n name,\n description,\n input_schema: inputSchema as ToolDefinition[\"input_schema\"],\n execution: {\n type,\n [sourceKey]: source,\n } as DeclarativeToolExecution,\n path,\n };\n}\n\nexport async function loadDeclarativeTools(\n db: ShadowClawDatabase,\n groupId: string = DEFAULT_GROUP_ID,\n): Promise<{ tools: DeclarativeToolDefinition[]; diagnostics: string[] }> {\n const tools: DeclarativeToolDefinition[] = [];\n const diagnostics: string[] = [];\n\n const groupIdsToScan =\n groupId === DEFAULT_GROUP_ID\n ? [DEFAULT_GROUP_ID]\n : [groupId, DEFAULT_GROUP_ID];\n\n for (const targetGroupId of groupIdsToScan) {\n try {\n const root = await getGroupDir(db, targetGroupId);\n const paths: string[] = [];\n\n async function visit(\n directory: FileSystemDirectoryHandle,\n relativePath: string,\n ) {\n for await (const [name, handle] of (directory as any).entries()) {\n const childPath = `${relativePath}/${name}`;\n if (handle.kind === \"directory\") {\n await visit(handle, childPath);\n } else if (\n name.endsWith(\".json\") &&\n childPath.startsWith(\".agents/tools/\")\n ) {\n paths.push(childPath);\n }\n }\n }\n\n try {\n const agentsDir = await root.getDirectoryHandle(\".agents\");\n const toolsDir = await agentsDir.getDirectoryHandle(\"tools\");\n await visit(toolsDir, \".agents/tools\");\n } catch {\n continue;\n }\n\n for (const path of paths.sort()) {\n try {\n const parsed = JSON.parse(\n await readGroupFile(db, targetGroupId, path),\n );\n const parsedTool = parseDeclarativeTool(path, parsed);\n if (!tools.some((t) => t.name === parsedTool.name)) {\n tools.push(parsedTool);\n }\n } catch (error) {\n diagnostics.push(\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n } catch {\n // Continue to next group directory\n }\n }\n\n return { tools, diagnostics };\n}\n\nexport async function findDeclarativeTool(\n db: ShadowClawDatabase,\n groupId: string = DEFAULT_GROUP_ID,\n name: string,\n): Promise<DeclarativeToolDefinition | null> {\n try {\n const { tools } = await loadDeclarativeTools(db, groupId);\n const tool = tools.find((t) => t.name === name) || null;\n if (!tool) {\n return null;\n }\n\n const rawEnabled = await getConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n );\n if (Array.isArray(rawEnabled) && !rawEnabled.includes(name)) {\n return null;\n }\n\n return tool;\n } catch {\n return null;\n }\n}\n","import { Signal } from \"signal-polyfill\";\n\nimport { CONFIG_KEYS } from \"../config/config.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { setConfig } from \"../db/setConfig.js\";\nimport { TOOL_DEFINITIONS } from \"../subsystems/tools/tools.js\";\nimport { DEFAULT_BUILTIN_PROFILE } from \"../subsystems/tools/builtin-profiles.js\";\nimport { loadDeclarativeTools } from \"../subsystems/tools/declarative.js\";\nimport type { DeclarativeToolDefinition } from \"../subsystems/tools/declarative.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\nimport type { ToolDefinition, ToolProfile } from \"../subsystems/tools/tools.js\";\n\nexport class ToolsStore {\n private _activeProfile: Signal.Computed<ToolProfile | null>;\n private _activeProfileId: Signal.State<string | null>;\n private _allTools: Signal.Computed<ToolDefinition[]>;\n private _customTools: Signal.State<ToolDefinition[]>;\n private _declarativeTools: Signal.State<DeclarativeToolDefinition[]>;\n private _declarativeToolNamesEnabled: Signal.State<Set<string> | null>;\n private _enabledDeclarativeTools: Signal.Computed<\n DeclarativeToolDefinition[]\n >;\n private _enabledToolNames: Signal.State<Set<string>>;\n private _enabledTools: Signal.Computed<ToolDefinition[]>;\n private _profiles: Signal.State<ToolProfile[]>;\n private _systemPromptOverride: Signal.State<string>;\n private _webSearchProxyUrl: Signal.State<string>;\n private _webSearchUrl: Signal.State<string>;\n private _webSearchUseProxy: Signal.State<boolean>;\n private _searchFilesMaxFileBytes: Signal.State<number>;\n private _searchFilesMaxFilesVisited: Signal.State<number>;\n private _searchFilesSkipDirs: Signal.State<string>;\n\n constructor() {\n this._enabledToolNames = new Signal.State(\n new Set(DEFAULT_BUILTIN_PROFILE.enabledToolNames),\n );\n this._customTools = new Signal.State([]);\n this._declarativeTools = new Signal.State([]);\n this._declarativeToolNamesEnabled = new Signal.State<Set<string> | null>(\n null,\n );\n this._systemPromptOverride = new Signal.State(\"\");\n this._profiles = new Signal.State([]);\n this._activeProfileId = new Signal.State(DEFAULT_BUILTIN_PROFILE.id);\n this._webSearchUseProxy = new Signal.State(false);\n this._webSearchProxyUrl = new Signal.State(\"/proxy\");\n this._webSearchUrl = new Signal.State(\n \"https://html.duckduckgo.com/html/?q={query}\",\n );\n this._searchFilesMaxFileBytes = new Signal.State(512 * 1024);\n this._searchFilesMaxFilesVisited = new Signal.State(1000);\n this._searchFilesSkipDirs = new Signal.State(\n \".git,node_modules,dist,dist-electron,.cache,.nx,.turbo,__pycache__,.venv,venv\",\n );\n\n // Derived signals using Signal.Computed for proper reactive propagation.\n this._allTools = new Signal.Computed(() => [\n ...TOOL_DEFINITIONS,\n ...this._customTools.get(),\n ]);\n\n this._enabledTools = new Signal.Computed(() => {\n const enabled = this._enabledToolNames.get();\n\n return this._allTools\n .get()\n .filter((t: ToolDefinition) => enabled.has(t.name));\n });\n\n this._enabledDeclarativeTools = new Signal.Computed(() => {\n const tools = this._declarativeTools.get();\n const enabledSet = this._declarativeToolNamesEnabled.get();\n if (enabledSet === null) {\n return tools;\n }\n return tools.filter((t) => enabledSet.has(t.name));\n });\n\n this._activeProfile = new Signal.Computed(() => {\n const id = this._activeProfileId.get();\n if (!id) {\n return null;\n }\n\n if (DEFAULT_BUILTIN_PROFILE.id === id) {\n return DEFAULT_BUILTIN_PROFILE;\n }\n\n return this._profiles.get().find((p: ToolProfile) => p.id === id) || null;\n });\n }\n\n get activeProfile(): ToolProfile | null {\n return this._activeProfile.get();\n }\n\n get activeProfileId(): string | null {\n return this._activeProfileId.get();\n }\n\n get allTools(): ToolDefinition[] {\n return this._allTools.get();\n }\n\n get customTools(): ToolDefinition[] {\n return this._customTools.get();\n }\n\n get declarativeTools(): DeclarativeToolDefinition[] {\n return this._declarativeTools.get();\n }\n\n get declarativeToolNamesEnabled(): Set<string> | null {\n return this._declarativeToolNamesEnabled.get();\n }\n\n get enabledDeclarativeTools(): DeclarativeToolDefinition[] {\n return this._enabledDeclarativeTools.get();\n }\n\n get enabledToolNames(): Set<string> {\n return this._enabledToolNames.get();\n }\n\n get enabledTools(): ToolDefinition[] {\n return this._enabledTools.get();\n }\n\n isDeclarativeToolEnabled(name: string): boolean {\n const enabledSet = this._declarativeToolNamesEnabled.get();\n if (enabledSet === null) {\n return true;\n }\n return enabledSet.has(name);\n }\n\n async refreshDeclarativeTools(\n db: ShadowClawDatabase,\n groupId?: string,\n ): Promise<DeclarativeToolDefinition[]> {\n try {\n const res = await loadDeclarativeTools(db, groupId || \"br:main\");\n const allBuiltInAndCustom = this.allTools;\n const declTools = (res?.tools || []).filter(\n (dt) => !allBuiltInAndCustom.some((bt) => bt.name === dt.name),\n );\n\n const current = this._declarativeTools.get();\n const isSame =\n current.length === declTools.length &&\n current.every(\n (t, i) =>\n t.name === declTools[i].name &&\n t.description === declTools[i].description &&\n JSON.stringify(t.execution) ===\n JSON.stringify(declTools[i].execution),\n );\n\n if (!isSame) {\n this._declarativeTools.set(declTools);\n }\n return declTools;\n } catch {\n if (this._declarativeTools.get().length > 0) {\n this._declarativeTools.set([]);\n }\n return [];\n }\n }\n\n async setDeclarativeToolEnabled(\n db: ShadowClawDatabase,\n toolName: string,\n enabled: boolean,\n ): Promise<void> {\n const currentEnabled = this._declarativeToolNamesEnabled.get();\n const allDeclTools = this._declarativeTools.get();\n const nextSet = new Set(\n currentEnabled === null\n ? allDeclTools.map((t) => t.name)\n : currentEnabled,\n );\n if (enabled) {\n nextSet.add(toolName);\n } else {\n nextSet.delete(toolName);\n }\n this._declarativeToolNamesEnabled.set(nextSet);\n await setConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n Array.from(nextSet),\n );\n }\n\n async setAllDeclarativeEnabled(\n db: ShadowClawDatabase,\n toolNames: string[],\n ): Promise<void> {\n const nextSet = new Set(toolNames);\n this._declarativeToolNamesEnabled.set(nextSet);\n await setConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED, toolNames);\n }\n\n /**\n * Export tools config as JSON for backup.\n */\n exportBackup(): string {\n return JSON.stringify(\n {\n enabledTools: [...this._enabledToolNames.get()],\n customTools: this._customTools.get(),\n declarativeToolsEnabled: this._declarativeToolNamesEnabled.get()\n ? Array.from(this._declarativeToolNamesEnabled.get()!)\n : null,\n systemPromptOverride: this._systemPromptOverride.get(),\n profiles: this._profiles.get(),\n activeProfileId: this._activeProfileId.get(),\n webSearchUseProxy: this._webSearchUseProxy.get(),\n webSearchProxyUrl: this._webSearchProxyUrl.get(),\n webSearchUrl: this._webSearchUrl.get(),\n searchFilesMaxFileBytes: this._searchFilesMaxFileBytes.get(),\n searchFilesMaxFilesVisited: this._searchFilesMaxFilesVisited.get(),\n searchFilesSkipDirs: this._searchFilesSkipDirs.get(),\n },\n null,\n 2,\n );\n }\n\n findProfilesForProvider(providerId?: string, model?: string): ToolProfile[] {\n return this.profiles.filter((p) => {\n if (p.providerId && p.providerId !== providerId) {\n return false;\n }\n\n if (p.model && p.model !== model) {\n return false;\n }\n\n return true;\n });\n }\n\n get profiles(): ToolProfile[] {\n return [DEFAULT_BUILTIN_PROFILE, ...this._profiles.get()];\n }\n\n get systemPromptOverride(): string {\n return this._systemPromptOverride.get();\n }\n\n get webSearchProxyUrl(): string {\n return this._webSearchProxyUrl.get();\n }\n\n get webSearchUrl(): string {\n return this._webSearchUrl.get();\n }\n\n get webSearchUseProxy(): boolean {\n return this._webSearchUseProxy.get();\n }\n\n get searchFilesMaxFileBytes(): number {\n return this._searchFilesMaxFileBytes.get();\n }\n\n get searchFilesMaxFilesVisited(): number {\n return this._searchFilesMaxFilesVisited.get();\n }\n\n /** Comma-separated list of directory names to skip when walking the workspace. */\n get searchFilesSkipDirs(): string {\n return this._searchFilesSkipDirs.get();\n }\n\n /** Parsed Set of directory names to skip — derived from the comma-separated string. */\n get searchFilesSkipDirsSet(): Set<string> {\n return new Set(\n this._searchFilesSkipDirs\n .get()\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n );\n }\n\n async activateProfile(\n db: ShadowClawDatabase,\n profileId: string,\n ): Promise<void> {\n const profile = this.profiles.find((p) => p.id === profileId);\n if (!profile) {\n return;\n }\n\n this._activeProfileId.set(profileId);\n this._enabledToolNames.set(new Set(profile.enabledToolNames));\n this._customTools.set(profile.customTools);\n this._systemPromptOverride.set(profile.systemPromptOverride || \"\");\n\n await Promise.all([\n setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, profileId),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, profile.enabledToolNames),\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, profile.customTools),\n setConfig(\n db,\n CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE,\n profile.systemPromptOverride || \"\",\n ),\n ]);\n }\n\n async addCustomTool(\n db: ShadowClawDatabase,\n tool: ToolDefinition,\n ): Promise<void> {\n const tools = [...this._customTools.get(), tool];\n this._customTools.set(tools);\n // Auto-enable new tool\n const enabled = new Set(this._enabledToolNames.get());\n enabled.add(tool.name);\n this._enabledToolNames.set(enabled);\n await Promise.all([\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, tools),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...enabled]),\n ]);\n }\n\n // ── Profile Management ───────────────────────────────────────────\n\n async addProfile(\n db: ShadowClawDatabase,\n profile: ToolProfile,\n ): Promise<void> {\n const profiles = [...this._profiles.get(), profile];\n this._profiles.set(profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n\n async cloneTool(\n db: ShadowClawDatabase,\n sourceToolName: string,\n newToolName: string,\n newDescription?: string,\n ): Promise<boolean> {\n const source = this.allTools.find((t) => t.name === sourceToolName);\n if (!source) {\n return false;\n }\n\n if (this.allTools.some((t) => t.name === newToolName)) {\n return false;\n }\n\n const cloned: ToolDefinition = {\n name: newToolName,\n description: newDescription || source.description,\n input_schema: JSON.parse(JSON.stringify(source.input_schema)),\n };\n\n await this.addCustomTool(db, cloned);\n\n return true;\n }\n\n async deactivateProfile(db: ShadowClawDatabase): Promise<void> {\n this._activeProfileId.set(null);\n await setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null);\n }\n\n async deleteProfile(\n db: ShadowClawDatabase,\n profileId: string,\n ): Promise<void> {\n if (profileId === DEFAULT_BUILTIN_PROFILE.id) {\n return;\n }\n\n const profiles = this._profiles.get().filter((p) => p.id !== profileId);\n this._profiles.set(profiles);\n if (this._activeProfileId.get() === profileId) {\n this._activeProfileId.set(null);\n await setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null);\n }\n\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n\n async importBackup(db: ShadowClawDatabase, json: string): Promise<void> {\n const data = JSON.parse(json);\n if (Array.isArray(data.enabledTools)) {\n this._enabledToolNames.set(new Set(data.enabledTools));\n await setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, data.enabledTools);\n }\n\n if (Array.isArray(data.customTools)) {\n this._customTools.set(data.customTools);\n await setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, data.customTools);\n }\n\n if (typeof data.systemPromptOverride === \"string\") {\n this._systemPromptOverride.set(data.systemPromptOverride);\n await setConfig(\n db,\n CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE,\n data.systemPromptOverride,\n );\n }\n\n if (Array.isArray(data.profiles)) {\n this._profiles.set(data.profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, data.profiles);\n }\n\n if (\n typeof data.activeProfileId === \"string\" ||\n data.activeProfileId === null\n ) {\n this._activeProfileId.set(data.activeProfileId);\n await setConfig(\n db,\n CONFIG_KEYS.ACTIVE_TOOL_PROFILE,\n data.activeProfileId,\n );\n }\n\n if (typeof data.webSearchUseProxy === \"boolean\") {\n this._webSearchUseProxy.set(data.webSearchUseProxy);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_USE_PROXY,\n data.webSearchUseProxy ? \"true\" : \"false\",\n );\n }\n\n if (typeof data.webSearchProxyUrl === \"string\") {\n this._webSearchProxyUrl.set(data.webSearchProxyUrl);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_PROXY_URL,\n data.webSearchProxyUrl,\n );\n }\n\n if (typeof data.webSearchUrl === \"string\") {\n this._webSearchUrl.set(data.webSearchUrl);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_URL, data.webSearchUrl);\n }\n\n if (\n typeof data.searchFilesMaxFileBytes === \"number\" &&\n data.searchFilesMaxFileBytes > 0\n ) {\n this._searchFilesMaxFileBytes.set(data.searchFilesMaxFileBytes);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES,\n String(data.searchFilesMaxFileBytes),\n );\n }\n\n if (\n typeof data.searchFilesMaxFilesVisited === \"number\" &&\n data.searchFilesMaxFilesVisited > 0\n ) {\n this._searchFilesMaxFilesVisited.set(data.searchFilesMaxFilesVisited);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED,\n String(data.searchFilesMaxFilesVisited),\n );\n }\n\n if (typeof data.searchFilesSkipDirs === \"string\") {\n this._searchFilesSkipDirs.set(data.searchFilesSkipDirs);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS,\n data.searchFilesSkipDirs,\n );\n }\n\n if (Array.isArray(data.declarativeToolsEnabled)) {\n this._declarativeToolNamesEnabled.set(\n new Set(data.declarativeToolsEnabled),\n );\n await setConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n data.declarativeToolsEnabled,\n );\n } else if (data.declarativeToolsEnabled === null) {\n this._declarativeToolNamesEnabled.set(null);\n await setConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED, null);\n }\n }\n\n /**\n * Load persisted tool config from IndexedDB.\n */\n async load(db: ShadowClawDatabase): Promise<void> {\n const [\n enabledRaw,\n customRaw,\n promptOverride,\n profilesRaw,\n activeProfileIdRaw,\n webSearchUseProxyRaw,\n webSearchProxyUrlRaw,\n webSearchUrlRaw,\n searchFilesMaxFileBytesRaw,\n searchFilesMaxFilesVisitedRaw,\n searchFilesSkipDirsRaw,\n declarativeEnabledRaw,\n ] = await Promise.all([\n getConfig(db, CONFIG_KEYS.ENABLED_TOOLS),\n getConfig(db, CONFIG_KEYS.CUSTOM_TOOLS),\n getConfig(db, CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE),\n getConfig(db, CONFIG_KEYS.TOOL_PROFILES),\n getConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_USE_PROXY),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_PROXY_URL),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_URL),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS),\n getConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED),\n ]);\n\n if (Array.isArray(enabledRaw)) {\n this._enabledToolNames.set(new Set(enabledRaw));\n }\n\n if (Array.isArray(customRaw)) {\n this._customTools.set(customRaw);\n }\n\n if (Array.isArray(declarativeEnabledRaw)) {\n this._declarativeToolNamesEnabled.set(new Set(declarativeEnabledRaw));\n }\n\n if (typeof promptOverride === \"string\") {\n this._systemPromptOverride.set(promptOverride);\n }\n\n if (Array.isArray(profilesRaw)) {\n this._profiles.set(profilesRaw);\n }\n\n if (typeof activeProfileIdRaw === \"string\") {\n this._activeProfileId.set(activeProfileIdRaw);\n }\n\n if (webSearchUseProxyRaw !== null && webSearchUseProxyRaw !== undefined) {\n const strVal = String(webSearchUseProxyRaw).toLowerCase();\n this._webSearchUseProxy.set(strVal === \"true\" || strVal === \"1\");\n }\n\n if (\n typeof webSearchProxyUrlRaw === \"string\" &&\n webSearchProxyUrlRaw.trim().length > 0\n ) {\n this._webSearchProxyUrl.set(webSearchProxyUrlRaw.trim());\n }\n\n if (\n typeof webSearchUrlRaw === \"string\" &&\n webSearchUrlRaw.trim().length > 0\n ) {\n this._webSearchUrl.set(webSearchUrlRaw.trim());\n }\n\n if (\n searchFilesMaxFileBytesRaw !== null &&\n searchFilesMaxFileBytesRaw !== undefined\n ) {\n const n = Number(searchFilesMaxFileBytesRaw);\n if (Number.isFinite(n) && n > 0) {\n this._searchFilesMaxFileBytes.set(n);\n }\n }\n\n if (\n searchFilesMaxFilesVisitedRaw !== null &&\n searchFilesMaxFilesVisitedRaw !== undefined\n ) {\n const n = Number(searchFilesMaxFilesVisitedRaw);\n if (Number.isFinite(n) && n > 0) {\n this._searchFilesMaxFilesVisited.set(n);\n }\n }\n\n if (\n typeof searchFilesSkipDirsRaw === \"string\" &&\n searchFilesSkipDirsRaw.trim().length > 0\n ) {\n this._searchFilesSkipDirs.set(searchFilesSkipDirsRaw.trim());\n }\n }\n\n async setWebSearchProxyUrl(\n db: ShadowClawDatabase,\n proxyUrl: string,\n ): Promise<void> {\n const trimmed = proxyUrl.trim() || \"/proxy\";\n this._webSearchProxyUrl.set(trimmed);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_PROXY_URL, trimmed);\n }\n\n async setWebSearchUrl(db: ShadowClawDatabase, url: string): Promise<void> {\n const trimmed = url.trim() || \"https://html.duckduckgo.com/html/?q={query}\";\n this._webSearchUrl.set(trimmed);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_URL, trimmed);\n }\n\n async setWebSearchUseProxy(\n db: ShadowClawDatabase,\n useProxy: boolean,\n ): Promise<void> {\n const enabled = !!useProxy;\n this._webSearchUseProxy.set(enabled);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_USE_PROXY,\n enabled ? \"true\" : \"false\",\n );\n }\n\n async setSearchFilesMaxFileBytes(\n db: ShadowClawDatabase,\n bytes: number,\n ): Promise<void> {\n const clamped = Math.max(1, Math.round(bytes));\n this._searchFilesMaxFileBytes.set(clamped);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES,\n String(clamped),\n );\n }\n\n async setSearchFilesMaxFilesVisited(\n db: ShadowClawDatabase,\n count: number,\n ): Promise<void> {\n const clamped = Math.max(1, Math.round(count));\n this._searchFilesMaxFilesVisited.set(clamped);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED,\n String(clamped),\n );\n }\n\n async setSearchFilesSkipDirs(\n db: ShadowClawDatabase,\n dirs: string,\n ): Promise<void> {\n const trimmed = dirs.trim();\n this._searchFilesSkipDirs.set(trimmed);\n await setConfig(db, CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS, trimmed);\n }\n\n async removeCustomTool(\n db: ShadowClawDatabase,\n toolName: string,\n ): Promise<void> {\n const tools = this._customTools.get().filter((t) => t.name !== toolName);\n this._customTools.set(tools);\n const enabled = new Set(this._enabledToolNames.get());\n enabled.delete(toolName);\n this._enabledToolNames.set(enabled);\n await Promise.all([\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, tools),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...enabled]),\n ]);\n }\n\n async saveToActiveProfile(db: ShadowClawDatabase): Promise<void> {\n const id = this._activeProfileId.get();\n if (!id) {\n return;\n }\n\n const profile = this._profiles.get().find((p) => p.id === id);\n if (!profile) {\n return;\n }\n\n const updated = {\n ...profile,\n enabledToolNames: [...this._enabledToolNames.get()],\n customTools: [...this._customTools.get()],\n systemPromptOverride: this._systemPromptOverride.get(),\n };\n await this.updateProfile(db, updated);\n }\n\n async setAllEnabled(\n db: ShadowClawDatabase,\n toolNames: string[],\n ): Promise<void> {\n this._enabledToolNames.set(new Set(toolNames));\n\n const saves = [setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, toolNames)];\n if (this._activeProfileId.get()) {\n this._activeProfileId.set(null);\n saves.push(setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null));\n }\n\n await Promise.all(saves);\n }\n\n async setSystemPromptOverride(\n db: ShadowClawDatabase,\n override: string,\n ): Promise<void> {\n this._systemPromptOverride.set(override);\n await setConfig(db, CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE, override);\n }\n\n async setToolEnabled(\n db: ShadowClawDatabase,\n toolName: string,\n enabled: boolean,\n ): Promise<void> {\n const current = new Set(this._enabledToolNames.get());\n if (enabled) {\n current.add(toolName);\n } else {\n current.delete(toolName);\n }\n\n this._enabledToolNames.set(current);\n\n const saves = [setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...current])];\n if (this._activeProfileId.get()) {\n this._activeProfileId.set(null);\n saves.push(setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null));\n }\n\n await Promise.all(saves);\n }\n\n async updateProfile(\n db: ShadowClawDatabase,\n profile: ToolProfile,\n ): Promise<void> {\n const profiles = this._profiles\n .get()\n .map((p) => (p.id === profile.id ? profile : p));\n this._profiles.set(profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n}\n\nexport const toolsStore = new ToolsStore();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tools-DqcJe8LS.js","names":[],"sources":["../../src/storage/readGroupFile.ts","../../src/subsystems/tools/builtin-profiles.ts","../../src/subsystems/tools/declarative.ts","../../src/stores/tools.ts"],"sourcesContent":["import { getGroupDir } from \"./getGroupDir.js\";\nimport { parsePath } from \"./parsePath.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Read a file from a group's workspace.\n */\nexport async function readGroupFile(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<string> {\n const groupDir = await getGroupDir(db, groupId);\n const { dirs, filename } = parsePath(filePath);\n\n let dir = groupDir;\n for (const seg of dirs) {\n dir = await dir.getDirectoryHandle(seg);\n }\n\n // Re-acquire file handle and file object to force filesystem re-stat\n const fileHandle = await dir.getFileHandle(filename);\n\n try {\n const syncHandle = await (fileHandle as any).createSyncAccessHandle();\n const size = syncHandle.getSize();\n const buf = new Uint8Array(size);\n\n syncHandle.read(buf, { at: 0 });\n syncHandle.close();\n\n return new TextDecoder(\"utf-8\").decode(buf);\n } catch {\n // Not OPFS or not in a Worker — use File System Access API path\n const file = await fileHandle.getFile();\n\n return file.text();\n }\n}\n","import { ToolProfile } from \"./types.js\";\n\n/**\n * Built-in profile optimized for Gemini Nano (Prompt API).\n * Minimizes context consumption so Nano has maximum tokens for generation.\n */\nexport const DEFAULT_BUILTIN_PROFILE: ToolProfile = {\n id: \"__builtin_default\",\n name: \"Default\",\n providerId: \"prompt_api\",\n enabledToolNames: [\n \"javascript\",\n \"list_files\",\n \"open_file\",\n \"read_file\",\n \"write_file\",\n ],\n customTools: [],\n systemPromptOverride:\n \"You are a helpful coding assistant.\\n\" +\n \"Content intended to be rendered as a `Page` (HTML or Markdown) SHOULD include frontmatter (title, created, updated, and slug).\\n\" +\n \"HTML content intended to be rendered as a `Page` SHOULD USE `<article><h2>${subTitle}</h2>...</article>` for its main body content.\",\n};\n","import { CONFIG_KEYS, DEFAULT_GROUP_ID } from \"../../config/config.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { getGroupDir } from \"../../storage/getGroupDir.js\";\nimport { readGroupFile } from \"../../storage/readGroupFile.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/types.js\";\nimport type {\n DeclarativeToolDefinition,\n DeclarativeToolExecution,\n ToolDefinition,\n} from \"./types.js\";\n\nexport type { DeclarativeToolDefinition };\n\nconst TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;\n\nexport function parseDeclarativeTool(\n path: string,\n value: unknown,\n): DeclarativeToolDefinition {\n if (!value || typeof value !== \"object\") {\n throw new Error(`Tool at ${path} must be a JSON object`);\n }\n\n const candidate = value as Record<string, unknown>;\n const name = typeof candidate.name === \"string\" ? candidate.name.trim() : \"\";\n const description =\n typeof candidate.description === \"string\"\n ? candidate.description.trim()\n : \"\";\n const inputSchema = candidate.input_schema ?? candidate.parameters;\n const execution = candidate.execution ?? candidate.evaluation;\n\n if (!TOOL_NAME_PATTERN.test(name)) {\n throw new Error(`Tool name is invalid: ${name || \"(missing)\"}`);\n }\n if (!description) {\n throw new Error(`Tool ${name} requires a description`);\n }\n if (!inputSchema || typeof inputSchema !== \"object\") {\n throw new Error(`Tool ${name} requires input_schema`);\n }\n if (!execution || typeof execution !== \"object\") {\n throw new Error(`Tool ${name} requires execution`);\n }\n\n const parsedExecution = execution as Record<string, unknown>;\n const type = parsedExecution.type;\n if (type !== \"bash\" && type !== \"javascript\" && type !== \"tool\") {\n throw new Error(\n `Tool ${name} execution type must be bash, javascript, or tool`,\n );\n }\n if (type === \"tool\") {\n if (\n typeof parsedExecution.name !== \"string\" ||\n !TOOL_NAME_PATTERN.test(parsedExecution.name)\n ) {\n throw new Error(`Tool ${name} execution requires a valid tool name`);\n }\n\n return {\n name,\n description,\n input_schema: inputSchema as ToolDefinition[\"input_schema\"],\n execution: {\n type,\n name: parsedExecution.name,\n ...(parsedExecution.input && typeof parsedExecution.input === \"object\"\n ? { input: parsedExecution.input as Record<string, unknown> }\n : {}),\n },\n path,\n };\n }\n const sourceKey = type === \"bash\" ? \"command\" : \"code\";\n const source = parsedExecution[sourceKey] ?? parsedExecution.expression;\n if (typeof source !== \"string\" || source.trim() === \"\") {\n throw new Error(`Tool ${name} execution requires ${sourceKey}`);\n }\n\n return {\n name,\n description,\n input_schema: inputSchema as ToolDefinition[\"input_schema\"],\n execution: {\n type,\n [sourceKey]: source,\n } as DeclarativeToolExecution,\n path,\n };\n}\n\nexport async function loadDeclarativeTools(\n db: ShadowClawDatabase,\n groupId: string = DEFAULT_GROUP_ID,\n): Promise<{ tools: DeclarativeToolDefinition[]; diagnostics: string[] }> {\n const tools: DeclarativeToolDefinition[] = [];\n const diagnostics: string[] = [];\n\n const groupIdsToScan =\n groupId === DEFAULT_GROUP_ID\n ? [DEFAULT_GROUP_ID]\n : [groupId, DEFAULT_GROUP_ID];\n\n for (const targetGroupId of groupIdsToScan) {\n try {\n const root = await getGroupDir(db, targetGroupId);\n const paths: string[] = [];\n\n async function visit(\n directory: FileSystemDirectoryHandle,\n relativePath: string,\n ) {\n for await (const [name, handle] of (directory as any).entries()) {\n const childPath = `${relativePath}/${name}`;\n if (handle.kind === \"directory\") {\n await visit(handle, childPath);\n } else if (\n name.endsWith(\".json\") &&\n childPath.startsWith(\".agents/tools/\")\n ) {\n paths.push(childPath);\n }\n }\n }\n\n try {\n const agentsDir = await root.getDirectoryHandle(\".agents\");\n const toolsDir = await agentsDir.getDirectoryHandle(\"tools\");\n await visit(toolsDir, \".agents/tools\");\n } catch {\n continue;\n }\n\n for (const path of paths.sort()) {\n try {\n const parsed = JSON.parse(\n await readGroupFile(db, targetGroupId, path),\n );\n const parsedTool = parseDeclarativeTool(path, parsed);\n if (!tools.some((t) => t.name === parsedTool.name)) {\n tools.push(parsedTool);\n }\n } catch (error) {\n diagnostics.push(\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n } catch {\n // Continue to next group directory\n }\n }\n\n return { tools, diagnostics };\n}\n\nexport async function findDeclarativeTool(\n db: ShadowClawDatabase,\n groupId: string = DEFAULT_GROUP_ID,\n name: string,\n): Promise<DeclarativeToolDefinition | null> {\n try {\n const { tools } = await loadDeclarativeTools(db, groupId);\n const tool = tools.find((t) => t.name === name) || null;\n if (!tool) {\n return null;\n }\n\n const rawEnabled = await getConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n );\n if (Array.isArray(rawEnabled) && !rawEnabled.includes(name)) {\n return null;\n }\n\n return tool;\n } catch {\n return null;\n }\n}\n","import { Signal } from \"signal-polyfill\";\n\nimport { CONFIG_KEYS } from \"../config/config.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { setConfig } from \"../db/setConfig.js\";\nimport { TOOL_DEFINITIONS } from \"../subsystems/tools/tools.js\";\nimport { DEFAULT_BUILTIN_PROFILE } from \"../subsystems/tools/builtin-profiles.js\";\nimport { loadDeclarativeTools } from \"../subsystems/tools/declarative.js\";\nimport type { DeclarativeToolDefinition } from \"../subsystems/tools/declarative.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\nimport type { ToolDefinition, ToolProfile } from \"../subsystems/tools/tools.js\";\n\nexport class ToolsStore {\n private _activeProfile: Signal.Computed<ToolProfile | null>;\n private _activeProfileId: Signal.State<string | null>;\n private _allTools: Signal.Computed<ToolDefinition[]>;\n private _customTools: Signal.State<ToolDefinition[]>;\n private _declarativeTools: Signal.State<DeclarativeToolDefinition[]>;\n private _declarativeToolNamesEnabled: Signal.State<Set<string> | null>;\n private _enabledDeclarativeTools: Signal.Computed<\n DeclarativeToolDefinition[]\n >;\n private _enabledToolNames: Signal.State<Set<string>>;\n private _enabledTools: Signal.Computed<ToolDefinition[]>;\n private _profiles: Signal.State<ToolProfile[]>;\n private _systemPromptOverride: Signal.State<string>;\n private _webSearchProxyUrl: Signal.State<string>;\n private _webSearchUrl: Signal.State<string>;\n private _webSearchUseProxy: Signal.State<boolean>;\n private _searchFilesMaxFileBytes: Signal.State<number>;\n private _searchFilesMaxFilesVisited: Signal.State<number>;\n private _searchFilesSkipDirs: Signal.State<string>;\n\n constructor() {\n this._enabledToolNames = new Signal.State(\n new Set(DEFAULT_BUILTIN_PROFILE.enabledToolNames),\n );\n this._customTools = new Signal.State([]);\n this._declarativeTools = new Signal.State([]);\n this._declarativeToolNamesEnabled = new Signal.State<Set<string> | null>(\n null,\n );\n this._systemPromptOverride = new Signal.State(\"\");\n this._profiles = new Signal.State([]);\n this._activeProfileId = new Signal.State(DEFAULT_BUILTIN_PROFILE.id);\n this._webSearchUseProxy = new Signal.State(false);\n this._webSearchProxyUrl = new Signal.State(\"/proxy\");\n this._webSearchUrl = new Signal.State(\n \"https://html.duckduckgo.com/html/?q={query}\",\n );\n this._searchFilesMaxFileBytes = new Signal.State(512 * 1024);\n this._searchFilesMaxFilesVisited = new Signal.State(1000);\n this._searchFilesSkipDirs = new Signal.State(\n \".git,node_modules,dist,dist-electron,.cache,.nx,.turbo,__pycache__,.venv,venv\",\n );\n\n // Derived signals using Signal.Computed for proper reactive propagation.\n this._allTools = new Signal.Computed(() => [\n ...TOOL_DEFINITIONS,\n ...this._customTools.get(),\n ]);\n\n this._enabledTools = new Signal.Computed(() => {\n const enabled = this._enabledToolNames.get();\n\n return this._allTools\n .get()\n .filter((t: ToolDefinition) => enabled.has(t.name));\n });\n\n this._enabledDeclarativeTools = new Signal.Computed(() => {\n const tools = this._declarativeTools.get();\n const enabledSet = this._declarativeToolNamesEnabled.get();\n if (enabledSet === null) {\n return tools;\n }\n return tools.filter((t) => enabledSet.has(t.name));\n });\n\n this._activeProfile = new Signal.Computed(() => {\n const id = this._activeProfileId.get();\n if (!id) {\n return null;\n }\n\n if (DEFAULT_BUILTIN_PROFILE.id === id) {\n return DEFAULT_BUILTIN_PROFILE;\n }\n\n return this._profiles.get().find((p: ToolProfile) => p.id === id) || null;\n });\n }\n\n get activeProfile(): ToolProfile | null {\n return this._activeProfile.get();\n }\n\n get activeProfileId(): string | null {\n return this._activeProfileId.get();\n }\n\n get allTools(): ToolDefinition[] {\n return this._allTools.get();\n }\n\n get customTools(): ToolDefinition[] {\n return this._customTools.get();\n }\n\n get declarativeTools(): DeclarativeToolDefinition[] {\n return this._declarativeTools.get();\n }\n\n get declarativeToolNamesEnabled(): Set<string> | null {\n return this._declarativeToolNamesEnabled.get();\n }\n\n get enabledDeclarativeTools(): DeclarativeToolDefinition[] {\n return this._enabledDeclarativeTools.get();\n }\n\n get enabledToolNames(): Set<string> {\n return this._enabledToolNames.get();\n }\n\n get enabledTools(): ToolDefinition[] {\n return this._enabledTools.get();\n }\n\n isDeclarativeToolEnabled(name: string): boolean {\n const enabledSet = this._declarativeToolNamesEnabled.get();\n if (enabledSet === null) {\n return true;\n }\n return enabledSet.has(name);\n }\n\n async refreshDeclarativeTools(\n db: ShadowClawDatabase,\n groupId?: string,\n ): Promise<DeclarativeToolDefinition[]> {\n try {\n const res = await loadDeclarativeTools(db, groupId || \"br:main\");\n const allBuiltInAndCustom = this.allTools;\n const declTools = (res?.tools || []).filter(\n (dt) => !allBuiltInAndCustom.some((bt) => bt.name === dt.name),\n );\n\n const current = this._declarativeTools.get();\n const isSame =\n current.length === declTools.length &&\n current.every(\n (t, i) =>\n t.name === declTools[i].name &&\n t.description === declTools[i].description &&\n JSON.stringify(t.execution) ===\n JSON.stringify(declTools[i].execution),\n );\n\n if (!isSame) {\n this._declarativeTools.set(declTools);\n }\n return declTools;\n } catch {\n if (this._declarativeTools.get().length > 0) {\n this._declarativeTools.set([]);\n }\n return [];\n }\n }\n\n async setDeclarativeToolEnabled(\n db: ShadowClawDatabase,\n toolName: string,\n enabled: boolean,\n ): Promise<void> {\n const currentEnabled = this._declarativeToolNamesEnabled.get();\n const allDeclTools = this._declarativeTools.get();\n const nextSet = new Set(\n currentEnabled === null\n ? allDeclTools.map((t) => t.name)\n : currentEnabled,\n );\n if (enabled) {\n nextSet.add(toolName);\n } else {\n nextSet.delete(toolName);\n }\n this._declarativeToolNamesEnabled.set(nextSet);\n await setConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n Array.from(nextSet),\n );\n }\n\n async setAllDeclarativeEnabled(\n db: ShadowClawDatabase,\n toolNames: string[],\n ): Promise<void> {\n const nextSet = new Set(toolNames);\n this._declarativeToolNamesEnabled.set(nextSet);\n await setConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED, toolNames);\n }\n\n /**\n * Export tools config as JSON for backup.\n */\n exportBackup(): string {\n return JSON.stringify(\n {\n enabledTools: [...this._enabledToolNames.get()],\n customTools: this._customTools.get(),\n declarativeToolsEnabled: this._declarativeToolNamesEnabled.get()\n ? Array.from(this._declarativeToolNamesEnabled.get()!)\n : null,\n systemPromptOverride: this._systemPromptOverride.get(),\n profiles: this._profiles.get(),\n activeProfileId: this._activeProfileId.get(),\n webSearchUseProxy: this._webSearchUseProxy.get(),\n webSearchProxyUrl: this._webSearchProxyUrl.get(),\n webSearchUrl: this._webSearchUrl.get(),\n searchFilesMaxFileBytes: this._searchFilesMaxFileBytes.get(),\n searchFilesMaxFilesVisited: this._searchFilesMaxFilesVisited.get(),\n searchFilesSkipDirs: this._searchFilesSkipDirs.get(),\n },\n null,\n 2,\n );\n }\n\n findProfilesForProvider(providerId?: string, model?: string): ToolProfile[] {\n return this.profiles.filter((p) => {\n if (p.providerId && p.providerId !== providerId) {\n return false;\n }\n\n if (p.model && p.model !== model) {\n return false;\n }\n\n return true;\n });\n }\n\n get profiles(): ToolProfile[] {\n return [DEFAULT_BUILTIN_PROFILE, ...this._profiles.get()];\n }\n\n get systemPromptOverride(): string {\n return this._systemPromptOverride.get();\n }\n\n get webSearchProxyUrl(): string {\n return this._webSearchProxyUrl.get();\n }\n\n get webSearchUrl(): string {\n return this._webSearchUrl.get();\n }\n\n get webSearchUseProxy(): boolean {\n return this._webSearchUseProxy.get();\n }\n\n get searchFilesMaxFileBytes(): number {\n return this._searchFilesMaxFileBytes.get();\n }\n\n get searchFilesMaxFilesVisited(): number {\n return this._searchFilesMaxFilesVisited.get();\n }\n\n /** Comma-separated list of directory names to skip when walking the workspace. */\n get searchFilesSkipDirs(): string {\n return this._searchFilesSkipDirs.get();\n }\n\n /** Parsed Set of directory names to skip — derived from the comma-separated string. */\n get searchFilesSkipDirsSet(): Set<string> {\n return new Set(\n this._searchFilesSkipDirs\n .get()\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n );\n }\n\n async activateProfile(\n db: ShadowClawDatabase,\n profileId: string,\n ): Promise<void> {\n const profile = this.profiles.find((p) => p.id === profileId);\n if (!profile) {\n return;\n }\n\n this._activeProfileId.set(profileId);\n this._enabledToolNames.set(new Set(profile.enabledToolNames));\n this._customTools.set(profile.customTools);\n this._systemPromptOverride.set(profile.systemPromptOverride || \"\");\n\n await Promise.all([\n setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, profileId),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, profile.enabledToolNames),\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, profile.customTools),\n setConfig(\n db,\n CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE,\n profile.systemPromptOverride || \"\",\n ),\n ]);\n }\n\n async addCustomTool(\n db: ShadowClawDatabase,\n tool: ToolDefinition,\n ): Promise<void> {\n const tools = [...this._customTools.get(), tool];\n this._customTools.set(tools);\n // Auto-enable new tool\n const enabled = new Set(this._enabledToolNames.get());\n enabled.add(tool.name);\n this._enabledToolNames.set(enabled);\n await Promise.all([\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, tools),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...enabled]),\n ]);\n }\n\n // ── Profile Management ───────────────────────────────────────────\n\n async addProfile(\n db: ShadowClawDatabase,\n profile: ToolProfile,\n ): Promise<void> {\n const profiles = [...this._profiles.get(), profile];\n this._profiles.set(profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n\n async cloneTool(\n db: ShadowClawDatabase,\n sourceToolName: string,\n newToolName: string,\n newDescription?: string,\n ): Promise<boolean> {\n const source = this.allTools.find((t) => t.name === sourceToolName);\n if (!source) {\n return false;\n }\n\n if (this.allTools.some((t) => t.name === newToolName)) {\n return false;\n }\n\n const cloned: ToolDefinition = {\n name: newToolName,\n description: newDescription || source.description,\n input_schema: JSON.parse(JSON.stringify(source.input_schema)),\n };\n\n await this.addCustomTool(db, cloned);\n\n return true;\n }\n\n async deactivateProfile(db: ShadowClawDatabase): Promise<void> {\n this._activeProfileId.set(null);\n await setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null);\n }\n\n async deleteProfile(\n db: ShadowClawDatabase,\n profileId: string,\n ): Promise<void> {\n if (profileId === DEFAULT_BUILTIN_PROFILE.id) {\n return;\n }\n\n const profiles = this._profiles.get().filter((p) => p.id !== profileId);\n this._profiles.set(profiles);\n if (this._activeProfileId.get() === profileId) {\n this._activeProfileId.set(null);\n await setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null);\n }\n\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n\n async importBackup(db: ShadowClawDatabase, json: string): Promise<void> {\n const data = JSON.parse(json);\n if (Array.isArray(data.enabledTools)) {\n this._enabledToolNames.set(new Set(data.enabledTools));\n await setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, data.enabledTools);\n }\n\n if (Array.isArray(data.customTools)) {\n this._customTools.set(data.customTools);\n await setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, data.customTools);\n }\n\n if (typeof data.systemPromptOverride === \"string\") {\n this._systemPromptOverride.set(data.systemPromptOverride);\n await setConfig(\n db,\n CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE,\n data.systemPromptOverride,\n );\n }\n\n if (Array.isArray(data.profiles)) {\n this._profiles.set(data.profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, data.profiles);\n }\n\n if (\n typeof data.activeProfileId === \"string\" ||\n data.activeProfileId === null\n ) {\n this._activeProfileId.set(data.activeProfileId);\n await setConfig(\n db,\n CONFIG_KEYS.ACTIVE_TOOL_PROFILE,\n data.activeProfileId,\n );\n }\n\n if (typeof data.webSearchUseProxy === \"boolean\") {\n this._webSearchUseProxy.set(data.webSearchUseProxy);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_USE_PROXY,\n data.webSearchUseProxy ? \"true\" : \"false\",\n );\n }\n\n if (typeof data.webSearchProxyUrl === \"string\") {\n this._webSearchProxyUrl.set(data.webSearchProxyUrl);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_PROXY_URL,\n data.webSearchProxyUrl,\n );\n }\n\n if (typeof data.webSearchUrl === \"string\") {\n this._webSearchUrl.set(data.webSearchUrl);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_URL, data.webSearchUrl);\n }\n\n if (\n typeof data.searchFilesMaxFileBytes === \"number\" &&\n data.searchFilesMaxFileBytes > 0\n ) {\n this._searchFilesMaxFileBytes.set(data.searchFilesMaxFileBytes);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES,\n String(data.searchFilesMaxFileBytes),\n );\n }\n\n if (\n typeof data.searchFilesMaxFilesVisited === \"number\" &&\n data.searchFilesMaxFilesVisited > 0\n ) {\n this._searchFilesMaxFilesVisited.set(data.searchFilesMaxFilesVisited);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED,\n String(data.searchFilesMaxFilesVisited),\n );\n }\n\n if (typeof data.searchFilesSkipDirs === \"string\") {\n this._searchFilesSkipDirs.set(data.searchFilesSkipDirs);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS,\n data.searchFilesSkipDirs,\n );\n }\n\n if (Array.isArray(data.declarativeToolsEnabled)) {\n this._declarativeToolNamesEnabled.set(\n new Set(data.declarativeToolsEnabled),\n );\n await setConfig(\n db,\n CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED,\n data.declarativeToolsEnabled,\n );\n } else if (data.declarativeToolsEnabled === null) {\n this._declarativeToolNamesEnabled.set(null);\n await setConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED, null);\n }\n }\n\n /**\n * Load persisted tool config from IndexedDB.\n */\n async load(db: ShadowClawDatabase): Promise<void> {\n const [\n enabledRaw,\n customRaw,\n promptOverride,\n profilesRaw,\n activeProfileIdRaw,\n webSearchUseProxyRaw,\n webSearchProxyUrlRaw,\n webSearchUrlRaw,\n searchFilesMaxFileBytesRaw,\n searchFilesMaxFilesVisitedRaw,\n searchFilesSkipDirsRaw,\n declarativeEnabledRaw,\n ] = await Promise.all([\n getConfig(db, CONFIG_KEYS.ENABLED_TOOLS),\n getConfig(db, CONFIG_KEYS.CUSTOM_TOOLS),\n getConfig(db, CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE),\n getConfig(db, CONFIG_KEYS.TOOL_PROFILES),\n getConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_USE_PROXY),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_PROXY_URL),\n getConfig(db, CONFIG_KEYS.WEB_SEARCH_URL),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED),\n getConfig(db, CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS),\n getConfig(db, CONFIG_KEYS.DECLARATIVE_TOOLS_ENABLED),\n ]);\n\n if (Array.isArray(enabledRaw)) {\n this._enabledToolNames.set(new Set(enabledRaw));\n }\n\n if (Array.isArray(customRaw)) {\n this._customTools.set(customRaw);\n }\n\n if (Array.isArray(declarativeEnabledRaw)) {\n this._declarativeToolNamesEnabled.set(new Set(declarativeEnabledRaw));\n }\n\n if (typeof promptOverride === \"string\") {\n this._systemPromptOverride.set(promptOverride);\n }\n\n if (Array.isArray(profilesRaw)) {\n this._profiles.set(profilesRaw);\n }\n\n if (typeof activeProfileIdRaw === \"string\") {\n this._activeProfileId.set(activeProfileIdRaw);\n }\n\n if (webSearchUseProxyRaw !== null && webSearchUseProxyRaw !== undefined) {\n const strVal = String(webSearchUseProxyRaw).toLowerCase();\n this._webSearchUseProxy.set(strVal === \"true\" || strVal === \"1\");\n }\n\n if (\n typeof webSearchProxyUrlRaw === \"string\" &&\n webSearchProxyUrlRaw.trim().length > 0\n ) {\n this._webSearchProxyUrl.set(webSearchProxyUrlRaw.trim());\n }\n\n if (\n typeof webSearchUrlRaw === \"string\" &&\n webSearchUrlRaw.trim().length > 0\n ) {\n this._webSearchUrl.set(webSearchUrlRaw.trim());\n }\n\n if (\n searchFilesMaxFileBytesRaw !== null &&\n searchFilesMaxFileBytesRaw !== undefined\n ) {\n const n = Number(searchFilesMaxFileBytesRaw);\n if (Number.isFinite(n) && n > 0) {\n this._searchFilesMaxFileBytes.set(n);\n }\n }\n\n if (\n searchFilesMaxFilesVisitedRaw !== null &&\n searchFilesMaxFilesVisitedRaw !== undefined\n ) {\n const n = Number(searchFilesMaxFilesVisitedRaw);\n if (Number.isFinite(n) && n > 0) {\n this._searchFilesMaxFilesVisited.set(n);\n }\n }\n\n if (\n typeof searchFilesSkipDirsRaw === \"string\" &&\n searchFilesSkipDirsRaw.trim().length > 0\n ) {\n this._searchFilesSkipDirs.set(searchFilesSkipDirsRaw.trim());\n }\n }\n\n async setWebSearchProxyUrl(\n db: ShadowClawDatabase,\n proxyUrl: string,\n ): Promise<void> {\n const trimmed = proxyUrl.trim() || \"/proxy\";\n this._webSearchProxyUrl.set(trimmed);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_PROXY_URL, trimmed);\n }\n\n async setWebSearchUrl(db: ShadowClawDatabase, url: string): Promise<void> {\n const trimmed = url.trim() || \"https://html.duckduckgo.com/html/?q={query}\";\n this._webSearchUrl.set(trimmed);\n await setConfig(db, CONFIG_KEYS.WEB_SEARCH_URL, trimmed);\n }\n\n async setWebSearchUseProxy(\n db: ShadowClawDatabase,\n useProxy: boolean,\n ): Promise<void> {\n const enabled = !!useProxy;\n this._webSearchUseProxy.set(enabled);\n await setConfig(\n db,\n CONFIG_KEYS.WEB_SEARCH_USE_PROXY,\n enabled ? \"true\" : \"false\",\n );\n }\n\n async setSearchFilesMaxFileBytes(\n db: ShadowClawDatabase,\n bytes: number,\n ): Promise<void> {\n const clamped = Math.max(1, Math.round(bytes));\n this._searchFilesMaxFileBytes.set(clamped);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILE_BYTES,\n String(clamped),\n );\n }\n\n async setSearchFilesMaxFilesVisited(\n db: ShadowClawDatabase,\n count: number,\n ): Promise<void> {\n const clamped = Math.max(1, Math.round(count));\n this._searchFilesMaxFilesVisited.set(clamped);\n await setConfig(\n db,\n CONFIG_KEYS.SEARCH_FILES_MAX_FILES_VISITED,\n String(clamped),\n );\n }\n\n async setSearchFilesSkipDirs(\n db: ShadowClawDatabase,\n dirs: string,\n ): Promise<void> {\n const trimmed = dirs.trim();\n this._searchFilesSkipDirs.set(trimmed);\n await setConfig(db, CONFIG_KEYS.SEARCH_FILES_SKIP_DIRS, trimmed);\n }\n\n async removeCustomTool(\n db: ShadowClawDatabase,\n toolName: string,\n ): Promise<void> {\n const tools = this._customTools.get().filter((t) => t.name !== toolName);\n this._customTools.set(tools);\n const enabled = new Set(this._enabledToolNames.get());\n enabled.delete(toolName);\n this._enabledToolNames.set(enabled);\n await Promise.all([\n setConfig(db, CONFIG_KEYS.CUSTOM_TOOLS, tools),\n setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...enabled]),\n ]);\n }\n\n async saveToActiveProfile(db: ShadowClawDatabase): Promise<void> {\n const id = this._activeProfileId.get();\n if (!id) {\n return;\n }\n\n const profile = this._profiles.get().find((p) => p.id === id);\n if (!profile) {\n return;\n }\n\n const updated = {\n ...profile,\n enabledToolNames: [...this._enabledToolNames.get()],\n customTools: [...this._customTools.get()],\n systemPromptOverride: this._systemPromptOverride.get(),\n };\n await this.updateProfile(db, updated);\n }\n\n async setAllEnabled(\n db: ShadowClawDatabase,\n toolNames: string[],\n ): Promise<void> {\n this._enabledToolNames.set(new Set(toolNames));\n\n const saves = [setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, toolNames)];\n if (this._activeProfileId.get()) {\n this._activeProfileId.set(null);\n saves.push(setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null));\n }\n\n await Promise.all(saves);\n }\n\n async setSystemPromptOverride(\n db: ShadowClawDatabase,\n override: string,\n ): Promise<void> {\n this._systemPromptOverride.set(override);\n await setConfig(db, CONFIG_KEYS.SYSTEM_PROMPT_OVERRIDE, override);\n }\n\n async setToolEnabled(\n db: ShadowClawDatabase,\n toolName: string,\n enabled: boolean,\n ): Promise<void> {\n const current = new Set(this._enabledToolNames.get());\n if (enabled) {\n current.add(toolName);\n } else {\n current.delete(toolName);\n }\n\n this._enabledToolNames.set(current);\n\n const saves = [setConfig(db, CONFIG_KEYS.ENABLED_TOOLS, [...current])];\n if (this._activeProfileId.get()) {\n this._activeProfileId.set(null);\n saves.push(setConfig(db, CONFIG_KEYS.ACTIVE_TOOL_PROFILE, null));\n }\n\n await Promise.all(saves);\n }\n\n async updateProfile(\n db: ShadowClawDatabase,\n profile: ToolProfile,\n ): Promise<void> {\n const profiles = this._profiles\n .get()\n .map((p) => (p.id === profile.id ? profile : p));\n this._profiles.set(profiles);\n await setConfig(db, CONFIG_KEYS.TOOL_PROFILES, profiles);\n }\n}\n\nexport const toolsStore = new ToolsStore();\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as getDb } from "./txPromise-CuGh-TGK.js";
|
|
2
|
-
import { r as CONFIG_KEYS } from "./config
|
|
3
|
-
import {
|
|
2
|
+
import { r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
|
|
3
|
+
import { l as parseRouteFromUrl } from "./app-routes-BAEMLu9g.js";
|
|
4
4
|
import { t as getConfig } from "./getConfig-BxxXMyuM.js";
|
|
5
|
-
import { i as parseHostPatternMatch, n as getDOMPurify, t as ensureIframeSanitizerHook } from "./iframe-sanitizer-
|
|
5
|
+
import { i as parseHostPatternMatch, n as getDOMPurify, t as ensureIframeSanitizerHook } from "./iframe-sanitizer-Bujgq14T.js";
|
|
6
6
|
|
|
7
7
|
//#region src/security/custom-element-security.ts
|
|
8
8
|
/** Default allowed custom elements: none by default */
|
|
@@ -548,4 +548,4 @@ function toTrustedScriptUrl(url) {
|
|
|
548
548
|
|
|
549
549
|
//#endregion
|
|
550
550
|
export { getIframeSandboxPolicy as _, toTrustedScriptUrl as a, isAllowedCustomElement as b, escapeHtml as c, handleSpecialLinkNavigation as d, sanitizeHtml as f, getIframeCsp as g, getApprovedCustomElementScriptDescriptors as h, toTrustedHtmlPresanitized as i, formatDateForFilename as l, configureCustomElementSecurity as m, setSanitizedHtml as n, bufferToHex as o, toArrayBuffer as p, setTrustedSrcdoc as r, computeSha256 as s, sanitizeSrcdocHtml as t, formatTimestamp as u, installCustomElementDomGuard as v, loadCustomElementSecurityFromDb as x, installCustomElementsRegistryGuard as y };
|
|
551
|
-
//# sourceMappingURL=trusted-types-
|
|
551
|
+
//# sourceMappingURL=trusted-types-Oz7xXJAY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trusted-types-Dx0RZlrd.js","names":[],"sources":["../../src/security/custom-element-security.ts","../../src/utils/utils.ts","../../src/security/trusted-types.ts"],"sourcesContent":["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 * 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 hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n\n return bufferToHex(hashBuffer);\n}\n","/// <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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"trusted-types-Oz7xXJAY.js","names":[],"sources":["../../src/security/custom-element-security.ts","../../src/utils/utils.ts","../../src/security/trusted-types.ts"],"sourcesContent":["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 * 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 hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n\n return bufferToHex(hashBuffer);\n}\n","/// <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"],"mappings":"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"}
|
package/dist/lib/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __exportAll } from "../rolldown-runtime-DZ8SGSJo.js";
|
|
2
2
|
import { ulid } from "./ulid.js";
|
|
3
|
-
import { c as escapeHtml, d as handleSpecialLinkNavigation, f as sanitizeHtml, l as formatDateForFilename, o as bufferToHex, p as toArrayBuffer, s as computeSha256, u as formatTimestamp } from "../trusted-types-
|
|
3
|
+
import { c as escapeHtml, d as handleSpecialLinkNavigation, f as sanitizeHtml, l as formatDateForFilename, o as bufferToHex, p as toArrayBuffer, s as computeSha256, u as formatTimestamp } from "../trusted-types-Oz7xXJAY.js";
|
|
4
4
|
import { getNamespacedItem, getNamespacedStorageKey, removeNamespacedItem, setNamespacedItem } from "./namespacedStorage.js";
|
|
5
5
|
import { applyJsonPatch } from "./jsonPatch.js";
|
|
6
6
|
import { base64ToBytes, bytesToBase64 } from "./base64.js";
|
package/dist/lib/utils/utils.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { c as escapeHtml, d as handleSpecialLinkNavigation, f as sanitizeHtml, l as formatDateForFilename, o as bufferToHex, p as toArrayBuffer, s as computeSha256, u as formatTimestamp } from "../trusted-types-
|
|
1
|
+
import { c as escapeHtml, d as handleSpecialLinkNavigation, f as sanitizeHtml, l as formatDateForFilename, o as bufferToHex, p as toArrayBuffer, s as computeSha256, u as formatTimestamp } from "../trusted-types-Oz7xXJAY.js";
|
|
2
2
|
|
|
3
3
|
export { bufferToHex, computeSha256, escapeHtml, formatDateForFilename, formatTimestamp, handleSpecialLinkNavigation, sanitizeHtml, toArrayBuffer };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-DZ8SGSJo.js";
|
|
2
|
-
import { o as DEFAULT_GROUP_ID } from "./config
|
|
3
|
-
import { t as TOOL_DEFINITIONS } from "./tools-
|
|
4
|
-
import "./tools-
|
|
2
|
+
import { o as DEFAULT_GROUP_ID } from "./config-DjZ9QWc4.js";
|
|
3
|
+
import { t as TOOL_DEFINITIONS } from "./tools-DKzPWc0q.js";
|
|
4
|
+
import "./tools-C3Kft940.js";
|
|
5
5
|
|
|
6
6
|
//#region node_modules/@cfworker/json-schema/dist/esm/deep-compare-strict.js
|
|
7
7
|
function deepCompareStrict(a, b) {
|
|
@@ -1707,4 +1707,4 @@ function unregisterWebMcpTools() {
|
|
|
1707
1707
|
|
|
1708
1708
|
//#endregion
|
|
1709
1709
|
export { webmcp_exports as a, unregisterWebMcpTools as i, registerWebMcpTools as n, setWebMcpMode as r, getWebMcpMode as t };
|
|
1710
|
-
//# sourceMappingURL=webmcp-
|
|
1710
|
+
//# sourceMappingURL=webmcp-BC8_WafM.js.map
|