shadow-claw 1.31.0 → 1.33.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/dist/electron/main.cjs +1 -1
- package/dist/lib/components/index.js +26 -26
- package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/settings/shadow-claw-git.js +1 -1
- package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
- package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
- package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
- package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw-a2ui.js +1 -1
- package/dist/lib/components/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/shadow-claw-channels.js +1 -1
- package/dist/lib/components/shadow-claw-chat.js +1 -1
- package/dist/lib/components/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/shadow-claw-conversations.js +1 -1
- package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
- package/dist/lib/components/shadow-claw-files.js +1 -1
- package/dist/lib/components/shadow-claw-git.js +1 -1
- package/dist/lib/components/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/shadow-claw-llm.js +1 -1
- package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/shadow-claw-networking.js +1 -1
- package/dist/lib/components/shadow-claw-notifications.js +1 -1
- package/dist/lib/components/shadow-claw-page-header.js +1 -1
- package/dist/lib/components/shadow-claw-pages.js +1 -1
- package/dist/lib/components/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/shadow-claw-settings.js +1 -1
- package/dist/lib/components/shadow-claw-storage.js +1 -1
- package/dist/lib/components/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/shadow-claw-tasks.js +1 -1
- package/dist/lib/components/shadow-claw-terminal.js +1 -1
- package/dist/lib/components/shadow-claw-tools.js +1 -1
- package/dist/lib/components/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw.js +1 -1
- package/dist/lib/{config-DjZ9QWc4.js → config-BcFbkaQv.js} +21 -4
- package/dist/lib/config-BcFbkaQv.js.map +1 -0
- package/dist/lib/{configurePeerJs-u7CYSquX.js → configurePeerJs-CBMPHbwa.js} +3 -3
- package/dist/lib/{configurePeerJs-u7CYSquX.js.map → configurePeerJs-CBMPHbwa.js.map} +1 -1
- package/dist/lib/{connections-BURqMIUv.js → connections-PZrUDf49.js} +2 -2
- package/dist/lib/{connections-BURqMIUv.js.map → connections-PZrUDf49.js.map} +1 -1
- package/dist/lib/{downloadGroupFile-B8J4up2a.js → downloadGroupFile-DSRUa9Au.js} +2 -2
- package/dist/lib/{downloadGroupFile-B8J4up2a.js.map → downloadGroupFile-DSRUa9Au.js.map} +1 -1
- package/dist/lib/{file-viewer-DoHM75Jz.js → file-viewer-11VVOpJv.js} +5 -5
- package/dist/lib/{file-viewer-DoHM75Jz.js.map → file-viewer-11VVOpJv.js.map} +1 -1
- package/dist/lib/{getGroupDir-QrN2aTo8.js → getGroupDir-BxKMYPPm.js} +3 -3
- package/dist/lib/{getGroupDir-QrN2aTo8.js.map → getGroupDir-BxKMYPPm.js.map} +1 -1
- package/dist/lib/{git-DAP_EV6R.js → git-BppibnJW.js} +27 -10
- package/dist/lib/{git-DAP_EV6R.js.map → git-BppibnJW.js.map} +1 -1
- package/dist/lib/{iframe-sanitizer-Bujgq14T.js → iframe-sanitizer-Dp8EYffI.js} +2 -2
- package/dist/lib/{iframe-sanitizer-Bujgq14T.js.map → iframe-sanitizer-Dp8EYffI.js.map} +1 -1
- package/dist/lib/index.js +27 -27
- package/dist/lib/{initChatSplitResize-BjiWoqC_.js → initChatSplitResize-CE_kWaLf.js} +2 -2
- package/dist/lib/{initChatSplitResize-BjiWoqC_.js.map → initChatSplitResize-CE_kWaLf.js.map} +1 -1
- package/dist/lib/{initControlPlane-DCK_SHeR.js → initControlPlane-BRIIOzoH.js} +18 -17
- package/dist/lib/{initControlPlane-DCK_SHeR.js.map → initControlPlane-BRIIOzoH.js.map} +1 -1
- package/dist/lib/{markdown-BFUTPQoO.js → markdown-Cq4sVwUT.js} +4 -4
- package/dist/lib/{markdown-BFUTPQoO.js.map → markdown-Cq4sVwUT.js.map} +1 -1
- package/dist/lib/{mcp-reconnect-BxJ77WSb.js → mcp-reconnect-CoHDMjmY.js} +2 -2
- package/dist/lib/{mcp-reconnect-BxJ77WSb.js.map → mcp-reconnect-CoHDMjmY.js.map} +1 -1
- package/dist/lib/{memoryStorage-D3FBwO9T.js → memoryStorage-DcFWrn_y.js} +2 -2
- package/dist/lib/{memoryStorage-D3FBwO9T.js.map → memoryStorage-DcFWrn_y.js.map} +1 -1
- package/dist/lib/{orchestrator-DNamnY-k.js → orchestrator-C3TgDZvq.js} +100 -19
- package/dist/lib/{orchestrator-DNamnY-k.js.map → orchestrator-C3TgDZvq.js.map} +1 -1
- package/dist/lib/{orchestrator-XygttQw2.js → orchestrator-Ce9_lmL2.js} +12 -12
- package/dist/lib/{orchestrator-XygttQw2.js.map → orchestrator-Ce9_lmL2.js.map} +1 -1
- package/dist/lib/{peerjs-BgkPSHKa.js → peerjs-PTYQ7yEG.js} +6 -6
- package/dist/lib/{peerjs-BgkPSHKa.js.map → peerjs-PTYQ7yEG.js.map} +1 -1
- package/dist/lib/{push-client-C09NQEk5.js → push-client-DDV5Rcg6.js} +3 -3
- package/dist/lib/{push-client-C09NQEk5.js.map → push-client-DDV5Rcg6.js.map} +1 -1
- package/dist/lib/{readGroupFileBytes-CSA7u-nJ.js → readGroupFileBytes-7C8G-yps.js} +2 -2
- package/dist/lib/{readGroupFileBytes-CSA7u-nJ.js.map → readGroupFileBytes-7C8G-yps.js.map} +1 -1
- package/dist/lib/{shadow-claw-vzcggiax.js → shadow-claw-WrWoPqFx.js} +10 -10
- package/dist/lib/{shadow-claw-vzcggiax.js.map → shadow-claw-WrWoPqFx.js.map} +1 -1
- package/dist/lib/{shadow-claw-a2ui-2I5nffIn.js → shadow-claw-a2ui-CcmJNXQP.js} +2 -2
- package/dist/lib/{shadow-claw-a2ui-2I5nffIn.js.map → shadow-claw-a2ui-CcmJNXQP.js.map} +1 -1
- package/dist/lib/{shadow-claw-accounts-DMb0y4ca.js → shadow-claw-accounts-CcB2429E.js} +3 -3
- package/dist/lib/{shadow-claw-accounts-DMb0y4ca.js.map → shadow-claw-accounts-CcB2429E.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-Cl3JvxIJ.js → shadow-claw-channel-config-C4v0h8oa.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-Cl3JvxIJ.js.map → shadow-claw-channel-config-C4v0h8oa.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-kv21lr_O.js → shadow-claw-channels-CyV88k9T.js} +3 -3
- package/dist/lib/{shadow-claw-channels-kv21lr_O.js.map → shadow-claw-channels-CyV88k9T.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-Cj1fHQIl.js → shadow-claw-chat-DSYtuZod.js} +11 -11
- package/dist/lib/{shadow-claw-chat-Cj1fHQIl.js.map → shadow-claw-chat-DSYtuZod.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-DySeKB36.js → shadow-claw-control-plane-DBSGuDT1.js} +7 -7
- package/dist/lib/{shadow-claw-control-plane-DySeKB36.js.map → shadow-claw-control-plane-DBSGuDT1.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-DghueOOD.js → shadow-claw-conversations-Cp8pK4PM.js} +5 -5
- package/dist/lib/{shadow-claw-conversations-DghueOOD.js.map → shadow-claw-conversations-Cp8pK4PM.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-C_ITv8T6.js → shadow-claw-file-viewer-B8G8yo48.js} +8 -8
- package/dist/lib/{shadow-claw-file-viewer-C_ITv8T6.js.map → shadow-claw-file-viewer-B8G8yo48.js.map} +1 -1
- package/dist/lib/{shadow-claw-files-CWBaYt9p.js → shadow-claw-files-D1COKzuC.js} +9 -9
- package/dist/lib/{shadow-claw-files-CWBaYt9p.js.map → shadow-claw-files-D1COKzuC.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-XfPBpfXd.js → shadow-claw-git-60tWU4Ee.js} +6 -6
- package/dist/lib/{shadow-claw-git-XfPBpfXd.js.map → shadow-claw-git-60tWU4Ee.js.map} +1 -1
- package/dist/lib/{shadow-claw-integrations-yT7j07TM.js → shadow-claw-integrations-Bw1cG1ze.js} +4 -4
- package/dist/lib/{shadow-claw-integrations-yT7j07TM.js.map → shadow-claw-integrations-Bw1cG1ze.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-Gzx4ufL_.js → shadow-claw-llm-By5CvsFJ.js} +6 -6
- package/dist/lib/{shadow-claw-llm-Gzx4ufL_.js.map → shadow-claw-llm-By5CvsFJ.js.map} +1 -1
- package/dist/lib/{shadow-claw-mcp-remote-DGDWjByQ.js → shadow-claw-mcp-remote-BaNODd1v.js} +4 -4
- package/dist/lib/{shadow-claw-mcp-remote-DGDWjByQ.js.map → shadow-claw-mcp-remote-BaNODd1v.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-CYEbc5TR.js → shadow-claw-networking-DtZ5bsTz.js} +2 -2
- package/dist/lib/{shadow-claw-networking-CYEbc5TR.js.map → shadow-claw-networking-DtZ5bsTz.js.map} +1 -1
- package/dist/lib/{shadow-claw-notifications-DHvkTrgv.js → shadow-claw-notifications-C3VEba_A.js} +3 -3
- package/dist/lib/{shadow-claw-notifications-DHvkTrgv.js.map → shadow-claw-notifications-C3VEba_A.js.map} +1 -1
- package/dist/lib/{shadow-claw-page-header-DrAcWCZ9.js → shadow-claw-page-header-BLowJopA.js} +2 -2
- package/dist/lib/{shadow-claw-page-header-DrAcWCZ9.js.map → shadow-claw-page-header-BLowJopA.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-Bj3w3V6Y.js → shadow-claw-pages-CpeUV-hw.js} +9 -9
- package/dist/lib/{shadow-claw-pages-Bj3w3V6Y.js.map → shadow-claw-pages-CpeUV-hw.js.map} +1 -1
- package/dist/lib/{shadow-claw-peerjs-B3sx2xLA.js → shadow-claw-peerjs-DYAzJbTy.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-B3sx2xLA.js.map → shadow-claw-peerjs-DYAzJbTy.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-DK-0kp3A.js → shadow-claw-settings-ByxwW3WK.js} +9 -9
- package/dist/lib/{shadow-claw-settings-DK-0kp3A.js.map → shadow-claw-settings-ByxwW3WK.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-p9nVMQPF.js → shadow-claw-storage-CsSPYVDJ.js} +5 -5
- package/dist/lib/{shadow-claw-storage-p9nVMQPF.js.map → shadow-claw-storage-CsSPYVDJ.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-BNKCWG2M.js → shadow-claw-task-server-De2WCEw4.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-BNKCWG2M.js.map → shadow-claw-task-server-De2WCEw4.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-Dbq9rUku.js → shadow-claw-tasks-zHWT4GaE.js} +7 -7
- package/dist/lib/{shadow-claw-tasks-Dbq9rUku.js.map → shadow-claw-tasks-zHWT4GaE.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-Wk2qRWJ9.js → shadow-claw-terminal-Bpawfv4N.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-Wk2qRWJ9.js.map → shadow-claw-terminal-Bpawfv4N.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-C9TEf2k7.js → shadow-claw-tools-BbKdWcps.js} +7 -7
- package/dist/lib/{shadow-claw-tools-C9TEf2k7.js.map → shadow-claw-tools-BbKdWcps.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-VoKerWW8.js → shadow-claw-webvm-DLqK0AxW.js} +3 -3
- package/dist/lib/{shadow-claw-webvm-VoKerWW8.js.map → shadow-claw-webvm-DLqK0AxW.js.map} +1 -1
- package/dist/lib/subsystems/git/git.d.ts +8 -1
- package/dist/lib/subsystems/git/types.d.ts +7 -1
- package/dist/lib/subsystems/mcp/webmcp.d.ts +37 -0
- package/dist/lib/subsystems/providers/model-registry.d.ts +4 -1
- package/dist/lib/subsystems/providers/providers.d.ts +10 -0
- package/dist/lib/{syncWebMcpRegistration-DEs4JjI_.js → syncWebMcpRegistration-mlbbvcdm.js} +5 -5
- package/dist/lib/{syncWebMcpRegistration-DEs4JjI_.js.map → syncWebMcpRegistration-mlbbvcdm.js.map} +1 -1
- package/dist/lib/{tools-f1WPNDSS.js → tools-Bb2ujM2E.js} +4 -4
- package/dist/lib/{tools-f1WPNDSS.js.map → tools-Bb2ujM2E.js.map} +1 -1
- package/dist/lib/utils/index.js +1 -1
- package/dist/lib/utils/utils.js +1 -1
- package/dist/lib/{utils-B99XP70b.js → utils-mpsYPfS7.js} +3 -3
- package/dist/lib/{utils-B99XP70b.js.map → utils-mpsYPfS7.js.map} +1 -1
- package/dist/lib/webmcp-BVR2lBVo.js +1544 -0
- package/dist/lib/webmcp-BVR2lBVo.js.map +1 -0
- package/dist/public/.well-known/mcp/server-card.json +1 -1
- package/dist/public/.well-known/mcp.json +1 -1
- package/dist/public/agent.worker.js +44 -44
- package/dist/public/config-BqecTktB.js +1 -0
- package/dist/public/{configurePeerJs-B68egTBd.js → configurePeerJs-BPKfWuEt.js} +1 -1
- package/dist/public/{connections-6575KDGE.js → connections-C_3tYsmX.js} +1 -1
- package/dist/public/{custom-element-security-Da_6HQ6X.js → custom-element-security-DXwU3Lae.js} +1 -1
- package/dist/public/docs/example/article/index.html +2 -2
- package/dist/public/docs/publishing/index.html +2 -2
- package/dist/public/docs/skill-creator/index.html +2 -2
- package/dist/public/docs/subsystems/tools.md +4 -3
- package/dist/public/docs/subsystems/webmcp.md +58 -13
- package/dist/public/{downloadGroupFile-Dj-AMNsd.js → downloadGroupFile-DTyf5DIC.js} +1 -1
- package/dist/public/{e2e-bridge-DQ4Mb_eC.js → e2e-bridge-DXwWCQKw.js} +1 -1
- package/dist/public/{file-viewer-BqNHyqzy.js → file-viewer-ConEyDDG.js} +1 -1
- package/dist/public/{getGroupDir-BwprrdrQ.js → getGroupDir-ZfZsiq6d.js} +1 -1
- package/dist/public/git-BtBaLC1-.js +100 -0
- package/dist/public/git-DgFF7xTW.js +100 -0
- package/dist/public/{iframe-sanitizer-viROQkRn.js → iframe-sanitizer-Corkvo_d.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/public/index.js +1 -1
- package/dist/public/{initChatSplitResize-BA18wLQQ.js → initChatSplitResize-CUc-TEmT.js} +1 -1
- package/dist/public/{initControlPlane-DG_LcLDy.js → initControlPlane-B_uYS8a4.js} +1 -1
- package/dist/public/main/index.html +2 -2
- package/dist/public/main/memory/index.html +2 -2
- package/dist/public/{markdown-eFKxxpVP.js → markdown-Cfa6GuJs.js} +1 -1
- package/dist/public/{mcp-reconnect-CBHuaYdF.js → mcp-reconnect-CUOkdPEz.js} +1 -1
- package/dist/public/{memoryStorage-C1llaYus.js → memoryStorage-Bh8fjmip.js} +1 -1
- package/dist/public/{orchestrator-BXwxW4N2.js → orchestrator-BcSzrg6E.js} +2 -2
- package/dist/public/{orchestrator-DAJkyJmV.js → orchestrator-Bi5OdVZD.js} +11 -11
- package/dist/public/{peerjs-BaDbzfgl.js → peerjs-CzCXG-NW.js} +1 -1
- package/dist/public/{push-client-B1CCaldJ.js → push-client-Cr3Ruahp.js} +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-CpBmveOh.js → shadow-claw-CzUYuuOa.js} +2 -2
- package/dist/public/{shadow-claw-accounts-D1y-zbMs.js → shadow-claw-accounts-BgIHB_aP.js} +1 -1
- package/dist/public/{shadow-claw-channels-7Oew09u0.js → shadow-claw-channels-Ce_trJ5D.js} +1 -1
- package/dist/public/{shadow-claw-chat-CskwjDzZ.js → shadow-claw-chat-CdECLLwL.js} +1 -1
- package/dist/public/{shadow-claw-control-plane-BqjEyhx7.js → shadow-claw-control-plane-DM62UmOz.js} +2 -2
- package/dist/public/{shadow-claw-conversations-ClGgBPVY.js → shadow-claw-conversations-AM5g3C00.js} +1 -1
- package/dist/public/{shadow-claw-file-viewer-rDepUwFJ.js → shadow-claw-file-viewer-BP7gWS5g.js} +1 -1
- package/dist/public/{shadow-claw-files-C0r05PYf.js → shadow-claw-files-RPPGszcK.js} +1 -1
- package/dist/public/{shadow-claw-git-CXrECHKy.js → shadow-claw-git-BsHEvLrb.js} +2 -2
- package/dist/public/{shadow-claw-integrations-CRGL78Fy.js → shadow-claw-integrations-B0vbcOqg.js} +1 -1
- package/dist/public/{shadow-claw-llm-jeGVNciG.js → shadow-claw-llm-FNNamrc_.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-DyGnK4S_.js → shadow-claw-mcp-remote-7mDgniQu.js} +1 -1
- package/dist/public/{shadow-claw-networking--q6MgEAT.js → shadow-claw-networking-CGsetaLp.js} +1 -1
- package/dist/public/{shadow-claw-notifications-CrFUF0fl.js → shadow-claw-notifications-pnwRcR-4.js} +1 -1
- package/dist/public/{shadow-claw-page-header-DA-FG08G.js → shadow-claw-page-header-BUy15Poz.js} +1 -1
- package/dist/public/{shadow-claw-pages-_n1wVXAV.js → shadow-claw-pages-ILAjGWNk.js} +1 -1
- package/dist/public/{shadow-claw-settings-5yIfa3ie.js → shadow-claw-settings-Bx5IgVqN.js} +3 -3
- package/dist/public/{shadow-claw-storage-PLX9EFGn.js → shadow-claw-storage-PAtNykaF.js} +1 -1
- package/dist/public/{shadow-claw-task-server-BMps7aSr.js → shadow-claw-task-server-Cbbi_2OO.js} +1 -1
- package/dist/public/{shadow-claw-tasks-CHO1xvsu.js → shadow-claw-tasks-B-jKYWZJ.js} +1 -1
- package/dist/public/{shadow-claw-terminal-BJnSXRsb.js → shadow-claw-terminal-BRejND-Z.js} +1 -1
- package/dist/public/{shadow-claw-tools-BHfxRckC.js → shadow-claw-tools-DNQe3oa-.js} +1 -1
- package/dist/public/{shadow-claw-webvm-CyI23mQT.js → shadow-claw-webvm-BFuwRifU.js} +1 -1
- package/dist/public/{syncWebMcpRegistration-R0tha3kP.js → syncWebMcpRegistration-FxKAPwaz.js} +1 -1
- package/dist/public/theme-init.js +1 -1
- package/dist/public/{tools-Cp1gequ8.js → tools-BwQKGsro.js} +1 -1
- package/dist/public/transformers-js.worker.js +1 -1
- package/dist/public/webmcp-C28PAlfy.js +1 -0
- package/dist/server.js +1 -1
- package/package.json +3 -3
- package/src/core/utils/initControlPlane.test.ts +122 -1
- package/src/core/utils/initControlPlane.ts +12 -8
- package/src/storage/staticMainSite.ts +16 -2
- package/src/stores/orchestrator.test.ts +33 -0
- package/src/stores/orchestrator.ts +36 -0
- package/src/subsystems/git/git.test.ts +99 -0
- package/src/subsystems/git/git.ts +92 -12
- package/src/subsystems/git/types.ts +7 -0
- package/src/subsystems/mcp/webmcp.test.ts +253 -1
- package/src/subsystems/mcp/webmcp.ts +147 -4
- package/src/subsystems/providers/model-registry.test.ts +139 -0
- package/src/subsystems/providers/model-registry.ts +54 -2
- package/src/subsystems/providers/providers.test.ts +329 -0
- package/src/subsystems/providers/providers.ts +135 -11
- package/dist/lib/config-DjZ9QWc4.js.map +0 -1
- package/dist/lib/webmcp-BC8_WafM.js +0 -1710
- package/dist/lib/webmcp-BC8_WafM.js.map +0 -1
- package/dist/public/config-Bnwx4EfS.js +0 -1
- package/dist/public/git-BDaM5VT5.js +0 -100
- package/dist/public/git-D4n46G9B.js +0 -100
- package/dist/public/webmcp-DBONjQWd.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-BcFbkaQv.js","names":[],"sources":["../../src/subsystems/providers/model-registry.ts","../../src/config/config.ts"],"sourcesContent":["import { ProviderConfig } from \"../../config/config.js\";\n\nexport interface ModelMetadata {\n contextWindow: number;\n maxOutput: number | null;\n reasoning?: {\n supportedEfforts?: string[];\n defaultEffort?: string;\n defaultEnabled?: boolean;\n supportsMaxTokens?: boolean;\n mandatory?: boolean;\n };\n supportsTools?: boolean;\n inputModalities?: string[];\n outputModalities?: string[];\n supportsImageInput?: boolean;\n supportsAudioInput?: boolean;\n supportsVideoInput?: boolean;\n supportsDocumentInput?: boolean;\n routesByRequestFeatures?: boolean;\n supportsPromptCaching?: boolean;\n}\n\n/**\n * Registry for dynamic model metadata (context window, output limits)\n * fetched from provider APIs.\n *\n * All model IDs are stored and looked up in lowercase so that a model\n * selected as \"moonshotai/Kimi-K2-Thinking\" still matches the registry\n * entry stored under \"moonshotai/kimi-k2-thinking\" (as returned by the\n * OpenRouter API).\n */\nclass ModelRegistry {\n loading: boolean = false;\n models: Map<string, ModelMetadata> = new Map();\n\n /**\n * Get metadata for a model ID. Lookup is case-insensitive and resilient\n * to provider prefixes (e.g. \"anthropic/claude-3.7-sonnet\" vs \"claude-3.7-sonnet\")\n * and variant tags (e.g. \":thinking\").\n */\n getModelInfo(modelId: string): ModelMetadata | null {\n if (!modelId || typeof modelId !== \"string\") {\n return null;\n }\n\n const key = modelId.toLowerCase().trim();\n const direct = this.models.get(key);\n if (direct) {\n return direct;\n }\n\n // Try without provider prefix (e.g. \"anthropic/claude-3.7-sonnet\" -> \"claude-3.7-sonnet\")\n if (key.includes(\"/\")) {\n const bare = key.split(\"/\").pop();\n if (bare && this.models.has(bare)) {\n return this.models.get(bare)!;\n }\n } else {\n // Or if key doesn't have provider prefix, find a registered model ending in \"/<key>\".\n // Note: Assumes bare model names are reasonably unique across registered providers.\n // If duplicates exist, the first registered match is returned.\n for (const [regKey, meta] of this.models.entries()) {\n if (regKey.endsWith(`/${key}`)) {\n return meta;\n }\n }\n }\n\n // Try stripping tag/variant suffix (e.g. \"anthropic/claude-3.7-sonnet:thinking\" -> \"anthropic/claude-3.7-sonnet\")\n if (key.includes(\":\")) {\n const withoutTag = key.split(\":\")[0];\n const match = this.getModelInfo(withoutTag);\n if (match) {\n return match;\n }\n }\n\n return null;\n }\n\n /**\n * Manually register model info. Keys are normalized to lowercase.\n */\n registerModelInfo(modelId: string, info: ModelMetadata) {\n this.models.set(modelId.toLowerCase(), info);\n }\n\n /**\n * Clear all registered model metadata.\n */\n clear() {\n this.models.clear();\n }\n\n /**\n * Fetch model info from a provider's modelsUrl and populate the registry.\n * Handles OpenRouter and any OpenAI-compatible provider that returns\n * {data: [{id, context_length, top_provider: {max_completion_tokens}}]}\n * as well as HuggingFace Router's identical response shape.\n */\n async fetchModelInfo(\n provider: ProviderConfig,\n apiKey?: string,\n extraHeaders?: Record<string, string>,\n ) {\n if (!provider.modelsUrl) {\n return;\n }\n\n this.loading = true;\n try {\n const headers = new Headers();\n headers.set(\"Content-Type\", \"application/json\");\n\n // add extra headers\n if (provider.headers) {\n for (const [key, value] of Object.entries(provider.headers)) {\n headers.set(key, value);\n }\n }\n\n // add extra headers\n if (extraHeaders) {\n for (const [key, value] of Object.entries(extraHeaders)) {\n headers.set(key, value);\n }\n }\n\n // Forward the API key so authenticated endpoints (e.g. HuggingFace)\n // return the full model list rather than a 401.\n if (apiKey && provider.apiKeyHeader) {\n const fmt = provider.apiKeyHeaderFormat;\n headers.set(\n provider.apiKeyHeader,\n fmt ? fmt.replace(\"{key}\", apiKey) : apiKey,\n );\n }\n\n const response = await fetch(provider.modelsUrl, { headers });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n // OpenRouter / HuggingFace Router / any OpenAI-compatible /v1/models\n // All return {data: [{id, context_length, top_provider?:{max_completion_tokens}}]}\n const items: any[] = Array.isArray(data.data)\n ? data.data\n : Array.isArray(data.models)\n ? data.models\n : [];\n\n for (const model of items) {\n if (!model.id) {\n continue;\n }\n\n let contextLength = model.context_length ?? model.context_window ?? 0;\n let maxOutput =\n model.max_completion_tokens ||\n model.per_request_limits?.completion_tokens ||\n model.top_provider?.max_completion_tokens ||\n null;\n const supportsTools =\n typeof model.supports_tools === \"boolean\"\n ? model.supports_tools\n : typeof model.supportsTools === \"boolean\"\n ? model.supportsTools\n : undefined;\n const inputModalities = this.extractModalities(model, \"input\");\n const outputModalities = this.extractModalities(model, \"output\");\n const supportsImageInput = this.modalitiesInclude(\n inputModalities,\n \"image\",\n \"vision\",\n );\n const supportsAudioInput = this.modalitiesInclude(\n inputModalities,\n \"audio\",\n \"voice\",\n \"hearing\",\n );\n const supportsVideoInput = this.modalitiesInclude(\n inputModalities,\n \"video\",\n );\n const routesByRequestFeatures =\n model.id === \"openrouter/free\" ||\n this.supportedParametersInclude(\n model,\n \"image\",\n \"vision\",\n \"audio\",\n \"tool\",\n \"structured\",\n );\n const reasoning = this.extractReasoning(model);\n const supportsPromptCaching =\n typeof model.supports_prompt_caching === \"boolean\"\n ? model.supports_prompt_caching\n : typeof model.supportsPromptCaching === \"boolean\"\n ? model.supportsPromptCaching\n : this.supportedParametersInclude(\n model,\n \"cache_control\",\n \"prompt_caching\",\n )\n ? true\n : undefined;\n\n // HuggingFace Router structure nests info inside `providers` array\n if (\n !contextLength &&\n Array.isArray(model.providers) &&\n model.providers.length > 0\n ) {\n contextLength = model.providers[0]?.context_length || 0;\n }\n\n this.registerModelInfo(model.id, {\n contextWindow: contextLength,\n maxOutput,\n ...(supportsTools !== undefined && { supportsTools }),\n ...(inputModalities.length > 0 && { inputModalities }),\n ...(outputModalities.length > 0 && { outputModalities }),\n ...(supportsImageInput !== undefined && { supportsImageInput }),\n ...(supportsAudioInput !== undefined && { supportsAudioInput }),\n ...(supportsVideoInput !== undefined && { supportsVideoInput }),\n ...(reasoning && { reasoning }),\n ...(routesByRequestFeatures && { routesByRequestFeatures }),\n ...(supportsPromptCaching !== undefined && { supportsPromptCaching }),\n });\n }\n\n if (items.length > 0) {\n console.log(\n `[ModelRegistry] Registered ${items.length} models for provider \"${provider.id}\"`,\n );\n }\n } catch (err) {\n console.error(\n `[ModelRegistry] Error fetching models for ${provider.id}:`,\n err,\n );\n } finally {\n this.loading = false;\n }\n }\n\n private extractModalities(\n model: any,\n direction: \"input\" | \"output\",\n ): string[] {\n const direct =\n direction === \"input\"\n ? model.input_modalities || model.inputModalities\n : model.output_modalities || model.outputModalities;\n\n const architecture = model.architecture || {};\n const architectureValue =\n direction === \"input\"\n ? architecture.input_modalities || architecture.inputModalities\n : architecture.output_modalities || architecture.outputModalities;\n\n const modalityString =\n typeof architecture.modality === \"string\" ? architecture.modality : \"\";\n const parsedFromModalityString = this.parseArchitectureModality(\n modalityString,\n direction,\n );\n\n const merged = [\n ...this.normalizeStringArray(direct),\n ...this.normalizeStringArray(architectureValue),\n ...parsedFromModalityString,\n ];\n\n return Array.from(new Set(merged));\n }\n\n private extractReasoning(model: any):\n | {\n supportedEfforts?: string[];\n defaultEffort?: string;\n defaultEnabled?: boolean;\n supportsMaxTokens?: boolean;\n mandatory?: boolean;\n }\n | undefined {\n const raw = model?.reasoning;\n if (!raw || typeof raw !== \"object\") {\n return undefined;\n }\n\n const supportedEfforts = this.normalizeStringArray(raw.supported_efforts);\n const defaultEffort =\n typeof raw.default_effort === \"string\"\n ? raw.default_effort.toLowerCase()\n : undefined;\n const defaultEnabled =\n typeof raw.default_enabled === \"boolean\"\n ? raw.default_enabled\n : undefined;\n const supportsMaxTokens =\n typeof raw.supports_max_tokens === \"boolean\"\n ? raw.supports_max_tokens\n : undefined;\n const mandatory =\n typeof raw.mandatory === \"boolean\" ? raw.mandatory : undefined;\n\n if (\n supportedEfforts.length === 0 &&\n defaultEffort === undefined &&\n defaultEnabled === undefined &&\n supportsMaxTokens === undefined &&\n mandatory === undefined\n ) {\n return undefined;\n }\n\n return {\n ...(supportedEfforts.length > 0 && { supportedEfforts }),\n ...(defaultEffort !== undefined && { defaultEffort }),\n ...(defaultEnabled !== undefined && { defaultEnabled }),\n ...(supportsMaxTokens !== undefined && { supportsMaxTokens }),\n ...(mandatory !== undefined && { mandatory }),\n };\n }\n\n private modalitiesInclude(\n modalities: string[],\n ...needles: string[]\n ): boolean | undefined {\n if (modalities.length === 0) {\n return undefined;\n }\n\n return needles.some((needle) =>\n modalities.some((modality) => modality.includes(needle)),\n );\n }\n\n private normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .filter((entry): entry is string => typeof entry === \"string\")\n .map((entry) => entry.toLowerCase());\n }\n\n private parseArchitectureModality(\n modality: string,\n direction: \"input\" | \"output\",\n ): string[] {\n if (!modality) {\n return [];\n }\n\n const [input = \"\", output = \"\"] = modality\n .toLowerCase()\n .split(\"->\")\n .map((part) => part.trim());\n const segment = direction === \"input\" ? input : output;\n\n return segment\n .split(/[+,/\\s]+/)\n .map((part) => part.trim())\n .filter(Boolean);\n }\n\n private supportedParametersInclude(\n model: any,\n ...needles: string[]\n ): boolean {\n const parameters = this.normalizeStringArray(\n model.supported_parameters || model.supportedParameters,\n );\n\n return needles.some((needle) =>\n parameters.some((parameter) => parameter.includes(needle)),\n );\n }\n}\n\nexport const modelRegistry = new ModelRegistry();\n","import { modelRegistry } from \"../subsystems/providers/model-registry.js\";\nimport { getDeploymentNamespace } from \"../core/app-routes.js\";\n\n/** Default assistant name (used in trigger pattern) */\n\nexport const ASSISTANT_NAME = \"ShadowClaw\";\n\n/**\n * Build a trigger pattern for the assistant name\n */\nexport function buildTriggerPattern(name: string): RegExp {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n return new RegExp(`(^|\\\\s)@${escaped}\\\\b`, \"i\");\n}\n\nexport const TRIGGER_PATTERN = buildTriggerPattern(ASSISTANT_NAME);\n\n/** How many recent messages to include in agent context */\nexport const CONTEXT_WINDOW_SIZE = 50;\n\n/** Max tokens for API response (fallback for unknown models) */\nexport const DEFAULT_MAX_TOKENS = 8192;\n\n/** Default max tool-use iterations per invocation */\nexport const DEFAULT_MAX_ITERATIONS = 50;\n\n/**\n * Model-specific max output token limits.\n * Matched in order — first pattern whose string appears in the model ID wins.\n * More specific entries must come before broader ones.\n *\n * Sources:\n * Anthropic: https://platform.claude.com/docs/en/about-claude/models/overview\n * OpenAI: https://platform.openai.com/docs/models\n */\nexport const MODEL_OUTPUT_LIMITS: Array<{\n pattern: string;\n maxTokens: number;\n}> = [\n // Anthropic Claude Fable 5 — 128k max output (1M context)\n { pattern: \"claude-fable-5\", maxTokens: 128000 },\n // Anthropic Claude Sonnet 5 — 128k max output (1M context)\n { pattern: \"claude-sonnet-5\", maxTokens: 128000 },\n // Anthropic Claude Opus 5 — 128k max output (1M context); must precede claude-opus-4\n { pattern: \"claude-opus-5\", maxTokens: 128000 },\n // Anthropic Claude Opus 4.8 — 128k max output (1M context); must precede claude-opus-4\n { pattern: \"claude-opus-4-8\", maxTokens: 128000 },\n // Anthropic Claude Opus 4.x — 128k max output\n { pattern: \"claude-opus-4\", maxTokens: 128000 },\n // Anthropic Claude Sonnet 4.x — 64k max output\n { pattern: \"claude-sonnet-4\", maxTokens: 64000 },\n // Anthropic Claude Haiku 4.x — 64k max output\n { pattern: \"claude-haiku-4\", maxTokens: 64000 },\n // Anthropic Claude 3.5 family — 8192 max output\n { pattern: \"claude-3-5\", maxTokens: 8192 },\n // Anthropic Claude 3 family — 4096 max output\n { pattern: \"claude-3\", maxTokens: 4096 },\n // OpenAI GPT-5 variants — 128k max output\n { pattern: \"gpt-5\", maxTokens: 128000 },\n // OpenAI GPT-4o variants — 16384 max output\n { pattern: \"gpt-4o\", maxTokens: 16384 },\n // OpenAI GPT-4.1 — 32768 max output (1M context); must precede gpt-4 catch-all\n { pattern: \"gpt-4.1\", maxTokens: 32768 },\n // OpenAI GPT-4 Turbo — 4096 max output\n { pattern: \"gpt-4-turbo\", maxTokens: 4096 },\n // OpenAI GPT-4 (non-4o) — 8192 max output\n { pattern: \"gpt-4\", maxTokens: 8192 },\n // OpenAI GPT-3.5 — 4096 max output\n { pattern: \"gpt-3.5\", maxTokens: 4096 },\n // Qwen 2.5 family — 32k+ max output\n { pattern: \"qwen-2.5\", maxTokens: 32768 },\n // Qwen3.5 family (MTP etc.) — large context, 32k max output (must precede qwen3)\n { pattern: \"Qwen3.5\", maxTokens: 32768 },\n { pattern: \"qwen3.5\", maxTokens: 32768 },\n // Qwen3 family — 32k max output\n { pattern: \"Qwen3\", maxTokens: 32768 },\n { pattern: \"qwen3\", maxTokens: 32768 },\n // Gemma 4 family (covers unsloth GGUF variants served via Mesh LLM)\n { pattern: \"gemma-4\", maxTokens: 16384 },\n\n // ── Browser-native built-in engines ───────────────────────────────────\n // Chrome Gemini Nano — hard API cap 4,096–6,144 tokens\n { pattern: \"gemini-nano\", maxTokens: 4096 },\n // Edge Phi Mini / Aion — hard API cap ~9,216 tokens\n { pattern: \"phi-mini\", maxTokens: 9216 },\n { pattern: \"aion\", maxTokens: 9216 },\n\n // ── ONNX Community models (WebGPU/WASM, no enforced API cap) ──────────\n // Gemma 3 1B GQA — native 128K context; must precede gemma-3 catch-all\n { pattern: \"gemma-3-1b-it-ONNX-GQA\", maxTokens: 32768 },\n { pattern: \"gemma-3-1b-it-ONNX\", maxTokens: 32768 },\n // Gemma 3 catch-all\n { pattern: \"gemma-3\", maxTokens: 32768 },\n // Qwen3 0.6B ONNX — native 32K context\n { pattern: \"Qwen3-0.6B-ONNX\", maxTokens: 32768 },\n // Qwen3.5 ONNX variants\n { pattern: \"Qwen3.5\", maxTokens: 32768 },\n // Llama 3.2 1B/3B Instruct ONNX — native 128K context\n { pattern: \"Llama-3.2\", maxTokens: 32768 },\n // SmolLM2/SmolLM3 — smaller context\n { pattern: \"SmolLM\", maxTokens: 8192 },\n // DeepSeek-R1 Distill Qwen 1.5B — 128K native context\n { pattern: \"DeepSeek-R1\", maxTokens: 32768 },\n // Phi-3.5/Phi-4 mini ONNX — 128K native context\n { pattern: \"Phi-4\", maxTokens: 16384 },\n { pattern: \"Phi-3.5\", maxTokens: 16384 },\n // LFM2 1.2B ONNX\n { pattern: \"LFM2\", maxTokens: 16384 },\n // GPT-OSS 20B ONNX\n { pattern: \"gpt-oss\", maxTokens: 32768 },\n\n // ── Prompt API fallback (browser-built-in sentinel model ID) ──────────\n // Conservative default for unknown native browser models\n { pattern: \"browser-built-in\", maxTokens: 4096 },\n\n // Mesh LLM \"mesh\" routing model (MoA) — API reports context_length 242144\n { pattern: \"mesh\", maxTokens: 32768 },\n // OpenRouter Free — generous 32k fallback for routing\n { pattern: \"openrouter/free\", maxTokens: 32768 },\n // Ollama Qwen3 8B — 4096 max output\n { pattern: \"qwen3:8b\", maxTokens: 4096 },\n // Ollama Llama3 8B — 8192 max output (if you use it)\n { pattern: \"llama3:8b\", maxTokens: 8192 },\n];\n\n/**\n * Resolve max output tokens for a model ID.\n * Falls back to DEFAULT_MAX_TOKENS for unknown models.\n */\nexport function getModelMaxTokens(modelId: string): number {\n if (!modelId) {\n return DEFAULT_MAX_TOKENS;\n }\n\n // Check dynamic registry first\n const info = modelRegistry.getModelInfo(modelId);\n if (info) {\n // If the provider specifies maxOutput natively:\n if (typeof info.maxOutput === \"number\") {\n // If the provider set maxOutput equal to the total contextWindow (e.g. Nemotron=128k),\n // we must cap it so total requested tokens don't exceed the window.\n // E.g. Math.min(128000, 32768) prevents 400 errors for long outputs.\n const safeMax = info.contextWindow\n ? Math.max(8192, Math.floor(info.contextWindow / 2))\n : 32768;\n\n return Math.min(info.maxOutput, safeMax);\n }\n\n // Registry hit but no explicit maxOutput.\n // Scale the ceiling with the context window so large-context models\n // (e.g. Mesh LLM mesh 242k, Qwen3.5 262k) aren't hard-capped at 32k.\n if (info.contextWindow) {\n let ceiling: number;\n if (info.contextWindow >= 200_000) {\n ceiling = 131_072; // very-large-context models\n } else if (info.contextWindow >= 100_000) {\n ceiling = 65_536; // large-context models\n } else {\n ceiling = 32_768; // standard models\n }\n\n return Math.min(ceiling, Math.floor(info.contextWindow / 2));\n }\n }\n\n for (const { pattern, maxTokens } of MODEL_OUTPUT_LIMITS) {\n if (modelId.includes(pattern)) {\n return maxTokens;\n }\n }\n\n return DEFAULT_MAX_TOKENS;\n}\n\n/** Default provider */\nexport const DEFAULT_PROVIDER = \"prompt_api\";\n\n/** Task scheduler check interval (ms) */\nexport const SCHEDULER_INTERVAL = 60_000;\n\n/** Message processing loop interval (ms) */\nexport const PROCESS_LOOP_INTERVAL = 100;\n\n/** Fetch tool response truncation limit (100 KB to match tool description) */\nexport const FETCH_MAX_RESPONSE = 102_400;\n\n/** Default bash tool timeout in WebVM (seconds) */\nexport const BASH_DEFAULT_TIMEOUT_SEC = 900;\n\n/** Max bash tool timeout in WebVM (seconds) */\nexport const BASH_MAX_TIMEOUT_SEC = 1_800;\n\n/** Default VM network relay URL */\nexport const DEFAULT_VM_NETWORK_RELAY_URL = \"wss://relay.widgetry.org/\";\n\n/**\n * Default hosted WebVM asset root used by Settings and worker startup when\n * vm_boot_host has never been configured.\n */\nexport const DEFAULT_VM_BOOT_HOST = \"http://localhost:8888\";\n\n/** Legacy IndexedDB database name (unnamespaced) */\nexport const LEGACY_DB_NAME = \"shadowclaw\";\n\n/** Get current deployment IndexedDB database name */\nexport function getDbName(): string {\n const ns = getDeploymentNamespace();\n return ns ? `shadowclaw-${ns}` : LEGACY_DB_NAME;\n}\n\n/** IndexedDB database name */\nexport const DB_NAME = getDbName();\n\n/** IndexedDB version */\nexport const DB_VERSION = 2;\n\n/** Legacy OPFS root directory name (unnamespaced) */\nexport const LEGACY_OPFS_ROOT = \"shadowclaw\";\n\n/** Get current deployment OPFS root directory name */\nexport function getOpfsRootName(): string {\n const ns = getDeploymentNamespace();\n return ns ? `shadowclaw-${ns}` : LEGACY_OPFS_ROOT;\n}\n\n/** OPFS root directory name */\nexport const OPFS_ROOT = \"shadowclaw\";\n\n/** Default group for browser chat */\nexport const DEFAULT_GROUP_ID = \"br:main\";\n\n/** Telegram Bot API base URL */\nexport const TELEGRAM_API_BASE = \"https://api.telegram.org/bot\";\n\n/** Same-origin Telegram proxy base URL */\nexport const TELEGRAM_PROXY_BASE = \"/telegram/bot\";\n\n/** Telegram message length limit */\nexport const TELEGRAM_MAX_LENGTH = 4096;\n\n/** Telegram long-poll timeout in seconds */\nexport const TELEGRAM_POLL_TIMEOUT = 30;\n\n/** iMessage bridge long-poll timeout in seconds */\nexport const IMESSAGE_POLL_TIMEOUT = 25;\n\n/** iMessage bridge request timeout in milliseconds */\nexport const IMESSAGE_REQUEST_TIMEOUT_MS = 15000;\n\n/** PeerJS public cloud signaling server host (default, no self-hosted server required) */\nexport const PEERJS_DEFAULT_HOST = \"0.peerjs.com\";\n\n/** PeerJS public cloud signaling server port */\nexport const PEERJS_DEFAULT_PORT = 443;\n\n/** PeerJS public cloud signaling server path */\nexport const PEERJS_DEFAULT_PATH = \"/\";\n\n/** Whether to use TLS for PeerJS signaling (true for the public cloud) */\nexport const PEERJS_DEFAULT_SECURE = true;\n\n/** Bedrock proxy endpoint (models fetched dynamically) */\nexport const BEDROCK_PROXY_URL = \"http://localhost:8888/bedrock-proxy/invoke\";\n\n/** Bedrock proxy models endpoint */\nexport const BEDROCK_PROXY_MODELS_URL =\n \"http://localhost:8888/bedrock-proxy/models\";\n\n/** Transformers.js local proxy endpoint (Node-side inference) */\nexport const TRANSFORMERS_JS_PROXY_URL =\n \"http://localhost:8888/transformers-js-proxy/chat/completions\";\n\n/** Transformers.js local proxy models endpoint */\nexport const TRANSFORMERS_JS_PROXY_MODELS_URL =\n \"http://localhost:8888/transformers-js-proxy/models\";\n\n/** Llamafile proxy endpoint (local binary execution) */\nexport const LLAMAFILE_PROXY_URL =\n \"http://localhost:8888/llamafile-proxy/chat/completions\";\n\n/** Llamafile proxy models endpoint */\nexport const LLAMAFILE_PROXY_MODELS_URL =\n \"http://localhost:8888/llamafile-proxy/models\";\n\n/** Ollama proxy endpoint (local LLM server) */\nexport const OLLAMA_PROXY_URL =\n \"http://localhost:8888/ollama-proxy/chat/completions\";\n\n/** Ollama proxy models endpoint */\nexport const OLLAMA_PROXY_MODELS_URL =\n \"http://localhost:8888/ollama-proxy/models\";\n\nexport interface ProviderConfig {\n id: string;\n name: string;\n baseUrl: string;\n format:\n | \"openai\"\n | \"anthropic\"\n | \"prompt_api\"\n | \"transformers_js\"\n | \"google\"\n | \"mesh-llm\";\n apiKeyHeader: string;\n apiKeyHeaderFormat?: string;\n headers: Record<string, string>;\n defaultModel: string;\n models?: string[];\n modelsUrl?: string;\n requiresApiKey?: boolean;\n /**\n * Whether the provider endpoint returns SSE streams.\n * When true, the proxy must support returning an SSE stream when the request\n * includes `stream: true`. The orchestrator will only enable streaming when\n * this flag is explicitly `true`.\n */\n supportsStreaming?: boolean;\n /**\n * How this provider accepts reasoning/thinking control.\n * - `reasoning`: flat payload.reasoning object (OpenRouter style)\n * - `thinking`: Anthropic payload.thinking block (Bedrock Anthropic style)\n * - `thinkingConfig`: payload.reasoning translated server-side for Google proxies\n */\n reasoningParam?: \"reasoning\" | \"thinking\" | \"thinkingConfig\";\n}\n\nexport type ProviderAuthMode = \"token\" | \"basic\" | \"oauth\";\n\nexport type ServiceType =\n | \"http_api\"\n | \"git_remote\"\n | \"mcp_remote\"\n | \"webmcp_local\";\n\nexport type AuthType =\n | \"none\"\n | \"token\"\n | \"oauth\"\n | \"basic_userpass\"\n | \"custom_header\"\n | \"ssh_key\";\n\nexport type OAuthClientAuthMethod = \"request_body\" | \"basic_header\";\n\nexport type OAuthScopeSeparator = \"space\" | \"comma\";\n\nexport interface ProviderTokenAuthScheme {\n headerName: string;\n headerPrefix?: string;\n}\n\nexport interface OAuthProviderFlowCapabilities {\n authorizeUrl: string;\n tokenUrl: string;\n refreshUrl?: string;\n redirectUri?: string;\n defaultScopes: string[];\n usePkce: boolean;\n clientAuthMethod: OAuthClientAuthMethod;\n scopeSeparator: OAuthScopeSeparator;\n}\n\nexport interface GeneralAccountProviderCapabilities {\n providerId: string;\n name: string;\n aliases?: string[];\n modes: ProviderAuthMode[];\n defaultMode: ProviderAuthMode;\n serviceTypes?: ServiceType[];\n authTypes?: AuthType[];\n tokenAuth: {\n token: ProviderTokenAuthScheme;\n oauth: ProviderTokenAuthScheme;\n basic?: ProviderTokenAuthScheme;\n };\n tokenAuthByServiceType?: Partial<\n Record<\n ServiceType,\n {\n token: ProviderTokenAuthScheme;\n oauth: ProviderTokenAuthScheme;\n basic?: ProviderTokenAuthScheme;\n }\n >\n >;\n oauth?: OAuthProviderFlowCapabilities;\n}\n\nexport interface ProviderAuthCapabilities {\n providerId: string;\n modes: ProviderAuthMode[];\n defaultMode: ProviderAuthMode;\n}\n\nexport interface OAuthProviderDefinition {\n id: string;\n name: string;\n authorizeUrl: string;\n tokenUrl: string;\n redirectUri?: string;\n defaultScopes: string[];\n usePkce: boolean;\n clientAuthMethod?: OAuthClientAuthMethod;\n scopeSeparator?: OAuthScopeSeparator;\n}\n\n/**\n * Unified provider capability catalog for \"General Accounts\".\n *\n * Goal: onboarding providers should be mostly data/configuration, not custom code.\n * This schema covers auth modes, OAuth endpoints/settings, and request auth headers.\n */\nexport const GENERAL_ACCOUNT_PROVIDER_CAPABILITIES: Record<\n string,\n GeneralAccountProviderCapabilities\n> = {\n github: {\n providerId: \"github\",\n name: \"GitHub\",\n aliases: [\"github\", \"api.github.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\", \"git_remote\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"token \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://github.com/login/oauth/authorize\",\n tokenUrl: \"https://github.com/login/oauth/access_token\",\n defaultScopes: [\"repo\", \"read:user\"],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n gitlab: {\n providerId: \"gitlab\",\n name: \"GitLab\",\n aliases: [\"gitlab\", \"gitlab.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\", \"git_remote\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"PRIVATE-TOKEN\", headerPrefix: \"\" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n tokenAuthByServiceType: {\n git_remote: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n },\n oauth: {\n authorizeUrl: \"https://gitlab.com/oauth/authorize\",\n tokenUrl: \"https://gitlab.com/oauth/token\",\n defaultScopes: [\"read_api\", \"read_user\"],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n figma: {\n providerId: \"figma\",\n name: \"Figma\",\n aliases: [\"figma\", \"api.figma.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"X-Figma-Token\", headerPrefix: \"\" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://www.figma.com/oauth\",\n tokenUrl: \"https://api.figma.com/v1/oauth/token\",\n refreshUrl: \"https://api.figma.com/v1/oauth/refresh\",\n // Leave empty so no scope param is sent unless user explicitly overrides.\n // When entering multiple scopes, separate them with spaces.\n defaultScopes: [],\n usePkce: true,\n clientAuthMethod: \"basic_header\",\n scopeSeparator: \"space\",\n },\n },\n notion: {\n providerId: \"notion\",\n name: \"Notion\",\n aliases: [\"notion\", \"api.notion.com\", \"notion.so\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://api.notion.com/v1/oauth/authorize\",\n tokenUrl: \"https://api.notion.com/v1/oauth/token\",\n defaultScopes: [],\n usePkce: true,\n clientAuthMethod: \"basic_header\",\n scopeSeparator: \"space\",\n },\n },\n microsoft_graph: {\n providerId: \"microsoft_graph\",\n name: \"Microsoft Graph\",\n aliases: [\"microsoft\", \"graph.microsoft.com\", \"microsoft_graph\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl:\n \"https://login.microsoftonline.com/common/oauth2/v2.0/authorize\",\n tokenUrl: \"https://login.microsoftonline.com/common/oauth2/v2.0/token\",\n defaultScopes: [\"openid\", \"profile\", \"offline_access\", \"User.Read\"],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n yahoo_mail: {\n providerId: \"yahoo_mail\",\n name: \"Yahoo Mail\",\n aliases: [\"yahoo\", \"yahoo_mail\", \"mail.yahoo.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://api.login.yahoo.com/oauth2/request_auth\",\n tokenUrl: \"https://api.login.yahoo.com/oauth2/get_token\",\n defaultScopes: [\"mail-r\", \"mail-w\"],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n google: {\n providerId: \"google\",\n name: \"Google\",\n aliases: [\"google\", \"googleapis.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n defaultScopes: [\"openid\", \"profile\", \"email\"],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n atlassian: {\n providerId: \"atlassian\",\n name: \"Atlassian\",\n aliases: [\"atlassian\", \"api.atlassian.com\"],\n modes: [\"oauth\", \"token\", \"basic\"],\n defaultMode: \"basic\",\n serviceTypes: [\"http_api\", \"git_remote\"],\n authTypes: [\"token\", \"oauth\", \"basic_userpass\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n basic: { headerName: \"Authorization\", headerPrefix: \"Basic \" },\n },\n oauth: {\n authorizeUrl: \"https://auth.atlassian.com/authorize\",\n tokenUrl: \"https://auth.atlassian.com/oauth/token\",\n defaultScopes: [],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n slack: {\n providerId: \"slack\",\n name: \"Slack\",\n aliases: [\"slack\", \"slack.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://slack.com/oauth/v2/authorize\",\n tokenUrl: \"https://slack.com/api/oauth.v2.access\",\n defaultScopes: [],\n usePkce: false,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"comma\",\n },\n },\n linear: {\n providerId: \"linear\",\n name: \"Linear\",\n aliases: [\"linear\", \"api.linear.app\", \"linear.app\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\"],\n authTypes: [\"token\", \"oauth\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://linear.app/oauth/authorize\",\n tokenUrl: \"https://api.linear.app/oauth/token\",\n defaultScopes: [],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n azure_devops: {\n providerId: \"azure_devops\",\n name: \"Azure DevOps\",\n aliases: [\"azure_devops\", \"dev.azure.com\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"http_api\", \"git_remote\"],\n authTypes: [\"token\", \"oauth\", \"basic_userpass\", \"ssh_key\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n tokenAuthByServiceType: {\n git_remote: {\n token: { headerName: \"Authorization\", headerPrefix: \"Basic \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Basic \" },\n },\n },\n oauth: {\n authorizeUrl: \"https://app.vssps.visualstudio.com/oauth2/authorize\",\n tokenUrl: \"https://app.vssps.visualstudio.com/oauth2/token\",\n defaultScopes: [\"vso.code\", \"vso.profile\", \"offline_access\"],\n usePkce: false,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n custom_mcp: {\n providerId: \"custom_mcp\",\n name: \"Custom MCP\",\n aliases: [\"custom_mcp\"],\n modes: [\"oauth\", \"token\"],\n defaultMode: \"oauth\",\n serviceTypes: [\"mcp_remote\", \"webmcp_local\"],\n authTypes: [\"none\", \"token\", \"oauth\", \"custom_header\", \"ssh_key\"],\n tokenAuth: {\n token: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n oauth: { headerName: \"Authorization\", headerPrefix: \"Bearer \" },\n },\n oauth: {\n authorizeUrl: \"https://example.com/oauth/authorize\",\n tokenUrl: \"https://example.com/oauth/token\",\n defaultScopes: [],\n usePkce: true,\n clientAuthMethod: \"request_body\",\n scopeSeparator: \"space\",\n },\n },\n};\n\n/**\n * OAuth provider catalog used by both UI and server-side allowlist enforcement.\n * Only providers listed here can be used by /oauth/authorize.\n */\nexport const OAUTH_PROVIDER_DEFINITIONS: Record<\n string,\n OAuthProviderDefinition\n> = Object.fromEntries(\n Object.values(GENERAL_ACCOUNT_PROVIDER_CAPABILITIES)\n .filter((provider) => !!provider.oauth)\n .map((provider) => {\n const oauth = provider.oauth!;\n\n return [\n provider.providerId,\n {\n id: provider.providerId,\n name: provider.name,\n authorizeUrl: oauth.authorizeUrl,\n tokenUrl: oauth.tokenUrl,\n redirectUri: oauth.redirectUri,\n defaultScopes: oauth.defaultScopes,\n usePkce: oauth.usePkce,\n clientAuthMethod: oauth.clientAuthMethod,\n scopeSeparator: oauth.scopeSeparator,\n },\n ];\n }),\n) as Record<string, OAuthProviderDefinition>;\n\n/**\n * Provider-level auth mode support for non-LLM endpoint credentials.\n * Used by Accounts and tool auth resolution to support dual-mode PAT/OAuth flows.\n */\nexport const PROVIDER_AUTH_CAPABILITIES: Record<\n string,\n ProviderAuthCapabilities\n> = Object.fromEntries(\n Object.values(GENERAL_ACCOUNT_PROVIDER_CAPABILITIES).map((provider) => [\n provider.providerId,\n {\n providerId: provider.providerId,\n modes: provider.modes,\n defaultMode: provider.defaultMode,\n },\n ]),\n) as Record<string, ProviderAuthCapabilities>;\n\n/**\n * LLM Provider definitions\n *\n * Each provider specifies how to make API calls and format messages\n *\n */\nexport const PROVIDERS: Record<string, ProviderConfig> = {\n openrouter: {\n id: \"openrouter\",\n name: \"OpenRouter\",\n baseUrl: \"https://openrouter.ai/api/v1/chat/completions\",\n format: \"openai\",\n apiKeyHeader: \"Authorization\",\n apiKeyHeaderFormat: \"Bearer {key}\",\n headers: {\n \"HTTP-Referer\": \"https://xt-ml.github.io/shadow-claw/\",\n \"X-OpenRouter-Title\": \"ShadowClaw\",\n },\n defaultModel: \"openrouter/free\",\n modelsUrl: \"https://openrouter.ai/api/v1/models\",\n requiresApiKey: true,\n supportsStreaming: true,\n reasoningParam: \"reasoning\",\n },\n huggingface: {\n id: \"huggingface\",\n name: \"HuggingFace\",\n baseUrl: \"https://router.huggingface.co/v1/chat/completions\",\n format: \"openai\",\n apiKeyHeader: \"Authorization\",\n apiKeyHeaderFormat: \"Bearer {key}\",\n headers: {},\n defaultModel: \"meta-llama/Llama-3.1-8B-Instruct\",\n modelsUrl: \"https://router.huggingface.co/v1/models\",\n requiresApiKey: true,\n supportsStreaming: true,\n },\n bedrock_proxy: {\n id: \"bedrock_proxy\",\n name: \"AWS Bedrock (Local Proxy)\",\n baseUrl: BEDROCK_PROXY_URL,\n format: \"anthropic\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"anthropic.claude-sonnet-4-6-v1:0\",\n modelsUrl: BEDROCK_PROXY_MODELS_URL,\n requiresApiKey: false,\n supportsStreaming: true,\n reasoningParam: \"thinking\",\n },\n gemini_proxy: {\n id: \"gemini_proxy\",\n name: \"Gemini (Local Proxy)\",\n baseUrl: \"http://localhost:8888/gemini-proxy/chat/completions\",\n format: \"openai\",\n apiKeyHeader: \"x-goog-api-key\",\n headers: {},\n defaultModel: \"gemini-2.0-flash\",\n modelsUrl: \"http://localhost:8888/gemini-proxy/models\",\n requiresApiKey: true,\n supportsStreaming: true,\n reasoningParam: \"thinkingConfig\",\n },\n vertex_ai: {\n id: \"vertex_ai\",\n name: \"Vertex AI (Local Proxy)\",\n baseUrl: \"http://localhost:8888/vertex-ai-proxy/chat/completions\",\n format: \"openai\",\n apiKeyHeader: \"x-vertex-project\",\n headers: {},\n defaultModel: \"gemini-2.5-flash\",\n modelsUrl: \"http://localhost:8888/vertex-ai-proxy/models\",\n requiresApiKey: true,\n supportsStreaming: true,\n reasoningParam: \"thinkingConfig\",\n },\n \"mesh-llm\": {\n id: \"mesh-llm\",\n name: \"Mesh LLM (Local Proxy)\",\n baseUrl: \"http://localhost:8888/mesh-llm-proxy/chat/completions\",\n format: \"mesh-llm\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"mesh\",\n modelsUrl: \"http://localhost:8888/mesh-llm-proxy/models\",\n requiresApiKey: false,\n supportsStreaming: true,\n },\n ollama: {\n id: \"ollama\",\n name: \"Ollama (Local Proxy)\",\n baseUrl: OLLAMA_PROXY_URL,\n format: \"openai\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"qwen3:8b\",\n modelsUrl: OLLAMA_PROXY_MODELS_URL,\n requiresApiKey: false,\n supportsStreaming: true,\n },\n llamafile: {\n id: \"llamafile\",\n name: \"Llamafile (Local Proxy)\",\n baseUrl: LLAMAFILE_PROXY_URL,\n format: \"openai\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"Qwen3.5-9B-Q5_K_S\",\n modelsUrl: LLAMAFILE_PROXY_MODELS_URL,\n requiresApiKey: false,\n supportsStreaming: true,\n },\n transformers_js_local: {\n id: \"transformers_js_local\",\n name: \"Transformers.js (Local Proxy)\",\n baseUrl: TRANSFORMERS_JS_PROXY_URL,\n format: \"openai\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"onnx-community/Qwen3-0.6B-ONNX\",\n modelsUrl: TRANSFORMERS_JS_PROXY_MODELS_URL,\n models: [\n \"onnx-community/DeepSeek-R1-Distill-Qwen-1.5B-ONNX\",\n \"onnx-community/gemma-3-1b-it-ONNX-GQA\",\n \"onnx-community/gemma-3-1b-it-ONNX\",\n \"onnx-community/gemma-4-E2B-it-ONNX\",\n \"onnx-community/gemma-4-E2B-it-qat-mobile-ONNX\",\n \"onnx-community/gemma-4-E4B-it-ONNX\",\n \"onnx-community/gemma-4-E4B-it-qat-mobile-ONNX\",\n \"onnx-community/gemma-4-E9B-it-ONNX\",\n \"onnx-community/gemma-4-12B-it-ONNX\",\n \"onnx-community/gemma-4-12B-it-qat-mobile-ONNX\",\n \"onnx-community/gemma-4-E27B-it-ONNX\",\n \"onnx-community/gpt-oss-20b-ONNX\",\n \"onnx-community/LFM2-1.2B-ONNX\",\n \"onnx-community/Llama-3.2-1B-Instruct-ONNX\",\n \"onnx-community/Llama-3.2-3B-Instruct-ONNX\",\n \"onnx-community/Phi-3.5-mini-instruct-onnx-web\",\n \"onnx-community/Phi-4-mini-instruct-ONNX\",\n \"onnx-community/Qwen3-0.6B-ONNX\",\n \"onnx-community/Qwen3.5-0.8B-ONNX-OPT\",\n \"onnx-community/Qwen3.5-4B-ONNX-OPT\",\n \"HuggingFaceTB/SmolLM3-3B-ONNX\",\n \"LiquidAI/LFM2.5-1.2B-Thinking-ONNX\",\n \"webgpu/Qwen3-4B-ONNX\",\n ],\n requiresApiKey: false,\n supportsStreaming: true,\n },\n transformers_js_browser: {\n id: \"transformers_js_browser\",\n name: \"Transformers.js (Browser)\",\n baseUrl: \"local://transformers-js\",\n format: \"transformers_js\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"onnx-community/Qwen3-0.6B-ONNX\",\n modelsUrl: \"https://huggingface.co/api/models?author=onnx-community\",\n models: [\n \"onnx-community/Qwen3-0.6B-ONNX\",\n \"onnx-community/gemma-3-1b-it-ONNX\",\n \"onnx-community/gemma-3-1b-it-ONNX-GQA\",\n \"onnx-community/gemma-4-E2B-it-ONNX\",\n \"onnx-community/gemma-4-E4B-it-ONNX\",\n \"onnx-community/gemma-4-E9B-it-ONNX\",\n \"onnx-community/gemma-4-E27B-it-ONNX\",\n \"onnx-community/gemma-4-12B-it-ONNX\",\n \"onnx-community/gemma-4-E2B-it-qat-mobile-ONNX\",\n \"onnx-community/gemma-4-E4B-it-qat-mobile-ONNX\",\n \"onnx-community/gemma-4-12B-it-qat-mobile-ONNX\",\n \"onnx-community/Phi-3.5-mini-instruct-onnx-web\",\n \"onnx-community/Phi-4-mini-instruct-ONNX\",\n \"onnx-community/Llama-3.2-1B-Instruct-ONNX\",\n \"onnx-community/Llama-3.2-3B-Instruct-ONNX\",\n \"webgpu/Qwen3-4B-ONNX\",\n \"onnx-community/DeepSeek-R1-Distill-Qwen-1.5B-ONNX\",\n \"onnx-community/gpt-oss-20b-ONNX\",\n \"onnx-community/LFM2-1.2B-ONNX\",\n \"LiquidAI/LFM2.5-1.2B-Thinking-ONNX\",\n \"HuggingFaceTB/SmolLM3-3B-ONNX\",\n \"onnx-community/Qwen3.5-0.8B-ONNX-OPT\",\n \"onnx-community/Qwen3.5-4B-ONNX-OPT\",\n ],\n requiresApiKey: false,\n supportsStreaming: false,\n },\n litert_lm_browser: {\n id: \"litert_lm_browser\",\n name: \"LiteRT-LM (Browser)\",\n baseUrl: \"local://litert-lm\",\n format: \"transformers_js\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"litert-community/gemma-4-E2B-it-litert-lm\",\n models: [\n \"litert-community/gemma-4-E2B-it-litert-lm\",\n \"litert-community/gemma-4-E4B-it-litert-lm\",\n ],\n requiresApiKey: false,\n supportsStreaming: false,\n },\n prompt_api: {\n id: \"prompt_api\",\n name: \"Prompt API (Browser)\",\n baseUrl: \"builtin://language-model\",\n format: \"prompt_api\",\n apiKeyHeader: \"Authorization\",\n headers: {},\n defaultModel: \"browser-built-in\",\n models: [\"browser-built-in\"],\n requiresApiKey: false,\n supportsStreaming: false,\n },\n};\n\n/**\n * Get provider configuration by ID\n */\nexport function getProvider(providerId: string): ProviderConfig | null {\n return PROVIDERS[providerId] || null;\n}\n\n/**\n * Get the default provider configuration\n */\nexport function getDefaultProvider(): ProviderConfig {\n return PROVIDERS[DEFAULT_PROVIDER];\n}\n\n/**\n * Get list of available provider IDs\n */\nexport function getAvailableProviders(): string[] {\n return Object.keys(PROVIDERS);\n}\n\n/**\n * Get the config key used to store an API key for a specific provider.\n */\nexport function getProviderApiKeyConfigKey(providerId: string): string {\n return `api_key:${providerId}`;\n}\n\nexport function getGeneralAccountProviderCapabilities(\n providerId: string,\n): GeneralAccountProviderCapabilities | null {\n return GENERAL_ACCOUNT_PROVIDER_CAPABILITIES[providerId] || null;\n}\n\nexport function getProviderTokenAuthScheme(\n providerId: string,\n authMode: ProviderAuthMode,\n serviceType: ServiceType = \"http_api\",\n): ProviderTokenAuthScheme | null {\n const provider = getGeneralAccountProviderCapabilities(providerId);\n if (!provider) {\n return null;\n }\n\n const byServiceType =\n provider.tokenAuthByServiceType?.[serviceType]?.[authMode];\n if (byServiceType) {\n return byServiceType;\n }\n\n return provider.tokenAuth[authMode] || null;\n}\n\nexport function getProviderAuthCapabilities(\n providerId: string,\n): ProviderAuthCapabilities | null {\n return PROVIDER_AUTH_CAPABILITIES[providerId] || null;\n}\n\nexport function getOAuthProviderDefinition(\n providerId: string,\n): OAuthProviderDefinition | null {\n return OAUTH_PROVIDER_DEFINITIONS[providerId] || null;\n}\n\n/** Config keys */\nexport const CONFIG_KEYS = {\n ACTIVE_TOOL_PROFILE: \"active_tool_profile\",\n ACTIVITY_LOG_DISK_LOGGING_ENABLED: \"activity_log_disk_logging_enabled\",\n ALLOWED_CUSTOM_ELEMENTS: \"allowed_custom_elements\",\n ALLOWED_CUSTOM_ELEMENT_HOST_PATTERNS: \"allowed_custom_element_host_patterns\",\n ALLOWED_IFRAME_HOST_PATTERNS: \"allowed_iframe_host_patterns\",\n API_KEY: \"api_key\",\n ASSISTANT_NAME: \"assistant_name\",\n BEDROCK_AUTH_MODE: \"bedrock_auth_mode\",\n BEDROCK_PROFILE_FALLBACK: \"bedrock_profile_fallback\",\n BEDROCK_REGION_FALLBACK: \"bedrock_region_fallback\",\n BUILTIN_AI_SUBAGENT_ROUTING: \"builtin_ai_subagent_routing\",\n BUILTIN_AI_TOOLS_BACKEND: \"builtin_ai_tools_backend\",\n CHANNEL_ENABLED_PREFIX: \"channel_enabled:\",\n CHAT_INPUT_AREA_HEIGHT: \"chat_input_area_height\",\n CHAT_SPLIT_VIEW_ENABLED: \"chat_split_view_enabled\",\n CHAT_SPLIT_VIEW_HEIGHT: \"chat_split_view_height\",\n COMPACTION_ENGINE_PREFERENCE: \"compaction_engine_preference\",\n CONTEXT_COMPRESSION_ENABLED: \"context_compression_enabled\",\n CONTROL_PLANE_CLIENT_ID: \"control_plane_client_id\",\n CONTROL_PLANE_ENABLED: \"control_plane_enabled\",\n CONTROL_PLANE_TRANSPORT: \"control_plane_transport\",\n CONTROL_PLANE_URL: \"control_plane_url\",\n CONVERSATIONS_HEIGHT: \"conversations_height\",\n CUSTOM_TOOLS: \"custom_tools\",\n DB_MIGRATED_FROM_LEGACY: \"db_migrated_from_legacy\",\n DECLARATIVE_TOOLS_ENABLED: \"declarative_tools_enabled\",\n DEFAULT_PINNED_PAGE: \"default_pinned_page\",\n DIRECT_TOOL_COMMAND_POLICY: \"direct_tool_command_policy\",\n ENABLED_TOOLS: \"enabled_tools\",\n FILES_UPLOAD_APPEND_ULID: \"files_upload_append_ulid\",\n GIT_ACCOUNTS: \"git_accounts\",\n GIT_AUTHOR_EMAIL: \"git_author_email\",\n GIT_AUTHOR_NAME: \"git_author_name\",\n GIT_CORS_PROXY: \"git_cors_proxy\",\n GIT_DEFAULT_ACCOUNT: \"git_default_account\",\n GIT_PASSWORD: \"git_password\",\n GIT_PROXY_URL: \"git_proxy_url\",\n GIT_TOKEN: \"git_token\",\n GIT_USERNAME: \"git_username\",\n IMESSAGE_API_KEY: \"imessage_api_key\",\n IMESSAGE_CHAT_IDS: \"imessage_chat_ids\",\n IMESSAGE_SERVER_URL: \"imessage_server_url\",\n INTEGRATION_CONNECTIONS: \"integration_connections\",\n MARKDOWN_FRONTMATTER_CHAT: \"markdown_frontmatter_chat\",\n MARKDOWN_FRONTMATTER_FILE_VIEWER: \"markdown_frontmatter_file_viewer\",\n MARKDOWN_FRONTMATTER_PAGES: \"markdown_frontmatter_pages\",\n MARKDOWN_FRONTMATTER_TASKS: \"markdown_frontmatter_tasks\",\n LAST_ACTIVE_GROUP: \"last_active_group\",\n LAST_ACTIVE_PAGE: \"last_active_page\",\n LAST_SELECTED_PINNED_PAGE: \"last_selected_pinned_page\",\n LLAMAFILE_HOST: \"llamafile_host\",\n LLAMAFILE_MODE: \"llamafile_mode\",\n LLAMAFILE_OFFLINE: \"llamafile_offline\",\n LLAMAFILE_PORT: \"llamafile_port\",\n MAIN_GROUP_INDEX_SUPPRESSED: \"main_group_index_suppressed\",\n MAIN_GROUP_README_SUPPRESSED: \"main_group_readme_suppressed\",\n MAX_ITERATIONS: \"max_iterations\",\n MAX_TOKENS: \"max_tokens\",\n MESH_LLM_HOST: \"mesh_llm_host\",\n MODEL: \"model\",\n OAUTH_PROVIDER_DEFINITIONS: \"oauth_provider_definitions\",\n OPFS_MIGRATED_FROM_LEGACY: \"opfs_migrated_from_legacy\",\n OVERRIDE_PRERENDER_SKELETON: \"override_prerender_skeleton\",\n PAGES_AUTO_REFRESH_INTERVAL: \"pages_auto_refresh_interval\",\n PAGES_LIST: \"pages_list\",\n PASSPHRASE_SALT: \"passphrase_salt\",\n PASSPHRASE_VERIFY: \"passphrase_verify\",\n PROMPT_API_BACKEND: \"prompt_api_backend\",\n PROMPT_API_DTYPE_STRATEGY: \"prompt_api_dtype_strategy\",\n PROMPT_API_FALLBACK_MODEL: \"prompt_api_fallback_model\",\n PROMPT_API_ONBOARDING_SEEN: \"prompt_api_onboarding_seen\",\n PEERJS_MY_ALIAS: \"peerjs_my_alias\",\n PEERJS_MY_PEER_ID: \"peerjs_my_peer_id\",\n PEERJS_PEER_ALIASES: \"peerjs_peer_aliases\",\n PEERJS_SERVER_HOST: \"peerjs_server_host\",\n PEERJS_SERVER_PATH: \"peerjs_server_path\",\n PEERJS_SERVER_PORT: \"peerjs_server_port\",\n PEERJS_SERVER_SECURE: \"peerjs_server_secure\",\n PEERJS_TRUSTED_PEER_IDS: \"peerjs_trusted_peer_ids\",\n PROVIDER: \"provider\",\n PROXY_URL: \"proxy_url\",\n PUSH_PROXY_URL: \"push_proxy_url\",\n RATE_LIMIT_AUTO_ADAPT: \"rate_limit_auto_adapt\",\n RATE_LIMIT_CALLS_PER_MINUTE: \"rate_limit_calls_per_minute\",\n REASONING_EFFORT: \"reasoning_effort\",\n REMOTE_MCP_CONNECTIONS: \"remote_mcp_connections\",\n SERVICE_ACCOUNTS: \"service_accounts\",\n SERVICE_DEFAULT_ACCOUNT: \"service_default_account\",\n SIDEBAR_CHAT_HIDDEN: \"sidebar_chat_hidden\",\n SIDEBAR_DEFAULT_PAGE: \"sidebar_default_page\",\n SIDEBAR_FILES_HIDDEN: \"sidebar_files_hidden\",\n SIDEBAR_PAGES_HIDDEN: \"sidebar_pages_hidden\",\n SIDEBAR_TASKS_HIDDEN: \"sidebar_tasks_hidden\",\n SIDEBAR_WIDTH: \"sidebar_width\",\n SITE_CONFIG_SEEDED: \"site_config_seeded\",\n STATIC_MAIN_SITE_SEEDED: \"static_main_site_seeded\",\n STORAGE_HANDLE: \"storage_handle\",\n SUBSCRIBER_ID: \"subscriber_id\",\n STREAMING_ENABLED: \"streaming_enabled\",\n SUBAGENT_MAX_PARALLEL: \"subagent_max_parallel\",\n SUBAGENT_WORKSPACE_MODE: \"subagent_workspace_mode\",\n SUPPRESSED_PAGES_LIST: \"suppressed_pages_list\",\n SYSTEM_PROMPT_OVERRIDE: \"system_prompt_override\",\n TASK_SERVER_ENABLED: \"task_server_enabled\",\n TASK_SERVER_URL: \"task_server_url\",\n TASK_SYNC_OUTBOX: \"task_sync_outbox\",\n TELEGRAM_BOT_TOKEN: \"telegram_bot_token\",\n TELEGRAM_CHAT_IDS: \"telegram_chat_ids\",\n TELEGRAM_USE_PROXY: \"telegram_use_proxy\",\n TOOL_PROFILES: \"tool_profiles\",\n TRANSFORMERS_JS_BACKEND: \"transformers_js_backend\",\n TRANSFORMERS_JS_DTYPE_STRATEGY: \"transformers_js_dtype_strategy\",\n TRIGGER_PATTERN: \"trigger_pattern\",\n USE_PROXY: \"use_proxy\",\n VAPID_SUBJECT: \"vapid_subject\",\n VM_BASH_FULL_INTERNET_ACCESS: \"vm_bash_full_internet_access\",\n VM_BASH_TIMEOUT_SEC: \"vm_bash_timeout_sec\",\n VM_BOOT_HOST: \"vm_boot_host\",\n VM_BOOT_MODE: \"vm_boot_mode\",\n VM_NETWORK_RELAY_URL: \"vm_network_relay_url\",\n WEBMCP_MODE: \"webmcp_mode\",\n WEBMCP_TOOLS_ENABLED: \"webmcp_tools_enabled\",\n WEB_SEARCH_PROXY_URL: \"web_search_proxy_url\",\n WEB_SEARCH_URL: \"web_search_url\",\n WEB_SEARCH_USE_PROXY: \"web_search_use_proxy\",\n SEARCH_FILES_MAX_FILE_BYTES: \"search_files_max_file_bytes\",\n SEARCH_FILES_MAX_FILES_VISITED: \"search_files_max_files_visited\",\n SEARCH_FILES_SKIP_DIRS: \"search_files_skip_dirs\",\n};\n\n/** Default dev server host */\nexport const DEFAULT_DEV_HOST = \"localhost\";\n\n/** Default dev server IP */\nexport const DEFAULT_DEV_IP = \"127.0.0.1\";\n\n/** Default dev server port */\nexport const DEFAULT_DEV_PORT = 8888;\n\n/** Default maximum number of parallel subagents */\nexport const DEFAULT_SUBAGENT_MAX_PARALLEL = 5;\n\n/** Default subagent workspace mode */\nexport const DEFAULT_SUBAGENT_WORKSPACE_MODE = \"automatic\";\n\n/** Default Prompt API fallback model */\nexport const DEFAULT_PROMPT_API_FALLBACK_MODEL =\n \"onnx-community/Qwen3-0.6B-ONNX\";\n\n/** Default Prompt API fallback backend */\nexport const DEFAULT_PROMPT_API_BACKEND = \"auto\";\n\n/** Default Prompt API fallback dtype strategy */\nexport const DEFAULT_PROMPT_API_DTYPE_STRATEGY = \"auto\";\n\n/** Default Transformers.js model */\nexport const DEFAULT_TRANSFORMERS_JS_MODEL = \"onnx-community/Qwen3-0.6B-ONNX\";\n\n/** Default Transformers.js backend */\nexport const DEFAULT_TRANSFORMERS_JS_BACKEND = \"auto\";\n\n/** Default Transformers.js dtype strategy */\nexport const DEFAULT_TRANSFORMERS_JS_DTYPE_STRATEGY = \"auto\";\n\n/** Default Task Server URL (base path, without /tasks suffix) */\nexport const DEFAULT_TASK_SERVER_URL = \"http://localhost:8888/schedule\";\n\n/** Default Task Server Enabled */\nexport const DEFAULT_TASK_SERVER_ENABLED = false;\n\n/** Default Files Upload Append ULID */\nexport const DEFAULT_FILES_UPLOAD_APPEND_ULID = false;\n\n/** Default Control Plane Enabled (opt-in) */\nexport const DEFAULT_CONTROL_PLANE_ENABLED = false;\n\n/** Default Control Plane Transport (\"sse\" or \"websocket\") */\nexport const DEFAULT_CONTROL_PLANE_TRANSPORT = \"sse\";\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as CONFIG_KEYS } from "./config-
|
|
2
|
-
import { dt as getChannelEnabled, yt as normalizeStringList } from "./orchestrator-
|
|
1
|
+
import { r as CONFIG_KEYS } from "./config-BcFbkaQv.js";
|
|
2
|
+
import { dt as getChannelEnabled, yt as normalizeStringList } from "./orchestrator-C3TgDZvq.js";
|
|
3
3
|
import { t as setConfig } from "./setConfig-BFED5CXn.js";
|
|
4
4
|
|
|
5
5
|
//#region src/core/orchestrator/utils/configurePeerJs.ts
|
|
@@ -35,4 +35,4 @@ async function configurePeerJs(orchestrator, db, myPeerId, trustedPeerIds, serve
|
|
|
35
35
|
|
|
36
36
|
//#endregion
|
|
37
37
|
export { configurePeerJs as t };
|
|
38
|
-
//# sourceMappingURL=configurePeerJs-
|
|
38
|
+
//# sourceMappingURL=configurePeerJs-CBMPHbwa.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurePeerJs-
|
|
1
|
+
{"version":3,"file":"configurePeerJs-CBMPHbwa.js","names":[],"sources":["../../src/core/orchestrator/utils/configurePeerJs.ts"],"sourcesContent":["import { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\nimport { normalizeStringList } from \"./normalizeStringList.js\";\nimport { getChannelEnabled } from \"./operations/channel.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function configurePeerJs(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n myPeerId: string,\n trustedPeerIds: string[],\n serverHost = \"\",\n serverPort = 0,\n serverPath = \"\",\n serverSecure = true,\n): Promise<void> {\n const normalizedMyPeerId = myPeerId.trim();\n const normalizedTrustedPeerIds = normalizeStringList(trustedPeerIds);\n const normalizedServerHost = serverHost.trim();\n const normalizedServerPort = Number.isFinite(serverPort)\n ? Math.max(0, Math.floor(serverPort))\n : 0;\n\n const normalizedServerPath = serverPath.trim();\n const normalizedServerSecure = !!serverSecure;\n\n orchestrator.peerjsMyPeerId = normalizedMyPeerId;\n orchestrator.peerjsTrustedPeerIds = normalizedTrustedPeerIds;\n orchestrator.peerjsServerHost = normalizedServerHost;\n orchestrator.peerjsServerPort = normalizedServerPort;\n orchestrator.peerjsServerPath = normalizedServerPath;\n orchestrator.peerjsServerSecure = normalizedServerSecure;\n\n await setConfig(db, CONFIG_KEYS.PEERJS_MY_PEER_ID, normalizedMyPeerId);\n await setConfig(\n db,\n CONFIG_KEYS.PEERJS_TRUSTED_PEER_IDS,\n JSON.stringify(normalizedTrustedPeerIds),\n );\n\n await setConfig(db, CONFIG_KEYS.PEERJS_SERVER_HOST, normalizedServerHost);\n await setConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_PORT,\n normalizedServerPort ? String(normalizedServerPort) : \"\",\n );\n\n await setConfig(db, CONFIG_KEYS.PEERJS_SERVER_PATH, normalizedServerPath);\n await setConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_SECURE,\n normalizedServerSecure ? \"true\" : \"false\",\n );\n\n const serverConfig = normalizedServerHost\n ? {\n host: normalizedServerHost,\n path: normalizedServerPath || undefined,\n port: normalizedServerPort || undefined,\n secure: normalizedServerSecure,\n }\n : {};\n\n orchestrator.peerjs.stop();\n orchestrator.peerjs.configure(\n normalizedMyPeerId,\n normalizedTrustedPeerIds,\n serverConfig,\n );\n\n if (normalizedMyPeerId && getChannelEnabled(orchestrator, \"peerjs\")) {\n orchestrator.peerjs.start();\n }\n}\n"],"mappings":";;;;;AAQA,eAAsB,gBACpB,cACA,IACA,UACA,gBACA,aAAa,IACb,aAAa,GACb,aAAa,IACb,eAAe,MACA;CACf,MAAM,qBAAqB,SAAS,KAAK;CACzC,MAAM,2BAA2B,oBAAoB,cAAc;CACnE,MAAM,uBAAuB,WAAW,KAAK;CAC7C,MAAM,uBAAuB,OAAO,SAAS,UAAU,IACnD,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,CAAC,IAClC;CAEJ,MAAM,uBAAuB,WAAW,KAAK;CAC7C,MAAM,yBAAyB,CAAC,CAAC;CAEjC,aAAa,iBAAiB;CAC9B,aAAa,uBAAuB;CACpC,aAAa,mBAAmB;CAChC,aAAa,mBAAmB;CAChC,aAAa,mBAAmB;CAChC,aAAa,qBAAqB;CAElC,MAAM,UAAU,IAAI,YAAY,mBAAmB,kBAAkB;CACrE,MAAM,UACJ,IACA,YAAY,yBACZ,KAAK,UAAU,wBAAwB,CACzC;CAEA,MAAM,UAAU,IAAI,YAAY,oBAAoB,oBAAoB;CACxE,MAAM,UACJ,IACA,YAAY,oBACZ,uBAAuB,OAAO,oBAAoB,IAAI,EACxD;CAEA,MAAM,UAAU,IAAI,YAAY,oBAAoB,oBAAoB;CACxE,MAAM,UACJ,IACA,YAAY,sBACZ,yBAAyB,SAAS,OACpC;CAEA,MAAM,eAAe,uBACjB;EACE,MAAM;EACN,MAAM,wBAAwB;EAC9B,MAAM,wBAAwB;EAC9B,QAAQ;CACV,IACA,CAAC;CAEL,aAAa,OAAO,KAAK;CACzB,aAAa,OAAO,UAClB,oBACA,0BACA,YACF;CAEA,IAAI,sBAAsB,kBAAkB,cAAc,QAAQ,GAChE,aAAa,OAAO,MAAM;AAE9B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as CONFIG_KEYS } from "./config-
|
|
1
|
+
import { r as CONFIG_KEYS } from "./config-BcFbkaQv.js";
|
|
2
2
|
import { t as getConfig } from "./getConfig-BxxXMyuM.js";
|
|
3
3
|
import { t as setConfig } from "./setConfig-BFED5CXn.js";
|
|
4
4
|
import { ulid } from "./utils/ulid.js";
|
|
@@ -149,4 +149,4 @@ async function deleteEmailConnection(db, id) {
|
|
|
149
149
|
|
|
150
150
|
//#endregion
|
|
151
151
|
export { upsertEmailConnection as a, listEmailConnections as i, deleteEmailConnection as n, getEmailPluginManifest as o, getEmailConnection as r, listEmailPluginManifests as s, bindEmailCredentialRef as t };
|
|
152
|
-
//# sourceMappingURL=connections-
|
|
152
|
+
//# sourceMappingURL=connections-PZrUDf49.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connections-BURqMIUv.js","names":[],"sources":["../../src/subsystems/email/catalog.ts","../../src/subsystems/email/connections.ts"],"sourcesContent":["import type { AuthType, ServiceType } from \"../../config/config.js\";\n\nexport interface EmailPluginManifest {\n id: string;\n name: string;\n protocol: string;\n description: string;\n version: string;\n actions: string[];\n authTypes: AuthType[];\n serviceTypes: ServiceType[];\n configurableFields: string[];\n}\n\nexport const EMAIL_PLUGIN_MANIFESTS: EmailPluginManifest[] = [\n {\n id: \"imap\",\n name: \"IMAP Mail\",\n protocol: \"imap\",\n description: \"Read mailboxes and fetch message metadata/content.\",\n version: \"0.1.0\",\n actions: [\"messages.read\", \"messages.send\"],\n authTypes: [\"basic_userpass\", \"oauth\"],\n serviceTypes: [\"http_api\"],\n configurableFields: [\n \"host\",\n \"port\",\n \"secure\",\n \"mailboxPath\",\n \"smtpHost\",\n \"smtpPort\",\n \"smtpSecure\",\n \"fromAddress\",\n \"executionMode\",\n \"pollIntervalSec\",\n ],\n },\n];\n\nexport function listEmailPluginManifests(): EmailPluginManifest[] {\n return [...EMAIL_PLUGIN_MANIFESTS].sort((a, b) => a.id.localeCompare(b.id));\n}\n\nexport function getEmailPluginManifest(id: string): EmailPluginManifest | null {\n if (!id) {\n return null;\n }\n\n return EMAIL_PLUGIN_MANIFESTS.find((item) => item.id === id) || null;\n}\n","import {\n CONFIG_KEYS,\n type AuthType,\n type ServiceType,\n} from \"../../config/config.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { setConfig } from \"../../db/setConfig.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport { getEmailPluginManifest } from \"./catalog.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/types.js\";\n\nexport interface EmailCredentialRef {\n serviceType: ServiceType;\n authType: AuthType;\n providerId?: string;\n accountId?: string;\n username?: string;\n headerName?: string;\n encryptedSecret?: string;\n}\n\nexport interface EmailConnectionRecord {\n id: string;\n label: string;\n pluginId: string;\n enabled: boolean;\n config: Record<string, unknown>;\n credentialRef: EmailCredentialRef | null;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface UpsertEmailConnectionInput {\n id?: string;\n label: string;\n pluginId: string;\n enabled?: boolean;\n config?: Record<string, unknown>;\n}\n\nfunction normalizeCredentialRef(value: unknown): EmailCredentialRef | null {\n if (!value || typeof value !== \"object\") {\n return null;\n }\n\n const candidate = value as EmailCredentialRef;\n if (!candidate.serviceType || !candidate.authType) {\n return null;\n }\n\n return {\n serviceType: candidate.serviceType,\n authType: candidate.authType,\n providerId: candidate.providerId || undefined,\n accountId: candidate.accountId || undefined,\n username: candidate.username || undefined,\n headerName: candidate.headerName || undefined,\n encryptedSecret: candidate.encryptedSecret || undefined,\n };\n}\n\nfunction normalizeConnection(value: unknown): EmailConnectionRecord | null {\n if (!value || typeof value !== \"object\") {\n return null;\n }\n\n const candidate = value as Partial<EmailConnectionRecord>;\n if (\n !candidate.id ||\n !candidate.label ||\n !candidate.pluginId ||\n typeof candidate.enabled !== \"boolean\" ||\n typeof candidate.createdAt !== \"number\" ||\n typeof candidate.updatedAt !== \"number\"\n ) {\n return null;\n }\n\n if (!getEmailPluginManifest(candidate.pluginId)) {\n return null;\n }\n\n return {\n id: candidate.id,\n label: candidate.label,\n pluginId: candidate.pluginId,\n enabled: candidate.enabled,\n config:\n candidate.config && typeof candidate.config === \"object\"\n ? { ...candidate.config }\n : {},\n credentialRef: normalizeCredentialRef(candidate.credentialRef),\n createdAt: candidate.createdAt,\n updatedAt: candidate.updatedAt,\n };\n}\n\nasync function loadConnections(\n db: ShadowClawDatabase,\n): Promise<EmailConnectionRecord[]> {\n const raw = await getConfig(db, CONFIG_KEYS.INTEGRATION_CONNECTIONS);\n if (!Array.isArray(raw)) {\n return [];\n }\n\n const normalized: EmailConnectionRecord[] = [];\n for (const item of raw) {\n const record = normalizeConnection(item);\n if (record) {\n normalized.push(record);\n }\n }\n\n return normalized;\n}\n\nasync function saveConnections(\n db: ShadowClawDatabase,\n records: EmailConnectionRecord[],\n): Promise<void> {\n await setConfig(db, CONFIG_KEYS.INTEGRATION_CONNECTIONS, records);\n}\n\nexport async function listEmailConnections(\n db: ShadowClawDatabase,\n): Promise<EmailConnectionRecord[]> {\n return loadConnections(db);\n}\n\nexport async function getEmailConnection(\n db: ShadowClawDatabase,\n id: string,\n): Promise<EmailConnectionRecord | null> {\n if (!id) {\n return null;\n }\n\n const records = await loadConnections(db);\n\n return (\n records.find((record) => record.id === id) ||\n records.find((record) => record.label.toLowerCase() === id.toLowerCase()) ||\n null\n );\n}\n\nexport async function upsertEmailConnection(\n db: ShadowClawDatabase,\n input: UpsertEmailConnectionInput,\n): Promise<EmailConnectionRecord> {\n if (!input.label?.trim()) {\n throw new Error(\"Email connection label is required\");\n }\n\n const plugin = getEmailPluginManifest(input.pluginId);\n if (!plugin) {\n throw new Error(`Unknown email plugin: ${input.pluginId}`);\n }\n\n const records = await loadConnections(db);\n const now = Date.now();\n\n if (input.id) {\n const idx = records.findIndex((record) => record.id === input.id);\n if (idx !== -1) {\n const existing = records[idx];\n const updated: EmailConnectionRecord = {\n ...existing,\n label: input.label.trim(),\n pluginId: plugin.id,\n enabled: input.enabled ?? existing.enabled,\n config: input.config ? { ...input.config } : existing.config,\n updatedAt: now,\n };\n records[idx] = updated;\n await saveConnections(db, records);\n\n return updated;\n }\n }\n\n const created: EmailConnectionRecord = {\n id: input.id || ulid(),\n label: input.label.trim(),\n pluginId: plugin.id,\n enabled: input.enabled ?? true,\n config: input.config ? { ...input.config } : {},\n credentialRef: null,\n createdAt: now,\n updatedAt: now,\n };\n records.push(created);\n await saveConnections(db, records);\n\n return created;\n}\n\nexport async function bindEmailCredentialRef(\n db: ShadowClawDatabase,\n connectionId: string,\n credentialRef: EmailCredentialRef | null,\n): Promise<EmailConnectionRecord | null> {\n if (!connectionId) {\n return null;\n }\n\n const records = await loadConnections(db);\n const idx = records.findIndex((record) => record.id === connectionId);\n if (idx === -1) {\n return null;\n }\n\n const current = records[idx];\n const updated: EmailConnectionRecord = {\n ...current,\n credentialRef: credentialRef ? normalizeCredentialRef(credentialRef) : null,\n updatedAt: Date.now(),\n };\n\n records[idx] = updated;\n await saveConnections(db, records);\n\n return updated;\n}\n\nexport async function deleteEmailConnection(\n db: ShadowClawDatabase,\n id: string,\n): Promise<boolean> {\n if (!id) {\n return false;\n }\n\n const records = await loadConnections(db);\n const next = records.filter((record) => record.id !== id);\n if (next.length === records.length) {\n return false;\n }\n\n await saveConnections(db, next);\n\n return true;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connections-PZrUDf49.js","names":[],"sources":["../../src/subsystems/email/catalog.ts","../../src/subsystems/email/connections.ts"],"sourcesContent":["import type { AuthType, ServiceType } from \"../../config/config.js\";\n\nexport interface EmailPluginManifest {\n id: string;\n name: string;\n protocol: string;\n description: string;\n version: string;\n actions: string[];\n authTypes: AuthType[];\n serviceTypes: ServiceType[];\n configurableFields: string[];\n}\n\nexport const EMAIL_PLUGIN_MANIFESTS: EmailPluginManifest[] = [\n {\n id: \"imap\",\n name: \"IMAP Mail\",\n protocol: \"imap\",\n description: \"Read mailboxes and fetch message metadata/content.\",\n version: \"0.1.0\",\n actions: [\"messages.read\", \"messages.send\"],\n authTypes: [\"basic_userpass\", \"oauth\"],\n serviceTypes: [\"http_api\"],\n configurableFields: [\n \"host\",\n \"port\",\n \"secure\",\n \"mailboxPath\",\n \"smtpHost\",\n \"smtpPort\",\n \"smtpSecure\",\n \"fromAddress\",\n \"executionMode\",\n \"pollIntervalSec\",\n ],\n },\n];\n\nexport function listEmailPluginManifests(): EmailPluginManifest[] {\n return [...EMAIL_PLUGIN_MANIFESTS].sort((a, b) => a.id.localeCompare(b.id));\n}\n\nexport function getEmailPluginManifest(id: string): EmailPluginManifest | null {\n if (!id) {\n return null;\n }\n\n return EMAIL_PLUGIN_MANIFESTS.find((item) => item.id === id) || null;\n}\n","import {\n CONFIG_KEYS,\n type AuthType,\n type ServiceType,\n} from \"../../config/config.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { setConfig } from \"../../db/setConfig.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport { getEmailPluginManifest } from \"./catalog.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/types.js\";\n\nexport interface EmailCredentialRef {\n serviceType: ServiceType;\n authType: AuthType;\n providerId?: string;\n accountId?: string;\n username?: string;\n headerName?: string;\n encryptedSecret?: string;\n}\n\nexport interface EmailConnectionRecord {\n id: string;\n label: string;\n pluginId: string;\n enabled: boolean;\n config: Record<string, unknown>;\n credentialRef: EmailCredentialRef | null;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface UpsertEmailConnectionInput {\n id?: string;\n label: string;\n pluginId: string;\n enabled?: boolean;\n config?: Record<string, unknown>;\n}\n\nfunction normalizeCredentialRef(value: unknown): EmailCredentialRef | null {\n if (!value || typeof value !== \"object\") {\n return null;\n }\n\n const candidate = value as EmailCredentialRef;\n if (!candidate.serviceType || !candidate.authType) {\n return null;\n }\n\n return {\n serviceType: candidate.serviceType,\n authType: candidate.authType,\n providerId: candidate.providerId || undefined,\n accountId: candidate.accountId || undefined,\n username: candidate.username || undefined,\n headerName: candidate.headerName || undefined,\n encryptedSecret: candidate.encryptedSecret || undefined,\n };\n}\n\nfunction normalizeConnection(value: unknown): EmailConnectionRecord | null {\n if (!value || typeof value !== \"object\") {\n return null;\n }\n\n const candidate = value as Partial<EmailConnectionRecord>;\n if (\n !candidate.id ||\n !candidate.label ||\n !candidate.pluginId ||\n typeof candidate.enabled !== \"boolean\" ||\n typeof candidate.createdAt !== \"number\" ||\n typeof candidate.updatedAt !== \"number\"\n ) {\n return null;\n }\n\n if (!getEmailPluginManifest(candidate.pluginId)) {\n return null;\n }\n\n return {\n id: candidate.id,\n label: candidate.label,\n pluginId: candidate.pluginId,\n enabled: candidate.enabled,\n config:\n candidate.config && typeof candidate.config === \"object\"\n ? { ...candidate.config }\n : {},\n credentialRef: normalizeCredentialRef(candidate.credentialRef),\n createdAt: candidate.createdAt,\n updatedAt: candidate.updatedAt,\n };\n}\n\nasync function loadConnections(\n db: ShadowClawDatabase,\n): Promise<EmailConnectionRecord[]> {\n const raw = await getConfig(db, CONFIG_KEYS.INTEGRATION_CONNECTIONS);\n if (!Array.isArray(raw)) {\n return [];\n }\n\n const normalized: EmailConnectionRecord[] = [];\n for (const item of raw) {\n const record = normalizeConnection(item);\n if (record) {\n normalized.push(record);\n }\n }\n\n return normalized;\n}\n\nasync function saveConnections(\n db: ShadowClawDatabase,\n records: EmailConnectionRecord[],\n): Promise<void> {\n await setConfig(db, CONFIG_KEYS.INTEGRATION_CONNECTIONS, records);\n}\n\nexport async function listEmailConnections(\n db: ShadowClawDatabase,\n): Promise<EmailConnectionRecord[]> {\n return loadConnections(db);\n}\n\nexport async function getEmailConnection(\n db: ShadowClawDatabase,\n id: string,\n): Promise<EmailConnectionRecord | null> {\n if (!id) {\n return null;\n }\n\n const records = await loadConnections(db);\n\n return (\n records.find((record) => record.id === id) ||\n records.find((record) => record.label.toLowerCase() === id.toLowerCase()) ||\n null\n );\n}\n\nexport async function upsertEmailConnection(\n db: ShadowClawDatabase,\n input: UpsertEmailConnectionInput,\n): Promise<EmailConnectionRecord> {\n if (!input.label?.trim()) {\n throw new Error(\"Email connection label is required\");\n }\n\n const plugin = getEmailPluginManifest(input.pluginId);\n if (!plugin) {\n throw new Error(`Unknown email plugin: ${input.pluginId}`);\n }\n\n const records = await loadConnections(db);\n const now = Date.now();\n\n if (input.id) {\n const idx = records.findIndex((record) => record.id === input.id);\n if (idx !== -1) {\n const existing = records[idx];\n const updated: EmailConnectionRecord = {\n ...existing,\n label: input.label.trim(),\n pluginId: plugin.id,\n enabled: input.enabled ?? existing.enabled,\n config: input.config ? { ...input.config } : existing.config,\n updatedAt: now,\n };\n records[idx] = updated;\n await saveConnections(db, records);\n\n return updated;\n }\n }\n\n const created: EmailConnectionRecord = {\n id: input.id || ulid(),\n label: input.label.trim(),\n pluginId: plugin.id,\n enabled: input.enabled ?? true,\n config: input.config ? { ...input.config } : {},\n credentialRef: null,\n createdAt: now,\n updatedAt: now,\n };\n records.push(created);\n await saveConnections(db, records);\n\n return created;\n}\n\nexport async function bindEmailCredentialRef(\n db: ShadowClawDatabase,\n connectionId: string,\n credentialRef: EmailCredentialRef | null,\n): Promise<EmailConnectionRecord | null> {\n if (!connectionId) {\n return null;\n }\n\n const records = await loadConnections(db);\n const idx = records.findIndex((record) => record.id === connectionId);\n if (idx === -1) {\n return null;\n }\n\n const current = records[idx];\n const updated: EmailConnectionRecord = {\n ...current,\n credentialRef: credentialRef ? normalizeCredentialRef(credentialRef) : null,\n updatedAt: Date.now(),\n };\n\n records[idx] = updated;\n await saveConnections(db, records);\n\n return updated;\n}\n\nexport async function deleteEmailConnection(\n db: ShadowClawDatabase,\n id: string,\n): Promise<boolean> {\n if (!id) {\n return false;\n }\n\n const records = await loadConnections(db);\n const next = records.filter((record) => record.id !== id);\n if (next.length === records.length) {\n return false;\n }\n\n await saveConnections(db, next);\n\n return true;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as getGroupDir } from "./getGroupDir-
|
|
1
|
+
import { t as getGroupDir } from "./getGroupDir-BxKMYPPm.js";
|
|
2
2
|
import { t as parsePath } from "./parsePath-DwC_YZjw.js";
|
|
3
3
|
|
|
4
4
|
//#region src/storage/downloadGroupFile.ts
|
|
@@ -23,4 +23,4 @@ async function downloadGroupFile(db, groupId, filePath) {
|
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
25
|
export { downloadGroupFile as t };
|
|
26
|
-
//# sourceMappingURL=downloadGroupFile-
|
|
26
|
+
//# sourceMappingURL=downloadGroupFile-DSRUa9Au.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloadGroupFile-
|
|
1
|
+
{"version":3,"file":"downloadGroupFile-DSRUa9Au.js","names":[],"sources":["../../src/storage/downloadGroupFile.ts"],"sourcesContent":["import { getGroupDir } from \"./getGroupDir.js\";\nimport { parsePath } from \"./parsePath.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Download a single file\n */\nexport async function downloadGroupFile(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<void> {\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 const file = await fileHandle.getFile();\n\n // Create a download link and trigger download\n const url = URL.createObjectURL(file);\n const link = document.createElement(\"a\");\n\n link.href = url;\n link.download = filename;\n\n document.body.appendChild(link);\n\n link.click();\n\n document.body.removeChild(link);\n\n URL.revokeObjectURL(url);\n}\n"],"mappings":";;;;;;;AAOA,eAAsB,kBACpB,IACA,SACA,UACe;CACf,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;CAIxC,MAAM,OAAO,OAAM,MADM,IAAI,cAAc,QAAQ,EACtB,CAAC,QAAQ;CAGtC,MAAM,MAAM,IAAI,gBAAgB,IAAI;CACpC,MAAM,OAAO,SAAS,cAAc,GAAG;CAEvC,KAAK,OAAO;CACZ,KAAK,WAAW;CAEhB,SAAS,KAAK,YAAY,IAAI;CAE9B,KAAK,MAAM;CAEX,SAAS,KAAK,YAAY,IAAI;CAE9B,IAAI,gBAAgB,GAAG;AACzB"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as Signal } from "./dist-Bxg3C_zy.js";
|
|
2
|
-
import { t as getGroupDir } from "./getGroupDir-
|
|
3
|
-
import { o as DEFAULT_GROUP_ID } from "./config-
|
|
2
|
+
import { t as getGroupDir } from "./getGroupDir-BxKMYPPm.js";
|
|
3
|
+
import { o as DEFAULT_GROUP_ID } from "./config-BcFbkaQv.js";
|
|
4
4
|
import { t as parsePath } from "./parsePath-DwC_YZjw.js";
|
|
5
|
-
import { f as readGroupFile } from "./tools-
|
|
6
|
-
import { t as readGroupFileBytes } from "./readGroupFileBytes-
|
|
5
|
+
import { f as readGroupFile } from "./tools-Bb2ujM2E.js";
|
|
6
|
+
import { t as readGroupFileBytes } from "./readGroupFileBytes-7C8G-yps.js";
|
|
7
7
|
|
|
8
8
|
//#region src/storage/getGroupFile.ts
|
|
9
9
|
/**
|
|
@@ -148,4 +148,4 @@ const fileViewerStore = new FileViewerStore();
|
|
|
148
148
|
|
|
149
149
|
//#endregion
|
|
150
150
|
export { fileViewerStore as t };
|
|
151
|
-
//# sourceMappingURL=file-viewer-
|
|
151
|
+
//# sourceMappingURL=file-viewer-11VVOpJv.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-viewer-
|
|
1
|
+
{"version":3,"file":"file-viewer-11VVOpJv.js","names":[],"sources":["../../src/storage/getGroupFile.ts","../../src/stores/file-viewer.ts"],"sourcesContent":["import { getGroupDir } from \"./getGroupDir.js\";\nimport { parsePath } from \"./parsePath.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Get a native File object from a file in a group's workspace.\n */\nexport async function getGroupFile(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<File> {\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 return await fileHandle.getFile();\n}\n","import { Signal } from \"signal-polyfill\";\n\nimport { readGroupFile } from \"../storage/readGroupFile.js\";\nimport { readGroupFileBytes } from \"../storage/readGroupFileBytes.js\";\nimport { getGroupFile } from \"../storage/getGroupFile.js\";\nimport { DEFAULT_GROUP_ID } from \"../config/config.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\nexport interface FileInfo {\n name: string;\n path?: string;\n groupId?: string;\n content: string;\n kind: \"text\" | \"pdf\" | \"binary\";\n binaryContent: Uint8Array | null;\n nativeFile?: File | null;\n mimeType: string;\n}\n\nexport interface FileViewerState {\n file: FileInfo | null;\n openFile: (\n db: ShadowClawDatabase,\n path: string,\n groupId?: string,\n ) => Promise<void>;\n closeFile: () => void;\n}\n\nexport class FileViewerStore {\n private _file: Signal.State<FileInfo | null>;\n\n constructor() {\n this._file = new Signal.State(null);\n }\n\n /**\n * Close the current file\n */\n closeFile() {\n this._file.set(null);\n }\n\n get file(): FileInfo | null {\n return this._file.get();\n }\n\n /**\n * Get current file\n */\n getFile(): FileInfo | null {\n return this.file;\n }\n\n /**\n * Get preview binary MIME type\n */\n getPreviewBinaryMimeType(fileName: string): string {\n const extension = fileName.toLowerCase().split(\".\").pop() || \"\";\n\n const mimeTypes: Record<string, string> = {\n \"3gp\": \"video/3gpp\",\n \"7z\": \"application/x-7z-compressed\",\n aac: \"audio/aac\",\n apng: \"image/apng\",\n avi: \"video/x-msvideo\",\n avif: \"image/avif\",\n bin: \"application/octet-stream\",\n bmp: \"image/bmp\",\n db: \"application/vnd.sqlite3\",\n dll: \"application/octet-stream\",\n dmg: \"application/octet-stream\",\n dylib: \"application/octet-stream\",\n exe: \"application/vnd.microsoft.portable-executable\",\n flac: \"audio/flac\",\n flv: \"video/x-flv\",\n gif: \"image/gif\",\n gz: \"application/gzip\",\n heic: \"image/heic\",\n heif: \"image/heif\",\n ico: \"image/x-icon\",\n iso: \"application/octet-stream\",\n jpeg: \"image/jpeg\",\n jpg: \"image/jpeg\",\n m4a: \"audio/mp4\",\n m4v: \"video/mp4\",\n mkv: \"video/x-matroska\",\n mov: \"video/mp4\",\n mp3: \"audio/mpeg\",\n mp4: \"video/mp4\",\n oga: \"audio/ogg\",\n ogg: \"audio/ogg\",\n ogv: \"video/ogg\",\n png: \"image/png\",\n rar: \"application/vnd.rar\",\n so: \"application/octet-stream\",\n sqlite: \"application/vnd.sqlite3\",\n sqlite3: \"application/vnd.sqlite3\",\n tar: \"application/x-tar\",\n tif: \"image/tiff\",\n tiff: \"image/tiff\",\n wasm: \"application/wasm\",\n wav: \"audio/wav\",\n weba: \"audio/webm\",\n webm: \"video/webm\",\n webp: \"image/webp\",\n wmv: \"video/x-ms-wmv\",\n zip: \"application/zip\",\n };\n\n return mimeTypes[extension] || \"\";\n }\n\n /**\n * Open a file\n */\n async openFile(\n db: ShadowClawDatabase,\n path: string,\n groupId: string = DEFAULT_GROUP_ID,\n ): Promise<void> {\n try {\n const name = path.split(\"/\").pop() || path;\n const isPdf = /\\.pdf$/i.test(name);\n const binaryMimeType = this.getPreviewBinaryMimeType(name);\n\n if (isPdf) {\n const binaryContent = await readGroupFileBytes(db, groupId, path);\n\n this._file.set({\n name,\n path,\n groupId,\n content: \"\",\n kind: \"pdf\",\n binaryContent,\n mimeType: \"application/pdf\",\n });\n\n return;\n }\n\n if (binaryMimeType) {\n const nativeFile = await getGroupFile(db, groupId, path);\n\n this._file.set({\n name,\n path,\n groupId,\n content: \"\",\n kind: \"binary\",\n binaryContent: null,\n nativeFile,\n mimeType: binaryMimeType,\n });\n\n return;\n }\n\n const content = await readGroupFile(db, groupId, path);\n this._file.set({\n name,\n path,\n groupId,\n content,\n kind: \"text\",\n binaryContent: null,\n mimeType: \"text/plain\",\n });\n } catch (err) {\n console.error(\"Failed to open file:\", path, err);\n\n throw err;\n }\n }\n}\n\nexport const fileViewerStore = new FileViewerStore();\n"],"mappings":";;;;;;;;;;;AAOA,eAAsB,aACpB,IACA,SACA,UACe;CACf,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;CAKxC,OAAO,OAAM,MAFY,IAAI,cAAc,QAAQ,EAE5B,CAAC,QAAQ;AAClC;;;;ACMA,IAAa,kBAAb,MAA6B;CAC3B,AAAQ;CAER,cAAc;EACZ,KAAK,QAAQ,IAAI,OAAO,MAAM,IAAI;CACpC;;;;CAKA,YAAY;EACV,KAAK,MAAM,IAAI,IAAI;CACrB;CAEA,IAAI,OAAwB;EAC1B,OAAO,KAAK,MAAM,IAAI;CACxB;;;;CAKA,UAA2B;EACzB,OAAO,KAAK;CACd;;;;CAKA,yBAAyB,UAA0B;EAqDjD,OAAO;GAjDL,OAAO;GACP,MAAM;GACN,KAAK;GACL,MAAM;GACN,KAAK;GACL,MAAM;GACN,KAAK;GACL,KAAK;GACL,IAAI;GACJ,KAAK;GACL,KAAK;GACL,OAAO;GACP,KAAK;GACL,MAAM;GACN,KAAK;GACL,KAAK;GACL,IAAI;GACJ,MAAM;GACN,MAAM;GACN,KAAK;GACL,KAAK;GACL,MAAM;GACN,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,IAAI;GACJ,QAAQ;GACR,SAAS;GACT,KAAK;GACL,KAAK;GACL,MAAM;GACN,MAAM;GACN,KAAK;GACL,MAAM;GACN,MAAM;GACN,MAAM;GACN,KAAK;GACL,KAAK;EAGQ,EApDG,SAAS,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,OAoD9B;CACjC;;;;CAKA,MAAM,SACJ,IACA,MACA,UAAkB,kBACH;EACf,IAAI;GACF,MAAM,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;GACtC,MAAM,QAAQ,UAAU,KAAK,IAAI;GACjC,MAAM,iBAAiB,KAAK,yBAAyB,IAAI;GAEzD,IAAI,OAAO;IACT,MAAM,gBAAgB,MAAM,mBAAmB,IAAI,SAAS,IAAI;IAEhE,KAAK,MAAM,IAAI;KACb;KACA;KACA;KACA,SAAS;KACT,MAAM;KACN;KACA,UAAU;IACZ,CAAC;IAED;GACF;GAEA,IAAI,gBAAgB;IAClB,MAAM,aAAa,MAAM,aAAa,IAAI,SAAS,IAAI;IAEvD,KAAK,MAAM,IAAI;KACb;KACA;KACA;KACA,SAAS;KACT,MAAM;KACN,eAAe;KACf;KACA,UAAU;IACZ,CAAC;IAED;GACF;GAEA,MAAM,UAAU,MAAM,cAAc,IAAI,SAAS,IAAI;GACrD,KAAK,MAAM,IAAI;IACb;IACA;IACA;IACA;IACA,MAAM;IACN,eAAe;IACf,UAAU;GACZ,CAAC;EACH,SAAS,KAAK;GACZ,QAAQ,MAAM,wBAAwB,MAAM,GAAG;GAE/C,MAAM;EACR;CACF;AACF;AAEA,MAAa,kBAAkB,IAAI,gBAAgB"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-DZ8SGSJo.js";
|
|
2
2
|
import { t as txPromise } from "./txPromise-CuGh-TGK.js";
|
|
3
|
-
import { r as CONFIG_KEYS, x as OPFS_ROOT } from "./config-
|
|
3
|
+
import { r as CONFIG_KEYS, x as OPFS_ROOT } from "./config-BcFbkaQv.js";
|
|
4
4
|
import { a as getDeploymentNamespace } from "./app-routes-BAEMLu9g.js";
|
|
5
5
|
import { t as getConfig } from "./getConfig-BxxXMyuM.js";
|
|
6
|
-
import { t as getMemoryOpfsRoot } from "./memoryStorage-
|
|
6
|
+
import { t as getMemoryOpfsRoot } from "./memoryStorage-DcFWrn_y.js";
|
|
7
7
|
|
|
8
8
|
//#region src/storage/getNestedDir.ts
|
|
9
9
|
/**
|
|
@@ -169,4 +169,4 @@ async function getGroupDir(db, groupId) {
|
|
|
169
169
|
|
|
170
170
|
//#endregion
|
|
171
171
|
export { getStorageStatus as a, resetStorageDirectory as c, getStorageRoot as i, setStorageRoot as l, getGroupDir_exports as n, invalidateStorageRoot as o, getOpfsRootDirName as r, isStaleHandleError as s, getGroupDir as t };
|
|
172
|
-
//# sourceMappingURL=getGroupDir-
|
|
172
|
+
//# sourceMappingURL=getGroupDir-BxKMYPPm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getGroupDir-QrN2aTo8.js","names":[],"sources":["../../src/storage/getNestedDir.ts","../../src/db/deleteConfig.ts","../../src/storage/storage.ts","../../src/storage/getGroupDir.ts"],"sourcesContent":["/**\n * Get a handle to a nested directory, creating intermediate dirs.\n */\nexport async function getNestedDir(\n root: FileSystemDirectoryHandle,\n ...segments: string[]\n): Promise<FileSystemDirectoryHandle> {\n let current = root;\n\n for (const seg of segments) {\n const child = await current.getDirectoryHandle(seg, { create: true });\n\n // Guard against stale handles (e.g. Electron after app restart) where\n // getDirectoryHandle returns the same directory instead of navigating.\n if (\n typeof current.isSameEntry === \"function\" &&\n (await current.isSameEntry(child))\n ) {\n throw new Error(\n `Directory navigation failed: \"${seg}\" resolved to the same directory as its parent. ` +\n \"The stored directory handle may be stale — try re-selecting the storage folder.\",\n );\n }\n\n current = child;\n }\n\n return current;\n}\n","import { txPromise } from \"./txPromise.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Delete a config value\n */\nexport function deleteConfig(\n db: ShadowClawDatabase,\n key: string,\n): Promise<void> {\n return txPromise(db, \"config\", \"readwrite\", (store) =>\n store.delete(key),\n ).then(() => undefined);\n}\n","import { CONFIG_KEYS, OPFS_ROOT } from \"../config/config.js\";\nimport { getDeploymentNamespace } from \"../core/app-routes.js\";\nimport { deleteConfig } from \"../db/deleteConfig.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { getMemoryOpfsRoot } from \"./memoryStorage.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\nexport interface StorageStatus {\n type: \"opfs\" | \"local\";\n permission: \"granted\" | \"denied\" | \"prompt\";\n name: string | null;\n}\n\nlet explicitRoot: FileSystemDirectoryHandle | null = null;\n\n/**\n * Verify whether a directory handle is actually functional by attempting\n * to iterate its entries.\n */\nasync function probeHandleAccess(\n handle: FileSystemDirectoryHandle,\n reportedPermission: \"granted\" | \"denied\" | \"prompt\",\n): Promise<\"granted\" | \"denied\" | \"prompt\"> {\n try {\n const iter = (handle as any).entries();\n await iter.next();\n\n // I/O succeeded — the handle is functional regardless of what\n // queryPermission reported.\n\n return \"granted\";\n } catch {\n return reportedPermission;\n }\n}\n\n/**\n * Get the OPFS root directory name taking into account deployment namespace.\n */\nexport function getOpfsRootDirName(): string {\n const ns = getDeploymentNamespace();\n\n return ns ? `${OPFS_ROOT}-${ns}` : OPFS_ROOT;\n}\n\nasync function getOpfsRoot(): Promise<FileSystemDirectoryHandle> {\n try {\n if (\n typeof navigator !== \"undefined\" &&\n navigator.storage &&\n typeof navigator.storage.getDirectory === \"function\"\n ) {\n const opfsRoot = await navigator.storage.getDirectory();\n const opfsRootName = getOpfsRootDirName();\n\n return await opfsRoot.getDirectoryHandle(opfsRootName, {\n create: true,\n });\n }\n } catch (err) {\n console.warn(\n \"OPFS is unavailable (e.g. Firefox Private Browsing). Using in-memory storage fallback:\",\n err,\n );\n }\n\n return getMemoryOpfsRoot();\n}\n\n/**\n * Determine whether a value behaves like a FileSystemDirectoryHandle.\n */\nfunction isDirectoryHandle(handle: any): handle is FileSystemDirectoryHandle {\n if (!handle || typeof handle !== \"object\") {\n return false;\n }\n\n const ctor = globalThis.FileSystemDirectoryHandle;\n if (typeof ctor !== \"undefined\" && handle instanceof ctor) {\n return true;\n }\n\n return (\n typeof handle.getDirectoryHandle === \"function\" &&\n typeof handle.getFileHandle === \"function\"\n );\n}\n\n/**\n * Get the current storage root handle.\n */\nexport async function getStorageRoot(\n db: ShadowClawDatabase,\n): Promise<FileSystemDirectoryHandle> {\n if (explicitRoot) {\n return explicitRoot;\n }\n\n try {\n const storedHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n if (isDirectoryHandle(storedHandle)) {\n const handle = storedHandle as any;\n // Check if we still have permission (main thread only)\n if (typeof handle.queryPermission === \"function\") {\n const status = await handle.queryPermission({\n mode: \"readwrite\",\n });\n\n // Electron (and some other embedders) report \"prompt\" even when the\n // handle is functional. Try to silently re-activate the permission\n // so downstream code doesn't hit stale-handle errors.\n if (\n status !== \"granted\" &&\n typeof handle.requestPermission === \"function\"\n ) {\n try {\n await handle.requestPermission({ mode: \"readwrite\" });\n } catch {\n // requestPermission may throw in some contexts — that's OK\n }\n }\n }\n\n // If we have a handle but no permission, we still return it so tools\n // fail with a clear \"permission denied\" error instead of silently\n // falling back to OPFS and causing \"split brain\".\n\n return handle;\n }\n } catch (err) {\n console.warn(\"Failed to retrieve local storage handle from DB:\", err);\n }\n\n // Fallback to OPFS root only if NO local handle is configured\n\n return getOpfsRoot();\n}\n\n/**\n * Set an explicit storage root handle (used to sync handle to workers).\n */\nexport function setStorageRoot(handle: FileSystemDirectoryHandle): void {\n explicitRoot = handle;\n}\n\n/**\n * Clear the cached storage root so the next call to getStorageRoot()\n * re-acquires a fresh handle. Call this when an InvalidStateError\n * indicates the cached handle has gone stale.\n */\nexport function invalidateStorageRoot() {\n explicitRoot = null;\n}\n\n/**\n * Detect a stale-handle DOMException (\"InvalidStateError\") thrown by\n * the File System Access API when the underlying entry has changed\n * since the handle was obtained.\n */\nexport function isStaleHandleError(err: unknown): boolean {\n if (!(err instanceof DOMException)) {\n return false;\n }\n\n return err.name === \"InvalidStateError\";\n}\n\n/**\n * Reset storage to use browser-internal OPFS.\n */\nexport async function resetStorageDirectory(\n db: ShadowClawDatabase,\n): Promise<void> {\n await deleteConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n\n explicitRoot = null;\n}\n\n/**\n * Get the current storage status.\n */\nexport async function getStorageStatus(\n db: ShadowClawDatabase,\n): Promise<StorageStatus> {\n if (explicitRoot) {\n try {\n const permission = await (explicitRoot as any).queryPermission({\n mode: \"readwrite\",\n });\n\n // Electron may report \"prompt\" even when the handle works.\n // Test actual functionality before reporting the permission level.\n const effectivePermission =\n permission === \"granted\"\n ? \"granted\"\n : await probeHandleAccess(explicitRoot, permission);\n\n return {\n type: \"local\",\n permission: effectivePermission,\n name: explicitRoot.name,\n };\n } catch {\n // If queryPermission fails, explicitRoot might be stale\n console.warn(\"Getting storage status failed for explicit storage root.\");\n }\n }\n\n try {\n const storedHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n\n if (isDirectoryHandle(storedHandle)) {\n const handle = storedHandle as any;\n const permission = await handle.queryPermission({\n mode: \"readwrite\",\n });\n\n const effectivePermission =\n permission === \"granted\"\n ? \"granted\"\n : await probeHandleAccess(handle, permission);\n\n return {\n type: \"local\",\n permission: effectivePermission,\n name: handle.name,\n };\n }\n } catch (err) {\n console.warn(\"Failed to check storage status:\", err);\n }\n\n return { type: \"opfs\", permission: \"granted\", name: \"OPFS\" };\n}\n","import { getNestedDir } from \"./getNestedDir.js\";\nimport { getStorageRoot } from \"./storage.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Get the group workspace directory.\n */\nexport async function getGroupDir(\n db: ShadowClawDatabase,\n groupId: string,\n): Promise<FileSystemDirectoryHandle> {\n const root = await getStorageRoot(db);\n // Sanitize groupId for filesystem: replace colons with dashes\n const safeId = groupId.replace(/:/g, \"-\");\n\n return getNestedDir(root, \"groups\", safeId);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getGroupDir-BxKMYPPm.js","names":[],"sources":["../../src/storage/getNestedDir.ts","../../src/db/deleteConfig.ts","../../src/storage/storage.ts","../../src/storage/getGroupDir.ts"],"sourcesContent":["/**\n * Get a handle to a nested directory, creating intermediate dirs.\n */\nexport async function getNestedDir(\n root: FileSystemDirectoryHandle,\n ...segments: string[]\n): Promise<FileSystemDirectoryHandle> {\n let current = root;\n\n for (const seg of segments) {\n const child = await current.getDirectoryHandle(seg, { create: true });\n\n // Guard against stale handles (e.g. Electron after app restart) where\n // getDirectoryHandle returns the same directory instead of navigating.\n if (\n typeof current.isSameEntry === \"function\" &&\n (await current.isSameEntry(child))\n ) {\n throw new Error(\n `Directory navigation failed: \"${seg}\" resolved to the same directory as its parent. ` +\n \"The stored directory handle may be stale — try re-selecting the storage folder.\",\n );\n }\n\n current = child;\n }\n\n return current;\n}\n","import { txPromise } from \"./txPromise.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Delete a config value\n */\nexport function deleteConfig(\n db: ShadowClawDatabase,\n key: string,\n): Promise<void> {\n return txPromise(db, \"config\", \"readwrite\", (store) =>\n store.delete(key),\n ).then(() => undefined);\n}\n","import { CONFIG_KEYS, OPFS_ROOT } from \"../config/config.js\";\nimport { getDeploymentNamespace } from \"../core/app-routes.js\";\nimport { deleteConfig } from \"../db/deleteConfig.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { getMemoryOpfsRoot } from \"./memoryStorage.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\nexport interface StorageStatus {\n type: \"opfs\" | \"local\";\n permission: \"granted\" | \"denied\" | \"prompt\";\n name: string | null;\n}\n\nlet explicitRoot: FileSystemDirectoryHandle | null = null;\n\n/**\n * Verify whether a directory handle is actually functional by attempting\n * to iterate its entries.\n */\nasync function probeHandleAccess(\n handle: FileSystemDirectoryHandle,\n reportedPermission: \"granted\" | \"denied\" | \"prompt\",\n): Promise<\"granted\" | \"denied\" | \"prompt\"> {\n try {\n const iter = (handle as any).entries();\n await iter.next();\n\n // I/O succeeded — the handle is functional regardless of what\n // queryPermission reported.\n\n return \"granted\";\n } catch {\n return reportedPermission;\n }\n}\n\n/**\n * Get the OPFS root directory name taking into account deployment namespace.\n */\nexport function getOpfsRootDirName(): string {\n const ns = getDeploymentNamespace();\n\n return ns ? `${OPFS_ROOT}-${ns}` : OPFS_ROOT;\n}\n\nasync function getOpfsRoot(): Promise<FileSystemDirectoryHandle> {\n try {\n if (\n typeof navigator !== \"undefined\" &&\n navigator.storage &&\n typeof navigator.storage.getDirectory === \"function\"\n ) {\n const opfsRoot = await navigator.storage.getDirectory();\n const opfsRootName = getOpfsRootDirName();\n\n return await opfsRoot.getDirectoryHandle(opfsRootName, {\n create: true,\n });\n }\n } catch (err) {\n console.warn(\n \"OPFS is unavailable (e.g. Firefox Private Browsing). Using in-memory storage fallback:\",\n err,\n );\n }\n\n return getMemoryOpfsRoot();\n}\n\n/**\n * Determine whether a value behaves like a FileSystemDirectoryHandle.\n */\nfunction isDirectoryHandle(handle: any): handle is FileSystemDirectoryHandle {\n if (!handle || typeof handle !== \"object\") {\n return false;\n }\n\n const ctor = globalThis.FileSystemDirectoryHandle;\n if (typeof ctor !== \"undefined\" && handle instanceof ctor) {\n return true;\n }\n\n return (\n typeof handle.getDirectoryHandle === \"function\" &&\n typeof handle.getFileHandle === \"function\"\n );\n}\n\n/**\n * Get the current storage root handle.\n */\nexport async function getStorageRoot(\n db: ShadowClawDatabase,\n): Promise<FileSystemDirectoryHandle> {\n if (explicitRoot) {\n return explicitRoot;\n }\n\n try {\n const storedHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n if (isDirectoryHandle(storedHandle)) {\n const handle = storedHandle as any;\n // Check if we still have permission (main thread only)\n if (typeof handle.queryPermission === \"function\") {\n const status = await handle.queryPermission({\n mode: \"readwrite\",\n });\n\n // Electron (and some other embedders) report \"prompt\" even when the\n // handle is functional. Try to silently re-activate the permission\n // so downstream code doesn't hit stale-handle errors.\n if (\n status !== \"granted\" &&\n typeof handle.requestPermission === \"function\"\n ) {\n try {\n await handle.requestPermission({ mode: \"readwrite\" });\n } catch {\n // requestPermission may throw in some contexts — that's OK\n }\n }\n }\n\n // If we have a handle but no permission, we still return it so tools\n // fail with a clear \"permission denied\" error instead of silently\n // falling back to OPFS and causing \"split brain\".\n\n return handle;\n }\n } catch (err) {\n console.warn(\"Failed to retrieve local storage handle from DB:\", err);\n }\n\n // Fallback to OPFS root only if NO local handle is configured\n\n return getOpfsRoot();\n}\n\n/**\n * Set an explicit storage root handle (used to sync handle to workers).\n */\nexport function setStorageRoot(handle: FileSystemDirectoryHandle): void {\n explicitRoot = handle;\n}\n\n/**\n * Clear the cached storage root so the next call to getStorageRoot()\n * re-acquires a fresh handle. Call this when an InvalidStateError\n * indicates the cached handle has gone stale.\n */\nexport function invalidateStorageRoot() {\n explicitRoot = null;\n}\n\n/**\n * Detect a stale-handle DOMException (\"InvalidStateError\") thrown by\n * the File System Access API when the underlying entry has changed\n * since the handle was obtained.\n */\nexport function isStaleHandleError(err: unknown): boolean {\n if (!(err instanceof DOMException)) {\n return false;\n }\n\n return err.name === \"InvalidStateError\";\n}\n\n/**\n * Reset storage to use browser-internal OPFS.\n */\nexport async function resetStorageDirectory(\n db: ShadowClawDatabase,\n): Promise<void> {\n await deleteConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n\n explicitRoot = null;\n}\n\n/**\n * Get the current storage status.\n */\nexport async function getStorageStatus(\n db: ShadowClawDatabase,\n): Promise<StorageStatus> {\n if (explicitRoot) {\n try {\n const permission = await (explicitRoot as any).queryPermission({\n mode: \"readwrite\",\n });\n\n // Electron may report \"prompt\" even when the handle works.\n // Test actual functionality before reporting the permission level.\n const effectivePermission =\n permission === \"granted\"\n ? \"granted\"\n : await probeHandleAccess(explicitRoot, permission);\n\n return {\n type: \"local\",\n permission: effectivePermission,\n name: explicitRoot.name,\n };\n } catch {\n // If queryPermission fails, explicitRoot might be stale\n console.warn(\"Getting storage status failed for explicit storage root.\");\n }\n }\n\n try {\n const storedHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n\n if (isDirectoryHandle(storedHandle)) {\n const handle = storedHandle as any;\n const permission = await handle.queryPermission({\n mode: \"readwrite\",\n });\n\n const effectivePermission =\n permission === \"granted\"\n ? \"granted\"\n : await probeHandleAccess(handle, permission);\n\n return {\n type: \"local\",\n permission: effectivePermission,\n name: handle.name,\n };\n }\n } catch (err) {\n console.warn(\"Failed to check storage status:\", err);\n }\n\n return { type: \"opfs\", permission: \"granted\", name: \"OPFS\" };\n}\n","import { getNestedDir } from \"./getNestedDir.js\";\nimport { getStorageRoot } from \"./storage.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Get the group workspace directory.\n */\nexport async function getGroupDir(\n db: ShadowClawDatabase,\n groupId: string,\n): Promise<FileSystemDirectoryHandle> {\n const root = await getStorageRoot(db);\n // Sanitize groupId for filesystem: replace colons with dashes\n const safeId = groupId.replace(/:/g, \"-\");\n\n return getNestedDir(root, \"groups\", safeId);\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __toESM, t as __commonJSMin } from "./rolldown-runtime-DZ8SGSJo.js";
|
|
2
|
-
import { a as DEFAULT_DEV_PORT, i as DEFAULT_DEV_HOST } from "./config-
|
|
2
|
+
import { a as DEFAULT_DEV_PORT, i as DEFAULT_DEV_HOST } from "./config-BcFbkaQv.js";
|
|
3
3
|
import { t as require_browser } from "./browser-FvTfy_Ym.js";
|
|
4
4
|
import { t as require_buffer } from "./buffer-BEXn271X.js";
|
|
5
5
|
import { a as require_common, i as require_messages, n as require_inflate$1, o as require_zstream, r as require_deflate$1, t as require_constants } from "./constants-DsXVuJVP.js";
|
|
@@ -15198,14 +15198,25 @@ ${obj.gpgsig ? obj.gpgsig : ""}`;
|
|
|
15198
15198
|
var import_isomorphic_git = /* @__PURE__ */ __toESM(require_isomorphic_git(), 1);
|
|
15199
15199
|
var import_buffer = require_buffer();
|
|
15200
15200
|
if (!globalThis.Buffer) globalThis.Buffer = import_buffer.Buffer;
|
|
15201
|
+
function getGitTargetAddressSpace(url) {
|
|
15202
|
+
try {
|
|
15203
|
+
const locOrigin = typeof location !== "undefined" && location.origin ? location.origin : typeof globalThis !== "undefined" && globalThis.location?.origin ? globalThis.location.origin : "http://127.0.0.1:8888";
|
|
15204
|
+
const host = new URL(url, locOrigin).hostname.toLowerCase();
|
|
15205
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]") return "loopback";
|
|
15206
|
+
else if (/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(host) || !host.includes(".") || host.endsWith(".local") || host.endsWith(".lan") || host.endsWith(".home") || host.endsWith(".internal")) return "private";
|
|
15207
|
+
} catch (_) {}
|
|
15208
|
+
}
|
|
15201
15209
|
const httpClient = { async request({ url, method = "GET", headers = {}, body }) {
|
|
15202
15210
|
if (body) body = await collectBody(body);
|
|
15203
|
-
const
|
|
15211
|
+
const targetAddressSpace = getGitTargetAddressSpace(url);
|
|
15212
|
+
const fetchOptions = {
|
|
15204
15213
|
method,
|
|
15205
15214
|
headers,
|
|
15206
15215
|
body,
|
|
15207
15216
|
credentials: "omit"
|
|
15208
|
-
}
|
|
15217
|
+
};
|
|
15218
|
+
if (targetAddressSpace) fetchOptions.targetAddressSpace = targetAddressSpace;
|
|
15219
|
+
const res = await fetch(url, fetchOptions);
|
|
15209
15220
|
const iter = res.body && typeof res.body.getReader === "function" ? fromStream(res.body) : [new Uint8Array(await res.arrayBuffer())];
|
|
15210
15221
|
const responseHeaders = {};
|
|
15211
15222
|
for (const [key, value] of res.headers.entries()) responseHeaders[key] = value;
|
|
@@ -15503,12 +15514,18 @@ const DEFAULT_DEPTH = 20;
|
|
|
15503
15514
|
/**
|
|
15504
15515
|
* Get the CORS proxy URL based on preference.
|
|
15505
15516
|
*/
|
|
15506
|
-
function getProxyUrl(preference, customUrl) {
|
|
15517
|
+
function getProxyUrl(preference, customUrl, loc) {
|
|
15507
15518
|
if (preference === "custom" && customUrl) return customUrl;
|
|
15508
15519
|
if (preference === "public") return PUBLIC_CORS_PROXY;
|
|
15509
|
-
const
|
|
15510
|
-
|
|
15511
|
-
|
|
15520
|
+
const currentLoc = loc || (typeof globalThis !== "undefined" && globalThis.location ? globalThis.location : typeof self !== "undefined" && self.location ? self.location : typeof window !== "undefined" && window.location ? window.location : null);
|
|
15521
|
+
const rawProtocol = currentLoc?.protocol || "";
|
|
15522
|
+
const scheme = rawProtocol === "https:" || rawProtocol === "https" || typeof currentLoc?.origin === "string" && currentLoc.origin.startsWith("https:") || typeof currentLoc?.href === "string" && currentLoc.href.startsWith("https://") ? "https:" : "http:";
|
|
15523
|
+
const host = currentLoc?.host || "";
|
|
15524
|
+
const hostname = currentLoc?.hostname || "";
|
|
15525
|
+
const isLoopback = hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]" || hostname === "0.0.0.0" || host.startsWith("localhost:") || host.startsWith("127.0.0.1:") || host.startsWith("[::1]:");
|
|
15526
|
+
const isStaticHost = currentLoc && (currentLoc.protocol === "file:" || hostname && (hostname.endsWith(".github.io") || hostname.endsWith(".pages.dev")));
|
|
15527
|
+
if (host && (isLoopback || !isStaticHost)) return `${scheme}//${host}/git-proxy`;
|
|
15528
|
+
return `${scheme}//${DEFAULT_DEV_HOST}:${DEFAULT_DEV_PORT}/git-proxy`;
|
|
15512
15529
|
}
|
|
15513
15530
|
/**
|
|
15514
15531
|
* Lazily initialise the native OPFS filesystem adapter and isomorphic-git.
|
|
@@ -15525,7 +15542,7 @@ async function initGitFs() {
|
|
|
15525
15542
|
opfsRoot = await navigator.storage.getDirectory();
|
|
15526
15543
|
} catch (err) {
|
|
15527
15544
|
console.warn("OPFS is unavailable for git root, falling back to memory:", err);
|
|
15528
|
-
const { getMemoryOpfsRoot } = await import("./memoryStorage-
|
|
15545
|
+
const { getMemoryOpfsRoot } = await import("./memoryStorage-DcFWrn_y.js").then((n) => n.n);
|
|
15529
15546
|
opfsRoot = getMemoryOpfsRoot();
|
|
15530
15547
|
}
|
|
15531
15548
|
_fs = makeDirHandleFs(opfsRoot);
|
|
@@ -16440,5 +16457,5 @@ async function gitUnstage({ repo, filepath, groupRoot }) {
|
|
|
16440
16457
|
}
|
|
16441
16458
|
|
|
16442
16459
|
//#endregion
|
|
16443
|
-
export { buildAuthCallbacks, ensureCoreFilemodeFalse, ensureDir, getProxyUrl, getRemoteUrl, gitAdd, gitBranch, gitCheckout, gitClone, gitCommit, gitConfig, gitCurrentBranch, gitDeleteBranch, gitDeleteRepo, gitDiff, gitFetch, gitInit, gitListBranches, gitListRepos, gitListTags, gitLog, gitMerge, gitPull, gitPush, gitReadFileAtRef, gitRemote, gitReset, gitShow, gitStatus, gitTag, gitUnstage, initGitContext, initGitFs, makeDirHandleFs, makeOpfsFs, repoDir, repoNameFromUrl, rmdirRecursive };
|
|
16444
|
-
//# sourceMappingURL=git-
|
|
16460
|
+
export { buildAuthCallbacks, ensureCoreFilemodeFalse, ensureDir, getGitTargetAddressSpace, getProxyUrl, getRemoteUrl, gitAdd, gitBranch, gitCheckout, gitClone, gitCommit, gitConfig, gitCurrentBranch, gitDeleteBranch, gitDeleteRepo, gitDiff, gitFetch, gitInit, gitListBranches, gitListRepos, gitListTags, gitLog, gitMerge, gitPull, gitPush, gitReadFileAtRef, gitRemote, gitReset, gitShow, gitStatus, gitTag, gitUnstage, initGitContext, initGitFs, makeDirHandleFs, makeOpfsFs, repoDir, repoNameFromUrl, rmdirRecursive };
|
|
16461
|
+
//# sourceMappingURL=git-BppibnJW.js.map
|