shadow-claw 1.59.7 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/.well-known/mcp/server-card.json +4 -12
  2. package/.well-known/mcp.json +4 -12
  3. package/README.md +6 -2
  4. package/dist/cli/build/build.js +1 -1
  5. package/dist/cli/{chunk-DDvuLVfW.js → chunk-3C5izdQW.js} +1 -1
  6. package/dist/cli/chunk-B-75h9gX.js +1 -0
  7. package/dist/cli/{chunk-hVf839t7.js → chunk-B7Kn-otm.js} +1 -1
  8. package/dist/cli/{chunk-YX32FcN7.js → chunk-BBczgswQ.js} +1 -1
  9. package/dist/cli/{chunk-DcNxjqH6.js → chunk-BE-lYWcn.js} +1 -1
  10. package/dist/cli/{chunk-CQaCgswD.js → chunk-BECr0WxI.js} +11 -11
  11. package/dist/cli/chunk-BEz1PD1_.js +1 -0
  12. package/dist/cli/chunk-BLzI1Fp2.js +1 -0
  13. package/dist/cli/{chunk-B3TrWbca.js → chunk-BVSC1MNQ.js} +11 -11
  14. package/dist/cli/{chunk-D_te8ufL.js → chunk-BdWcep6o.js} +1 -1
  15. package/dist/cli/{chunk-SRBRVorc.js → chunk-BfTpnSS4.js} +1 -1
  16. package/dist/cli/{chunk-D2_eAO83.js → chunk-BgvqTf7w.js} +1 -1
  17. package/dist/cli/chunk-BwsJfUT3.js +1 -0
  18. package/dist/cli/{chunk--PFY91kE.js → chunk-C9b4b7c_.js} +1 -1
  19. package/dist/cli/{chunk-SxK79JmB.js → chunk-CAw9XYFe.js} +1 -1
  20. package/dist/cli/chunk-CFCcbFs2.js +396 -0
  21. package/dist/cli/{chunk-Cnjb8Usu.js → chunk-CTarF4FC.js} +1 -1
  22. package/dist/cli/{chunk-3vNYrs_L.js → chunk-Cbq5hpjb.js} +4 -4
  23. package/dist/cli/chunk-CjTjKy_v.js +310 -0
  24. package/dist/cli/chunk-Cjyu4cr_.js +36 -0
  25. package/dist/cli/{chunk-DUGZPka_.js → chunk-ClMKygjZ.js} +1 -1
  26. package/dist/cli/chunk-Cppnq1KF.js +1 -0
  27. package/dist/cli/{chunk-DvemF16v.js → chunk-D9QCNFMO.js} +1 -1
  28. package/dist/cli/{chunk-iB8OoMmW.js → chunk-DB21BMqt.js} +1 -1
  29. package/dist/cli/{chunk-_Vo-o_e3.js → chunk-DHoIWvCc.js} +1 -1
  30. package/dist/cli/chunk-DZEN9T5y.js +1 -0
  31. package/dist/cli/{chunk-5rLO4DWS.js → chunk-Dl14OyYO.js} +9 -9
  32. package/dist/cli/chunk-Dl_vv0dI.js +1 -0
  33. package/dist/cli/chunk-Dpmfhlyl.js +1 -0
  34. package/dist/cli/{chunk-BrR1DOBS.js → chunk-Du7Xtucq.js} +1 -1
  35. package/dist/cli/{chunk-B88Z8T_9.js → chunk-DxcDFUi_.js} +1 -1
  36. package/dist/cli/{chunk-Dt7-hzJU.js → chunk-DyyEWbV7.js} +1 -1
  37. package/dist/cli/chunk-N0x3mXU0.js +1 -0
  38. package/dist/cli/{chunk-CGoE4llV.js → chunk-V-w0Bata.js} +1 -1
  39. package/dist/cli/{chunk-CncW6_WL.js → chunk-ZxDxSSn-.js} +1 -1
  40. package/dist/cli/{chunk-CZdCRqNe.js → chunk-lPvFUkd5.js} +1 -1
  41. package/dist/cli/{chunk-66BvqAV0.js → chunk-n5s-sCdU.js} +1 -1
  42. package/dist/cli/{chunk-CAAeGOdy.js → chunk-nD9VPVMq.js} +1 -1
  43. package/dist/cli/{chunk-DMs7kREC.js → chunk-rFuy8aS_.js} +1 -1
  44. package/dist/cli/{chunk-B0qusANw.js → chunk-wjM6JXWa.js} +1 -1
  45. package/dist/cli/{chunk-DhOU6GYX.js → chunk-zcES9rut.js} +1 -1
  46. package/dist/cli/cli.js +3 -3
  47. package/dist/headless-agent.js +1 -1
  48. package/dist/lib/{channel-mmdGzPkT.js → channel-DB77spML.js} +2 -2
  49. package/dist/lib/{channel-mmdGzPkT.js.map → channel-DB77spML.js.map} +1 -1
  50. package/dist/lib/{compact-context-CY9BBlUQ.js → compact-context-Q9t9aL1e.js} +7 -7
  51. package/dist/lib/{compact-context-CY9BBlUQ.js.map → compact-context-Q9t9aL1e.js.map} +1 -1
  52. package/dist/lib/components/index.js +21 -21
  53. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  54. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  55. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  56. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  57. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  58. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  59. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  60. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  61. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  62. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  63. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  64. package/dist/lib/components/shadow-claw-channels.js +1 -1
  65. package/dist/lib/components/shadow-claw-chat.js +1 -1
  66. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  67. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  68. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  69. package/dist/lib/components/shadow-claw-files.js +1 -1
  70. package/dist/lib/components/shadow-claw-git.js +1 -1
  71. package/dist/lib/components/shadow-claw-llm.js +1 -1
  72. package/dist/lib/components/shadow-claw-networking.js +1 -1
  73. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  74. package/dist/lib/components/shadow-claw-pages.js +1 -1
  75. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  76. package/dist/lib/components/shadow-claw-settings.js +1 -1
  77. package/dist/lib/components/shadow-claw-storage.js +1 -1
  78. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  79. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  80. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  81. package/dist/lib/components/shadow-claw-tools.js +1 -1
  82. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  83. package/dist/lib/components/shadow-claw.js +1 -1
  84. package/dist/lib/{configure-peer-js-ccNvax2N.js → configure-peer-js-CgFiwoxY.js} +2 -2
  85. package/dist/lib/{configure-peer-js-ccNvax2N.js.map → configure-peer-js-CgFiwoxY.js.map} +1 -1
  86. package/dist/lib/content/build-attachment-content-blocks.d.ts +2 -0
  87. package/dist/lib/{discover-skills-OwlQ2sXA.js → discover-skills-CXyaWHKi.js} +5 -5
  88. package/dist/lib/{discover-skills-OwlQ2sXA.js.map → discover-skills-CXyaWHKi.js.map} +1 -1
  89. package/dist/lib/{git-D2J_j9X9.js → git-CogDRlEz.js} +2 -2
  90. package/dist/lib/{git-D2J_j9X9.js.map → git-CogDRlEz.js.map} +1 -1
  91. package/dist/lib/index.js +21 -21
  92. package/dist/lib/{init-control-plane-B7blDVIE.js → init-control-plane-CEGdzgWX.js} +7 -7
  93. package/dist/lib/{init-control-plane-B7blDVIE.js.map → init-control-plane-CEGdzgWX.js.map} +1 -1
  94. package/dist/lib/{invoke-agent-SxvudiDT.js → invoke-agent-cac3gCsj.js} +6 -6
  95. package/dist/lib/{invoke-agent-SxvudiDT.js.map → invoke-agent-cac3gCsj.js.map} +1 -1
  96. package/dist/lib/{move-group-entry-DDpjxa10.js → move-group-entry-D8dptMg0.js} +2 -2
  97. package/dist/lib/{move-group-entry-DDpjxa10.js.map → move-group-entry-D8dptMg0.js.map} +1 -1
  98. package/dist/lib/{orchestrator-C7fkh7T7.js → orchestrator-BBAwy9Nm.js} +12 -12
  99. package/dist/lib/{orchestrator-C7fkh7T7.js.map → orchestrator-BBAwy9Nm.js.map} +1 -1
  100. package/dist/lib/{orchestrator-CCARkxQC.js → orchestrator-cRBe3lhq.js} +2 -2
  101. package/dist/lib/{orchestrator-CCARkxQC.js.map → orchestrator-cRBe3lhq.js.map} +1 -1
  102. package/dist/lib/{peerjs-Bfw_FWLB.js → peerjs-BLg8aGUj.js} +3 -3
  103. package/dist/lib/{peerjs-Bfw_FWLB.js.map → peerjs-BLg8aGUj.js.map} +1 -1
  104. package/dist/lib/{process-peer-query-param-BxYiZNdf.js → process-peer-query-param-BnsVnxzH.js} +5 -5
  105. package/dist/lib/{process-peer-query-param-BxYiZNdf.js.map → process-peer-query-param-BnsVnxzH.js.map} +1 -1
  106. package/dist/lib/{process-pending-shared-payloads-DPIbwRb3.js → process-pending-shared-payloads-DBZfZOOa.js} +2 -2
  107. package/dist/lib/{process-pending-shared-payloads-DPIbwRb3.js.map → process-pending-shared-payloads-DBZfZOOa.js.map} +1 -1
  108. package/dist/lib/{process-room-query-param-B2_d50nE.js → process-room-query-param-B8EYg_-r.js} +4 -4
  109. package/dist/lib/{process-room-query-param-B2_d50nE.js.map → process-room-query-param-B8EYg_-r.js.map} +1 -1
  110. package/dist/lib/{push-client-rrjTdc-U.js → push-client-CAm6UMvE.js} +3 -3
  111. package/dist/lib/{push-client-rrjTdc-U.js.map → push-client-CAm6UMvE.js.map} +1 -1
  112. package/dist/lib/{rooms-bwGoYb1q.js → rooms-Dzphx3rK.js} +2 -2
  113. package/dist/lib/{rooms-bwGoYb1q.js.map → rooms-Dzphx3rK.js.map} +1 -1
  114. package/dist/lib/{shadow-claw-CypGVlVO.js → shadow-claw-CGl8tXtG.js} +6 -6
  115. package/dist/lib/{shadow-claw-CypGVlVO.js.map → shadow-claw-CGl8tXtG.js.map} +1 -1
  116. package/dist/lib/{shadow-claw-channel-config-DJpDovkF.js → shadow-claw-channel-config-BNIWCdsL.js} +4 -4
  117. package/dist/lib/{shadow-claw-channel-config-DJpDovkF.js.map → shadow-claw-channel-config-BNIWCdsL.js.map} +1 -1
  118. package/dist/lib/{shadow-claw-channels-DJLwRovH.js → shadow-claw-channels-C2QSn4Ew.js} +2 -2
  119. package/dist/lib/{shadow-claw-channels-DJLwRovH.js.map → shadow-claw-channels-C2QSn4Ew.js.map} +1 -1
  120. package/dist/lib/{shadow-claw-chat-B92cPaft.js → shadow-claw-chat-Wx3y9y6c.js} +3 -3
  121. package/dist/lib/{shadow-claw-chat-B92cPaft.js.map → shadow-claw-chat-Wx3y9y6c.js.map} +1 -1
  122. package/dist/lib/{shadow-claw-control-plane-fvn-qyHj.js → shadow-claw-control-plane-D5E4cFGu.js} +6 -6
  123. package/dist/lib/{shadow-claw-control-plane-fvn-qyHj.js.map → shadow-claw-control-plane-D5E4cFGu.js.map} +1 -1
  124. package/dist/lib/{shadow-claw-conversations-CsVyDOny.js → shadow-claw-conversations-BtDv7GRW.js} +2 -2
  125. package/dist/lib/{shadow-claw-conversations-CsVyDOny.js.map → shadow-claw-conversations-BtDv7GRW.js.map} +1 -1
  126. package/dist/lib/{shadow-claw-file-viewer-DFfyP7s5.js → shadow-claw-file-viewer-CG40kwWV.js} +2 -2
  127. package/dist/lib/{shadow-claw-file-viewer-DFfyP7s5.js.map → shadow-claw-file-viewer-CG40kwWV.js.map} +1 -1
  128. package/dist/lib/{shadow-claw-files-cT6HL7ye.js → shadow-claw-files-BOUULrlX.js} +3 -3
  129. package/dist/lib/{shadow-claw-files-cT6HL7ye.js.map → shadow-claw-files-BOUULrlX.js.map} +1 -1
  130. package/dist/lib/{shadow-claw-git-Cv9mQgTx.js → shadow-claw-git-BeHV73_9.js} +3 -3
  131. package/dist/lib/{shadow-claw-git-Cv9mQgTx.js.map → shadow-claw-git-BeHV73_9.js.map} +1 -1
  132. package/dist/lib/{shadow-claw-llm-CKOYzPDp.js → shadow-claw-llm-KONyWKZM.js} +2 -2
  133. package/dist/lib/{shadow-claw-llm-CKOYzPDp.js.map → shadow-claw-llm-KONyWKZM.js.map} +1 -1
  134. package/dist/lib/{shadow-claw-networking-DYfiUQaH.js → shadow-claw-networking-Diy3JJkc.js} +2 -2
  135. package/dist/lib/{shadow-claw-networking-DYfiUQaH.js.map → shadow-claw-networking-Diy3JJkc.js.map} +1 -1
  136. package/dist/lib/{shadow-claw-notifications-JJlzriuX.js → shadow-claw-notifications-C-upPa-4.js} +2 -2
  137. package/dist/lib/{shadow-claw-notifications-JJlzriuX.js.map → shadow-claw-notifications-C-upPa-4.js.map} +1 -1
  138. package/dist/lib/{shadow-claw-pages-BCo3ihZI.js → shadow-claw-pages-CfAjUKgd.js} +2 -2
  139. package/dist/lib/{shadow-claw-pages-BCo3ihZI.js.map → shadow-claw-pages-CfAjUKgd.js.map} +1 -1
  140. package/dist/lib/{shadow-claw-peerjs-CFNjfrY5.js → shadow-claw-peerjs-t4YibS9s.js} +5 -5
  141. package/dist/lib/{shadow-claw-peerjs-CFNjfrY5.js.map → shadow-claw-peerjs-t4YibS9s.js.map} +1 -1
  142. package/dist/lib/{shadow-claw-settings-BMwne0bh.js → shadow-claw-settings-Cg5V0e9g.js} +2 -2
  143. package/dist/lib/{shadow-claw-settings-BMwne0bh.js.map → shadow-claw-settings-Cg5V0e9g.js.map} +1 -1
  144. package/dist/lib/{shadow-claw-storage-DUY8B9m-.js → shadow-claw-storage-C7tCnsSG.js} +2 -2
  145. package/dist/lib/{shadow-claw-storage-DUY8B9m-.js.map → shadow-claw-storage-C7tCnsSG.js.map} +1 -1
  146. package/dist/lib/{shadow-claw-task-server-yWeoA3eL.js → shadow-claw-task-server-BObsRdf8.js} +2 -2
  147. package/dist/lib/{shadow-claw-task-server-yWeoA3eL.js.map → shadow-claw-task-server-BObsRdf8.js.map} +1 -1
  148. package/dist/lib/{shadow-claw-tasks-Bg0uM15I.js → shadow-claw-tasks-B2EEqrcY.js} +3 -3
  149. package/dist/lib/{shadow-claw-tasks-Bg0uM15I.js.map → shadow-claw-tasks-B2EEqrcY.js.map} +1 -1
  150. package/dist/lib/{shadow-claw-terminal-fyJPppY_.js → shadow-claw-terminal-DSHfO2b9.js} +2 -2
  151. package/dist/lib/{shadow-claw-terminal-fyJPppY_.js.map → shadow-claw-terminal-DSHfO2b9.js.map} +1 -1
  152. package/dist/lib/{shadow-claw-tools-D0T8m3go.js → shadow-claw-tools-DwPBADua.js} +3 -3
  153. package/dist/lib/{shadow-claw-tools-D0T8m3go.js.map → shadow-claw-tools-DwPBADua.js.map} +1 -1
  154. package/dist/lib/{shadow-claw-webvm-CQvzJwKI.js → shadow-claw-webvm-CY4qGaMB.js} +2 -2
  155. package/dist/lib/{shadow-claw-webvm-CQvzJwKI.js.map → shadow-claw-webvm-CY4qGaMB.js.map} +1 -1
  156. package/dist/lib/{sync-web-mcp-registration-BFtG_4kx.js → sync-web-mcp-registration-BiOZvW-R.js} +3 -3
  157. package/dist/lib/{sync-web-mcp-registration-BFtG_4kx.js.map → sync-web-mcp-registration-BiOZvW-R.js.map} +1 -1
  158. package/dist/lib/{system-prompt-bhGRLoL2.js → system-prompt-CxJ3Nx4c.js} +4 -3
  159. package/dist/lib/system-prompt-CxJ3Nx4c.js.map +1 -0
  160. package/dist/public/.well-known/mcp/server-card.json +4 -12
  161. package/dist/public/.well-known/mcp.json +4 -12
  162. package/dist/public/AGENTS.md +3 -1
  163. package/dist/public/README.md +6 -2
  164. package/dist/public/agent.worker.js +1 -1
  165. package/dist/public/{channel-Dk7wl-Av.js → channel-DIpDQekL.js} +1 -1
  166. package/dist/public/{chat-template-BwAnTFKf.js → chat-template-CXKs8lFR.js} +1 -1
  167. package/dist/public/compact-context-BQ2ZXoAc.js +5 -0
  168. package/dist/public/{compact-context-fOTqwKF6.js → compact-context-dHitmPsV.js} +2 -2
  169. package/dist/public/{configure-peer-js-BOV0tR6G.js → configure-peer-js-DV1rqvFX.js} +1 -1
  170. package/dist/public/{create-model-cache-fetch-DSAFjOwc.js → create-model-cache-fetch-B0mSCEk6.js} +1 -1
  171. package/dist/public/{discover-skills-D1sNTy2r.js → discover-skills-BWJB8HUA.js} +1 -1
  172. package/dist/public/docs/architecture/overview.md +1 -1
  173. package/dist/public/docs/example/article/index.html +21 -21
  174. package/dist/public/docs/example/article.html +21 -21
  175. package/dist/public/docs/publishing/index.html +21 -21
  176. package/dist/public/docs/publishing.html +21 -21
  177. package/dist/public/docs/skill-creator/index.html +21 -21
  178. package/dist/public/docs/skill-creator.html +21 -21
  179. package/dist/public/docs/subsystems/attachment-capabilities.md +14 -1
  180. package/dist/public/docs/subsystems/cli.md +95 -51
  181. package/dist/public/docs/subsystems/pages.md +5 -0
  182. package/dist/public/e2e/README.md +1 -1
  183. package/dist/public/{e2e-bridge-Cz95DLlb.js → e2e-bridge-lP2qqiv3.js} +1 -1
  184. package/dist/public/{git-BmMlwIMP.js → git-DjmQ16rm.js} +1 -1
  185. package/dist/public/{iframe-bridge-scripts-Cibg0m6A.js → iframe-bridge-scripts-CO0izGjW.js} +1 -1
  186. package/dist/public/index.html +21 -21
  187. package/dist/public/index.js +1 -1
  188. package/dist/public/{init-control-plane-Cb31yLTY.js → init-control-plane-Ctz7FI8M.js} +1 -1
  189. package/dist/public/{invoke-agent-CN7mSV0Z.js → invoke-agent-C_geruwq.js} +1 -1
  190. package/dist/public/llms.txt +1 -1
  191. package/dist/public/main/index.html +21 -21
  192. package/dist/public/main/memory/index.html +21 -21
  193. package/dist/public/main/memory.html +21 -21
  194. package/dist/public/main.html +21 -21
  195. package/dist/public/{move-group-entry-CXneuNVa.js → move-group-entry-QQ9Hkk54.js} +1 -1
  196. package/dist/public/{orchestrator-Dyylc8IU.js → orchestrator-C1kaTltu.js} +2 -2
  197. package/dist/public/{orchestrator-DBO4NZqd.js → orchestrator-Li1UAsv7.js} +1 -1
  198. package/dist/public/{peerjs-l0jiBoh6.js → peerjs-DbBryE-9.js} +1 -1
  199. package/dist/public/{process-peer-query-param-s-aSP1Rq.js → process-peer-query-param-DQIgr3KL.js} +1 -1
  200. package/dist/public/{process-pending-shared-payloads-BN3GigPT.js → process-pending-shared-payloads-Ctb-TFqB.js} +1 -1
  201. package/dist/public/{process-room-query-param-B2Qe0F0M.js → process-room-query-param-F-XnIVoZ.js} +1 -1
  202. package/dist/public/{push-client-B2LC8Qp9.js → push-client-DRx9Eggz.js} +1 -1
  203. package/dist/public/{rooms-ChCEOvkw.js → rooms-BurBI7is.js} +1 -1
  204. package/dist/public/service-worker/init.js +1 -1
  205. package/dist/public/service-worker.js +1 -1
  206. package/dist/public/{shadow-claw-Br8mWDUx.js → shadow-claw-Bg9AQ5x_.js} +2 -2
  207. package/dist/public/{shadow-claw-accounts-Dm6G7KMP.js → shadow-claw-accounts-B3mjYI0M.js} +1 -1
  208. package/dist/public/{shadow-claw-card-CggS8uSa.js → shadow-claw-card-tcXRS1GF.js} +1 -1
  209. package/dist/public/{shadow-claw-channels-088vhuWO.js → shadow-claw-channels-BiSfLvWv.js} +1 -1
  210. package/dist/public/{shadow-claw-chat-BRwRlq-n.js → shadow-claw-chat-N5jMsXZZ.js} +1 -1
  211. package/dist/public/{shadow-claw-control-plane-rhKACK85.js → shadow-claw-control-plane-DFVe_Xdq.js} +2 -2
  212. package/dist/public/{shadow-claw-conversations-CF_yUfKl.js → shadow-claw-conversations-wAR06_ya.js} +1 -1
  213. package/dist/public/{shadow-claw-empty-state-CkpOSXCS.js → shadow-claw-empty-state-CnPm3NVM.js} +1 -1
  214. package/dist/public/{shadow-claw-file-viewer-DWCejuY3.js → shadow-claw-file-viewer-sZN_FCDW.js} +2 -2
  215. package/dist/public/{shadow-claw-files-L6_ioyzh.js → shadow-claw-files-CnvkCbd4.js} +2 -2
  216. package/dist/public/{shadow-claw-git-DsdkwLqQ.js → shadow-claw-git-BBHfClGk.js} +2 -2
  217. package/dist/public/{shadow-claw-integrations-CSbRTOm3.js → shadow-claw-integrations-DvdBqzRJ.js} +1 -1
  218. package/dist/public/{shadow-claw-llm-BitaeAVc.js → shadow-claw-llm-YfohG519.js} +1 -1
  219. package/dist/public/{shadow-claw-mcp-remote-gSbV5riy.js → shadow-claw-mcp-remote-BAVbf5pi.js} +1 -1
  220. package/dist/public/{shadow-claw-networking-Dn_y6Cl9.js → shadow-claw-networking-CZ4LWPW7.js} +1 -1
  221. package/dist/public/{shadow-claw-notifications-Cj4Lqx8U.js → shadow-claw-notifications-BHwyREkG.js} +1 -1
  222. package/dist/public/{shadow-claw-page-header-DR4OZFt2.js → shadow-claw-page-header-De6Qf6eY.js} +1 -1
  223. package/dist/public/{shadow-claw-page-header-action-button-BnCV_2Kb.js → shadow-claw-page-header-action-button-FSOhTc9z.js} +1 -1
  224. package/dist/public/{shadow-claw-pages-mpDOtNYj.js → shadow-claw-pages-D_oPyDca.js} +1 -1
  225. package/dist/public/{shadow-claw-pdf-viewer-DZ_84qJH.js → shadow-claw-pdf-viewer-CrU4wqRq.js} +1 -1
  226. package/dist/public/{shadow-claw-settings-CfFTYTEy.js → shadow-claw-settings-DkUhvxVr.js} +2 -2
  227. package/dist/public/{shadow-claw-storage-DLmiT4bG.js → shadow-claw-storage-D0o56Tjw.js} +1 -1
  228. package/dist/public/{shadow-claw-task-server-BoMBCsiS.js → shadow-claw-task-server-4rkroO9K.js} +1 -1
  229. package/dist/public/{shadow-claw-tasks-ChEp1j7x.js → shadow-claw-tasks-BdP7lmvu.js} +1 -1
  230. package/dist/public/{shadow-claw-terminal-BaoVbOda.js → shadow-claw-terminal-DVHX7Fsu.js} +1 -1
  231. package/dist/public/{shadow-claw-toast-e8oz7z6Z.js → shadow-claw-toast-B9Y9tSkW.js} +1 -1
  232. package/dist/public/{shadow-claw-tools-BYjUBiJz.js → shadow-claw-tools-BwwY53Lr.js} +1 -1
  233. package/dist/public/{shadow-claw-webvm-xGb13TME.js → shadow-claw-webvm-CXGdkCNM.js} +1 -1
  234. package/dist/public/{sync-web-mcp-registration-CQluj-Kz.js → sync-web-mcp-registration-DVK_IhXZ.js} +1 -1
  235. package/dist/public/{system-prompt-CTJn0tK-.js → system-prompt-BmswoQwF.js} +2 -2
  236. package/dist/public/{workbox-92eae37e.js → workbox-e4022e15.js} +1 -1
  237. package/dist/public/{zip-reader-DN7FB-Q0.js → zip-reader-JHoTbATw.js} +1 -1
  238. package/dist/server.js +5 -5
  239. package/package.json +1 -1
  240. package/dist/cli/chunk-2gZFafgY.js +0 -1
  241. package/dist/cli/chunk-BCjL0JXf.js +0 -1
  242. package/dist/cli/chunk-BNcu1oiT.js +0 -1
  243. package/dist/cli/chunk-BUNoeMKY.js +0 -36
  244. package/dist/cli/chunk-C5ypckWC.js +0 -225
  245. package/dist/cli/chunk-CFxww5Yz.js +0 -1
  246. package/dist/cli/chunk-CGIgtL6R.js +0 -1
  247. package/dist/cli/chunk-CafdvLx-.js +0 -1
  248. package/dist/cli/chunk-Dhap1VwA.js +0 -1
  249. package/dist/cli/chunk-Ds5-K-9o.js +0 -1
  250. package/dist/cli/chunk-DwvavohW.js +0 -1
  251. package/dist/cli/chunk-_a0CkUNS.js +0 -139
  252. package/dist/lib/system-prompt-bhGRLoL2.js.map +0 -1
  253. package/dist/public/compact-context-CX4H8V57.js +0 -5
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-C7fkh7T7.js","names":["sleep","extractMarkdownAttachments","normalizeAttachmentPath"],"sources":["../../src/db/migrate-legacy-database.ts","../../src/storage/migrate-legacy-opfs.ts","../../src/db/open-database.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/format-a2ui-action-prompt.ts","../../src/core/router.ts","../../src/core/orchestrator/utils/parse-direct-tool-command.ts","../../src/subsystems/skills/parse-skill-command.ts","../../src/core/orchestrator/utils/enqueue.ts","../../src/core/orchestrator/utils/event-bus.ts","../../src/subsystems/channels/room-manager.ts","../../src/db/get-enabled-tasks.ts","../../src/subsystems/tools/cron.ts","../../src/subsystems/tools/task-scheduler.ts","../../src/core/orchestrator/utils/load-channel-configurations.ts","../../src/core/orchestrator/utils/types.ts","../../src/core/orchestrator/utils/parse-direct-tool-command-policy.ts","../../src/core/orchestrator/utils/setup-push-task-listener.ts","../../src/core/orchestrator/utils/init-tasks.ts","../../src/core/orchestrator/orchestrator.ts"],"sourcesContent":["import { CONFIG_KEYS, LEGACY_DB_NAME } from \"../config/config.js\";\nimport { getConfig } from \"./get-config.js\";\nimport { setConfig } from \"./set-config.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: IDBDatabase | null,\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<IDBDatabase | 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/get-config.js\";\nimport { setConfig } from \"../db/set-config.js\";\nimport { getOpfsRootDirName } from \"./storage.js\";\nimport {\n writeFileHandle,\n writeOpfsPathViaWorker,\n} from \"./write-file-handle.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 \"./migrate-legacy-database.js\";\nimport { migrateLegacyOpfs } from \"../storage/migrate-legacy-opfs.js\";\n\n/**\n * Open (or create) the IndexedDB database.\n */\nexport function openDatabase(): Promise<IDBDatabase> {\n return new Promise(async (resolve, reject) => {\n let db: IDBDatabase;\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 ensureConnected(): void {\n if (!this.isConfigured() || !this.running) {\n return;\n }\n\n this.reconnectDelayMs = 1000;\n this.abortController?.abort();\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 { PeerJsChannel } from \"./peerjs.js\";\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 private _peerjs: PeerJsChannel | 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 /** Wire the PeerJS channel used for WebRTC file streaming. */\n setPeerJs(peerjs: PeerJsChannel): void {\n this._peerjs = peerjs;\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\n if (attachments && attachments.length > 0 && this._peerjs) {\n const room = this._manager.get(roomId);\n if (room) {\n await this._peerjs.sendAttachmentsToRoom(room, groupId, attachments);\n }\n }\n\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 ensureConnected(): void {\n if (!this.token || !this.running) {\n return;\n }\n\n this.resetPollBackoff();\n this.abortController?.abort();\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, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\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","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/save-message.js\";\n\nimport { clearPeerJsTypingState } from \"./operations/channel.js\";\nimport { getApiKeyForRequest } from \"./operations/provider.js\";\n\nimport { parseDirectToolCommand } from \"./parse-direct-tool-command.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discover-skills.js\";\nimport { parseSkillCommand } from \"../../../subsystems/skills/parse-skill-command.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) {\n await o.ensureWorkerReady?.();\n if (!o.agentWorker) {\n throw new Error(\"Worker is not initialized.\");\n }\n\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) {\n await o.ensureWorkerReady?.();\n if (!o.agentWorker) {\n throw new Error(\"Worker is not initialized.\");\n }\n\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 const { invokeAgent } = await import(\"./invoke-agent.js\");\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/format-a2ui-action-prompt.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 { isSqliteDatabase } from \"./sqlite/types.js\";\nimport type { ShadowClawDatabase, Task } from \"./types.js\";\n\n/**\n * Get all enabled tasks.\n *\n * Accepts an optional `db` parameter for headless/SQLite usage. When omitted,\n * falls back to the singleton `getDb()` (browser IDB path).\n */\nexport function getEnabledTasks(db?: ShadowClawDatabase): Promise<Task[]> {\n // SQLite fast path\n if (db && isSqliteDatabase(db)) {\n return Promise.resolve().then(() => {\n const rows = (db.db\n .prepare(\"SELECT * FROM tasks WHERE enabled = 1\")\n .all() ?? []) as any[];\n return rows.map((r) => ({\n ...r,\n enabled: true,\n tools: r.tools ? JSON.parse(r.tools) : undefined,\n }));\n });\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n const tx: ShadowClawDatabase = db ?? (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 as IDBDatabase).transaction(\n \"tasks\",\n \"readonly\",\n );\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/get-enabled-tasks.js\";\nimport { updateTaskLastRun } from \"../../db/update-task-last-run.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\nexport interface ShouldDeferPredicate {\n (task: Task): boolean | Promise<boolean>;\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 shouldDefer?: ShouldDeferPredicate;\n\n constructor(\n runner: TaskRunner,\n onTaskChange?: () => void,\n shouldDefer?: ShouldDeferPredicate,\n ) {\n this.runner = runner;\n this.onTaskChange = onTaskChange;\n this.shouldDefer = shouldDefer;\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 if (this.shouldDefer && (await this.shouldDefer(task))) {\n continue;\n }\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 { CONFIG_KEYS } from \"../../../config/config.js\";\n\nimport { inferAttachmentMimeType } from \"../../../content/message-attachments.js\";\nimport { getConfig } from \"../../../db/get-config.js\";\nimport { readGroupFileBytes } from \"../../../storage/read-group-file-bytes.js\";\nimport { loadChannelEnabled } from \"./operations/channel.js\";\nimport { parseStoredStringList } from \"../../../utils/parse-stored-string-list.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 { getOrCreateSubscriberId } from \"../../../db/get-or-create-subscriber-id.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { syncExistingPushSubscription } from \"../../../subsystems/notifications/push-client.js\";\nimport { submitMessage } from \"./operations/channel.js\";\nimport { syncProxyConfigToServiceWorker } from \"./sync-proxy-config-to-service-worker.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 // Ensure any existing active push subscription is registered with our local subscriberId\n void (async () => {\n try {\n const subscriberId = await getOrCreateSubscriberId(db);\n await syncExistingPushSubscription(subscriberId);\n } catch (_) {}\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, subscriberId } =\n event.data;\n if (!groupId) {\n return;\n }\n\n // Execute the task via the same path as client-side scheduler\n const runTaskHandler = async () => {\n // Validate subscriber ownership if provided\n if (subscriberId) {\n const localSubscriberId = await getOrCreateSubscriberId(db);\n if (localSubscriberId && subscriberId !== localSubscriberId) {\n console.warn(\n `Ignoring push-triggered task ${taskId}: subscriberId mismatch (${subscriberId} !== ${localSubscriberId})`,\n );\n return;\n }\n }\n\n // Mark this group as scheduler-triggered for recursion prevention\n orchestrator.schedulerTriggeredGroups.add(groupId);\n\n try {\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 } finally {\n orchestrator.schedulerTriggeredGroups.delete(groupId);\n }\n };\n\n runTaskHandler().catch((err) =>\n console.error(`Push-triggered task ${taskId} failed:`, err),\n );\n });\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { getConfig } from \"../../../db/get-config.js\";\nimport { deleteRoom, getRoomMetadata, upsertRoom } from \"../../../db/rooms.js\";\nimport { setConfig } from \"../../../db/set-config.js\";\n\nimport { createModuleWorker } from \"../../../utils/runtime-assets.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/utils/is-prompt-api-supported.js\";\nimport { fetchTokenizerConfig } from \"../../../subsystems/providers/utils/chat-template.js\";\nimport { TaskScheduler } from \"../../../subsystems/tools/task-scheduler.js\";\nimport { STATIC_ROUTING_SCRIPT_ID } from \"../../../storage/static-routing.js\";\nimport { enqueue } from \"./enqueue.js\";\nimport { handleWorkerMessage } from \"./handle-worker-message.js\";\nimport { loadChannelConfigurations } from \"./load-channel-configurations.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 shouldDeferTaskToServer,\n} from \"./operations/task.js\";\n\nimport { parseDirectToolCommandPolicy } from \"./parse-direct-tool-command-policy.js\";\nimport { setupPushTaskListener } from \"./setup-push-task-listener.js\";\nimport { syncProxyConfigToServiceWorker } from \"./sync-proxy-config-to-service-worker.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 const effectiveProvider = storedProvider || orchestrator.provider;\n const matchedProvider = effectiveProvider\n ? getProvider(effectiveProvider)\n : undefined;\n if (matchedProvider) {\n orchestrator.provider = effectiveProvider;\n orchestrator.providerConfig = matchedProvider;\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 // In static site publication mode or for local in-browser models (transformers_js),\n // model catalogs are static and background network fetches are skipped entirely.\n const isStaticSite =\n typeof document !== \"undefined\" &&\n Boolean(document.getElementById(STATIC_ROUTING_SCRIPT_ID));\n const isTransformersJs =\n orchestrator.providerConfig?.format === \"transformers_js\";\n const hasModelsUrl = Boolean(orchestrator.providerConfig?.modelsUrl);\n\n const scheduleFetch = () => {\n if (isStaticSite || isTransformersJs || !hasModelsUrl) {\n return;\n }\n\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 (!isStaticSite && !isTransformersJs && hasModelsUrl) {\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\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 = createModuleWorker(\n new URL(\"./agent.worker.js\", import.meta.url).href,\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 // The local scheduler runs for tasks that have not opted into push notifications,\n // or when push scheduling is unavailable. Tasks opted into push with an active subscription\n // defer to the server scheduler.\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 (task) => shouldDeferTaskToServer(task, orchestrator),\n );\n\n orchestrator.scheduler.start();\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/build-dynamic-context.js\";\nimport { estimateTokens } from \"../../context/estimate-tokens.js\";\nimport { buildConversationMessages } from \"../../db/build-conversation-messages.js\";\nimport { clearGroupMessages } from \"../../db/clear-group-messages.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { listGroups } from \"../../db/groups.js\";\nimport { openDatabase } from \"../../db/open-database.js\";\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\nimport { saveMessage } from \"../../db/save-message.js\";\nimport { setConfig } from \"../../db/set-config.js\";\nimport { decryptValue, encryptValue } from \"../../security/crypto.js\";\nimport { VMBootMode, VMStatus } from \"../../shell/vm.js\";\nimport { readGroupFile } from \"../../storage/read-group-file.js\";\nimport { STATIC_ROUTING_SCRIPT_ID } from \"../../storage/static-routing.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/utils/is-prompt-api-supported.js\";\n\nimport { getContextLimit } from \"../../subsystems/providers/providers.js\";\nimport { TaskScheduler } from \"../../subsystems/tools/task-scheduler.js\";\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/format-a2ui-action-prompt.js\";\nimport { isTruthyConfigValue } from \"../../utils/parse-boolean-config.js\";\nimport { getSiteConfig } from \"../../utils/site-config.js\";\nimport { ulid } from \"../../utils/ulid.js\";\nimport { yieldToMain } from \"../../utils/delay.js\";\nimport { buildSystemPrompt } from \"../../worker/utils/system-prompt.js\";\nimport { Router } from \"../router.js\";\nimport { enqueue } from \"./utils/enqueue.js\";\nimport { EventBus } from \"./utils/event-bus.js\";\n\nimport {\n createRoomManager,\n initChannelsAndRooms,\n initCoreConfig,\n initFeatureFlagsAndLimits,\n initLlamafileAndMesh,\n initProviderAndModel,\n initWorkerAndScheduler,\n} from \"./utils/init-tasks.js\";\n\nimport {\n cancelLlamafileRequest,\n stopTransformersProgressPolling,\n} from \"./utils/operations/provider.js\";\n\nimport { syncWebMcpRegistration } from \"./utils/sync-web-mcp-registration.js\";\nimport { DEFAULT_DIRECT_TOOL_COMMAND_POLICY } from \"./utils/types.js\";\nimport { ensureControlPlaneConnected } from \"../utils/init-control-plane.js\";\nimport { applyAllChannelRunningStates } from \"./utils/operations/channel.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/db.js\";\nimport type { InboundMessage } from \"../../subsystems/channels/types.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 channelsInitialized: boolean = false;\n contextCompressionEnabled: boolean = false;\n\n db: ShadowClawDatabase | null = null;\n directToolCommandPolicy: DirectToolCommandPolicy = {\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n };\n\n ensureControlPlaneConnected: typeof ensureControlPlaneConnected =\n ensureControlPlaneConnected;\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: InboundMessage[] = [];\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 async ensureWorkerReady(): Promise<void> {\n if (this.db && !this.channelsInitialized) {\n this.channelsInitialized = true;\n await initChannelsAndRooms(this, this.db);\n this.browserChat.onDisplay(() => {});\n }\n if (!this.agentWorker && this.db) {\n await initWorkerAndScheduler(this, this.db);\n }\n if (this.db) {\n void toolsStore.load(this.db);\n syncWebMcpRegistration(this, this.db);\n }\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.roomChannel.setPeerJs(this.peerjs);\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 /**\n * Ensure all enabled external connections (Control Plane, Channels, Task Server)\n * are actively connected and healthy (e.g. on initial app load, wake-up from sleep,\n * switching back from another app, or regaining network connectivity).\n */\n async ensureAllConnections(options: { force?: boolean } = {}): Promise<void> {\n const force = options.force ?? false;\n\n // 1. Control Plane\n try {\n await this.ensureControlPlaneConnected({\n orchestrator: this,\n db: this.db || undefined,\n force,\n });\n } catch (err) {\n console.warn(\"Error ensuring Control Plane connection:\", err);\n }\n\n // 2. Messaging Channels\n try {\n applyAllChannelRunningStates(this, force);\n } catch (err) {\n console.warn(\"Error ensuring channel connections:\", err);\n }\n\n // 3. Server Task Scheduling & Local Scheduler\n if (this.taskServerEnabled && this.db) {\n void orchestratorStore.replayTaskSyncOutbox(this.db);\n void orchestratorStore.loadTasks(this.db);\n }\n\n if (this.scheduler) {\n this.scheduler.start();\n void this.scheduler.tick();\n }\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 await yieldToMain();\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 await yieldToMain();\n\n // Worker + scheduler need provider/model/flags to be ready.\n // Under static routing, defer worker startup so initial page interactive timing is not blocked.\n const isStaticSite =\n typeof document !== \"undefined\" &&\n Boolean(document.getElementById(STATIC_ROUTING_SCRIPT_ID));\n\n const siteConfig = getSiteConfig();\n const siteChatHidden = siteConfig?.sidebar?.chatHidden;\n const siteTasksHidden = siteConfig?.sidebar?.tasksHidden;\n\n const [dbChatHiddenRaw, dbTasksHiddenRaw] = await Promise.all([\n getConfig(db, CONFIG_KEYS.SIDEBAR_CHAT_HIDDEN),\n getConfig(db, CONFIG_KEYS.SIDEBAR_TASKS_HIDDEN),\n ]);\n\n const isChatHidden =\n dbChatHiddenRaw !== null && dbChatHiddenRaw !== undefined\n ? isTruthyConfigValue(dbChatHiddenRaw)\n : Boolean(siteChatHidden);\n\n const isTasksHidden =\n dbTasksHiddenRaw !== null && dbTasksHiddenRaw !== undefined\n ? isTruthyConfigValue(dbTasksHiddenRaw)\n : Boolean(siteTasksHidden);\n\n const areChatAndTasksHidden = isChatHidden && isTasksHidden;\n\n if (isStaticSite) {\n if (!areChatAndTasksHidden) {\n setTimeout(() => {\n void this.ensureWorkerReady();\n }, 15_000);\n }\n } else if (!areChatAndTasksHidden) {\n await initWorkerAndScheduler(this, db);\n }\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 if (!areChatAndTasksHidden) {\n this.channelsInitialized = true;\n void initChannelsAndRooms(this, db).then(() => {\n this.browserChat.onDisplay(() => {});\n });\n }\n\n this.events.emit(\"ready\", undefined);\n\n // In browser environments with requestIdleCallback, defer toolsStore.load and\n // syncWebMcpRegistration to an idle frame so initial render and paint unblock completely.\n const win =\n typeof globalThis !== \"undefined\"\n ? (globalThis as any).window\n : undefined;\n if (isStaticSite) {\n if (!areChatAndTasksHidden) {\n setTimeout(() => {\n void toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n }, 15_000);\n }\n } else if (win && typeof win.requestIdleCallback === \"function\") {\n if (!areChatAndTasksHidden) {\n win.requestIdleCallback(() => {\n void toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n });\n }\n } else if (!areChatAndTasksHidden) {\n await toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n }\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 this.#encryptedApiKey = storedKey;\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 undefined,\n { groupId },\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 const { invokeAgent } = await import(\"./utils/invoke-agent.js\");\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-BBAwy9Nm.js","names":["sleep","extractMarkdownAttachments","normalizeAttachmentPath"],"sources":["../../src/db/migrate-legacy-database.ts","../../src/storage/migrate-legacy-opfs.ts","../../src/db/open-database.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/format-a2ui-action-prompt.ts","../../src/core/router.ts","../../src/core/orchestrator/utils/parse-direct-tool-command.ts","../../src/subsystems/skills/parse-skill-command.ts","../../src/core/orchestrator/utils/enqueue.ts","../../src/core/orchestrator/utils/event-bus.ts","../../src/subsystems/channels/room-manager.ts","../../src/db/get-enabled-tasks.ts","../../src/subsystems/tools/cron.ts","../../src/subsystems/tools/task-scheduler.ts","../../src/core/orchestrator/utils/load-channel-configurations.ts","../../src/core/orchestrator/utils/types.ts","../../src/core/orchestrator/utils/parse-direct-tool-command-policy.ts","../../src/core/orchestrator/utils/setup-push-task-listener.ts","../../src/core/orchestrator/utils/init-tasks.ts","../../src/core/orchestrator/orchestrator.ts"],"sourcesContent":["import { CONFIG_KEYS, LEGACY_DB_NAME } from \"../config/config.js\";\nimport { getConfig } from \"./get-config.js\";\nimport { setConfig } from \"./set-config.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: IDBDatabase | null,\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<IDBDatabase | 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/get-config.js\";\nimport { setConfig } from \"../db/set-config.js\";\nimport { getOpfsRootDirName } from \"./storage.js\";\nimport {\n writeFileHandle,\n writeOpfsPathViaWorker,\n} from \"./write-file-handle.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 \"./migrate-legacy-database.js\";\nimport { migrateLegacyOpfs } from \"../storage/migrate-legacy-opfs.js\";\n\n/**\n * Open (or create) the IndexedDB database.\n */\nexport function openDatabase(): Promise<IDBDatabase> {\n return new Promise(async (resolve, reject) => {\n let db: IDBDatabase;\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 ensureConnected(): void {\n if (!this.isConfigured() || !this.running) {\n return;\n }\n\n this.reconnectDelayMs = 1000;\n this.abortController?.abort();\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 { PeerJsChannel } from \"./peerjs.js\";\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 private _peerjs: PeerJsChannel | 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 /** Wire the PeerJS channel used for WebRTC file streaming. */\n setPeerJs(peerjs: PeerJsChannel): void {\n this._peerjs = peerjs;\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\n if (attachments && attachments.length > 0 && this._peerjs) {\n const room = this._manager.get(roomId);\n if (room) {\n await this._peerjs.sendAttachmentsToRoom(room, groupId, attachments);\n }\n }\n\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 ensureConnected(): void {\n if (!this.token || !this.running) {\n return;\n }\n\n this.resetPollBackoff();\n this.abortController?.abort();\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, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\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","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/save-message.js\";\n\nimport { clearPeerJsTypingState } from \"./operations/channel.js\";\nimport { getApiKeyForRequest } from \"./operations/provider.js\";\n\nimport { parseDirectToolCommand } from \"./parse-direct-tool-command.js\";\nimport { discoverSkills } from \"../../../subsystems/skills/discover-skills.js\";\nimport { parseSkillCommand } from \"../../../subsystems/skills/parse-skill-command.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) {\n await o.ensureWorkerReady?.();\n if (!o.agentWorker) {\n throw new Error(\"Worker is not initialized.\");\n }\n\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) {\n await o.ensureWorkerReady?.();\n if (!o.agentWorker) {\n throw new Error(\"Worker is not initialized.\");\n }\n\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 const { invokeAgent } = await import(\"./invoke-agent.js\");\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/format-a2ui-action-prompt.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 { isSqliteDatabase } from \"./sqlite/types.js\";\nimport type { ShadowClawDatabase, Task } from \"./types.js\";\n\n/**\n * Get all enabled tasks.\n *\n * Accepts an optional `db` parameter for headless/SQLite usage. When omitted,\n * falls back to the singleton `getDb()` (browser IDB path).\n */\nexport function getEnabledTasks(db?: ShadowClawDatabase): Promise<Task[]> {\n // SQLite fast path\n if (db && isSqliteDatabase(db)) {\n return Promise.resolve().then(() => {\n const rows = (db.db\n .prepare(\"SELECT * FROM tasks WHERE enabled = 1\")\n .all() ?? []) as any[];\n return rows.map((r) => ({\n ...r,\n enabled: true,\n tools: r.tools ? JSON.parse(r.tools) : undefined,\n }));\n });\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n const tx: ShadowClawDatabase = db ?? (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 as IDBDatabase).transaction(\n \"tasks\",\n \"readonly\",\n );\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/get-enabled-tasks.js\";\nimport { updateTaskLastRun } from \"../../db/update-task-last-run.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\nexport interface ShouldDeferPredicate {\n (task: Task): boolean | Promise<boolean>;\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 shouldDefer?: ShouldDeferPredicate;\n\n constructor(\n runner: TaskRunner,\n onTaskChange?: () => void,\n shouldDefer?: ShouldDeferPredicate,\n ) {\n this.runner = runner;\n this.onTaskChange = onTaskChange;\n this.shouldDefer = shouldDefer;\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 if (this.shouldDefer && (await this.shouldDefer(task))) {\n continue;\n }\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 { CONFIG_KEYS } from \"../../../config/config.js\";\n\nimport { inferAttachmentMimeType } from \"../../../content/message-attachments.js\";\nimport { getConfig } from \"../../../db/get-config.js\";\nimport { readGroupFileBytes } from \"../../../storage/read-group-file-bytes.js\";\nimport { loadChannelEnabled } from \"./operations/channel.js\";\nimport { parseStoredStringList } from \"../../../utils/parse-stored-string-list.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 { getOrCreateSubscriberId } from \"../../../db/get-or-create-subscriber-id.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { syncExistingPushSubscription } from \"../../../subsystems/notifications/push-client.js\";\nimport { submitMessage } from \"./operations/channel.js\";\nimport { syncProxyConfigToServiceWorker } from \"./sync-proxy-config-to-service-worker.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 // Ensure any existing active push subscription is registered with our local subscriberId\n void (async () => {\n try {\n const subscriberId = await getOrCreateSubscriberId(db);\n await syncExistingPushSubscription(subscriberId);\n } catch (_) {}\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, subscriberId } =\n event.data;\n if (!groupId) {\n return;\n }\n\n // Execute the task via the same path as client-side scheduler\n const runTaskHandler = async () => {\n // Validate subscriber ownership if provided\n if (subscriberId) {\n const localSubscriberId = await getOrCreateSubscriberId(db);\n if (localSubscriberId && subscriberId !== localSubscriberId) {\n console.warn(\n `Ignoring push-triggered task ${taskId}: subscriberId mismatch (${subscriberId} !== ${localSubscriberId})`,\n );\n return;\n }\n }\n\n // Mark this group as scheduler-triggered for recursion prevention\n orchestrator.schedulerTriggeredGroups.add(groupId);\n\n try {\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 } finally {\n orchestrator.schedulerTriggeredGroups.delete(groupId);\n }\n };\n\n runTaskHandler().catch((err) =>\n console.error(`Push-triggered task ${taskId} failed:`, err),\n );\n });\n}\n","import {\n ASSISTANT_NAME,\n CONFIG_KEYS,\n DEFAULT_MAX_ITERATIONS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../config/config.js\";\n\nimport { getConfig } from \"../../../db/get-config.js\";\nimport { deleteRoom, getRoomMetadata, upsertRoom } from \"../../../db/rooms.js\";\nimport { setConfig } from \"../../../db/set-config.js\";\n\nimport { createModuleWorker } from \"../../../utils/runtime-assets.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/utils/is-prompt-api-supported.js\";\nimport { fetchTokenizerConfig } from \"../../../subsystems/providers/utils/chat-template.js\";\nimport { TaskScheduler } from \"../../../subsystems/tools/task-scheduler.js\";\nimport { STATIC_ROUTING_SCRIPT_ID } from \"../../../storage/static-routing.js\";\nimport { enqueue } from \"./enqueue.js\";\nimport { handleWorkerMessage } from \"./handle-worker-message.js\";\nimport { loadChannelConfigurations } from \"./load-channel-configurations.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 shouldDeferTaskToServer,\n} from \"./operations/task.js\";\n\nimport { parseDirectToolCommandPolicy } from \"./parse-direct-tool-command-policy.js\";\nimport { setupPushTaskListener } from \"./setup-push-task-listener.js\";\nimport { syncProxyConfigToServiceWorker } from \"./sync-proxy-config-to-service-worker.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 const effectiveProvider = storedProvider || orchestrator.provider;\n const matchedProvider = effectiveProvider\n ? getProvider(effectiveProvider)\n : undefined;\n if (matchedProvider) {\n orchestrator.provider = effectiveProvider;\n orchestrator.providerConfig = matchedProvider;\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 // In static site publication mode or for local in-browser models (transformers_js),\n // model catalogs are static and background network fetches are skipped entirely.\n const isStaticSite =\n typeof document !== \"undefined\" &&\n Boolean(document.getElementById(STATIC_ROUTING_SCRIPT_ID));\n const isTransformersJs =\n orchestrator.providerConfig?.format === \"transformers_js\";\n const hasModelsUrl = Boolean(orchestrator.providerConfig?.modelsUrl);\n\n const scheduleFetch = () => {\n if (isStaticSite || isTransformersJs || !hasModelsUrl) {\n return;\n }\n\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 (!isStaticSite && !isTransformersJs && hasModelsUrl) {\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\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 = createModuleWorker(\n new URL(\"./agent.worker.js\", import.meta.url).href,\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 // The local scheduler runs for tasks that have not opted into push notifications,\n // or when push scheduling is unavailable. Tasks opted into push with an active subscription\n // defer to the server scheduler.\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 (task) => shouldDeferTaskToServer(task, orchestrator),\n );\n\n orchestrator.scheduler.start();\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/build-dynamic-context.js\";\nimport { estimateTokens } from \"../../context/estimate-tokens.js\";\nimport { buildConversationMessages } from \"../../db/build-conversation-messages.js\";\nimport { clearGroupMessages } from \"../../db/clear-group-messages.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { listGroups } from \"../../db/groups.js\";\nimport { openDatabase } from \"../../db/open-database.js\";\nimport { roomIdFromGroupId } from \"../../db/rooms.js\";\nimport { saveMessage } from \"../../db/save-message.js\";\nimport { setConfig } from \"../../db/set-config.js\";\nimport { decryptValue, encryptValue } from \"../../security/crypto.js\";\nimport { VMBootMode, VMStatus } from \"../../shell/vm.js\";\nimport { readGroupFile } from \"../../storage/read-group-file.js\";\nimport { STATIC_ROUTING_SCRIPT_ID } from \"../../storage/static-routing.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/utils/is-prompt-api-supported.js\";\n\nimport { getContextLimit } from \"../../subsystems/providers/providers.js\";\nimport { TaskScheduler } from \"../../subsystems/tools/task-scheduler.js\";\nimport { formatA2UIActionPrompt } from \"../../ui/a2ui/utils/format-a2ui-action-prompt.js\";\nimport { isTruthyConfigValue } from \"../../utils/parse-boolean-config.js\";\nimport { getSiteConfig } from \"../../utils/site-config.js\";\nimport { ulid } from \"../../utils/ulid.js\";\nimport { yieldToMain } from \"../../utils/delay.js\";\nimport { buildSystemPrompt } from \"../../worker/utils/system-prompt.js\";\nimport { Router } from \"../router.js\";\nimport { enqueue } from \"./utils/enqueue.js\";\nimport { EventBus } from \"./utils/event-bus.js\";\n\nimport {\n createRoomManager,\n initChannelsAndRooms,\n initCoreConfig,\n initFeatureFlagsAndLimits,\n initLlamafileAndMesh,\n initProviderAndModel,\n initWorkerAndScheduler,\n} from \"./utils/init-tasks.js\";\n\nimport {\n cancelLlamafileRequest,\n stopTransformersProgressPolling,\n} from \"./utils/operations/provider.js\";\n\nimport { syncWebMcpRegistration } from \"./utils/sync-web-mcp-registration.js\";\nimport { DEFAULT_DIRECT_TOOL_COMMAND_POLICY } from \"./utils/types.js\";\nimport { ensureControlPlaneConnected } from \"../utils/init-control-plane.js\";\nimport { applyAllChannelRunningStates } from \"./utils/operations/channel.js\";\n\nimport type { ShadowClawDatabase } from \"../../db/db.js\";\nimport type { InboundMessage } from \"../../subsystems/channels/types.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 channelsInitialized: boolean = false;\n contextCompressionEnabled: boolean = false;\n\n db: ShadowClawDatabase | null = null;\n directToolCommandPolicy: DirectToolCommandPolicy = {\n ...DEFAULT_DIRECT_TOOL_COMMAND_POLICY,\n };\n\n ensureControlPlaneConnected: typeof ensureControlPlaneConnected =\n ensureControlPlaneConnected;\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: InboundMessage[] = [];\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 async ensureWorkerReady(): Promise<void> {\n if (this.db && !this.channelsInitialized) {\n this.channelsInitialized = true;\n await initChannelsAndRooms(this, this.db);\n this.browserChat.onDisplay(() => {});\n }\n if (!this.agentWorker && this.db) {\n await initWorkerAndScheduler(this, this.db);\n }\n if (this.db) {\n void toolsStore.load(this.db);\n syncWebMcpRegistration(this, this.db);\n }\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.roomChannel.setPeerJs(this.peerjs);\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 /**\n * Ensure all enabled external connections (Control Plane, Channels, Task Server)\n * are actively connected and healthy (e.g. on initial app load, wake-up from sleep,\n * switching back from another app, or regaining network connectivity).\n */\n async ensureAllConnections(options: { force?: boolean } = {}): Promise<void> {\n const force = options.force ?? false;\n\n // 1. Control Plane\n try {\n await this.ensureControlPlaneConnected({\n orchestrator: this,\n db: this.db || undefined,\n force,\n });\n } catch (err) {\n console.warn(\"Error ensuring Control Plane connection:\", err);\n }\n\n // 2. Messaging Channels\n try {\n applyAllChannelRunningStates(this, force);\n } catch (err) {\n console.warn(\"Error ensuring channel connections:\", err);\n }\n\n // 3. Server Task Scheduling & Local Scheduler\n if (this.taskServerEnabled && this.db) {\n void orchestratorStore.replayTaskSyncOutbox(this.db);\n void orchestratorStore.loadTasks(this.db);\n }\n\n if (this.scheduler) {\n this.scheduler.start();\n void this.scheduler.tick();\n }\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 await yieldToMain();\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 await yieldToMain();\n\n // Worker + scheduler need provider/model/flags to be ready.\n // Under static routing, defer worker startup so initial page interactive timing is not blocked.\n const isStaticSite =\n typeof document !== \"undefined\" &&\n Boolean(document.getElementById(STATIC_ROUTING_SCRIPT_ID));\n\n const siteConfig = getSiteConfig();\n const siteChatHidden = siteConfig?.sidebar?.chatHidden;\n const siteTasksHidden = siteConfig?.sidebar?.tasksHidden;\n\n const [dbChatHiddenRaw, dbTasksHiddenRaw] = await Promise.all([\n getConfig(db, CONFIG_KEYS.SIDEBAR_CHAT_HIDDEN),\n getConfig(db, CONFIG_KEYS.SIDEBAR_TASKS_HIDDEN),\n ]);\n\n const isChatHidden =\n dbChatHiddenRaw !== null && dbChatHiddenRaw !== undefined\n ? isTruthyConfigValue(dbChatHiddenRaw)\n : Boolean(siteChatHidden);\n\n const isTasksHidden =\n dbTasksHiddenRaw !== null && dbTasksHiddenRaw !== undefined\n ? isTruthyConfigValue(dbTasksHiddenRaw)\n : Boolean(siteTasksHidden);\n\n const areChatAndTasksHidden = isChatHidden && isTasksHidden;\n\n if (isStaticSite) {\n if (!areChatAndTasksHidden) {\n setTimeout(() => {\n void this.ensureWorkerReady();\n }, 15_000);\n }\n } else if (!areChatAndTasksHidden) {\n await initWorkerAndScheduler(this, db);\n }\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 if (!areChatAndTasksHidden) {\n this.channelsInitialized = true;\n void initChannelsAndRooms(this, db).then(() => {\n this.browserChat.onDisplay(() => {});\n });\n }\n\n this.events.emit(\"ready\", undefined);\n\n // In browser environments with requestIdleCallback, defer toolsStore.load and\n // syncWebMcpRegistration to an idle frame so initial render and paint unblock completely.\n const win =\n typeof globalThis !== \"undefined\"\n ? (globalThis as any).window\n : undefined;\n if (isStaticSite) {\n if (!areChatAndTasksHidden) {\n setTimeout(() => {\n void toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n }, 15_000);\n }\n } else if (win && typeof win.requestIdleCallback === \"function\") {\n if (!areChatAndTasksHidden) {\n win.requestIdleCallback(() => {\n void toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n });\n }\n } else if (!areChatAndTasksHidden) {\n await toolsStore.load(db);\n syncWebMcpRegistration(this, db);\n }\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 this.#encryptedApiKey = storedKey;\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 undefined,\n { groupId },\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 const { invokeAgent } = await import(\"./utils/invoke-agent.js\");\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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"}