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-mcp-remote-CT5Q-54E.js","names":["shadowClawMcpRemoteStyles","shadowClawMcpRemoteTemplate"],"sources":["../../src/components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.ts"],"sourcesContent":["import { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb, type ShadowClawDatabase } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { encryptValue } from \"../../../security/crypto.js\";\n\nimport { reconnectMcpOAuth } from \"../../../subsystems/mcp/mcp-reconnect.js\";\nimport { testRemoteMcpConnection } from \"../../../subsystems/mcp/remote-mcp-client.js\";\n\nimport {\n bindRemoteMcpCredentialRef,\n deleteRemoteMcpConnection,\n listRemoteMcpConnections,\n upsertRemoteMcpConnection,\n} from \"../../../subsystems/mcp/mcp-connections.js\";\n\nimport { setSanitizedHtml } from \"../../../security/trusted-types.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { escapeHtml } from \"../../../utils/utils.js\";\n\nimport { GitAccount } from \"../../../subsystems/git/types.js\";\n\nimport type { ServiceAccount } from \"../../../subsystems/accounts/service-accounts.js\";\nimport type { McpConnectionTestResult } from \"../../../subsystems/mcp/remote-mcp-client.js\";\n\nimport type {\n RemoteMcpConnectionRecord,\n RemoteMcpCredentialRef,\n RemoteMcpTransport,\n} from \"../../../subsystems/mcp/mcp-connections.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\n\nimport \"../../common/shadow-claw-actions/shadow-claw-actions.js\";\nimport \"../../common/shadow-claw-card/shadow-claw-card.js\";\nimport \"../../common/shadow-claw-empty-state/shadow-claw-empty-state.js\";\nimport shadowClawMcpRemoteStyles from \"./shadow-claw-mcp-remote.css\" with { type: \"css\" };\nimport shadowClawMcpRemoteTemplate from \"./shadow-claw-mcp-remote.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-mcp-remote\";\n\ntype AuthSelection =\n | \"none\"\n | \"service_pat\"\n | \"service_oauth\"\n | \"git_pat\"\n | \"git_oauth\"\n | \"custom_header\";\n\nexport class ShadowClawMcpRemote extends ShadowClawElement {\n static styles = shadowClawMcpRemoteStyles;\n static template = shadowClawMcpRemoteTemplate;\n\n connections: RemoteMcpConnectionRecord[] = [];\n db: ShadowClawDatabase | null = null;\n editingConnectionId: string | null = null;\n gitAccounts: GitAccount[] = [];\n serviceAccounts: ServiceAccount[] = [];\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.db = await getDb();\n await this.render();\n this.bindEventListeners();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"add-connection\"]')\n ?.addEventListener(\"click\", () => this.showConnectionForm(\"new\"));\n\n root\n .querySelector('[data-region=\"connection-list\"]')\n ?.addEventListener(\"settings-action\", (event) => {\n const detail = (event as CustomEvent<{ action: string; id: string }>)\n .detail;\n const { action, id } = detail || { action: \"\", id: \"\" };\n\n if (!id) {\n return;\n }\n\n if (action === \"edit-connection\") {\n this.showConnectionForm(id);\n } else if (action === \"delete-connection\") {\n void this.deleteConnection(id);\n } else if (action === \"test-connection\") {\n void this.testConnection(id);\n }\n });\n\n root\n .querySelector('[data-region=\"connection-list\"]')\n ?.addEventListener(\"click\", (event) => {\n const target = event.target;\n if (!(target instanceof HTMLButtonElement)) {\n return;\n }\n\n const connectionId = target.dataset.reconnectConnection;\n if (connectionId) {\n void this.reconnectOAuth(connectionId);\n }\n });\n }\n\n describeCredentialRef(ref: RemoteMcpCredentialRef | null): string {\n if (!ref || ref.authType === \"none\") {\n return \"No auth\";\n }\n\n if (ref.authType === \"custom_header\") {\n return `Custom header${ref.headerName ? ` (${ref.headerName})` : \"\"}`;\n }\n\n if (ref.accountId) {\n return `Service account (${ref.authType.toUpperCase()})`;\n }\n\n if (ref.gitAccountId) {\n return `Git account (${ref.authType.toUpperCase()})`;\n }\n\n return ref.authType.toUpperCase();\n }\n\n getAuthSelectionFromCredentialRef(\n ref: RemoteMcpCredentialRef | null,\n ): AuthSelection {\n if (!ref || ref.authType === \"none\") {\n return \"none\";\n }\n\n if (ref.authType === \"custom_header\") {\n return \"custom_header\";\n }\n\n if (ref.accountId) {\n return ref.authType === \"oauth\" ? \"service_oauth\" : \"service_pat\";\n }\n\n if (ref.gitAccountId) {\n return ref.authType === \"oauth\" ? \"git_oauth\" : \"git_pat\";\n }\n\n return \"none\";\n }\n\n hideConnectionForm() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (slot) {\n slot.replaceChildren();\n }\n\n this.editingConnectionId = null;\n }\n\n isOAuthConnection(connection: RemoteMcpConnectionRecord): boolean {\n const ref = connection.credentialRef;\n if (!ref) {\n return false;\n }\n\n return ref.authType === \"oauth\" && !!(ref.accountId || ref.gitAccountId);\n }\n\n renderConnectionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const listEl = root.querySelector('[data-region=\"connection-list\"]');\n if (!listEl) {\n return;\n }\n\n listEl.replaceChildren();\n\n if (this.connections.length === 0) {\n const emptyState = document.createElement(\"shadow-claw-empty-state\");\n emptyState.setAttribute(\n \"message\",\n \"No remote MCP connections configured.\",\n );\n emptyState.setAttribute(\n \"hint\",\n \"Click '+ Add Remote MCP Connection' to get started.\",\n );\n listEl.append(emptyState);\n\n return;\n }\n\n const fragment = document.createDocumentFragment();\n\n this.connections.forEach((connection) => {\n const authLabel = this.describeCredentialRef(connection.credentialRef);\n const enabledLabel = connection.enabled ? \"Enabled\" : \"Disabled\";\n const cardMeta = `${connection.serverUrl} · ${connection.transport} · ${authLabel}`;\n\n const card = document.createElement(\"shadow-claw-card\");\n card.setAttribute(\"data-connection-id\", connection.id);\n card.setAttribute(\"label\", connection.label);\n card.setAttribute(\"meta\", cardMeta);\n card.setAttribute(\"badge\", enabledLabel);\n if (!connection.enabled) {\n card.setAttribute(\"muted\", \"\");\n }\n\n const actions = document.createElement(\"shadow-claw-actions\");\n actions.setAttribute(\"slot\", \"actions\");\n actions.setAttribute(\"kind\", \"connection\");\n actions.setAttribute(\"item-id\", connection.id);\n\n card.append(actions);\n\n const isOAuth = this.isOAuthConnection(connection);\n if (isOAuth) {\n const reconnectBtn = document.createElement(\"button\");\n reconnectBtn.className = \"reconnect-btn\";\n reconnectBtn.textContent = \"🔑 Reconnect OAuth\";\n reconnectBtn.setAttribute(\"data-reconnect-connection\", connection.id);\n card.append(reconnectBtn);\n }\n\n fragment.append(card);\n });\n\n listEl.append(fragment);\n }\n\n renderDiagnostic(container: HTMLElement, result: McpConnectionTestResult) {\n const stepsHtml = result.steps\n .map((step) => {\n const icon =\n step.status === \"ok\"\n ? \"\\u2713\"\n : step.status === \"error\"\n ? \"\\u2717\"\n : \"\\u2014\";\n const cls = `diagnostic-step diagnostic-${step.status}`;\n\n return `\n <div class=\"${cls}\">\n <span class=\"diagnostic-icon\">${icon}</span>\n <span class=\"diagnostic-label\">${escapeHtml(step.step)}</span>\n ${step.detail ? `<span class=\"diagnostic-detail\">${escapeHtml(step.detail)}</span>` : \"\"}\n </div>`;\n })\n .join(\"\");\n\n const toolsHtml =\n result.success && result.toolNames.length > 0\n ? `<details class=\"diagnostic-tools\"><summary>${result.toolCount} tool${result.toolCount === 1 ? \"\" : \"s\"} available</summary><ul>${result.toolNames.map((n) => `<li>${escapeHtml(n)}</li>`).join(\"\")}</ul></details>`\n : \"\";\n\n setSanitizedHtml(\n container,\n `\n <div class=\"diagnostic-header diagnostic-${result.success ? \"ok\" : \"error\"}\">\n ${result.success ? \"\\u2713 Connection OK\" : \"\\u2717 Connection Failed\"}\n <button class=\"diagnostic-close\" data-action=\"close-diagnostic\" title=\"Dismiss\">\\u00d7</button>\n </div>\n <div class=\"diagnostic-steps\">${stepsHtml}</div>\n ${toolsHtml}\n `,\n );\n\n container\n .querySelector('[data-action=\"close-diagnostic\"]')\n ?.addEventListener(\"click\", () => container.remove());\n }\n\n renderGitAccountOptions(selectedId?: string): string {\n if (this.gitAccounts.length === 0) {\n return '<option value=\"\">No git accounts configured</option>';\n }\n\n return this.gitAccounts\n .map((account) => {\n const selected = account.id === selectedId ? \" selected\" : \"\";\n\n return `<option value=\"${account.id}\"${selected}>${escapeHtml(account.label)} · ${escapeHtml(account.hostPattern)}</option>`;\n })\n .join(\"\");\n }\n\n renderServiceAccountOptions(selectedId?: string): string {\n if (this.serviceAccounts.length === 0) {\n return '<option value=\"\">No service accounts configured</option>';\n }\n\n return this.serviceAccounts\n .map((account) => {\n const selected = account.id === selectedId ? \" selected\" : \"\";\n\n return `<option value=\"${account.id}\"${selected}>${escapeHtml(account.label)} · ${escapeHtml(account.hostPattern)}</option>`;\n })\n .join(\"\");\n }\n\n showConnectionForm(connectionId: string) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n this.editingConnectionId = connectionId;\n const isNew = connectionId === \"new\";\n const existing = isNew\n ? null\n : this.connections.find((item) => item.id === connectionId) || null;\n\n const transport = existing?.transport || \"streamable_http\";\n const authSelection = this.getAuthSelectionFromCredentialRef(\n existing?.credentialRef || null,\n );\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (!slot) {\n return;\n }\n\n setSanitizedHtml(\n slot,\n `\n <div class=\"connection-form\">\n <h4>${isNew ? \"Add Remote MCP Connection\" : \"Edit Remote MCP Connection\"}</h4>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Connection Label</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"connection-label\"\n placeholder=\"e.g. Figma MCP, Jira MCP\"\n value=\"${escapeHtml(existing?.label || \"\")}\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Server URL</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"connection-url\"\n placeholder=\"https://mcp.example.com/rpc\"\n value=\"${escapeHtml(existing?.serverUrl || \"\")}\"\n />\n <div class=\"form-helper\">Must be an absolute http(s) URL.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Transport</label>\n <select class=\"form-input\" data-field=\"connection-transport\">\n <option value=\"streamable_http\"${transport === \"streamable_http\" ? \" selected\" : \"\"}>streamable_http</option>\n <option value=\"sse\"${transport === \"sse\" ? \" selected\" : \"\"}>sse</option>\n <option value=\"websocket\"${transport === \"websocket\" ? \" selected\" : \"\"}>websocket</option>\n </select>\n <div class=\"form-helper\">\n Current runtime support is streamable_http. Other transports can be saved for future support.\n </div>\n </div>\n\n <div class=\"form-group connection-form-row\">\n <input type=\"checkbox\" data-field=\"connection-enabled\"${existing?.enabled === false ? \"\" : \" checked\"} />\n <label class=\"form-label\">Enabled</label>\n </div>\n\n <div class=\"form-group connection-form-row\" data-region=\"auto-reconnect-region\">\n <input type=\"checkbox\" data-field=\"connection-auto-reconnect\"${existing?.autoReconnectOAuth ? \" checked\" : \"\"} />\n <label class=\"form-label\">Auto-reconnect OAuth on 401</label>\n <div class=\"form-helper\" style=\"margin-left: 0.25rem;\">When enabled, a 401 error will automatically open the OAuth popup to re-authenticate.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Authentication</label>\n <select class=\"form-input\" data-field=\"auth-selection\">\n <option value=\"none\"${authSelection === \"none\" ? \" selected\" : \"\"}>None</option>\n <option value=\"service_pat\"${authSelection === \"service_pat\" ? \" selected\" : \"\"}>Service Account (PAT)</option>\n <option value=\"service_oauth\"${authSelection === \"service_oauth\" ? \" selected\" : \"\"}>Service Account (OAuth)</option>\n <option value=\"git_pat\"${authSelection === \"git_pat\" ? \" selected\" : \"\"}>Git Account (PAT)</option>\n <option value=\"git_oauth\"${authSelection === \"git_oauth\" ? \" selected\" : \"\"}>Git Account (OAuth)</option>\n <option value=\"custom_header\"${authSelection === \"custom_header\" ? \" selected\" : \"\"}>Custom Header</option>\n </select>\n </div>\n\n <div class=\"form-group\" data-region=\"service-account-region\">\n <label class=\"form-label\">Service Account</label>\n <select class=\"form-input\" data-field=\"service-account-id\">\n ${this.renderServiceAccountOptions(existing?.credentialRef?.accountId)}\n </select>\n </div>\n\n <div class=\"form-group\" data-region=\"git-account-region\">\n <label class=\"form-label\">Git Account</label>\n <select class=\"form-input\" data-field=\"git-account-id\">\n ${this.renderGitAccountOptions(existing?.credentialRef?.gitAccountId)}\n </select>\n </div>\n\n <div data-region=\"custom-header-region\">\n <div class=\"form-group\">\n <label class=\"form-label\">Header Name</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"custom-header-name\"\n placeholder=\"e.g. Authorization or X-API-Key\"\n value=\"${escapeHtml(existing?.credentialRef?.headerName || \"\")}\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Header Value</label>\n <input\n type=\"password\"\n class=\"form-input\"\n data-field=\"custom-header-value\"\n placeholder=\"${existing?.credentialRef?.authType === \"custom_header\" ? \"•••••••••••• (Saved)\" : \"Enter secret value\"}\"\n />\n <div class=\"auth-note\">Stored encrypted locally. Leave blank to keep existing value.</div>\n </div>\n </div>\n\n <div class=\"connection-form-actions\">\n <button class=\"confirm-btn\" data-action=\"save-connection\">\n ${isNew ? \"Add Connection\" : \"Update Connection\"}\n </button>\n <button class=\"cancel-btn\" data-action=\"cancel-connection-form\">Cancel</button>\n </div>\n </div>\n `,\n );\n\n slot\n .querySelector('[data-action=\"save-connection\"]')\n ?.addEventListener(\"click\", () => void this.saveConnectionForm());\n slot\n .querySelector('[data-action=\"cancel-connection-form\"]')\n ?.addEventListener(\"click\", () => this.hideConnectionForm());\n slot\n .querySelector('[data-field=\"auth-selection\"]')\n ?.addEventListener(\"change\", () => this.updateAuthFieldsVisibility(slot));\n\n this.updateAuthFieldsVisibility(slot);\n }\n\n updateAuthFieldsVisibility(slot: Element) {\n const authSelection = (\n slot.querySelector('[data-field=\"auth-selection\"]') as HTMLSelectElement\n )?.value as AuthSelection;\n\n const serviceRegion = slot.querySelector(\n '[data-region=\"service-account-region\"]',\n );\n\n const gitRegion = slot.querySelector('[data-region=\"git-account-region\"]');\n const customHeaderRegion = slot.querySelector(\n '[data-region=\"custom-header-region\"]',\n );\n\n const autoReconnectRegion = slot.querySelector(\n '[data-region=\"auto-reconnect-region\"]',\n );\n\n const showService =\n authSelection === \"service_pat\" || authSelection === \"service_oauth\";\n const showGit =\n authSelection === \"git_pat\" || authSelection === \"git_oauth\";\n const showCustom = authSelection === \"custom_header\";\n const showAutoReconnect =\n authSelection === \"service_oauth\" || authSelection === \"git_oauth\";\n\n if (serviceRegion instanceof HTMLElement) {\n serviceRegion.style.display = showService ? \"block\" : \"none\";\n }\n\n if (gitRegion instanceof HTMLElement) {\n gitRegion.style.display = showGit ? \"block\" : \"none\";\n }\n\n if (customHeaderRegion instanceof HTMLElement) {\n customHeaderRegion.style.display = showCustom ? \"block\" : \"none\";\n }\n\n if (autoReconnectRegion instanceof HTMLElement) {\n autoReconnectRegion.style.display = showAutoReconnect ? \"flex\" : \"none\";\n }\n }\n\n async buildCredentialRef(\n slot: Element,\n authSelection: AuthSelection,\n existing: RemoteMcpConnectionRecord | null,\n ): Promise<RemoteMcpCredentialRef | null> {\n if (authSelection === \"none\") {\n return null;\n }\n\n if (authSelection === \"service_pat\" || authSelection === \"service_oauth\") {\n const accountId = (\n slot.querySelector(\n '[data-field=\"service-account-id\"]',\n ) as HTMLSelectElement\n )?.value;\n if (!accountId) {\n throw new Error(\n \"Select a service account for this authentication mode.\",\n );\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: authSelection === \"service_oauth\" ? \"oauth\" : \"token\",\n providerId: \"custom_mcp\",\n accountId,\n };\n }\n\n if (authSelection === \"git_pat\" || authSelection === \"git_oauth\") {\n const gitAccountId = (\n slot.querySelector('[data-field=\"git-account-id\"]') as HTMLSelectElement\n )?.value;\n if (!gitAccountId) {\n throw new Error(\"Select a git account for this authentication mode.\");\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: authSelection === \"git_oauth\" ? \"oauth\" : \"token\",\n providerId: \"custom_mcp\",\n gitAccountId,\n };\n }\n\n const headerName = (\n slot.querySelector(\n '[data-field=\"custom-header-name\"]',\n ) as HTMLInputElement\n )?.value.trim();\n const headerValueRaw = (\n slot.querySelector(\n '[data-field=\"custom-header-value\"]',\n ) as HTMLInputElement\n )?.value.trim();\n\n if (!headerName) {\n throw new Error(\n \"Header name is required for custom header authentication.\",\n );\n }\n\n let encryptedValue: string | undefined;\n if (headerValueRaw) {\n encryptedValue = (await encryptValue(headerValueRaw)) || undefined;\n }\n\n if (!encryptedValue) {\n if (\n existing?.credentialRef?.authType === \"custom_header\" &&\n existing.credentialRef.encryptedValue\n ) {\n encryptedValue = existing.credentialRef.encryptedValue;\n } else {\n throw new Error(\n \"Header value is required for custom header authentication.\",\n );\n }\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: \"custom_header\",\n providerId: \"custom_mcp\",\n headerName,\n encryptedValue,\n };\n }\n\n async deleteConnection(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n try {\n const deleted = await deleteRemoteMcpConnection(this.db, connectionId);\n if (!deleted) {\n showError(\"Remote MCP connection not found.\", 4000);\n\n return;\n }\n\n await this.render();\n if (this.editingConnectionId === connectionId) {\n this.hideConnectionForm();\n }\n\n showSuccess(\"Remote MCP connection deleted\", 3000);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n showError(`Failed to delete remote MCP connection: ${message}`, 6000);\n }\n }\n\n async reconnectOAuth(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n const connection = this.connections.find(\n (item) => item.id === connectionId,\n );\n\n const label = connection?.label || connectionId;\n\n const result = await reconnectMcpOAuth(this.db, connectionId);\n\n if (result.success) {\n showSuccess(`OAuth reconnected for \"${label}\"`, 4000);\n } else {\n showError(`OAuth reconnect failed: ${result.error}`, 6000);\n }\n }\n\n async render() {\n const root = this.shadowRoot;\n if (!root || !this.db) {\n return;\n }\n\n try {\n this.connections = await listRemoteMcpConnections(this.db);\n const serviceRaw = await getConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS);\n this.serviceAccounts = Array.isArray(serviceRaw) ? serviceRaw : [];\n const gitRaw = await getConfig(this.db, CONFIG_KEYS.GIT_ACCOUNTS);\n this.gitAccounts = Array.isArray(gitRaw) ? gitRaw : [];\n\n this.renderConnectionList();\n } catch (err) {\n console.warn(\"Could not load remote MCP connections:\", err);\n }\n }\n\n async saveConnectionForm() {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (!slot) {\n return;\n }\n\n const label = (\n slot.querySelector('[data-field=\"connection-label\"]') as HTMLInputElement\n )?.value.trim();\n const serverUrl = (\n slot.querySelector('[data-field=\"connection-url\"]') as HTMLInputElement\n )?.value.trim();\n const transport = (\n slot.querySelector(\n '[data-field=\"connection-transport\"]',\n ) as HTMLSelectElement\n )?.value as RemoteMcpTransport;\n const enabled = (\n slot.querySelector(\n '[data-field=\"connection-enabled\"]',\n ) as HTMLInputElement\n )?.checked;\n const autoReconnectOAuth = (\n slot.querySelector(\n '[data-field=\"connection-auto-reconnect\"]',\n ) as HTMLInputElement\n )?.checked;\n const authSelection = (\n slot.querySelector('[data-field=\"auth-selection\"]') as HTMLSelectElement\n )?.value as AuthSelection;\n\n if (!label || !serverUrl) {\n showError(\"Connection label and server URL are required.\", 4000);\n\n return;\n }\n\n const isNew = this.editingConnectionId === \"new\";\n const existing = isNew\n ? null\n : this.connections.find((item) => item.id === this.editingConnectionId) ||\n null;\n\n try {\n const connection = await upsertRemoteMcpConnection(this.db, {\n id: isNew ? undefined : existing?.id,\n label,\n serviceType: \"mcp_remote\",\n serverUrl,\n transport,\n enabled,\n autoReconnectOAuth,\n });\n\n const credentialRef = await this.buildCredentialRef(\n slot,\n authSelection,\n existing,\n );\n\n await bindRemoteMcpCredentialRef(this.db, connection.id, credentialRef);\n await this.render();\n this.hideConnectionForm();\n\n showSuccess(\n isNew ? \"Remote MCP connection added\" : \"Remote MCP connection updated\",\n 3000,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n showError(`Failed to save remote MCP connection: ${message}`, 6000);\n }\n }\n\n async testConnection(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Show loading state in the card\n const card = root.querySelector(\n `.connection-card[data-connection-id=\"${connectionId}\"]`,\n );\n\n const existingDiag = card?.querySelector(\".connection-diagnostic\");\n if (existingDiag) {\n existingDiag.remove();\n }\n\n const diagEl = document.createElement(\"div\");\n diagEl.className = \"connection-diagnostic\";\n const loadingEl = document.createElement(\"div\");\n loadingEl.className = \"diagnostic-loading\";\n loadingEl.textContent = \"Testing connection…\";\n diagEl.appendChild(loadingEl);\n card?.appendChild(diagEl);\n\n const result = await testRemoteMcpConnection(this.db, connectionId);\n this.renderDiagnostic(diagEl, result);\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawMcpRemote);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shadow-claw-mcp-remote-BLxs_Z4I.js","names":["shadowClawMcpRemoteStyles","shadowClawMcpRemoteTemplate"],"sources":["../../src/components/settings/shadow-claw-mcp-remote/shadow-claw-mcp-remote.ts"],"sourcesContent":["import { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb, type ShadowClawDatabase } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { encryptValue } from \"../../../security/crypto.js\";\n\nimport { reconnectMcpOAuth } from \"../../../subsystems/mcp/mcp-reconnect.js\";\nimport { testRemoteMcpConnection } from \"../../../subsystems/mcp/remote-mcp-client.js\";\n\nimport {\n bindRemoteMcpCredentialRef,\n deleteRemoteMcpConnection,\n listRemoteMcpConnections,\n upsertRemoteMcpConnection,\n} from \"../../../subsystems/mcp/mcp-connections.js\";\n\nimport { setSanitizedHtml } from \"../../../security/trusted-types.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { escapeHtml } from \"../../../utils/utils.js\";\n\nimport { GitAccount } from \"../../../subsystems/git/types.js\";\n\nimport type { ServiceAccount } from \"../../../subsystems/accounts/service-accounts.js\";\nimport type { McpConnectionTestResult } from \"../../../subsystems/mcp/remote-mcp-client.js\";\n\nimport type {\n RemoteMcpConnectionRecord,\n RemoteMcpCredentialRef,\n RemoteMcpTransport,\n} from \"../../../subsystems/mcp/mcp-connections.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\n\nimport \"../../common/shadow-claw-actions/shadow-claw-actions.js\";\nimport \"../../common/shadow-claw-card/shadow-claw-card.js\";\nimport \"../../common/shadow-claw-empty-state/shadow-claw-empty-state.js\";\nimport shadowClawMcpRemoteStyles from \"./shadow-claw-mcp-remote.css\" with { type: \"css\" };\nimport shadowClawMcpRemoteTemplate from \"./shadow-claw-mcp-remote.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-mcp-remote\";\n\ntype AuthSelection =\n | \"none\"\n | \"service_pat\"\n | \"service_oauth\"\n | \"git_pat\"\n | \"git_oauth\"\n | \"custom_header\";\n\nexport class ShadowClawMcpRemote extends ShadowClawElement {\n static styles = shadowClawMcpRemoteStyles;\n static template = shadowClawMcpRemoteTemplate;\n\n connections: RemoteMcpConnectionRecord[] = [];\n db: ShadowClawDatabase | null = null;\n editingConnectionId: string | null = null;\n gitAccounts: GitAccount[] = [];\n serviceAccounts: ServiceAccount[] = [];\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.db = await getDb();\n await this.render();\n this.bindEventListeners();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"add-connection\"]')\n ?.addEventListener(\"click\", () => this.showConnectionForm(\"new\"));\n\n root\n .querySelector('[data-region=\"connection-list\"]')\n ?.addEventListener(\"settings-action\", (event) => {\n const detail = (event as CustomEvent<{ action: string; id: string }>)\n .detail;\n const { action, id } = detail || { action: \"\", id: \"\" };\n\n if (!id) {\n return;\n }\n\n if (action === \"edit-connection\") {\n this.showConnectionForm(id);\n } else if (action === \"delete-connection\") {\n void this.deleteConnection(id);\n } else if (action === \"test-connection\") {\n void this.testConnection(id);\n }\n });\n\n root\n .querySelector('[data-region=\"connection-list\"]')\n ?.addEventListener(\"click\", (event) => {\n const target = event.target;\n if (!(target instanceof HTMLButtonElement)) {\n return;\n }\n\n const connectionId = target.dataset.reconnectConnection;\n if (connectionId) {\n void this.reconnectOAuth(connectionId);\n }\n });\n }\n\n describeCredentialRef(ref: RemoteMcpCredentialRef | null): string {\n if (!ref || ref.authType === \"none\") {\n return \"No auth\";\n }\n\n if (ref.authType === \"custom_header\") {\n return `Custom header${ref.headerName ? ` (${ref.headerName})` : \"\"}`;\n }\n\n if (ref.accountId) {\n return `Service account (${ref.authType.toUpperCase()})`;\n }\n\n if (ref.gitAccountId) {\n return `Git account (${ref.authType.toUpperCase()})`;\n }\n\n return ref.authType.toUpperCase();\n }\n\n getAuthSelectionFromCredentialRef(\n ref: RemoteMcpCredentialRef | null,\n ): AuthSelection {\n if (!ref || ref.authType === \"none\") {\n return \"none\";\n }\n\n if (ref.authType === \"custom_header\") {\n return \"custom_header\";\n }\n\n if (ref.accountId) {\n return ref.authType === \"oauth\" ? \"service_oauth\" : \"service_pat\";\n }\n\n if (ref.gitAccountId) {\n return ref.authType === \"oauth\" ? \"git_oauth\" : \"git_pat\";\n }\n\n return \"none\";\n }\n\n hideConnectionForm() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (slot) {\n slot.replaceChildren();\n }\n\n this.editingConnectionId = null;\n }\n\n isOAuthConnection(connection: RemoteMcpConnectionRecord): boolean {\n const ref = connection.credentialRef;\n if (!ref) {\n return false;\n }\n\n return ref.authType === \"oauth\" && !!(ref.accountId || ref.gitAccountId);\n }\n\n renderConnectionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const listEl = root.querySelector('[data-region=\"connection-list\"]');\n if (!listEl) {\n return;\n }\n\n listEl.replaceChildren();\n\n if (this.connections.length === 0) {\n const emptyState = document.createElement(\"shadow-claw-empty-state\");\n emptyState.setAttribute(\n \"message\",\n \"No remote MCP connections configured.\",\n );\n emptyState.setAttribute(\n \"hint\",\n \"Click '+ Add Remote MCP Connection' to get started.\",\n );\n listEl.append(emptyState);\n\n return;\n }\n\n const fragment = document.createDocumentFragment();\n\n this.connections.forEach((connection) => {\n const authLabel = this.describeCredentialRef(connection.credentialRef);\n const enabledLabel = connection.enabled ? \"Enabled\" : \"Disabled\";\n const cardMeta = `${connection.serverUrl} · ${connection.transport} · ${authLabel}`;\n\n const card = document.createElement(\"shadow-claw-card\");\n card.setAttribute(\"data-connection-id\", connection.id);\n card.setAttribute(\"label\", connection.label);\n card.setAttribute(\"meta\", cardMeta);\n card.setAttribute(\"badge\", enabledLabel);\n if (!connection.enabled) {\n card.setAttribute(\"muted\", \"\");\n }\n\n const actions = document.createElement(\"shadow-claw-actions\");\n actions.setAttribute(\"slot\", \"actions\");\n actions.setAttribute(\"kind\", \"connection\");\n actions.setAttribute(\"item-id\", connection.id);\n\n card.append(actions);\n\n const isOAuth = this.isOAuthConnection(connection);\n if (isOAuth) {\n const reconnectBtn = document.createElement(\"button\");\n reconnectBtn.className = \"reconnect-btn\";\n reconnectBtn.textContent = \"🔑 Reconnect OAuth\";\n reconnectBtn.setAttribute(\"data-reconnect-connection\", connection.id);\n card.append(reconnectBtn);\n }\n\n fragment.append(card);\n });\n\n listEl.append(fragment);\n }\n\n renderDiagnostic(container: HTMLElement, result: McpConnectionTestResult) {\n const stepsHtml = result.steps\n .map((step) => {\n const icon =\n step.status === \"ok\"\n ? \"\\u2713\"\n : step.status === \"error\"\n ? \"\\u2717\"\n : \"\\u2014\";\n const cls = `diagnostic-step diagnostic-${step.status}`;\n\n return `\n <div class=\"${cls}\">\n <span class=\"diagnostic-icon\">${icon}</span>\n <span class=\"diagnostic-label\">${escapeHtml(step.step)}</span>\n ${step.detail ? `<span class=\"diagnostic-detail\">${escapeHtml(step.detail)}</span>` : \"\"}\n </div>`;\n })\n .join(\"\");\n\n const toolsHtml =\n result.success && result.toolNames.length > 0\n ? `<details class=\"diagnostic-tools\"><summary>${result.toolCount} tool${result.toolCount === 1 ? \"\" : \"s\"} available</summary><ul>${result.toolNames.map((n) => `<li>${escapeHtml(n)}</li>`).join(\"\")}</ul></details>`\n : \"\";\n\n setSanitizedHtml(\n container,\n `\n <div class=\"diagnostic-header diagnostic-${result.success ? \"ok\" : \"error\"}\">\n ${result.success ? \"\\u2713 Connection OK\" : \"\\u2717 Connection Failed\"}\n <button class=\"diagnostic-close\" data-action=\"close-diagnostic\" title=\"Dismiss\">\\u00d7</button>\n </div>\n <div class=\"diagnostic-steps\">${stepsHtml}</div>\n ${toolsHtml}\n `,\n );\n\n container\n .querySelector('[data-action=\"close-diagnostic\"]')\n ?.addEventListener(\"click\", () => container.remove());\n }\n\n renderGitAccountOptions(selectedId?: string): string {\n if (this.gitAccounts.length === 0) {\n return '<option value=\"\">No git accounts configured</option>';\n }\n\n return this.gitAccounts\n .map((account) => {\n const selected = account.id === selectedId ? \" selected\" : \"\";\n\n return `<option value=\"${account.id}\"${selected}>${escapeHtml(account.label)} · ${escapeHtml(account.hostPattern)}</option>`;\n })\n .join(\"\");\n }\n\n renderServiceAccountOptions(selectedId?: string): string {\n if (this.serviceAccounts.length === 0) {\n return '<option value=\"\">No service accounts configured</option>';\n }\n\n return this.serviceAccounts\n .map((account) => {\n const selected = account.id === selectedId ? \" selected\" : \"\";\n\n return `<option value=\"${account.id}\"${selected}>${escapeHtml(account.label)} · ${escapeHtml(account.hostPattern)}</option>`;\n })\n .join(\"\");\n }\n\n showConnectionForm(connectionId: string) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n this.editingConnectionId = connectionId;\n const isNew = connectionId === \"new\";\n const existing = isNew\n ? null\n : this.connections.find((item) => item.id === connectionId) || null;\n\n const transport = existing?.transport || \"streamable_http\";\n const authSelection = this.getAuthSelectionFromCredentialRef(\n existing?.credentialRef || null,\n );\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (!slot) {\n return;\n }\n\n setSanitizedHtml(\n slot,\n `\n <div class=\"connection-form\">\n <h4>${isNew ? \"Add Remote MCP Connection\" : \"Edit Remote MCP Connection\"}</h4>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Connection Label</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"connection-label\"\n placeholder=\"e.g. Figma MCP, Jira MCP\"\n value=\"${escapeHtml(existing?.label || \"\")}\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Server URL</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"connection-url\"\n placeholder=\"https://mcp.example.com/rpc\"\n value=\"${escapeHtml(existing?.serverUrl || \"\")}\"\n />\n <div class=\"form-helper\">Must be an absolute http(s) URL.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Transport</label>\n <select class=\"form-input\" data-field=\"connection-transport\">\n <option value=\"streamable_http\"${transport === \"streamable_http\" ? \" selected\" : \"\"}>streamable_http</option>\n <option value=\"sse\"${transport === \"sse\" ? \" selected\" : \"\"}>sse</option>\n <option value=\"websocket\"${transport === \"websocket\" ? \" selected\" : \"\"}>websocket</option>\n </select>\n <div class=\"form-helper\">\n Current runtime support is streamable_http. Other transports can be saved for future support.\n </div>\n </div>\n\n <div class=\"form-group connection-form-row\">\n <input type=\"checkbox\" data-field=\"connection-enabled\"${existing?.enabled === false ? \"\" : \" checked\"} />\n <label class=\"form-label\">Enabled</label>\n </div>\n\n <div class=\"form-group connection-form-row\" data-region=\"auto-reconnect-region\">\n <input type=\"checkbox\" data-field=\"connection-auto-reconnect\"${existing?.autoReconnectOAuth ? \" checked\" : \"\"} />\n <label class=\"form-label\">Auto-reconnect OAuth on 401</label>\n <div class=\"form-helper\" style=\"margin-left: 0.25rem;\">When enabled, a 401 error will automatically open the OAuth popup to re-authenticate.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Authentication</label>\n <select class=\"form-input\" data-field=\"auth-selection\">\n <option value=\"none\"${authSelection === \"none\" ? \" selected\" : \"\"}>None</option>\n <option value=\"service_pat\"${authSelection === \"service_pat\" ? \" selected\" : \"\"}>Service Account (PAT)</option>\n <option value=\"service_oauth\"${authSelection === \"service_oauth\" ? \" selected\" : \"\"}>Service Account (OAuth)</option>\n <option value=\"git_pat\"${authSelection === \"git_pat\" ? \" selected\" : \"\"}>Git Account (PAT)</option>\n <option value=\"git_oauth\"${authSelection === \"git_oauth\" ? \" selected\" : \"\"}>Git Account (OAuth)</option>\n <option value=\"custom_header\"${authSelection === \"custom_header\" ? \" selected\" : \"\"}>Custom Header</option>\n </select>\n </div>\n\n <div class=\"form-group\" data-region=\"service-account-region\">\n <label class=\"form-label\">Service Account</label>\n <select class=\"form-input\" data-field=\"service-account-id\">\n ${this.renderServiceAccountOptions(existing?.credentialRef?.accountId)}\n </select>\n </div>\n\n <div class=\"form-group\" data-region=\"git-account-region\">\n <label class=\"form-label\">Git Account</label>\n <select class=\"form-input\" data-field=\"git-account-id\">\n ${this.renderGitAccountOptions(existing?.credentialRef?.gitAccountId)}\n </select>\n </div>\n\n <div data-region=\"custom-header-region\">\n <div class=\"form-group\">\n <label class=\"form-label\">Header Name</label>\n <input\n type=\"text\"\n class=\"form-input\"\n data-field=\"custom-header-name\"\n placeholder=\"e.g. Authorization or X-API-Key\"\n value=\"${escapeHtml(existing?.credentialRef?.headerName || \"\")}\"\n />\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Header Value</label>\n <input\n type=\"password\"\n class=\"form-input\"\n data-field=\"custom-header-value\"\n placeholder=\"${existing?.credentialRef?.authType === \"custom_header\" ? \"•••••••••••• (Saved)\" : \"Enter secret value\"}\"\n />\n <div class=\"auth-note\">Stored encrypted locally. Leave blank to keep existing value.</div>\n </div>\n </div>\n\n <div class=\"connection-form-actions\">\n <button class=\"confirm-btn\" data-action=\"save-connection\">\n ${isNew ? \"Add Connection\" : \"Update Connection\"}\n </button>\n <button class=\"cancel-btn\" data-action=\"cancel-connection-form\">Cancel</button>\n </div>\n </div>\n `,\n );\n\n slot\n .querySelector('[data-action=\"save-connection\"]')\n ?.addEventListener(\"click\", () => void this.saveConnectionForm());\n slot\n .querySelector('[data-action=\"cancel-connection-form\"]')\n ?.addEventListener(\"click\", () => this.hideConnectionForm());\n slot\n .querySelector('[data-field=\"auth-selection\"]')\n ?.addEventListener(\"change\", () => this.updateAuthFieldsVisibility(slot));\n\n this.updateAuthFieldsVisibility(slot);\n }\n\n updateAuthFieldsVisibility(slot: Element) {\n const authSelection = (\n slot.querySelector('[data-field=\"auth-selection\"]') as HTMLSelectElement\n )?.value as AuthSelection;\n\n const serviceRegion = slot.querySelector(\n '[data-region=\"service-account-region\"]',\n );\n\n const gitRegion = slot.querySelector('[data-region=\"git-account-region\"]');\n const customHeaderRegion = slot.querySelector(\n '[data-region=\"custom-header-region\"]',\n );\n\n const autoReconnectRegion = slot.querySelector(\n '[data-region=\"auto-reconnect-region\"]',\n );\n\n const showService =\n authSelection === \"service_pat\" || authSelection === \"service_oauth\";\n const showGit =\n authSelection === \"git_pat\" || authSelection === \"git_oauth\";\n const showCustom = authSelection === \"custom_header\";\n const showAutoReconnect =\n authSelection === \"service_oauth\" || authSelection === \"git_oauth\";\n\n if (serviceRegion instanceof HTMLElement) {\n serviceRegion.style.display = showService ? \"block\" : \"none\";\n }\n\n if (gitRegion instanceof HTMLElement) {\n gitRegion.style.display = showGit ? \"block\" : \"none\";\n }\n\n if (customHeaderRegion instanceof HTMLElement) {\n customHeaderRegion.style.display = showCustom ? \"block\" : \"none\";\n }\n\n if (autoReconnectRegion instanceof HTMLElement) {\n autoReconnectRegion.style.display = showAutoReconnect ? \"flex\" : \"none\";\n }\n }\n\n async buildCredentialRef(\n slot: Element,\n authSelection: AuthSelection,\n existing: RemoteMcpConnectionRecord | null,\n ): Promise<RemoteMcpCredentialRef | null> {\n if (authSelection === \"none\") {\n return null;\n }\n\n if (authSelection === \"service_pat\" || authSelection === \"service_oauth\") {\n const accountId = (\n slot.querySelector(\n '[data-field=\"service-account-id\"]',\n ) as HTMLSelectElement\n )?.value;\n if (!accountId) {\n throw new Error(\n \"Select a service account for this authentication mode.\",\n );\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: authSelection === \"service_oauth\" ? \"oauth\" : \"token\",\n providerId: \"custom_mcp\",\n accountId,\n };\n }\n\n if (authSelection === \"git_pat\" || authSelection === \"git_oauth\") {\n const gitAccountId = (\n slot.querySelector('[data-field=\"git-account-id\"]') as HTMLSelectElement\n )?.value;\n if (!gitAccountId) {\n throw new Error(\"Select a git account for this authentication mode.\");\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: authSelection === \"git_oauth\" ? \"oauth\" : \"token\",\n providerId: \"custom_mcp\",\n gitAccountId,\n };\n }\n\n const headerName = (\n slot.querySelector(\n '[data-field=\"custom-header-name\"]',\n ) as HTMLInputElement\n )?.value.trim();\n const headerValueRaw = (\n slot.querySelector(\n '[data-field=\"custom-header-value\"]',\n ) as HTMLInputElement\n )?.value.trim();\n\n if (!headerName) {\n throw new Error(\n \"Header name is required for custom header authentication.\",\n );\n }\n\n let encryptedValue: string | undefined;\n if (headerValueRaw) {\n encryptedValue = (await encryptValue(headerValueRaw)) || undefined;\n }\n\n if (!encryptedValue) {\n if (\n existing?.credentialRef?.authType === \"custom_header\" &&\n existing.credentialRef.encryptedValue\n ) {\n encryptedValue = existing.credentialRef.encryptedValue;\n } else {\n throw new Error(\n \"Header value is required for custom header authentication.\",\n );\n }\n }\n\n return {\n serviceType: \"mcp_remote\",\n authType: \"custom_header\",\n providerId: \"custom_mcp\",\n headerName,\n encryptedValue,\n };\n }\n\n async deleteConnection(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n try {\n const deleted = await deleteRemoteMcpConnection(this.db, connectionId);\n if (!deleted) {\n showError(\"Remote MCP connection not found.\", 4000);\n\n return;\n }\n\n await this.render();\n if (this.editingConnectionId === connectionId) {\n this.hideConnectionForm();\n }\n\n showSuccess(\"Remote MCP connection deleted\", 3000);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n showError(`Failed to delete remote MCP connection: ${message}`, 6000);\n }\n }\n\n async reconnectOAuth(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n const connection = this.connections.find(\n (item) => item.id === connectionId,\n );\n\n const label = connection?.label || connectionId;\n\n const result = await reconnectMcpOAuth(this.db, connectionId);\n\n if (result.success) {\n showSuccess(`OAuth reconnected for \"${label}\"`, 4000);\n } else {\n showError(`OAuth reconnect failed: ${result.error}`, 6000);\n }\n }\n\n async render() {\n const root = this.shadowRoot;\n if (!root || !this.db) {\n return;\n }\n\n try {\n this.connections = await listRemoteMcpConnections(this.db);\n const serviceRaw = await getConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS);\n this.serviceAccounts = Array.isArray(serviceRaw) ? serviceRaw : [];\n const gitRaw = await getConfig(this.db, CONFIG_KEYS.GIT_ACCOUNTS);\n this.gitAccounts = Array.isArray(gitRaw) ? gitRaw : [];\n\n this.renderConnectionList();\n } catch (err) {\n console.warn(\"Could not load remote MCP connections:\", err);\n }\n }\n\n async saveConnectionForm() {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form-slot\"]');\n if (!slot) {\n return;\n }\n\n const label = (\n slot.querySelector('[data-field=\"connection-label\"]') as HTMLInputElement\n )?.value.trim();\n const serverUrl = (\n slot.querySelector('[data-field=\"connection-url\"]') as HTMLInputElement\n )?.value.trim();\n const transport = (\n slot.querySelector(\n '[data-field=\"connection-transport\"]',\n ) as HTMLSelectElement\n )?.value as RemoteMcpTransport;\n const enabled = (\n slot.querySelector(\n '[data-field=\"connection-enabled\"]',\n ) as HTMLInputElement\n )?.checked;\n const autoReconnectOAuth = (\n slot.querySelector(\n '[data-field=\"connection-auto-reconnect\"]',\n ) as HTMLInputElement\n )?.checked;\n const authSelection = (\n slot.querySelector('[data-field=\"auth-selection\"]') as HTMLSelectElement\n )?.value as AuthSelection;\n\n if (!label || !serverUrl) {\n showError(\"Connection label and server URL are required.\", 4000);\n\n return;\n }\n\n const isNew = this.editingConnectionId === \"new\";\n const existing = isNew\n ? null\n : this.connections.find((item) => item.id === this.editingConnectionId) ||\n null;\n\n try {\n const connection = await upsertRemoteMcpConnection(this.db, {\n id: isNew ? undefined : existing?.id,\n label,\n serviceType: \"mcp_remote\",\n serverUrl,\n transport,\n enabled,\n autoReconnectOAuth,\n });\n\n const credentialRef = await this.buildCredentialRef(\n slot,\n authSelection,\n existing,\n );\n\n await bindRemoteMcpCredentialRef(this.db, connection.id, credentialRef);\n await this.render();\n this.hideConnectionForm();\n\n showSuccess(\n isNew ? \"Remote MCP connection added\" : \"Remote MCP connection updated\",\n 3000,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n showError(`Failed to save remote MCP connection: ${message}`, 6000);\n }\n }\n\n async testConnection(connectionId: string) {\n if (!this.db) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Show loading state in the card\n const card = root.querySelector(\n `.connection-card[data-connection-id=\"${connectionId}\"]`,\n );\n\n const existingDiag = card?.querySelector(\".connection-diagnostic\");\n if (existingDiag) {\n existingDiag.remove();\n }\n\n const diagEl = document.createElement(\"div\");\n diagEl.className = \"connection-diagnostic\";\n const loadingEl = document.createElement(\"div\");\n loadingEl.className = \"diagnostic-loading\";\n loadingEl.textContent = \"Testing connection…\";\n diagEl.appendChild(loadingEl);\n card?.appendChild(diagEl);\n\n const result = await testRemoteMcpConnection(this.db, connectionId);\n this.renderDiagnostic(diagEl, result);\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawMcpRemote);\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { n as getDb } from "./txPromise-CuGh-TGK.js";
3
- import { _ as setUseProxy, t as orchestratorStore, u as setProxyUrl } from "./orchestrator-ClXbJ4Mb.js";
3
+ import { _ as setUseProxy, t as orchestratorStore, u as setProxyUrl } from "./orchestrator-C6dc-2OQ.js";
4
4
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-DZ6r7_YI.js";
5
5
  import { t as effect } from "./effect-DL6j9HJp.js";
6
6
 
@@ -233,4 +233,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
233
233
 
234
234
  //#endregion
235
235
  export { ShadowClawNetworking as t };
236
- //# sourceMappingURL=shadow-claw-networking-dpYvfchh.js.map
236
+ //# sourceMappingURL=shadow-claw-networking-BYt-kMSI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-networking-dpYvfchh.js","names":["shadowClawNetworkingStyles","shadowClawNetworkingTemplate"],"sources":["../../src/components/settings/shadow-claw-networking/shadow-claw-networking.ts"],"sourcesContent":["import { effect } from \"../../../core/effect.js\";\n\nimport {\n setProxyUrl,\n setUseProxy,\n} from \"../../../core/orchestrator/utils/settings.js\";\n\nimport { getDb } from \"../../../db/db.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 shadowClawNetworkingStyles from \"./shadow-claw-networking.css\" with { type: \"css\" };\nimport shadowClawNetworkingTemplate from \"./shadow-claw-networking.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-networking\";\n\n/**\n * Settings sub-component for network proxy configuration.\n */\nexport class ShadowClawNetworking extends ShadowClawElement {\n static styles = shadowClawNetworkingStyles;\n static template = shadowClawNetworkingTemplate;\n\n db: ShadowClawDatabase | null;\n orchestrator: Orchestrator | null;\n\n constructor() {\n super();\n\n this.db = null;\n this.orchestrator = null;\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n this.db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n\n this.bindEventListeners();\n this.setupEffects();\n await this.render();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-setting=\"proxy-toggle\"]')\n ?.addEventListener(\"change\", (e) => {\n if (e.target instanceof HTMLInputElement) {\n void this.onProxyToggle(e.target.checked);\n }\n });\n\n root\n .querySelector('[data-action=\"save-proxy-url\"]')\n ?.addEventListener(\"click\", () => {\n void this.saveProxyUrl();\n });\n }\n\n setupEffects() {\n effect(() => {\n if (orchestratorStore.ready) {\n this.orchestrator = orchestratorStore.orchestrator;\n this.render();\n }\n });\n }\n\n async onProxyToggle(enabled: boolean) {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n try {\n await setUseProxy(this.orchestrator, this.db, enabled);\n showSuccess(enabled ? \"CORS Proxy enabled\" : \"CORS Proxy disabled\", 2500);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving proxy setting: \" + errorMsg, 6000);\n }\n }\n\n async render() {\n if (!this.orchestrator) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const proxyToggle = root.querySelector(\n '[data-setting=\"proxy-toggle\"]',\n ) as HTMLInputElement | null;\n if (proxyToggle) {\n proxyToggle.checked = this.orchestrator.useProxy;\n }\n\n const proxyUrlInput = root.querySelector(\n '[data-setting=\"proxy-url-input\"]',\n ) as HTMLInputElement | null;\n if (proxyUrlInput) {\n proxyUrlInput.value = this.orchestrator.proxyUrl;\n }\n }\n\n async saveProxyUrl() {\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=\"proxy-url-input\"]',\n ) as HTMLInputElement | null;\n if (!input) {\n return;\n }\n\n const url = input.value.trim();\n if (!url) {\n showWarning(\"Please enter a proxy URL (e.g. /proxy)\", 3000);\n\n return;\n }\n\n try {\n await setProxyUrl(this.orchestrator, this.db, url);\n showSuccess(\"Proxy URL saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving proxy URL: \" + errorMsg, 6000);\n }\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawNetworking);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAM,cAAc;;;;AAKpB,IAAa,uBAAb,cAA0C,kBAAkB;CAC1D,OAAO,SAASA;CAChB,OAAO,WAAWC;CAElB;CACA;CAEA,cAAc;EACZ,MAAM;EAEN,KAAK,KAAK;EACV,KAAK,eAAe;CACtB;CAEA,MAAM,oBAAoB;EAExB,IAAI,CADS,KAAK,YAEhB,MAAM,IAAI,MAAM,sBAAsB;EAGxC,KAAK,KAAK,MAAM,MAAM;EACtB,KAAK,eAAe,kBAAkB;EAEtC,KAAK,mBAAmB;EACxB,KAAK,aAAa;EAClB,MAAM,KAAK,OAAO;CACpB;CAEA,qBAAqB;EACnB,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,KACG,cAAc,iCAA+B,CAAC,EAC7C,iBAAiB,WAAW,MAAM;GAClC,IAAI,EAAE,kBAAkB,kBACtB,AAAK,KAAK,cAAc,EAAE,OAAO,OAAO;EAE5C,CAAC;EAEH,KACG,cAAc,kCAAgC,CAAC,EAC9C,iBAAiB,eAAe;GAChC,AAAK,KAAK,aAAa;EACzB,CAAC;CACL;CAEA,eAAe;EACb,aAAa;GACX,IAAI,kBAAkB,OAAO;IAC3B,KAAK,eAAe,kBAAkB;IACtC,KAAK,OAAO;GACd;EACF,CAAC;CACH;CAEA,MAAM,cAAc,SAAkB;EACpC,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,IAC9B;EAGF,IAAI;GACF,MAAM,YAAY,KAAK,cAAc,KAAK,IAAI,OAAO;GACrD,YAAY,UAAU,uBAAuB,uBAAuB,IAAI;EAC1E,SAAS,KAAK;GAEZ,UAAU,kCADO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,IACX,GAAI;EAC3D;CACF;CAEA,MAAM,SAAS;EACb,IAAI,CAAC,KAAK,cACR;EAGF,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,cAAc,KAAK,cACvB,iCACF;EACA,IAAI,aACF,YAAY,UAAU,KAAK,aAAa;EAG1C,MAAM,gBAAgB,KAAK,cACzB,oCACF;EACA,IAAI,eACF,cAAc,QAAQ,KAAK,aAAa;CAE5C;CAEA,MAAM,eAAe;EACnB,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,IAC9B;EAGF,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,QAAQ,KAAK,cACjB,oCACF;EACA,IAAI,CAAC,OACH;EAGF,MAAM,MAAM,MAAM,MAAM,KAAK;EAC7B,IAAI,CAAC,KAAK;GACR,YAAY,0CAA0C,GAAI;GAE1D;EACF;EAEA,IAAI;GACF,MAAM,YAAY,KAAK,cAAc,KAAK,IAAI,GAAG;GACjD,YAAY,mBAAmB,GAAI;EACrC,SAAS,KAAK;GAEZ,UAAU,8BADO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,IACf,GAAI;EACvD;CACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,WAAW,GACjC,eAAe,OAAO,aAAa,oBAAoB"}
1
+ {"version":3,"file":"shadow-claw-networking-BYt-kMSI.js","names":["shadowClawNetworkingStyles","shadowClawNetworkingTemplate"],"sources":["../../src/components/settings/shadow-claw-networking/shadow-claw-networking.ts"],"sourcesContent":["import { effect } from \"../../../core/effect.js\";\n\nimport {\n setProxyUrl,\n setUseProxy,\n} from \"../../../core/orchestrator/utils/settings.js\";\n\nimport { getDb } from \"../../../db/db.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 shadowClawNetworkingStyles from \"./shadow-claw-networking.css\" with { type: \"css\" };\nimport shadowClawNetworkingTemplate from \"./shadow-claw-networking.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-networking\";\n\n/**\n * Settings sub-component for network proxy configuration.\n */\nexport class ShadowClawNetworking extends ShadowClawElement {\n static styles = shadowClawNetworkingStyles;\n static template = shadowClawNetworkingTemplate;\n\n db: ShadowClawDatabase | null;\n orchestrator: Orchestrator | null;\n\n constructor() {\n super();\n\n this.db = null;\n this.orchestrator = null;\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n this.db = await getDb();\n this.orchestrator = orchestratorStore.orchestrator;\n\n this.bindEventListeners();\n this.setupEffects();\n await this.render();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-setting=\"proxy-toggle\"]')\n ?.addEventListener(\"change\", (e) => {\n if (e.target instanceof HTMLInputElement) {\n void this.onProxyToggle(e.target.checked);\n }\n });\n\n root\n .querySelector('[data-action=\"save-proxy-url\"]')\n ?.addEventListener(\"click\", () => {\n void this.saveProxyUrl();\n });\n }\n\n setupEffects() {\n effect(() => {\n if (orchestratorStore.ready) {\n this.orchestrator = orchestratorStore.orchestrator;\n this.render();\n }\n });\n }\n\n async onProxyToggle(enabled: boolean) {\n if (!this.orchestrator || !this.db) {\n return;\n }\n\n try {\n await setUseProxy(this.orchestrator, this.db, enabled);\n showSuccess(enabled ? \"CORS Proxy enabled\" : \"CORS Proxy disabled\", 2500);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving proxy setting: \" + errorMsg, 6000);\n }\n }\n\n async render() {\n if (!this.orchestrator) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const proxyToggle = root.querySelector(\n '[data-setting=\"proxy-toggle\"]',\n ) as HTMLInputElement | null;\n if (proxyToggle) {\n proxyToggle.checked = this.orchestrator.useProxy;\n }\n\n const proxyUrlInput = root.querySelector(\n '[data-setting=\"proxy-url-input\"]',\n ) as HTMLInputElement | null;\n if (proxyUrlInput) {\n proxyUrlInput.value = this.orchestrator.proxyUrl;\n }\n }\n\n async saveProxyUrl() {\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=\"proxy-url-input\"]',\n ) as HTMLInputElement | null;\n if (!input) {\n return;\n }\n\n const url = input.value.trim();\n if (!url) {\n showWarning(\"Please enter a proxy URL (e.g. /proxy)\", 3000);\n\n return;\n }\n\n try {\n await setProxyUrl(this.orchestrator, this.db, url);\n showSuccess(\"Proxy URL saved\", 3000);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n showError(\"Error saving proxy URL: \" + errorMsg, 6000);\n }\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawNetworking);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAM,cAAc;;;;AAKpB,IAAa,uBAAb,cAA0C,kBAAkB;CAC1D,OAAO,SAASA;CAChB,OAAO,WAAWC;CAElB;CACA;CAEA,cAAc;EACZ,MAAM;EAEN,KAAK,KAAK;EACV,KAAK,eAAe;CACtB;CAEA,MAAM,oBAAoB;EAExB,IAAI,CADS,KAAK,YAEhB,MAAM,IAAI,MAAM,sBAAsB;EAGxC,KAAK,KAAK,MAAM,MAAM;EACtB,KAAK,eAAe,kBAAkB;EAEtC,KAAK,mBAAmB;EACxB,KAAK,aAAa;EAClB,MAAM,KAAK,OAAO;CACpB;CAEA,qBAAqB;EACnB,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,KACG,cAAc,iCAA+B,CAAC,EAC7C,iBAAiB,WAAW,MAAM;GAClC,IAAI,EAAE,kBAAkB,kBACtB,AAAK,KAAK,cAAc,EAAE,OAAO,OAAO;EAE5C,CAAC;EAEH,KACG,cAAc,kCAAgC,CAAC,EAC9C,iBAAiB,eAAe;GAChC,AAAK,KAAK,aAAa;EACzB,CAAC;CACL;CAEA,eAAe;EACb,aAAa;GACX,IAAI,kBAAkB,OAAO;IAC3B,KAAK,eAAe,kBAAkB;IACtC,KAAK,OAAO;GACd;EACF,CAAC;CACH;CAEA,MAAM,cAAc,SAAkB;EACpC,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,IAC9B;EAGF,IAAI;GACF,MAAM,YAAY,KAAK,cAAc,KAAK,IAAI,OAAO;GACrD,YAAY,UAAU,uBAAuB,uBAAuB,IAAI;EAC1E,SAAS,KAAK;GAEZ,UAAU,kCADO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,IACX,GAAI;EAC3D;CACF;CAEA,MAAM,SAAS;EACb,IAAI,CAAC,KAAK,cACR;EAGF,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,cAAc,KAAK,cACvB,iCACF;EACA,IAAI,aACF,YAAY,UAAU,KAAK,aAAa;EAG1C,MAAM,gBAAgB,KAAK,cACzB,oCACF;EACA,IAAI,eACF,cAAc,QAAQ,KAAK,aAAa;CAE5C;CAEA,MAAM,eAAe;EACnB,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,IAC9B;EAGF,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,QAAQ,KAAK,cACjB,oCACF;EACA,IAAI,CAAC,OACH;EAGF,MAAM,MAAM,MAAM,MAAM,KAAK;EAC7B,IAAI,CAAC,KAAK;GACR,YAAY,0CAA0C,GAAI;GAE1D;EACF;EAEA,IAAI;GACF,MAAM,YAAY,KAAK,cAAc,KAAK,IAAI,GAAG;GACjD,YAAY,mBAAmB,GAAI;EACrC,SAAS,KAAK;GAEZ,UAAU,8BADO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,IACf,GAAI;EACvD;CACF;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,WAAW,GACjC,eAAe,OAAO,aAAa,oBAAoB"}
@@ -1,9 +1,9 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { n as getDb } from "./txPromise-CuGh-TGK.js";
3
- import { r as CONFIG_KEYS } from "./config--CFrw3J3.js";
3
+ import { r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
4
4
  import { t as getConfig } from "./getConfig-BxxXMyuM.js";
5
5
  import { t as setConfig } from "./setConfig-BFED5CXn.js";
6
- import { a as unsubscribeFromPush, i as subscribeToPush, n as getPushFetchOptions, r as getPushUrl, t as getCurrentSubscription } from "./push-client-DjwKknNg.js";
6
+ import { a as unsubscribeFromPush, i as subscribeToPush, n as getPushFetchOptions, r as getPushUrl, t as getCurrentSubscription } from "./push-client-4JsQGmQa.js";
7
7
  import { a as showSuccess, r as showError } from "./toast-DZ6r7_YI.js";
8
8
  import "./shadow-claw-empty-state-DPfDqaMA.js";
9
9
 
@@ -489,4 +489,4 @@ customElements.define(elementName, ShadowClawNotifications);
489
489
 
490
490
  //#endregion
491
491
  export { ShadowClawNotifications as t };
492
- //# sourceMappingURL=shadow-claw-notifications-_YeAVPga.js.map
492
+ //# sourceMappingURL=shadow-claw-notifications-Dpe4EtZI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-notifications-_YeAVPga.js","names":["shadowClawNotificationsStyles","shadowClawNotificationsTemplate"],"sources":["../../src/components/settings/shadow-claw-notifications/shadow-claw-notifications.ts"],"sourcesContent":["import {\n getCurrentSubscription,\n getPushFetchOptions,\n getPushUrl,\n subscribeToPush,\n unsubscribeFromPush,\n} from \"../../../subsystems/notifications/push-client.js\";\n\nimport { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\n\nimport \"../../common/shadow-claw-empty-state/shadow-claw-empty-state.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawNotificationsStyles from \"./shadow-claw-notifications.css\" with { type: \"css\" };\nimport shadowClawNotificationsTemplate from \"./shadow-claw-notifications.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-notifications\";\n\n/**\n * Settings sub-component for Web Push Notification management:\n * subscribe/unsubscribe toggle, subscription list, send test notification.\n */\nexport class ShadowClawNotifications extends ShadowClawElement {\n static styles = shadowClawNotificationsStyles;\n static template = shadowClawNotificationsTemplate;\n\n public _backendAvailable: boolean = true;\n public _selectedId: number | null = null;\n public _subscribed: boolean = false;\n public _subscriptions: Array<{\n id: number;\n endpoint: string;\n created_at: string;\n }> = [];\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 await this.refreshState();\n await this.loadProxyConfig();\n await this.loadSubscriptions();\n\n this.bindEventListeners();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"toggle-push\"]')\n ?.addEventListener(\"click\", () => this.handleToggle());\n\n root\n .querySelector('[data-action=\"send-notification\"]')\n ?.addEventListener(\"click\", () => this.handleSendNotification());\n\n root\n .querySelector('[data-action=\"delete-subscription\"]')\n ?.addEventListener(\"click\", () => this.handleDeleteSubscription());\n\n root\n .querySelector('[data-action=\"refresh-subscriptions\"]')\n ?.addEventListener(\"click\", () => this.loadSubscriptions());\n\n root\n .querySelector('[data-input=\"push-proxy-url\"]')\n ?.addEventListener(\"change\", (e) => this.handleProxyUrlChange(e));\n }\n\n renderSubscriptionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector('[data-info=\"subscription-list\"]');\n if (!list) {\n return;\n }\n\n list.replaceChildren();\n\n if (this._subscriptions.length === 0) {\n const message = this._backendAvailable\n ? \"No subscriptions stored.\"\n : \"⚠️ Backend services unavailable (push notification server is not running).\";\n\n const emptyState = document.createElement(\"shadow-claw-empty-state\");\n emptyState.setAttribute(\"compact\", \"\");\n emptyState.setAttribute(\"message\", message);\n list.append(emptyState);\n\n return;\n }\n\n this._subscriptions.forEach((sub) => {\n const shortId = `#${sub.id}`;\n const endpointShort =\n sub.endpoint.length > 60 ? `…${sub.endpoint.slice(-56)}` : sub.endpoint;\n const date = sub.created_at || \"\";\n\n const item = document.createElement(\"div\");\n item.className = `subscription-item${this._selectedId === sub.id ? \" selected\" : \"\"}`;\n item.setAttribute(\"data-sub-id\", String(sub.id));\n item.setAttribute(\"data-endpoint\", sub.endpoint);\n\n const idEl = document.createElement(\"span\");\n idEl.className = \"subscription-id\";\n idEl.title = sub.endpoint;\n idEl.textContent = `${shortId} ${endpointShort}`;\n\n const dateEl = document.createElement(\"span\");\n dateEl.className = \"subscription-date\";\n dateEl.textContent = date;\n\n item.append(idEl, dateEl);\n\n item.addEventListener(\"click\", () => {\n this._selectedId = sub.id;\n this.renderSubscriptionList();\n this.updateActionButtons();\n });\n\n list.append(item);\n });\n }\n\n updateActionButtons() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const hasSelection = this._selectedId != null;\n const sendBtn = root.querySelector(\n '[data-action=\"send-notification\"]',\n ) as HTMLButtonElement | null;\n const deleteBtn = root.querySelector(\n '[data-action=\"delete-subscription\"]',\n ) as HTMLButtonElement | null;\n\n if (sendBtn) {\n sendBtn.disabled = !hasSelection;\n }\n\n if (deleteBtn) {\n deleteBtn.disabled = !hasSelection;\n }\n }\n\n updateToggle() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const toggle = root.querySelector('[data-action=\"toggle-push\"]');\n const status = root.querySelector('[data-info=\"subscription-status\"]');\n\n if (toggle) {\n toggle.setAttribute(\"aria-checked\", String(this._subscribed));\n }\n\n if (status) {\n status.textContent = this._subscribed ? \"Enabled\" : \"Disabled\";\n }\n }\n\n async handleDeleteSubscription() {\n if (this._selectedId == null) {\n return;\n }\n\n try {\n const url = await getPushUrl(`/push/subscription/${this._selectedId}`);\n const res = await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n }),\n );\n\n if (res.ok) {\n showSuccess(\"Subscription deleted.\");\n await this.loadSubscriptions();\n } else {\n showError(\"Failed to delete subscription.\");\n }\n } catch (err) {\n showError(`Delete failed: ${(err as Error).message}`);\n }\n }\n\n async handleProxyUrlChange(e: Event) {\n const input = e.target as HTMLInputElement;\n const value = input.value.trim();\n\n try {\n const db = await getDb();\n await setConfig(db, CONFIG_KEYS.PUSH_PROXY_URL, value);\n showSuccess(\"Push proxy URL updated.\");\n await this.loadSubscriptions();\n } catch (err) {\n showError(`Failed to save proxy URL: ${(err as Error).message}`);\n }\n }\n\n async handleSendNotification() {\n if (this._selectedId == null) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-input=\"notification-text\"]',\n ) as HTMLInputElement | null;\n const payload = input?.value?.trim() || \"Test notification from ShadowClaw\";\n\n const sub = this._subscriptions.find((s) => s.id === this._selectedId);\n if (!sub) {\n return;\n }\n\n try {\n const url = await getPushUrl(\"/push/send\");\n const res = await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint: sub.endpoint, payload }),\n }),\n );\n\n if (res.ok) {\n showSuccess(\"Notification sent!\");\n } else if (res.status === 410) {\n showError(\"Subscription expired and was removed.\");\n await this.loadSubscriptions();\n } else {\n const data = await res.json().catch(() => ({}));\n showError(`Failed to send: ${data.error || res.statusText}`);\n }\n } catch (err) {\n showError(`Send failed: ${(err as Error).message}`);\n }\n }\n\n async handleToggle() {\n try {\n if (this._subscribed) {\n await unsubscribeFromPush();\n this._subscribed = false;\n showSuccess(\"Push notifications disabled.\");\n } else {\n await subscribeToPush();\n this._subscribed = true;\n showSuccess(\"Push notifications enabled!\");\n }\n\n this.updateToggle();\n await this.loadSubscriptions();\n } catch (err) {\n showError(`Push notification error: ${(err as Error).message}`);\n }\n }\n\n async loadProxyConfig() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const db = await getDb();\n const proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n const input = root.querySelector(\n '[data-input=\"push-proxy-url\"]',\n ) as HTMLInputElement | null;\n\n if (input) {\n input.value = proxyUrl || \"\";\n }\n }\n\n /**\n * Load all stored subscriptions from the server.\n */\n async loadSubscriptions() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n try {\n const isStaticHost =\n typeof location !== \"undefined\" &&\n (location.protocol === \"file:\" ||\n location.hostname.endsWith(\".github.io\") ||\n location.hostname.endsWith(\".pages.dev\"));\n\n const db = await getDb();\n const proxyUrl =\n (await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL)) ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL)\n : null);\n\n if (isStaticHost && !proxyUrl) {\n this._subscriptions = [];\n this._backendAvailable = false;\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n return;\n }\n\n const url = await getPushUrl(\"/push/subscriptions\");\n const res = await fetch(url, getPushFetchOptions(url));\n\n if (!res.ok) {\n this._subscriptions = [];\n this._backendAvailable = false;\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n return;\n }\n\n this._subscriptions = await res.json();\n this._backendAvailable = true;\n } catch {\n this._subscriptions = [];\n this._backendAvailable = false;\n }\n\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n }\n\n /**\n * Check current subscription state and update the toggle.\n */\n async refreshState() {\n try {\n const sub = await getCurrentSubscription();\n this._subscribed = !!sub;\n this.updateToggle();\n } catch {\n // Service worker may not be ready\n this._subscribed = false;\n this.updateToggle();\n }\n }\n}\n\n/**\n * Encode a string safe for use as an HTML attribute value.\n */\ncustomElements.define(elementName, ShadowClawNotifications);\n"],"mappings":"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"}
1
+ {"version":3,"file":"shadow-claw-notifications-Dpe4EtZI.js","names":["shadowClawNotificationsStyles","shadowClawNotificationsTemplate"],"sources":["../../src/components/settings/shadow-claw-notifications/shadow-claw-notifications.ts"],"sourcesContent":["import {\n getCurrentSubscription,\n getPushFetchOptions,\n getPushUrl,\n subscribeToPush,\n unsubscribeFromPush,\n} from \"../../../subsystems/notifications/push-client.js\";\n\nimport { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\n\nimport \"../../common/shadow-claw-empty-state/shadow-claw-empty-state.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawNotificationsStyles from \"./shadow-claw-notifications.css\" with { type: \"css\" };\nimport shadowClawNotificationsTemplate from \"./shadow-claw-notifications.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-notifications\";\n\n/**\n * Settings sub-component for Web Push Notification management:\n * subscribe/unsubscribe toggle, subscription list, send test notification.\n */\nexport class ShadowClawNotifications extends ShadowClawElement {\n static styles = shadowClawNotificationsStyles;\n static template = shadowClawNotificationsTemplate;\n\n public _backendAvailable: boolean = true;\n public _selectedId: number | null = null;\n public _subscribed: boolean = false;\n public _subscriptions: Array<{\n id: number;\n endpoint: string;\n created_at: string;\n }> = [];\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 await this.refreshState();\n await this.loadProxyConfig();\n await this.loadSubscriptions();\n\n this.bindEventListeners();\n }\n\n bindEventListeners() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n root\n .querySelector('[data-action=\"toggle-push\"]')\n ?.addEventListener(\"click\", () => this.handleToggle());\n\n root\n .querySelector('[data-action=\"send-notification\"]')\n ?.addEventListener(\"click\", () => this.handleSendNotification());\n\n root\n .querySelector('[data-action=\"delete-subscription\"]')\n ?.addEventListener(\"click\", () => this.handleDeleteSubscription());\n\n root\n .querySelector('[data-action=\"refresh-subscriptions\"]')\n ?.addEventListener(\"click\", () => this.loadSubscriptions());\n\n root\n .querySelector('[data-input=\"push-proxy-url\"]')\n ?.addEventListener(\"change\", (e) => this.handleProxyUrlChange(e));\n }\n\n renderSubscriptionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector('[data-info=\"subscription-list\"]');\n if (!list) {\n return;\n }\n\n list.replaceChildren();\n\n if (this._subscriptions.length === 0) {\n const message = this._backendAvailable\n ? \"No subscriptions stored.\"\n : \"⚠️ Backend services unavailable (push notification server is not running).\";\n\n const emptyState = document.createElement(\"shadow-claw-empty-state\");\n emptyState.setAttribute(\"compact\", \"\");\n emptyState.setAttribute(\"message\", message);\n list.append(emptyState);\n\n return;\n }\n\n this._subscriptions.forEach((sub) => {\n const shortId = `#${sub.id}`;\n const endpointShort =\n sub.endpoint.length > 60 ? `…${sub.endpoint.slice(-56)}` : sub.endpoint;\n const date = sub.created_at || \"\";\n\n const item = document.createElement(\"div\");\n item.className = `subscription-item${this._selectedId === sub.id ? \" selected\" : \"\"}`;\n item.setAttribute(\"data-sub-id\", String(sub.id));\n item.setAttribute(\"data-endpoint\", sub.endpoint);\n\n const idEl = document.createElement(\"span\");\n idEl.className = \"subscription-id\";\n idEl.title = sub.endpoint;\n idEl.textContent = `${shortId} ${endpointShort}`;\n\n const dateEl = document.createElement(\"span\");\n dateEl.className = \"subscription-date\";\n dateEl.textContent = date;\n\n item.append(idEl, dateEl);\n\n item.addEventListener(\"click\", () => {\n this._selectedId = sub.id;\n this.renderSubscriptionList();\n this.updateActionButtons();\n });\n\n list.append(item);\n });\n }\n\n updateActionButtons() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const hasSelection = this._selectedId != null;\n const sendBtn = root.querySelector(\n '[data-action=\"send-notification\"]',\n ) as HTMLButtonElement | null;\n const deleteBtn = root.querySelector(\n '[data-action=\"delete-subscription\"]',\n ) as HTMLButtonElement | null;\n\n if (sendBtn) {\n sendBtn.disabled = !hasSelection;\n }\n\n if (deleteBtn) {\n deleteBtn.disabled = !hasSelection;\n }\n }\n\n updateToggle() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const toggle = root.querySelector('[data-action=\"toggle-push\"]');\n const status = root.querySelector('[data-info=\"subscription-status\"]');\n\n if (toggle) {\n toggle.setAttribute(\"aria-checked\", String(this._subscribed));\n }\n\n if (status) {\n status.textContent = this._subscribed ? \"Enabled\" : \"Disabled\";\n }\n }\n\n async handleDeleteSubscription() {\n if (this._selectedId == null) {\n return;\n }\n\n try {\n const url = await getPushUrl(`/push/subscription/${this._selectedId}`);\n const res = await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n }),\n );\n\n if (res.ok) {\n showSuccess(\"Subscription deleted.\");\n await this.loadSubscriptions();\n } else {\n showError(\"Failed to delete subscription.\");\n }\n } catch (err) {\n showError(`Delete failed: ${(err as Error).message}`);\n }\n }\n\n async handleProxyUrlChange(e: Event) {\n const input = e.target as HTMLInputElement;\n const value = input.value.trim();\n\n try {\n const db = await getDb();\n await setConfig(db, CONFIG_KEYS.PUSH_PROXY_URL, value);\n showSuccess(\"Push proxy URL updated.\");\n await this.loadSubscriptions();\n } catch (err) {\n showError(`Failed to save proxy URL: ${(err as Error).message}`);\n }\n }\n\n async handleSendNotification() {\n if (this._selectedId == null) {\n return;\n }\n\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const input = root.querySelector(\n '[data-input=\"notification-text\"]',\n ) as HTMLInputElement | null;\n const payload = input?.value?.trim() || \"Test notification from ShadowClaw\";\n\n const sub = this._subscriptions.find((s) => s.id === this._selectedId);\n if (!sub) {\n return;\n }\n\n try {\n const url = await getPushUrl(\"/push/send\");\n const res = await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint: sub.endpoint, payload }),\n }),\n );\n\n if (res.ok) {\n showSuccess(\"Notification sent!\");\n } else if (res.status === 410) {\n showError(\"Subscription expired and was removed.\");\n await this.loadSubscriptions();\n } else {\n const data = await res.json().catch(() => ({}));\n showError(`Failed to send: ${data.error || res.statusText}`);\n }\n } catch (err) {\n showError(`Send failed: ${(err as Error).message}`);\n }\n }\n\n async handleToggle() {\n try {\n if (this._subscribed) {\n await unsubscribeFromPush();\n this._subscribed = false;\n showSuccess(\"Push notifications disabled.\");\n } else {\n await subscribeToPush();\n this._subscribed = true;\n showSuccess(\"Push notifications enabled!\");\n }\n\n this.updateToggle();\n await this.loadSubscriptions();\n } catch (err) {\n showError(`Push notification error: ${(err as Error).message}`);\n }\n }\n\n async loadProxyConfig() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const db = await getDb();\n const proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n const input = root.querySelector(\n '[data-input=\"push-proxy-url\"]',\n ) as HTMLInputElement | null;\n\n if (input) {\n input.value = proxyUrl || \"\";\n }\n }\n\n /**\n * Load all stored subscriptions from the server.\n */\n async loadSubscriptions() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n try {\n const isStaticHost =\n typeof location !== \"undefined\" &&\n (location.protocol === \"file:\" ||\n location.hostname.endsWith(\".github.io\") ||\n location.hostname.endsWith(\".pages.dev\"));\n\n const db = await getDb();\n const proxyUrl =\n (await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL)) ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL)\n : null);\n\n if (isStaticHost && !proxyUrl) {\n this._subscriptions = [];\n this._backendAvailable = false;\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n return;\n }\n\n const url = await getPushUrl(\"/push/subscriptions\");\n const res = await fetch(url, getPushFetchOptions(url));\n\n if (!res.ok) {\n this._subscriptions = [];\n this._backendAvailable = false;\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n return;\n }\n\n this._subscriptions = await res.json();\n this._backendAvailable = true;\n } catch {\n this._subscriptions = [];\n this._backendAvailable = false;\n }\n\n this._selectedId = null;\n this.renderSubscriptionList();\n this.updateActionButtons();\n }\n\n /**\n * Check current subscription state and update the toggle.\n */\n async refreshState() {\n try {\n const sub = await getCurrentSubscription();\n this._subscribed = !!sub;\n this.updateToggle();\n } catch {\n // Service worker may not be ready\n this._subscribed = false;\n this.updateToggle();\n }\n }\n}\n\n/**\n * Encode a string safe for use as an HTML attribute value.\n */\ncustomElements.define(elementName, ShadowClawNotifications);\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
- import { n as setSanitizedHtml } from "./trusted-types-Dx0RZlrd.js";
2
+ import { n as setSanitizedHtml } from "./trusted-types-Oz7xXJAY.js";
3
3
 
4
4
  //#region src/components/shadow-claw-page-header/shadow-claw-page-header.css
5
5
  const sheet = new CSSStyleSheet();
@@ -361,4 +361,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
361
361
 
362
362
  //#endregion
363
363
  export { ShadowClawPageHeader as t };
364
- //# sourceMappingURL=shadow-claw-page-header-Cti2fzf-.js.map
364
+ //# sourceMappingURL=shadow-claw-page-header-P4EvWyUr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-page-header-Cti2fzf-.js","names":["shadowClawPageHeaderStyles","shadowClawPageHeaderTemplate"],"sources":["../../src/components/shadow-claw-page-header/shadow-claw-page-header.ts"],"sourcesContent":["import ShadowClawElement from \"../shadow-claw-element.js\";\nimport { setSanitizedHtml } from \"../../security/trusted-types.js\";\nimport shadowClawPageHeaderStyles from \"./shadow-claw-page-header.css\" with { type: \"css\" };\nimport shadowClawPageHeaderTemplate from \"./shadow-claw-page-header.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-page-header\";\n\n/**\n * Reusable page header component with mobile-first responsive design.\n * Supports title, actions, and optional breadcrumbs.\n */\nexport class ShadowClawPageHeader extends ShadowClawElement {\n static styles = shadowClawPageHeaderStyles;\n static template = shadowClawPageHeaderTemplate;\n\n static get observedAttributes() {\n return [\"title\", \"page-title\", \"icon\"];\n }\n\n mainCollapsed: boolean = false;\n mainVisibilityMediaQuery: MediaQueryList | null = null;\n manualMainCollapsedOverride: boolean | null = null;\n\n constructor() {\n super();\n }\n\n attributeChangedCallback(_name, oldValue, newValue) {\n if (oldValue !== newValue) {\n this.render();\n }\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n await this.render();\n }\n\n disconnectedCallback() {\n this.actionsLayoutCleanup();\n this.mainVisibilityCleanup();\n }\n\n actionsLayoutCleanup: () => void = () => {};\n\n applyMainVisibility(root?: ShadowRoot) {\n const targetRoot = root || this.shadowRoot;\n if (!targetRoot) {\n return;\n }\n\n const headerMain = targetRoot.querySelector(\".header__main\");\n if (!(headerMain instanceof HTMLElement)) {\n return;\n }\n\n const collapsed = this.getEffectiveMainCollapsed();\n this.mainCollapsed = collapsed;\n headerMain.hidden = collapsed;\n }\n\n getAutoMainCollapsed() {\n return false;\n }\n\n getEffectiveMainCollapsed() {\n if (typeof this.manualMainCollapsedOverride === \"boolean\") {\n return this.manualMainCollapsedOverride;\n }\n\n return this.getAutoMainCollapsed();\n }\n\n isMainCollapsed() {\n return this.mainCollapsed;\n }\n\n mainVisibilityCleanup: () => void = () => {};\n\n setMainCollapsedOverride(collapsed: boolean | null) {\n this.manualMainCollapsedOverride =\n typeof collapsed === \"boolean\" ? collapsed : null;\n this.applyMainVisibility();\n }\n\n /**\n * Hide the actions container when no action buttons are slotted.\n */\n setupActionsContainer(root: ShadowRoot) {\n const actionSlot = root.querySelector('slot[name=\"actions\"]');\n const actions = root.querySelector(\".header__actions\");\n const disclosure = root.querySelector(\".header__actions-disclosure\");\n\n if (\n !(actionSlot instanceof HTMLSlotElement) ||\n !(actions instanceof HTMLElement) ||\n !(disclosure instanceof HTMLElement)\n ) {\n return;\n }\n\n const updateVisibility = () => {\n const hasActions = actionSlot.assignedElements().length > 0;\n actions.hidden = !hasActions;\n disclosure.hidden = !hasActions;\n };\n\n actionSlot.addEventListener(\"slotchange\", updateVisibility);\n updateVisibility();\n }\n\n setupMainVisibility(root: ShadowRoot) {\n this.mainVisibilityCleanup();\n this.mainVisibilityMediaQuery = null;\n this.mainVisibilityCleanup = () => {};\n this.applyMainVisibility(root);\n }\n\n /**\n * Keep actions collapsed by default on stacked/mobile layout and expanded on wider screens.\n */\n setupResponsiveActionsDisclosure(root: ShadowRoot) {\n this.actionsLayoutCleanup();\n\n const disclosure = root.querySelector(\".header__actions-disclosure\");\n if (!(disclosure instanceof HTMLDetailsElement)) {\n return;\n }\n\n if (typeof globalThis.matchMedia !== \"function\") {\n disclosure.open = false;\n this.actionsLayoutCleanup = () => {};\n\n return;\n }\n\n const mediaQuery = globalThis.matchMedia(\"(min-width: 40.625rem)\");\n\n const applyLayoutMode = () => {\n if (mediaQuery.matches) {\n disclosure.open = true;\n } else {\n disclosure.open = false;\n }\n };\n\n applyLayoutMode();\n\n const onChange = () => {\n applyLayoutMode();\n };\n\n mediaQuery.addEventListener(\"change\", onChange);\n\n this.actionsLayoutCleanup = () => {\n mediaQuery.removeEventListener(\"change\", onChange);\n };\n }\n\n toggleMainCollapsedOverride() {\n this.setMainCollapsedOverride(!this.isMainCollapsed());\n\n return this.isMainCollapsed();\n }\n\n async render() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Set title\n const titleEl = root.querySelector(\".header__title\");\n if (titleEl) {\n const icon = this.getAttribute(\"icon\") || \"\";\n const title = this.hasAttribute(\"page-title\")\n ? this.getAttribute(\"page-title\") || \"\"\n : this.getAttribute(\"title\") || \"\";\n setSanitizedHtml(titleEl, icon ? `${icon} ${title}` : title);\n }\n\n this.setupActionsContainer(root);\n this.setupResponsiveActionsDisclosure(root);\n this.setupMainVisibility(root);\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawPageHeader);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shadow-claw-page-header-P4EvWyUr.js","names":["shadowClawPageHeaderStyles","shadowClawPageHeaderTemplate"],"sources":["../../src/components/shadow-claw-page-header/shadow-claw-page-header.ts"],"sourcesContent":["import ShadowClawElement from \"../shadow-claw-element.js\";\nimport { setSanitizedHtml } from \"../../security/trusted-types.js\";\nimport shadowClawPageHeaderStyles from \"./shadow-claw-page-header.css\" with { type: \"css\" };\nimport shadowClawPageHeaderTemplate from \"./shadow-claw-page-header.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-page-header\";\n\n/**\n * Reusable page header component with mobile-first responsive design.\n * Supports title, actions, and optional breadcrumbs.\n */\nexport class ShadowClawPageHeader extends ShadowClawElement {\n static styles = shadowClawPageHeaderStyles;\n static template = shadowClawPageHeaderTemplate;\n\n static get observedAttributes() {\n return [\"title\", \"page-title\", \"icon\"];\n }\n\n mainCollapsed: boolean = false;\n mainVisibilityMediaQuery: MediaQueryList | null = null;\n manualMainCollapsedOverride: boolean | null = null;\n\n constructor() {\n super();\n }\n\n attributeChangedCallback(_name, oldValue, newValue) {\n if (oldValue !== newValue) {\n this.render();\n }\n }\n\n async connectedCallback() {\n const root = this.shadowRoot;\n if (!root) {\n throw new Error(\"shadowRoot not found\");\n }\n\n await this.render();\n }\n\n disconnectedCallback() {\n this.actionsLayoutCleanup();\n this.mainVisibilityCleanup();\n }\n\n actionsLayoutCleanup: () => void = () => {};\n\n applyMainVisibility(root?: ShadowRoot) {\n const targetRoot = root || this.shadowRoot;\n if (!targetRoot) {\n return;\n }\n\n const headerMain = targetRoot.querySelector(\".header__main\");\n if (!(headerMain instanceof HTMLElement)) {\n return;\n }\n\n const collapsed = this.getEffectiveMainCollapsed();\n this.mainCollapsed = collapsed;\n headerMain.hidden = collapsed;\n }\n\n getAutoMainCollapsed() {\n return false;\n }\n\n getEffectiveMainCollapsed() {\n if (typeof this.manualMainCollapsedOverride === \"boolean\") {\n return this.manualMainCollapsedOverride;\n }\n\n return this.getAutoMainCollapsed();\n }\n\n isMainCollapsed() {\n return this.mainCollapsed;\n }\n\n mainVisibilityCleanup: () => void = () => {};\n\n setMainCollapsedOverride(collapsed: boolean | null) {\n this.manualMainCollapsedOverride =\n typeof collapsed === \"boolean\" ? collapsed : null;\n this.applyMainVisibility();\n }\n\n /**\n * Hide the actions container when no action buttons are slotted.\n */\n setupActionsContainer(root: ShadowRoot) {\n const actionSlot = root.querySelector('slot[name=\"actions\"]');\n const actions = root.querySelector(\".header__actions\");\n const disclosure = root.querySelector(\".header__actions-disclosure\");\n\n if (\n !(actionSlot instanceof HTMLSlotElement) ||\n !(actions instanceof HTMLElement) ||\n !(disclosure instanceof HTMLElement)\n ) {\n return;\n }\n\n const updateVisibility = () => {\n const hasActions = actionSlot.assignedElements().length > 0;\n actions.hidden = !hasActions;\n disclosure.hidden = !hasActions;\n };\n\n actionSlot.addEventListener(\"slotchange\", updateVisibility);\n updateVisibility();\n }\n\n setupMainVisibility(root: ShadowRoot) {\n this.mainVisibilityCleanup();\n this.mainVisibilityMediaQuery = null;\n this.mainVisibilityCleanup = () => {};\n this.applyMainVisibility(root);\n }\n\n /**\n * Keep actions collapsed by default on stacked/mobile layout and expanded on wider screens.\n */\n setupResponsiveActionsDisclosure(root: ShadowRoot) {\n this.actionsLayoutCleanup();\n\n const disclosure = root.querySelector(\".header__actions-disclosure\");\n if (!(disclosure instanceof HTMLDetailsElement)) {\n return;\n }\n\n if (typeof globalThis.matchMedia !== \"function\") {\n disclosure.open = false;\n this.actionsLayoutCleanup = () => {};\n\n return;\n }\n\n const mediaQuery = globalThis.matchMedia(\"(min-width: 40.625rem)\");\n\n const applyLayoutMode = () => {\n if (mediaQuery.matches) {\n disclosure.open = true;\n } else {\n disclosure.open = false;\n }\n };\n\n applyLayoutMode();\n\n const onChange = () => {\n applyLayoutMode();\n };\n\n mediaQuery.addEventListener(\"change\", onChange);\n\n this.actionsLayoutCleanup = () => {\n mediaQuery.removeEventListener(\"change\", onChange);\n };\n }\n\n toggleMainCollapsedOverride() {\n this.setMainCollapsedOverride(!this.isMainCollapsed());\n\n return this.isMainCollapsed();\n }\n\n async render() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n // Set title\n const titleEl = root.querySelector(\".header__title\");\n if (titleEl) {\n const icon = this.getAttribute(\"icon\") || \"\";\n const title = this.hasAttribute(\"page-title\")\n ? this.getAttribute(\"page-title\") || \"\"\n : this.getAttribute(\"title\") || \"\";\n setSanitizedHtml(titleEl, icon ? `${icon} ${title}` : title);\n }\n\n this.setupActionsContainer(root);\n this.setupResponsiveActionsDisclosure(root);\n this.setupMainVisibility(root);\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawPageHeader);\n}\n"],"mappings":"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"}
@@ -1,22 +1,22 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { n as getDb } from "./txPromise-CuGh-TGK.js";
3
3
  import { t as Signal } from "./dist-Bxg3C_zy.js";
4
- import { r as CONFIG_KEYS } from "./config--CFrw3J3.js";
5
- import { a as getFileRouteDirPath, n as applyBasePath, o as getWorkspaceRouteRequestPath, r as buildRoutePath, s as isPossibleAppRoute, u as resolveHrefAgainstRoute } from "./app-routes-CqBOeA5q.js";
4
+ import { r as CONFIG_KEYS } from "./config-DjZ9QWc4.js";
5
+ import { c as isPossibleAppRoute, d as resolveHrefAgainstRoute, n as applyBasePath, o as getFileRouteDirPath, r as buildRoutePath, s as getWorkspaceRouteRequestPath } from "./app-routes-BAEMLu9g.js";
6
6
  import { t as getConfig } from "./getConfig-BxxXMyuM.js";
7
- import { o as readGroupFile, t as toolsStore } from "./tools-DwwB9RBa.js";
8
- import { t as readGroupFileBytes } from "./readGroupFileBytes-C8oOe8Iu.js";
9
- import { t as fileViewerStore } from "./file-viewer-C3YKnq_-.js";
10
- import { nn as writeGroupFile, r as getStaticPageContent, t as orchestratorStore } from "./orchestrator-ClXbJ4Mb.js";
11
- import { _ as getIframeSandboxPolicy, b as isAllowedCustomElement, g as getIframeCsp, h as getApprovedCustomElementScriptDescriptors, n as setSanitizedHtml, r as setTrustedSrcdoc, t as sanitizeSrcdocHtml } from "./trusted-types-Dx0RZlrd.js";
7
+ import { o as readGroupFile, t as toolsStore } from "./tools-DqcJe8LS.js";
8
+ import { t as readGroupFileBytes } from "./readGroupFileBytes-CSA7u-nJ.js";
9
+ import { t as fileViewerStore } from "./file-viewer-CwvhxAAG.js";
10
+ import { nn as writeGroupFile, r as getStaticPageContent, t as orchestratorStore } from "./orchestrator-C6dc-2OQ.js";
11
+ import { _ as getIframeSandboxPolicy, b as isAllowedCustomElement, g as getIframeCsp, h as getApprovedCustomElementScriptDescriptors, n as setSanitizedHtml, r as setTrustedSrcdoc, t as sanitizeSrcdocHtml } from "./trusted-types-Oz7xXJAY.js";
12
12
  import { t as require_buffer } from "./buffer-BEXn271X.js";
13
13
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-DZ6r7_YI.js";
14
14
  import { getNamespacedItem, removeNamespacedItem, setNamespacedItem } from "./utils/namespacedStorage.js";
15
15
  import { t as effect } from "./effect-DL6j9HJp.js";
16
- import { n as splitFrontmatter, t as renderMarkdown } from "./markdown-DgdSt2GD.js";
16
+ import { n as splitFrontmatter, t as renderMarkdown } from "./markdown-DYHmNjC4.js";
17
17
  import { t as isTruthyConfigValue } from "./config-value-Cxggje2K.js";
18
18
  import "./shadow-claw-page-header-action-button-BXXm5b5N.js";
19
- import "./shadow-claw-page-header-Cti2fzf-.js";
19
+ import "./shadow-claw-page-header-P4EvWyUr.js";
20
20
  import { a as iframeStorageSet, c as getIframeThemeStyleHtml, i as iframeStorageGetAll, n as iframeStorageDelete, o as IframeBroadcastProxy, r as iframeStorageGet, s as getIframeHtmlClass, t as iframeStorageClear } from "./iframe-storage-proxy-Bx5GWTs0.js";
21
21
 
22
22
  //#region src/components/shadow-claw-pages/utils/announcePageChange.ts
@@ -2307,4 +2307,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
2307
2307
 
2308
2308
  //#endregion
2309
2309
  export { ShadowClawPages as t };
2310
- //# sourceMappingURL=shadow-claw-pages-DVzZriZ7.js.map
2310
+ //# sourceMappingURL=shadow-claw-pages-DWd_c4d6.js.map