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,9 +1,11 @@
|
|
|
1
1
|
import { jest } from "@jest/globals";
|
|
2
2
|
|
|
3
3
|
const mockLoadSkill = jest.fn() as any;
|
|
4
|
+
const mockDiscoverSkills = jest.fn() as any;
|
|
4
5
|
|
|
5
6
|
jest.unstable_mockModule("./discoverSkills.js", () => ({
|
|
6
7
|
loadSkill: mockLoadSkill,
|
|
8
|
+
discoverSkills: mockDiscoverSkills,
|
|
7
9
|
}));
|
|
8
10
|
|
|
9
11
|
const { executeActivateSkill } = await import("./activateSkill.js");
|
|
@@ -11,21 +13,27 @@ const { executeActivateSkill } = await import("./activateSkill.js");
|
|
|
11
13
|
describe("executeActivateSkill", () => {
|
|
12
14
|
beforeEach(() => {
|
|
13
15
|
jest.clearAllMocks();
|
|
16
|
+
mockDiscoverSkills.mockResolvedValue({
|
|
17
|
+
skills: [{ name: "existing-skill", description: "An existing skill" }],
|
|
18
|
+
diagnostics: [],
|
|
19
|
+
});
|
|
14
20
|
});
|
|
15
21
|
|
|
16
|
-
it("returns error when skill name is missing or empty", async () => {
|
|
22
|
+
it("returns error when skill name is missing or empty, including available skills", async () => {
|
|
17
23
|
const res1 = await executeActivateSkill({} as any, {}, "group-1");
|
|
18
|
-
expect(res1).
|
|
24
|
+
expect(res1).toContain("Error: activate_skill requires a skill name.");
|
|
25
|
+
expect(res1).toContain("Available skills: existing-skill.");
|
|
19
26
|
|
|
20
27
|
const res2 = await executeActivateSkill(
|
|
21
28
|
{} as any,
|
|
22
29
|
{ name: " " },
|
|
23
30
|
"group-1",
|
|
24
31
|
);
|
|
25
|
-
expect(res2).
|
|
32
|
+
expect(res2).toContain("Error: activate_skill requires a skill name.");
|
|
33
|
+
expect(res2).toContain("Available skills: existing-skill.");
|
|
26
34
|
});
|
|
27
35
|
|
|
28
|
-
it("returns error when skill is not found", async () => {
|
|
36
|
+
it("returns error when skill is not found, including available skills", async () => {
|
|
29
37
|
mockLoadSkill.mockResolvedValue(null);
|
|
30
38
|
|
|
31
39
|
const res = await executeActivateSkill(
|
|
@@ -33,9 +41,34 @@ describe("executeActivateSkill", () => {
|
|
|
33
41
|
{ name: "my-skill" },
|
|
34
42
|
"group-1",
|
|
35
43
|
);
|
|
36
|
-
expect(res).
|
|
44
|
+
expect(res).toContain(
|
|
37
45
|
'Error: skill "my-skill" was not found in this conversation workspace.',
|
|
38
46
|
);
|
|
47
|
+
expect(res).toContain("Available skills: existing-skill.");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("reports matched diagnostic when a skill exists on disk but failed to parse", async () => {
|
|
51
|
+
mockLoadSkill.mockResolvedValue(null);
|
|
52
|
+
mockDiscoverSkills.mockResolvedValue({
|
|
53
|
+
skills: [{ name: "existing-skill", description: "An existing skill" }],
|
|
54
|
+
diagnostics: [
|
|
55
|
+
{
|
|
56
|
+
path: ".agents/skills/main/broken-skill/SKILL.md",
|
|
57
|
+
message: "YAML parse error on line 3",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const res = await executeActivateSkill(
|
|
63
|
+
{} as any,
|
|
64
|
+
{ name: "broken-skill" },
|
|
65
|
+
"group-1",
|
|
66
|
+
);
|
|
67
|
+
expect(res).toContain(
|
|
68
|
+
'Error: skill "broken-skill" was found at ".agents/skills/main/broken-skill/SKILL.md" but failed to load: YAML parse error on line 3.',
|
|
69
|
+
);
|
|
70
|
+
expect(res).toContain("Please fix the frontmatter in SKILL.md.");
|
|
71
|
+
expect(res).toContain("Available skills: existing-skill.");
|
|
39
72
|
});
|
|
40
73
|
|
|
41
74
|
it("returns error when skill disables model invocation", async () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadSkill } from "./discoverSkills.js";
|
|
1
|
+
import { discoverSkills, loadSkill } from "./discoverSkills.js";
|
|
2
2
|
import type { ShadowClawDatabase } from "../../db/types.js";
|
|
3
3
|
|
|
4
4
|
export async function executeActivateSkill(
|
|
@@ -7,13 +7,35 @@ export async function executeActivateSkill(
|
|
|
7
7
|
groupId: string,
|
|
8
8
|
): Promise<string> {
|
|
9
9
|
const name = typeof input.name === "string" ? input.name.trim() : "";
|
|
10
|
+
const discovery = await discoverSkills(db, groupId);
|
|
11
|
+
const availableSkillNames = discovery.skills.map((s) => s.name);
|
|
12
|
+
const availableList =
|
|
13
|
+
availableSkillNames.length > 0 ? availableSkillNames.join(", ") : "(none)";
|
|
14
|
+
|
|
10
15
|
if (!name) {
|
|
11
|
-
|
|
16
|
+
let msg = `Error: activate_skill requires a skill name. Available skills: ${availableList}.`;
|
|
17
|
+
if (discovery.diagnostics.length > 0) {
|
|
18
|
+
msg += ` (Note: ${discovery.diagnostics.length} skill file(s) had errors: ${discovery.diagnostics.map((d) => `${d.path}: ${d.message}`).join("; ")})`;
|
|
19
|
+
}
|
|
20
|
+
return msg;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
23
|
const skill = await loadSkill(db, groupId, name);
|
|
15
24
|
if (!skill) {
|
|
16
|
-
|
|
25
|
+
const matchedDiag = discovery.diagnostics.find(
|
|
26
|
+
(d) =>
|
|
27
|
+
d.path.toLowerCase().includes(name.toLowerCase()) ||
|
|
28
|
+
d.message.toLowerCase().includes(name.toLowerCase()),
|
|
29
|
+
);
|
|
30
|
+
if (matchedDiag) {
|
|
31
|
+
return `Error: skill "${name}" was found at "${matchedDiag.path}" but failed to load: ${matchedDiag.message}. Please fix the frontmatter in SKILL.md. Available skills: ${availableList}.`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let msg = `Error: skill "${name}" was not found in this conversation workspace. Available skills: ${availableList}.`;
|
|
35
|
+
if (discovery.diagnostics.length > 0) {
|
|
36
|
+
msg += ` (Note: ${discovery.diagnostics.length} skill file(s) had errors: ${discovery.diagnostics.map((d) => `${d.path}: ${d.message}`).join("; ")})`;
|
|
37
|
+
}
|
|
38
|
+
return msg;
|
|
17
39
|
}
|
|
18
40
|
if (skill.disableModelInvocation) {
|
|
19
41
|
return `Error: skill "${name}" is not available for model-driven activation.`;
|
|
@@ -83,4 +83,75 @@ describe("parseSkill", () => {
|
|
|
83
83
|
|
|
84
84
|
expect(result.execution).toBeUndefined();
|
|
85
85
|
});
|
|
86
|
+
|
|
87
|
+
it("resiliently parses frontmatter with unquoted colons, URLs, and quotes in description", () => {
|
|
88
|
+
const rawSkill = `---
|
|
89
|
+
name: bible-lookup
|
|
90
|
+
description: Look up Bible verses from the bible-tools/data repository (https://bible-tools.github.io/data/). Supports multiple translations in Arabic (ar), German (de), English (en: ASV, KJV, WEB), Spanish (es), and French (fr). Trigger phrases: "bible lookup", "look up a bible verse", "bible verse", "find bible verse", "bible reference", "what does the bible say about", "scripture reference", "look up verse", "bible passage".
|
|
91
|
+
user-invocable: true
|
|
92
|
+
metadata:
|
|
93
|
+
allowed-tools:
|
|
94
|
+
- fetch_url
|
|
95
|
+
- javascript
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
# Bible Lookup Skill
|
|
99
|
+
|
|
100
|
+
Instructions here.`;
|
|
101
|
+
|
|
102
|
+
const result = parseSkill(
|
|
103
|
+
".agents/skills/main/bible-lookup/SKILL.md",
|
|
104
|
+
rawSkill,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect(result.name).toBe("bible-lookup");
|
|
108
|
+
expect(result.description).toContain(
|
|
109
|
+
"Look up Bible verses from the bible-tools/data repository",
|
|
110
|
+
);
|
|
111
|
+
expect(result.description).toContain("(en: ASV, KJV, WEB)");
|
|
112
|
+
expect(result.userInvocable).toBe(true);
|
|
113
|
+
expect(result.allowedTools).toBe("fetch_url javascript");
|
|
114
|
+
expect(result.metadata?.["allowed-tools"]).toBe("fetch_url javascript");
|
|
115
|
+
expect(result.body).toBe("# Bible Lookup Skill\n\nInstructions here.");
|
|
116
|
+
expect(result.path).toBe(".agents/skills/main/bible-lookup/SKILL.md");
|
|
117
|
+
expect(result.basePath).toBe(".agents/skills/main/bible-lookup");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("normalizes array allowed-tools into a space-separated string", () => {
|
|
121
|
+
const result = parseSkill(
|
|
122
|
+
"skills/tools/SKILL.md",
|
|
123
|
+
`---\nname: tools-test\ndescription: Test tools array\nmetadata:\n allowed-tools:\n - read_file\n - write_file\n - javascript\n---\nbody`,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
expect(result.allowedTools).toBe("read_file write_file javascript");
|
|
127
|
+
expect(result.metadata?.["allowed-tools"]).toBe(
|
|
128
|
+
"read_file write_file javascript",
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("recovers via fallback extraction when YAML syntax is malformed", () => {
|
|
133
|
+
const brokenYaml = `---
|
|
134
|
+
name: broken-yaml-skill
|
|
135
|
+
description: Resilient fallback description with : colons and [broken brackets
|
|
136
|
+
user-invocable: true
|
|
137
|
+
disable-model-invocation: false
|
|
138
|
+
allowed-tools:
|
|
139
|
+
- tool_a
|
|
140
|
+
- tool_b
|
|
141
|
+
some_random_key: {unclosed object
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
# Fallback Body`;
|
|
145
|
+
|
|
146
|
+
const result = parseSkill("skills/broken/SKILL.md", brokenYaml);
|
|
147
|
+
|
|
148
|
+
expect(result.name).toBe("broken-yaml-skill");
|
|
149
|
+
expect(result.description).toBe(
|
|
150
|
+
"Resilient fallback description with : colons and [broken brackets",
|
|
151
|
+
);
|
|
152
|
+
expect(result.userInvocable).toBe(true);
|
|
153
|
+
expect(result.disableModelInvocation).toBe(false);
|
|
154
|
+
expect(result.allowedTools).toBe("tool_a tool_b");
|
|
155
|
+
expect(result.body).toBe("# Fallback Body");
|
|
156
|
+
});
|
|
86
157
|
});
|
|
@@ -5,10 +5,145 @@ import type { SkillExecution, SkillRecord } from "./types.js";
|
|
|
5
5
|
|
|
6
6
|
const NAME_PATTERN = /^[a-z0-9](?:[a-z0-9]|-(?!-))*[a-z0-9]$|^[a-z0-9]$/;
|
|
7
7
|
|
|
8
|
+
interface FrontmatterParseResult {
|
|
9
|
+
data: Record<string, unknown>;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseFrontmatterResiliently(source: string): FrontmatterParseResult {
|
|
14
|
+
try {
|
|
15
|
+
const parsed = matter(source);
|
|
16
|
+
return {
|
|
17
|
+
data: parsed.data && typeof parsed.data === "object" ? parsed.data : {},
|
|
18
|
+
content: parsed.content || "",
|
|
19
|
+
};
|
|
20
|
+
} catch {
|
|
21
|
+
// Attempt 1: Sanitize unquoted scalar lines in the frontmatter block
|
|
22
|
+
const fmMatch = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
23
|
+
if (fmMatch) {
|
|
24
|
+
const rawFm = fmMatch[1];
|
|
25
|
+
const rest = fmMatch[2] || "";
|
|
26
|
+
const lines = rawFm.split(/\r?\n/);
|
|
27
|
+
const sanitizedLines = lines.map((line) => {
|
|
28
|
+
const fieldMatch = line.match(/^([a-zA-Z0-9_-]+):\s*(.+)$/);
|
|
29
|
+
if (fieldMatch) {
|
|
30
|
+
const [, key, val] = fieldMatch;
|
|
31
|
+
const trimmed = val.trim();
|
|
32
|
+
// If value is not already quoted and not a YAML block indicator/collection opening or boolean/number
|
|
33
|
+
if (
|
|
34
|
+
trimmed &&
|
|
35
|
+
trimmed !== "true" &&
|
|
36
|
+
trimmed !== "false" &&
|
|
37
|
+
trimmed !== "null" &&
|
|
38
|
+
!trimmed.startsWith('"') &&
|
|
39
|
+
!trimmed.startsWith("'") &&
|
|
40
|
+
!trimmed.startsWith("[") &&
|
|
41
|
+
!trimmed.startsWith("{") &&
|
|
42
|
+
trimmed !== ">" &&
|
|
43
|
+
trimmed !== "|" &&
|
|
44
|
+
trimmed !== ">-" &&
|
|
45
|
+
trimmed !== "|-" &&
|
|
46
|
+
!/^-?\d+(?:\.\d+)?$/.test(trimmed)
|
|
47
|
+
) {
|
|
48
|
+
return `${key}: ${JSON.stringify(trimmed)}`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return line;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const sanitizedSource = `---\n${sanitizedLines.join("\n")}\n---\n${rest}`;
|
|
56
|
+
const parsed = matter(sanitizedSource);
|
|
57
|
+
return {
|
|
58
|
+
data:
|
|
59
|
+
parsed.data && typeof parsed.data === "object" ? parsed.data : {},
|
|
60
|
+
content: parsed.content || "",
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
// Continue to fallback
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Attempt 2: Line-by-line fallback extraction for essential frontmatter fields
|
|
67
|
+
const fallbackData: Record<string, unknown> = {};
|
|
68
|
+
const nameMatch = rawFm.match(/^name:\s*["']?([^"'\r\n]+)["']?/m);
|
|
69
|
+
if (nameMatch) {
|
|
70
|
+
fallbackData.name = nameMatch[1].trim();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const descMatch = rawFm.match(/^description:\s*(.+)$/m);
|
|
74
|
+
if (descMatch) {
|
|
75
|
+
let desc = descMatch[1].trim();
|
|
76
|
+
if (
|
|
77
|
+
(desc.startsWith('"') && desc.endsWith('"')) ||
|
|
78
|
+
(desc.startsWith("'") && desc.endsWith("'"))
|
|
79
|
+
) {
|
|
80
|
+
desc = desc.slice(1, -1);
|
|
81
|
+
}
|
|
82
|
+
fallbackData.description = desc;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const userInvocableMatch = rawFm.match(
|
|
86
|
+
/^user-invocable:\s*(true|false)/im,
|
|
87
|
+
);
|
|
88
|
+
if (userInvocableMatch) {
|
|
89
|
+
fallbackData["user-invocable"] =
|
|
90
|
+
userInvocableMatch[1].toLowerCase() === "true";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const disableModelMatch = rawFm.match(
|
|
94
|
+
/^disable-model-invocation:\s*(true|false)/im,
|
|
95
|
+
);
|
|
96
|
+
if (disableModelMatch) {
|
|
97
|
+
fallbackData["disable-model-invocation"] =
|
|
98
|
+
disableModelMatch[1].toLowerCase() === "true";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const toolsMatch = rawFm.match(
|
|
102
|
+
/^allowed-tools:\s*["']?([^"'\r\n]+)["']?/m,
|
|
103
|
+
);
|
|
104
|
+
if (toolsMatch) {
|
|
105
|
+
fallbackData["allowed-tools"] = toolsMatch[1].trim();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check for bullet list allowed-tools
|
|
109
|
+
const toolListMatch = rawFm.match(
|
|
110
|
+
/allowed-tools:\s*\n((?:\s*-\s*[^\r\n]+\r?\n?)+)/m,
|
|
111
|
+
);
|
|
112
|
+
if (toolListMatch) {
|
|
113
|
+
const tools = toolListMatch[1]
|
|
114
|
+
.split(/\r?\n/)
|
|
115
|
+
.map((l) => l.replace(/^\s*-\s*/, "").trim())
|
|
116
|
+
.filter(Boolean);
|
|
117
|
+
if (tools.length > 0) {
|
|
118
|
+
fallbackData["allowed-tools"] = tools;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return { data: fallbackData, content: rest };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { data: {}, content: source };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function extractAllowedTools(raw: unknown): string | undefined {
|
|
130
|
+
if (typeof raw === "string") {
|
|
131
|
+
const trimmed = raw.trim();
|
|
132
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
133
|
+
}
|
|
134
|
+
if (Array.isArray(raw)) {
|
|
135
|
+
const tools = raw
|
|
136
|
+
.filter((item): item is string => typeof item === "string")
|
|
137
|
+
.map((item) => item.trim())
|
|
138
|
+
.filter((item) => item.length > 0);
|
|
139
|
+
return tools.length > 0 ? tools.join(" ") : undefined;
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
8
144
|
export function parseSkill(path: string, source: string): SkillRecord {
|
|
9
|
-
const parsed =
|
|
10
|
-
const data =
|
|
11
|
-
parsed.data && typeof parsed.data === "object" ? parsed.data : {};
|
|
145
|
+
const parsed = parseFrontmatterResiliently(source);
|
|
146
|
+
const data = parsed.data;
|
|
12
147
|
const name = typeof data.name === "string" ? data.name.trim() : "";
|
|
13
148
|
const description =
|
|
14
149
|
typeof data.description === "string" ? data.description.trim() : "";
|
|
@@ -36,31 +171,45 @@ export function parseSkill(path: string, source: string): SkillRecord {
|
|
|
36
171
|
? (data.metadata as Record<string, unknown>)
|
|
37
172
|
: undefined;
|
|
38
173
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
174
|
+
const allowedToolsRaw =
|
|
175
|
+
extractAllowedTools(rawMetadata?.["allowed-tools"]) ||
|
|
176
|
+
extractAllowedTools(rawMetadata?.["allowedTools"]) ||
|
|
177
|
+
extractAllowedTools(data["allowed-tools"]) ||
|
|
178
|
+
extractAllowedTools(data["allowedTools"]);
|
|
179
|
+
|
|
180
|
+
const metadataEntries: [string, string][] = [];
|
|
181
|
+
if (rawMetadata) {
|
|
182
|
+
for (const [key, value] of Object.entries(rawMetadata)) {
|
|
183
|
+
if (key === "execution" || value === null || value === undefined) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (key === "allowed-tools" || key === "allowedTools") {
|
|
187
|
+
if (allowedToolsRaw) {
|
|
188
|
+
metadataEntries.push([key, allowedToolsRaw]);
|
|
189
|
+
}
|
|
190
|
+
} else if (
|
|
191
|
+
typeof value === "string" ||
|
|
192
|
+
typeof value === "number" ||
|
|
193
|
+
typeof value === "boolean"
|
|
194
|
+
) {
|
|
195
|
+
metadataEntries.push([key, String(value)]);
|
|
196
|
+
} else if (Array.isArray(value)) {
|
|
197
|
+
const stringItems = value
|
|
198
|
+
.filter((item): item is string => typeof item === "string")
|
|
199
|
+
.map((item) => item.trim())
|
|
200
|
+
.filter(Boolean);
|
|
201
|
+
if (stringItems.length > 0) {
|
|
202
|
+
metadataEntries.push([key, stringItems.join(" ")]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
45
207
|
|
|
46
208
|
const metadata =
|
|
47
209
|
metadataEntries.length > 0
|
|
48
|
-
? Object.fromEntries(
|
|
49
|
-
metadataEntries.map(([key, value]) => [key, String(value)]),
|
|
50
|
-
)
|
|
210
|
+
? Object.fromEntries(metadataEntries)
|
|
51
211
|
: undefined;
|
|
52
212
|
|
|
53
|
-
const allowedToolsRaw =
|
|
54
|
-
(rawMetadata &&
|
|
55
|
-
(typeof rawMetadata["allowed-tools"] === "string"
|
|
56
|
-
? rawMetadata["allowed-tools"]
|
|
57
|
-
: typeof rawMetadata["allowedTools"] === "string"
|
|
58
|
-
? rawMetadata["allowedTools"]
|
|
59
|
-
: undefined)) ||
|
|
60
|
-
(typeof data["allowed-tools"] === "string"
|
|
61
|
-
? data["allowed-tools"]
|
|
62
|
-
: undefined);
|
|
63
|
-
|
|
64
213
|
const execution = rawMetadata?.execution;
|
|
65
214
|
|
|
66
215
|
let parsedExecution;
|
|
@@ -119,10 +268,21 @@ export function parseSkill(path: string, source: string): SkillRecord {
|
|
|
119
268
|
: {}),
|
|
120
269
|
...(typeof data["user-invocable"] === "boolean"
|
|
121
270
|
? { userInvocable: data["user-invocable"] }
|
|
122
|
-
:
|
|
271
|
+
: typeof data["user-invocable"] === "string" &&
|
|
272
|
+
(data["user-invocable"].toLowerCase() === "true" ||
|
|
273
|
+
data["user-invocable"].toLowerCase() === "false")
|
|
274
|
+
? { userInvocable: data["user-invocable"].toLowerCase() === "true" }
|
|
275
|
+
: {}),
|
|
123
276
|
...(typeof data["disable-model-invocation"] === "boolean"
|
|
124
277
|
? { disableModelInvocation: data["disable-model-invocation"] }
|
|
125
|
-
:
|
|
278
|
+
: typeof data["disable-model-invocation"] === "string" &&
|
|
279
|
+
(data["disable-model-invocation"].toLowerCase() === "true" ||
|
|
280
|
+
data["disable-model-invocation"].toLowerCase() === "false")
|
|
281
|
+
? {
|
|
282
|
+
disableModelInvocation:
|
|
283
|
+
data["disable-model-invocation"].toLowerCase() === "true",
|
|
284
|
+
}
|
|
285
|
+
: {}),
|
|
126
286
|
...(parsedExecution ? { execution: parsedExecution } : {}),
|
|
127
287
|
body: parsed.content.trim(),
|
|
128
288
|
path,
|
|
@@ -278,10 +278,10 @@ export const search_files: ToolDefinition = {
|
|
|
278
278
|
export const send_file: ToolDefinition = {
|
|
279
279
|
name: "send_file",
|
|
280
280
|
description:
|
|
281
|
-
"Send a workspace file directly to
|
|
282
|
-
"Use this when the user is in a peer conversation and
|
|
283
|
-
"Do NOT use this for local-browser or non-peer conversations — it only works when the active conversation " +
|
|
284
|
-
"is a peer: group. The file is read from the current group workspace and transferred in binary chunks " +
|
|
281
|
+
"Send a workspace file directly to connected peer(s) over the P2P (PeerJS/WebRTC) data channel. " +
|
|
282
|
+
"Use this when the user is in a peer conversation or room and asks to send or transfer a file. " +
|
|
283
|
+
"Do NOT use this for local-browser or other non-peer conversations — it only works when the active conversation " +
|
|
284
|
+
"is a peer or room session (peer: or room: group). The file is read from the current group workspace and transferred in binary chunks " +
|
|
285
285
|
"so there is no size limit.",
|
|
286
286
|
input_schema: {
|
|
287
287
|
type: "object",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import { jest } from "@jest/globals";
|
|
3
2
|
|
|
4
3
|
describe("executeSpawnSubagentTool", () => {
|
|
@@ -131,7 +130,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
131
130
|
});
|
|
132
131
|
|
|
133
132
|
it("calls handleInvoke with a subagent groupId starting with 'subagent:'", async () => {
|
|
134
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
133
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
135
134
|
// Simulate the subagent posting a response message
|
|
136
135
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
137
136
|
const lastCall = collectors[collectors.length - 1];
|
|
@@ -161,7 +160,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
161
160
|
it("uses a unique ulid for subagent groupId", async () => {
|
|
162
161
|
mockUlid.mockReturnValueOnce("ulid-aaa").mockReturnValueOnce("ulid-bbb");
|
|
163
162
|
|
|
164
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
163
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
165
164
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
166
165
|
const lastCall = collectors[collectors.length - 1];
|
|
167
166
|
if (lastCall) {
|
|
@@ -186,7 +185,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
186
185
|
});
|
|
187
186
|
|
|
188
187
|
it("excludes spawn_subagent from the subagent's tool list to prevent recursion", async () => {
|
|
189
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
188
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
190
189
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
191
190
|
const lastCall = collectors[collectors.length - 1];
|
|
192
191
|
if (lastCall) {
|
|
@@ -212,7 +211,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
212
211
|
});
|
|
213
212
|
|
|
214
213
|
it("uses the provided tools list when specified in input", async () => {
|
|
215
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
214
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
216
215
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
217
216
|
const lastCall = collectors[collectors.length - 1];
|
|
218
217
|
if (lastCall) {
|
|
@@ -238,7 +237,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
238
237
|
});
|
|
239
238
|
|
|
240
239
|
it("in manual mode, overrides model when specified as pinned model", async () => {
|
|
241
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
240
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
242
241
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
243
242
|
const lastCall = collectors[collectors.length - 1];
|
|
244
243
|
if (lastCall) {
|
|
@@ -267,7 +266,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
267
266
|
});
|
|
268
267
|
|
|
269
268
|
it("in automatic mode, ignores LLM-emitted model and falls back to parent ctx model", async () => {
|
|
270
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
269
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
271
270
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
272
271
|
const lastCall = collectors[collectors.length - 1];
|
|
273
272
|
if (lastCall) {
|
|
@@ -299,7 +298,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
299
298
|
});
|
|
300
299
|
|
|
301
300
|
it("clamps subagent max tokens by selected model limit", async () => {
|
|
302
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
301
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
303
302
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
304
303
|
const lastCall = collectors[collectors.length - 1];
|
|
305
304
|
if (lastCall) {
|
|
@@ -329,7 +328,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
329
328
|
});
|
|
330
329
|
|
|
331
330
|
it("uses conversation subagent max tokens override but keeps model-safe clamp", async () => {
|
|
332
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
331
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
333
332
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
334
333
|
const lastCall = collectors[collectors.length - 1];
|
|
335
334
|
if (lastCall) {
|
|
@@ -360,7 +359,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
360
359
|
});
|
|
361
360
|
|
|
362
361
|
it("uses the selected subagent model limit when auto max tokens is enabled", async () => {
|
|
363
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
362
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
364
363
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
365
364
|
const lastCall = collectors[collectors.length - 1];
|
|
366
365
|
if (lastCall) {
|
|
@@ -391,7 +390,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
391
390
|
});
|
|
392
391
|
|
|
393
392
|
it("in manual mode, overrides provider to a different provider with its api key", async () => {
|
|
394
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
393
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
395
394
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
396
395
|
const lastCall = collectors[collectors.length - 1];
|
|
397
396
|
if (lastCall) {
|
|
@@ -421,7 +420,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
421
420
|
});
|
|
422
421
|
|
|
423
422
|
it("in automatic mode, ignores LLM-emitted provider and falls back to parent ctx provider", async () => {
|
|
424
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
423
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
425
424
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
426
425
|
const lastCall = collectors[collectors.length - 1];
|
|
427
426
|
if (lastCall) {
|
|
@@ -452,7 +451,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
452
451
|
});
|
|
453
452
|
|
|
454
453
|
it("in automatic mode, maps profile 'fast', 'smart', 'powerful' to their configured provider/model", async () => {
|
|
455
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
454
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
456
455
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
457
456
|
const lastCall = collectors[collectors.length - 1];
|
|
458
457
|
if (lastCall) {
|
|
@@ -507,7 +506,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
507
506
|
});
|
|
508
507
|
|
|
509
508
|
it("in automatic mode, falls back to parent model/provider if profile is not configured or current", async () => {
|
|
510
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
509
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
511
510
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
512
511
|
const lastCall = collectors[collectors.length - 1];
|
|
513
512
|
if (lastCall) {
|
|
@@ -552,7 +551,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
552
551
|
});
|
|
553
552
|
|
|
554
553
|
it("in manual mode, ignores profile selection and uses pinned model/provider", async () => {
|
|
555
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
554
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
556
555
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
557
556
|
const lastCall = collectors[collectors.length - 1];
|
|
558
557
|
if (lastCall) {
|
|
@@ -609,7 +608,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
609
608
|
return undefined;
|
|
610
609
|
});
|
|
611
610
|
|
|
612
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
611
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
613
612
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
614
613
|
const lastCall = collectors[collectors.length - 1];
|
|
615
614
|
if (lastCall) {
|
|
@@ -642,7 +641,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
642
641
|
});
|
|
643
642
|
|
|
644
643
|
it("forwards storageHandle from parent context", async () => {
|
|
645
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
644
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
646
645
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
647
646
|
const lastCall = collectors[collectors.length - 1];
|
|
648
647
|
if (lastCall) {
|
|
@@ -679,7 +678,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
679
678
|
return undefined;
|
|
680
679
|
});
|
|
681
680
|
|
|
682
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
681
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
683
682
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
684
683
|
const lastCall = collectors[collectors.length - 1];
|
|
685
684
|
if (lastCall) {
|
|
@@ -716,7 +715,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
716
715
|
return undefined;
|
|
717
716
|
});
|
|
718
717
|
|
|
719
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
718
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
720
719
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
721
720
|
const lastCall = collectors[collectors.length - 1];
|
|
722
721
|
if (lastCall) {
|
|
@@ -754,7 +753,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
754
753
|
});
|
|
755
754
|
|
|
756
755
|
mockUlid.mockReturnValueOnce("iso-123");
|
|
757
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
756
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
758
757
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
759
758
|
const lastCall = collectors[collectors.length - 1];
|
|
760
759
|
if (lastCall) {
|
|
@@ -779,7 +778,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
779
778
|
});
|
|
780
779
|
|
|
781
780
|
it("uses conversation-level manual subagent provider/model defaults when tool input omits them", async () => {
|
|
782
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
781
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
783
782
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
784
783
|
const lastCall = collectors[collectors.length - 1];
|
|
785
784
|
if (lastCall) {
|
|
@@ -809,7 +808,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
809
808
|
});
|
|
810
809
|
|
|
811
810
|
it("manual subagent defaults override per-tool provider/model inputs", async () => {
|
|
812
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
811
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
813
812
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
814
813
|
const lastCall = collectors[collectors.length - 1];
|
|
815
814
|
if (lastCall) {
|
|
@@ -947,7 +946,7 @@ describe("executeSpawnSubagentTool", () => {
|
|
|
947
946
|
});
|
|
948
947
|
|
|
949
948
|
it("overrides system_prompt when specified", async () => {
|
|
950
|
-
mockHandleInvoke.mockImplementation((_db: any,
|
|
949
|
+
mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
|
|
951
950
|
const collectors = mockRegisterSubagentCollector.mock.calls;
|
|
952
951
|
const lastCall = collectors[collectors.length - 1];
|
|
953
952
|
if (lastCall) {
|