shadow-claw 1.29.0 → 1.30.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 (277) hide show
  1. package/.agents/skills/main/skill-creator/SKILL.md +3 -2
  2. package/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  3. package/.well-known/agent-skills/index.json +1 -1
  4. package/.well-known/mcp/server-card.json +1 -1
  5. package/.well-known/mcp.json +1 -1
  6. package/dist/lib/{app-routes-CqBOeA5q.js → app-routes-BAEMLu9g.js} +3 -2
  7. package/dist/lib/app-routes-BAEMLu9g.js.map +1 -0
  8. package/dist/lib/{bundler-8JNIKwOs.js → bundler-CsL7hHMq.js} +4 -9
  9. package/dist/lib/{bundler-8JNIKwOs.js.map → bundler-CsL7hHMq.js.map} +1 -1
  10. package/dist/lib/components/index.js +26 -26
  11. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  12. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  13. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  14. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  15. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  16. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  17. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  18. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  19. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  20. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  21. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  22. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  23. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  24. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  25. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  26. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  27. package/dist/lib/components/shadow-claw-channels.js +1 -1
  28. package/dist/lib/components/shadow-claw-chat.js +1 -1
  29. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  30. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  31. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  32. package/dist/lib/components/shadow-claw-files.js +1 -1
  33. package/dist/lib/components/shadow-claw-git.js +1 -1
  34. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  35. package/dist/lib/components/shadow-claw-llm.js +1 -1
  36. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  37. package/dist/lib/components/shadow-claw-networking.js +1 -1
  38. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  39. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  40. package/dist/lib/components/shadow-claw-pages.js +1 -1
  41. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  42. package/dist/lib/components/shadow-claw-settings.js +1 -1
  43. package/dist/lib/components/shadow-claw-storage.js +1 -1
  44. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  45. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  46. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  47. package/dist/lib/components/shadow-claw-tools.js +1 -1
  48. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  49. package/dist/lib/components/shadow-claw.js +1 -1
  50. package/dist/lib/{config--CFrw3J3.js → config-DjZ9QWc4.js} +2 -2
  51. package/dist/lib/{config--CFrw3J3.js.map → config-DjZ9QWc4.js.map} +1 -1
  52. package/dist/lib/{configurePeerJs-DG4hliKp.js → configurePeerJs-H0WaoT0w.js} +3 -3
  53. package/dist/lib/{configurePeerJs-DG4hliKp.js.map → configurePeerJs-H0WaoT0w.js.map} +1 -1
  54. package/dist/lib/{connections-DwjzwVz0.js → connections-BURqMIUv.js} +2 -2
  55. package/dist/lib/{connections-DwjzwVz0.js.map → connections-BURqMIUv.js.map} +1 -1
  56. package/dist/lib/content/markdown-links.d.ts +19 -0
  57. package/dist/lib/core/app-routes.d.ts +1 -0
  58. package/dist/lib/{downloadGroupFile-DmcBQU1n.js → downloadGroupFile-B8J4up2a.js} +2 -2
  59. package/dist/lib/{downloadGroupFile-DmcBQU1n.js.map → downloadGroupFile-B8J4up2a.js.map} +1 -1
  60. package/dist/lib/{file-viewer-C3YKnq_-.js → file-viewer-CwvhxAAG.js} +5 -5
  61. package/dist/lib/{file-viewer-C3YKnq_-.js.map → file-viewer-CwvhxAAG.js.map} +1 -1
  62. package/dist/lib/{getGroupDir-m0f-ekgX.js → getGroupDir-QrN2aTo8.js} +4 -4
  63. package/dist/lib/{getGroupDir-m0f-ekgX.js.map → getGroupDir-QrN2aTo8.js.map} +1 -1
  64. package/dist/lib/{git-C-Q6-IVe.js → git-DhZoe1SE.js} +3 -3
  65. package/dist/lib/{git-C-Q6-IVe.js.map → git-DhZoe1SE.js.map} +1 -1
  66. package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js → iframe-sanitizer-Bujgq14T.js} +2 -2
  67. package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js.map → iframe-sanitizer-Bujgq14T.js.map} +1 -1
  68. package/dist/lib/index.js +27 -27
  69. package/dist/lib/{initChatSplitResize-yyBTU6h9.js → initChatSplitResize-BjiWoqC_.js} +2 -2
  70. package/dist/lib/{initChatSplitResize-yyBTU6h9.js.map → initChatSplitResize-BjiWoqC_.js.map} +1 -1
  71. package/dist/lib/{initControlPlane-DnpAzphg.js → initControlPlane-C9JxQCDh.js} +16 -16
  72. package/dist/lib/{initControlPlane-DnpAzphg.js.map → initControlPlane-C9JxQCDh.js.map} +1 -1
  73. package/dist/lib/{markdown-DgdSt2GD.js → markdown-DYHmNjC4.js} +126 -5
  74. package/dist/lib/markdown-DYHmNjC4.js.map +1 -0
  75. package/dist/lib/{mcp-reconnect-C86MR3z8.js → mcp-reconnect-BxJ77WSb.js} +2 -2
  76. package/dist/lib/{mcp-reconnect-C86MR3z8.js.map → mcp-reconnect-BxJ77WSb.js.map} +1 -1
  77. package/dist/lib/{memoryStorage-UR8E8K-H.js → memoryStorage-D3FBwO9T.js} +2 -2
  78. package/dist/lib/{memoryStorage-UR8E8K-H.js.map → memoryStorage-D3FBwO9T.js.map} +1 -1
  79. package/dist/lib/{orchestrator-ClXbJ4Mb.js → orchestrator-C6dc-2OQ.js} +130 -27
  80. package/dist/lib/{orchestrator-ClXbJ4Mb.js.map → orchestrator-C6dc-2OQ.js.map} +1 -1
  81. package/dist/lib/{orchestrator-CjEau_RG.js → orchestrator-DVkyd8K9.js} +27 -17
  82. package/dist/lib/orchestrator-DVkyd8K9.js.map +1 -0
  83. package/dist/lib/{peerjs-BdfpltIe.js → peerjs-BUS9O04I.js} +274 -60
  84. package/dist/lib/peerjs-BUS9O04I.js.map +1 -0
  85. package/dist/lib/{push-client-DjwKknNg.js → push-client-4JsQGmQa.js} +3 -3
  86. package/dist/lib/{push-client-DjwKknNg.js.map → push-client-4JsQGmQa.js.map} +1 -1
  87. package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js → readGroupFileBytes-CSA7u-nJ.js} +2 -2
  88. package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js.map → readGroupFileBytes-CSA7u-nJ.js.map} +1 -1
  89. package/dist/lib/{shadow-claw-DcPGKenn.js → shadow-claw-BMoF8Auf.js} +11 -11
  90. package/dist/lib/{shadow-claw-DcPGKenn.js.map → shadow-claw-BMoF8Auf.js.map} +1 -1
  91. package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js → shadow-claw-a2ui-2I5nffIn.js} +2 -2
  92. package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js.map → shadow-claw-a2ui-2I5nffIn.js.map} +1 -1
  93. package/dist/lib/{shadow-claw-accounts-03oJ__XC.js → shadow-claw-accounts-BCjlgvzy.js} +3 -3
  94. package/dist/lib/{shadow-claw-accounts-03oJ__XC.js.map → shadow-claw-accounts-BCjlgvzy.js.map} +1 -1
  95. package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js → shadow-claw-channel-config-CxQAmlDE.js} +3 -3
  96. package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js.map → shadow-claw-channel-config-CxQAmlDE.js.map} +1 -1
  97. package/dist/lib/{shadow-claw-channels-BgaJiPdE.js → shadow-claw-channels-CuYMUVAG.js} +3 -3
  98. package/dist/lib/{shadow-claw-channels-BgaJiPdE.js.map → shadow-claw-channels-CuYMUVAG.js.map} +1 -1
  99. package/dist/lib/{shadow-claw-chat-mXPQZbwT.js → shadow-claw-chat-RFtPmmyl.js} +13 -12
  100. package/dist/lib/shadow-claw-chat-RFtPmmyl.js.map +1 -0
  101. package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js → shadow-claw-control-plane-siqmRzR1.js} +7 -7
  102. package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js.map → shadow-claw-control-plane-siqmRzR1.js.map} +1 -1
  103. package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js → shadow-claw-conversations-DygK5y1e.js} +7 -7
  104. package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js.map → shadow-claw-conversations-DygK5y1e.js.map} +1 -1
  105. package/dist/lib/{shadow-claw-file-viewer-BSbZvSl-.js → shadow-claw-file-viewer-DGMA7d7H.js} +11 -11
  106. package/dist/lib/shadow-claw-file-viewer-DGMA7d7H.js.map +1 -0
  107. package/dist/lib/{shadow-claw-files-BLVr9Pua.js → shadow-claw-files-CgD1B9J7.js} +8 -8
  108. package/dist/lib/{shadow-claw-files-BLVr9Pua.js.map → shadow-claw-files-CgD1B9J7.js.map} +1 -1
  109. package/dist/lib/{shadow-claw-git-CHC1H86J.js → shadow-claw-git-Bw1jGRrf.js} +6 -6
  110. package/dist/lib/{shadow-claw-git-CHC1H86J.js.map → shadow-claw-git-Bw1jGRrf.js.map} +1 -1
  111. package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js → shadow-claw-integrations-ChaXtvsg.js} +4 -4
  112. package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js.map → shadow-claw-integrations-ChaXtvsg.js.map} +1 -1
  113. package/dist/lib/{shadow-claw-llm-CKXfxd3D.js → shadow-claw-llm-CDM4Akjc.js} +6 -6
  114. package/dist/lib/{shadow-claw-llm-CKXfxd3D.js.map → shadow-claw-llm-CDM4Akjc.js.map} +1 -1
  115. package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js → shadow-claw-mcp-remote-BLxs_Z4I.js} +4 -4
  116. package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js.map → shadow-claw-mcp-remote-BLxs_Z4I.js.map} +1 -1
  117. package/dist/lib/{shadow-claw-networking-dpYvfchh.js → shadow-claw-networking-BYt-kMSI.js} +2 -2
  118. package/dist/lib/{shadow-claw-networking-dpYvfchh.js.map → shadow-claw-networking-BYt-kMSI.js.map} +1 -1
  119. package/dist/lib/{shadow-claw-notifications-_YeAVPga.js → shadow-claw-notifications-Dpe4EtZI.js} +3 -3
  120. package/dist/lib/{shadow-claw-notifications-_YeAVPga.js.map → shadow-claw-notifications-Dpe4EtZI.js.map} +1 -1
  121. package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js → shadow-claw-page-header-P4EvWyUr.js} +2 -2
  122. package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js.map → shadow-claw-page-header-P4EvWyUr.js.map} +1 -1
  123. package/dist/lib/{shadow-claw-pages-DVzZriZ7.js → shadow-claw-pages-DWd_c4d6.js} +10 -10
  124. package/dist/lib/{shadow-claw-pages-DVzZriZ7.js.map → shadow-claw-pages-DWd_c4d6.js.map} +1 -1
  125. package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js → shadow-claw-peerjs-D928817m.js} +3 -3
  126. package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js.map → shadow-claw-peerjs-D928817m.js.map} +1 -1
  127. package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js → shadow-claw-settings-C8OPrSqs.js} +8 -8
  128. package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js.map → shadow-claw-settings-C8OPrSqs.js.map} +1 -1
  129. package/dist/lib/{shadow-claw-storage-Bv__kXG6.js → shadow-claw-storage-CZ2uZJNw.js} +5 -5
  130. package/dist/lib/{shadow-claw-storage-Bv__kXG6.js.map → shadow-claw-storage-CZ2uZJNw.js.map} +1 -1
  131. package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js → shadow-claw-task-server-CLT018BX.js} +2 -2
  132. package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js.map → shadow-claw-task-server-CLT018BX.js.map} +1 -1
  133. package/dist/lib/{shadow-claw-tasks-qmcDT4PU.js → shadow-claw-tasks-D5h-lGmq.js} +9 -8
  134. package/dist/lib/shadow-claw-tasks-D5h-lGmq.js.map +1 -0
  135. package/dist/lib/{shadow-claw-terminal-0QUWP8of.js → shadow-claw-terminal-Cy1O6KVM.js} +2 -2
  136. package/dist/lib/{shadow-claw-terminal-0QUWP8of.js.map → shadow-claw-terminal-Cy1O6KVM.js.map} +1 -1
  137. package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js → shadow-claw-tools-CVD06bCR.js} +9 -9
  138. package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js.map → shadow-claw-tools-CVD06bCR.js.map} +1 -1
  139. package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js → shadow-claw-webvm-DoGl5ZSJ.js} +3 -3
  140. package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js.map → shadow-claw-webvm-DoGl5ZSJ.js.map} +1 -1
  141. package/dist/lib/subsystems/channels/peerjs.d.ts +37 -4
  142. package/dist/lib/subsystems/channels/room.d.ts +4 -0
  143. package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js → syncWebMcpRegistration-BeYkQEvj.js} +5 -5
  144. package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js.map → syncWebMcpRegistration-BeYkQEvj.js.map} +1 -1
  145. package/dist/lib/tools-C3Kft940.js +1 -0
  146. package/dist/lib/{tools-DBaMRiEu.js → tools-DKzPWc0q.js} +2 -2
  147. package/dist/lib/{tools-DBaMRiEu.js.map → tools-DKzPWc0q.js.map} +1 -1
  148. package/dist/lib/{tools-DwwB9RBa.js → tools-DqcJe8LS.js} +5 -5
  149. package/dist/lib/{tools-DwwB9RBa.js.map → tools-DqcJe8LS.js.map} +1 -1
  150. package/dist/lib/{trusted-types-Dx0RZlrd.js → trusted-types-Oz7xXJAY.js} +4 -4
  151. package/dist/lib/{trusted-types-Dx0RZlrd.js.map → trusted-types-Oz7xXJAY.js.map} +1 -1
  152. package/dist/lib/utils/index.js +1 -1
  153. package/dist/lib/utils/namespacedStorage.js +1 -1
  154. package/dist/lib/utils/utils.js +1 -1
  155. package/dist/lib/{webmcp-j_1_T3wf.js → webmcp-BC8_WafM.js} +4 -4
  156. package/dist/lib/{webmcp-j_1_T3wf.js.map → webmcp-BC8_WafM.js.map} +1 -1
  157. package/dist/lib/worker/utils/system-prompt.d.ts +4 -1
  158. package/dist/public/.agents/skills/main/skill-creator/SKILL.md +3 -2
  159. package/dist/public/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  160. package/dist/public/.well-known/agent-skills/index.json +1 -1
  161. package/dist/public/.well-known/mcp/server-card.json +1 -1
  162. package/dist/public/.well-known/mcp.json +1 -1
  163. package/dist/public/agent.worker.js +18 -17
  164. package/dist/public/app-routes-BMQ4HFaM.js +1 -0
  165. package/dist/public/{bundler-Ca-Xwln8.js → bundler-0if-QelV.js} +4 -4
  166. package/dist/public/{config-CrHchneq.js → config-Bnwx4EfS.js} +1 -1
  167. package/dist/public/{configurePeerJs-B470pdeU.js → configurePeerJs-DkyGvwk_.js} +1 -1
  168. package/dist/public/{connections-DvbgdkaB.js → connections-6575KDGE.js} +1 -1
  169. package/dist/public/{custom-element-security-FU04Cq05.js → custom-element-security-BQJQ_oKz.js} +1 -1
  170. package/dist/public/docs/example/article/index.html +2 -2
  171. package/dist/public/docs/publishing/index.html +2 -2
  172. package/dist/public/docs/skill-creator/index.html +2 -2
  173. package/dist/public/docs/subsystems/skills.md +3 -1
  174. package/dist/public/{downloadGroupFile-D8KRJGGL.js → downloadGroupFile-Wo1Sxdhr.js} +1 -1
  175. package/dist/public/{e2e-bridge-CSW0S5Yz.js → e2e-bridge-CvLCUU2O.js} +1 -1
  176. package/dist/public/{file-viewer-Cs-riNvy.js → file-viewer-CIjqAvNF.js} +1 -1
  177. package/dist/public/{getGroupDir-P1h9wl6S.js → getGroupDir-BwprrdrQ.js} +1 -1
  178. package/dist/public/{git-7Vq_SJSp.js → git-BSnY2D-A.js} +2 -2
  179. package/dist/public/{iframe-sanitizer-y2Z1pPwY.js → iframe-sanitizer-viROQkRn.js} +1 -1
  180. package/dist/public/index.html +2 -2
  181. package/dist/public/index.js +1 -1
  182. package/dist/public/{initChatSplitResize-CzV2E7Ul.js → initChatSplitResize-BA18wLQQ.js} +1 -1
  183. package/dist/public/{initControlPlane-BqCY0NQy.js → initControlPlane-L96uJkRA.js} +1 -1
  184. package/dist/public/main/index.html +2 -2
  185. package/dist/public/main/memory/index.html +2 -2
  186. package/dist/public/{markdown-Cw7vCtTg.js → markdown-DGjZAm_w.js} +17 -14
  187. package/dist/public/{mcp-reconnect-9emsqGRe.js → mcp-reconnect-CBHuaYdF.js} +1 -1
  188. package/dist/public/{memoryStorage-C0KvLNUp.js → memoryStorage-C1llaYus.js} +1 -1
  189. package/dist/public/orchestrator-C0VOoTiK.js +15 -0
  190. package/dist/public/{orchestrator-DpkkeD6T.js → orchestrator-DMWi--Dc.js} +20 -19
  191. package/dist/public/peerjs-Bf6ZxfbA.js +1 -0
  192. package/dist/public/{push-client-CHjSbrWs.js → push-client-BD4YalBa.js} +1 -1
  193. package/dist/public/service-worker.js +1 -1
  194. package/dist/public/{shadow-claw-BBPV_9X8.js → shadow-claw-DRy-D4Qi.js} +2 -2
  195. package/dist/public/{shadow-claw-accounts-xUOLBsQZ.js → shadow-claw-accounts-DnfmA8cb.js} +1 -1
  196. package/dist/public/{shadow-claw-channels-BJvrKQjg.js → shadow-claw-channels-8UkycZAa.js} +1 -1
  197. package/dist/public/{shadow-claw-chat-BG2EaRaw.js → shadow-claw-chat-Cf5LUiul.js} +9 -9
  198. package/dist/public/{shadow-claw-control-plane-BBa7WbTg.js → shadow-claw-control-plane-UsBF-Nvd.js} +2 -2
  199. package/dist/public/{shadow-claw-conversations-CFaWFmkm.js → shadow-claw-conversations-Aoe61Y21.js} +1 -1
  200. package/dist/public/{shadow-claw-file-viewer-Z-GIKaE9.js → shadow-claw-file-viewer-D28dSSEn.js} +6 -6
  201. package/dist/public/{shadow-claw-files-BBx4iMsk.js → shadow-claw-files-CaDUlPEU.js} +1 -1
  202. package/dist/public/{shadow-claw-git-vTOKatwd.js → shadow-claw-git-DYNcZMWA.js} +2 -2
  203. package/dist/public/{shadow-claw-integrations-BBVnO0Fc.js → shadow-claw-integrations-BJf_hQVv.js} +1 -1
  204. package/dist/public/{shadow-claw-llm-Ce1Ax6-x.js → shadow-claw-llm-BqK2SIRf.js} +2 -2
  205. package/dist/public/{shadow-claw-mcp-remote-Bkx0gsmF.js → shadow-claw-mcp-remote-B_dDG990.js} +1 -1
  206. package/dist/public/{shadow-claw-networking-q4XIzdB5.js → shadow-claw-networking-D8LxOofv.js} +1 -1
  207. package/dist/public/{shadow-claw-notifications-D2cz0gmm.js → shadow-claw-notifications-DpVyiNG_.js} +1 -1
  208. package/dist/public/{shadow-claw-page-header-BccSHItx.js → shadow-claw-page-header-DdC7bJuW.js} +1 -1
  209. package/dist/public/{shadow-claw-pages-3335lmSC.js → shadow-claw-pages-CYMl4J-6.js} +3 -3
  210. package/dist/public/{shadow-claw-settings-4ptYuJwO.js → shadow-claw-settings-Da_8Oy3O.js} +3 -3
  211. package/dist/public/{shadow-claw-storage-bIrPKFhF.js → shadow-claw-storage-DXIm86_-.js} +1 -1
  212. package/dist/public/{shadow-claw-task-server-5yqVBxy1.js → shadow-claw-task-server-BCceBD0G.js} +1 -1
  213. package/dist/public/{shadow-claw-tasks-DcqYHPLZ.js → shadow-claw-tasks-BW1QZ5L3.js} +19 -19
  214. package/dist/public/{shadow-claw-terminal-fARaDONr.js → shadow-claw-terminal-vqfsxhcK.js} +1 -1
  215. package/dist/public/{shadow-claw-tools-paEAhcJr.js → shadow-claw-tools-l0Jsa7UJ.js} +1 -1
  216. package/dist/public/{shadow-claw-webvm-CbzH_vyX.js → shadow-claw-webvm-CDPOWZm7.js} +1 -1
  217. package/dist/public/skills/main/skill-creator/SKILL.md +3 -2
  218. package/dist/public/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  219. package/dist/public/static-main-manifest.json +2 -2
  220. package/dist/public/{syncWebMcpRegistration-CWSYaHex.js → syncWebMcpRegistration-5b5FkP9_.js} +1 -1
  221. package/dist/public/tools-B-PzsLc2.js +1 -0
  222. package/dist/public/{tools-C8x3nmo4.js → tools-CcgG5XuA.js} +1 -1
  223. package/dist/public/{tools-DvckJZG2.js → tools-VSOY66vs.js} +1 -1
  224. package/dist/public/{webmcp-DAjmliCx.js → webmcp-DBONjQWd.js} +1 -1
  225. package/dist/server.js +2 -2
  226. package/package.json +2 -2
  227. package/src/__mocks__/marked.cjs +14 -0
  228. package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +17 -0
  229. package/src/components/shadow-claw-chat/shadow-claw-chat.ts +5 -1
  230. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +78 -0
  231. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +6 -2
  232. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +56 -0
  233. package/src/components/shadow-claw-tasks/shadow-claw-tasks.test.ts +22 -0
  234. package/src/components/shadow-claw-tasks/shadow-claw-tasks.ts +5 -1
  235. package/src/content/markdown-links.test.ts +109 -0
  236. package/src/content/markdown-links.ts +187 -0
  237. package/src/content/markdown.test.ts +33 -0
  238. package/src/content/markdown.ts +6 -1
  239. package/src/core/app-routes.test.ts +65 -0
  240. package/src/core/app-routes.ts +1 -1
  241. package/src/core/orchestrator/orchestrator.ts +3 -0
  242. package/src/core/orchestrator/utils/compactContext.ts +2 -0
  243. package/src/core/orchestrator/utils/invokeAgent.ts +1 -0
  244. package/src/subsystems/accounts/service-accounts.test.ts +0 -1
  245. package/src/subsystems/channels/peerjs.test.ts +479 -1
  246. package/src/subsystems/channels/peerjs.ts +420 -75
  247. package/src/subsystems/channels/room.test.ts +35 -0
  248. package/src/subsystems/channels/room.ts +15 -0
  249. package/src/subsystems/skills/activateSkill.test.ts +38 -5
  250. package/src/subsystems/skills/activateSkill.ts +25 -3
  251. package/src/subsystems/skills/parseSkill.test.ts +71 -0
  252. package/src/subsystems/skills/parseSkill.ts +185 -25
  253. package/src/subsystems/tools/files.ts +4 -4
  254. package/src/worker/tools/spawn-subagent/spawn-subagent.test.ts +22 -23
  255. package/src/worker/tools/workspace/send-file.test.ts +24 -1
  256. package/src/worker/tools/workspace/send-file.ts +6 -3
  257. package/src/worker/utils/handleCompact.test.ts +3 -4
  258. package/src/worker/utils/handleInvoke.test.ts +13 -11
  259. package/src/worker/utils/handleInvoke.ts +3 -0
  260. package/src/worker/utils/handleMessage.test.ts +0 -1
  261. package/src/worker/utils/post.test.ts +3 -4
  262. package/src/worker/utils/sandboxedEval.test.ts +1 -2
  263. package/src/worker/utils/system-prompt.test.ts +59 -0
  264. package/src/worker/utils/system-prompt.ts +21 -1
  265. package/src/worker/utils/withRetry.test.ts +3 -16
  266. package/dist/lib/app-routes-CqBOeA5q.js.map +0 -1
  267. package/dist/lib/markdown-DgdSt2GD.js.map +0 -1
  268. package/dist/lib/orchestrator-CjEau_RG.js.map +0 -1
  269. package/dist/lib/peerjs-BdfpltIe.js.map +0 -1
  270. package/dist/lib/shadow-claw-chat-mXPQZbwT.js.map +0 -1
  271. package/dist/lib/shadow-claw-file-viewer-BSbZvSl-.js.map +0 -1
  272. package/dist/lib/shadow-claw-tasks-qmcDT4PU.js.map +0 -1
  273. package/dist/lib/tools-D4Pp-nUw.js +0 -1
  274. package/dist/public/app-routes-Bs-riIvr.js +0 -1
  275. package/dist/public/orchestrator-BWkHHO9Y.js +0 -15
  276. package/dist/public/peerjs-tf2EmWjB.js +0 -1
  277. package/dist/public/tools-COduyYJ0.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-tools-Bs_bmI6-.js","names":["shadowClawToolsStyles","shadowClawToolsTemplate"],"sources":["../../src/components/shadow-claw-tools/shadow-claw-tools.ts"],"sourcesContent":["import { getAvailableProviders, getProvider } from \"../../config/config.js\";\nimport { effect } from \"../../core/effect.js\";\n\nimport { getDb, ShadowClawDatabase } from \"../../db/db.js\";\nimport { getWebMcpMode } from \"../../subsystems/mcp/webmcp.js\";\n\nimport { orchestratorStore } from \"../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../stores/tools.js\";\n\nimport { TOOL_DEFINITIONS } from \"../../subsystems/tools/tools.js\";\nimport { showError, showInfo, showSuccess } from \"../../ui/toast.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { Orchestrator } from \"../../core/orchestrator/orchestrator.js\";\nimport {\n setWebMcpMode,\n setWebMcpToolsEnabled,\n} from \"../../core/orchestrator/utils/syncWebMcpRegistration.js\";\n\nimport \"../common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.js\";\nimport \"../shadow-claw-dialog/shadow-claw-dialog.js\";\nimport \"../shadow-claw-page-header/shadow-claw-page-header.js\";\n\nimport ShadowClawElement from \"../shadow-claw-element.js\";\nimport shadowClawToolsStyles from \"./shadow-claw-tools.css\" with { type: \"css\" };\nimport shadowClawToolsTemplate from \"./shadow-claw-tools.html\" with { type: \"html\" };\n\nconst BUILTIN_TOOL_NAMES = new Set(TOOL_DEFINITIONS.map((t) => t.name));\n\nconst elementName = \"shadow-claw-tools\";\nexport class ShadowClawTools extends ShadowClawElement {\n static styles = shadowClawToolsStyles;\n static template = shadowClawToolsTemplate;\n\n orchestrator: Orchestrator | null = null;\n\n constructor() {\n super();\n }\n\n async connectedCallback() {\n const db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n\n await toolsStore.refreshDeclarativeTools(db);\n this.setupEffects(db);\n this.bindEventListeners(db);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n }\n\n bindEventListeners(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Back button\n root.querySelector(\".tools__back-btn\")?.addEventListener(\"click\", () => {\n this.dispatchEvent(\n new CustomEvent(\"navigate-back\", { bubbles: true, composed: true }),\n );\n });\n\n // Add tool button\n root.querySelector(\".tools__add-btn\")?.addEventListener(\"click\", () => {\n const dialog = root.querySelector(\"dialog\");\n if (dialog) {\n const form = root.querySelector(\n \".tools__dialog-form\",\n ) as HTMLFormElement | null;\n form?.reset();\n dialog.showModal();\n }\n });\n\n // Backup\n root.querySelector(\".tools__backup-btn\")?.addEventListener(\"click\", () => {\n this.handleBackup();\n });\n\n // Restore\n const restoreInput = root.querySelector(\".tools__hidden-restore\");\n root.querySelector(\".tools__restore-btn\")?.addEventListener(\"click\", () => {\n if (restoreInput instanceof HTMLInputElement) {\n restoreInput.click();\n }\n });\n restoreInput?.addEventListener(\"change\", (e) => {\n if (e.target instanceof HTMLInputElement) {\n this.handleRestore(db, e.target);\n }\n });\n\n // Select all / none\n root\n .querySelector(\".tools__select-all-btn\")\n ?.addEventListener(\"click\", () => {\n const allNames = toolsStore.allTools.map((t) => t.name);\n toolsStore.setAllEnabled(db, allNames);\n const declNames = toolsStore.declarativeTools.map((t) => t.name);\n toolsStore.setAllDeclarativeEnabled(db, declNames);\n showInfo(\"All tools enabled\");\n });\n\n root\n .querySelector(\".tools__select-none-btn\")\n ?.addEventListener(\"click\", () => {\n toolsStore.setAllEnabled(db, []);\n toolsStore.setAllDeclarativeEnabled(db, []);\n showInfo(\"All tools disabled\");\n });\n\n // WebMCP toggle listener\n const webMcpToggle = root.querySelector(\n \".tools__webmcp-toggle\",\n ) as HTMLInputElement | null;\n if (webMcpToggle) {\n webMcpToggle.addEventListener(\"change\", async () => {\n const orchestrator =\n this.orchestrator ?? orchestratorStore.orchestrator;\n if (!orchestrator) {\n webMcpToggle.checked = false;\n showError(\"Orchestrator is not ready\");\n\n return;\n }\n\n const next = webMcpToggle.checked;\n try {\n await setWebMcpToolsEnabled(orchestrator, db, next, { orchestrator });\n showInfo(\n next\n ? \"WebMCP tool registration enabled\"\n : \"WebMCP tool registration disabled\",\n );\n } catch (err) {\n webMcpToggle.checked = !next;\n showError(\n `Failed to update WebMCP setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Shared full internet access toggle listener\n const internetAccessToggle = root.querySelector(\n \".tools__internet-access-toggle\",\n ) as HTMLInputElement | null;\n if (internetAccessToggle) {\n internetAccessToggle.addEventListener(\"change\", async () => {\n const next = internetAccessToggle.checked;\n try {\n await orchestratorStore.setVMBashFullInternetAccess(db, next);\n showInfo(\n next\n ? \"Full internet access enabled for Bash and JavaScript tools\"\n : \"Full internet access disabled for Bash and JavaScript tools\",\n );\n } catch (err) {\n internetAccessToggle.checked = !next;\n showError(\n `Failed to update internet access setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Web Search toggle\n const webSearchUseProxyToggle = root.querySelector(\n \".tools__websearch-proxy-toggle\",\n ) as HTMLInputElement | null;\n webSearchUseProxyToggle?.addEventListener(\"change\", async () => {\n try {\n await toolsStore.setWebSearchUseProxy(\n db,\n webSearchUseProxyToggle.checked,\n );\n showInfo(\n webSearchUseProxyToggle.checked\n ? \"Web Search local proxy enabled\"\n : \"Web Search local proxy disabled\",\n );\n } catch (err) {\n webSearchUseProxyToggle.checked = !webSearchUseProxyToggle.checked;\n showError(\n `Failed to update Web Search proxy setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // Search Files save button\n root\n .querySelector(\".tools__save-searchfiles-btn\")\n ?.addEventListener(\"click\", async () => {\n const maxFileBytesInput = root.querySelector(\n \".tools__searchfiles-max-file-bytes-input\",\n ) as HTMLInputElement | null;\n const maxFilesVisitedInput = root.querySelector(\n \".tools__searchfiles-max-files-visited-input\",\n ) as HTMLInputElement | null;\n const skipDirsInput = root.querySelector(\n \".tools__searchfiles-skip-dirs-input\",\n ) as HTMLInputElement | null;\n\n const maxFileBytes = parseInt(maxFileBytesInput?.value || \"\", 10);\n const maxFilesVisited = parseInt(maxFilesVisitedInput?.value || \"\", 10);\n const skipDirs = skipDirsInput?.value ?? \"\";\n\n try {\n if (!isNaN(maxFileBytes) && maxFileBytes > 0) {\n await toolsStore.setSearchFilesMaxFileBytes(db, maxFileBytes);\n }\n if (!isNaN(maxFilesVisited) && maxFilesVisited > 0) {\n await toolsStore.setSearchFilesMaxFilesVisited(db, maxFilesVisited);\n }\n await toolsStore.setSearchFilesSkipDirs(db, skipDirs);\n showSuccess(\"Search Files settings saved\");\n } catch (err) {\n showError(\n `Failed to save Search Files settings: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // Web Search save button\n root\n .querySelector(\".tools__save-websearch-btn\")\n ?.addEventListener(\"click\", async () => {\n const proxyUrlInput = root.querySelector(\n \".tools__websearch-proxy-url-input\",\n ) as HTMLInputElement | null;\n const searchUrlInput = root.querySelector(\n \".tools__websearch-url-input\",\n ) as HTMLInputElement | null;\n\n const proxyUrl = proxyUrlInput?.value.trim() || \"/proxy\";\n const searchUrl =\n searchUrlInput?.value.trim() ||\n \"https://html.duckduckgo.com/html/?q={query}\";\n\n try {\n await toolsStore.setWebSearchProxyUrl(db, proxyUrl);\n await toolsStore.setWebSearchUrl(db, searchUrl);\n showSuccess(\"Web Search settings saved\");\n } catch (err) {\n showError(\n `Failed to save Web Search settings: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // WebMCP mode selector\n const webMcpModeSelect = root.querySelector(\n \".tools__webmcp-mode\",\n ) as HTMLSelectElement | null;\n if (webMcpModeSelect) {\n webMcpModeSelect.addEventListener(\"change\", async () => {\n const orchestrator =\n this.orchestrator ?? orchestratorStore.orchestrator;\n if (!orchestrator) {\n return;\n }\n\n const mode = webMcpModeSelect.value as \"polyfill\" | \"native\";\n try {\n await setWebMcpMode(orchestrator, db, mode, { orchestrator });\n showInfo(`WebMCP mode set to ${mode}`);\n } catch (err) {\n showError(\n `Failed to update WebMCP mode: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Save prompt\n root\n .querySelector(\".tools__save-prompt-btn\")\n ?.addEventListener(\"click\", () => {\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (textarea instanceof HTMLTextAreaElement) {\n toolsStore.setSystemPromptOverride(db, textarea.value);\n showSuccess(\"System prompt override saved\");\n }\n });\n\n // Clear prompt\n root\n .querySelector(\".tools__clear-prompt-btn\")\n ?.addEventListener(\"click\", () => {\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (textarea instanceof HTMLTextAreaElement) {\n textarea.value = \"\";\n toolsStore.setSystemPromptOverride(db, \"\");\n showSuccess(\"System prompt override cleared\");\n }\n });\n\n // Dialog controls — Add Tool\n const dialog = root.querySelector(\n \".tools__dialog\",\n ) as HTMLDialogElement | null;\n const closeBtn = dialog?.querySelector(\".tools__dialog-close\");\n const cancelBtn = dialog?.querySelector(\".tools__btn-cancel\");\n const form = root.querySelector(\n \".tools__dialog-form\",\n ) as HTMLFormElement | null;\n\n closeBtn?.addEventListener(\"click\", () => dialog?.close());\n cancelBtn?.addEventListener(\"click\", () => dialog?.close());\n\n dialog?.addEventListener(\"click\", (e) => {\n if (e.target === dialog) {\n dialog.close();\n }\n });\n\n form?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (form) {\n this.handleAddTool(db, form);\n }\n });\n\n // Dialog controls — Clone Tool\n const cloneDialog = root.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n const cloneCloseBtn = root.querySelector(\".tools__clone-dialog-close\");\n const cloneCancelBtn = root.querySelector(\".tools__clone-cancel-btn\");\n const cloneForm = root.querySelector(\n \".tools__clone-dialog-form\",\n ) as HTMLFormElement | null;\n\n cloneCloseBtn?.addEventListener(\"click\", () => cloneDialog?.close());\n cloneCancelBtn?.addEventListener(\"click\", () => cloneDialog?.close());\n cloneDialog?.addEventListener(\"click\", (e) => {\n if (e.target === cloneDialog) {\n cloneDialog.close();\n }\n });\n\n cloneForm?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (cloneForm) {\n this.handleCloneTool(db, cloneForm);\n }\n });\n\n // Dialog controls — Profile\n const profileDialog = root.querySelector(\n \".tools__profile-dialog\",\n ) as HTMLDialogElement | null;\n const profileCloseBtn = root.querySelector(\".tools__profile-dialog-close\");\n const profileCancelBtn = root.querySelector(\".tools__profile-cancel-btn\");\n const profileForm = root.querySelector(\n \".tools__profile-dialog-form\",\n ) as HTMLFormElement | null;\n\n profileCloseBtn?.addEventListener(\"click\", () => profileDialog?.close());\n profileCancelBtn?.addEventListener(\"click\", () => profileDialog?.close());\n profileDialog?.addEventListener(\"click\", (e) => {\n if (e.target === profileDialog) {\n profileDialog.close();\n }\n });\n\n profileForm?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (profileForm) {\n this.handleSaveProfile(db, profileForm);\n }\n });\n\n // Profile select\n const profileSelect = root.querySelector(\".tools__profile-select\");\n profileSelect?.addEventListener(\"change\", (e) => {\n const select = e.target as HTMLSelectElement;\n const value = select.value;\n if (value) {\n toolsStore.activateProfile(db, value);\n showInfo(\"Profile activated\");\n } else {\n toolsStore.deactivateProfile(db);\n showInfo(\"Profile deactivated\");\n }\n });\n\n // Profile new button → open dialog\n root\n .querySelector(\".tools__profile-new-btn\")\n ?.addEventListener(\"click\", () => {\n if (profileDialog && profileForm) {\n profileForm.reset();\n // Populate provider dropdown\n const providerSelect = profileForm.querySelector(\n '[name=\"providerId\"]',\n );\n if (providerSelect) {\n providerSelect.replaceChildren();\n const defaultOption = document.createElement(\"option\");\n defaultOption.value = \"\";\n defaultOption.textContent = \"— Any provider —\";\n providerSelect.append(defaultOption);\n for (const pid of getAvailableProviders()) {\n const p = getProvider(pid);\n if (p) {\n const opt = document.createElement(\"option\");\n opt.value = pid;\n opt.textContent = p.name;\n providerSelect.appendChild(opt);\n }\n }\n }\n\n (profileDialog as HTMLDialogElement).showModal();\n }\n });\n\n // Profile save (overwrite active)\n root\n .querySelector(\".tools__profile-save-btn\")\n ?.addEventListener(\"click\", async () => {\n const activeId = toolsStore.activeProfileId;\n if (activeId) {\n await toolsStore.saveToActiveProfile(db);\n showSuccess(\"Profile saved\");\n } else {\n // No active profile — open new profile dialog\n root\n .querySelector(\".tools__profile-new-btn\")\n ?.dispatchEvent(new Event(\"click\"));\n }\n });\n\n // Profile delete\n root\n .querySelector(\".tools__profile-delete-btn\")\n ?.addEventListener(\"click\", async () => {\n const activeId = toolsStore.activeProfileId;\n if (!activeId) {\n showInfo(\"No profile selected\");\n\n return;\n }\n\n if (activeId.startsWith(\"__builtin_\")) {\n showInfo(\"Built-in profiles cannot be deleted\");\n\n return;\n }\n\n await toolsStore.deleteProfile(db, activeId);\n showSuccess(\"Profile deleted\");\n });\n }\n\n handleBackup() {\n const json = toolsStore.exportBackup();\n const blob = new Blob([json], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `shadowclaw-tools-${Date.now()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n showSuccess(\"Tools config exported\");\n }\n\n /**\n * Open the clone tool dialog for a given source tool.\n */\n openCloneDialog(sourceToolName: string) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const cloneDialog = root.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n const cloneForm = root.querySelector(\n \".tools__clone-dialog-form\",\n ) as HTMLFormElement | null;\n if (!cloneDialog || !cloneForm) {\n return;\n }\n\n cloneForm.reset();\n const sourceInput = cloneForm.querySelector(\n '[name=\"source\"]',\n ) as HTMLInputElement | null;\n if (sourceInput) {\n sourceInput.value = sourceToolName;\n }\n\n cloneDialog.showModal();\n }\n\n setupEffects(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Reactive re-render on tool store changes\n this.addCleanup(\n effect(() => {\n toolsStore.enabledToolNames;\n toolsStore.customTools;\n toolsStore.declarativeTools;\n toolsStore.declarativeToolNamesEnabled;\n toolsStore.systemPromptOverride;\n toolsStore.profiles;\n toolsStore.activeProfileId;\n this.updateToolList(db);\n }),\n );\n\n // WebMCP opt-in toggle\n const webMcpToggle = root.querySelector(\n \".tools__webmcp-toggle\",\n ) as HTMLInputElement | null;\n const internetAccessToggle = root.querySelector(\n \".tools__internet-access-toggle\",\n ) as HTMLInputElement | null;\n const webMcpModeSelect = root.querySelector(\n \".tools__webmcp-mode\",\n ) as HTMLSelectElement | null;\n\n if (webMcpToggle) {\n // Sync checked state and mode when orchestrator becomes available\n this.addCleanup(\n effect(() => {\n if (orchestratorStore.ready) {\n this.orchestrator = orchestratorStore.orchestrator;\n webMcpToggle.checked =\n this.orchestrator?.webMcpToolsEnabled === true;\n if (webMcpModeSelect && this.orchestrator) {\n webMcpModeSelect.value = getWebMcpMode() || \"polyfill\";\n }\n }\n }),\n );\n }\n\n if (internetAccessToggle) {\n this.addCleanup(\n effect(() => {\n internetAccessToggle.checked =\n orchestratorStore.vmBashFullInternetAccess;\n }),\n );\n }\n\n // Web Search reactive effects\n const webSearchProxyToggle = root.querySelector(\n \".tools__websearch-proxy-toggle\",\n ) as HTMLInputElement | null;\n const webSearchProxyUrlInput = root.querySelector(\n \".tools__websearch-proxy-url-input\",\n ) as HTMLInputElement | null;\n const webSearchUrlInput = root.querySelector(\n \".tools__websearch-url-input\",\n ) as HTMLInputElement | null;\n\n if (webSearchProxyToggle) {\n this.addCleanup(\n effect(() => {\n webSearchProxyToggle.checked = toolsStore.webSearchUseProxy;\n }),\n );\n }\n\n if (webSearchProxyUrlInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== webSearchProxyUrlInput &&\n !webSearchProxyUrlInput.matches(\":focus\")\n ) {\n webSearchProxyUrlInput.value = toolsStore.webSearchProxyUrl;\n }\n }),\n );\n }\n\n if (webSearchUrlInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== webSearchUrlInput &&\n !webSearchUrlInput.matches(\":focus\")\n ) {\n webSearchUrlInput.value = toolsStore.webSearchUrl;\n }\n }),\n );\n }\n\n // Search Files reactive effects\n const searchFilesMaxFileBytesInput = root.querySelector(\n \".tools__searchfiles-max-file-bytes-input\",\n ) as HTMLInputElement | null;\n const searchFilesMaxFilesVisitedInput = root.querySelector(\n \".tools__searchfiles-max-files-visited-input\",\n ) as HTMLInputElement | null;\n const searchFilesSkipDirsInput = root.querySelector(\n \".tools__searchfiles-skip-dirs-input\",\n ) as HTMLInputElement | null;\n\n if (searchFilesMaxFileBytesInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesMaxFileBytesInput &&\n !searchFilesMaxFileBytesInput.matches(\":focus\")\n ) {\n searchFilesMaxFileBytesInput.value = String(\n toolsStore.searchFilesMaxFileBytes,\n );\n }\n }),\n );\n }\n\n if (searchFilesMaxFilesVisitedInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesMaxFilesVisitedInput &&\n !searchFilesMaxFilesVisitedInput.matches(\":focus\")\n ) {\n searchFilesMaxFilesVisitedInput.value = String(\n toolsStore.searchFilesMaxFilesVisited,\n );\n }\n }),\n );\n }\n\n if (searchFilesSkipDirsInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesSkipDirsInput &&\n !searchFilesSkipDirsInput.matches(\":focus\")\n ) {\n searchFilesSkipDirsInput.value = toolsStore.searchFilesSkipDirs;\n }\n }),\n );\n }\n }\n\n /** Update the profile dropdown to reflect current state. */\n updateProfileSelector() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const select = root.querySelector(\".tools__profile-select\");\n if (!select) {\n return;\n }\n\n const profiles = toolsStore.profiles;\n const activeId = toolsStore.activeProfileId;\n\n // Preserve selection\n select.replaceChildren();\n const defaultOption = document.createElement(\"option\");\n defaultOption.value = \"\";\n defaultOption.textContent = \"— No profile (manual config) —\";\n select.append(defaultOption);\n for (const p of profiles) {\n const opt = document.createElement(\"option\");\n opt.value = p.id;\n const isBuiltin = p.id.startsWith(\"__builtin_\");\n const providerLabel = p.providerId\n ? getProvider(p.providerId)?.name || p.providerId\n : \"any\";\n const modelLabel = p.model || \"any\";\n opt.textContent = isBuiltin\n ? `⚡ ${p.name} (${providerLabel})`\n : `${p.name} (${providerLabel} / ${modelLabel})`;\n if (p.id === activeId) {\n opt.selected = true;\n }\n\n select.appendChild(opt);\n }\n\n // Disable delete button for built-in profiles\n const deleteBtn = root.querySelector(\n \".tools__profile-delete-btn\",\n ) as HTMLButtonElement | null;\n if (deleteBtn) {\n const isBuiltinActive = activeId?.startsWith(\"__builtin_\");\n deleteBtn.disabled = !!isBuiltinActive;\n deleteBtn.title = isBuiltinActive\n ? \"Built-in profiles cannot be deleted\"\n : \"\";\n }\n }\n\n updateToolList(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector(\".tools__list\");\n if (!list) {\n return;\n }\n\n const enabled = toolsStore.enabledToolNames;\n const allTools = toolsStore.allTools;\n const declarativeTools = toolsStore.declarativeTools;\n\n const existingCheckboxes = list.querySelectorAll<HTMLInputElement>(\n \".tools__item-checkbox[data-tool]\",\n );\n const existingToolNames = Array.from(existingCheckboxes).map(\n (cb) => cb.getAttribute(\"data-tool\") || \"\",\n );\n const targetToolNames = [\n ...allTools.map((t) => t.name),\n ...declarativeTools.map((t) => t.name),\n ];\n\n const isSameStructure =\n existingToolNames.length === targetToolNames.length &&\n existingToolNames.every((name, i) => name === targetToolNames[i]);\n\n if (isSameStructure) {\n for (const cb of existingCheckboxes) {\n const toolName = cb.getAttribute(\"data-tool\");\n if (!toolName) continue;\n const isDeclarative = declarativeTools.some((t) => t.name === toolName);\n const isChecked = isDeclarative\n ? toolsStore.isDeclarativeToolEnabled(toolName)\n : enabled.has(toolName);\n if (cb.checked !== isChecked) {\n cb.checked = isChecked;\n }\n }\n } else {\n list.replaceChildren();\n\n for (const tool of allTools) {\n const isCustom = !BUILTIN_TOOL_NAMES.has(tool.name);\n const isChecked = enabled.has(tool.name);\n const brief = tool.description.split(\". \")[0];\n\n const item = document.createElement(\"div\");\n item.className = \"tools__item\";\n item.setAttribute(\"role\", \"listitem\");\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.className = \"tools__item-checkbox\";\n checkbox.setAttribute(\"data-tool\", tool.name);\n checkbox.setAttribute(\"aria-label\", `Enable ${tool.name}`);\n checkbox.checked = isChecked;\n\n const info = document.createElement(\"div\");\n info.className = \"tools__item-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"tools__item-name\";\n name.textContent = tool.name;\n\n const desc = document.createElement(\"div\");\n desc.className = \"tools__item-desc\";\n desc.setAttribute(\"title\", tool.description);\n desc.textContent = brief;\n info.append(name, desc);\n\n const cloneBtn = document.createElement(\"button\");\n cloneBtn.className = \"tools__item-clone\";\n cloneBtn.setAttribute(\"data-clone\", tool.name);\n cloneBtn.setAttribute(\"aria-label\", `Clone ${tool.name}`);\n cloneBtn.setAttribute(\"title\", \"Clone tool\");\n cloneBtn.textContent = \"📋\";\n\n item.append(checkbox, info);\n\n if (isCustom) {\n const badge = document.createElement(\"span\");\n badge.className = \"tools__item-badge\";\n badge.textContent = \"custom\";\n item.append(badge);\n }\n\n item.append(cloneBtn);\n\n let deleteBtn: HTMLButtonElement | null = null;\n if (isCustom) {\n deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"tools__item-delete\";\n deleteBtn.setAttribute(\"data-delete\", tool.name);\n deleteBtn.setAttribute(\"aria-label\", `Delete ${tool.name}`);\n deleteBtn.textContent = \"🗑️\";\n item.append(deleteBtn);\n }\n\n // Toggle\n checkbox?.addEventListener(\"change\", () => {\n toolsStore.setToolEnabled(db, tool.name, checkbox.checked);\n });\n\n // Clone\n cloneBtn?.addEventListener(\"click\", () => {\n this.openCloneDialog(tool.name);\n });\n\n // Delete custom tool\n deleteBtn?.addEventListener(\"click\", () => {\n toolsStore.removeCustomTool(db, tool.name);\n showInfo(`Removed custom tool: ${tool.name}`);\n });\n\n list.appendChild(item);\n }\n\n for (const tool of declarativeTools) {\n const isChecked = toolsStore.isDeclarativeToolEnabled(tool.name);\n const brief = tool.description.split(\". \")[0];\n\n const item = document.createElement(\"div\");\n item.className = \"tools__item\";\n item.setAttribute(\"role\", \"listitem\");\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.className = \"tools__item-checkbox\";\n checkbox.setAttribute(\"data-tool\", tool.name);\n checkbox.setAttribute(\"aria-label\", `Enable ${tool.name}`);\n checkbox.checked = isChecked;\n\n const info = document.createElement(\"div\");\n info.className = \"tools__item-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"tools__item-name\";\n name.textContent = tool.name;\n\n const desc = document.createElement(\"div\");\n desc.className = \"tools__item-desc\";\n desc.setAttribute(\"title\", tool.description);\n desc.textContent = brief;\n info.append(name, desc);\n\n const badge = document.createElement(\"span\");\n badge.className = \"tools__item-badge tools__item-badge--declarative\";\n badge.textContent = \"declarative\";\n item.append(checkbox, info, badge);\n\n checkbox.addEventListener(\"change\", () => {\n toolsStore.setDeclarativeToolEnabled(db, tool.name, checkbox.checked);\n });\n\n list.appendChild(item);\n }\n }\n\n // Update count\n const countEl = root.querySelector(\".tools__count\");\n if (countEl) {\n const enabledBuiltinCount = (toolsStore.enabledTools || []).length;\n const enabledDeclarativeCount = (toolsStore.enabledDeclarativeTools || [])\n .length;\n const totalEnabled = enabledBuiltinCount + enabledDeclarativeCount;\n const totalCount = allTools.length + declarativeTools.length;\n countEl.textContent = `${totalEnabled} of ${totalCount} enabled`;\n }\n\n // Update prompt textarea\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (\n textarea instanceof HTMLTextAreaElement &&\n document.activeElement !== textarea &&\n !textarea.matches(\":focus\")\n ) {\n textarea.value = toolsStore.systemPromptOverride;\n }\n\n // Update profile selector\n this.updateProfileSelector();\n }\n\n async handleAddTool(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const name = String(data.get(\"name\") || \"\").trim();\n const description = String(data.get(\"description\") || \"\").trim();\n const schemaStr = String(data.get(\"input_schema\") || \"\").trim();\n\n if (!name || !description) {\n showError(\"Name and description are required\");\n\n return;\n }\n\n // Check uniqueness\n if (toolsStore.allTools.some((t) => t.name === name)) {\n showError(`A tool named \"${name}\" already exists`);\n\n return;\n }\n\n let input_schema = { type: \"object\", properties: {} };\n if (schemaStr) {\n try {\n input_schema = JSON.parse(schemaStr);\n } catch {\n showError(\"Invalid JSON in input schema\");\n\n return;\n }\n }\n\n await toolsStore.addCustomTool(db, { name, description, input_schema });\n showSuccess(`Added custom tool: ${name}`);\n\n const dialog = this.shadowRoot?.querySelector(\n \".tools__dialog\",\n ) as HTMLDialogElement | null;\n dialog?.close();\n }\n\n async handleCloneTool(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const sourceToolName = String(data.get(\"source\") || \"\").trim();\n const newName = String(data.get(\"name\") || \"\").trim();\n const newDesc = String(data.get(\"description\") || \"\").trim();\n\n if (!sourceToolName || !newName) {\n showError(\"Source and new tool name are required\");\n\n return;\n }\n\n const ok = await toolsStore.cloneTool(\n db,\n sourceToolName,\n newName,\n newDesc || undefined,\n );\n if (!ok) {\n showError(\n `Clone failed: source not found or name \"${newName}\" already exists.`,\n );\n\n return;\n }\n\n showSuccess(`Cloned \"${sourceToolName}\" → \"${newName}\"`);\n const cloneDialog = this.shadowRoot?.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n cloneDialog?.close();\n }\n\n async handleRestore(db: ShadowClawDatabase, input: HTMLInputElement) {\n const file = input.files?.[0];\n if (!file) {\n return;\n }\n\n try {\n const text = await file.text();\n await toolsStore.importBackup(db, text);\n showSuccess(\"Tools config restored\");\n } catch (err) {\n showError(\n `Failed to restore: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n input.value = \"\";\n }\n\n async handleSaveProfile(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const name = String(data.get(\"name\") || \"\").trim();\n const providerId = String(data.get(\"providerId\") || \"\").trim();\n const model = String(data.get(\"model\") || \"\").trim();\n\n if (!name) {\n showError(\"Profile name is required\");\n\n return;\n }\n\n const profile = {\n id: ulid(),\n name,\n providerId: providerId || undefined,\n model: model || undefined,\n enabledToolNames: [...toolsStore.enabledToolNames],\n customTools: [...toolsStore.customTools],\n systemPromptOverride: toolsStore.systemPromptOverride,\n };\n\n await toolsStore.addProfile(db, profile);\n await toolsStore.activateProfile(db, profile.id);\n showSuccess(`Profile \"${name}\" created and activated`);\n\n const profileDialog = this.shadowRoot?.querySelector(\n \".tools__profile-dialog\",\n ) as HTMLDialogElement | null;\n profileDialog?.close();\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawTools);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shadow-claw-tools-CVD06bCR.js","names":["shadowClawToolsStyles","shadowClawToolsTemplate"],"sources":["../../src/components/shadow-claw-tools/shadow-claw-tools.ts"],"sourcesContent":["import { getAvailableProviders, getProvider } from \"../../config/config.js\";\nimport { effect } from \"../../core/effect.js\";\n\nimport { getDb, ShadowClawDatabase } from \"../../db/db.js\";\nimport { getWebMcpMode } from \"../../subsystems/mcp/webmcp.js\";\n\nimport { orchestratorStore } from \"../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../stores/tools.js\";\n\nimport { TOOL_DEFINITIONS } from \"../../subsystems/tools/tools.js\";\nimport { showError, showInfo, showSuccess } from \"../../ui/toast.js\";\nimport { ulid } from \"../../utils/ulid.js\";\n\nimport type { Orchestrator } from \"../../core/orchestrator/orchestrator.js\";\nimport {\n setWebMcpMode,\n setWebMcpToolsEnabled,\n} from \"../../core/orchestrator/utils/syncWebMcpRegistration.js\";\n\nimport \"../common/shadow-claw-page-header-action-button/shadow-claw-page-header-action-button.js\";\nimport \"../shadow-claw-dialog/shadow-claw-dialog.js\";\nimport \"../shadow-claw-page-header/shadow-claw-page-header.js\";\n\nimport ShadowClawElement from \"../shadow-claw-element.js\";\nimport shadowClawToolsStyles from \"./shadow-claw-tools.css\" with { type: \"css\" };\nimport shadowClawToolsTemplate from \"./shadow-claw-tools.html\" with { type: \"html\" };\n\nconst BUILTIN_TOOL_NAMES = new Set(TOOL_DEFINITIONS.map((t) => t.name));\n\nconst elementName = \"shadow-claw-tools\";\nexport class ShadowClawTools extends ShadowClawElement {\n static styles = shadowClawToolsStyles;\n static template = shadowClawToolsTemplate;\n\n orchestrator: Orchestrator | null = null;\n\n constructor() {\n super();\n }\n\n async connectedCallback() {\n const db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n\n await toolsStore.refreshDeclarativeTools(db);\n this.setupEffects(db);\n this.bindEventListeners(db);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n }\n\n bindEventListeners(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Back button\n root.querySelector(\".tools__back-btn\")?.addEventListener(\"click\", () => {\n this.dispatchEvent(\n new CustomEvent(\"navigate-back\", { bubbles: true, composed: true }),\n );\n });\n\n // Add tool button\n root.querySelector(\".tools__add-btn\")?.addEventListener(\"click\", () => {\n const dialog = root.querySelector(\"dialog\");\n if (dialog) {\n const form = root.querySelector(\n \".tools__dialog-form\",\n ) as HTMLFormElement | null;\n form?.reset();\n dialog.showModal();\n }\n });\n\n // Backup\n root.querySelector(\".tools__backup-btn\")?.addEventListener(\"click\", () => {\n this.handleBackup();\n });\n\n // Restore\n const restoreInput = root.querySelector(\".tools__hidden-restore\");\n root.querySelector(\".tools__restore-btn\")?.addEventListener(\"click\", () => {\n if (restoreInput instanceof HTMLInputElement) {\n restoreInput.click();\n }\n });\n restoreInput?.addEventListener(\"change\", (e) => {\n if (e.target instanceof HTMLInputElement) {\n this.handleRestore(db, e.target);\n }\n });\n\n // Select all / none\n root\n .querySelector(\".tools__select-all-btn\")\n ?.addEventListener(\"click\", () => {\n const allNames = toolsStore.allTools.map((t) => t.name);\n toolsStore.setAllEnabled(db, allNames);\n const declNames = toolsStore.declarativeTools.map((t) => t.name);\n toolsStore.setAllDeclarativeEnabled(db, declNames);\n showInfo(\"All tools enabled\");\n });\n\n root\n .querySelector(\".tools__select-none-btn\")\n ?.addEventListener(\"click\", () => {\n toolsStore.setAllEnabled(db, []);\n toolsStore.setAllDeclarativeEnabled(db, []);\n showInfo(\"All tools disabled\");\n });\n\n // WebMCP toggle listener\n const webMcpToggle = root.querySelector(\n \".tools__webmcp-toggle\",\n ) as HTMLInputElement | null;\n if (webMcpToggle) {\n webMcpToggle.addEventListener(\"change\", async () => {\n const orchestrator =\n this.orchestrator ?? orchestratorStore.orchestrator;\n if (!orchestrator) {\n webMcpToggle.checked = false;\n showError(\"Orchestrator is not ready\");\n\n return;\n }\n\n const next = webMcpToggle.checked;\n try {\n await setWebMcpToolsEnabled(orchestrator, db, next, { orchestrator });\n showInfo(\n next\n ? \"WebMCP tool registration enabled\"\n : \"WebMCP tool registration disabled\",\n );\n } catch (err) {\n webMcpToggle.checked = !next;\n showError(\n `Failed to update WebMCP setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Shared full internet access toggle listener\n const internetAccessToggle = root.querySelector(\n \".tools__internet-access-toggle\",\n ) as HTMLInputElement | null;\n if (internetAccessToggle) {\n internetAccessToggle.addEventListener(\"change\", async () => {\n const next = internetAccessToggle.checked;\n try {\n await orchestratorStore.setVMBashFullInternetAccess(db, next);\n showInfo(\n next\n ? \"Full internet access enabled for Bash and JavaScript tools\"\n : \"Full internet access disabled for Bash and JavaScript tools\",\n );\n } catch (err) {\n internetAccessToggle.checked = !next;\n showError(\n `Failed to update internet access setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Web Search toggle\n const webSearchUseProxyToggle = root.querySelector(\n \".tools__websearch-proxy-toggle\",\n ) as HTMLInputElement | null;\n webSearchUseProxyToggle?.addEventListener(\"change\", async () => {\n try {\n await toolsStore.setWebSearchUseProxy(\n db,\n webSearchUseProxyToggle.checked,\n );\n showInfo(\n webSearchUseProxyToggle.checked\n ? \"Web Search local proxy enabled\"\n : \"Web Search local proxy disabled\",\n );\n } catch (err) {\n webSearchUseProxyToggle.checked = !webSearchUseProxyToggle.checked;\n showError(\n `Failed to update Web Search proxy setting: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // Search Files save button\n root\n .querySelector(\".tools__save-searchfiles-btn\")\n ?.addEventListener(\"click\", async () => {\n const maxFileBytesInput = root.querySelector(\n \".tools__searchfiles-max-file-bytes-input\",\n ) as HTMLInputElement | null;\n const maxFilesVisitedInput = root.querySelector(\n \".tools__searchfiles-max-files-visited-input\",\n ) as HTMLInputElement | null;\n const skipDirsInput = root.querySelector(\n \".tools__searchfiles-skip-dirs-input\",\n ) as HTMLInputElement | null;\n\n const maxFileBytes = parseInt(maxFileBytesInput?.value || \"\", 10);\n const maxFilesVisited = parseInt(maxFilesVisitedInput?.value || \"\", 10);\n const skipDirs = skipDirsInput?.value ?? \"\";\n\n try {\n if (!isNaN(maxFileBytes) && maxFileBytes > 0) {\n await toolsStore.setSearchFilesMaxFileBytes(db, maxFileBytes);\n }\n if (!isNaN(maxFilesVisited) && maxFilesVisited > 0) {\n await toolsStore.setSearchFilesMaxFilesVisited(db, maxFilesVisited);\n }\n await toolsStore.setSearchFilesSkipDirs(db, skipDirs);\n showSuccess(\"Search Files settings saved\");\n } catch (err) {\n showError(\n `Failed to save Search Files settings: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // Web Search save button\n root\n .querySelector(\".tools__save-websearch-btn\")\n ?.addEventListener(\"click\", async () => {\n const proxyUrlInput = root.querySelector(\n \".tools__websearch-proxy-url-input\",\n ) as HTMLInputElement | null;\n const searchUrlInput = root.querySelector(\n \".tools__websearch-url-input\",\n ) as HTMLInputElement | null;\n\n const proxyUrl = proxyUrlInput?.value.trim() || \"/proxy\";\n const searchUrl =\n searchUrlInput?.value.trim() ||\n \"https://html.duckduckgo.com/html/?q={query}\";\n\n try {\n await toolsStore.setWebSearchProxyUrl(db, proxyUrl);\n await toolsStore.setWebSearchUrl(db, searchUrl);\n showSuccess(\"Web Search settings saved\");\n } catch (err) {\n showError(\n `Failed to save Web Search settings: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n\n // WebMCP mode selector\n const webMcpModeSelect = root.querySelector(\n \".tools__webmcp-mode\",\n ) as HTMLSelectElement | null;\n if (webMcpModeSelect) {\n webMcpModeSelect.addEventListener(\"change\", async () => {\n const orchestrator =\n this.orchestrator ?? orchestratorStore.orchestrator;\n if (!orchestrator) {\n return;\n }\n\n const mode = webMcpModeSelect.value as \"polyfill\" | \"native\";\n try {\n await setWebMcpMode(orchestrator, db, mode, { orchestrator });\n showInfo(`WebMCP mode set to ${mode}`);\n } catch (err) {\n showError(\n `Failed to update WebMCP mode: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n }\n\n // Save prompt\n root\n .querySelector(\".tools__save-prompt-btn\")\n ?.addEventListener(\"click\", () => {\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (textarea instanceof HTMLTextAreaElement) {\n toolsStore.setSystemPromptOverride(db, textarea.value);\n showSuccess(\"System prompt override saved\");\n }\n });\n\n // Clear prompt\n root\n .querySelector(\".tools__clear-prompt-btn\")\n ?.addEventListener(\"click\", () => {\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (textarea instanceof HTMLTextAreaElement) {\n textarea.value = \"\";\n toolsStore.setSystemPromptOverride(db, \"\");\n showSuccess(\"System prompt override cleared\");\n }\n });\n\n // Dialog controls — Add Tool\n const dialog = root.querySelector(\n \".tools__dialog\",\n ) as HTMLDialogElement | null;\n const closeBtn = dialog?.querySelector(\".tools__dialog-close\");\n const cancelBtn = dialog?.querySelector(\".tools__btn-cancel\");\n const form = root.querySelector(\n \".tools__dialog-form\",\n ) as HTMLFormElement | null;\n\n closeBtn?.addEventListener(\"click\", () => dialog?.close());\n cancelBtn?.addEventListener(\"click\", () => dialog?.close());\n\n dialog?.addEventListener(\"click\", (e) => {\n if (e.target === dialog) {\n dialog.close();\n }\n });\n\n form?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (form) {\n this.handleAddTool(db, form);\n }\n });\n\n // Dialog controls — Clone Tool\n const cloneDialog = root.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n const cloneCloseBtn = root.querySelector(\".tools__clone-dialog-close\");\n const cloneCancelBtn = root.querySelector(\".tools__clone-cancel-btn\");\n const cloneForm = root.querySelector(\n \".tools__clone-dialog-form\",\n ) as HTMLFormElement | null;\n\n cloneCloseBtn?.addEventListener(\"click\", () => cloneDialog?.close());\n cloneCancelBtn?.addEventListener(\"click\", () => cloneDialog?.close());\n cloneDialog?.addEventListener(\"click\", (e) => {\n if (e.target === cloneDialog) {\n cloneDialog.close();\n }\n });\n\n cloneForm?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (cloneForm) {\n this.handleCloneTool(db, cloneForm);\n }\n });\n\n // Dialog controls — Profile\n const profileDialog = root.querySelector(\n \".tools__profile-dialog\",\n ) as HTMLDialogElement | null;\n const profileCloseBtn = root.querySelector(\".tools__profile-dialog-close\");\n const profileCancelBtn = root.querySelector(\".tools__profile-cancel-btn\");\n const profileForm = root.querySelector(\n \".tools__profile-dialog-form\",\n ) as HTMLFormElement | null;\n\n profileCloseBtn?.addEventListener(\"click\", () => profileDialog?.close());\n profileCancelBtn?.addEventListener(\"click\", () => profileDialog?.close());\n profileDialog?.addEventListener(\"click\", (e) => {\n if (e.target === profileDialog) {\n profileDialog.close();\n }\n });\n\n profileForm?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n if (profileForm) {\n this.handleSaveProfile(db, profileForm);\n }\n });\n\n // Profile select\n const profileSelect = root.querySelector(\".tools__profile-select\");\n profileSelect?.addEventListener(\"change\", (e) => {\n const select = e.target as HTMLSelectElement;\n const value = select.value;\n if (value) {\n toolsStore.activateProfile(db, value);\n showInfo(\"Profile activated\");\n } else {\n toolsStore.deactivateProfile(db);\n showInfo(\"Profile deactivated\");\n }\n });\n\n // Profile new button → open dialog\n root\n .querySelector(\".tools__profile-new-btn\")\n ?.addEventListener(\"click\", () => {\n if (profileDialog && profileForm) {\n profileForm.reset();\n // Populate provider dropdown\n const providerSelect = profileForm.querySelector(\n '[name=\"providerId\"]',\n );\n if (providerSelect) {\n providerSelect.replaceChildren();\n const defaultOption = document.createElement(\"option\");\n defaultOption.value = \"\";\n defaultOption.textContent = \"— Any provider —\";\n providerSelect.append(defaultOption);\n for (const pid of getAvailableProviders()) {\n const p = getProvider(pid);\n if (p) {\n const opt = document.createElement(\"option\");\n opt.value = pid;\n opt.textContent = p.name;\n providerSelect.appendChild(opt);\n }\n }\n }\n\n (profileDialog as HTMLDialogElement).showModal();\n }\n });\n\n // Profile save (overwrite active)\n root\n .querySelector(\".tools__profile-save-btn\")\n ?.addEventListener(\"click\", async () => {\n const activeId = toolsStore.activeProfileId;\n if (activeId) {\n await toolsStore.saveToActiveProfile(db);\n showSuccess(\"Profile saved\");\n } else {\n // No active profile — open new profile dialog\n root\n .querySelector(\".tools__profile-new-btn\")\n ?.dispatchEvent(new Event(\"click\"));\n }\n });\n\n // Profile delete\n root\n .querySelector(\".tools__profile-delete-btn\")\n ?.addEventListener(\"click\", async () => {\n const activeId = toolsStore.activeProfileId;\n if (!activeId) {\n showInfo(\"No profile selected\");\n\n return;\n }\n\n if (activeId.startsWith(\"__builtin_\")) {\n showInfo(\"Built-in profiles cannot be deleted\");\n\n return;\n }\n\n await toolsStore.deleteProfile(db, activeId);\n showSuccess(\"Profile deleted\");\n });\n }\n\n handleBackup() {\n const json = toolsStore.exportBackup();\n const blob = new Blob([json], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `shadowclaw-tools-${Date.now()}.json`;\n a.click();\n URL.revokeObjectURL(url);\n showSuccess(\"Tools config exported\");\n }\n\n /**\n * Open the clone tool dialog for a given source tool.\n */\n openCloneDialog(sourceToolName: string) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const cloneDialog = root.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n const cloneForm = root.querySelector(\n \".tools__clone-dialog-form\",\n ) as HTMLFormElement | null;\n if (!cloneDialog || !cloneForm) {\n return;\n }\n\n cloneForm.reset();\n const sourceInput = cloneForm.querySelector(\n '[name=\"source\"]',\n ) as HTMLInputElement | null;\n if (sourceInput) {\n sourceInput.value = sourceToolName;\n }\n\n cloneDialog.showModal();\n }\n\n setupEffects(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Reactive re-render on tool store changes\n this.addCleanup(\n effect(() => {\n toolsStore.enabledToolNames;\n toolsStore.customTools;\n toolsStore.declarativeTools;\n toolsStore.declarativeToolNamesEnabled;\n toolsStore.systemPromptOverride;\n toolsStore.profiles;\n toolsStore.activeProfileId;\n this.updateToolList(db);\n }),\n );\n\n // WebMCP opt-in toggle\n const webMcpToggle = root.querySelector(\n \".tools__webmcp-toggle\",\n ) as HTMLInputElement | null;\n const internetAccessToggle = root.querySelector(\n \".tools__internet-access-toggle\",\n ) as HTMLInputElement | null;\n const webMcpModeSelect = root.querySelector(\n \".tools__webmcp-mode\",\n ) as HTMLSelectElement | null;\n\n if (webMcpToggle) {\n // Sync checked state and mode when orchestrator becomes available\n this.addCleanup(\n effect(() => {\n if (orchestratorStore.ready) {\n this.orchestrator = orchestratorStore.orchestrator;\n webMcpToggle.checked =\n this.orchestrator?.webMcpToolsEnabled === true;\n if (webMcpModeSelect && this.orchestrator) {\n webMcpModeSelect.value = getWebMcpMode() || \"polyfill\";\n }\n }\n }),\n );\n }\n\n if (internetAccessToggle) {\n this.addCleanup(\n effect(() => {\n internetAccessToggle.checked =\n orchestratorStore.vmBashFullInternetAccess;\n }),\n );\n }\n\n // Web Search reactive effects\n const webSearchProxyToggle = root.querySelector(\n \".tools__websearch-proxy-toggle\",\n ) as HTMLInputElement | null;\n const webSearchProxyUrlInput = root.querySelector(\n \".tools__websearch-proxy-url-input\",\n ) as HTMLInputElement | null;\n const webSearchUrlInput = root.querySelector(\n \".tools__websearch-url-input\",\n ) as HTMLInputElement | null;\n\n if (webSearchProxyToggle) {\n this.addCleanup(\n effect(() => {\n webSearchProxyToggle.checked = toolsStore.webSearchUseProxy;\n }),\n );\n }\n\n if (webSearchProxyUrlInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== webSearchProxyUrlInput &&\n !webSearchProxyUrlInput.matches(\":focus\")\n ) {\n webSearchProxyUrlInput.value = toolsStore.webSearchProxyUrl;\n }\n }),\n );\n }\n\n if (webSearchUrlInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== webSearchUrlInput &&\n !webSearchUrlInput.matches(\":focus\")\n ) {\n webSearchUrlInput.value = toolsStore.webSearchUrl;\n }\n }),\n );\n }\n\n // Search Files reactive effects\n const searchFilesMaxFileBytesInput = root.querySelector(\n \".tools__searchfiles-max-file-bytes-input\",\n ) as HTMLInputElement | null;\n const searchFilesMaxFilesVisitedInput = root.querySelector(\n \".tools__searchfiles-max-files-visited-input\",\n ) as HTMLInputElement | null;\n const searchFilesSkipDirsInput = root.querySelector(\n \".tools__searchfiles-skip-dirs-input\",\n ) as HTMLInputElement | null;\n\n if (searchFilesMaxFileBytesInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesMaxFileBytesInput &&\n !searchFilesMaxFileBytesInput.matches(\":focus\")\n ) {\n searchFilesMaxFileBytesInput.value = String(\n toolsStore.searchFilesMaxFileBytes,\n );\n }\n }),\n );\n }\n\n if (searchFilesMaxFilesVisitedInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesMaxFilesVisitedInput &&\n !searchFilesMaxFilesVisitedInput.matches(\":focus\")\n ) {\n searchFilesMaxFilesVisitedInput.value = String(\n toolsStore.searchFilesMaxFilesVisited,\n );\n }\n }),\n );\n }\n\n if (searchFilesSkipDirsInput) {\n this.addCleanup(\n effect(() => {\n if (\n document.activeElement !== searchFilesSkipDirsInput &&\n !searchFilesSkipDirsInput.matches(\":focus\")\n ) {\n searchFilesSkipDirsInput.value = toolsStore.searchFilesSkipDirs;\n }\n }),\n );\n }\n }\n\n /** Update the profile dropdown to reflect current state. */\n updateProfileSelector() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const select = root.querySelector(\".tools__profile-select\");\n if (!select) {\n return;\n }\n\n const profiles = toolsStore.profiles;\n const activeId = toolsStore.activeProfileId;\n\n // Preserve selection\n select.replaceChildren();\n const defaultOption = document.createElement(\"option\");\n defaultOption.value = \"\";\n defaultOption.textContent = \"— No profile (manual config) —\";\n select.append(defaultOption);\n for (const p of profiles) {\n const opt = document.createElement(\"option\");\n opt.value = p.id;\n const isBuiltin = p.id.startsWith(\"__builtin_\");\n const providerLabel = p.providerId\n ? getProvider(p.providerId)?.name || p.providerId\n : \"any\";\n const modelLabel = p.model || \"any\";\n opt.textContent = isBuiltin\n ? `⚡ ${p.name} (${providerLabel})`\n : `${p.name} (${providerLabel} / ${modelLabel})`;\n if (p.id === activeId) {\n opt.selected = true;\n }\n\n select.appendChild(opt);\n }\n\n // Disable delete button for built-in profiles\n const deleteBtn = root.querySelector(\n \".tools__profile-delete-btn\",\n ) as HTMLButtonElement | null;\n if (deleteBtn) {\n const isBuiltinActive = activeId?.startsWith(\"__builtin_\");\n deleteBtn.disabled = !!isBuiltinActive;\n deleteBtn.title = isBuiltinActive\n ? \"Built-in profiles cannot be deleted\"\n : \"\";\n }\n }\n\n updateToolList(db: ShadowClawDatabase) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector(\".tools__list\");\n if (!list) {\n return;\n }\n\n const enabled = toolsStore.enabledToolNames;\n const allTools = toolsStore.allTools;\n const declarativeTools = toolsStore.declarativeTools;\n\n const existingCheckboxes = list.querySelectorAll<HTMLInputElement>(\n \".tools__item-checkbox[data-tool]\",\n );\n const existingToolNames = Array.from(existingCheckboxes).map(\n (cb) => cb.getAttribute(\"data-tool\") || \"\",\n );\n const targetToolNames = [\n ...allTools.map((t) => t.name),\n ...declarativeTools.map((t) => t.name),\n ];\n\n const isSameStructure =\n existingToolNames.length === targetToolNames.length &&\n existingToolNames.every((name, i) => name === targetToolNames[i]);\n\n if (isSameStructure) {\n for (const cb of existingCheckboxes) {\n const toolName = cb.getAttribute(\"data-tool\");\n if (!toolName) continue;\n const isDeclarative = declarativeTools.some((t) => t.name === toolName);\n const isChecked = isDeclarative\n ? toolsStore.isDeclarativeToolEnabled(toolName)\n : enabled.has(toolName);\n if (cb.checked !== isChecked) {\n cb.checked = isChecked;\n }\n }\n } else {\n list.replaceChildren();\n\n for (const tool of allTools) {\n const isCustom = !BUILTIN_TOOL_NAMES.has(tool.name);\n const isChecked = enabled.has(tool.name);\n const brief = tool.description.split(\". \")[0];\n\n const item = document.createElement(\"div\");\n item.className = \"tools__item\";\n item.setAttribute(\"role\", \"listitem\");\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.className = \"tools__item-checkbox\";\n checkbox.setAttribute(\"data-tool\", tool.name);\n checkbox.setAttribute(\"aria-label\", `Enable ${tool.name}`);\n checkbox.checked = isChecked;\n\n const info = document.createElement(\"div\");\n info.className = \"tools__item-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"tools__item-name\";\n name.textContent = tool.name;\n\n const desc = document.createElement(\"div\");\n desc.className = \"tools__item-desc\";\n desc.setAttribute(\"title\", tool.description);\n desc.textContent = brief;\n info.append(name, desc);\n\n const cloneBtn = document.createElement(\"button\");\n cloneBtn.className = \"tools__item-clone\";\n cloneBtn.setAttribute(\"data-clone\", tool.name);\n cloneBtn.setAttribute(\"aria-label\", `Clone ${tool.name}`);\n cloneBtn.setAttribute(\"title\", \"Clone tool\");\n cloneBtn.textContent = \"📋\";\n\n item.append(checkbox, info);\n\n if (isCustom) {\n const badge = document.createElement(\"span\");\n badge.className = \"tools__item-badge\";\n badge.textContent = \"custom\";\n item.append(badge);\n }\n\n item.append(cloneBtn);\n\n let deleteBtn: HTMLButtonElement | null = null;\n if (isCustom) {\n deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"tools__item-delete\";\n deleteBtn.setAttribute(\"data-delete\", tool.name);\n deleteBtn.setAttribute(\"aria-label\", `Delete ${tool.name}`);\n deleteBtn.textContent = \"🗑️\";\n item.append(deleteBtn);\n }\n\n // Toggle\n checkbox?.addEventListener(\"change\", () => {\n toolsStore.setToolEnabled(db, tool.name, checkbox.checked);\n });\n\n // Clone\n cloneBtn?.addEventListener(\"click\", () => {\n this.openCloneDialog(tool.name);\n });\n\n // Delete custom tool\n deleteBtn?.addEventListener(\"click\", () => {\n toolsStore.removeCustomTool(db, tool.name);\n showInfo(`Removed custom tool: ${tool.name}`);\n });\n\n list.appendChild(item);\n }\n\n for (const tool of declarativeTools) {\n const isChecked = toolsStore.isDeclarativeToolEnabled(tool.name);\n const brief = tool.description.split(\". \")[0];\n\n const item = document.createElement(\"div\");\n item.className = \"tools__item\";\n item.setAttribute(\"role\", \"listitem\");\n\n const checkbox = document.createElement(\"input\");\n checkbox.type = \"checkbox\";\n checkbox.className = \"tools__item-checkbox\";\n checkbox.setAttribute(\"data-tool\", tool.name);\n checkbox.setAttribute(\"aria-label\", `Enable ${tool.name}`);\n checkbox.checked = isChecked;\n\n const info = document.createElement(\"div\");\n info.className = \"tools__item-info\";\n\n const name = document.createElement(\"div\");\n name.className = \"tools__item-name\";\n name.textContent = tool.name;\n\n const desc = document.createElement(\"div\");\n desc.className = \"tools__item-desc\";\n desc.setAttribute(\"title\", tool.description);\n desc.textContent = brief;\n info.append(name, desc);\n\n const badge = document.createElement(\"span\");\n badge.className = \"tools__item-badge tools__item-badge--declarative\";\n badge.textContent = \"declarative\";\n item.append(checkbox, info, badge);\n\n checkbox.addEventListener(\"change\", () => {\n toolsStore.setDeclarativeToolEnabled(db, tool.name, checkbox.checked);\n });\n\n list.appendChild(item);\n }\n }\n\n // Update count\n const countEl = root.querySelector(\".tools__count\");\n if (countEl) {\n const enabledBuiltinCount = (toolsStore.enabledTools || []).length;\n const enabledDeclarativeCount = (toolsStore.enabledDeclarativeTools || [])\n .length;\n const totalEnabled = enabledBuiltinCount + enabledDeclarativeCount;\n const totalCount = allTools.length + declarativeTools.length;\n countEl.textContent = `${totalEnabled} of ${totalCount} enabled`;\n }\n\n // Update prompt textarea\n const textarea = root.querySelector(\".tools__prompt-area\");\n if (\n textarea instanceof HTMLTextAreaElement &&\n document.activeElement !== textarea &&\n !textarea.matches(\":focus\")\n ) {\n textarea.value = toolsStore.systemPromptOverride;\n }\n\n // Update profile selector\n this.updateProfileSelector();\n }\n\n async handleAddTool(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const name = String(data.get(\"name\") || \"\").trim();\n const description = String(data.get(\"description\") || \"\").trim();\n const schemaStr = String(data.get(\"input_schema\") || \"\").trim();\n\n if (!name || !description) {\n showError(\"Name and description are required\");\n\n return;\n }\n\n // Check uniqueness\n if (toolsStore.allTools.some((t) => t.name === name)) {\n showError(`A tool named \"${name}\" already exists`);\n\n return;\n }\n\n let input_schema = { type: \"object\", properties: {} };\n if (schemaStr) {\n try {\n input_schema = JSON.parse(schemaStr);\n } catch {\n showError(\"Invalid JSON in input schema\");\n\n return;\n }\n }\n\n await toolsStore.addCustomTool(db, { name, description, input_schema });\n showSuccess(`Added custom tool: ${name}`);\n\n const dialog = this.shadowRoot?.querySelector(\n \".tools__dialog\",\n ) as HTMLDialogElement | null;\n dialog?.close();\n }\n\n async handleCloneTool(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const sourceToolName = String(data.get(\"source\") || \"\").trim();\n const newName = String(data.get(\"name\") || \"\").trim();\n const newDesc = String(data.get(\"description\") || \"\").trim();\n\n if (!sourceToolName || !newName) {\n showError(\"Source and new tool name are required\");\n\n return;\n }\n\n const ok = await toolsStore.cloneTool(\n db,\n sourceToolName,\n newName,\n newDesc || undefined,\n );\n if (!ok) {\n showError(\n `Clone failed: source not found or name \"${newName}\" already exists.`,\n );\n\n return;\n }\n\n showSuccess(`Cloned \"${sourceToolName}\" → \"${newName}\"`);\n const cloneDialog = this.shadowRoot?.querySelector(\n \".tools__clone-dialog\",\n ) as HTMLDialogElement | null;\n cloneDialog?.close();\n }\n\n async handleRestore(db: ShadowClawDatabase, input: HTMLInputElement) {\n const file = input.files?.[0];\n if (!file) {\n return;\n }\n\n try {\n const text = await file.text();\n await toolsStore.importBackup(db, text);\n showSuccess(\"Tools config restored\");\n } catch (err) {\n showError(\n `Failed to restore: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n input.value = \"\";\n }\n\n async handleSaveProfile(db: ShadowClawDatabase, form: HTMLFormElement) {\n const data = new FormData(form);\n const name = String(data.get(\"name\") || \"\").trim();\n const providerId = String(data.get(\"providerId\") || \"\").trim();\n const model = String(data.get(\"model\") || \"\").trim();\n\n if (!name) {\n showError(\"Profile name is required\");\n\n return;\n }\n\n const profile = {\n id: ulid(),\n name,\n providerId: providerId || undefined,\n model: model || undefined,\n enabledToolNames: [...toolsStore.enabledToolNames],\n customTools: [...toolsStore.customTools],\n systemPromptOverride: toolsStore.systemPromptOverride,\n };\n\n await toolsStore.addProfile(db, profile);\n await toolsStore.activateProfile(db, profile.id);\n showSuccess(`Profile \"${name}\" created and activated`);\n\n const profileDialog = this.shadowRoot?.querySelector(\n \".tools__profile-dialog\",\n ) as HTMLDialogElement | null;\n profileDialog?.close();\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawTools);\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { n as getDb } from "./txPromise-CuGh-TGK.js";
3
- import { f as DEFAULT_VM_BOOT_HOST, n as BASH_MAX_TIMEOUT_SEC, r as CONFIG_KEYS } from "./config--CFrw3J3.js";
3
+ import { f as DEFAULT_VM_BOOT_HOST, n as BASH_MAX_TIMEOUT_SEC, r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
4
4
  import { t as getConfig } from "./getConfig-BxxXMyuM.js";
5
- import { E as setVMNetworkRelayURL, T as setVMBootMode, t as orchestratorStore, v as setVMBashTimeout, w as setVMBootHost } from "./orchestrator-ClXbJ4Mb.js";
5
+ import { E as setVMNetworkRelayURL, T as setVMBootMode, t as orchestratorStore, v as setVMBashTimeout, w as setVMBootHost } from "./orchestrator-C6dc-2OQ.js";
6
6
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-DZ6r7_YI.js";
7
7
  import { t as effect } from "./effect-DL6j9HJp.js";
8
8
 
@@ -344,4 +344,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
344
344
 
345
345
  //#endregion
346
346
  export { ShadowClawWebvm as t };
347
- //# sourceMappingURL=shadow-claw-webvm-DYaoL7QY.js.map
347
+ //# sourceMappingURL=shadow-claw-webvm-DoGl5ZSJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-webvm-DYaoL7QY.js","names":["shadowClawWebvmStyles","shadowClawWebvmTemplate"],"sources":["../../src/components/settings/shadow-claw-webvm/shadow-claw-webvm.ts"],"sourcesContent":["import {\n BASH_DEFAULT_TIMEOUT_SEC,\n BASH_MAX_TIMEOUT_SEC,\n CONFIG_KEYS,\n DEFAULT_VM_BOOT_HOST,\n} from \"../../../config/config.js\";\n\nimport { effect } from \"../../../core/effect.js\";\n\nimport {\n setVMBootHost,\n setVMBootMode,\n setVMNetworkRelayURL,\n} from \"../../../core/orchestrator/utils/operations/vm.js\";\n\nimport { setVMBashTimeout } from \"../../../core/orchestrator/utils/settings.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { showError, showSuccess, showWarning } from \"../../../ui/toast.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawWebvmStyles from \"./shadow-claw-webvm.css\" with { type: \"css\" };\nimport shadowClawWebvmTemplate from \"./shadow-claw-webvm.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-webvm\";\n\n/**\n * Settings sub-component for WebVM configuration:\n * boot mode, bash timeout, boot host, network relay URL.\n */\nexport class ShadowClawWebvm extends ShadowClawElement {\n static styles = shadowClawWebvmStyles;\n static template = shadowClawWebvmTemplate;\n\n db: ShadowClawDatabase | null = null;\n orchestrator: Orchestrator | null = null;\n\n constructor() {\n super();\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n this.bindEventListeners();\n this.setupEffects();\n }\n\n /**\n * Bind all event listeners.\n */\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"save-vm-boot-mode\"]')\n ?.addEventListener(\"click\", () => this.saveVMBootMode());\n\n root\n .querySelector('[data-action=\"save-vm-bash-timeout\"]')\n ?.addEventListener(\"click\", () => this.saveVMBashTimeout());\n\n root\n .querySelector('[data-action=\"save-vm-boot-host\"]')\n ?.addEventListener(\"click\", () => this.saveVMBootHost());\n\n root\n .querySelector('[data-action=\"save-vm-network-relay-url\"]')\n ?.addEventListener(\"click\", () => this.saveVMNetworkRelayURL());\n }\n\n /**\n * Set up reactive effects.\n */\n setupEffects() {\n effect(() => {\n if (orchestratorStore.ready) {\n void (async () => {\n this.db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n await this.render();\n })();\n }\n });\n }\n\n /**\n * Load and populate all WebVM settings fields.\n */\n async render() {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n try {\n // Boot mode\n const vmBootModeSelect = root.querySelector(\n '[data-setting=\"vm-boot-mode-select\"]',\n ) as HTMLSelectElement | null;\n const vmBootMode = await getConfig(this.db, CONFIG_KEYS.VM_BOOT_MODE);\n const normalizedVMBootMode =\n vmBootMode === \"disabled\" ||\n vmBootMode === \"9p\" ||\n vmBootMode === \"ext2\" ||\n vmBootMode === \"auto\"\n ? vmBootMode\n : \"disabled\";\n if (vmBootModeSelect) {\n vmBootModeSelect.value = normalizedVMBootMode;\n }\n\n // Bash timeout\n const vmBashTimeoutInput = root.querySelector(\n '[data-setting=\"vm-bash-timeout-input\"]',\n ) as HTMLInputElement | null;\n const vmBashTimeoutRaw = await getConfig(\n this.db,\n CONFIG_KEYS.VM_BASH_TIMEOUT_SEC,\n );\n const vmBashTimeoutParsed = Number(vmBashTimeoutRaw);\n const normalizedVMBashTimeout = Number.isFinite(vmBashTimeoutParsed)\n ? Math.min(\n Math.max(Math.floor(vmBashTimeoutParsed), 1),\n BASH_MAX_TIMEOUT_SEC,\n )\n : BASH_DEFAULT_TIMEOUT_SEC;\n if (vmBashTimeoutInput) {\n vmBashTimeoutInput.value = String(normalizedVMBashTimeout);\n }\n\n // Boot host\n const vmBootHostInput = root.querySelector(\n '[data-setting=\"vm-boot-host-input\"]',\n ) as HTMLInputElement | null;\n const vmBootHostRaw = await getConfig(this.db, CONFIG_KEYS.VM_BOOT_HOST);\n if (vmBootHostInput) {\n vmBootHostInput.value =\n typeof vmBootHostRaw === \"string\"\n ? vmBootHostRaw.trim()\n : DEFAULT_VM_BOOT_HOST;\n }\n\n // Network relay URL\n const vmNetworkRelayURLInput = root.querySelector(\n '[data-setting=\"vm-network-relay-url-input\"]',\n ) as HTMLInputElement | null;\n const vmNetworkRelayURLRaw = await getConfig(\n this.db,\n CONFIG_KEYS.VM_NETWORK_RELAY_URL,\n );\n if (vmNetworkRelayURLInput && typeof vmNetworkRelayURLRaw === \"string\") {\n vmNetworkRelayURLInput.value = vmNetworkRelayURLRaw.trim();\n }\n } catch (e) {\n console.warn(\"Could not load WebVM settings:\", e);\n }\n }\n\n /**\n * Save default bash timeout.\n */\n async saveVMBashTimeout() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-bash-timeout-input\"]',\n ) as HTMLInputElement | null;\n const parsed = Number(input?.value);\n\n if (!Number.isFinite(parsed)) {\n showWarning(\"Please enter a valid timeout in seconds\", 3000);\n\n return;\n }\n\n const normalized = Math.min(\n Math.max(Math.floor(parsed), 1),\n BASH_MAX_TIMEOUT_SEC,\n );\n if (input) {\n input.value = String(normalized);\n }\n\n try {\n await setVMBashTimeout(this.orchestrator, this.db, normalized);\n showSuccess(\"WebVM bash timeout saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM bash timeout: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save boot host URL.\n */\n async saveVMBootHost() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-boot-host-input\"]',\n ) as HTMLInputElement | null;\n const value = input?.value?.trim() || \"\";\n\n if (value) {\n try {\n const parsed = new URL(value);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"Boot host must use http:// or https://\");\n }\n } catch {\n showWarning(\"Please enter a valid HTTP(S) boot host URL\", 3500);\n\n return;\n }\n }\n\n try {\n await setVMBootHost(this.orchestrator, this.db, value);\n showSuccess(\"WebVM boot host saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM boot host: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save VM boot mode.\n */\n async saveVMBootMode() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const select = root.querySelector(\n '[data-setting=\"vm-boot-mode-select\"]',\n ) as HTMLSelectElement | null;\n const selected = select?.value || \"disabled\";\n const mode =\n selected === \"disabled\" ||\n selected === \"9p\" ||\n selected === \"ext2\" ||\n selected === \"auto\"\n ? selected\n : \"disabled\";\n\n try {\n await setVMBootMode(this.orchestrator, this.db, mode);\n showSuccess(\"WebVM boot mode saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM mode: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save network relay URL.\n */\n async saveVMNetworkRelayURL() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-network-relay-url-input\"]',\n ) as HTMLInputElement | null;\n const value = input?.value?.trim() || \"\";\n\n if (value) {\n try {\n const parsed = new URL(value);\n if (parsed.protocol !== \"ws:\" && parsed.protocol !== \"wss:\") {\n throw new Error(\"Relay URL must use ws:// or wss://\");\n }\n } catch {\n showWarning(\"Please enter a valid ws:// or wss:// relay URL\", 3500);\n\n return;\n }\n }\n\n if (input) {\n input.value = value;\n }\n\n try {\n await setVMNetworkRelayURL(this.orchestrator, this.db, value);\n showSuccess(\"WebVM relay URL saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM relay URL: \" + errorMsg, 6000);\n }\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawWebvm);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shadow-claw-webvm-DoGl5ZSJ.js","names":["shadowClawWebvmStyles","shadowClawWebvmTemplate"],"sources":["../../src/components/settings/shadow-claw-webvm/shadow-claw-webvm.ts"],"sourcesContent":["import {\n BASH_DEFAULT_TIMEOUT_SEC,\n BASH_MAX_TIMEOUT_SEC,\n CONFIG_KEYS,\n DEFAULT_VM_BOOT_HOST,\n} from \"../../../config/config.js\";\n\nimport { effect } from \"../../../core/effect.js\";\n\nimport {\n setVMBootHost,\n setVMBootMode,\n setVMNetworkRelayURL,\n} from \"../../../core/orchestrator/utils/operations/vm.js\";\n\nimport { setVMBashTimeout } from \"../../../core/orchestrator/utils/settings.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { showError, showSuccess, showWarning } from \"../../../ui/toast.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawWebvmStyles from \"./shadow-claw-webvm.css\" with { type: \"css\" };\nimport shadowClawWebvmTemplate from \"./shadow-claw-webvm.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-webvm\";\n\n/**\n * Settings sub-component for WebVM configuration:\n * boot mode, bash timeout, boot host, network relay URL.\n */\nexport class ShadowClawWebvm extends ShadowClawElement {\n static styles = shadowClawWebvmStyles;\n static template = shadowClawWebvmTemplate;\n\n db: ShadowClawDatabase | null = null;\n orchestrator: Orchestrator | null = null;\n\n constructor() {\n super();\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n this.bindEventListeners();\n this.setupEffects();\n }\n\n /**\n * Bind all event listeners.\n */\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"save-vm-boot-mode\"]')\n ?.addEventListener(\"click\", () => this.saveVMBootMode());\n\n root\n .querySelector('[data-action=\"save-vm-bash-timeout\"]')\n ?.addEventListener(\"click\", () => this.saveVMBashTimeout());\n\n root\n .querySelector('[data-action=\"save-vm-boot-host\"]')\n ?.addEventListener(\"click\", () => this.saveVMBootHost());\n\n root\n .querySelector('[data-action=\"save-vm-network-relay-url\"]')\n ?.addEventListener(\"click\", () => this.saveVMNetworkRelayURL());\n }\n\n /**\n * Set up reactive effects.\n */\n setupEffects() {\n effect(() => {\n if (orchestratorStore.ready) {\n void (async () => {\n this.db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n await this.render();\n })();\n }\n });\n }\n\n /**\n * Load and populate all WebVM settings fields.\n */\n async render() {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n try {\n // Boot mode\n const vmBootModeSelect = root.querySelector(\n '[data-setting=\"vm-boot-mode-select\"]',\n ) as HTMLSelectElement | null;\n const vmBootMode = await getConfig(this.db, CONFIG_KEYS.VM_BOOT_MODE);\n const normalizedVMBootMode =\n vmBootMode === \"disabled\" ||\n vmBootMode === \"9p\" ||\n vmBootMode === \"ext2\" ||\n vmBootMode === \"auto\"\n ? vmBootMode\n : \"disabled\";\n if (vmBootModeSelect) {\n vmBootModeSelect.value = normalizedVMBootMode;\n }\n\n // Bash timeout\n const vmBashTimeoutInput = root.querySelector(\n '[data-setting=\"vm-bash-timeout-input\"]',\n ) as HTMLInputElement | null;\n const vmBashTimeoutRaw = await getConfig(\n this.db,\n CONFIG_KEYS.VM_BASH_TIMEOUT_SEC,\n );\n const vmBashTimeoutParsed = Number(vmBashTimeoutRaw);\n const normalizedVMBashTimeout = Number.isFinite(vmBashTimeoutParsed)\n ? Math.min(\n Math.max(Math.floor(vmBashTimeoutParsed), 1),\n BASH_MAX_TIMEOUT_SEC,\n )\n : BASH_DEFAULT_TIMEOUT_SEC;\n if (vmBashTimeoutInput) {\n vmBashTimeoutInput.value = String(normalizedVMBashTimeout);\n }\n\n // Boot host\n const vmBootHostInput = root.querySelector(\n '[data-setting=\"vm-boot-host-input\"]',\n ) as HTMLInputElement | null;\n const vmBootHostRaw = await getConfig(this.db, CONFIG_KEYS.VM_BOOT_HOST);\n if (vmBootHostInput) {\n vmBootHostInput.value =\n typeof vmBootHostRaw === \"string\"\n ? vmBootHostRaw.trim()\n : DEFAULT_VM_BOOT_HOST;\n }\n\n // Network relay URL\n const vmNetworkRelayURLInput = root.querySelector(\n '[data-setting=\"vm-network-relay-url-input\"]',\n ) as HTMLInputElement | null;\n const vmNetworkRelayURLRaw = await getConfig(\n this.db,\n CONFIG_KEYS.VM_NETWORK_RELAY_URL,\n );\n if (vmNetworkRelayURLInput && typeof vmNetworkRelayURLRaw === \"string\") {\n vmNetworkRelayURLInput.value = vmNetworkRelayURLRaw.trim();\n }\n } catch (e) {\n console.warn(\"Could not load WebVM settings:\", e);\n }\n }\n\n /**\n * Save default bash timeout.\n */\n async saveVMBashTimeout() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-bash-timeout-input\"]',\n ) as HTMLInputElement | null;\n const parsed = Number(input?.value);\n\n if (!Number.isFinite(parsed)) {\n showWarning(\"Please enter a valid timeout in seconds\", 3000);\n\n return;\n }\n\n const normalized = Math.min(\n Math.max(Math.floor(parsed), 1),\n BASH_MAX_TIMEOUT_SEC,\n );\n if (input) {\n input.value = String(normalized);\n }\n\n try {\n await setVMBashTimeout(this.orchestrator, this.db, normalized);\n showSuccess(\"WebVM bash timeout saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM bash timeout: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save boot host URL.\n */\n async saveVMBootHost() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-boot-host-input\"]',\n ) as HTMLInputElement | null;\n const value = input?.value?.trim() || \"\";\n\n if (value) {\n try {\n const parsed = new URL(value);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"Boot host must use http:// or https://\");\n }\n } catch {\n showWarning(\"Please enter a valid HTTP(S) boot host URL\", 3500);\n\n return;\n }\n }\n\n try {\n await setVMBootHost(this.orchestrator, this.db, value);\n showSuccess(\"WebVM boot host saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM boot host: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save VM boot mode.\n */\n async saveVMBootMode() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const select = root.querySelector(\n '[data-setting=\"vm-boot-mode-select\"]',\n ) as HTMLSelectElement | null;\n const selected = select?.value || \"disabled\";\n const mode =\n selected === \"disabled\" ||\n selected === \"9p\" ||\n selected === \"ext2\" ||\n selected === \"auto\"\n ? selected\n : \"disabled\";\n\n try {\n await setVMBootMode(this.orchestrator, this.db, mode);\n showSuccess(\"WebVM boot mode saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM mode: \" + errorMsg, 6000);\n }\n }\n\n /**\n * Save network relay URL.\n */\n async saveVMNetworkRelayURL() {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-setting=\"vm-network-relay-url-input\"]',\n ) as HTMLInputElement | null;\n const value = input?.value?.trim() || \"\";\n\n if (value) {\n try {\n const parsed = new URL(value);\n if (parsed.protocol !== \"ws:\" && parsed.protocol !== \"wss:\") {\n throw new Error(\"Relay URL must use ws:// or wss://\");\n }\n } catch {\n showWarning(\"Please enter a valid ws:// or wss:// relay URL\", 3500);\n\n return;\n }\n }\n\n if (input) {\n input.value = value;\n }\n\n try {\n await setVMNetworkRelayURL(this.orchestrator, this.db, value);\n showSuccess(\"WebVM relay URL saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving WebVM relay URL: \" + errorMsg, 6000);\n }\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawWebvm);\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { Signal } from "signal-polyfill";
2
2
  import type { DataConnection } from "peerjs";
3
3
  import type { MessageAttachment } from "../../content/types.js";
4
4
  import type { A2UIAction, A2UIEnvelope } from "../../ui/a2ui/types.js";
5
- import type { Channel, ChannelMessageCallback, ChannelTypingCallback } from "./types.js";
5
+ import type { Channel, ChannelMessageCallback, ChannelTypingCallback, RoomMeta } from "./types.js";
6
6
  import { PeerCardStore } from "./peer-agent-card.js";
7
7
  import { PeerTaskManager } from "./peer-task-manager.js";
8
8
  /**
@@ -14,6 +14,22 @@ export declare const transferProgressSignal: Signal.State<{
14
14
  total: number;
15
15
  direction: "send" | "receive";
16
16
  } | null>;
17
+ /**
18
+ * Update transfer progress signal and cancel any pending delayed clear timer.
19
+ */
20
+ export declare function updateTransferProgress(progress: {
21
+ count: number;
22
+ total: number;
23
+ direction: "send" | "receive";
24
+ } | null): void;
25
+ /**
26
+ * Clear transfer progress after a delay, ensuring any existing timer is reset.
27
+ */
28
+ export declare function clearTransferProgressDelayed(delayMs?: number): void;
29
+ /** Maximum chunk size in bytes for application-level file transfers (15 KB to stay safely under PeerJS 16,300 MTU after msgpack framing) */
30
+ export declare const FILE_CHUNK_SIZE = 15360;
31
+ /** Threshold for WebRTC DataChannel bufferedAmount backpressure (64 KB) */
32
+ export declare const FILE_BUFFER_DRAIN_THRESHOLD = 65536;
17
33
  export interface PeerJsServerConfig {
18
34
  host?: string;
19
35
  port?: number;
@@ -69,6 +85,8 @@ export declare class PeerJsChannel implements Channel {
69
85
  private _roomNotificationHandler;
70
86
  /** Per-connection task managers keyed by remote peer ID */
71
87
  private _taskManagers;
88
+ /** Inbound multi-chunk file transfers keyed by transferId */
89
+ private _inboundTransfers;
72
90
  constructor();
73
91
  /**
74
92
  * Mark the active task for a peer groupId as COMPLETED.
@@ -108,6 +126,11 @@ export declare class PeerJsChannel implements Channel {
108
126
  * relay traffic carried over the existing DataChannel.
109
127
  */
110
128
  setRoomNotificationHandler(handler: (fromPeerId: string, method: string, params: unknown) => void): void;
129
+ /**
130
+ * Stream file attachments to all other members in a room over WebRTC DataConnections,
131
+ * tagged with the room groupId.
132
+ */
133
+ sendAttachmentsToRoom(room: RoomMeta, groupId: string, attachments: MessageAttachment[]): Promise<void>;
111
134
  setTyping(groupId: string, typing: boolean): void;
112
135
  start(): void;
113
136
  ensureConnected(force?: boolean): void;
@@ -163,6 +186,11 @@ export declare class PeerJsChannel implements Channel {
163
186
  private _handleInboundData;
164
187
  private _isTrustedPeer;
165
188
  private _handleIncomingConnection;
189
+ /**
190
+ * Intercept incoming BinaryPack chunk handling on DataConnection to track
191
+ * file reception progress without requiring a custom PeerJS fork.
192
+ */
193
+ private _attachChunkProgressTracker;
166
194
  /**
167
195
  * Handle an inbound task status update notification.
168
196
  */
@@ -182,10 +210,15 @@ export declare class PeerJsChannel implements Channel {
182
210
  */
183
211
  private _sendJsonRpcError;
184
212
  /**
185
- * Track outbound send progress by polling RTCDataChannel.bufferedAmount.
186
- * Resolves when all queued data has been flushed to the network.
213
+ * Pause execution if the underlying WebRTC DataChannel send buffer
214
+ * exceeds the drain threshold, preventing buffer bloat during large transfers.
215
+ */
216
+ private _waitForBufferDrain;
217
+ /**
218
+ * Persist complete received file bytes into group storage, handling
219
+ * duplicate filename incrementing and path remapping.
187
220
  */
188
- private _trackSendProgress;
221
+ private _saveInboundFile;
189
222
  private _updateConnectedPeersSignal;
190
223
  /**
191
224
  * Waits up to 5s for a DataConnection to open. Resolves immediately if
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import type { MessageAttachment } from "../../content/types.js";
14
14
  import type { Channel, ChannelMessageCallback, ChannelTypingCallback, InboundMessage } from "./types.js";
15
+ import type { PeerJsChannel } from "./peerjs.js";
15
16
  import type { RoomManager } from "./room-manager.js";
16
17
  export declare class RoomChannel implements Channel {
17
18
  messageCallback: ChannelMessageCallback | null;
@@ -19,12 +20,15 @@ export declare class RoomChannel implements Channel {
19
20
  type: Channel["type"];
20
21
  typingCallback: ChannelTypingCallback | null;
21
22
  private _manager;
23
+ private _peerjs;
22
24
  /** Deliver an inbound room message (called by the {@link RoomManager}). */
23
25
  deliverInbound(msg: InboundMessage): void;
24
26
  onMessage(callback: ChannelMessageCallback): void;
25
27
  onTyping(callback: ChannelTypingCallback): void;
26
28
  /** Wire the room manager used for transport. */
27
29
  setManager(manager: RoomManager): void;
30
+ /** Wire the PeerJS channel used for WebRTC file streaming. */
31
+ setPeerJs(peerjs: PeerJsChannel): void;
28
32
  setTyping(_groupId: string, _typing: boolean): void;
29
33
  start(): void;
30
34
  stop(): void;
@@ -1,9 +1,9 @@
1
- import { r as CONFIG_KEYS } from "./config--CFrw3J3.js";
2
- import { t as toolsStore } from "./tools-DwwB9RBa.js";
3
- import { Mt as discoverSkills, O as handleWorkerMessage, t as orchestratorStore } from "./orchestrator-ClXbJ4Mb.js";
1
+ import { r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
2
+ import { t as toolsStore } from "./tools-DqcJe8LS.js";
3
+ import { Mt as discoverSkills, O as handleWorkerMessage, t as orchestratorStore } from "./orchestrator-C6dc-2OQ.js";
4
4
  import { t as setConfig } from "./setConfig-BFED5CXn.js";
5
5
  import { t as effect } from "./effect-DL6j9HJp.js";
6
- import { i as unregisterWebMcpTools, n as registerWebMcpTools, r as setWebMcpMode$1 } from "./webmcp-j_1_T3wf.js";
6
+ import { i as unregisterWebMcpTools, n as registerWebMcpTools, r as setWebMcpMode$1 } from "./webmcp-BC8_WafM.js";
7
7
 
8
8
  //#region src/subsystems/skills/tool.ts
9
9
  const activate_skill = {
@@ -74,4 +74,4 @@ async function setWebMcpToolsEnabled(state, db, enabled, syncDeps) {
74
74
 
75
75
  //#endregion
76
76
  export { activate_skill as i, setWebMcpToolsEnabled as n, syncWebMcpRegistration as r, setWebMcpMode as t };
77
- //# sourceMappingURL=syncWebMcpRegistration-BhbqI6R2.js.map
77
+ //# sourceMappingURL=syncWebMcpRegistration-BeYkQEvj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncWebMcpRegistration-BhbqI6R2.js","names":[],"sources":["../../src/subsystems/skills/tool.ts","../../src/core/orchestrator/utils/syncWebMcpRegistration.ts"],"sourcesContent":["import type { ToolDefinition } from \"../../subsystems/tools/types.js\";\n\nexport const activate_skill: ToolDefinition = {\n name: \"activate_skill\",\n description:\n \"Load the full instructions for a workspace skill when its description matches the current task.\",\n input_schema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: \"The exact skill name from the available skills catalog.\",\n },\n },\n required: [\"name\"],\n },\n};\n","import { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../../stores/tools.js\";\n\nimport {\n setWebMcpMode as applyWebMcpMode,\n registerWebMcpTools,\n unregisterWebMcpTools,\n} from \"../../../subsystems/mcp/webmcp.js\";\n\nimport { effect } from \"../../effect.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\n\nimport { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { WebMcpMode } from \"../../../subsystems/mcp/webmcp.js\";\nimport type { OrchestratorState } from \"../orchestrator-state.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { activate_skill } from \"../../../subsystems/skills/tool.js\";\n\nexport function syncWebMcpRegistration(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): void {\n if (typeof orchestrator.webMcpEffectCleanup === \"function\") {\n orchestrator.webMcpEffectCleanup();\n orchestrator.webMcpEffectCleanup = null;\n }\n\n if (!orchestrator.webMcpToolsEnabled) {\n unregisterWebMcpTools();\n\n return;\n }\n\n // Register WebMCP tools and re-register when tool config changes.\n // This effect runs once immediately to perform the initial registration.\n // We intentionally do NOT call isWebMcpSupported() here — that accesses\n // the browser's modelContext API which can crash Chrome Canary's\n // early-preview renderer. Instead, registerWebMcpTools handles feature detection\n // internally and skips modelContext access entirely when 0 tools are\n // passed.\n orchestrator.webMcpEffectCleanup = effect(() => {\n // Access signals to establish tracking.\n const activeGroupId = orchestratorStore.activeGroupId;\n const allTools = toolsStore.allTools;\n const globalTools = toolsStore.enabledTools;\n void toolsStore.declarativeTools;\n void toolsStore.declarativeToolNamesEnabled;\n const groups = orchestratorStore.groups;\n const group = groups.find((g) => g.groupId === activeGroupId);\n\n // Serialize WebMCP registration calls to prevent overlapping unregister/register cycles.\n orchestrator.webMcpRegistrationLock = orchestrator.webMcpRegistrationLock\n .then(async () => {\n unregisterWebMcpTools();\n // Small delay to allow the browser's ModelContext to process the unregistrations.\n await new Promise((resolve) => setTimeout(resolve, 0));\n\n let declarativeTools: any[] = [];\n try {\n declarativeTools = await toolsStore.refreshDeclarativeTools(\n db,\n activeGroupId,\n );\n } catch {\n // Ignore OPFS load errors\n }\n\n const enabledDeclarativeTools = declarativeTools.filter((dt) =>\n toolsStore.isDeclarativeToolEnabled(dt.name),\n );\n\n const candidateTools = [...allTools, ...declarativeTools];\n let tools =\n group?.toolTags && group.toolTags.length > 0\n ? candidateTools.filter((t) => group.toolTags!.includes(t.name))\n : [...globalTools, ...enabledDeclarativeTools];\n\n let skillDiscovery: { skills: any[] } = { skills: [] };\n try {\n skillDiscovery = await discoverSkills(db, activeGroupId);\n } catch {\n // Ignore OPFS load errors\n }\n\n if (\n skillDiscovery.skills.length > 0 &&\n !tools.some((t) => t.name === activate_skill.name)\n ) {\n tools = [...tools, activate_skill];\n }\n\n await registerWebMcpTools(\n orchestrator.agentWorker,\n async (msg) => {\n await handleWorkerMessage(orchestrator, db, msg);\n },\n activeGroupId,\n tools,\n );\n })\n .catch((err) => {\n console.error(\"WebMCP registration failed:\", err);\n });\n });\n}\nexport async function setWebMcpMode(\n _state: Pick<\n OrchestratorState,\n \"webMcpToolsEnabled\" | \"webMcpRegistrationLock\"\n > & {\n webMcpEffectCleanup: (() => void) | null;\n agentWorker: Worker | null;\n },\n db: ShadowClawDatabase,\n mode: WebMcpMode,\n syncDeps: { orchestrator: Orchestrator },\n): Promise<void> {\n // Unregister with old mode, switch, re-register with new mode.\n unregisterWebMcpTools();\n applyWebMcpMode(mode);\n\n await setConfig(db, CONFIG_KEYS.WEBMCP_MODE, mode);\n\n syncWebMcpRegistration(syncDeps.orchestrator, db);\n}\n\nexport async function setWebMcpToolsEnabled(\n state: Pick<OrchestratorState, \"webMcpToolsEnabled\">,\n db: ShadowClawDatabase,\n enabled: boolean,\n syncDeps: { orchestrator: Orchestrator },\n): Promise<void> {\n state.webMcpToolsEnabled = !!enabled;\n\n await setConfig(\n db,\n CONFIG_KEYS.WEBMCP_TOOLS_ENABLED,\n state.webMcpToolsEnabled ? \"true\" : \"false\",\n );\n\n syncWebMcpRegistration(syncDeps.orchestrator, db);\n}\n"],"mappings":";;;;;;;;AAEA,MAAa,iBAAiC;CAC5C,MAAM;CACN,aACE;CACF,cAAc;EACZ,MAAM;EACN,YAAY,EACV,MAAM;GACJ,MAAM;GACN,aAAa;EACf,EACF;EACA,UAAU,CAAC,MAAM;CACnB;AACF;;;;ACOA,SAAgB,uBACd,cACA,IACM;CACN,IAAI,OAAO,aAAa,wBAAwB,YAAY;EAC1D,aAAa,oBAAoB;EACjC,aAAa,sBAAsB;CACrC;CAEA,IAAI,CAAC,aAAa,oBAAoB;EACpC,sBAAsB;EAEtB;CACF;CASA,aAAa,sBAAsB,aAAa;EAE9C,MAAM,gBAAgB,kBAAkB;EACxC,MAAM,WAAW,WAAW;EAC5B,MAAM,cAAc,WAAW;EAC/B,AAAK,WAAW;EAChB,AAAK,WAAW;EAEhB,MAAM,QADS,kBAAkB,OACZ,MAAM,MAAM,EAAE,YAAY,aAAa;EAG5D,aAAa,yBAAyB,aAAa,uBAChD,KAAK,YAAY;GAChB,sBAAsB;GAEtB,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,CAAC,CAAC;GAErD,IAAI,mBAA0B,CAAC;GAC/B,IAAI;IACF,mBAAmB,MAAM,WAAW,wBAClC,IACA,aACF;GACF,QAAQ,CAER;GAEA,MAAM,0BAA0B,iBAAiB,QAAQ,OACvD,WAAW,yBAAyB,GAAG,IAAI,CAC7C;GAEA,MAAM,iBAAiB,CAAC,GAAG,UAAU,GAAG,gBAAgB;GACxD,IAAI,QACF,OAAO,YAAY,MAAM,SAAS,SAAS,IACvC,eAAe,QAAQ,MAAM,MAAM,SAAU,SAAS,EAAE,IAAI,CAAC,IAC7D,CAAC,GAAG,aAAa,GAAG,uBAAuB;GAEjD,IAAI,iBAAoC,EAAE,QAAQ,CAAC,EAAE;GACrD,IAAI;IACF,iBAAiB,MAAM,eAAe,IAAI,aAAa;GACzD,QAAQ,CAER;GAEA,IACE,eAAe,OAAO,SAAS,KAC/B,CAAC,MAAM,MAAM,MAAM,EAAE,SAAS,eAAe,IAAI,GAEjD,QAAQ,CAAC,GAAG,OAAO,cAAc;GAGnC,MAAM,oBACJ,aAAa,aACb,OAAO,QAAQ;IACb,MAAM,oBAAoB,cAAc,IAAI,GAAG;GACjD,GACA,eACA,KACF;EACF,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,QAAQ,MAAM,+BAA+B,GAAG;EAClD,CAAC;CACL,CAAC;AACH;AACA,eAAsB,cACpB,QAOA,IACA,MACA,UACe;CAEf,sBAAsB;CACtB,gBAAgB,IAAI;CAEpB,MAAM,UAAU,IAAI,YAAY,aAAa,IAAI;CAEjD,uBAAuB,SAAS,cAAc,EAAE;AAClD;AAEA,eAAsB,sBACpB,OACA,IACA,SACA,UACe;CACf,MAAM,qBAAqB,CAAC,CAAC;CAE7B,MAAM,UACJ,IACA,YAAY,sBACZ,MAAM,qBAAqB,SAAS,OACtC;CAEA,uBAAuB,SAAS,cAAc,EAAE;AAClD"}
1
+ {"version":3,"file":"syncWebMcpRegistration-BeYkQEvj.js","names":[],"sources":["../../src/subsystems/skills/tool.ts","../../src/core/orchestrator/utils/syncWebMcpRegistration.ts"],"sourcesContent":["import type { ToolDefinition } from \"../../subsystems/tools/types.js\";\n\nexport const activate_skill: ToolDefinition = {\n name: \"activate_skill\",\n description:\n \"Load the full instructions for a workspace skill when its description matches the current task.\",\n input_schema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: \"The exact skill name from the available skills catalog.\",\n },\n },\n required: [\"name\"],\n },\n};\n","import { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { toolsStore } from \"../../../stores/tools.js\";\n\nimport {\n setWebMcpMode as applyWebMcpMode,\n registerWebMcpTools,\n unregisterWebMcpTools,\n} from \"../../../subsystems/mcp/webmcp.js\";\n\nimport { effect } from \"../../effect.js\";\nimport { handleWorkerMessage } from \"./handleWorkerMessage.js\";\n\nimport { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { WebMcpMode } from \"../../../subsystems/mcp/webmcp.js\";\nimport type { OrchestratorState } from \"../orchestrator-state.js\";\nimport type { Orchestrator } from \"../orchestrator.js\";\n\nimport { discoverSkills } from \"../../../subsystems/skills/discoverSkills.js\";\nimport { activate_skill } from \"../../../subsystems/skills/tool.js\";\n\nexport function syncWebMcpRegistration(\n orchestrator: Orchestrator,\n db: ShadowClawDatabase,\n): void {\n if (typeof orchestrator.webMcpEffectCleanup === \"function\") {\n orchestrator.webMcpEffectCleanup();\n orchestrator.webMcpEffectCleanup = null;\n }\n\n if (!orchestrator.webMcpToolsEnabled) {\n unregisterWebMcpTools();\n\n return;\n }\n\n // Register WebMCP tools and re-register when tool config changes.\n // This effect runs once immediately to perform the initial registration.\n // We intentionally do NOT call isWebMcpSupported() here — that accesses\n // the browser's modelContext API which can crash Chrome Canary's\n // early-preview renderer. Instead, registerWebMcpTools handles feature detection\n // internally and skips modelContext access entirely when 0 tools are\n // passed.\n orchestrator.webMcpEffectCleanup = effect(() => {\n // Access signals to establish tracking.\n const activeGroupId = orchestratorStore.activeGroupId;\n const allTools = toolsStore.allTools;\n const globalTools = toolsStore.enabledTools;\n void toolsStore.declarativeTools;\n void toolsStore.declarativeToolNamesEnabled;\n const groups = orchestratorStore.groups;\n const group = groups.find((g) => g.groupId === activeGroupId);\n\n // Serialize WebMCP registration calls to prevent overlapping unregister/register cycles.\n orchestrator.webMcpRegistrationLock = orchestrator.webMcpRegistrationLock\n .then(async () => {\n unregisterWebMcpTools();\n // Small delay to allow the browser's ModelContext to process the unregistrations.\n await new Promise((resolve) => setTimeout(resolve, 0));\n\n let declarativeTools: any[] = [];\n try {\n declarativeTools = await toolsStore.refreshDeclarativeTools(\n db,\n activeGroupId,\n );\n } catch {\n // Ignore OPFS load errors\n }\n\n const enabledDeclarativeTools = declarativeTools.filter((dt) =>\n toolsStore.isDeclarativeToolEnabled(dt.name),\n );\n\n const candidateTools = [...allTools, ...declarativeTools];\n let tools =\n group?.toolTags && group.toolTags.length > 0\n ? candidateTools.filter((t) => group.toolTags!.includes(t.name))\n : [...globalTools, ...enabledDeclarativeTools];\n\n let skillDiscovery: { skills: any[] } = { skills: [] };\n try {\n skillDiscovery = await discoverSkills(db, activeGroupId);\n } catch {\n // Ignore OPFS load errors\n }\n\n if (\n skillDiscovery.skills.length > 0 &&\n !tools.some((t) => t.name === activate_skill.name)\n ) {\n tools = [...tools, activate_skill];\n }\n\n await registerWebMcpTools(\n orchestrator.agentWorker,\n async (msg) => {\n await handleWorkerMessage(orchestrator, db, msg);\n },\n activeGroupId,\n tools,\n );\n })\n .catch((err) => {\n console.error(\"WebMCP registration failed:\", err);\n });\n });\n}\nexport async function setWebMcpMode(\n _state: Pick<\n OrchestratorState,\n \"webMcpToolsEnabled\" | \"webMcpRegistrationLock\"\n > & {\n webMcpEffectCleanup: (() => void) | null;\n agentWorker: Worker | null;\n },\n db: ShadowClawDatabase,\n mode: WebMcpMode,\n syncDeps: { orchestrator: Orchestrator },\n): Promise<void> {\n // Unregister with old mode, switch, re-register with new mode.\n unregisterWebMcpTools();\n applyWebMcpMode(mode);\n\n await setConfig(db, CONFIG_KEYS.WEBMCP_MODE, mode);\n\n syncWebMcpRegistration(syncDeps.orchestrator, db);\n}\n\nexport async function setWebMcpToolsEnabled(\n state: Pick<OrchestratorState, \"webMcpToolsEnabled\">,\n db: ShadowClawDatabase,\n enabled: boolean,\n syncDeps: { orchestrator: Orchestrator },\n): Promise<void> {\n state.webMcpToolsEnabled = !!enabled;\n\n await setConfig(\n db,\n CONFIG_KEYS.WEBMCP_TOOLS_ENABLED,\n state.webMcpToolsEnabled ? \"true\" : \"false\",\n );\n\n syncWebMcpRegistration(syncDeps.orchestrator, db);\n}\n"],"mappings":";;;;;;;;AAEA,MAAa,iBAAiC;CAC5C,MAAM;CACN,aACE;CACF,cAAc;EACZ,MAAM;EACN,YAAY,EACV,MAAM;GACJ,MAAM;GACN,aAAa;EACf,EACF;EACA,UAAU,CAAC,MAAM;CACnB;AACF;;;;ACOA,SAAgB,uBACd,cACA,IACM;CACN,IAAI,OAAO,aAAa,wBAAwB,YAAY;EAC1D,aAAa,oBAAoB;EACjC,aAAa,sBAAsB;CACrC;CAEA,IAAI,CAAC,aAAa,oBAAoB;EACpC,sBAAsB;EAEtB;CACF;CASA,aAAa,sBAAsB,aAAa;EAE9C,MAAM,gBAAgB,kBAAkB;EACxC,MAAM,WAAW,WAAW;EAC5B,MAAM,cAAc,WAAW;EAC/B,AAAK,WAAW;EAChB,AAAK,WAAW;EAEhB,MAAM,QADS,kBAAkB,OACZ,MAAM,MAAM,EAAE,YAAY,aAAa;EAG5D,aAAa,yBAAyB,aAAa,uBAChD,KAAK,YAAY;GAChB,sBAAsB;GAEtB,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,CAAC,CAAC;GAErD,IAAI,mBAA0B,CAAC;GAC/B,IAAI;IACF,mBAAmB,MAAM,WAAW,wBAClC,IACA,aACF;GACF,QAAQ,CAER;GAEA,MAAM,0BAA0B,iBAAiB,QAAQ,OACvD,WAAW,yBAAyB,GAAG,IAAI,CAC7C;GAEA,MAAM,iBAAiB,CAAC,GAAG,UAAU,GAAG,gBAAgB;GACxD,IAAI,QACF,OAAO,YAAY,MAAM,SAAS,SAAS,IACvC,eAAe,QAAQ,MAAM,MAAM,SAAU,SAAS,EAAE,IAAI,CAAC,IAC7D,CAAC,GAAG,aAAa,GAAG,uBAAuB;GAEjD,IAAI,iBAAoC,EAAE,QAAQ,CAAC,EAAE;GACrD,IAAI;IACF,iBAAiB,MAAM,eAAe,IAAI,aAAa;GACzD,QAAQ,CAER;GAEA,IACE,eAAe,OAAO,SAAS,KAC/B,CAAC,MAAM,MAAM,MAAM,EAAE,SAAS,eAAe,IAAI,GAEjD,QAAQ,CAAC,GAAG,OAAO,cAAc;GAGnC,MAAM,oBACJ,aAAa,aACb,OAAO,QAAQ;IACb,MAAM,oBAAoB,cAAc,IAAI,GAAG;GACjD,GACA,eACA,KACF;EACF,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,QAAQ,MAAM,+BAA+B,GAAG;EAClD,CAAC;CACL,CAAC;AACH;AACA,eAAsB,cACpB,QAOA,IACA,MACA,UACe;CAEf,sBAAsB;CACtB,gBAAgB,IAAI;CAEpB,MAAM,UAAU,IAAI,YAAY,aAAa,IAAI;CAEjD,uBAAuB,SAAS,cAAc,EAAE;AAClD;AAEA,eAAsB,sBACpB,OACA,IACA,SACA,UACe;CACf,MAAM,qBAAqB,CAAC,CAAC;CAE7B,MAAM,UACJ,IACA,YAAY,sBACZ,MAAM,qBAAqB,SAAS,OACtC;CAEA,uBAAuB,SAAS,cAAc,EAAE;AAClD"}
@@ -0,0 +1 @@
1
+ import "./tools-DKzPWc0q.js";
@@ -1062,7 +1062,7 @@ const search_files = {
1062
1062
  };
1063
1063
  const send_file = {
1064
1064
  name: "send_file",
1065
- description: "Send a workspace file directly to the current peer over the P2P (PeerJS/WebRTC) data channel. Use this when the user is in a peer conversation and explicitly asks to send or transfer a file to their peer. Do NOT use this for local-browser or non-peer conversations — it only works when the active conversation is a peer: group. The file is read from the current group workspace and transferred in binary chunks so there is no size limit.",
1065
+ description: "Send a workspace file directly to connected peer(s) over the P2P (PeerJS/WebRTC) data channel. Use this when the user is in a peer conversation or room and asks to send or transfer a file. Do NOT use this for local-browser or other non-peer conversations — it only works when the active conversation is a peer or room session (peer: or room: group). The file is read from the current group workspace and transferred in binary chunks so there is no size limit.",
1066
1066
  input_schema: {
1067
1067
  type: "object",
1068
1068
  properties: { path: {
@@ -2059,4 +2059,4 @@ const TOOL_DEFINITIONS = [
2059
2059
 
2060
2060
  //#endregion
2061
2061
  export { BASIC_CATALOG_REFERENCE as i, tools_exports as n, A2UI_BASIC_CATALOG_ID as r, TOOL_DEFINITIONS as t };
2062
- //# sourceMappingURL=tools-DBaMRiEu.js.map
2062
+ //# sourceMappingURL=tools-DKzPWc0q.js.map