shadow-claw 1.26.0 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/main/skill-creator/SKILL.md +39 -0
- package/.agents/skills/main/skill-creator/references/declarative-pipelines.md +44 -0
- package/.agents/skills/main/skill-creator/references/declarative-tools.md +35 -0
- package/.agents/skills/main/skill-creator/references/frontmatter-spec.md +50 -0
- package/.well-known/agent-skills/index.json +14 -0
- package/README.md +5 -3
- package/bin/build/build.mjs +146 -15
- package/bin/build/build.test.mjs +57 -0
- package/bin/cli.mjs +26 -0
- package/bin/commands/mcp.mjs +277 -55
- package/bin/commands/mcp.test.mjs +275 -1
- package/bin/commands/skills-index.mjs +328 -0
- package/bin/commands/skills-index.test.mjs +161 -0
- package/bin/site-config/utils/custom-elements/get-approved-custom-element-scripts.test.mjs +2 -0
- package/bin/site-config/utils/custom-elements/sanitize-embedded-custom-element-scripts.test.mjs +10 -1
- package/dist/lib/components/index.js +25 -25
- package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/settings/shadow-claw-git.js +1 -1
- package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
- package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
- package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
- package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw-a2ui.js +1 -1
- package/dist/lib/components/shadow-claw-accounts.js +1 -1
- package/dist/lib/components/shadow-claw-channel-config.js +1 -1
- package/dist/lib/components/shadow-claw-channels.js +1 -1
- package/dist/lib/components/shadow-claw-chat.js +1 -1
- package/dist/lib/components/shadow-claw-control-plane.js +1 -1
- package/dist/lib/components/shadow-claw-conversations.js +1 -1
- package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
- package/dist/lib/components/shadow-claw-files.js +1 -1
- package/dist/lib/components/shadow-claw-git.js +1 -1
- package/dist/lib/components/shadow-claw-integrations.js +1 -1
- package/dist/lib/components/shadow-claw-llm.js +1 -1
- package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
- package/dist/lib/components/shadow-claw-networking.js +1 -1
- package/dist/lib/components/shadow-claw-page-header.js +1 -1
- package/dist/lib/components/shadow-claw-pages.js +1 -1
- package/dist/lib/components/shadow-claw-peerjs.js +1 -1
- package/dist/lib/components/shadow-claw-settings.js +1 -1
- package/dist/lib/components/shadow-claw-storage.js +1 -1
- package/dist/lib/components/shadow-claw-task-server.js +1 -1
- package/dist/lib/components/shadow-claw-tasks.js +1 -1
- package/dist/lib/components/shadow-claw-terminal.js +1 -1
- package/dist/lib/components/shadow-claw-tools.js +1 -1
- package/dist/lib/components/shadow-claw-webvm.js +1 -1
- package/dist/lib/components/shadow-claw.js +1 -1
- package/dist/lib/{configurePeerJs-CrlGan0m.js → configurePeerJs-oODzltaC.js} +2 -2
- package/dist/lib/{configurePeerJs-CrlGan0m.js.map → configurePeerJs-oODzltaC.js.map} +1 -1
- package/dist/lib/core/control-plane-client.d.ts +1 -0
- package/dist/lib/{downloadGroupFile-DboUjmp2.js → downloadGroupFile-DmcBQU1n.js} +2 -2
- package/dist/lib/{downloadGroupFile-DboUjmp2.js.map → downloadGroupFile-DmcBQU1n.js.map} +1 -1
- package/dist/lib/{file-viewer-BrK2Wxgh.js → file-viewer-C3YKnq_-.js} +4 -3
- package/dist/lib/{file-viewer-BrK2Wxgh.js.map → file-viewer-C3YKnq_-.js.map} +1 -1
- package/dist/lib/index.js +26 -26
- package/dist/lib/{initControlPlane-CsO4UR6_.js → initControlPlane-C2zURVIS.js} +86 -13
- package/dist/lib/initControlPlane-C2zURVIS.js.map +1 -0
- package/dist/lib/{markdown-eeSTFnMA.js → markdown-C6EHl9zs.js} +3 -3
- package/dist/lib/{markdown-eeSTFnMA.js.map → markdown-C6EHl9zs.js.map} +1 -1
- package/dist/lib/{orchestrator-CJvoC2Uu.js → orchestrator-CACLa_Ro.js} +7 -6
- package/dist/lib/{orchestrator-CJvoC2Uu.js.map → orchestrator-CACLa_Ro.js.map} +1 -1
- package/dist/lib/{orchestrator-DCfomsn9.js → orchestrator-KRjx0eba.js} +6 -534
- package/dist/lib/{orchestrator-DCfomsn9.js.map → orchestrator-KRjx0eba.js.map} +1 -1
- package/dist/lib/parsePath-DwC_YZjw.js +16 -0
- package/dist/lib/parsePath-DwC_YZjw.js.map +1 -0
- package/dist/lib/{peerjs-Dp02bXcG.js → peerjs-DFWOBcXf.js} +4 -4
- package/dist/lib/{peerjs-Dp02bXcG.js.map → peerjs-DFWOBcXf.js.map} +1 -1
- package/dist/lib/{readGroupFileBytes-Bve-e5e_.js → readGroupFileBytes-C8oOe8Iu.js} +3 -16
- package/dist/lib/readGroupFileBytes-C8oOe8Iu.js.map +1 -0
- package/dist/lib/security/custom-element-security.d.ts +8 -0
- package/dist/lib/server/control-plane-types.d.ts +1 -1
- package/dist/lib/{shadow-claw-D8xINM3c.js → shadow-claw-6UHdiy4a.js} +5 -5
- package/dist/lib/{shadow-claw-D8xINM3c.js.map → shadow-claw-6UHdiy4a.js.map} +1 -1
- package/dist/lib/{shadow-claw-a2ui-7rJqG4Ke.js → shadow-claw-a2ui-CpZUTzlh.js} +5 -4
- package/dist/lib/{shadow-claw-a2ui-7rJqG4Ke.js.map → shadow-claw-a2ui-CpZUTzlh.js.map} +1 -1
- package/dist/lib/{shadow-claw-accounts-CdruwN8A.js → shadow-claw-accounts-03oJ__XC.js} +2 -2
- package/dist/lib/{shadow-claw-accounts-CdruwN8A.js.map → shadow-claw-accounts-03oJ__XC.js.map} +1 -1
- package/dist/lib/{shadow-claw-channel-config-Bj0-Nk3t.js → shadow-claw-channel-config-DmfwJc6G.js} +3 -3
- package/dist/lib/{shadow-claw-channel-config-Bj0-Nk3t.js.map → shadow-claw-channel-config-DmfwJc6G.js.map} +1 -1
- package/dist/lib/{shadow-claw-channels-C_jI4KhP.js → shadow-claw-channels-1N6Jl-By.js} +3 -3
- package/dist/lib/{shadow-claw-channels-C_jI4KhP.js.map → shadow-claw-channels-1N6Jl-By.js.map} +1 -1
- package/dist/lib/{shadow-claw-chat-B16MspoP.js → shadow-claw-chat-BMoqQJRK.js} +10 -10
- package/dist/lib/{shadow-claw-chat-B16MspoP.js.map → shadow-claw-chat-BMoqQJRK.js.map} +1 -1
- package/dist/lib/{shadow-claw-control-plane-x8Ldid_h.js → shadow-claw-control-plane-UG0o7pCz.js} +6 -6
- package/dist/lib/{shadow-claw-control-plane-x8Ldid_h.js.map → shadow-claw-control-plane-UG0o7pCz.js.map} +1 -1
- package/dist/lib/{shadow-claw-conversations-Ct1kAYdB.js → shadow-claw-conversations-BwXep3iu.js} +4 -3
- package/dist/lib/{shadow-claw-conversations-Ct1kAYdB.js.map → shadow-claw-conversations-BwXep3iu.js.map} +1 -1
- package/dist/lib/{shadow-claw-file-viewer-BfDHHgpA.js → shadow-claw-file-viewer-DUxzVxDT.js} +14 -10
- package/dist/lib/shadow-claw-file-viewer-DUxzVxDT.js.map +1 -0
- package/dist/lib/{shadow-claw-files-EYhOPYIH.js → shadow-claw-files-DIREEnT2.js} +7 -7
- package/dist/lib/{shadow-claw-files-EYhOPYIH.js.map → shadow-claw-files-DIREEnT2.js.map} +1 -1
- package/dist/lib/{shadow-claw-git-tcSpT-P0.js → shadow-claw-git-Bg1SWgsF.js} +4 -4
- package/dist/lib/{shadow-claw-git-tcSpT-P0.js.map → shadow-claw-git-Bg1SWgsF.js.map} +1 -1
- package/dist/lib/{shadow-claw-integrations-NbcCx_ZI.js → shadow-claw-integrations-Ds-CLPhj.js} +2 -2
- package/dist/lib/{shadow-claw-integrations-NbcCx_ZI.js.map → shadow-claw-integrations-Ds-CLPhj.js.map} +1 -1
- package/dist/lib/{shadow-claw-llm-BazJdD5f.js → shadow-claw-llm-CazBrVpM.js} +3 -3
- package/dist/lib/{shadow-claw-llm-BazJdD5f.js.map → shadow-claw-llm-CazBrVpM.js.map} +1 -1
- package/dist/lib/{shadow-claw-mcp-remote-CYmhpg7a.js → shadow-claw-mcp-remote-CT5Q-54E.js} +2 -2
- package/dist/lib/{shadow-claw-mcp-remote-CYmhpg7a.js.map → shadow-claw-mcp-remote-CT5Q-54E.js.map} +1 -1
- package/dist/lib/{shadow-claw-networking-DImPxe0H.js → shadow-claw-networking-Df85tCbO.js} +2 -2
- package/dist/lib/{shadow-claw-networking-DImPxe0H.js.map → shadow-claw-networking-Df85tCbO.js.map} +1 -1
- package/dist/lib/{shadow-claw-page-header-CcHUfFUx.js → shadow-claw-page-header-Cti2fzf-.js} +2 -2
- package/dist/lib/{shadow-claw-page-header-CcHUfFUx.js.map → shadow-claw-page-header-Cti2fzf-.js.map} +1 -1
- package/dist/lib/{shadow-claw-pages-D54jF1Qq.js → shadow-claw-pages-BgPyIEZO.js} +15 -11
- package/dist/lib/shadow-claw-pages-BgPyIEZO.js.map +1 -0
- package/dist/lib/{shadow-claw-peerjs-B9-T8Nlx.js → shadow-claw-peerjs-xkBXILed.js} +3 -3
- package/dist/lib/{shadow-claw-peerjs-B9-T8Nlx.js.map → shadow-claw-peerjs-xkBXILed.js.map} +1 -1
- package/dist/lib/{shadow-claw-settings-Bt1VAe-1.js → shadow-claw-settings-CN89xRVU.js} +4 -4
- package/dist/lib/{shadow-claw-settings-Bt1VAe-1.js.map → shadow-claw-settings-CN89xRVU.js.map} +1 -1
- package/dist/lib/{shadow-claw-storage-CFOjGf1d.js → shadow-claw-storage-VnhcObCe.js} +3 -3
- package/dist/lib/{shadow-claw-storage-CFOjGf1d.js.map → shadow-claw-storage-VnhcObCe.js.map} +1 -1
- package/dist/lib/{shadow-claw-task-server-BiKa2GOm.js → shadow-claw-task-server-jgEC2hHB.js} +2 -2
- package/dist/lib/{shadow-claw-task-server-BiKa2GOm.js.map → shadow-claw-task-server-jgEC2hHB.js.map} +1 -1
- package/dist/lib/{shadow-claw-tasks-DDHd8W4d.js → shadow-claw-tasks-i_evIufy.js} +6 -6
- package/dist/lib/{shadow-claw-tasks-DDHd8W4d.js.map → shadow-claw-tasks-i_evIufy.js.map} +1 -1
- package/dist/lib/{shadow-claw-terminal-kB6_tWKz.js → shadow-claw-terminal-CwScROlu.js} +2 -2
- package/dist/lib/{shadow-claw-terminal-kB6_tWKz.js.map → shadow-claw-terminal-CwScROlu.js.map} +1 -1
- package/dist/lib/{shadow-claw-tools-DxXIm0ku.js → shadow-claw-tools-DD3fyXP4.js} +5 -4
- package/dist/lib/{shadow-claw-tools-DxXIm0ku.js.map → shadow-claw-tools-DD3fyXP4.js.map} +1 -1
- package/dist/lib/{shadow-claw-webvm-Dc8oo7ao.js → shadow-claw-webvm-DbJq4I3-.js} +2 -2
- package/dist/lib/{shadow-claw-webvm-Dc8oo7ao.js.map → shadow-claw-webvm-DbJq4I3-.js.map} +1 -1
- package/dist/lib/{syncWebMcpRegistration-jyRGbC9w.js → syncWebMcpRegistration-DNLnQ-jz.js} +3 -2
- package/dist/lib/{syncWebMcpRegistration-jyRGbC9w.js.map → syncWebMcpRegistration-DNLnQ-jz.js.map} +1 -1
- package/dist/lib/tools-DwwB9RBa.js +546 -0
- package/dist/lib/tools-DwwB9RBa.js.map +1 -0
- package/dist/lib/{trusted-types-CkLDpLiZ.js → trusted-types-Dx0RZlrd.js} +19 -8
- package/dist/lib/trusted-types-Dx0RZlrd.js.map +1 -0
- package/dist/lib/utils/index.js +1 -1
- package/dist/lib/utils/utils.js +1 -1
- package/dist/public/.well-known/agent-skills/index.json +14 -0
- package/dist/public/AGENTS.md +5 -3
- package/dist/public/README.md +5 -3
- package/dist/public/agent.worker.js +1 -1
- package/dist/public/{configurePeerJs-COcwE0E7.js → configurePeerJs-BqgeBjP7.js} +1 -1
- package/dist/public/custom-element-security-FU04Cq05.js +1 -0
- package/dist/public/dist-B9m1QM9v.js +58 -0
- package/dist/public/docs/README.md +31 -31
- package/dist/public/docs/example/article/index.html +1 -1
- package/dist/public/docs/publishing/index.html +1 -1
- package/dist/public/docs/skill-creator/index.html +1 -1
- package/dist/public/docs/subsystems/a2ui.md +11 -1
- package/dist/public/docs/subsystems/cli.md +29 -0
- package/dist/public/docs/subsystems/control-plane.md +8 -2
- package/dist/public/docs/subsystems/custom-element-security.md +19 -9
- package/dist/public/docs/subsystems/mcp-server.md +39 -15
- package/dist/public/docs/subsystems/skills.md +30 -0
- package/dist/public/docs/subsystems/webmcp.md +9 -0
- package/dist/public/downloadGroupFile-D8KRJGGL.js +1 -0
- package/dist/public/e2e/README.md +7 -4
- package/dist/public/{e2e-bridge-CHARpbpW.js → e2e-bridge-Ceqr5kGc.js} +1 -1
- package/dist/public/effect-BJCrpFdp.js +1 -0
- package/dist/public/file-viewer-C-6Jc_tb.js +1 -0
- package/dist/public/index.html +1 -1
- package/dist/public/index.js +1 -1
- package/dist/public/initControlPlane-BN9cWyO0.js +1 -0
- package/dist/public/main/index.html +1 -1
- package/dist/public/main/memory/index.html +1 -1
- package/dist/public/{markdown-1I3O6Mmd.js → markdown-C3M4OW_A.js} +1 -1
- package/dist/public/{orchestrator-Cl95w2vb.js → orchestrator-CMbCTjBf.js} +7 -7
- package/dist/public/{orchestrator-D-xlXG92.js → orchestrator-DHjdLtqa.js} +663 -663
- package/dist/public/peerjs-DUCKH-m9.js +1 -0
- package/dist/public/service-worker.js +1 -1
- package/dist/public/{shadow-claw-CaoKmIIB.js → shadow-claw-EAt2ml5Y.js} +3 -3
- package/dist/public/{shadow-claw-accounts-CJvYC4li.js → shadow-claw-accounts-xUOLBsQZ.js} +1 -1
- package/dist/public/{shadow-claw-channels-3K62sU5f.js → shadow-claw-channels-XsfuWFF8.js} +4 -4
- package/dist/public/{shadow-claw-chat-Cu2keU2I.js → shadow-claw-chat-CbSaOZ4q.js} +7 -7
- package/dist/public/{shadow-claw-control-plane-D1OwlQI_.js → shadow-claw-control-plane-DHvN3Ukg.js} +2 -2
- package/dist/public/{shadow-claw-conversations-DDtg3BEZ.js → shadow-claw-conversations-BWs5VVfs.js} +2 -2
- package/dist/public/{shadow-claw-file-viewer-BR__1z9S.js → shadow-claw-file-viewer-BWsoW5QS.js} +5 -4
- package/dist/public/{shadow-claw-files-BJSyZ-Bl.js → shadow-claw-files-CG7MqWiV.js} +8 -8
- package/dist/public/{shadow-claw-git-MAjhXRLc.js → shadow-claw-git-DBRPZNav.js} +6 -6
- package/dist/public/{shadow-claw-integrations-82UoFuDR.js → shadow-claw-integrations-BBVnO0Fc.js} +8 -8
- package/dist/public/{shadow-claw-llm-R8j0lwPP.js → shadow-claw-llm-DMvLgKXo.js} +2 -2
- package/dist/public/{shadow-claw-mcp-remote-BzZoz4LX.js → shadow-claw-mcp-remote-Bkx0gsmF.js} +2 -2
- package/dist/public/{shadow-claw-networking-DLEd9cNm.js → shadow-claw-networking-Dd8Rw31D.js} +2 -2
- package/dist/public/{shadow-claw-notifications-1vwR7TbT.js → shadow-claw-notifications-Dbevj-lq.js} +2 -2
- package/dist/public/{shadow-claw-page-header-DMKbkv3s.js → shadow-claw-page-header-BccSHItx.js} +1 -1
- package/dist/public/{shadow-claw-pages-CjyeIV__.js → shadow-claw-pages-3_lQAv0t.js} +4 -3
- package/dist/public/{shadow-claw-settings-BfbT4dBU.js → shadow-claw-settings-t8TIlgrM.js} +5 -5
- package/dist/public/{shadow-claw-storage-C-mWQQML.js → shadow-claw-storage-CfEXoSIE.js} +2 -2
- package/dist/public/{shadow-claw-task-server-D3lHp0Nc.js → shadow-claw-task-server-DxQSsgRZ.js} +2 -2
- package/dist/public/{shadow-claw-tasks-DVVWEm-c.js → shadow-claw-tasks-DNpicQwz.js} +14 -14
- package/dist/public/{shadow-claw-terminal-BwuTRp-O.js → shadow-claw-terminal-DpY6zU_r.js} +1 -1
- package/dist/public/{shadow-claw-toast-ClCwgzFG.js → shadow-claw-toast-BkrQIP-3.js} +1 -1
- package/dist/public/{shadow-claw-tools-zFLk2nbV.js → shadow-claw-tools-WSwWohnk.js} +2 -2
- package/dist/public/{shadow-claw-webvm-qR9X7fg7.js → shadow-claw-webvm-CP6oFjg5.js} +2 -2
- package/dist/public/syncWebMcpRegistration-DOn9gLnD.js +1 -0
- package/dist/public/toast-BXgUfbyh.js +1 -0
- package/dist/public/tools-DvckJZG2.js +1 -0
- package/dist/server.js +188 -188
- package/package.json +3 -1
- package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.stories.ts +1380 -93
- package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.ts +11 -6
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +8 -1
- package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +13 -5
- package/src/components/shadow-claw-pages/utils/buildHtmlPageSrcdoc.ts +13 -5
- package/src/core/control-plane-client.ts +15 -0
- package/src/core/utils/initControlPlane.test.ts +187 -0
- package/src/core/utils/initControlPlane.ts +194 -20
- package/src/security/custom-element-security.test.ts +51 -0
- package/src/security/custom-element-security.ts +33 -15
- package/src/server/control-plane-types.ts +1 -0
- package/src/server/control-plane.test.ts +69 -0
- package/src/server/control-plane.ts +45 -3
- package/src/server/mcp/tools/built-in-tools.ts +80 -5
- package/src/server/mcp/tools/client-tool-relay.ts +183 -26
- package/src/server/mcp/tools/mcp-tools.test.ts +140 -0
- package/src/server/middleware/static-files.test.ts +142 -0
- package/src/server/middleware/static-files.ts +66 -8
- package/src/testing/jest-setup.ts +1 -0
- package/src/worker/utils/handleMessage.ts +4 -1
- package/dist/lib/initControlPlane-CsO4UR6_.js.map +0 -1
- package/dist/lib/readGroupFileBytes-Bve-e5e_.js.map +0 -1
- package/dist/lib/shadow-claw-file-viewer-BfDHHgpA.js.map +0 -1
- package/dist/lib/shadow-claw-pages-D54jF1Qq.js.map +0 -1
- package/dist/lib/trusted-types-CkLDpLiZ.js.map +0 -1
- package/dist/public/custom-element-security-NCqQ5lmC.js +0 -1
- package/dist/public/downloadGroupFile-G0BZQgQg.js +0 -1
- package/dist/public/effect-rHYr4nfu.js +0 -1
- package/dist/public/file-viewer-8PdCURDD.js +0 -1
- package/dist/public/initControlPlane-CcGXax0A.js +0 -1
- package/dist/public/peerjs-BZdxWQFv.js +0 -1
- package/dist/public/syncWebMcpRegistration-DD42YsYV.js +0 -1
- package/dist/public/toast-HAq8XWFj.js +0 -58
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator-CJvoC2Uu.js","names":["sleep","extractMarkdownAttachments","normalizeAttachmentPath","#finalizeOpenAI","#finalizeAnthropic","#pushOpenAI","#pushAnthropic","#anthropicBlocks","#sanitize","#openaiText","#openaiReasoningText","#openaiToolCalls","#encryptedApiKey","#apiKeyCache"],"sources":["../../src/db/migrateLegacyDatabase.ts","../../src/storage/migrateLegacyOpfs.ts","../../src/db/openDatabase.ts","../../src/subsystems/channels/browser-chat.ts","../../src/subsystems/channels/channel-registry.ts","../../src/subsystems/channels/imessage.ts","../../src/subsystems/channels/room.ts","../../src/subsystems/channels/telegram.ts","../../src/ui/a2ui/utils/formatA2UIActionPrompt.ts","../../src/core/router.ts","../../src/subsystems/providers/litert-lm-provider.ts","../../src/subsystems/providers/transformers-js-provider.ts","../../src/worker/utils/createTokenUsageMessage.ts","../../src/worker/utils/log.ts","../../src/worker/utils/parseSSEStream.ts","../../src/worker/utils/rate-limit.ts","../../src/worker/StreamAccumulator/StreamAccumulator.ts","../../src/worker/utils/tool-state.ts","../../src/worker/utils/handleInvoke.ts","../../src/core/orchestrator/utils/dispatchSubagentInvoke.ts","../../src/core/orchestrator/utils/invokeAgent.ts","../../src/core/orchestrator/utils/parseDirectToolCommand.ts","../../src/subsystems/skills/parseSkillCommand.ts","../../src/core/orchestrator/utils/enqueue.ts","../../src/core/orchestrator/utils/EventBus.ts","../../src/subsystems/channels/room-manager.ts","../../src/db/getEnabledTasks.ts","../../src/subsystems/tools/cron.ts","../../src/subsystems/tools/task-scheduler.ts","../../src/core/orchestrator/utils/parseStoredStringList.ts","../../src/core/orchestrator/utils/loadChannelConfigurations.ts","../../src/core/orchestrator/utils/types.ts","../../src/core/orchestrator/utils/parseDirectToolCommandPolicy.ts","../../src/core/orchestrator/utils/setupPushTaskListener.ts","../../src/core/orchestrator/utils/initTasks.ts","../../src/core/orchestrator/orchestrator.ts"],"sourcesContent":["import { CONFIG_KEYS, LEGACY_DB_NAME } from \"../config/config.js\";\nimport { getConfig } from \"./getConfig.js\";\nimport { setConfig } from \"./setConfig.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Perform a one-time migration from the legacy unnamespaced database \"shadowclaw\"\n * to the new namespaced database if not already done.\n */\nexport async function migrateLegacyDatabase(\n targetDb: ShadowClawDatabase,\n): Promise<void> {\n if (!targetDb || targetDb.name === LEGACY_DB_NAME) {\n return;\n }\n\n try {\n const alreadyMigrated = await getConfig(\n targetDb,\n CONFIG_KEYS.DB_MIGRATED_FROM_LEGACY,\n );\n if (alreadyMigrated === \"true\") {\n return;\n }\n } catch {\n // ignore read error\n }\n\n try {\n const legacyDb = await new Promise<ShadowClawDatabase | null>((resolve) => {\n const req = indexedDB.open(LEGACY_DB_NAME);\n req.onsuccess = () => {\n const db = req.result;\n if (!db.objectStoreNames || db.objectStoreNames.length === 0) {\n db.close();\n resolve(null);\n\n return;\n }\n resolve(db);\n };\n req.onerror = () => resolve(null);\n });\n\n if (legacyDb) {\n const storeNames = Array.from(legacyDb.objectStoreNames).filter((name) =>\n targetDb.objectStoreNames.contains(name),\n );\n\n for (const storeName of storeNames) {\n await new Promise<void>((resolve) => {\n try {\n const readTx = legacyDb.transaction(storeName, \"readonly\");\n const readStore = readTx.objectStore(storeName);\n const getAllReq = readStore.getAll();\n\n getAllReq.onsuccess = () => {\n const items: any[] = getAllReq.result || [];\n if (items.length > 0) {\n try {\n const writeTx = targetDb.transaction(storeName, \"readwrite\");\n const writeStore = writeTx.objectStore(storeName);\n for (const item of items) {\n writeStore.put(item);\n }\n writeTx.oncomplete = () => resolve();\n writeTx.onerror = () => resolve();\n writeTx.onabort = () => resolve();\n } catch {\n resolve();\n }\n } else {\n resolve();\n }\n };\n getAllReq.onerror = () => resolve();\n } catch {\n resolve();\n }\n });\n }\n\n legacyDb.close();\n }\n } catch (err) {\n console.warn(\"Legacy IndexedDB migration warning:\", err);\n } finally {\n try {\n await setConfig(targetDb, CONFIG_KEYS.DB_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n }\n}\n","import { CONFIG_KEYS, LEGACY_OPFS_ROOT } from \"../config/config.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { setConfig } from \"../db/setConfig.js\";\nimport { getOpfsRootDirName } from \"./storage.js\";\nimport { writeFileHandle, writeOpfsPathViaWorker } from \"./writeFileHandle.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Recursively copy entries from a source OPFS directory to a target OPFS directory.\n */\nasync function copyOpfsEntriesRecursively(\n sourceDir: FileSystemDirectoryHandle,\n targetDir: FileSystemDirectoryHandle,\n pathSegments: string[],\n): Promise<void> {\n for await (const [name, handle] of (sourceDir as any).entries()) {\n if (handle.kind === \"directory\") {\n const nextTargetDir = await targetDir.getDirectoryHandle(name, {\n create: true,\n });\n await copyOpfsEntriesRecursively(handle, nextTargetDir, [\n ...pathSegments,\n name,\n ]);\n } else if (handle.kind === \"file\") {\n const file = await handle.getFile();\n const targetFileHandle = await targetDir.getFileHandle(name, {\n create: true,\n });\n\n try {\n await writeFileHandle(targetFileHandle, file);\n } catch (writeErr) {\n const message =\n writeErr instanceof Error ? writeErr.message : String(writeErr);\n const needsOpfsWorkerFallback = message.includes(\n \"Writable file streams are not supported\",\n );\n\n if (!needsOpfsWorkerFallback) {\n throw writeErr;\n }\n\n await writeOpfsPathViaWorker([...pathSegments, name], file);\n }\n }\n }\n}\n\n/**\n * Perform a one-time migration of OPFS workspace files and directories from the\n * legacy unnamespaced root directory (\"shadowclaw\") to the active namespaced\n * deployment root directory if not already done.\n */\nexport async function migrateLegacyOpfs(db: ShadowClawDatabase): Promise<void> {\n if (!db) {\n return;\n }\n\n try {\n const alreadyMigrated = await getConfig(\n db,\n CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,\n );\n if (alreadyMigrated === \"true\") {\n return;\n }\n } catch {\n // ignore read error\n }\n\n const targetRootName = getOpfsRootDirName();\n if (targetRootName === LEGACY_OPFS_ROOT) {\n return;\n }\n\n if (\n typeof navigator === \"undefined\" ||\n !navigator.storage ||\n typeof navigator.storage.getDirectory !== \"function\"\n ) {\n return;\n }\n\n try {\n const opfsRoot = await navigator.storage.getDirectory();\n let legacyRootHandle: FileSystemDirectoryHandle;\n\n try {\n legacyRootHandle = await opfsRoot.getDirectoryHandle(LEGACY_OPFS_ROOT);\n } catch {\n // Legacy OPFS folder does not exist (fresh installation or already cleaned up)\n try {\n await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n return;\n }\n\n const targetRootHandle = await opfsRoot.getDirectoryHandle(targetRootName, {\n create: true,\n });\n\n await copyOpfsEntriesRecursively(legacyRootHandle, targetRootHandle, [\n targetRootName,\n ]);\n } catch (err) {\n console.warn(\"Legacy OPFS migration warning:\", err);\n } finally {\n try {\n await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n }\n}\n","import { DB_VERSION, getDbName } from \"../config/config.js\";\nimport { setDB } from \"./db.js\";\nimport { migrateLegacyDatabase } from \"./migrateLegacyDatabase.js\";\nimport { migrateLegacyOpfs } from \"../storage/migrateLegacyOpfs.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Open (or create) the IndexedDB database.\n */\nexport function openDatabase(): Promise<ShadowClawDatabase> {\n return new Promise(async (resolve, reject) => {\n let db: ShadowClawDatabase;\n\n const dbName = getDbName();\n const request = indexedDB.open(dbName, DB_VERSION);\n\n request.onupgradeneeded = () => {\n const database = request.result;\n\n // Messages store\n if (!database.objectStoreNames.contains(\"messages\")) {\n const msgStore = database.createObjectStore(\"messages\", {\n keyPath: \"id\",\n });\n msgStore.createIndex(\"by-group-time\", [\"groupId\", \"timestamp\"]);\n msgStore.createIndex(\"by-group\", \"groupId\");\n }\n\n // Sessions store (conversation state per group)\n if (!database.objectStoreNames.contains(\"sessions\")) {\n database.createObjectStore(\"sessions\", { keyPath: \"groupId\" });\n }\n\n // Tasks store (scheduled tasks)\n if (!database.objectStoreNames.contains(\"tasks\")) {\n const taskStore = database.createObjectStore(\"tasks\", {\n keyPath: \"id\",\n });\n\n taskStore.createIndex(\"by-group\", \"groupId\");\n taskStore.createIndex(\"by-enabled\", \"enabled\");\n }\n\n // Config store (key-value)\n if (!database.objectStoreNames.contains(\"config\")) {\n database.createObjectStore(\"config\", { keyPath: \"key\" });\n }\n\n // Pending Web Share Target payloads\n if (!database.objectStoreNames.contains(\"pendingShares\")) {\n const pendingShares = database.createObjectStore(\"pendingShares\", {\n keyPath: \"id\",\n });\n pendingShares.createIndex(\"by-createdAt\", \"createdAt\");\n }\n };\n\n request.onsuccess = async () => {\n db = request.result;\n setDB(db);\n try {\n await migrateLegacyDatabase(db);\n await migrateLegacyOpfs(db);\n } catch (e) {\n console.warn(\"Error running legacy migration:\", e);\n }\n resolve(db);\n };\n\n request.onerror = () => {\n reject(new Error(`Failed to open IndexedDB: ${request.error?.message}`));\n };\n });\n}\n","import { DEFAULT_GROUP_ID } from \"../../config/config.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type { A2UIAction } from \"../../ui/a2ui/types.js\";\n\nimport type {\n Channel,\n ChannelDisplayCallback,\n ChannelMessageCallback,\n ChannelTypingCallback,\n InboundMessage,\n} from \"./types.js\";\n\nexport class BrowserChatChannel implements Channel {\n activeGroupId: string;\n displayCallback: ChannelDisplayCallback | null;\n messageCallback: ChannelMessageCallback | null;\n type: Channel[\"type\"];\n typingCallback: ChannelTypingCallback | null;\n\n constructor() {\n this.type = \"browser\";\n this.messageCallback = null;\n this.typingCallback = null;\n this.displayCallback = null;\n\n this.activeGroupId = DEFAULT_GROUP_ID;\n }\n\n /**\n * Get the currently active group.\n */\n getActiveGroup(): string {\n return this.activeGroupId;\n }\n\n /**\n * Register callback for displaying messages in the UI.\n */\n onDisplay(callback: ChannelDisplayCallback) {\n this.displayCallback = callback;\n }\n\n /**\n * Register callback for inbound messages (from UI → orchestrator).\n */\n onMessage(callback: ChannelMessageCallback) {\n this.messageCallback = callback;\n }\n\n /**\n * Register callback for typing indicator changes.\n */\n onTyping(callback: ChannelTypingCallback) {\n this.typingCallback = callback;\n }\n\n /**\n * Set the currently active group (for UI tab switching).\n */\n setActiveGroup(groupId: string) {\n this.activeGroupId = groupId;\n }\n\n /**\n * Show/hide typing indicator in the UI.\n */\n setTyping(groupId: string, typing: boolean) {\n this.typingCallback?.(groupId, typing);\n }\n\n start() {\n // No-op — browser chat is always \"started\"\n }\n\n stop() {\n // No-op\n }\n\n submit(\n text: string,\n groupId?: string,\n attachments: MessageAttachment[] = [],\n a2uiAction?: A2UIAction,\n freshContext?: boolean,\n subagent?: boolean,\n ) {\n const gid = groupId || this.activeGroupId;\n const msg: InboundMessage = {\n id: ulid(),\n groupId: gid,\n sender: \"You\",\n content: text,\n timestamp: Date.now(),\n channel: \"browser\",\n attachments,\n a2uiAction,\n freshContext,\n subagent,\n };\n\n this.messageCallback?.(msg);\n }\n\n /**\n * Send a response to the browser chat UI for display.\n */\n async send(\n groupId: string,\n text: string,\n _attachments?: MessageAttachment[],\n ) {\n this.displayCallback?.(groupId, text, true);\n }\n}\n","/**\n * ShadowClaw — Channel Registry\n *\n * Generic registry that maps groupId prefixes to Channel implementations.\n * Channels register with a prefix (e.g. \"br:\", \"ext:\", \"custom:\") and the\n * registry routes groupIds to the correct channel at runtime.\n */\n\nimport {\n Channel,\n ChannelRegistrationOptions,\n ChannelType,\n InboundMessage,\n} from \"./types.js\";\n\ninterface ChannelEntry {\n prefix: string;\n channel: Channel;\n badge: string;\n autoTrigger: boolean;\n}\n\nexport class ChannelRegistry {\n _entries: ChannelEntry[];\n\n constructor() {\n this._entries = [];\n }\n\n /**\n * Find the channel that owns a groupId.\n * Matches the longest registered prefix.\n */\n find(groupId: string): Channel | null {\n return this.resolve(groupId)?.channel ?? null;\n }\n\n /**\n * Get a channel by its exact prefix.\n */\n get(prefix: string): Channel | undefined {\n return this._entries.find((e) => e.prefix === prefix)?.channel;\n }\n\n /**\n * Get a badge label for a groupId based on its prefix.\n */\n getBadge(groupId: string): string {\n return this.resolve(groupId)?.badge ?? \"\";\n }\n\n /**\n * Resolve a channel type from the group prefix.\n */\n getChannelType(groupId: string): ChannelType | null {\n return this.resolve(groupId)?.channel.type ?? null;\n }\n\n /**\n * Register a message handler on all channels.\n */\n onMessage(handler: (msg: InboundMessage) => void) {\n for (const entry of this._entries) {\n entry.channel.onMessage(handler);\n }\n }\n\n /**\n * Register a typing handler on all channels.\n */\n onTyping(handler: (groupId: string, typing: boolean) => void) {\n for (const entry of this._entries) {\n if (entry.channel.onTyping) {\n entry.channel.onTyping(handler);\n }\n }\n }\n\n /**\n * List all registered prefixes.\n */\n prefixes(): string[] {\n return this._entries.map((e) => e.prefix);\n }\n\n /**\n * Register a channel for a given prefix.\n */\n register(\n prefix: string,\n channel: Channel,\n badgeOrOptions?: string | ChannelRegistrationOptions,\n ) {\n const options =\n typeof badgeOrOptions === \"string\"\n ? { badge: badgeOrOptions }\n : (badgeOrOptions ?? {});\n\n this._entries.push({\n prefix,\n channel,\n badge: options.badge ?? prefix.replace(/:$/, \"\"),\n autoTrigger: options.autoTrigger ?? false,\n });\n // Sort by prefix length descending so longest‑prefix wins in find()\n this._entries.sort((a, b) => b.prefix.length - a.prefix.length);\n }\n\n /**\n * Resolve the full channel entry for a groupId.\n */\n resolve(groupId: string): ChannelEntry | null {\n for (const entry of this._entries) {\n if (groupId.startsWith(entry.prefix)) {\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Whether this channel should auto-trigger the agent.\n */\n shouldAutoTrigger(groupId: string): boolean {\n return this.resolve(groupId)?.autoTrigger ?? false;\n }\n\n /**\n * Start all registered channels.\n */\n startAll() {\n for (const entry of this._entries) {\n entry.channel.start();\n }\n }\n\n /**\n * Stop all registered channels.\n */\n stopAll() {\n for (const entry of this._entries) {\n entry.channel.stop();\n }\n }\n}\n","import type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport {\n IMESSAGE_POLL_TIMEOUT,\n IMESSAGE_REQUEST_TIMEOUT_MS,\n} from \"../../config/config.js\";\n\nconst IMESSAGE_DEDUP_TTL_MS = 60_000;\n\nexport type IMessageFileReader = (\n groupId: string,\n path: string,\n) => Promise<Blob | null>;\n\nexport class IMessageChannel implements Channel {\n abortController: AbortController | null = null;\n apiKey = \"\";\n apiMode: \"unknown\" | \"beeper-desktop\" | \"legacy\" = \"unknown\";\n cursor: string | null = null;\n fileReader: IMessageFileReader | null = null;\n messageCallback: ChannelMessageCallback | null = null;\n reconnectDelayMs = 1000;\n registeredChatIds: Set<string> = new Set();\n running = false;\n seenMessageIds: Map<string, number> = new Map();\n serverUrl = \"\";\n type: Channel[\"type\"] = \"imessage\";\n\n configure(serverUrl: string, apiKey: string, chatIds: string[]): void {\n this.serverUrl = normalizeBaseUrl(serverUrl);\n this.apiKey = apiKey.trim();\n this.registeredChatIds = new Set(\n chatIds.map((chatId) => chatId.trim()).filter(Boolean),\n );\n this.cursor = null;\n this.apiMode = \"unknown\";\n }\n\n handleIncomingMessage(message: IMessageBridgeMessage): void {\n this.pruneSeenMessageIds();\n\n const chatId = String(\n message.chatId || message.conversationId || \"\",\n ).trim();\n if (!chatId) {\n return;\n }\n\n if (\n this.registeredChatIds.size > 0 &&\n !this.registeredChatIds.has(chatId)\n ) {\n return;\n }\n\n const content = `${message.text || message.body || \"\"}`.trim();\n if (!content) {\n return;\n }\n\n const id = `${message.id || message.guid || `${chatId}:${message.timestamp || message.createdAt || content}`}`;\n if (this.seenMessageIds.has(id)) {\n return;\n }\n\n this.seenMessageIds.set(id, Date.now());\n\n const inbound: InboundMessage = {\n id,\n groupId: `im:${chatId}`,\n sender: `${message.sender || message.handle || message.from || \"iMessage\"}`,\n content,\n timestamp: normalizeTimestamp(message.timestamp || message.createdAt),\n channel: \"imessage\",\n };\n\n this.messageCallback?.(inbound);\n }\n\n handlePollResponse(response: IMessagePollResponse): void {\n if (response.nextCursor !== undefined && response.nextCursor !== null) {\n this.cursor = String(response.nextCursor);\n } else if (response.cursor !== undefined && response.cursor !== null) {\n this.cursor = String(response.cursor);\n }\n\n const messages = Array.isArray(response.messages) ? response.messages : [];\n for (const message of messages) {\n this.handleIncomingMessage(message);\n }\n }\n\n isConfigured(): boolean {\n return this.serverUrl.length > 0;\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n pruneSeenMessageIds(): void {\n const now = Date.now();\n for (const [id, seenAt] of this.seenMessageIds.entries()) {\n if (now - seenAt > IMESSAGE_DEDUP_TTL_MS) {\n this.seenMessageIds.delete(id);\n }\n }\n }\n\n setTyping(groupId: string, typing: boolean): void {\n if (!typing) {\n return;\n }\n\n const chatId = groupId.replace(/^im:/, \"\");\n void this.requestJson(\"/messages/typing\", {\n method: \"POST\",\n body: JSON.stringify({ chatId, typing: true }),\n }).catch(() => {});\n }\n\n start(): void {\n if (!this.isConfigured() || this.running) {\n return;\n }\n\n this.running = true;\n this.abortController = new AbortController();\n void this.poll();\n }\n\n stop(): void {\n this.running = false;\n this.abortController?.abort();\n this.abortController = null;\n }\n\n async ensureApiMode(): Promise<\"beeper-desktop\" | \"legacy\"> {\n if (this.apiMode !== \"unknown\") {\n return this.apiMode;\n }\n\n try {\n await this.requestJson(\"/v1/info\", { method: \"GET\" });\n this.apiMode = \"beeper-desktop\";\n } catch {\n this.apiMode = \"legacy\";\n }\n\n return this.apiMode;\n }\n\n async poll(): Promise<void> {\n while (\n this.running &&\n this.abortController &&\n !this.abortController.signal.aborted\n ) {\n try {\n const params = new URLSearchParams({\n timeout: String(IMESSAGE_POLL_TIMEOUT),\n });\n if (this.cursor) {\n params.set(\"cursor\", this.cursor);\n }\n\n const response = (await this.requestJson(\n `/messages?${params.toString()}`,\n { method: \"GET\" },\n IMESSAGE_REQUEST_TIMEOUT_MS + 5000,\n this.abortController.signal,\n )) as IMessagePollResponse;\n\n this.reconnectDelayMs = 1000;\n this.handlePollResponse(response);\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n break;\n }\n\n console.error(\"iMessage bridge poll error:\", error);\n await sleep(this.reconnectDelayMs);\n this.reconnectDelayMs = Math.min(this.reconnectDelayMs * 2, 30_000);\n }\n }\n }\n\n async requestJson(\n path: string,\n init: RequestInit,\n timeoutMs = IMESSAGE_REQUEST_TIMEOUT_MS,\n parentSignal?: AbortSignal,\n ): Promise<unknown> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n const onAbort = () => controller.abort();\n parentSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n const headers = new Headers(init.headers);\n headers.set(\"Accept\", \"application/json\");\n\n if (\n !headers.has(\"Content-Type\") &&\n init.body &&\n !(init.body instanceof FormData)\n ) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n if (this.apiKey) {\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-API-Key\", this.apiKey);\n }\n\n const response = await fetch(`${this.serverUrl}${path}`, {\n ...init,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n\n throw new Error(\n `iMessage bridge request failed: ${response.status} ${text}`,\n );\n }\n\n if (response.status === 204) {\n return { messages: [] };\n }\n\n return await response.json();\n } finally {\n clearTimeout(timeout);\n parentSignal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n async send(\n groupId: string,\n text: string,\n _providedAttachments?: MessageAttachment[],\n ): Promise<void> {\n const chatId = groupId.replace(/^im:/, \"\");\n const { remainingText, attachments: markdownAttachments } =\n extractMarkdownAttachments(text);\n\n for (const attachment of markdownAttachments) {\n if (!this.fileReader) {\n await this.sendText(\n chatId,\n `[${attachment.alt}] (file: ${attachment.path})`,\n );\n\n continue;\n }\n\n try {\n const blob = await this.fileReader(groupId, attachment.path);\n if (!blob || blob.size === 0) {\n throw new Error(\"Attachment file is empty or unavailable.\");\n }\n\n await this.sendAttachment(chatId, blob, attachment);\n } catch (err) {\n console.warn(\n `iMessage attachment send failed for ${attachment.path}:`,\n err,\n );\n\n await this.sendText(\n chatId,\n `[${attachment.alt}] (file: ${attachment.path})`,\n );\n }\n }\n\n const trimmed = remainingText.trim();\n if (!trimmed) {\n return;\n }\n\n await this.sendText(chatId, trimmed);\n }\n\n async sendAttachment(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const mode = await this.ensureApiMode();\n if (mode === \"beeper-desktop\") {\n await this.sendAttachmentViaBeeperDesktop(chatId, blob, attachment);\n\n return;\n }\n\n await this.sendAttachmentViaLegacyBridge(chatId, blob, attachment);\n }\n\n async sendAttachmentViaBeeperDesktop(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const basename = attachment.path.split(\"/\").pop() || \"attachment.bin\";\n const formData = new FormData();\n formData.append(\"file\", blob, basename);\n formData.append(\"fileName\", basename);\n if (blob.type) {\n formData.append(\"mimeType\", blob.type);\n }\n\n const uploadResponse = (await this.requestJson(\"/v1/assets/upload\", {\n method: \"POST\",\n body: formData,\n })) as { uploadID?: string };\n\n const uploadID = `${uploadResponse.uploadID || \"\"}`.trim();\n if (!uploadID) {\n throw new Error(\"Beeper asset upload failed: missing uploadID\");\n }\n\n await this.requestJson(`/v1/chats/${encodeURIComponent(chatId)}/messages`, {\n method: \"POST\",\n body: JSON.stringify({\n text: attachment.alt || undefined,\n attachment: {\n uploadID,\n fileName: basename,\n mimeType: blob.type || undefined,\n },\n }),\n });\n }\n\n async sendAttachmentViaLegacyBridge(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const basename = attachment.path.split(\"/\").pop() || \"attachment.bin\";\n const formData = new FormData();\n formData.append(\"chatId\", chatId);\n if (attachment.alt) {\n formData.append(\"text\", attachment.alt);\n }\n\n formData.append(\"file\", blob, basename);\n\n await this.requestJson(\"/messages/send\", {\n method: \"POST\",\n body: formData,\n });\n }\n\n async sendText(chatId: string, text: string): Promise<void> {\n const mode = await this.ensureApiMode();\n if (mode === \"beeper-desktop\") {\n await this.requestJson(\n `/v1/chats/${encodeURIComponent(chatId)}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({ text }),\n },\n );\n\n return;\n }\n\n await this.requestJson(\"/messages/send\", {\n method: \"POST\",\n body: JSON.stringify({ chatId, text }),\n });\n }\n}\n\nfunction normalizeBaseUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n\nfunction normalizeTimestamp(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value > 1_000_000_000_000 ? value : value * 1000;\n }\n\n if (typeof value === \"string\") {\n const numeric = Number(value);\n if (Number.isFinite(numeric)) {\n return normalizeTimestamp(numeric);\n }\n\n const parsed = Date.parse(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction extractMarkdownAttachments(text: string): {\n remainingText: string;\n attachments: { alt: string; path: string }[];\n} {\n const attachments: { alt: string; path: string }[] = [];\n const regex = /!?\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n let match: RegExpExecArray | null = null;\n let remainingText = text;\n\n while ((match = regex.exec(text)) !== null) {\n const alt = match[1] || \"\";\n const rawPath = (match[2] || \"\").trim();\n const path = normalizeAttachmentPath(rawPath);\n\n if (path) {\n attachments.push({ alt, path });\n remainingText = remainingText.replace(match[0], \"\");\n }\n }\n\n return { remainingText, attachments };\n}\n\nfunction normalizeAttachmentPath(path: string): string | null {\n if (!path) {\n return null;\n }\n\n const trimmed = path.trim();\n\n // Ignore URI schemes (https:, data:, mailto:, etc.) and protocol-relative URLs.\n if (/^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed) || trimmed.startsWith(\"//\")) {\n return null;\n }\n\n const normalized = trimmed\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/^\\.\\//, \"\");\n\n if (!normalized) {\n return null;\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.some((seg) => seg === \"..\")) {\n return null;\n }\n\n return segments.join(\"/\");\n}\n\ninterface IMessagePollResponse {\n messages?: IMessageBridgeMessage[];\n nextCursor?: string | number | null;\n cursor?: string | number | null;\n}\n\ninterface IMessageBridgeMessage {\n id?: string;\n guid?: string;\n chatId?: string;\n conversationId?: string;\n sender?: string;\n handle?: string;\n from?: string;\n text?: string;\n body?: string;\n timestamp?: number | string;\n createdAt?: number | string;\n}\n","/**\n * ShadowClaw — Room Channel\n *\n * Thin {@link Channel} adapter for multi-party rooms. Outbound messages are\n * broadcast to all room members via the {@link RoomManager} (which delegates\n * transport to the PeerJS mesh with host-relay fallback). Inbound messages are\n * delivered by the manager back through this channel's registered callback so\n * they flow into the orchestrator's normal enqueue path.\n *\n * - Prefix: `room:`\n * - groupId format: `room:<roomId>`\n */\n\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n ChannelTypingCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport type { RoomManager } from \"./room-manager.js\";\n\nexport class RoomChannel implements Channel {\n messageCallback: ChannelMessageCallback | null = null;\n\n running = false;\n type: Channel[\"type\"] = \"room\";\n typingCallback: ChannelTypingCallback | null = null;\n\n private _manager: RoomManager | null = null;\n\n /** Deliver an inbound room message (called by the {@link RoomManager}). */\n deliverInbound(msg: InboundMessage): void {\n this.messageCallback?.(msg);\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n onTyping(callback: ChannelTypingCallback): void {\n this.typingCallback = callback;\n }\n\n /** Wire the room manager used for transport. */\n setManager(manager: RoomManager): void {\n this._manager = manager;\n }\n\n setTyping(_groupId: string, _typing: boolean): void {\n // Typing presence within rooms is not propagated in this version.\n }\n\n start(): void {\n this.running = true;\n }\n\n stop(): void {\n this.running = false;\n }\n\n async send(\n groupId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): Promise<void> {\n if (!this._manager) {\n return;\n }\n\n const roomId = roomIdFromGroupId(groupId);\n this._manager.broadcast(roomId, text, attachments);\n }\n}\n","import type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport {\n TELEGRAM_API_BASE,\n TELEGRAM_MAX_LENGTH,\n TELEGRAM_POLL_TIMEOUT,\n TELEGRAM_PROXY_BASE,\n} from \"../../config/config.js\";\n\nconst TELEGRAM_POLL_RETRY_MIN_MS = 1_000;\nconst TELEGRAM_POLL_RETRY_MAX_MS = 60_000;\n\nexport type TelegramFileReader = (\n groupId: string,\n path: string,\n) => Promise<Blob | null>;\n\nexport class TelegramChannel implements Channel {\n abortController: AbortController | null = null;\n fileReader: TelegramFileReader | null = null;\n messageCallback: ChannelMessageCallback | null = null;\n offset = 0;\n pollRetryDelayMs = TELEGRAM_POLL_RETRY_MIN_MS;\n pollSessionId = 0;\n registeredChatIds: Set<string> = new Set();\n running = false;\n token = \"\";\n type: Channel[\"type\"] = \"telegram\";\n useProxy = false;\n\n buildFileUrl(filePath: string): string {\n const normalizedPath = filePath\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n const base = this.useProxy\n ? \"/telegram/file/bot\"\n : \"https://api.telegram.org/file/bot\";\n\n return `${base}${this.token}/${normalizedPath}`;\n }\n\n buildMethodUrl(methodOrPath: string): string {\n const normalized = methodOrPath.replace(/^\\/+/, \"\");\n const base = this.useProxy ? TELEGRAM_PROXY_BASE : TELEGRAM_API_BASE;\n\n return `${base}${this.token}/${normalized}`;\n }\n\n configure(token: string, chatIds: string[], useProxy = false): void {\n this.token = token.trim();\n this.registeredChatIds = new Set(\n chatIds.map((chatId) => chatId.trim()).filter(Boolean),\n );\n this.useProxy = !!useProxy;\n }\n\n isConfigured(): boolean {\n return this.token.length > 0;\n }\n\n nextPollRetryDelay(): number {\n const delay = this.pollRetryDelayMs;\n this.pollRetryDelayMs = Math.min(\n this.pollRetryDelayMs * 2,\n TELEGRAM_POLL_RETRY_MAX_MS,\n );\n\n return delay;\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n registerChatId(chatId: string): void {\n const normalized = chatId.trim();\n if (!normalized) {\n return;\n }\n\n this.registeredChatIds.add(normalized);\n }\n\n resetPollBackoff(): void {\n this.pollRetryDelayMs = TELEGRAM_POLL_RETRY_MIN_MS;\n }\n\n setTyping(groupId: string, typing: boolean): void {\n if (!typing) {\n return;\n }\n\n const chatId = groupId.replace(/^tg:/, \"\");\n void this.apiCall(\"sendChatAction\", {\n chat_id: chatId,\n action: \"typing\",\n }).catch(() => {});\n }\n\n start(): void {\n if (!this.token || this.running) {\n return;\n }\n\n this.running = true;\n this.resetPollBackoff();\n const sessionId = ++this.pollSessionId;\n const controller = new AbortController();\n this.abortController = controller;\n void this.poll(sessionId, controller);\n }\n\n stop(): void {\n this.running = false;\n this.resetPollBackoff();\n this.pollSessionId += 1;\n this.abortController?.abort();\n this.abortController = null;\n }\n\n async apiCall<T = unknown>(\n method: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetch(this.buildMethodUrl(method), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram API ${method} failed: ${res.status} ${text}`);\n }\n\n return (await res.json()) as T;\n }\n\n async extractAttachments(msg: TelegramMessage): Promise<MessageAttachment[]> {\n const descriptors: TelegramFileDescriptor[] = [];\n\n const largestPhoto = Array.isArray(msg.photo) ? msg.photo.at(-1) : null;\n if (largestPhoto?.file_id) {\n descriptors.push({\n id: largestPhoto.file_id,\n fileName: `photo-${msg.message_id}.png`,\n mimeType: \"image/png\",\n previewDisposition: \"inline\",\n });\n }\n\n if (msg.document?.file_id) {\n descriptors.push({\n id: msg.document.file_id,\n fileName: msg.document.file_name || `document-${msg.message_id}`,\n mimeType: msg.document.mime_type,\n });\n }\n\n if (msg.video?.file_id) {\n descriptors.push({\n id: msg.video.file_id,\n fileName: msg.video.file_name || `video-${msg.message_id}.mp4`,\n mimeType: msg.video.mime_type || \"video/mp4\",\n });\n }\n\n if (msg.audio?.file_id) {\n descriptors.push({\n id: msg.audio.file_id,\n fileName: msg.audio.file_name || `audio-${msg.message_id}.mp3`,\n mimeType: msg.audio.mime_type || \"audio/mpeg\",\n });\n }\n\n if (msg.voice?.file_id) {\n descriptors.push({\n id: msg.voice.file_id,\n fileName: `voice-${msg.message_id}.ogg`,\n mimeType: msg.voice.mime_type || \"audio/ogg\",\n });\n }\n\n if (msg.animation?.file_id) {\n descriptors.push({\n id: msg.animation.file_id,\n fileName: msg.animation.file_name || `animation-${msg.message_id}.mp4`,\n mimeType: msg.animation.mime_type || \"video/mp4\",\n });\n }\n\n if (msg.sticker?.file_id) {\n descriptors.push({\n id: msg.sticker.file_id,\n fileName: `sticker-${msg.message_id}.${inferStickerExtension(msg.sticker)}`,\n mimeType: msg.sticker.is_animated\n ? \"application/x-tgsticker\"\n : msg.sticker.is_video\n ? \"video/webm\"\n : \"image/webp\",\n });\n }\n\n const attachments: MessageAttachment[] = [];\n for (const descriptor of descriptors) {\n const fileInfo = await this.fetchTelegramFileInfo(descriptor.id);\n attachments.push({\n id: descriptor.id,\n fileName: descriptor.fileName,\n mimeType: descriptor.mimeType,\n size: fileInfo.file_size,\n previewDisposition: descriptor.previewDisposition,\n source: {\n kind: \"remote-url\",\n url: this.buildFileUrl(fileInfo.file_path),\n },\n });\n }\n\n return attachments;\n }\n\n async fetchTelegramFileInfo(fileId: string): Promise<TelegramFileInfo> {\n const response = await this.apiCall<TelegramFileApiResponse>(\"getFile\", {\n file_id: fileId,\n });\n\n if (!response.ok || !response.result?.file_path) {\n throw new Error(`Telegram getFile failed for attachment ${fileId}`);\n }\n\n return response.result;\n }\n\n async handleUpdate(update: TelegramUpdate): Promise<void> {\n const msg = update.message;\n if (!msg) {\n return;\n }\n\n const chatId = String(msg.chat.id);\n\n if (msg.text === \"/chatid\") {\n void this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: `Chat ID: ${chatId}\\nRegister this ID in ShadowClaw settings.`,\n }).catch(console.error);\n\n return;\n }\n\n if (msg.text === \"/ping\") {\n void this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: \"Pong! ShadowClaw is running.\",\n }).catch(console.error);\n\n return;\n }\n\n if (!this.registeredChatIds.has(chatId)) {\n return;\n }\n\n const attachments = await this.extractAttachments(msg);\n const textContent = `${msg.text || msg.caption || \"\"}`.trim();\n\n const content =\n textContent ||\n (msg.photo?.length ? \"[Photo]\" : null) ||\n (msg.voice ? \"[Voice message]\" : null) ||\n (msg.video ? \"[Video]\" : null) ||\n (msg.audio ? \"[Audio]\" : null) ||\n (msg.animation ? \"[Animation]\" : null) ||\n (msg.document\n ? `[Document: ${msg.document.file_name || \"unnamed\"}]`\n : null) ||\n (msg.sticker ? `[Sticker: ${msg.sticker.emoji || \"\"}]` : null) ||\n (msg.location\n ? `[Location: ${msg.location.latitude}, ${msg.location.longitude}]`\n : null) ||\n (msg.contact ? `[Contact: ${msg.contact.first_name}]` : null) ||\n \"[Unsupported message type]\";\n\n const senderName =\n msg.from?.first_name ||\n msg.from?.username ||\n String(msg.from?.id || \"Unknown\");\n\n const inbound: InboundMessage = {\n id: String(msg.message_id),\n groupId: `tg:${chatId}`,\n sender: senderName,\n content,\n timestamp: msg.date * 1000,\n channel: \"telegram\",\n attachments,\n };\n\n this.messageCallback?.(inbound);\n }\n\n async poll(sessionId: number, controller: AbortController): Promise<void> {\n while (\n this.running &&\n this.pollSessionId === sessionId &&\n !controller.signal.aborted\n ) {\n try {\n const res = await fetch(\n this.buildMethodUrl(\n `getUpdates?offset=${this.offset}&timeout=${TELEGRAM_POLL_TIMEOUT}`,\n ),\n { signal: controller.signal },\n );\n\n if (!res.ok) {\n console.error(`Telegram poll error: HTTP ${res.status}`);\n await this.waitForRetry(this.nextPollRetryDelay());\n\n continue;\n }\n\n const data = (await res.json()) as TelegramApiResponse;\n if (!data.ok || !Array.isArray(data.result)) {\n await this.waitForRetry(this.nextPollRetryDelay());\n\n continue;\n }\n\n this.resetPollBackoff();\n\n for (const update of data.result) {\n this.offset = update.update_id + 1;\n await this.handleUpdate(update);\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n break;\n }\n\n console.error(\"Telegram poll error:\", error);\n await this.waitForRetry(this.nextPollRetryDelay());\n }\n }\n }\n\n async send(\n groupId: string,\n text: string,\n _providedAttachments?: MessageAttachment[],\n ): Promise<void> {\n const chatId = groupId.replace(/^tg:/, \"\");\n\n // Extract and send inline images and documents as Telegram attachments\n const { remainingText, attachments: markdownAttachments } =\n extractMarkdownAttachments(text);\n\n for (const att of markdownAttachments) {\n if (this.fileReader) {\n try {\n const blob = await this.fileReader(groupId, att.path);\n if (blob && blob.size > 0) {\n const lowerPath = att.path.toLowerCase();\n const isImage =\n lowerPath.endsWith(\".png\") ||\n lowerPath.endsWith(\".jpg\") ||\n lowerPath.endsWith(\".jpeg\") ||\n lowerPath.endsWith(\".gif\") ||\n lowerPath.endsWith(\".webp\");\n\n if (isImage) {\n await this.sendPhoto(chatId, blob, att.alt, att.path);\n } else {\n await this.sendDocument(chatId, blob, att.alt, att.path);\n }\n\n continue;\n }\n } catch (err) {\n console.warn(\n `TelegramChannel: failed to read file ${att.path}:`,\n err,\n );\n }\n }\n\n // Fallback: send the markdown as text if file reader is unavailable\n await this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: `[${att.alt}] (file: ${att.path})`,\n });\n }\n\n // Send remaining text if any\n const trimmed = remainingText.trim();\n if (trimmed) {\n const chunks = splitText(trimmed, TELEGRAM_MAX_LENGTH);\n for (const chunk of chunks) {\n await this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: chunk,\n });\n }\n }\n }\n\n async sendDocument(\n chatId: string,\n blob: Blob,\n caption: string,\n filename: string,\n ): Promise<void> {\n const basename = filename.split(\"/\").pop() || \"document.file\";\n const formData = new FormData();\n formData.append(\"chat_id\", chatId);\n formData.append(\"document\", blob, basename);\n if (caption) {\n formData.append(\"caption\", caption);\n }\n\n const res = await fetch(this.buildMethodUrl(\"sendDocument\"), {\n method: \"POST\",\n body: formData,\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram sendDocument failed: ${res.status} ${text}`);\n }\n }\n\n async sendPhoto(\n chatId: string,\n blob: Blob,\n caption: string,\n filename: string,\n ): Promise<void> {\n const basename = filename.split(\"/\").pop() || \"image.png\";\n const formData = new FormData();\n formData.append(\"chat_id\", chatId);\n formData.append(\"photo\", blob, basename);\n if (caption) {\n formData.append(\"caption\", caption);\n }\n\n const res = await fetch(this.buildMethodUrl(\"sendPhoto\"), {\n method: \"POST\",\n body: formData,\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram sendPhoto failed: ${res.status} ${text}`);\n }\n }\n\n async waitForRetry(ms: number): Promise<void> {\n await sleep(ms);\n }\n}\n\nfunction splitText(text: string, max: number): string[] {\n if (text.length <= max) {\n return [text];\n }\n\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= max) {\n chunks.push(remaining);\n\n break;\n }\n\n let end = max;\n const lastNewline = remaining.lastIndexOf(\"\\n\", max);\n if (lastNewline > max * 0.5) {\n end = lastNewline;\n }\n\n chunks.push(remaining.slice(0, end));\n remaining = remaining.slice(end);\n }\n\n return chunks;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\ninterface TelegramApiResponse {\n ok?: boolean;\n result?: TelegramUpdate[];\n}\n\ninterface TelegramFileApiResponse {\n ok?: boolean;\n result?: TelegramFileInfo;\n}\n\ninterface TelegramFileInfo {\n file_id: string;\n file_path: string;\n file_size?: number;\n}\n\ninterface TelegramUpdate {\n update_id: number;\n message?: TelegramMessage;\n}\n\ninterface TelegramMessage {\n message_id: number;\n chat: { id: number; type: string };\n from?: { id: number; first_name?: string; username?: string };\n date: number;\n text?: string;\n caption?: string;\n photo?: Array<{ file_id: string; width?: number; height?: number }>;\n voice?: { file_id: string; mime_type?: string };\n video?: { file_id: string; file_name?: string; mime_type?: string };\n audio?: { file_id: string; file_name?: string; mime_type?: string };\n animation?: { file_id: string; file_name?: string; mime_type?: string };\n document?: { file_id: string; file_name?: string; mime_type?: string };\n sticker?: {\n emoji?: string;\n file_id: string;\n is_animated?: boolean;\n is_video?: boolean;\n };\n location?: { latitude: number; longitude: number };\n contact?: { first_name: string };\n}\n\ninterface TelegramFileDescriptor {\n id: string;\n fileName: string;\n mimeType?: string;\n previewDisposition?: \"inline\" | \"file\";\n}\n\nfunction inferStickerExtension(sticker: TelegramMessage[\"sticker\"]): string {\n if (sticker?.is_animated) {\n return \"tgs\";\n }\n\n if (sticker?.is_video) {\n return \"webm\";\n }\n\n return \"webp\";\n}\n\nexport function extractMarkdownAttachments(text: string): {\n remainingText: string;\n attachments: { alt: string; path: string }[];\n} {\n const attachments: { alt: string; path: string }[] = [];\n const regex = /!?\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n\n let match;\n let remainingText = text;\n\n // Find all matches\n while ((match = regex.exec(text)) !== null) {\n const alt = match[1];\n const path = (match[2] || \"\").trim();\n\n const normalizedPath = normalizeAttachmentPath(path);\n\n // Only capture valid normalized workspace-relative paths.\n if (normalizedPath) {\n attachments.push({ alt, path: normalizedPath });\n // Remove the markdown from the text\n remainingText = remainingText.replace(match[0], \"\");\n }\n }\n\n return { remainingText, attachments };\n}\n\nfunction normalizeAttachmentPath(path: string): string | null {\n if (!path) {\n return null;\n }\n\n const trimmed = path.trim();\n\n // Ignore URI schemes (https:, data:, mailto:, etc.) and protocol-relative URLs.\n if (/^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed) || trimmed.startsWith(\"//\")) {\n return null;\n }\n\n const normalized = trimmed\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/^\\.\\//, \"\");\n\n if (!normalized) {\n return null;\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.some((seg) => seg === \"..\")) {\n return null;\n }\n\n return segments.join(\"/\");\n}\n","import type { A2UIAction } from \"../types.js\";\n\n/**\n * Build the `[A2UI ACTION]` prompt delivered to the surface owner's agent when\n * a user interacts with a surface (clicks a Button, submits a TextField, …).\n *\n * The prompt is intentionally prefixed with `[A2UI ACTION]` so the orchestrator\n * can force-trigger the agent regardless of channel. It is the single source of\n * truth shared by the local chat UI and the multi-party room manager.\n *\n * @param action The action fired on the surface.\n * @param actorAlias Optional human-readable name of the peer that fired the\n * action (used in shared room surfaces to give the owner context).\n */\nexport function formatA2UIActionPrompt(\n action: A2UIAction,\n actorAlias?: string,\n): string {\n const dataModelJson = JSON.stringify(action.dataModel ?? {}, null, 2);\n const actor = actorAlias ? `${actorAlias}` : \"The user\";\n\n return (\n `[A2UI ACTION]\\n` +\n `surfaceId: \"${action.surfaceId}\"\\n` +\n `actionId: \"${action.actionId}\"\\n` +\n (actorAlias ? `firedBy: \"${actorAlias}\"\\n` : \"\") +\n `dataModel:\\n${dataModelJson}\\n\\n` +\n `Instructions: ${actor} triggered the \"${action.actionId}\" action on ` +\n `surface \"${action.surfaceId}\". ` +\n `The dataModel above contains the current form values. ` +\n `Use the appropriate tool(s) to fulfill the action based on the actionId ` +\n `and dataModel values. ` +\n `After you have a result, call render_component with action ` +\n `\"updateDataModel\" on surfaceId \"${action.surfaceId}\" to update the ` +\n `surface (e.g. set path \"/result\" to the output value). ` +\n `Do NOT respond with plain text only — always update the surface via ` +\n `render_component.`\n );\n}\n","import type { ChannelRegistry } from \"../subsystems/channels/channel-registry.js\";\nimport type { Channel } from \"../subsystems/channels/types.js\";\nimport type { MessageAttachment } from \"../content/types.js\";\n\nexport class Router {\n /**\n * Format messages in XML for agent context\n */\n static formatMessagesXml(messages: any[]): string {\n const escapeXml = (s: string) =>\n s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n\n const lines = messages.map(\n (m) =>\n `<message sender=\"${escapeXml(m.sender)}\" time=\"${new Date(m.timestamp).toISOString()}\">${escapeXml(m.content)}</message>`,\n );\n\n return `<messages>\\n${lines.join(\"\\n\")}\\n</messages>`;\n }\n\n /**\n * Strip internal tags from agent output\n */\n static formatOutbound(rawText: string): string {\n return rawText.replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\").trim();\n }\n\n registry: ChannelRegistry;\n\n /**\n * Routes outbound messages and typing indicators to the correct channel\n * based on the groupId prefix, using a ChannelRegistry.\n */\n constructor(registry: ChannelRegistry) {\n this.registry = registry;\n }\n\n /**\n * Find the appropriate channel for a groupId\n */\n findChannel(groupId: string): Channel | null {\n return this.registry.find(groupId);\n }\n\n /**\n * Set typing indicator on the correct channel\n */\n setTyping(groupId: string, typing: boolean): void {\n const channel = this.findChannel(groupId);\n channel?.setTyping(groupId, typing);\n }\n\n /**\n * Send a message to the correct channel\n */\n async send(\n groupId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): Promise<void> {\n const channel = this.findChannel(groupId);\n if (!channel) {\n console.warn(`No channel for groupId: ${groupId}`);\n\n return;\n }\n\n await channel.send(groupId, text, attachments);\n }\n}\n","/**\n * LiteRT-LM Browser Provider\n *\n * Wraps the Google LiteRT-LM Web API (@litert-lm/core) to provide\n * in-browser LLM inference for Gemma 4 models via WebGPU.\n *\n * https://developers.google.com/edge/litert-lm/js\n *\n * Currently supports:\n * - litert-community/gemma-4-E2B-it-litert-lm (gemma-4-E2B-it-web.litertlm)\n * - litert-community/gemma-4-E4B-it-litert-lm (gemma-4-E4B-it-web.litertlm)\n *\n * Model IDs in config use the litert-community HuggingFace repo ID. We resolve\n * the actual .litertlm file URL from the repo's main branch.\n */\n\nimport { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\nimport { ShadowClawDatabase } from \"../../db/db.js\";\nimport { createLogMessage } from \"../../worker/utils/createLogMessage.js\";\nimport { createToolActivityMessage } from \"../../worker/utils/createToolActivityMessage.js\";\nimport { executeTool } from \"../../worker/utils/executeTool.js\";\nimport { setPostHandler } from \"../../worker/utils/post.js\";\nimport { ToolDefinition } from \"../tools/tools.js\";\n\nimport type { SubagentInvokeContext } from \"../../worker/tools/spawn-subagent/spawn-subagent.js\";\n\n/**\n * Map from provider model ID (HuggingFace repo) to the .litertlm web model URL.\n */\nconst LITERT_LM_MODEL_URLS: Record<string, string> = {\n \"litert-community/gemma-4-E2B-it-litert-lm\":\n \"https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it-web.litertlm\",\n \"litert-community/gemma-4-E4B-it-litert-lm\":\n \"https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it-web.litertlm\",\n};\n\nexport const LITERT_LM_SUPPORTED_MODELS = Object.keys(LITERT_LM_MODEL_URLS);\n\nexport const DEFAULT_LITERT_LM_MODEL =\n \"litert-community/gemma-4-E2B-it-litert-lm\";\n\n/**\n * Returns true if the LiteRT-LM JS API is available (WebGPU required).\n */\nexport function isLiteRtLmSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"gpu\" in navigator &&\n typeof WebAssembly !== \"undefined\" &&\n \"Suspending\" in WebAssembly\n );\n}\n\n/**\n * Lazy-loaded LiteRT-LM Engine singleton per model.\n * We keep one engine alive to avoid expensive re-initialization.\n */\nlet liteRtEngine: any | null = null;\nlet liteRtEngineModelId: string | null = null;\n\nlet liteRtEnginePromise: Promise<any> | null = null;\nlet liteRtEnginePromiseModelId: string | null = null;\n\nimport {\n DEFAULT_CHUNK_SIZE,\n loadModelStream,\n type ModelProgressCallback as LiteRtProgressCallback,\n} from \"./utils/index.js\";\n\n/**\n * Persistent Cache Storage bucket for downloaded `.litertlm` model weights.\n */\nexport const LITERT_LM_CACHE_NAME = \"shadow-claw-litertlm-models\";\nexport const LITERT_LM_CHUNK_SIZE = DEFAULT_CHUNK_SIZE;\n\nexport async function loadLiteRtModelStream(\n url: string,\n onProgress: LiteRtProgressCallback,\n abortSignal?: AbortSignal,\n): Promise<ReadableStream<Uint8Array>> {\n return loadModelStream(url, onProgress, abortSignal, {\n cacheName: LITERT_LM_CACHE_NAME,\n chunkSize: LITERT_LM_CHUNK_SIZE,\n });\n}\n\nasync function getLiteRtEngine(\n modelId: string,\n onProgress?: LiteRtProgressCallback,\n abortSignal?: AbortSignal,\n): Promise<any> {\n if (liteRtEngineModelId === modelId && liteRtEngine) {\n return liteRtEngine;\n }\n\n if (liteRtEnginePromise && liteRtEnginePromiseModelId === modelId) {\n return liteRtEnginePromise;\n }\n\n liteRtEnginePromiseModelId = modelId;\n liteRtEnginePromise = (async () => {\n if (liteRtEngine) {\n try {\n await liteRtEngine.delete?.();\n } catch {}\n\n liteRtEngine = null;\n liteRtEngineModelId = null;\n }\n\n const modelUrl = LITERT_LM_MODEL_URLS[modelId];\n if (!modelUrl) {\n throw new Error(\n `LiteRT-LM: Model '${modelId} is not supported. Supported models: ${LITERT_LM_SUPPORTED_MODELS.join(\", \")}`,\n );\n }\n\n const litertlm = await import(\"@litert-lm/core\").catch(() => {\n throw new Error(\n \"LiteRT-LM: The @litert-lm/core package is not installed. Run: npm install @litert-lm/core\",\n );\n });\n\n const Engine: any = litertlm.Engine ?? (litertlm as any).default?.Engine;\n if (typeof Engine?.create !== \"function\") {\n throw new Error(\n \"LiteRT-LM: Could not locate Engine.create in @litert-lm/core. Ensure you have the latest version installed.\",\n );\n }\n\n const modelStream = await loadLiteRtModelStream(\n modelUrl,\n onProgress ?? (() => {}),\n abortSignal,\n );\n\n const engine = await Engine.create({\n model: modelStream,\n mainExecutorSettings: {\n maxNumTokens: 8192,\n },\n });\n\n liteRtEngine = engine;\n liteRtEngineModelId = modelId;\n\n return engine;\n })();\n\n try {\n return await liteRtEnginePromise;\n } finally {\n liteRtEnginePromise = null;\n liteRtEnginePromiseModelId = null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tool-call output parsing (model-agnostic)\n// ---------------------------------------------------------------------------\n\n/**\n * Internal parsed tool-call / response envelope.\n */\ninterface LiteRtParsed {\n type: \"response\" | \"tool_use\";\n format?: \"json\" | \"model_specific\";\n response?: string;\n tool_calls?: Array<{\n id?: string;\n name: string;\n input?: Record<string, any>;\n }>;\n}\n\n/**\n * Try to parse Gemma 4's native tool-call syntax:\n * <|tool_call>call:TOOLNAME{...args...}<tool_call|>\n *\n * The model sometimes emits <|\"|> instead of literal quote chars, and may\n * omit the closing sentinel if generation was cut off.\n *\n * Returns a normalised { name, input } object on success, or null.\n *\n * NOTE: This is a *fallback* for models that ignore the JSON-envelope\n * instructions. The primary path is always the JSON envelope.\n */\nexport function parseModelSpecificToolCall(\n text: string,\n): { name: string; input: Record<string, any> } | null {\n if (!text) {\n return null;\n }\n\n // Match <|tool_call>call:TOOLNAME{...}<tool_call|> (closing sentinel optional)\n const match = text.match(\n /<\\|tool_call>call:([A-Za-z0-9_]+)(\\{[\\s\\S]*?)(?:<tool_call\\|>|$)/,\n );\n if (!match) {\n return null;\n }\n\n const name = match[1];\n let body = match[2];\n\n // Replace the Gemma 4 quote sentinel <|\"|> → \" so the body becomes\n // valid JSON-like text that we can parse.\n body = body.replace(/<\\|\"\\|>/g, '\"');\n\n /**\n * Gemma 4 emits JavaScript-style objects with unquoted property names,\n * e.g. {queries:[\"blueberries\"]}. This function wraps bare identifier keys\n * with double quotes so the result is valid JSON.\n */\n function normaliseToJson(src: string): string {\n // Quote any unquoted object key: an identifier followed by a colon that\n // is NOT already preceded by a double quote.\n\n return src.replace(\n /([{,]\\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\\s*:)/g,\n '$1\"$2\"$3',\n );\n }\n\n // Attempt JSON.parse of the argument block, with progressive relaxation.\n let input: Record<string, any> = {};\n\n const candidates = [body, normaliseToJson(body)];\n\n for (const candidate of candidates) {\n try {\n const parsed = JSON.parse(candidate);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n input = parsed;\n\n break;\n }\n } catch {\n // try next candidate\n }\n }\n\n // If still unparsed, try extracting the first complete {...} block.\n if (Object.keys(input).length === 0) {\n const start = body.indexOf(\"{\");\n const end = body.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n const slice = body.slice(start, end + 1);\n for (const candidate of [slice, normaliseToJson(slice)]) {\n try {\n const parsed = JSON.parse(candidate);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n input = parsed;\n\n break;\n }\n } catch {\n // Best-effort: leave input as {}\n }\n }\n }\n }\n\n return { name, input };\n}\n\n/**\n * Parse the model's accumulated response into a structured envelope.\n *\n * Priority:\n * 1. JSON envelope { \"type\": \"tool_use\" | \"response\", ... } (model-agnostic, primary)\n * 2. Gemma 4 native <|tool_call>call:NAME{...}<tool_call|> (fallback)\n *\n * Returns null when the output is plain text with no recognised structure.\n */\nexport function parseLiteRtStructured(raw: string): LiteRtParsed | null {\n const text = sanitizeModelOutput(String(raw || \"\"), \"litert_lm\").trim();\n if (!text) {\n return null;\n }\n\n // ── 1. Try JSON (primary, model-agnostic) ──────────────────────────────\n const tryJson = (src: string): LiteRtParsed | null => {\n try {\n const obj = JSON.parse(src);\n if (\n obj &&\n typeof obj === \"object\" &&\n (obj.type === \"tool_use\" || obj.type === \"response\")\n ) {\n // Fix common model typos\n if (obj.tools_calls && !obj.tool_calls) {\n obj.tool_calls = obj.tools_calls;\n }\n\n return { ...obj, format: \"json\" } as LiteRtParsed;\n }\n } catch {\n // fall through\n }\n\n return null;\n };\n\n let result = tryJson(text);\n if (result) {\n return result;\n }\n\n // Try extracting the first {...} block in case the model wrapped it in prose.\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n result = tryJson(text.slice(start, end + 1));\n if (result) {\n return result;\n }\n }\n\n // ── 2. Regex fallback for malformed JSON ─────────────────────────────\n // Handle cases where the model forgets closing braces or brackets\n // e.g. {\"type\": \"tool_use\", \"tools_calls\": [{ \"name\": \"web_search\", \"input\": { \"query\": \"...\" } ]}\n if (text.includes('\"tool_use\"')) {\n const nameMatch = /\"name\"\\s*:\\s*\"([^\"]+)\"/.exec(text);\n if (nameMatch) {\n let input = {};\n const inputMatch = /\"input\"\\s*:\\s*(\\{.*?\\})\\s*(?:]|\\}|\"|$)/s.exec(text);\n if (inputMatch) {\n try {\n input = JSON.parse(inputMatch[1]);\n } catch {\n // Leave input empty if it's too mangled\n }\n }\n\n return {\n type: \"tool_use\",\n format: \"json\",\n tool_calls: [\n {\n id: `litert_${Date.now()}`,\n name: nameMatch[1],\n input,\n },\n ],\n };\n }\n }\n\n // ── 2. Gemma 4 native tool-call format (fallback) ──────────────────────\n const native = parseModelSpecificToolCall(text);\n if (native) {\n return {\n type: \"tool_use\",\n format: \"model_specific\",\n tool_calls: [\n {\n id: `litert_${Date.now()}`,\n name: native.name,\n input: native.input,\n },\n ],\n };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Conversation building helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build the preface (system messages) and per-turn text strings that will be\n * sent to the LiteRT-LM stateful conversation API.\n *\n * When tools are active we prepend JSON-envelope instructions so that any\n * LiteRT model (not just Gemma 4) knows how to signal tool calls.\n */\nfunction buildLiteRtMessages(\n systemPrompt: string,\n messages: any[],\n tools: ToolDefinition[],\n): { preface: any[]; turns: string[] } {\n const preface: any[] = [];\n\n // Compose the effective system content: original prompt + tool instructions.\n let effectiveSystem = systemPrompt || \"\";\n\n if (tools.length > 0) {\n const toolHints = tools\n .map((t) => {\n const params = Object.keys(t.input_schema.properties || {}).join(\", \");\n const brief = t.description.split(\". \")[0];\n\n return `${t.name}(${params}): ${brief}`;\n })\n .join(\"\\n\");\n\n const jsonInstructions = [\n \"\",\n \"TOOL CALLING INSTRUCTIONS:\",\n \"Return ONLY valid JSON (no markdown fences).\",\n 'To call a tool: {\"type\":\"tool_use\",\"tool_calls\":[{\"name\":\"<tool>\",\"input\":{...}}]}',\n 'To reply: {\"type\":\"response\",\"response\":\"<your answer>\"}',\n \"IMPORTANT: When you need to use a tool, output ONLY the JSON above — do NOT describe the call as text.\",\n \"\",\n \"Available tools:\",\n toolHints,\n ].join(\"\\n\");\n\n effectiveSystem = effectiveSystem\n ? effectiveSystem + jsonInstructions\n : jsonInstructions;\n }\n\n if (effectiveSystem) {\n preface.push({ role: \"system\", content: effectiveSystem });\n }\n\n // Build prior turns. All message types (text, tool_use, tool_result) are\n // serialised to a flat string so the stateful conversation engine can replay\n // them without native tool-call support.\n const turns: string[] = [];\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const content = Array.isArray(msg.content)\n ? msg.content\n .map((b: any) => {\n if (b?.type === \"text\") {\n return b.text;\n }\n\n if (b?.type === \"tool_result\") {\n return `[TOOL_RESULT ${b.tool_use_id}] ${String(b.content || \"\")}`;\n }\n\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\")\n : String(msg.content || \"\");\n if (content) {\n turns.push(content);\n }\n } else if (msg.role === \"assistant\") {\n // Skip — LiteRT conversation is stateful; assistant turns are generated\n // by the model itself.\n }\n }\n\n return { preface, turns };\n}\n\n/**\n * Main entry point. Invokes the LiteRT-LM browser engine and streams the\n * response back via the emit callback, following the same protocol as\n * invokeWithTransformersJs / invokeWithPromptApi.\n *\n * When `tools` is non-empty the provider enters an agentic loop:\n * 1. Append JSON-envelope tool instructions to the system prompt.\n * 2. Parse the model's full response for a tool_use or response envelope.\n * 3. If tool_use: execute the tools, append results, loop.\n * 4. If response (or plain text): emit the final text and return.\n */\nexport async function invokeWithLiteRtLm(\n db: ShadowClawDatabase,\n groupId: string,\n systemPrompt: string,\n messages: any[],\n _maxTokens: number,\n emit: (message: any) => Promise<void> | void,\n abortSignal: AbortSignal | undefined,\n modelId: string,\n tools?: ToolDefinition[],\n invokeContext?: SubagentInvokeContext,\n) {\n if (!isLiteRtLmSupported()) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: \"⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.\",\n },\n });\n\n return;\n }\n\n await emit(\n createLogMessage(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: LiteRT-LM (Browser · WebGPU) · Model: ${modelId}`,\n ),\n );\n\n // Emit model-download-progress so the UI shows a loading state\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"running\",\n progress: 0,\n message: `Loading LiteRT-LM model: ${modelId}…`,\n },\n });\n\n const formatMb = (bytes: number) => (bytes / (1024 * 1024)).toFixed(0);\n\n let lastEmittedPct = -1;\n\n const onProgress: LiteRtProgressCallback = (received, total, fromCache) => {\n const progress = total ? received / total : null;\n const pct = progress != null ? Math.floor(progress * 100) : -1;\n\n if (pct === lastEmittedPct && !fromCache) {\n return;\n }\n\n lastEmittedPct = pct;\n\n const message = fromCache\n ? `Loaded ${modelId} from cache (${formatMb(received)} MB )`\n : total\n ? `Downloading ${modelId}: ${formatMb(received)} / ${formatMb(total)} MB`\n : `Downloading ${modelId}: ${formatMb(received)} MB`;\n\n void emit({\n type: \"model-download-progress\",\n payload: { groupId, status: \"running\", progress, message },\n });\n };\n\n let engine: any;\n\n try {\n engine = await getLiteRtEngine(modelId, onProgress, abortSignal);\n } catch (err: any) {\n if (abortSignal?.aborted || err?.name === \"AbortError\") {\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"error\",\n progress: null,\n message: \"LiteRT-LM model download cancelled.\",\n },\n });\n\n return;\n }\n\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"error\",\n progress: null,\n message: `LiteRT-LM model failed to load: ${err?.message ?? String(err)}`,\n },\n });\n\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM failed to initialize: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"done\",\n progress: 1,\n message: \"LiteRT-LM model ready.\",\n },\n });\n\n const activeTools = tools ?? [];\n\n const { preface, turns } = buildLiteRtMessages(\n systemPrompt,\n messages,\n activeTools,\n );\n\n let conversation: any;\n try {\n conversation = await engine.createConversation({\n preface: { messages: preface },\n });\n } catch (err: any) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM failed to create conversation: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n // Replay prior turns (if any) — LiteRT-LM conversation is stateful.\n // All turns except the final user turn are sent non-streaming.\n const priorTurns = turns.slice(0, -1);\n const lastTurn = turns[turns.length - 1] ?? \"Hello.\";\n\n for (const turn of priorTurns) {\n if (abortSignal?.aborted) {\n return;\n }\n\n try {\n await conversation.sendMessage(turn);\n } catch {\n // If replaying history fails, continue to latest turn anyway\n }\n }\n\n if (abortSignal?.aborted) {\n return;\n }\n\n // ── Agentic tool-calling loop ─────────────────────────────────────────────\n // We maintain a mutable list of messages that grows as tool results arrive,\n // and re-send the current user query on each iteration (with tool results\n // appended) until the model emits a plain response or we hit the limit.\n const MAX_ITERATIONS = 10;\n let currentTurn = lastTurn;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n if (abortSignal?.aborted) {\n return;\n }\n\n await emit({ type: \"streaming-start\", payload: { groupId } });\n\n let accumulated = \"\";\n try {\n const stream = conversation.sendMessageStreaming(currentTurn);\n for await (const chunk of stream) {\n if (abortSignal?.aborted) {\n break;\n }\n\n const text = chunk?.content?.[0]?.text ?? \"\";\n if (text) {\n const cleaned = sanitizeModelOutput(text, \"litert_lm\");\n if (cleaned) {\n accumulated += cleaned;\n // Stream chunks to the UI so the user sees partial output\n await emit({\n type: \"streaming-chunk\",\n payload: { groupId, text: cleaned },\n });\n }\n }\n }\n } catch (err: any) {\n if (abortSignal?.aborted) {\n return;\n }\n\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM generation error: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n // ── Parse the accumulated output ───────────────────────────────────────\n const parsed =\n activeTools.length > 0 ? parseLiteRtStructured(accumulated) : null;\n\n if (parsed?.type === \"tool_use\") {\n // Tool call detected — hide the raw JSON from the user.\n await emit({ type: \"streaming-end\", payload: { groupId } });\n\n const calls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];\n if (calls.length === 0) {\n // Malformed tool_use with no calls — treat as final response.\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text: \"(no response)\" },\n });\n await emit({\n type: \"response\",\n payload: { groupId, text: \"(no response)\" },\n });\n\n return;\n }\n\n // Execute each tool and collect results.\n const resultLines: string[] = [];\n const isNative = parsed.format === \"model_specific\";\n\n for (const call of calls) {\n await emit(createToolActivityMessage(groupId, call.name, \"running\"));\n // LiteRT-LM runs on the main thread (emit === handleWorkerMessage).\n // Route builtin-AI cross-thread requests (e.g. summarize_text's\n // \"request-native-ai-task\") back through emit so the main-thread\n // handler rseolves them; otherwise post() fails through to\n // self.postMessage and the tool promise hangs forever. Matches the\n // transformers-js / prompt-api providers.\n setPostHandler((msg) => {\n void emit(msg);\n });\n\n let output: any;\n try {\n output = await executeTool(db, call.name, call.input || {}, groupId, {\n allowedTools: activeTools,\n invokeContext,\n });\n } catch (err: any) {\n output = `Error: ${err?.message ?? String(err)}`;\n } finally {\n setPostHandler(null);\n }\n\n await emit(createToolActivityMessage(groupId, call.name, \"done\"));\n\n const resultText =\n typeof output === \"string\" ? output : JSON.stringify(output);\n\n if (isNative) {\n resultLines.push(`<|tool_response>${resultText}<|tool_response|>`);\n } else {\n resultLines.push(\n `[TOOL_RESULT ${call.id ?? call.name}] ${resultText}`,\n );\n }\n }\n\n // Feed results back to the model as the next turn.\n if (isNative) {\n currentTurn = resultLines.join(\"\\n\");\n } else {\n const lastUserContent = turns[turns.length - 1] ?? \"\";\n currentTurn = [\n ...resultLines,\n \"\",\n \"Based on the above tool results, please respond to the original request.\",\n lastUserContent ? `Original request: \"${lastUserContent}\"` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n continue; // next iteration\n }\n\n // ── Plain text or JSON response envelope ─────────────────────────────\n let finalText: string;\n if (parsed?.type === \"response\" && parsed.response) {\n finalText = sanitizeModelOutput(parsed.response, \"litert_lm\");\n } else {\n // No recognised structure — treat accumulated text as the answer.\n finalText = sanitizeModelOutput(accumulated, \"litert_lm\");\n }\n\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text: finalText },\n });\n\n await emit({\n type: \"response\",\n payload: { groupId, text: finalText },\n });\n\n return;\n }\n\n // Exhausted iterations without a plain-text response.\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: \"⚠️ LiteRT-LM reached the maximum number of tool-calling iterations without producing a final response.\",\n },\n });\n}\n","import { CONFIG_KEYS } from \"../../config/config.js\";\nimport { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\nimport { ShadowClawDatabase } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { toTrustedScriptUrl } from \"../../security/trusted-types.js\";\nimport { createLogMessage } from \"../../worker/utils/createLogMessage.js\";\nimport { createToolActivityMessage } from \"../../worker/utils/createToolActivityMessage.js\";\nimport { executeTool } from \"../../worker/utils/executeTool.js\";\nimport { setPostHandler } from \"../../worker/utils/post.js\";\nimport { ToolDefinition } from \"../tools/tools.js\";\n\nimport type { SubagentInvokeContext } from \"../../worker/tools/spawn-subagent/spawn-subagent.js\";\n\nclass TransformersJsManager {\n private chunkCallbacks = new Map<string, (payload: any) => void>();\n private loadRejects = new Map<string, (reason: any) => void>();\n private loadResolves = new Map<string, () => void>();\n private pendingRejects = new Map<string, (reason: any) => void>();\n private pendingResolves = new Map<string, (value: any) => void>();\n private progressCallbacks = new Map<string, (payload: any) => void>();\n private thinkingCallbacks = new Map<string, (text: string) => void>();\n private worker: Worker | null = null;\n\n async generate(\n messages: any[],\n maxTokens: number,\n groupId: string,\n onChunk: (text: string) => void,\n onThinking?: (text: string) => void,\n tools?: any[],\n ): Promise<string> {\n const worker = this.getWorker();\n\n return new Promise((resolve, reject) => {\n this.pendingResolves.set(groupId, resolve);\n this.pendingRejects.set(groupId, reject);\n this.chunkCallbacks.set(groupId, (payload) => onChunk(payload.text));\n if (onThinking) {\n this.thinkingCallbacks.set(groupId, onThinking);\n }\n\n worker.postMessage({\n type: \"generate\",\n payload: { messages, maxTokens, groupId, tools },\n });\n });\n }\n\n async load(\n modelId: string,\n device: string,\n dtypeStrategy: string,\n groupId: string,\n onProgress: (payload: any) => void,\n ): Promise<void> {\n const worker = this.getWorker();\n\n return new Promise((resolve, reject) => {\n this.loadResolves.set(groupId, resolve);\n this.loadRejects.set(groupId, reject);\n this.progressCallbacks.set(groupId, onProgress);\n worker.postMessage({\n type: \"load\",\n payload: { modelId, device, dtypeStrategy, groupId },\n });\n });\n }\n\n private cleanup(groupId: string) {\n this.pendingResolves.delete(groupId);\n this.pendingRejects.delete(groupId);\n this.progressCallbacks.delete(groupId);\n this.chunkCallbacks.delete(groupId);\n this.thinkingCallbacks.delete(groupId);\n }\n\n private getWorker() {\n if (!this.worker) {\n this.worker = new Worker(\n toTrustedScriptUrl(\n new URL(\"./transformers-js.worker.js\", import.meta.url).href,\n ) as string,\n {\n type: \"module\",\n },\n );\n this.worker.onmessage = (event) => {\n const { type, payload } = event.data;\n const groupId = payload?.groupId;\n\n switch (type) {\n case \"progress\":\n this.progressCallbacks.get(groupId)?.(payload);\n if (payload.status === \"done\") {\n this.loadResolves.get(groupId)?.();\n this.loadResolves.delete(groupId);\n this.loadRejects.delete(groupId);\n }\n\n break;\n case \"chunk\":\n this.chunkCallbacks.get(groupId)?.(payload);\n\n break;\n case \"thinking-chunk\":\n this.thinkingCallbacks.get(groupId)?.(payload.text);\n\n break;\n case \"done\":\n this.pendingResolves.get(groupId)?.(payload.text);\n this.cleanup(groupId);\n\n break;\n case \"error\":\n this.pendingRejects.get(groupId)?.(payload.error);\n this.loadRejects.get(groupId)?.(payload.error);\n this.cleanup(groupId);\n this.loadResolves.delete(groupId);\n this.loadRejects.delete(groupId);\n\n break;\n }\n };\n }\n\n return this.worker;\n }\n}\n\nconst manager = new TransformersJsManager();\n\nfunction formatMessageContent(msg: any): string {\n if (typeof msg?.content === \"string\") {\n return msg.content;\n }\n\n if (Array.isArray(msg?.content)) {\n return msg.content\n .map((block: any) => {\n if (block?.type === \"text\") {\n return block.text || \"\";\n }\n if (block?.type === \"tool_use\") {\n return `[TOOL_CALL ${block.name}] ${JSON.stringify(block.input || {})}`;\n }\n if (block?.type === \"tool_result\") {\n return `[TOOL_RESULT ${block.tool_use_id}] ${String(block.content || \"\")}`;\n }\n if (block?.type === \"attachment\") {\n return `[ATTACHMENT ${block.mediaType}] ${block.fileName} (${block.mimeType})`;\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n return \"\";\n}\n\nfunction parseStructured(raw: string) {\n const text = sanitizeModelOutput(String(raw || \"\"), \"transformers_js\").trim();\n if (!text) {\n return null;\n }\n\n // Check for Qwen/Llama XML-like tool calls: <tool_call>{\"name\": \"...\", \"arguments\": ...}</tool_call>\n const toolCallMatch = text.match(/<tool_call>([\\s\\S]*?)<\\/tool_call>/);\n if (toolCallMatch) {\n try {\n const parsedTool = JSON.parse(toolCallMatch[1]);\n if (parsedTool.name) {\n return {\n type: \"tool_use\",\n tool_calls: [\n {\n name: parsedTool.name,\n input: parsedTool.arguments || parsedTool.parameters || {},\n },\n ],\n };\n }\n } catch {\n // fallback to other parsing if invalid JSON\n }\n }\n\n try {\n return JSON.parse(text);\n } catch {\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n try {\n return JSON.parse(text.slice(start, end + 1));\n } catch {\n return null;\n }\n }\n\n return null;\n }\n}\n\nexport async function invokeWithTransformersJs(\n db: ShadowClawDatabase,\n groupId: string,\n systemPrompt: string,\n messages: any[],\n maxTokens: number,\n emit: (message: any) => Promise<void> | void,\n _abortSignal: AbortSignal | undefined,\n tools: ToolDefinition[] | undefined,\n modelId: string,\n invokeContext?: SubagentInvokeContext,\n) {\n const activeTools = tools || [];\n const backend =\n (await getConfig(db, CONFIG_KEYS.TRANSFORMERS_JS_BACKEND)) || \"auto\";\n const dtypeStrategy =\n (await getConfig(db, CONFIG_KEYS.TRANSFORMERS_JS_DTYPE_STRATEGY)) || \"auto\";\n\n await emit(\n createLogMessage(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: Transformers.js (Local Worker) · Model: ${modelId} · Backend: ${backend} · Dtype: ${dtypeStrategy}`,\n ),\n );\n\n await manager.load(modelId, backend, dtypeStrategy, groupId, (payload) => {\n void emit({ type: \"model-download-progress\", payload });\n });\n\n let currentMessages = [...messages];\n\n for (let i = 0; i < 10; i++) {\n const systemMessage = {\n role: \"system\",\n content: systemPrompt,\n };\n\n const structuredMessages = [\n systemMessage,\n ...currentMessages.map((m) => ({\n role: m.role === \"assistant\" ? \"assistant\" : \"user\",\n content: formatMessageContent(m),\n })),\n ];\n\n await emit({ type: \"streaming-start\", payload: { groupId } });\n\n let thinkingBuffer = \"\";\n let accumulated = \"\";\n const response = await manager.generate(\n structuredMessages,\n maxTokens,\n groupId,\n (chunk) => {\n accumulated += chunk;\n void emit({\n type: \"streaming-chunk\",\n payload: { groupId, text: chunk },\n });\n },\n (thinkingChunk) => {\n thinkingBuffer += thinkingChunk;\n void emit(\n createLogMessage(groupId, \"text\", \"Thinking\", thinkingBuffer),\n );\n },\n activeTools,\n );\n\n await emit({ type: \"typing\", payload: { groupId } });\n\n const parsed = parseStructured(response);\n\n if (parsed?.type === \"tool_use\") {\n await emit({ type: \"streaming-end\", payload: { groupId } });\n } else {\n const text = parsed?.response\n ? sanitizeModelOutput(parsed.response, \"transformers_js\")\n : sanitizeModelOutput(response, \"transformers_js\");\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text },\n });\n }\n\n if (!parsed || parsed.type === \"response\") {\n const text = parsed?.response\n ? sanitizeModelOutput(parsed.response, \"transformers_js\")\n : sanitizeModelOutput(response, \"transformers_js\");\n await emit({ type: \"response\", payload: { groupId, text } });\n\n return;\n }\n\n const calls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];\n if (calls.length === 0) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: sanitizeModelOutput(\n parsed.response || response,\n \"transformers_js\",\n ),\n },\n });\n\n return;\n }\n\n const toolResults: any[] = [];\n for (const call of calls) {\n await emit(createToolActivityMessage(groupId, call.name, \"running\"));\n setPostHandler((msg) => {\n emit(msg);\n });\n let output: any;\n try {\n output = await executeTool(db, call.name, call.input || {}, groupId, {\n allowedTools: activeTools,\n invokeContext,\n });\n } finally {\n setPostHandler(null);\n }\n\n await emit(createToolActivityMessage(groupId, call.name, \"done\"));\n\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: call.id || `call_${Date.now()}`,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n });\n }\n\n currentMessages.push({\n role: \"assistant\",\n content: [\n ...(parsed.response ? [{ type: \"text\", text: parsed.response }] : []),\n ...calls.map((c) => ({\n type: \"tool_use\",\n id: c.id || `call_${Date.now()}_${Math.random()}`,\n name: c.name,\n input: c.input || {},\n })),\n ] as any,\n });\n\n currentMessages.push({ role: \"user\", content: toolResults as any });\n }\n}\n","/**\n * Create a token-usage message object\n */\nexport function createTokenUsageMessage(\n groupId: string,\n usage: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n },\n contextLimit: number,\n): any {\n const inputTokens = usage.input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n\n return {\n type: \"token-usage\",\n payload: {\n groupId,\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n totalTokens:\n inputTokens + outputTokens + cacheReadTokens + cacheCreationTokens,\n contextLimit,\n },\n };\n}\n","import { createLogMessage } from \"./createLogMessage.js\";\nimport { post } from \"./post.js\";\n\n/**\n * Log a message\n */\nexport function log(\n groupId: string,\n level:\n | \"info\"\n | \"api-call\"\n | \"tool\"\n | \"error\"\n | \"warning\"\n | \"tool-call\"\n | \"tool-result\"\n | \"text\",\n label: string,\n message?: string,\n): void {\n post(createLogMessage(groupId, level as any, label, message));\n}\n","/**\n * Parse a Server-Sent Events (SSE) stream from a ReadableStream.\n *\n * Yields parsed JSON data objects from `data:` lines, skipping `[DONE]`\n * sentinel and comment lines.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<any> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n if (signal?.aborted) {\n break;\n }\n\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n\n // Keep the last incomplete part in the buffer\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const lines = part.split(\"\\n\");\n\n for (const line of lines) {\n // Skip empty lines and comments\n if (!line || line.startsWith(\":\")) {\n continue;\n }\n\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6).trim();\n\n // Skip the [DONE] sentinel\n if (data === \"[DONE]\") {\n continue;\n }\n\n try {\n yield JSON.parse(data);\n } catch {\n // Skip malformed JSON lines\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import { post } from \"./post.js\";\n\nconst ONE_MINUTE_MS = 60_000;\n\nexport interface RateLimitConfig {\n callsPerMinute: number;\n autoAdapt: boolean;\n}\n\ninterface ProviderRateLimitState {\n recentCalls: number[];\n nextAllowedAt: number;\n remoteLimit: number | null;\n remoteRemaining: number | null;\n remoteResetAt: number | null;\n}\n\nconst stateByProvider = new Map<string, ProviderRateLimitState>();\n\nfunction getState(providerId: string): ProviderRateLimitState {\n const existing = stateByProvider.get(providerId);\n if (existing) {\n return existing;\n }\n\n const created: ProviderRateLimitState = {\n recentCalls: [],\n nextAllowedAt: 0,\n remoteLimit: null,\n remoteRemaining: null,\n remoteResetAt: null,\n };\n\n stateByProvider.set(providerId, created);\n\n return created;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction parseHeaderNumber(raw: string | null): number | null {\n if (!raw) {\n return null;\n }\n\n const value = Number(raw.trim());\n if (!Number.isFinite(value)) {\n return null;\n }\n\n return value;\n}\n\nfunction parseRetryAfterMs(retryAfter: string | null): number | null {\n if (!retryAfter) {\n return null;\n }\n\n const trimmed = retryAfter.trim();\n const numeric = Number(trimmed);\n if (Number.isFinite(numeric)) {\n if (numeric <= 0) {\n return null;\n }\n\n return Math.round(numeric * 1000);\n }\n\n const dateMs = Date.parse(trimmed);\n if (!Number.isFinite(dateMs)) {\n return null;\n }\n\n const delta = dateMs - nowMs();\n\n return delta > 0 ? delta : null;\n}\n\nfunction parseResetAtMs(resetHeader: string | null): number | null {\n const numeric = parseHeaderNumber(resetHeader);\n if (numeric === null || numeric <= 0) {\n return null;\n }\n\n // 13-digit epoch milliseconds\n if (numeric >= 1_000_000_000_000) {\n return Math.round(numeric);\n }\n\n // 10-digit epoch seconds\n if (numeric >= 1_000_000_000) {\n return Math.round(numeric * 1000);\n }\n\n // Otherwise treat as delta seconds from now.\n\n return nowMs() + Math.round(numeric * 1000);\n}\n\nasync function waitWithAbort(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | null = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n\n const onAbort = () => {\n cleanup();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n signal?.removeEventListener(\"abort\", onAbort);\n };\n\n if (signal?.aborted) {\n onAbort();\n\n return;\n }\n\n signal?.addEventListener(\"abort\", onAbort);\n });\n}\n\nfunction computeManualWaitMs(\n state: ProviderRateLimitState,\n callsPerMinute: number,\n): number {\n if (!Number.isFinite(callsPerMinute) || callsPerMinute <= 0) {\n return 0;\n }\n\n const now = nowMs();\n state.recentCalls = state.recentCalls.filter(\n (ts) => now - ts < ONE_MINUTE_MS,\n );\n\n if (state.recentCalls.length < callsPerMinute) {\n return 0;\n }\n\n const oldest = state.recentCalls[0] || now;\n\n return Math.max(0, ONE_MINUTE_MS - (now - oldest));\n}\n\nfunction computeAutoWaitMs(state: ProviderRateLimitState): number {\n const now = nowMs();\n let waitMs = 0;\n\n if (state.nextAllowedAt > now) {\n waitMs = Math.max(waitMs, state.nextAllowedAt - now);\n }\n\n if (\n state.remoteRemaining !== null &&\n state.remoteRemaining <= 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n waitMs = Math.max(waitMs, state.remoteResetAt - now);\n }\n\n return waitMs;\n}\n\nexport async function waitForRateLimitSlot(\n providerId: string,\n groupId: string,\n config: RateLimitConfig,\n signal?: AbortSignal,\n): Promise<void> {\n const state = getState(providerId);\n\n while (true) {\n const manualWait = computeManualWaitMs(state, config.callsPerMinute);\n const autoWait = config.autoAdapt ? computeAutoWaitMs(state) : 0;\n const waitMs = Math.max(manualWait, autoWait);\n\n if (waitMs <= 0) {\n const now = nowMs();\n if (config.callsPerMinute > 0) {\n state.recentCalls.push(now);\n }\n\n if (\n config.autoAdapt &&\n state.remoteRemaining !== null &&\n state.remoteRemaining > 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n const msLeft = state.remoteResetAt - now;\n const slotsLeft = Math.max(1, state.remoteRemaining);\n const interval = Math.ceil(msLeft / slotsLeft);\n state.nextAllowedAt = Math.max(state.nextAllowedAt, now + interval);\n }\n\n return;\n }\n\n if (waitMs >= 1000) {\n post({\n type: \"thinking-log\",\n payload: {\n groupId,\n level: \"info\",\n label: \"Rate limiter\",\n message: `Waiting ${Math.ceil(waitMs / 1000)}s before next provider call to avoid 429s.`,\n timestamp: Date.now(),\n },\n });\n }\n\n await waitWithAbort(waitMs, signal);\n }\n}\n\ntype HeaderReader = {\n get(name: string): string | null;\n};\n\nexport function updateRateLimitFromHeaders(\n providerId: string,\n headers: HeaderReader | null | undefined,\n config: RateLimitConfig,\n): void {\n if (!config.autoAdapt) {\n return;\n }\n\n if (!headers || typeof headers.get !== \"function\") {\n return;\n }\n\n const state = getState(providerId);\n const now = nowMs();\n\n const limit = parseHeaderNumber(headers.get(\"x-ratelimit-limit\"));\n const remaining = parseHeaderNumber(headers.get(\"x-ratelimit-remaining\"));\n const resetAt = parseResetAtMs(headers.get(\"x-ratelimit-reset\"));\n\n if (limit !== null) {\n state.remoteLimit = Math.max(0, Math.floor(limit));\n }\n\n if (remaining !== null) {\n state.remoteRemaining = Math.max(0, Math.floor(remaining));\n }\n\n if (resetAt !== null) {\n state.remoteResetAt = resetAt;\n }\n\n const retryAfterMs = parseRetryAfterMs(headers.get(\"retry-after\"));\n if (retryAfterMs !== null) {\n state.nextAllowedAt = Math.max(state.nextAllowedAt, now + retryAfterMs);\n }\n\n if (\n state.remoteRemaining !== null &&\n state.remoteRemaining <= 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n state.nextAllowedAt = Math.max(state.nextAllowedAt, state.remoteResetAt);\n }\n}\n","import { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\n\nimport type {\n ContentBlockAccumulator,\n StreamCallbacks,\n StreamFormat,\n} from \"./types.js\";\n\n/**\n * Accumulates streamed SSE chunks into a unified response object.\n *\n * Supports both OpenAI-format (choices[].delta) and Anthropic-format\n * (content_block_start / content_block_delta / message_delta) SSE streams.\n *\n * Emits callbacks for incremental text and tool-call progress.\n */\nexport class StreamAccumulator {\n callbacks: StreamCallbacks;\n contentBlocks: ContentBlockAccumulator[] = [];\n format: StreamFormat;\n stopReason: string = \"end_turn\";\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n } = {\n input_tokens: 0,\n output_tokens: 0,\n };\n\n #anthropicBlocks = new Map<number, ContentBlockAccumulator>();\n\n #openaiReasoningText: string = \"\";\n #openaiText: string = \"\";\n #openaiToolCalls = new Map<\n number,\n { id: string; name: string; args: string }\n >();\n\n constructor(format: StreamFormat, callbacks: StreamCallbacks = {}) {\n this.format = format;\n this.callbacks = callbacks;\n }\n\n /**\n * Build the final normalized response (same shape as parseResponse).\n */\n finalize(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n if (this.format === \"openai\" || this.format === \"mesh-llm\") {\n return this.#finalizeOpenAI();\n }\n\n return this.#finalizeAnthropic();\n }\n\n /**\n * Feed a single parsed SSE chunk into the accumulator.\n */\n push(chunk: any): void {\n if (this.format === \"openai\" || this.format === \"mesh-llm\") {\n this.#pushOpenAI(chunk);\n } else {\n this.#pushAnthropic(chunk);\n }\n }\n\n #finalizeAnthropic(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n const content: any[] = [];\n\n for (const [, block] of [...this.#anthropicBlocks.entries()].sort(\n (a, b) => a[0] - b[0],\n )) {\n if (block.type === \"text\") {\n const cleaned = this.#sanitize(block.text || \"\");\n if (cleaned) {\n content.push({ type: \"text\", text: cleaned });\n }\n } else if (block.type === \"tool_use\") {\n let input;\n try {\n input = block.partialJson ? JSON.parse(block.partialJson) : {};\n } catch {\n input = {};\n }\n\n content.push({\n type: \"tool_use\",\n id: block.id || `call_${Date.now()}_${Math.random()}`,\n name: block.name,\n input,\n });\n } else if (block.type === \"thinking\") {\n if (typeof block.text === \"string\" && block.text.length > 0) {\n content.push({\n type: \"thinking\",\n thinking: block.text,\n ...(typeof block.id === \"string\" ? { signature: block.id } : {}),\n });\n }\n } else if (block.type === \"redacted_thinking\") {\n if (typeof block.text === \"string\" && block.text.length > 0) {\n content.push({\n type: \"redacted_thinking\",\n data: block.text,\n });\n }\n }\n }\n\n return {\n content,\n stop_reason: this.stopReason,\n usage: { ...this.usage },\n };\n }\n\n #finalizeOpenAI(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n const content: any[] = [];\n\n if (this.#openaiText) {\n const cleaned = this.#sanitize(this.#openaiText);\n if (cleaned) {\n content.push({ type: \"text\", text: cleaned });\n }\n }\n\n if (this.#openaiReasoningText) {\n content.unshift({\n type: \"thinking\",\n thinking: this.#openaiReasoningText,\n });\n }\n\n if (this.#openaiToolCalls.size > 0) {\n this.stopReason = \"tool_use\";\n\n for (const [, tc] of [...this.#openaiToolCalls.entries()].sort(\n (a, b) => a[0] - b[0],\n )) {\n let input;\n try {\n input = tc.args ? JSON.parse(tc.args) : {};\n } catch {\n input = {};\n }\n\n content.push({\n type: \"tool_use\",\n id: tc.id || `call_${Date.now()}_${Math.random()}`,\n name: tc.name,\n input,\n });\n }\n }\n\n return {\n content,\n stop_reason: this.stopReason,\n usage: { ...this.usage },\n };\n }\n\n #pushAnthropic(chunk: any): void {\n switch (chunk.type) {\n case \"message_start\": {\n if (chunk.message?.usage) {\n this.usage.input_tokens = chunk.message.usage.input_tokens || 0;\n this.usage.cache_read_input_tokens =\n chunk.message.usage.cache_read_input_tokens || 0;\n this.usage.cache_creation_input_tokens =\n chunk.message.usage.cache_creation_input_tokens || 0;\n }\n\n break;\n }\n\n case \"content_block_start\": {\n const idx = chunk.index ?? this.#anthropicBlocks.size;\n const block = chunk.content_block || {};\n\n this.#anthropicBlocks.set(idx, {\n type: block.type || \"text\",\n id: block.type === \"thinking\" ? block.signature : block.id,\n name: block.name,\n text: block.text || block.thinking || block.data || \"\",\n partialJson: block.type === \"tool_use\" ? \"\" : undefined,\n });\n\n if (block.type === \"tool_use\" && block.name) {\n this.callbacks.onToolStart?.(block.name);\n }\n\n break;\n }\n\n case \"content_block_delta\": {\n const idx = chunk.index ?? 0;\n let block = this.#anthropicBlocks.get(idx);\n if (!block) {\n const inferredType =\n chunk.delta?.type === \"input_json_delta\" ? \"tool_use\" : \"text\";\n\n block = {\n type: inferredType,\n text: inferredType === \"text\" ? \"\" : undefined,\n partialJson: inferredType === \"tool_use\" ? \"\" : undefined,\n };\n\n this.#anthropicBlocks.set(idx, block);\n }\n\n const delta = chunk.delta;\n if (!delta) {\n break;\n }\n\n if (delta.type === \"text_delta\" && typeof delta.text === \"string\") {\n const cleaned = this.#sanitize(delta.text);\n if (!cleaned) {\n break;\n }\n\n block.text = (block.text || \"\") + cleaned;\n this.callbacks.onText?.(cleaned);\n }\n\n if (\n delta.type === \"thinking_delta\" &&\n typeof delta.thinking === \"string\"\n ) {\n block.type = \"thinking\";\n block.text = (block.text || \"\") + delta.thinking;\n this.callbacks.onThinking?.(delta.thinking);\n }\n\n if (\n delta.type === \"signature_delta\" &&\n typeof delta.signature === \"string\"\n ) {\n block.type = \"thinking\";\n block.id = delta.signature;\n }\n\n if (\n delta.type === \"redacted_thinking_delta\" &&\n typeof delta.data === \"string\"\n ) {\n block.type = \"redacted_thinking\";\n block.text = (block.text || \"\") + delta.data;\n }\n\n if (\n delta.type === \"input_json_delta\" &&\n typeof delta.partial_json === \"string\"\n ) {\n block.partialJson = (block.partialJson || \"\") + delta.partial_json;\n }\n\n break;\n }\n\n case \"content_block_stop\":\n // No action needed; block is already accumulated\n\n break;\n\n case \"message_delta\": {\n if (chunk.delta?.stop_reason) {\n this.stopReason = chunk.delta.stop_reason;\n }\n\n if (chunk.usage) {\n this.usage.output_tokens = chunk.usage.output_tokens || 0;\n this.callbacks.onUsage?.(this.usage);\n }\n\n break;\n }\n\n case \"message_stop\":\n break;\n\n default:\n // Ignore ping, error events, etc.\n\n break;\n }\n }\n\n #pushOpenAI(chunk: any): void {\n // Handle usage in the final chunk (OpenAI includes it when stream_options.include_usage is set,\n // or in the last chunk for some providers)\n if (chunk.usage) {\n this.usage.input_tokens = chunk.usage.prompt_tokens || 0;\n this.usage.output_tokens = chunk.usage.completion_tokens || 0;\n this.usage.cache_read_input_tokens =\n chunk.usage.prompt_tokens_details?.cached_tokens || 0;\n this.callbacks.onUsage?.(this.usage);\n }\n\n const choice = chunk.choices?.[0];\n if (!choice) {\n return;\n }\n\n const delta = choice.delta;\n if (!delta) {\n return;\n }\n\n // Accumulate text content\n if (typeof delta.content === \"string\") {\n const cleaned = this.#sanitize(delta.content);\n if (cleaned) {\n this.#openaiText += cleaned;\n this.callbacks.onText?.(cleaned);\n }\n }\n\n // Accumulate reasoning content from OpenAI-compatible providers that expose\n // thought tokens separately from user-visible assistant text.\n if (typeof delta.reasoning === \"string\") {\n this.#openaiReasoningText += delta.reasoning;\n this.callbacks.onThinking?.(delta.reasoning);\n } else if (delta.reasoning && typeof delta.reasoning === \"object\") {\n const reasoningObj: any = delta.reasoning;\n if (typeof reasoningObj.content === \"string\") {\n this.#openaiReasoningText += reasoningObj.content;\n this.callbacks.onThinking?.(reasoningObj.content);\n } else if (typeof reasoningObj.text === \"string\") {\n this.#openaiReasoningText += reasoningObj.text;\n this.callbacks.onThinking?.(reasoningObj.text);\n }\n }\n\n // Accumulate tool calls\n if (Array.isArray(delta.tool_calls)) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n\n if (!this.#openaiToolCalls.has(idx)) {\n this.#openaiToolCalls.set(idx, {\n id: tc.id || \"\",\n name: tc.function?.name || \"\",\n args: \"\",\n });\n\n if (tc.function?.name) {\n this.callbacks.onToolStart?.(tc.function.name);\n }\n }\n\n const existing = this.#openaiToolCalls.get(idx);\n if (!existing) {\n continue;\n }\n\n if (tc.id) {\n existing.id = tc.id;\n }\n\n if (tc.function?.name) {\n existing.name = tc.function.name;\n }\n\n if (tc.function?.arguments) {\n existing.args += tc.function.arguments;\n }\n }\n }\n\n // Capture finish reason\n if (choice.finish_reason) {\n if (choice.finish_reason === \"tool_calls\") {\n this.stopReason = \"tool_use\";\n } else if (choice.finish_reason === \"stop\") {\n this.stopReason = \"end_turn\";\n } else {\n this.stopReason = choice.finish_reason;\n }\n }\n }\n\n #sanitize(text: string): string {\n return sanitizeModelOutput(text, this.callbacks.source ?? this.format);\n }\n}\n","import { ToolDefinition } from \"../../subsystems/tools/types.js\";\n\ninterface ToolState {\n enabledTools: ToolDefinition[];\n systemPromptOverride: string;\n}\n\n/**\n * Worker-side tool state cache per groupId.\n * This allows the worker to reflect tool management changes in the middle\n * of an agent invocation loop.\n */\nconst toolStateMap = new Map<string, ToolState>();\n\nexport function setToolState(\n groupId: string,\n enabledTools: ToolDefinition[],\n systemPromptOverride: string,\n) {\n toolStateMap.set(groupId, { enabledTools, systemPromptOverride });\n}\n\nexport function getToolState(groupId: string): ToolState | undefined {\n return toolStateMap.get(groupId);\n}\n\nexport function clearToolState(groupId: string) {\n toolStateMap.delete(groupId);\n}\n","import {\n DEFAULT_MAX_ITERATIONS,\n getProvider,\n ProviderConfig,\n} from \"../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../context/estimateTokens.js\";\n\nimport {\n buildHeaders,\n formatRequest,\n getContextLimit,\n normalizeMeshLlmResult,\n parseResponse,\n} from \"../../subsystems/providers/providers.js\";\n\nimport { setStorageRoot } from \"../../storage/storage.js\";\nimport { TOOL_DEFINITIONS } from \"../../subsystems/tools/tools.js\";\nimport { createTokenUsageMessage } from \"./createTokenUsageMessage.js\";\nimport { createToolActivityMessage } from \"./createToolActivityMessage.js\";\nimport { executeTool } from \"./executeTool.js\";\nimport { log } from \"./log.js\";\nimport { parseSSEStream } from \"./parseSSEStream.js\";\n\nimport {\n post,\n registerSubagentCollector,\n unregisterSubagentCollector,\n} from \"./post.js\";\n\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport {\n RateLimitConfig,\n updateRateLimitFromHeaders,\n waitForRateLimitSlot,\n} from \"./rate-limit.js\";\n\nimport { ContentBlock, ToolResultContentBlock } from \"../../content/types.js\";\nimport { dispatchSubagentInvoke } from \"../../core/orchestrator/utils/dispatchSubagentInvoke.js\";\nimport { InvokePayload } from \"../../subsystems/worker/types.js\";\nimport { StreamAccumulator } from \"../StreamAccumulator/StreamAccumulator.js\";\nimport { StreamFormat } from \"../StreamAccumulator/types.js\";\n\nimport { buildSystemPrompt } from \"./system-prompt.js\";\nimport { clearToolState, getToolState } from \"./tool-state.js\";\nimport { isRetryableHttpError, withRetry } from \"./withRetry.js\";\n\nimport type { SubagentInvokeContext, ToolResult } from \"./executeTool.js\";\n\n/**\n * Throttle interval (ms) for streaming text chunks sent to the UI.\n * Keeps the main thread responsive during fast token delivery.\n */\nconst STREAM_THROTTLE_MS = 50;\n\ntype ParsedToolCodeBlock = {\n toolBlocks: Array<{\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, any>;\n }>;\n residualText: string;\n};\n\nfunction parseToolCodeBlock(\n text: string,\n allowedToolNames: Set<string>,\n): ParsedToolCodeBlock {\n const trimmed = text.trim();\n const wrappedMatch = trimmed.match(\n /^\\[tool_code\\]([\\s\\S]*?)\\[\\/tool_code\\]$/i,\n );\n if (!wrappedMatch?.[1]) {\n return { toolBlocks: [], residualText: text };\n }\n\n const body = wrappedMatch[1].trim();\n\n const printMatch = body.match(\n /^print\\s*\\(\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(\\s*(.*?)\\s*\\)\\s*\\)$/s,\n );\n\n const directMatch = body.match(\n /^([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(\\s*(.*?)\\s*\\)$/s,\n );\n\n const match = printMatch || directMatch;\n if (!match?.[1]) {\n return { toolBlocks: [], residualText: text };\n }\n\n const toolName = match[1];\n if (!allowedToolNames.has(toolName)) {\n return { toolBlocks: [], residualText: text };\n }\n\n const rawArgs = (match[2] || \"\").trim();\n let input: Record<string, any> = {};\n if (rawArgs) {\n if (!rawArgs.startsWith(\"{\") || !rawArgs.endsWith(\"}\")) {\n return { toolBlocks: [], residualText: text };\n }\n\n try {\n const parsed = JSON.parse(rawArgs);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return { toolBlocks: [], residualText: text };\n }\n\n input = parsed as Record<string, any>;\n } catch {\n return { toolBlocks: [], residualText: text };\n }\n }\n\n return {\n toolBlocks: [\n {\n type: \"tool_use\",\n id: `tool_code_${Date.now()}_${Math.random()}`,\n name: toolName,\n input,\n },\n ],\n residualText: \"\",\n };\n}\n\nfunction normalizeToolCodeResponses(result: any, enabledTools: any[]): any {\n if (\n !result ||\n result.stop_reason === \"tool_use\" ||\n !Array.isArray(result.content)\n ) {\n return result;\n }\n\n const allowedToolNames = new Set(\n (enabledTools || [])\n .map((tool: any) => (typeof tool?.name === \"string\" ? tool.name : \"\"))\n .filter(Boolean),\n );\n\n if (allowedToolNames.size === 0) {\n return result;\n }\n\n const normalizedContent: any[] = [];\n let convertedAny = false;\n\n for (const block of result.content) {\n if (block?.type !== \"text\" || typeof block.text !== \"string\") {\n normalizedContent.push(block);\n\n continue;\n }\n\n const parsed = parseToolCodeBlock(block.text, allowedToolNames);\n if (parsed.toolBlocks.length > 0) {\n convertedAny = true;\n if (parsed.residualText.trim()) {\n normalizedContent.push({ type: \"text\", text: parsed.residualText });\n }\n\n normalizedContent.push(...parsed.toolBlocks);\n\n continue;\n }\n\n normalizedContent.push(block);\n }\n\n if (!convertedAny) {\n return result;\n }\n\n return {\n ...result,\n content: normalizedContent,\n stop_reason: \"tool_use\",\n };\n}\n\nfunction buildToolResultsFallbackText(toolResults: ContentBlock[]): string {\n const lines = toolResults\n .filter((entry) => entry?.type === \"tool_result\")\n .map((entry) => {\n if (typeof (entry as any).content === \"string\") {\n return (entry as any).content.trim();\n }\n\n if (Array.isArray((entry as any).content)) {\n return ((entry as any).content as ToolResultContentBlock[])\n .filter((block) => block.type === \"text\")\n .map((block) => (block as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n .trim();\n }\n\n return JSON.stringify((entry as any).content).trim();\n })\n .filter(Boolean);\n\n if (lines.length === 0) {\n return \"\";\n }\n\n return lines.join(\"\\n\\n\").slice(0, 10_000);\n}\n\nfunction formatToolFallbackResponseText(text: string): string {\n const trimmed = text.trim();\n if (!trimmed) {\n return \"\";\n }\n\n return `Tool result:\\n${trimmed}`;\n}\n\n/**\n * Handle agent invocation with tool-use loop\n */\nexport async function handleInvoke(\n db: any,\n payload: InvokePayload & { isScheduledTask?: boolean },\n abortSignal?: AbortSignal,\n): Promise<void> {\n const {\n apiKey,\n assistantName,\n contextCompression = false,\n contextLimit: payloadContextLimit,\n enabledTools,\n groupId: originalGroupId,\n isScheduledTask = false,\n maxIterations: payloadMaxIterations,\n maxTokens,\n memory,\n messages,\n model,\n provider: providerId,\n providerHeaders = {},\n providerRuntimeOverrides,\n reasoning,\n rateLimitAutoAdapt = true,\n rateLimitCallsPerMinute = 0,\n storageHandle,\n streaming = false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedModel,\n subagentPinnedProvider,\n systemPrompt,\n workspaceGroupId,\n } = payload;\n\n const isSubagentTask = !!payload.subagentTask;\n const groupId = isSubagentTask\n ? originalGroupId.startsWith(\"subagent:\")\n ? originalGroupId\n : `subagent:${ulid()}`\n : originalGroupId;\n const effectiveWorkspaceGroupId = workspaceGroupId || originalGroupId;\n\n if (isSubagentTask) {\n registerSubagentCollector(groupId, []);\n }\n\n const rateLimitConfig: RateLimitConfig = {\n autoAdapt: rateLimitAutoAdapt !== false,\n callsPerMinute: Number.isFinite(rateLimitCallsPerMinute)\n ? Math.max(0, Math.floor(rateLimitCallsPerMinute))\n : 0,\n };\n\n if (storageHandle) {\n setStorageRoot(storageHandle);\n }\n\n const provider = getProvider(providerId);\n if (!provider) {\n post({\n payload: { groupId, error: `Unknown provider: ${providerId}` },\n type: \"error\",\n });\n\n return;\n }\n\n const typedProvider = provider as ProviderConfig;\n\n // Determine whether we can actually use streaming for this provider.\n const useStreaming =\n streaming &&\n typedProvider.supportsStreaming === true &&\n typedProvider.format !== \"prompt_api\";\n\n post({ type: \"typing\", payload: { groupId } });\n\n log(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: ${typedProvider.name} · Model: ${model} · Max tokens: ${maxTokens} · Streaming: ${useStreaming ? \"on\" : \"off\"}${streaming && !useStreaming ? \" (provider does not support streaming)\" : \"\"}`,\n );\n\n try {\n let currentMessages = [...messages];\n let iterations = 0;\n\n const maxIterations =\n typeof payloadMaxIterations === \"number\" && payloadMaxIterations > 0\n ? payloadMaxIterations\n : DEFAULT_MAX_ITERATIONS;\n\n let currentTools = Array.isArray(enabledTools)\n ? enabledTools\n : TOOL_DEFINITIONS;\n\n let currentSystemPrompt = systemPrompt;\n let latestToolResultsFallbackText = \"\";\n\n // Build the invoke context for spawn_subagent to inherit\n const invokeContext: SubagentInvokeContext = {\n apiKey,\n assistantName: assistantName ?? \"\",\n db,\n enabledTools: currentTools as any,\n invokeSubagent: (subPayload) =>\n dispatchSubagentInvoke(db, subPayload, abortSignal),\n maxTokens,\n memory: memory ?? \"\",\n model,\n provider: providerId,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n providerHeaders,\n providerRuntimeOverrides,\n storageHandle,\n streaming: false, // subagents always use non-streaming for clean capture\n systemPrompt: currentSystemPrompt ?? \"\",\n };\n\n // Track exact tool calls to prevent loops\n const toolCallHistory: string[] = [];\n\n while (iterations < maxIterations) {\n iterations++;\n\n // Check for mid-invocation tool updates from main thread\n const updatedState = getToolState(groupId);\n if (updatedState) {\n currentTools = updatedState.enabledTools;\n currentSystemPrompt = buildSystemPrompt(\n assistantName,\n memory,\n currentTools,\n updatedState.systemPromptOverride,\n );\n }\n\n const contextLimit = payloadContextLimit ?? getContextLimit(model);\n const systemPromptTokens = estimateTokens(currentSystemPrompt);\n\n // Re-evaluate context dynamically for each API call to handle large tool outputs\n const { messages: payloadMessages, estimatedTokens } =\n buildDynamicContext(currentMessages as any, {\n contextLimit,\n maxOutputTokens: maxTokens,\n skimTop: contextCompression,\n systemPromptTokens,\n });\n\n // Strict proxy boundaries (e.g. Azure OpenAI) calculate: prompt_tokens + max_tokens <= context_window.\n const SAFETY_BUFFER = 500;\n const totalPromptEstimate =\n (estimatedTokens as number) + systemPromptTokens;\n\n // Mathematically guarantee we don't overflow the strict provider budget\n const safeMaxTokens = Math.max(\n 100, // floor\n Math.min(maxTokens, contextLimit - totalPromptEstimate - SAFETY_BUFFER),\n );\n\n const body = formatRequest(\n typedProvider,\n payloadMessages,\n currentTools as any,\n {\n contextCompression,\n maxTokens: safeMaxTokens,\n model,\n reasoning,\n system: currentSystemPrompt,\n },\n );\n\n log(\n groupId,\n \"api-call\",\n `API call #${iterations}`,\n `${payloadMessages.length} messages in context`,\n );\n\n const headers = {\n ...buildHeaders(typedProvider, apiKey),\n ...providerHeaders,\n };\n\n const url = typedProvider.baseUrl;\n\n let result: any;\n\n if (useStreaming) {\n result = await callWithStreaming(\n providerId,\n typedProvider,\n url,\n headers,\n body,\n groupId,\n model,\n rateLimitConfig,\n abortSignal,\n );\n } else {\n result = await callApi(\n providerId,\n typedProvider,\n url,\n headers,\n body,\n groupId,\n rateLimitConfig,\n abortSignal,\n );\n }\n\n result = normalizeToolCodeResponses(result, currentTools as any[]);\n\n // Emit token usage\n if (result.usage) {\n post(\n createTokenUsageMessage(\n groupId,\n result.usage,\n getContextLimit(model),\n ),\n );\n }\n\n // Log text blocks\n for (const block of result.content) {\n if (block.type === \"text\" && block.text) {\n const preview =\n block.text.length > 200\n ? block.text.slice(0, 200) + \"…\"\n : block.text;\n\n log(groupId, \"text\", \"Response text\", preview);\n }\n }\n\n if (result.stop_reason === \"tool_use\") {\n const allowedToolNames = new Set(\n (currentTools as any[])\n .map((tool: any) =>\n typeof tool?.name === \"string\" ? tool.name : \"\",\n )\n .filter(Boolean),\n );\n\n // If the response includes text alongside tool calls, persist it\n const intermediateText = result.content\n .filter((b: any) => b.type === \"text\")\n .map((b: any) => b.text)\n .join(\"\")\n .replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\")\n .trim();\n\n if (intermediateText) {\n post({\n payload: { groupId, text: intermediateText },\n type: \"intermediate-response\",\n });\n }\n\n // If we were streaming text before tool calls, clear the streaming bubble\n if (useStreaming) {\n post({\n payload: { groupId },\n type: \"streaming-end\",\n });\n }\n\n // Execute tool calls\n const toolResults: ContentBlock[] = [];\n for (const block of result.content) {\n if (block.type === \"tool_use\") {\n const isAllowed = allowedToolNames.has(block.name);\n\n // Prevent infinite loops by detecting repeated identical tool calls\n const toolCallSignature = `${block.name}:${JSON.stringify(block.input)}`;\n const timesCalled = toolCallHistory.filter(\n (s) => s === toolCallSignature,\n ).length;\n\n toolCallHistory.push(toolCallSignature);\n\n if (!isAllowed) {\n const blockedMessage =\n `SYSTEM ERROR: Tool '${block.name}' is disabled or unavailable for this request. ` +\n \"Do not call it again. Try a different approach or ask the user for help.\";\n\n log(groupId, \"warning\", \"Tool blocked\", blockedMessage);\n\n toolResults.push({\n content: blockedMessage,\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n\n continue;\n }\n\n const inputPreview = JSON.stringify(block.input);\n const inputShort =\n inputPreview.length > 300\n ? inputPreview.slice(0, 300) + \"…\"\n : inputPreview;\n\n log(groupId, \"tool-call\", `Tool: ${block.name}`, inputShort);\n\n post(createToolActivityMessage(groupId, block.name, \"running\"));\n\n let output: ToolResult;\n if (timesCalled >= 3) {\n output = `SYSTEM ERROR: You have repeatedly called this tool with the exact same input (${timesCalled + 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.`;\n\n console.warn(\n `[Worker] Blocked repetitive tool call:`,\n toolCallSignature,\n );\n } else {\n output = await executeTool(\n db,\n block.name,\n block.input,\n effectiveWorkspaceGroupId,\n {\n allowedTools: currentTools,\n isScheduledTask,\n invokeContext,\n },\n );\n }\n\n const outputStr =\n typeof output === \"string\" ? output : JSON.stringify(output);\n\n const outputShort =\n outputStr.length > 500\n ? outputStr.slice(0, 500) + \"…\"\n : outputStr;\n\n log(groupId, \"tool-result\", `Result: ${block.name}`, outputShort);\n\n post(createToolActivityMessage(groupId, block.name, \"done\"));\n\n if (Array.isArray(output)) {\n toolResults.push({\n content: output as ToolResultContentBlock[],\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n } else {\n toolResults.push({\n content:\n typeof output === \"string\"\n ? output.slice(0, 100_000)\n : JSON.stringify(output).slice(0, 100_000),\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n }\n }\n }\n\n // Continue conversation with tool results\n latestToolResultsFallbackText =\n buildToolResultsFallbackText(toolResults);\n\n currentMessages.push({ role: \"assistant\", content: result.content });\n currentMessages.push({ role: \"user\", content: toolResults as any });\n\n post({ type: \"typing\", payload: { groupId } });\n } else {\n // Final response\n const text = result.content\n .filter((b: any) => b.type === \"text\")\n .map((b: any) => b.text)\n .join(\"\");\n\n const cleaned = text\n .replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\")\n .trim();\n\n const isPlaceholderOnly = cleaned.toLowerCase() === \"(no response)\";\n const preferredModelText = isPlaceholderOnly ? \"\" : cleaned;\n const finalText = preferredModelText\n ? preferredModelText\n : latestToolResultsFallbackText\n ? formatToolFallbackResponseText(latestToolResultsFallbackText)\n : \"(no response)\";\n\n // If streaming was used, the text was already streamed chunk-by-chunk.\n if (useStreaming) {\n post({\n payload: { groupId, text: finalText },\n type: \"streaming-done\",\n });\n }\n\n post({\n payload: { groupId, text: finalText },\n type: \"response\",\n });\n\n return;\n }\n }\n\n // Max iterations reached\n post({\n payload: {\n text: `⚠️ Reached maximum tool-use iterations (${maxIterations}). Stopping to avoid excessive API usage.`,\n groupId,\n },\n type: \"response\",\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n\n // If we were streaming when the error occurred, preserve partial content\n if (useStreaming) {\n post({\n payload: { groupId, error: message },\n type: \"streaming-error\",\n });\n }\n\n post({ type: \"error\", payload: { groupId, error: message } });\n } finally {\n clearToolState(groupId);\n if (isSubagentTask) {\n unregisterSubagentCollector(groupId);\n }\n }\n}\n\n/**\n * Make a non-streaming LLM API call with retry.\n */\nasync function callApi(\n providerId: string,\n typedProvider: ProviderConfig,\n url: string,\n headers: Record<string, string>,\n body: any,\n groupId: string,\n rateLimitConfig: RateLimitConfig,\n abortSignal?: AbortSignal,\n): Promise<any> {\n return withRetry(\n async () => {\n await waitForRateLimitSlot(\n providerId,\n groupId,\n rateLimitConfig,\n abortSignal,\n );\n\n const res = await fetch(url, {\n body: JSON.stringify(body),\n headers,\n method: \"POST\",\n signal: abortSignal,\n });\n\n updateRateLimitFromHeaders(providerId, res.headers, rateLimitConfig);\n\n if (!res.ok) {\n const errBody = await res.text();\n const error = new Error(\n `${typedProvider.name} API error ${res.status}: ${errBody}`,\n );\n (error as any).status = res.status;\n\n throw error;\n }\n\n const rawResult = await res.json();\n\n return parseResponse(typedProvider, rawResult);\n },\n {\n baseDelayMs: 2000,\n jitterFactor: 0.5,\n maxDelayMs: 30_000,\n maxRetries: 3,\n onRetry: (_attempt, _maxRetries, _delayMs, _error) => {\n const errMsg =\n _error instanceof Error ? _error.message : String(_error);\n\n log(\n groupId,\n \"warning\",\n `Retrying API call (${_attempt}/${_maxRetries})`,\n errMsg,\n );\n\n post({\n type: \"show-toast\",\n payload: {\n message: `LLM API: Retrying (${_attempt}/${_maxRetries})… ${errMsg.slice(0, 120)}`,\n type: \"warning\",\n duration: 5000,\n },\n });\n },\n shouldRetry: (error) => isRetryableHttpError(error),\n signal: abortSignal,\n },\n );\n}\n\n/**\n * Make a streaming LLM API call.\n */\nasync function callWithStreaming(\n providerId: string,\n typedProvider: ProviderConfig,\n url: string,\n headers: Record<string, string>,\n body: any,\n groupId: string,\n model: string,\n rateLimitConfig: RateLimitConfig,\n abortSignal?: AbortSignal,\n): Promise<any> {\n // Add stream flag to the request body\n const streamBody = {\n ...body,\n stream: true,\n // For OpenAI-compatible APIs, request usage in the stream\n ...((typedProvider.format === \"openai\" ||\n typedProvider.format === \"mesh-llm\") && {\n stream_options: { include_usage: true },\n }),\n };\n\n await waitForRateLimitSlot(providerId, groupId, rateLimitConfig, abortSignal);\n\n const res = await fetch(url, {\n body: JSON.stringify(streamBody),\n headers,\n method: \"POST\",\n signal: abortSignal,\n });\n\n updateRateLimitFromHeaders(providerId, res.headers, rateLimitConfig);\n\n if (!res.ok) {\n const errBody = await res.text();\n const error = new Error(\n `${typedProvider.name} API error ${res.status}: ${errBody}`,\n );\n\n (error as any).status = res.status;\n\n throw error;\n }\n\n if (!res.body) {\n throw new Error(\"Streaming response has no body\");\n }\n\n // Signal the UI that a streaming response is starting\n post({\n payload: { groupId },\n type: \"streaming-start\",\n });\n\n let lastChunkTime = 0;\n let pendingText = \"\";\n let lastReasoningChunkTime = 0;\n let pendingReasoning = \"\";\n\n const flushReasoning = (force = false) => {\n const now = Date.now();\n if (!pendingReasoning) {\n return;\n }\n\n if (!force && now - lastReasoningChunkTime < STREAM_THROTTLE_MS) {\n return;\n }\n\n const message =\n pendingReasoning.length > 400\n ? `${pendingReasoning.slice(0, 400)}…`\n : pendingReasoning;\n\n log(groupId, \"info\", \"Reasoning\", message);\n pendingReasoning = \"\";\n lastReasoningChunkTime = now;\n };\n\n const accumulator = new StreamAccumulator(\n typedProvider.format as StreamFormat,\n {\n source: typedProvider.id,\n onText: (text) => {\n const now = Date.now();\n\n // Always buffer incoming text\n pendingText += text;\n\n // Flush to the UI only when the throttle interval has elapsed\n if (now - lastChunkTime >= STREAM_THROTTLE_MS) {\n post({\n payload: { groupId, text: pendingText },\n type: \"streaming-chunk\",\n });\n\n pendingText = \"\";\n lastChunkTime = now;\n }\n },\n onToolStart: (name) => {\n post(createToolActivityMessage(groupId, name, \"running\"));\n },\n onUsage: (usage) => {\n post(createTokenUsageMessage(groupId, usage, getContextLimit(model)));\n },\n onThinking: (text) => {\n pendingReasoning += text;\n flushReasoning(false);\n },\n },\n );\n\n for await (const chunk of parseSSEStream(res.body, abortSignal)) {\n accumulator.push(chunk);\n }\n\n // Flush any remaining buffered text that didn't make it through the throttle\n if (pendingText) {\n post({\n payload: { groupId, text: pendingText },\n type: \"streaming-chunk\",\n });\n }\n\n flushReasoning(true);\n\n let finalResult = accumulator.finalize();\n\n // Mesh LLM streams standard OpenAI SSE chunks but its assembled text may\n // contain proprietary markers for thoughts and tool calls.\n // We normalize the final assembled object before the agent loop consumes it.\n if (typedProvider.format === \"mesh-llm\") {\n finalResult = normalizeMeshLlmResult(finalResult);\n }\n\n return finalResult;\n}\n","import { ShadowClawDatabase } from \"../../../db/types\";\n\nimport {\n invokeWithLiteRtLm,\n isLiteRtLmSupported,\n} from \"../../../subsystems/providers/litert-lm-provider\";\n\nimport {\n invokeWithPromptApi,\n isPromptApiSupported,\n} from \"../../../subsystems/providers/prompt-api-provider\";\n\nimport { invokeWithTransformersJs } from \"../../../subsystems/providers/transformers-js-provider\";\n\nimport { InvokePayload } from \"../../../subsystems/worker/types\";\nimport { handleInvoke } from \"../../../worker/utils/handleInvoke\";\nimport { post as workerPost } from \"../../../worker/utils/post\";\n\ntype SubagentPayload = InvokePayload & { isScheduledTask?: boolean };\n\nconst BROWSER_PROVIDER_IDS = new Set([\n \"litert_lm_browser\",\n \"prompt_api\",\n \"transformers_js_browser\",\n]);\n\nexport function isBrowserProviderId(providerId: string | undefined): boolean {\n return !!providerId && BROWSER_PROVIDER_IDS.has(providerId);\n}\n\nexport async function dispatchSubagentInvoke(\n db: ShadowClawDatabase,\n payload: SubagentPayload,\n abortSignal?: AbortSignal | undefined,\n): Promise<void> {\n const providerId = payload.provider;\n\n const emit = async (msg: any) => {\n workerPost(msg);\n };\n\n if (providerId === \"transformers_js_browser\") {\n await invokeWithTransformersJs(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.enabledTools,\n payload.model,\n );\n\n return;\n }\n\n if (providerId === \"prompt_api\") {\n if (!isPromptApiSupported()) {\n throw new Error(\n \"Prompt API provider is not supported in this environment.\",\n );\n }\n\n await invokeWithPromptApi(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.enabledTools,\n );\n\n return;\n }\n\n if (providerId === \"litert_lm_browser\") {\n if (!isLiteRtLmSupported()) {\n throw new Error(\n \"Litert LM Browser provider is not supported in this environment.\",\n );\n }\n\n await invokeWithLiteRtLm(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.model,\n payload.enabledTools,\n );\n\n return;\n }\n\n await handleInvoke(db, payload, abortSignal);\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../../context/estimateTokens.js\";\n\nimport { buildConversationMessages } from \"../../../db/buildConversationMessages.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { listGroups } from \"../../../db/groups.js\";\nimport { saveMessage } from \"../../../db/saveMessage.js\";\n\nimport { readGroupFile } from \"../../../storage/readGroupFile.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../../stores/tools.js\";\n\nimport {\n invokeWithLiteRtLm,\n isLiteRtLmSupported,\n} from \"../../../subsystems/providers/litert-lm-provider.js\";\n\nimport {\n invokeWithPromptApi,\n isPromptApiSupported,\n} from \"../../../subsystems/providers/prompt-api-provider.js\";\nimport { ensureBuiltinAiPolyfills } from \"../../../subsystems/providers/builtin-ai-tasks.js\";\n\nimport { getContextLimit } from \"../../../subsystems/providers/providers.js\";\nimport { invokeWithTransformersJs } from \"../../../subsystems/providers/transformers-js-provider.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { buildSystemPrompt } from \"../../../worker/utils/system-prompt.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { activate_skill } from \"../../../subsystems/skills/tool.js\";\nimport { loadDeclarativeTools } from \"../../../subsystems/tools/declarative.js\";\n\nimport { compactContext } from \"./compactContext.js\";\nimport { deliverResponse } from \"./deliverResponse.js\";\nimport { dispatchSubagentInvoke } from \"./dispatchSubagentInvoke.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\nimport { getChannelTypeForGroup } from \"./operations/channel.js\";\n\nimport {\n getApiKeyForRequest,\n getProviderRuntimeHeaders,\n getReasoningConfig,\n startTransformersProgressPolling,\n} from \"./operations/provider.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { SubagentInvokeContext } from \"../../../worker/tools/spawn-subagent/spawn-subagent.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function invokeAgent(\n o: Orchestrator,\n db: ShadowClawDatabase,\n groupId: string,\n triggerContent: string,\n freshContext = false,\n subagent = false,\n): Promise<void> {\n const executionGroupId = subagent ? `subagent:${ulid()}` : groupId;\n\n o.inFlightTriggerByGroup.set(executionGroupId, triggerContent);\n o.setState(\"thinking\", executionGroupId);\n o.router?.setTyping(executionGroupId, true);\n o.events.emit(\"typing\", { groupId: executionGroupId, typing: true });\n\n // Save scheduled task as client message\n if (triggerContent.startsWith(\"[SCHEDULED TASK]\")) {\n o.pendingScheduledTasks.add(groupId);\n\n const stored = {\n id: ulid(),\n groupId,\n sender: \"Scheduler\",\n content: triggerContent,\n timestamp: Date.now(),\n channel: getChannelTypeForGroup(o, groupId),\n isFromMe: false,\n isTrigger: true,\n };\n\n await saveMessage(db, stored);\n\n o.events.emit(\"message\", stored);\n }\n\n // Load group memory\n let memory = \"\";\n try {\n memory = await readGroupFile(db, groupId, \"MEMORY.md\");\n } catch {}\n\n // Load group metadata to check for conversation-specific pinned tools\n const groups = await listGroups(db);\n const group = groups.find((g) => g.groupId === groupId);\n\n const effectiveProviderId = group?.pinnedProvider ?? o.provider;\n\n // When a provider is pinned but no specific model is pinned, default to that provider's own defaultModel\n const effectiveModel =\n group?.pinnedModel ??\n (group?.pinnedProvider\n ? (getProvider(group.pinnedProvider)?.defaultModel ?? o.model)\n : o.model);\n\n const configuredMaxTokens =\n typeof group?.pinnedMaxTokens === \"number\" &&\n Number.isFinite(group.pinnedMaxTokens) &&\n group.pinnedMaxTokens > 0\n ? Math.floor(group.pinnedMaxTokens)\n : o.maxTokens;\n\n let modelForTokenLimits = effectiveModel;\n if (\n effectiveProviderId === \"prompt_api\" &&\n (effectiveModel === \"browser-built-in\" || !effectiveModel) &&\n !isPromptApiSupported()\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n modelForTokenLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n const effectiveMaxTokens = Math.max(\n 1,\n Math.min(configuredMaxTokens, getModelMaxTokens(modelForTokenLimits)),\n );\n\n const effectiveProviderConfig =\n getProvider(effectiveProviderId) ?? o.providerConfig;\n\n // Track the effective provider for this group so the error handler\n // can show the right help UI and avoid showing the wrong provider's error.\n o.inFlightEffectiveProviderByGroup.set(executionGroupId, {\n providerId: effectiveProviderId,\n providerConfig: effectiveProviderConfig,\n model: effectiveModel,\n });\n\n // Use pinned tools if set; otherwise fallback to global enabled tools.\n const configuredTools = Array.isArray(group?.toolTags)\n ? toolsStore.allTools.filter((t) => group.toolTags!.includes(t.name))\n : toolsStore.enabledTools;\n const declarativeToolResult = await loadDeclarativeTools(\n db,\n executionGroupId,\n );\n const rawDeclarativeTools = declarativeToolResult.tools.filter(\n (tool) =>\n !toolsStore.allTools.some((builtIn) => builtIn.name === tool.name),\n );\n const declarativeTools = Array.isArray(group?.toolTags)\n ? rawDeclarativeTools.filter((tool) => group.toolTags!.includes(tool.name))\n : rawDeclarativeTools.filter((tool) =>\n toolsStore.isDeclarativeToolEnabled(tool.name),\n );\n const toolsWithDeclarative = [...configuredTools, ...declarativeTools];\n const skillDiscovery = await discoverSkills(db, executionGroupId);\n const activeTools =\n skillDiscovery.skills.length > 0 &&\n !toolsWithDeclarative.some((tool) => tool.name === activate_skill.name)\n ? [...toolsWithDeclarative, activate_skill]\n : toolsWithDeclarative;\n\n const subagentModelSelectionMode =\n group?.subagentModelSelectionMode === \"manual\" ? \"manual\" : \"automatic\";\n const subagentMaxTokens = group?.subagentMaxTokens;\n const subagentPinnedProvider = group?.subagentPinnedProvider;\n const subagentPinnedModel = group?.subagentPinnedModel;\n const subagentFastProvider = group?.subagentFastProvider;\n const subagentFastModel = group?.subagentFastModel;\n const subagentSmartProvider = group?.subagentSmartProvider;\n const subagentSmartModel = group?.subagentSmartModel;\n const subagentPowerfulProvider = group?.subagentPowerfulProvider;\n const subagentPowerfulModel = group?.subagentPowerfulModel;\n const providerRuntimeOverrides = group?.providerRuntimeOverrides;\n\n const peerState = orchestratorStore.getPeerState(groupId) || undefined;\n const systemPrompt = buildSystemPrompt(\n o.assistantName,\n memory,\n activeTools,\n toolsStore.systemPromptOverride,\n peerState,\n skillDiscovery.skills,\n );\n\n // Build conversation context with dynamic token-aware windowing\n const contextLimit = getContextLimit(modelForTokenLimits);\n const systemPromptTokens =\n estimateTokens(systemPrompt) +\n (activeTools?.reduce(\n (acc, t) => acc + estimateTokens(JSON.stringify(t)),\n 0,\n ) ?? 0);\n let allMessages = await buildConversationMessages(groupId, 200);\n if (freshContext) {\n if (allMessages.length > 0) {\n allMessages = [allMessages[allMessages.length - 1]];\n } else {\n allMessages = [{ role: \"user\", content: triggerContent }];\n }\n }\n const dynamicContext = buildDynamicContext(allMessages, {\n contextLimit,\n systemPromptTokens,\n maxOutputTokens: effectiveMaxTokens,\n skimTop: o.contextCompressionEnabled,\n });\n\n const messages = dynamicContext.messages;\n\n let displayTokens = dynamicContext.estimatedTokens + systemPromptTokens;\n\n if (orchestratorStore.tokenUsage) {\n const u = orchestratorStore.tokenUsage;\n const actualPrompt =\n (u.inputTokens || 0) + (u.cacheReadTokens || 0) + (u.outputTokens || 0);\n\n displayTokens = Math.max(displayTokens, actualPrompt);\n }\n\n // Emit context usage for UI display\n o.events.emit(\"context-usage\", {\n estimatedTokens: displayTokens,\n contextLimit,\n usagePercent: Math.min(\n 100,\n Math.max(\n dynamicContext.usagePercent,\n (displayTokens / contextLimit) * 100,\n ),\n ),\n truncatedCount: dynamicContext.truncatedCount,\n });\n\n // Auto-compact when context usage exceeds 80% and there are enough messages\n if (\n dynamicContext.usagePercent > 80 &&\n dynamicContext.truncatedCount > 0 &&\n allMessages.length > 10\n ) {\n o.events.emit(\"show-toast\", {\n message: `Context ${dynamicContext.usagePercent.toFixed(0)}% full — auto-compacting older messages…`,\n type: \"info\",\n duration: 4000,\n });\n // Queue compaction after this invocation completes\n queueMicrotask(() => compactContext(o, db, groupId));\n }\n\n if (effectiveProviderId === \"transformers_js_browser\") {\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const transformersInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithTransformersJs(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n activeTools,\n effectiveModel,\n transformersInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n if (effectiveProviderId === \"prompt_api\") {\n if (!isPromptApiSupported()) {\n await ensureBuiltinAiPolyfills();\n }\n if (!isPromptApiSupported()) {\n await deliverResponse(\n o,\n db,\n executionGroupId,\n \"⚠️ Error: Prompt API is not available in this browser. Switch provider or enable experimental browser flags.\",\n );\n\n return;\n }\n\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const promptApiInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithPromptApi(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n activeTools,\n promptApiInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n if (effectiveProviderId === \"litert_lm_browser\") {\n if (!isLiteRtLmSupported()) {\n await deliverResponse(\n o,\n db,\n executionGroupId,\n \"⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.\",\n );\n\n return;\n }\n\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const liteRtInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithLiteRtLm(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n effectiveModel,\n activeTools,\n liteRtInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n // Determine whether to stream. The provider must explicitly opt in via\n // supportsStreaming (proxies like bedrock_proxy use synchronous\n // InvokeModelCommand and cannot return SSE streams).\n const shouldStream =\n o.streamingEnabled &&\n effectiveProviderConfig.supportsStreaming === true &&\n (effectiveProviderConfig.format === \"openai\" ||\n effectiveProviderConfig.format === \"anthropic\");\n\n if (effectiveProviderId === \"transformers_js_local\") {\n startTransformersProgressPolling(o, o.events, executionGroupId);\n }\n\n const providerRequestId = o.createProviderRequestId(executionGroupId);\n\n // Send to agent worker\n o.agentWorker?.postMessage({\n type: \"invoke\",\n payload: {\n apiKey:\n effectiveProviderId === o.provider\n ? await getApiKeyForRequest(o)\n : await o.getApiKeyForSpecificProvider(db, effectiveProviderId),\n assistantName: o.assistantName,\n contextCompression: o.contextCompressionEnabled,\n contextLimit: getContextLimit(modelForTokenLimits),\n enabledTools: activeTools,\n groupId: executionGroupId,\n isScheduledTask: o.schedulerTriggeredGroups.has(groupId),\n maxIterations: o.maxIterations,\n maxTokens: effectiveMaxTokens,\n memory,\n messages,\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n providerRequestId,\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n reasoning: getReasoningConfig(o),\n rateLimitAutoAdapt: o.rateLimitAutoAdapt,\n rateLimitCallsPerMinute: o.rateLimitCallsPerMinute,\n storageHandle: await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE),\n streaming: shouldStream,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n subagentTask: subagent,\n },\n });\n}\n","import type { InboundMessage } from \"../../../subsystems/channels/types.js\";\n\nimport type {\n DirectToolCommandPolicy,\n ParsedDirectToolCommand,\n} from \"./types.js\";\n\nexport function parseDirectToolCommand(\n policy: DirectToolCommandPolicy,\n assistantName: string,\n msg: InboundMessage,\n): ParsedDirectToolCommand | null {\n if (!policy.enabledChannelTypes.includes(msg.channel)) {\n return null;\n }\n\n const content = msg.content.trim();\n const escapedAssistant = assistantName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n let commandPart = content;\n if (policy.requireMention) {\n const mentionPrefix = new RegExp(\n `^@${escapedAssistant}\\\\b\\\\s*(?:-|:)?\\\\s*`,\n \"i\",\n );\n\n if (!mentionPrefix.test(commandPart)) {\n return null;\n }\n\n commandPart = commandPart.replace(mentionPrefix, \"\").trim();\n }\n\n const toolMatch = commandPart.match(/^\\/([a-zA-Z0-9_]+)(?:\\s+([\\s\\S]+))?$/);\n if (!toolMatch) {\n return null;\n }\n\n const toolName = toolMatch[1];\n if (!policy.allowedTools.includes(toolName)) {\n return null;\n }\n\n const rawArgs = (toolMatch[2] || \"\").trim();\n if (!rawArgs) {\n return { toolName, input: {} };\n }\n\n const unwrappedArgs =\n (rawArgs.startsWith(\"'\") && rawArgs.endsWith(\"'\")) ||\n (rawArgs.startsWith('\"') && rawArgs.endsWith('\"'))\n ? rawArgs.slice(1, -1).trim()\n : rawArgs;\n\n try {\n const parsedInput = JSON.parse(unwrappedArgs);\n if (parsedInput && typeof parsedInput === \"object\") {\n return {\n toolName,\n input: parsedInput as Record<string, any>,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","import type { SkillRecord } from \"./types.js\";\n\nexport interface ParsedSkillCommand {\n skill: SkillRecord;\n arguments: string;\n}\n\nexport function parseSkillCommand(\n content: string,\n skills: SkillRecord[],\n): ParsedSkillCommand | null {\n const match = content\n .trim()\n .match(\n /^\\/([a-z0-9](?:[a-z0-9]|-(?!-))*[a-z0-9]|[a-z0-9])(?:\\s+([\\s\\S]+))?$/u,\n );\n if (!match) {\n return null;\n }\n\n const skill = skills.find(\n (candidate) =>\n candidate.name === match[1] && candidate.userInvocable !== false,\n );\n if (!skill) {\n return null;\n }\n\n return {\n skill,\n arguments: (match[2] || \"\").trim(),\n };\n}\n","import { detectProviderHelpType } from \"../../../components/common/help/providers.js\";\nimport { getProvider } from \"../../../config/config.js\";\nimport { persistMessageAttachments } from \"../../../content/message-attachments.js\";\n\nimport { listGroups } from \"../../../db/groups.js\";\nimport { saveMessage } from \"../../../db/saveMessage.js\";\n\nimport { invokeAgent } from \"./invokeAgent.js\";\n\nimport { clearPeerJsTypingState } from \"./operations/channel.js\";\nimport { getApiKeyForRequest } from \"./operations/provider.js\";\n\nimport { parseDirectToolCommand } from \"./parseDirectToolCommand.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { parseSkillCommand } from \"../../../subsystems/skills/parseSkillCommand.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { InboundMessage } from \"../../../subsystems/channels/types.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function enqueue(\n o: Orchestrator,\n db: ShadowClawDatabase,\n msg: InboundMessage,\n): Promise<void> {\n // ── A2UI inbound dispatch ────────────────────────────────────────────────\n // Surface envelopes and actions arrive via the peer channel. Emit them so\n // the UI layer can render/update surfaces, then fall through to persist the\n // message normally (so the conversation history is complete).\n if (msg.a2uiEnvelopes && msg.a2uiEnvelopes.length > 0) {\n for (const envelope of msg.a2uiEnvelopes) {\n o.events.emit(\"a2ui-surface\", {\n groupId: msg.groupId,\n envelope,\n });\n }\n }\n\n if (msg.a2uiAction) {\n o.events.emit(\"a2ui-action\", {\n groupId: msg.groupId,\n action: msg.a2uiAction,\n });\n }\n\n // If there's nothing else in the message (no text, no attachments, only\n // A2UI parts), skip the rest of the enqueue flow.\n const hasTextContent = !!msg.content;\n const hasAttachments = (msg.attachments?.length ?? 0) > 0;\n if (\n !hasTextContent &&\n !hasAttachments &&\n (msg.a2uiEnvelopes?.length ?? 0) > 0\n ) {\n return;\n }\n\n // ── Normal message handling ──────────────────────────────────────────────\n const directToolCommand = parseDirectToolCommand(\n o.directToolCommandPolicy,\n o.assistantName,\n msg,\n );\n const skillCommand = directToolCommand\n ? null\n : parseSkillCommand(\n msg.content,\n (await discoverSkills(db, msg.groupId)).skills,\n );\n const isFromBrowser = msg.channel === \"browser\"; // Messages submitted in ShadowClaw UI\n const autoTrigger = o.channelRegistry.shouldAutoTrigger(msg.groupId);\n\n let hasTrigger = false;\n\n if (msg.channel === \"browser\" || msg.groupId.startsWith(\"room:\")) {\n hasTrigger = o.triggerPattern.test(msg.content.trim());\n }\n\n if (skillCommand) {\n hasTrigger = true;\n }\n\n // ── A2A task-state conversation termination ──────────────────────────────\n // If the local user sends a new message in a completed peer conversation,\n // reopen it (clear the terminal state) so the agent will respond again.\n if (isFromBrowser && msg.groupId.startsWith(\"peer:\")) {\n o.peerCompletedContexts.delete(msg.groupId);\n }\n\n const isDirectToolCommand = !!directToolCommand;\n\n // Check for explicit peer ID mention (works for both local and remote)\n if (!hasTrigger && o.peerjsMyPeerId) {\n if (msg.content.includes(`@${o.peerjsMyPeerId}`)) {\n hasTrigger = true;\n } else if (o.peerjsMyAlias && msg.content.includes(`@${o.peerjsMyAlias}`)) {\n // Also respond to @<my-alias> so peers can use the friendly name\n hasTrigger = true;\n } else {\n // Also check if any alias maps to o.peerjsMyPeerId\n for (const [alias, rawId] of Object.entries(o.peerjsPeerAliases)) {\n if (rawId === o.peerjsMyPeerId && msg.content.includes(`@${alias}`)) {\n hasTrigger = true;\n\n break;\n }\n }\n }\n }\n\n // Always trigger the agent for scheduled tasks\n if (msg.content.trim().startsWith(\"[SCHEDULED TASK]\")) {\n hasTrigger = true;\n }\n\n // Always trigger the owning agent to process an A2UI surface action. These\n // `[A2UI ACTION]` messages are only ever constructed on the surface owner's\n // side (local click on an owned surface, or an inbound `room/a2ui-action`\n // for a surface we own), so force-triggering here is safe and keeps shared\n // surfaces owner-authoritative.\n if (msg.content.trim().startsWith(\"[A2UI ACTION]\")) {\n hasTrigger = true;\n }\n\n let isTrigger = false;\n if (isDirectToolCommand) {\n isTrigger = true;\n } else if (hasTrigger) {\n isTrigger = true;\n } else if (isFromBrowser) {\n // Messages from the local UI trigger the agent by default,\n // EXCEPT in P2P / room channels where we just want to chat with peers.\n if (msg.groupId.startsWith(\"peer:\") || msg.groupId.startsWith(\"room:\")) {\n isTrigger = false;\n } else {\n isTrigger = true;\n }\n } else {\n isTrigger = autoTrigger;\n }\n\n // ── A2A terminal-state suppression ───────────────────────────────────────\n // If the peer conversation's task has reached a terminal state (COMPLETED,\n // FAILED, CANCELED) via A2A protocol, suppress auto-trigger. The human\n // user can reopen by sending a new message from the browser UI.\n if (\n isTrigger &&\n !isFromBrowser &&\n !skillCommand &&\n msg.groupId.startsWith(\"peer:\") &&\n o.peerCompletedContexts.has(msg.groupId)\n ) {\n isTrigger = false;\n }\n\n const attachments = await persistMessageAttachments(\n db,\n msg.groupId,\n msg.attachments || [],\n );\n\n const stored = {\n ...msg,\n attachments,\n isFromMe: false,\n isTrigger,\n };\n\n if (isTrigger && !isDirectToolCommand && !skillCommand?.skill.execution) {\n o.messageQueue.push(\n skillCommand\n ? {\n ...msg,\n content: `[SKILL COMMAND] Activate the \"${skillCommand.skill.name}\" skill and follow its instructions.\\n${skillCommand.arguments}`,\n }\n : msg,\n );\n }\n\n await saveMessage(db, stored);\n o.events.emit(\"message\", stored);\n\n if (skillCommand?.skill.execution && o.agentWorker) {\n const rawTools = skillCommand.skill.execution.tools;\n const tools = rawTools.map((t) => {\n const inputObj =\n t.input && typeof t.input === \"object\" ? { ...t.input } : {};\n if (skillCommand.arguments && Object.keys(inputObj).length === 0) {\n inputObj.rawInput = skillCommand.arguments;\n }\n return {\n ...t,\n input: inputObj,\n };\n });\n\n o.agentWorker.postMessage({\n type: \"execute-skill-tools\",\n payload: {\n groupId: msg.groupId,\n skillName: skillCommand.skill.name,\n tools,\n },\n });\n return;\n }\n\n // Keep peer typing state in sync, but do not treat every P2P chat message\n // as an agent response. Normal peer messages should not force the remote\n // peer into a temporary \"responding\" state.\n if (msg.channel === \"peerjs\") {\n clearPeerJsTypingState(msg.groupId);\n }\n\n // Forward browser messages to the P2P / room channel so users can chat directly\n if (\n isFromBrowser &&\n (msg.groupId.startsWith(\"peer:\") || msg.groupId.startsWith(\"room:\"))\n ) {\n o.router?.send(msg.groupId, msg.content, attachments).catch((err) => {\n console.error(\"Failed to route browser message to peer:\", err);\n });\n }\n\n if (directToolCommand && o.agentWorker) {\n o.agentWorker.postMessage({\n type: \"execute-direct-tool\",\n payload: {\n groupId: msg.groupId,\n name: directToolCommand.toolName,\n input: directToolCommand.input,\n },\n });\n\n return;\n }\n\n processQueue(o, db);\n}\n\nexport async function processQueue(\n o: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n if (o.processing) {\n return;\n }\n\n if (o.messageQueue.length === 0) {\n return;\n }\n\n // Look up the effective provider for the next message's group\n const nextMsg = o.messageQueue[0];\n const nextGroupId = nextMsg?.groupId;\n\n let effectiveProviderConfig = o.providerConfig;\n let effectiveProviderId = o.provider;\n\n if (nextGroupId) {\n try {\n const groups = await listGroups(db);\n const grp = groups.find((g) => g.groupId === nextGroupId);\n if (grp?.pinnedProvider) {\n const pinned = getProvider(grp.pinnedProvider);\n if (pinned) {\n effectiveProviderConfig = pinned;\n effectiveProviderId = grp.pinnedProvider;\n }\n }\n } catch {\n // best-effort\n }\n }\n\n const requiresApiKey = effectiveProviderConfig?.requiresApiKey !== false;\n let apiKeyPresent = true;\n if (requiresApiKey) {\n if (effectiveProviderId === o.provider) {\n apiKeyPresent = !!(await getApiKeyForRequest(o));\n } else {\n apiKeyPresent = !!(await o.getApiKeyForSpecificProvider(\n db,\n effectiveProviderId,\n ));\n }\n }\n\n if (requiresApiKey && !apiKeyPresent) {\n const reason =\n \"API key not configured. Go to Settings to add your API key.\";\n\n o.events.emit(\"provider-help\", {\n providerId: effectiveProviderId,\n reason,\n helpType: detectProviderHelpType(\n effectiveProviderId,\n reason,\n requiresApiKey,\n ),\n });\n\n const msg = o.messageQueue.shift()!;\n o.events.emit(\"error\", {\n groupId: msg.groupId,\n error: reason,\n });\n\n return;\n }\n\n o.processing = true;\n const msg = o.messageQueue.shift()!;\n\n try {\n await invokeAgent(\n o,\n db,\n msg.groupId,\n msg.content,\n msg.freshContext,\n msg.subagent,\n );\n } catch (err) {\n console.error(\"Failed to invoke agent:\", err);\n } finally {\n o.processing = false;\n if (o.messageQueue.length > 0) {\n processQueue(o, db);\n }\n }\n}\n","/**\n * Simple event emitter for orchestrator events.\n */\nexport class EventBus {\n listeners: Map<string, Set<Function>>;\n\n constructor() {\n this.listeners = new Map();\n }\n\n emit(event: string, data: any) {\n this.listeners.get(event)?.forEach((cb) => cb(data));\n }\n\n off(event: string, callback: Function) {\n this.listeners.get(event)?.delete(callback);\n }\n\n on(event: string, callback: Function) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n\n this.listeners.get(event)?.add(callback);\n }\n}\n","/**\n * ShadowClaw — Room Manager (multi-party PeerJS conversations)\n *\n * Coordinates a hybrid room topology on top of the existing 1:1\n * {@link PeerJsChannel} transport:\n *\n * - The room **host** runs a star for signaling, roster and membership\n * (`room/join`, `room/roster`, `room/leave`, `room/invite`).\n * - Actual chat traffic (`room/message`) flows peer-to-peer over the **mesh**,\n * falling back to **host relay** (`room/relay`) when a direct connection to a\n * recipient is not available.\n *\n * The manager owns no socket of its own — it delegates all transport to an\n * injected {@link RoomTransport} so it can be unit-tested in isolation. Trigger\n * (@mention) detection is intentionally left to the orchestrator's existing\n * enqueue logic; this layer only delivers inbound messages.\n */\n\nimport { Signal } from \"signal-polyfill\";\n\nimport { roomGroupId } from \"../../db/rooms.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type { A2UIAction, A2UIEnvelope } from \"../../ui/a2ui/types.js\";\nimport type { InboundMessage, RoomMember, RoomMeta } from \"./types.js\";\n\nimport type {\n A2AJsonRpcNotification,\n RoomA2UIActionEnvelope,\n RoomA2UIEnvelope,\n RoomInvitePayload,\n RoomJoinPayload,\n RoomLeavePayload,\n RoomMessageEnvelope,\n RoomRelayPayload,\n RoomRosterPayload,\n} from \"./peer-protocol.js\";\n\nimport { ROOM_METHOD } from \"./peer-protocol.js\";\n\n/** Build the `[A2UI ACTION]` prompt that drives owner-side action processing. */\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/formatA2UIActionPrompt.js\";\n\n/** Transport surface the {@link RoomManager} depends on. */\nexport interface RoomTransport {\n /** The local peer ID. */\n readonly myPeerId: string;\n /** Send a JSON-RPC notification to a single peer. Returns true if dispatched. */\n sendToPeer(peerId: string, notification: A2AJsonRpcNotification): boolean;\n /** Whether a direct, open connection to the peer currently exists. */\n isConnected(peerId: string): boolean;\n /** Best-effort: ensure an outbound connection to the peer is opened. */\n connectToPeer(peerId: string): void;\n}\n\nexport interface RoomManagerOptions {\n transport: RoomTransport;\n /** Resolve the local member identity used when creating/joining rooms. */\n getLocalMember: () => RoomMember;\n /** Deliver an inbound room chat message to the orchestrator. */\n onMessage: (msg: InboundMessage) => void;\n /** Deliver an inbound room invitation (e.g. to a notification / dialog). */\n onInvite?: (invite: RoomInvitePayload) => void;\n /** Persist (insert or replace) a room record. */\n persistRoom?: (room: RoomMeta) => void;\n /** Remove a persisted room record. */\n removeRoom?: (roomId: string) => void;\n}\n\n/** Max remembered message ids per room for cross-path de-duplication. */\nconst MAX_SEEN_PER_ROOM = 500;\n\nfunction notification(method: string, params: unknown): A2AJsonRpcNotification {\n return { jsonrpc: \"2.0\", method, params };\n}\n\nexport class RoomManager {\n // ---------------------------------------------------------------------------\n // Inbound dispatch\n // ---------------------------------------------------------------------------\n\n /**\n * Returns true if the method is a room protocol method this manager handles.\n */\n static isRoomMethod(method: string): boolean {\n return (\n method === ROOM_METHOD.JOIN ||\n method === ROOM_METHOD.ROSTER ||\n method === ROOM_METHOD.LEAVE ||\n method === ROOM_METHOD.MESSAGE ||\n method === ROOM_METHOD.INVITE ||\n method === ROOM_METHOD.RELAY ||\n method === ROOM_METHOD.A2UI ||\n method === ROOM_METHOD.A2UI_ACTION\n );\n }\n\n /** Reactive snapshot of joined rooms for the UI. */\n readonly roomsSignal = new Signal.State<RoomMeta[]>([]);\n private readonly _opts: RoomManagerOptions;\n\n /** Joined rooms keyed by bare room id. */\n private readonly _rooms = new Map<string, RoomMeta>();\n\n /** Per-room set of seen message ids (insertion-ordered for trimming). */\n private readonly _seen = new Map<string, Set<string>>();\n\n /**\n * Owner of each shared A2UI surface, keyed by surfaceId. Populated when the\n * local peer broadcasts a surface it created, or when an inbound\n * `room/a2ui` createSurface broadcast is received. Used to enforce the\n * owner-authoritative model: only the surface owner's agent processes\n * actions and mutates the data model.\n */\n private readonly _surfaceOwners = new Map<string, string>();\n\n constructor(opts: RoomManagerOptions) {\n this._opts = opts;\n }\n\n // ---------------------------------------------------------------------------\n // Outbound messages\n // ---------------------------------------------------------------------------\n\n /**\n * Broadcast a chat message to every other room member. Uses mesh delivery\n * with host-relay fallback. Returns the message id used.\n */\n broadcast(\n roomId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._opts.getLocalMember();\n const messageId = ulid();\n const envelope: RoomMessageEnvelope = {\n roomId,\n messageId,\n senderPeerId: me.peerId,\n senderAlias: me.alias,\n text,\n attachments: attachments?.map((a) => ({\n fileName: a.fileName,\n mimeType: a.mimeType,\n path: a.path,\n size: a.size,\n })),\n };\n\n // Remember our own id so an echo (e.g. host relay) is not re-delivered.\n this._markSeen(roomId, messageId);\n this._deliverToMembers(room, notification(ROOM_METHOD.MESSAGE, envelope));\n\n return messageId;\n }\n\n /**\n * Broadcast a locally produced A2UI surface envelope to every other room\n * member. Records the local peer as the surface owner so subsequent actions\n * route back here. Returns the broadcast id used (null if not a member).\n */\n broadcastA2UI(roomId: string, envelope: A2UIEnvelope): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._myPeerId;\n // The local peer authored this surface — record (or refresh) ownership.\n this._surfaceOwners.set(envelope.surfaceId, me);\n\n const broadcastId = ulid();\n const payload: RoomA2UIEnvelope = {\n roomId,\n broadcastId,\n ownerPeerId: me,\n senderPeerId: me,\n envelope,\n };\n\n this._markSeen(roomId, broadcastId);\n this._deliverToMembers(room, notification(ROOM_METHOD.A2UI, payload));\n\n return broadcastId;\n }\n\n /**\n * Broadcast a user action fired on a shared surface to every other room\n * member. The surface owner's agent will process it (and broadcast the\n * resulting data-model update). Returns the broadcast id (null if not a\n * member).\n */\n broadcastA2UIAction(roomId: string, action: A2UIAction): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._opts.getLocalMember();\n const ownerPeerId = this._surfaceOwners.get(action.surfaceId) ?? \"\";\n const broadcastId = ulid();\n const payload: RoomA2UIActionEnvelope = {\n roomId,\n broadcastId,\n ownerPeerId,\n senderPeerId: me.peerId,\n senderAlias: me.alias,\n action,\n };\n\n this._markSeen(roomId, broadcastId);\n this._deliverToMembers(\n room,\n notification(ROOM_METHOD.A2UI_ACTION, payload),\n );\n\n return broadcastId;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (host + member)\n // ---------------------------------------------------------------------------\n\n /** Create a new room hosted by the local peer. */\n createRoom(name: string): RoomMeta {\n const me = this._opts.getLocalMember();\n const room: RoomMeta = {\n roomId: ulid(),\n name,\n hostPeerId: me.peerId,\n members: [me],\n createdAt: Date.now(),\n };\n\n this._save(room);\n\n return room;\n }\n\n /** Get a joined room by id. */\n get(roomId: string): RoomMeta | null {\n return this._rooms.get(roomId) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // Shared A2UI surfaces (owner-authoritative)\n // ---------------------------------------------------------------------------\n\n /** The peer that owns the given shared surface, if known locally. */\n getSurfaceOwner(surfaceId: string): string | undefined {\n return this._surfaceOwners.get(surfaceId);\n }\n\n /** Dispatch an inbound room notification received from {@link fromPeerId}. */\n handleNotification(\n fromPeerId: string,\n method: string,\n params: unknown,\n ): void {\n switch (method) {\n case ROOM_METHOD.JOIN:\n this._onJoin(fromPeerId, params as RoomJoinPayload);\n\n break;\n case ROOM_METHOD.ROSTER:\n this._onRoster(params as RoomRosterPayload);\n\n break;\n case ROOM_METHOD.LEAVE:\n this._onLeave(fromPeerId, params as RoomLeavePayload);\n\n break;\n case ROOM_METHOD.MESSAGE:\n this._onMessage(params as RoomMessageEnvelope);\n\n break;\n case ROOM_METHOD.INVITE:\n this._opts.onInvite?.(params as RoomInvitePayload);\n\n break;\n case ROOM_METHOD.RELAY:\n this._onRelay(params as RoomRelayPayload);\n\n break;\n case ROOM_METHOD.A2UI:\n this._onA2UI(params as RoomA2UIEnvelope);\n\n break;\n case ROOM_METHOD.A2UI_ACTION:\n this._onA2UIAction(params as RoomA2UIActionEnvelope);\n\n break;\n }\n }\n\n /** Invite a peer to a room (out-of-band, peer-to-peer). */\n invite(roomId: string, targetPeerId: string): boolean {\n const room = this._rooms.get(roomId);\n if (!room) {\n return false;\n }\n\n const me = this._opts.getLocalMember();\n const payload: RoomInvitePayload = {\n roomId,\n roomName: room.name,\n hostPeerId: room.hostPeerId,\n fromPeerId: me.peerId,\n fromAlias: me.alias,\n };\n\n const transport = this._opts.transport;\n transport.connectToPeer(targetPeerId);\n\n return transport.sendToPeer(\n targetPeerId,\n notification(ROOM_METHOD.INVITE, payload),\n );\n }\n\n /** Whether the local peer is the host of the given room. */\n isHost(roomId: string): boolean {\n const room = this._rooms.get(roomId);\n\n return !!room && room.hostPeerId === this._myPeerId;\n }\n\n /**\n * Join an existing room hosted by {@link hostPeerId}. Establishes a local\n * provisional roster (host + self) and sends a join request to the host; the\n * authoritative roster arrives via a `room/roster` notification.\n */\n joinRoom(roomId: string, hostPeerId: string, name: string): RoomMeta {\n const me = this._opts.getLocalMember();\n const existing = this._rooms.get(roomId);\n const room: RoomMeta = existing ?? {\n roomId,\n name,\n hostPeerId,\n members: [{ peerId: hostPeerId, alias: hostPeerId, kind: \"agent\" }, me],\n createdAt: Date.now(),\n };\n\n this._save(room);\n\n const transport = this._opts.transport;\n transport.connectToPeer(hostPeerId);\n const payload: RoomJoinPayload = { roomId, member: me };\n transport.sendToPeer(hostPeerId, notification(ROOM_METHOD.JOIN, payload));\n\n return room;\n }\n\n /**\n * Leave (member) or disband (host) a room. The host notifies all members that\n * the room is disbanded; a member notifies the host of its departure.\n */\n leaveRoom(roomId: string): void {\n const room = this._rooms.get(roomId);\n if (!room) {\n return;\n }\n\n const me = this._myPeerId;\n if (room.hostPeerId === me) {\n const payload: RoomLeavePayload = {\n roomId,\n peerId: me,\n disbanded: true,\n };\n this._deliverToMembers(room, notification(ROOM_METHOD.LEAVE, payload));\n } else {\n const payload: RoomLeavePayload = { roomId, peerId: me };\n this._opts.transport.sendToPeer(\n room.hostPeerId,\n notification(ROOM_METHOD.LEAVE, payload),\n );\n }\n\n this._rooms.delete(roomId);\n this._seen.delete(roomId);\n this._opts.removeRoom?.(roomId);\n this._publish();\n }\n\n /** All joined rooms. */\n list(): RoomMeta[] {\n return Array.from(this._rooms.values());\n }\n\n // ---------------------------------------------------------------------------\n // State\n // ---------------------------------------------------------------------------\n\n /** Load persisted rooms at startup. */\n loadRooms(rooms: RoomMeta[]): void {\n this._rooms.clear();\n for (const room of rooms) {\n this._rooms.set(room.roomId, room);\n }\n\n this._publish();\n }\n\n // ---------------------------------------------------------------------------\n // Delivery helpers\n // ---------------------------------------------------------------------------\n\n private _broadcastRoster(room: RoomMeta): void {\n const payload: RoomRosterPayload = {\n roomId: room.roomId,\n name: room.name,\n hostPeerId: room.hostPeerId,\n members: room.members,\n };\n this._deliverToMembers(room, notification(ROOM_METHOD.ROSTER, payload));\n }\n\n /**\n * Deliver a notification to all room members except the local peer, using a\n * direct mesh connection where possible and host relay as a fallback.\n */\n private _deliverToMembers(\n room: RoomMeta,\n note: A2AJsonRpcNotification,\n ): void {\n const me = this._myPeerId;\n for (const member of room.members) {\n if (member.peerId === me) {\n continue;\n }\n\n this._deliverToPeer(room, member.peerId, note);\n }\n }\n\n private _deliverToPeer(\n room: RoomMeta,\n targetPeerId: string,\n note: A2AJsonRpcNotification,\n ): void {\n const transport = this._opts.transport;\n if (transport.isConnected(targetPeerId)) {\n transport.sendToPeer(targetPeerId, note);\n\n return;\n }\n\n // Not directly connected — relay via the host when possible.\n const me = this._myPeerId;\n if (\n room.hostPeerId !== me &&\n room.hostPeerId !== targetPeerId &&\n transport.isConnected(room.hostPeerId)\n ) {\n const relay: RoomRelayPayload = {\n roomId: room.roomId,\n targetPeerId,\n inner: note,\n };\n transport.sendToPeer(\n room.hostPeerId,\n notification(ROOM_METHOD.RELAY, relay),\n );\n // Opportunistically upgrade to a direct mesh link for next time.\n transport.connectToPeer(targetPeerId);\n\n return;\n }\n\n // Last resort: open a connection and attempt a direct send.\n transport.connectToPeer(targetPeerId);\n transport.sendToPeer(targetPeerId, note);\n }\n\n // ---------------------------------------------------------------------------\n // De-duplication\n // ---------------------------------------------------------------------------\n\n private _hasSeen(roomId: string, messageId: string): boolean {\n return this._seen.get(roomId)?.has(messageId) ?? false;\n }\n\n private _markSeen(roomId: string, messageId: string): void {\n let set = this._seen.get(roomId);\n if (!set) {\n set = new Set();\n this._seen.set(roomId, set);\n }\n\n set.add(messageId);\n if (set.size > MAX_SEEN_PER_ROOM) {\n // Drop the oldest entry (insertion order).\n const oldest = set.values().next().value;\n if (oldest !== undefined) {\n set.delete(oldest);\n }\n }\n }\n\n private get _myPeerId(): string {\n return this._opts.transport.myPeerId;\n }\n\n /**\n * Inbound shared A2UI surface broadcast. De-duplicate, record the surface\n * owner, then deliver the envelope to the local UI so the surface renders /\n * updates in lockstep with the rest of the room.\n */\n private _onA2UI(payload: RoomA2UIEnvelope): void {\n if (\n !payload ||\n typeof payload.roomId !== \"string\" ||\n typeof payload.broadcastId !== \"string\" ||\n !payload.envelope\n ) {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(payload.roomId, payload.broadcastId)) {\n return;\n }\n\n this._markSeen(payload.roomId, payload.broadcastId);\n\n // Record ownership so any action we fire on this surface routes to its\n // authoritative owner. Never let an inbound broadcast claim ownership of a\n // surface we authored locally.\n const surfaceId = payload.envelope.surfaceId;\n if (this._surfaceOwners.get(surfaceId) !== this._myPeerId) {\n this._surfaceOwners.set(surfaceId, payload.ownerPeerId);\n }\n\n const inbound: InboundMessage = {\n id: payload.broadcastId,\n groupId: roomGroupId(payload.roomId),\n sender: payload.senderPeerId,\n content: \"\",\n timestamp: Date.now(),\n channel: \"room\",\n a2uiEnvelopes: [payload.envelope],\n };\n\n this._opts.onMessage(inbound);\n }\n\n /**\n * Inbound shared A2UI action. De-duplicate, then — only when the local peer\n * is the authoritative owner of the target surface — deliver a trigger\n * message so the owner's agent processes the action and broadcasts the\n * resulting data-model update. Non-owners ignore the action; their surface is\n * synchronized by the owner's subsequent `room/a2ui` broadcast.\n */\n private _onA2UIAction(payload: RoomA2UIActionEnvelope): void {\n if (\n !payload ||\n typeof payload.roomId !== \"string\" ||\n typeof payload.broadcastId !== \"string\" ||\n !payload.action\n ) {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(payload.roomId, payload.broadcastId)) {\n return;\n }\n\n this._markSeen(payload.roomId, payload.broadcastId);\n\n // Owner-authoritative: only process actions for surfaces we locally own.\n // Trust our own ownership map over any self-reported `ownerPeerId`.\n if (this._surfaceOwners.get(payload.action.surfaceId) !== this._myPeerId) {\n return;\n }\n\n const inbound: InboundMessage = {\n id: payload.broadcastId,\n groupId: roomGroupId(payload.roomId),\n sender: payload.senderAlias || payload.senderPeerId,\n content: formatA2UIActionPrompt(payload.action, payload.senderAlias),\n timestamp: Date.now(),\n channel: \"room\",\n a2uiAction: payload.action,\n };\n\n this._opts.onMessage(inbound);\n }\n\n /** Host: a peer requested to join. Add to roster and broadcast it. */\n private _onJoin(fromPeerId: string, payload: RoomJoinPayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room || room.hostPeerId !== this._myPeerId) {\n return; // Only the host services join requests.\n }\n\n const member: RoomMember = payload.member ?? {\n peerId: fromPeerId,\n alias: fromPeerId,\n kind: \"human\",\n };\n // Trust the connection's peer id over any self-reported value.\n member.peerId = fromPeerId;\n\n const index = room.members.findIndex((m) => m.peerId === fromPeerId);\n if (index >= 0) {\n room.members[index] = member;\n } else {\n room.members.push(member);\n }\n\n this._save(room);\n this._broadcastRoster(room);\n }\n\n /** Leave/disband notification. */\n private _onLeave(fromPeerId: string, payload: RoomLeavePayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return;\n }\n\n if (payload.disbanded) {\n // Host disbanded the room for everyone.\n this._rooms.delete(payload.roomId);\n this._seen.delete(payload.roomId);\n this._opts.removeRoom?.(payload.roomId);\n this._publish();\n\n return;\n }\n\n // Host receives a member's departure: drop them and re-broadcast roster.\n if (room.hostPeerId === this._myPeerId) {\n room.members = room.members.filter(\n (m) => m.peerId !== (payload.peerId || fromPeerId),\n );\n this._save(room);\n this._broadcastRoster(room);\n }\n }\n\n /** Inbound chat message — de-duplicate then deliver to the orchestrator. */\n private _onMessage(envelope: RoomMessageEnvelope): void {\n if (\n !envelope ||\n typeof envelope.roomId !== \"string\" ||\n typeof envelope.messageId !== \"string\"\n ) {\n return;\n }\n\n const room = this._rooms.get(envelope.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(envelope.roomId, envelope.messageId)) {\n return;\n }\n\n this._markSeen(envelope.roomId, envelope.messageId);\n\n const inbound: InboundMessage = {\n id: envelope.messageId,\n groupId: roomGroupId(envelope.roomId),\n sender: envelope.senderAlias || envelope.senderPeerId,\n content: envelope.text ?? \"\",\n timestamp: Date.now(),\n channel: \"room\",\n attachments: envelope.attachments?.map((a) => ({\n fileName: a.fileName,\n mimeType: a.mimeType,\n path: a.path,\n size: a.size,\n })),\n };\n\n this._opts.onMessage(inbound);\n }\n\n /** Host: forward a relayed notification to its intended target. */\n private _onRelay(payload: RoomRelayPayload): void {\n if (\n !payload ||\n typeof payload.targetPeerId !== \"string\" ||\n !payload.inner\n ) {\n return;\n }\n\n // Only relay for rooms we host.\n if (!this.isHost(payload.roomId)) {\n return;\n }\n\n this._opts.transport.sendToPeer(payload.targetPeerId, payload.inner);\n }\n\n /** Member: authoritative roster received from the host. */\n private _onRoster(payload: RoomRosterPayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const existing = this._rooms.get(payload.roomId);\n const room: RoomMeta = {\n roomId: payload.roomId,\n name: payload.name ?? existing?.name ?? payload.roomId,\n hostPeerId: payload.hostPeerId,\n members: Array.isArray(payload.members) ? payload.members : [],\n createdAt: existing?.createdAt ?? Date.now(),\n };\n\n this._save(room);\n }\n\n private _publish(): void {\n this.roomsSignal.set(this.list());\n }\n\n private _save(room: RoomMeta): void {\n this._rooms.set(room.roomId, room);\n this._opts.persistRoom?.(room);\n this._publish();\n }\n}\n","import { getDb } from \"./db.js\";\nimport type { ShadowClawDatabase, Task } from \"./types.js\";\n\n/**\n * Get all enabled tasks\n */\nexport function getEnabledTasks(): Promise<Task[]> {\n return new Promise(async (resolve, reject) => {\n try {\n const tx: ShadowClawDatabase = await getDb();\n\n if (!tx) {\n return reject(\n new Error(\"failed to get transaction, cannot get enabled tasks.\"),\n );\n }\n\n const transactionStore = tx.transaction(\"tasks\", \"readonly\");\n if (!transactionStore) {\n return reject(new Error(\"failed to get transaction\"));\n }\n\n const store = transactionStore.objectStore(\"tasks\");\n const index = store.index(\"by-enabled\");\n const request = index.getAll(1); // enabled = true (stored as 1)\n\n request.onsuccess = () => {\n // Convert numeric `enabled` back to boolean\n const tasks: Task[] = (request.result as any[]).map((t) => ({\n ...t,\n enabled: true,\n }));\n\n resolve(tasks);\n };\n\n request.onerror = () => reject(request.error);\n } catch (err) {\n reject(err);\n }\n });\n}\n","// =========================================================================\n// Cron expression parser (lightweight, no dependencies)\n// =========================================================================\n// Format: minute hour day-of-month month day-of-week\n// Supports: * (any), N (exact), N-M (range), N,M (list), */N (step)\n\n/**\n * Match a cron expression against a date\n */\nexport function matchesCron(expr: string, date: Date): boolean {\n if (typeof expr !== \"string\" || !expr.trim()) {\n return false;\n }\n\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) {\n return false;\n }\n\n const [min, hour, dom, mon, dow] = parts;\n\n return (\n matchField(min, date.getMinutes()) &&\n matchField(hour, date.getHours()) &&\n matchField(dom, date.getDate()) &&\n matchField(mon, date.getMonth() + 1) &&\n matchField(dow, date.getDay())\n );\n}\n\n/**\n * Match a single cron field\n */\nfunction matchField(field: string, value: number): boolean {\n if (field === \"*\") {\n return true;\n }\n\n return field.split(\",\").some((part) => {\n // Step: */N or N/M\n if (part.includes(\"/\")) {\n const [range, stepStr] = part.split(\"/\");\n const step = parseInt(stepStr, 10);\n if (isNaN(step) || step <= 0) {\n return false;\n }\n\n if (range === \"*\") {\n return value % step === 0;\n }\n\n // Range with step: N-M/S\n if (range.includes(\"-\")) {\n const [lo, hi] = range.split(\"-\").map(Number);\n\n return value >= lo && value <= hi && (value - lo) % step === 0;\n }\n\n const start = parseInt(range, 10);\n\n return value >= start && (value - start) % step === 0;\n }\n\n // Range: N-M\n if (part.includes(\"-\")) {\n const [lo, hi] = part.split(\"-\").map(Number);\n\n return value >= lo && value <= hi;\n }\n\n // Exact match\n\n return parseInt(part, 10) === value;\n });\n}\n","import { getEnabledTasks } from \"../../db/getEnabledTasks.js\";\nimport { updateTaskLastRun } from \"../../db/updateTaskLastRun.js\";\nimport { matchesCron } from \"./cron.js\";\n\nimport { SCHEDULER_INTERVAL } from \"../../config/config.js\";\nimport type { Task } from \"../../db/types.js\";\n\n// Re-export matchesCron for existing consumers (tests, etc.)\nexport { matchesCron };\n\nexport interface TaskRunner {\n (task: Task): Promise<void>;\n}\n\n/**\n * ShadowClaw — Task Scheduler\n *\n * Evaluates cron expressions and fires tasks on schedule.\n *\n * Runs on the main thread via setInterval.\n */\nexport class TaskScheduler {\n interval: ReturnType<typeof setInterval> | null = null;\n onTaskChange?: () => void;\n runner: TaskRunner;\n\n constructor(runner: TaskRunner, onTaskChange?: () => void) {\n this.runner = runner;\n this.onTaskChange = onTaskChange;\n }\n\n /**\n * Check if a task already ran in this minute (prevent double-execution).\n */\n ranThisMinute(task: Task, now: Date): boolean {\n if (!task.lastRun) {\n return false;\n }\n\n const last = new Date(task.lastRun);\n\n return (\n last.getFullYear() === now.getFullYear() &&\n last.getMonth() === now.getMonth() &&\n last.getDate() === now.getDate() &&\n last.getHours() === now.getHours() &&\n last.getMinutes() === now.getMinutes()\n );\n }\n\n /**\n * Start the scheduler. Checks for due tasks every 60 seconds.\n */\n start() {\n if (this.interval) {\n return;\n }\n\n this.interval = setInterval(() => this.tick(), SCHEDULER_INTERVAL);\n\n // Immediate first check\n this.tick();\n }\n\n /**\n * Stop the scheduler.\n */\n stop() {\n if (this.interval) {\n clearInterval(this.interval);\n\n this.interval = null;\n }\n }\n\n /**\n * Check for due tasks and run them.\n */\n async tick() {\n try {\n const tasks = await getEnabledTasks();\n const now = new Date();\n\n for (const task of tasks) {\n const taskSchedule = task.schedule || \"\";\n if (\n taskSchedule !== \"\" &&\n matchesCron(taskSchedule, now) &&\n !this.ranThisMinute(task, now)\n ) {\n // Mark as run immediately to prevent double-firing\n await updateTaskLastRun(task.id, now.getTime());\n this.onTaskChange?.();\n\n // Fire task (non-blocking)\n this.runner(task).catch((err) => {\n console.error(`Task ${task.id} failed:`, err);\n });\n }\n }\n } catch (err) {\n console.error(\"Scheduler tick error:\", err);\n }\n }\n}\n","import { normalizeStringList } from \"./normalizeStringList.js\";\n\n/**\n * Parses a stored string value into a normalized list of strings.\n * Attempts JSON array parse first, then falls back to comma-separated.\n */\nexport function parseStoredStringList(value: string | undefined): string[] {\n if (!value) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(value);\n if (Array.isArray(parsed)) {\n return normalizeStringList(parsed.map((entry) => String(entry)));\n }\n } catch {\n // Fall back to comma-separated input for forward compatibility.\n }\n\n return normalizeStringList(value.split(\",\"));\n}\n","import { CONFIG_KEYS } from \"../../../config/config.js\";\n\nimport { inferAttachmentMimeType } from \"../../../content/message-attachments.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { readGroupFileBytes } from \"../../../storage/readGroupFileBytes.js\";\nimport { loadChannelEnabled } from \"./operations/channel.js\";\nimport { parseStoredStringList } from \"./parseStoredStringList.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function loadChannelConfigurations(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.channelEnabledByType.telegram = await loadChannelEnabled(\n \"telegram\",\n db,\n );\n\n orchestrator.channelEnabledByType.imessage = await loadChannelEnabled(\n \"imessage\",\n db,\n );\n\n const telegramToken = await orchestrator.loadSecretConfig(\n db,\n CONFIG_KEYS.TELEGRAM_BOT_TOKEN,\n );\n\n const telegramChatIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.TELEGRAM_CHAT_IDS),\n );\n\n const telegramUseProxy =\n (await getConfig(db, CONFIG_KEYS.TELEGRAM_USE_PROXY)) === \"true\";\n\n orchestrator.telegramBotToken = telegramToken;\n orchestrator.telegramChatIds = telegramChatIds;\n orchestrator.telegramUseProxy = telegramUseProxy;\n orchestrator.telegram.configure(\n telegramToken,\n telegramChatIds,\n telegramUseProxy,\n );\n\n const readWorkspaceFileAsBlob = async (\n groupId: string,\n path: string,\n ): Promise<Blob | null> => {\n try {\n const bytes = await readGroupFileBytes(db, groupId, path);\n const blobBytes = new Uint8Array(bytes.byteLength);\n blobBytes.set(bytes);\n\n const fileName = path.split(\"/\").pop() || path;\n const mimeType = inferAttachmentMimeType(fileName);\n\n return new Blob([blobBytes], { type: mimeType });\n } catch (err) {\n console.warn(`Orchestrator: channel fileReader failed for ${path}:`, err);\n\n return null;\n }\n };\n\n orchestrator.telegram.fileReader = readWorkspaceFileAsBlob;\n orchestrator.imessage.fileReader = readWorkspaceFileAsBlob;\n\n const imessageServerUrl = (\n (await getConfig(db, CONFIG_KEYS.IMESSAGE_SERVER_URL)) || \"\"\n )\n .trim()\n .replace(/\\/+$/, \"\");\n\n const imessageApiKey = await orchestrator.loadSecretConfig(\n db,\n CONFIG_KEYS.IMESSAGE_API_KEY,\n );\n\n const imessageChatIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.IMESSAGE_CHAT_IDS),\n );\n\n orchestrator.imessageServerUrl = imessageServerUrl;\n orchestrator.imessageApiKey = imessageApiKey;\n orchestrator.imessageChatIds = imessageChatIds;\n orchestrator.imessage.configure(\n imessageServerUrl,\n imessageApiKey,\n imessageChatIds,\n );\n\n // ---- PeerJS ----\n orchestrator.channelEnabledByType.peerjs = await loadChannelEnabled(\n \"peerjs\",\n db,\n );\n\n const peerjsMyPeerId = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_MY_PEER_ID)) || \"\"\n ).trim();\n\n const peerjsTrustedPeerIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.PEERJS_TRUSTED_PEER_IDS),\n );\n\n const peerjsServerHost = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_SERVER_HOST)) || \"\"\n ).trim();\n\n const peerjsServerPortRaw = await getConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_PORT,\n );\n\n const peerjsServerPort = peerjsServerPortRaw\n ? parseInt(peerjsServerPortRaw, 10) || 0\n : 0;\n\n const peerjsServerPath = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_SERVER_PATH)) || \"\"\n ).trim();\n\n const peerjsServerSecureRaw = await getConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_SECURE,\n );\n\n const peerjsServerSecure = peerjsServerSecureRaw !== \"false\";\n\n let peerjsPeerAliases: Record<string, string> = {};\n\n const storedAliasesRaw = await getConfig(db, CONFIG_KEYS.PEERJS_PEER_ALIASES);\n\n if (storedAliasesRaw) {\n try {\n peerjsPeerAliases = JSON.parse(storedAliasesRaw);\n } catch (err) {\n console.warn(\"Failed to parse peerjs_peer_aliases\", err);\n }\n }\n\n orchestrator.peerjsMyPeerId = peerjsMyPeerId;\n orchestrator.peerjsMyAlias = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS)) || \"\"\n ).trim();\n\n orchestrator.peerjsTrustedPeerIds = peerjsTrustedPeerIds;\n orchestrator.peerjsPeerAliases = peerjsPeerAliases;\n orchestrator.peerjsServerHost = peerjsServerHost;\n orchestrator.peerjsServerPort = peerjsServerPort;\n orchestrator.peerjsServerPath = peerjsServerPath;\n orchestrator.peerjsServerSecure = peerjsServerSecure;\n\n const peerjsServerConfig = peerjsServerHost\n ? {\n host: peerjsServerHost,\n port: peerjsServerPort || undefined,\n path: peerjsServerPath || undefined,\n secure: peerjsServerSecure,\n }\n : {};\n\n orchestrator.peerjs.configure(\n peerjsMyPeerId,\n peerjsTrustedPeerIds,\n peerjsServerConfig,\n );\n}\n","export const DEFAULT_DIRECT_TOOL_COMMAND_POLICY: DirectToolCommandPolicy = {\n allowedTools: [\"clear_chat\", \"show_toast\"],\n enabledChannelTypes: [\"telegram\"],\n requireMention: true,\n};\n\nexport type ParsedDirectToolCommand = {\n input: Record<string, any>;\n toolName: string;\n};\n\nexport interface DirectToolCommandPolicy {\n allowedTools: string[];\n enabledChannelTypes: string[];\n requireMention: boolean;\n}\n","import {\n DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n type DirectToolCommandPolicy,\n} from \"./types.js\";\n\n/**\n * Parses a raw JSON string into a validated DirectToolCommandPolicy.\n * Falls back to the default policy on parse failure or missing input.\n */\nexport function parseDirectToolCommandPolicy(\n raw: string | null | undefined,\n): DirectToolCommandPolicy {\n if (!raw) {\n return {\n allowedTools: [...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools],\n enabledChannelTypes: [\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes,\n ],\n requireMention: DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n }\n\n try {\n const parsed = JSON.parse(raw) as Partial<DirectToolCommandPolicy>;\n\n const enabledChannelTypes = Array.isArray(parsed.enabledChannelTypes)\n ? parsed.enabledChannelTypes.filter(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n )\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes;\n\n const allowedTools = Array.isArray(parsed.allowedTools)\n ? parsed.allowedTools.filter(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n )\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools;\n\n return {\n allowedTools,\n enabledChannelTypes,\n requireMention:\n typeof parsed.requireMention === \"boolean\"\n ? parsed.requireMention\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n } catch {\n return {\n allowedTools: [...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools],\n enabledChannelTypes: [\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes,\n ],\n requireMention: DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n }\n}\n","import { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { submitMessage } from \"./operations/channel.js\";\nimport { syncProxyConfigToServiceWorker } from \"./syncProxyConfigToServiceWorker.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport function setupPushTaskListener(\n orchestrator: Orchestrator,\n _db: ShadowClawDatabase,\n): void {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n\n navigator.serviceWorker.addEventListener(\"message\", (event) => {\n if (event.data?.type === \"request-proxy-config\") {\n // The service worker just restarted and lost its in-memory proxy config.\n // Re-sync so fetch interception resumes immediately.\n syncProxyConfigToServiceWorker(orchestrator);\n\n return;\n }\n\n if (event.data?.type !== \"scheduled-task-trigger\") {\n return;\n }\n\n const { taskId, groupId, prompt, taskType, tools } = event.data;\n if (!groupId) {\n return;\n }\n\n // Mark this group as scheduler-triggered for recursion prevention\n orchestrator.schedulerTriggeredGroups.add(groupId);\n\n // Execute the task via the same path as client-side scheduler\n const runTaskHandler = async () => {\n const fullTask = orchestratorStore.tasks.find((t) => t.id === taskId);\n if (fullTask) {\n orchestratorStore.runTask(fullTask);\n\n return;\n }\n\n if (taskType === \"tools\" && Array.isArray(tools) && tools.length > 0) {\n orchestratorStore.runTask({\n id: taskId || `push-task-${Date.now()}`,\n groupId,\n createdAt: Date.now(),\n enabled: true,\n prompt: prompt || \"\",\n type: \"tools\",\n tools,\n lastRun: null,\n });\n\n return;\n }\n\n if (prompt) {\n // Fallback if not found in local store\n submitMessage(orchestrator, prompt, groupId);\n }\n };\n\n runTaskHandler()\n .catch((err) =>\n console.error(`Push-triggered task ${taskId} failed:`, err),\n )\n .finally(() => {\n orchestrator.schedulerTriggeredGroups.delete(groupId);\n });\n });\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n buildTriggerPattern,\n getDefaultProvider,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { deleteRoom, getRoomMetadata, upsertRoom } from \"../../../db/rooms.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\n\nimport { toTrustedScriptUrl } from \"../../../security/trusted-types.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { RoomManager } from \"../../../subsystems/channels/room-manager.js\";\nimport { setWebMcpMode as applyWebMcpMode } from \"../../../subsystems/mcp/webmcp.js\";\nimport { modelRegistry } from \"../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../subsystems/providers/prompt-api-provider.js\";\nimport { fetchTokenizerConfig } from \"../../../subsystems/providers/utils/chatTemplate.js\";\nimport { TaskScheduler } from \"../../../subsystems/tools/task-scheduler.js\";\nimport { enqueue } from \"./enqueue.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\nimport { loadChannelConfigurations } from \"./loadChannelConfigurations.js\";\nimport { applyAllChannelRunningStates } from \"./operations/channel.js\";\n\nimport {\n applyLlamafileHeaders,\n applyMeshLlmHeaders,\n getApiKeyForHeaders,\n getProviderRuntimeHeaders,\n} from \"./operations/provider.js\";\n\nimport { handleRoomInvite } from \"./operations/room.js\";\n\nimport {\n runTaskAsScheduled,\n shouldStartLocalScheduler,\n} from \"./operations/task.js\";\n\nimport { parseDirectToolCommandPolicy } from \"./parseDirectToolCommandPolicy.js\";\nimport { setupPushTaskListener } from \"./setupPushTaskListener.js\";\nimport { syncProxyConfigToServiceWorker } from \"./syncProxyConfigToServiceWorker.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { RoomTransport } from \"../../../subsystems/channels/room-manager.js\";\n\nimport type {\n InboundMessage,\n RoomMember,\n} from \"../../../subsystems/channels/types.js\";\n\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport function createRoomManager(orchestrator: Orchestrator): RoomManager {\n const transport: RoomTransport = {\n get myPeerId() {\n return orchestrator.peerjs.myPeerId || orchestrator.peerjsMyPeerId;\n },\n sendToPeer: (peerId, note) =>\n orchestrator.peerjs.sendRoomNotification(peerId, note),\n isConnected: (peerId) => orchestrator.peerjs.isPeerConnected(peerId),\n connectToPeer: (peerId) => orchestrator.peerjs.connectPeer(peerId),\n };\n\n return new RoomManager({\n transport,\n getLocalMember: (): RoomMember => ({\n peerId: orchestrator.peerjs.myPeerId || orchestrator.peerjsMyPeerId,\n alias:\n orchestrator.peerjsMyAlias ||\n orchestrator.peerjs.myPeerId ||\n orchestrator.peerjsMyPeerId ||\n orchestrator.assistantName,\n kind: \"agent\",\n agentName: orchestrator.assistantName,\n }),\n onMessage: (msg) => orchestrator.roomChannel.deliverInbound(msg),\n onInvite: (invite) => handleRoomInvite(orchestrator, invite),\n persistRoom: (room) => {\n if (orchestrator.db) {\n upsertRoom(orchestrator.db, room).catch((err) =>\n console.error(\"Failed to persist room:\", err),\n );\n }\n },\n removeRoom: (roomId) => {\n if (orchestrator.db) {\n deleteRoom(orchestrator.db, roomId).catch((err) =>\n console.error(\"Failed to delete room:\", err),\n );\n }\n },\n });\n}\n\nexport async function initChannelsAndRooms(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.initializeChannelRegistry();\n\n orchestrator.channelRegistry.onMessage((msg: InboundMessage) => {\n enqueue(orchestrator, db, msg).catch((error) => {\n console.error(\"Failed to enqueue inbound message:\", error);\n });\n });\n\n orchestrator.channelRegistry.onTyping((groupId: string, typing: boolean) => {\n orchestrator.events.emit(\"typing\", { groupId, typing });\n // Update remote agent typing status for peer channels\n if (groupId.startsWith(\"peer:\")) {\n orchestratorStore.setRemoteAgentTyping(groupId, typing);\n }\n });\n\n // A2A task completion: when a remote peer sends a terminal status update,\n // suppress further auto-triggers for that conversation.\n orchestrator.peerjs.onTaskComplete((groupId: string) => {\n orchestrator.peerCompletedContexts.add(groupId);\n });\n\n await loadChannelConfigurations(orchestrator, db);\n applyAllChannelRunningStates(orchestrator);\n\n // Restore persisted multi-party rooms\n try {\n const rooms = await getRoomMetadata(db);\n orchestrator.roomManager.loadRooms(rooms);\n } catch (err) {\n console.error(\"Failed to load rooms:\", err);\n }\n}\n\nexport async function initCoreConfig(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.assistantName =\n (await getConfig(db, CONFIG_KEYS.ASSISTANT_NAME)) || ASSISTANT_NAME;\n\n orchestrator.triggerPattern = buildTriggerPattern(orchestrator.assistantName);\n}\n\nexport async function initFeatureFlagsAndLimits(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n const storedVMBootMode = await getConfig(db, CONFIG_KEYS.VM_BOOT_MODE);\n orchestrator.vmBootMode =\n storedVMBootMode === \"disabled\" ||\n storedVMBootMode === \"auto\" ||\n storedVMBootMode === \"9p\" ||\n storedVMBootMode === \"ext2\"\n ? (storedVMBootMode as any)\n : \"disabled\";\n\n const storedStreaming = await getConfig(db, CONFIG_KEYS.STREAMING_ENABLED);\n orchestrator.streamingEnabled = storedStreaming !== \"false\";\n\n const storedWebMcpToolsEnabled = await getConfig(\n db,\n CONFIG_KEYS.WEBMCP_TOOLS_ENABLED,\n );\n\n orchestrator.webMcpToolsEnabled = storedWebMcpToolsEnabled !== \"false\";\n\n const storedBashFullInternetAccess = await getConfig(\n db,\n CONFIG_KEYS.VM_BASH_FULL_INTERNET_ACCESS,\n );\n\n orchestrator.vmBashFullInternetAccess =\n storedBashFullInternetAccess === \"true\";\n\n const storedWebMcpMode = await getConfig(db, CONFIG_KEYS.WEBMCP_MODE);\n if (storedWebMcpMode === \"native\" || storedWebMcpMode === \"polyfill\") {\n applyWebMcpMode(storedWebMcpMode);\n }\n\n const storedCompression = await getConfig(\n db,\n CONFIG_KEYS.CONTEXT_COMPRESSION_ENABLED,\n );\n\n orchestrator.contextCompressionEnabled = storedCompression === \"true\";\n\n const storedReasoningEffort = await getConfig(\n db,\n CONFIG_KEYS.REASONING_EFFORT,\n );\n orchestrator.reasoningEffort = storedReasoningEffort\n ? storedReasoningEffort.trim().toLowerCase()\n : \"none\";\n\n const storedDirectToolPolicy = await getConfig(\n db,\n CONFIG_KEYS.DIRECT_TOOL_COMMAND_POLICY,\n );\n\n orchestrator.directToolCommandPolicy = parseDirectToolCommandPolicy(\n storedDirectToolPolicy,\n );\n\n const storedUseProxy = await getConfig(db, CONFIG_KEYS.USE_PROXY);\n orchestrator.useProxy = storedUseProxy === \"true\";\n\n orchestrator.proxyUrl =\n (await getConfig(db, CONFIG_KEYS.PROXY_URL)) || \"/proxy\";\n orchestrator.gitProxyUrl =\n (await getConfig(db, CONFIG_KEYS.GIT_PROXY_URL)) || \"/git-proxy\";\n const storedTaskServerEnabled = await getConfig(\n db,\n CONFIG_KEYS.TASK_SERVER_ENABLED,\n );\n orchestrator.taskServerEnabled = storedTaskServerEnabled === \"true\";\n\n orchestrator.taskServerUrl =\n (await getConfig(db, CONFIG_KEYS.TASK_SERVER_URL)) ||\n (await import(\"../../../config/config.js\")).DEFAULT_TASK_SERVER_URL;\n}\n\nexport async function initLlamafileAndMesh(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n const storedLlamafileMode = await getConfig(db, CONFIG_KEYS.LLAMAFILE_MODE);\n if (storedLlamafileMode === \"cli\" || storedLlamafileMode === \"server\") {\n orchestrator.llamafileMode = storedLlamafileMode;\n } else {\n await setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, orchestrator.llamafileMode);\n }\n\n const storedLlamafileHost = await getConfig(db, CONFIG_KEYS.LLAMAFILE_HOST);\n if (storedLlamafileHost) {\n orchestrator.llamafileHost = storedLlamafileHost;\n }\n\n const storedLlamafilePort = await getConfig(db, CONFIG_KEYS.LLAMAFILE_PORT);\n if (storedLlamafilePort) {\n const parsedPort = parseInt(storedLlamafilePort, 10);\n if (Number.isFinite(parsedPort) && parsedPort >= 1 && parsedPort <= 65535) {\n orchestrator.llamafilePort = parsedPort;\n }\n }\n\n const storedLlamafileOffline = await getConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n );\n\n if (storedLlamafileOffline === \"false\") {\n orchestrator.llamafileOffline = false;\n }\n\n applyLlamafileHeaders(orchestrator);\n\n const storedmeshLlmHost = await getConfig(db, CONFIG_KEYS.MESH_LLM_HOST);\n if (storedmeshLlmHost) {\n orchestrator.meshLlmHost = storedmeshLlmHost;\n }\n\n applyMeshLlmHeaders(orchestrator);\n}\n\nexport async function initProviderAndModel(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Parallelize all independent IDB reads in this function.\n const [\n storedProvider,\n bedrockRegion,\n bedrockProfile,\n bedrockAuthMode,\n storedModel,\n storedMaxTokens,\n storedMaxIterations,\n storedRateLimitCallsPerMinute,\n storedRateLimitAutoAdapt,\n ] = await Promise.all([\n getConfig(db, CONFIG_KEYS.PROVIDER),\n getConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK),\n getConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK),\n getConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE),\n getConfig(db, CONFIG_KEYS.MODEL),\n getConfig(db, CONFIG_KEYS.MAX_TOKENS),\n getConfig(db, CONFIG_KEYS.MAX_ITERATIONS),\n getConfig(db, CONFIG_KEYS.RATE_LIMIT_CALLS_PER_MINUTE),\n getConfig(db, CONFIG_KEYS.RATE_LIMIT_AUTO_ADAPT),\n ]);\n\n if (storedProvider && getProvider(storedProvider)) {\n orchestrator.provider = storedProvider;\n orchestrator.providerConfig =\n getProvider(storedProvider) || getDefaultProvider();\n }\n\n // Load API key — must happen after provider is set.\n await orchestrator.loadApiKeyForProvider(db, orchestrator.provider);\n\n orchestrator.bedrockRegionFallback = (bedrockRegion || \"\").trim();\n orchestrator.bedrockProfileFallback = (bedrockProfile || \"\").trim();\n orchestrator.bedrockAuthMode = (bedrockAuthMode || \"provider_chain\").trim();\n\n // Fetch model info in the background. While primarily used to populate\n // the model picker in Settings, it is also required to dynamically resolve\n // optimal max_tokens limits for scheduled jobs and background tasks.\n // We defer it until the browser is idle to ensure it doesn't block first paint.\n const scheduleFetch = () => {\n const doFetch = () => {\n void getApiKeyForHeaders(orchestrator).then((apiKey) =>\n modelRegistry.fetchModelInfo(\n orchestrator.providerConfig,\n apiKey || undefined,\n getProviderRuntimeHeaders(orchestrator, orchestrator.provider),\n ),\n );\n };\n\n if (typeof (globalThis as any).requestIdleCallback === \"function\") {\n (globalThis as any).requestIdleCallback(doFetch, { timeout: 5000 });\n } else {\n setTimeout(doFetch, 2000);\n }\n };\n\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n if (document.readyState === \"complete\") {\n scheduleFetch();\n } else {\n window.addEventListener(\"load\", scheduleFetch, { once: true });\n }\n } else {\n scheduleFetch();\n }\n\n if (storedModel) {\n orchestrator.model = storedModel;\n } else {\n orchestrator.model = orchestrator.providerConfig.defaultModel;\n }\n\n let effectiveMaxTokensModel = orchestrator.model;\n if (\n orchestrator.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (orchestrator.model === \"browser-built-in\" || !orchestrator.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveMaxTokensModel =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n fetchTokenizerConfig(effectiveMaxTokensModel).catch(() => {});\n }\n\n const dynamicMaxTokens = getModelMaxTokens(effectiveMaxTokensModel);\n\n // If the stored value is exactly 8192 (our legacy fallback) or 4096 (legacy prompt_api default),\n // prioritize the dynamic value from our registry and updated limits definitions.\n if (\n storedMaxTokens === \"8192\" ||\n (orchestrator.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n storedMaxTokens === \"4096\")\n ) {\n orchestrator.maxTokens = dynamicMaxTokens;\n } else {\n const parsedStored = parseInt(\n storedMaxTokens || String(dynamicMaxTokens),\n 10,\n );\n\n orchestrator.maxTokens = Math.max(1, parsedStored);\n }\n\n if (storedMaxIterations) {\n orchestrator.maxIterations =\n parseInt(storedMaxIterations, 10) || DEFAULT_MAX_ITERATIONS;\n }\n\n if (storedRateLimitCallsPerMinute) {\n const parsed = parseInt(storedRateLimitCallsPerMinute, 10);\n orchestrator.rateLimitCallsPerMinute = Number.isFinite(parsed)\n ? Math.max(0, parsed)\n : 0;\n }\n\n orchestrator.rateLimitAutoAdapt = storedRateLimitAutoAdapt !== \"false\";\n}\n\nexport async function initWorkerAndScheduler(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.agentWorker = new Worker(\n toTrustedScriptUrl(\n new URL(\"./agent.worker.js\", import.meta.url).href,\n ) as string,\n {\n type: \"module\",\n },\n );\n\n orchestrator.agentWorker.onmessage = (event) =>\n handleWorkerMessage(orchestrator, db, event.data);\n\n orchestrator.agentWorker.onerror = (err) => {\n console.error(\"Agent worker error:\", err);\n };\n\n const storageHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n if (storageHandle) {\n orchestrator.agentWorker.postMessage({\n payload: { storageHandle },\n type: \"set-storage\",\n });\n }\n\n // Sync proxy config to Service Worker\n syncProxyConfigToServiceWorker(orchestrator);\n\n // Set up task scheduler.\n // When push scheduling is available, the server-side scheduler should be\n // authoritative. The local client scheduler is only used as a fallback\n // when push background execution is unavailable.\n orchestrator.scheduler = new TaskScheduler(\n async (task) => {\n await runTaskAsScheduled(orchestrator, task);\n },\n () => {\n orchestrator.events.emit(\"task-change\", { type: \"executed\" });\n },\n );\n\n // Start the task scheduler in the background — shouldStartLocalScheduler()\n // is an async IDB read that doesn't need to block UI readiness.\n // The scheduler starting one microtask-tick late is harmless because no\n // scheduled task can fire before the app is fully initialized anyway.\n void shouldStartLocalScheduler().then((should) => {\n if (should) {\n orchestrator.scheduler?.start();\n }\n });\n\n setupPushTaskListener(orchestrator, db);\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_GROUP_ID,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_MAX_TOKENS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n DEFAULT_PROVIDER,\n DEFAULT_TASK_SERVER_ENABLED,\n ProviderConfig,\n buildTriggerPattern,\n getDefaultProvider,\n getProvider,\n getProviderApiKeyConfigKey,\n getModelMaxTokens,\n} from \"../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../context/estimateTokens.js\";\nimport { buildConversationMessages } from \"../../db/buildConversationMessages.js\";\nimport { clearGroupMessages } from \"../../db/clearGroupMessages.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { listGroups } from \"../../db/groups.js\";\nimport { openDatabase } from \"../../db/openDatabase.js\";\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\nimport { saveMessage } from \"../../db/saveMessage.js\";\nimport { setConfig } from \"../../db/setConfig.js\";\nimport { decryptValue, encryptValue } from \"../../security/crypto.js\";\nimport { VMBootMode, VMStatus } from \"../../shell/vm.js\";\nimport { readGroupFile } from \"../../storage/readGroupFile.js\";\n\nimport {\n OrchestratorDisplayState,\n orchestratorStore,\n} from \"../../stores/orchestrator.js\";\n\nimport { toolsStore } from \"../../stores/tools.js\";\nimport { BrowserChatChannel } from \"../../subsystems/channels/browser-chat.js\";\nimport { ChannelRegistry } from \"../../subsystems/channels/channel-registry.js\";\nimport { IMessageChannel } from \"../../subsystems/channels/imessage.js\";\nimport { PeerJsChannel } from \"../../subsystems/channels/peerjs.js\";\nimport { RoomManager } from \"../../subsystems/channels/room-manager.js\";\nimport { RoomChannel } from \"../../subsystems/channels/room.js\";\nimport { TelegramChannel } from \"../../subsystems/channels/telegram.js\";\n\nimport { unregisterWebMcpTools } from \"../../subsystems/mcp/webmcp.js\";\nimport { isPromptApiSupported } from \"../../subsystems/providers/prompt-api-provider.js\";\n\nimport { getContextLimit } from \"../../subsystems/providers/providers.js\";\nimport { TaskScheduler } from \"../../subsystems/tools/task-scheduler.js\";\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/formatA2UIActionPrompt.js\";\nimport { ulid } from \"../../utils/ulid.js\";\nimport { buildSystemPrompt } from \"../../worker/utils/system-prompt.js\";\nimport { Router } from \"../router.js\";\nimport { enqueue } from \"./utils/enqueue.js\";\nimport { EventBus } from \"./utils/EventBus.js\";\n\nimport {\n createRoomManager,\n initChannelsAndRooms,\n initCoreConfig,\n initFeatureFlagsAndLimits,\n initLlamafileAndMesh,\n initProviderAndModel,\n initWorkerAndScheduler,\n} from \"./utils/initTasks.js\";\n\nimport { invokeAgent } from \"./utils/invokeAgent.js\";\n\nimport {\n cancelLlamafileRequest,\n stopTransformersProgressPolling,\n} from \"./utils/operations/provider.js\";\n\nimport { syncWebMcpRegistration } from \"./utils/syncWebMcpRegistration.js\";\nimport { DEFAULT_DIRECT_TOOL_COMMAND_POLICY } from \"./utils/types.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/db.js\";\nimport type { A2UIAction } from \"../../ui/a2ui/types.js\";\nimport type { DirectToolCommandPolicy } from \"./utils/types.js\";\n\nexport class Orchestrator {\n agentWorker: Worker | null = null;\n assistantName: string = ASSISTANT_NAME;\n\n bedrockAuthMode: string = \"provider_chain\";\n bedrockProfileFallback: string = \"\";\n bedrockRegionFallback: string = \"\";\n\n browserChat: BrowserChatChannel = new BrowserChatChannel();\n\n channelEnabledByType: Record<string, boolean> = {\n browser: true,\n peerjs: false,\n telegram: false,\n imessage: false,\n };\n\n channelRegistry: ChannelRegistry = new ChannelRegistry();\n contextCompressionEnabled: boolean = false;\n\n db: ShadowClawDatabase | null = null;\n directToolCommandPolicy: DirectToolCommandPolicy = {\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n };\n\n events: EventBus = new EventBus();\n gitProxyUrl: string = \"/git-proxy\";\n\n imessage: IMessageChannel = new IMessageChannel();\n imessageApiKey: string = \"\";\n imessageChatIds: string[] = [];\n imessageServerUrl: string = \"\";\n\n inFlightEffectiveProviderByGroup: Map<\n string,\n {\n providerId: string;\n providerConfig: ProviderConfig;\n model: string;\n }\n > = new Map();\n\n inFlightProviderRequestIds: Map<string, string> = new Map();\n inFlightTriggerByGroup: Map<string, string> = new Map();\n\n llamafileHost: string = \"127.0.0.1\";\n llamafileMode: \"server\" | \"cli\" = \"cli\";\n llamafileOffline: boolean = true;\n llamafilePort: number = 8080;\n\n maxIterations: number = DEFAULT_MAX_ITERATIONS;\n maxTokens: number = DEFAULT_MAX_TOKENS;\n\n meshLlmHost: string = \"\";\n\n messageQueue: any[] = [];\n model: string = getDefaultProvider().defaultModel;\n\n /** Peer groupIds where the A2A task has reached a terminal state */\n peerCompletedContexts = new Set<string>();\n peerjs: PeerJsChannel = new PeerJsChannel();\n peerjsMyAlias: string = \"\";\n peerjsMyPeerId: string = \"\";\n peerjsPeerAliases: Record<string, string> = {};\n peerjsServerHost: string = \"\";\n peerjsServerPath: string = \"\";\n peerjsServerPort: number = 0;\n peerjsServerSecure: boolean = true;\n peerjsTrustedPeerIds: string[] = [];\n\n pendingScheduledTasks: Set<string> = new Set();\n processing: boolean = false;\n promptControllers: Map<string, AbortController> = new Map();\n\n provider: string = DEFAULT_PROVIDER;\n providerConfig: ProviderConfig = getDefaultProvider();\n\n proxyUrl: string = \"/proxy\";\n pushSubscriptionWarned: boolean = false;\n rateLimitAutoAdapt: boolean = true;\n\n rateLimitCallsPerMinute: number = 0;\n reasoningEffort: string = \"none\";\n\n /** Multi-party room channel + manager (layered on the PeerJS transport). */\n roomChannel: RoomChannel = new RoomChannel();\n roomManager!: RoomManager;\n\n router: Router | null = null;\n\n scheduler: TaskScheduler | null = null;\n schedulerTriggeredGroups: Set<string> = new Set();\n\n state: OrchestratorDisplayState = \"idle\";\n streamingEnabled: boolean = true;\n taskServerEnabled: boolean = DEFAULT_TASK_SERVER_ENABLED;\n taskServerUrl: string = \"/schedule\";\n\n telegram: TelegramChannel = new TelegramChannel();\n telegramBotToken: string = \"\";\n telegramChatIds: string[] = [];\n telegramUseProxy: boolean = false;\n\n transformersProgressPollers: Map<string, number> = new Map();\n triggerPattern: RegExp = buildTriggerPattern(ASSISTANT_NAME);\n useProxy: boolean = false;\n\n vmBashFullInternetAccess: boolean = false;\n vmBootMode: VMBootMode = \"disabled\";\n vmStatus: VMStatus = {\n ready: false,\n booting: false,\n bootAttempted: false,\n error: null,\n };\n\n webMcpEffectCleanup: (() => void) | null = null;\n webMcpRegistrationLock: Promise<void> = Promise.resolve();\n webMcpToolsEnabled: boolean = true;\n\n #apiKeyCache: { value: string; expiresAt: number } | null = null;\n #encryptedApiKey: string | null = null;\n\n constructor() {\n this.roomManager = createRoomManager(this);\n this.initializeChannelRegistry();\n }\n\n clearProviderRequest(groupId: string): void {\n this.inFlightProviderRequestIds.delete(groupId);\n }\n\n createProviderRequestId(groupId: string): string {\n if (this.provider !== \"llamafile\") {\n this.inFlightProviderRequestIds.delete(groupId);\n\n return \"\";\n }\n\n const requestId = `${groupId}:${Date.now().toString(36)}:${Math.random()\n .toString(36)\n .slice(2, 10)}`;\n\n this.inFlightProviderRequestIds.set(groupId, requestId);\n\n return requestId;\n }\n\n initializeChannelRegistry(): void {\n this.channelRegistry = new ChannelRegistry();\n this.channelRegistry.register(\"br:\", this.browserChat, {\n badge: \"Browser\",\n autoTrigger: true,\n });\n\n this.channelRegistry.register(\"tg:\", this.telegram, {\n badge: \"Telegram\",\n autoTrigger: false,\n });\n\n this.channelRegistry.register(\"im:\", this.imessage, {\n badge: \"iMessage\",\n autoTrigger: true,\n });\n\n this.channelRegistry.register(\"peer:\", this.peerjs, {\n badge: \"PeerJS\",\n autoTrigger: false,\n });\n\n this.channelRegistry.register(\"room:\", this.roomChannel, {\n badge: \"Room\",\n autoTrigger: false,\n });\n\n this.roomChannel.setManager(this.roomManager);\n this.peerjs.setRoomNotificationHandler((from, method, params) =>\n this.roomManager.handleNotification(from, method, params),\n );\n\n this.router = new Router(this.channelRegistry);\n }\n\n setState(state: OrchestratorDisplayState, groupId?: string): void {\n this.state = state;\n this.events.emit(\"state-change\", { state, groupId });\n }\n\n /**\n * Shut down everything\n */\n shutdown() {\n this.channelRegistry.stopAll();\n this.scheduler?.stop();\n\n for (const groupId of this.transformersProgressPollers.keys()) {\n stopTransformersProgressPolling(this, groupId);\n }\n\n this.agentWorker?.terminate();\n\n if (typeof this.webMcpEffectCleanup === \"function\") {\n this.webMcpEffectCleanup();\n }\n\n unregisterWebMcpTools();\n }\n\n stopCurrentRequest(groupId = DEFAULT_GROUP_ID): void {\n if (this.state !== \"thinking\" && this.state !== \"responding\") {\n return;\n }\n\n stopTransformersProgressPolling(this, groupId);\n const providerRequestId =\n this.inFlightProviderRequestIds.get(groupId) || \"\";\n this.clearProviderRequest(groupId);\n\n this.agentWorker?.postMessage({\n type: \"cancel\",\n payload: { groupId },\n });\n\n if (this.provider === \"llamafile\" && providerRequestId) {\n void cancelLlamafileRequest(providerRequestId);\n }\n\n const promptController = this.promptControllers.get(groupId);\n if (promptController) {\n promptController.abort();\n\n this.promptControllers.delete(groupId);\n }\n\n this.inFlightTriggerByGroup.delete(groupId);\n this.inFlightEffectiveProviderByGroup.delete(groupId);\n\n this.events.emit(\"typing\", { groupId, typing: false });\n this.router?.setTyping(groupId, false);\n this.setState(\"idle\", groupId);\n }\n\n async getApiKey(): Promise<string | null> {\n if (!this.#encryptedApiKey) {\n return null;\n }\n\n const now = Date.now();\n if (this.#apiKeyCache && this.#apiKeyCache.expiresAt > now) {\n return this.#apiKeyCache.value;\n }\n\n try {\n const decrypted = await decryptValue(this.#encryptedApiKey);\n if (decrypted === null) {\n return null;\n }\n\n this.#apiKeyCache = {\n expiresAt: now + 30000, // 30s TTL\n value: decrypted,\n };\n\n return decrypted;\n } catch (e) {\n console.error(\"[Orchestrator] Failed to decrypt API key:\", e);\n\n return null;\n }\n }\n\n async getApiKeyForSpecificProvider(\n db: ShadowClawDatabase,\n providerId: string,\n ): Promise<string> {\n let storedKey = await getConfig(db, getProviderApiKeyConfigKey(providerId));\n\n if (!storedKey && providerId === \"openrouter\") {\n const legacyKey = await getConfig(db, CONFIG_KEYS.API_KEY);\n if (legacyKey) {\n storedKey = legacyKey;\n }\n }\n\n if (!storedKey) {\n return \"\";\n }\n\n try {\n const decrypted = await decryptValue(storedKey);\n\n return decrypted || \"\";\n } catch (e) {\n console.error(\"[Orchestrator] Failed to decrypt API key:\", e);\n\n return \"\";\n }\n }\n\n async handleCompactDone(\n db: ShadowClawDatabase,\n groupId: string,\n summary: string,\n ): Promise<void> {\n await clearGroupMessages(db, groupId);\n\n const stored = {\n channel: this.channelRegistry.getChannelType(groupId) ?? \"browser\",\n content: `📝 **Context Compacted**\\n\\n${summary}`,\n groupId,\n id: ulid(),\n isFromMe: true,\n isTrigger: false,\n sender: this.assistantName,\n timestamp: Date.now(),\n };\n\n await saveMessage(db, stored);\n\n this.events.emit(\"context-compacted\", { groupId, summary });\n this.events.emit(\"typing\", { groupId, typing: false });\n\n this.setState(\"idle\", groupId);\n }\n\n async init(): Promise<ShadowClawDatabase> {\n const db = await openDatabase();\n this.db = db;\n\n // Fast parallel path: these four functions only read from IndexedDB and are\n // fully independent of each other. Running them concurrently saves ~200–400 ms\n // compared to the previous sequential await chain.\n await Promise.all([\n initCoreConfig(this, db),\n initProviderAndModel(this, db),\n initLlamafileAndMesh(this, db),\n initFeatureFlagsAndLimits(this, db),\n ]);\n\n // Worker + scheduler need provider/model/flags to be ready, so they still\n // start synchronously after the parallel group above.\n await initWorkerAndScheduler(this, db);\n\n // Channels/rooms are deferred to a background microtask so the UI reaches\n // \"ready\" without waiting for room metadata reads or peer-channel setup.\n // browserChat.onDisplay is called after channels are configured.\n void initChannelsAndRooms(this, db).then(() => {\n this.browserChat.onDisplay(() => {});\n });\n\n this.events.emit(\"ready\", undefined);\n\n await toolsStore.load(db);\n // syncWebMcpRegistration only installs an effect listener; it is safe to\n // call before channels are fully ready because it reacts reactively.\n syncWebMcpRegistration(this, db);\n\n return db;\n }\n\n /**\n * Load the API key for a provider into memory.\n */\n async loadApiKeyForProvider(\n db: ShadowClawDatabase,\n providerId: string,\n ): Promise<void> {\n let storedKey = await getConfig(db, getProviderApiKeyConfigKey(providerId));\n\n if (!storedKey && providerId === \"openrouter\") {\n const legacyKey = await getConfig(db, CONFIG_KEYS.API_KEY);\n if (legacyKey) {\n storedKey = legacyKey;\n await setConfig(db, getProviderApiKeyConfigKey(providerId), legacyKey);\n }\n }\n\n if (!storedKey) {\n this.#encryptedApiKey = \"\";\n } else {\n try {\n // We now store the encrypted key directly in the field.\n // decryptValue is only called on-demand.\n this.#encryptedApiKey = storedKey;\n } catch (e) {\n console.warn(\"[Orchestrator] Failed to load API key:\", e);\n\n this.#encryptedApiKey = \"\";\n }\n }\n\n this.#apiKeyCache = null; // Invalidate cache\n }\n\n async loadSecretConfig(db: ShadowClawDatabase, key: string): Promise<string> {\n const storedValue = await getConfig(db, key);\n if (!storedValue) {\n return \"\";\n }\n\n try {\n return (await decryptValue(storedValue)) || \"\";\n } catch {\n const encrypted = await encryptValue(storedValue);\n if (encrypted) {\n await setConfig(db, key, encrypted);\n }\n\n return storedValue;\n }\n }\n\n async newSession(\n db: ShadowClawDatabase,\n groupId = DEFAULT_GROUP_ID,\n ): Promise<void> {\n await clearGroupMessages(db, groupId);\n\n this.events.emit(\"session-reset\", { groupId });\n }\n\n /**\n * Recompute and emit context usage for the given conversation.\n * Useful after message mutation operations (for example delete) so the\n * context bar updates without waiting for the next model invocation.\n */\n async refreshContextUsage(\n db: ShadowClawDatabase,\n groupId = DEFAULT_GROUP_ID,\n ): Promise<void> {\n let memory = \"\";\n try {\n memory = await readGroupFile(db, groupId, \"MEMORY.md\");\n } catch {\n // No memory file yet.\n }\n\n const activeTools = toolsStore.enabledTools;\n const peerState = orchestratorStore.getPeerState(groupId) || undefined;\n const systemPrompt = buildSystemPrompt(\n this.assistantName,\n memory,\n activeTools,\n toolsStore.systemPromptOverride,\n peerState,\n );\n\n const groups = await listGroups(db);\n const group = groups.find((g) => g.groupId === groupId);\n\n const effectiveModel =\n group?.pinnedModel ??\n (group?.pinnedProvider\n ? (getProvider(group.pinnedProvider)?.defaultModel ?? this.model)\n : this.model);\n\n let modelForTokenLimits = effectiveModel;\n if (\n (group?.pinnedProvider ?? this.provider) === \"prompt_api\" &&\n (effectiveModel === \"browser-built-in\" || !effectiveModel) &&\n !isPromptApiSupported()\n ) {\n const configuredFallback = await getConfig(\n this.db!,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n modelForTokenLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n const configuredMaxTokens =\n typeof group?.pinnedMaxTokens === \"number\" &&\n Number.isFinite(group.pinnedMaxTokens) &&\n group.pinnedMaxTokens > 0\n ? Math.floor(group.pinnedMaxTokens)\n : this.maxTokens;\n\n const effectiveMaxTokens = Math.max(\n 1,\n Math.min(configuredMaxTokens, getModelMaxTokens(modelForTokenLimits)),\n );\n\n const contextLimit = getContextLimit(modelForTokenLimits);\n const systemPromptTokens =\n estimateTokens(systemPrompt) +\n (activeTools?.reduce(\n (acc, t) => acc + estimateTokens(JSON.stringify(t)),\n 0,\n ) ?? 0);\n const allMessages = await buildConversationMessages(groupId, 200);\n const dynamicContext = buildDynamicContext(allMessages, {\n contextLimit,\n systemPromptTokens,\n maxOutputTokens: effectiveMaxTokens,\n skimTop: this.contextCompressionEnabled,\n });\n\n let displayTokens = dynamicContext.estimatedTokens + systemPromptTokens;\n\n // If we have actual token usage from the most recent request,\n // and our heuristic is significantly lower, blend it in to provide a more accurate percentage.\n if (orchestratorStore.tokenUsage) {\n const u = orchestratorStore.tokenUsage;\n const actualPrompt =\n (u.inputTokens || 0) + (u.cacheReadTokens || 0) + (u.outputTokens || 0);\n\n displayTokens = Math.max(displayTokens, actualPrompt);\n }\n\n this.events.emit(\"context-usage\", {\n estimatedTokens: displayTokens,\n contextLimit,\n usagePercent: Math.min(\n 100,\n Math.max(\n dynamicContext.usagePercent,\n (displayTokens / contextLimit) * 100,\n ),\n ),\n truncatedCount: dynamicContext.truncatedCount,\n });\n }\n\n async restartCurrentRequest(groupId = DEFAULT_GROUP_ID): Promise<boolean> {\n if (this.state !== \"thinking\" && this.state !== \"responding\") {\n return false;\n }\n\n if (!this.db) {\n return false;\n }\n\n const triggerContent = this.inFlightTriggerByGroup.get(groupId);\n if (!triggerContent) {\n return false;\n }\n\n this.stopCurrentRequest(groupId);\n\n await invokeAgent(this, this.db, groupId, triggerContent);\n\n return true;\n }\n\n /**\n * Route a user interaction on a **shared room surface** (owner-authoritative).\n *\n * - If the local peer owns the surface (it called `render_component`), the\n * action is enqueued locally so this peer's agent processes it and\n * broadcasts the resulting `updateDataModel` envelope to the room.\n * - Otherwise the action is broadcast over the room mesh so the surface\n * owner's agent can process it. The owner then broadcasts the data-model\n * update, keeping every member's surface in lockstep.\n */\n async routeRoomA2UIAction(\n groupId: string,\n action: A2UIAction,\n ): Promise<void> {\n const roomId = roomIdFromGroupId(groupId);\n const myPeerId = this.peerjs.myPeerId || this.peerjsMyPeerId;\n const ownerPeerId = this.roomManager.getSurfaceOwner(action.surfaceId);\n\n // We own the surface (or no owner is recorded yet — treat a locally\n // initiated action on an unknown surface as ours): process it here.\n if (!ownerPeerId || ownerPeerId === myPeerId) {\n if (!this.db) {\n return;\n }\n\n await enqueue(this, this.db, {\n id: ulid(),\n groupId,\n sender: this.peerjsMyAlias || myPeerId || \"you\",\n content: formatA2UIActionPrompt(action),\n timestamp: Date.now(),\n channel: \"room\",\n a2uiAction: action,\n });\n\n return;\n }\n\n // A remote peer owns the surface — broadcast the action to the room so the\n // owner's agent processes it and synchronizes everyone.\n this.roomManager.broadcastA2UIAction(roomId, action);\n }\n\n async saveSecretConfig(\n db: ShadowClawDatabase,\n key: string,\n value: string,\n ): Promise<void> {\n if (!value) {\n await setConfig(db, key, \"\");\n\n return;\n }\n\n const encrypted = await encryptValue(value);\n if (!encrypted) {\n throw new Error(`Failed to encrypt secret config for ${key}`);\n }\n\n await setConfig(db, key, encrypted);\n }\n\n async setApiKey(db: ShadowClawDatabase, key: string): Promise<void> {\n this.#encryptedApiKey = await encryptValue(key);\n\n // Invalidate cache\n this.#apiKeyCache = null;\n\n const encrypted = await encryptValue(key);\n\n if (!encrypted) {\n throw new Error(\"key failed to encrypt. config cannot set.\");\n }\n\n await setConfig(db, getProviderApiKeyConfigKey(this.provider), encrypted);\n }\n\n submitMessage(text: string, groupId: string = DEFAULT_GROUP_ID): void {\n this.browserChat.submit(text, groupId);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"orchestrator-CACLa_Ro.js","names":["sleep","extractMarkdownAttachments","normalizeAttachmentPath","#finalizeOpenAI","#finalizeAnthropic","#pushOpenAI","#pushAnthropic","#anthropicBlocks","#sanitize","#openaiText","#openaiReasoningText","#openaiToolCalls","#encryptedApiKey","#apiKeyCache"],"sources":["../../src/db/migrateLegacyDatabase.ts","../../src/storage/migrateLegacyOpfs.ts","../../src/db/openDatabase.ts","../../src/subsystems/channels/browser-chat.ts","../../src/subsystems/channels/channel-registry.ts","../../src/subsystems/channels/imessage.ts","../../src/subsystems/channels/room.ts","../../src/subsystems/channels/telegram.ts","../../src/ui/a2ui/utils/formatA2UIActionPrompt.ts","../../src/core/router.ts","../../src/subsystems/providers/litert-lm-provider.ts","../../src/subsystems/providers/transformers-js-provider.ts","../../src/worker/utils/createTokenUsageMessage.ts","../../src/worker/utils/log.ts","../../src/worker/utils/parseSSEStream.ts","../../src/worker/utils/rate-limit.ts","../../src/worker/StreamAccumulator/StreamAccumulator.ts","../../src/worker/utils/tool-state.ts","../../src/worker/utils/handleInvoke.ts","../../src/core/orchestrator/utils/dispatchSubagentInvoke.ts","../../src/core/orchestrator/utils/invokeAgent.ts","../../src/core/orchestrator/utils/parseDirectToolCommand.ts","../../src/subsystems/skills/parseSkillCommand.ts","../../src/core/orchestrator/utils/enqueue.ts","../../src/core/orchestrator/utils/EventBus.ts","../../src/subsystems/channels/room-manager.ts","../../src/db/getEnabledTasks.ts","../../src/subsystems/tools/cron.ts","../../src/subsystems/tools/task-scheduler.ts","../../src/core/orchestrator/utils/parseStoredStringList.ts","../../src/core/orchestrator/utils/loadChannelConfigurations.ts","../../src/core/orchestrator/utils/types.ts","../../src/core/orchestrator/utils/parseDirectToolCommandPolicy.ts","../../src/core/orchestrator/utils/setupPushTaskListener.ts","../../src/core/orchestrator/utils/initTasks.ts","../../src/core/orchestrator/orchestrator.ts"],"sourcesContent":["import { CONFIG_KEYS, LEGACY_DB_NAME } from \"../config/config.js\";\nimport { getConfig } from \"./getConfig.js\";\nimport { setConfig } from \"./setConfig.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Perform a one-time migration from the legacy unnamespaced database \"shadowclaw\"\n * to the new namespaced database if not already done.\n */\nexport async function migrateLegacyDatabase(\n targetDb: ShadowClawDatabase,\n): Promise<void> {\n if (!targetDb || targetDb.name === LEGACY_DB_NAME) {\n return;\n }\n\n try {\n const alreadyMigrated = await getConfig(\n targetDb,\n CONFIG_KEYS.DB_MIGRATED_FROM_LEGACY,\n );\n if (alreadyMigrated === \"true\") {\n return;\n }\n } catch {\n // ignore read error\n }\n\n try {\n const legacyDb = await new Promise<ShadowClawDatabase | null>((resolve) => {\n const req = indexedDB.open(LEGACY_DB_NAME);\n req.onsuccess = () => {\n const db = req.result;\n if (!db.objectStoreNames || db.objectStoreNames.length === 0) {\n db.close();\n resolve(null);\n\n return;\n }\n resolve(db);\n };\n req.onerror = () => resolve(null);\n });\n\n if (legacyDb) {\n const storeNames = Array.from(legacyDb.objectStoreNames).filter((name) =>\n targetDb.objectStoreNames.contains(name),\n );\n\n for (const storeName of storeNames) {\n await new Promise<void>((resolve) => {\n try {\n const readTx = legacyDb.transaction(storeName, \"readonly\");\n const readStore = readTx.objectStore(storeName);\n const getAllReq = readStore.getAll();\n\n getAllReq.onsuccess = () => {\n const items: any[] = getAllReq.result || [];\n if (items.length > 0) {\n try {\n const writeTx = targetDb.transaction(storeName, \"readwrite\");\n const writeStore = writeTx.objectStore(storeName);\n for (const item of items) {\n writeStore.put(item);\n }\n writeTx.oncomplete = () => resolve();\n writeTx.onerror = () => resolve();\n writeTx.onabort = () => resolve();\n } catch {\n resolve();\n }\n } else {\n resolve();\n }\n };\n getAllReq.onerror = () => resolve();\n } catch {\n resolve();\n }\n });\n }\n\n legacyDb.close();\n }\n } catch (err) {\n console.warn(\"Legacy IndexedDB migration warning:\", err);\n } finally {\n try {\n await setConfig(targetDb, CONFIG_KEYS.DB_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n }\n}\n","import { CONFIG_KEYS, LEGACY_OPFS_ROOT } from \"../config/config.js\";\nimport { getConfig } from \"../db/getConfig.js\";\nimport { setConfig } from \"../db/setConfig.js\";\nimport { getOpfsRootDirName } from \"./storage.js\";\nimport { writeFileHandle, writeOpfsPathViaWorker } from \"./writeFileHandle.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Recursively copy entries from a source OPFS directory to a target OPFS directory.\n */\nasync function copyOpfsEntriesRecursively(\n sourceDir: FileSystemDirectoryHandle,\n targetDir: FileSystemDirectoryHandle,\n pathSegments: string[],\n): Promise<void> {\n for await (const [name, handle] of (sourceDir as any).entries()) {\n if (handle.kind === \"directory\") {\n const nextTargetDir = await targetDir.getDirectoryHandle(name, {\n create: true,\n });\n await copyOpfsEntriesRecursively(handle, nextTargetDir, [\n ...pathSegments,\n name,\n ]);\n } else if (handle.kind === \"file\") {\n const file = await handle.getFile();\n const targetFileHandle = await targetDir.getFileHandle(name, {\n create: true,\n });\n\n try {\n await writeFileHandle(targetFileHandle, file);\n } catch (writeErr) {\n const message =\n writeErr instanceof Error ? writeErr.message : String(writeErr);\n const needsOpfsWorkerFallback = message.includes(\n \"Writable file streams are not supported\",\n );\n\n if (!needsOpfsWorkerFallback) {\n throw writeErr;\n }\n\n await writeOpfsPathViaWorker([...pathSegments, name], file);\n }\n }\n }\n}\n\n/**\n * Perform a one-time migration of OPFS workspace files and directories from the\n * legacy unnamespaced root directory (\"shadowclaw\") to the active namespaced\n * deployment root directory if not already done.\n */\nexport async function migrateLegacyOpfs(db: ShadowClawDatabase): Promise<void> {\n if (!db) {\n return;\n }\n\n try {\n const alreadyMigrated = await getConfig(\n db,\n CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY,\n );\n if (alreadyMigrated === \"true\") {\n return;\n }\n } catch {\n // ignore read error\n }\n\n const targetRootName = getOpfsRootDirName();\n if (targetRootName === LEGACY_OPFS_ROOT) {\n return;\n }\n\n if (\n typeof navigator === \"undefined\" ||\n !navigator.storage ||\n typeof navigator.storage.getDirectory !== \"function\"\n ) {\n return;\n }\n\n try {\n const opfsRoot = await navigator.storage.getDirectory();\n let legacyRootHandle: FileSystemDirectoryHandle;\n\n try {\n legacyRootHandle = await opfsRoot.getDirectoryHandle(LEGACY_OPFS_ROOT);\n } catch {\n // Legacy OPFS folder does not exist (fresh installation or already cleaned up)\n try {\n await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n return;\n }\n\n const targetRootHandle = await opfsRoot.getDirectoryHandle(targetRootName, {\n create: true,\n });\n\n await copyOpfsEntriesRecursively(legacyRootHandle, targetRootHandle, [\n targetRootName,\n ]);\n } catch (err) {\n console.warn(\"Legacy OPFS migration warning:\", err);\n } finally {\n try {\n await setConfig(db, CONFIG_KEYS.OPFS_MIGRATED_FROM_LEGACY, \"true\");\n } catch {\n // ignore write error\n }\n }\n}\n","import { DB_VERSION, getDbName } from \"../config/config.js\";\nimport { setDB } from \"./db.js\";\nimport { migrateLegacyDatabase } from \"./migrateLegacyDatabase.js\";\nimport { migrateLegacyOpfs } from \"../storage/migrateLegacyOpfs.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\n\n/**\n * Open (or create) the IndexedDB database.\n */\nexport function openDatabase(): Promise<ShadowClawDatabase> {\n return new Promise(async (resolve, reject) => {\n let db: ShadowClawDatabase;\n\n const dbName = getDbName();\n const request = indexedDB.open(dbName, DB_VERSION);\n\n request.onupgradeneeded = () => {\n const database = request.result;\n\n // Messages store\n if (!database.objectStoreNames.contains(\"messages\")) {\n const msgStore = database.createObjectStore(\"messages\", {\n keyPath: \"id\",\n });\n msgStore.createIndex(\"by-group-time\", [\"groupId\", \"timestamp\"]);\n msgStore.createIndex(\"by-group\", \"groupId\");\n }\n\n // Sessions store (conversation state per group)\n if (!database.objectStoreNames.contains(\"sessions\")) {\n database.createObjectStore(\"sessions\", { keyPath: \"groupId\" });\n }\n\n // Tasks store (scheduled tasks)\n if (!database.objectStoreNames.contains(\"tasks\")) {\n const taskStore = database.createObjectStore(\"tasks\", {\n keyPath: \"id\",\n });\n\n taskStore.createIndex(\"by-group\", \"groupId\");\n taskStore.createIndex(\"by-enabled\", \"enabled\");\n }\n\n // Config store (key-value)\n if (!database.objectStoreNames.contains(\"config\")) {\n database.createObjectStore(\"config\", { keyPath: \"key\" });\n }\n\n // Pending Web Share Target payloads\n if (!database.objectStoreNames.contains(\"pendingShares\")) {\n const pendingShares = database.createObjectStore(\"pendingShares\", {\n keyPath: \"id\",\n });\n pendingShares.createIndex(\"by-createdAt\", \"createdAt\");\n }\n };\n\n request.onsuccess = async () => {\n db = request.result;\n setDB(db);\n try {\n await migrateLegacyDatabase(db);\n await migrateLegacyOpfs(db);\n } catch (e) {\n console.warn(\"Error running legacy migration:\", e);\n }\n resolve(db);\n };\n\n request.onerror = () => {\n reject(new Error(`Failed to open IndexedDB: ${request.error?.message}`));\n };\n });\n}\n","import { DEFAULT_GROUP_ID } from \"../../config/config.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type { A2UIAction } from \"../../ui/a2ui/types.js\";\n\nimport type {\n Channel,\n ChannelDisplayCallback,\n ChannelMessageCallback,\n ChannelTypingCallback,\n InboundMessage,\n} from \"./types.js\";\n\nexport class BrowserChatChannel implements Channel {\n activeGroupId: string;\n displayCallback: ChannelDisplayCallback | null;\n messageCallback: ChannelMessageCallback | null;\n type: Channel[\"type\"];\n typingCallback: ChannelTypingCallback | null;\n\n constructor() {\n this.type = \"browser\";\n this.messageCallback = null;\n this.typingCallback = null;\n this.displayCallback = null;\n\n this.activeGroupId = DEFAULT_GROUP_ID;\n }\n\n /**\n * Get the currently active group.\n */\n getActiveGroup(): string {\n return this.activeGroupId;\n }\n\n /**\n * Register callback for displaying messages in the UI.\n */\n onDisplay(callback: ChannelDisplayCallback) {\n this.displayCallback = callback;\n }\n\n /**\n * Register callback for inbound messages (from UI → orchestrator).\n */\n onMessage(callback: ChannelMessageCallback) {\n this.messageCallback = callback;\n }\n\n /**\n * Register callback for typing indicator changes.\n */\n onTyping(callback: ChannelTypingCallback) {\n this.typingCallback = callback;\n }\n\n /**\n * Set the currently active group (for UI tab switching).\n */\n setActiveGroup(groupId: string) {\n this.activeGroupId = groupId;\n }\n\n /**\n * Show/hide typing indicator in the UI.\n */\n setTyping(groupId: string, typing: boolean) {\n this.typingCallback?.(groupId, typing);\n }\n\n start() {\n // No-op — browser chat is always \"started\"\n }\n\n stop() {\n // No-op\n }\n\n submit(\n text: string,\n groupId?: string,\n attachments: MessageAttachment[] = [],\n a2uiAction?: A2UIAction,\n freshContext?: boolean,\n subagent?: boolean,\n ) {\n const gid = groupId || this.activeGroupId;\n const msg: InboundMessage = {\n id: ulid(),\n groupId: gid,\n sender: \"You\",\n content: text,\n timestamp: Date.now(),\n channel: \"browser\",\n attachments,\n a2uiAction,\n freshContext,\n subagent,\n };\n\n this.messageCallback?.(msg);\n }\n\n /**\n * Send a response to the browser chat UI for display.\n */\n async send(\n groupId: string,\n text: string,\n _attachments?: MessageAttachment[],\n ) {\n this.displayCallback?.(groupId, text, true);\n }\n}\n","/**\n * ShadowClaw — Channel Registry\n *\n * Generic registry that maps groupId prefixes to Channel implementations.\n * Channels register with a prefix (e.g. \"br:\", \"ext:\", \"custom:\") and the\n * registry routes groupIds to the correct channel at runtime.\n */\n\nimport {\n Channel,\n ChannelRegistrationOptions,\n ChannelType,\n InboundMessage,\n} from \"./types.js\";\n\ninterface ChannelEntry {\n prefix: string;\n channel: Channel;\n badge: string;\n autoTrigger: boolean;\n}\n\nexport class ChannelRegistry {\n _entries: ChannelEntry[];\n\n constructor() {\n this._entries = [];\n }\n\n /**\n * Find the channel that owns a groupId.\n * Matches the longest registered prefix.\n */\n find(groupId: string): Channel | null {\n return this.resolve(groupId)?.channel ?? null;\n }\n\n /**\n * Get a channel by its exact prefix.\n */\n get(prefix: string): Channel | undefined {\n return this._entries.find((e) => e.prefix === prefix)?.channel;\n }\n\n /**\n * Get a badge label for a groupId based on its prefix.\n */\n getBadge(groupId: string): string {\n return this.resolve(groupId)?.badge ?? \"\";\n }\n\n /**\n * Resolve a channel type from the group prefix.\n */\n getChannelType(groupId: string): ChannelType | null {\n return this.resolve(groupId)?.channel.type ?? null;\n }\n\n /**\n * Register a message handler on all channels.\n */\n onMessage(handler: (msg: InboundMessage) => void) {\n for (const entry of this._entries) {\n entry.channel.onMessage(handler);\n }\n }\n\n /**\n * Register a typing handler on all channels.\n */\n onTyping(handler: (groupId: string, typing: boolean) => void) {\n for (const entry of this._entries) {\n if (entry.channel.onTyping) {\n entry.channel.onTyping(handler);\n }\n }\n }\n\n /**\n * List all registered prefixes.\n */\n prefixes(): string[] {\n return this._entries.map((e) => e.prefix);\n }\n\n /**\n * Register a channel for a given prefix.\n */\n register(\n prefix: string,\n channel: Channel,\n badgeOrOptions?: string | ChannelRegistrationOptions,\n ) {\n const options =\n typeof badgeOrOptions === \"string\"\n ? { badge: badgeOrOptions }\n : (badgeOrOptions ?? {});\n\n this._entries.push({\n prefix,\n channel,\n badge: options.badge ?? prefix.replace(/:$/, \"\"),\n autoTrigger: options.autoTrigger ?? false,\n });\n // Sort by prefix length descending so longest‑prefix wins in find()\n this._entries.sort((a, b) => b.prefix.length - a.prefix.length);\n }\n\n /**\n * Resolve the full channel entry for a groupId.\n */\n resolve(groupId: string): ChannelEntry | null {\n for (const entry of this._entries) {\n if (groupId.startsWith(entry.prefix)) {\n return entry;\n }\n }\n\n return null;\n }\n\n /**\n * Whether this channel should auto-trigger the agent.\n */\n shouldAutoTrigger(groupId: string): boolean {\n return this.resolve(groupId)?.autoTrigger ?? false;\n }\n\n /**\n * Start all registered channels.\n */\n startAll() {\n for (const entry of this._entries) {\n entry.channel.start();\n }\n }\n\n /**\n * Stop all registered channels.\n */\n stopAll() {\n for (const entry of this._entries) {\n entry.channel.stop();\n }\n }\n}\n","import type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport {\n IMESSAGE_POLL_TIMEOUT,\n IMESSAGE_REQUEST_TIMEOUT_MS,\n} from \"../../config/config.js\";\n\nconst IMESSAGE_DEDUP_TTL_MS = 60_000;\n\nexport type IMessageFileReader = (\n groupId: string,\n path: string,\n) => Promise<Blob | null>;\n\nexport class IMessageChannel implements Channel {\n abortController: AbortController | null = null;\n apiKey = \"\";\n apiMode: \"unknown\" | \"beeper-desktop\" | \"legacy\" = \"unknown\";\n cursor: string | null = null;\n fileReader: IMessageFileReader | null = null;\n messageCallback: ChannelMessageCallback | null = null;\n reconnectDelayMs = 1000;\n registeredChatIds: Set<string> = new Set();\n running = false;\n seenMessageIds: Map<string, number> = new Map();\n serverUrl = \"\";\n type: Channel[\"type\"] = \"imessage\";\n\n configure(serverUrl: string, apiKey: string, chatIds: string[]): void {\n this.serverUrl = normalizeBaseUrl(serverUrl);\n this.apiKey = apiKey.trim();\n this.registeredChatIds = new Set(\n chatIds.map((chatId) => chatId.trim()).filter(Boolean),\n );\n this.cursor = null;\n this.apiMode = \"unknown\";\n }\n\n handleIncomingMessage(message: IMessageBridgeMessage): void {\n this.pruneSeenMessageIds();\n\n const chatId = String(\n message.chatId || message.conversationId || \"\",\n ).trim();\n if (!chatId) {\n return;\n }\n\n if (\n this.registeredChatIds.size > 0 &&\n !this.registeredChatIds.has(chatId)\n ) {\n return;\n }\n\n const content = `${message.text || message.body || \"\"}`.trim();\n if (!content) {\n return;\n }\n\n const id = `${message.id || message.guid || `${chatId}:${message.timestamp || message.createdAt || content}`}`;\n if (this.seenMessageIds.has(id)) {\n return;\n }\n\n this.seenMessageIds.set(id, Date.now());\n\n const inbound: InboundMessage = {\n id,\n groupId: `im:${chatId}`,\n sender: `${message.sender || message.handle || message.from || \"iMessage\"}`,\n content,\n timestamp: normalizeTimestamp(message.timestamp || message.createdAt),\n channel: \"imessage\",\n };\n\n this.messageCallback?.(inbound);\n }\n\n handlePollResponse(response: IMessagePollResponse): void {\n if (response.nextCursor !== undefined && response.nextCursor !== null) {\n this.cursor = String(response.nextCursor);\n } else if (response.cursor !== undefined && response.cursor !== null) {\n this.cursor = String(response.cursor);\n }\n\n const messages = Array.isArray(response.messages) ? response.messages : [];\n for (const message of messages) {\n this.handleIncomingMessage(message);\n }\n }\n\n isConfigured(): boolean {\n return this.serverUrl.length > 0;\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n pruneSeenMessageIds(): void {\n const now = Date.now();\n for (const [id, seenAt] of this.seenMessageIds.entries()) {\n if (now - seenAt > IMESSAGE_DEDUP_TTL_MS) {\n this.seenMessageIds.delete(id);\n }\n }\n }\n\n setTyping(groupId: string, typing: boolean): void {\n if (!typing) {\n return;\n }\n\n const chatId = groupId.replace(/^im:/, \"\");\n void this.requestJson(\"/messages/typing\", {\n method: \"POST\",\n body: JSON.stringify({ chatId, typing: true }),\n }).catch(() => {});\n }\n\n start(): void {\n if (!this.isConfigured() || this.running) {\n return;\n }\n\n this.running = true;\n this.abortController = new AbortController();\n void this.poll();\n }\n\n stop(): void {\n this.running = false;\n this.abortController?.abort();\n this.abortController = null;\n }\n\n async ensureApiMode(): Promise<\"beeper-desktop\" | \"legacy\"> {\n if (this.apiMode !== \"unknown\") {\n return this.apiMode;\n }\n\n try {\n await this.requestJson(\"/v1/info\", { method: \"GET\" });\n this.apiMode = \"beeper-desktop\";\n } catch {\n this.apiMode = \"legacy\";\n }\n\n return this.apiMode;\n }\n\n async poll(): Promise<void> {\n while (\n this.running &&\n this.abortController &&\n !this.abortController.signal.aborted\n ) {\n try {\n const params = new URLSearchParams({\n timeout: String(IMESSAGE_POLL_TIMEOUT),\n });\n if (this.cursor) {\n params.set(\"cursor\", this.cursor);\n }\n\n const response = (await this.requestJson(\n `/messages?${params.toString()}`,\n { method: \"GET\" },\n IMESSAGE_REQUEST_TIMEOUT_MS + 5000,\n this.abortController.signal,\n )) as IMessagePollResponse;\n\n this.reconnectDelayMs = 1000;\n this.handlePollResponse(response);\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n break;\n }\n\n console.error(\"iMessage bridge poll error:\", error);\n await sleep(this.reconnectDelayMs);\n this.reconnectDelayMs = Math.min(this.reconnectDelayMs * 2, 30_000);\n }\n }\n }\n\n async requestJson(\n path: string,\n init: RequestInit,\n timeoutMs = IMESSAGE_REQUEST_TIMEOUT_MS,\n parentSignal?: AbortSignal,\n ): Promise<unknown> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n const onAbort = () => controller.abort();\n parentSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n const headers = new Headers(init.headers);\n headers.set(\"Accept\", \"application/json\");\n\n if (\n !headers.has(\"Content-Type\") &&\n init.body &&\n !(init.body instanceof FormData)\n ) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n if (this.apiKey) {\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-API-Key\", this.apiKey);\n }\n\n const response = await fetch(`${this.serverUrl}${path}`, {\n ...init,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n\n throw new Error(\n `iMessage bridge request failed: ${response.status} ${text}`,\n );\n }\n\n if (response.status === 204) {\n return { messages: [] };\n }\n\n return await response.json();\n } finally {\n clearTimeout(timeout);\n parentSignal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n async send(\n groupId: string,\n text: string,\n _providedAttachments?: MessageAttachment[],\n ): Promise<void> {\n const chatId = groupId.replace(/^im:/, \"\");\n const { remainingText, attachments: markdownAttachments } =\n extractMarkdownAttachments(text);\n\n for (const attachment of markdownAttachments) {\n if (!this.fileReader) {\n await this.sendText(\n chatId,\n `[${attachment.alt}] (file: ${attachment.path})`,\n );\n\n continue;\n }\n\n try {\n const blob = await this.fileReader(groupId, attachment.path);\n if (!blob || blob.size === 0) {\n throw new Error(\"Attachment file is empty or unavailable.\");\n }\n\n await this.sendAttachment(chatId, blob, attachment);\n } catch (err) {\n console.warn(\n `iMessage attachment send failed for ${attachment.path}:`,\n err,\n );\n\n await this.sendText(\n chatId,\n `[${attachment.alt}] (file: ${attachment.path})`,\n );\n }\n }\n\n const trimmed = remainingText.trim();\n if (!trimmed) {\n return;\n }\n\n await this.sendText(chatId, trimmed);\n }\n\n async sendAttachment(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const mode = await this.ensureApiMode();\n if (mode === \"beeper-desktop\") {\n await this.sendAttachmentViaBeeperDesktop(chatId, blob, attachment);\n\n return;\n }\n\n await this.sendAttachmentViaLegacyBridge(chatId, blob, attachment);\n }\n\n async sendAttachmentViaBeeperDesktop(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const basename = attachment.path.split(\"/\").pop() || \"attachment.bin\";\n const formData = new FormData();\n formData.append(\"file\", blob, basename);\n formData.append(\"fileName\", basename);\n if (blob.type) {\n formData.append(\"mimeType\", blob.type);\n }\n\n const uploadResponse = (await this.requestJson(\"/v1/assets/upload\", {\n method: \"POST\",\n body: formData,\n })) as { uploadID?: string };\n\n const uploadID = `${uploadResponse.uploadID || \"\"}`.trim();\n if (!uploadID) {\n throw new Error(\"Beeper asset upload failed: missing uploadID\");\n }\n\n await this.requestJson(`/v1/chats/${encodeURIComponent(chatId)}/messages`, {\n method: \"POST\",\n body: JSON.stringify({\n text: attachment.alt || undefined,\n attachment: {\n uploadID,\n fileName: basename,\n mimeType: blob.type || undefined,\n },\n }),\n });\n }\n\n async sendAttachmentViaLegacyBridge(\n chatId: string,\n blob: Blob,\n attachment: { alt: string; path: string },\n ): Promise<void> {\n const basename = attachment.path.split(\"/\").pop() || \"attachment.bin\";\n const formData = new FormData();\n formData.append(\"chatId\", chatId);\n if (attachment.alt) {\n formData.append(\"text\", attachment.alt);\n }\n\n formData.append(\"file\", blob, basename);\n\n await this.requestJson(\"/messages/send\", {\n method: \"POST\",\n body: formData,\n });\n }\n\n async sendText(chatId: string, text: string): Promise<void> {\n const mode = await this.ensureApiMode();\n if (mode === \"beeper-desktop\") {\n await this.requestJson(\n `/v1/chats/${encodeURIComponent(chatId)}/messages`,\n {\n method: \"POST\",\n body: JSON.stringify({ text }),\n },\n );\n\n return;\n }\n\n await this.requestJson(\"/messages/send\", {\n method: \"POST\",\n body: JSON.stringify({ chatId, text }),\n });\n }\n}\n\nfunction normalizeBaseUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n\nfunction normalizeTimestamp(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value > 1_000_000_000_000 ? value : value * 1000;\n }\n\n if (typeof value === \"string\") {\n const numeric = Number(value);\n if (Number.isFinite(numeric)) {\n return normalizeTimestamp(numeric);\n }\n\n const parsed = Date.parse(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction extractMarkdownAttachments(text: string): {\n remainingText: string;\n attachments: { alt: string; path: string }[];\n} {\n const attachments: { alt: string; path: string }[] = [];\n const regex = /!?\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n let match: RegExpExecArray | null = null;\n let remainingText = text;\n\n while ((match = regex.exec(text)) !== null) {\n const alt = match[1] || \"\";\n const rawPath = (match[2] || \"\").trim();\n const path = normalizeAttachmentPath(rawPath);\n\n if (path) {\n attachments.push({ alt, path });\n remainingText = remainingText.replace(match[0], \"\");\n }\n }\n\n return { remainingText, attachments };\n}\n\nfunction normalizeAttachmentPath(path: string): string | null {\n if (!path) {\n return null;\n }\n\n const trimmed = path.trim();\n\n // Ignore URI schemes (https:, data:, mailto:, etc.) and protocol-relative URLs.\n if (/^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed) || trimmed.startsWith(\"//\")) {\n return null;\n }\n\n const normalized = trimmed\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/^\\.\\//, \"\");\n\n if (!normalized) {\n return null;\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.some((seg) => seg === \"..\")) {\n return null;\n }\n\n return segments.join(\"/\");\n}\n\ninterface IMessagePollResponse {\n messages?: IMessageBridgeMessage[];\n nextCursor?: string | number | null;\n cursor?: string | number | null;\n}\n\ninterface IMessageBridgeMessage {\n id?: string;\n guid?: string;\n chatId?: string;\n conversationId?: string;\n sender?: string;\n handle?: string;\n from?: string;\n text?: string;\n body?: string;\n timestamp?: number | string;\n createdAt?: number | string;\n}\n","/**\n * ShadowClaw — Room Channel\n *\n * Thin {@link Channel} adapter for multi-party rooms. Outbound messages are\n * broadcast to all room members via the {@link RoomManager} (which delegates\n * transport to the PeerJS mesh with host-relay fallback). Inbound messages are\n * delivered by the manager back through this channel's registered callback so\n * they flow into the orchestrator's normal enqueue path.\n *\n * - Prefix: `room:`\n * - groupId format: `room:<roomId>`\n */\n\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n ChannelTypingCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport type { RoomManager } from \"./room-manager.js\";\n\nexport class RoomChannel implements Channel {\n messageCallback: ChannelMessageCallback | null = null;\n\n running = false;\n type: Channel[\"type\"] = \"room\";\n typingCallback: ChannelTypingCallback | null = null;\n\n private _manager: RoomManager | null = null;\n\n /** Deliver an inbound room message (called by the {@link RoomManager}). */\n deliverInbound(msg: InboundMessage): void {\n this.messageCallback?.(msg);\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n onTyping(callback: ChannelTypingCallback): void {\n this.typingCallback = callback;\n }\n\n /** Wire the room manager used for transport. */\n setManager(manager: RoomManager): void {\n this._manager = manager;\n }\n\n setTyping(_groupId: string, _typing: boolean): void {\n // Typing presence within rooms is not propagated in this version.\n }\n\n start(): void {\n this.running = true;\n }\n\n stop(): void {\n this.running = false;\n }\n\n async send(\n groupId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): Promise<void> {\n if (!this._manager) {\n return;\n }\n\n const roomId = roomIdFromGroupId(groupId);\n this._manager.broadcast(roomId, text, attachments);\n }\n}\n","import type { MessageAttachment } from \"../../content/types.js\";\nimport type {\n Channel,\n ChannelMessageCallback,\n InboundMessage,\n} from \"./types.js\";\n\nimport {\n TELEGRAM_API_BASE,\n TELEGRAM_MAX_LENGTH,\n TELEGRAM_POLL_TIMEOUT,\n TELEGRAM_PROXY_BASE,\n} from \"../../config/config.js\";\n\nconst TELEGRAM_POLL_RETRY_MIN_MS = 1_000;\nconst TELEGRAM_POLL_RETRY_MAX_MS = 60_000;\n\nexport type TelegramFileReader = (\n groupId: string,\n path: string,\n) => Promise<Blob | null>;\n\nexport class TelegramChannel implements Channel {\n abortController: AbortController | null = null;\n fileReader: TelegramFileReader | null = null;\n messageCallback: ChannelMessageCallback | null = null;\n offset = 0;\n pollRetryDelayMs = TELEGRAM_POLL_RETRY_MIN_MS;\n pollSessionId = 0;\n registeredChatIds: Set<string> = new Set();\n running = false;\n token = \"\";\n type: Channel[\"type\"] = \"telegram\";\n useProxy = false;\n\n buildFileUrl(filePath: string): string {\n const normalizedPath = filePath\n .split(\"/\")\n .filter(Boolean)\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n const base = this.useProxy\n ? \"/telegram/file/bot\"\n : \"https://api.telegram.org/file/bot\";\n\n return `${base}${this.token}/${normalizedPath}`;\n }\n\n buildMethodUrl(methodOrPath: string): string {\n const normalized = methodOrPath.replace(/^\\/+/, \"\");\n const base = this.useProxy ? TELEGRAM_PROXY_BASE : TELEGRAM_API_BASE;\n\n return `${base}${this.token}/${normalized}`;\n }\n\n configure(token: string, chatIds: string[], useProxy = false): void {\n this.token = token.trim();\n this.registeredChatIds = new Set(\n chatIds.map((chatId) => chatId.trim()).filter(Boolean),\n );\n this.useProxy = !!useProxy;\n }\n\n isConfigured(): boolean {\n return this.token.length > 0;\n }\n\n nextPollRetryDelay(): number {\n const delay = this.pollRetryDelayMs;\n this.pollRetryDelayMs = Math.min(\n this.pollRetryDelayMs * 2,\n TELEGRAM_POLL_RETRY_MAX_MS,\n );\n\n return delay;\n }\n\n onMessage(callback: ChannelMessageCallback): void {\n this.messageCallback = callback;\n }\n\n registerChatId(chatId: string): void {\n const normalized = chatId.trim();\n if (!normalized) {\n return;\n }\n\n this.registeredChatIds.add(normalized);\n }\n\n resetPollBackoff(): void {\n this.pollRetryDelayMs = TELEGRAM_POLL_RETRY_MIN_MS;\n }\n\n setTyping(groupId: string, typing: boolean): void {\n if (!typing) {\n return;\n }\n\n const chatId = groupId.replace(/^tg:/, \"\");\n void this.apiCall(\"sendChatAction\", {\n chat_id: chatId,\n action: \"typing\",\n }).catch(() => {});\n }\n\n start(): void {\n if (!this.token || this.running) {\n return;\n }\n\n this.running = true;\n this.resetPollBackoff();\n const sessionId = ++this.pollSessionId;\n const controller = new AbortController();\n this.abortController = controller;\n void this.poll(sessionId, controller);\n }\n\n stop(): void {\n this.running = false;\n this.resetPollBackoff();\n this.pollSessionId += 1;\n this.abortController?.abort();\n this.abortController = null;\n }\n\n async apiCall<T = unknown>(\n method: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetch(this.buildMethodUrl(method), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram API ${method} failed: ${res.status} ${text}`);\n }\n\n return (await res.json()) as T;\n }\n\n async extractAttachments(msg: TelegramMessage): Promise<MessageAttachment[]> {\n const descriptors: TelegramFileDescriptor[] = [];\n\n const largestPhoto = Array.isArray(msg.photo) ? msg.photo.at(-1) : null;\n if (largestPhoto?.file_id) {\n descriptors.push({\n id: largestPhoto.file_id,\n fileName: `photo-${msg.message_id}.png`,\n mimeType: \"image/png\",\n previewDisposition: \"inline\",\n });\n }\n\n if (msg.document?.file_id) {\n descriptors.push({\n id: msg.document.file_id,\n fileName: msg.document.file_name || `document-${msg.message_id}`,\n mimeType: msg.document.mime_type,\n });\n }\n\n if (msg.video?.file_id) {\n descriptors.push({\n id: msg.video.file_id,\n fileName: msg.video.file_name || `video-${msg.message_id}.mp4`,\n mimeType: msg.video.mime_type || \"video/mp4\",\n });\n }\n\n if (msg.audio?.file_id) {\n descriptors.push({\n id: msg.audio.file_id,\n fileName: msg.audio.file_name || `audio-${msg.message_id}.mp3`,\n mimeType: msg.audio.mime_type || \"audio/mpeg\",\n });\n }\n\n if (msg.voice?.file_id) {\n descriptors.push({\n id: msg.voice.file_id,\n fileName: `voice-${msg.message_id}.ogg`,\n mimeType: msg.voice.mime_type || \"audio/ogg\",\n });\n }\n\n if (msg.animation?.file_id) {\n descriptors.push({\n id: msg.animation.file_id,\n fileName: msg.animation.file_name || `animation-${msg.message_id}.mp4`,\n mimeType: msg.animation.mime_type || \"video/mp4\",\n });\n }\n\n if (msg.sticker?.file_id) {\n descriptors.push({\n id: msg.sticker.file_id,\n fileName: `sticker-${msg.message_id}.${inferStickerExtension(msg.sticker)}`,\n mimeType: msg.sticker.is_animated\n ? \"application/x-tgsticker\"\n : msg.sticker.is_video\n ? \"video/webm\"\n : \"image/webp\",\n });\n }\n\n const attachments: MessageAttachment[] = [];\n for (const descriptor of descriptors) {\n const fileInfo = await this.fetchTelegramFileInfo(descriptor.id);\n attachments.push({\n id: descriptor.id,\n fileName: descriptor.fileName,\n mimeType: descriptor.mimeType,\n size: fileInfo.file_size,\n previewDisposition: descriptor.previewDisposition,\n source: {\n kind: \"remote-url\",\n url: this.buildFileUrl(fileInfo.file_path),\n },\n });\n }\n\n return attachments;\n }\n\n async fetchTelegramFileInfo(fileId: string): Promise<TelegramFileInfo> {\n const response = await this.apiCall<TelegramFileApiResponse>(\"getFile\", {\n file_id: fileId,\n });\n\n if (!response.ok || !response.result?.file_path) {\n throw new Error(`Telegram getFile failed for attachment ${fileId}`);\n }\n\n return response.result;\n }\n\n async handleUpdate(update: TelegramUpdate): Promise<void> {\n const msg = update.message;\n if (!msg) {\n return;\n }\n\n const chatId = String(msg.chat.id);\n\n if (msg.text === \"/chatid\") {\n void this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: `Chat ID: ${chatId}\\nRegister this ID in ShadowClaw settings.`,\n }).catch(console.error);\n\n return;\n }\n\n if (msg.text === \"/ping\") {\n void this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: \"Pong! ShadowClaw is running.\",\n }).catch(console.error);\n\n return;\n }\n\n if (!this.registeredChatIds.has(chatId)) {\n return;\n }\n\n const attachments = await this.extractAttachments(msg);\n const textContent = `${msg.text || msg.caption || \"\"}`.trim();\n\n const content =\n textContent ||\n (msg.photo?.length ? \"[Photo]\" : null) ||\n (msg.voice ? \"[Voice message]\" : null) ||\n (msg.video ? \"[Video]\" : null) ||\n (msg.audio ? \"[Audio]\" : null) ||\n (msg.animation ? \"[Animation]\" : null) ||\n (msg.document\n ? `[Document: ${msg.document.file_name || \"unnamed\"}]`\n : null) ||\n (msg.sticker ? `[Sticker: ${msg.sticker.emoji || \"\"}]` : null) ||\n (msg.location\n ? `[Location: ${msg.location.latitude}, ${msg.location.longitude}]`\n : null) ||\n (msg.contact ? `[Contact: ${msg.contact.first_name}]` : null) ||\n \"[Unsupported message type]\";\n\n const senderName =\n msg.from?.first_name ||\n msg.from?.username ||\n String(msg.from?.id || \"Unknown\");\n\n const inbound: InboundMessage = {\n id: String(msg.message_id),\n groupId: `tg:${chatId}`,\n sender: senderName,\n content,\n timestamp: msg.date * 1000,\n channel: \"telegram\",\n attachments,\n };\n\n this.messageCallback?.(inbound);\n }\n\n async poll(sessionId: number, controller: AbortController): Promise<void> {\n while (\n this.running &&\n this.pollSessionId === sessionId &&\n !controller.signal.aborted\n ) {\n try {\n const res = await fetch(\n this.buildMethodUrl(\n `getUpdates?offset=${this.offset}&timeout=${TELEGRAM_POLL_TIMEOUT}`,\n ),\n { signal: controller.signal },\n );\n\n if (!res.ok) {\n console.error(`Telegram poll error: HTTP ${res.status}`);\n await this.waitForRetry(this.nextPollRetryDelay());\n\n continue;\n }\n\n const data = (await res.json()) as TelegramApiResponse;\n if (!data.ok || !Array.isArray(data.result)) {\n await this.waitForRetry(this.nextPollRetryDelay());\n\n continue;\n }\n\n this.resetPollBackoff();\n\n for (const update of data.result) {\n this.offset = update.update_id + 1;\n await this.handleUpdate(update);\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n break;\n }\n\n console.error(\"Telegram poll error:\", error);\n await this.waitForRetry(this.nextPollRetryDelay());\n }\n }\n }\n\n async send(\n groupId: string,\n text: string,\n _providedAttachments?: MessageAttachment[],\n ): Promise<void> {\n const chatId = groupId.replace(/^tg:/, \"\");\n\n // Extract and send inline images and documents as Telegram attachments\n const { remainingText, attachments: markdownAttachments } =\n extractMarkdownAttachments(text);\n\n for (const att of markdownAttachments) {\n if (this.fileReader) {\n try {\n const blob = await this.fileReader(groupId, att.path);\n if (blob && blob.size > 0) {\n const lowerPath = att.path.toLowerCase();\n const isImage =\n lowerPath.endsWith(\".png\") ||\n lowerPath.endsWith(\".jpg\") ||\n lowerPath.endsWith(\".jpeg\") ||\n lowerPath.endsWith(\".gif\") ||\n lowerPath.endsWith(\".webp\");\n\n if (isImage) {\n await this.sendPhoto(chatId, blob, att.alt, att.path);\n } else {\n await this.sendDocument(chatId, blob, att.alt, att.path);\n }\n\n continue;\n }\n } catch (err) {\n console.warn(\n `TelegramChannel: failed to read file ${att.path}:`,\n err,\n );\n }\n }\n\n // Fallback: send the markdown as text if file reader is unavailable\n await this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: `[${att.alt}] (file: ${att.path})`,\n });\n }\n\n // Send remaining text if any\n const trimmed = remainingText.trim();\n if (trimmed) {\n const chunks = splitText(trimmed, TELEGRAM_MAX_LENGTH);\n for (const chunk of chunks) {\n await this.apiCall(\"sendMessage\", {\n chat_id: chatId,\n text: chunk,\n });\n }\n }\n }\n\n async sendDocument(\n chatId: string,\n blob: Blob,\n caption: string,\n filename: string,\n ): Promise<void> {\n const basename = filename.split(\"/\").pop() || \"document.file\";\n const formData = new FormData();\n formData.append(\"chat_id\", chatId);\n formData.append(\"document\", blob, basename);\n if (caption) {\n formData.append(\"caption\", caption);\n }\n\n const res = await fetch(this.buildMethodUrl(\"sendDocument\"), {\n method: \"POST\",\n body: formData,\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram sendDocument failed: ${res.status} ${text}`);\n }\n }\n\n async sendPhoto(\n chatId: string,\n blob: Blob,\n caption: string,\n filename: string,\n ): Promise<void> {\n const basename = filename.split(\"/\").pop() || \"image.png\";\n const formData = new FormData();\n formData.append(\"chat_id\", chatId);\n formData.append(\"photo\", blob, basename);\n if (caption) {\n formData.append(\"caption\", caption);\n }\n\n const res = await fetch(this.buildMethodUrl(\"sendPhoto\"), {\n method: \"POST\",\n body: formData,\n });\n\n if (!res.ok) {\n const text = await res.text();\n\n throw new Error(`Telegram sendPhoto failed: ${res.status} ${text}`);\n }\n }\n\n async waitForRetry(ms: number): Promise<void> {\n await sleep(ms);\n }\n}\n\nfunction splitText(text: string, max: number): string[] {\n if (text.length <= max) {\n return [text];\n }\n\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= max) {\n chunks.push(remaining);\n\n break;\n }\n\n let end = max;\n const lastNewline = remaining.lastIndexOf(\"\\n\", max);\n if (lastNewline > max * 0.5) {\n end = lastNewline;\n }\n\n chunks.push(remaining.slice(0, end));\n remaining = remaining.slice(end);\n }\n\n return chunks;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\ninterface TelegramApiResponse {\n ok?: boolean;\n result?: TelegramUpdate[];\n}\n\ninterface TelegramFileApiResponse {\n ok?: boolean;\n result?: TelegramFileInfo;\n}\n\ninterface TelegramFileInfo {\n file_id: string;\n file_path: string;\n file_size?: number;\n}\n\ninterface TelegramUpdate {\n update_id: number;\n message?: TelegramMessage;\n}\n\ninterface TelegramMessage {\n message_id: number;\n chat: { id: number; type: string };\n from?: { id: number; first_name?: string; username?: string };\n date: number;\n text?: string;\n caption?: string;\n photo?: Array<{ file_id: string; width?: number; height?: number }>;\n voice?: { file_id: string; mime_type?: string };\n video?: { file_id: string; file_name?: string; mime_type?: string };\n audio?: { file_id: string; file_name?: string; mime_type?: string };\n animation?: { file_id: string; file_name?: string; mime_type?: string };\n document?: { file_id: string; file_name?: string; mime_type?: string };\n sticker?: {\n emoji?: string;\n file_id: string;\n is_animated?: boolean;\n is_video?: boolean;\n };\n location?: { latitude: number; longitude: number };\n contact?: { first_name: string };\n}\n\ninterface TelegramFileDescriptor {\n id: string;\n fileName: string;\n mimeType?: string;\n previewDisposition?: \"inline\" | \"file\";\n}\n\nfunction inferStickerExtension(sticker: TelegramMessage[\"sticker\"]): string {\n if (sticker?.is_animated) {\n return \"tgs\";\n }\n\n if (sticker?.is_video) {\n return \"webm\";\n }\n\n return \"webp\";\n}\n\nexport function extractMarkdownAttachments(text: string): {\n remainingText: string;\n attachments: { alt: string; path: string }[];\n} {\n const attachments: { alt: string; path: string }[] = [];\n const regex = /!?\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n\n let match;\n let remainingText = text;\n\n // Find all matches\n while ((match = regex.exec(text)) !== null) {\n const alt = match[1];\n const path = (match[2] || \"\").trim();\n\n const normalizedPath = normalizeAttachmentPath(path);\n\n // Only capture valid normalized workspace-relative paths.\n if (normalizedPath) {\n attachments.push({ alt, path: normalizedPath });\n // Remove the markdown from the text\n remainingText = remainingText.replace(match[0], \"\");\n }\n }\n\n return { remainingText, attachments };\n}\n\nfunction normalizeAttachmentPath(path: string): string | null {\n if (!path) {\n return null;\n }\n\n const trimmed = path.trim();\n\n // Ignore URI schemes (https:, data:, mailto:, etc.) and protocol-relative URLs.\n if (/^[a-zA-Z][a-zA-Z\\d+.-]*:/.test(trimmed) || trimmed.startsWith(\"//\")) {\n return null;\n }\n\n const normalized = trimmed\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/^\\.\\//, \"\");\n\n if (!normalized) {\n return null;\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.some((seg) => seg === \"..\")) {\n return null;\n }\n\n return segments.join(\"/\");\n}\n","import type { A2UIAction } from \"../types.js\";\n\n/**\n * Build the `[A2UI ACTION]` prompt delivered to the surface owner's agent when\n * a user interacts with a surface (clicks a Button, submits a TextField, …).\n *\n * The prompt is intentionally prefixed with `[A2UI ACTION]` so the orchestrator\n * can force-trigger the agent regardless of channel. It is the single source of\n * truth shared by the local chat UI and the multi-party room manager.\n *\n * @param action The action fired on the surface.\n * @param actorAlias Optional human-readable name of the peer that fired the\n * action (used in shared room surfaces to give the owner context).\n */\nexport function formatA2UIActionPrompt(\n action: A2UIAction,\n actorAlias?: string,\n): string {\n const dataModelJson = JSON.stringify(action.dataModel ?? {}, null, 2);\n const actor = actorAlias ? `${actorAlias}` : \"The user\";\n\n return (\n `[A2UI ACTION]\\n` +\n `surfaceId: \"${action.surfaceId}\"\\n` +\n `actionId: \"${action.actionId}\"\\n` +\n (actorAlias ? `firedBy: \"${actorAlias}\"\\n` : \"\") +\n `dataModel:\\n${dataModelJson}\\n\\n` +\n `Instructions: ${actor} triggered the \"${action.actionId}\" action on ` +\n `surface \"${action.surfaceId}\". ` +\n `The dataModel above contains the current form values. ` +\n `Use the appropriate tool(s) to fulfill the action based on the actionId ` +\n `and dataModel values. ` +\n `After you have a result, call render_component with action ` +\n `\"updateDataModel\" on surfaceId \"${action.surfaceId}\" to update the ` +\n `surface (e.g. set path \"/result\" to the output value). ` +\n `Do NOT respond with plain text only — always update the surface via ` +\n `render_component.`\n );\n}\n","import type { ChannelRegistry } from \"../subsystems/channels/channel-registry.js\";\nimport type { Channel } from \"../subsystems/channels/types.js\";\nimport type { MessageAttachment } from \"../content/types.js\";\n\nexport class Router {\n /**\n * Format messages in XML for agent context\n */\n static formatMessagesXml(messages: any[]): string {\n const escapeXml = (s: string) =>\n s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n\n const lines = messages.map(\n (m) =>\n `<message sender=\"${escapeXml(m.sender)}\" time=\"${new Date(m.timestamp).toISOString()}\">${escapeXml(m.content)}</message>`,\n );\n\n return `<messages>\\n${lines.join(\"\\n\")}\\n</messages>`;\n }\n\n /**\n * Strip internal tags from agent output\n */\n static formatOutbound(rawText: string): string {\n return rawText.replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\").trim();\n }\n\n registry: ChannelRegistry;\n\n /**\n * Routes outbound messages and typing indicators to the correct channel\n * based on the groupId prefix, using a ChannelRegistry.\n */\n constructor(registry: ChannelRegistry) {\n this.registry = registry;\n }\n\n /**\n * Find the appropriate channel for a groupId\n */\n findChannel(groupId: string): Channel | null {\n return this.registry.find(groupId);\n }\n\n /**\n * Set typing indicator on the correct channel\n */\n setTyping(groupId: string, typing: boolean): void {\n const channel = this.findChannel(groupId);\n channel?.setTyping(groupId, typing);\n }\n\n /**\n * Send a message to the correct channel\n */\n async send(\n groupId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): Promise<void> {\n const channel = this.findChannel(groupId);\n if (!channel) {\n console.warn(`No channel for groupId: ${groupId}`);\n\n return;\n }\n\n await channel.send(groupId, text, attachments);\n }\n}\n","/**\n * LiteRT-LM Browser Provider\n *\n * Wraps the Google LiteRT-LM Web API (@litert-lm/core) to provide\n * in-browser LLM inference for Gemma 4 models via WebGPU.\n *\n * https://developers.google.com/edge/litert-lm/js\n *\n * Currently supports:\n * - litert-community/gemma-4-E2B-it-litert-lm (gemma-4-E2B-it-web.litertlm)\n * - litert-community/gemma-4-E4B-it-litert-lm (gemma-4-E4B-it-web.litertlm)\n *\n * Model IDs in config use the litert-community HuggingFace repo ID. We resolve\n * the actual .litertlm file URL from the repo's main branch.\n */\n\nimport { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\nimport { ShadowClawDatabase } from \"../../db/db.js\";\nimport { createLogMessage } from \"../../worker/utils/createLogMessage.js\";\nimport { createToolActivityMessage } from \"../../worker/utils/createToolActivityMessage.js\";\nimport { executeTool } from \"../../worker/utils/executeTool.js\";\nimport { setPostHandler } from \"../../worker/utils/post.js\";\nimport { ToolDefinition } from \"../tools/tools.js\";\n\nimport type { SubagentInvokeContext } from \"../../worker/tools/spawn-subagent/spawn-subagent.js\";\n\n/**\n * Map from provider model ID (HuggingFace repo) to the .litertlm web model URL.\n */\nconst LITERT_LM_MODEL_URLS: Record<string, string> = {\n \"litert-community/gemma-4-E2B-it-litert-lm\":\n \"https://huggingface.co/litert-community/gemma-4-E2B-it-litert-lm/resolve/main/gemma-4-E2B-it-web.litertlm\",\n \"litert-community/gemma-4-E4B-it-litert-lm\":\n \"https://huggingface.co/litert-community/gemma-4-E4B-it-litert-lm/resolve/main/gemma-4-E4B-it-web.litertlm\",\n};\n\nexport const LITERT_LM_SUPPORTED_MODELS = Object.keys(LITERT_LM_MODEL_URLS);\n\nexport const DEFAULT_LITERT_LM_MODEL =\n \"litert-community/gemma-4-E2B-it-litert-lm\";\n\n/**\n * Returns true if the LiteRT-LM JS API is available (WebGPU required).\n */\nexport function isLiteRtLmSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"gpu\" in navigator &&\n typeof WebAssembly !== \"undefined\" &&\n \"Suspending\" in WebAssembly\n );\n}\n\n/**\n * Lazy-loaded LiteRT-LM Engine singleton per model.\n * We keep one engine alive to avoid expensive re-initialization.\n */\nlet liteRtEngine: any | null = null;\nlet liteRtEngineModelId: string | null = null;\n\nlet liteRtEnginePromise: Promise<any> | null = null;\nlet liteRtEnginePromiseModelId: string | null = null;\n\nimport {\n DEFAULT_CHUNK_SIZE,\n loadModelStream,\n type ModelProgressCallback as LiteRtProgressCallback,\n} from \"./utils/index.js\";\n\n/**\n * Persistent Cache Storage bucket for downloaded `.litertlm` model weights.\n */\nexport const LITERT_LM_CACHE_NAME = \"shadow-claw-litertlm-models\";\nexport const LITERT_LM_CHUNK_SIZE = DEFAULT_CHUNK_SIZE;\n\nexport async function loadLiteRtModelStream(\n url: string,\n onProgress: LiteRtProgressCallback,\n abortSignal?: AbortSignal,\n): Promise<ReadableStream<Uint8Array>> {\n return loadModelStream(url, onProgress, abortSignal, {\n cacheName: LITERT_LM_CACHE_NAME,\n chunkSize: LITERT_LM_CHUNK_SIZE,\n });\n}\n\nasync function getLiteRtEngine(\n modelId: string,\n onProgress?: LiteRtProgressCallback,\n abortSignal?: AbortSignal,\n): Promise<any> {\n if (liteRtEngineModelId === modelId && liteRtEngine) {\n return liteRtEngine;\n }\n\n if (liteRtEnginePromise && liteRtEnginePromiseModelId === modelId) {\n return liteRtEnginePromise;\n }\n\n liteRtEnginePromiseModelId = modelId;\n liteRtEnginePromise = (async () => {\n if (liteRtEngine) {\n try {\n await liteRtEngine.delete?.();\n } catch {}\n\n liteRtEngine = null;\n liteRtEngineModelId = null;\n }\n\n const modelUrl = LITERT_LM_MODEL_URLS[modelId];\n if (!modelUrl) {\n throw new Error(\n `LiteRT-LM: Model '${modelId} is not supported. Supported models: ${LITERT_LM_SUPPORTED_MODELS.join(\", \")}`,\n );\n }\n\n const litertlm = await import(\"@litert-lm/core\").catch(() => {\n throw new Error(\n \"LiteRT-LM: The @litert-lm/core package is not installed. Run: npm install @litert-lm/core\",\n );\n });\n\n const Engine: any = litertlm.Engine ?? (litertlm as any).default?.Engine;\n if (typeof Engine?.create !== \"function\") {\n throw new Error(\n \"LiteRT-LM: Could not locate Engine.create in @litert-lm/core. Ensure you have the latest version installed.\",\n );\n }\n\n const modelStream = await loadLiteRtModelStream(\n modelUrl,\n onProgress ?? (() => {}),\n abortSignal,\n );\n\n const engine = await Engine.create({\n model: modelStream,\n mainExecutorSettings: {\n maxNumTokens: 8192,\n },\n });\n\n liteRtEngine = engine;\n liteRtEngineModelId = modelId;\n\n return engine;\n })();\n\n try {\n return await liteRtEnginePromise;\n } finally {\n liteRtEnginePromise = null;\n liteRtEnginePromiseModelId = null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tool-call output parsing (model-agnostic)\n// ---------------------------------------------------------------------------\n\n/**\n * Internal parsed tool-call / response envelope.\n */\ninterface LiteRtParsed {\n type: \"response\" | \"tool_use\";\n format?: \"json\" | \"model_specific\";\n response?: string;\n tool_calls?: Array<{\n id?: string;\n name: string;\n input?: Record<string, any>;\n }>;\n}\n\n/**\n * Try to parse Gemma 4's native tool-call syntax:\n * <|tool_call>call:TOOLNAME{...args...}<tool_call|>\n *\n * The model sometimes emits <|\"|> instead of literal quote chars, and may\n * omit the closing sentinel if generation was cut off.\n *\n * Returns a normalised { name, input } object on success, or null.\n *\n * NOTE: This is a *fallback* for models that ignore the JSON-envelope\n * instructions. The primary path is always the JSON envelope.\n */\nexport function parseModelSpecificToolCall(\n text: string,\n): { name: string; input: Record<string, any> } | null {\n if (!text) {\n return null;\n }\n\n // Match <|tool_call>call:TOOLNAME{...}<tool_call|> (closing sentinel optional)\n const match = text.match(\n /<\\|tool_call>call:([A-Za-z0-9_]+)(\\{[\\s\\S]*?)(?:<tool_call\\|>|$)/,\n );\n if (!match) {\n return null;\n }\n\n const name = match[1];\n let body = match[2];\n\n // Replace the Gemma 4 quote sentinel <|\"|> → \" so the body becomes\n // valid JSON-like text that we can parse.\n body = body.replace(/<\\|\"\\|>/g, '\"');\n\n /**\n * Gemma 4 emits JavaScript-style objects with unquoted property names,\n * e.g. {queries:[\"blueberries\"]}. This function wraps bare identifier keys\n * with double quotes so the result is valid JSON.\n */\n function normaliseToJson(src: string): string {\n // Quote any unquoted object key: an identifier followed by a colon that\n // is NOT already preceded by a double quote.\n\n return src.replace(\n /([{,]\\s*)([A-Za-z_$][A-Za-z0-9_$]*)(\\s*:)/g,\n '$1\"$2\"$3',\n );\n }\n\n // Attempt JSON.parse of the argument block, with progressive relaxation.\n let input: Record<string, any> = {};\n\n const candidates = [body, normaliseToJson(body)];\n\n for (const candidate of candidates) {\n try {\n const parsed = JSON.parse(candidate);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n input = parsed;\n\n break;\n }\n } catch {\n // try next candidate\n }\n }\n\n // If still unparsed, try extracting the first complete {...} block.\n if (Object.keys(input).length === 0) {\n const start = body.indexOf(\"{\");\n const end = body.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n const slice = body.slice(start, end + 1);\n for (const candidate of [slice, normaliseToJson(slice)]) {\n try {\n const parsed = JSON.parse(candidate);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n input = parsed;\n\n break;\n }\n } catch {\n // Best-effort: leave input as {}\n }\n }\n }\n }\n\n return { name, input };\n}\n\n/**\n * Parse the model's accumulated response into a structured envelope.\n *\n * Priority:\n * 1. JSON envelope { \"type\": \"tool_use\" | \"response\", ... } (model-agnostic, primary)\n * 2. Gemma 4 native <|tool_call>call:NAME{...}<tool_call|> (fallback)\n *\n * Returns null when the output is plain text with no recognised structure.\n */\nexport function parseLiteRtStructured(raw: string): LiteRtParsed | null {\n const text = sanitizeModelOutput(String(raw || \"\"), \"litert_lm\").trim();\n if (!text) {\n return null;\n }\n\n // ── 1. Try JSON (primary, model-agnostic) ──────────────────────────────\n const tryJson = (src: string): LiteRtParsed | null => {\n try {\n const obj = JSON.parse(src);\n if (\n obj &&\n typeof obj === \"object\" &&\n (obj.type === \"tool_use\" || obj.type === \"response\")\n ) {\n // Fix common model typos\n if (obj.tools_calls && !obj.tool_calls) {\n obj.tool_calls = obj.tools_calls;\n }\n\n return { ...obj, format: \"json\" } as LiteRtParsed;\n }\n } catch {\n // fall through\n }\n\n return null;\n };\n\n let result = tryJson(text);\n if (result) {\n return result;\n }\n\n // Try extracting the first {...} block in case the model wrapped it in prose.\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n result = tryJson(text.slice(start, end + 1));\n if (result) {\n return result;\n }\n }\n\n // ── 2. Regex fallback for malformed JSON ─────────────────────────────\n // Handle cases where the model forgets closing braces or brackets\n // e.g. {\"type\": \"tool_use\", \"tools_calls\": [{ \"name\": \"web_search\", \"input\": { \"query\": \"...\" } ]}\n if (text.includes('\"tool_use\"')) {\n const nameMatch = /\"name\"\\s*:\\s*\"([^\"]+)\"/.exec(text);\n if (nameMatch) {\n let input = {};\n const inputMatch = /\"input\"\\s*:\\s*(\\{.*?\\})\\s*(?:]|\\}|\"|$)/s.exec(text);\n if (inputMatch) {\n try {\n input = JSON.parse(inputMatch[1]);\n } catch {\n // Leave input empty if it's too mangled\n }\n }\n\n return {\n type: \"tool_use\",\n format: \"json\",\n tool_calls: [\n {\n id: `litert_${Date.now()}`,\n name: nameMatch[1],\n input,\n },\n ],\n };\n }\n }\n\n // ── 2. Gemma 4 native tool-call format (fallback) ──────────────────────\n const native = parseModelSpecificToolCall(text);\n if (native) {\n return {\n type: \"tool_use\",\n format: \"model_specific\",\n tool_calls: [\n {\n id: `litert_${Date.now()}`,\n name: native.name,\n input: native.input,\n },\n ],\n };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Conversation building helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build the preface (system messages) and per-turn text strings that will be\n * sent to the LiteRT-LM stateful conversation API.\n *\n * When tools are active we prepend JSON-envelope instructions so that any\n * LiteRT model (not just Gemma 4) knows how to signal tool calls.\n */\nfunction buildLiteRtMessages(\n systemPrompt: string,\n messages: any[],\n tools: ToolDefinition[],\n): { preface: any[]; turns: string[] } {\n const preface: any[] = [];\n\n // Compose the effective system content: original prompt + tool instructions.\n let effectiveSystem = systemPrompt || \"\";\n\n if (tools.length > 0) {\n const toolHints = tools\n .map((t) => {\n const params = Object.keys(t.input_schema.properties || {}).join(\", \");\n const brief = t.description.split(\". \")[0];\n\n return `${t.name}(${params}): ${brief}`;\n })\n .join(\"\\n\");\n\n const jsonInstructions = [\n \"\",\n \"TOOL CALLING INSTRUCTIONS:\",\n \"Return ONLY valid JSON (no markdown fences).\",\n 'To call a tool: {\"type\":\"tool_use\",\"tool_calls\":[{\"name\":\"<tool>\",\"input\":{...}}]}',\n 'To reply: {\"type\":\"response\",\"response\":\"<your answer>\"}',\n \"IMPORTANT: When you need to use a tool, output ONLY the JSON above — do NOT describe the call as text.\",\n \"\",\n \"Available tools:\",\n toolHints,\n ].join(\"\\n\");\n\n effectiveSystem = effectiveSystem\n ? effectiveSystem + jsonInstructions\n : jsonInstructions;\n }\n\n if (effectiveSystem) {\n preface.push({ role: \"system\", content: effectiveSystem });\n }\n\n // Build prior turns. All message types (text, tool_use, tool_result) are\n // serialised to a flat string so the stateful conversation engine can replay\n // them without native tool-call support.\n const turns: string[] = [];\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const content = Array.isArray(msg.content)\n ? msg.content\n .map((b: any) => {\n if (b?.type === \"text\") {\n return b.text;\n }\n\n if (b?.type === \"tool_result\") {\n return `[TOOL_RESULT ${b.tool_use_id}] ${String(b.content || \"\")}`;\n }\n\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\")\n : String(msg.content || \"\");\n if (content) {\n turns.push(content);\n }\n } else if (msg.role === \"assistant\") {\n // Skip — LiteRT conversation is stateful; assistant turns are generated\n // by the model itself.\n }\n }\n\n return { preface, turns };\n}\n\n/**\n * Main entry point. Invokes the LiteRT-LM browser engine and streams the\n * response back via the emit callback, following the same protocol as\n * invokeWithTransformersJs / invokeWithPromptApi.\n *\n * When `tools` is non-empty the provider enters an agentic loop:\n * 1. Append JSON-envelope tool instructions to the system prompt.\n * 2. Parse the model's full response for a tool_use or response envelope.\n * 3. If tool_use: execute the tools, append results, loop.\n * 4. If response (or plain text): emit the final text and return.\n */\nexport async function invokeWithLiteRtLm(\n db: ShadowClawDatabase,\n groupId: string,\n systemPrompt: string,\n messages: any[],\n _maxTokens: number,\n emit: (message: any) => Promise<void> | void,\n abortSignal: AbortSignal | undefined,\n modelId: string,\n tools?: ToolDefinition[],\n invokeContext?: SubagentInvokeContext,\n) {\n if (!isLiteRtLmSupported()) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: \"⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.\",\n },\n });\n\n return;\n }\n\n await emit(\n createLogMessage(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: LiteRT-LM (Browser · WebGPU) · Model: ${modelId}`,\n ),\n );\n\n // Emit model-download-progress so the UI shows a loading state\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"running\",\n progress: 0,\n message: `Loading LiteRT-LM model: ${modelId}…`,\n },\n });\n\n const formatMb = (bytes: number) => (bytes / (1024 * 1024)).toFixed(0);\n\n let lastEmittedPct = -1;\n\n const onProgress: LiteRtProgressCallback = (received, total, fromCache) => {\n const progress = total ? received / total : null;\n const pct = progress != null ? Math.floor(progress * 100) : -1;\n\n if (pct === lastEmittedPct && !fromCache) {\n return;\n }\n\n lastEmittedPct = pct;\n\n const message = fromCache\n ? `Loaded ${modelId} from cache (${formatMb(received)} MB )`\n : total\n ? `Downloading ${modelId}: ${formatMb(received)} / ${formatMb(total)} MB`\n : `Downloading ${modelId}: ${formatMb(received)} MB`;\n\n void emit({\n type: \"model-download-progress\",\n payload: { groupId, status: \"running\", progress, message },\n });\n };\n\n let engine: any;\n\n try {\n engine = await getLiteRtEngine(modelId, onProgress, abortSignal);\n } catch (err: any) {\n if (abortSignal?.aborted || err?.name === \"AbortError\") {\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"error\",\n progress: null,\n message: \"LiteRT-LM model download cancelled.\",\n },\n });\n\n return;\n }\n\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"error\",\n progress: null,\n message: `LiteRT-LM model failed to load: ${err?.message ?? String(err)}`,\n },\n });\n\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM failed to initialize: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n await emit({\n type: \"model-download-progress\",\n payload: {\n groupId,\n status: \"done\",\n progress: 1,\n message: \"LiteRT-LM model ready.\",\n },\n });\n\n const activeTools = tools ?? [];\n\n const { preface, turns } = buildLiteRtMessages(\n systemPrompt,\n messages,\n activeTools,\n );\n\n let conversation: any;\n try {\n conversation = await engine.createConversation({\n preface: { messages: preface },\n });\n } catch (err: any) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM failed to create conversation: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n // Replay prior turns (if any) — LiteRT-LM conversation is stateful.\n // All turns except the final user turn are sent non-streaming.\n const priorTurns = turns.slice(0, -1);\n const lastTurn = turns[turns.length - 1] ?? \"Hello.\";\n\n for (const turn of priorTurns) {\n if (abortSignal?.aborted) {\n return;\n }\n\n try {\n await conversation.sendMessage(turn);\n } catch {\n // If replaying history fails, continue to latest turn anyway\n }\n }\n\n if (abortSignal?.aborted) {\n return;\n }\n\n // ── Agentic tool-calling loop ─────────────────────────────────────────────\n // We maintain a mutable list of messages that grows as tool results arrive,\n // and re-send the current user query on each iteration (with tool results\n // appended) until the model emits a plain response or we hit the limit.\n const MAX_ITERATIONS = 10;\n let currentTurn = lastTurn;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n if (abortSignal?.aborted) {\n return;\n }\n\n await emit({ type: \"streaming-start\", payload: { groupId } });\n\n let accumulated = \"\";\n try {\n const stream = conversation.sendMessageStreaming(currentTurn);\n for await (const chunk of stream) {\n if (abortSignal?.aborted) {\n break;\n }\n\n const text = chunk?.content?.[0]?.text ?? \"\";\n if (text) {\n const cleaned = sanitizeModelOutput(text, \"litert_lm\");\n if (cleaned) {\n accumulated += cleaned;\n // Stream chunks to the UI so the user sees partial output\n await emit({\n type: \"streaming-chunk\",\n payload: { groupId, text: cleaned },\n });\n }\n }\n }\n } catch (err: any) {\n if (abortSignal?.aborted) {\n return;\n }\n\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: `⚠️ LiteRT-LM generation error: ${err?.message ?? String(err)}`,\n },\n });\n\n return;\n }\n\n // ── Parse the accumulated output ───────────────────────────────────────\n const parsed =\n activeTools.length > 0 ? parseLiteRtStructured(accumulated) : null;\n\n if (parsed?.type === \"tool_use\") {\n // Tool call detected — hide the raw JSON from the user.\n await emit({ type: \"streaming-end\", payload: { groupId } });\n\n const calls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];\n if (calls.length === 0) {\n // Malformed tool_use with no calls — treat as final response.\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text: \"(no response)\" },\n });\n await emit({\n type: \"response\",\n payload: { groupId, text: \"(no response)\" },\n });\n\n return;\n }\n\n // Execute each tool and collect results.\n const resultLines: string[] = [];\n const isNative = parsed.format === \"model_specific\";\n\n for (const call of calls) {\n await emit(createToolActivityMessage(groupId, call.name, \"running\"));\n // LiteRT-LM runs on the main thread (emit === handleWorkerMessage).\n // Route builtin-AI cross-thread requests (e.g. summarize_text's\n // \"request-native-ai-task\") back through emit so the main-thread\n // handler rseolves them; otherwise post() fails through to\n // self.postMessage and the tool promise hangs forever. Matches the\n // transformers-js / prompt-api providers.\n setPostHandler((msg) => {\n void emit(msg);\n });\n\n let output: any;\n try {\n output = await executeTool(db, call.name, call.input || {}, groupId, {\n allowedTools: activeTools,\n invokeContext,\n });\n } catch (err: any) {\n output = `Error: ${err?.message ?? String(err)}`;\n } finally {\n setPostHandler(null);\n }\n\n await emit(createToolActivityMessage(groupId, call.name, \"done\"));\n\n const resultText =\n typeof output === \"string\" ? output : JSON.stringify(output);\n\n if (isNative) {\n resultLines.push(`<|tool_response>${resultText}<|tool_response|>`);\n } else {\n resultLines.push(\n `[TOOL_RESULT ${call.id ?? call.name}] ${resultText}`,\n );\n }\n }\n\n // Feed results back to the model as the next turn.\n if (isNative) {\n currentTurn = resultLines.join(\"\\n\");\n } else {\n const lastUserContent = turns[turns.length - 1] ?? \"\";\n currentTurn = [\n ...resultLines,\n \"\",\n \"Based on the above tool results, please respond to the original request.\",\n lastUserContent ? `Original request: \"${lastUserContent}\"` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n continue; // next iteration\n }\n\n // ── Plain text or JSON response envelope ─────────────────────────────\n let finalText: string;\n if (parsed?.type === \"response\" && parsed.response) {\n finalText = sanitizeModelOutput(parsed.response, \"litert_lm\");\n } else {\n // No recognised structure — treat accumulated text as the answer.\n finalText = sanitizeModelOutput(accumulated, \"litert_lm\");\n }\n\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text: finalText },\n });\n\n await emit({\n type: \"response\",\n payload: { groupId, text: finalText },\n });\n\n return;\n }\n\n // Exhausted iterations without a plain-text response.\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: \"⚠️ LiteRT-LM reached the maximum number of tool-calling iterations without producing a final response.\",\n },\n });\n}\n","import { CONFIG_KEYS } from \"../../config/config.js\";\nimport { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\nimport { ShadowClawDatabase } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { toTrustedScriptUrl } from \"../../security/trusted-types.js\";\nimport { createLogMessage } from \"../../worker/utils/createLogMessage.js\";\nimport { createToolActivityMessage } from \"../../worker/utils/createToolActivityMessage.js\";\nimport { executeTool } from \"../../worker/utils/executeTool.js\";\nimport { setPostHandler } from \"../../worker/utils/post.js\";\nimport { ToolDefinition } from \"../tools/tools.js\";\n\nimport type { SubagentInvokeContext } from \"../../worker/tools/spawn-subagent/spawn-subagent.js\";\n\nclass TransformersJsManager {\n private chunkCallbacks = new Map<string, (payload: any) => void>();\n private loadRejects = new Map<string, (reason: any) => void>();\n private loadResolves = new Map<string, () => void>();\n private pendingRejects = new Map<string, (reason: any) => void>();\n private pendingResolves = new Map<string, (value: any) => void>();\n private progressCallbacks = new Map<string, (payload: any) => void>();\n private thinkingCallbacks = new Map<string, (text: string) => void>();\n private worker: Worker | null = null;\n\n async generate(\n messages: any[],\n maxTokens: number,\n groupId: string,\n onChunk: (text: string) => void,\n onThinking?: (text: string) => void,\n tools?: any[],\n ): Promise<string> {\n const worker = this.getWorker();\n\n return new Promise((resolve, reject) => {\n this.pendingResolves.set(groupId, resolve);\n this.pendingRejects.set(groupId, reject);\n this.chunkCallbacks.set(groupId, (payload) => onChunk(payload.text));\n if (onThinking) {\n this.thinkingCallbacks.set(groupId, onThinking);\n }\n\n worker.postMessage({\n type: \"generate\",\n payload: { messages, maxTokens, groupId, tools },\n });\n });\n }\n\n async load(\n modelId: string,\n device: string,\n dtypeStrategy: string,\n groupId: string,\n onProgress: (payload: any) => void,\n ): Promise<void> {\n const worker = this.getWorker();\n\n return new Promise((resolve, reject) => {\n this.loadResolves.set(groupId, resolve);\n this.loadRejects.set(groupId, reject);\n this.progressCallbacks.set(groupId, onProgress);\n worker.postMessage({\n type: \"load\",\n payload: { modelId, device, dtypeStrategy, groupId },\n });\n });\n }\n\n private cleanup(groupId: string) {\n this.pendingResolves.delete(groupId);\n this.pendingRejects.delete(groupId);\n this.progressCallbacks.delete(groupId);\n this.chunkCallbacks.delete(groupId);\n this.thinkingCallbacks.delete(groupId);\n }\n\n private getWorker() {\n if (!this.worker) {\n this.worker = new Worker(\n toTrustedScriptUrl(\n new URL(\"./transformers-js.worker.js\", import.meta.url).href,\n ) as string,\n {\n type: \"module\",\n },\n );\n this.worker.onmessage = (event) => {\n const { type, payload } = event.data;\n const groupId = payload?.groupId;\n\n switch (type) {\n case \"progress\":\n this.progressCallbacks.get(groupId)?.(payload);\n if (payload.status === \"done\") {\n this.loadResolves.get(groupId)?.();\n this.loadResolves.delete(groupId);\n this.loadRejects.delete(groupId);\n }\n\n break;\n case \"chunk\":\n this.chunkCallbacks.get(groupId)?.(payload);\n\n break;\n case \"thinking-chunk\":\n this.thinkingCallbacks.get(groupId)?.(payload.text);\n\n break;\n case \"done\":\n this.pendingResolves.get(groupId)?.(payload.text);\n this.cleanup(groupId);\n\n break;\n case \"error\":\n this.pendingRejects.get(groupId)?.(payload.error);\n this.loadRejects.get(groupId)?.(payload.error);\n this.cleanup(groupId);\n this.loadResolves.delete(groupId);\n this.loadRejects.delete(groupId);\n\n break;\n }\n };\n }\n\n return this.worker;\n }\n}\n\nconst manager = new TransformersJsManager();\n\nfunction formatMessageContent(msg: any): string {\n if (typeof msg?.content === \"string\") {\n return msg.content;\n }\n\n if (Array.isArray(msg?.content)) {\n return msg.content\n .map((block: any) => {\n if (block?.type === \"text\") {\n return block.text || \"\";\n }\n if (block?.type === \"tool_use\") {\n return `[TOOL_CALL ${block.name}] ${JSON.stringify(block.input || {})}`;\n }\n if (block?.type === \"tool_result\") {\n return `[TOOL_RESULT ${block.tool_use_id}] ${String(block.content || \"\")}`;\n }\n if (block?.type === \"attachment\") {\n return `[ATTACHMENT ${block.mediaType}] ${block.fileName} (${block.mimeType})`;\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n return \"\";\n}\n\nfunction parseStructured(raw: string) {\n const text = sanitizeModelOutput(String(raw || \"\"), \"transformers_js\").trim();\n if (!text) {\n return null;\n }\n\n // Check for Qwen/Llama XML-like tool calls: <tool_call>{\"name\": \"...\", \"arguments\": ...}</tool_call>\n const toolCallMatch = text.match(/<tool_call>([\\s\\S]*?)<\\/tool_call>/);\n if (toolCallMatch) {\n try {\n const parsedTool = JSON.parse(toolCallMatch[1]);\n if (parsedTool.name) {\n return {\n type: \"tool_use\",\n tool_calls: [\n {\n name: parsedTool.name,\n input: parsedTool.arguments || parsedTool.parameters || {},\n },\n ],\n };\n }\n } catch {\n // fallback to other parsing if invalid JSON\n }\n }\n\n try {\n return JSON.parse(text);\n } catch {\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n try {\n return JSON.parse(text.slice(start, end + 1));\n } catch {\n return null;\n }\n }\n\n return null;\n }\n}\n\nexport async function invokeWithTransformersJs(\n db: ShadowClawDatabase,\n groupId: string,\n systemPrompt: string,\n messages: any[],\n maxTokens: number,\n emit: (message: any) => Promise<void> | void,\n _abortSignal: AbortSignal | undefined,\n tools: ToolDefinition[] | undefined,\n modelId: string,\n invokeContext?: SubagentInvokeContext,\n) {\n const activeTools = tools || [];\n const backend =\n (await getConfig(db, CONFIG_KEYS.TRANSFORMERS_JS_BACKEND)) || \"auto\";\n const dtypeStrategy =\n (await getConfig(db, CONFIG_KEYS.TRANSFORMERS_JS_DTYPE_STRATEGY)) || \"auto\";\n\n await emit(\n createLogMessage(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: Transformers.js (Local Worker) · Model: ${modelId} · Backend: ${backend} · Dtype: ${dtypeStrategy}`,\n ),\n );\n\n await manager.load(modelId, backend, dtypeStrategy, groupId, (payload) => {\n void emit({ type: \"model-download-progress\", payload });\n });\n\n let currentMessages = [...messages];\n\n for (let i = 0; i < 10; i++) {\n const systemMessage = {\n role: \"system\",\n content: systemPrompt,\n };\n\n const structuredMessages = [\n systemMessage,\n ...currentMessages.map((m) => ({\n role: m.role === \"assistant\" ? \"assistant\" : \"user\",\n content: formatMessageContent(m),\n })),\n ];\n\n await emit({ type: \"streaming-start\", payload: { groupId } });\n\n let thinkingBuffer = \"\";\n let accumulated = \"\";\n const response = await manager.generate(\n structuredMessages,\n maxTokens,\n groupId,\n (chunk) => {\n accumulated += chunk;\n void emit({\n type: \"streaming-chunk\",\n payload: { groupId, text: chunk },\n });\n },\n (thinkingChunk) => {\n thinkingBuffer += thinkingChunk;\n void emit(\n createLogMessage(groupId, \"text\", \"Thinking\", thinkingBuffer),\n );\n },\n activeTools,\n );\n\n await emit({ type: \"typing\", payload: { groupId } });\n\n const parsed = parseStructured(response);\n\n if (parsed?.type === \"tool_use\") {\n await emit({ type: \"streaming-end\", payload: { groupId } });\n } else {\n const text = parsed?.response\n ? sanitizeModelOutput(parsed.response, \"transformers_js\")\n : sanitizeModelOutput(response, \"transformers_js\");\n await emit({\n type: \"streaming-done\",\n payload: { groupId, text },\n });\n }\n\n if (!parsed || parsed.type === \"response\") {\n const text = parsed?.response\n ? sanitizeModelOutput(parsed.response, \"transformers_js\")\n : sanitizeModelOutput(response, \"transformers_js\");\n await emit({ type: \"response\", payload: { groupId, text } });\n\n return;\n }\n\n const calls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];\n if (calls.length === 0) {\n await emit({\n type: \"response\",\n payload: {\n groupId,\n text: sanitizeModelOutput(\n parsed.response || response,\n \"transformers_js\",\n ),\n },\n });\n\n return;\n }\n\n const toolResults: any[] = [];\n for (const call of calls) {\n await emit(createToolActivityMessage(groupId, call.name, \"running\"));\n setPostHandler((msg) => {\n emit(msg);\n });\n let output: any;\n try {\n output = await executeTool(db, call.name, call.input || {}, groupId, {\n allowedTools: activeTools,\n invokeContext,\n });\n } finally {\n setPostHandler(null);\n }\n\n await emit(createToolActivityMessage(groupId, call.name, \"done\"));\n\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: call.id || `call_${Date.now()}`,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n });\n }\n\n currentMessages.push({\n role: \"assistant\",\n content: [\n ...(parsed.response ? [{ type: \"text\", text: parsed.response }] : []),\n ...calls.map((c) => ({\n type: \"tool_use\",\n id: c.id || `call_${Date.now()}_${Math.random()}`,\n name: c.name,\n input: c.input || {},\n })),\n ] as any,\n });\n\n currentMessages.push({ role: \"user\", content: toolResults as any });\n }\n}\n","/**\n * Create a token-usage message object\n */\nexport function createTokenUsageMessage(\n groupId: string,\n usage: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n },\n contextLimit: number,\n): any {\n const inputTokens = usage.input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n\n return {\n type: \"token-usage\",\n payload: {\n groupId,\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreationTokens,\n totalTokens:\n inputTokens + outputTokens + cacheReadTokens + cacheCreationTokens,\n contextLimit,\n },\n };\n}\n","import { createLogMessage } from \"./createLogMessage.js\";\nimport { post } from \"./post.js\";\n\n/**\n * Log a message\n */\nexport function log(\n groupId: string,\n level:\n | \"info\"\n | \"api-call\"\n | \"tool\"\n | \"error\"\n | \"warning\"\n | \"tool-call\"\n | \"tool-result\"\n | \"text\",\n label: string,\n message?: string,\n): void {\n post(createLogMessage(groupId, level as any, label, message));\n}\n","/**\n * Parse a Server-Sent Events (SSE) stream from a ReadableStream.\n *\n * Yields parsed JSON data objects from `data:` lines, skipping `[DONE]`\n * sentinel and comment lines.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<any> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n if (signal?.aborted) {\n break;\n }\n\n const { done, value } = await reader.read();\n\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n\n // Keep the last incomplete part in the buffer\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const lines = part.split(\"\\n\");\n\n for (const line of lines) {\n // Skip empty lines and comments\n if (!line || line.startsWith(\":\")) {\n continue;\n }\n\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6).trim();\n\n // Skip the [DONE] sentinel\n if (data === \"[DONE]\") {\n continue;\n }\n\n try {\n yield JSON.parse(data);\n } catch {\n // Skip malformed JSON lines\n }\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import { post } from \"./post.js\";\n\nconst ONE_MINUTE_MS = 60_000;\n\nexport interface RateLimitConfig {\n callsPerMinute: number;\n autoAdapt: boolean;\n}\n\ninterface ProviderRateLimitState {\n recentCalls: number[];\n nextAllowedAt: number;\n remoteLimit: number | null;\n remoteRemaining: number | null;\n remoteResetAt: number | null;\n}\n\nconst stateByProvider = new Map<string, ProviderRateLimitState>();\n\nfunction getState(providerId: string): ProviderRateLimitState {\n const existing = stateByProvider.get(providerId);\n if (existing) {\n return existing;\n }\n\n const created: ProviderRateLimitState = {\n recentCalls: [],\n nextAllowedAt: 0,\n remoteLimit: null,\n remoteRemaining: null,\n remoteResetAt: null,\n };\n\n stateByProvider.set(providerId, created);\n\n return created;\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction parseHeaderNumber(raw: string | null): number | null {\n if (!raw) {\n return null;\n }\n\n const value = Number(raw.trim());\n if (!Number.isFinite(value)) {\n return null;\n }\n\n return value;\n}\n\nfunction parseRetryAfterMs(retryAfter: string | null): number | null {\n if (!retryAfter) {\n return null;\n }\n\n const trimmed = retryAfter.trim();\n const numeric = Number(trimmed);\n if (Number.isFinite(numeric)) {\n if (numeric <= 0) {\n return null;\n }\n\n return Math.round(numeric * 1000);\n }\n\n const dateMs = Date.parse(trimmed);\n if (!Number.isFinite(dateMs)) {\n return null;\n }\n\n const delta = dateMs - nowMs();\n\n return delta > 0 ? delta : null;\n}\n\nfunction parseResetAtMs(resetHeader: string | null): number | null {\n const numeric = parseHeaderNumber(resetHeader);\n if (numeric === null || numeric <= 0) {\n return null;\n }\n\n // 13-digit epoch milliseconds\n if (numeric >= 1_000_000_000_000) {\n return Math.round(numeric);\n }\n\n // 10-digit epoch seconds\n if (numeric >= 1_000_000_000) {\n return Math.round(numeric * 1000);\n }\n\n // Otherwise treat as delta seconds from now.\n\n return nowMs() + Math.round(numeric * 1000);\n}\n\nasync function waitWithAbort(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | null = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n\n const onAbort = () => {\n cleanup();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n signal?.removeEventListener(\"abort\", onAbort);\n };\n\n if (signal?.aborted) {\n onAbort();\n\n return;\n }\n\n signal?.addEventListener(\"abort\", onAbort);\n });\n}\n\nfunction computeManualWaitMs(\n state: ProviderRateLimitState,\n callsPerMinute: number,\n): number {\n if (!Number.isFinite(callsPerMinute) || callsPerMinute <= 0) {\n return 0;\n }\n\n const now = nowMs();\n state.recentCalls = state.recentCalls.filter(\n (ts) => now - ts < ONE_MINUTE_MS,\n );\n\n if (state.recentCalls.length < callsPerMinute) {\n return 0;\n }\n\n const oldest = state.recentCalls[0] || now;\n\n return Math.max(0, ONE_MINUTE_MS - (now - oldest));\n}\n\nfunction computeAutoWaitMs(state: ProviderRateLimitState): number {\n const now = nowMs();\n let waitMs = 0;\n\n if (state.nextAllowedAt > now) {\n waitMs = Math.max(waitMs, state.nextAllowedAt - now);\n }\n\n if (\n state.remoteRemaining !== null &&\n state.remoteRemaining <= 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n waitMs = Math.max(waitMs, state.remoteResetAt - now);\n }\n\n return waitMs;\n}\n\nexport async function waitForRateLimitSlot(\n providerId: string,\n groupId: string,\n config: RateLimitConfig,\n signal?: AbortSignal,\n): Promise<void> {\n const state = getState(providerId);\n\n while (true) {\n const manualWait = computeManualWaitMs(state, config.callsPerMinute);\n const autoWait = config.autoAdapt ? computeAutoWaitMs(state) : 0;\n const waitMs = Math.max(manualWait, autoWait);\n\n if (waitMs <= 0) {\n const now = nowMs();\n if (config.callsPerMinute > 0) {\n state.recentCalls.push(now);\n }\n\n if (\n config.autoAdapt &&\n state.remoteRemaining !== null &&\n state.remoteRemaining > 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n const msLeft = state.remoteResetAt - now;\n const slotsLeft = Math.max(1, state.remoteRemaining);\n const interval = Math.ceil(msLeft / slotsLeft);\n state.nextAllowedAt = Math.max(state.nextAllowedAt, now + interval);\n }\n\n return;\n }\n\n if (waitMs >= 1000) {\n post({\n type: \"thinking-log\",\n payload: {\n groupId,\n level: \"info\",\n label: \"Rate limiter\",\n message: `Waiting ${Math.ceil(waitMs / 1000)}s before next provider call to avoid 429s.`,\n timestamp: Date.now(),\n },\n });\n }\n\n await waitWithAbort(waitMs, signal);\n }\n}\n\ntype HeaderReader = {\n get(name: string): string | null;\n};\n\nexport function updateRateLimitFromHeaders(\n providerId: string,\n headers: HeaderReader | null | undefined,\n config: RateLimitConfig,\n): void {\n if (!config.autoAdapt) {\n return;\n }\n\n if (!headers || typeof headers.get !== \"function\") {\n return;\n }\n\n const state = getState(providerId);\n const now = nowMs();\n\n const limit = parseHeaderNumber(headers.get(\"x-ratelimit-limit\"));\n const remaining = parseHeaderNumber(headers.get(\"x-ratelimit-remaining\"));\n const resetAt = parseResetAtMs(headers.get(\"x-ratelimit-reset\"));\n\n if (limit !== null) {\n state.remoteLimit = Math.max(0, Math.floor(limit));\n }\n\n if (remaining !== null) {\n state.remoteRemaining = Math.max(0, Math.floor(remaining));\n }\n\n if (resetAt !== null) {\n state.remoteResetAt = resetAt;\n }\n\n const retryAfterMs = parseRetryAfterMs(headers.get(\"retry-after\"));\n if (retryAfterMs !== null) {\n state.nextAllowedAt = Math.max(state.nextAllowedAt, now + retryAfterMs);\n }\n\n if (\n state.remoteRemaining !== null &&\n state.remoteRemaining <= 0 &&\n state.remoteResetAt !== null &&\n state.remoteResetAt > now\n ) {\n state.nextAllowedAt = Math.max(state.nextAllowedAt, state.remoteResetAt);\n }\n}\n","import { sanitizeModelOutput } from \"../../content/chat-template-sanitizer.js\";\n\nimport type {\n ContentBlockAccumulator,\n StreamCallbacks,\n StreamFormat,\n} from \"./types.js\";\n\n/**\n * Accumulates streamed SSE chunks into a unified response object.\n *\n * Supports both OpenAI-format (choices[].delta) and Anthropic-format\n * (content_block_start / content_block_delta / message_delta) SSE streams.\n *\n * Emits callbacks for incremental text and tool-call progress.\n */\nexport class StreamAccumulator {\n callbacks: StreamCallbacks;\n contentBlocks: ContentBlockAccumulator[] = [];\n format: StreamFormat;\n stopReason: string = \"end_turn\";\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n } = {\n input_tokens: 0,\n output_tokens: 0,\n };\n\n #anthropicBlocks = new Map<number, ContentBlockAccumulator>();\n\n #openaiReasoningText: string = \"\";\n #openaiText: string = \"\";\n #openaiToolCalls = new Map<\n number,\n { id: string; name: string; args: string }\n >();\n\n constructor(format: StreamFormat, callbacks: StreamCallbacks = {}) {\n this.format = format;\n this.callbacks = callbacks;\n }\n\n /**\n * Build the final normalized response (same shape as parseResponse).\n */\n finalize(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n if (this.format === \"openai\" || this.format === \"mesh-llm\") {\n return this.#finalizeOpenAI();\n }\n\n return this.#finalizeAnthropic();\n }\n\n /**\n * Feed a single parsed SSE chunk into the accumulator.\n */\n push(chunk: any): void {\n if (this.format === \"openai\" || this.format === \"mesh-llm\") {\n this.#pushOpenAI(chunk);\n } else {\n this.#pushAnthropic(chunk);\n }\n }\n\n #finalizeAnthropic(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n const content: any[] = [];\n\n for (const [, block] of [...this.#anthropicBlocks.entries()].sort(\n (a, b) => a[0] - b[0],\n )) {\n if (block.type === \"text\") {\n const cleaned = this.#sanitize(block.text || \"\");\n if (cleaned) {\n content.push({ type: \"text\", text: cleaned });\n }\n } else if (block.type === \"tool_use\") {\n let input;\n try {\n input = block.partialJson ? JSON.parse(block.partialJson) : {};\n } catch {\n input = {};\n }\n\n content.push({\n type: \"tool_use\",\n id: block.id || `call_${Date.now()}_${Math.random()}`,\n name: block.name,\n input,\n });\n } else if (block.type === \"thinking\") {\n if (typeof block.text === \"string\" && block.text.length > 0) {\n content.push({\n type: \"thinking\",\n thinking: block.text,\n ...(typeof block.id === \"string\" ? { signature: block.id } : {}),\n });\n }\n } else if (block.type === \"redacted_thinking\") {\n if (typeof block.text === \"string\" && block.text.length > 0) {\n content.push({\n type: \"redacted_thinking\",\n data: block.text,\n });\n }\n }\n }\n\n return {\n content,\n stop_reason: this.stopReason,\n usage: { ...this.usage },\n };\n }\n\n #finalizeOpenAI(): {\n content: any[];\n stop_reason: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n } {\n const content: any[] = [];\n\n if (this.#openaiText) {\n const cleaned = this.#sanitize(this.#openaiText);\n if (cleaned) {\n content.push({ type: \"text\", text: cleaned });\n }\n }\n\n if (this.#openaiReasoningText) {\n content.unshift({\n type: \"thinking\",\n thinking: this.#openaiReasoningText,\n });\n }\n\n if (this.#openaiToolCalls.size > 0) {\n this.stopReason = \"tool_use\";\n\n for (const [, tc] of [...this.#openaiToolCalls.entries()].sort(\n (a, b) => a[0] - b[0],\n )) {\n let input;\n try {\n input = tc.args ? JSON.parse(tc.args) : {};\n } catch {\n input = {};\n }\n\n content.push({\n type: \"tool_use\",\n id: tc.id || `call_${Date.now()}_${Math.random()}`,\n name: tc.name,\n input,\n });\n }\n }\n\n return {\n content,\n stop_reason: this.stopReason,\n usage: { ...this.usage },\n };\n }\n\n #pushAnthropic(chunk: any): void {\n switch (chunk.type) {\n case \"message_start\": {\n if (chunk.message?.usage) {\n this.usage.input_tokens = chunk.message.usage.input_tokens || 0;\n this.usage.cache_read_input_tokens =\n chunk.message.usage.cache_read_input_tokens || 0;\n this.usage.cache_creation_input_tokens =\n chunk.message.usage.cache_creation_input_tokens || 0;\n }\n\n break;\n }\n\n case \"content_block_start\": {\n const idx = chunk.index ?? this.#anthropicBlocks.size;\n const block = chunk.content_block || {};\n\n this.#anthropicBlocks.set(idx, {\n type: block.type || \"text\",\n id: block.type === \"thinking\" ? block.signature : block.id,\n name: block.name,\n text: block.text || block.thinking || block.data || \"\",\n partialJson: block.type === \"tool_use\" ? \"\" : undefined,\n });\n\n if (block.type === \"tool_use\" && block.name) {\n this.callbacks.onToolStart?.(block.name);\n }\n\n break;\n }\n\n case \"content_block_delta\": {\n const idx = chunk.index ?? 0;\n let block = this.#anthropicBlocks.get(idx);\n if (!block) {\n const inferredType =\n chunk.delta?.type === \"input_json_delta\" ? \"tool_use\" : \"text\";\n\n block = {\n type: inferredType,\n text: inferredType === \"text\" ? \"\" : undefined,\n partialJson: inferredType === \"tool_use\" ? \"\" : undefined,\n };\n\n this.#anthropicBlocks.set(idx, block);\n }\n\n const delta = chunk.delta;\n if (!delta) {\n break;\n }\n\n if (delta.type === \"text_delta\" && typeof delta.text === \"string\") {\n const cleaned = this.#sanitize(delta.text);\n if (!cleaned) {\n break;\n }\n\n block.text = (block.text || \"\") + cleaned;\n this.callbacks.onText?.(cleaned);\n }\n\n if (\n delta.type === \"thinking_delta\" &&\n typeof delta.thinking === \"string\"\n ) {\n block.type = \"thinking\";\n block.text = (block.text || \"\") + delta.thinking;\n this.callbacks.onThinking?.(delta.thinking);\n }\n\n if (\n delta.type === \"signature_delta\" &&\n typeof delta.signature === \"string\"\n ) {\n block.type = \"thinking\";\n block.id = delta.signature;\n }\n\n if (\n delta.type === \"redacted_thinking_delta\" &&\n typeof delta.data === \"string\"\n ) {\n block.type = \"redacted_thinking\";\n block.text = (block.text || \"\") + delta.data;\n }\n\n if (\n delta.type === \"input_json_delta\" &&\n typeof delta.partial_json === \"string\"\n ) {\n block.partialJson = (block.partialJson || \"\") + delta.partial_json;\n }\n\n break;\n }\n\n case \"content_block_stop\":\n // No action needed; block is already accumulated\n\n break;\n\n case \"message_delta\": {\n if (chunk.delta?.stop_reason) {\n this.stopReason = chunk.delta.stop_reason;\n }\n\n if (chunk.usage) {\n this.usage.output_tokens = chunk.usage.output_tokens || 0;\n this.callbacks.onUsage?.(this.usage);\n }\n\n break;\n }\n\n case \"message_stop\":\n break;\n\n default:\n // Ignore ping, error events, etc.\n\n break;\n }\n }\n\n #pushOpenAI(chunk: any): void {\n // Handle usage in the final chunk (OpenAI includes it when stream_options.include_usage is set,\n // or in the last chunk for some providers)\n if (chunk.usage) {\n this.usage.input_tokens = chunk.usage.prompt_tokens || 0;\n this.usage.output_tokens = chunk.usage.completion_tokens || 0;\n this.usage.cache_read_input_tokens =\n chunk.usage.prompt_tokens_details?.cached_tokens || 0;\n this.callbacks.onUsage?.(this.usage);\n }\n\n const choice = chunk.choices?.[0];\n if (!choice) {\n return;\n }\n\n const delta = choice.delta;\n if (!delta) {\n return;\n }\n\n // Accumulate text content\n if (typeof delta.content === \"string\") {\n const cleaned = this.#sanitize(delta.content);\n if (cleaned) {\n this.#openaiText += cleaned;\n this.callbacks.onText?.(cleaned);\n }\n }\n\n // Accumulate reasoning content from OpenAI-compatible providers that expose\n // thought tokens separately from user-visible assistant text.\n if (typeof delta.reasoning === \"string\") {\n this.#openaiReasoningText += delta.reasoning;\n this.callbacks.onThinking?.(delta.reasoning);\n } else if (delta.reasoning && typeof delta.reasoning === \"object\") {\n const reasoningObj: any = delta.reasoning;\n if (typeof reasoningObj.content === \"string\") {\n this.#openaiReasoningText += reasoningObj.content;\n this.callbacks.onThinking?.(reasoningObj.content);\n } else if (typeof reasoningObj.text === \"string\") {\n this.#openaiReasoningText += reasoningObj.text;\n this.callbacks.onThinking?.(reasoningObj.text);\n }\n }\n\n // Accumulate tool calls\n if (Array.isArray(delta.tool_calls)) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index ?? 0;\n\n if (!this.#openaiToolCalls.has(idx)) {\n this.#openaiToolCalls.set(idx, {\n id: tc.id || \"\",\n name: tc.function?.name || \"\",\n args: \"\",\n });\n\n if (tc.function?.name) {\n this.callbacks.onToolStart?.(tc.function.name);\n }\n }\n\n const existing = this.#openaiToolCalls.get(idx);\n if (!existing) {\n continue;\n }\n\n if (tc.id) {\n existing.id = tc.id;\n }\n\n if (tc.function?.name) {\n existing.name = tc.function.name;\n }\n\n if (tc.function?.arguments) {\n existing.args += tc.function.arguments;\n }\n }\n }\n\n // Capture finish reason\n if (choice.finish_reason) {\n if (choice.finish_reason === \"tool_calls\") {\n this.stopReason = \"tool_use\";\n } else if (choice.finish_reason === \"stop\") {\n this.stopReason = \"end_turn\";\n } else {\n this.stopReason = choice.finish_reason;\n }\n }\n }\n\n #sanitize(text: string): string {\n return sanitizeModelOutput(text, this.callbacks.source ?? this.format);\n }\n}\n","import { ToolDefinition } from \"../../subsystems/tools/types.js\";\n\ninterface ToolState {\n enabledTools: ToolDefinition[];\n systemPromptOverride: string;\n}\n\n/**\n * Worker-side tool state cache per groupId.\n * This allows the worker to reflect tool management changes in the middle\n * of an agent invocation loop.\n */\nconst toolStateMap = new Map<string, ToolState>();\n\nexport function setToolState(\n groupId: string,\n enabledTools: ToolDefinition[],\n systemPromptOverride: string,\n) {\n toolStateMap.set(groupId, { enabledTools, systemPromptOverride });\n}\n\nexport function getToolState(groupId: string): ToolState | undefined {\n return toolStateMap.get(groupId);\n}\n\nexport function clearToolState(groupId: string) {\n toolStateMap.delete(groupId);\n}\n","import {\n DEFAULT_MAX_ITERATIONS,\n getProvider,\n ProviderConfig,\n} from \"../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../context/estimateTokens.js\";\n\nimport {\n buildHeaders,\n formatRequest,\n getContextLimit,\n normalizeMeshLlmResult,\n parseResponse,\n} from \"../../subsystems/providers/providers.js\";\n\nimport { setStorageRoot } from \"../../storage/storage.js\";\nimport { TOOL_DEFINITIONS } from \"../../subsystems/tools/tools.js\";\nimport { createTokenUsageMessage } from \"./createTokenUsageMessage.js\";\nimport { createToolActivityMessage } from \"./createToolActivityMessage.js\";\nimport { executeTool } from \"./executeTool.js\";\nimport { log } from \"./log.js\";\nimport { parseSSEStream } from \"./parseSSEStream.js\";\n\nimport {\n post,\n registerSubagentCollector,\n unregisterSubagentCollector,\n} from \"./post.js\";\n\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport {\n RateLimitConfig,\n updateRateLimitFromHeaders,\n waitForRateLimitSlot,\n} from \"./rate-limit.js\";\n\nimport { ContentBlock, ToolResultContentBlock } from \"../../content/types.js\";\nimport { dispatchSubagentInvoke } from \"../../core/orchestrator/utils/dispatchSubagentInvoke.js\";\nimport { InvokePayload } from \"../../subsystems/worker/types.js\";\nimport { StreamAccumulator } from \"../StreamAccumulator/StreamAccumulator.js\";\nimport { StreamFormat } from \"../StreamAccumulator/types.js\";\n\nimport { buildSystemPrompt } from \"./system-prompt.js\";\nimport { clearToolState, getToolState } from \"./tool-state.js\";\nimport { isRetryableHttpError, withRetry } from \"./withRetry.js\";\n\nimport type { SubagentInvokeContext, ToolResult } from \"./executeTool.js\";\n\n/**\n * Throttle interval (ms) for streaming text chunks sent to the UI.\n * Keeps the main thread responsive during fast token delivery.\n */\nconst STREAM_THROTTLE_MS = 50;\n\ntype ParsedToolCodeBlock = {\n toolBlocks: Array<{\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, any>;\n }>;\n residualText: string;\n};\n\nfunction parseToolCodeBlock(\n text: string,\n allowedToolNames: Set<string>,\n): ParsedToolCodeBlock {\n const trimmed = text.trim();\n const wrappedMatch = trimmed.match(\n /^\\[tool_code\\]([\\s\\S]*?)\\[\\/tool_code\\]$/i,\n );\n if (!wrappedMatch?.[1]) {\n return { toolBlocks: [], residualText: text };\n }\n\n const body = wrappedMatch[1].trim();\n\n const printMatch = body.match(\n /^print\\s*\\(\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(\\s*(.*?)\\s*\\)\\s*\\)$/s,\n );\n\n const directMatch = body.match(\n /^([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(\\s*(.*?)\\s*\\)$/s,\n );\n\n const match = printMatch || directMatch;\n if (!match?.[1]) {\n return { toolBlocks: [], residualText: text };\n }\n\n const toolName = match[1];\n if (!allowedToolNames.has(toolName)) {\n return { toolBlocks: [], residualText: text };\n }\n\n const rawArgs = (match[2] || \"\").trim();\n let input: Record<string, any> = {};\n if (rawArgs) {\n if (!rawArgs.startsWith(\"{\") || !rawArgs.endsWith(\"}\")) {\n return { toolBlocks: [], residualText: text };\n }\n\n try {\n const parsed = JSON.parse(rawArgs);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return { toolBlocks: [], residualText: text };\n }\n\n input = parsed as Record<string, any>;\n } catch {\n return { toolBlocks: [], residualText: text };\n }\n }\n\n return {\n toolBlocks: [\n {\n type: \"tool_use\",\n id: `tool_code_${Date.now()}_${Math.random()}`,\n name: toolName,\n input,\n },\n ],\n residualText: \"\",\n };\n}\n\nfunction normalizeToolCodeResponses(result: any, enabledTools: any[]): any {\n if (\n !result ||\n result.stop_reason === \"tool_use\" ||\n !Array.isArray(result.content)\n ) {\n return result;\n }\n\n const allowedToolNames = new Set(\n (enabledTools || [])\n .map((tool: any) => (typeof tool?.name === \"string\" ? tool.name : \"\"))\n .filter(Boolean),\n );\n\n if (allowedToolNames.size === 0) {\n return result;\n }\n\n const normalizedContent: any[] = [];\n let convertedAny = false;\n\n for (const block of result.content) {\n if (block?.type !== \"text\" || typeof block.text !== \"string\") {\n normalizedContent.push(block);\n\n continue;\n }\n\n const parsed = parseToolCodeBlock(block.text, allowedToolNames);\n if (parsed.toolBlocks.length > 0) {\n convertedAny = true;\n if (parsed.residualText.trim()) {\n normalizedContent.push({ type: \"text\", text: parsed.residualText });\n }\n\n normalizedContent.push(...parsed.toolBlocks);\n\n continue;\n }\n\n normalizedContent.push(block);\n }\n\n if (!convertedAny) {\n return result;\n }\n\n return {\n ...result,\n content: normalizedContent,\n stop_reason: \"tool_use\",\n };\n}\n\nfunction buildToolResultsFallbackText(toolResults: ContentBlock[]): string {\n const lines = toolResults\n .filter((entry) => entry?.type === \"tool_result\")\n .map((entry) => {\n if (typeof (entry as any).content === \"string\") {\n return (entry as any).content.trim();\n }\n\n if (Array.isArray((entry as any).content)) {\n return ((entry as any).content as ToolResultContentBlock[])\n .filter((block) => block.type === \"text\")\n .map((block) => (block as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n .trim();\n }\n\n return JSON.stringify((entry as any).content).trim();\n })\n .filter(Boolean);\n\n if (lines.length === 0) {\n return \"\";\n }\n\n return lines.join(\"\\n\\n\").slice(0, 10_000);\n}\n\nfunction formatToolFallbackResponseText(text: string): string {\n const trimmed = text.trim();\n if (!trimmed) {\n return \"\";\n }\n\n return `Tool result:\\n${trimmed}`;\n}\n\n/**\n * Handle agent invocation with tool-use loop\n */\nexport async function handleInvoke(\n db: any,\n payload: InvokePayload & { isScheduledTask?: boolean },\n abortSignal?: AbortSignal,\n): Promise<void> {\n const {\n apiKey,\n assistantName,\n contextCompression = false,\n contextLimit: payloadContextLimit,\n enabledTools,\n groupId: originalGroupId,\n isScheduledTask = false,\n maxIterations: payloadMaxIterations,\n maxTokens,\n memory,\n messages,\n model,\n provider: providerId,\n providerHeaders = {},\n providerRuntimeOverrides,\n reasoning,\n rateLimitAutoAdapt = true,\n rateLimitCallsPerMinute = 0,\n storageHandle,\n streaming = false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedModel,\n subagentPinnedProvider,\n systemPrompt,\n workspaceGroupId,\n } = payload;\n\n const isSubagentTask = !!payload.subagentTask;\n const groupId = isSubagentTask\n ? originalGroupId.startsWith(\"subagent:\")\n ? originalGroupId\n : `subagent:${ulid()}`\n : originalGroupId;\n const effectiveWorkspaceGroupId = workspaceGroupId || originalGroupId;\n\n if (isSubagentTask) {\n registerSubagentCollector(groupId, []);\n }\n\n const rateLimitConfig: RateLimitConfig = {\n autoAdapt: rateLimitAutoAdapt !== false,\n callsPerMinute: Number.isFinite(rateLimitCallsPerMinute)\n ? Math.max(0, Math.floor(rateLimitCallsPerMinute))\n : 0,\n };\n\n if (storageHandle) {\n setStorageRoot(storageHandle);\n }\n\n const provider = getProvider(providerId);\n if (!provider) {\n post({\n payload: { groupId, error: `Unknown provider: ${providerId}` },\n type: \"error\",\n });\n\n return;\n }\n\n const typedProvider = provider as ProviderConfig;\n\n // Determine whether we can actually use streaming for this provider.\n const useStreaming =\n streaming &&\n typedProvider.supportsStreaming === true &&\n typedProvider.format !== \"prompt_api\";\n\n post({ type: \"typing\", payload: { groupId } });\n\n log(\n groupId,\n \"info\",\n \"Starting\",\n `Provider: ${typedProvider.name} · Model: ${model} · Max tokens: ${maxTokens} · Streaming: ${useStreaming ? \"on\" : \"off\"}${streaming && !useStreaming ? \" (provider does not support streaming)\" : \"\"}`,\n );\n\n try {\n let currentMessages = [...messages];\n let iterations = 0;\n\n const maxIterations =\n typeof payloadMaxIterations === \"number\" && payloadMaxIterations > 0\n ? payloadMaxIterations\n : DEFAULT_MAX_ITERATIONS;\n\n let currentTools = Array.isArray(enabledTools)\n ? enabledTools\n : TOOL_DEFINITIONS;\n\n let currentSystemPrompt = systemPrompt;\n let latestToolResultsFallbackText = \"\";\n\n // Build the invoke context for spawn_subagent to inherit\n const invokeContext: SubagentInvokeContext = {\n apiKey,\n assistantName: assistantName ?? \"\",\n db,\n enabledTools: currentTools as any,\n invokeSubagent: (subPayload) =>\n dispatchSubagentInvoke(db, subPayload, abortSignal),\n maxTokens,\n memory: memory ?? \"\",\n model,\n provider: providerId,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n providerHeaders,\n providerRuntimeOverrides,\n storageHandle,\n streaming: false, // subagents always use non-streaming for clean capture\n systemPrompt: currentSystemPrompt ?? \"\",\n };\n\n // Track exact tool calls to prevent loops\n const toolCallHistory: string[] = [];\n\n while (iterations < maxIterations) {\n iterations++;\n\n // Check for mid-invocation tool updates from main thread\n const updatedState = getToolState(groupId);\n if (updatedState) {\n currentTools = updatedState.enabledTools;\n currentSystemPrompt = buildSystemPrompt(\n assistantName,\n memory,\n currentTools,\n updatedState.systemPromptOverride,\n );\n }\n\n const contextLimit = payloadContextLimit ?? getContextLimit(model);\n const systemPromptTokens = estimateTokens(currentSystemPrompt);\n\n // Re-evaluate context dynamically for each API call to handle large tool outputs\n const { messages: payloadMessages, estimatedTokens } =\n buildDynamicContext(currentMessages as any, {\n contextLimit,\n maxOutputTokens: maxTokens,\n skimTop: contextCompression,\n systemPromptTokens,\n });\n\n // Strict proxy boundaries (e.g. Azure OpenAI) calculate: prompt_tokens + max_tokens <= context_window.\n const SAFETY_BUFFER = 500;\n const totalPromptEstimate =\n (estimatedTokens as number) + systemPromptTokens;\n\n // Mathematically guarantee we don't overflow the strict provider budget\n const safeMaxTokens = Math.max(\n 100, // floor\n Math.min(maxTokens, contextLimit - totalPromptEstimate - SAFETY_BUFFER),\n );\n\n const body = formatRequest(\n typedProvider,\n payloadMessages,\n currentTools as any,\n {\n contextCompression,\n maxTokens: safeMaxTokens,\n model,\n reasoning,\n system: currentSystemPrompt,\n },\n );\n\n log(\n groupId,\n \"api-call\",\n `API call #${iterations}`,\n `${payloadMessages.length} messages in context`,\n );\n\n const headers = {\n ...buildHeaders(typedProvider, apiKey),\n ...providerHeaders,\n };\n\n const url = typedProvider.baseUrl;\n\n let result: any;\n\n if (useStreaming) {\n result = await callWithStreaming(\n providerId,\n typedProvider,\n url,\n headers,\n body,\n groupId,\n model,\n rateLimitConfig,\n abortSignal,\n );\n } else {\n result = await callApi(\n providerId,\n typedProvider,\n url,\n headers,\n body,\n groupId,\n rateLimitConfig,\n abortSignal,\n );\n }\n\n result = normalizeToolCodeResponses(result, currentTools as any[]);\n\n // Emit token usage\n if (result.usage) {\n post(\n createTokenUsageMessage(\n groupId,\n result.usage,\n getContextLimit(model),\n ),\n );\n }\n\n // Log text blocks\n for (const block of result.content) {\n if (block.type === \"text\" && block.text) {\n const preview =\n block.text.length > 200\n ? block.text.slice(0, 200) + \"…\"\n : block.text;\n\n log(groupId, \"text\", \"Response text\", preview);\n }\n }\n\n if (result.stop_reason === \"tool_use\") {\n const allowedToolNames = new Set(\n (currentTools as any[])\n .map((tool: any) =>\n typeof tool?.name === \"string\" ? tool.name : \"\",\n )\n .filter(Boolean),\n );\n\n // If the response includes text alongside tool calls, persist it\n const intermediateText = result.content\n .filter((b: any) => b.type === \"text\")\n .map((b: any) => b.text)\n .join(\"\")\n .replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\")\n .trim();\n\n if (intermediateText) {\n post({\n payload: { groupId, text: intermediateText },\n type: \"intermediate-response\",\n });\n }\n\n // If we were streaming text before tool calls, clear the streaming bubble\n if (useStreaming) {\n post({\n payload: { groupId },\n type: \"streaming-end\",\n });\n }\n\n // Execute tool calls\n const toolResults: ContentBlock[] = [];\n for (const block of result.content) {\n if (block.type === \"tool_use\") {\n const isAllowed = allowedToolNames.has(block.name);\n\n // Prevent infinite loops by detecting repeated identical tool calls\n const toolCallSignature = `${block.name}:${JSON.stringify(block.input)}`;\n const timesCalled = toolCallHistory.filter(\n (s) => s === toolCallSignature,\n ).length;\n\n toolCallHistory.push(toolCallSignature);\n\n if (!isAllowed) {\n const blockedMessage =\n `SYSTEM ERROR: Tool '${block.name}' is disabled or unavailable for this request. ` +\n \"Do not call it again. Try a different approach or ask the user for help.\";\n\n log(groupId, \"warning\", \"Tool blocked\", blockedMessage);\n\n toolResults.push({\n content: blockedMessage,\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n\n continue;\n }\n\n const inputPreview = JSON.stringify(block.input);\n const inputShort =\n inputPreview.length > 300\n ? inputPreview.slice(0, 300) + \"…\"\n : inputPreview;\n\n log(groupId, \"tool-call\", `Tool: ${block.name}`, inputShort);\n\n post(createToolActivityMessage(groupId, block.name, \"running\"));\n\n let output: ToolResult;\n if (timesCalled >= 3) {\n output = `SYSTEM ERROR: You have repeatedly called this tool with the exact same input (${timesCalled + 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.`;\n\n console.warn(\n `[Worker] Blocked repetitive tool call:`,\n toolCallSignature,\n );\n } else {\n output = await executeTool(\n db,\n block.name,\n block.input,\n effectiveWorkspaceGroupId,\n {\n allowedTools: currentTools,\n isScheduledTask,\n invokeContext,\n },\n );\n }\n\n const outputStr =\n typeof output === \"string\" ? output : JSON.stringify(output);\n\n const outputShort =\n outputStr.length > 500\n ? outputStr.slice(0, 500) + \"…\"\n : outputStr;\n\n log(groupId, \"tool-result\", `Result: ${block.name}`, outputShort);\n\n post(createToolActivityMessage(groupId, block.name, \"done\"));\n\n if (Array.isArray(output)) {\n toolResults.push({\n content: output as ToolResultContentBlock[],\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n } else {\n toolResults.push({\n content:\n typeof output === \"string\"\n ? output.slice(0, 100_000)\n : JSON.stringify(output).slice(0, 100_000),\n tool_use_id: block.id,\n type: \"tool_result\",\n });\n }\n }\n }\n\n // Continue conversation with tool results\n latestToolResultsFallbackText =\n buildToolResultsFallbackText(toolResults);\n\n currentMessages.push({ role: \"assistant\", content: result.content });\n currentMessages.push({ role: \"user\", content: toolResults as any });\n\n post({ type: \"typing\", payload: { groupId } });\n } else {\n // Final response\n const text = result.content\n .filter((b: any) => b.type === \"text\")\n .map((b: any) => b.text)\n .join(\"\");\n\n const cleaned = text\n .replace(/<internal>[\\s\\S]*?<\\/internal>/g, \"\")\n .trim();\n\n const isPlaceholderOnly = cleaned.toLowerCase() === \"(no response)\";\n const preferredModelText = isPlaceholderOnly ? \"\" : cleaned;\n const finalText = preferredModelText\n ? preferredModelText\n : latestToolResultsFallbackText\n ? formatToolFallbackResponseText(latestToolResultsFallbackText)\n : \"(no response)\";\n\n // If streaming was used, the text was already streamed chunk-by-chunk.\n if (useStreaming) {\n post({\n payload: { groupId, text: finalText },\n type: \"streaming-done\",\n });\n }\n\n post({\n payload: { groupId, text: finalText },\n type: \"response\",\n });\n\n return;\n }\n }\n\n // Max iterations reached\n post({\n payload: {\n text: `⚠️ Reached maximum tool-use iterations (${maxIterations}). Stopping to avoid excessive API usage.`,\n groupId,\n },\n type: \"response\",\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n\n // If we were streaming when the error occurred, preserve partial content\n if (useStreaming) {\n post({\n payload: { groupId, error: message },\n type: \"streaming-error\",\n });\n }\n\n post({ type: \"error\", payload: { groupId, error: message } });\n } finally {\n clearToolState(groupId);\n if (isSubagentTask) {\n unregisterSubagentCollector(groupId);\n }\n }\n}\n\n/**\n * Make a non-streaming LLM API call with retry.\n */\nasync function callApi(\n providerId: string,\n typedProvider: ProviderConfig,\n url: string,\n headers: Record<string, string>,\n body: any,\n groupId: string,\n rateLimitConfig: RateLimitConfig,\n abortSignal?: AbortSignal,\n): Promise<any> {\n return withRetry(\n async () => {\n await waitForRateLimitSlot(\n providerId,\n groupId,\n rateLimitConfig,\n abortSignal,\n );\n\n const res = await fetch(url, {\n body: JSON.stringify(body),\n headers,\n method: \"POST\",\n signal: abortSignal,\n });\n\n updateRateLimitFromHeaders(providerId, res.headers, rateLimitConfig);\n\n if (!res.ok) {\n const errBody = await res.text();\n const error = new Error(\n `${typedProvider.name} API error ${res.status}: ${errBody}`,\n );\n (error as any).status = res.status;\n\n throw error;\n }\n\n const rawResult = await res.json();\n\n return parseResponse(typedProvider, rawResult);\n },\n {\n baseDelayMs: 2000,\n jitterFactor: 0.5,\n maxDelayMs: 30_000,\n maxRetries: 3,\n onRetry: (_attempt, _maxRetries, _delayMs, _error) => {\n const errMsg =\n _error instanceof Error ? _error.message : String(_error);\n\n log(\n groupId,\n \"warning\",\n `Retrying API call (${_attempt}/${_maxRetries})`,\n errMsg,\n );\n\n post({\n type: \"show-toast\",\n payload: {\n message: `LLM API: Retrying (${_attempt}/${_maxRetries})… ${errMsg.slice(0, 120)}`,\n type: \"warning\",\n duration: 5000,\n },\n });\n },\n shouldRetry: (error) => isRetryableHttpError(error),\n signal: abortSignal,\n },\n );\n}\n\n/**\n * Make a streaming LLM API call.\n */\nasync function callWithStreaming(\n providerId: string,\n typedProvider: ProviderConfig,\n url: string,\n headers: Record<string, string>,\n body: any,\n groupId: string,\n model: string,\n rateLimitConfig: RateLimitConfig,\n abortSignal?: AbortSignal,\n): Promise<any> {\n // Add stream flag to the request body\n const streamBody = {\n ...body,\n stream: true,\n // For OpenAI-compatible APIs, request usage in the stream\n ...((typedProvider.format === \"openai\" ||\n typedProvider.format === \"mesh-llm\") && {\n stream_options: { include_usage: true },\n }),\n };\n\n await waitForRateLimitSlot(providerId, groupId, rateLimitConfig, abortSignal);\n\n const res = await fetch(url, {\n body: JSON.stringify(streamBody),\n headers,\n method: \"POST\",\n signal: abortSignal,\n });\n\n updateRateLimitFromHeaders(providerId, res.headers, rateLimitConfig);\n\n if (!res.ok) {\n const errBody = await res.text();\n const error = new Error(\n `${typedProvider.name} API error ${res.status}: ${errBody}`,\n );\n\n (error as any).status = res.status;\n\n throw error;\n }\n\n if (!res.body) {\n throw new Error(\"Streaming response has no body\");\n }\n\n // Signal the UI that a streaming response is starting\n post({\n payload: { groupId },\n type: \"streaming-start\",\n });\n\n let lastChunkTime = 0;\n let pendingText = \"\";\n let lastReasoningChunkTime = 0;\n let pendingReasoning = \"\";\n\n const flushReasoning = (force = false) => {\n const now = Date.now();\n if (!pendingReasoning) {\n return;\n }\n\n if (!force && now - lastReasoningChunkTime < STREAM_THROTTLE_MS) {\n return;\n }\n\n const message =\n pendingReasoning.length > 400\n ? `${pendingReasoning.slice(0, 400)}…`\n : pendingReasoning;\n\n log(groupId, \"info\", \"Reasoning\", message);\n pendingReasoning = \"\";\n lastReasoningChunkTime = now;\n };\n\n const accumulator = new StreamAccumulator(\n typedProvider.format as StreamFormat,\n {\n source: typedProvider.id,\n onText: (text) => {\n const now = Date.now();\n\n // Always buffer incoming text\n pendingText += text;\n\n // Flush to the UI only when the throttle interval has elapsed\n if (now - lastChunkTime >= STREAM_THROTTLE_MS) {\n post({\n payload: { groupId, text: pendingText },\n type: \"streaming-chunk\",\n });\n\n pendingText = \"\";\n lastChunkTime = now;\n }\n },\n onToolStart: (name) => {\n post(createToolActivityMessage(groupId, name, \"running\"));\n },\n onUsage: (usage) => {\n post(createTokenUsageMessage(groupId, usage, getContextLimit(model)));\n },\n onThinking: (text) => {\n pendingReasoning += text;\n flushReasoning(false);\n },\n },\n );\n\n for await (const chunk of parseSSEStream(res.body, abortSignal)) {\n accumulator.push(chunk);\n }\n\n // Flush any remaining buffered text that didn't make it through the throttle\n if (pendingText) {\n post({\n payload: { groupId, text: pendingText },\n type: \"streaming-chunk\",\n });\n }\n\n flushReasoning(true);\n\n let finalResult = accumulator.finalize();\n\n // Mesh LLM streams standard OpenAI SSE chunks but its assembled text may\n // contain proprietary markers for thoughts and tool calls.\n // We normalize the final assembled object before the agent loop consumes it.\n if (typedProvider.format === \"mesh-llm\") {\n finalResult = normalizeMeshLlmResult(finalResult);\n }\n\n return finalResult;\n}\n","import { ShadowClawDatabase } from \"../../../db/types\";\n\nimport {\n invokeWithLiteRtLm,\n isLiteRtLmSupported,\n} from \"../../../subsystems/providers/litert-lm-provider\";\n\nimport {\n invokeWithPromptApi,\n isPromptApiSupported,\n} from \"../../../subsystems/providers/prompt-api-provider\";\n\nimport { invokeWithTransformersJs } from \"../../../subsystems/providers/transformers-js-provider\";\n\nimport { InvokePayload } from \"../../../subsystems/worker/types\";\nimport { handleInvoke } from \"../../../worker/utils/handleInvoke\";\nimport { post as workerPost } from \"../../../worker/utils/post\";\n\ntype SubagentPayload = InvokePayload & { isScheduledTask?: boolean };\n\nconst BROWSER_PROVIDER_IDS = new Set([\n \"litert_lm_browser\",\n \"prompt_api\",\n \"transformers_js_browser\",\n]);\n\nexport function isBrowserProviderId(providerId: string | undefined): boolean {\n return !!providerId && BROWSER_PROVIDER_IDS.has(providerId);\n}\n\nexport async function dispatchSubagentInvoke(\n db: ShadowClawDatabase,\n payload: SubagentPayload,\n abortSignal?: AbortSignal | undefined,\n): Promise<void> {\n const providerId = payload.provider;\n\n const emit = async (msg: any) => {\n workerPost(msg);\n };\n\n if (providerId === \"transformers_js_browser\") {\n await invokeWithTransformersJs(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.enabledTools,\n payload.model,\n );\n\n return;\n }\n\n if (providerId === \"prompt_api\") {\n if (!isPromptApiSupported()) {\n throw new Error(\n \"Prompt API provider is not supported in this environment.\",\n );\n }\n\n await invokeWithPromptApi(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.enabledTools,\n );\n\n return;\n }\n\n if (providerId === \"litert_lm_browser\") {\n if (!isLiteRtLmSupported()) {\n throw new Error(\n \"Litert LM Browser provider is not supported in this environment.\",\n );\n }\n\n await invokeWithLiteRtLm(\n db,\n payload.groupId,\n payload.systemPrompt,\n payload.messages,\n payload.maxTokens,\n emit,\n abortSignal,\n payload.model,\n payload.enabledTools,\n );\n\n return;\n }\n\n await handleInvoke(db, payload, abortSignal);\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../../context/estimateTokens.js\";\n\nimport { buildConversationMessages } from \"../../../db/buildConversationMessages.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { listGroups } from \"../../../db/groups.js\";\nimport { saveMessage } from \"../../../db/saveMessage.js\";\n\nimport { readGroupFile } from \"../../../storage/readGroupFile.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../../stores/tools.js\";\n\nimport {\n invokeWithLiteRtLm,\n isLiteRtLmSupported,\n} from \"../../../subsystems/providers/litert-lm-provider.js\";\n\nimport {\n invokeWithPromptApi,\n isPromptApiSupported,\n} from \"../../../subsystems/providers/prompt-api-provider.js\";\nimport { ensureBuiltinAiPolyfills } from \"../../../subsystems/providers/builtin-ai-tasks.js\";\n\nimport { getContextLimit } from \"../../../subsystems/providers/providers.js\";\nimport { invokeWithTransformersJs } from \"../../../subsystems/providers/transformers-js-provider.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { buildSystemPrompt } from \"../../../worker/utils/system-prompt.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { activate_skill } from \"../../../subsystems/skills/tool.js\";\nimport { loadDeclarativeTools } from \"../../../subsystems/tools/declarative.js\";\n\nimport { compactContext } from \"./compactContext.js\";\nimport { deliverResponse } from \"./deliverResponse.js\";\nimport { dispatchSubagentInvoke } from \"./dispatchSubagentInvoke.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\nimport { getChannelTypeForGroup } from \"./operations/channel.js\";\n\nimport {\n getApiKeyForRequest,\n getProviderRuntimeHeaders,\n getReasoningConfig,\n startTransformersProgressPolling,\n} from \"./operations/provider.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { SubagentInvokeContext } from \"../../../worker/tools/spawn-subagent/spawn-subagent.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function invokeAgent(\n o: Orchestrator,\n db: ShadowClawDatabase,\n groupId: string,\n triggerContent: string,\n freshContext = false,\n subagent = false,\n): Promise<void> {\n const executionGroupId = subagent ? `subagent:${ulid()}` : groupId;\n\n o.inFlightTriggerByGroup.set(executionGroupId, triggerContent);\n o.setState(\"thinking\", executionGroupId);\n o.router?.setTyping(executionGroupId, true);\n o.events.emit(\"typing\", { groupId: executionGroupId, typing: true });\n\n // Save scheduled task as client message\n if (triggerContent.startsWith(\"[SCHEDULED TASK]\")) {\n o.pendingScheduledTasks.add(groupId);\n\n const stored = {\n id: ulid(),\n groupId,\n sender: \"Scheduler\",\n content: triggerContent,\n timestamp: Date.now(),\n channel: getChannelTypeForGroup(o, groupId),\n isFromMe: false,\n isTrigger: true,\n };\n\n await saveMessage(db, stored);\n\n o.events.emit(\"message\", stored);\n }\n\n // Load group memory\n let memory = \"\";\n try {\n memory = await readGroupFile(db, groupId, \"MEMORY.md\");\n } catch {}\n\n // Load group metadata to check for conversation-specific pinned tools\n const groups = await listGroups(db);\n const group = groups.find((g) => g.groupId === groupId);\n\n const effectiveProviderId = group?.pinnedProvider ?? o.provider;\n\n // When a provider is pinned but no specific model is pinned, default to that provider's own defaultModel\n const effectiveModel =\n group?.pinnedModel ??\n (group?.pinnedProvider\n ? (getProvider(group.pinnedProvider)?.defaultModel ?? o.model)\n : o.model);\n\n const configuredMaxTokens =\n typeof group?.pinnedMaxTokens === \"number\" &&\n Number.isFinite(group.pinnedMaxTokens) &&\n group.pinnedMaxTokens > 0\n ? Math.floor(group.pinnedMaxTokens)\n : o.maxTokens;\n\n let modelForTokenLimits = effectiveModel;\n if (\n effectiveProviderId === \"prompt_api\" &&\n (effectiveModel === \"browser-built-in\" || !effectiveModel) &&\n !isPromptApiSupported()\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n modelForTokenLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n const effectiveMaxTokens = Math.max(\n 1,\n Math.min(configuredMaxTokens, getModelMaxTokens(modelForTokenLimits)),\n );\n\n const effectiveProviderConfig =\n getProvider(effectiveProviderId) ?? o.providerConfig;\n\n // Track the effective provider for this group so the error handler\n // can show the right help UI and avoid showing the wrong provider's error.\n o.inFlightEffectiveProviderByGroup.set(executionGroupId, {\n providerId: effectiveProviderId,\n providerConfig: effectiveProviderConfig,\n model: effectiveModel,\n });\n\n // Use pinned tools if set; otherwise fallback to global enabled tools.\n const configuredTools = Array.isArray(group?.toolTags)\n ? toolsStore.allTools.filter((t) => group.toolTags!.includes(t.name))\n : toolsStore.enabledTools;\n const declarativeToolResult = await loadDeclarativeTools(\n db,\n executionGroupId,\n );\n const rawDeclarativeTools = declarativeToolResult.tools.filter(\n (tool) =>\n !toolsStore.allTools.some((builtIn) => builtIn.name === tool.name),\n );\n const declarativeTools = Array.isArray(group?.toolTags)\n ? rawDeclarativeTools.filter((tool) => group.toolTags!.includes(tool.name))\n : rawDeclarativeTools.filter((tool) =>\n toolsStore.isDeclarativeToolEnabled(tool.name),\n );\n const toolsWithDeclarative = [...configuredTools, ...declarativeTools];\n const skillDiscovery = await discoverSkills(db, executionGroupId);\n const activeTools =\n skillDiscovery.skills.length > 0 &&\n !toolsWithDeclarative.some((tool) => tool.name === activate_skill.name)\n ? [...toolsWithDeclarative, activate_skill]\n : toolsWithDeclarative;\n\n const subagentModelSelectionMode =\n group?.subagentModelSelectionMode === \"manual\" ? \"manual\" : \"automatic\";\n const subagentMaxTokens = group?.subagentMaxTokens;\n const subagentPinnedProvider = group?.subagentPinnedProvider;\n const subagentPinnedModel = group?.subagentPinnedModel;\n const subagentFastProvider = group?.subagentFastProvider;\n const subagentFastModel = group?.subagentFastModel;\n const subagentSmartProvider = group?.subagentSmartProvider;\n const subagentSmartModel = group?.subagentSmartModel;\n const subagentPowerfulProvider = group?.subagentPowerfulProvider;\n const subagentPowerfulModel = group?.subagentPowerfulModel;\n const providerRuntimeOverrides = group?.providerRuntimeOverrides;\n\n const peerState = orchestratorStore.getPeerState(groupId) || undefined;\n const systemPrompt = buildSystemPrompt(\n o.assistantName,\n memory,\n activeTools,\n toolsStore.systemPromptOverride,\n peerState,\n skillDiscovery.skills,\n );\n\n // Build conversation context with dynamic token-aware windowing\n const contextLimit = getContextLimit(modelForTokenLimits);\n const systemPromptTokens =\n estimateTokens(systemPrompt) +\n (activeTools?.reduce(\n (acc, t) => acc + estimateTokens(JSON.stringify(t)),\n 0,\n ) ?? 0);\n let allMessages = await buildConversationMessages(groupId, 200);\n if (freshContext) {\n if (allMessages.length > 0) {\n allMessages = [allMessages[allMessages.length - 1]];\n } else {\n allMessages = [{ role: \"user\", content: triggerContent }];\n }\n }\n const dynamicContext = buildDynamicContext(allMessages, {\n contextLimit,\n systemPromptTokens,\n maxOutputTokens: effectiveMaxTokens,\n skimTop: o.contextCompressionEnabled,\n });\n\n const messages = dynamicContext.messages;\n\n let displayTokens = dynamicContext.estimatedTokens + systemPromptTokens;\n\n if (orchestratorStore.tokenUsage) {\n const u = orchestratorStore.tokenUsage;\n const actualPrompt =\n (u.inputTokens || 0) + (u.cacheReadTokens || 0) + (u.outputTokens || 0);\n\n displayTokens = Math.max(displayTokens, actualPrompt);\n }\n\n // Emit context usage for UI display\n o.events.emit(\"context-usage\", {\n estimatedTokens: displayTokens,\n contextLimit,\n usagePercent: Math.min(\n 100,\n Math.max(\n dynamicContext.usagePercent,\n (displayTokens / contextLimit) * 100,\n ),\n ),\n truncatedCount: dynamicContext.truncatedCount,\n });\n\n // Auto-compact when context usage exceeds 80% and there are enough messages\n if (\n dynamicContext.usagePercent > 80 &&\n dynamicContext.truncatedCount > 0 &&\n allMessages.length > 10\n ) {\n o.events.emit(\"show-toast\", {\n message: `Context ${dynamicContext.usagePercent.toFixed(0)}% full — auto-compacting older messages…`,\n type: \"info\",\n duration: 4000,\n });\n // Queue compaction after this invocation completes\n queueMicrotask(() => compactContext(o, db, groupId));\n }\n\n if (effectiveProviderId === \"transformers_js_browser\") {\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const transformersInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithTransformersJs(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n activeTools,\n effectiveModel,\n transformersInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n if (effectiveProviderId === \"prompt_api\") {\n if (!isPromptApiSupported()) {\n await ensureBuiltinAiPolyfills();\n }\n if (!isPromptApiSupported()) {\n await deliverResponse(\n o,\n db,\n executionGroupId,\n \"⚠️ Error: Prompt API is not available in this browser. Switch provider or enable experimental browser flags.\",\n );\n\n return;\n }\n\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const promptApiInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithPromptApi(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n activeTools,\n promptApiInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n if (effectiveProviderId === \"litert_lm_browser\") {\n if (!isLiteRtLmSupported()) {\n await deliverResponse(\n o,\n db,\n executionGroupId,\n \"⚠️ LiteRT-LM requires WebGPU and WebAssembly.Suspending. These are not both available in this browser.\",\n );\n\n return;\n }\n\n const controller = new AbortController();\n o.promptControllers.set(executionGroupId, controller);\n\n const liteRtInvokeContext: SubagentInvokeContext = {\n apiKey: \"\",\n assistantName: o.assistantName,\n db,\n enabledTools: activeTools as any,\n invokeSubagent: async (subPayload) => {\n await dispatchSubagentInvoke(db, subPayload, controller.signal);\n },\n maxTokens: effectiveMaxTokens,\n memory: memory ?? \"\",\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n \"\",\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n streaming: false,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n };\n\n try {\n await invokeWithLiteRtLm(\n db,\n executionGroupId,\n systemPrompt,\n messages,\n effectiveMaxTokens,\n async (msg) => {\n await handleWorkerMessage(o, db, msg);\n },\n controller.signal,\n effectiveModel,\n activeTools,\n liteRtInvokeContext,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n await deliverResponse(o, db, executionGroupId, `⚠️ Error: ${message}`);\n } finally {\n o.promptControllers.delete(executionGroupId);\n }\n\n return;\n }\n\n // Determine whether to stream. The provider must explicitly opt in via\n // supportsStreaming (proxies like bedrock_proxy use synchronous\n // InvokeModelCommand and cannot return SSE streams).\n const shouldStream =\n o.streamingEnabled &&\n effectiveProviderConfig.supportsStreaming === true &&\n (effectiveProviderConfig.format === \"openai\" ||\n effectiveProviderConfig.format === \"anthropic\");\n\n if (effectiveProviderId === \"transformers_js_local\") {\n startTransformersProgressPolling(o, o.events, executionGroupId);\n }\n\n const providerRequestId = o.createProviderRequestId(executionGroupId);\n\n // Send to agent worker\n o.agentWorker?.postMessage({\n type: \"invoke\",\n payload: {\n apiKey:\n effectiveProviderId === o.provider\n ? await getApiKeyForRequest(o)\n : await o.getApiKeyForSpecificProvider(db, effectiveProviderId),\n assistantName: o.assistantName,\n contextCompression: o.contextCompressionEnabled,\n contextLimit: getContextLimit(modelForTokenLimits),\n enabledTools: activeTools,\n groupId: executionGroupId,\n isScheduledTask: o.schedulerTriggeredGroups.has(groupId),\n maxIterations: o.maxIterations,\n maxTokens: effectiveMaxTokens,\n memory,\n messages,\n model: effectiveModel,\n provider: effectiveProviderId,\n providerHeaders: getProviderRuntimeHeaders(\n o,\n effectiveProviderId,\n providerRequestId,\n providerRuntimeOverrides,\n ),\n providerRuntimeOverrides,\n reasoning: getReasoningConfig(o),\n rateLimitAutoAdapt: o.rateLimitAutoAdapt,\n rateLimitCallsPerMinute: o.rateLimitCallsPerMinute,\n storageHandle: await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE),\n streaming: shouldStream,\n subagentModelSelectionMode,\n subagentMaxTokens,\n subagentPinnedProvider,\n subagentPinnedModel,\n subagentFastProvider,\n subagentFastModel,\n subagentSmartProvider,\n subagentSmartModel,\n subagentPowerfulProvider,\n subagentPowerfulModel,\n systemPrompt,\n subagentTask: subagent,\n },\n });\n}\n","import type { InboundMessage } from \"../../../subsystems/channels/types.js\";\n\nimport type {\n DirectToolCommandPolicy,\n ParsedDirectToolCommand,\n} from \"./types.js\";\n\nexport function parseDirectToolCommand(\n policy: DirectToolCommandPolicy,\n assistantName: string,\n msg: InboundMessage,\n): ParsedDirectToolCommand | null {\n if (!policy.enabledChannelTypes.includes(msg.channel)) {\n return null;\n }\n\n const content = msg.content.trim();\n const escapedAssistant = assistantName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n let commandPart = content;\n if (policy.requireMention) {\n const mentionPrefix = new RegExp(\n `^@${escapedAssistant}\\\\b\\\\s*(?:-|:)?\\\\s*`,\n \"i\",\n );\n\n if (!mentionPrefix.test(commandPart)) {\n return null;\n }\n\n commandPart = commandPart.replace(mentionPrefix, \"\").trim();\n }\n\n const toolMatch = commandPart.match(/^\\/([a-zA-Z0-9_]+)(?:\\s+([\\s\\S]+))?$/);\n if (!toolMatch) {\n return null;\n }\n\n const toolName = toolMatch[1];\n if (!policy.allowedTools.includes(toolName)) {\n return null;\n }\n\n const rawArgs = (toolMatch[2] || \"\").trim();\n if (!rawArgs) {\n return { toolName, input: {} };\n }\n\n const unwrappedArgs =\n (rawArgs.startsWith(\"'\") && rawArgs.endsWith(\"'\")) ||\n (rawArgs.startsWith('\"') && rawArgs.endsWith('\"'))\n ? rawArgs.slice(1, -1).trim()\n : rawArgs;\n\n try {\n const parsedInput = JSON.parse(unwrappedArgs);\n if (parsedInput && typeof parsedInput === \"object\") {\n return {\n toolName,\n input: parsedInput as Record<string, any>,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","import type { SkillRecord } from \"./types.js\";\n\nexport interface ParsedSkillCommand {\n skill: SkillRecord;\n arguments: string;\n}\n\nexport function parseSkillCommand(\n content: string,\n skills: SkillRecord[],\n): ParsedSkillCommand | null {\n const match = content\n .trim()\n .match(\n /^\\/([a-z0-9](?:[a-z0-9]|-(?!-))*[a-z0-9]|[a-z0-9])(?:\\s+([\\s\\S]+))?$/u,\n );\n if (!match) {\n return null;\n }\n\n const skill = skills.find(\n (candidate) =>\n candidate.name === match[1] && candidate.userInvocable !== false,\n );\n if (!skill) {\n return null;\n }\n\n return {\n skill,\n arguments: (match[2] || \"\").trim(),\n };\n}\n","import { detectProviderHelpType } from \"../../../components/common/help/providers.js\";\nimport { getProvider } from \"../../../config/config.js\";\nimport { persistMessageAttachments } from \"../../../content/message-attachments.js\";\n\nimport { listGroups } from \"../../../db/groups.js\";\nimport { saveMessage } from \"../../../db/saveMessage.js\";\n\nimport { invokeAgent } from \"./invokeAgent.js\";\n\nimport { clearPeerJsTypingState } from \"./operations/channel.js\";\nimport { getApiKeyForRequest } from \"./operations/provider.js\";\n\nimport { parseDirectToolCommand } from \"./parseDirectToolCommand.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { parseSkillCommand } from \"../../../subsystems/skills/parseSkillCommand.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { InboundMessage } from \"../../../subsystems/channels/types.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function enqueue(\n o: Orchestrator,\n db: ShadowClawDatabase,\n msg: InboundMessage,\n): Promise<void> {\n // ── A2UI inbound dispatch ────────────────────────────────────────────────\n // Surface envelopes and actions arrive via the peer channel. Emit them so\n // the UI layer can render/update surfaces, then fall through to persist the\n // message normally (so the conversation history is complete).\n if (msg.a2uiEnvelopes && msg.a2uiEnvelopes.length > 0) {\n for (const envelope of msg.a2uiEnvelopes) {\n o.events.emit(\"a2ui-surface\", {\n groupId: msg.groupId,\n envelope,\n });\n }\n }\n\n if (msg.a2uiAction) {\n o.events.emit(\"a2ui-action\", {\n groupId: msg.groupId,\n action: msg.a2uiAction,\n });\n }\n\n // If there's nothing else in the message (no text, no attachments, only\n // A2UI parts), skip the rest of the enqueue flow.\n const hasTextContent = !!msg.content;\n const hasAttachments = (msg.attachments?.length ?? 0) > 0;\n if (\n !hasTextContent &&\n !hasAttachments &&\n (msg.a2uiEnvelopes?.length ?? 0) > 0\n ) {\n return;\n }\n\n // ── Normal message handling ──────────────────────────────────────────────\n const directToolCommand = parseDirectToolCommand(\n o.directToolCommandPolicy,\n o.assistantName,\n msg,\n );\n const skillCommand = directToolCommand\n ? null\n : parseSkillCommand(\n msg.content,\n (await discoverSkills(db, msg.groupId)).skills,\n );\n const isFromBrowser = msg.channel === \"browser\"; // Messages submitted in ShadowClaw UI\n const autoTrigger = o.channelRegistry.shouldAutoTrigger(msg.groupId);\n\n let hasTrigger = false;\n\n if (msg.channel === \"browser\" || msg.groupId.startsWith(\"room:\")) {\n hasTrigger = o.triggerPattern.test(msg.content.trim());\n }\n\n if (skillCommand) {\n hasTrigger = true;\n }\n\n // ── A2A task-state conversation termination ──────────────────────────────\n // If the local user sends a new message in a completed peer conversation,\n // reopen it (clear the terminal state) so the agent will respond again.\n if (isFromBrowser && msg.groupId.startsWith(\"peer:\")) {\n o.peerCompletedContexts.delete(msg.groupId);\n }\n\n const isDirectToolCommand = !!directToolCommand;\n\n // Check for explicit peer ID mention (works for both local and remote)\n if (!hasTrigger && o.peerjsMyPeerId) {\n if (msg.content.includes(`@${o.peerjsMyPeerId}`)) {\n hasTrigger = true;\n } else if (o.peerjsMyAlias && msg.content.includes(`@${o.peerjsMyAlias}`)) {\n // Also respond to @<my-alias> so peers can use the friendly name\n hasTrigger = true;\n } else {\n // Also check if any alias maps to o.peerjsMyPeerId\n for (const [alias, rawId] of Object.entries(o.peerjsPeerAliases)) {\n if (rawId === o.peerjsMyPeerId && msg.content.includes(`@${alias}`)) {\n hasTrigger = true;\n\n break;\n }\n }\n }\n }\n\n // Always trigger the agent for scheduled tasks\n if (msg.content.trim().startsWith(\"[SCHEDULED TASK]\")) {\n hasTrigger = true;\n }\n\n // Always trigger the owning agent to process an A2UI surface action. These\n // `[A2UI ACTION]` messages are only ever constructed on the surface owner's\n // side (local click on an owned surface, or an inbound `room/a2ui-action`\n // for a surface we own), so force-triggering here is safe and keeps shared\n // surfaces owner-authoritative.\n if (msg.content.trim().startsWith(\"[A2UI ACTION]\")) {\n hasTrigger = true;\n }\n\n let isTrigger = false;\n if (isDirectToolCommand) {\n isTrigger = true;\n } else if (hasTrigger) {\n isTrigger = true;\n } else if (isFromBrowser) {\n // Messages from the local UI trigger the agent by default,\n // EXCEPT in P2P / room channels where we just want to chat with peers.\n if (msg.groupId.startsWith(\"peer:\") || msg.groupId.startsWith(\"room:\")) {\n isTrigger = false;\n } else {\n isTrigger = true;\n }\n } else {\n isTrigger = autoTrigger;\n }\n\n // ── A2A terminal-state suppression ───────────────────────────────────────\n // If the peer conversation's task has reached a terminal state (COMPLETED,\n // FAILED, CANCELED) via A2A protocol, suppress auto-trigger. The human\n // user can reopen by sending a new message from the browser UI.\n if (\n isTrigger &&\n !isFromBrowser &&\n !skillCommand &&\n msg.groupId.startsWith(\"peer:\") &&\n o.peerCompletedContexts.has(msg.groupId)\n ) {\n isTrigger = false;\n }\n\n const attachments = await persistMessageAttachments(\n db,\n msg.groupId,\n msg.attachments || [],\n );\n\n const stored = {\n ...msg,\n attachments,\n isFromMe: false,\n isTrigger,\n };\n\n if (isTrigger && !isDirectToolCommand && !skillCommand?.skill.execution) {\n o.messageQueue.push(\n skillCommand\n ? {\n ...msg,\n content: `[SKILL COMMAND] Activate the \"${skillCommand.skill.name}\" skill and follow its instructions.\\n${skillCommand.arguments}`,\n }\n : msg,\n );\n }\n\n await saveMessage(db, stored);\n o.events.emit(\"message\", stored);\n\n if (skillCommand?.skill.execution && o.agentWorker) {\n const rawTools = skillCommand.skill.execution.tools;\n const tools = rawTools.map((t) => {\n const inputObj =\n t.input && typeof t.input === \"object\" ? { ...t.input } : {};\n if (skillCommand.arguments && Object.keys(inputObj).length === 0) {\n inputObj.rawInput = skillCommand.arguments;\n }\n return {\n ...t,\n input: inputObj,\n };\n });\n\n o.agentWorker.postMessage({\n type: \"execute-skill-tools\",\n payload: {\n groupId: msg.groupId,\n skillName: skillCommand.skill.name,\n tools,\n },\n });\n return;\n }\n\n // Keep peer typing state in sync, but do not treat every P2P chat message\n // as an agent response. Normal peer messages should not force the remote\n // peer into a temporary \"responding\" state.\n if (msg.channel === \"peerjs\") {\n clearPeerJsTypingState(msg.groupId);\n }\n\n // Forward browser messages to the P2P / room channel so users can chat directly\n if (\n isFromBrowser &&\n (msg.groupId.startsWith(\"peer:\") || msg.groupId.startsWith(\"room:\"))\n ) {\n o.router?.send(msg.groupId, msg.content, attachments).catch((err) => {\n console.error(\"Failed to route browser message to peer:\", err);\n });\n }\n\n if (directToolCommand && o.agentWorker) {\n o.agentWorker.postMessage({\n type: \"execute-direct-tool\",\n payload: {\n groupId: msg.groupId,\n name: directToolCommand.toolName,\n input: directToolCommand.input,\n },\n });\n\n return;\n }\n\n processQueue(o, db);\n}\n\nexport async function processQueue(\n o: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n if (o.processing) {\n return;\n }\n\n if (o.messageQueue.length === 0) {\n return;\n }\n\n // Look up the effective provider for the next message's group\n const nextMsg = o.messageQueue[0];\n const nextGroupId = nextMsg?.groupId;\n\n let effectiveProviderConfig = o.providerConfig;\n let effectiveProviderId = o.provider;\n\n if (nextGroupId) {\n try {\n const groups = await listGroups(db);\n const grp = groups.find((g) => g.groupId === nextGroupId);\n if (grp?.pinnedProvider) {\n const pinned = getProvider(grp.pinnedProvider);\n if (pinned) {\n effectiveProviderConfig = pinned;\n effectiveProviderId = grp.pinnedProvider;\n }\n }\n } catch {\n // best-effort\n }\n }\n\n const requiresApiKey = effectiveProviderConfig?.requiresApiKey !== false;\n let apiKeyPresent = true;\n if (requiresApiKey) {\n if (effectiveProviderId === o.provider) {\n apiKeyPresent = !!(await getApiKeyForRequest(o));\n } else {\n apiKeyPresent = !!(await o.getApiKeyForSpecificProvider(\n db,\n effectiveProviderId,\n ));\n }\n }\n\n if (requiresApiKey && !apiKeyPresent) {\n const reason =\n \"API key not configured. Go to Settings to add your API key.\";\n\n o.events.emit(\"provider-help\", {\n providerId: effectiveProviderId,\n reason,\n helpType: detectProviderHelpType(\n effectiveProviderId,\n reason,\n requiresApiKey,\n ),\n });\n\n const msg = o.messageQueue.shift()!;\n o.events.emit(\"error\", {\n groupId: msg.groupId,\n error: reason,\n });\n\n return;\n }\n\n o.processing = true;\n const msg = o.messageQueue.shift()!;\n\n try {\n await invokeAgent(\n o,\n db,\n msg.groupId,\n msg.content,\n msg.freshContext,\n msg.subagent,\n );\n } catch (err) {\n console.error(\"Failed to invoke agent:\", err);\n } finally {\n o.processing = false;\n if (o.messageQueue.length > 0) {\n processQueue(o, db);\n }\n }\n}\n","/**\n * Simple event emitter for orchestrator events.\n */\nexport class EventBus {\n listeners: Map<string, Set<Function>>;\n\n constructor() {\n this.listeners = new Map();\n }\n\n emit(event: string, data: any) {\n this.listeners.get(event)?.forEach((cb) => cb(data));\n }\n\n off(event: string, callback: Function) {\n this.listeners.get(event)?.delete(callback);\n }\n\n on(event: string, callback: Function) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n\n this.listeners.get(event)?.add(callback);\n }\n}\n","/**\n * ShadowClaw — Room Manager (multi-party PeerJS conversations)\n *\n * Coordinates a hybrid room topology on top of the existing 1:1\n * {@link PeerJsChannel} transport:\n *\n * - The room **host** runs a star for signaling, roster and membership\n * (`room/join`, `room/roster`, `room/leave`, `room/invite`).\n * - Actual chat traffic (`room/message`) flows peer-to-peer over the **mesh**,\n * falling back to **host relay** (`room/relay`) when a direct connection to a\n * recipient is not available.\n *\n * The manager owns no socket of its own — it delegates all transport to an\n * injected {@link RoomTransport} so it can be unit-tested in isolation. Trigger\n * (@mention) detection is intentionally left to the orchestrator's existing\n * enqueue logic; this layer only delivers inbound messages.\n */\n\nimport { Signal } from \"signal-polyfill\";\n\nimport { roomGroupId } from \"../../db/rooms.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { MessageAttachment } from \"../../content/types.js\";\nimport type { A2UIAction, A2UIEnvelope } from \"../../ui/a2ui/types.js\";\nimport type { InboundMessage, RoomMember, RoomMeta } from \"./types.js\";\n\nimport type {\n A2AJsonRpcNotification,\n RoomA2UIActionEnvelope,\n RoomA2UIEnvelope,\n RoomInvitePayload,\n RoomJoinPayload,\n RoomLeavePayload,\n RoomMessageEnvelope,\n RoomRelayPayload,\n RoomRosterPayload,\n} from \"./peer-protocol.js\";\n\nimport { ROOM_METHOD } from \"./peer-protocol.js\";\n\n/** Build the `[A2UI ACTION]` prompt that drives owner-side action processing. */\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/formatA2UIActionPrompt.js\";\n\n/** Transport surface the {@link RoomManager} depends on. */\nexport interface RoomTransport {\n /** The local peer ID. */\n readonly myPeerId: string;\n /** Send a JSON-RPC notification to a single peer. Returns true if dispatched. */\n sendToPeer(peerId: string, notification: A2AJsonRpcNotification): boolean;\n /** Whether a direct, open connection to the peer currently exists. */\n isConnected(peerId: string): boolean;\n /** Best-effort: ensure an outbound connection to the peer is opened. */\n connectToPeer(peerId: string): void;\n}\n\nexport interface RoomManagerOptions {\n transport: RoomTransport;\n /** Resolve the local member identity used when creating/joining rooms. */\n getLocalMember: () => RoomMember;\n /** Deliver an inbound room chat message to the orchestrator. */\n onMessage: (msg: InboundMessage) => void;\n /** Deliver an inbound room invitation (e.g. to a notification / dialog). */\n onInvite?: (invite: RoomInvitePayload) => void;\n /** Persist (insert or replace) a room record. */\n persistRoom?: (room: RoomMeta) => void;\n /** Remove a persisted room record. */\n removeRoom?: (roomId: string) => void;\n}\n\n/** Max remembered message ids per room for cross-path de-duplication. */\nconst MAX_SEEN_PER_ROOM = 500;\n\nfunction notification(method: string, params: unknown): A2AJsonRpcNotification {\n return { jsonrpc: \"2.0\", method, params };\n}\n\nexport class RoomManager {\n // ---------------------------------------------------------------------------\n // Inbound dispatch\n // ---------------------------------------------------------------------------\n\n /**\n * Returns true if the method is a room protocol method this manager handles.\n */\n static isRoomMethod(method: string): boolean {\n return (\n method === ROOM_METHOD.JOIN ||\n method === ROOM_METHOD.ROSTER ||\n method === ROOM_METHOD.LEAVE ||\n method === ROOM_METHOD.MESSAGE ||\n method === ROOM_METHOD.INVITE ||\n method === ROOM_METHOD.RELAY ||\n method === ROOM_METHOD.A2UI ||\n method === ROOM_METHOD.A2UI_ACTION\n );\n }\n\n /** Reactive snapshot of joined rooms for the UI. */\n readonly roomsSignal = new Signal.State<RoomMeta[]>([]);\n private readonly _opts: RoomManagerOptions;\n\n /** Joined rooms keyed by bare room id. */\n private readonly _rooms = new Map<string, RoomMeta>();\n\n /** Per-room set of seen message ids (insertion-ordered for trimming). */\n private readonly _seen = new Map<string, Set<string>>();\n\n /**\n * Owner of each shared A2UI surface, keyed by surfaceId. Populated when the\n * local peer broadcasts a surface it created, or when an inbound\n * `room/a2ui` createSurface broadcast is received. Used to enforce the\n * owner-authoritative model: only the surface owner's agent processes\n * actions and mutates the data model.\n */\n private readonly _surfaceOwners = new Map<string, string>();\n\n constructor(opts: RoomManagerOptions) {\n this._opts = opts;\n }\n\n // ---------------------------------------------------------------------------\n // Outbound messages\n // ---------------------------------------------------------------------------\n\n /**\n * Broadcast a chat message to every other room member. Uses mesh delivery\n * with host-relay fallback. Returns the message id used.\n */\n broadcast(\n roomId: string,\n text: string,\n attachments?: MessageAttachment[],\n ): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._opts.getLocalMember();\n const messageId = ulid();\n const envelope: RoomMessageEnvelope = {\n roomId,\n messageId,\n senderPeerId: me.peerId,\n senderAlias: me.alias,\n text,\n attachments: attachments?.map((a) => ({\n fileName: a.fileName,\n mimeType: a.mimeType,\n path: a.path,\n size: a.size,\n })),\n };\n\n // Remember our own id so an echo (e.g. host relay) is not re-delivered.\n this._markSeen(roomId, messageId);\n this._deliverToMembers(room, notification(ROOM_METHOD.MESSAGE, envelope));\n\n return messageId;\n }\n\n /**\n * Broadcast a locally produced A2UI surface envelope to every other room\n * member. Records the local peer as the surface owner so subsequent actions\n * route back here. Returns the broadcast id used (null if not a member).\n */\n broadcastA2UI(roomId: string, envelope: A2UIEnvelope): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._myPeerId;\n // The local peer authored this surface — record (or refresh) ownership.\n this._surfaceOwners.set(envelope.surfaceId, me);\n\n const broadcastId = ulid();\n const payload: RoomA2UIEnvelope = {\n roomId,\n broadcastId,\n ownerPeerId: me,\n senderPeerId: me,\n envelope,\n };\n\n this._markSeen(roomId, broadcastId);\n this._deliverToMembers(room, notification(ROOM_METHOD.A2UI, payload));\n\n return broadcastId;\n }\n\n /**\n * Broadcast a user action fired on a shared surface to every other room\n * member. The surface owner's agent will process it (and broadcast the\n * resulting data-model update). Returns the broadcast id (null if not a\n * member).\n */\n broadcastA2UIAction(roomId: string, action: A2UIAction): string | null {\n const room = this._rooms.get(roomId);\n if (!room) {\n return null;\n }\n\n const me = this._opts.getLocalMember();\n const ownerPeerId = this._surfaceOwners.get(action.surfaceId) ?? \"\";\n const broadcastId = ulid();\n const payload: RoomA2UIActionEnvelope = {\n roomId,\n broadcastId,\n ownerPeerId,\n senderPeerId: me.peerId,\n senderAlias: me.alias,\n action,\n };\n\n this._markSeen(roomId, broadcastId);\n this._deliverToMembers(\n room,\n notification(ROOM_METHOD.A2UI_ACTION, payload),\n );\n\n return broadcastId;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (host + member)\n // ---------------------------------------------------------------------------\n\n /** Create a new room hosted by the local peer. */\n createRoom(name: string): RoomMeta {\n const me = this._opts.getLocalMember();\n const room: RoomMeta = {\n roomId: ulid(),\n name,\n hostPeerId: me.peerId,\n members: [me],\n createdAt: Date.now(),\n };\n\n this._save(room);\n\n return room;\n }\n\n /** Get a joined room by id. */\n get(roomId: string): RoomMeta | null {\n return this._rooms.get(roomId) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // Shared A2UI surfaces (owner-authoritative)\n // ---------------------------------------------------------------------------\n\n /** The peer that owns the given shared surface, if known locally. */\n getSurfaceOwner(surfaceId: string): string | undefined {\n return this._surfaceOwners.get(surfaceId);\n }\n\n /** Dispatch an inbound room notification received from {@link fromPeerId}. */\n handleNotification(\n fromPeerId: string,\n method: string,\n params: unknown,\n ): void {\n switch (method) {\n case ROOM_METHOD.JOIN:\n this._onJoin(fromPeerId, params as RoomJoinPayload);\n\n break;\n case ROOM_METHOD.ROSTER:\n this._onRoster(params as RoomRosterPayload);\n\n break;\n case ROOM_METHOD.LEAVE:\n this._onLeave(fromPeerId, params as RoomLeavePayload);\n\n break;\n case ROOM_METHOD.MESSAGE:\n this._onMessage(params as RoomMessageEnvelope);\n\n break;\n case ROOM_METHOD.INVITE:\n this._opts.onInvite?.(params as RoomInvitePayload);\n\n break;\n case ROOM_METHOD.RELAY:\n this._onRelay(params as RoomRelayPayload);\n\n break;\n case ROOM_METHOD.A2UI:\n this._onA2UI(params as RoomA2UIEnvelope);\n\n break;\n case ROOM_METHOD.A2UI_ACTION:\n this._onA2UIAction(params as RoomA2UIActionEnvelope);\n\n break;\n }\n }\n\n /** Invite a peer to a room (out-of-band, peer-to-peer). */\n invite(roomId: string, targetPeerId: string): boolean {\n const room = this._rooms.get(roomId);\n if (!room) {\n return false;\n }\n\n const me = this._opts.getLocalMember();\n const payload: RoomInvitePayload = {\n roomId,\n roomName: room.name,\n hostPeerId: room.hostPeerId,\n fromPeerId: me.peerId,\n fromAlias: me.alias,\n };\n\n const transport = this._opts.transport;\n transport.connectToPeer(targetPeerId);\n\n return transport.sendToPeer(\n targetPeerId,\n notification(ROOM_METHOD.INVITE, payload),\n );\n }\n\n /** Whether the local peer is the host of the given room. */\n isHost(roomId: string): boolean {\n const room = this._rooms.get(roomId);\n\n return !!room && room.hostPeerId === this._myPeerId;\n }\n\n /**\n * Join an existing room hosted by {@link hostPeerId}. Establishes a local\n * provisional roster (host + self) and sends a join request to the host; the\n * authoritative roster arrives via a `room/roster` notification.\n */\n joinRoom(roomId: string, hostPeerId: string, name: string): RoomMeta {\n const me = this._opts.getLocalMember();\n const existing = this._rooms.get(roomId);\n const room: RoomMeta = existing ?? {\n roomId,\n name,\n hostPeerId,\n members: [{ peerId: hostPeerId, alias: hostPeerId, kind: \"agent\" }, me],\n createdAt: Date.now(),\n };\n\n this._save(room);\n\n const transport = this._opts.transport;\n transport.connectToPeer(hostPeerId);\n const payload: RoomJoinPayload = { roomId, member: me };\n transport.sendToPeer(hostPeerId, notification(ROOM_METHOD.JOIN, payload));\n\n return room;\n }\n\n /**\n * Leave (member) or disband (host) a room. The host notifies all members that\n * the room is disbanded; a member notifies the host of its departure.\n */\n leaveRoom(roomId: string): void {\n const room = this._rooms.get(roomId);\n if (!room) {\n return;\n }\n\n const me = this._myPeerId;\n if (room.hostPeerId === me) {\n const payload: RoomLeavePayload = {\n roomId,\n peerId: me,\n disbanded: true,\n };\n this._deliverToMembers(room, notification(ROOM_METHOD.LEAVE, payload));\n } else {\n const payload: RoomLeavePayload = { roomId, peerId: me };\n this._opts.transport.sendToPeer(\n room.hostPeerId,\n notification(ROOM_METHOD.LEAVE, payload),\n );\n }\n\n this._rooms.delete(roomId);\n this._seen.delete(roomId);\n this._opts.removeRoom?.(roomId);\n this._publish();\n }\n\n /** All joined rooms. */\n list(): RoomMeta[] {\n return Array.from(this._rooms.values());\n }\n\n // ---------------------------------------------------------------------------\n // State\n // ---------------------------------------------------------------------------\n\n /** Load persisted rooms at startup. */\n loadRooms(rooms: RoomMeta[]): void {\n this._rooms.clear();\n for (const room of rooms) {\n this._rooms.set(room.roomId, room);\n }\n\n this._publish();\n }\n\n // ---------------------------------------------------------------------------\n // Delivery helpers\n // ---------------------------------------------------------------------------\n\n private _broadcastRoster(room: RoomMeta): void {\n const payload: RoomRosterPayload = {\n roomId: room.roomId,\n name: room.name,\n hostPeerId: room.hostPeerId,\n members: room.members,\n };\n this._deliverToMembers(room, notification(ROOM_METHOD.ROSTER, payload));\n }\n\n /**\n * Deliver a notification to all room members except the local peer, using a\n * direct mesh connection where possible and host relay as a fallback.\n */\n private _deliverToMembers(\n room: RoomMeta,\n note: A2AJsonRpcNotification,\n ): void {\n const me = this._myPeerId;\n for (const member of room.members) {\n if (member.peerId === me) {\n continue;\n }\n\n this._deliverToPeer(room, member.peerId, note);\n }\n }\n\n private _deliverToPeer(\n room: RoomMeta,\n targetPeerId: string,\n note: A2AJsonRpcNotification,\n ): void {\n const transport = this._opts.transport;\n if (transport.isConnected(targetPeerId)) {\n transport.sendToPeer(targetPeerId, note);\n\n return;\n }\n\n // Not directly connected — relay via the host when possible.\n const me = this._myPeerId;\n if (\n room.hostPeerId !== me &&\n room.hostPeerId !== targetPeerId &&\n transport.isConnected(room.hostPeerId)\n ) {\n const relay: RoomRelayPayload = {\n roomId: room.roomId,\n targetPeerId,\n inner: note,\n };\n transport.sendToPeer(\n room.hostPeerId,\n notification(ROOM_METHOD.RELAY, relay),\n );\n // Opportunistically upgrade to a direct mesh link for next time.\n transport.connectToPeer(targetPeerId);\n\n return;\n }\n\n // Last resort: open a connection and attempt a direct send.\n transport.connectToPeer(targetPeerId);\n transport.sendToPeer(targetPeerId, note);\n }\n\n // ---------------------------------------------------------------------------\n // De-duplication\n // ---------------------------------------------------------------------------\n\n private _hasSeen(roomId: string, messageId: string): boolean {\n return this._seen.get(roomId)?.has(messageId) ?? false;\n }\n\n private _markSeen(roomId: string, messageId: string): void {\n let set = this._seen.get(roomId);\n if (!set) {\n set = new Set();\n this._seen.set(roomId, set);\n }\n\n set.add(messageId);\n if (set.size > MAX_SEEN_PER_ROOM) {\n // Drop the oldest entry (insertion order).\n const oldest = set.values().next().value;\n if (oldest !== undefined) {\n set.delete(oldest);\n }\n }\n }\n\n private get _myPeerId(): string {\n return this._opts.transport.myPeerId;\n }\n\n /**\n * Inbound shared A2UI surface broadcast. De-duplicate, record the surface\n * owner, then deliver the envelope to the local UI so the surface renders /\n * updates in lockstep with the rest of the room.\n */\n private _onA2UI(payload: RoomA2UIEnvelope): void {\n if (\n !payload ||\n typeof payload.roomId !== \"string\" ||\n typeof payload.broadcastId !== \"string\" ||\n !payload.envelope\n ) {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(payload.roomId, payload.broadcastId)) {\n return;\n }\n\n this._markSeen(payload.roomId, payload.broadcastId);\n\n // Record ownership so any action we fire on this surface routes to its\n // authoritative owner. Never let an inbound broadcast claim ownership of a\n // surface we authored locally.\n const surfaceId = payload.envelope.surfaceId;\n if (this._surfaceOwners.get(surfaceId) !== this._myPeerId) {\n this._surfaceOwners.set(surfaceId, payload.ownerPeerId);\n }\n\n const inbound: InboundMessage = {\n id: payload.broadcastId,\n groupId: roomGroupId(payload.roomId),\n sender: payload.senderPeerId,\n content: \"\",\n timestamp: Date.now(),\n channel: \"room\",\n a2uiEnvelopes: [payload.envelope],\n };\n\n this._opts.onMessage(inbound);\n }\n\n /**\n * Inbound shared A2UI action. De-duplicate, then — only when the local peer\n * is the authoritative owner of the target surface — deliver a trigger\n * message so the owner's agent processes the action and broadcasts the\n * resulting data-model update. Non-owners ignore the action; their surface is\n * synchronized by the owner's subsequent `room/a2ui` broadcast.\n */\n private _onA2UIAction(payload: RoomA2UIActionEnvelope): void {\n if (\n !payload ||\n typeof payload.roomId !== \"string\" ||\n typeof payload.broadcastId !== \"string\" ||\n !payload.action\n ) {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(payload.roomId, payload.broadcastId)) {\n return;\n }\n\n this._markSeen(payload.roomId, payload.broadcastId);\n\n // Owner-authoritative: only process actions for surfaces we locally own.\n // Trust our own ownership map over any self-reported `ownerPeerId`.\n if (this._surfaceOwners.get(payload.action.surfaceId) !== this._myPeerId) {\n return;\n }\n\n const inbound: InboundMessage = {\n id: payload.broadcastId,\n groupId: roomGroupId(payload.roomId),\n sender: payload.senderAlias || payload.senderPeerId,\n content: formatA2UIActionPrompt(payload.action, payload.senderAlias),\n timestamp: Date.now(),\n channel: \"room\",\n a2uiAction: payload.action,\n };\n\n this._opts.onMessage(inbound);\n }\n\n /** Host: a peer requested to join. Add to roster and broadcast it. */\n private _onJoin(fromPeerId: string, payload: RoomJoinPayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room || room.hostPeerId !== this._myPeerId) {\n return; // Only the host services join requests.\n }\n\n const member: RoomMember = payload.member ?? {\n peerId: fromPeerId,\n alias: fromPeerId,\n kind: \"human\",\n };\n // Trust the connection's peer id over any self-reported value.\n member.peerId = fromPeerId;\n\n const index = room.members.findIndex((m) => m.peerId === fromPeerId);\n if (index >= 0) {\n room.members[index] = member;\n } else {\n room.members.push(member);\n }\n\n this._save(room);\n this._broadcastRoster(room);\n }\n\n /** Leave/disband notification. */\n private _onLeave(fromPeerId: string, payload: RoomLeavePayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const room = this._rooms.get(payload.roomId);\n if (!room) {\n return;\n }\n\n if (payload.disbanded) {\n // Host disbanded the room for everyone.\n this._rooms.delete(payload.roomId);\n this._seen.delete(payload.roomId);\n this._opts.removeRoom?.(payload.roomId);\n this._publish();\n\n return;\n }\n\n // Host receives a member's departure: drop them and re-broadcast roster.\n if (room.hostPeerId === this._myPeerId) {\n room.members = room.members.filter(\n (m) => m.peerId !== (payload.peerId || fromPeerId),\n );\n this._save(room);\n this._broadcastRoster(room);\n }\n }\n\n /** Inbound chat message — de-duplicate then deliver to the orchestrator. */\n private _onMessage(envelope: RoomMessageEnvelope): void {\n if (\n !envelope ||\n typeof envelope.roomId !== \"string\" ||\n typeof envelope.messageId !== \"string\"\n ) {\n return;\n }\n\n const room = this._rooms.get(envelope.roomId);\n if (!room) {\n return; // Not a member of this room.\n }\n\n if (this._hasSeen(envelope.roomId, envelope.messageId)) {\n return;\n }\n\n this._markSeen(envelope.roomId, envelope.messageId);\n\n const inbound: InboundMessage = {\n id: envelope.messageId,\n groupId: roomGroupId(envelope.roomId),\n sender: envelope.senderAlias || envelope.senderPeerId,\n content: envelope.text ?? \"\",\n timestamp: Date.now(),\n channel: \"room\",\n attachments: envelope.attachments?.map((a) => ({\n fileName: a.fileName,\n mimeType: a.mimeType,\n path: a.path,\n size: a.size,\n })),\n };\n\n this._opts.onMessage(inbound);\n }\n\n /** Host: forward a relayed notification to its intended target. */\n private _onRelay(payload: RoomRelayPayload): void {\n if (\n !payload ||\n typeof payload.targetPeerId !== \"string\" ||\n !payload.inner\n ) {\n return;\n }\n\n // Only relay for rooms we host.\n if (!this.isHost(payload.roomId)) {\n return;\n }\n\n this._opts.transport.sendToPeer(payload.targetPeerId, payload.inner);\n }\n\n /** Member: authoritative roster received from the host. */\n private _onRoster(payload: RoomRosterPayload): void {\n if (!payload || typeof payload.roomId !== \"string\") {\n return;\n }\n\n const existing = this._rooms.get(payload.roomId);\n const room: RoomMeta = {\n roomId: payload.roomId,\n name: payload.name ?? existing?.name ?? payload.roomId,\n hostPeerId: payload.hostPeerId,\n members: Array.isArray(payload.members) ? payload.members : [],\n createdAt: existing?.createdAt ?? Date.now(),\n };\n\n this._save(room);\n }\n\n private _publish(): void {\n this.roomsSignal.set(this.list());\n }\n\n private _save(room: RoomMeta): void {\n this._rooms.set(room.roomId, room);\n this._opts.persistRoom?.(room);\n this._publish();\n }\n}\n","import { getDb } from \"./db.js\";\nimport type { ShadowClawDatabase, Task } from \"./types.js\";\n\n/**\n * Get all enabled tasks\n */\nexport function getEnabledTasks(): Promise<Task[]> {\n return new Promise(async (resolve, reject) => {\n try {\n const tx: ShadowClawDatabase = await getDb();\n\n if (!tx) {\n return reject(\n new Error(\"failed to get transaction, cannot get enabled tasks.\"),\n );\n }\n\n const transactionStore = tx.transaction(\"tasks\", \"readonly\");\n if (!transactionStore) {\n return reject(new Error(\"failed to get transaction\"));\n }\n\n const store = transactionStore.objectStore(\"tasks\");\n const index = store.index(\"by-enabled\");\n const request = index.getAll(1); // enabled = true (stored as 1)\n\n request.onsuccess = () => {\n // Convert numeric `enabled` back to boolean\n const tasks: Task[] = (request.result as any[]).map((t) => ({\n ...t,\n enabled: true,\n }));\n\n resolve(tasks);\n };\n\n request.onerror = () => reject(request.error);\n } catch (err) {\n reject(err);\n }\n });\n}\n","// =========================================================================\n// Cron expression parser (lightweight, no dependencies)\n// =========================================================================\n// Format: minute hour day-of-month month day-of-week\n// Supports: * (any), N (exact), N-M (range), N,M (list), */N (step)\n\n/**\n * Match a cron expression against a date\n */\nexport function matchesCron(expr: string, date: Date): boolean {\n if (typeof expr !== \"string\" || !expr.trim()) {\n return false;\n }\n\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) {\n return false;\n }\n\n const [min, hour, dom, mon, dow] = parts;\n\n return (\n matchField(min, date.getMinutes()) &&\n matchField(hour, date.getHours()) &&\n matchField(dom, date.getDate()) &&\n matchField(mon, date.getMonth() + 1) &&\n matchField(dow, date.getDay())\n );\n}\n\n/**\n * Match a single cron field\n */\nfunction matchField(field: string, value: number): boolean {\n if (field === \"*\") {\n return true;\n }\n\n return field.split(\",\").some((part) => {\n // Step: */N or N/M\n if (part.includes(\"/\")) {\n const [range, stepStr] = part.split(\"/\");\n const step = parseInt(stepStr, 10);\n if (isNaN(step) || step <= 0) {\n return false;\n }\n\n if (range === \"*\") {\n return value % step === 0;\n }\n\n // Range with step: N-M/S\n if (range.includes(\"-\")) {\n const [lo, hi] = range.split(\"-\").map(Number);\n\n return value >= lo && value <= hi && (value - lo) % step === 0;\n }\n\n const start = parseInt(range, 10);\n\n return value >= start && (value - start) % step === 0;\n }\n\n // Range: N-M\n if (part.includes(\"-\")) {\n const [lo, hi] = part.split(\"-\").map(Number);\n\n return value >= lo && value <= hi;\n }\n\n // Exact match\n\n return parseInt(part, 10) === value;\n });\n}\n","import { getEnabledTasks } from \"../../db/getEnabledTasks.js\";\nimport { updateTaskLastRun } from \"../../db/updateTaskLastRun.js\";\nimport { matchesCron } from \"./cron.js\";\n\nimport { SCHEDULER_INTERVAL } from \"../../config/config.js\";\nimport type { Task } from \"../../db/types.js\";\n\n// Re-export matchesCron for existing consumers (tests, etc.)\nexport { matchesCron };\n\nexport interface TaskRunner {\n (task: Task): Promise<void>;\n}\n\n/**\n * ShadowClaw — Task Scheduler\n *\n * Evaluates cron expressions and fires tasks on schedule.\n *\n * Runs on the main thread via setInterval.\n */\nexport class TaskScheduler {\n interval: ReturnType<typeof setInterval> | null = null;\n onTaskChange?: () => void;\n runner: TaskRunner;\n\n constructor(runner: TaskRunner, onTaskChange?: () => void) {\n this.runner = runner;\n this.onTaskChange = onTaskChange;\n }\n\n /**\n * Check if a task already ran in this minute (prevent double-execution).\n */\n ranThisMinute(task: Task, now: Date): boolean {\n if (!task.lastRun) {\n return false;\n }\n\n const last = new Date(task.lastRun);\n\n return (\n last.getFullYear() === now.getFullYear() &&\n last.getMonth() === now.getMonth() &&\n last.getDate() === now.getDate() &&\n last.getHours() === now.getHours() &&\n last.getMinutes() === now.getMinutes()\n );\n }\n\n /**\n * Start the scheduler. Checks for due tasks every 60 seconds.\n */\n start() {\n if (this.interval) {\n return;\n }\n\n this.interval = setInterval(() => this.tick(), SCHEDULER_INTERVAL);\n\n // Immediate first check\n this.tick();\n }\n\n /**\n * Stop the scheduler.\n */\n stop() {\n if (this.interval) {\n clearInterval(this.interval);\n\n this.interval = null;\n }\n }\n\n /**\n * Check for due tasks and run them.\n */\n async tick() {\n try {\n const tasks = await getEnabledTasks();\n const now = new Date();\n\n for (const task of tasks) {\n const taskSchedule = task.schedule || \"\";\n if (\n taskSchedule !== \"\" &&\n matchesCron(taskSchedule, now) &&\n !this.ranThisMinute(task, now)\n ) {\n // Mark as run immediately to prevent double-firing\n await updateTaskLastRun(task.id, now.getTime());\n this.onTaskChange?.();\n\n // Fire task (non-blocking)\n this.runner(task).catch((err) => {\n console.error(`Task ${task.id} failed:`, err);\n });\n }\n }\n } catch (err) {\n console.error(\"Scheduler tick error:\", err);\n }\n }\n}\n","import { normalizeStringList } from \"./normalizeStringList.js\";\n\n/**\n * Parses a stored string value into a normalized list of strings.\n * Attempts JSON array parse first, then falls back to comma-separated.\n */\nexport function parseStoredStringList(value: string | undefined): string[] {\n if (!value) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(value);\n if (Array.isArray(parsed)) {\n return normalizeStringList(parsed.map((entry) => String(entry)));\n }\n } catch {\n // Fall back to comma-separated input for forward compatibility.\n }\n\n return normalizeStringList(value.split(\",\"));\n}\n","import { CONFIG_KEYS } from \"../../../config/config.js\";\n\nimport { inferAttachmentMimeType } from \"../../../content/message-attachments.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { readGroupFileBytes } from \"../../../storage/readGroupFileBytes.js\";\nimport { loadChannelEnabled } from \"./operations/channel.js\";\nimport { parseStoredStringList } from \"./parseStoredStringList.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport async function loadChannelConfigurations(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.channelEnabledByType.telegram = await loadChannelEnabled(\n \"telegram\",\n db,\n );\n\n orchestrator.channelEnabledByType.imessage = await loadChannelEnabled(\n \"imessage\",\n db,\n );\n\n const telegramToken = await orchestrator.loadSecretConfig(\n db,\n CONFIG_KEYS.TELEGRAM_BOT_TOKEN,\n );\n\n const telegramChatIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.TELEGRAM_CHAT_IDS),\n );\n\n const telegramUseProxy =\n (await getConfig(db, CONFIG_KEYS.TELEGRAM_USE_PROXY)) === \"true\";\n\n orchestrator.telegramBotToken = telegramToken;\n orchestrator.telegramChatIds = telegramChatIds;\n orchestrator.telegramUseProxy = telegramUseProxy;\n orchestrator.telegram.configure(\n telegramToken,\n telegramChatIds,\n telegramUseProxy,\n );\n\n const readWorkspaceFileAsBlob = async (\n groupId: string,\n path: string,\n ): Promise<Blob | null> => {\n try {\n const bytes = await readGroupFileBytes(db, groupId, path);\n const blobBytes = new Uint8Array(bytes.byteLength);\n blobBytes.set(bytes);\n\n const fileName = path.split(\"/\").pop() || path;\n const mimeType = inferAttachmentMimeType(fileName);\n\n return new Blob([blobBytes], { type: mimeType });\n } catch (err) {\n console.warn(`Orchestrator: channel fileReader failed for ${path}:`, err);\n\n return null;\n }\n };\n\n orchestrator.telegram.fileReader = readWorkspaceFileAsBlob;\n orchestrator.imessage.fileReader = readWorkspaceFileAsBlob;\n\n const imessageServerUrl = (\n (await getConfig(db, CONFIG_KEYS.IMESSAGE_SERVER_URL)) || \"\"\n )\n .trim()\n .replace(/\\/+$/, \"\");\n\n const imessageApiKey = await orchestrator.loadSecretConfig(\n db,\n CONFIG_KEYS.IMESSAGE_API_KEY,\n );\n\n const imessageChatIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.IMESSAGE_CHAT_IDS),\n );\n\n orchestrator.imessageServerUrl = imessageServerUrl;\n orchestrator.imessageApiKey = imessageApiKey;\n orchestrator.imessageChatIds = imessageChatIds;\n orchestrator.imessage.configure(\n imessageServerUrl,\n imessageApiKey,\n imessageChatIds,\n );\n\n // ---- PeerJS ----\n orchestrator.channelEnabledByType.peerjs = await loadChannelEnabled(\n \"peerjs\",\n db,\n );\n\n const peerjsMyPeerId = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_MY_PEER_ID)) || \"\"\n ).trim();\n\n const peerjsTrustedPeerIds = parseStoredStringList(\n await getConfig(db, CONFIG_KEYS.PEERJS_TRUSTED_PEER_IDS),\n );\n\n const peerjsServerHost = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_SERVER_HOST)) || \"\"\n ).trim();\n\n const peerjsServerPortRaw = await getConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_PORT,\n );\n\n const peerjsServerPort = peerjsServerPortRaw\n ? parseInt(peerjsServerPortRaw, 10) || 0\n : 0;\n\n const peerjsServerPath = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_SERVER_PATH)) || \"\"\n ).trim();\n\n const peerjsServerSecureRaw = await getConfig(\n db,\n CONFIG_KEYS.PEERJS_SERVER_SECURE,\n );\n\n const peerjsServerSecure = peerjsServerSecureRaw !== \"false\";\n\n let peerjsPeerAliases: Record<string, string> = {};\n\n const storedAliasesRaw = await getConfig(db, CONFIG_KEYS.PEERJS_PEER_ALIASES);\n\n if (storedAliasesRaw) {\n try {\n peerjsPeerAliases = JSON.parse(storedAliasesRaw);\n } catch (err) {\n console.warn(\"Failed to parse peerjs_peer_aliases\", err);\n }\n }\n\n orchestrator.peerjsMyPeerId = peerjsMyPeerId;\n orchestrator.peerjsMyAlias = (\n (await getConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS)) || \"\"\n ).trim();\n\n orchestrator.peerjsTrustedPeerIds = peerjsTrustedPeerIds;\n orchestrator.peerjsPeerAliases = peerjsPeerAliases;\n orchestrator.peerjsServerHost = peerjsServerHost;\n orchestrator.peerjsServerPort = peerjsServerPort;\n orchestrator.peerjsServerPath = peerjsServerPath;\n orchestrator.peerjsServerSecure = peerjsServerSecure;\n\n const peerjsServerConfig = peerjsServerHost\n ? {\n host: peerjsServerHost,\n port: peerjsServerPort || undefined,\n path: peerjsServerPath || undefined,\n secure: peerjsServerSecure,\n }\n : {};\n\n orchestrator.peerjs.configure(\n peerjsMyPeerId,\n peerjsTrustedPeerIds,\n peerjsServerConfig,\n );\n}\n","export const DEFAULT_DIRECT_TOOL_COMMAND_POLICY: DirectToolCommandPolicy = {\n allowedTools: [\"clear_chat\", \"show_toast\"],\n enabledChannelTypes: [\"telegram\"],\n requireMention: true,\n};\n\nexport type ParsedDirectToolCommand = {\n input: Record<string, any>;\n toolName: string;\n};\n\nexport interface DirectToolCommandPolicy {\n allowedTools: string[];\n enabledChannelTypes: string[];\n requireMention: boolean;\n}\n","import {\n DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n type DirectToolCommandPolicy,\n} from \"./types.js\";\n\n/**\n * Parses a raw JSON string into a validated DirectToolCommandPolicy.\n * Falls back to the default policy on parse failure or missing input.\n */\nexport function parseDirectToolCommandPolicy(\n raw: string | null | undefined,\n): DirectToolCommandPolicy {\n if (!raw) {\n return {\n allowedTools: [...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools],\n enabledChannelTypes: [\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes,\n ],\n requireMention: DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n }\n\n try {\n const parsed = JSON.parse(raw) as Partial<DirectToolCommandPolicy>;\n\n const enabledChannelTypes = Array.isArray(parsed.enabledChannelTypes)\n ? parsed.enabledChannelTypes.filter(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n )\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes;\n\n const allowedTools = Array.isArray(parsed.allowedTools)\n ? parsed.allowedTools.filter(\n (v): v is string => typeof v === \"string\" && v.trim().length > 0,\n )\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools;\n\n return {\n allowedTools,\n enabledChannelTypes,\n requireMention:\n typeof parsed.requireMention === \"boolean\"\n ? parsed.requireMention\n : DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n } catch {\n return {\n allowedTools: [...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.allowedTools],\n enabledChannelTypes: [\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY.enabledChannelTypes,\n ],\n requireMention: DEFAULT_DIRECT_TOOL_COMMAND_POLICY.requireMention,\n };\n }\n}\n","import { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { submitMessage } from \"./operations/channel.js\";\nimport { syncProxyConfigToServiceWorker } from \"./syncProxyConfigToServiceWorker.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport function setupPushTaskListener(\n orchestrator: Orchestrator,\n _db: ShadowClawDatabase,\n): void {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n\n navigator.serviceWorker.addEventListener(\"message\", (event) => {\n if (event.data?.type === \"request-proxy-config\") {\n // The service worker just restarted and lost its in-memory proxy config.\n // Re-sync so fetch interception resumes immediately.\n syncProxyConfigToServiceWorker(orchestrator);\n\n return;\n }\n\n if (event.data?.type !== \"scheduled-task-trigger\") {\n return;\n }\n\n const { taskId, groupId, prompt, taskType, tools } = event.data;\n if (!groupId) {\n return;\n }\n\n // Mark this group as scheduler-triggered for recursion prevention\n orchestrator.schedulerTriggeredGroups.add(groupId);\n\n // Execute the task via the same path as client-side scheduler\n const runTaskHandler = async () => {\n const fullTask = orchestratorStore.tasks.find((t) => t.id === taskId);\n if (fullTask) {\n orchestratorStore.runTask(fullTask);\n\n return;\n }\n\n if (taskType === \"tools\" && Array.isArray(tools) && tools.length > 0) {\n orchestratorStore.runTask({\n id: taskId || `push-task-${Date.now()}`,\n groupId,\n createdAt: Date.now(),\n enabled: true,\n prompt: prompt || \"\",\n type: \"tools\",\n tools,\n lastRun: null,\n });\n\n return;\n }\n\n if (prompt) {\n // Fallback if not found in local store\n submitMessage(orchestrator, prompt, groupId);\n }\n };\n\n runTaskHandler()\n .catch((err) =>\n console.error(`Push-triggered task ${taskId} failed:`, err),\n )\n .finally(() => {\n orchestrator.schedulerTriggeredGroups.delete(groupId);\n });\n });\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n buildTriggerPattern,\n getDefaultProvider,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { deleteRoom, getRoomMetadata, upsertRoom } from \"../../../db/rooms.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\n\nimport { toTrustedScriptUrl } from \"../../../security/trusted-types.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { RoomManager } from \"../../../subsystems/channels/room-manager.js\";\nimport { setWebMcpMode as applyWebMcpMode } from \"../../../subsystems/mcp/webmcp.js\";\nimport { modelRegistry } from \"../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../subsystems/providers/prompt-api-provider.js\";\nimport { fetchTokenizerConfig } from \"../../../subsystems/providers/utils/chatTemplate.js\";\nimport { TaskScheduler } from \"../../../subsystems/tools/task-scheduler.js\";\nimport { enqueue } from \"./enqueue.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\nimport { loadChannelConfigurations } from \"./loadChannelConfigurations.js\";\nimport { applyAllChannelRunningStates } from \"./operations/channel.js\";\n\nimport {\n applyLlamafileHeaders,\n applyMeshLlmHeaders,\n getApiKeyForHeaders,\n getProviderRuntimeHeaders,\n} from \"./operations/provider.js\";\n\nimport { handleRoomInvite } from \"./operations/room.js\";\n\nimport {\n runTaskAsScheduled,\n shouldStartLocalScheduler,\n} from \"./operations/task.js\";\n\nimport { parseDirectToolCommandPolicy } from \"./parseDirectToolCommandPolicy.js\";\nimport { setupPushTaskListener } from \"./setupPushTaskListener.js\";\nimport { syncProxyConfigToServiceWorker } from \"./syncProxyConfigToServiceWorker.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { RoomTransport } from \"../../../subsystems/channels/room-manager.js\";\n\nimport type {\n InboundMessage,\n RoomMember,\n} from \"../../../subsystems/channels/types.js\";\n\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nexport function createRoomManager(orchestrator: Orchestrator): RoomManager {\n const transport: RoomTransport = {\n get myPeerId() {\n return orchestrator.peerjs.myPeerId || orchestrator.peerjsMyPeerId;\n },\n sendToPeer: (peerId, note) =>\n orchestrator.peerjs.sendRoomNotification(peerId, note),\n isConnected: (peerId) => orchestrator.peerjs.isPeerConnected(peerId),\n connectToPeer: (peerId) => orchestrator.peerjs.connectPeer(peerId),\n };\n\n return new RoomManager({\n transport,\n getLocalMember: (): RoomMember => ({\n peerId: orchestrator.peerjs.myPeerId || orchestrator.peerjsMyPeerId,\n alias:\n orchestrator.peerjsMyAlias ||\n orchestrator.peerjs.myPeerId ||\n orchestrator.peerjsMyPeerId ||\n orchestrator.assistantName,\n kind: \"agent\",\n agentName: orchestrator.assistantName,\n }),\n onMessage: (msg) => orchestrator.roomChannel.deliverInbound(msg),\n onInvite: (invite) => handleRoomInvite(orchestrator, invite),\n persistRoom: (room) => {\n if (orchestrator.db) {\n upsertRoom(orchestrator.db, room).catch((err) =>\n console.error(\"Failed to persist room:\", err),\n );\n }\n },\n removeRoom: (roomId) => {\n if (orchestrator.db) {\n deleteRoom(orchestrator.db, roomId).catch((err) =>\n console.error(\"Failed to delete room:\", err),\n );\n }\n },\n });\n}\n\nexport async function initChannelsAndRooms(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.initializeChannelRegistry();\n\n orchestrator.channelRegistry.onMessage((msg: InboundMessage) => {\n enqueue(orchestrator, db, msg).catch((error) => {\n console.error(\"Failed to enqueue inbound message:\", error);\n });\n });\n\n orchestrator.channelRegistry.onTyping((groupId: string, typing: boolean) => {\n orchestrator.events.emit(\"typing\", { groupId, typing });\n // Update remote agent typing status for peer channels\n if (groupId.startsWith(\"peer:\")) {\n orchestratorStore.setRemoteAgentTyping(groupId, typing);\n }\n });\n\n // A2A task completion: when a remote peer sends a terminal status update,\n // suppress further auto-triggers for that conversation.\n orchestrator.peerjs.onTaskComplete((groupId: string) => {\n orchestrator.peerCompletedContexts.add(groupId);\n });\n\n await loadChannelConfigurations(orchestrator, db);\n applyAllChannelRunningStates(orchestrator);\n\n // Restore persisted multi-party rooms\n try {\n const rooms = await getRoomMetadata(db);\n orchestrator.roomManager.loadRooms(rooms);\n } catch (err) {\n console.error(\"Failed to load rooms:\", err);\n }\n}\n\nexport async function initCoreConfig(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.assistantName =\n (await getConfig(db, CONFIG_KEYS.ASSISTANT_NAME)) || ASSISTANT_NAME;\n\n orchestrator.triggerPattern = buildTriggerPattern(orchestrator.assistantName);\n}\n\nexport async function initFeatureFlagsAndLimits(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n const storedVMBootMode = await getConfig(db, CONFIG_KEYS.VM_BOOT_MODE);\n orchestrator.vmBootMode =\n storedVMBootMode === \"disabled\" ||\n storedVMBootMode === \"auto\" ||\n storedVMBootMode === \"9p\" ||\n storedVMBootMode === \"ext2\"\n ? (storedVMBootMode as any)\n : \"disabled\";\n\n const storedStreaming = await getConfig(db, CONFIG_KEYS.STREAMING_ENABLED);\n orchestrator.streamingEnabled = storedStreaming !== \"false\";\n\n const storedWebMcpToolsEnabled = await getConfig(\n db,\n CONFIG_KEYS.WEBMCP_TOOLS_ENABLED,\n );\n\n orchestrator.webMcpToolsEnabled = storedWebMcpToolsEnabled !== \"false\";\n\n const storedBashFullInternetAccess = await getConfig(\n db,\n CONFIG_KEYS.VM_BASH_FULL_INTERNET_ACCESS,\n );\n\n orchestrator.vmBashFullInternetAccess =\n storedBashFullInternetAccess === \"true\";\n\n const storedWebMcpMode = await getConfig(db, CONFIG_KEYS.WEBMCP_MODE);\n if (storedWebMcpMode === \"native\" || storedWebMcpMode === \"polyfill\") {\n applyWebMcpMode(storedWebMcpMode);\n }\n\n const storedCompression = await getConfig(\n db,\n CONFIG_KEYS.CONTEXT_COMPRESSION_ENABLED,\n );\n\n orchestrator.contextCompressionEnabled = storedCompression === \"true\";\n\n const storedReasoningEffort = await getConfig(\n db,\n CONFIG_KEYS.REASONING_EFFORT,\n );\n orchestrator.reasoningEffort = storedReasoningEffort\n ? storedReasoningEffort.trim().toLowerCase()\n : \"none\";\n\n const storedDirectToolPolicy = await getConfig(\n db,\n CONFIG_KEYS.DIRECT_TOOL_COMMAND_POLICY,\n );\n\n orchestrator.directToolCommandPolicy = parseDirectToolCommandPolicy(\n storedDirectToolPolicy,\n );\n\n const storedUseProxy = await getConfig(db, CONFIG_KEYS.USE_PROXY);\n orchestrator.useProxy = storedUseProxy === \"true\";\n\n orchestrator.proxyUrl =\n (await getConfig(db, CONFIG_KEYS.PROXY_URL)) || \"/proxy\";\n orchestrator.gitProxyUrl =\n (await getConfig(db, CONFIG_KEYS.GIT_PROXY_URL)) || \"/git-proxy\";\n const storedTaskServerEnabled = await getConfig(\n db,\n CONFIG_KEYS.TASK_SERVER_ENABLED,\n );\n orchestrator.taskServerEnabled = storedTaskServerEnabled === \"true\";\n\n orchestrator.taskServerUrl =\n (await getConfig(db, CONFIG_KEYS.TASK_SERVER_URL)) ||\n (await import(\"../../../config/config.js\")).DEFAULT_TASK_SERVER_URL;\n}\n\nexport async function initLlamafileAndMesh(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n const storedLlamafileMode = await getConfig(db, CONFIG_KEYS.LLAMAFILE_MODE);\n if (storedLlamafileMode === \"cli\" || storedLlamafileMode === \"server\") {\n orchestrator.llamafileMode = storedLlamafileMode;\n } else {\n await setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, orchestrator.llamafileMode);\n }\n\n const storedLlamafileHost = await getConfig(db, CONFIG_KEYS.LLAMAFILE_HOST);\n if (storedLlamafileHost) {\n orchestrator.llamafileHost = storedLlamafileHost;\n }\n\n const storedLlamafilePort = await getConfig(db, CONFIG_KEYS.LLAMAFILE_PORT);\n if (storedLlamafilePort) {\n const parsedPort = parseInt(storedLlamafilePort, 10);\n if (Number.isFinite(parsedPort) && parsedPort >= 1 && parsedPort <= 65535) {\n orchestrator.llamafilePort = parsedPort;\n }\n }\n\n const storedLlamafileOffline = await getConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n );\n\n if (storedLlamafileOffline === \"false\") {\n orchestrator.llamafileOffline = false;\n }\n\n applyLlamafileHeaders(orchestrator);\n\n const storedmeshLlmHost = await getConfig(db, CONFIG_KEYS.MESH_LLM_HOST);\n if (storedmeshLlmHost) {\n orchestrator.meshLlmHost = storedmeshLlmHost;\n }\n\n applyMeshLlmHeaders(orchestrator);\n}\n\nexport async function initProviderAndModel(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Parallelize all independent IDB reads in this function.\n const [\n storedProvider,\n bedrockRegion,\n bedrockProfile,\n bedrockAuthMode,\n storedModel,\n storedMaxTokens,\n storedMaxIterations,\n storedRateLimitCallsPerMinute,\n storedRateLimitAutoAdapt,\n ] = await Promise.all([\n getConfig(db, CONFIG_KEYS.PROVIDER),\n getConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK),\n getConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK),\n getConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE),\n getConfig(db, CONFIG_KEYS.MODEL),\n getConfig(db, CONFIG_KEYS.MAX_TOKENS),\n getConfig(db, CONFIG_KEYS.MAX_ITERATIONS),\n getConfig(db, CONFIG_KEYS.RATE_LIMIT_CALLS_PER_MINUTE),\n getConfig(db, CONFIG_KEYS.RATE_LIMIT_AUTO_ADAPT),\n ]);\n\n if (storedProvider && getProvider(storedProvider)) {\n orchestrator.provider = storedProvider;\n orchestrator.providerConfig =\n getProvider(storedProvider) || getDefaultProvider();\n }\n\n // Load API key — must happen after provider is set.\n await orchestrator.loadApiKeyForProvider(db, orchestrator.provider);\n\n orchestrator.bedrockRegionFallback = (bedrockRegion || \"\").trim();\n orchestrator.bedrockProfileFallback = (bedrockProfile || \"\").trim();\n orchestrator.bedrockAuthMode = (bedrockAuthMode || \"provider_chain\").trim();\n\n // Fetch model info in the background. While primarily used to populate\n // the model picker in Settings, it is also required to dynamically resolve\n // optimal max_tokens limits for scheduled jobs and background tasks.\n // We defer it until the browser is idle to ensure it doesn't block first paint.\n const scheduleFetch = () => {\n const doFetch = () => {\n void getApiKeyForHeaders(orchestrator).then((apiKey) =>\n modelRegistry.fetchModelInfo(\n orchestrator.providerConfig,\n apiKey || undefined,\n getProviderRuntimeHeaders(orchestrator, orchestrator.provider),\n ),\n );\n };\n\n if (typeof (globalThis as any).requestIdleCallback === \"function\") {\n (globalThis as any).requestIdleCallback(doFetch, { timeout: 5000 });\n } else {\n setTimeout(doFetch, 2000);\n }\n };\n\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n if (document.readyState === \"complete\") {\n scheduleFetch();\n } else {\n window.addEventListener(\"load\", scheduleFetch, { once: true });\n }\n } else {\n scheduleFetch();\n }\n\n if (storedModel) {\n orchestrator.model = storedModel;\n } else {\n orchestrator.model = orchestrator.providerConfig.defaultModel;\n }\n\n let effectiveMaxTokensModel = orchestrator.model;\n if (\n orchestrator.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (orchestrator.model === \"browser-built-in\" || !orchestrator.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveMaxTokensModel =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n fetchTokenizerConfig(effectiveMaxTokensModel).catch(() => {});\n }\n\n const dynamicMaxTokens = getModelMaxTokens(effectiveMaxTokensModel);\n\n // If the stored value is exactly 8192 (our legacy fallback) or 4096 (legacy prompt_api default),\n // prioritize the dynamic value from our registry and updated limits definitions.\n if (\n storedMaxTokens === \"8192\" ||\n (orchestrator.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n storedMaxTokens === \"4096\")\n ) {\n orchestrator.maxTokens = dynamicMaxTokens;\n } else {\n const parsedStored = parseInt(\n storedMaxTokens || String(dynamicMaxTokens),\n 10,\n );\n\n orchestrator.maxTokens = Math.max(1, parsedStored);\n }\n\n if (storedMaxIterations) {\n orchestrator.maxIterations =\n parseInt(storedMaxIterations, 10) || DEFAULT_MAX_ITERATIONS;\n }\n\n if (storedRateLimitCallsPerMinute) {\n const parsed = parseInt(storedRateLimitCallsPerMinute, 10);\n orchestrator.rateLimitCallsPerMinute = Number.isFinite(parsed)\n ? Math.max(0, parsed)\n : 0;\n }\n\n orchestrator.rateLimitAutoAdapt = storedRateLimitAutoAdapt !== \"false\";\n}\n\nexport async function initWorkerAndScheduler(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): Promise<void> {\n orchestrator.agentWorker = new Worker(\n toTrustedScriptUrl(\n new URL(\"./agent.worker.js\", import.meta.url).href,\n ) as string,\n {\n type: \"module\",\n },\n );\n\n orchestrator.agentWorker.onmessage = (event) =>\n handleWorkerMessage(orchestrator, db, event.data);\n\n orchestrator.agentWorker.onerror = (err) => {\n console.error(\"Agent worker error:\", err);\n };\n\n const storageHandle = await getConfig(db, CONFIG_KEYS.STORAGE_HANDLE);\n if (storageHandle) {\n orchestrator.agentWorker.postMessage({\n payload: { storageHandle },\n type: \"set-storage\",\n });\n }\n\n // Sync proxy config to Service Worker\n syncProxyConfigToServiceWorker(orchestrator);\n\n // Set up task scheduler.\n // When push scheduling is available, the server-side scheduler should be\n // authoritative. The local client scheduler is only used as a fallback\n // when push background execution is unavailable.\n orchestrator.scheduler = new TaskScheduler(\n async (task) => {\n await runTaskAsScheduled(orchestrator, task);\n },\n () => {\n orchestrator.events.emit(\"task-change\", { type: \"executed\" });\n },\n );\n\n // Start the task scheduler in the background — shouldStartLocalScheduler()\n // is an async IDB read that doesn't need to block UI readiness.\n // The scheduler starting one microtask-tick late is harmless because no\n // scheduled task can fire before the app is fully initialized anyway.\n void shouldStartLocalScheduler().then((should) => {\n if (should) {\n orchestrator.scheduler?.start();\n }\n });\n\n setupPushTaskListener(orchestrator, db);\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_GROUP_ID,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_MAX_TOKENS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n DEFAULT_PROVIDER,\n DEFAULT_TASK_SERVER_ENABLED,\n ProviderConfig,\n buildTriggerPattern,\n getDefaultProvider,\n getProvider,\n getProviderApiKeyConfigKey,\n getModelMaxTokens,\n} from \"../../config/config.js\";\n\nimport { buildDynamicContext } from \"../../context/buildDynamicContext.js\";\nimport { estimateTokens } from \"../../context/estimateTokens.js\";\nimport { buildConversationMessages } from \"../../db/buildConversationMessages.js\";\nimport { clearGroupMessages } from \"../../db/clearGroupMessages.js\";\nimport { getConfig } from \"../../db/getConfig.js\";\nimport { listGroups } from \"../../db/groups.js\";\nimport { openDatabase } from \"../../db/openDatabase.js\";\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\nimport { saveMessage } from \"../../db/saveMessage.js\";\nimport { setConfig } from \"../../db/setConfig.js\";\nimport { decryptValue, encryptValue } from \"../../security/crypto.js\";\nimport { VMBootMode, VMStatus } from \"../../shell/vm.js\";\nimport { readGroupFile } from \"../../storage/readGroupFile.js\";\n\nimport {\n OrchestratorDisplayState,\n orchestratorStore,\n} from \"../../stores/orchestrator.js\";\n\nimport { toolsStore } from \"../../stores/tools.js\";\nimport { BrowserChatChannel } from \"../../subsystems/channels/browser-chat.js\";\nimport { ChannelRegistry } from \"../../subsystems/channels/channel-registry.js\";\nimport { IMessageChannel } from \"../../subsystems/channels/imessage.js\";\nimport { PeerJsChannel } from \"../../subsystems/channels/peerjs.js\";\nimport { RoomManager } from \"../../subsystems/channels/room-manager.js\";\nimport { RoomChannel } from \"../../subsystems/channels/room.js\";\nimport { TelegramChannel } from \"../../subsystems/channels/telegram.js\";\n\nimport { unregisterWebMcpTools } from \"../../subsystems/mcp/webmcp.js\";\nimport { isPromptApiSupported } from \"../../subsystems/providers/prompt-api-provider.js\";\n\nimport { getContextLimit } from \"../../subsystems/providers/providers.js\";\nimport { TaskScheduler } from \"../../subsystems/tools/task-scheduler.js\";\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/formatA2UIActionPrompt.js\";\nimport { ulid } from \"../../utils/ulid.js\";\nimport { buildSystemPrompt } from \"../../worker/utils/system-prompt.js\";\nimport { Router } from \"../router.js\";\nimport { enqueue } from \"./utils/enqueue.js\";\nimport { EventBus } from \"./utils/EventBus.js\";\n\nimport {\n createRoomManager,\n initChannelsAndRooms,\n initCoreConfig,\n initFeatureFlagsAndLimits,\n initLlamafileAndMesh,\n initProviderAndModel,\n initWorkerAndScheduler,\n} from \"./utils/initTasks.js\";\n\nimport { invokeAgent } from \"./utils/invokeAgent.js\";\n\nimport {\n cancelLlamafileRequest,\n stopTransformersProgressPolling,\n} from \"./utils/operations/provider.js\";\n\nimport { syncWebMcpRegistration } from \"./utils/syncWebMcpRegistration.js\";\nimport { DEFAULT_DIRECT_TOOL_COMMAND_POLICY } from \"./utils/types.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/db.js\";\nimport type { A2UIAction } from \"../../ui/a2ui/types.js\";\nimport type { DirectToolCommandPolicy } from \"./utils/types.js\";\n\nexport class Orchestrator {\n agentWorker: Worker | null = null;\n assistantName: string = ASSISTANT_NAME;\n\n bedrockAuthMode: string = \"provider_chain\";\n bedrockProfileFallback: string = \"\";\n bedrockRegionFallback: string = \"\";\n\n browserChat: BrowserChatChannel = new BrowserChatChannel();\n\n channelEnabledByType: Record<string, boolean> = {\n browser: true,\n peerjs: false,\n telegram: false,\n imessage: false,\n };\n\n channelRegistry: ChannelRegistry = new ChannelRegistry();\n contextCompressionEnabled: boolean = false;\n\n db: ShadowClawDatabase | null = null;\n directToolCommandPolicy: DirectToolCommandPolicy = {\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n };\n\n events: EventBus = new EventBus();\n gitProxyUrl: string = \"/git-proxy\";\n\n imessage: IMessageChannel = new IMessageChannel();\n imessageApiKey: string = \"\";\n imessageChatIds: string[] = [];\n imessageServerUrl: string = \"\";\n\n inFlightEffectiveProviderByGroup: Map<\n string,\n {\n providerId: string;\n providerConfig: ProviderConfig;\n model: string;\n }\n > = new Map();\n\n inFlightProviderRequestIds: Map<string, string> = new Map();\n inFlightTriggerByGroup: Map<string, string> = new Map();\n\n llamafileHost: string = \"127.0.0.1\";\n llamafileMode: \"server\" | \"cli\" = \"cli\";\n llamafileOffline: boolean = true;\n llamafilePort: number = 8080;\n\n maxIterations: number = DEFAULT_MAX_ITERATIONS;\n maxTokens: number = DEFAULT_MAX_TOKENS;\n\n meshLlmHost: string = \"\";\n\n messageQueue: any[] = [];\n model: string = getDefaultProvider().defaultModel;\n\n /** Peer groupIds where the A2A task has reached a terminal state */\n peerCompletedContexts = new Set<string>();\n peerjs: PeerJsChannel = new PeerJsChannel();\n peerjsMyAlias: string = \"\";\n peerjsMyPeerId: string = \"\";\n peerjsPeerAliases: Record<string, string> = {};\n peerjsServerHost: string = \"\";\n peerjsServerPath: string = \"\";\n peerjsServerPort: number = 0;\n peerjsServerSecure: boolean = true;\n peerjsTrustedPeerIds: string[] = [];\n\n pendingScheduledTasks: Set<string> = new Set();\n processing: boolean = false;\n promptControllers: Map<string, AbortController> = new Map();\n\n provider: string = DEFAULT_PROVIDER;\n providerConfig: ProviderConfig = getDefaultProvider();\n\n proxyUrl: string = \"/proxy\";\n pushSubscriptionWarned: boolean = false;\n rateLimitAutoAdapt: boolean = true;\n\n rateLimitCallsPerMinute: number = 0;\n reasoningEffort: string = \"none\";\n\n /** Multi-party room channel + manager (layered on the PeerJS transport). */\n roomChannel: RoomChannel = new RoomChannel();\n roomManager!: RoomManager;\n\n router: Router | null = null;\n\n scheduler: TaskScheduler | null = null;\n schedulerTriggeredGroups: Set<string> = new Set();\n\n state: OrchestratorDisplayState = \"idle\";\n streamingEnabled: boolean = true;\n taskServerEnabled: boolean = DEFAULT_TASK_SERVER_ENABLED;\n taskServerUrl: string = \"/schedule\";\n\n telegram: TelegramChannel = new TelegramChannel();\n telegramBotToken: string = \"\";\n telegramChatIds: string[] = [];\n telegramUseProxy: boolean = false;\n\n transformersProgressPollers: Map<string, number> = new Map();\n triggerPattern: RegExp = buildTriggerPattern(ASSISTANT_NAME);\n useProxy: boolean = false;\n\n vmBashFullInternetAccess: boolean = false;\n vmBootMode: VMBootMode = \"disabled\";\n vmStatus: VMStatus = {\n ready: false,\n booting: false,\n bootAttempted: false,\n error: null,\n };\n\n webMcpEffectCleanup: (() => void) | null = null;\n webMcpRegistrationLock: Promise<void> = Promise.resolve();\n webMcpToolsEnabled: boolean = true;\n\n #apiKeyCache: { value: string; expiresAt: number } | null = null;\n #encryptedApiKey: string | null = null;\n\n constructor() {\n this.roomManager = createRoomManager(this);\n this.initializeChannelRegistry();\n }\n\n clearProviderRequest(groupId: string): void {\n this.inFlightProviderRequestIds.delete(groupId);\n }\n\n createProviderRequestId(groupId: string): string {\n if (this.provider !== \"llamafile\") {\n this.inFlightProviderRequestIds.delete(groupId);\n\n return \"\";\n }\n\n const requestId = `${groupId}:${Date.now().toString(36)}:${Math.random()\n .toString(36)\n .slice(2, 10)}`;\n\n this.inFlightProviderRequestIds.set(groupId, requestId);\n\n return requestId;\n }\n\n initializeChannelRegistry(): void {\n this.channelRegistry = new ChannelRegistry();\n this.channelRegistry.register(\"br:\", this.browserChat, {\n badge: \"Browser\",\n autoTrigger: true,\n });\n\n this.channelRegistry.register(\"tg:\", this.telegram, {\n badge: \"Telegram\",\n autoTrigger: false,\n });\n\n this.channelRegistry.register(\"im:\", this.imessage, {\n badge: \"iMessage\",\n autoTrigger: true,\n });\n\n this.channelRegistry.register(\"peer:\", this.peerjs, {\n badge: \"PeerJS\",\n autoTrigger: false,\n });\n\n this.channelRegistry.register(\"room:\", this.roomChannel, {\n badge: \"Room\",\n autoTrigger: false,\n });\n\n this.roomChannel.setManager(this.roomManager);\n this.peerjs.setRoomNotificationHandler((from, method, params) =>\n this.roomManager.handleNotification(from, method, params),\n );\n\n this.router = new Router(this.channelRegistry);\n }\n\n setState(state: OrchestratorDisplayState, groupId?: string): void {\n this.state = state;\n this.events.emit(\"state-change\", { state, groupId });\n }\n\n /**\n * Shut down everything\n */\n shutdown() {\n this.channelRegistry.stopAll();\n this.scheduler?.stop();\n\n for (const groupId of this.transformersProgressPollers.keys()) {\n stopTransformersProgressPolling(this, groupId);\n }\n\n this.agentWorker?.terminate();\n\n if (typeof this.webMcpEffectCleanup === \"function\") {\n this.webMcpEffectCleanup();\n }\n\n unregisterWebMcpTools();\n }\n\n stopCurrentRequest(groupId = DEFAULT_GROUP_ID): void {\n if (this.state !== \"thinking\" && this.state !== \"responding\") {\n return;\n }\n\n stopTransformersProgressPolling(this, groupId);\n const providerRequestId =\n this.inFlightProviderRequestIds.get(groupId) || \"\";\n this.clearProviderRequest(groupId);\n\n this.agentWorker?.postMessage({\n type: \"cancel\",\n payload: { groupId },\n });\n\n if (this.provider === \"llamafile\" && providerRequestId) {\n void cancelLlamafileRequest(providerRequestId);\n }\n\n const promptController = this.promptControllers.get(groupId);\n if (promptController) {\n promptController.abort();\n\n this.promptControllers.delete(groupId);\n }\n\n this.inFlightTriggerByGroup.delete(groupId);\n this.inFlightEffectiveProviderByGroup.delete(groupId);\n\n this.events.emit(\"typing\", { groupId, typing: false });\n this.router?.setTyping(groupId, false);\n this.setState(\"idle\", groupId);\n }\n\n async getApiKey(): Promise<string | null> {\n if (!this.#encryptedApiKey) {\n return null;\n }\n\n const now = Date.now();\n if (this.#apiKeyCache && this.#apiKeyCache.expiresAt > now) {\n return this.#apiKeyCache.value;\n }\n\n try {\n const decrypted = await decryptValue(this.#encryptedApiKey);\n if (decrypted === null) {\n return null;\n }\n\n this.#apiKeyCache = {\n expiresAt: now + 30000, // 30s TTL\n value: decrypted,\n };\n\n return decrypted;\n } catch (e) {\n console.error(\"[Orchestrator] Failed to decrypt API key:\", e);\n\n return null;\n }\n }\n\n async getApiKeyForSpecificProvider(\n db: ShadowClawDatabase,\n providerId: string,\n ): Promise<string> {\n let storedKey = await getConfig(db, getProviderApiKeyConfigKey(providerId));\n\n if (!storedKey && providerId === \"openrouter\") {\n const legacyKey = await getConfig(db, CONFIG_KEYS.API_KEY);\n if (legacyKey) {\n storedKey = legacyKey;\n }\n }\n\n if (!storedKey) {\n return \"\";\n }\n\n try {\n const decrypted = await decryptValue(storedKey);\n\n return decrypted || \"\";\n } catch (e) {\n console.error(\"[Orchestrator] Failed to decrypt API key:\", e);\n\n return \"\";\n }\n }\n\n async handleCompactDone(\n db: ShadowClawDatabase,\n groupId: string,\n summary: string,\n ): Promise<void> {\n await clearGroupMessages(db, groupId);\n\n const stored = {\n channel: this.channelRegistry.getChannelType(groupId) ?? \"browser\",\n content: `📝 **Context Compacted**\\n\\n${summary}`,\n groupId,\n id: ulid(),\n isFromMe: true,\n isTrigger: false,\n sender: this.assistantName,\n timestamp: Date.now(),\n };\n\n await saveMessage(db, stored);\n\n this.events.emit(\"context-compacted\", { groupId, summary });\n this.events.emit(\"typing\", { groupId, typing: false });\n\n this.setState(\"idle\", groupId);\n }\n\n async init(): Promise<ShadowClawDatabase> {\n const db = await openDatabase();\n this.db = db;\n\n // Fast parallel path: these four functions only read from IndexedDB and are\n // fully independent of each other. Running them concurrently saves ~200–400 ms\n // compared to the previous sequential await chain.\n await Promise.all([\n initCoreConfig(this, db),\n initProviderAndModel(this, db),\n initLlamafileAndMesh(this, db),\n initFeatureFlagsAndLimits(this, db),\n ]);\n\n // Worker + scheduler need provider/model/flags to be ready, so they still\n // start synchronously after the parallel group above.\n await initWorkerAndScheduler(this, db);\n\n // Channels/rooms are deferred to a background microtask so the UI reaches\n // \"ready\" without waiting for room metadata reads or peer-channel setup.\n // browserChat.onDisplay is called after channels are configured.\n void initChannelsAndRooms(this, db).then(() => {\n this.browserChat.onDisplay(() => {});\n });\n\n this.events.emit(\"ready\", undefined);\n\n await toolsStore.load(db);\n // syncWebMcpRegistration only installs an effect listener; it is safe to\n // call before channels are fully ready because it reacts reactively.\n syncWebMcpRegistration(this, db);\n\n return db;\n }\n\n /**\n * Load the API key for a provider into memory.\n */\n async loadApiKeyForProvider(\n db: ShadowClawDatabase,\n providerId: string,\n ): Promise<void> {\n let storedKey = await getConfig(db, getProviderApiKeyConfigKey(providerId));\n\n if (!storedKey && providerId === \"openrouter\") {\n const legacyKey = await getConfig(db, CONFIG_KEYS.API_KEY);\n if (legacyKey) {\n storedKey = legacyKey;\n await setConfig(db, getProviderApiKeyConfigKey(providerId), legacyKey);\n }\n }\n\n if (!storedKey) {\n this.#encryptedApiKey = \"\";\n } else {\n try {\n // We now store the encrypted key directly in the field.\n // decryptValue is only called on-demand.\n this.#encryptedApiKey = storedKey;\n } catch (e) {\n console.warn(\"[Orchestrator] Failed to load API key:\", e);\n\n this.#encryptedApiKey = \"\";\n }\n }\n\n this.#apiKeyCache = null; // Invalidate cache\n }\n\n async loadSecretConfig(db: ShadowClawDatabase, key: string): Promise<string> {\n const storedValue = await getConfig(db, key);\n if (!storedValue) {\n return \"\";\n }\n\n try {\n return (await decryptValue(storedValue)) || \"\";\n } catch {\n const encrypted = await encryptValue(storedValue);\n if (encrypted) {\n await setConfig(db, key, encrypted);\n }\n\n return storedValue;\n }\n }\n\n async newSession(\n db: ShadowClawDatabase,\n groupId = DEFAULT_GROUP_ID,\n ): Promise<void> {\n await clearGroupMessages(db, groupId);\n\n this.events.emit(\"session-reset\", { groupId });\n }\n\n /**\n * Recompute and emit context usage for the given conversation.\n * Useful after message mutation operations (for example delete) so the\n * context bar updates without waiting for the next model invocation.\n */\n async refreshContextUsage(\n db: ShadowClawDatabase,\n groupId = DEFAULT_GROUP_ID,\n ): Promise<void> {\n let memory = \"\";\n try {\n memory = await readGroupFile(db, groupId, \"MEMORY.md\");\n } catch {\n // No memory file yet.\n }\n\n const activeTools = toolsStore.enabledTools;\n const peerState = orchestratorStore.getPeerState(groupId) || undefined;\n const systemPrompt = buildSystemPrompt(\n this.assistantName,\n memory,\n activeTools,\n toolsStore.systemPromptOverride,\n peerState,\n );\n\n const groups = await listGroups(db);\n const group = groups.find((g) => g.groupId === groupId);\n\n const effectiveModel =\n group?.pinnedModel ??\n (group?.pinnedProvider\n ? (getProvider(group.pinnedProvider)?.defaultModel ?? this.model)\n : this.model);\n\n let modelForTokenLimits = effectiveModel;\n if (\n (group?.pinnedProvider ?? this.provider) === \"prompt_api\" &&\n (effectiveModel === \"browser-built-in\" || !effectiveModel) &&\n !isPromptApiSupported()\n ) {\n const configuredFallback = await getConfig(\n this.db!,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n modelForTokenLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n const configuredMaxTokens =\n typeof group?.pinnedMaxTokens === \"number\" &&\n Number.isFinite(group.pinnedMaxTokens) &&\n group.pinnedMaxTokens > 0\n ? Math.floor(group.pinnedMaxTokens)\n : this.maxTokens;\n\n const effectiveMaxTokens = Math.max(\n 1,\n Math.min(configuredMaxTokens, getModelMaxTokens(modelForTokenLimits)),\n );\n\n const contextLimit = getContextLimit(modelForTokenLimits);\n const systemPromptTokens =\n estimateTokens(systemPrompt) +\n (activeTools?.reduce(\n (acc, t) => acc + estimateTokens(JSON.stringify(t)),\n 0,\n ) ?? 0);\n const allMessages = await buildConversationMessages(groupId, 200);\n const dynamicContext = buildDynamicContext(allMessages, {\n contextLimit,\n systemPromptTokens,\n maxOutputTokens: effectiveMaxTokens,\n skimTop: this.contextCompressionEnabled,\n });\n\n let displayTokens = dynamicContext.estimatedTokens + systemPromptTokens;\n\n // If we have actual token usage from the most recent request,\n // and our heuristic is significantly lower, blend it in to provide a more accurate percentage.\n if (orchestratorStore.tokenUsage) {\n const u = orchestratorStore.tokenUsage;\n const actualPrompt =\n (u.inputTokens || 0) + (u.cacheReadTokens || 0) + (u.outputTokens || 0);\n\n displayTokens = Math.max(displayTokens, actualPrompt);\n }\n\n this.events.emit(\"context-usage\", {\n estimatedTokens: displayTokens,\n contextLimit,\n usagePercent: Math.min(\n 100,\n Math.max(\n dynamicContext.usagePercent,\n (displayTokens / contextLimit) * 100,\n ),\n ),\n truncatedCount: dynamicContext.truncatedCount,\n });\n }\n\n async restartCurrentRequest(groupId = DEFAULT_GROUP_ID): Promise<boolean> {\n if (this.state !== \"thinking\" && this.state !== \"responding\") {\n return false;\n }\n\n if (!this.db) {\n return false;\n }\n\n const triggerContent = this.inFlightTriggerByGroup.get(groupId);\n if (!triggerContent) {\n return false;\n }\n\n this.stopCurrentRequest(groupId);\n\n await invokeAgent(this, this.db, groupId, triggerContent);\n\n return true;\n }\n\n /**\n * Route a user interaction on a **shared room surface** (owner-authoritative).\n *\n * - If the local peer owns the surface (it called `render_component`), the\n * action is enqueued locally so this peer's agent processes it and\n * broadcasts the resulting `updateDataModel` envelope to the room.\n * - Otherwise the action is broadcast over the room mesh so the surface\n * owner's agent can process it. The owner then broadcasts the data-model\n * update, keeping every member's surface in lockstep.\n */\n async routeRoomA2UIAction(\n groupId: string,\n action: A2UIAction,\n ): Promise<void> {\n const roomId = roomIdFromGroupId(groupId);\n const myPeerId = this.peerjs.myPeerId || this.peerjsMyPeerId;\n const ownerPeerId = this.roomManager.getSurfaceOwner(action.surfaceId);\n\n // We own the surface (or no owner is recorded yet — treat a locally\n // initiated action on an unknown surface as ours): process it here.\n if (!ownerPeerId || ownerPeerId === myPeerId) {\n if (!this.db) {\n return;\n }\n\n await enqueue(this, this.db, {\n id: ulid(),\n groupId,\n sender: this.peerjsMyAlias || myPeerId || \"you\",\n content: formatA2UIActionPrompt(action),\n timestamp: Date.now(),\n channel: \"room\",\n a2uiAction: action,\n });\n\n return;\n }\n\n // A remote peer owns the surface — broadcast the action to the room so the\n // owner's agent processes it and synchronizes everyone.\n this.roomManager.broadcastA2UIAction(roomId, action);\n }\n\n async saveSecretConfig(\n db: ShadowClawDatabase,\n key: string,\n value: string,\n ): Promise<void> {\n if (!value) {\n await setConfig(db, key, \"\");\n\n return;\n }\n\n const encrypted = await encryptValue(value);\n if (!encrypted) {\n throw new Error(`Failed to encrypt secret config for ${key}`);\n }\n\n await setConfig(db, key, encrypted);\n }\n\n async setApiKey(db: ShadowClawDatabase, key: string): Promise<void> {\n this.#encryptedApiKey = await encryptValue(key);\n\n // Invalidate cache\n this.#apiKeyCache = null;\n\n const encrypted = await encryptValue(key);\n\n if (!encrypted) {\n throw new Error(\"key failed to encrypt. config cannot set.\");\n }\n\n await setConfig(db, getProviderApiKeyConfigKey(this.provider), encrypted);\n }\n\n submitMessage(text: string, groupId: string = DEFAULT_GROUP_ID): void {\n this.browserChat.submit(text, groupId);\n }\n}\n"],"mappings":"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"}
|