shadow-claw 1.23.4 → 1.24.1
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/README.md +42 -5
- package/bin/cli.mjs +166 -0
- package/bin/cli.test.mjs +60 -0
- package/bin/commands/backup.mjs +70 -0
- package/bin/commands/clients.mjs +41 -0
- package/bin/commands/peer-id.mjs +76 -0
- package/bin/commands/peer-id.test.mjs +104 -0
- package/bin/commands/send.mjs +51 -0
- package/bin/commands/tasks.mjs +59 -0
- package/bin/commands/webrtc-listen.mjs +254 -0
- package/bin/prerender-dsd-shell/prerender-dsd-shell.test.mjs +46 -0
- package/bin/rolldown.config.test.mjs +401 -8
- package/bin/utils/control-client.mjs +243 -0
- package/bin/utils/control-client.test.mjs +83 -0
- package/bin/utils/ulid.mjs +45 -0
- package/bin/utils/webrtc-control-client.mjs +699 -0
- package/bin/utils/webrtc-control-client.test.mjs +318 -0
- package/dist/electron/main.cjs +1 -1
- package/dist/public/AGENTS.md +12 -3
- package/dist/public/README.md +42 -5
- package/dist/public/agent.worker.js +50 -50
- package/dist/public/backup-controller-CvzDOq4T.js +1 -0
- package/dist/public/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css +1 -0
- package/dist/public/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html +1 -0
- package/dist/public/components/settings/shadow-claw-task-server/shadow-claw-task-server.css +1 -1
- package/dist/public/components/settings/shadow-claw-task-server/shadow-claw-task-server.html +1 -1
- package/dist/public/components/shadow-claw-settings/shadow-claw-settings.html +1 -1
- package/dist/public/config-CrHchneq.js +1 -0
- package/dist/public/{configurePeerJs-B4Ym9VMj.js → configurePeerJs-UfQ6HUlv.js} +1 -1
- package/dist/public/{connections-BEn6JYdu.js → connections-DvbgdkaB.js} +1 -1
- package/dist/public/{custom-element-security-DdYlUozq.js → custom-element-security-NCqQ5lmC.js} +1 -1
- package/dist/public/docs/README.md +3 -1
- package/dist/public/docs/architecture/overview.md +12 -12
- package/dist/public/docs/decisions/bundled-typescript-architecture.md +1 -1
- package/dist/public/docs/decisions/indexeddb-and-opfs-storage.md +2 -2
- package/dist/public/docs/decisions/native-web-components-and-signals.md +1 -1
- package/dist/public/docs/example/article/index.html +1 -1
- package/dist/public/docs/guides/configuring-messaging-channels.md +41 -6
- package/dist/public/docs/guides/server-development-configuration.md +24 -0
- package/dist/public/docs/publishing/index.html +1 -1
- package/dist/public/docs/skill-creator/index.html +1 -1
- package/dist/public/docs/subsystems/backup.md +56 -0
- package/dist/public/docs/subsystems/cli.md +124 -0
- package/dist/public/docs/subsystems/control-plane.md +169 -0
- package/dist/public/docs/subsystems/notifications.md +54 -2
- package/dist/public/docs/subsystems/reactive-ui.md +1 -0
- package/dist/public/downloadGroupFile-9niHBj9n.js +1 -0
- package/dist/public/e2e/README.md +5 -1
- package/dist/public/{e2e-bridge-BQ4KzUt5.js → e2e-bridge-D28tOggc.js} +1 -1
- package/dist/public/file-viewer-BVg3B_JH.js +1 -0
- package/dist/public/getAllTasks-vpBlgGsc.js +1 -0
- package/dist/public/getGroupDir-P1h9wl6S.js +1 -0
- package/dist/public/{git-DEUvQTUA.js → git-7Vq_SJSp.js} +2 -2
- package/dist/public/{iframe-sanitizer-0NS4XLOd.js → iframe-sanitizer-y2Z1pPwY.js} +1 -1
- package/dist/public/index.html +1 -1
- package/dist/public/index.js +1 -1
- package/dist/public/{initChatSplitResize-llGkSJXg.js → initChatSplitResize-CzV2E7Ul.js} +1 -1
- package/dist/public/initControlPlane-DKNht5ph.js +1 -0
- package/dist/public/llms.txt +1 -1
- package/dist/public/main/index.html +1 -1
- package/dist/public/main/memory/index.html +1 -1
- package/dist/public/{markdown-CyYR4App.js → markdown-SiFq0PTy.js} +1 -1
- package/dist/public/{mcp-reconnect-CSx4aMwy.js → mcp-reconnect-9emsqGRe.js} +1 -1
- package/dist/public/{memoryStorage-Dwg8NhAZ.js → memoryStorage-C0KvLNUp.js} +1 -1
- package/dist/public/orchestrator-8w9-exfN.js +15 -0
- package/dist/public/{orchestrator-DRfEudXk.js → orchestrator-tHWrqi_F.js} +676 -676
- package/dist/public/{peerjs-CurBuKvk.js → peerjs-D8hck8Ih.js} +1 -1
- package/dist/public/push-client-D0lkwrK0.js +1 -0
- package/dist/public/service-worker/fetch-proxy.js +1 -1
- package/dist/public/service-worker/push-handler.js +1 -1
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-5IHaDDMJ.js → shadow-claw-Cs8wbk3d.js} +2 -2
- package/dist/public/{shadow-claw-accounts-CZvz4iQz.js → shadow-claw-accounts-B4sBTQEj.js} +1 -1
- package/dist/public/{shadow-claw-channels-BKXFyRS3.js → shadow-claw-channels-mY-JMvib.js} +1 -1
- package/dist/public/{shadow-claw-chat-CCLuhWdI.js → shadow-claw-chat-DGPKpmU5.js} +6 -6
- package/dist/public/shadow-claw-control-plane-B1F0jnPk.js +199 -0
- package/dist/public/{shadow-claw-conversations-DV-87UUh.js → shadow-claw-conversations-0Q-VC_7N.js} +1 -1
- package/dist/public/shadow-claw-dialog-BrOwAOdk.js +1 -0
- package/dist/public/{shadow-claw-file-viewer-Dk2dbAUd.js → shadow-claw-file-viewer-AZfG4D-u.js} +1 -1
- package/dist/public/shadow-claw-files-Bx4v0Ggp.js +840 -0
- package/dist/public/{shadow-claw-git-DRA7_qck.js → shadow-claw-git-DD7iQRxq.js} +2 -2
- package/dist/public/{shadow-claw-integrations-1Xu5snuV.js → shadow-claw-integrations-D7ufpwhX.js} +1 -1
- package/dist/public/{shadow-claw-llm-6Aci1BDP.js → shadow-claw-llm-CfeDBZKB.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-BUjAeVXC.js → shadow-claw-mcp-remote-kY4LMFNN.js} +1 -1
- package/dist/public/{shadow-claw-networking-FQe4nCp3.js → shadow-claw-networking-e0EarDVs.js} +1 -1
- package/dist/public/{shadow-claw-notifications-DV2wibL3.js → shadow-claw-notifications-BkxuDEQI.js} +3 -3
- package/dist/public/{shadow-claw-page-header-B63S4HTU.js → shadow-claw-page-header-DMKbkv3s.js} +1 -1
- package/dist/public/{shadow-claw-pages-DE3jWj5K.js → shadow-claw-pages-BWSE91I1.js} +1 -1
- package/dist/public/{shadow-claw-settings-S6DAKfYx.js → shadow-claw-settings-D6lPBn6m.js} +10 -3
- package/dist/public/{shadow-claw-storage-DaacA3_K.js → shadow-claw-storage-Crs6LY15.js} +2 -2
- package/dist/public/{shadow-claw-task-server-IjKX042p.js → shadow-claw-task-server-CKm_Ennl.js} +25 -4
- package/dist/public/{shadow-claw-tasks-Cy0JYmGU.js → shadow-claw-tasks-Czx6Ucf5.js} +1 -1
- package/dist/public/{shadow-claw-terminal-znAt7HyP.js → shadow-claw-terminal-Dmtr9KY1.js} +1 -1
- package/dist/public/{shadow-claw-tools-Cutv9Si5.js → shadow-claw-tools-t3Qq4TDO.js} +1 -1
- package/dist/public/{shadow-claw-webvm-BH8mPDEu.js → shadow-claw-webvm-CIuSywD_.js} +1 -1
- package/dist/public/{syncWebMcpRegistration-BqJxaMGR.js → syncWebMcpRegistration-DzC80wVG.js} +1 -1
- package/dist/server.js +286 -189
- package/package.json +2 -1
- package/src/__mocks__/jszip.cjs +15 -5
- package/src/components/settings/shadow-claw-accounts/shadow-claw-accounts.test.ts +35 -0
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.css +117 -0
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.html +81 -0
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.test.ts +127 -0
- package/src/components/settings/shadow-claw-control-plane/shadow-claw-control-plane.ts +292 -0
- package/src/components/settings/shadow-claw-git/shadow-claw-git.test.ts +72 -0
- package/src/components/settings/shadow-claw-integrations/connection-test-auth.test.ts +20 -30
- package/src/components/settings/shadow-claw-integrations/shadow-claw-integrations.test.ts +116 -0
- package/src/components/settings/shadow-claw-llm/model-ranking.test.ts +143 -51
- package/src/components/settings/shadow-claw-llm/shadow-claw-llm.test.ts +307 -4
- package/src/components/settings/shadow-claw-llm/shadow-claw-llm.ts +8 -8
- package/src/components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.test.ts +31 -0
- package/src/components/settings/shadow-claw-notifications/shadow-claw-notifications.test.ts +3 -0
- package/src/components/settings/shadow-claw-notifications/shadow-claw-notifications.ts +43 -9
- package/src/components/settings/shadow-claw-peerjs/shadow-claw-peerjs.test.ts +186 -0
- package/src/components/settings/shadow-claw-storage/shadow-claw-storage.test.ts +76 -0
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.css +23 -2
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.html +1 -1
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.test.ts +19 -0
- package/src/components/settings/shadow-claw-task-server/shadow-claw-task-server.ts +2 -1
- package/src/components/shadow-claw/utils/initChatSplitResize.test.ts +180 -13
- package/src/components/shadow-claw/utils/setupEffects.test.ts +39 -0
- package/src/components/shadow-claw-a2ui/catalog/basic/shared.test.ts +117 -0
- package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.test.ts +1159 -1
- package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +1523 -19
- package/src/components/shadow-claw-chat/utils/escapeHtml.test.ts +13 -0
- package/src/components/shadow-claw-chat/utils/getPeerChatDisplayStatus.test.ts +20 -0
- package/src/components/shadow-claw-conversations/shadow-claw-conversations.test.ts +494 -0
- package/src/components/shadow-claw-dialog/shadow-claw-dialog.ts +13 -2
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +273 -0
- package/src/components/shadow-claw-files/shadow-claw-files.test.ts +408 -1
- package/src/components/shadow-claw-pdf-viewer/utils/installGetOrInsertComputedPolyfill.test.ts +65 -0
- package/src/components/shadow-claw-settings/shadow-claw-settings.html +7 -0
- package/src/components/shadow-claw-settings/shadow-claw-settings.test.ts +221 -0
- package/src/components/shadow-claw-settings/shadow-claw-settings.ts +2 -0
- package/src/components/shadow-claw-tasks/shadow-claw-tasks.test.ts +407 -0
- package/src/components/shadow-claw-terminal/utils/consumeEscapeSequence.test.ts +58 -0
- package/src/components/shadow-claw-tools/shadow-claw-tools.test.ts +80 -0
- package/src/config/config.ts +10 -0
- package/src/core/backup-controller.test.ts +101 -0
- package/src/core/backup-controller.ts +166 -0
- package/src/core/control-plane-client.test.ts +415 -0
- package/src/core/control-plane-client.ts +441 -0
- package/src/core/orchestrator/orchestrator.ts +4 -0
- package/src/core/orchestrator/utils/compactContext.test.ts +78 -0
- package/src/core/orchestrator/utils/operations/channel.test.ts +254 -9
- package/src/core/orchestrator/utils/operations/provider.test.ts +326 -34
- package/src/core/orchestrator/utils/operations/task.ts +46 -15
- package/src/core/orchestrator/utils/operations/vm.test.ts +114 -2
- package/src/core/orchestrator/utils/syncProxyConfigToServiceWorker.test.ts +60 -0
- package/src/core/utils/initControlPlane.test.ts +276 -0
- package/src/core/utils/initControlPlane.ts +437 -0
- package/src/core/utils/initializeApp.ts +18 -0
- package/src/db/getSession.test.ts +13 -1
- package/src/server/app.test.ts +12 -0
- package/src/server/app.ts +20 -8
- package/src/server/client-registry.test.ts +250 -0
- package/src/server/client-registry.ts +477 -0
- package/src/server/config.ts +15 -0
- package/src/server/control-plane-types.ts +120 -0
- package/src/server/control-plane.test.ts +508 -0
- package/src/server/control-plane.ts +607 -0
- package/src/server/middleware/pna.test.ts +15 -3
- package/src/server/middleware/pna.ts +6 -2
- package/src/server/routes/backup.test.ts +277 -0
- package/src/server/routes/backup.ts +291 -0
- package/src/server/routes/integrations-email.test.ts +532 -0
- package/src/server/routes/llamafile.test.ts +172 -48
- package/src/server/routes/mesh-llm.test.ts +192 -0
- package/src/server/routes/ollama.test.ts +49 -0
- package/src/server/server-peer.test.ts +86 -0
- package/src/server/server-peer.ts +330 -0
- package/src/server/server.ts +37 -0
- package/src/server/services/llamafile-manager.test.ts +230 -6
- package/src/server/services/transformers-runtime.test.ts +186 -18
- package/src/server/webrtc.test.ts +21 -0
- package/src/server/webrtc.ts +72 -0
- package/src/service-worker/fetch-proxy-rules.test.ts +41 -0
- package/src/service-worker/fetch-proxy-rules.ts +15 -8
- package/src/service-worker/fetch-proxy.test.ts +64 -1
- package/src/service-worker/fetch-proxy.ts +18 -2
- package/src/service-worker/push-handler.ts +39 -0
- package/src/shell/vm.test.ts +744 -12
- package/src/storage/ensureMainGroupIndex.test.ts +153 -0
- package/src/storage/getGroupFile.test.ts +66 -0
- package/src/storage/memoryStorage.test.ts +82 -2
- package/src/storage/writeGroupFileBytes.test.ts +143 -0
- package/src/stores/chat-ui.test.ts +20 -0
- package/src/stores/orchestrator.test.ts +134 -0
- package/src/stores/toast.test.ts +50 -0
- package/src/stores/tools.test.ts +147 -10
- package/src/subsystems/channels/imessage.test.ts +59 -0
- package/src/subsystems/channels/peerjs.test.ts +500 -62
- package/src/subsystems/channels/peerjs.ts +71 -4
- package/src/subsystems/channels/telegram.test.ts +177 -0
- package/src/subsystems/email/catalog.test.ts +1 -0
- package/src/subsystems/email/connections.test.ts +39 -1
- package/src/subsystems/git/credentials.test.ts +160 -825
- package/src/subsystems/git/git.test.ts +463 -0
- package/src/subsystems/notifications/__mocks__/node-sqlite.cjs +12 -1
- package/src/subsystems/notifications/push-client.test.ts +5 -1
- package/src/subsystems/notifications/push-client.ts +50 -12
- package/src/subsystems/notifications/push-routes.test.ts +33 -0
- package/src/subsystems/notifications/push-routes.ts +23 -0
- package/src/subsystems/notifications/push-store.ts +1 -1
- package/src/subsystems/providers/builtin-ai-tasks.test.ts +74 -0
- package/src/subsystems/providers/litert-lm-provider.test.ts +212 -51
- package/src/subsystems/providers/model-registry.test.ts +115 -0
- package/src/subsystems/providers/providers.test.ts +94 -1
- package/src/subsystems/providers/transformers-js-provider.test.ts +279 -0
- package/src/subsystems/providers/utils/createModelCacheFetch.test.ts +2 -2
- package/src/subsystems/providers/utils/downloadModelToCache.test.ts +2 -2
- package/src/subsystems/providers/utils/loadModelStream.test.ts +2 -2
- package/src/subsystems/skills/activateSkill.test.ts +101 -0
- package/src/subsystems/skills/discoverSkills.test.ts +251 -0
- package/src/subsystems/tools/cron.test.ts +64 -0
- package/src/subsystems/tools/declarative.test.ts +255 -89
- package/src/testing/assets/v86.9pfs/libv86.mjs +63 -0
- package/src/testing/assets/v86.ext2/libv86.mjs +3 -0
- package/src/testing/assets_missing_v86/assets/v86.9pfs/libv86.mjs +1 -0
- package/src/testing/jest-setup.ts +328 -40
- package/src/testing/mock-v86.mjs +49 -0
- package/src/ui/a2ui/types.ts +4 -3
- package/src/ui/a2ui/utils/normaliseComponentsToMap.test.ts +102 -0
- package/src/ui/a2ui/utils/resolveChildIds.test.ts +63 -0
- package/src/ui/a2ui/utils/resolveDynamicNumber.test.ts +13 -1
- package/src/worker/tools/bash/utils/waitForVMReady.test.ts +40 -0
- package/src/worker/tools/email/email.test.ts +193 -8
- package/src/worker/tools/email/utils/asEmailAttachmentInputs.test.ts +47 -0
- package/src/worker/tools/git/git.test.ts +214 -3
- package/src/worker/tools/rooms/invite-to-room.test.ts +54 -0
- package/src/worker/tools/rooms/leave-room.test.ts +40 -0
- package/src/worker/tools/rooms/list-room-members.test.ts +75 -0
- package/src/worker/tools/tasks/tasks-utils.test.ts +22 -0
- package/src/worker/tools/ui/ask-user.test.ts +50 -0
- package/src/worker/tools/ui/clear-chat.test.ts +19 -0
- package/src/worker/tools/ui/get-current-time.test.ts +19 -0
- package/src/worker/tools/ui/javascript.test.ts +116 -0
- package/src/worker/tools/ui/list-components.test.ts +10 -0
- package/src/worker/tools/ui/list-tool-profiles.test.ts +42 -0
- package/src/worker/tools/ui/manage-tools.test.ts +34 -0
- package/src/worker/tools/ui/render-component.test.ts +346 -0
- package/src/worker/tools/ui/send-notification.test.ts +40 -0
- package/src/worker/tools/ui/utils/getAllowFullInternetAccess.test.ts +31 -0
- package/src/worker/tools/ui/utils/parseBooleanConfig.test.ts +25 -0
- package/src/worker/tools/workspace/attach-file.test.ts +84 -0
- package/src/worker/tools/workspace/copy-file.test.ts +69 -0
- package/src/worker/tools/workspace/create-directory.test.ts +40 -0
- package/src/worker/tools/workspace/delete-file.test.ts +73 -0
- package/src/worker/tools/workspace/diff-files.test.ts +94 -0
- package/src/worker/tools/workspace/list-files.test.ts +36 -0
- package/src/worker/tools/workspace/move-file.test.ts +66 -0
- package/src/worker/tools/workspace/open-file.test.ts +57 -0
- package/src/worker/tools/workspace/patch-file.test.ts +81 -0
- package/src/worker/tools/workspace/read-file.test.ts +116 -0
- package/src/worker/tools/workspace/send-file.test.ts +82 -0
- package/src/worker/tools/workspace/update-memory.test.ts +29 -0
- package/src/worker/tools/workspace/write-file.test.ts +28 -0
- package/src/worker/utils/rate-limit.test.ts +199 -0
- package/src/worker/utils/tool-state.test.ts +29 -0
- package/src/worker/utils/transformers-js-utils.test.ts +59 -0
- package/dist/public/config-BYAuxx3j.js +0 -1
- package/dist/public/downloadGroupFile-Drdvg1Ev.js +0 -1
- package/dist/public/file-viewer-CcZYw-PS.js +0 -1
- package/dist/public/orchestrator-o9Fj67BN.js +0 -15
- package/dist/public/push-client-Dii-vPEh.js +0 -1
- package/dist/public/shadow-claw-dialog-ByyHgxM9.js +0 -1
- package/dist/public/shadow-claw-files-BpfpJIuP.js +0 -840
|
@@ -1 +1 @@
|
|
|
1
|
-
import{L as e,N as t,b as n,h as r,r as i}from"./config-BYAuxx3j.js";import{t as a}from"./getConfig-D89uJgo5.js";import{t as o}from"./setConfig-DFMYnYLE.js";import{t as s}from"./ulid-BY7rQVLN.js";import{n as c,r as l}from"./crypto-C8c5wMzN.js";function u(e){return!e||e.authMode===`token`||e.authMode===`pat`?`token`:e.authMode===`basic`?`basic`:e.authMode===`oauth`||e.oauthProviderId||e.oauthClientId||e.oauthClientSecret||e.refreshToken||e.accessTokenExpiresAt||e.tokenType||e.oauthReauthRequired?`oauth`:`token`}function d(e){return u(e)}function f(e,t){return d(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function p(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let r=await c(n.refreshToken);if(!r)return n;let a=n.oauthClientSecret?await c(n.oauthClientSecret):void 0,s=async r=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=r,await o(e,i.SERVICE_ACCOUNTS,t))},u=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({providerId:n.oauthProviderId,clientId:n.oauthClientId,clientSecret:a,refreshToken:r,scope:n.scopes,tokenUrl:n.oauthCustomTokenUrl})});if(!e.ok)return u();let t=await e.json();if(!t.accessToken)return u();let i=await l(t.accessToken);if(!i)return u();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let c={...n,token:i,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(c),c}catch{return u()}}function m(e,n){if(e.oauthProviderId){let n=t(e.oauthProviderId);if(n)return n}let i=[e.service,e.hostPattern,n].filter(e=>!!e).map(e=>e.toLowerCase());for(let e of Object.values(r))if([e.providerId,...e.aliases||[]].map(e=>e.toLowerCase()).some(e=>i.some(t=>t.includes(e))))return e;return null}function h(e,t){let n=d(e),r=m(e,t);if(r){let e;return e=n===`oauth`?r.tokenAuth.oauth:n===`basic`&&r.tokenAuth.basic?r.tokenAuth.basic:r.tokenAuth.token,{headerName:e.headerName,headerPrefix:e.headerPrefix||``}}return{headerName:`Authorization`,headerPrefix:n===`basic`?`Basic `:`Bearer `}}function g(e,t){let n=[],r=-1,i=t.toLowerCase();for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();i.includes(e)&&(e.length>r?(r=e.length,n.length=0,n.push(t)):e.length===r&&n.push(t))}return n}function _(e,t){return e.length?t&&e.find(e=>d(e)===t)||e[0]:void 0}async function v(e,t,n={}){let r=await a(e,i.SERVICE_ACCOUNTS),o=Array.isArray(r)?r:[];if(o.length===0)return;let s;if(n.accountId&&(s=o.find(e=>e.id===n.accountId)),!s&&t){let e=g(o,t);s=n.authMode?_(e,n.authMode):_(e,e[0]?m(e[0],t)?.defaultMode:void 0)}if(!s){let t=await a(e,i.SERVICE_DEFAULT_ACCOUNT);t&&(s=o.find(e=>e.id===t))}if(!s&&n.authMode&&(s=_(o,n.authMode)),s||=o[0],!s)return;if(f(s,n)&&(s=await p(e,o,s)),d(s)===`oauth`&&s.oauthReauthRequired)return{token:``,service:s.service,hostPattern:s.hostPattern,headerName:`Authorization`,headerValue:``,accountId:s.id,authMode:`oauth`,reauthRequired:!0};let l=``;s.token&&(l=await c(s.token)??``);let{headerName:u,headerPrefix:v}=h(s,t),y=l;d(s)===`basic`&&s.basicUsername&&(y=btoa(`${s.basicUsername}:${l}`));let b=v?`${v}${y}`:y;return{token:l,service:s.service,hostPattern:s.hostPattern,headerName:u,headerValue:b,accountId:s.id,authMode:d(s)}}function y(e){return u(e)}function b(e){switch(e){case`azure-devops`:return`azure_devops`;default:return e}}function x(e){if(!e)return`generic`;let t=e.toLowerCase();return t.includes(`github`)?`github`:t.includes(`dev.azure.com`)||t.includes(`visualstudio.com`)?`azure-devops`:t.includes(`gitlab`)?`gitlab`:`generic`}function S(t){if(t.reauthRequired)return{};let n=t.provider||x(t.hostPattern||``),r=b(n),i=t.authMode||`token`;if(t.token&&r===`azure_devops`&&e(r,i,`git_remote`)?.headerPrefix===`Basic `)return{Authorization:`Basic ${btoa(`:`+t.token)}`};switch(n){case`azure-devops`:if(t.username&&t.password)return{Authorization:`Basic ${btoa(t.username+`:`+t.password)}`};break;default:break}if(t.token){let n=e(r,i,`git_remote`);return n?.headerName?{[n.headerName]:`${n.headerPrefix||``}${t.token}`}:{Authorization:`Bearer ${t.token}`}}return{}}function C(e){try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n?t.hostname+n:t.hostname}catch{return}}function w(e,t){let n=t.toLowerCase(),r=[],i=-1;for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();n.includes(e)&&(e.length>i?(i=e.length,r.length=0,r.push(t)):e.length===i&&r.push(t))}return r}function T(e,t){if(!e.length)return;if(!t)return e[0];let n=e.find(e=>y(e)===t);if(n)return n;if(t===`token`){let t=e.find(e=>y(e)===`token`&&!e.authMode);if(t)return t}return e[0]}async function E(e){if(e)return await c(e)??void 0}function D(e,t){return y(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function O(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let r=await E(n.refreshToken);if(!r)return n;let a=n.oauthClientSecret?await E(n.oauthClientSecret):void 0,s=async r=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=r,await o(e,i.GIT_ACCOUNTS,t))},c=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:n.oauthClientId,clientSecret:a,providerId:n.oauthProviderId,refreshToken:r,scope:n.scopes}),headers:{"content-type":`application/json`},method:`POST`});if(!e.ok)return c();let t=await e.json();if(!t.accessToken)return c();let i=await l(t.accessToken);if(!i)return c();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let u={...n,token:i,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(u),u}catch{return c()}}async function k(e,t,n={}){let r=await a(e,i.GIT_ACCOUNTS);return Array.isArray(r)&&r.length>0?ee(e,r,t,n):A(e)}async function ee(e,t,n,r={}){let o;if(r.accountId&&(o=t.find(e=>e.id===r.accountId)),!o&&n){let e=C(n);e&&(o=T(w(t,e),r.authMode))}if(!o){let r=await a(e,i.GIT_DEFAULT_ACCOUNT);if(r){let e=t.find(e=>e.id===r);if(e)if(!n)o=e;else{let t=C(n);if(t&&e.hostPattern){let n=t?.toLowerCase(),r=e.hostPattern.toLowerCase();n?.includes(r)&&(o=e)}}}}if(!o&&!n&&r.authMode&&(o=T(t,r.authMode)),!o&&!n&&(o=t[0]),!o)return{authMode:`token`,authorEmail:void 0,authorName:void 0,password:void 0,provider:`generic`,token:void 0,username:void 0};D(o,r)&&(o=await O(e,t,o));let s=o.provider||x(o.hostPattern||``);return y(o)===`oauth`&&o.oauthReauthRequired?{accountId:o.id,authMode:`oauth`,authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:void 0,provider:s,reauthRequired:!0,token:void 0,username:o.username||void 0}:{accountId:o.id,authMode:y(o),authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:await E(o.password),provider:s,token:await E(o.token),username:o.username||void 0}}async function A(e){let t=await a(e,i.GIT_TOKEN),n=await a(e,i.GIT_PASSWORD);return{authMode:`token`,authorEmail:await a(e,i.GIT_AUTHOR_EMAIL)||void 0,authorName:await a(e,i.GIT_AUTHOR_NAME)||void 0,password:n?await E(n):void 0,provider:`generic`,token:t?await E(t):void 0,username:await a(e,i.GIT_USERNAME)||void 0}}function j(e){if(typeof e!=`string`||!e.trim())return!1;try{let t=new URL(e);return t.protocol===`https:`||t.protocol===`http:`}catch{return!1}}function M(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(!n.serviceType||!n.authType)return null;if(n.serviceType!==t)throw Error(`Credential ref serviceType must match connection serviceType`);return{serviceType:n.serviceType,authType:n.authType,providerId:n.providerId||void 0,accountId:n.accountId||void 0,gitAccountId:n.gitAccountId||void 0,headerName:n.headerName||void 0,encryptedValue:n.encryptedValue||void 0}}function N(e){if(!e||typeof e!=`object`)return null;let t=e;return!t.id||!t.label||!t.serviceType||!t.transport||typeof t.enabled!=`boolean`||typeof t.createdAt!=`number`||typeof t.updatedAt!=`number`||!j(t.serverUrl)||t.serviceType!==`mcp_remote`&&t.serviceType!==`webmcp_local`||t.transport!==`streamable_http`&&t.transport!==`sse`&&t.transport!==`websocket`?null:{id:t.id,label:t.label,serviceType:t.serviceType,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled,autoReconnectOAuth:t.autoReconnectOAuth===!0,createdAt:t.createdAt,updatedAt:t.updatedAt,credentialRef:M(t.credentialRef,t.serviceType)}}async function P(e){let t=await a(e,i.REMOTE_MCP_CONNECTIONS);if(!Array.isArray(t))return[];let n=[];for(let e of t){let t=N(e);t&&n.push(t)}return n}async function F(e,t){await o(e,i.REMOTE_MCP_CONNECTIONS,t)}async function te(e){return P(e)}async function I(e,t){if(!t)return null;let n=await P(e);return n.find(e=>e.id===t)||n.find(e=>e.label.toLowerCase()===t.toLowerCase())||null}async function ne(e,t){if(!t?.label?.trim())throw Error(`Connection label is required`);if(!j(t.serverUrl))throw Error(`Connection serverUrl must be an absolute http(s) URL`);let n=t.serviceType||`mcp_remote`;if(n!==`mcp_remote`&&n!==`webmcp_local`)throw Error(`Unsupported serviceType for remote MCP connection`);let r=await P(e),i=Date.now();if(t.id){let a=r.findIndex(e=>e.id===t.id);if(a!==-1){let o=r[a],s={...o,label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??o.enabled,autoReconnectOAuth:t.autoReconnectOAuth??o.autoReconnectOAuth,updatedAt:i};return r[a]=s,await F(e,r),s}}let a={id:t.id||s(),label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??!0,autoReconnectOAuth:t.autoReconnectOAuth??!1,createdAt:i,updatedAt:i,credentialRef:null};return r.push(a),await F(e,r),a}async function re(e,t,n){if(!t)return null;let r=await P(e),i=r.findIndex(e=>e.id===t);if(i===-1)return null;let a=r[i],o=n?M(n,a.serviceType):null,s={...a,credentialRef:o,updatedAt:Date.now()};return r[i]=s,await F(e,r),s}async function L(e,t){if(!t)return!1;let n=await P(e),r=n.filter(e=>e.id!==t);return r.length===n.length?!1:(await F(e,r),!0)}function R(e){return e===`oauth`?`oauth`:`token`}async function z(e,t,n={}){let r=await I(e,t);if(!r)return null;let i=r.credentialRef;if(!i||i.authType===`none`)return{connection:r,authType:`none`,headers:{}};if(i.authType===`custom_header`){if(!i.headerName||!i.encryptedValue)return{connection:r,authType:`custom_header`,headers:{}};let e=await c(i.encryptedValue);return{connection:r,authType:`custom_header`,headers:e?{[i.headerName]:e}:{}}}let a=R(i.authType);if(i.accountId){let t=await v(e,r.serverUrl,{accountId:i.accountId,authMode:a,forceRefresh:n.forceRefresh});return t?t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:t.headerValue?{[t.headerName]:t.headerValue}:{}}:{connection:r,authType:i.authType,headers:{}}}if(i.gitAccountId){let t=await k(e,r.serverUrl,{accountId:i.gitAccountId,authMode:a,forceRefresh:n.forceRefresh});return t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:S(t)}}return{connection:r,authType:i.authType,headers:{}}}const B=new Map;function V(e){return typeof e==`object`&&!!e&&`method`in e&&`id`in e&&!(`result`in e)&&!(`error`in e)}function H(e){let t=(e.requestedSchema||{}).properties||{},n={};for(let[e,r]of Object.entries(t))`default`in r?n[e]=r.default:r.type===`boolean`&&(n[e]=!0);return n}var U=class extends Error{constructor(e){super(e),this.name=`InvalidRemoteMcpSessionError`}},W=class extends Error{status;constructor(e,t){super(t),this.name=`HttpRemoteMcpError`,this.status=e}},G=class extends Error{connectionId;constructor(e){super(`OAuth reconnect required for remote MCP connection`),this.name=`McpReauthRequiredError`,this.connectionId=e}};function K(e,t){return!e.headers||typeof e.headers.get!=`function`?null:e.headers.get(t)}function ie(e){return/no valid session id provided/i.test(e)}function q(e,t){let n=t&&`error`in t?t.error.message||`Remote MCP JSON-RPC error`:``;return ie(n)?new U(n):e.ok?Error(n||`Remote MCP JSON-RPC error`):new W(e.status,n?`Remote MCP HTTP error: ${e.status} (${n})`:`Remote MCP HTTP error: ${e.status}`)}function ae(e){if(!e)return null;let t=null,n=e.split(/\r?\n/);for(let e of n){let n=e.trim();if(!n.startsWith(`data:`))continue;let r=n.slice(5).trim();if(!(!r||r===`[DONE]`))try{let e=JSON.parse(r);e&&typeof e==`object`&&`jsonrpc`in e&&(t=e)}catch{}}return t}function oe(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function J(e,t,n){let r=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`,accept:`application/json, text/event-stream`,...t},body:JSON.stringify(n)}),i=(K(r,`content-type`)||``).toLowerCase(),a=null;if(typeof r.text==`function`){let e=await r.text();a=i.includes(`text/event-stream`)?ae(e):oe(e)}else try{a=await r.json()}catch{a=null}return{response:r,payload:a}}async function se(e,t,n){let{response:r,payload:i}=await J(e,{...t,"mcp-session-id":n},{jsonrpc:`2.0`,method:`notifications/initialized`,params:{}});if(!r.ok||i&&`error`in i)throw q(r,i)}async function Y(e,t,n){let r=B.get(e);if(r?.sessionId)return r;let{response:i,payload:a}=await J(t,n,{jsonrpc:`2.0`,id:`initialize-${Date.now().toString(36)}`,method:`initialize`,params:{protocolVersion:`2025-03-26`,capabilities:{elicitation:{}},clientInfo:{name:`shadowclaw-remote-mcp-client`,version:`1.0.0`}}});if(!i.ok||a&&`error`in a)throw q(i,a);let o=K(i,`mcp-session-id`)||`local-${Date.now()}-${Math.random().toString(36).slice(2)}`,s={sessionId:o,protocolVersion:K(i,`mcp-protocol-version`)||a?.result?.protocolVersion,lastUsedAt:Date.now()};return await se(t,n,o),B.set(e,s),s}async function X(e,t,n,r,i){let a=await Y(e,t,n),o=async e=>{let a={jsonrpc:`2.0`,id:Date.now().toString(),method:r,params:i||{}},o={...n,"mcp-session-id":e},{response:s,payload:c}=await J(t,o,a),l=0;for(;V(c)&&l<5&&(l++,c.method===`elicitation/create`);){let e=H(c.params||{});({response:s,payload:c}=await J(t,o,{jsonrpc:`2.0`,id:c.id,result:{action:`accept`,content:e}}))}if(V(c))throw Error(`Unsupported server request: ${c.method}`);if(!s.ok||!c||`error`in c)throw q(s,c);return c.result};try{let t=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),t}catch(r){if(!(r instanceof U))throw r;B.delete(e),a=await Y(e,t,n);let i=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),i}}function Z(e){e&&B.delete(e)}async function Q(e,t,n,r){let i=await z(e,t);if(!i)throw Error(`Remote MCP connection not found`);if(i.reauthRequired)throw new G(t);let{connection:a,authType:o,headers:s}=i;if(a.transport!==`streamable_http`)throw Error(`Unsupported remote MCP transport`);try{return await X(t,a.serverUrl,s,n,r)}catch(i){if(!(i instanceof W)||i.status!==401||o!==`oauth`)throw i;Z(t);let a=await z(e,t,{forceRefresh:!0});if(!a||a.reauthRequired)throw new G(t);try{return await X(t,a.connection.serverUrl,a.headers,n,r)}catch(e){throw e instanceof W&&e.status===401?new G(t):e}}}async function ce(e,t){let n=await Q(e,t,`tools/list`);return Array.isArray(n.tools)?n.tools:[]}async function le(e,t,n,r={}){return Q(e,t,`tools/call`,{name:n,arguments:r})}async function ue(e,t){let n=[],r;try{r=await z(e,t)}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Resolve authentication`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}if(!r)return n.push({step:`Resolve authentication`,status:`error`,detail:`Connection not found`}),{success:!1,error:`Connection not found`,toolCount:0,toolNames:[],steps:n};if(r.reauthRequired){let e=`OAuth token expired or revoked — re-authenticate in Settings`;return n.push({step:`Resolve authentication`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}n.push({step:`Resolve authentication`,status:`ok`,detail:`Auth type: ${r.authType}`});let{connection:i,authType:a,headers:o}=r;if(i.transport!==`streamable_http`){let e=`Unsupported transport: ${i.transport}`;return n.push({step:`Establish MCP session`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}Z(t);try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(r){let s=r instanceof Error?r.message:String(r);if(n.push({step:`Establish MCP session`,status:`error`,detail:s}),r instanceof W&&r.status===401&&a===`oauth`){Z(t);let r=await z(e,t,{forceRefresh:!0});if(r&&!r.reauthRequired){n.push({step:`Refresh OAuth token`,status:`ok`,detail:`Token refreshed, retrying`}),i=r.connection,o=r.headers;try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(e){let t=e instanceof Error?e.message:String(e),r=e instanceof W&&e.status===401?`${t} — re-authorize in Settings → Accounts`:t;return n.push({step:`Establish MCP session`,status:`error`,detail:r}),{success:!1,error:r,toolCount:0,toolNames:[],steps:n}}}else return n.push({step:`Refresh OAuth token`,status:`error`,detail:`Token refresh failed — re-authenticate in Settings`}),{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}else return{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}try{let e=await X(t,i.serverUrl,o,`tools/list`),r=Array.isArray(e.tools)?e.tools:[],a=r.map(e=>e.name);return n.push({step:`Discover tools`,status:`ok`,detail:`${r.length} tool${r.length===1?``:`s`} available`}),{success:!0,error:null,toolCount:r.length,toolNames:a,steps:n}}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Discover tools`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}}function $(e,t,n,r){return{accessTokenExpiresAt:e.expiresIn?Date.now()+e.expiresIn*1e3:t.accessTokenExpiresAt,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0,oauthRefreshFailureCount:0,refreshToken:r,scopes:e.scope?e.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):t.scopes,token:n,tokenType:e.tokenType||t.tokenType}}async function de(e,t,n,r,a,s,u){if(!t.refreshToken)return{success:!1,error:`No refresh token available.`};let d=await c(t.refreshToken);if(!d)return{success:!1,error:`Failed to decrypt refresh token.`};let f=t.oauthClientSecret?await c(t.oauthClientSecret):void 0;try{let c=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:t.oauthClientId,clientSecret:f||void 0,providerId:t.oauthProviderId,refreshToken:d,scope:t.scopes,tokenUrl:t.oauthCustomTokenUrl}),headers:{"content-type":`application/json`},method:`POST`});if(!c.ok)return{success:!1,error:`Token refresh request failed.`};let p=await c.json();if(!p.accessToken)return{success:!1,error:`No access token in refresh response.`};let m=await l(p.accessToken);if(!m)return{success:!1,error:`Failed to encrypt access token.`};let h=t.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(h=e)}let g=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},t,m,h);if(n===`service`&&s.accountId){let t=r.findIndex(e=>e.id===s.accountId);t!==-1&&(Object.assign(r[t],g),await o(e,i.SERVICE_ACCOUNTS,r))}else if(n===`git`&&s.gitAccountId){let t=a.findIndex(e=>e.id===s.gitAccountId);t!==-1&&(Object.assign(a[t],g),await o(e,i.GIT_ACCOUNTS,a))}return Z(u),{success:!0}}catch(e){return{success:!1,error:`Silent refresh failed: ${e instanceof Error?e.message:String(e)}`}}}async function fe(e,t,r={}){let s=await I(e,t);if(!s?.credentialRef)return{success:!1,error:`Connection not found.`};let u=s.credentialRef;if(u.authType!==`oauth`)return{success:!1,error:`This connection does not use OAuth authentication.`};let d=await a(e,i.SERVICE_ACCOUNTS),f=Array.isArray(d)?d:[],p=await a(e,i.GIT_ACCOUNTS),m=Array.isArray(p)?p:[],h,g=null;if(u.accountId?(h=f.find(e=>e.id===u.accountId),g=`service`):u.gitAccountId&&(h=m.find(e=>e.id===u.gitAccountId),g=`git`),!h||!g)return{error:`Linked account not found. Edit the connection to re-configure authentication.`,success:!1};let _=h.oauthClientId,v=h.oauthProviderId;if(!v||!_)return{error:`Account is missing OAuth provider or client ID. Edit the account in Settings → Accounts to fix.`,success:!1};if(h.refreshToken){let n=await de(e,h,g,f,m,u,t);if(n.success)return n}if(r.silentOnly)return{error:`Silent token refresh failed. Use Settings → Remote MCP → Reconnect OAuth for full re-authorization.`,success:!1};let y=h.oauthClientSecret?await c(h.oauthClientSecret):void 0,b=h.scopes,x=n[v],S=v===`custom_mcp`,C=S&&h.oauthCustomRedirectUri?h.oauthCustomRedirectUri:x?.redirectUri?x.redirectUri:`${globalThis.location?.origin||``}/oauth/callback`;try{let n=await fetch(`/oauth/authorize`,{body:JSON.stringify({providerId:v,clientId:_,clientSecret:y||void 0,redirectUri:C,scope:b,...S&&h.oauthCustomAuthorizeUrl?{authorizeUrl:h.oauthCustomAuthorizeUrl}:{},...S&&h.oauthCustomTokenUrl?{tokenUrl:h.oauthCustomTokenUrl}:{},...S&&typeof h.oauthCustomUsePkce==`boolean`?{usePkce:h.oauthCustomUsePkce}:{}}),headers:{"content-type":`application/json`},method:`POST`}),r=await n.json();if(!n.ok||!r.state||!r.authorizeUrl)throw Error(r.error||`OAuth authorize failed`);let a=window.open(r.authorizeUrl,`shadowclaw-oauth`,`popup=yes,width=540,height=720`);if(!a||a.closed||a.closed===void 0)throw Error(`OAuth popup was blocked by the browser. Please enable popups for this site and try again.`);let s=r.state,c=`pending`;for(let e=0;e<60;e++){let e=await fetch(`/oauth/session/${encodeURIComponent(s)}`),t=await e.json();if(!e.ok)throw Error(t.error||`OAuth session not found`);if(c=t.status||`pending`,c===`authorized`)break;if(c===`error`)throw Error(t.error||`OAuth authorization failed`);await new Promise(e=>setTimeout(e,1e3))}if(c!==`authorized`)throw Error(`OAuth authorization timed out`);let d=await fetch(`/oauth/token`,{body:JSON.stringify({state:s}),headers:{"content-type":`application/json`},method:`POST`}),p=await d.json();if(!d.ok||!p.accessToken)throw Error(p.error||`OAuth token exchange failed`);let x=await l(p.accessToken);if(!x)throw Error(`Failed to encrypt access token`);let w=h.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(w=e)}let T=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},h,x,w);if(g===`service`&&u.accountId){let t=f.findIndex(e=>e.id===u.accountId);t!==-1&&(Object.assign(f[t],T),await o(e,i.SERVICE_ACCOUNTS,f))}else if(g===`git`&&u.gitAccountId){let t=m.findIndex(e=>e.id===u.gitAccountId);t!==-1&&(Object.assign(m[t],T),await o(e,i.GIT_ACCOUNTS,m))}return Z(t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}export{ue as a,I as c,S as d,x as f,u as h,ce as i,te as l,v as m,G as n,re as o,k as p,le as r,L as s,fe as t,ne as u};
|
|
1
|
+
import{L as e,N as t,b as n,h as r,r as i}from"./config-CrHchneq.js";import{t as a}from"./getConfig-D89uJgo5.js";import{t as o}from"./setConfig-DFMYnYLE.js";import{t as s}from"./ulid-BY7rQVLN.js";import{n as c,r as l}from"./crypto-C8c5wMzN.js";function u(e){return!e||e.authMode===`token`||e.authMode===`pat`?`token`:e.authMode===`basic`?`basic`:e.authMode===`oauth`||e.oauthProviderId||e.oauthClientId||e.oauthClientSecret||e.refreshToken||e.accessTokenExpiresAt||e.tokenType||e.oauthReauthRequired?`oauth`:`token`}function d(e){return u(e)}function f(e,t){return d(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function p(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let r=await c(n.refreshToken);if(!r)return n;let a=n.oauthClientSecret?await c(n.oauthClientSecret):void 0,s=async r=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=r,await o(e,i.SERVICE_ACCOUNTS,t))},u=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({providerId:n.oauthProviderId,clientId:n.oauthClientId,clientSecret:a,refreshToken:r,scope:n.scopes,tokenUrl:n.oauthCustomTokenUrl})});if(!e.ok)return u();let t=await e.json();if(!t.accessToken)return u();let i=await l(t.accessToken);if(!i)return u();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let c={...n,token:i,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(c),c}catch{return u()}}function m(e,n){if(e.oauthProviderId){let n=t(e.oauthProviderId);if(n)return n}let i=[e.service,e.hostPattern,n].filter(e=>!!e).map(e=>e.toLowerCase());for(let e of Object.values(r))if([e.providerId,...e.aliases||[]].map(e=>e.toLowerCase()).some(e=>i.some(t=>t.includes(e))))return e;return null}function h(e,t){let n=d(e),r=m(e,t);if(r){let e;return e=n===`oauth`?r.tokenAuth.oauth:n===`basic`&&r.tokenAuth.basic?r.tokenAuth.basic:r.tokenAuth.token,{headerName:e.headerName,headerPrefix:e.headerPrefix||``}}return{headerName:`Authorization`,headerPrefix:n===`basic`?`Basic `:`Bearer `}}function g(e,t){let n=[],r=-1,i=t.toLowerCase();for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();i.includes(e)&&(e.length>r?(r=e.length,n.length=0,n.push(t)):e.length===r&&n.push(t))}return n}function _(e,t){return e.length?t&&e.find(e=>d(e)===t)||e[0]:void 0}async function v(e,t,n={}){let r=await a(e,i.SERVICE_ACCOUNTS),o=Array.isArray(r)?r:[];if(o.length===0)return;let s;if(n.accountId&&(s=o.find(e=>e.id===n.accountId)),!s&&t){let e=g(o,t);s=n.authMode?_(e,n.authMode):_(e,e[0]?m(e[0],t)?.defaultMode:void 0)}if(!s){let t=await a(e,i.SERVICE_DEFAULT_ACCOUNT);t&&(s=o.find(e=>e.id===t))}if(!s&&n.authMode&&(s=_(o,n.authMode)),s||=o[0],!s)return;if(f(s,n)&&(s=await p(e,o,s)),d(s)===`oauth`&&s.oauthReauthRequired)return{token:``,service:s.service,hostPattern:s.hostPattern,headerName:`Authorization`,headerValue:``,accountId:s.id,authMode:`oauth`,reauthRequired:!0};let l=``;s.token&&(l=await c(s.token)??``);let{headerName:u,headerPrefix:v}=h(s,t),y=l;d(s)===`basic`&&s.basicUsername&&(y=btoa(`${s.basicUsername}:${l}`));let b=v?`${v}${y}`:y;return{token:l,service:s.service,hostPattern:s.hostPattern,headerName:u,headerValue:b,accountId:s.id,authMode:d(s)}}function y(e){return u(e)}function b(e){switch(e){case`azure-devops`:return`azure_devops`;default:return e}}function x(e){if(!e)return`generic`;let t=e.toLowerCase();return t.includes(`github`)?`github`:t.includes(`dev.azure.com`)||t.includes(`visualstudio.com`)?`azure-devops`:t.includes(`gitlab`)?`gitlab`:`generic`}function S(t){if(t.reauthRequired)return{};let n=t.provider||x(t.hostPattern||``),r=b(n),i=t.authMode||`token`;if(t.token&&r===`azure_devops`&&e(r,i,`git_remote`)?.headerPrefix===`Basic `)return{Authorization:`Basic ${btoa(`:`+t.token)}`};switch(n){case`azure-devops`:if(t.username&&t.password)return{Authorization:`Basic ${btoa(t.username+`:`+t.password)}`};break;default:break}if(t.token){let n=e(r,i,`git_remote`);return n?.headerName?{[n.headerName]:`${n.headerPrefix||``}${t.token}`}:{Authorization:`Bearer ${t.token}`}}return{}}function C(e){try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n?t.hostname+n:t.hostname}catch{return}}function w(e,t){let n=t.toLowerCase(),r=[],i=-1;for(let t of e){if(!t.hostPattern)continue;let e=t.hostPattern.toLowerCase();n.includes(e)&&(e.length>i?(i=e.length,r.length=0,r.push(t)):e.length===i&&r.push(t))}return r}function T(e,t){if(!e.length)return;if(!t)return e[0];let n=e.find(e=>y(e)===t);if(n)return n;if(t===`token`){let t=e.find(e=>y(e)===`token`&&!e.authMode);if(t)return t}return e[0]}async function E(e){if(e)return await c(e)??void 0}function D(e,t){return y(e)!==`oauth`||e.oauthReauthRequired||!e.refreshToken||!e.oauthProviderId||!e.oauthClientId?!1:t.forceRefresh?!0:e.accessTokenExpiresAt?e.accessTokenExpiresAt<=Date.now()+6e4:!1}async function O(e,t,n){if(!n.refreshToken||!n.oauthProviderId||!n.oauthClientId)return n;let r=await E(n.refreshToken);if(!r)return n;let a=n.oauthClientSecret?await E(n.oauthClientSecret):void 0,s=async r=>{let a=t.findIndex(e=>e.id===n.id);a!==-1&&(t[a]=r,await o(e,i.GIT_ACCOUNTS,t))},c=async()=>{let e=(n.oauthRefreshFailureCount||0)+1,t=e>=3,r={...n,oauthRefreshFailureCount:e,oauthReauthRequired:t,oauthReauthRequiredAt:t?n.oauthReauthRequiredAt||Date.now():void 0};return await s(r),r};try{let e=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:n.oauthClientId,clientSecret:a,providerId:n.oauthProviderId,refreshToken:r,scope:n.scopes}),headers:{"content-type":`application/json`},method:`POST`});if(!e.ok)return c();let t=await e.json();if(!t.accessToken)return c();let i=await l(t.accessToken);if(!i)return c();let o=n.refreshToken;if(t.refreshToken){let e=await l(t.refreshToken);e&&(o=e)}let u={...n,token:i,refreshToken:o,accessTokenExpiresAt:t.expiresIn?Date.now()+t.expiresIn*1e3:n.accessTokenExpiresAt,tokenType:t.tokenType||n.tokenType,scopes:t.scope?t.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):n.scopes,oauthRefreshFailureCount:0,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0};return await s(u),u}catch{return c()}}async function k(e,t,n={}){let r=await a(e,i.GIT_ACCOUNTS);return Array.isArray(r)&&r.length>0?ee(e,r,t,n):A(e)}async function ee(e,t,n,r={}){let o;if(r.accountId&&(o=t.find(e=>e.id===r.accountId)),!o&&n){let e=C(n);e&&(o=T(w(t,e),r.authMode))}if(!o){let r=await a(e,i.GIT_DEFAULT_ACCOUNT);if(r){let e=t.find(e=>e.id===r);if(e)if(!n)o=e;else{let t=C(n);if(t&&e.hostPattern){let n=t?.toLowerCase(),r=e.hostPattern.toLowerCase();n?.includes(r)&&(o=e)}}}}if(!o&&!n&&r.authMode&&(o=T(t,r.authMode)),!o&&!n&&(o=t[0]),!o)return{authMode:`token`,authorEmail:void 0,authorName:void 0,password:void 0,provider:`generic`,token:void 0,username:void 0};D(o,r)&&(o=await O(e,t,o));let s=o.provider||x(o.hostPattern||``);return y(o)===`oauth`&&o.oauthReauthRequired?{accountId:o.id,authMode:`oauth`,authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:void 0,provider:s,reauthRequired:!0,token:void 0,username:o.username||void 0}:{accountId:o.id,authMode:y(o),authorEmail:o.authorEmail||void 0,authorName:o.authorName||void 0,hostPattern:o.hostPattern||void 0,password:await E(o.password),provider:s,token:await E(o.token),username:o.username||void 0}}async function A(e){let t=await a(e,i.GIT_TOKEN),n=await a(e,i.GIT_PASSWORD);return{authMode:`token`,authorEmail:await a(e,i.GIT_AUTHOR_EMAIL)||void 0,authorName:await a(e,i.GIT_AUTHOR_NAME)||void 0,password:n?await E(n):void 0,provider:`generic`,token:t?await E(t):void 0,username:await a(e,i.GIT_USERNAME)||void 0}}function j(e){if(typeof e!=`string`||!e.trim())return!1;try{let t=new URL(e);return t.protocol===`https:`||t.protocol===`http:`}catch{return!1}}function M(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(!n.serviceType||!n.authType)return null;if(n.serviceType!==t)throw Error(`Credential ref serviceType must match connection serviceType`);return{serviceType:n.serviceType,authType:n.authType,providerId:n.providerId||void 0,accountId:n.accountId||void 0,gitAccountId:n.gitAccountId||void 0,headerName:n.headerName||void 0,encryptedValue:n.encryptedValue||void 0}}function N(e){if(!e||typeof e!=`object`)return null;let t=e;return!t.id||!t.label||!t.serviceType||!t.transport||typeof t.enabled!=`boolean`||typeof t.createdAt!=`number`||typeof t.updatedAt!=`number`||!j(t.serverUrl)||t.serviceType!==`mcp_remote`&&t.serviceType!==`webmcp_local`||t.transport!==`streamable_http`&&t.transport!==`sse`&&t.transport!==`websocket`?null:{id:t.id,label:t.label,serviceType:t.serviceType,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled,autoReconnectOAuth:t.autoReconnectOAuth===!0,createdAt:t.createdAt,updatedAt:t.updatedAt,credentialRef:M(t.credentialRef,t.serviceType)}}async function P(e){let t=await a(e,i.REMOTE_MCP_CONNECTIONS);if(!Array.isArray(t))return[];let n=[];for(let e of t){let t=N(e);t&&n.push(t)}return n}async function F(e,t){await o(e,i.REMOTE_MCP_CONNECTIONS,t)}async function te(e){return P(e)}async function I(e,t){if(!t)return null;let n=await P(e);return n.find(e=>e.id===t)||n.find(e=>e.label.toLowerCase()===t.toLowerCase())||null}async function ne(e,t){if(!t?.label?.trim())throw Error(`Connection label is required`);if(!j(t.serverUrl))throw Error(`Connection serverUrl must be an absolute http(s) URL`);let n=t.serviceType||`mcp_remote`;if(n!==`mcp_remote`&&n!==`webmcp_local`)throw Error(`Unsupported serviceType for remote MCP connection`);let r=await P(e),i=Date.now();if(t.id){let a=r.findIndex(e=>e.id===t.id);if(a!==-1){let o=r[a],s={...o,label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??o.enabled,autoReconnectOAuth:t.autoReconnectOAuth??o.autoReconnectOAuth,updatedAt:i};return r[a]=s,await F(e,r),s}}let a={id:t.id||s(),label:t.label.trim(),serviceType:n,serverUrl:t.serverUrl,transport:t.transport,enabled:t.enabled??!0,autoReconnectOAuth:t.autoReconnectOAuth??!1,createdAt:i,updatedAt:i,credentialRef:null};return r.push(a),await F(e,r),a}async function re(e,t,n){if(!t)return null;let r=await P(e),i=r.findIndex(e=>e.id===t);if(i===-1)return null;let a=r[i],o=n?M(n,a.serviceType):null,s={...a,credentialRef:o,updatedAt:Date.now()};return r[i]=s,await F(e,r),s}async function L(e,t){if(!t)return!1;let n=await P(e),r=n.filter(e=>e.id!==t);return r.length===n.length?!1:(await F(e,r),!0)}function R(e){return e===`oauth`?`oauth`:`token`}async function z(e,t,n={}){let r=await I(e,t);if(!r)return null;let i=r.credentialRef;if(!i||i.authType===`none`)return{connection:r,authType:`none`,headers:{}};if(i.authType===`custom_header`){if(!i.headerName||!i.encryptedValue)return{connection:r,authType:`custom_header`,headers:{}};let e=await c(i.encryptedValue);return{connection:r,authType:`custom_header`,headers:e?{[i.headerName]:e}:{}}}let a=R(i.authType);if(i.accountId){let t=await v(e,r.serverUrl,{accountId:i.accountId,authMode:a,forceRefresh:n.forceRefresh});return t?t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:t.headerValue?{[t.headerName]:t.headerValue}:{}}:{connection:r,authType:i.authType,headers:{}}}if(i.gitAccountId){let t=await k(e,r.serverUrl,{accountId:i.gitAccountId,authMode:a,forceRefresh:n.forceRefresh});return t.reauthRequired?{connection:r,authType:i.authType,headers:{},reauthRequired:!0}:{connection:r,authType:i.authType,headers:S(t)}}return{connection:r,authType:i.authType,headers:{}}}const B=new Map;function V(e){return typeof e==`object`&&!!e&&`method`in e&&`id`in e&&!(`result`in e)&&!(`error`in e)}function H(e){let t=(e.requestedSchema||{}).properties||{},n={};for(let[e,r]of Object.entries(t))`default`in r?n[e]=r.default:r.type===`boolean`&&(n[e]=!0);return n}var U=class extends Error{constructor(e){super(e),this.name=`InvalidRemoteMcpSessionError`}},W=class extends Error{status;constructor(e,t){super(t),this.name=`HttpRemoteMcpError`,this.status=e}},G=class extends Error{connectionId;constructor(e){super(`OAuth reconnect required for remote MCP connection`),this.name=`McpReauthRequiredError`,this.connectionId=e}};function K(e,t){return!e.headers||typeof e.headers.get!=`function`?null:e.headers.get(t)}function ie(e){return/no valid session id provided/i.test(e)}function q(e,t){let n=t&&`error`in t?t.error.message||`Remote MCP JSON-RPC error`:``;return ie(n)?new U(n):e.ok?Error(n||`Remote MCP JSON-RPC error`):new W(e.status,n?`Remote MCP HTTP error: ${e.status} (${n})`:`Remote MCP HTTP error: ${e.status}`)}function ae(e){if(!e)return null;let t=null,n=e.split(/\r?\n/);for(let e of n){let n=e.trim();if(!n.startsWith(`data:`))continue;let r=n.slice(5).trim();if(!(!r||r===`[DONE]`))try{let e=JSON.parse(r);e&&typeof e==`object`&&`jsonrpc`in e&&(t=e)}catch{}}return t}function oe(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function J(e,t,n){let r=await fetch(e,{method:`POST`,headers:{"content-type":`application/json`,accept:`application/json, text/event-stream`,...t},body:JSON.stringify(n)}),i=(K(r,`content-type`)||``).toLowerCase(),a=null;if(typeof r.text==`function`){let e=await r.text();a=i.includes(`text/event-stream`)?ae(e):oe(e)}else try{a=await r.json()}catch{a=null}return{response:r,payload:a}}async function se(e,t,n){let{response:r,payload:i}=await J(e,{...t,"mcp-session-id":n},{jsonrpc:`2.0`,method:`notifications/initialized`,params:{}});if(!r.ok||i&&`error`in i)throw q(r,i)}async function Y(e,t,n){let r=B.get(e);if(r?.sessionId)return r;let{response:i,payload:a}=await J(t,n,{jsonrpc:`2.0`,id:`initialize-${Date.now().toString(36)}`,method:`initialize`,params:{protocolVersion:`2025-03-26`,capabilities:{elicitation:{}},clientInfo:{name:`shadowclaw-remote-mcp-client`,version:`1.0.0`}}});if(!i.ok||a&&`error`in a)throw q(i,a);let o=K(i,`mcp-session-id`)||`local-${Date.now()}-${Math.random().toString(36).slice(2)}`,s={sessionId:o,protocolVersion:K(i,`mcp-protocol-version`)||a?.result?.protocolVersion,lastUsedAt:Date.now()};return await se(t,n,o),B.set(e,s),s}async function X(e,t,n,r,i){let a=await Y(e,t,n),o=async e=>{let a={jsonrpc:`2.0`,id:Date.now().toString(),method:r,params:i||{}},o={...n,"mcp-session-id":e},{response:s,payload:c}=await J(t,o,a),l=0;for(;V(c)&&l<5&&(l++,c.method===`elicitation/create`);){let e=H(c.params||{});({response:s,payload:c}=await J(t,o,{jsonrpc:`2.0`,id:c.id,result:{action:`accept`,content:e}}))}if(V(c))throw Error(`Unsupported server request: ${c.method}`);if(!s.ok||!c||`error`in c)throw q(s,c);return c.result};try{let t=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),t}catch(r){if(!(r instanceof U))throw r;B.delete(e),a=await Y(e,t,n);let i=await o(a.sessionId);return a.lastUsedAt=Date.now(),B.set(e,a),i}}function Z(e){e&&B.delete(e)}async function Q(e,t,n,r){let i=await z(e,t);if(!i)throw Error(`Remote MCP connection not found`);if(i.reauthRequired)throw new G(t);let{connection:a,authType:o,headers:s}=i;if(a.transport!==`streamable_http`)throw Error(`Unsupported remote MCP transport`);try{return await X(t,a.serverUrl,s,n,r)}catch(i){if(!(i instanceof W)||i.status!==401||o!==`oauth`)throw i;Z(t);let a=await z(e,t,{forceRefresh:!0});if(!a||a.reauthRequired)throw new G(t);try{return await X(t,a.connection.serverUrl,a.headers,n,r)}catch(e){throw e instanceof W&&e.status===401?new G(t):e}}}async function ce(e,t){let n=await Q(e,t,`tools/list`);return Array.isArray(n.tools)?n.tools:[]}async function le(e,t,n,r={}){return Q(e,t,`tools/call`,{name:n,arguments:r})}async function ue(e,t){let n=[],r;try{r=await z(e,t)}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Resolve authentication`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}if(!r)return n.push({step:`Resolve authentication`,status:`error`,detail:`Connection not found`}),{success:!1,error:`Connection not found`,toolCount:0,toolNames:[],steps:n};if(r.reauthRequired){let e=`OAuth token expired or revoked — re-authenticate in Settings`;return n.push({step:`Resolve authentication`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}n.push({step:`Resolve authentication`,status:`ok`,detail:`Auth type: ${r.authType}`});let{connection:i,authType:a,headers:o}=r;if(i.transport!==`streamable_http`){let e=`Unsupported transport: ${i.transport}`;return n.push({step:`Establish MCP session`,status:`error`,detail:e}),{success:!1,error:e,toolCount:0,toolNames:[],steps:n}}Z(t);try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(r){let s=r instanceof Error?r.message:String(r);if(n.push({step:`Establish MCP session`,status:`error`,detail:s}),r instanceof W&&r.status===401&&a===`oauth`){Z(t);let r=await z(e,t,{forceRefresh:!0});if(r&&!r.reauthRequired){n.push({step:`Refresh OAuth token`,status:`ok`,detail:`Token refreshed, retrying`}),i=r.connection,o=r.headers;try{await Y(t,i.serverUrl,o),n.push({step:`Establish MCP session`,status:`ok`,detail:`Session established`})}catch(e){let t=e instanceof Error?e.message:String(e),r=e instanceof W&&e.status===401?`${t} — re-authorize in Settings → Accounts`:t;return n.push({step:`Establish MCP session`,status:`error`,detail:r}),{success:!1,error:r,toolCount:0,toolNames:[],steps:n}}}else return n.push({step:`Refresh OAuth token`,status:`error`,detail:`Token refresh failed — re-authenticate in Settings`}),{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}else return{success:!1,error:s,toolCount:0,toolNames:[],steps:n}}try{let e=await X(t,i.serverUrl,o,`tools/list`),r=Array.isArray(e.tools)?e.tools:[],a=r.map(e=>e.name);return n.push({step:`Discover tools`,status:`ok`,detail:`${r.length} tool${r.length===1?``:`s`} available`}),{success:!0,error:null,toolCount:r.length,toolNames:a,steps:n}}catch(e){let t=e instanceof Error?e.message:String(e);return n.push({step:`Discover tools`,status:`error`,detail:t}),{success:!1,error:t,toolCount:0,toolNames:[],steps:n}}}function $(e,t,n,r){return{accessTokenExpiresAt:e.expiresIn?Date.now()+e.expiresIn*1e3:t.accessTokenExpiresAt,oauthReauthRequired:!1,oauthReauthRequiredAt:void 0,oauthRefreshFailureCount:0,refreshToken:r,scopes:e.scope?e.scope.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean):t.scopes,token:n,tokenType:e.tokenType||t.tokenType}}async function de(e,t,n,r,a,s,u){if(!t.refreshToken)return{success:!1,error:`No refresh token available.`};let d=await c(t.refreshToken);if(!d)return{success:!1,error:`Failed to decrypt refresh token.`};let f=t.oauthClientSecret?await c(t.oauthClientSecret):void 0;try{let c=await fetch(`/oauth/refresh`,{body:JSON.stringify({clientId:t.oauthClientId,clientSecret:f||void 0,providerId:t.oauthProviderId,refreshToken:d,scope:t.scopes,tokenUrl:t.oauthCustomTokenUrl}),headers:{"content-type":`application/json`},method:`POST`});if(!c.ok)return{success:!1,error:`Token refresh request failed.`};let p=await c.json();if(!p.accessToken)return{success:!1,error:`No access token in refresh response.`};let m=await l(p.accessToken);if(!m)return{success:!1,error:`Failed to encrypt access token.`};let h=t.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(h=e)}let g=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},t,m,h);if(n===`service`&&s.accountId){let t=r.findIndex(e=>e.id===s.accountId);t!==-1&&(Object.assign(r[t],g),await o(e,i.SERVICE_ACCOUNTS,r))}else if(n===`git`&&s.gitAccountId){let t=a.findIndex(e=>e.id===s.gitAccountId);t!==-1&&(Object.assign(a[t],g),await o(e,i.GIT_ACCOUNTS,a))}return Z(u),{success:!0}}catch(e){return{success:!1,error:`Silent refresh failed: ${e instanceof Error?e.message:String(e)}`}}}async function fe(e,t,r={}){let s=await I(e,t);if(!s?.credentialRef)return{success:!1,error:`Connection not found.`};let u=s.credentialRef;if(u.authType!==`oauth`)return{success:!1,error:`This connection does not use OAuth authentication.`};let d=await a(e,i.SERVICE_ACCOUNTS),f=Array.isArray(d)?d:[],p=await a(e,i.GIT_ACCOUNTS),m=Array.isArray(p)?p:[],h,g=null;if(u.accountId?(h=f.find(e=>e.id===u.accountId),g=`service`):u.gitAccountId&&(h=m.find(e=>e.id===u.gitAccountId),g=`git`),!h||!g)return{error:`Linked account not found. Edit the connection to re-configure authentication.`,success:!1};let _=h.oauthClientId,v=h.oauthProviderId;if(!v||!_)return{error:`Account is missing OAuth provider or client ID. Edit the account in Settings → Accounts to fix.`,success:!1};if(h.refreshToken){let n=await de(e,h,g,f,m,u,t);if(n.success)return n}if(r.silentOnly)return{error:`Silent token refresh failed. Use Settings → Remote MCP → Reconnect OAuth for full re-authorization.`,success:!1};let y=h.oauthClientSecret?await c(h.oauthClientSecret):void 0,b=h.scopes,x=n[v],S=v===`custom_mcp`,C=S&&h.oauthCustomRedirectUri?h.oauthCustomRedirectUri:x?.redirectUri?x.redirectUri:`${globalThis.location?.origin||``}/oauth/callback`;try{let n=await fetch(`/oauth/authorize`,{body:JSON.stringify({providerId:v,clientId:_,clientSecret:y||void 0,redirectUri:C,scope:b,...S&&h.oauthCustomAuthorizeUrl?{authorizeUrl:h.oauthCustomAuthorizeUrl}:{},...S&&h.oauthCustomTokenUrl?{tokenUrl:h.oauthCustomTokenUrl}:{},...S&&typeof h.oauthCustomUsePkce==`boolean`?{usePkce:h.oauthCustomUsePkce}:{}}),headers:{"content-type":`application/json`},method:`POST`}),r=await n.json();if(!n.ok||!r.state||!r.authorizeUrl)throw Error(r.error||`OAuth authorize failed`);let a=window.open(r.authorizeUrl,`shadowclaw-oauth`,`popup=yes,width=540,height=720`);if(!a||a.closed||a.closed===void 0)throw Error(`OAuth popup was blocked by the browser. Please enable popups for this site and try again.`);let s=r.state,c=`pending`;for(let e=0;e<60;e++){let e=await fetch(`/oauth/session/${encodeURIComponent(s)}`),t=await e.json();if(!e.ok)throw Error(t.error||`OAuth session not found`);if(c=t.status||`pending`,c===`authorized`)break;if(c===`error`)throw Error(t.error||`OAuth authorization failed`);await new Promise(e=>setTimeout(e,1e3))}if(c!==`authorized`)throw Error(`OAuth authorization timed out`);let d=await fetch(`/oauth/token`,{body:JSON.stringify({state:s}),headers:{"content-type":`application/json`},method:`POST`}),p=await d.json();if(!d.ok||!p.accessToken)throw Error(p.error||`OAuth token exchange failed`);let x=await l(p.accessToken);if(!x)throw Error(`Failed to encrypt access token`);let w=h.refreshToken;if(p.refreshToken){let e=await l(p.refreshToken);e&&(w=e)}let T=$({accessToken:p.accessToken,expiresIn:p.expiresIn,refreshToken:p.refreshToken,scope:p.scope,tokenType:p.tokenType},h,x,w);if(g===`service`&&u.accountId){let t=f.findIndex(e=>e.id===u.accountId);t!==-1&&(Object.assign(f[t],T),await o(e,i.SERVICE_ACCOUNTS,f))}else if(g===`git`&&u.gitAccountId){let t=m.findIndex(e=>e.id===u.gitAccountId);t!==-1&&(Object.assign(m[t],T),await o(e,i.GIT_ACCOUNTS,m))}return Z(t),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}export{ue as a,I as c,S as d,x as f,u as h,ce as i,te as l,v as m,G as n,re as o,k as p,le as r,L as s,fe as t,ne as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-aKtaBQYM.js";import{x as t}from"./config-
|
|
1
|
+
import{n as e}from"./rolldown-runtime-aKtaBQYM.js";import{x as t}from"./config-CrHchneq.js";var n=e({MemoryDirectoryHandle:()=>c,MemoryFileHandle:()=>s,MemorySyncAccessHandle:()=>a,MemoryWritableStream:()=>o,getMemoryOpfsRoot:()=>u,isMemoryStorageFallbackActive:()=>d});function r(e,t){if(typeof DOMException<`u`)try{return new DOMException(e,t)}catch{}let n=Error(e);return n.name=t,n}function i(e){let t=e();return t[Symbol.asyncDispose??Symbol.for(`Symbol.asyncDispose`)]=async()=>{},t}var a=class{_file;_closed=!1;constructor(e){this._file=e}close(){this._closed=!0}flush(){}getSize(){if(this._closed)throw r(`SyncAccessHandle is closed`,`InvalidStateError`);return this._file.getRawData().byteLength}read(e,t){if(this._closed)throw r(`SyncAccessHandle is closed`,`InvalidStateError`);let n=this._file.getRawData(),i=t?.at??0;if(i>=n.byteLength)return 0;let a=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),o=n.subarray(i,i+a.byteLength);return a.set(o),o.byteLength}write(e,t){if(this._closed)throw r(`SyncAccessHandle is closed`,`InvalidStateError`);let n=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),i=t?.at??0,a=this._file.getRawData(),o=i+n.byteLength,s;return o>a.byteLength?(s=new Uint8Array(o),s.set(a)):s=new Uint8Array(a),s.set(n,i),this._file.setRawData(s),n.byteLength}truncate(e){if(this._closed)throw r(`SyncAccessHandle is closed`,`InvalidStateError`);let t=this._file.getRawData(),n=new Uint8Array(e);n.set(t.subarray(0,Math.min(t.byteLength,e))),this._file.setRawData(n)}},o=class{_file;_buffer;_position=0;_length=0;_closed=!1;constructor(e,t=!1){this._file=e;let n=e.getRawData();t?(this._buffer=new Uint8Array(n),this._length=n.byteLength):(this._buffer=new Uint8Array(1024),this._length=0)}async write(e){if(this._closed)throw r(`WritableStream is closed`,`InvalidStateError`);let t;if(typeof e==`string`)t=new TextEncoder().encode(e);else if(e instanceof Uint8Array)t=e;else if(e instanceof ArrayBuffer)t=new Uint8Array(e);else if(typeof Blob<`u`&&e instanceof Blob)t=typeof e.arrayBuffer==`function`?new Uint8Array(await e.arrayBuffer()):typeof e.text==`function`?new TextEncoder().encode(await e.text()):typeof FileReader<`u`?await new Promise(t=>{let n=new FileReader;n.onload=()=>{t(new Uint8Array(n.result))},n.onerror=()=>t(new Uint8Array),n.readAsArrayBuffer(e)}):new Uint8Array;else if(e&&typeof e==`object`&&`type`in e)if(e.type===`write`){typeof e.position==`number`&&(this._position=e.position);let n=e.data;t=typeof n==`string`?new TextEncoder().encode(n):n instanceof Uint8Array?n:n instanceof ArrayBuffer?new Uint8Array(n):typeof Blob<`u`&&n instanceof Blob&&typeof n.arrayBuffer==`function`?new Uint8Array(await n.arrayBuffer()):new Uint8Array}else if(e.type===`seek`){this._position=e.position??0;return}else if(e.type===`truncate`){this._truncate(e.size??0);return}else t=new Uint8Array;else t=new Uint8Array;let n=this._position+t.length;if(n>this._buffer.length){let e=Math.max(this._buffer.length*2,n,1024),t=new Uint8Array(e);t.set(this._buffer),this._buffer=t}this._buffer.set(t,this._position),this._position+=t.length,this._position>this._length&&(this._length=this._position)}_truncate(e){if(e<this._length)this._length=e;else if(e>this._length){if(e>this._buffer.length){let t=new Uint8Array(e);t.set(this._buffer),this._buffer=t}this._length=e}this._position>e&&(this._position=e)}async seek(e){if(this._closed)throw r(`WritableStream is closed`,`InvalidStateError`);this._position=e}async truncate(e){if(this._closed)throw r(`WritableStream is closed`,`InvalidStateError`);this._truncate(e)}async close(){if(this._closed)return;this._closed=!0;let e=this._buffer.slice(0,this._length);this._file.setRawData(e)}async abort(){this._closed=!0}},s=class{kind=`file`;name;_data;_lastModified;constructor(e,t=new Uint8Array){this.name=e,this._data=t,this._lastModified=Date.now()}getRawData(){return this._data}setRawData(e){this._data=e,this._lastModified=Date.now()}_getArrayBuffer(){let e=new ArrayBuffer(this._data.byteLength);return new Uint8Array(e).set(this._data),e}async getFile(){let e=this._getArrayBuffer(),t=this._data,n=this.name,r=this._lastModified,i={name:n,size:t.byteLength,type:``,lastModified:r,async text(){return new TextDecoder().decode(t)},async arrayBuffer(){return e},slice(n=0,r=t.byteLength){return new Blob([e.slice(n,r)])}};if(typeof File<`u`)try{let t=new File([e],this.name,{lastModified:this._lastModified});return typeof t.text!=`function`&&(t.text=i.text),typeof t.arrayBuffer!=`function`&&(t.arrayBuffer=i.arrayBuffer),t}catch{}return i}async createWritable(e){return new o(this,e?.keepExistingData??!1)}async createSyncAccessHandle(){return new a(this)}async isSameEntry(e){return this===e}async queryPermission(){return`granted`}async requestPermission(){return`granted`}},c=class e{kind=`directory`;name;_entries=new Map;constructor(e){this.name=e}_setEntry(e,t){this._entries.set(e,t)}async getDirectoryHandle(t,n){if(t===`.`||t===``)return this;if(t===`..`)throw r(`Cannot navigate to parent directory with '..'`,`SecurityError`);let i=this._entries.get(t);if(i){if(i.kind===`directory`)return i;throw r(`"${t}" is a file, not a directory`,`TypeMismatchError`)}if(n?.create){let n=new e(t);return this._entries.set(t,n),n}throw r(`A requested file or directory could not be found at "${t}"`,`NotFoundError`)}async getFileHandle(e,t){if(e===`.`||e===`..`||e===``)throw r(`Invalid file name "${e}"`,`TypeMismatchError`);let n=this._entries.get(e);if(n){if(n.kind===`file`)return n;throw r(`"${e}" is a directory, not a file`,`TypeMismatchError`)}if(t?.create){let t=new s(e);return this._entries.set(e,t),t}throw r(`A requested file could not be found at "${e}"`,`NotFoundError`)}async removeEntry(e,t){let n=this._entries.get(e);if(!n)throw r(`Entry "${e}" not found`,`NotFoundError`);if(n.kind===`directory`&&n._entries.size>0&&!t?.recursive)throw r(`Directory "${e}" is not empty`,`InvalidModificationError`);this._entries.delete(e)}async resolve(e){if(this===e)return[];for(let[t,n]of this._entries.entries()){if(n===e)return[t];if(n.kind===`directory`){let r=await n.resolve(e);if(r)return[t,...r]}}return null}entries(){let e=this;return i(async function*(){for(let[t,n]of e._entries.entries())yield[t,n]})}values(){let e=this;return i(async function*(){for(let t of e._entries.values())yield t})}keys(){let e=this;return i(async function*(){for(let t of e._entries.keys())yield t})}[Symbol.asyncIterator](){return this.entries()}async isSameEntry(e){return this===e}async queryPermission(){return`granted`}async requestPermission(){return`granted`}};let l=null;function u(){if(!l){let e=new c(`memory-root`),n=new c(t);e._setEntry(t,n),l=n}return l}function d(){return l!==null}export{n,u as t};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import{D as e,E as t,F as n,I as r,M as i,O as a,P as o,R as s,T as c,_ as l,g as u,j as d,l as f,o as p,r as m,s as h,t as g,v as _,w as v}from"./config-CrHchneq.js";import{n as y,r as b}from"./txPromise-EBECky1b.js";import{t as x}from"./getConfig-D89uJgo5.js";import{p as S}from"./custom-element-security-NCqQ5lmC.js";import{n as C}from"./toast-60iDlgiH.js";import{At as w,C as T,Ct as E,Dt as ee,En as te,Et as ne,Ft as D,G as O,Gt as k,H as A,Ht as j,I as M,It as N,Jt as P,Kt as F,Lt as I,M as re,Mt as ie,N as L,Nt as R,On as ae,Ot as z,P as oe,Pt as se,St as B,Tn as ce,Tt as le,U as V,Ut as ue,V as de,W as fe,Wt as pe,X as me,Xt as he,Y as ge,Yt as _e,_n as ve,an as ye,at as be,bn as xe,bt as Se,dn as H,dt as Ce,fn as we,ft as Te,gn as Ee,gt as De,hn as Oe,in as ke,j as Ae,jt as je,kt as U,l as Me,ln as Ne,mn as W,on as Pe,ot as Fe,pn as G,qt as Ie,rn as K,t as q,u as Le,un as Re,ut as ze,vn as Be,yn as Ve}from"./orchestrator-tHWrqi_F.js";import{l as He,r as Ue}from"./getGroupDir-P1h9wl6S.js";import{t as J}from"./setConfig-DFMYnYLE.js";import{t as Y}from"./ulid-BY7rQVLN.js";import{a as We,o as Ge,r as Ke,s as qe}from"./syncWebMcpRegistration-DzC80wVG.js";import{n as Je,r as Ye}from"./crypto-C8c5wMzN.js";import{a as Xe,i as Ze,r as X,t as Qe}from"./peerjs-D8hck8Ih.js";async function $e(e){if(!(!e||e.name===`shadowclaw`)){try{if(await x(e,m.DB_MIGRATED_FROM_LEGACY)===`true`)return}catch{}try{let t=await new Promise(e=>{let t=indexedDB.open(l);t.onsuccess=()=>{let n=t.result;if(!n.objectStoreNames||n.objectStoreNames.length===0){n.close(),e(null);return}e(n)},t.onerror=()=>e(null)});if(t){let n=Array.from(t.objectStoreNames).filter(t=>e.objectStoreNames.contains(t));for(let r of n)await new Promise(n=>{try{let i=t.transaction(r,`readonly`).objectStore(r).getAll();i.onsuccess=()=>{let t=i.result||[];if(t.length>0)try{let i=e.transaction(r,`readwrite`),a=i.objectStore(r);for(let e of t)a.put(e);i.oncomplete=()=>n(),i.onerror=()=>n(),i.onabort=()=>n()}catch{n()}else n()},i.onerror=()=>n()}catch{n()}});t.close()}}catch(e){console.warn(`Legacy IndexedDB migration warning:`,e)}finally{try{await J(e,m.DB_MIGRATED_FROM_LEGACY,`true`)}catch{}}}}async function et(e,t,n){for await(let[r,i]of e.entries())if(i.kind===`directory`)await et(i,await t.getDirectoryHandle(r,{create:!0}),[...n,r]);else if(i.kind===`file`){let e=await i.getFile(),a=await t.getFileHandle(r,{create:!0});try{await Ne(a,e)}catch(t){if(!(t instanceof Error?t.message:String(t)).includes(`Writable file streams are not supported`))throw t;await Re([...n,r],e)}}}async function tt(e){if(!e)return;try{if(await x(e,m.OPFS_MIGRATED_FROM_LEGACY)===`true`)return}catch{}let t=Ue();if(t!==`shadowclaw`&&!(typeof navigator>`u`||!navigator.storage||typeof navigator.storage.getDirectory!=`function`))try{let n=await navigator.storage.getDirectory(),r;try{r=await n.getDirectoryHandle(_)}catch{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}return}let i=await n.getDirectoryHandle(t,{create:!0});await et(r,i,[t])}catch(e){console.warn(`Legacy OPFS migration warning:`,e)}finally{try{await J(e,m.OPFS_MIGRATED_FROM_LEGACY,`true`)}catch{}}}function nt(){return new Promise(async(e,t)=>{let n,r=d(),i=indexedDB.open(r,2);i.onupgradeneeded=()=>{let e=i.result;if(!e.objectStoreNames.contains(`messages`)){let t=e.createObjectStore(`messages`,{keyPath:`id`});t.createIndex(`by-group-time`,[`groupId`,`timestamp`]),t.createIndex(`by-group`,`groupId`)}if(e.objectStoreNames.contains(`sessions`)||e.createObjectStore(`sessions`,{keyPath:`groupId`}),!e.objectStoreNames.contains(`tasks`)){let t=e.createObjectStore(`tasks`,{keyPath:`id`});t.createIndex(`by-group`,`groupId`),t.createIndex(`by-enabled`,`enabled`)}e.objectStoreNames.contains(`config`)||e.createObjectStore(`config`,{keyPath:`key`}),e.objectStoreNames.contains(`pendingShares`)||e.createObjectStore(`pendingShares`,{keyPath:`id`}).createIndex(`by-createdAt`,`createdAt`)},i.onsuccess=async()=>{n=i.result,b(n);try{await $e(n),await tt(n)}catch(e){console.warn(`Error running legacy migration:`,e)}e(n)},i.onerror=()=>{t(Error(`Failed to open IndexedDB: ${i.error?.message}`))}})}var rt=class{activeGroupId;displayCallback;messageCallback;type;typingCallback;constructor(){this.type=`browser`,this.messageCallback=null,this.typingCallback=null,this.displayCallback=null,this.activeGroupId=p}getActiveGroup(){return this.activeGroupId}onDisplay(e){this.displayCallback=e}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setActiveGroup(e){this.activeGroupId=e}setTyping(e,t){this.typingCallback?.(e,t)}start(){}stop(){}submit(e,t,n=[],r,i,a){let o=t||this.activeGroupId,s={id:Y(),groupId:o,sender:`You`,content:e,timestamp:Date.now(),channel:`browser`,attachments:n,a2uiAction:r,freshContext:i,subagent:a};this.messageCallback?.(s)}async send(e,t,n){this.displayCallback?.(e,t,!0)}},it=class{_entries;constructor(){this._entries=[]}find(e){return this.resolve(e)?.channel??null}get(e){return this._entries.find(t=>t.prefix===e)?.channel}getBadge(e){return this.resolve(e)?.badge??``}getChannelType(e){return this.resolve(e)?.channel.type??null}onMessage(e){for(let t of this._entries)t.channel.onMessage(e)}onTyping(e){for(let t of this._entries)t.channel.onTyping&&t.channel.onTyping(e)}prefixes(){return this._entries.map(e=>e.prefix)}register(e,t,n){let r=typeof n==`string`?{badge:n}:n??{};this._entries.push({prefix:e,channel:t,badge:r.badge??e.replace(/:$/,``),autoTrigger:r.autoTrigger??!1}),this._entries.sort((e,t)=>t.prefix.length-e.prefix.length)}resolve(e){for(let t of this._entries)if(e.startsWith(t.prefix))return t;return null}shouldAutoTrigger(e){return this.resolve(e)?.autoTrigger??!1}startAll(){for(let e of this._entries)e.channel.start()}stopAll(){for(let e of this._entries)e.channel.stop()}},at=class{abortController=null;apiKey=``;apiMode=`unknown`;cursor=null;fileReader=null;messageCallback=null;reconnectDelayMs=1e3;registeredChatIds=new Set;running=!1;seenMessageIds=new Map;serverUrl=``;type=`imessage`;configure(e,t,n){this.serverUrl=ot(e),this.apiKey=t.trim(),this.registeredChatIds=new Set(n.map(e=>e.trim()).filter(Boolean)),this.cursor=null,this.apiMode=`unknown`}handleIncomingMessage(e){this.pruneSeenMessageIds();let t=String(e.chatId||e.conversationId||``).trim();if(!t||this.registeredChatIds.size>0&&!this.registeredChatIds.has(t))return;let n=`${e.text||e.body||``}`.trim();if(!n)return;let r=`${e.id||e.guid||`${t}:${e.timestamp||e.createdAt||n}`}`;if(this.seenMessageIds.has(r))return;this.seenMessageIds.set(r,Date.now());let i={id:r,groupId:`im:${t}`,sender:`${e.sender||e.handle||e.from||`iMessage`}`,content:n,timestamp:st(e.timestamp||e.createdAt),channel:`imessage`};this.messageCallback?.(i)}handlePollResponse(e){e.nextCursor!==void 0&&e.nextCursor!==null?this.cursor=String(e.nextCursor):e.cursor!==void 0&&e.cursor!==null&&(this.cursor=String(e.cursor));let t=Array.isArray(e.messages)?e.messages:[];for(let e of t)this.handleIncomingMessage(e)}isConfigured(){return this.serverUrl.length>0}onMessage(e){this.messageCallback=e}pruneSeenMessageIds(){let e=Date.now();for(let[t,n]of this.seenMessageIds.entries())e-n>6e4&&this.seenMessageIds.delete(t)}setTyping(e,t){if(!t)return;let n=e.replace(/^im:/,``);this.requestJson(`/messages/typing`,{method:`POST`,body:JSON.stringify({chatId:n,typing:!0})}).catch(()=>{})}start(){!this.isConfigured()||this.running||(this.running=!0,this.abortController=new AbortController,this.poll())}stop(){this.running=!1,this.abortController?.abort(),this.abortController=null}async ensureApiMode(){if(this.apiMode!==`unknown`)return this.apiMode;try{await this.requestJson(`/v1/info`,{method:`GET`}),this.apiMode=`beeper-desktop`}catch{this.apiMode=`legacy`}return this.apiMode}async poll(){for(;this.running&&this.abortController&&!this.abortController.signal.aborted;)try{let e=new URLSearchParams({timeout:`25`});this.cursor&&e.set(`cursor`,this.cursor);let t=await this.requestJson(`/messages?${e.toString()}`,{method:`GET`},u+5e3,this.abortController.signal);this.reconnectDelayMs=1e3,this.handlePollResponse(t)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`iMessage bridge poll error:`,e),await ct(this.reconnectDelayMs),this.reconnectDelayMs=Math.min(this.reconnectDelayMs*2,3e4)}}async requestJson(e,t,n=u,r){let i=new AbortController,a=setTimeout(()=>i.abort(),n),o=()=>i.abort();r?.addEventListener(`abort`,o,{once:!0});try{let n=new Headers(t.headers);n.set(`Accept`,`application/json`),!n.has(`Content-Type`)&&t.body&&!(t.body instanceof FormData)&&n.set(`Content-Type`,`application/json`),this.apiKey&&(n.set(`Authorization`,`Bearer ${this.apiKey}`),n.set(`X-API-Key`,this.apiKey));let r=await fetch(`${this.serverUrl}${e}`,{...t,headers:n,signal:i.signal});if(!r.ok){let e=await r.text();throw Error(`iMessage bridge request failed: ${r.status} ${e}`)}return r.status===204?{messages:[]}:await r.json()}finally{clearTimeout(a),r?.removeEventListener(`abort`,o)}}async send(e,t,n){let r=e.replace(/^im:/,``),{remainingText:i,attachments:a}=lt(t);for(let t of a){if(!this.fileReader){await this.sendText(r,`[${t.alt}] (file: ${t.path})`);continue}try{let n=await this.fileReader(e,t.path);if(!n||n.size===0)throw Error(`Attachment file is empty or unavailable.`);await this.sendAttachment(r,n,t)}catch(e){console.warn(`iMessage attachment send failed for ${t.path}:`,e),await this.sendText(r,`[${t.alt}] (file: ${t.path})`)}}let o=i.trim();o&&await this.sendText(r,o)}async sendAttachment(e,t,n){if(await this.ensureApiMode()===`beeper-desktop`){await this.sendAttachmentViaBeeperDesktop(e,t,n);return}await this.sendAttachmentViaLegacyBridge(e,t,n)}async sendAttachmentViaBeeperDesktop(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`file`,t,r),i.append(`fileName`,r),t.type&&i.append(`mimeType`,t.type);let a=`${(await this.requestJson(`/v1/assets/upload`,{method:`POST`,body:i})).uploadID||``}`.trim();if(!a)throw Error(`Beeper asset upload failed: missing uploadID`);await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:n.alt||void 0,attachment:{uploadID:a,fileName:r,mimeType:t.type||void 0}})})}async sendAttachmentViaLegacyBridge(e,t,n){let r=n.path.split(`/`).pop()||`attachment.bin`,i=new FormData;i.append(`chatId`,e),n.alt&&i.append(`text`,n.alt),i.append(`file`,t,r),await this.requestJson(`/messages/send`,{method:`POST`,body:i})}async sendText(e,t){if(await this.ensureApiMode()===`beeper-desktop`){await this.requestJson(`/v1/chats/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify({text:t})});return}await this.requestJson(`/messages/send`,{method:`POST`,body:JSON.stringify({chatId:e,text:t})})}};function ot(e){return e.trim().replace(/\/+$/,``)}function st(e){if(typeof e==`number`&&Number.isFinite(e))return e>0xe8d4a51000?e:e*1e3;if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return st(t);let n=Date.parse(e);if(Number.isFinite(n))return n}return Date.now()}function ct(e){return new Promise(t=>setTimeout(t,e))}function lt(e){let t=[],n=/!?\[([^\]]*)\]\(([^)]+)\)/g,r=null,i=e;for(;(r=n.exec(e))!==null;){let e=r[1]||``,n=ut((r[2]||``).trim());n&&(t.push({alt:e,path:n}),i=i.replace(r[0],``))}return{remainingText:i,attachments:t}}function ut(e){if(!e)return null;let t=e.trim();if(/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.replace(/\\/g,`/`).replace(/^\/+/,``).replace(/^\.\//,``);if(!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}var dt=class{messageCallback=null;running=!1;type=`room`;typingCallback=null;_manager=null;deliverInbound(e){this.messageCallback?.(e)}onMessage(e){this.messageCallback=e}onTyping(e){this.typingCallback=e}setManager(e){this._manager=e}setTyping(e,t){}start(){this.running=!0}stop(){this.running=!1}async send(e,t,n){if(!this._manager)return;let r=_e(e);this._manager.broadcast(r,t,n)}};const ft=1e3;var pt=class{abortController=null;fileReader=null;messageCallback=null;offset=0;pollRetryDelayMs=ft;pollSessionId=0;registeredChatIds=new Set;running=!1;token=``;type=`telegram`;useProxy=!1;buildFileUrl(e){let t=e.split(`/`).filter(Boolean).map(e=>encodeURIComponent(e)).join(`/`);return`${this.useProxy?`/telegram/file/bot`:`https://api.telegram.org/file/bot`}${this.token}/${t}`}buildMethodUrl(t){let n=t.replace(/^\/+/,``);return`${this.useProxy?e:c}${this.token}/${n}`}configure(e,t,n=!1){this.token=e.trim(),this.registeredChatIds=new Set(t.map(e=>e.trim()).filter(Boolean)),this.useProxy=!!n}isConfigured(){return this.token.length>0}nextPollRetryDelay(){let e=this.pollRetryDelayMs;return this.pollRetryDelayMs=Math.min(this.pollRetryDelayMs*2,6e4),e}onMessage(e){this.messageCallback=e}registerChatId(e){let t=e.trim();t&&this.registeredChatIds.add(t)}resetPollBackoff(){this.pollRetryDelayMs=ft}setTyping(e,t){if(!t)return;let n=e.replace(/^tg:/,``);this.apiCall(`sendChatAction`,{chat_id:n,action:`typing`}).catch(()=>{})}start(){if(!this.token||this.running)return;this.running=!0,this.resetPollBackoff();let e=++this.pollSessionId,t=new AbortController;this.abortController=t,this.poll(e,t)}stop(){this.running=!1,this.resetPollBackoff(),this.pollSessionId+=1,this.abortController?.abort(),this.abortController=null}async apiCall(e,t){let n=await fetch(this.buildMethodUrl(e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let t=await n.text();throw Error(`Telegram API ${e} failed: ${n.status} ${t}`)}return await n.json()}async extractAttachments(e){let t=[],n=Array.isArray(e.photo)?e.photo.at(-1):null;n?.file_id&&t.push({id:n.file_id,fileName:`photo-${e.message_id}.png`,mimeType:`image/png`,previewDisposition:`inline`}),e.document?.file_id&&t.push({id:e.document.file_id,fileName:e.document.file_name||`document-${e.message_id}`,mimeType:e.document.mime_type}),e.video?.file_id&&t.push({id:e.video.file_id,fileName:e.video.file_name||`video-${e.message_id}.mp4`,mimeType:e.video.mime_type||`video/mp4`}),e.audio?.file_id&&t.push({id:e.audio.file_id,fileName:e.audio.file_name||`audio-${e.message_id}.mp3`,mimeType:e.audio.mime_type||`audio/mpeg`}),e.voice?.file_id&&t.push({id:e.voice.file_id,fileName:`voice-${e.message_id}.ogg`,mimeType:e.voice.mime_type||`audio/ogg`}),e.animation?.file_id&&t.push({id:e.animation.file_id,fileName:e.animation.file_name||`animation-${e.message_id}.mp4`,mimeType:e.animation.mime_type||`video/mp4`}),e.sticker?.file_id&&t.push({id:e.sticker.file_id,fileName:`sticker-${e.message_id}.${gt(e.sticker)}`,mimeType:e.sticker.is_animated?`application/x-tgsticker`:e.sticker.is_video?`video/webm`:`image/webp`});let r=[];for(let e of t){let t=await this.fetchTelegramFileInfo(e.id);r.push({id:e.id,fileName:e.fileName,mimeType:e.mimeType,size:t.file_size,previewDisposition:e.previewDisposition,source:{kind:`remote-url`,url:this.buildFileUrl(t.file_path)}})}return r}async fetchTelegramFileInfo(e){let t=await this.apiCall(`getFile`,{file_id:e});if(!t.ok||!t.result?.file_path)throw Error(`Telegram getFile failed for attachment ${e}`);return t.result}async handleUpdate(e){let t=e.message;if(!t)return;let n=String(t.chat.id);if(t.text===`/chatid`){this.apiCall(`sendMessage`,{chat_id:n,text:`Chat ID: ${n}\nRegister this ID in ShadowClaw settings.`}).catch(console.error);return}if(t.text===`/ping`){this.apiCall(`sendMessage`,{chat_id:n,text:`Pong! ShadowClaw is running.`}).catch(console.error);return}if(!this.registeredChatIds.has(n))return;let r=await this.extractAttachments(t),i=`${t.text||t.caption||``}`.trim()||(t.photo?.length?`[Photo]`:null)||(t.voice?`[Voice message]`:null)||(t.video?`[Video]`:null)||(t.audio?`[Audio]`:null)||(t.animation?`[Animation]`:null)||(t.document?`[Document: ${t.document.file_name||`unnamed`}]`:null)||(t.sticker?`[Sticker: ${t.sticker.emoji||``}]`:null)||(t.location?`[Location: ${t.location.latitude}, ${t.location.longitude}]`:null)||(t.contact?`[Contact: ${t.contact.first_name}]`:null)||`[Unsupported message type]`,a=t.from?.first_name||t.from?.username||String(t.from?.id||`Unknown`),o={id:String(t.message_id),groupId:`tg:${n}`,sender:a,content:i,timestamp:t.date*1e3,channel:`telegram`,attachments:r};this.messageCallback?.(o)}async poll(e,t){for(;this.running&&this.pollSessionId===e&&!t.signal.aborted;)try{let e=await fetch(this.buildMethodUrl(`getUpdates?offset=${this.offset}&timeout=30`),{signal:t.signal});if(!e.ok){console.error(`Telegram poll error: HTTP ${e.status}`),await this.waitForRetry(this.nextPollRetryDelay());continue}let n=await e.json();if(!n.ok||!Array.isArray(n.result)){await this.waitForRetry(this.nextPollRetryDelay());continue}this.resetPollBackoff();for(let e of n.result)this.offset=e.update_id+1,await this.handleUpdate(e)}catch(e){if(e instanceof Error&&e.name===`AbortError`)break;console.error(`Telegram poll error:`,e),await this.waitForRetry(this.nextPollRetryDelay())}}async send(e,n,r){let i=e.replace(/^tg:/,``),{remainingText:a,attachments:o}=_t(n);for(let t of o){if(this.fileReader)try{let n=await this.fileReader(e,t.path);if(n&&n.size>0){let e=t.path.toLowerCase();e.endsWith(`.png`)||e.endsWith(`.jpg`)||e.endsWith(`.jpeg`)||e.endsWith(`.gif`)||e.endsWith(`.webp`)?await this.sendPhoto(i,n,t.alt,t.path):await this.sendDocument(i,n,t.alt,t.path);continue}}catch(e){console.warn(`TelegramChannel: failed to read file ${t.path}:`,e)}await this.apiCall(`sendMessage`,{chat_id:i,text:`[${t.alt}] (file: ${t.path})`})}let s=a.trim();if(s){let e=mt(s,t);for(let t of e)await this.apiCall(`sendMessage`,{chat_id:i,text:t})}}async sendDocument(e,t,n,r){let i=r.split(`/`).pop()||`document.file`,a=new FormData;a.append(`chat_id`,e),a.append(`document`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendDocument`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendDocument failed: ${o.status} ${e}`)}}async sendPhoto(e,t,n,r){let i=r.split(`/`).pop()||`image.png`,a=new FormData;a.append(`chat_id`,e),a.append(`photo`,t,i),n&&a.append(`caption`,n);let o=await fetch(this.buildMethodUrl(`sendPhoto`),{method:`POST`,body:a});if(!o.ok){let e=await o.text();throw Error(`Telegram sendPhoto failed: ${o.status} ${e}`)}}async waitForRetry(e){await ht(e)}};function mt(e,t){if(e.length<=t)return[e];let n=[],r=e;for(;r.length>0;){if(r.length<=t){n.push(r);break}let e=t,i=r.lastIndexOf(`
|
|
2
|
+
`,t);i>t*.5&&(e=i),n.push(r.slice(0,e)),r=r.slice(e)}return n}function ht(e){return new Promise(t=>setTimeout(t,e))}function gt(e){return e?.is_animated?`tgs`:e?.is_video?`webm`:`webp`}function _t(e){let t=[],n=/!?\[([^\]]*)\]\(([^)]+)\)/g,r,i=e;for(;(r=n.exec(e))!==null;){let e=r[1],n=vt((r[2]||``).trim());n&&(t.push({alt:e,path:n}),i=i.replace(r[0],``))}return{remainingText:i,attachments:t}}function vt(e){if(!e)return null;let t=e.trim();if(/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(t)||t.startsWith(`//`))return null;let n=t.replace(/\\/g,`/`).replace(/^\/+/,``).replace(/^\.\//,``);if(!n)return null;let r=n.split(`/`).filter(Boolean);return r.some(e=>e===`..`)?null:r.join(`/`)}function yt(e,t){let n=JSON.stringify(e.dataModel??{},null,2),r=t?`${t}`:`The user`;return`[A2UI ACTION]\nsurfaceId: "${e.surfaceId}"\nactionId: "${e.actionId}"\n`+(t?`firedBy: "${t}"\n`:``)+`dataModel:\n${n}\n\nInstructions: ${r} triggered the "${e.actionId}" action on surface "${e.surfaceId}". The dataModel above contains the current form values. Use the appropriate tool(s) to fulfill the action based on the actionId and dataModel values. After you have a result, call render_component with action "updateDataModel" on surfaceId "${e.surfaceId}" to update the surface (e.g. set path "/result" to the output value). Do NOT respond with plain text only — always update the surface via render_component.`}var bt=class{static formatMessagesXml(e){let t=e=>e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`);return`<messages>\n${e.map(e=>`<message sender="${t(e.sender)}" time="${new Date(e.timestamp).toISOString()}">${t(e.content)}</message>`).join(`
|
|
3
|
+
`)}\n</messages>`}static formatOutbound(e){return e.replace(/<internal>[\s\S]*?<\/internal>/g,``).trim()}registry;constructor(e){this.registry=e}findChannel(e){return this.registry.find(e)}setTyping(e,t){this.findChannel(e)?.setTyping(e,t)}async send(e,t,n){let r=this.findChannel(e);if(!r){console.warn(`No channel for groupId: ${e}`);return}await r.send(e,t,n)}};const xt={"litert-community/gemma-4-E2B-it-litert-lm":`https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it-web.litertlm`,"litert-community/gemma-4-E4B-it-litert-lm":`https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it-web.litertlm`},St=Object.keys(xt);function Ct(){return typeof navigator<`u`&&`gpu`in navigator&&typeof WebAssembly<`u`&&`Suspending`in WebAssembly}let wt=null,Tt=null,Et=null,Dt=null;const Ot=k;async function kt(e,t,n){return pe(e,t,n,{cacheName:`shadow-claw-litertlm-models`,chunkSize:Ot})}async function At(e,t,n){if(Tt===e&&wt)return wt;if(Et&&Dt===e)return Et;Dt=e,Et=(async()=>{if(wt){try{await wt.delete?.()}catch{}wt=null,Tt=null}let r=xt[e];if(!r)throw Error(`LiteRT-LM: Model '${e} is not supported. Supported models: ${St.join(`, `)}`);let i=await import(`./dist-DUy1CvmT.js`).catch(()=>{throw Error(`LiteRT-LM: The @litert-lm/core package is not installed. Run: npm install @litert-lm/core`)}),a=i.Engine??i.default?.Engine;if(typeof a?.create!=`function`)throw Error(`LiteRT-LM: Could not locate Engine.create in @litert-lm/core. Ensure you have the latest version installed.`);let o=await kt(r,t??(()=>{}),n),s=await a.create({model:o,mainExecutorSettings:{maxNumTokens:8192}});return wt=s,Tt=e,s})();try{return await Et}finally{Et=null,Dt=null}}function jt(e){if(!e)return null;let t=e.match(/<\|tool_call>call:([A-Za-z0-9_]+)(\{[\s\S]*?)(?:<tool_call\|>|$)/);if(!t)return null;let n=t[1],r=t[2];r=r.replace(/<\|"\|>/g,`"`);function i(e){return e.replace(/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\s*:)/g,`$1"$2"$3`)}let a={},o=[r,i(r)];for(let e of o)try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){a=t;break}}catch{}if(Object.keys(a).length===0){let e=r.indexOf(`{`),t=r.lastIndexOf(`}`);if(e>=0&&t>e){let n=r.slice(e,t+1);for(let e of[n,i(n)])try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t)){a=t;break}}catch{}}}return{name:n,input:a}}function Mt(e){let t=G(String(e||``),`litert_lm`).trim();if(!t)return null;let n=e=>{try{let t=JSON.parse(e);if(t&&typeof t==`object`&&(t.type===`tool_use`||t.type===`response`))return t.tools_calls&&!t.tool_calls&&(t.tool_calls=t.tools_calls),{...t,format:`json`}}catch{}return null},r=n(t);if(r)return r;let i=t.indexOf(`{`),a=t.lastIndexOf(`}`);if(i>=0&&a>i&&(r=n(t.slice(i,a+1)),r))return r;if(t.includes(`"tool_use"`)){let e=/"name"\s*:\s*"([^"]+)"/.exec(t);if(e){let n={},r=/"input"\s*:\s*(\{.*?\})\s*(?:]|\}|"|$)/s.exec(t);if(r)try{n=JSON.parse(r[1])}catch{}return{type:`tool_use`,format:`json`,tool_calls:[{id:`litert_${Date.now()}`,name:e[1],input:n}]}}}let o=jt(t);return o?{type:`tool_use`,format:`model_specific`,tool_calls:[{id:`litert_${Date.now()}`,name:o.name,input:o.input}]}:null}function Nt(e,t,n){let r=[],i=e||``;if(n.length>0){let e=[``,`TOOL CALLING INSTRUCTIONS:`,`Return ONLY valid JSON (no markdown fences).`,`To call a tool: {"type":"tool_use","tool_calls":[{"name":"<tool>","input":{...}}]}`,`To reply: {"type":"response","response":"<your answer>"}`,`IMPORTANT: When you need to use a tool, output ONLY the JSON above — do NOT describe the call as text.`,``,`Available tools:`,n.map(e=>{let t=Object.keys(e.input_schema.properties||{}).join(`, `),n=e.description.split(`. `)[0];return`${e.name}(${t}): ${n}`}).join(`
|
|
4
|
+
`)].join(`
|
|
5
|
+
`);i=i?i+e:e}i&&r.push({role:`system`,content:i});let a=[];for(let e of t)if(e.role===`user`){let t=Array.isArray(e.content)?e.content.map(e=>e?.type===`text`?e.text:e?.type===`tool_result`?`[TOOL_RESULT ${e.tool_use_id}] ${String(e.content||``)}`:``).filter(Boolean).join(`
|
|
6
|
+
`):String(e.content||``);t&&a.push(t)}else e.role;return{preface:r,turns:a}}async function Pt(e,t,n,r,i,a,o,s,c,l){if(!Ct()){await a({type:`response`,payload:{groupId:t,text:`⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.`}});return}await a(we(t,`info`,`Starting`,`Provider: LiteRT-LM (Browser · WebGPU) · Model: ${s}`)),await a({type:`model-download-progress`,payload:{groupId:t,status:`running`,progress:0,message:`Loading LiteRT-LM model: ${s}…`}});let u=e=>(e/(1024*1024)).toFixed(0),d=-1,f=(e,n,r)=>{let i=n?e/n:null,o=i==null?-1:Math.floor(i*100);o===d&&!r||(d=o,a({type:`model-download-progress`,payload:{groupId:t,status:`running`,progress:i,message:r?`Loaded ${s} from cache (${u(e)} MB )`:n?`Downloading ${s}: ${u(e)} / ${u(n)} MB`:`Downloading ${s}: ${u(e)} MB`}}))},p;try{p=await At(s,f,o)}catch(e){if(o?.aborted||e?.name===`AbortError`){await a({type:`model-download-progress`,payload:{groupId:t,status:`error`,progress:null,message:`LiteRT-LM model download cancelled.`}});return}await a({type:`model-download-progress`,payload:{groupId:t,status:`error`,progress:null,message:`LiteRT-LM model failed to load: ${e?.message??String(e)}`}}),await a({type:`response`,payload:{groupId:t,text:`⚠️ LiteRT-LM failed to initialize: ${e?.message??String(e)}`}});return}await a({type:`model-download-progress`,payload:{groupId:t,status:`done`,progress:1,message:`LiteRT-LM model ready.`}});let m=c??[],{preface:h,turns:g}=Nt(n,r,m),_;try{_=await p.createConversation({preface:{messages:h}})}catch(e){await a({type:`response`,payload:{groupId:t,text:`⚠️ LiteRT-LM failed to create conversation: ${e?.message??String(e)}`}});return}let v=g.slice(0,-1),y=g[g.length-1]??`Hello.`;for(let e of v){if(o?.aborted)return;try{await _.sendMessage(e)}catch{}}if(o?.aborted)return;let b=y;for(let n=0;n<10;n++){if(o?.aborted)return;await a({type:`streaming-start`,payload:{groupId:t}});let n=``;try{let e=_.sendMessageStreaming(b);for await(let r of e){if(o?.aborted)break;let e=r?.content?.[0]?.text??``;if(e){let r=G(e,`litert_lm`);r&&(n+=r,await a({type:`streaming-chunk`,payload:{groupId:t,text:r}}))}}}catch(e){if(o?.aborted)return;await a({type:`response`,payload:{groupId:t,text:`⚠️ LiteRT-LM generation error: ${e?.message??String(e)}`}});return}let r=m.length>0?Mt(n):null;if(r?.type===`tool_use`){await a({type:`streaming-end`,payload:{groupId:t}});let n=Array.isArray(r.tool_calls)?r.tool_calls:[];if(n.length===0){await a({type:`streaming-done`,payload:{groupId:t,text:`(no response)`}}),await a({type:`response`,payload:{groupId:t,text:`(no response)`}});return}let i=[],o=r.format===`model_specific`;for(let r of n){await a(H(t,r.name,`running`)),ye(e=>{a(e)});let n;try{n=await se(e,r.name,r.input||{},t,{allowedTools:m,invokeContext:l})}catch(e){n=`Error: ${e?.message??String(e)}`}finally{ye(null)}await a(H(t,r.name,`done`));let s=typeof n==`string`?n:JSON.stringify(n);o?i.push(`<|tool_response>${s}<|tool_response|>`):i.push(`[TOOL_RESULT ${r.id??r.name}] ${s}`)}if(o)b=i.join(`
|
|
7
|
+
`);else{let e=g[g.length-1]??``;b=[...i,``,`Based on the above tool results, please respond to the original request.`,e?`Original request: "${e}"`:``].filter(Boolean).join(`
|
|
8
|
+
`)}continue}let i;i=r?.type===`response`&&r.response?G(r.response,`litert_lm`):G(n,`litert_lm`),await a({type:`streaming-done`,payload:{groupId:t,text:i}}),await a({type:`response`,payload:{groupId:t,text:i}});return}await a({type:`response`,payload:{groupId:t,text:`⚠️ LiteRT-LM reached the maximum number of tool-calling iterations without producing a final response.`}})}const Ft=new class{chunkCallbacks=new Map;loadRejects=new Map;loadResolves=new Map;pendingRejects=new Map;pendingResolves=new Map;progressCallbacks=new Map;thinkingCallbacks=new Map;worker=null;async generate(e,t,n,r,i,a){let o=this.getWorker();return new Promise((s,c)=>{this.pendingResolves.set(n,s),this.pendingRejects.set(n,c),this.chunkCallbacks.set(n,e=>r(e.text)),i&&this.thinkingCallbacks.set(n,i),o.postMessage({type:`generate`,payload:{messages:e,maxTokens:t,groupId:n,tools:a}})})}async load(e,t,n,r,i){let a=this.getWorker();return new Promise((o,s)=>{this.loadResolves.set(r,o),this.loadRejects.set(r,s),this.progressCallbacks.set(r,i),a.postMessage({type:`load`,payload:{modelId:e,device:t,dtypeStrategy:n,groupId:r}})})}cleanup(e){this.pendingResolves.delete(e),this.pendingRejects.delete(e),this.progressCallbacks.delete(e),this.chunkCallbacks.delete(e),this.thinkingCallbacks.delete(e)}getWorker(){return this.worker||(this.worker=new Worker(S(new URL(`./transformers-js.worker.js`,import.meta.url).href),{type:`module`}),this.worker.onmessage=e=>{let{type:t,payload:n}=e.data,r=n?.groupId;switch(t){case`progress`:this.progressCallbacks.get(r)?.(n),n.status===`done`&&(this.loadResolves.get(r)?.(),this.loadResolves.delete(r),this.loadRejects.delete(r));break;case`chunk`:this.chunkCallbacks.get(r)?.(n);break;case`thinking-chunk`:this.thinkingCallbacks.get(r)?.(n.text);break;case`done`:this.pendingResolves.get(r)?.(n.text),this.cleanup(r);break;case`error`:this.pendingRejects.get(r)?.(n.error),this.loadRejects.get(r)?.(n.error),this.cleanup(r),this.loadResolves.delete(r),this.loadRejects.delete(r);break}}),this.worker}};function It(e){return typeof e?.content==`string`?e.content:Array.isArray(e?.content)?e.content.map(e=>e?.type===`text`?e.text||``:e?.type===`tool_use`?`[TOOL_CALL ${e.name}] ${JSON.stringify(e.input||{})}`:e?.type===`tool_result`?`[TOOL_RESULT ${e.tool_use_id}] ${String(e.content||``)}`:e?.type===`attachment`?`[ATTACHMENT ${e.mediaType}] ${e.fileName} (${e.mimeType})`:``).filter(Boolean).join(`
|
|
9
|
+
`):``}function Lt(e){let t=G(String(e||``),`transformers_js`).trim();if(!t)return null;let n=t.match(/<tool_call>([\s\S]*?)<\/tool_call>/);if(n)try{let e=JSON.parse(n[1]);if(e.name)return{type:`tool_use`,tool_calls:[{name:e.name,input:e.arguments||e.parameters||{}}]}}catch{}try{return JSON.parse(t)}catch{let e=t.indexOf(`{`),n=t.lastIndexOf(`}`);if(e>=0&&n>e)try{return JSON.parse(t.slice(e,n+1))}catch{return null}return null}}async function Rt(e,t,n,r,i,a,o,s,c,l){let u=s||[],d=await x(e,m.TRANSFORMERS_JS_BACKEND)||`auto`,f=await x(e,m.TRANSFORMERS_JS_DTYPE_STRATEGY)||`auto`;await a(we(t,`info`,`Starting`,`Provider: Transformers.js (Local Worker) · Model: ${c} · Backend: ${d} · Dtype: ${f}`)),await Ft.load(c,d,f,t,e=>{a({type:`model-download-progress`,payload:e})});let p=[...r];for(let r=0;r<10;r++){let r=[{role:`system`,content:n},...p.map(e=>({role:e.role===`assistant`?`assistant`:`user`,content:It(e)}))];await a({type:`streaming-start`,payload:{groupId:t}});let o=``,s=``,c=await Ft.generate(r,i,t,e=>{s+=e,a({type:`streaming-chunk`,payload:{groupId:t,text:e}})},e=>{o+=e,a(we(t,`text`,`Thinking`,o))},u);await a({type:`typing`,payload:{groupId:t}});let d=Lt(c);if(d?.type===`tool_use`?await a({type:`streaming-end`,payload:{groupId:t}}):await a({type:`streaming-done`,payload:{groupId:t,text:d?.response?G(d.response,`transformers_js`):G(c,`transformers_js`)}}),!d||d.type===`response`){await a({type:`response`,payload:{groupId:t,text:d?.response?G(d.response,`transformers_js`):G(c,`transformers_js`)}});return}let f=Array.isArray(d.tool_calls)?d.tool_calls:[];if(f.length===0){await a({type:`response`,payload:{groupId:t,text:G(d.response||c,`transformers_js`)}});return}let m=[];for(let n of f){await a(H(t,n.name,`running`)),ye(e=>{a(e)});let r;try{r=await se(e,n.name,n.input||{},t,{allowedTools:u,invokeContext:l})}finally{ye(null)}await a(H(t,n.name,`done`)),m.push({type:`tool_result`,tool_use_id:n.id||`call_${Date.now()}`,content:typeof r==`string`?r:JSON.stringify(r)})}p.push({role:`assistant`,content:[...d.response?[{type:`text`,text:d.response}]:[],...f.map(e=>({type:`tool_use`,id:e.id||`call_${Date.now()}_${Math.random()}`,name:e.name,input:e.input||{}}))]}),p.push({role:`user`,content:m})}}function zt(e,t,n){let r=t.input_tokens||0,i=t.output_tokens||0,a=t.cache_read_input_tokens||0,o=t.cache_creation_input_tokens||0;return{type:`token-usage`,payload:{groupId:e,inputTokens:r,outputTokens:i,cacheReadTokens:a,cacheCreationTokens:o,totalTokens:r+i+a+o,contextLimit:n}}}function Z(e,t,n,r){K(we(e,t,n,r))}async function*Bt(e,t){let n=e.getReader(),r=new TextDecoder,i=``;try{for(;!t?.aborted;){let{done:e,value:t}=await n.read();if(e)break;i+=r.decode(t,{stream:!0});let a=i.split(`
|
|
10
|
+
|
|
11
|
+
`);i=a.pop()||``;for(let e of a){let t=e.split(`
|
|
12
|
+
`);for(let e of t)if(!(!e||e.startsWith(`:`))&&e.startsWith(`data: `)){let t=e.slice(6).trim();if(t===`[DONE]`)continue;try{yield JSON.parse(t)}catch{}}}}}finally{n.releaseLock()}}const Vt=6e4,Ht=new Map;function Ut(e){let t=Ht.get(e);if(t)return t;let n={recentCalls:[],nextAllowedAt:0,remoteLimit:null,remoteRemaining:null,remoteResetAt:null};return Ht.set(e,n),n}function Wt(){return Date.now()}function Gt(e){if(!e)return null;let t=Number(e.trim());return Number.isFinite(t)?t:null}function Kt(e){if(!e)return null;let t=e.trim(),n=Number(t);if(Number.isFinite(n))return n<=0?null:Math.round(n*1e3);let r=Date.parse(t);if(!Number.isFinite(r))return null;let i=r-Wt();return i>0?i:null}function qt(e){let t=Gt(e);return t===null||t<=0?null:t>=0xe8d4a51000?Math.round(t):t>=1e9?Math.round(t*1e3):Wt()+Math.round(t*1e3)}async function Jt(e,t){e<=0||await new Promise((n,r)=>{let i=setTimeout(()=>{o(),n()},e),a=()=>{o(),r(new DOMException(`Aborted`,`AbortError`))},o=()=>{i&&=(clearTimeout(i),null),t?.removeEventListener(`abort`,a)};if(t?.aborted){a();return}t?.addEventListener(`abort`,a)})}function Yt(e,t){if(!Number.isFinite(t)||t<=0)return 0;let n=Wt();if(e.recentCalls=e.recentCalls.filter(e=>n-e<Vt),e.recentCalls.length<t)return 0;let r=e.recentCalls[0]||n;return Math.max(0,Vt-(n-r))}function Xt(e){let t=Wt(),n=0;return e.nextAllowedAt>t&&(n=Math.max(n,e.nextAllowedAt-t)),e.remoteRemaining!==null&&e.remoteRemaining<=0&&e.remoteResetAt!==null&&e.remoteResetAt>t&&(n=Math.max(n,e.remoteResetAt-t)),n}async function Zt(e,t,n,r){let i=Ut(e);for(;;){let e=Yt(i,n.callsPerMinute),a=n.autoAdapt?Xt(i):0,o=Math.max(e,a);if(o<=0){let e=Wt();if(n.callsPerMinute>0&&i.recentCalls.push(e),n.autoAdapt&&i.remoteRemaining!==null&&i.remoteRemaining>0&&i.remoteResetAt!==null&&i.remoteResetAt>e){let t=i.remoteResetAt-e,n=Math.max(1,i.remoteRemaining),r=Math.ceil(t/n);i.nextAllowedAt=Math.max(i.nextAllowedAt,e+r)}return}o>=1e3&&K({type:`thinking-log`,payload:{groupId:t,level:`info`,label:`Rate limiter`,message:`Waiting ${Math.ceil(o/1e3)}s before next provider call to avoid 429s.`,timestamp:Date.now()}}),await Jt(o,r)}}function Qt(e,t,n){if(!n.autoAdapt||!t||typeof t.get!=`function`)return;let r=Ut(e),i=Wt(),a=Gt(t.get(`x-ratelimit-limit`)),o=Gt(t.get(`x-ratelimit-remaining`)),s=qt(t.get(`x-ratelimit-reset`));a!==null&&(r.remoteLimit=Math.max(0,Math.floor(a))),o!==null&&(r.remoteRemaining=Math.max(0,Math.floor(o))),s!==null&&(r.remoteResetAt=s);let c=Kt(t.get(`retry-after`));c!==null&&(r.nextAllowedAt=Math.max(r.nextAllowedAt,i+c)),r.remoteRemaining!==null&&r.remoteRemaining<=0&&r.remoteResetAt!==null&&r.remoteResetAt>i&&(r.nextAllowedAt=Math.max(r.nextAllowedAt,r.remoteResetAt))}var $t=class{callbacks;contentBlocks=[];format;stopReason=`end_turn`;usage={input_tokens:0,output_tokens:0};#e=new Map;#t=``;#n=``;#r=new Map;constructor(e,t={}){this.format=e,this.callbacks=t}finalize(){return this.format===`openai`||this.format===`mesh-llm`?this.#a():this.#i()}push(e){this.format===`openai`||this.format===`mesh-llm`?this.#s(e):this.#o(e)}#i(){let e=[];for(let[,t]of[...this.#e.entries()].sort((e,t)=>e[0]-t[0]))if(t.type===`text`){let n=this.#c(t.text||``);n&&e.push({type:`text`,text:n})}else if(t.type===`tool_use`){let n;try{n=t.partialJson?JSON.parse(t.partialJson):{}}catch{n={}}e.push({type:`tool_use`,id:t.id||`call_${Date.now()}_${Math.random()}`,name:t.name,input:n})}else t.type===`thinking`?typeof t.text==`string`&&t.text.length>0&&e.push({type:`thinking`,thinking:t.text,...typeof t.id==`string`?{signature:t.id}:{}}):t.type===`redacted_thinking`&&typeof t.text==`string`&&t.text.length>0&&e.push({type:`redacted_thinking`,data:t.text});return{content:e,stop_reason:this.stopReason,usage:{...this.usage}}}#a(){let e=[];if(this.#n){let t=this.#c(this.#n);t&&e.push({type:`text`,text:t})}if(this.#t&&e.unshift({type:`thinking`,thinking:this.#t}),this.#r.size>0){this.stopReason=`tool_use`;for(let[,t]of[...this.#r.entries()].sort((e,t)=>e[0]-t[0])){let n;try{n=t.args?JSON.parse(t.args):{}}catch{n={}}e.push({type:`tool_use`,id:t.id||`call_${Date.now()}_${Math.random()}`,name:t.name,input:n})}}return{content:e,stop_reason:this.stopReason,usage:{...this.usage}}}#o(e){switch(e.type){case`message_start`:e.message?.usage&&(this.usage.input_tokens=e.message.usage.input_tokens||0,this.usage.cache_read_input_tokens=e.message.usage.cache_read_input_tokens||0,this.usage.cache_creation_input_tokens=e.message.usage.cache_creation_input_tokens||0);break;case`content_block_start`:{let t=e.index??this.#e.size,n=e.content_block||{};this.#e.set(t,{type:n.type||`text`,id:n.type===`thinking`?n.signature:n.id,name:n.name,text:n.text||n.thinking||n.data||``,partialJson:n.type===`tool_use`?``:void 0}),n.type===`tool_use`&&n.name&&this.callbacks.onToolStart?.(n.name);break}case`content_block_delta`:{let t=e.index??0,n=this.#e.get(t);if(!n){let r=e.delta?.type===`input_json_delta`?`tool_use`:`text`;n={type:r,text:r===`text`?``:void 0,partialJson:r===`tool_use`?``:void 0},this.#e.set(t,n)}let r=e.delta;if(!r)break;if(r.type===`text_delta`&&typeof r.text==`string`){let e=this.#c(r.text);if(!e)break;n.text=(n.text||``)+e,this.callbacks.onText?.(e)}r.type===`thinking_delta`&&typeof r.thinking==`string`&&(n.type=`thinking`,n.text=(n.text||``)+r.thinking,this.callbacks.onThinking?.(r.thinking)),r.type===`signature_delta`&&typeof r.signature==`string`&&(n.type=`thinking`,n.id=r.signature),r.type===`redacted_thinking_delta`&&typeof r.data==`string`&&(n.type=`redacted_thinking`,n.text=(n.text||``)+r.data),r.type===`input_json_delta`&&typeof r.partial_json==`string`&&(n.partialJson=(n.partialJson||``)+r.partial_json);break}case`content_block_stop`:break;case`message_delta`:e.delta?.stop_reason&&(this.stopReason=e.delta.stop_reason),e.usage&&(this.usage.output_tokens=e.usage.output_tokens||0,this.callbacks.onUsage?.(this.usage));break;case`message_stop`:break;default:break}}#s(e){e.usage&&(this.usage.input_tokens=e.usage.prompt_tokens||0,this.usage.output_tokens=e.usage.completion_tokens||0,this.usage.cache_read_input_tokens=e.usage.prompt_tokens_details?.cached_tokens||0,this.callbacks.onUsage?.(this.usage));let t=e.choices?.[0];if(!t)return;let n=t.delta;if(n){if(typeof n.content==`string`){let e=this.#c(n.content);e&&(this.#n+=e,this.callbacks.onText?.(e))}if(typeof n.reasoning==`string`)this.#t+=n.reasoning,this.callbacks.onThinking?.(n.reasoning);else if(n.reasoning&&typeof n.reasoning==`object`){let e=n.reasoning;typeof e.content==`string`?(this.#t+=e.content,this.callbacks.onThinking?.(e.content)):typeof e.text==`string`&&(this.#t+=e.text,this.callbacks.onThinking?.(e.text))}if(Array.isArray(n.tool_calls))for(let e of n.tool_calls){let t=e.index??0;this.#r.has(t)||(this.#r.set(t,{id:e.id||``,name:e.function?.name||``,args:``}),e.function?.name&&this.callbacks.onToolStart?.(e.function.name));let n=this.#r.get(t);n&&(e.id&&(n.id=e.id),e.function?.name&&(n.name=e.function.name),e.function?.arguments&&(n.args+=e.function.arguments))}t.finish_reason&&(t.finish_reason===`tool_calls`?this.stopReason=`tool_use`:t.finish_reason===`stop`?this.stopReason=`end_turn`:this.stopReason=t.finish_reason)}}#c(e){return G(e,this.callbacks.source??this.format)}};const en=new Map;function tn(e){return en.get(e)}function nn(e){en.delete(e)}function rn(e,t){let n=e.trim().match(/^\[tool_code\]([\s\S]*?)\[\/tool_code\]$/i);if(!n?.[1])return{toolBlocks:[],residualText:e};let r=n[1].trim(),i=r.match(/^print\s*\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\(\s*(.*?)\s*\)\s*\)$/s),a=r.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*\(\s*(.*?)\s*\)$/s),o=i||a;if(!o?.[1])return{toolBlocks:[],residualText:e};let s=o[1];if(!t.has(s))return{toolBlocks:[],residualText:e};let c=(o[2]||``).trim(),l={};if(c){if(!c.startsWith(`{`)||!c.endsWith(`}`))return{toolBlocks:[],residualText:e};try{let t=JSON.parse(c);if(!t||typeof t!=`object`||Array.isArray(t))return{toolBlocks:[],residualText:e};l=t}catch{return{toolBlocks:[],residualText:e}}}return{toolBlocks:[{type:`tool_use`,id:`tool_code_${Date.now()}_${Math.random()}`,name:s,input:l}],residualText:``}}function an(e,t){if(!e||e.stop_reason===`tool_use`||!Array.isArray(e.content))return e;let n=new Set((t||[]).map(e=>typeof e?.name==`string`?e.name:``).filter(Boolean));if(n.size===0)return e;let r=[],i=!1;for(let t of e.content){if(t?.type!==`text`||typeof t.text!=`string`){r.push(t);continue}let e=rn(t.text,n);if(e.toolBlocks.length>0){i=!0,e.residualText.trim()&&r.push({type:`text`,text:e.residualText}),r.push(...e.toolBlocks);continue}r.push(t)}return i?{...e,content:r,stop_reason:`tool_use`}:e}function on(e){let t=e.filter(e=>e?.type===`tool_result`).map(e=>typeof e.content==`string`?e.content.trim():Array.isArray(e.content)?e.content.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
13
|
+
`).trim():JSON.stringify(e.content).trim()).filter(Boolean);return t.length===0?``:t.join(`
|
|
14
|
+
|
|
15
|
+
`).slice(0,1e4)}function sn(e){let t=e.trim();return t?`Tool result:\n${t}`:``}async function cn(e,t,r){let{apiKey:i,assistantName:a,contextCompression:o=!1,contextLimit:s,enabledTools:c,groupId:l,isScheduledTask:u=!1,maxIterations:d,maxTokens:f,memory:p,messages:m,model:h,provider:g,providerHeaders:_={},providerRuntimeOverrides:v,reasoning:y,rateLimitAutoAdapt:b=!0,rateLimitCallsPerMinute:x=0,storageHandle:S,streaming:C=!1,subagentModelSelectionMode:w,subagentMaxTokens:T,subagentPinnedModel:E,subagentPinnedProvider:D,systemPrompt:O,workspaceGroupId:k}=t,A=!!t.subagentTask,j=A?l.startsWith(`subagent:`)?l:`subagent:${Y()}`:l,M=k||l;A&&ke(j,[]);let N={autoAdapt:b!==!1,callsPerMinute:Number.isFinite(x)?Math.max(0,Math.floor(x)):0};S&&He(S);let P=n(g);if(!P){K({payload:{groupId:j,error:`Unknown provider: ${g}`},type:`error`});return}let F=P,I=C&&F.supportsStreaming===!0&&F.format!==`prompt_api`;K({type:`typing`,payload:{groupId:j}}),Z(j,`info`,`Starting`,`Provider: ${F.name} · Model: ${h} · Max tokens: ${f} · Streaming: ${I?`on`:`off`}${C&&!I?` (provider does not support streaming)`:``}`);try{let t=[...m],n=0,l=typeof d==`number`&&d>0?d:50,b=Array.isArray(c)?c:Ee,x=O,C=``,k={apiKey:i,assistantName:a??``,db:e,enabledTools:b,invokeSubagent:t=>dn(e,t,r),maxTokens:f,memory:p??``,model:h,provider:g,subagentModelSelectionMode:w,subagentMaxTokens:T,subagentPinnedProvider:D,subagentPinnedModel:E,providerHeaders:_,providerRuntimeOverrides:v,storageHandle:S,streaming:!1,systemPrompt:x??``},A=[];for(;n<l;){n++;let c=tn(j);c&&(b=c.enabledTools,x=ne(a,p,b,c.systemPromptOverride));let l=s??U(h),d=te(x),{messages:m,estimatedTokens:v}=ce(t,{contextLimit:l,maxOutputTokens:f,skimTop:o,systemPromptTokens:d}),S=v+d,w=Math.max(100,Math.min(f,l-S-500)),T=z(F,m,b,{contextCompression:o,maxTokens:w,model:h,reasoning:y,system:x});Z(j,`api-call`,`API call #${n}`,`${m.length} messages in context`);let E={...ee(F,i),..._},D=F.baseUrl,O;O=I?await un(g,F,D,E,T,j,h,N,r):await ln(g,F,D,E,T,j,N,r),O=an(O,b),O.usage&&K(zt(j,O.usage,U(h)));for(let e of O.content)e.type===`text`&&e.text&&Z(j,`text`,`Response text`,e.text.length>200?e.text.slice(0,200)+`…`:e.text);if(O.stop_reason===`tool_use`){let n=new Set(b.map(e=>typeof e?.name==`string`?e.name:``).filter(Boolean)),r=O.content.filter(e=>e.type===`text`).map(e=>e.text).join(``).replace(/<internal>[\s\S]*?<\/internal>/g,``).trim();r&&K({payload:{groupId:j,text:r},type:`intermediate-response`}),I&&K({payload:{groupId:j},type:`streaming-end`});let i=[];for(let t of O.content)if(t.type===`tool_use`){let r=n.has(t.name),a=`${t.name}:${JSON.stringify(t.input)}`,o=A.filter(e=>e===a).length;if(A.push(a),!r){let e=`SYSTEM ERROR: Tool '${t.name}' is disabled or unavailable for this request. Do not call it again. Try a different approach or ask the user for help.`;Z(j,`warning`,`Tool blocked`,e),i.push({content:e,tool_use_id:t.id,type:`tool_result`});continue}let s=JSON.stringify(t.input),c=s.length>300?s.slice(0,300)+`…`:s;Z(j,`tool-call`,`Tool: ${t.name}`,c),K(H(j,t.name,`running`));let l;o>=3?(l=`SYSTEM ERROR: You have repeatedly called this tool with the exact same input (${o+1} times). This is a rigid loop. STOP calling this tool with these arguments. Try a different approach, fix the underlying issue, or ask the user for help.`,console.warn(`[Worker] Blocked repetitive tool call:`,a)):l=await se(e,t.name,t.input,M,{allowedTools:b,isScheduledTask:u,invokeContext:k});let d=typeof l==`string`?l:JSON.stringify(l),f=d.length>500?d.slice(0,500)+`…`:d;Z(j,`tool-result`,`Result: ${t.name}`,f),K(H(j,t.name,`done`)),Array.isArray(l)?i.push({content:l,tool_use_id:t.id,type:`tool_result`}):i.push({content:typeof l==`string`?l.slice(0,1e5):JSON.stringify(l).slice(0,1e5),tool_use_id:t.id,type:`tool_result`})}C=on(i),t.push({role:`assistant`,content:O.content}),t.push({role:`user`,content:i}),K({type:`typing`,payload:{groupId:j}})}else{let e=O.content.filter(e=>e.type===`text`).map(e=>e.text).join(``).replace(/<internal>[\s\S]*?<\/internal>/g,``).trim(),t=(e.toLowerCase()===`(no response)`?``:e)||(C?sn(C):`(no response)`);I&&K({payload:{groupId:j,text:t},type:`streaming-done`}),K({payload:{groupId:j,text:t},type:`response`});return}}K({payload:{text:`⚠️ Reached maximum tool-use iterations (${l}). Stopping to avoid excessive API usage.`,groupId:j},type:`response`})}catch(e){if(e instanceof Error&&e.name===`AbortError`)return;let t=e instanceof Error?e.message:String(e);I&&K({payload:{groupId:j,error:t},type:`streaming-error`}),K({type:`error`,payload:{groupId:j,error:t}})}finally{nn(j),A&&Pe(j)}}async function ln(e,t,n,r,i,a,o,s){return N(async()=>{await Zt(e,a,o,s);let c=await fetch(n,{body:JSON.stringify(i),headers:r,method:`POST`,signal:s});if(Qt(e,c.headers,o),!c.ok){let e=await c.text(),n=Error(`${t.name} API error ${c.status}: ${e}`);throw n.status=c.status,n}return je(t,await c.json())},{baseDelayMs:2e3,jitterFactor:.5,maxDelayMs:3e4,maxRetries:3,onRetry:(e,t,n,r)=>{let i=r instanceof Error?r.message:String(r);Z(a,`warning`,`Retrying API call (${e}/${t})`,i),K({type:`show-toast`,payload:{message:`LLM API: Retrying (${e}/${t})… ${i.slice(0,120)}`,type:`warning`,duration:5e3}})},shouldRetry:e=>D(e),signal:s})}async function un(e,t,n,r,i,a,o,s,c){let l={...i,stream:!0,...(t.format===`openai`||t.format===`mesh-llm`)&&{stream_options:{include_usage:!0}}};await Zt(e,a,s,c);let u=await fetch(n,{body:JSON.stringify(l),headers:r,method:`POST`,signal:c});if(Qt(e,u.headers,s),!u.ok){let e=await u.text(),n=Error(`${t.name} API error ${u.status}: ${e}`);throw n.status=u.status,n}if(!u.body)throw Error(`Streaming response has no body`);K({payload:{groupId:a},type:`streaming-start`});let d=0,f=``,p=0,m=``,h=(e=!1)=>{let t=Date.now();m&&(!e&&t-p<50||(Z(a,`info`,`Reasoning`,m.length>400?`${m.slice(0,400)}…`:m),m=``,p=t))},g=new $t(t.format,{source:t.id,onText:e=>{let t=Date.now();f+=e,t-d>=50&&(K({payload:{groupId:a,text:f},type:`streaming-chunk`}),f=``,d=t)},onToolStart:e=>{K(H(a,e,`running`))},onUsage:e=>{K(zt(a,e,U(o)))},onThinking:e=>{m+=e,h(!1)}});for await(let e of Bt(u.body,c))g.push(e);f&&K({payload:{groupId:a,text:f},type:`streaming-chunk`}),h(!0);let _=g.finalize();return t.format===`mesh-llm`&&(_=w(_)),_}async function dn(e,t,n){let r=t.provider,i=async e=>{K(e)};if(r===`transformers_js_browser`){await Rt(e,t.groupId,t.systemPrompt,t.messages,t.maxTokens,i,n,t.enabledTools,t.model);return}if(r===`prompt_api`){if(!R())throw Error(`Prompt API provider is not supported in this environment.`);await ie(e,t.groupId,t.systemPrompt,t.messages,t.maxTokens,i,n,t.enabledTools);return}if(r===`litert_lm_browser`){if(!Ct())throw Error(`Litert LM Browser provider is not supported in this environment.`);await Pt(e,t.groupId,t.systemPrompt,t.messages,t.maxTokens,i,n,t.model,t.enabledTools);return}await cn(e,t,n)}async function fn(e,t,r,i,a=!1,s=!1){let c=s?`subagent:${Y()}`:r;if(e.inFlightTriggerByGroup.set(c,i),e.setState(`thinking`,c),e.router?.setTyping(c,!0),e.events.emit(`typing`,{groupId:c,typing:!0}),i.startsWith(`[SCHEDULED TASK]`)){e.pendingScheduledTasks.add(r);let n={id:Y(),groupId:r,sender:`Scheduler`,content:i,timestamp:Date.now(),channel:De(e,r),isFromMe:!1,isTrigger:!0};await le(t,n),e.events.emit(`message`,n)}let l=``;try{l=await ve(t,r,`MEMORY.md`)}catch{}let u=(await Be(t)).find(e=>e.groupId===r),d=u?.pinnedProvider??e.provider,f=u?.pinnedModel??(u?.pinnedProvider?n(u.pinnedProvider)?.defaultModel??e.model:e.model),p=typeof u?.pinnedMaxTokens==`number`&&Number.isFinite(u.pinnedMaxTokens)&&u.pinnedMaxTokens>0?Math.floor(u.pinnedMaxTokens):e.maxTokens,h=f;d===`prompt_api`&&(f===`browser-built-in`||!f)&&!R()&&(h=await x(t,m.PROMPT_API_FALLBACK_MODEL)||`onnx-community/Qwen3-0.6B-ONNX`);let g=Math.max(1,Math.min(p,o(h))),_=n(d)??e.providerConfig;e.inFlightEffectiveProviderByGroup.set(c,{providerId:d,providerConfig:_,model:f});let v=Array.isArray(u?.toolTags)?W.allTools.filter(e=>u.toolTags.includes(e.name)):W.enabledTools,y=(await Oe(t,c)).tools.filter(e=>!W.allTools.some(t=>t.name===e.name)),b=Array.isArray(u?.toolTags)?y.filter(e=>u.toolTags.includes(e.name)):y.filter(e=>W.isDeclarativeToolEnabled(e.name)),S=[...v,...b],C=await I(t,c),w=C.skills.length>0&&!S.some(e=>e.name===qe.name)?[...S,qe]:S,T=u?.subagentModelSelectionMode===`manual`?`manual`:`automatic`,E=u?.subagentMaxTokens,ee=u?.subagentPinnedProvider,D=u?.subagentPinnedModel,k=u?.subagentFastProvider,A=u?.subagentFastModel,M=u?.subagentSmartProvider,N=u?.subagentSmartModel,P=u?.subagentPowerfulProvider,F=u?.subagentPowerfulModel,L=u?.providerRuntimeOverrides,ae=q.getPeerState(r)||void 0,z=ne(e.assistantName,l,w,W.systemPromptOverride,ae,C.skills),oe=U(h),se=te(z)+(w?.reduce((e,t)=>e+te(JSON.stringify(t)),0)??0),B=await Ve(r,200);a&&(B=B.length>0?[B[B.length-1]]:[{role:`user`,content:i}]);let V=ce(B,{contextLimit:oe,systemPromptTokens:se,maxOutputTokens:g,skimTop:e.contextCompressionEnabled}),ue=V.messages,de=V.estimatedTokens+se;if(q.tokenUsage){let e=q.tokenUsage,t=(e.inputTokens||0)+(e.cacheReadTokens||0)+(e.outputTokens||0);de=Math.max(de,t)}if(e.events.emit(`context-usage`,{estimatedTokens:de,contextLimit:oe,usagePercent:Math.min(100,Math.max(V.usagePercent,de/oe*100)),truncatedCount:V.truncatedCount}),V.usagePercent>80&&V.truncatedCount>0&&B.length>10&&(e.events.emit(`show-toast`,{message:`Context ${V.usagePercent.toFixed(0)}% full — auto-compacting older messages…`,type:`info`,duration:4e3}),queueMicrotask(()=>Ae(e,t,r))),d===`transformers_js_browser`){let n=new AbortController;e.promptControllers.set(c,n);let r={apiKey:``,assistantName:e.assistantName,db:t,enabledTools:w,invokeSubagent:async e=>{await dn(t,e,n.signal)},maxTokens:g,memory:l??``,model:f,provider:d,providerHeaders:ge(e,d,``,L),providerRuntimeOverrides:L,streaming:!1,subagentModelSelectionMode:T,subagentMaxTokens:E,subagentPinnedProvider:ee,subagentPinnedModel:D,subagentFastProvider:k,subagentFastModel:A,subagentSmartProvider:M,subagentSmartModel:N,subagentPowerfulProvider:P,subagentPowerfulModel:F,systemPrompt:z};try{await Rt(t,c,z,ue,g,async n=>{await re(e,t,n)},n.signal,w,f,r)}catch(n){if(n instanceof Error&&n.name===`AbortError`)return;await ze(e,t,c,`⚠️ Error: ${n instanceof Error?n.message:String(n)}`)}finally{e.promptControllers.delete(c)}return}if(d===`prompt_api`){if(R()||await j(),!R()){await ze(e,t,c,`⚠️ Error: Prompt API is not available in this browser. Switch provider or enable experimental browser flags.`);return}let n=new AbortController;e.promptControllers.set(c,n);let r={apiKey:``,assistantName:e.assistantName,db:t,enabledTools:w,invokeSubagent:async e=>{await dn(t,e,n.signal)},maxTokens:g,memory:l??``,model:f,provider:d,providerHeaders:ge(e,d,``,L),providerRuntimeOverrides:L,streaming:!1,subagentModelSelectionMode:T,subagentMaxTokens:E,subagentPinnedProvider:ee,subagentPinnedModel:D,subagentFastProvider:k,subagentFastModel:A,subagentSmartProvider:M,subagentSmartModel:N,subagentPowerfulProvider:P,subagentPowerfulModel:F,systemPrompt:z};try{await ie(t,c,z,ue,g,async n=>{await re(e,t,n)},n.signal,w,r)}catch(n){if(n instanceof Error&&n.name===`AbortError`)return;await ze(e,t,c,`⚠️ Error: ${n instanceof Error?n.message:String(n)}`)}finally{e.promptControllers.delete(c)}return}if(d===`litert_lm_browser`){if(!Ct()){await ze(e,t,c,`⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.`);return}let n=new AbortController;e.promptControllers.set(c,n);let r={apiKey:``,assistantName:e.assistantName,db:t,enabledTools:w,invokeSubagent:async e=>{await dn(t,e,n.signal)},maxTokens:g,memory:l??``,model:f,provider:d,providerHeaders:ge(e,d,``,L),providerRuntimeOverrides:L,streaming:!1,subagentModelSelectionMode:T,subagentMaxTokens:E,subagentPinnedProvider:ee,subagentPinnedModel:D,subagentFastProvider:k,subagentFastModel:A,subagentSmartProvider:M,subagentSmartModel:N,subagentPowerfulProvider:P,subagentPowerfulModel:F,systemPrompt:z};try{await Pt(t,c,z,ue,g,async n=>{await re(e,t,n)},n.signal,f,w,r)}catch(n){if(n instanceof Error&&n.name===`AbortError`)return;await ze(e,t,c,`⚠️ Error: ${n instanceof Error?n.message:String(n)}`)}finally{e.promptControllers.delete(c)}return}let fe=e.streamingEnabled&&_.supportsStreaming===!0&&(_.format===`openai`||_.format===`anthropic`);d===`transformers_js_local`&&be(e,e.events,c);let pe=e.createProviderRequestId(c);e.agentWorker?.postMessage({type:`invoke`,payload:{apiKey:d===e.provider?await O(e):await e.getApiKeyForSpecificProvider(t,d),assistantName:e.assistantName,contextCompression:e.contextCompressionEnabled,contextLimit:U(h),enabledTools:w,groupId:c,isScheduledTask:e.schedulerTriggeredGroups.has(r),maxIterations:e.maxIterations,maxTokens:g,memory:l,messages:ue,model:f,provider:d,providerHeaders:ge(e,d,pe,L),providerRuntimeOverrides:L,reasoning:me(e),rateLimitAutoAdapt:e.rateLimitAutoAdapt,rateLimitCallsPerMinute:e.rateLimitCallsPerMinute,storageHandle:await x(t,m.STORAGE_HANDLE),streaming:fe,subagentModelSelectionMode:T,subagentMaxTokens:E,subagentPinnedProvider:ee,subagentPinnedModel:D,subagentFastProvider:k,subagentFastModel:A,subagentSmartProvider:M,subagentSmartModel:N,subagentPowerfulProvider:P,subagentPowerfulModel:F,systemPrompt:z,subagentTask:s}})}function pn(e,t,n){if(!e.enabledChannelTypes.includes(n.channel))return null;let r=n.content.trim(),i=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),a=r;if(e.requireMention){let e=RegExp(`^@${i}\\b\\s*(?:-|:)?\\s*`,`i`);if(!e.test(a))return null;a=a.replace(e,``).trim()}let o=a.match(/^\/([a-zA-Z0-9_]+)(?:\s+([\s\S]+))?$/);if(!o)return null;let s=o[1];if(!e.allowedTools.includes(s))return null;let c=(o[2]||``).trim();if(!c)return{toolName:s,input:{}};let l=c.startsWith(`'`)&&c.endsWith(`'`)||c.startsWith(`"`)&&c.endsWith(`"`)?c.slice(1,-1).trim():c;try{let e=JSON.parse(l);return e&&typeof e==`object`?{toolName:s,input:e}:null}catch{return null}}function mn(e,t){let n=e.trim().match(/^\/([a-z0-9](?:[a-z0-9]|-(?!-))*[a-z0-9]|[a-z0-9])(?:\s+([\s\S]+))?$/u);if(!n)return null;let r=t.find(e=>e.name===n[1]&&e.userInvocable!==!1);return r?{skill:r,arguments:(n[2]||``).trim()}:null}async function hn(e,t,n){if(n.a2uiEnvelopes&&n.a2uiEnvelopes.length>0)for(let t of n.a2uiEnvelopes)e.events.emit(`a2ui-surface`,{groupId:n.groupId,envelope:t});n.a2uiAction&&e.events.emit(`a2ui-action`,{groupId:n.groupId,action:n.a2uiAction});let r=!!n.content,i=(n.attachments?.length??0)>0;if(!r&&!i&&(n.a2uiEnvelopes?.length??0)>0)return;let a=pn(e.directToolCommandPolicy,e.assistantName,n),o=a?null:mn(n.content,(await I(t,n.groupId)).skills),s=n.channel===`browser`,c=e.channelRegistry.shouldAutoTrigger(n.groupId),l=!1;(n.channel===`browser`||n.groupId.startsWith(`room:`))&&(l=e.triggerPattern.test(n.content.trim())),o&&(l=!0),s&&n.groupId.startsWith(`peer:`)&&e.peerCompletedContexts.delete(n.groupId);let u=!!a;if(!l&&e.peerjsMyPeerId){if(n.content.includes(`@${e.peerjsMyPeerId}`))l=!0;else if(e.peerjsMyAlias&&n.content.includes(`@${e.peerjsMyAlias}`))l=!0;else for(let[t,r]of Object.entries(e.peerjsPeerAliases))if(r===e.peerjsMyPeerId&&n.content.includes(`@${t}`)){l=!0;break}}n.content.trim().startsWith(`[SCHEDULED TASK]`)&&(l=!0),n.content.trim().startsWith(`[A2UI ACTION]`)&&(l=!0);let d=!1;d=u||l?!0:s?!(n.groupId.startsWith(`peer:`)||n.groupId.startsWith(`room:`)):c,d&&!s&&!o&&n.groupId.startsWith(`peer:`)&&e.peerCompletedContexts.has(n.groupId)&&(d=!1);let f=await Xe(t,n.groupId,n.attachments||[]),p={...n,attachments:f,isFromMe:!1,isTrigger:d};if(d&&!u&&!o?.skill.execution&&e.messageQueue.push(o?{...n,content:`[SKILL COMMAND] Activate the "${o.skill.name}" skill and follow its instructions.\n${o.arguments}`}:n),await le(t,p),e.events.emit(`message`,p),o?.skill.execution&&e.agentWorker){let t=o.skill.execution.tools.map(e=>{let t=e.input&&typeof e.input==`object`?{...e.input}:{};return o.arguments&&Object.keys(t).length===0&&(t.rawInput=o.arguments),{...e,input:t}});e.agentWorker.postMessage({type:`execute-skill-tools`,payload:{groupId:n.groupId,skillName:o.skill.name,tools:t}});return}if(n.channel===`peerjs`&&Te(n.groupId),s&&(n.groupId.startsWith(`peer:`)||n.groupId.startsWith(`room:`))&&e.router?.send(n.groupId,n.content,f).catch(e=>{console.error(`Failed to route browser message to peer:`,e)}),a&&e.agentWorker){e.agentWorker.postMessage({type:`execute-direct-tool`,payload:{groupId:n.groupId,name:a.toolName,input:a.input}});return}gn(e,t)}async function gn(e,t){if(e.processing||e.messageQueue.length===0)return;let r=e.messageQueue[0]?.groupId,i=e.providerConfig,a=e.provider;if(r)try{let e=(await Be(t)).find(e=>e.groupId===r);if(e?.pinnedProvider){let t=n(e.pinnedProvider);t&&(i=t,a=e.pinnedProvider)}}catch{}let o=i?.requiresApiKey!==!1,s=!0;if(o&&(s=a===e.provider?!!await O(e):!!await e.getApiKeyForSpecificProvider(t,a)),o&&!s){let t=`API key not configured. Go to Settings to add your API key.`;e.events.emit(`provider-help`,{providerId:a,reason:t,helpType:ae(a,t,o)});let n=e.messageQueue.shift();e.events.emit(`error`,{groupId:n.groupId,error:t});return}e.processing=!0;let c=e.messageQueue.shift();try{await fn(e,t,c.groupId,c.content,c.freshContext,c.subagent)}catch(e){console.error(`Failed to invoke agent:`,e)}finally{e.processing=!1,e.messageQueue.length>0&&gn(e,t)}}var _n=class{listeners;constructor(){this.listeners=new Map}emit(e,t){this.listeners.get(e)?.forEach(e=>e(t))}off(e,t){this.listeners.get(e)?.delete(t)}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e)?.add(t)}};function Q(e,t){return{jsonrpc:`2.0`,method:e,params:t}}var vn=class{static isRoomMethod(e){return e===X.JOIN||e===X.ROSTER||e===X.LEAVE||e===X.MESSAGE||e===X.INVITE||e===X.RELAY||e===X.A2UI||e===X.A2UI_ACTION}roomsSignal=new C.State([]);_opts;_rooms=new Map;_seen=new Map;_surfaceOwners=new Map;constructor(e){this._opts=e}broadcast(e,t,n){let r=this._rooms.get(e);if(!r)return null;let i=this._opts.getLocalMember(),a=Y(),o={roomId:e,messageId:a,senderPeerId:i.peerId,senderAlias:i.alias,text:t,attachments:n?.map(e=>({fileName:e.fileName,mimeType:e.mimeType,path:e.path,size:e.size}))};return this._markSeen(e,a),this._deliverToMembers(r,Q(X.MESSAGE,o)),a}broadcastA2UI(e,t){let n=this._rooms.get(e);if(!n)return null;let r=this._myPeerId;this._surfaceOwners.set(t.surfaceId,r);let i=Y(),a={roomId:e,broadcastId:i,ownerPeerId:r,senderPeerId:r,envelope:t};return this._markSeen(e,i),this._deliverToMembers(n,Q(X.A2UI,a)),i}broadcastA2UIAction(e,t){let n=this._rooms.get(e);if(!n)return null;let r=this._opts.getLocalMember(),i=this._surfaceOwners.get(t.surfaceId)??``,a=Y(),o={roomId:e,broadcastId:a,ownerPeerId:i,senderPeerId:r.peerId,senderAlias:r.alias,action:t};return this._markSeen(e,a),this._deliverToMembers(n,Q(X.A2UI_ACTION,o)),a}createRoom(e){let t=this._opts.getLocalMember(),n={roomId:Y(),name:e,hostPeerId:t.peerId,members:[t],createdAt:Date.now()};return this._save(n),n}get(e){return this._rooms.get(e)??null}getSurfaceOwner(e){return this._surfaceOwners.get(e)}handleNotification(e,t,n){switch(t){case X.JOIN:this._onJoin(e,n);break;case X.ROSTER:this._onRoster(n);break;case X.LEAVE:this._onLeave(e,n);break;case X.MESSAGE:this._onMessage(n);break;case X.INVITE:this._opts.onInvite?.(n);break;case X.RELAY:this._onRelay(n);break;case X.A2UI:this._onA2UI(n);break;case X.A2UI_ACTION:this._onA2UIAction(n);break}}invite(e,t){let n=this._rooms.get(e);if(!n)return!1;let r=this._opts.getLocalMember(),i={roomId:e,roomName:n.name,hostPeerId:n.hostPeerId,fromPeerId:r.peerId,fromAlias:r.alias},a=this._opts.transport;return a.connectToPeer(t),a.sendToPeer(t,Q(X.INVITE,i))}isHost(e){let t=this._rooms.get(e);return!!t&&t.hostPeerId===this._myPeerId}joinRoom(e,t,n){let r=this._opts.getLocalMember(),i=this._rooms.get(e)??{roomId:e,name:n,hostPeerId:t,members:[{peerId:t,alias:t,kind:`agent`},r],createdAt:Date.now()};this._save(i);let a=this._opts.transport;a.connectToPeer(t);let o={roomId:e,member:r};return a.sendToPeer(t,Q(X.JOIN,o)),i}leaveRoom(e){let t=this._rooms.get(e);if(!t)return;let n=this._myPeerId;if(t.hostPeerId===n){let r={roomId:e,peerId:n,disbanded:!0};this._deliverToMembers(t,Q(X.LEAVE,r))}else{let r={roomId:e,peerId:n};this._opts.transport.sendToPeer(t.hostPeerId,Q(X.LEAVE,r))}this._rooms.delete(e),this._seen.delete(e),this._opts.removeRoom?.(e),this._publish()}list(){return Array.from(this._rooms.values())}loadRooms(e){this._rooms.clear();for(let t of e)this._rooms.set(t.roomId,t);this._publish()}_broadcastRoster(e){let t={roomId:e.roomId,name:e.name,hostPeerId:e.hostPeerId,members:e.members};this._deliverToMembers(e,Q(X.ROSTER,t))}_deliverToMembers(e,t){let n=this._myPeerId;for(let r of e.members)r.peerId!==n&&this._deliverToPeer(e,r.peerId,t)}_deliverToPeer(e,t,n){let r=this._opts.transport;if(r.isConnected(t)){r.sendToPeer(t,n);return}let i=this._myPeerId;if(e.hostPeerId!==i&&e.hostPeerId!==t&&r.isConnected(e.hostPeerId)){let i={roomId:e.roomId,targetPeerId:t,inner:n};r.sendToPeer(e.hostPeerId,Q(X.RELAY,i)),r.connectToPeer(t);return}r.connectToPeer(t),r.sendToPeer(t,n)}_hasSeen(e,t){return this._seen.get(e)?.has(t)??!1}_markSeen(e,t){let n=this._seen.get(e);if(n||(n=new Set,this._seen.set(e,n)),n.add(t),n.size>500){let e=n.values().next().value;e!==void 0&&n.delete(e)}}get _myPeerId(){return this._opts.transport.myPeerId}_onA2UI(e){if(!e||typeof e.roomId!=`string`||typeof e.broadcastId!=`string`||!e.envelope||!this._rooms.get(e.roomId)||this._hasSeen(e.roomId,e.broadcastId))return;this._markSeen(e.roomId,e.broadcastId);let t=e.envelope.surfaceId;this._surfaceOwners.get(t)!==this._myPeerId&&this._surfaceOwners.set(t,e.ownerPeerId);let n={id:e.broadcastId,groupId:P(e.roomId),sender:e.senderPeerId,content:``,timestamp:Date.now(),channel:`room`,a2uiEnvelopes:[e.envelope]};this._opts.onMessage(n)}_onA2UIAction(e){if(!e||typeof e.roomId!=`string`||typeof e.broadcastId!=`string`||!e.action||!this._rooms.get(e.roomId)||this._hasSeen(e.roomId,e.broadcastId)||(this._markSeen(e.roomId,e.broadcastId),this._surfaceOwners.get(e.action.surfaceId)!==this._myPeerId))return;let t={id:e.broadcastId,groupId:P(e.roomId),sender:e.senderAlias||e.senderPeerId,content:yt(e.action,e.senderAlias),timestamp:Date.now(),channel:`room`,a2uiAction:e.action};this._opts.onMessage(t)}_onJoin(e,t){if(!t||typeof t.roomId!=`string`)return;let n=this._rooms.get(t.roomId);if(!n||n.hostPeerId!==this._myPeerId)return;let r=t.member??{peerId:e,alias:e,kind:`human`};r.peerId=e;let i=n.members.findIndex(t=>t.peerId===e);i>=0?n.members[i]=r:n.members.push(r),this._save(n),this._broadcastRoster(n)}_onLeave(e,t){if(!t||typeof t.roomId!=`string`)return;let n=this._rooms.get(t.roomId);if(n){if(t.disbanded){this._rooms.delete(t.roomId),this._seen.delete(t.roomId),this._opts.removeRoom?.(t.roomId),this._publish();return}n.hostPeerId===this._myPeerId&&(n.members=n.members.filter(n=>n.peerId!==(t.peerId||e)),this._save(n),this._broadcastRoster(n))}}_onMessage(e){if(!e||typeof e.roomId!=`string`||typeof e.messageId!=`string`||!this._rooms.get(e.roomId)||this._hasSeen(e.roomId,e.messageId))return;this._markSeen(e.roomId,e.messageId);let t={id:e.messageId,groupId:P(e.roomId),sender:e.senderAlias||e.senderPeerId,content:e.text??``,timestamp:Date.now(),channel:`room`,attachments:e.attachments?.map(e=>({fileName:e.fileName,mimeType:e.mimeType,path:e.path,size:e.size}))};this._opts.onMessage(t)}_onRelay(e){!e||typeof e.targetPeerId!=`string`||!e.inner||this.isHost(e.roomId)&&this._opts.transport.sendToPeer(e.targetPeerId,e.inner)}_onRoster(e){if(!e||typeof e.roomId!=`string`)return;let t=this._rooms.get(e.roomId),n={roomId:e.roomId,name:e.name??t?.name??e.roomId,hostPeerId:e.hostPeerId,members:Array.isArray(e.members)?e.members:[],createdAt:t?.createdAt??Date.now()};this._save(n)}_publish(){this.roomsSignal.set(this.list())}_save(e){this._rooms.set(e.roomId,e),this._opts.persistRoom?.(e),this._publish()}};function yn(){return new Promise(async(e,t)=>{try{let n=await y();if(!n)return t(Error(`failed to get transaction, cannot get enabled tasks.`));let r=n.transaction(`tasks`,`readonly`);if(!r)return t(Error(`failed to get transaction`));let i=r.objectStore(`tasks`).index(`by-enabled`).getAll(1);i.onsuccess=()=>{e(i.result.map(e=>({...e,enabled:!0})))},i.onerror=()=>t(i.error)}catch(e){t(e)}})}function bn(e,t){if(typeof e!=`string`||!e.trim())return!1;let n=e.trim().split(/\s+/);if(n.length!==5)return!1;let[r,i,a,o,s]=n;return xn(r,t.getMinutes())&&xn(i,t.getHours())&&xn(a,t.getDate())&&xn(o,t.getMonth()+1)&&xn(s,t.getDay())}function xn(e,t){return e===`*`||e.split(`,`).some(e=>{if(e.includes(`/`)){let[n,r]=e.split(`/`),i=parseInt(r,10);if(isNaN(i)||i<=0)return!1;if(n===`*`)return t%i===0;if(n.includes(`-`)){let[e,r]=n.split(`-`).map(Number);return t>=e&&t<=r&&(t-e)%i===0}let a=parseInt(n,10);return t>=a&&(t-a)%i===0}if(e.includes(`-`)){let[n,r]=e.split(`-`).map(Number);return t>=n&&t<=r}return parseInt(e,10)===t})}var Sn=class{interval=null;onTaskChange;runner;constructor(e,t){this.runner=e,this.onTaskChange=t}ranThisMinute(e,t){if(!e.lastRun)return!1;let n=new Date(e.lastRun);return n.getFullYear()===t.getFullYear()&&n.getMonth()===t.getMonth()&&n.getDate()===t.getDate()&&n.getHours()===t.getHours()&&n.getMinutes()===t.getMinutes()}start(){this.interval||(this.interval=setInterval(()=>this.tick(),v),this.tick())}stop(){this.interval&&=(clearInterval(this.interval),null)}async tick(){try{let e=await yn(),t=new Date;for(let n of e){let e=n.schedule||``;e!==``&&bn(e,t)&&!this.ranThisMinute(n,t)&&(await Me(n.id,t.getTime()),this.onTaskChange?.(),this.runner(n).catch(e=>{console.error(`Task ${n.id} failed:`,e)}))}}catch(e){console.error(`Scheduler tick error:`,e)}}};function Cn(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return E(t.map(e=>String(e)))}catch{}return E(e.split(`,`))}async function wn(e,t){e.channelEnabledByType.telegram=await Se(`telegram`,t),e.channelEnabledByType.imessage=await Se(`imessage`,t);let n=await e.loadSecretConfig(t,m.TELEGRAM_BOT_TOKEN),r=Cn(await x(t,m.TELEGRAM_CHAT_IDS)),i=await x(t,m.TELEGRAM_USE_PROXY)===`true`;e.telegramBotToken=n,e.telegramChatIds=r,e.telegramUseProxy=i,e.telegram.configure(n,r,i);let a=async(e,n)=>{try{let r=await xe(t,e,n),i=new Uint8Array(r.byteLength);i.set(r);let a=Ze(n.split(`/`).pop()||n);return new Blob([i],{type:a})}catch(e){return console.warn(`Orchestrator: channel fileReader failed for ${n}:`,e),null}};e.telegram.fileReader=a,e.imessage.fileReader=a;let o=(await x(t,m.IMESSAGE_SERVER_URL)||``).trim().replace(/\/+$/,``),s=await e.loadSecretConfig(t,m.IMESSAGE_API_KEY),c=Cn(await x(t,m.IMESSAGE_CHAT_IDS));e.imessageServerUrl=o,e.imessageApiKey=s,e.imessageChatIds=c,e.imessage.configure(o,s,c),e.channelEnabledByType.peerjs=await Se(`peerjs`,t);let l=(await x(t,m.PEERJS_MY_PEER_ID)||``).trim(),u=Cn(await x(t,m.PEERJS_TRUSTED_PEER_IDS)),d=(await x(t,m.PEERJS_SERVER_HOST)||``).trim(),f=await x(t,m.PEERJS_SERVER_PORT),p=f&&parseInt(f,10)||0,h=(await x(t,m.PEERJS_SERVER_PATH)||``).trim(),g=await x(t,m.PEERJS_SERVER_SECURE)!==`false`,_={},v=await x(t,m.PEERJS_PEER_ALIASES);if(v)try{_=JSON.parse(v)}catch(e){console.warn(`Failed to parse peerjs_peer_aliases`,e)}e.peerjsMyPeerId=l,e.peerjsMyAlias=(await x(t,m.PEERJS_MY_ALIAS)||``).trim(),e.peerjsTrustedPeerIds=u,e.peerjsPeerAliases=_,e.peerjsServerHost=d,e.peerjsServerPort=p,e.peerjsServerPath=h,e.peerjsServerSecure=g;let y=d?{host:d,port:p||void 0,path:h||void 0,secure:g}:{};e.peerjs.configure(l,u,y)}const $={allowedTools:[`clear_chat`,`show_toast`],enabledChannelTypes:[`telegram`],requireMention:!0};function Tn(e){if(!e)return{allowedTools:[...$.allowedTools],enabledChannelTypes:[...$.enabledChannelTypes],requireMention:$.requireMention};try{let t=JSON.parse(e),n=Array.isArray(t.enabledChannelTypes)?t.enabledChannelTypes.filter(e=>typeof e==`string`&&e.trim().length>0):$.enabledChannelTypes;return{allowedTools:Array.isArray(t.allowedTools)?t.allowedTools.filter(e=>typeof e==`string`&&e.trim().length>0):$.allowedTools,enabledChannelTypes:n,requireMention:typeof t.requireMention==`boolean`?t.requireMention:$.requireMention}}catch{return{allowedTools:[...$.allowedTools],enabledChannelTypes:[...$.enabledChannelTypes],requireMention:$.requireMention}}}function En(e,t){typeof navigator>`u`||!navigator.serviceWorker||navigator.serviceWorker.addEventListener(`message`,t=>{if(t.data?.type===`request-proxy-config`){T(e);return}if(t.data?.type!==`scheduled-task-trigger`)return;let{taskId:n,groupId:r,prompt:i,taskType:a,tools:o}=t.data;r&&(e.schedulerTriggeredGroups.add(r),(async()=>{let t=q.tasks.find(e=>e.id===n);if(t){q.runTask(t);return}if(a===`tools`&&Array.isArray(o)&&o.length>0){q.runTask({id:n||`push-task-${Date.now()}`,groupId:r,createdAt:Date.now(),enabled:!0,prompt:i||``,type:`tools`,tools:o,lastRun:null});return}i&&B(e,i,r)})().catch(e=>console.error(`Push-triggered task ${n} failed:`,e)).finally(()=>{e.schedulerTriggeredGroups.delete(r)}))})}function Dn(e){return new vn({transport:{get myPeerId(){return e.peerjs.myPeerId||e.peerjsMyPeerId},sendToPeer:(t,n)=>e.peerjs.sendRoomNotification(t,n),isConnected:t=>e.peerjs.isPeerConnected(t),connectToPeer:t=>e.peerjs.connectPeer(t)},getLocalMember:()=>({peerId:e.peerjs.myPeerId||e.peerjsMyPeerId,alias:e.peerjsMyAlias||e.peerjs.myPeerId||e.peerjsMyPeerId||e.assistantName,kind:`agent`,agentName:e.assistantName}),onMessage:t=>e.roomChannel.deliverInbound(t),onInvite:t=>M(e,t),persistRoom:t=>{e.db&&he(e.db,t).catch(e=>console.error(`Failed to persist room:`,e))},removeRoom:t=>{e.db&&F(e.db,t).catch(e=>console.error(`Failed to delete room:`,e))}})}async function On(e,t){e.initializeChannelRegistry(),e.channelRegistry.onMessage(n=>{hn(e,t,n).catch(e=>{console.error(`Failed to enqueue inbound message:`,e)})}),e.channelRegistry.onTyping((t,n)=>{e.events.emit(`typing`,{groupId:t,typing:n}),t.startsWith(`peer:`)&&q.setRemoteAgentTyping(t,n)}),e.peerjs.onTaskComplete(t=>{e.peerCompletedContexts.add(t)}),await wn(e,t),Ce(e);try{let n=await Ie(t);e.roomManager.loadRooms(n)}catch(e){console.error(`Failed to load rooms:`,e)}}async function kn(e,t){e.assistantName=await x(t,m.ASSISTANT_NAME)||`ShadowClaw`,e.triggerPattern=a(e.assistantName)}async function An(e,t){let n=await x(t,m.VM_BOOT_MODE);e.vmBootMode=n===`disabled`||n===`auto`||n===`9p`||n===`ext2`?n:`disabled`,e.streamingEnabled=await x(t,m.STREAMING_ENABLED)!==`false`,e.webMcpToolsEnabled=await x(t,m.WEBMCP_TOOLS_ENABLED)!==`false`,e.vmBashFullInternetAccess=await x(t,m.VM_BASH_FULL_INTERNET_ACCESS)===`true`;let r=await x(t,m.WEBMCP_MODE);(r===`native`||r===`polyfill`)&&We(r),e.contextCompressionEnabled=await x(t,m.CONTEXT_COMPRESSION_ENABLED)===`true`;let i=await x(t,m.REASONING_EFFORT);e.reasoningEffort=i?i.trim().toLowerCase():`none`,e.directToolCommandPolicy=Tn(await x(t,m.DIRECT_TOOL_COMMAND_POLICY)),e.useProxy=await x(t,m.USE_PROXY)===`true`,e.proxyUrl=await x(t,m.PROXY_URL)||`/proxy`,e.gitProxyUrl=await x(t,m.GIT_PROXY_URL)||`/git-proxy`,e.taskServerEnabled=await x(t,m.TASK_SERVER_ENABLED)===`true`,e.taskServerUrl=await x(t,m.TASK_SERVER_URL)||(await import(`./config-CrHchneq.js`).then(e=>e.k)).DEFAULT_TASK_SERVER_URL}async function jn(e,t){let n=await x(t,m.LLAMAFILE_MODE);n===`cli`||n===`server`?e.llamafileMode=n:await J(t,m.LLAMAFILE_MODE,e.llamafileMode);let r=await x(t,m.LLAMAFILE_HOST);r&&(e.llamafileHost=r);let i=await x(t,m.LLAMAFILE_PORT);if(i){let t=parseInt(i,10);Number.isFinite(t)&&t>=1&&t<=65535&&(e.llamafilePort=t)}await x(t,m.LLAMAFILE_OFFLINE)===`false`&&(e.llamafileOffline=!1),de(e);let a=await x(t,m.MESH_LLM_HOST);a&&(e.meshLlmHost=a),A(e)}async function Mn(e,t){let[r,a,c,l,u,d,f,p,h]=await Promise.all([x(t,m.PROVIDER),x(t,m.BEDROCK_REGION_FALLBACK),x(t,m.BEDROCK_PROFILE_FALLBACK),x(t,m.BEDROCK_AUTH_MODE),x(t,m.MODEL),x(t,m.MAX_TOKENS),x(t,m.MAX_ITERATIONS),x(t,m.RATE_LIMIT_CALLS_PER_MINUTE),x(t,m.RATE_LIMIT_AUTO_ADAPT)]);r&&n(r)&&(e.provider=r,e.providerConfig=n(r)||i()),await e.loadApiKeyForProvider(t,e.provider),e.bedrockRegionFallback=(a||``).trim(),e.bedrockProfileFallback=(c||``).trim(),e.bedrockAuthMode=(l||`provider_chain`).trim();let g=()=>{let t=()=>{fe(e).then(t=>s.fetchModelInfo(e.providerConfig,t||void 0,ge(e,e.provider)))};typeof globalThis.requestIdleCallback==`function`?globalThis.requestIdleCallback(t,{timeout:5e3}):setTimeout(t,2e3)};typeof window<`u`&&typeof document<`u`?document.readyState===`complete`?g():window.addEventListener(`load`,g,{once:!0}):g(),u?e.model=u:e.model=e.providerConfig.defaultModel;let _=e.model;e.provider===`prompt_api`&&!R()&&(e.model===`browser-built-in`||!e.model)&&(_=await x(t,m.PROMPT_API_FALLBACK_MODEL)||`onnx-community/Qwen3-0.6B-ONNX`,ue(_).catch(()=>{}));let v=o(_);if(d===`8192`||e.provider===`prompt_api`&&!R()&&d===`4096`?e.maxTokens=v:e.maxTokens=Math.max(1,parseInt(d||String(v),10)),f&&(e.maxIterations=parseInt(f,10)||50),p){let t=parseInt(p,10);e.rateLimitCallsPerMinute=Number.isFinite(t)?Math.max(0,t):0}e.rateLimitAutoAdapt=h!==`false`}async function Nn(e,t){e.agentWorker=new Worker(S(new URL(`./agent.worker.js`,import.meta.url).href),{type:`module`}),e.agentWorker.onmessage=n=>re(e,t,n.data),e.agentWorker.onerror=e=>{console.error(`Agent worker error:`,e)};let n=await x(t,m.STORAGE_HANDLE);n&&e.agentWorker.postMessage({payload:{storageHandle:n},type:`set-storage`}),T(e),e.scheduler=new Sn(async t=>{await L(e,t)},()=>{e.events.emit(`task-change`,{type:`executed`})}),oe().then(t=>{t&&e.scheduler?.start()}),En(e,t)}var Pn=class{agentWorker=null;assistantName=g;bedrockAuthMode=`provider_chain`;bedrockProfileFallback=``;bedrockRegionFallback=``;browserChat=new rt;channelEnabledByType={browser:!0,peerjs:!1,telegram:!1,imessage:!1};channelRegistry=new it;contextCompressionEnabled=!1;db=null;directToolCommandPolicy={...$};events=new _n;gitProxyUrl=`/git-proxy`;imessage=new at;imessageApiKey=``;imessageChatIds=[];imessageServerUrl=``;inFlightEffectiveProviderByGroup=new Map;inFlightProviderRequestIds=new Map;inFlightTriggerByGroup=new Map;llamafileHost=`127.0.0.1`;llamafileMode=`cli`;llamafileOffline=!0;llamafilePort=8080;maxIterations=50;maxTokens=h;meshLlmHost=``;messageQueue=[];model=i().defaultModel;peerCompletedContexts=new Set;peerjs=new Qe;peerjsMyAlias=``;peerjsMyPeerId=``;peerjsPeerAliases={};peerjsServerHost=``;peerjsServerPath=``;peerjsServerPort=0;peerjsServerSecure=!0;peerjsTrustedPeerIds=[];pendingScheduledTasks=new Set;processing=!1;promptControllers=new Map;provider=f;providerConfig=i();proxyUrl=`/proxy`;pushSubscriptionWarned=!1;rateLimitAutoAdapt=!0;rateLimitCallsPerMinute=0;reasoningEffort=`none`;roomChannel=new dt;roomManager;router=null;scheduler=null;schedulerTriggeredGroups=new Set;state=`idle`;streamingEnabled=!0;taskServerEnabled=!1;taskServerUrl=`/schedule`;telegram=new pt;telegramBotToken=``;telegramChatIds=[];telegramUseProxy=!1;transformersProgressPollers=new Map;triggerPattern=a(g);useProxy=!1;vmBashFullInternetAccess=!1;vmBootMode=`disabled`;vmStatus={ready:!1,booting:!1,bootAttempted:!1,error:null};webMcpEffectCleanup=null;webMcpRegistrationLock=Promise.resolve();webMcpToolsEnabled=!0;#e=null;#t=null;constructor(){this.roomManager=Dn(this),this.initializeChannelRegistry()}clearProviderRequest(e){this.inFlightProviderRequestIds.delete(e)}createProviderRequestId(e){if(this.provider!==`llamafile`)return this.inFlightProviderRequestIds.delete(e),``;let t=`${e}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2,10)}`;return this.inFlightProviderRequestIds.set(e,t),t}initializeChannelRegistry(){this.channelRegistry=new it,this.channelRegistry.register(`br:`,this.browserChat,{badge:`Browser`,autoTrigger:!0}),this.channelRegistry.register(`tg:`,this.telegram,{badge:`Telegram`,autoTrigger:!1}),this.channelRegistry.register(`im:`,this.imessage,{badge:`iMessage`,autoTrigger:!0}),this.channelRegistry.register(`peer:`,this.peerjs,{badge:`PeerJS`,autoTrigger:!1}),this.channelRegistry.register(`room:`,this.roomChannel,{badge:`Room`,autoTrigger:!1}),this.roomChannel.setManager(this.roomManager),this.peerjs.setRoomNotificationHandler((e,t,n)=>this.roomManager.handleNotification(e,t,n)),this.router=new bt(this.channelRegistry)}setState(e,t){this.state=e,this.events.emit(`state-change`,{state:e,groupId:t})}shutdown(){this.channelRegistry.stopAll(),this.scheduler?.stop();for(let e of this.transformersProgressPollers.keys())Fe(this,e);this.agentWorker?.terminate(),typeof this.webMcpEffectCleanup==`function`&&this.webMcpEffectCleanup(),Ge()}stopCurrentRequest(e=p){if(this.state!==`thinking`&&this.state!==`responding`)return;Fe(this,e);let t=this.inFlightProviderRequestIds.get(e)||``;this.clearProviderRequest(e),this.agentWorker?.postMessage({type:`cancel`,payload:{groupId:e}}),this.provider===`llamafile`&&t&&V(t);let n=this.promptControllers.get(e);n&&(n.abort(),this.promptControllers.delete(e)),this.inFlightTriggerByGroup.delete(e),this.inFlightEffectiveProviderByGroup.delete(e),this.events.emit(`typing`,{groupId:e,typing:!1}),this.router?.setTyping(e,!1),this.setState(`idle`,e)}async getApiKey(){if(!this.#t)return null;let e=Date.now();if(this.#e&&this.#e.expiresAt>e)return this.#e.value;try{let t=await Je(this.#t);return t===null?null:(this.#e={expiresAt:e+3e4,value:t},t)}catch(e){return console.error(`[Orchestrator] Failed to decrypt API key:`,e),null}}async getApiKeyForSpecificProvider(e,t){let n=await x(e,r(t));if(!n&&t===`openrouter`){let t=await x(e,m.API_KEY);t&&(n=t)}if(!n)return``;try{return await Je(n)||``}catch(e){return console.error(`[Orchestrator] Failed to decrypt API key:`,e),``}}async handleCompactDone(e,t,n){await Le(e,t),await le(e,{channel:this.channelRegistry.getChannelType(t)??`browser`,content:`📝 **Context Compacted**\n\n${n}`,groupId:t,id:Y(),isFromMe:!0,isTrigger:!1,sender:this.assistantName,timestamp:Date.now()}),this.events.emit(`context-compacted`,{groupId:t,summary:n}),this.events.emit(`typing`,{groupId:t,typing:!1}),this.setState(`idle`,t)}async init(){let e=await nt();return this.db=e,await Promise.all([kn(this,e),Mn(this,e),jn(this,e),An(this,e)]),await Nn(this,e),On(this,e).then(()=>{this.browserChat.onDisplay(()=>{})}),this.events.emit(`ready`,void 0),await W.load(e),Ke(this,e),e}async loadApiKeyForProvider(e,t){let n=await x(e,r(t));if(!n&&t===`openrouter`){let i=await x(e,m.API_KEY);i&&(n=i,await J(e,r(t),i))}if(!n)this.#t=``;else try{this.#t=n}catch(e){console.warn(`[Orchestrator] Failed to load API key:`,e),this.#t=``}this.#e=null}async loadSecretConfig(e,t){let n=await x(e,t);if(!n)return``;try{return await Je(n)||``}catch{let r=await Ye(n);return r&&await J(e,t,r),n}}async newSession(e,t=p){await Le(e,t),this.events.emit(`session-reset`,{groupId:t})}async refreshContextUsage(e,t=p){let r=``;try{r=await ve(e,t,`MEMORY.md`)}catch{}let i=W.enabledTools,a=q.getPeerState(t)||void 0,s=ne(this.assistantName,r,i,W.systemPromptOverride,a),c=(await Be(e)).find(e=>e.groupId===t),l=c?.pinnedModel??(c?.pinnedProvider?n(c.pinnedProvider)?.defaultModel??this.model:this.model),u=l;(c?.pinnedProvider??this.provider)===`prompt_api`&&(l===`browser-built-in`||!l)&&!R()&&(u=await x(this.db,m.PROMPT_API_FALLBACK_MODEL)||`onnx-community/Qwen3-0.6B-ONNX`);let d=typeof c?.pinnedMaxTokens==`number`&&Number.isFinite(c.pinnedMaxTokens)&&c.pinnedMaxTokens>0?Math.floor(c.pinnedMaxTokens):this.maxTokens,f=Math.max(1,Math.min(d,o(u))),h=U(u),g=te(s)+(i?.reduce((e,t)=>e+te(JSON.stringify(t)),0)??0),_=ce(await Ve(t,200),{contextLimit:h,systemPromptTokens:g,maxOutputTokens:f,skimTop:this.contextCompressionEnabled}),v=_.estimatedTokens+g;if(q.tokenUsage){let e=q.tokenUsage,t=(e.inputTokens||0)+(e.cacheReadTokens||0)+(e.outputTokens||0);v=Math.max(v,t)}this.events.emit(`context-usage`,{estimatedTokens:v,contextLimit:h,usagePercent:Math.min(100,Math.max(_.usagePercent,v/h*100)),truncatedCount:_.truncatedCount})}async restartCurrentRequest(e=p){if(this.state!==`thinking`&&this.state!==`responding`||!this.db)return!1;let t=this.inFlightTriggerByGroup.get(e);return t?(this.stopCurrentRequest(e),await fn(this,this.db,e,t),!0):!1}async routeRoomA2UIAction(e,t){let n=_e(e),r=this.peerjs.myPeerId||this.peerjsMyPeerId,i=this.roomManager.getSurfaceOwner(t.surfaceId);if(!i||i===r){if(!this.db)return;await hn(this,this.db,{id:Y(),groupId:e,sender:this.peerjsMyAlias||r||`you`,content:yt(t),timestamp:Date.now(),channel:`room`,a2uiAction:t});return}this.roomManager.broadcastA2UIAction(n,t)}async saveSecretConfig(e,t,n){if(!n){await J(e,t,``);return}let r=await Ye(n);if(!r)throw Error(`Failed to encrypt secret config for ${t}`);await J(e,t,r)}async setApiKey(e,t){this.#t=await Ye(t),this.#e=null;let n=await Ye(t);if(!n)throw Error(`key failed to encrypt. config cannot set.`);await J(e,r(this.provider),n)}submitMessage(e,t=p){this.browserChat.submit(e,t)}};export{Pn as Orchestrator};
|