shadow-claw 1.59.6 → 1.60.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 +1 -1
- package/.well-known/mcp.json +1 -1
- package/README.md +6 -2
- package/dist/cli/build/build.js +1 -1
- package/dist/cli/chunk-3C5izdQW.js +1 -0
- package/dist/cli/chunk-B-75h9gX.js +1 -0
- package/dist/cli/{chunk-C9o6lXP3.js → chunk-B7Kn-otm.js} +1 -1
- package/dist/cli/{chunk-YX32FcN7.js → chunk-BBczgswQ.js} +1 -1
- package/dist/cli/{chunk-DcNxjqH6.js → chunk-BE-lYWcn.js} +1 -1
- package/dist/cli/{chunk-DJqHK-qS.js → chunk-BECr0WxI.js} +11 -11
- package/dist/cli/chunk-BEz1PD1_.js +1 -0
- package/dist/cli/chunk-BLzI1Fp2.js +1 -0
- package/dist/cli/{chunk-yiVdvGCJ.js → chunk-BVSC1MNQ.js} +11 -11
- package/dist/cli/{chunk-CX2itile.js → chunk-BdWcep6o.js} +1 -1
- package/dist/cli/{chunk-DLde6nuO.js → chunk-BfTpnSS4.js} +1 -1
- package/dist/cli/{chunk-D2_eAO83.js → chunk-BgvqTf7w.js} +1 -1
- package/dist/cli/chunk-BwsJfUT3.js +1 -0
- package/dist/cli/{chunk--PFY91kE.js → chunk-C9b4b7c_.js} +1 -1
- package/dist/cli/{chunk-D3y7h9Xe.js → chunk-CAw9XYFe.js} +1 -1
- package/dist/cli/chunk-CFCcbFs2.js +396 -0
- package/dist/cli/{chunk-Cnjb8Usu.js → chunk-CTarF4FC.js} +1 -1
- package/dist/cli/{chunk-DM4xsTry.js → chunk-Cbq5hpjb.js} +4 -4
- package/dist/cli/chunk-CjTjKy_v.js +310 -0
- package/dist/cli/chunk-Cjyu4cr_.js +36 -0
- package/dist/cli/{chunk-DUGZPka_.js → chunk-ClMKygjZ.js} +1 -1
- package/dist/cli/chunk-Cppnq1KF.js +1 -0
- package/dist/cli/{chunk-DvemF16v.js → chunk-D9QCNFMO.js} +1 -1
- package/dist/cli/chunk-DB21BMqt.js +7 -0
- package/dist/cli/{chunk-_Vo-o_e3.js → chunk-DHoIWvCc.js} +1 -1
- package/dist/cli/chunk-DZEN9T5y.js +1 -0
- package/dist/cli/{chunk-5rLO4DWS.js → chunk-Dl14OyYO.js} +9 -9
- package/dist/cli/chunk-Dl_vv0dI.js +1 -0
- package/dist/cli/chunk-Dpmfhlyl.js +1 -0
- package/dist/cli/{chunk-BrR1DOBS.js → chunk-Du7Xtucq.js} +1 -1
- package/dist/cli/{chunk-Bc_weULz.js → chunk-DxcDFUi_.js} +1 -1
- package/dist/cli/{chunk-Dt7-hzJU.js → chunk-DyyEWbV7.js} +1 -1
- package/dist/cli/chunk-N0x3mXU0.js +1 -0
- package/dist/cli/{chunk-CGoE4llV.js → chunk-V-w0Bata.js} +1 -1
- package/dist/cli/{chunk-C8DBACtx.js → chunk-ZxDxSSn-.js} +1 -1
- package/dist/cli/chunk-lPvFUkd5.js +7 -0
- package/dist/cli/{chunk-Ctg5L55n.js → chunk-n5s-sCdU.js} +1 -1
- package/dist/cli/{chunk-Dw8GndPD.js → chunk-nD9VPVMq.js} +1 -1
- package/dist/cli/{chunk-Cq_kQohv.js → chunk-rFuy8aS_.js} +1 -1
- package/dist/cli/{chunk-Bq38OubR.js → chunk-wjM6JXWa.js} +1 -1
- package/dist/cli/{chunk-3wTukVof.js → chunk-zcES9rut.js} +1 -1
- package/dist/cli/cli.js +3 -3
- package/dist/headless-agent.js +2 -2
- package/dist/lib/{app-routes-DJdIjp2V.js → app-routes-BXiRvlNl.js} +7 -25
- package/dist/lib/{app-routes-DJdIjp2V.js.map → app-routes-BXiRvlNl.js.map} +1 -1
- package/dist/lib/{attachment-capabilities-Dbb-4ZP5.js → attachment-capabilities-BjkEPip8.js} +2 -2
- package/dist/lib/{attachment-capabilities-Dbb-4ZP5.js.map → attachment-capabilities-BjkEPip8.js.map} +1 -1
- package/dist/lib/{channel-Dlru5ofR.js → channel-DB77spML.js} +3 -3
- package/dist/lib/{channel-Dlru5ofR.js.map → channel-DB77spML.js.map} +1 -1
- package/dist/lib/{chat-template-BuuLY8l7.js → chat-template-DPEKGJhB.js} +2 -2
- package/dist/lib/{chat-template-BuuLY8l7.js.map → chat-template-DPEKGJhB.js.map} +1 -1
- package/dist/lib/{compact-context-BtR55YPU.js → compact-context-Q9t9aL1e.js} +19 -19
- package/dist/lib/{compact-context-BtR55YPU.js.map → compact-context-Q9t9aL1e.js.map} +1 -1
- package/dist/lib/components/common/shadow-claw-provider-model-picker.js +1 -1
- package/dist/lib/components/index.js +27 -27
- 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-provider-model-picker.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-DxNI3TlW.js → config-BrHR97zt.js} +2 -2
- package/dist/lib/{config-DxNI3TlW.js.map → config-BrHR97zt.js.map} +1 -1
- package/dist/lib/{configure-peer-js-ChDhOZU4.js → configure-peer-js-CgFiwoxY.js} +3 -3
- package/dist/lib/{configure-peer-js-ChDhOZU4.js.map → configure-peer-js-CgFiwoxY.js.map} +1 -1
- package/dist/lib/{connections-DC4NZkJE.js → connections-C1FWsBsE.js} +2 -2
- package/dist/lib/{connections-DC4NZkJE.js.map → connections-C1FWsBsE.js.map} +1 -1
- package/dist/lib/content/build-attachment-content-blocks.d.ts +2 -0
- package/dist/lib/{credentials-5vpz0XPk.js → credentials-CZbngHXW.js} +2 -2
- package/dist/lib/{credentials-5vpz0XPk.js.map → credentials-CZbngHXW.js.map} +1 -1
- package/dist/lib/{discover-skills-CD0sKvAI.js → discover-skills-CXyaWHKi.js} +13 -13
- package/dist/lib/{discover-skills-CD0sKvAI.js.map → discover-skills-CXyaWHKi.js.map} +1 -1
- package/dist/lib/{download-group-file-Dk3qaxhJ.js → download-group-file-D0wgg10Q.js} +2 -2
- package/dist/lib/{download-group-file-Dk3qaxhJ.js.map → download-group-file-D0wgg10Q.js.map} +1 -1
- package/dist/lib/{file-viewer-B4pRW-_G.js → file-viewer-DOfvX6yy.js} +5 -5
- package/dist/lib/{file-viewer-B4pRW-_G.js.map → file-viewer-DOfvX6yy.js.map} +1 -1
- package/dist/lib/{get-or-create-subscriber-id-HCcgDEPz.js → get-or-create-subscriber-id-wyzaML7Z.js} +2 -2
- package/dist/lib/{get-or-create-subscriber-id-HCcgDEPz.js.map → get-or-create-subscriber-id-wyzaML7Z.js.map} +1 -1
- package/dist/lib/{git-B3Q1euc5.js → git-CogDRlEz.js} +5 -5
- package/dist/lib/{git-B3Q1euc5.js.map → git-CogDRlEz.js.map} +1 -1
- package/dist/lib/{iframe-bridge-scripts-D8iuFhUk.js → iframe-bridge-scripts-Dx825LLG.js} +2 -2
- package/dist/lib/{iframe-bridge-scripts-D8iuFhUk.js.map → iframe-bridge-scripts-Dx825LLG.js.map} +1 -1
- package/dist/lib/index.js +28 -28
- package/dist/lib/{init-chat-split-resize-B0ODULx9.js → init-chat-split-resize-Cc0bd2z9.js} +2 -2
- package/dist/lib/{init-chat-split-resize-B0ODULx9.js.map → init-chat-split-resize-Cc0bd2z9.js.map} +1 -1
- package/dist/lib/{init-control-plane-C1FRRmjC.js → init-control-plane-CEGdzgWX.js} +15 -15
- package/dist/lib/{init-control-plane-C1FRRmjC.js.map → init-control-plane-CEGdzgWX.js.map} +1 -1
- package/dist/lib/{invoke-agent-CzN7sVh-.js → invoke-agent-cac3gCsj.js} +11 -11
- package/dist/lib/{invoke-agent-CzN7sVh-.js.map → invoke-agent-cac3gCsj.js.map} +1 -1
- package/dist/lib/{markdown-mbNo7cV3.js → markdown--6vTAPEH.js} +2 -2
- package/dist/lib/{markdown-mbNo7cV3.js.map → markdown--6vTAPEH.js.map} +1 -1
- package/dist/lib/{mcp-reconnect-3T7yWGEY.js → mcp-reconnect-BeqQvNWO.js} +3 -3
- package/dist/lib/{mcp-reconnect-3T7yWGEY.js.map → mcp-reconnect-BeqQvNWO.js.map} +1 -1
- package/dist/lib/{model-ranking-DGNSWYwN.js → model-ranking-BhsJV7vb.js} +2 -2
- package/dist/lib/{model-ranking-DGNSWYwN.js.map → model-ranking-BhsJV7vb.js.map} +1 -1
- package/dist/lib/{move-group-entry-NMTJ59M9.js → move-group-entry-D8dptMg0.js} +5 -5
- package/dist/lib/{move-group-entry-NMTJ59M9.js.map → move-group-entry-D8dptMg0.js.map} +1 -1
- package/dist/lib/{orchestrator-B8FV1V7x.js → orchestrator-BBAwy9Nm.js} +24 -24
- package/dist/lib/{orchestrator-B8FV1V7x.js.map → orchestrator-BBAwy9Nm.js.map} +1 -1
- package/dist/lib/{orchestrator-i_QJ-o22.js → orchestrator-cRBe3lhq.js} +11 -11
- package/dist/lib/orchestrator-cRBe3lhq.js.map +1 -0
- package/dist/lib/{parse-path-DPCn-HwI.js → parse-path-BOHQP_IQ.js} +3 -3
- package/dist/lib/{parse-path-DPCn-HwI.js.map → parse-path-BOHQP_IQ.js.map} +1 -1
- package/dist/lib/{peerjs-z5zeioPV.js → peerjs-BLg8aGUj.js} +8 -8
- package/dist/lib/{peerjs-z5zeioPV.js.map → peerjs-BLg8aGUj.js.map} +1 -1
- package/dist/lib/{process-peer-query-param-CJp7w7AU.js → process-peer-query-param-BnsVnxzH.js} +5 -5
- package/dist/lib/{process-peer-query-param-CJp7w7AU.js.map → process-peer-query-param-BnsVnxzH.js.map} +1 -1
- package/dist/lib/{process-pending-shared-payloads-B6_TlBFA.js → process-pending-shared-payloads-DBZfZOOa.js} +4 -4
- package/dist/lib/{process-pending-shared-payloads-B6_TlBFA.js.map → process-pending-shared-payloads-DBZfZOOa.js.map} +1 -1
- package/dist/lib/{process-room-query-param-C3FFGGn6.js → process-room-query-param-B8EYg_-r.js} +4 -4
- package/dist/lib/{process-room-query-param-C3FFGGn6.js.map → process-room-query-param-B8EYg_-r.js.map} +1 -1
- package/dist/lib/{provider-DcQZypu5.js → provider-BC9KPI14.js} +3 -3
- package/dist/lib/{provider-DcQZypu5.js.map → provider-BC9KPI14.js.map} +1 -1
- package/dist/lib/{push-client-Cx5rMs6J.js → push-client-CAm6UMvE.js} +5 -5
- package/dist/lib/{push-client-Cx5rMs6J.js.map → push-client-CAm6UMvE.js.map} +1 -1
- package/dist/lib/{read-group-file-bytes-CXOG_YyM.js → read-group-file-bytes-UQIk1eJG.js} +2 -2
- package/dist/lib/{read-group-file-bytes-CXOG_YyM.js.map → read-group-file-bytes-UQIk1eJG.js.map} +1 -1
- package/dist/lib/{rooms-CwlkYLDU.js → rooms-Dzphx3rK.js} +2 -2
- package/dist/lib/{rooms-CwlkYLDU.js.map → rooms-Dzphx3rK.js.map} +1 -1
- package/dist/lib/{shadow-claw-DoQ7fgl5.js → shadow-claw-CGl8tXtG.js} +17 -20
- package/dist/lib/shadow-claw-CGl8tXtG.js.map +1 -0
- package/dist/lib/{shadow-claw-a2ui-Br6qJMs1.js → shadow-claw-a2ui-lG0vQbW8.js} +2 -2
- package/dist/lib/{shadow-claw-a2ui-Br6qJMs1.js.map → shadow-claw-a2ui-lG0vQbW8.js.map} +1 -1
- package/dist/lib/{shadow-claw-accounts-BTDILfWw.js → shadow-claw-accounts-CkqyCxwp.js} +3 -3
- package/dist/lib/{shadow-claw-accounts-BTDILfWw.js.map → shadow-claw-accounts-CkqyCxwp.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-IKiL34tI.js → shadow-claw-channel-config-BNIWCdsL.js} +4 -4
- package/dist/lib/{shadow-claw-channel-config-IKiL34tI.js.map → shadow-claw-channel-config-BNIWCdsL.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-JgEzuHWK.js → shadow-claw-channels-C2QSn4Ew.js} +3 -3
- package/dist/lib/{shadow-claw-channels-JgEzuHWK.js.map → shadow-claw-channels-C2QSn4Ew.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-SGUDT31r.js → shadow-claw-chat-Wx3y9y6c.js} +15 -15
- package/dist/lib/{shadow-claw-chat-SGUDT31r.js.map → shadow-claw-chat-Wx3y9y6c.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-CRWFZ3vD.js → shadow-claw-control-plane-D5E4cFGu.js} +7 -7
- package/dist/lib/{shadow-claw-control-plane-CRWFZ3vD.js.map → shadow-claw-control-plane-D5E4cFGu.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-D23GJ7qo.js → shadow-claw-conversations-BtDv7GRW.js} +7 -7
- package/dist/lib/{shadow-claw-conversations-D23GJ7qo.js.map → shadow-claw-conversations-BtDv7GRW.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-C1V8WTiU.js → shadow-claw-file-viewer-CG40kwWV.js} +10 -10
- package/dist/lib/{shadow-claw-file-viewer-C1V8WTiU.js.map → shadow-claw-file-viewer-CG40kwWV.js.map} +1 -1
- package/dist/lib/{shadow-claw-files-DN7irmE1.js → shadow-claw-files-BOUULrlX.js} +11 -11
- package/dist/lib/{shadow-claw-files-DN7irmE1.js.map → shadow-claw-files-BOUULrlX.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-D-1oIh65.js → shadow-claw-git-BeHV73_9.js} +6 -6
- package/dist/lib/{shadow-claw-git-D-1oIh65.js.map → shadow-claw-git-BeHV73_9.js.map} +1 -1
- package/dist/lib/{shadow-claw-integrations-CZjnm7cM.js → shadow-claw-integrations-RZZ-m-Id.js} +4 -4
- package/dist/lib/{shadow-claw-integrations-CZjnm7cM.js.map → shadow-claw-integrations-RZZ-m-Id.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-4Gefh5FN.js → shadow-claw-llm-KONyWKZM.js} +9 -9
- package/dist/lib/{shadow-claw-llm-4Gefh5FN.js.map → shadow-claw-llm-KONyWKZM.js.map} +1 -1
- package/dist/lib/{shadow-claw-mcp-remote-B9ssb3YV.js → shadow-claw-mcp-remote-BKFROurv.js} +4 -4
- package/dist/lib/{shadow-claw-mcp-remote-B9ssb3YV.js.map → shadow-claw-mcp-remote-BKFROurv.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-BN5BB4hb.js → shadow-claw-networking-Diy3JJkc.js} +2 -2
- package/dist/lib/{shadow-claw-networking-BN5BB4hb.js.map → shadow-claw-networking-Diy3JJkc.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-71KARtkY.js → shadow-claw-notifications-C-upPa-4.js} +3 -3
- package/dist/lib/{shadow-claw-notifications-71KARtkY.js.map → shadow-claw-notifications-C-upPa-4.js.map} +1 -1
- package/dist/lib/{shadow-claw-page-header-DMGO-TSe.js → shadow-claw-page-header-C_Qr3xZM.js} +2 -2
- package/dist/lib/{shadow-claw-page-header-DMGO-TSe.js.map → shadow-claw-page-header-C_Qr3xZM.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-BiRM6qiA.js → shadow-claw-pages-CfAjUKgd.js} +11 -11
- package/dist/lib/{shadow-claw-pages-BiRM6qiA.js.map → shadow-claw-pages-CfAjUKgd.js.map} +1 -1
- package/dist/lib/{shadow-claw-peerjs-BZu7jNSe.js → shadow-claw-peerjs-t4YibS9s.js} +6 -6
- package/dist/lib/{shadow-claw-peerjs-BZu7jNSe.js.map → shadow-claw-peerjs-t4YibS9s.js.map} +1 -1
- package/dist/lib/{shadow-claw-provider-model-picker-BXYXEobD.js → shadow-claw-provider-model-picker-B-Ct4yW-.js} +2 -2
- package/dist/lib/{shadow-claw-provider-model-picker-BXYXEobD.js.map → shadow-claw-provider-model-picker-B-Ct4yW-.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-CcT5EK08.js → shadow-claw-settings-Cg5V0e9g.js} +7 -7
- package/dist/lib/{shadow-claw-settings-CcT5EK08.js.map → shadow-claw-settings-Cg5V0e9g.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-eTOpbvpi.js → shadow-claw-storage-C7tCnsSG.js} +5 -5
- package/dist/lib/{shadow-claw-storage-eTOpbvpi.js.map → shadow-claw-storage-C7tCnsSG.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-DFImTUbw.js → shadow-claw-task-server-BObsRdf8.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-DFImTUbw.js.map → shadow-claw-task-server-BObsRdf8.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-BjaxsmUx.js → shadow-claw-tasks-B2EEqrcY.js} +9 -9
- package/dist/lib/{shadow-claw-tasks-BjaxsmUx.js.map → shadow-claw-tasks-B2EEqrcY.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-C-4wreFe.js → shadow-claw-terminal-DSHfO2b9.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-C-4wreFe.js.map → shadow-claw-terminal-DSHfO2b9.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-COdrGZJk.js → shadow-claw-tools-DwPBADua.js} +7 -7
- package/dist/lib/{shadow-claw-tools-COdrGZJk.js.map → shadow-claw-tools-DwPBADua.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-sxqVjO0L.js → shadow-claw-webvm-CY4qGaMB.js} +3 -3
- package/dist/lib/{shadow-claw-webvm-sxqVjO0L.js.map → shadow-claw-webvm-CY4qGaMB.js.map} +1 -1
- package/dist/lib/{sync-web-mcp-registration-D4hdUwtv.js → sync-web-mcp-registration-BiOZvW-R.js} +6 -6
- package/dist/lib/{sync-web-mcp-registration-D4hdUwtv.js.map → sync-web-mcp-registration-BiOZvW-R.js.map} +1 -1
- package/dist/lib/{system-prompt-DT_KeYaL.js → system-prompt-CxJ3Nx4c.js} +9 -8
- package/dist/lib/system-prompt-CxJ3Nx4c.js.map +1 -0
- package/dist/lib/{tools-Beuyh8y1.js → tools-B8OJ4sMF.js} +4 -4
- package/dist/lib/{tools-Beuyh8y1.js.map → tools-B8OJ4sMF.js.map} +1 -1
- package/dist/lib/{transformers-DydnReu4.js → transformers-BMURofG6.js} +2 -2
- package/dist/lib/{transformers-DydnReu4.js.map → transformers-BMURofG6.js.map} +1 -1
- package/dist/lib/{trusted-types-CfwZl_rr.js → trusted-types-HwsGS5Nj.js} +19 -17
- package/dist/lib/{trusted-types-CfwZl_rr.js.map → trusted-types-HwsGS5Nj.js.map} +1 -1
- package/dist/lib/{upload-group-file-BbBzjTcN.js → upload-group-file-CJpoNjEb.js} +3 -3
- package/dist/lib/{upload-group-file-BbBzjTcN.js.map → upload-group-file-CJpoNjEb.js.map} +1 -1
- package/dist/lib/utils/index.js +1 -1
- package/dist/lib/utils/namespaced-storage.js +1 -1
- package/dist/lib/utils/runtime-assets.js +1 -1
- package/dist/lib/utils/utils.js +1 -1
- package/dist/lib/{webmcp-DCfAFiIO.js → webmcp-BoMTvgmX.js} +3 -3
- package/dist/lib/{webmcp-DCfAFiIO.js.map → webmcp-BoMTvgmX.js.map} +1 -1
- package/dist/lib/{write-group-file-bytes-Ccn-VFUU.js → write-group-file-bytes-CNT7DqOZ.js} +3 -3
- package/dist/lib/{write-group-file-bytes-Ccn-VFUU.js.map → write-group-file-bytes-CNT7DqOZ.js.map} +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/AGENTS.md +3 -1
- package/dist/public/README.md +6 -2
- package/dist/public/agent.worker.js +1 -1
- package/dist/public/attachment-capabilities-AdwXt3--.js +1 -0
- package/dist/public/{channel-BylT3rJC.js → channel-DIpDQekL.js} +1 -1
- package/dist/public/{chat-template-DPHJy7tr.js → chat-template-CXKs8lFR.js} +1 -1
- package/dist/public/compact-context-BQ2ZXoAc.js +5 -0
- package/dist/public/{compact-context-BINQh64w.js → compact-context-dHitmPsV.js} +2 -2
- package/dist/public/config-C16fFWtP.js +1 -0
- package/dist/public/{configure-peer-js-DChhcOfe.js → configure-peer-js-DV1rqvFX.js} +1 -1
- package/dist/public/{connections-CHaw0VqP.js → connections-Dxwj8yK_.js} +1 -1
- package/dist/public/{create-model-cache-fetch-DQebkoPL.js → create-model-cache-fetch-B0mSCEk6.js} +1 -1
- package/dist/public/{credentials-CgVqS119.js → credentials-CJUQ5Ep2.js} +1 -1
- package/dist/public/{custom-element-security-kiDhPfb8.js → custom-element-security-B2daIE5r.js} +2 -2
- package/dist/public/{discover-skills-Cvmx5I9V.js → discover-skills-BWJB8HUA.js} +6 -6
- package/dist/public/docs/architecture/overview.md +1 -1
- package/dist/public/docs/example/article/index.html +29 -30
- package/dist/public/docs/example/article.html +29 -30
- package/dist/public/docs/publishing/index.html +29 -30
- package/dist/public/docs/publishing.html +29 -30
- package/dist/public/docs/skill-creator/index.html +29 -30
- package/dist/public/docs/skill-creator.html +29 -30
- package/dist/public/docs/subsystems/attachment-capabilities.md +14 -1
- package/dist/public/docs/subsystems/cli.md +95 -51
- package/dist/public/docs/subsystems/pages.md +5 -0
- package/dist/public/{download-group-file-BapoRgfU.js → download-group-file-BkMH-JKi.js} +1 -1
- package/dist/public/e2e/README.md +1 -1
- package/dist/public/{e2e-bridge-C0g8vZKr.js → e2e-bridge-lP2qqiv3.js} +1 -1
- package/dist/public/get-group-dir-D--BiEyk.js +1 -0
- package/dist/public/{get-or-create-subscriber-id-GvRZYXwA.js → get-or-create-subscriber-id-jVHnQfbr.js} +1 -1
- package/dist/public/{git-CaAAZfVd.js → git-DjmQ16rm.js} +2 -2
- package/dist/public/{iframe-bridge-scripts-BnqtKhE4.js → iframe-bridge-scripts-CO0izGjW.js} +1 -1
- package/dist/public/index.html +29 -30
- package/dist/public/index.js +1 -1
- package/dist/public/{init-chat-split-resize-Btonoy8u.js → init-chat-split-resize-C8AqCCiK.js} +1 -1
- package/dist/public/init-control-plane-Ctz7FI8M.js +1 -0
- package/dist/public/{invoke-agent-B3Osw6K7.js → invoke-agent-C_geruwq.js} +1 -1
- package/dist/public/llms.txt +1 -1
- package/dist/public/main/index.html +29 -30
- package/dist/public/main/memory/index.html +29 -30
- package/dist/public/main/memory.html +29 -30
- package/dist/public/main.html +29 -30
- package/dist/public/{markdown-CPbU4r1U.js → markdown-CDSb5Hrl.js} +1 -1
- package/dist/public/{mcp-reconnect-CzROVsXG.js → mcp-reconnect-iPZPihwX.js} +1 -1
- package/dist/public/{memory-storage-BkoMlxOr.js → memory-storage-2m7KZ-aP.js} +1 -1
- package/dist/public/{model-ranking-CK0iBo3Z.js → model-ranking-BgOSaNIy.js} +1 -1
- package/dist/public/{move-group-entry-CTxoq7lw.js → move-group-entry-QQ9Hkk54.js} +1 -1
- package/dist/public/{orchestrator-BrDjQbGf.js → orchestrator-C1kaTltu.js} +2 -2
- package/dist/public/orchestrator-Li1UAsv7.js +63 -0
- package/dist/public/{peerjs-CgF4Iz5W.js → peerjs-DbBryE-9.js} +1 -1
- package/dist/public/{process-peer-query-param-BL2k0Hu-.js → process-peer-query-param-DQIgr3KL.js} +1 -1
- package/dist/public/{process-pending-shared-payloads-C1AgGvn8.js → process-pending-shared-payloads-Ctb-TFqB.js} +1 -1
- package/dist/public/{process-room-query-param-DM0QCq3_.js → process-room-query-param-F-XnIVoZ.js} +1 -1
- package/dist/public/provider-YPZmsuHR.js +1 -0
- package/dist/public/{push-client-DJEOz7bi.js → push-client-DRx9Eggz.js} +1 -1
- package/dist/public/{rooms-C6LXIJl4.js → rooms-BurBI7is.js} +1 -1
- package/dist/public/service-worker/init.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/shadow-claw-Bg9AQ5x_.js +1176 -0
- package/dist/public/{shadow-claw-accounts--4hd_oCz.js → shadow-claw-accounts-B3mjYI0M.js} +1 -1
- package/dist/public/{shadow-claw-card-IbNlZAdK.js → shadow-claw-card-tcXRS1GF.js} +1 -1
- package/dist/public/{shadow-claw-channels-Vq_pPGa2.js → shadow-claw-channels-BiSfLvWv.js} +1 -1
- package/dist/public/{shadow-claw-chat-D7_GS25e.js → shadow-claw-chat-N5jMsXZZ.js} +3 -3
- package/dist/public/{shadow-claw-control-plane-WTMEV8_p.js → shadow-claw-control-plane-DFVe_Xdq.js} +2 -2
- package/dist/public/{shadow-claw-conversations-CLQgU1IT.js → shadow-claw-conversations-wAR06_ya.js} +1 -1
- package/dist/public/{shadow-claw-empty-state-D4CrFGsN.js → shadow-claw-empty-state-CnPm3NVM.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-BhqiqLWQ.js → shadow-claw-file-viewer-sZN_FCDW.js} +4 -4
- package/dist/public/{shadow-claw-files-senDiG9l.js → shadow-claw-files-CnvkCbd4.js} +2 -2
- package/dist/public/{shadow-claw-git-DOOCqY23.js → shadow-claw-git-BBHfClGk.js} +2 -2
- package/dist/public/{shadow-claw-integrations-Bsvc3Agq.js → shadow-claw-integrations-DvdBqzRJ.js} +1 -1
- package/dist/public/{shadow-claw-llm-actYICAk.js → shadow-claw-llm-YfohG519.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-BYUgrK3v.js → shadow-claw-mcp-remote-BAVbf5pi.js} +1 -1
- package/dist/public/{shadow-claw-networking-Dk3p5Ny_.js → shadow-claw-networking-CZ4LWPW7.js} +1 -1
- package/dist/public/{shadow-claw-notifications-CzPAlay8.js → shadow-claw-notifications-BHwyREkG.js} +1 -1
- package/dist/public/{shadow-claw-page-header-CjJpVkyL.js → shadow-claw-page-header-De6Qf6eY.js} +1 -1
- package/dist/public/{shadow-claw-page-header-action-button-2DH5O1TD.js → shadow-claw-page-header-action-button-FSOhTc9z.js} +1 -1
- package/dist/public/{shadow-claw-pages-3r5I-wI8.js → shadow-claw-pages-D_oPyDca.js} +6 -6
- package/dist/public/{shadow-claw-pdf-viewer-BiCEwsoY.js → shadow-claw-pdf-viewer-CrU4wqRq.js} +1 -1
- package/dist/public/{shadow-claw-settings-DgB9RSZN.js → shadow-claw-settings-DkUhvxVr.js} +2 -2
- package/dist/public/{shadow-claw-storage-JB_43nd8.js → shadow-claw-storage-D0o56Tjw.js} +1 -1
- package/dist/public/{shadow-claw-task-server-oi5UIxdA.js → shadow-claw-task-server-4rkroO9K.js} +1 -1
- package/dist/public/{shadow-claw-tasks-CnyiOt81.js → shadow-claw-tasks-BdP7lmvu.js} +3 -3
- package/dist/public/{shadow-claw-terminal-BC3RynHt.js → shadow-claw-terminal-DVHX7Fsu.js} +1 -1
- package/dist/public/{shadow-claw-toast-YjG--2Za.js → shadow-claw-toast-B9Y9tSkW.js} +1 -1
- package/dist/public/{shadow-claw-tools-Bbwk4vlT.js → shadow-claw-tools-BwwY53Lr.js} +1 -1
- package/dist/public/{shadow-claw-webvm-HZqzl2H5.js → shadow-claw-webvm-CXGdkCNM.js} +1 -1
- package/dist/public/{sync-web-mcp-registration-BaH2nAP0.js → sync-web-mcp-registration-DVK_IhXZ.js} +1 -1
- package/dist/public/{system-prompt-Dck3N8T0.js → system-prompt-BmswoQwF.js} +2 -2
- package/dist/public/{tools-DHA1dK2I.js → tools-D-52Zmfc.js} +1 -1
- package/dist/public/{transformers-C-DuTM2K.js → transformers-CQ9ss9rD.js} +1 -1
- package/dist/public/{upload-group-file-Cejr3zo1.js → upload-group-file-A8kB7lvO.js} +1 -1
- package/dist/public/{webmcp-CMRtu57-.js → webmcp-DIUZjVF5.js} +1 -1
- package/dist/public/{workbox-92eae37e.js → workbox-e4022e15.js} +1 -1
- package/dist/public/{write-group-file-CmJuVQNO.js → write-group-file-R67DjJ-q.js} +1 -1
- package/dist/public/{write-group-file-bytes-Cejr3zo1.js → write-group-file-bytes-A8kB7lvO.js} +1 -1
- package/dist/public/{zip-reader-CuQ13eLe.js → zip-reader-JHoTbATw.js} +1 -1
- package/dist/server.js +6 -6
- package/package.json +1 -1
- package/dist/cli/chunk-2gZFafgY.js +0 -1
- package/dist/cli/chunk-BFziiMKt.js +0 -7
- package/dist/cli/chunk-BM3llsxb.js +0 -1
- package/dist/cli/chunk-BUNoeMKY.js +0 -36
- package/dist/cli/chunk-Bj5qFsDi.js +0 -7
- package/dist/cli/chunk-Bj95zm-y.js +0 -1
- package/dist/cli/chunk-BpyP-esT.js +0 -1
- package/dist/cli/chunk-CX696s3_.js +0 -1
- package/dist/cli/chunk-DRxCrCAA.js +0 -139
- package/dist/cli/chunk-DjbCHa0h.js +0 -1
- package/dist/cli/chunk-Ds5-K-9o.js +0 -1
- package/dist/cli/chunk-DsQhAF31.js +0 -1
- package/dist/cli/chunk-VM-dECyG.js +0 -1
- package/dist/cli/chunk-gvNsvav0.js +0 -225
- package/dist/cli/chunk-heu2xRw1.js +0 -1
- package/dist/lib/orchestrator-i_QJ-o22.js.map +0 -1
- package/dist/lib/shadow-claw-DoQ7fgl5.js.map +0 -1
- package/dist/lib/system-prompt-DT_KeYaL.js.map +0 -1
- package/dist/public/app-routes-V_-URXc5.js +0 -1
- package/dist/public/attachment-capabilities-B6ibLwQB.js +0 -1
- package/dist/public/compact-context-CX4H8V57.js +0 -5
- package/dist/public/config-C-YdSFZB.js +0 -1
- package/dist/public/get-group-dir-DL44kvqW.js +0 -1
- package/dist/public/init-control-plane-BoJijVtf.js +0 -1
- package/dist/public/orchestrator-CaUpEVkQ.js +0 -63
- package/dist/public/provider-DNIL4-Hw.js +0 -1
- package/dist/public/shadow-claw-DdgeYPg5.js +0 -1176
package/dist/lib/{process-peer-query-param-CJp7w7AU.js → process-peer-query-param-BnsVnxzH.js}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as orchestratorStore } from "./orchestrator-
|
|
1
|
+
import { t as orchestratorStore } from "./orchestrator-cRBe3lhq.js";
|
|
2
2
|
import { ulid } from "./utils/ulid.js";
|
|
3
3
|
import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
|
|
4
|
-
import { a as showPage } from "./shadow-claw-
|
|
5
|
-
import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-
|
|
6
|
-
import { t as configurePeerJs } from "./configure-peer-js-
|
|
4
|
+
import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
|
|
5
|
+
import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-DB77spML.js";
|
|
6
|
+
import { t as configurePeerJs } from "./configure-peer-js-CgFiwoxY.js";
|
|
7
7
|
|
|
8
8
|
//#region src/components/shadow-claw/utils/process-peer-query-param.ts
|
|
9
9
|
async function processPeerQueryParam(shadow, shadowClaw, db, orchestrator) {
|
|
@@ -36,4 +36,4 @@ async function processPeerQueryParam(shadow, shadowClaw, db, orchestrator) {
|
|
|
36
36
|
|
|
37
37
|
//#endregion
|
|
38
38
|
export { processPeerQueryParam };
|
|
39
|
-
//# sourceMappingURL=process-peer-query-param-
|
|
39
|
+
//# sourceMappingURL=process-peer-query-param-BnsVnxzH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-peer-query-param-
|
|
1
|
+
{"version":3,"file":"process-peer-query-param-BnsVnxzH.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-peer-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\n\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\n\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"../utils/show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPeerQueryParam(\n shadow: ShadowRoot,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase | null,\n orchestrator: Orchestrator,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const peerParam = currentUrl.searchParams.get(\"peer\");\n if (!peerParam) {\n return;\n }\n\n const remotePeerId = peerParam.trim();\n if (!remotePeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and configured\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n // Automatically trust the remote peer we are connecting to\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(remotePeerId);\n\n // Save/configure\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Ensure peer conversation exists in the list\n const targetGroupId = await orchestratorStore.ensurePeerConversation(\n db,\n remotePeerId,\n );\n\n // 3. Switch conversation and navigate to chat\n await orchestratorStore.switchConversation(db, targetGroupId);\n showPage(shadow, shadowClaw, db, orchestratorStore, \"chat\");\n\n // 4. Remove 'peer' from URL params to prevent re-triggering\n currentUrl.searchParams.delete(\"peer\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n window.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Connected to Peer: ${remotePeerId.substring(0, 8)}`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to process peer parameter: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAgBA,eAAsB,sBACpB,QACA,YACA,IACA,cACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM;CACpD,IAAI,CAAC,WACH;CAGF,MAAM,eAAe,UAAU,KAAK;CACpC,IAAI,CAAC,cACH;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAIhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,YAAY;EAGxB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,MAAM,gBAAgB,MAAM,kBAAkB,uBAC5C,IACA,YACF;EAGA,MAAM,kBAAkB,mBAAmB,IAAI,aAAa;EAC5D,SAAS,QAAQ,YAAY,IAAI,mBAAmB,MAAM;EAG1D,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,OAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAElD,YAAY,sBAAsB,aAAa,UAAU,GAAG,CAAC,GAAG;CAClE,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,qCAAqC,WAAW,GAAI;CAChE;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as writeGroupFile } from "./tools-
|
|
1
|
+
import { o as writeGroupFile } from "./tools-B8OJ4sMF.js";
|
|
2
2
|
import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
|
|
3
|
-
import { a as showPage } from "./shadow-claw-
|
|
4
|
-
import { t as writeGroupFileBytes } from "./write-group-file-bytes-
|
|
3
|
+
import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
|
|
4
|
+
import { t as writeGroupFileBytes } from "./write-group-file-bytes-CNT7DqOZ.js";
|
|
5
5
|
|
|
6
6
|
//#region src/share-target/pending-shares.ts
|
|
7
7
|
const PENDING_SHARES_STORE = "pendingShares";
|
|
@@ -128,4 +128,4 @@ async function processPendingSharedPayloads(win, shadow, shadowClaw, oStore, fSt
|
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
130
|
export { processPendingSharedPayloads };
|
|
131
|
-
//# sourceMappingURL=process-pending-shared-payloads-
|
|
131
|
+
//# sourceMappingURL=process-pending-shared-payloads-DBZfZOOa.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-pending-shared-payloads-B6_TlBFA.js","names":[],"sources":["../../src/share-target/pending-shares.ts","../../src/components/shadow-claw/utils/build-shared-text-payload.ts","../../src/components/shadow-claw/utils/resolve-shared-files-conversation-id.ts","../../src/components/shadow-claw/utils/sanitize-shared-file-name.ts","../../src/components/shadow-claw/utils/process-pending-shared-payloads.ts"],"sourcesContent":["import type { ShadowClawDatabase } from \"../db/types.js\";\n\nconst PENDING_SHARES_STORE = \"pendingShares\";\n\nexport interface PendingShareRecord {\n id: string;\n createdAt: number;\n title: string;\n text: string;\n url: string;\n fileName: string;\n fileType: string;\n fileBytes: ArrayBuffer | null;\n}\n\nfunction normalizeRecord(raw: any): PendingShareRecord {\n return {\n id: typeof raw?.id === \"string\" ? raw.id : \"\",\n createdAt: typeof raw?.createdAt === \"number\" ? raw.createdAt : 0,\n title: typeof raw?.title === \"string\" ? raw.title : \"\",\n text: typeof raw?.text === \"string\" ? raw.text : \"\",\n url: typeof raw?.url === \"string\" ? raw.url : \"\",\n fileName: typeof raw?.fileName === \"string\" ? raw.fileName : \"\",\n fileType: typeof raw?.fileType === \"string\" ? raw.fileType : \"\",\n fileBytes: raw?.fileBytes instanceof ArrayBuffer ? raw.fileBytes : null,\n };\n}\n\n/**\n * Read and clear pending Web Share Target payloads in FIFO order.\n */\nexport async function consumePendingShares(\n db: ShadowClawDatabase,\n): Promise<PendingShareRecord[]> {\n if (!db || typeof (db as any).transaction !== \"function\") {\n return [];\n }\n\n return new Promise((resolve, reject) => {\n let tx: IDBTransaction;\n\n try {\n tx = (db as IDBDatabase).transaction(PENDING_SHARES_STORE, \"readwrite\");\n } catch (error) {\n if (error instanceof DOMException && error.name === \"NotFoundError\") {\n resolve([]);\n\n return;\n }\n\n reject(error);\n\n return;\n }\n\n const store = tx.objectStore(PENDING_SHARES_STORE);\n const getAllRequest = store.getAll();\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error || new Error(\"Failed to read pending shares\"));\n };\n\n getAllRequest.onsuccess = () => {\n const rows = Array.isArray(getAllRequest.result)\n ? getAllRequest.result\n .map(normalizeRecord)\n .filter(\n (record) => typeof record.id === \"string\" && record.id.length > 0,\n )\n .sort((a, b) => a.createdAt - b.createdAt)\n : [];\n\n const clearRequest = store.clear();\n clearRequest.onerror = () => {\n reject(\n clearRequest.error || new Error(\"Failed to clear pending shares\"),\n );\n };\n\n clearRequest.onsuccess = () => {\n resolve(rows);\n };\n };\n\n tx.onabort = () => {\n reject(tx.error || new Error(\"Pending share transaction aborted\"));\n };\n });\n}\n","export function buildSharedTextPayload(share: {\n title: string;\n text: string;\n url: string;\n}): string {\n const lines: string[] = [\"# Shared Content\", \"\"];\n\n if (share.title) {\n lines.push(`Title: ${share.title}`);\n }\n\n if (share.url) {\n lines.push(`URL: ${share.url}`);\n }\n\n if (share.text) {\n lines.push(\"\", share.text);\n }\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","import type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\n\nexport async function resolveSharedFilesConversationId(\n db: ShadowClawDatabase,\n oStore: OrchestratorStore,\n): Promise<string> {\n const now = new Date();\n const year = String(now.getFullYear());\n const month = String(now.getMonth() + 1).padStart(2, \"0\");\n const day = String(now.getDate()).padStart(2, \"0\");\n const isoDate = `${year}-${month}-${day}`;\n const conversationName = `Shared Files ${isoDate}`;\n const existing = oStore.groups.find(\n (group) => group.name === conversationName,\n );\n\n if (existing) {\n await oStore.switchConversation(db, existing.groupId);\n\n return existing.groupId;\n }\n\n const group = await oStore.createConversation(db, conversationName);\n\n return group.groupId;\n}\n","export function sanitizeSharedFileName(\n name: string,\n fallbackBase: string,\n): string {\n const normalized =\n name.replace(/\\\\/g, \"/\").split(\"/\").filter(Boolean).pop() || \"\";\n\n const collapsed = normalized\n .replace(/\\s+/g, \"-\")\n .replace(/[^A-Za-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n if (collapsed) {\n return collapsed;\n }\n\n return `${fallbackBase}.txt`;\n}\n","import { consumePendingShares } from \"../../../share-target/pending-shares.js\";\nimport { writeGroupFile } from \"../../../storage/write-group-file.js\";\nimport { writeGroupFileBytes } from \"../../../storage/write-group-file-bytes.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { buildSharedTextPayload } from \"./build-shared-text-payload.js\";\nimport { resolveSharedFilesConversationId } from \"./resolve-shared-files-conversation-id.js\";\nimport { sanitizeSharedFileName } from \"./sanitize-shared-file-name.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { FileViewerStore } from \"../../../stores/file-viewer.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPendingSharedPayloads(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n oStore: OrchestratorStore,\n fStore: FileViewerStore,\n db: ShadowClawDatabase,\n url: URL,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const pendingShares = await consumePendingShares(db);\n if (pendingShares.length === 0) {\n return;\n }\n\n try {\n const targetGroupId = await resolveSharedFilesConversationId(db, oStore);\n const savedPaths: string[] = [];\n\n for (let i = 0; i < pendingShares.length; i++) {\n const share = pendingShares[i];\n const baseName = `shared-${Date.now()}-${i + 1}`;\n\n if (share.fileBytes instanceof ArrayBuffer) {\n const preferredName =\n share.fileName ||\n (share.fileType === \"application/pdf\"\n ? `${baseName}.pdf`\n : `${baseName}.bin`);\n const fileName = sanitizeSharedFileName(preferredName, baseName);\n\n await writeGroupFileBytes(\n db,\n targetGroupId,\n fileName,\n new Uint8Array(share.fileBytes),\n );\n savedPaths.push(fileName);\n\n continue;\n }\n\n const textFileName = sanitizeSharedFileName(\n share.fileName || `${baseName}.md`,\n baseName,\n );\n const textPayload = buildSharedTextPayload(share);\n await writeGroupFile(db, targetGroupId, textFileName, textPayload);\n savedPaths.push(textFileName);\n }\n\n await oStore.loadFiles(db);\n showPage(shadow, shadowClaw, db, oStore, \"files\");\n\n if (savedPaths.length > 0) {\n await fStore.openFile(db, savedPaths[0], targetGroupId);\n }\n\n showSuccess(\n `Imported ${savedPaths.length} shared item${savedPaths.length === 1 ? \"\" : \"s\"}.`,\n );\n\n const currentUrl = url;\n if (currentUrl.searchParams.has(\"share-target\")) {\n currentUrl.searchParams.delete(\"share-target\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to import shared content: ${message}`, 6000);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process-pending-shared-payloads-DBZfZOOa.js","names":[],"sources":["../../src/share-target/pending-shares.ts","../../src/components/shadow-claw/utils/build-shared-text-payload.ts","../../src/components/shadow-claw/utils/resolve-shared-files-conversation-id.ts","../../src/components/shadow-claw/utils/sanitize-shared-file-name.ts","../../src/components/shadow-claw/utils/process-pending-shared-payloads.ts"],"sourcesContent":["import type { ShadowClawDatabase } from \"../db/types.js\";\n\nconst PENDING_SHARES_STORE = \"pendingShares\";\n\nexport interface PendingShareRecord {\n id: string;\n createdAt: number;\n title: string;\n text: string;\n url: string;\n fileName: string;\n fileType: string;\n fileBytes: ArrayBuffer | null;\n}\n\nfunction normalizeRecord(raw: any): PendingShareRecord {\n return {\n id: typeof raw?.id === \"string\" ? raw.id : \"\",\n createdAt: typeof raw?.createdAt === \"number\" ? raw.createdAt : 0,\n title: typeof raw?.title === \"string\" ? raw.title : \"\",\n text: typeof raw?.text === \"string\" ? raw.text : \"\",\n url: typeof raw?.url === \"string\" ? raw.url : \"\",\n fileName: typeof raw?.fileName === \"string\" ? raw.fileName : \"\",\n fileType: typeof raw?.fileType === \"string\" ? raw.fileType : \"\",\n fileBytes: raw?.fileBytes instanceof ArrayBuffer ? raw.fileBytes : null,\n };\n}\n\n/**\n * Read and clear pending Web Share Target payloads in FIFO order.\n */\nexport async function consumePendingShares(\n db: ShadowClawDatabase,\n): Promise<PendingShareRecord[]> {\n if (!db || typeof (db as any).transaction !== \"function\") {\n return [];\n }\n\n return new Promise((resolve, reject) => {\n let tx: IDBTransaction;\n\n try {\n tx = (db as IDBDatabase).transaction(PENDING_SHARES_STORE, \"readwrite\");\n } catch (error) {\n if (error instanceof DOMException && error.name === \"NotFoundError\") {\n resolve([]);\n\n return;\n }\n\n reject(error);\n\n return;\n }\n\n const store = tx.objectStore(PENDING_SHARES_STORE);\n const getAllRequest = store.getAll();\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error || new Error(\"Failed to read pending shares\"));\n };\n\n getAllRequest.onsuccess = () => {\n const rows = Array.isArray(getAllRequest.result)\n ? getAllRequest.result\n .map(normalizeRecord)\n .filter(\n (record) => typeof record.id === \"string\" && record.id.length > 0,\n )\n .sort((a, b) => a.createdAt - b.createdAt)\n : [];\n\n const clearRequest = store.clear();\n clearRequest.onerror = () => {\n reject(\n clearRequest.error || new Error(\"Failed to clear pending shares\"),\n );\n };\n\n clearRequest.onsuccess = () => {\n resolve(rows);\n };\n };\n\n tx.onabort = () => {\n reject(tx.error || new Error(\"Pending share transaction aborted\"));\n };\n });\n}\n","export function buildSharedTextPayload(share: {\n title: string;\n text: string;\n url: string;\n}): string {\n const lines: string[] = [\"# Shared Content\", \"\"];\n\n if (share.title) {\n lines.push(`Title: ${share.title}`);\n }\n\n if (share.url) {\n lines.push(`URL: ${share.url}`);\n }\n\n if (share.text) {\n lines.push(\"\", share.text);\n }\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","import type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\n\nexport async function resolveSharedFilesConversationId(\n db: ShadowClawDatabase,\n oStore: OrchestratorStore,\n): Promise<string> {\n const now = new Date();\n const year = String(now.getFullYear());\n const month = String(now.getMonth() + 1).padStart(2, \"0\");\n const day = String(now.getDate()).padStart(2, \"0\");\n const isoDate = `${year}-${month}-${day}`;\n const conversationName = `Shared Files ${isoDate}`;\n const existing = oStore.groups.find(\n (group) => group.name === conversationName,\n );\n\n if (existing) {\n await oStore.switchConversation(db, existing.groupId);\n\n return existing.groupId;\n }\n\n const group = await oStore.createConversation(db, conversationName);\n\n return group.groupId;\n}\n","export function sanitizeSharedFileName(\n name: string,\n fallbackBase: string,\n): string {\n const normalized =\n name.replace(/\\\\/g, \"/\").split(\"/\").filter(Boolean).pop() || \"\";\n\n const collapsed = normalized\n .replace(/\\s+/g, \"-\")\n .replace(/[^A-Za-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n if (collapsed) {\n return collapsed;\n }\n\n return `${fallbackBase}.txt`;\n}\n","import { consumePendingShares } from \"../../../share-target/pending-shares.js\";\nimport { writeGroupFile } from \"../../../storage/write-group-file.js\";\nimport { writeGroupFileBytes } from \"../../../storage/write-group-file-bytes.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { buildSharedTextPayload } from \"./build-shared-text-payload.js\";\nimport { resolveSharedFilesConversationId } from \"./resolve-shared-files-conversation-id.js\";\nimport { sanitizeSharedFileName } from \"./sanitize-shared-file-name.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { FileViewerStore } from \"../../../stores/file-viewer.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPendingSharedPayloads(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n oStore: OrchestratorStore,\n fStore: FileViewerStore,\n db: ShadowClawDatabase,\n url: URL,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const pendingShares = await consumePendingShares(db);\n if (pendingShares.length === 0) {\n return;\n }\n\n try {\n const targetGroupId = await resolveSharedFilesConversationId(db, oStore);\n const savedPaths: string[] = [];\n\n for (let i = 0; i < pendingShares.length; i++) {\n const share = pendingShares[i];\n const baseName = `shared-${Date.now()}-${i + 1}`;\n\n if (share.fileBytes instanceof ArrayBuffer) {\n const preferredName =\n share.fileName ||\n (share.fileType === \"application/pdf\"\n ? `${baseName}.pdf`\n : `${baseName}.bin`);\n const fileName = sanitizeSharedFileName(preferredName, baseName);\n\n await writeGroupFileBytes(\n db,\n targetGroupId,\n fileName,\n new Uint8Array(share.fileBytes),\n );\n savedPaths.push(fileName);\n\n continue;\n }\n\n const textFileName = sanitizeSharedFileName(\n share.fileName || `${baseName}.md`,\n baseName,\n );\n const textPayload = buildSharedTextPayload(share);\n await writeGroupFile(db, targetGroupId, textFileName, textPayload);\n savedPaths.push(textFileName);\n }\n\n await oStore.loadFiles(db);\n showPage(shadow, shadowClaw, db, oStore, \"files\");\n\n if (savedPaths.length > 0) {\n await fStore.openFile(db, savedPaths[0], targetGroupId);\n }\n\n showSuccess(\n `Imported ${savedPaths.length} shared item${savedPaths.length === 1 ? \"\" : \"s\"}.`,\n );\n\n const currentUrl = url;\n if (currentUrl.searchParams.has(\"share-target\")) {\n currentUrl.searchParams.delete(\"share-target\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to import shared content: ${message}`, 6000);\n }\n}\n"],"mappings":"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"}
|
package/dist/lib/{process-room-query-param-C3FFGGn6.js → process-room-query-param-B8EYg_-r.js}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ulid } from "./utils/ulid.js";
|
|
2
2
|
import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
|
|
3
|
-
import { a as showPage } from "./shadow-claw-
|
|
3
|
+
import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
|
|
4
4
|
import { i as joinRoomViaLink } from "./room-QujMjoxG.js";
|
|
5
|
-
import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-
|
|
6
|
-
import { t as configurePeerJs } from "./configure-peer-js-
|
|
5
|
+
import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-DB77spML.js";
|
|
6
|
+
import { t as configurePeerJs } from "./configure-peer-js-CgFiwoxY.js";
|
|
7
7
|
|
|
8
8
|
//#region src/components/shadow-claw/utils/process-room-query-param.ts
|
|
9
9
|
async function processRoomQueryParam(win, shadow, shadowClaw, db, orchestrator, oStore) {
|
|
@@ -38,4 +38,4 @@ async function processRoomQueryParam(win, shadow, shadowClaw, db, orchestrator,
|
|
|
38
38
|
|
|
39
39
|
//#endregion
|
|
40
40
|
export { processRoomQueryParam };
|
|
41
|
-
//# sourceMappingURL=process-room-query-param-
|
|
41
|
+
//# sourceMappingURL=process-room-query-param-B8EYg_-r.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-room-query-param-
|
|
1
|
+
{"version":3,"file":"process-room-query-param-B8EYg_-r.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-room-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\nimport { joinRoomViaLink } from \"../../../core/orchestrator/utils/operations/room.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processRoomQueryParam(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase,\n orchestrator: Orchestrator,\n oStore: OrchestratorStore,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const roomId = (currentUrl.searchParams.get(\"room\") || \"\").trim();\n const hostPeerId = (currentUrl.searchParams.get(\"host\") || \"\").trim();\n const roomName = (currentUrl.searchParams.get(\"name\") || \"\").trim() || \"Room\";\n\n if (!roomId || !hostPeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and the host is trusted\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(hostPeerId);\n\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Join the room (connects to host + announces membership)\n joinRoomViaLink(orchestrator, roomId, hostPeerId, roomName);\n\n // 3. Navigate to the room conversation\n await oStore.switchConversation(db, `room:${roomId}`);\n showPage(shadow, shadowClaw, db, oStore, \"chat\");\n\n // 4. Clean the URL to prevent re-triggering\n currentUrl.searchParams.delete(\"room\");\n currentUrl.searchParams.delete(\"host\");\n currentUrl.searchParams.delete(\"name\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Joined room \"${roomName}\"`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to join room: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAeA,eAAsB,sBACpB,KACA,QACA,YACA,IACA,cACA,QACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,UAAU,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CAChE,MAAM,cAAc,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CACpE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK,KAAK;CAEvE,IAAI,CAAC,UAAU,CAAC,YACd;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAGhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,UAAU;EAEtB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,gBAAgB,cAAc,QAAQ,YAAY,QAAQ;EAG1D,MAAM,OAAO,mBAAmB,IAAI,QAAQ,QAAQ;EACpD,SAAS,QAAQ,YAAY,IAAI,QAAQ,MAAM;EAG/C,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,IAAI,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAE/C,YAAY,gBAAgB,SAAS,EAAE;CACzC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,wBAAwB,WAAW,GAAI;CACnD;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as getConfig } from "./get-config-BWhs5HFF.js";
|
|
2
|
-
import { C as PROVIDERS, F as getProvider, O as buildTriggerPattern, P as getModelMaxTokens, R as modelRegistry, c as DEFAULT_PROMPT_API_FALLBACK_MODEL, r as CONFIG_KEYS, y as LLAMAFILE_PROXY_URL } from "./config-
|
|
3
|
-
import { t as toolsStore } from "./tools-
|
|
2
|
+
import { C as PROVIDERS, F as getProvider, O as buildTriggerPattern, P as getModelMaxTokens, R as modelRegistry, c as DEFAULT_PROMPT_API_FALLBACK_MODEL, r as CONFIG_KEYS, y as LLAMAFILE_PROXY_URL } from "./config-BrHR97zt.js";
|
|
3
|
+
import { t as toolsStore } from "./tools-B8OJ4sMF.js";
|
|
4
4
|
import { t as setConfig } from "./set-config-CUadvYZ1.js";
|
|
5
5
|
|
|
6
6
|
//#region src/subsystems/providers/utils/is-prompt-api-supported.ts
|
|
@@ -258,4 +258,4 @@ async function cancelLlamafileRequest(requestId) {
|
|
|
258
258
|
|
|
259
259
|
//#endregion
|
|
260
260
|
export { isPromptApiSupported as S, setPeerjsPeerAliases as _, getApiKeyForRequest as a, stopTransformersProgressPolling as b, getLlamafileSettings as c, setAssistantName as d, setBedrockSettings as f, setPeerjsMyAlias as g, setModel as h, getApiKeyForHeaders as i, getProviderRuntimeHeaders as l, setMeshLlmSettings as m, applyMeshLlmHeaders as n, getAvailableProviders as o, setLlamafileSettings as p, cancelLlamafileRequest as r, getBedrockSettings as s, applyLlamafileHeaders as t, getReasoningConfig as u, setProvider as v, getLanguageModelApi as x, startTransformersProgressPolling as y };
|
|
261
|
-
//# sourceMappingURL=provider-
|
|
261
|
+
//# sourceMappingURL=provider-BC9KPI14.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-DcQZypu5.js","names":["_defaultSetConfig"],"sources":["../../src/subsystems/providers/utils/is-prompt-api-supported.ts","../../src/core/orchestrator/utils/operations/provider.ts"],"sourcesContent":["export function getLanguageModelApi(): {\n availability: Function;\n create: Function;\n} | null {\n const candidate = (globalThis as any).LanguageModel;\n if (!candidate || typeof candidate !== \"function\") {\n return null;\n }\n\n if (\n typeof candidate.availability !== \"function\" ||\n typeof candidate.create !== \"function\"\n ) {\n return null;\n }\n\n return candidate;\n}\n\n/**\n * Lightweight feature detection for the browser Prompt API.\n */\nexport function isPromptApiSupported(): boolean {\n return !!getLanguageModelApi();\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n LLAMAFILE_PROXY_URL,\n PROVIDERS,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../../config/config.js\";\n\nimport type { ProviderConfig } from \"../../../../config/config.js\";\nimport { getConfig } from \"../../../../db/get-config.js\";\nimport { setConfig as _defaultSetConfig } from \"../../../../db/set-config.js\";\nimport { toolsStore } from \"../../../../stores/tools.js\";\nimport { modelRegistry } from \"../../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../../subsystems/providers/utils/is-prompt-api-supported.js\";\n\nimport type { ShadowClawDatabase } from \"../../../../db/db.js\";\nimport type { LLMProvider } from \"../../../../subsystems/providers/types.js\";\nimport type { ModelDownloadProgressPayload } from \"../../../../subsystems/worker/types.js\";\nimport type { OrchestratorState } from \"../../orchestrator-state.js\";\nimport type { EventBus } from \"../event-bus.js\";\n\ntype SetConfigFn = (\n db: ShadowClawDatabase,\n key: string,\n value: string,\n) => Promise<void>;\n\nexport async function getApiKeyForHeaders(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string | undefined> {\n return (await orchestrator.getApiKey()) || undefined;\n}\n\nexport async function getApiKeyForRequest(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string> {\n return (await orchestrator.getApiKey()) || \"\";\n}\n\nexport function getLlamafileSettings(\n state: Pick<\n OrchestratorState,\n \"llamafileMode\" | \"llamafileHost\" | \"llamafilePort\" | \"llamafileOffline\"\n >,\n): {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n} {\n return {\n mode: state.llamafileMode,\n host: state.llamafileHost,\n port: state.llamafilePort,\n offline: state.llamafileOffline,\n };\n}\n\nexport function getMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\">,\n): { host: string } {\n return {\n host: state.meshLlmHost,\n };\n}\n\nexport function getBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n): {\n authMode: string;\n profile: string;\n region: string;\n} {\n return {\n authMode: state.bedrockAuthMode,\n profile: state.bedrockProfileFallback,\n region: state.bedrockRegionFallback,\n };\n}\n\nexport function getAvailableProviders(): LLMProvider[] {\n return Object.entries(PROVIDERS).map(([id, config]) => ({\n id,\n name: config.name,\n ...(!config.modelsUrl && {\n models:\n Array.isArray(config.models) && config.models.length > 0\n ? config.models\n : [config.defaultModel],\n }),\n ...(config.modelsUrl && { modelsUrl: config.modelsUrl }),\n ...(config.headers && { headers: config.headers }),\n ...(config.apiKeyHeader && { apiKeyHeader: config.apiKeyHeader }),\n ...(config.apiKeyHeaderFormat && {\n apiKeyHeaderFormat: config.apiKeyHeaderFormat,\n }),\n ...(typeof config.requiresApiKey === \"boolean\" && {\n requiresApiKey: config.requiresApiKey,\n }),\n }));\n}\n\nexport function getReasoningConfig(\n state: Pick<OrchestratorState, \"reasoningEffort\">,\n): { effort: string } | undefined {\n const effort =\n typeof state.reasoningEffort === \"string\"\n ? state.reasoningEffort.trim().toLowerCase()\n : \"none\";\n if (!effort || effort === \"none\") {\n return undefined;\n }\n\n return { effort };\n}\n\nexport function getProviderRuntimeHeaders(\n state: Pick<\n OrchestratorState,\n | \"bedrockAuthMode\"\n | \"bedrockProfileFallback\"\n | \"bedrockRegionFallback\"\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n >,\n providerId: string,\n requestId = \"\",\n overrides?: {\n bedrock_proxy?: {\n authMode?: \"provider_chain\" | \"sso\";\n profile?: string;\n region?: string;\n };\n llamafile?: {\n host?: string;\n mode?: \"cli\" | \"server\";\n offline?: boolean;\n port?: number;\n };\n },\n): Record<string, string> {\n if (providerId === \"llamafile\") {\n const llama = overrides?.llamafile;\n const headers: Record<string, string> = {\n \"x-llamafile-mode\":\n llama?.mode === \"server\" || llama?.mode === \"cli\"\n ? llama.mode\n : state.llamafileMode,\n \"x-llamafile-host\": llama?.host || state.llamafileHost,\n \"x-llamafile-port\": String(llama?.port || state.llamafilePort),\n \"x-llamafile-offline\":\n (llama?.offline ?? state.llamafileOffline) ? \"true\" : \"false\",\n };\n\n if (requestId) {\n headers[\"x-shadowclaw-request-id\"] = requestId;\n }\n\n return headers;\n }\n\n if (providerId === \"bedrock_proxy\") {\n const bedrock = overrides?.bedrock_proxy;\n const headers: Record<string, string> = {};\n if (bedrock?.region || state.bedrockRegionFallback) {\n headers[\"x-bedrock-region\"] =\n bedrock?.region || state.bedrockRegionFallback;\n }\n\n if (bedrock?.profile || state.bedrockProfileFallback) {\n headers[\"x-bedrock-profile\"] =\n bedrock?.profile || state.bedrockProfileFallback;\n }\n\n headers[\"x-bedrock-auth-mode\"] = bedrock?.authMode || state.bedrockAuthMode;\n\n return headers;\n }\n\n return {};\n}\n\nexport function applyLlamafileHeaders(\n state: Pick<\n OrchestratorState,\n | \"providerConfig\"\n | \"llamafileMode\"\n | \"llamafileHost\"\n | \"llamafilePort\"\n | \"llamafileOffline\"\n >,\n): void {\n if (state.providerConfig?.id !== \"llamafile\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-llamafile-mode\": state.llamafileMode,\n \"x-llamafile-host\": state.llamafileHost,\n \"x-llamafile-port\": String(state.llamafilePort),\n \"x-llamafile-offline\": state.llamafileOffline ? \"true\" : \"false\",\n },\n };\n}\n\nexport function applyMeshLlmHeaders(\n state: Pick<OrchestratorState, \"providerConfig\" | \"meshLlmHost\">,\n): void {\n if (state.providerConfig?.id !== \"mesh-llm\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-mesh-llm-host\": state.meshLlmHost,\n },\n };\n}\n\nexport function getTransformersStatusUrl(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n groupId?: string,\n): string {\n // If we have a groupId, check if there is an in-flight effective provider config for it\n if (groupId && state.inFlightEffectiveProviderByGroup) {\n const info = state.inFlightEffectiveProviderByGroup.get(groupId);\n if (info?.providerId === \"transformers_js_local\") {\n const base = info.providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n }\n\n // If the current providerConfig is transformers_js_local (or undefined for mock tests), use its baseUrl\n const providerConfig = state.providerConfig;\n if (\n providerConfig &&\n (!providerConfig.id || providerConfig.id === \"transformers_js_local\")\n ) {\n const base = providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n\n // Fallback to local transformers.js proxy status\n const localProvider = getProvider(\"transformers_js_local\");\n const base = localProvider?.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n\n return \"http://localhost:8888/transformers-js-proxy/status\";\n}\n\n// ── Async setters ───────────────────────────────────────────────────────────\n\nexport async function setAssistantName(\n state: Pick<OrchestratorState, \"assistantName\" | \"triggerPattern\">,\n db: ShadowClawDatabase,\n name: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.assistantName = name;\n state.triggerPattern = buildTriggerPattern(name);\n\n await _setConfig(db, CONFIG_KEYS.ASSISTANT_NAME, name);\n}\n\nexport async function setBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n db: ShadowClawDatabase,\n settings: { authMode: string; profile: string; region: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const region =\n typeof settings.region === \"string\" ? settings.region.trim() : \"\";\n const profile =\n typeof settings.profile === \"string\" ? settings.profile.trim() : \"\";\n const authMode = settings.authMode === \"sso\" ? \"sso\" : \"provider_chain\";\n\n state.bedrockRegionFallback = region;\n state.bedrockProfileFallback = profile;\n state.bedrockAuthMode = authMode;\n\n await _setConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK, region);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK, profile);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE, authMode);\n}\n\nexport async function setLlamafileSettings(\n state: Pick<\n OrchestratorState,\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n | \"providerConfig\"\n >,\n db: ShadowClawDatabase,\n settings: {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.llamafileMode = settings.mode;\n state.llamafileHost = settings.host;\n state.llamafilePort = settings.port;\n state.llamafileOffline = settings.offline;\n\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, settings.mode);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_HOST, settings.host);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_PORT, String(settings.port));\n await _setConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n settings.offline ? \"true\" : \"false\",\n );\n\n applyLlamafileHeaders(state);\n}\n\nexport async function setMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\" | \"providerConfig\">,\n db: ShadowClawDatabase,\n settings: { host: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.meshLlmHost = settings.host;\n\n await _setConfig(db, CONFIG_KEYS.MESH_LLM_HOST, settings.host);\n\n applyMeshLlmHeaders(state);\n}\n\nexport async function setModel(\n state: Pick<OrchestratorState, \"model\" | \"maxTokens\" | \"provider\">,\n db: ShadowClawDatabase,\n model: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.model = model;\n let effectiveModelForLimits = model;\n if (\n state.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (model === \"browser-built-in\" || !model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.MODEL, model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function setPeerjsMyAlias(\n state: Pick<OrchestratorState, \"peerjsMyAlias\">,\n db: ShadowClawDatabase,\n alias: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsMyAlias = alias.trim();\n\n await _setConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS, state.peerjsMyAlias);\n}\n\nexport async function setPeerjsPeerAliases(\n state: Pick<OrchestratorState, \"peerjsPeerAliases\">,\n db: ShadowClawDatabase,\n aliases: Record<string, string>,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsPeerAliases = { ...aliases };\n\n await _setConfig(\n db,\n CONFIG_KEYS.PEERJS_PEER_ALIASES,\n JSON.stringify(state.peerjsPeerAliases),\n );\n}\n\nexport async function autoActivateProfile(\n state: Pick<OrchestratorState, \"provider\" | \"model\">,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Preserve an explicit manual \"no tools\" configuration.\n if (!toolsStore.activeProfileId && toolsStore.enabledToolNames.size === 0) {\n return;\n }\n\n const candidates = toolsStore.findProfilesForProvider(\n state.provider,\n state.model,\n );\n\n if (candidates.length === 0) {\n return;\n }\n\n const exact = candidates.find(\n (p) => p.providerId === state.provider && p.model === state.model,\n );\n\n if (exact) {\n await toolsStore.activateProfile(db, exact.id);\n\n return;\n }\n\n const providerOnly = candidates.find(\n (p) => p.providerId === state.provider && !p.model,\n );\n\n if (providerOnly) {\n await toolsStore.activateProfile(db, providerOnly.id);\n }\n}\n\n/**\n * Switch the active LLM provider. This is more complex than the simple\n * settings because it also fetches model info and auto-activates profiles.\n */\nexport async function setProvider(\n state: OrchestratorState,\n db: ShadowClawDatabase,\n providerId: string,\n deps: {\n loadApiKeyForProvider: (\n db: ShadowClawDatabase,\n providerId: string,\n ) => Promise<void>;\n getApiKeyForHeaders: () => Promise<string | undefined>;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const newProvider = getProvider(providerId);\n if (!newProvider) {\n throw new Error(`Unknown provider: ${providerId}`);\n }\n\n state.provider = providerId;\n state.providerConfig = newProvider;\n state.model = newProvider.defaultModel;\n applyLlamafileHeaders(state);\n applyMeshLlmHeaders(state);\n\n await deps.loadApiKeyForProvider(db, providerId);\n\n await modelRegistry.fetchModelInfo(\n newProvider,\n (await deps.getApiKeyForHeaders()) || undefined,\n getProviderRuntimeHeaders(state, providerId),\n );\n\n let effectiveModelForLimits = state.model;\n if (\n providerId === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (state.model === \"browser-built-in\" || !state.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.PROVIDER, providerId);\n await _setConfig(db, CONFIG_KEYS.MODEL, state.model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function pollTransformersProgress(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n stopPolling: (groupId: string) => void,\n): Promise<void> {\n try {\n const url = getTransformersStatusUrl(state, groupId);\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!res.ok) {\n return;\n }\n\n const status = await res.json();\n const raw = Number(status?.progress);\n const normalizedProgress =\n Number.isFinite(raw) && raw > 1\n ? Math.max(0, Math.min(1, raw / 100))\n : Number.isFinite(raw)\n ? Math.max(0, Math.min(1, raw))\n : null;\n\n const payload: ModelDownloadProgressPayload = {\n groupId,\n message:\n typeof status?.message === \"string\" && status.message\n ? status.message\n : undefined,\n progress: normalizedProgress,\n status:\n status?.status === \"done\" || status?.status === \"error\"\n ? status.status\n : \"running\",\n };\n\n events.emit(\"model-download-progress\", payload);\n\n if (payload.status === \"done\" || payload.status === \"error\") {\n stopPolling(groupId);\n }\n } catch {\n // Ignore status polling failures so inference can continue uninterrupted.\n }\n}\n\nexport function startTransformersProgressPolling(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n transformersProgressPollers: Map<string, number>;\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n): void {\n stopTransformersProgressPolling(state, groupId);\n\n // Show immediate feedback while the first network poll is in flight.\n events.emit(\"model-download-progress\", {\n groupId,\n message: \"Preparing local model download...\",\n progress: null,\n status: \"running\",\n });\n\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n\n const timer = setInterval(() => {\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n }, 1000);\n\n state.transformersProgressPollers.set(groupId, timer as unknown as number);\n}\n\nexport function stopTransformersProgressPolling(\n state: { transformersProgressPollers: Map<string, number> },\n groupId: string,\n): void {\n const timer = state.transformersProgressPollers.get(groupId);\n if (typeof timer === \"number\") {\n clearInterval(timer);\n\n state.transformersProgressPollers.delete(groupId);\n }\n}\n\nexport async function cancelLlamafileRequest(requestId: string): Promise<void> {\n try {\n await fetch(LLAMAFILE_PROXY_URL.replace(\"/chat/completions\", \"/cancel\"), {\n body: JSON.stringify({ requestId }),\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-shadowclaw-request-id\": requestId,\n },\n keepalive: true,\n method: \"POST\",\n });\n } catch {\n // Best-effort cancellation only.\n }\n}\n"],"mappings":";;;;;;AAAA,SAAgB,sBAGP;CACP,MAAM,YAAa,WAAmB;CACtC,IAAI,CAAC,aAAa,OAAO,cAAc,YACrC,OAAO;CAGT,IACE,OAAO,UAAU,iBAAiB,cAClC,OAAO,UAAU,WAAW,YAE5B,OAAO;CAGT,OAAO;AACT;;;;AAKA,SAAgB,uBAAgC;CAC9C,OAAO,CAAC,CAAC,oBAAoB;AAC/B;;;;ACKA,eAAsB,oBAAoB,cAEV;CAC9B,OAAQ,MAAM,aAAa,UAAU,KAAM;AAC7C;AAEA,eAAsB,oBAAoB,cAEtB;CAClB,OAAQ,MAAM,aAAa,UAAU,KAAM;AAC7C;AAEA,SAAgB,qBACd,OASA;CACA,OAAO;EACL,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,SAAS,MAAM;CACjB;AACF;AAUA,SAAgB,mBACd,OAQA;CACA,OAAO;EACL,UAAU,MAAM;EAChB,SAAS,MAAM;EACf,QAAQ,MAAM;CAChB;AACF;AAEA,SAAgB,wBAAuC;CACrD,OAAO,OAAO,QAAQ,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,aAAa;EACtD;EACA,MAAM,OAAO;EACb,GAAI,CAAC,OAAO,aAAa,EACvB,QACE,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,SAAS,IACnD,OAAO,SACP,CAAC,OAAO,YAAY,EAC5B;EACA,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;EACtD,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,QAAQ;EAChD,GAAI,OAAO,gBAAgB,EAAE,cAAc,OAAO,aAAa;EAC/D,GAAI,OAAO,sBAAsB,EAC/B,oBAAoB,OAAO,mBAC7B;EACA,GAAI,OAAO,OAAO,mBAAmB,aAAa,EAChD,gBAAgB,OAAO,eACzB;CACF,EAAE;AACJ;AAEA,SAAgB,mBACd,OACgC;CAChC,MAAM,SACJ,OAAO,MAAM,oBAAoB,WAC7B,MAAM,gBAAgB,KAAK,CAAC,CAAC,YAAY,IACzC;CACN,IAAI,CAAC,UAAU,WAAW,QACxB;CAGF,OAAO,EAAE,OAAO;AAClB;AAEA,SAAgB,0BACd,OAUA,YACA,YAAY,IACZ,WAawB;CACxB,IAAI,eAAe,aAAa;EAC9B,MAAM,QAAQ,WAAW;EACzB,MAAM,UAAkC;GACtC,oBACE,OAAO,SAAS,YAAY,OAAO,SAAS,QACxC,MAAM,OACN,MAAM;GACZ,oBAAoB,OAAO,QAAQ,MAAM;GACzC,oBAAoB,OAAO,OAAO,QAAQ,MAAM,aAAa;GAC7D,uBACG,OAAO,WAAW,MAAM,mBAAoB,SAAS;EAC1D;EAEA,IAAI,WACF,QAAQ,6BAA6B;EAGvC,OAAO;CACT;CAEA,IAAI,eAAe,iBAAiB;EAClC,MAAM,UAAU,WAAW;EAC3B,MAAM,UAAkC,CAAC;EACzC,IAAI,SAAS,UAAU,MAAM,uBAC3B,QAAQ,sBACN,SAAS,UAAU,MAAM;EAG7B,IAAI,SAAS,WAAW,MAAM,wBAC5B,QAAQ,uBACN,SAAS,WAAW,MAAM;EAG9B,QAAQ,yBAAyB,SAAS,YAAY,MAAM;EAE5D,OAAO;CACT;CAEA,OAAO,CAAC;AACV;AAEA,SAAgB,sBACd,OAQM;CACN,IAAI,MAAM,gBAAgB,OAAO,aAC/B;CAGF,MAAM,iBAAiB;EACrB,GAAG,MAAM;EACT,SAAS;GACP,GAAI,MAAM,eAAe,WAAW,CAAC;GACrC,oBAAoB,MAAM;GAC1B,oBAAoB,MAAM;GAC1B,oBAAoB,OAAO,MAAM,aAAa;GAC9C,uBAAuB,MAAM,mBAAmB,SAAS;EAC3D;CACF;AACF;AAEA,SAAgB,oBACd,OACM;CACN,IAAI,MAAM,gBAAgB,OAAO,YAC/B;CAGF,MAAM,iBAAiB;EACrB,GAAG,MAAM;EACT,SAAS;GACP,GAAI,MAAM,eAAe,WAAW,CAAC;GACrC,mBAAmB,MAAM;EAC3B;CACF;AACF;AAEA,SAAgB,yBACd,OASA,SACQ;CAER,IAAI,WAAW,MAAM,kCAAkC;EACrD,MAAM,OAAO,MAAM,iCAAiC,IAAI,OAAO;EAC/D,IAAI,MAAM,eAAe,yBAAyB;GAChD,MAAM,OAAO,KAAK,eAAe,WAAW;GAC5C,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;EAEtD;CACF;CAGA,MAAM,iBAAiB,MAAM;CAC7B,IACE,mBACC,CAAC,eAAe,MAAM,eAAe,OAAO,0BAC7C;EACA,MAAM,OAAO,eAAe,WAAW;EACvC,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;CAEtD;CAIA,MAAM,OADgB,YAAY,uBACT,CAAC,EAAE,WAAW;CACvC,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;CAGpD,OAAO;AACT;AAIA,eAAsB,iBACpB,OACA,IACA,MACA,aAA0BA,WACX;CACf,MAAM,gBAAgB;CACtB,MAAM,iBAAiB,oBAAoB,IAAI;CAE/C,MAAM,WAAW,IAAI,YAAY,gBAAgB,IAAI;AACvD;AAEA,eAAsB,mBACpB,OAIA,IACA,UACA,aAA0BA,WACX;CACf,MAAM,SACJ,OAAO,SAAS,WAAW,WAAW,SAAS,OAAO,KAAK,IAAI;CACjE,MAAM,UACJ,OAAO,SAAS,YAAY,WAAW,SAAS,QAAQ,KAAK,IAAI;CACnE,MAAM,WAAW,SAAS,aAAa,QAAQ,QAAQ;CAEvD,MAAM,wBAAwB;CAC9B,MAAM,yBAAyB;CAC/B,MAAM,kBAAkB;CAExB,MAAM,WAAW,IAAI,YAAY,yBAAyB,MAAM;CAChE,MAAM,WAAW,IAAI,YAAY,0BAA0B,OAAO;CAClE,MAAM,WAAW,IAAI,YAAY,mBAAmB,QAAQ;AAC9D;AAEA,eAAsB,qBACpB,OAQA,IACA,UAMA,aAA0BA,WACX;CACf,MAAM,gBAAgB,SAAS;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,MAAM,mBAAmB,SAAS;CAElC,MAAM,WAAW,IAAI,YAAY,gBAAgB,SAAS,IAAI;CAC9D,MAAM,WAAW,IAAI,YAAY,gBAAgB,SAAS,IAAI;CAC9D,MAAM,WAAW,IAAI,YAAY,gBAAgB,OAAO,SAAS,IAAI,CAAC;CACtE,MAAM,WACJ,IACA,YAAY,mBACZ,SAAS,UAAU,SAAS,OAC9B;CAEA,sBAAsB,KAAK;AAC7B;AAEA,eAAsB,mBACpB,OACA,IACA,UACA,aAA0BA,WACX;CACf,MAAM,cAAc,SAAS;CAE7B,MAAM,WAAW,IAAI,YAAY,eAAe,SAAS,IAAI;CAE7D,oBAAoB,KAAK;AAC3B;AAEA,eAAsB,SACpB,OACA,IACA,OACA,aAA0BA,WACX;CACf,MAAM,QAAQ;CACd,IAAI,0BAA0B;CAC9B,IACE,MAAM,aAAa,gBACnB,CAAC,qBAAqB,MACrB,UAAU,sBAAsB,CAAC,QAMlC,0BACE,MAL+B,UAC/B,IACA,YAAY,yBACd;CAIF,MAAM,YAAY,kBAAkB,uBAAuB;CAE3D,MAAM,WAAW,IAAI,YAAY,OAAO,KAAK;CAE7C,MAAM,oBAAoB,OAAO,EAAE;AACrC;AAEA,eAAsB,iBACpB,OACA,IACA,OACA,aAA0BA,WACX;CACf,MAAM,gBAAgB,MAAM,KAAK;CAEjC,MAAM,WAAW,IAAI,YAAY,iBAAiB,MAAM,aAAa;AACvE;AAEA,eAAsB,qBACpB,OACA,IACA,SACA,aAA0BA,WACX;CACf,MAAM,oBAAoB,EAAE,GAAG,QAAQ;CAEvC,MAAM,WACJ,IACA,YAAY,qBACZ,KAAK,UAAU,MAAM,iBAAiB,CACxC;AACF;AAEA,eAAsB,oBACpB,OACA,IACe;CAEf,IAAI,CAAC,WAAW,mBAAmB,WAAW,iBAAiB,SAAS,GACtE;CAGF,MAAM,aAAa,WAAW,wBAC5B,MAAM,UACN,MAAM,KACR;CAEA,IAAI,WAAW,WAAW,GACxB;CAGF,MAAM,QAAQ,WAAW,MACtB,MAAM,EAAE,eAAe,MAAM,YAAY,EAAE,UAAU,MAAM,KAC9D;CAEA,IAAI,OAAO;EACT,MAAM,WAAW,gBAAgB,IAAI,MAAM,EAAE;EAE7C;CACF;CAEA,MAAM,eAAe,WAAW,MAC7B,MAAM,EAAE,eAAe,MAAM,YAAY,CAAC,EAAE,KAC/C;CAEA,IAAI,cACF,MAAM,WAAW,gBAAgB,IAAI,aAAa,EAAE;AAExD;;;;;AAMA,eAAsB,YACpB,OACA,IACA,YACA,MAOA,aAA0BA,WACX;CACf,MAAM,cAAc,YAAY,UAAU;CAC1C,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,qBAAqB,YAAY;CAGnD,MAAM,WAAW;CACjB,MAAM,iBAAiB;CACvB,MAAM,QAAQ,YAAY;CAC1B,sBAAsB,KAAK;CAC3B,oBAAoB,KAAK;CAEzB,MAAM,KAAK,sBAAsB,IAAI,UAAU;CAE/C,MAAM,cAAc,eAClB,aACC,MAAM,KAAK,oBAAoB,KAAM,QACtC,0BAA0B,OAAO,UAAU,CAC7C;CAEA,IAAI,0BAA0B,MAAM;CACpC,IACE,eAAe,gBACf,CAAC,qBAAqB,MACrB,MAAM,UAAU,sBAAsB,CAAC,MAAM,QAM9C,0BACE,MAL+B,UAC/B,IACA,YAAY,yBACd;CAKF,MAAM,YAAY,kBAAkB,uBAAuB;CAE3D,MAAM,WAAW,IAAI,YAAY,UAAU,UAAU;CACrD,MAAM,WAAW,IAAI,YAAY,OAAO,MAAM,KAAK;CAEnD,MAAM,oBAAoB,OAAO,EAAE;AACrC;AAEA,eAAsB,yBACpB,OASA,QACA,SACA,aACe;CACf,IAAI;EACF,MAAM,MAAM,yBAAyB,OAAO,OAAO;EACnD,MAAM,MAAM,MAAM,MAAM,KAAK;GAC3B,SAAS,EACP,QAAQ,mBACV;GACA,QAAQ;EACV,CAAC;EAED,IAAI,CAAC,IAAI,IACP;EAGF,MAAM,SAAS,MAAM,IAAI,KAAK;EAC9B,MAAM,MAAM,OAAO,QAAQ,QAAQ;EACnC,MAAM,qBACJ,OAAO,SAAS,GAAG,KAAK,MAAM,IAC1B,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,IAClC,OAAO,SAAS,GAAG,IACjB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC,IAC5B;EAER,MAAM,UAAwC;GAC5C;GACA,SACE,OAAO,QAAQ,YAAY,YAAY,OAAO,UAC1C,OAAO,UACP;GACN,UAAU;GACV,QACE,QAAQ,WAAW,UAAU,QAAQ,WAAW,UAC5C,OAAO,SACP;EACR;EAEA,OAAO,KAAK,2BAA2B,OAAO;EAE9C,IAAI,QAAQ,WAAW,UAAU,QAAQ,WAAW,SAClD,YAAY,OAAO;CAEvB,QAAQ,CAER;AACF;AAEA,SAAgB,iCACd,OAUA,QACA,SACM;CACN,gCAAgC,OAAO,OAAO;CAG9C,OAAO,KAAK,2BAA2B;EACrC;EACA,SAAS;EACT,UAAU;EACV,QAAQ;CACV,CAAC;CAED,AAAK,yBAAyB,OAAO,QAAQ,UAAU,QACrD,gCAAgC,OAAO,GAAG,CAC5C;CAEA,MAAM,QAAQ,kBAAkB;EAC9B,AAAK,yBAAyB,OAAO,QAAQ,UAAU,QACrD,gCAAgC,OAAO,GAAG,CAC5C;CACF,GAAG,GAAI;CAEP,MAAM,4BAA4B,IAAI,SAAS,KAA0B;AAC3E;AAEA,SAAgB,gCACd,OACA,SACM;CACN,MAAM,QAAQ,MAAM,4BAA4B,IAAI,OAAO;CAC3D,IAAI,OAAO,UAAU,UAAU;EAC7B,cAAc,KAAK;EAEnB,MAAM,4BAA4B,OAAO,OAAO;CAClD;AACF;AAEA,eAAsB,uBAAuB,WAAkC;CAC7E,IAAI;EACF,MAAM,MAAM,oBAAoB,QAAQ,qBAAqB,SAAS,GAAG;GACvE,MAAM,KAAK,UAAU,EAAE,UAAU,CAAC;GAClC,SAAS;IACP,gBAAgB;IAChB,2BAA2B;GAC7B;GACA,WAAW;GACX,QAAQ;EACV,CAAC;CACH,QAAQ,CAER;AACF"}
|
|
1
|
+
{"version":3,"file":"provider-BC9KPI14.js","names":["_defaultSetConfig"],"sources":["../../src/subsystems/providers/utils/is-prompt-api-supported.ts","../../src/core/orchestrator/utils/operations/provider.ts"],"sourcesContent":["export function getLanguageModelApi(): {\n availability: Function;\n create: Function;\n} | null {\n const candidate = (globalThis as any).LanguageModel;\n if (!candidate || typeof candidate !== \"function\") {\n return null;\n }\n\n if (\n typeof candidate.availability !== \"function\" ||\n typeof candidate.create !== \"function\"\n ) {\n return null;\n }\n\n return candidate;\n}\n\n/**\n * Lightweight feature detection for the browser Prompt API.\n */\nexport function isPromptApiSupported(): boolean {\n return !!getLanguageModelApi();\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n LLAMAFILE_PROXY_URL,\n PROVIDERS,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../../config/config.js\";\n\nimport type { ProviderConfig } from \"../../../../config/config.js\";\nimport { getConfig } from \"../../../../db/get-config.js\";\nimport { setConfig as _defaultSetConfig } from \"../../../../db/set-config.js\";\nimport { toolsStore } from \"../../../../stores/tools.js\";\nimport { modelRegistry } from \"../../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../../subsystems/providers/utils/is-prompt-api-supported.js\";\n\nimport type { ShadowClawDatabase } from \"../../../../db/db.js\";\nimport type { LLMProvider } from \"../../../../subsystems/providers/types.js\";\nimport type { ModelDownloadProgressPayload } from \"../../../../subsystems/worker/types.js\";\nimport type { OrchestratorState } from \"../../orchestrator-state.js\";\nimport type { EventBus } from \"../event-bus.js\";\n\ntype SetConfigFn = (\n db: ShadowClawDatabase,\n key: string,\n value: string,\n) => Promise<void>;\n\nexport async function getApiKeyForHeaders(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string | undefined> {\n return (await orchestrator.getApiKey()) || undefined;\n}\n\nexport async function getApiKeyForRequest(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string> {\n return (await orchestrator.getApiKey()) || \"\";\n}\n\nexport function getLlamafileSettings(\n state: Pick<\n OrchestratorState,\n \"llamafileMode\" | \"llamafileHost\" | \"llamafilePort\" | \"llamafileOffline\"\n >,\n): {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n} {\n return {\n mode: state.llamafileMode,\n host: state.llamafileHost,\n port: state.llamafilePort,\n offline: state.llamafileOffline,\n };\n}\n\nexport function getMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\">,\n): { host: string } {\n return {\n host: state.meshLlmHost,\n };\n}\n\nexport function getBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n): {\n authMode: string;\n profile: string;\n region: string;\n} {\n return {\n authMode: state.bedrockAuthMode,\n profile: state.bedrockProfileFallback,\n region: state.bedrockRegionFallback,\n };\n}\n\nexport function getAvailableProviders(): LLMProvider[] {\n return Object.entries(PROVIDERS).map(([id, config]) => ({\n id,\n name: config.name,\n ...(!config.modelsUrl && {\n models:\n Array.isArray(config.models) && config.models.length > 0\n ? config.models\n : [config.defaultModel],\n }),\n ...(config.modelsUrl && { modelsUrl: config.modelsUrl }),\n ...(config.headers && { headers: config.headers }),\n ...(config.apiKeyHeader && { apiKeyHeader: config.apiKeyHeader }),\n ...(config.apiKeyHeaderFormat && {\n apiKeyHeaderFormat: config.apiKeyHeaderFormat,\n }),\n ...(typeof config.requiresApiKey === \"boolean\" && {\n requiresApiKey: config.requiresApiKey,\n }),\n }));\n}\n\nexport function getReasoningConfig(\n state: Pick<OrchestratorState, \"reasoningEffort\">,\n): { effort: string } | undefined {\n const effort =\n typeof state.reasoningEffort === \"string\"\n ? state.reasoningEffort.trim().toLowerCase()\n : \"none\";\n if (!effort || effort === \"none\") {\n return undefined;\n }\n\n return { effort };\n}\n\nexport function getProviderRuntimeHeaders(\n state: Pick<\n OrchestratorState,\n | \"bedrockAuthMode\"\n | \"bedrockProfileFallback\"\n | \"bedrockRegionFallback\"\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n >,\n providerId: string,\n requestId = \"\",\n overrides?: {\n bedrock_proxy?: {\n authMode?: \"provider_chain\" | \"sso\";\n profile?: string;\n region?: string;\n };\n llamafile?: {\n host?: string;\n mode?: \"cli\" | \"server\";\n offline?: boolean;\n port?: number;\n };\n },\n): Record<string, string> {\n if (providerId === \"llamafile\") {\n const llama = overrides?.llamafile;\n const headers: Record<string, string> = {\n \"x-llamafile-mode\":\n llama?.mode === \"server\" || llama?.mode === \"cli\"\n ? llama.mode\n : state.llamafileMode,\n \"x-llamafile-host\": llama?.host || state.llamafileHost,\n \"x-llamafile-port\": String(llama?.port || state.llamafilePort),\n \"x-llamafile-offline\":\n (llama?.offline ?? state.llamafileOffline) ? \"true\" : \"false\",\n };\n\n if (requestId) {\n headers[\"x-shadowclaw-request-id\"] = requestId;\n }\n\n return headers;\n }\n\n if (providerId === \"bedrock_proxy\") {\n const bedrock = overrides?.bedrock_proxy;\n const headers: Record<string, string> = {};\n if (bedrock?.region || state.bedrockRegionFallback) {\n headers[\"x-bedrock-region\"] =\n bedrock?.region || state.bedrockRegionFallback;\n }\n\n if (bedrock?.profile || state.bedrockProfileFallback) {\n headers[\"x-bedrock-profile\"] =\n bedrock?.profile || state.bedrockProfileFallback;\n }\n\n headers[\"x-bedrock-auth-mode\"] = bedrock?.authMode || state.bedrockAuthMode;\n\n return headers;\n }\n\n return {};\n}\n\nexport function applyLlamafileHeaders(\n state: Pick<\n OrchestratorState,\n | \"providerConfig\"\n | \"llamafileMode\"\n | \"llamafileHost\"\n | \"llamafilePort\"\n | \"llamafileOffline\"\n >,\n): void {\n if (state.providerConfig?.id !== \"llamafile\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-llamafile-mode\": state.llamafileMode,\n \"x-llamafile-host\": state.llamafileHost,\n \"x-llamafile-port\": String(state.llamafilePort),\n \"x-llamafile-offline\": state.llamafileOffline ? \"true\" : \"false\",\n },\n };\n}\n\nexport function applyMeshLlmHeaders(\n state: Pick<OrchestratorState, \"providerConfig\" | \"meshLlmHost\">,\n): void {\n if (state.providerConfig?.id !== \"mesh-llm\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-mesh-llm-host\": state.meshLlmHost,\n },\n };\n}\n\nexport function getTransformersStatusUrl(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n groupId?: string,\n): string {\n // If we have a groupId, check if there is an in-flight effective provider config for it\n if (groupId && state.inFlightEffectiveProviderByGroup) {\n const info = state.inFlightEffectiveProviderByGroup.get(groupId);\n if (info?.providerId === \"transformers_js_local\") {\n const base = info.providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n }\n\n // If the current providerConfig is transformers_js_local (or undefined for mock tests), use its baseUrl\n const providerConfig = state.providerConfig;\n if (\n providerConfig &&\n (!providerConfig.id || providerConfig.id === \"transformers_js_local\")\n ) {\n const base = providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n\n // Fallback to local transformers.js proxy status\n const localProvider = getProvider(\"transformers_js_local\");\n const base = localProvider?.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n\n return \"http://localhost:8888/transformers-js-proxy/status\";\n}\n\n// ── Async setters ───────────────────────────────────────────────────────────\n\nexport async function setAssistantName(\n state: Pick<OrchestratorState, \"assistantName\" | \"triggerPattern\">,\n db: ShadowClawDatabase,\n name: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.assistantName = name;\n state.triggerPattern = buildTriggerPattern(name);\n\n await _setConfig(db, CONFIG_KEYS.ASSISTANT_NAME, name);\n}\n\nexport async function setBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n db: ShadowClawDatabase,\n settings: { authMode: string; profile: string; region: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const region =\n typeof settings.region === \"string\" ? settings.region.trim() : \"\";\n const profile =\n typeof settings.profile === \"string\" ? settings.profile.trim() : \"\";\n const authMode = settings.authMode === \"sso\" ? \"sso\" : \"provider_chain\";\n\n state.bedrockRegionFallback = region;\n state.bedrockProfileFallback = profile;\n state.bedrockAuthMode = authMode;\n\n await _setConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK, region);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK, profile);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE, authMode);\n}\n\nexport async function setLlamafileSettings(\n state: Pick<\n OrchestratorState,\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n | \"providerConfig\"\n >,\n db: ShadowClawDatabase,\n settings: {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.llamafileMode = settings.mode;\n state.llamafileHost = settings.host;\n state.llamafilePort = settings.port;\n state.llamafileOffline = settings.offline;\n\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, settings.mode);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_HOST, settings.host);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_PORT, String(settings.port));\n await _setConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n settings.offline ? \"true\" : \"false\",\n );\n\n applyLlamafileHeaders(state);\n}\n\nexport async function setMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\" | \"providerConfig\">,\n db: ShadowClawDatabase,\n settings: { host: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.meshLlmHost = settings.host;\n\n await _setConfig(db, CONFIG_KEYS.MESH_LLM_HOST, settings.host);\n\n applyMeshLlmHeaders(state);\n}\n\nexport async function setModel(\n state: Pick<OrchestratorState, \"model\" | \"maxTokens\" | \"provider\">,\n db: ShadowClawDatabase,\n model: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.model = model;\n let effectiveModelForLimits = model;\n if (\n state.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (model === \"browser-built-in\" || !model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.MODEL, model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function setPeerjsMyAlias(\n state: Pick<OrchestratorState, \"peerjsMyAlias\">,\n db: ShadowClawDatabase,\n alias: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsMyAlias = alias.trim();\n\n await _setConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS, state.peerjsMyAlias);\n}\n\nexport async function setPeerjsPeerAliases(\n state: Pick<OrchestratorState, \"peerjsPeerAliases\">,\n db: ShadowClawDatabase,\n aliases: Record<string, string>,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsPeerAliases = { ...aliases };\n\n await _setConfig(\n db,\n CONFIG_KEYS.PEERJS_PEER_ALIASES,\n JSON.stringify(state.peerjsPeerAliases),\n );\n}\n\nexport async function autoActivateProfile(\n state: Pick<OrchestratorState, \"provider\" | \"model\">,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Preserve an explicit manual \"no tools\" configuration.\n if (!toolsStore.activeProfileId && toolsStore.enabledToolNames.size === 0) {\n return;\n }\n\n const candidates = toolsStore.findProfilesForProvider(\n state.provider,\n state.model,\n );\n\n if (candidates.length === 0) {\n return;\n }\n\n const exact = candidates.find(\n (p) => p.providerId === state.provider && p.model === state.model,\n );\n\n if (exact) {\n await toolsStore.activateProfile(db, exact.id);\n\n return;\n }\n\n const providerOnly = candidates.find(\n (p) => p.providerId === state.provider && !p.model,\n );\n\n if (providerOnly) {\n await toolsStore.activateProfile(db, providerOnly.id);\n }\n}\n\n/**\n * Switch the active LLM provider. This is more complex than the simple\n * settings because it also fetches model info and auto-activates profiles.\n */\nexport async function setProvider(\n state: OrchestratorState,\n db: ShadowClawDatabase,\n providerId: string,\n deps: {\n loadApiKeyForProvider: (\n db: ShadowClawDatabase,\n providerId: string,\n ) => Promise<void>;\n getApiKeyForHeaders: () => Promise<string | undefined>;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const newProvider = getProvider(providerId);\n if (!newProvider) {\n throw new Error(`Unknown provider: ${providerId}`);\n }\n\n state.provider = providerId;\n state.providerConfig = newProvider;\n state.model = newProvider.defaultModel;\n applyLlamafileHeaders(state);\n applyMeshLlmHeaders(state);\n\n await deps.loadApiKeyForProvider(db, providerId);\n\n await modelRegistry.fetchModelInfo(\n newProvider,\n (await deps.getApiKeyForHeaders()) || undefined,\n getProviderRuntimeHeaders(state, providerId),\n );\n\n let effectiveModelForLimits = state.model;\n if (\n providerId === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (state.model === \"browser-built-in\" || !state.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.PROVIDER, providerId);\n await _setConfig(db, CONFIG_KEYS.MODEL, state.model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function pollTransformersProgress(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n stopPolling: (groupId: string) => void,\n): Promise<void> {\n try {\n const url = getTransformersStatusUrl(state, groupId);\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!res.ok) {\n return;\n }\n\n const status = await res.json();\n const raw = Number(status?.progress);\n const normalizedProgress =\n Number.isFinite(raw) && raw > 1\n ? Math.max(0, Math.min(1, raw / 100))\n : Number.isFinite(raw)\n ? Math.max(0, Math.min(1, raw))\n : null;\n\n const payload: ModelDownloadProgressPayload = {\n groupId,\n message:\n typeof status?.message === \"string\" && status.message\n ? status.message\n : undefined,\n progress: normalizedProgress,\n status:\n status?.status === \"done\" || status?.status === \"error\"\n ? status.status\n : \"running\",\n };\n\n events.emit(\"model-download-progress\", payload);\n\n if (payload.status === \"done\" || payload.status === \"error\") {\n stopPolling(groupId);\n }\n } catch {\n // Ignore status polling failures so inference can continue uninterrupted.\n }\n}\n\nexport function startTransformersProgressPolling(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n transformersProgressPollers: Map<string, number>;\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n): void {\n stopTransformersProgressPolling(state, groupId);\n\n // Show immediate feedback while the first network poll is in flight.\n events.emit(\"model-download-progress\", {\n groupId,\n message: \"Preparing local model download...\",\n progress: null,\n status: \"running\",\n });\n\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n\n const timer = setInterval(() => {\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n }, 1000);\n\n state.transformersProgressPollers.set(groupId, timer as unknown as number);\n}\n\nexport function stopTransformersProgressPolling(\n state: { transformersProgressPollers: Map<string, number> },\n groupId: string,\n): void {\n const timer = state.transformersProgressPollers.get(groupId);\n if (typeof timer === \"number\") {\n clearInterval(timer);\n\n state.transformersProgressPollers.delete(groupId);\n }\n}\n\nexport async function cancelLlamafileRequest(requestId: string): Promise<void> {\n try {\n await fetch(LLAMAFILE_PROXY_URL.replace(\"/chat/completions\", \"/cancel\"), {\n body: JSON.stringify({ requestId }),\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-shadowclaw-request-id\": requestId,\n },\n keepalive: true,\n method: \"POST\",\n });\n } catch {\n // Best-effort cancellation only.\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as getDb, t as getConfig } from "./get-config-BWhs5HFF.js";
|
|
2
|
-
import { r as CONFIG_KEYS } from "./config-
|
|
3
|
-
import { t as getOrCreateSubscriberId } from "./get-or-create-subscriber-id-
|
|
2
|
+
import { r as CONFIG_KEYS } from "./config-BrHR97zt.js";
|
|
3
|
+
import { t as getOrCreateSubscriberId } from "./get-or-create-subscriber-id-wyzaML7Z.js";
|
|
4
4
|
|
|
5
5
|
//#region src/subsystems/notifications/push-client.ts
|
|
6
6
|
/**
|
|
@@ -61,7 +61,7 @@ async function subscribeToPush(clientId, deviceLabel, subscriberId) {
|
|
|
61
61
|
let resolvedDeviceLabel = deviceLabel;
|
|
62
62
|
let resolvedSubscriberId = subscriberId;
|
|
63
63
|
if (!resolvedClientId || !resolvedDeviceLabel) try {
|
|
64
|
-
const initCp = await import("./init-control-plane-
|
|
64
|
+
const initCp = await import("./init-control-plane-CEGdzgWX.js");
|
|
65
65
|
if (!resolvedClientId && typeof initCp.getOrCreateControlPlaneClientId === "function") resolvedClientId = initCp.getOrCreateControlPlaneClientId();
|
|
66
66
|
if (!resolvedDeviceLabel && typeof initCp.detectDeviceLabel === "function") resolvedDeviceLabel = initCp.detectDeviceLabel();
|
|
67
67
|
} catch (_) {}
|
|
@@ -97,7 +97,7 @@ async function syncExistingPushSubscription(subscriberId) {
|
|
|
97
97
|
let resolvedSubscriberId = subscriberId;
|
|
98
98
|
if (typeof localStorage !== "undefined") resolvedClientId = localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || void 0;
|
|
99
99
|
try {
|
|
100
|
-
const initCp = await import("./init-control-plane-
|
|
100
|
+
const initCp = await import("./init-control-plane-CEGdzgWX.js");
|
|
101
101
|
if (!resolvedClientId && typeof initCp.getOrCreateControlPlaneClientId === "function") resolvedClientId = initCp.getOrCreateControlPlaneClientId();
|
|
102
102
|
if (typeof initCp.detectDeviceLabel === "function") resolvedDeviceLabel = initCp.detectDeviceLabel();
|
|
103
103
|
} catch (_) {}
|
|
@@ -144,4 +144,4 @@ async function getCurrentSubscription() {
|
|
|
144
144
|
|
|
145
145
|
//#endregion
|
|
146
146
|
export { syncExistingPushSubscription as a, subscribeToPush as i, getPushFetchOptions as n, unsubscribeFromPush as o, getPushUrl as r, getCurrentSubscription as t };
|
|
147
|
-
//# sourceMappingURL=push-client-
|
|
147
|
+
//# sourceMappingURL=push-client-CAm6UMvE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push-client-Cx5rMs6J.js","names":[],"sources":["../../src/subsystems/notifications/push-client.ts"],"sourcesContent":["/**\n * Client-side Web Push subscription management.\n * Runs in the browser — communicates with the server's push routes.\n */\n\nimport { CONFIG_KEYS } from \"../../config/config.js\";\nimport { getDb } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { getOrCreateSubscriberId } from \"../../db/get-or-create-subscriber-id.js\";\n\n/**\n * Resolve a push route URL, optionally using a configured proxy.\n */\nexport async function getPushUrl(path: string): Promise<string> {\n const db = await getDb();\n let proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n\n if (!proxyUrl && typeof localStorage !== \"undefined\") {\n try {\n proxyUrl = localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL) || undefined;\n } catch (_) {}\n }\n\n if (!proxyUrl) {\n return path;\n }\n\n // Ensure path starts with /\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n // Ensure proxyUrl doesn't end with /\n const normalizedProxy = proxyUrl.endsWith(\"/\")\n ? proxyUrl.slice(0, -1)\n : proxyUrl;\n\n return `${normalizedProxy}${normalizedPath}`;\n}\n\nexport function getPushFetchOptions(\n url: string,\n baseOptions: RequestInit = {},\n): RequestInit {\n const opts: any = { ...baseOptions };\n try {\n const locOrigin =\n typeof location !== \"undefined\"\n ? location.origin\n : \"http://127.0.0.1:8888\";\n const u = new URL(url, locOrigin);\n const host = u.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host === \"[::1]\"\n ) {\n opts.targetAddressSpace = \"loopback\";\n } else if (\n /^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.)/.test(host) ||\n !host.includes(\".\") ||\n host.endsWith(\".local\") ||\n host.endsWith(\".lan\") ||\n host.endsWith(\".home\") ||\n host.endsWith(\".internal\")\n ) {\n opts.targetAddressSpace = \"private\";\n }\n } catch (_) {}\n return opts;\n}\n\n/**\n * Convert a URL-safe base64 string to a Uint8Array.\n * Required for PushManager.subscribe() applicationServerKey.\n */\nexport function urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n\n return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)));\n}\n\n/**\n * Fetch the VAPID public key from the server.\n */\nexport async function getVapidPublicKey(): Promise<string> {\n const url = await getPushUrl(\"/push/vapid-public-key\");\n const res = await fetch(url, getPushFetchOptions(url));\n const data = await res.json();\n\n return data.publicKey;\n}\n\n/**\n * Subscribe to push notifications.\n * Requests permission, creates a push subscription, and sends it to the server.\n */\nexport async function subscribeToPush(\n clientId?: string,\n deviceLabel?: string,\n subscriberId?: string,\n): Promise<PushSubscription> {\n const registration = await navigator.serviceWorker.ready;\n const publicKey = await getVapidPublicKey();\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(publicKey) as any,\n });\n\n let resolvedClientId =\n clientId ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined\n : undefined);\n\n let resolvedDeviceLabel = deviceLabel;\n let resolvedSubscriberId = subscriberId;\n\n if (!resolvedClientId || !resolvedDeviceLabel) {\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (\n !resolvedDeviceLabel &&\n typeof initCp.detectDeviceLabel === \"function\"\n ) {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n }\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof subscription.toJSON === \"function\"\n ? subscription.toJSON()\n : JSON.parse(JSON.stringify(subscription));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId ? { subscriberId: resolvedSubscriberId } : {}),\n }),\n }),\n );\n\n return subscription;\n}\n\n/**\n * Re-register an existing push subscription with the server if one exists,\n * ensuring clientId, deviceLabel, and subscriberId are up-to-date.\n */\nexport async function syncExistingPushSubscription(\n subscriberId?: string,\n): Promise<void> {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n try {\n const reg = await navigator.serviceWorker.ready;\n const sub = await reg.pushManager.getSubscription();\n if (!sub) {\n return;\n }\n\n let resolvedClientId: string | undefined;\n let resolvedDeviceLabel: string | undefined;\n let resolvedSubscriberId = subscriberId;\n\n if (typeof localStorage !== \"undefined\") {\n resolvedClientId =\n localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined;\n }\n\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (typeof initCp.detectDeviceLabel === \"function\") {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof sub.toJSON === \"function\"\n ? sub.toJSON()\n : JSON.parse(JSON.stringify(sub));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId\n ? { subscriberId: resolvedSubscriberId }\n : {}),\n }),\n }),\n );\n } catch (_) {\n // Non-fatal if server is unreachable\n }\n}\n\n/**\n * Unsubscribe from push notifications.\n * Removes the push subscription locally and notifies the server.\n */\nexport async function unsubscribeFromPush(): Promise<void> {\n const registration = await navigator.serviceWorker.ready;\n const subscription = await registration.pushManager.getSubscription();\n\n if (!subscription) {\n return;\n }\n\n const { endpoint } = subscription;\n await subscription.unsubscribe();\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint }),\n }),\n );\n}\n\n/**\n * Get the current push subscription (or null if not subscribed).\n */\nexport async function getCurrentSubscription(): Promise<PushSubscription | null> {\n const registration = await navigator.serviceWorker.ready;\n\n return registration.pushManager.getSubscription();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"push-client-CAm6UMvE.js","names":[],"sources":["../../src/subsystems/notifications/push-client.ts"],"sourcesContent":["/**\n * Client-side Web Push subscription management.\n * Runs in the browser — communicates with the server's push routes.\n */\n\nimport { CONFIG_KEYS } from \"../../config/config.js\";\nimport { getDb } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { getOrCreateSubscriberId } from \"../../db/get-or-create-subscriber-id.js\";\n\n/**\n * Resolve a push route URL, optionally using a configured proxy.\n */\nexport async function getPushUrl(path: string): Promise<string> {\n const db = await getDb();\n let proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n\n if (!proxyUrl && typeof localStorage !== \"undefined\") {\n try {\n proxyUrl = localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL) || undefined;\n } catch (_) {}\n }\n\n if (!proxyUrl) {\n return path;\n }\n\n // Ensure path starts with /\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n // Ensure proxyUrl doesn't end with /\n const normalizedProxy = proxyUrl.endsWith(\"/\")\n ? proxyUrl.slice(0, -1)\n : proxyUrl;\n\n return `${normalizedProxy}${normalizedPath}`;\n}\n\nexport function getPushFetchOptions(\n url: string,\n baseOptions: RequestInit = {},\n): RequestInit {\n const opts: any = { ...baseOptions };\n try {\n const locOrigin =\n typeof location !== \"undefined\"\n ? location.origin\n : \"http://127.0.0.1:8888\";\n const u = new URL(url, locOrigin);\n const host = u.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host === \"[::1]\"\n ) {\n opts.targetAddressSpace = \"loopback\";\n } else if (\n /^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.)/.test(host) ||\n !host.includes(\".\") ||\n host.endsWith(\".local\") ||\n host.endsWith(\".lan\") ||\n host.endsWith(\".home\") ||\n host.endsWith(\".internal\")\n ) {\n opts.targetAddressSpace = \"private\";\n }\n } catch (_) {}\n return opts;\n}\n\n/**\n * Convert a URL-safe base64 string to a Uint8Array.\n * Required for PushManager.subscribe() applicationServerKey.\n */\nexport function urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n\n return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)));\n}\n\n/**\n * Fetch the VAPID public key from the server.\n */\nexport async function getVapidPublicKey(): Promise<string> {\n const url = await getPushUrl(\"/push/vapid-public-key\");\n const res = await fetch(url, getPushFetchOptions(url));\n const data = await res.json();\n\n return data.publicKey;\n}\n\n/**\n * Subscribe to push notifications.\n * Requests permission, creates a push subscription, and sends it to the server.\n */\nexport async function subscribeToPush(\n clientId?: string,\n deviceLabel?: string,\n subscriberId?: string,\n): Promise<PushSubscription> {\n const registration = await navigator.serviceWorker.ready;\n const publicKey = await getVapidPublicKey();\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(publicKey) as any,\n });\n\n let resolvedClientId =\n clientId ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined\n : undefined);\n\n let resolvedDeviceLabel = deviceLabel;\n let resolvedSubscriberId = subscriberId;\n\n if (!resolvedClientId || !resolvedDeviceLabel) {\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (\n !resolvedDeviceLabel &&\n typeof initCp.detectDeviceLabel === \"function\"\n ) {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n }\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof subscription.toJSON === \"function\"\n ? subscription.toJSON()\n : JSON.parse(JSON.stringify(subscription));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId ? { subscriberId: resolvedSubscriberId } : {}),\n }),\n }),\n );\n\n return subscription;\n}\n\n/**\n * Re-register an existing push subscription with the server if one exists,\n * ensuring clientId, deviceLabel, and subscriberId are up-to-date.\n */\nexport async function syncExistingPushSubscription(\n subscriberId?: string,\n): Promise<void> {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n try {\n const reg = await navigator.serviceWorker.ready;\n const sub = await reg.pushManager.getSubscription();\n if (!sub) {\n return;\n }\n\n let resolvedClientId: string | undefined;\n let resolvedDeviceLabel: string | undefined;\n let resolvedSubscriberId = subscriberId;\n\n if (typeof localStorage !== \"undefined\") {\n resolvedClientId =\n localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined;\n }\n\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (typeof initCp.detectDeviceLabel === \"function\") {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof sub.toJSON === \"function\"\n ? sub.toJSON()\n : JSON.parse(JSON.stringify(sub));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId\n ? { subscriberId: resolvedSubscriberId }\n : {}),\n }),\n }),\n );\n } catch (_) {\n // Non-fatal if server is unreachable\n }\n}\n\n/**\n * Unsubscribe from push notifications.\n * Removes the push subscription locally and notifies the server.\n */\nexport async function unsubscribeFromPush(): Promise<void> {\n const registration = await navigator.serviceWorker.ready;\n const subscription = await registration.pushManager.getSubscription();\n\n if (!subscription) {\n return;\n }\n\n const { endpoint } = subscription;\n await subscription.unsubscribe();\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint }),\n }),\n );\n}\n\n/**\n * Get the current push subscription (or null if not subscribed).\n */\nexport async function getCurrentSubscription(): Promise<PushSubscription | null> {\n const registration = await navigator.serviceWorker.ready;\n\n return registration.pushManager.getSubscription();\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as getGroupDir, t as parsePath } from "./parse-path-
|
|
1
|
+
import { n as getGroupDir, t as parsePath } from "./parse-path-BOHQP_IQ.js";
|
|
2
2
|
|
|
3
3
|
//#region src/storage/read-group-file-bytes.ts
|
|
4
4
|
/**
|
|
@@ -25,4 +25,4 @@ async function readGroupFileBytes(db, groupId, filePath) {
|
|
|
25
25
|
|
|
26
26
|
//#endregion
|
|
27
27
|
export { readGroupFileBytes as t };
|
|
28
|
-
//# sourceMappingURL=read-group-file-bytes-
|
|
28
|
+
//# sourceMappingURL=read-group-file-bytes-UQIk1eJG.js.map
|
package/dist/lib/{read-group-file-bytes-CXOG_YyM.js.map → read-group-file-bytes-UQIk1eJG.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-group-file-bytes-
|
|
1
|
+
{"version":3,"file":"read-group-file-bytes-UQIk1eJG.js","names":[],"sources":["../../src/storage/read-group-file-bytes.ts"],"sourcesContent":["import { getGroupDir } from \"./get-group-dir.js\";\nimport { parsePath } from \"./parse-path.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Read raw bytes from a file in a group's workspace.\n */\nexport async function readGroupFileBytes(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<Uint8Array> {\n const groupDir = await getGroupDir(db, groupId);\n const { dirs, filename } = parsePath(filePath);\n\n let dir = groupDir;\n for (const seg of dirs) {\n dir = await dir.getDirectoryHandle(seg);\n }\n\n const fileHandle = await dir.getFileHandle(filename);\n\n try {\n const syncHandle = await (fileHandle as any).createSyncAccessHandle();\n const size = syncHandle.getSize();\n const buf = new Uint8Array(size);\n\n syncHandle.read(buf, { at: 0 });\n syncHandle.close();\n\n return buf;\n } catch {\n const file = await fileHandle.getFile();\n const arrayBuffer = await file.arrayBuffer();\n\n return new Uint8Array(arrayBuffer);\n }\n}\n"],"mappings":";;;;;;AAOA,eAAsB,mBACpB,IACA,SACA,UACqB;CACrB,MAAM,WAAW,MAAM,YAAY,IAAI,OAAO;CAC9C,MAAM,EAAE,MAAM,aAAa,UAAU,QAAQ;CAE7C,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,MAChB,MAAM,MAAM,IAAI,mBAAmB,GAAG;CAGxC,MAAM,aAAa,MAAM,IAAI,cAAc,QAAQ;CAEnD,IAAI;EACF,MAAM,aAAa,MAAO,WAAmB,uBAAuB;EACpE,MAAM,OAAO,WAAW,QAAQ;EAChC,MAAM,MAAM,IAAI,WAAW,IAAI;EAE/B,WAAW,KAAK,KAAK,EAAE,IAAI,EAAE,CAAC;EAC9B,WAAW,MAAM;EAEjB,OAAO;CACT,QAAQ;EAEN,MAAM,cAAc,OAAM,MADP,WAAW,QAAQ,EACR,CAAC,YAAY;EAE3C,OAAO,IAAI,WAAW,WAAW;CACnC;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as getConfig } from "./get-config-BWhs5HFF.js";
|
|
2
2
|
import { t as setConfig } from "./set-config-CUadvYZ1.js";
|
|
3
|
-
import { _ as createGroup, v as getGroupMetadata } from "./orchestrator-
|
|
3
|
+
import { _ as createGroup, v as getGroupMetadata } from "./orchestrator-cRBe3lhq.js";
|
|
4
4
|
|
|
5
5
|
//#region src/db/rooms.ts
|
|
6
6
|
/**
|
|
@@ -66,4 +66,4 @@ async function deleteRoom(db, roomId) {
|
|
|
66
66
|
|
|
67
67
|
//#endregion
|
|
68
68
|
export { roomIdFromGroupId as a, roomGroupId as i, deleteRoom as n, upsertRoom as o, getRoomMetadata as r, ROOM_PREFIX as t };
|
|
69
|
-
//# sourceMappingURL=rooms-
|
|
69
|
+
//# sourceMappingURL=rooms-Dzphx3rK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rooms-
|
|
1
|
+
{"version":3,"file":"rooms-Dzphx3rK.js","names":[],"sources":["../../src/db/rooms.ts"],"sourcesContent":["/**\n * ShadowClaw — Room (multi-party conversation) metadata management\n *\n * A room is layered on top of a {@link GroupMeta} whose groupId is\n * `room:<roomId>` (so existing message storage, OPFS workspace, unread state,\n * and the conversation list work unchanged). This module persists the room\n * roster / host separately under a dedicated config key.\n */\n\nimport { getConfig } from \"./get-config.js\";\nimport { setConfig } from \"./set-config.js\";\nimport { createGroup, getGroupMetadata } from \"./groups.js\";\nimport { ulid } from \"../utils/ulid.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\nimport type { RoomMember, RoomMeta } from \"../subsystems/channels/types.js\";\n\nconst CONFIG_KEY = \"room_metadata\";\n\n/** The groupId prefix used for room conversations. */\nexport const ROOM_PREFIX = \"room:\";\n\n/** Build the conversation groupId for a bare room id. */\nexport function roomGroupId(roomId: string): string {\n return `${ROOM_PREFIX}${roomId}`;\n}\n\n/** Extract the bare room id from a `room:<id>` groupId. */\nexport function roomIdFromGroupId(groupId: string): string {\n return groupId.startsWith(ROOM_PREFIX)\n ? groupId.slice(ROOM_PREFIX.length)\n : groupId;\n}\n\n/** Get all room metadata from config. */\nexport async function getRoomMetadata(\n db: ShadowClawDatabase,\n): Promise<RoomMeta[]> {\n const raw = await getConfig(db, CONFIG_KEY);\n if (!raw) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(raw);\n\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/** Save all room metadata to config. */\nexport async function saveRoomMetadata(\n db: ShadowClawDatabase,\n metadata: RoomMeta[],\n): Promise<void> {\n await setConfig(db, CONFIG_KEY, JSON.stringify(metadata));\n}\n\n/** Get a single room by its bare room id. */\nexport async function getRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n\n return rooms.find((r) => r.roomId === roomId) ?? null;\n}\n\n/**\n * Persist (insert or replace) a single room record and ensure a matching\n * conversation group exists.\n */\nexport async function upsertRoom(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n const index = rooms.findIndex((r) => r.roomId === room.roomId);\n if (index >= 0) {\n rooms[index] = room;\n } else {\n rooms.push(room);\n }\n\n await saveRoomMetadata(db, rooms);\n await ensureRoomGroup(db, room);\n}\n\n/**\n * Ensure a `room:<roomId>` GroupMeta exists for the given room so the\n * conversation, message history and workspace are available.\n */\nasync function ensureRoomGroup(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const groups = await getGroupMetadata(db);\n const groupId = roomGroupId(room.roomId);\n if (groups.some((g) => g.groupId === groupId)) {\n return;\n }\n\n await createGroup(db, room.name, ROOM_PREFIX, room.roomId);\n}\n\n/**\n * Create a new room (as host) and persist it along with its conversation group.\n */\nexport async function createRoom(\n db: ShadowClawDatabase,\n name: string,\n hostPeerId: string,\n hostMember: RoomMember,\n): Promise<RoomMeta> {\n const room: RoomMeta = {\n roomId: ulid(),\n name,\n hostPeerId,\n members: [hostMember],\n createdAt: Date.now(),\n };\n\n await upsertRoom(db, room);\n\n return room;\n}\n\n/** Add or update a member in a room's roster. Returns the updated room. */\nexport async function addRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n member: RoomMember,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n const index = room.members.findIndex((m) => m.peerId === member.peerId);\n if (index >= 0) {\n room.members[index] = member;\n } else {\n room.members.push(member);\n }\n\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Remove a member from a room's roster. Returns the updated room. */\nexport async function removeRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n peerId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n room.members = room.members.filter((m) => m.peerId !== peerId);\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Delete a room record (does not delete its conversation group/messages). */\nexport async function deleteRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n await saveRoomMetadata(\n db,\n rooms.filter((r) => r.roomId !== roomId),\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,aAAa;;AAGnB,MAAa,cAAc;;AAG3B,SAAgB,YAAY,QAAwB;CAClD,OAAO,GAAG,cAAc;AAC1B;;AAGA,SAAgB,kBAAkB,SAAyB;CACzD,OAAO,QAAQ,kBAAsB,IACjC,QAAQ,MAAM,CAAkB,IAChC;AACN;;AAGA,eAAsB,gBACpB,IACqB;CACrB,MAAM,MAAM,MAAM,UAAU,IAAI,UAAU;CAC1C,IAAI,CAAC,KACH,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAE7B,OAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;CAC3C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;AAGA,eAAsB,iBACpB,IACA,UACe;CACf,MAAM,UAAU,IAAI,YAAY,KAAK,UAAU,QAAQ,CAAC;AAC1D;;;;;AAgBA,eAAsB,WACpB,IACA,MACe;CACf,MAAM,QAAQ,MAAM,gBAAgB,EAAE;CACtC,MAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,WAAW,KAAK,MAAM;CAC7D,IAAI,SAAS,GACX,MAAM,SAAS;MAEf,MAAM,KAAK,IAAI;CAGjB,MAAM,iBAAiB,IAAI,KAAK;CAChC,MAAM,gBAAgB,IAAI,IAAI;AAChC;;;;;AAMA,eAAe,gBACb,IACA,MACe;CACf,MAAM,SAAS,MAAM,iBAAiB,EAAE;CACxC,MAAM,UAAU,YAAY,KAAK,MAAM;CACvC,IAAI,OAAO,MAAM,MAAM,EAAE,YAAY,OAAO,GAC1C;CAGF,MAAM,YAAY,IAAI,KAAK,MAAM,aAAa,KAAK,MAAM;AAC3D;;AAmEA,eAAsB,WACpB,IACA,QACe;CAEf,MAAM,iBACJ,KACA,MAHkB,gBAAgB,EAAE,EAG/B,CAAC,QAAQ,MAAM,EAAE,WAAW,MAAM,CACzC;AACF"}
|