shadow-claw 1.40.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.well-known/mcp/server-card.json +2 -2
- package/.well-known/mcp/servers.json +1 -1
- package/.well-known/mcp.json +2 -2
- package/README.md +1 -0
- package/dist/cli/build/build.js +1 -1
- package/dist/cli/{chunk-Bfz2NYgD.js → chunk-0IeC97mU.js} +7 -7
- package/dist/cli/chunk-3oLxlxPn.js +1 -0
- package/dist/cli/{chunk-BXg4-9Rq2.js → chunk-8CrZyP1b2.js} +1 -1
- package/dist/cli/{chunk-BP5Hg6CM.js → chunk-B--ueArB.js} +1 -1
- package/dist/cli/chunk-BIh7rXlJ2.js +1 -0
- package/dist/cli/{chunk-Drr0VSGA2.js → chunk-BKnTOLLS2.js} +1 -1
- package/dist/cli/{chunk-C5PuRV08.js → chunk-BLMC1Bxv.js} +1 -1
- package/dist/cli/{chunk-B2tNSlFy2.js → chunk-BOigzz2U2.js} +1 -1
- package/dist/cli/{chunk-DOf3DZdR.js → chunk-BOzn335y.js} +1 -1
- package/dist/cli/chunk-BjOeVLb42.js +1 -0
- package/dist/cli/{chunk-DqTx0rRp2.js → chunk-Bjqh5_SU2.js} +1 -1
- package/dist/cli/chunk-BqWBd_jF2.js +1 -0
- package/dist/cli/{chunk-Bc9nRNyN.js → chunk-BvVUnHTq.js} +12 -9
- package/dist/cli/{chunk-DIbSoQmd2.js → chunk-C6FFByBU2.js} +2 -2
- package/dist/cli/{chunk-Drq18VZe.js → chunk-C9-aL3rF.js} +1 -1
- package/dist/cli/{chunk-BUhqHeEA2.js → chunk-C9czddEh2.js} +2 -2
- package/dist/cli/chunk-CCx8WOwz2.js +1 -0
- package/dist/cli/{chunk-BkMSjVJb.js → chunk-CK6ejMig.js} +1 -1
- package/dist/cli/chunk-CUUERioR2.js +1 -0
- package/dist/cli/chunk-CXAobnJd.js +1 -0
- package/dist/cli/chunk-CY1X0pOF2.js +1 -0
- package/dist/cli/chunk-CZvvgLVv.js +1 -0
- package/dist/cli/chunk-CbcwbfJB.js +1 -0
- package/dist/cli/{chunk-quilB3TV2.js → chunk-Ci9OJGcd2.js} +1 -1
- package/dist/cli/chunk-Cj9wl0qx.js +1 -0
- package/dist/cli/{chunk-3gRhOmGo2.js → chunk-CjJsVrKI2.js} +1 -1
- package/dist/cli/{chunk-CmEfzm-_.js → chunk-ClPZ4Rea.js} +1 -1
- package/dist/cli/{chunk-WMPAfIvV2.js → chunk-DHJCGRuG2.js} +1 -1
- package/dist/cli/{chunk-C7Y2xIk4.js → chunk-DKVkYTV9.js} +1 -1
- package/dist/cli/chunk-DR2XtWRo.js +1 -0
- package/dist/cli/{chunk-DID5VvOG.js → chunk-DTES-dE6.js} +3 -3
- package/dist/cli/{chunk-BiVJVh_S.js → chunk-DUlIqkaX.js} +7 -7
- package/dist/cli/{chunk-CkpueGaZ2.js → chunk-DjWle8FF2.js} +1 -1
- package/dist/cli/{chunk-CSvHmNOk.js → chunk-DmRXVLfy.js} +1 -1
- package/dist/cli/{chunk-BT1xXZn72.js → chunk-HlSiTC-u2.js} +1 -1
- package/dist/cli/{chunk-da0bsiOn.js → chunk-P4JSeFBI.js} +1 -1
- package/dist/cli/chunk-UcNbHaRQ.js +1 -0
- package/dist/cli/{chunk-BXFHFbEd.js → chunk-UweLmfQS.js} +1 -1
- package/dist/cli/chunk-bQQkVCw-.js +94 -0
- package/dist/cli/{chunk-CGiXWHTi2.js → chunk-gwpxl-0W2.js} +1 -1
- package/dist/cli/{chunk-NH8koEis2.js → chunk-nmDhxXH_2.js} +1 -1
- package/dist/cli/chunk-p0n_c-I2.js +1 -0
- package/dist/cli/{chunk-D7xP72La.js → chunk-q7r4FosZ.js} +1 -1
- package/dist/cli/cli.js +3 -3
- package/dist/cli/prerender/dsd-shell/prerender-dsd-shell.js +1 -1
- package/dist/electron/main.cjs +1 -1
- package/dist/headless-agent.js +1 -1
- package/dist/lib/{app-routes-BAEMLu9g.js → app-routes-CKkiX12g.js} +7 -2
- package/dist/lib/app-routes-CKkiX12g.js.map +1 -0
- 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/utils/syncSlottedSidebarActiveLinks.d.ts +10 -0
- 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/shadow-claw-file-viewer.d.ts +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-CPHDmyTx.js → config-DZkF9LiO.js} +2 -2
- package/dist/lib/{config-CPHDmyTx.js.map → config-DZkF9LiO.js.map} +1 -1
- package/dist/lib/{configurePeerJs-BsJoycQd.js → configurePeerJs-B3IE9BY2.js} +3 -3
- package/dist/lib/{configurePeerJs-BsJoycQd.js.map → configurePeerJs-B3IE9BY2.js.map} +1 -1
- package/dist/lib/{connections-BdIru7bF.js → connections-CalJGWvZ.js} +2 -2
- package/dist/lib/{connections-BdIru7bF.js.map → connections-CalJGWvZ.js.map} +1 -1
- package/dist/lib/core/orchestrator/orchestrator-state.d.ts +2 -1
- package/dist/lib/core/orchestrator/orchestrator.d.ts +2 -1
- package/dist/lib/core/orchestrator/utils/operations/task.d.ts +1 -0
- package/dist/lib/{downloadGroupFile-Dn0KsMlV.js → downloadGroupFile-DDE1fIhJ.js} +2 -2
- package/dist/lib/{downloadGroupFile-Dn0KsMlV.js.map → downloadGroupFile-DDE1fIhJ.js.map} +1 -1
- package/dist/lib/{file-viewer-BYrXXu-X.js → file-viewer-Bll2EoGc.js} +5 -5
- package/dist/lib/{file-viewer-BYrXXu-X.js.map → file-viewer-Bll2EoGc.js.map} +1 -1
- package/dist/lib/{getGroupDir-DF-RZO8X.js → getGroupDir-MHv7Lvmp.js} +4 -4
- package/dist/lib/{getGroupDir-DF-RZO8X.js.map → getGroupDir-MHv7Lvmp.js.map} +1 -1
- package/dist/lib/{git-s_0cgKm1.js → git-Bv_M3dgw.js} +3 -3
- package/dist/lib/{git-s_0cgKm1.js.map → git-Bv_M3dgw.js.map} +1 -1
- package/dist/lib/{iframe-sanitizer-DFdda1jJ.js → iframe-sanitizer-C7ZGDjEI.js} +2 -2
- package/dist/lib/{iframe-sanitizer-DFdda1jJ.js.map → iframe-sanitizer-C7ZGDjEI.js.map} +1 -1
- package/dist/lib/{iframe-storage-proxy-qrhZmQyO.js → iframe-storage-proxy-CR8ZYHPd.js} +2 -2
- package/dist/lib/{iframe-storage-proxy-qrhZmQyO.js.map → iframe-storage-proxy-CR8ZYHPd.js.map} +1 -1
- package/dist/lib/index.js +27 -27
- package/dist/lib/{initChatSplitResize-DuNlwCuI.js → initChatSplitResize-DiKTI-wk.js} +2 -2
- package/dist/lib/{initChatSplitResize-DuNlwCuI.js.map → initChatSplitResize-DiKTI-wk.js.map} +1 -1
- package/dist/lib/{initControlPlane-D4UZ4EhV.js → initControlPlane-CzjtQ4aM.js} +15 -15
- package/dist/lib/{initControlPlane-D4UZ4EhV.js.map → initControlPlane-CzjtQ4aM.js.map} +1 -1
- package/dist/lib/{markdown-CRRwbN9h.js → markdown-k8wA9LKy.js} +4 -4
- package/dist/lib/{markdown-CRRwbN9h.js.map → markdown-k8wA9LKy.js.map} +1 -1
- package/dist/lib/{mcp-reconnect-COdZ-cea.js → mcp-reconnect-CGIdfZnS.js} +2 -2
- package/dist/lib/{mcp-reconnect-COdZ-cea.js.map → mcp-reconnect-CGIdfZnS.js.map} +1 -1
- package/dist/lib/{memoryStorage-BsMe2FOQ.js → memoryStorage-DL-Bo3dh.js} +2 -2
- package/dist/lib/{memoryStorage-BsMe2FOQ.js.map → memoryStorage-DL-Bo3dh.js.map} +1 -1
- package/dist/lib/{orchestrator-D9f5fDCb.js → orchestrator-DKHCoikY.js} +11 -11
- package/dist/lib/{orchestrator-D9f5fDCb.js.map → orchestrator-DKHCoikY.js.map} +1 -1
- package/dist/lib/{orchestrator-Bq9ft3uG.js → orchestrator-Dn1ZOz9B.js} +20 -24
- package/dist/lib/orchestrator-Dn1ZOz9B.js.map +1 -0
- package/dist/lib/{peerjs-6u8KtenE.js → peerjs-BK41iBvP.js} +7 -7
- package/dist/lib/{peerjs-6u8KtenE.js.map → peerjs-BK41iBvP.js.map} +1 -1
- package/dist/lib/{push-client-DCnB2-OU.js → push-client-DKgVFD2Z.js} +3 -3
- package/dist/lib/{push-client-DCnB2-OU.js.map → push-client-DKgVFD2Z.js.map} +1 -1
- package/dist/lib/{readGroupFileBytes-nKNJ6sbl.js → readGroupFileBytes-CgU_UfGv.js} +2 -2
- package/dist/lib/{readGroupFileBytes-nKNJ6sbl.js.map → readGroupFileBytes-CgU_UfGv.js.map} +1 -1
- package/dist/lib/{shadow-claw-MumteAJy.js → shadow-claw-CtCj5Rn_.js} +121 -16
- package/dist/lib/shadow-claw-CtCj5Rn_.js.map +1 -0
- package/dist/lib/{shadow-claw-a2ui-Dipe8nY2.js → shadow-claw-a2ui-CvK5w940.js} +2 -2
- package/dist/lib/{shadow-claw-a2ui-Dipe8nY2.js.map → shadow-claw-a2ui-CvK5w940.js.map} +1 -1
- package/dist/lib/{shadow-claw-accounts-BgCkz3Zv.js → shadow-claw-accounts-Br3XdHro.js} +3 -3
- package/dist/lib/{shadow-claw-accounts-BgCkz3Zv.js.map → shadow-claw-accounts-Br3XdHro.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-CIm_Bxd2.js → shadow-claw-channel-config-Da2dN19M.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-CIm_Bxd2.js.map → shadow-claw-channel-config-Da2dN19M.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-CaceK52s.js → shadow-claw-channels-BofYHgz8.js} +3 -3
- package/dist/lib/{shadow-claw-channels-CaceK52s.js.map → shadow-claw-channels-BofYHgz8.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-BD18-mAR.js → shadow-claw-chat-Dw32DPV2.js} +12 -12
- package/dist/lib/{shadow-claw-chat-BD18-mAR.js.map → shadow-claw-chat-Dw32DPV2.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-U6LsfRPm.js → shadow-claw-control-plane-CwFotFDh.js} +7 -7
- package/dist/lib/{shadow-claw-control-plane-U6LsfRPm.js.map → shadow-claw-control-plane-CwFotFDh.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-CDsza_oB.js → shadow-claw-conversations-0UXge23k.js} +5 -5
- package/dist/lib/{shadow-claw-conversations-CDsza_oB.js.map → shadow-claw-conversations-0UXge23k.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-CMOnFmcP.js → shadow-claw-file-viewer-CAsn9NxH.js} +30 -30
- package/dist/lib/{shadow-claw-file-viewer-CMOnFmcP.js.map → shadow-claw-file-viewer-CAsn9NxH.js.map} +1 -1
- package/dist/lib/{shadow-claw-files-BI0P3m8a.js → shadow-claw-files-xGGhsHNH.js} +9 -9
- package/dist/lib/{shadow-claw-files-BI0P3m8a.js.map → shadow-claw-files-xGGhsHNH.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-xRApLEMN.js → shadow-claw-git-B606hcMU.js} +6 -6
- package/dist/lib/{shadow-claw-git-xRApLEMN.js.map → shadow-claw-git-B606hcMU.js.map} +1 -1
- package/dist/lib/{shadow-claw-integrations-B2e1Nfg1.js → shadow-claw-integrations-Bwq5cba1.js} +4 -4
- package/dist/lib/{shadow-claw-integrations-B2e1Nfg1.js.map → shadow-claw-integrations-Bwq5cba1.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-Bc2mWuGb.js → shadow-claw-llm-BgpcMBIy.js} +6 -6
- package/dist/lib/{shadow-claw-llm-Bc2mWuGb.js.map → shadow-claw-llm-BgpcMBIy.js.map} +1 -1
- package/dist/lib/{shadow-claw-mcp-remote-D_Bh3aeC.js → shadow-claw-mcp-remote-DvQCA-Bk.js} +4 -4
- package/dist/lib/{shadow-claw-mcp-remote-D_Bh3aeC.js.map → shadow-claw-mcp-remote-DvQCA-Bk.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-F5W3n5ci.js → shadow-claw-networking-Cxvf9c7E.js} +2 -2
- package/dist/lib/{shadow-claw-networking-F5W3n5ci.js.map → shadow-claw-networking-Cxvf9c7E.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-lvMt9WJ1.js → shadow-claw-notifications-CGVcFYBy.js} +3 -3
- package/dist/lib/{shadow-claw-notifications-lvMt9WJ1.js.map → shadow-claw-notifications-CGVcFYBy.js.map} +1 -1
- package/dist/lib/{shadow-claw-page-header-6gq6EMqX.js → shadow-claw-page-header-DAYz3I_o.js} +2 -2
- package/dist/lib/{shadow-claw-page-header-6gq6EMqX.js.map → shadow-claw-page-header-DAYz3I_o.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-Bo8_z2S-.js → shadow-claw-pages-BLeEZb9k.js} +24 -12
- package/dist/lib/shadow-claw-pages-BLeEZb9k.js.map +1 -0
- package/dist/lib/{shadow-claw-peerjs-DRTLCVDQ.js → shadow-claw-peerjs-BcFnbK74.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-DRTLCVDQ.js.map → shadow-claw-peerjs-BcFnbK74.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-D00B4p4L.js → shadow-claw-settings-B7o0Z4hu.js} +9 -9
- package/dist/lib/{shadow-claw-settings-D00B4p4L.js.map → shadow-claw-settings-B7o0Z4hu.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-DgMe7-Zo.js → shadow-claw-storage-afMVqB7E.js} +5 -5
- package/dist/lib/{shadow-claw-storage-DgMe7-Zo.js.map → shadow-claw-storage-afMVqB7E.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-D103YOuI.js → shadow-claw-task-server-B9-MQjl6.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-D103YOuI.js.map → shadow-claw-task-server-B9-MQjl6.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-6OhALkq1.js → shadow-claw-tasks-Dc4BC-t-.js} +8 -8
- package/dist/lib/{shadow-claw-tasks-6OhALkq1.js.map → shadow-claw-tasks-Dc4BC-t-.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-BGtxA1qD.js → shadow-claw-terminal-BINcTdsk.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-BGtxA1qD.js.map → shadow-claw-terminal-BINcTdsk.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-OeIwAnnd.js → shadow-claw-tools-BjFgXNLR.js} +7 -7
- package/dist/lib/{shadow-claw-tools-OeIwAnnd.js.map → shadow-claw-tools-BjFgXNLR.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-gVFZ197u.js → shadow-claw-webvm-Xe3ByMDw.js} +3 -3
- package/dist/lib/{shadow-claw-webvm-gVFZ197u.js.map → shadow-claw-webvm-Xe3ByMDw.js.map} +1 -1
- package/dist/lib/subsystems/mcp/webmcp.d.ts +64 -0
- package/dist/lib/{syncWebMcpRegistration-Bbph0XZl.js → syncWebMcpRegistration-D7alChz0.js} +21 -6
- package/dist/lib/syncWebMcpRegistration-D7alChz0.js.map +1 -0
- package/dist/lib/{tools-D0OlSzMD.js → tools-Cmhpk3X8.js} +4 -4
- package/dist/lib/{tools-D0OlSzMD.js.map → tools-Cmhpk3X8.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/{utils-DYdrO2KI.js → utils-CzgKe_XZ.js} +4 -4
- package/dist/lib/{utils-DYdrO2KI.js.map → utils-CzgKe_XZ.js.map} +1 -1
- package/dist/lib/{webmcp-D2bocsgh.js → webmcp-oEP9YpR2.js} +119 -3
- package/dist/lib/{webmcp-D2bocsgh.js.map → webmcp-oEP9YpR2.js.map} +1 -1
- package/dist/public/.well-known/mcp/server-card.json +2 -2
- package/dist/public/.well-known/mcp/servers.json +1 -1
- package/dist/public/.well-known/mcp.json +2 -2
- package/dist/public/AGENTS.md +2 -1
- package/dist/public/README.md +1 -0
- package/dist/public/agent.worker.js +1 -1
- package/dist/public/app-routes-C6-H2zPH.js +1 -0
- package/dist/public/components/shadow-claw/shadow-claw.css +1 -1
- package/dist/public/components/shadow-claw/shadow-claw.html +1 -1
- package/dist/public/components/shadow-claw-pages/shadow-claw-pages.css +1 -1
- package/dist/public/{config-D4lVqMs8.js → config-Dewnqegf.js} +1 -1
- package/dist/public/{configurePeerJs-DDOAVSaH.js → configurePeerJs-CaPU2sN5.js} +1 -1
- package/dist/public/{connections-CiukjGiH.js → connections-CwE7jE9l.js} +1 -1
- package/dist/public/{custom-element-security-piU2U-Ec.js → custom-element-security-DLgHMf5R.js} +1 -1
- package/dist/public/docs/decisions/native-web-components-and-signals.md +1 -1
- package/dist/public/docs/example/article/index.html +5 -5
- package/dist/public/docs/guides/publishing-to-github-pages.md +49 -6
- package/dist/public/docs/publishing/index.html +5 -5
- package/dist/public/docs/skill-creator/index.html +5 -5
- package/dist/public/docs/subsystems/pages.md +10 -3
- package/dist/public/docs/subsystems/webmcp.md +89 -1
- package/dist/public/{downloadGroupFile-BiZQYY-O.js → downloadGroupFile-ChWHuap_.js} +1 -1
- package/dist/public/e2e/README.md +2 -2
- package/dist/public/{e2e-bridge-CybB810Q.js → e2e-bridge-BkaldjV2.js} +1 -1
- package/dist/public/{file-viewer-DLUBvOVD.js → file-viewer-Df4qUJCn.js} +1 -1
- package/dist/public/{getGroupDir-CLz5c8cg.js → getGroupDir-CeSr4fzS.js} +1 -1
- package/dist/public/{git-Ba8AeviI.js → git-Bscc1tK-.js} +2 -2
- package/dist/public/{iframe-sanitizer-CKOO7cxp.js → iframe-sanitizer-BVdkQsor.js} +1 -1
- package/dist/public/{iframe-storage-proxy-BvRiccH0.js → iframe-storage-proxy-Cg8aFw7o.js} +1 -1
- package/dist/public/index.css +1 -1
- package/dist/public/index.html +5 -5
- package/dist/public/index.js +1 -1
- package/dist/public/{initChatSplitResize-osJXM2gu.js → initChatSplitResize-C3Rp1LeZ.js} +1 -1
- package/dist/public/{initControlPlane-CNggzsRw.js → initControlPlane-C1pnzG16.js} +1 -1
- package/dist/public/llms.txt +1 -1
- package/dist/public/main/index.html +5 -5
- package/dist/public/main/memory/index.html +5 -5
- package/dist/public/{markdown-CZA-Ye2Q.js → markdown-D3A902nT.js} +1 -1
- package/dist/public/{mcp-reconnect-BK1bYBdC.js → mcp-reconnect-BJWxQBm_.js} +1 -1
- package/dist/public/{memoryStorage-Bew1X8Uy.js → memoryStorage-ykv-Ri-y.js} +1 -1
- package/dist/public/{orchestrator-D6tel2Zp.js → orchestrator-BVnC4Vtt.js} +2 -2
- package/dist/public/{orchestrator-BLkS_jpm.js → orchestrator-CQcc7OFA.js} +2 -2
- package/dist/public/{peerjs-CYs1F7sq.js → peerjs-CYC2cI1Y.js} +1 -1
- package/dist/public/{push-client-_HUyJlFJ.js → push-client-BJrnOULM.js} +1 -1
- package/dist/public/service-worker/fetch-proxy.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-DmrxnX3Q.js → shadow-claw-WwfOu-tu.js} +33 -3
- package/dist/public/{shadow-claw-accounts-BqGrm47Z.js → shadow-claw-accounts-BFZxrPsH.js} +1 -1
- package/dist/public/{shadow-claw-channels-Ci2UPaaA.js → shadow-claw-channels-C0w0c1EF.js} +1 -1
- package/dist/public/{shadow-claw-chat-BxR6cBYQ.js → shadow-claw-chat-DIJ0A-QN.js} +1 -1
- package/dist/public/{shadow-claw-control-plane-C1A-CZ9H.js → shadow-claw-control-plane-DZoxUd-1.js} +2 -2
- package/dist/public/{shadow-claw-conversations-DcwG05-H.js → shadow-claw-conversations-DMyG_5zj.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-a_uRA30F.js → shadow-claw-file-viewer-DYgZjZb9.js} +2 -2
- package/dist/public/{shadow-claw-files-B774Xz1d.js → shadow-claw-files-DIOUdKJr.js} +1 -1
- package/dist/public/{shadow-claw-git-CTIPP0vs.js → shadow-claw-git-if5S0QJr.js} +2 -2
- package/dist/public/{shadow-claw-integrations-CjtkA6l0.js → shadow-claw-integrations-BQt4hcWe.js} +1 -1
- package/dist/public/{shadow-claw-llm-DfmITHde.js → shadow-claw-llm-9uf1KFA0.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-BPuV22So.js → shadow-claw-mcp-remote-COpNIzJd.js} +1 -1
- package/dist/public/{shadow-claw-networking-DEMMygy0.js → shadow-claw-networking-AOVRUn6B.js} +1 -1
- package/dist/public/{shadow-claw-notifications-B9Xhcj1P.js → shadow-claw-notifications-CKB-W1TA.js} +1 -1
- package/dist/public/{shadow-claw-page-header-CAXokjQy.js → shadow-claw-page-header-D4LmUigA.js} +1 -1
- package/dist/public/{shadow-claw-pages-BRQw8bTm.js → shadow-claw-pages-BpHRY4vH.js} +12 -3
- package/dist/public/{shadow-claw-settings-BGrDNyqh.js → shadow-claw-settings-CE-aUo_J.js} +3 -3
- package/dist/public/{shadow-claw-storage-DK3pf11w.js → shadow-claw-storage-CFKC-Y3V.js} +1 -1
- package/dist/public/{shadow-claw-task-server-CMp5Vjza.js → shadow-claw-task-server-B_ZjqK4B.js} +1 -1
- package/dist/public/{shadow-claw-tasks-BO8aXM2B.js → shadow-claw-tasks-CGsEv48K.js} +1 -1
- package/dist/public/{shadow-claw-terminal-BSeTuyDa.js → shadow-claw-terminal-DcaS7cPH.js} +1 -1
- package/dist/public/{shadow-claw-tools-Bj6DLZ-2.js → shadow-claw-tools-Cnu9hKy0.js} +1 -1
- package/dist/public/{shadow-claw-webvm-M7d5RH8H.js → shadow-claw-webvm-BB8SFvJ8.js} +1 -1
- package/dist/public/syncWebMcpRegistration-D2Zx4oA1.js +1 -0
- package/dist/public/theme-init.js +1 -1
- package/dist/public/{tools-nysPKnGT.js → tools-sOLCHTj8.js} +1 -1
- package/dist/public/{webmcp-Bo3KTgRb.js → webmcp-YFt6vM1_.js} +1 -1
- package/dist/server.js +189 -189
- package/package.json +1 -1
- package/src/cli/cli.ts +2 -2
- package/src/cli/prerender/dsd-shell/prerender-dsd-shell.test.ts +4 -1
- package/src/cli/prerender/dsd-shell/prerender-dsd-shell.ts +7 -1
- package/src/cli/prerender/utils/insert-before-closing-head.test.ts +12 -0
- package/src/cli/prerender/utils/insert-before-closing-head.ts +4 -6
- package/src/cli/site-config/apply.test.ts +90 -0
- package/src/cli/site-config/apply.ts +181 -13
- package/src/components/shadow-claw/shadow-claw.css +26 -0
- package/src/components/shadow-claw/shadow-claw.html +4 -0
- package/src/components/shadow-claw/utils/applyRoute.ts +3 -0
- package/src/components/shadow-claw/utils/bindEventListeners.test.ts +6 -0
- package/src/components/shadow-claw/utils/bindEventListeners.ts +30 -1
- package/src/components/shadow-claw/utils/getRoute.test.ts +52 -0
- package/src/components/shadow-claw/utils/getRoute.ts +18 -0
- package/src/components/shadow-claw/utils/navigateToRoute.test.ts +21 -0
- package/src/components/shadow-claw/utils/navigateToRoute.ts +10 -0
- package/src/components/shadow-claw/utils/sidebarVisibility.ts +12 -4
- package/src/components/shadow-claw/utils/syncSlottedSidebarActiveLinks.test.ts +93 -0
- package/src/components/shadow-claw/utils/syncSlottedSidebarActiveLinks.ts +100 -0
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +31 -31
- package/src/components/shadow-claw-pages/shadow-claw-pages.css +10 -1
- package/src/components/shadow-claw-pages/utils/removePreviewIframe.ts +3 -0
- package/src/core/effect.test.ts +19 -0
- package/src/core/orchestrator/orchestrator-state.ts +2 -1
- package/src/core/orchestrator/orchestrator.test.ts +686 -5
- package/src/core/orchestrator/orchestrator.ts +3 -10
- package/src/core/orchestrator/utils/compactContext.test.ts +423 -121
- package/src/core/orchestrator/utils/configurePeerJs.test.ts +27 -0
- package/src/core/orchestrator/utils/deliverResponse.test.ts +127 -0
- package/src/core/orchestrator/utils/dispatchSubagentInvoke.test.ts +23 -0
- package/src/core/orchestrator/utils/enqueue.test.ts +520 -86
- package/src/core/orchestrator/utils/handleWorkerMessage.test.ts +664 -144
- package/src/core/orchestrator/utils/initTasks.node.test.ts +147 -0
- package/src/core/orchestrator/utils/initTasks.test.ts +926 -191
- package/src/core/orchestrator/utils/initTasks.ts +5 -4
- package/src/core/orchestrator/utils/invokeAgent.test.ts +563 -110
- package/src/core/orchestrator/utils/invokeAgent.ts +8 -10
- package/src/core/orchestrator/utils/loadChannelConfigurations.test.ts +50 -0
- package/src/core/orchestrator/utils/operations/channel.test.ts +377 -170
- package/src/core/orchestrator/utils/operations/provider.test.ts +663 -85
- package/src/core/orchestrator/utils/operations/room.test.ts +74 -11
- package/src/core/orchestrator/utils/operations/task.test.ts +452 -56
- package/src/core/orchestrator/utils/operations/task.ts +1 -1
- package/src/core/orchestrator/utils/operations/vm.test.ts +66 -7
- package/src/core/orchestrator/utils/parseDirectToolCommand.test.ts +6 -0
- package/src/core/orchestrator/utils/settings.test.ts +248 -81
- package/src/core/orchestrator/utils/setupPushTaskListener.test.ts +58 -0
- package/src/core/orchestrator/utils/syncWebMcpRegistration.test.ts +392 -64
- package/src/core/orchestrator/utils/syncWebMcpRegistration.ts +32 -3
- package/src/server/middleware/static-files.test.ts +36 -0
- package/src/server/middleware/static-files.ts +14 -6
- package/src/server/routes/mcp.ts +2 -2
- package/src/storage/staticRouting.test.ts +36 -0
- package/src/storage/staticRouting.ts +31 -3
- package/src/stores/file-viewer.test.ts +11 -0
- package/src/stores/theme.test.ts +41 -2
- package/src/stores/toast.test.ts +25 -0
- package/src/subsystems/mcp/webmcp.test.ts +255 -0
- package/src/subsystems/mcp/webmcp.ts +253 -0
- package/src/worker/tools/bash/native-bash-executor.test.ts +31 -1
- package/src/worker/tools/git/utils/extractConflictPaths.test.ts +24 -0
- package/src/worker/tools/git/utils/parseConflictRegions.test.ts +46 -0
- package/src/worker/tools/git/utils/resolveCorsProxy.test.ts +26 -5
- package/src/worker/tools/git/utils/truncateSnippet.test.ts +16 -0
- package/src/worker/tools/node-transformers-executor.test.ts +105 -6
- package/src/worker/tools/remote-mcp/remote-mcp.test.ts +172 -47
- package/src/worker/tools/remote-mcp/utils/formatListToolsOutput.test.ts +19 -0
- package/src/worker/tools/remote-mcp/utils/isMcpReauthError.test.ts +45 -0
- package/src/worker/tools/remote-mcp/utils/resolveMcpReauth.test.ts +48 -0
- package/src/worker/tools/rooms/list-room-members.test.ts +24 -10
- package/src/worker/tools/tasks/list-tasks.test.ts +39 -8
- package/src/worker/tools/tasks/update-task.test.ts +78 -14
- package/src/worker/tools/ui/javascript.test.ts +70 -17
- package/src/worker/tools/ui/list-tool-profiles.test.ts +31 -9
- package/dist/cli/chunk-00GAzVPl2.js +0 -1
- package/dist/cli/chunk-2hnFoNNC.js +0 -1
- package/dist/cli/chunk-BKQL4nzF2.js +0 -1
- package/dist/cli/chunk-BQ4K3fqj2.js +0 -1
- package/dist/cli/chunk-BVCGo6uf2.js +0 -1
- package/dist/cli/chunk-BcTH_-FL.js +0 -1
- package/dist/cli/chunk-BmD_sPRt.js +0 -1
- package/dist/cli/chunk-BsxNqqer.js +0 -1
- package/dist/cli/chunk-CCcF5T-c.js +0 -1
- package/dist/cli/chunk-CFhvwUeL.js +0 -91
- package/dist/cli/chunk-CwWtvULn.js +0 -1
- package/dist/cli/chunk-Drf-hXIR2.js +0 -1
- package/dist/cli/chunk-Dt5HNYVi.js +0 -1
- package/dist/cli/chunk-DwZQi9Ax.js +0 -1
- package/dist/cli/chunk-m9ZX7TyF2.js +0 -1
- package/dist/lib/app-routes-BAEMLu9g.js.map +0 -1
- package/dist/lib/orchestrator-Bq9ft3uG.js.map +0 -1
- package/dist/lib/shadow-claw-MumteAJy.js.map +0 -1
- package/dist/lib/shadow-claw-pages-Bo8_z2S-.js.map +0 -1
- package/dist/lib/syncWebMcpRegistration-Bbph0XZl.js.map +0 -1
- package/dist/public/app-routes-BMQ4HFaM.js +0 -1
- package/dist/public/syncWebMcpRegistration-4bT0YUyZ.js +0 -1
|
@@ -1,33 +1,71 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { ProviderConfig } from "../../../config/config.js";
|
|
3
|
+
import type { MessageAttachment } from "../../../content/types.js";
|
|
4
|
+
import type { ShadowClawDatabase } from "../../../db/db.js";
|
|
5
|
+
import type { GroupMeta, StoredMessage } from "../../../db/types.js";
|
|
6
|
+
import type {
|
|
7
|
+
ChannelType,
|
|
8
|
+
InboundMessage,
|
|
9
|
+
} from "../../../subsystems/channels/types.js";
|
|
10
|
+
import type {
|
|
11
|
+
SkillDiagnostic,
|
|
12
|
+
SkillRecord,
|
|
13
|
+
} from "../../../subsystems/skills/types.js";
|
|
14
|
+
import type { Orchestrator } from "../orchestrator.js";
|
|
15
|
+
import type { ParsedDirectToolCommand } from "./types.js";
|
|
16
|
+
|
|
17
|
+
const mockClearPeerJsTypingState = jest.fn<(groupId: string) => void>();
|
|
4
18
|
jest.unstable_mockModule("./operations/channel.js", () => ({
|
|
5
19
|
clearPeerJsTypingState: mockClearPeerJsTypingState,
|
|
6
20
|
}));
|
|
7
21
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
const mockParseDirectToolCommand =
|
|
23
|
+
jest.fn<
|
|
24
|
+
(
|
|
25
|
+
policy: unknown,
|
|
26
|
+
assistantName: string,
|
|
27
|
+
msg: InboundMessage,
|
|
28
|
+
) => ParsedDirectToolCommand | null
|
|
29
|
+
>();
|
|
11
30
|
jest.unstable_mockModule("./parseDirectToolCommand.js", () => ({
|
|
12
31
|
parseDirectToolCommand: mockParseDirectToolCommand,
|
|
13
32
|
}));
|
|
14
33
|
|
|
15
|
-
const mockDiscoverSkills =
|
|
34
|
+
const mockDiscoverSkills =
|
|
35
|
+
jest.fn<
|
|
36
|
+
(
|
|
37
|
+
db: ShadowClawDatabase,
|
|
38
|
+
groupId: string,
|
|
39
|
+
) => Promise<{ skills: SkillRecord[]; diagnostics: SkillDiagnostic[] }>
|
|
40
|
+
>();
|
|
16
41
|
jest.unstable_mockModule(
|
|
17
42
|
"../../../subsystems/skills/discoverSkills.js",
|
|
18
43
|
() => ({ discoverSkills: mockDiscoverSkills }),
|
|
19
44
|
);
|
|
20
45
|
|
|
21
|
-
const mockGetApiKeyForRequest =
|
|
46
|
+
const mockGetApiKeyForRequest =
|
|
47
|
+
jest.fn<(o: Orchestrator) => Promise<string | null>>();
|
|
22
48
|
jest.unstable_mockModule("./operations/provider.js", () => ({
|
|
23
49
|
getApiKeyForRequest: mockGetApiKeyForRequest,
|
|
24
50
|
}));
|
|
25
51
|
|
|
26
|
-
const mockDetectProviderHelpType =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
52
|
+
const mockDetectProviderHelpType =
|
|
53
|
+
jest.fn<
|
|
54
|
+
(providerId: string, reason: string, requiresApiKey: boolean) => string
|
|
55
|
+
>();
|
|
56
|
+
const mockGetProvider = jest.fn<(id: string) => ProviderConfig | null>();
|
|
57
|
+
const mockPersistMessageAttachments =
|
|
58
|
+
jest.fn<
|
|
59
|
+
(
|
|
60
|
+
db: ShadowClawDatabase,
|
|
61
|
+
groupId: string,
|
|
62
|
+
attachments: MessageAttachment[],
|
|
63
|
+
) => Promise<MessageAttachment[]>
|
|
64
|
+
>();
|
|
65
|
+
const mockListGroups =
|
|
66
|
+
jest.fn<(db: ShadowClawDatabase) => Promise<GroupMeta[]>>();
|
|
67
|
+
const mockSaveMessage =
|
|
68
|
+
jest.fn<(db: ShadowClawDatabase, msg: StoredMessage) => Promise<void>>();
|
|
31
69
|
|
|
32
70
|
jest.unstable_mockModule(
|
|
33
71
|
"../../../components/common/help/providers.js",
|
|
@@ -59,39 +97,130 @@ jest.unstable_mockModule("../../../db/saveMessage.js", () => ({
|
|
|
59
97
|
saveMessage: mockSaveMessage,
|
|
60
98
|
}));
|
|
61
99
|
|
|
62
|
-
const mockInvokeAgent =
|
|
100
|
+
const mockInvokeAgent =
|
|
101
|
+
jest.fn<
|
|
102
|
+
(
|
|
103
|
+
o: unknown,
|
|
104
|
+
db: unknown,
|
|
105
|
+
groupId: string,
|
|
106
|
+
content: string,
|
|
107
|
+
freshContext?: boolean,
|
|
108
|
+
subagent?: boolean,
|
|
109
|
+
) => Promise<void>
|
|
110
|
+
>();
|
|
63
111
|
jest.unstable_mockModule("./invokeAgent.js", () => ({
|
|
64
112
|
invokeAgent: mockInvokeAgent,
|
|
65
113
|
}));
|
|
66
114
|
|
|
115
|
+
const { clearPeerJsTypingState } = await import("./operations/channel.js");
|
|
67
116
|
const { enqueue, processQueue } = await import("./enqueue.js");
|
|
68
117
|
|
|
118
|
+
interface MockOrchestrator {
|
|
119
|
+
events: {
|
|
120
|
+
emit: jest.Mock<(_event: string, _payload: unknown) => void>;
|
|
121
|
+
};
|
|
122
|
+
channelRegistry: {
|
|
123
|
+
shouldAutoTrigger: jest.Mock<(_channel: ChannelType) => boolean>;
|
|
124
|
+
};
|
|
125
|
+
triggerPattern: RegExp;
|
|
126
|
+
peerCompletedContexts: Set<string>;
|
|
127
|
+
peerjsMyPeerId: string;
|
|
128
|
+
peerjsMyAlias: string;
|
|
129
|
+
peerjsPeerAliases: Record<string, string>;
|
|
130
|
+
messageQueue: Array<{
|
|
131
|
+
groupId: string;
|
|
132
|
+
content: string;
|
|
133
|
+
freshContext?: boolean;
|
|
134
|
+
subagent?: boolean;
|
|
135
|
+
}>;
|
|
136
|
+
clearPeerJsTypingState: jest.Mock<() => void>;
|
|
137
|
+
router: {
|
|
138
|
+
send: jest.Mock<
|
|
139
|
+
(
|
|
140
|
+
_groupId: string,
|
|
141
|
+
_content: string,
|
|
142
|
+
_attachments: MessageAttachment[],
|
|
143
|
+
) => Promise<void>
|
|
144
|
+
>;
|
|
145
|
+
};
|
|
146
|
+
agentWorker: {
|
|
147
|
+
postMessage: jest.Mock<(_msg: unknown) => void>;
|
|
148
|
+
};
|
|
149
|
+
processQueue: jest.Mock<() => void>;
|
|
150
|
+
providerConfig: {
|
|
151
|
+
requiresApiKey: boolean;
|
|
152
|
+
};
|
|
153
|
+
provider: string;
|
|
154
|
+
getApiKey: jest.Mock<() => Promise<string | null>>;
|
|
155
|
+
getApiKeyForSpecificProvider: jest.Mock<
|
|
156
|
+
(_db: ShadowClawDatabase, _prov: string) => Promise<string | null>
|
|
157
|
+
>;
|
|
158
|
+
directToolCommandPolicy: {
|
|
159
|
+
enabledChannelTypes: ChannelType[];
|
|
160
|
+
};
|
|
161
|
+
assistantName: string;
|
|
162
|
+
processing: boolean;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function makeInboundMessage(
|
|
166
|
+
overrides: Partial<InboundMessage> = {},
|
|
167
|
+
): InboundMessage {
|
|
168
|
+
return {
|
|
169
|
+
id: "msg-1",
|
|
170
|
+
groupId: "g1",
|
|
171
|
+
sender: "user",
|
|
172
|
+
content: "test message",
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
channel: "browser",
|
|
175
|
+
...overrides,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
69
179
|
describe("enqueue & processQueue", () => {
|
|
70
|
-
let mockOrchestrator:
|
|
71
|
-
|
|
180
|
+
let mockOrchestrator: MockOrchestrator;
|
|
181
|
+
const mockDb = {} as ShadowClawDatabase;
|
|
72
182
|
|
|
73
183
|
beforeEach(() => {
|
|
74
184
|
jest.clearAllMocks();
|
|
75
|
-
mockDb = {};
|
|
76
185
|
mockOrchestrator = {
|
|
77
186
|
events: { emit: jest.fn() },
|
|
78
|
-
channelRegistry: {
|
|
187
|
+
channelRegistry: {
|
|
188
|
+
shouldAutoTrigger: jest
|
|
189
|
+
.fn<(_channel: ChannelType) => boolean>()
|
|
190
|
+
.mockReturnValue(false),
|
|
191
|
+
},
|
|
79
192
|
triggerPattern: /trigger/i,
|
|
80
|
-
peerCompletedContexts: new Set(),
|
|
193
|
+
peerCompletedContexts: new Set<string>(),
|
|
81
194
|
peerjsMyPeerId: "my-id",
|
|
82
195
|
peerjsMyAlias: "my-alias",
|
|
83
196
|
peerjsPeerAliases: { "peer2-alias": "peer2-id" },
|
|
84
197
|
messageQueue: [],
|
|
85
198
|
clearPeerJsTypingState: jest.fn(),
|
|
86
|
-
router: {
|
|
199
|
+
router: {
|
|
200
|
+
send: jest
|
|
201
|
+
.fn<
|
|
202
|
+
(
|
|
203
|
+
_groupId: string,
|
|
204
|
+
_content: string,
|
|
205
|
+
_attachments: MessageAttachment[],
|
|
206
|
+
) => Promise<void>
|
|
207
|
+
>()
|
|
208
|
+
.mockResolvedValue(undefined),
|
|
209
|
+
},
|
|
87
210
|
agentWorker: { postMessage: jest.fn() },
|
|
88
211
|
processQueue: jest.fn(),
|
|
89
212
|
providerConfig: { requiresApiKey: true },
|
|
90
213
|
provider: "test-provider",
|
|
91
|
-
getApiKey:
|
|
92
|
-
|
|
214
|
+
getApiKey: jest
|
|
215
|
+
.fn<() => Promise<string | null>>()
|
|
216
|
+
.mockResolvedValue("key"),
|
|
217
|
+
getApiKeyForSpecificProvider: jest
|
|
218
|
+
.fn<
|
|
219
|
+
(_db: ShadowClawDatabase, _prov: string) => Promise<string | null>
|
|
220
|
+
>()
|
|
221
|
+
.mockResolvedValue("key"),
|
|
93
222
|
directToolCommandPolicy: {
|
|
94
|
-
enabledChannelTypes: ["browser", "peerjs"
|
|
223
|
+
enabledChannelTypes: ["browser", "peerjs"],
|
|
95
224
|
},
|
|
96
225
|
assistantName: "Assistant",
|
|
97
226
|
processing: false,
|
|
@@ -111,34 +240,64 @@ describe("enqueue & processQueue", () => {
|
|
|
111
240
|
});
|
|
112
241
|
|
|
113
242
|
it("should emit A2UI envelopes and actions and exit if no text/attachments", async () => {
|
|
114
|
-
const msg
|
|
243
|
+
const msg = makeInboundMessage({
|
|
115
244
|
groupId: "g1",
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
245
|
+
content: "",
|
|
246
|
+
a2uiEnvelopes: [
|
|
247
|
+
{
|
|
248
|
+
surfaceId: "s1",
|
|
249
|
+
data: {},
|
|
250
|
+
} as unknown as InboundMessage["a2uiEnvelopes"] extends Array<infer U>
|
|
251
|
+
? U
|
|
252
|
+
: never,
|
|
253
|
+
],
|
|
254
|
+
a2uiAction: {
|
|
255
|
+
actionId: "test",
|
|
256
|
+
} as unknown as InboundMessage["a2uiAction"],
|
|
257
|
+
});
|
|
119
258
|
|
|
120
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
259
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
121
260
|
|
|
122
261
|
expect(mockOrchestrator.events.emit).toHaveBeenCalledWith(
|
|
123
262
|
"a2ui-surface",
|
|
124
|
-
{ groupId: "g1", envelope: {
|
|
263
|
+
{ groupId: "g1", envelope: { surfaceId: "s1", data: {} } },
|
|
125
264
|
);
|
|
126
265
|
expect(mockOrchestrator.events.emit).toHaveBeenCalledWith("a2ui-action", {
|
|
127
266
|
groupId: "g1",
|
|
128
|
-
action: {
|
|
267
|
+
action: { actionId: "test" },
|
|
129
268
|
});
|
|
130
269
|
expect(mockSaveMessage).not.toHaveBeenCalled();
|
|
131
270
|
});
|
|
132
271
|
|
|
272
|
+
it("should proceed to normal handling if message has a2uiAction but no envelopes", async () => {
|
|
273
|
+
const msg = makeInboundMessage({
|
|
274
|
+
groupId: "g1",
|
|
275
|
+
content: "",
|
|
276
|
+
a2uiAction: {
|
|
277
|
+
actionId: "test-action",
|
|
278
|
+
} as unknown as InboundMessage["a2uiAction"],
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
282
|
+
|
|
283
|
+
expect(mockSaveMessage).toHaveBeenCalled();
|
|
284
|
+
});
|
|
285
|
+
|
|
133
286
|
it("should process normal message, detect trigger, persist and enqueue", async () => {
|
|
134
|
-
const msg
|
|
287
|
+
const msg = makeInboundMessage({
|
|
135
288
|
groupId: "g1",
|
|
136
289
|
content: "hello trigger",
|
|
137
290
|
channel: "browser",
|
|
291
|
+
});
|
|
292
|
+
const persistedAttachment: MessageAttachment = {
|
|
293
|
+
fileName: "test.png",
|
|
294
|
+
mimeType: "image/png",
|
|
295
|
+
path: "/path/test.png",
|
|
296
|
+
size: 100,
|
|
138
297
|
};
|
|
139
|
-
mockPersistMessageAttachments.mockResolvedValue([
|
|
298
|
+
mockPersistMessageAttachments.mockResolvedValue([persistedAttachment]);
|
|
140
299
|
|
|
141
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
300
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
142
301
|
|
|
143
302
|
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
144
303
|
mockDb,
|
|
@@ -151,24 +310,143 @@ describe("enqueue & processQueue", () => {
|
|
|
151
310
|
);
|
|
152
311
|
});
|
|
153
312
|
|
|
313
|
+
it("should auto-trigger from browser channel for regular conversations", async () => {
|
|
314
|
+
const msg = makeInboundMessage({
|
|
315
|
+
groupId: "normal-group",
|
|
316
|
+
content: "regular message without keywords",
|
|
317
|
+
channel: "browser",
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
321
|
+
|
|
322
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
323
|
+
mockDb,
|
|
324
|
+
expect.objectContaining({ isTrigger: true }),
|
|
325
|
+
);
|
|
326
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(1);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("should not auto-trigger from browser channel in peer and room channels", async () => {
|
|
330
|
+
const peerMsg = makeInboundMessage({
|
|
331
|
+
groupId: "peer:peer-1",
|
|
332
|
+
content: "direct peer message",
|
|
333
|
+
channel: "browser",
|
|
334
|
+
});
|
|
335
|
+
await enqueue(
|
|
336
|
+
mockOrchestrator as unknown as Orchestrator,
|
|
337
|
+
mockDb,
|
|
338
|
+
peerMsg,
|
|
339
|
+
);
|
|
340
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
341
|
+
mockDb,
|
|
342
|
+
expect.objectContaining({ isTrigger: false }),
|
|
343
|
+
);
|
|
344
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
345
|
+
|
|
346
|
+
const roomMsg = makeInboundMessage({
|
|
347
|
+
groupId: "room:room-1",
|
|
348
|
+
content: "direct room message",
|
|
349
|
+
channel: "browser",
|
|
350
|
+
});
|
|
351
|
+
await enqueue(
|
|
352
|
+
mockOrchestrator as unknown as Orchestrator,
|
|
353
|
+
mockDb,
|
|
354
|
+
roomMsg,
|
|
355
|
+
);
|
|
356
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
357
|
+
mockDb,
|
|
358
|
+
expect.objectContaining({ isTrigger: false }),
|
|
359
|
+
);
|
|
360
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("should reopen completed peer context when local user sends message from browser", async () => {
|
|
364
|
+
mockOrchestrator.peerCompletedContexts.add("peer:finished-task");
|
|
365
|
+
const msg = makeInboundMessage({
|
|
366
|
+
groupId: "peer:finished-task",
|
|
367
|
+
content: "reopen message",
|
|
368
|
+
channel: "browser",
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
372
|
+
|
|
373
|
+
expect(
|
|
374
|
+
mockOrchestrator.peerCompletedContexts.has("peer:finished-task"),
|
|
375
|
+
).toBe(false);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it("should suppress auto-trigger for peer conversations in peerCompletedContexts", async () => {
|
|
379
|
+
mockOrchestrator.peerCompletedContexts.add("peer:finished-task");
|
|
380
|
+
const msg = makeInboundMessage({
|
|
381
|
+
groupId: "peer:finished-task",
|
|
382
|
+
content: "hey @my-alias more work",
|
|
383
|
+
channel: "peerjs",
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
387
|
+
|
|
388
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
389
|
+
mockDb,
|
|
390
|
+
expect.objectContaining({ isTrigger: false }),
|
|
391
|
+
);
|
|
392
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it("should trigger if message mentions my exact peer ID", async () => {
|
|
396
|
+
const msg = makeInboundMessage({
|
|
397
|
+
groupId: "peer:group",
|
|
398
|
+
content: "hey @my-id can you help?",
|
|
399
|
+
channel: "peerjs",
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
403
|
+
|
|
404
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
405
|
+
mockDb,
|
|
406
|
+
expect.objectContaining({ isTrigger: true }),
|
|
407
|
+
);
|
|
408
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(1);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it("should trigger if message mentions an alias mapping to peerjsMyPeerId", async () => {
|
|
412
|
+
mockOrchestrator.peerjsPeerAliases = {
|
|
413
|
+
"friendly-peer": "my-id",
|
|
414
|
+
"other-peer": "different-id",
|
|
415
|
+
};
|
|
416
|
+
const msg = makeInboundMessage({
|
|
417
|
+
groupId: "peer:group",
|
|
418
|
+
content: "hey @friendly-peer check this out",
|
|
419
|
+
channel: "peerjs",
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
423
|
+
|
|
424
|
+
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
425
|
+
mockDb,
|
|
426
|
+
expect.objectContaining({ isTrigger: true }),
|
|
427
|
+
);
|
|
428
|
+
expect(mockOrchestrator.messageQueue).toHaveLength(1);
|
|
429
|
+
});
|
|
430
|
+
|
|
154
431
|
it("should route a user-invocable skill slash command to the agent", async () => {
|
|
432
|
+
const skill: SkillRecord = {
|
|
433
|
+
name: "toast-random-number",
|
|
434
|
+
description: "Show a random number",
|
|
435
|
+
userInvocable: true,
|
|
436
|
+
path: "/path/skill",
|
|
437
|
+
basePath: "/path",
|
|
438
|
+
};
|
|
155
439
|
mockDiscoverSkills.mockResolvedValue({
|
|
156
|
-
skills: [
|
|
157
|
-
{
|
|
158
|
-
name: "toast-random-number",
|
|
159
|
-
description: "Show a random number",
|
|
160
|
-
userInvocable: true,
|
|
161
|
-
},
|
|
162
|
-
],
|
|
440
|
+
skills: [skill],
|
|
163
441
|
diagnostics: [],
|
|
164
442
|
});
|
|
165
|
-
const msg
|
|
443
|
+
const msg = makeInboundMessage({
|
|
166
444
|
groupId: "g1",
|
|
167
445
|
content: "/toast-random-number",
|
|
168
446
|
channel: "peerjs",
|
|
169
|
-
};
|
|
447
|
+
});
|
|
170
448
|
|
|
171
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
449
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
172
450
|
|
|
173
451
|
expect(mockOrchestrator.messageQueue[0]).toEqual(
|
|
174
452
|
expect.objectContaining({
|
|
@@ -183,30 +461,31 @@ describe("enqueue & processQueue", () => {
|
|
|
183
461
|
});
|
|
184
462
|
|
|
185
463
|
it("should execute a declarative skill chain without queueing an agent turn", async () => {
|
|
464
|
+
const skill: SkillRecord = {
|
|
465
|
+
name: "toast-random-number",
|
|
466
|
+
description: "Show a random number",
|
|
467
|
+
userInvocable: true,
|
|
468
|
+
path: "/path/skill",
|
|
469
|
+
basePath: "/path",
|
|
470
|
+
execution: {
|
|
471
|
+
type: "tools",
|
|
472
|
+
tools: [
|
|
473
|
+
{ name: "javascript", input: { code: "1" } },
|
|
474
|
+
{ name: "show_toast", input: { message: { $pipe: "prev" } } },
|
|
475
|
+
],
|
|
476
|
+
},
|
|
477
|
+
};
|
|
186
478
|
mockDiscoverSkills.mockResolvedValue({
|
|
187
|
-
skills: [
|
|
188
|
-
{
|
|
189
|
-
name: "toast-random-number",
|
|
190
|
-
description: "Show a random number",
|
|
191
|
-
userInvocable: true,
|
|
192
|
-
execution: {
|
|
193
|
-
type: "tools",
|
|
194
|
-
tools: [
|
|
195
|
-
{ name: "javascript", input: { code: "1" } },
|
|
196
|
-
{ name: "show_toast", input: { message: { $pipe: "prev" } } },
|
|
197
|
-
],
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
],
|
|
479
|
+
skills: [skill],
|
|
201
480
|
diagnostics: [],
|
|
202
481
|
});
|
|
203
|
-
const msg
|
|
482
|
+
const msg = makeInboundMessage({
|
|
204
483
|
groupId: "g1",
|
|
205
484
|
content: "/toast-random-number",
|
|
206
485
|
channel: "browser",
|
|
207
|
-
};
|
|
486
|
+
});
|
|
208
487
|
|
|
209
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
488
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
210
489
|
|
|
211
490
|
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
212
491
|
expect(mockOrchestrator.agentWorker.postMessage).toHaveBeenCalledWith({
|
|
@@ -218,14 +497,65 @@ describe("enqueue & processQueue", () => {
|
|
|
218
497
|
});
|
|
219
498
|
});
|
|
220
499
|
|
|
500
|
+
it("should populate rawInput on declarative tools with arguments when input is empty or non-object", async () => {
|
|
501
|
+
const skill: SkillRecord = {
|
|
502
|
+
name: "echo-skill",
|
|
503
|
+
description: "Echo skill with arguments",
|
|
504
|
+
userInvocable: true,
|
|
505
|
+
path: "/path/skill",
|
|
506
|
+
basePath: "/path",
|
|
507
|
+
execution: {
|
|
508
|
+
type: "tools",
|
|
509
|
+
tools: [
|
|
510
|
+
{ name: "tool-with-empty-input", input: {} },
|
|
511
|
+
{
|
|
512
|
+
name: "tool-with-non-object-input",
|
|
513
|
+
input: null as unknown as Record<string, unknown>,
|
|
514
|
+
},
|
|
515
|
+
{ name: "tool-with-existing-input", input: { existing: "val" } },
|
|
516
|
+
],
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
mockDiscoverSkills.mockResolvedValue({
|
|
520
|
+
skills: [skill],
|
|
521
|
+
diagnostics: [],
|
|
522
|
+
});
|
|
523
|
+
const msg = makeInboundMessage({
|
|
524
|
+
groupId: "g1",
|
|
525
|
+
content: "/echo-skill hello world arguments",
|
|
526
|
+
channel: "browser",
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
530
|
+
|
|
531
|
+
expect(mockOrchestrator.agentWorker.postMessage).toHaveBeenCalledWith({
|
|
532
|
+
type: "execute-skill-tools",
|
|
533
|
+
payload: {
|
|
534
|
+
groupId: "g1",
|
|
535
|
+
skillName: "echo-skill",
|
|
536
|
+
tools: [
|
|
537
|
+
{
|
|
538
|
+
name: "tool-with-empty-input",
|
|
539
|
+
input: { rawInput: "hello world arguments" },
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: "tool-with-non-object-input",
|
|
543
|
+
input: { rawInput: "hello world arguments" },
|
|
544
|
+
},
|
|
545
|
+
{ name: "tool-with-existing-input", input: { existing: "val" } },
|
|
546
|
+
],
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
|
|
221
551
|
it("should handle direct tool commands without enqueuing for invokeAgent", async () => {
|
|
222
552
|
mockParseDirectToolCommand.mockReturnValue({
|
|
223
553
|
toolName: "tool1",
|
|
224
|
-
input: "input",
|
|
554
|
+
input: { text: "input" },
|
|
225
555
|
});
|
|
226
|
-
const msg
|
|
556
|
+
const msg = makeInboundMessage({ groupId: "g1", content: "cmd" });
|
|
227
557
|
|
|
228
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
558
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
229
559
|
|
|
230
560
|
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
231
561
|
mockDb,
|
|
@@ -234,17 +564,17 @@ describe("enqueue & processQueue", () => {
|
|
|
234
564
|
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
235
565
|
expect(mockOrchestrator.agentWorker.postMessage).toHaveBeenCalledWith({
|
|
236
566
|
type: "execute-direct-tool",
|
|
237
|
-
payload: { groupId: "g1", name: "tool1", input: "input" },
|
|
567
|
+
payload: { groupId: "g1", name: "tool1", input: { text: "input" } },
|
|
238
568
|
});
|
|
239
569
|
});
|
|
240
570
|
|
|
241
571
|
it("should trigger if mentioned by peerjs alias", async () => {
|
|
242
|
-
const msg
|
|
572
|
+
const msg = makeInboundMessage({
|
|
243
573
|
groupId: "peer:g1",
|
|
244
574
|
content: "hey @my-alias",
|
|
245
575
|
channel: "peerjs",
|
|
246
|
-
};
|
|
247
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
576
|
+
});
|
|
577
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
248
578
|
|
|
249
579
|
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
250
580
|
mockDb,
|
|
@@ -254,8 +584,11 @@ describe("enqueue & processQueue", () => {
|
|
|
254
584
|
});
|
|
255
585
|
|
|
256
586
|
it("should trigger if scheduled task", async () => {
|
|
257
|
-
const msg
|
|
258
|
-
|
|
587
|
+
const msg = makeInboundMessage({
|
|
588
|
+
groupId: "g1",
|
|
589
|
+
content: "[SCHEDULED TASK] go",
|
|
590
|
+
});
|
|
591
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
259
592
|
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
260
593
|
mockDb,
|
|
261
594
|
expect.objectContaining({ isTrigger: true }),
|
|
@@ -263,35 +596,52 @@ describe("enqueue & processQueue", () => {
|
|
|
263
596
|
});
|
|
264
597
|
|
|
265
598
|
it("should trigger if A2UI action message", async () => {
|
|
266
|
-
const msg
|
|
267
|
-
|
|
599
|
+
const msg = makeInboundMessage({
|
|
600
|
+
groupId: "g1",
|
|
601
|
+
content: "[A2UI ACTION] click",
|
|
602
|
+
});
|
|
603
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
268
604
|
expect(mockSaveMessage).toHaveBeenCalledWith(
|
|
269
605
|
mockDb,
|
|
270
606
|
expect.objectContaining({ isTrigger: true }),
|
|
271
607
|
);
|
|
272
608
|
});
|
|
273
609
|
|
|
274
|
-
it("should route browser message to peer channel", async () => {
|
|
275
|
-
const msg
|
|
610
|
+
it("should route browser message to peer channel and handle send errors", async () => {
|
|
611
|
+
const msg = makeInboundMessage({
|
|
276
612
|
groupId: "peer:g1",
|
|
277
613
|
content: "hello",
|
|
278
614
|
channel: "browser",
|
|
279
|
-
};
|
|
280
|
-
|
|
615
|
+
});
|
|
616
|
+
mockOrchestrator.router.send.mockRejectedValueOnce(
|
|
617
|
+
new Error("Network drop"),
|
|
618
|
+
);
|
|
619
|
+
const consoleErrorSpy = jest
|
|
620
|
+
.spyOn(console, "error")
|
|
621
|
+
.mockImplementation(() => {});
|
|
622
|
+
|
|
623
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
624
|
+
|
|
281
625
|
expect(mockOrchestrator.router.send).toHaveBeenCalledWith(
|
|
282
626
|
"peer:g1",
|
|
283
627
|
"hello",
|
|
284
628
|
[],
|
|
285
629
|
);
|
|
630
|
+
await Promise.resolve();
|
|
631
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
632
|
+
"Failed to route browser message to peer:",
|
|
633
|
+
expect.any(Error),
|
|
634
|
+
);
|
|
635
|
+
consoleErrorSpy.mockRestore();
|
|
286
636
|
});
|
|
287
637
|
|
|
288
638
|
it("should clear peerJs typing state for peerjs channel", async () => {
|
|
289
|
-
const msg
|
|
639
|
+
const msg = makeInboundMessage({
|
|
290
640
|
groupId: "peer:g1",
|
|
291
641
|
content: "hello",
|
|
292
642
|
channel: "peerjs",
|
|
293
|
-
};
|
|
294
|
-
await enqueue(mockOrchestrator, mockDb, msg);
|
|
643
|
+
});
|
|
644
|
+
await enqueue(mockOrchestrator as unknown as Orchestrator, mockDb, msg);
|
|
295
645
|
expect(clearPeerJsTypingState).toHaveBeenCalledWith("peer:g1");
|
|
296
646
|
});
|
|
297
647
|
});
|
|
@@ -299,18 +649,18 @@ describe("enqueue & processQueue", () => {
|
|
|
299
649
|
describe("processQueue", () => {
|
|
300
650
|
it("should do nothing if processing or queue is empty", async () => {
|
|
301
651
|
mockOrchestrator.processing = true;
|
|
302
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
652
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
303
653
|
expect(mockInvokeAgent).not.toHaveBeenCalled();
|
|
304
654
|
|
|
305
655
|
mockOrchestrator.processing = false;
|
|
306
656
|
mockOrchestrator.messageQueue = [];
|
|
307
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
657
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
308
658
|
expect(mockInvokeAgent).not.toHaveBeenCalled();
|
|
309
659
|
});
|
|
310
660
|
|
|
311
661
|
it("should process next message if API key present", async () => {
|
|
312
662
|
mockOrchestrator.messageQueue = [{ groupId: "g1", content: "hello" }];
|
|
313
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
663
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
314
664
|
expect(mockInvokeAgent).toHaveBeenCalledWith(
|
|
315
665
|
mockOrchestrator,
|
|
316
666
|
mockDb,
|
|
@@ -323,12 +673,87 @@ describe("enqueue & processQueue", () => {
|
|
|
323
673
|
expect(mockOrchestrator.messageQueue).toHaveLength(0);
|
|
324
674
|
});
|
|
325
675
|
|
|
676
|
+
it("should process message without checking API key if provider does not require one", async () => {
|
|
677
|
+
mockOrchestrator.messageQueue = [
|
|
678
|
+
{ groupId: "g1", content: "local message" },
|
|
679
|
+
];
|
|
680
|
+
mockOrchestrator.providerConfig = { requiresApiKey: false };
|
|
681
|
+
|
|
682
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
683
|
+
|
|
684
|
+
expect(mockGetApiKeyForRequest).not.toHaveBeenCalled();
|
|
685
|
+
expect(mockInvokeAgent).toHaveBeenCalledWith(
|
|
686
|
+
mockOrchestrator,
|
|
687
|
+
mockDb,
|
|
688
|
+
"g1",
|
|
689
|
+
"local message",
|
|
690
|
+
undefined,
|
|
691
|
+
undefined,
|
|
692
|
+
);
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it("should process message without groupId lookup when nextMsg groupId is empty", async () => {
|
|
696
|
+
mockOrchestrator.messageQueue = [{ groupId: "", content: "no group" }];
|
|
697
|
+
|
|
698
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
699
|
+
|
|
700
|
+
expect(mockListGroups).not.toHaveBeenCalled();
|
|
701
|
+
expect(mockInvokeAgent).toHaveBeenCalledWith(
|
|
702
|
+
mockOrchestrator,
|
|
703
|
+
mockDb,
|
|
704
|
+
"",
|
|
705
|
+
"no group",
|
|
706
|
+
undefined,
|
|
707
|
+
undefined,
|
|
708
|
+
);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it("should fallback to default provider if pinned provider is not found", async () => {
|
|
712
|
+
mockOrchestrator.messageQueue = [{ groupId: "g1", content: "hello" }];
|
|
713
|
+
mockListGroups.mockResolvedValue([
|
|
714
|
+
{
|
|
715
|
+
groupId: "g1",
|
|
716
|
+
name: "Group 1",
|
|
717
|
+
createdAt: Date.now(),
|
|
718
|
+
pinnedProvider: "unknown-prov",
|
|
719
|
+
} as GroupMeta,
|
|
720
|
+
]);
|
|
721
|
+
mockGetProvider.mockReturnValue(null);
|
|
722
|
+
|
|
723
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
724
|
+
|
|
725
|
+
expect(mockInvokeAgent).toHaveBeenCalledWith(
|
|
726
|
+
mockOrchestrator,
|
|
727
|
+
mockDb,
|
|
728
|
+
"g1",
|
|
729
|
+
"hello",
|
|
730
|
+
undefined,
|
|
731
|
+
undefined,
|
|
732
|
+
);
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
it("should handle listGroups error gracefully in processQueue", async () => {
|
|
736
|
+
mockOrchestrator.messageQueue = [{ groupId: "g1", content: "hello" }];
|
|
737
|
+
mockListGroups.mockRejectedValueOnce(new Error("Storage unavailable"));
|
|
738
|
+
|
|
739
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
740
|
+
|
|
741
|
+
expect(mockInvokeAgent).toHaveBeenCalledWith(
|
|
742
|
+
mockOrchestrator,
|
|
743
|
+
mockDb,
|
|
744
|
+
"g1",
|
|
745
|
+
"hello",
|
|
746
|
+
undefined,
|
|
747
|
+
undefined,
|
|
748
|
+
);
|
|
749
|
+
});
|
|
750
|
+
|
|
326
751
|
it("should emit provider-help if API key missing", async () => {
|
|
327
752
|
mockOrchestrator.messageQueue = [{ groupId: "g1", content: "hello" }];
|
|
328
753
|
mockGetApiKeyForRequest.mockResolvedValue(null);
|
|
329
754
|
mockDetectProviderHelpType.mockReturnValue("help");
|
|
330
755
|
|
|
331
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
756
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
332
757
|
|
|
333
758
|
expect(mockOrchestrator.events.emit).toHaveBeenCalledWith(
|
|
334
759
|
"provider-help",
|
|
@@ -348,7 +773,7 @@ describe("enqueue & processQueue", () => {
|
|
|
348
773
|
.spyOn(console, "error")
|
|
349
774
|
.mockImplementation(() => {});
|
|
350
775
|
|
|
351
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
776
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
352
777
|
|
|
353
778
|
expect(consoleError).toHaveBeenCalled();
|
|
354
779
|
expect(mockOrchestrator.processing).toBe(false);
|
|
@@ -364,7 +789,7 @@ describe("enqueue & processQueue", () => {
|
|
|
364
789
|
|
|
365
790
|
mockInvokeAgent.mockImplementation(() => Promise.resolve());
|
|
366
791
|
|
|
367
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
792
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
368
793
|
|
|
369
794
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
370
795
|
|
|
@@ -391,14 +816,23 @@ describe("enqueue & processQueue", () => {
|
|
|
391
816
|
it("should lookup pinned provider for API key check", async () => {
|
|
392
817
|
mockOrchestrator.messageQueue = [{ groupId: "g1", content: "hello" }];
|
|
393
818
|
mockListGroups.mockResolvedValue([
|
|
394
|
-
{
|
|
819
|
+
{
|
|
820
|
+
groupId: "g1",
|
|
821
|
+
name: "Group 1",
|
|
822
|
+
createdAt: Date.now(),
|
|
823
|
+
pinnedProvider: "pinned-prov",
|
|
824
|
+
} as GroupMeta,
|
|
395
825
|
]);
|
|
396
|
-
mockGetProvider.mockReturnValue({
|
|
826
|
+
mockGetProvider.mockReturnValue({
|
|
827
|
+
id: "pinned-prov",
|
|
828
|
+
name: "Pinned Provider",
|
|
829
|
+
requiresApiKey: true,
|
|
830
|
+
} as unknown as ProviderConfig);
|
|
397
831
|
mockOrchestrator.getApiKeyForSpecificProvider.mockResolvedValue(
|
|
398
832
|
"pinned-key",
|
|
399
833
|
);
|
|
400
834
|
|
|
401
|
-
await processQueue(mockOrchestrator, mockDb);
|
|
835
|
+
await processQueue(mockOrchestrator as unknown as Orchestrator, mockDb);
|
|
402
836
|
|
|
403
837
|
expect(
|
|
404
838
|
mockOrchestrator.getApiKeyForSpecificProvider,
|