shadow-claw 1.26.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/.agents/skills/main/skill-creator/SKILL.md +39 -0
  2. package/.agents/skills/main/skill-creator/references/declarative-pipelines.md +44 -0
  3. package/.agents/skills/main/skill-creator/references/declarative-tools.md +35 -0
  4. package/.agents/skills/main/skill-creator/references/frontmatter-spec.md +50 -0
  5. package/.well-known/agent-skills/index.json +14 -0
  6. package/README.md +5 -3
  7. package/bin/build/build.mjs +146 -15
  8. package/bin/build/build.test.mjs +57 -0
  9. package/bin/cli.mjs +26 -0
  10. package/bin/commands/mcp.mjs +277 -55
  11. package/bin/commands/mcp.test.mjs +275 -1
  12. package/bin/commands/skills-index.mjs +328 -0
  13. package/bin/commands/skills-index.test.mjs +161 -0
  14. package/bin/site-config/utils/custom-elements/get-approved-custom-element-scripts.test.mjs +2 -0
  15. package/bin/site-config/utils/custom-elements/sanitize-embedded-custom-element-scripts.test.mjs +10 -1
  16. package/dist/lib/components/index.js +25 -25
  17. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  18. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  19. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  20. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  21. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  22. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  23. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  24. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  25. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  26. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  27. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  28. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  29. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  30. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  31. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  32. package/dist/lib/components/shadow-claw-channels.js +1 -1
  33. package/dist/lib/components/shadow-claw-chat.js +1 -1
  34. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  35. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  36. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  37. package/dist/lib/components/shadow-claw-files.js +1 -1
  38. package/dist/lib/components/shadow-claw-git.js +1 -1
  39. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  40. package/dist/lib/components/shadow-claw-llm.js +1 -1
  41. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  42. package/dist/lib/components/shadow-claw-networking.js +1 -1
  43. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  44. package/dist/lib/components/shadow-claw-pages.js +1 -1
  45. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  46. package/dist/lib/components/shadow-claw-settings.js +1 -1
  47. package/dist/lib/components/shadow-claw-storage.js +1 -1
  48. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  49. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  50. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  51. package/dist/lib/components/shadow-claw-tools.js +1 -1
  52. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  53. package/dist/lib/components/shadow-claw.js +1 -1
  54. package/dist/lib/{configurePeerJs-CrlGan0m.js → configurePeerJs-oODzltaC.js} +2 -2
  55. package/dist/lib/{configurePeerJs-CrlGan0m.js.map → configurePeerJs-oODzltaC.js.map} +1 -1
  56. package/dist/lib/core/control-plane-client.d.ts +1 -0
  57. package/dist/lib/{downloadGroupFile-DboUjmp2.js → downloadGroupFile-DmcBQU1n.js} +2 -2
  58. package/dist/lib/{downloadGroupFile-DboUjmp2.js.map → downloadGroupFile-DmcBQU1n.js.map} +1 -1
  59. package/dist/lib/{file-viewer-BrK2Wxgh.js → file-viewer-C3YKnq_-.js} +4 -3
  60. package/dist/lib/{file-viewer-BrK2Wxgh.js.map → file-viewer-C3YKnq_-.js.map} +1 -1
  61. package/dist/lib/index.js +26 -26
  62. package/dist/lib/{initControlPlane-CsO4UR6_.js → initControlPlane-C2zURVIS.js} +86 -13
  63. package/dist/lib/initControlPlane-C2zURVIS.js.map +1 -0
  64. package/dist/lib/{markdown-eeSTFnMA.js → markdown-C6EHl9zs.js} +3 -3
  65. package/dist/lib/{markdown-eeSTFnMA.js.map → markdown-C6EHl9zs.js.map} +1 -1
  66. package/dist/lib/{orchestrator-CJvoC2Uu.js → orchestrator-CACLa_Ro.js} +7 -6
  67. package/dist/lib/{orchestrator-CJvoC2Uu.js.map → orchestrator-CACLa_Ro.js.map} +1 -1
  68. package/dist/lib/{orchestrator-DCfomsn9.js → orchestrator-KRjx0eba.js} +6 -534
  69. package/dist/lib/{orchestrator-DCfomsn9.js.map → orchestrator-KRjx0eba.js.map} +1 -1
  70. package/dist/lib/parsePath-DwC_YZjw.js +16 -0
  71. package/dist/lib/parsePath-DwC_YZjw.js.map +1 -0
  72. package/dist/lib/{peerjs-Dp02bXcG.js → peerjs-DFWOBcXf.js} +4 -4
  73. package/dist/lib/{peerjs-Dp02bXcG.js.map → peerjs-DFWOBcXf.js.map} +1 -1
  74. package/dist/lib/{readGroupFileBytes-Bve-e5e_.js → readGroupFileBytes-C8oOe8Iu.js} +3 -16
  75. package/dist/lib/readGroupFileBytes-C8oOe8Iu.js.map +1 -0
  76. package/dist/lib/security/custom-element-security.d.ts +8 -0
  77. package/dist/lib/server/control-plane-types.d.ts +1 -1
  78. package/dist/lib/{shadow-claw-D8xINM3c.js → shadow-claw-6UHdiy4a.js} +5 -5
  79. package/dist/lib/{shadow-claw-D8xINM3c.js.map → shadow-claw-6UHdiy4a.js.map} +1 -1
  80. package/dist/lib/{shadow-claw-a2ui-7rJqG4Ke.js → shadow-claw-a2ui-CpZUTzlh.js} +5 -4
  81. package/dist/lib/{shadow-claw-a2ui-7rJqG4Ke.js.map → shadow-claw-a2ui-CpZUTzlh.js.map} +1 -1
  82. package/dist/lib/{shadow-claw-accounts-CdruwN8A.js → shadow-claw-accounts-03oJ__XC.js} +2 -2
  83. package/dist/lib/{shadow-claw-accounts-CdruwN8A.js.map → shadow-claw-accounts-03oJ__XC.js.map} +1 -1
  84. package/dist/lib/{shadow-claw-channel-config-Bj0-Nk3t.js → shadow-claw-channel-config-DmfwJc6G.js} +3 -3
  85. package/dist/lib/{shadow-claw-channel-config-Bj0-Nk3t.js.map → shadow-claw-channel-config-DmfwJc6G.js.map} +1 -1
  86. package/dist/lib/{shadow-claw-channels-C_jI4KhP.js → shadow-claw-channels-1N6Jl-By.js} +3 -3
  87. package/dist/lib/{shadow-claw-channels-C_jI4KhP.js.map → shadow-claw-channels-1N6Jl-By.js.map} +1 -1
  88. package/dist/lib/{shadow-claw-chat-B16MspoP.js → shadow-claw-chat-BMoqQJRK.js} +10 -10
  89. package/dist/lib/{shadow-claw-chat-B16MspoP.js.map → shadow-claw-chat-BMoqQJRK.js.map} +1 -1
  90. package/dist/lib/{shadow-claw-control-plane-x8Ldid_h.js → shadow-claw-control-plane-UG0o7pCz.js} +6 -6
  91. package/dist/lib/{shadow-claw-control-plane-x8Ldid_h.js.map → shadow-claw-control-plane-UG0o7pCz.js.map} +1 -1
  92. package/dist/lib/{shadow-claw-conversations-Ct1kAYdB.js → shadow-claw-conversations-BwXep3iu.js} +4 -3
  93. package/dist/lib/{shadow-claw-conversations-Ct1kAYdB.js.map → shadow-claw-conversations-BwXep3iu.js.map} +1 -1
  94. package/dist/lib/{shadow-claw-file-viewer-BfDHHgpA.js → shadow-claw-file-viewer-DUxzVxDT.js} +14 -10
  95. package/dist/lib/shadow-claw-file-viewer-DUxzVxDT.js.map +1 -0
  96. package/dist/lib/{shadow-claw-files-EYhOPYIH.js → shadow-claw-files-DIREEnT2.js} +7 -7
  97. package/dist/lib/{shadow-claw-files-EYhOPYIH.js.map → shadow-claw-files-DIREEnT2.js.map} +1 -1
  98. package/dist/lib/{shadow-claw-git-tcSpT-P0.js → shadow-claw-git-Bg1SWgsF.js} +4 -4
  99. package/dist/lib/{shadow-claw-git-tcSpT-P0.js.map → shadow-claw-git-Bg1SWgsF.js.map} +1 -1
  100. package/dist/lib/{shadow-claw-integrations-NbcCx_ZI.js → shadow-claw-integrations-Ds-CLPhj.js} +2 -2
  101. package/dist/lib/{shadow-claw-integrations-NbcCx_ZI.js.map → shadow-claw-integrations-Ds-CLPhj.js.map} +1 -1
  102. package/dist/lib/{shadow-claw-llm-BazJdD5f.js → shadow-claw-llm-CazBrVpM.js} +3 -3
  103. package/dist/lib/{shadow-claw-llm-BazJdD5f.js.map → shadow-claw-llm-CazBrVpM.js.map} +1 -1
  104. package/dist/lib/{shadow-claw-mcp-remote-CYmhpg7a.js → shadow-claw-mcp-remote-CT5Q-54E.js} +2 -2
  105. package/dist/lib/{shadow-claw-mcp-remote-CYmhpg7a.js.map → shadow-claw-mcp-remote-CT5Q-54E.js.map} +1 -1
  106. package/dist/lib/{shadow-claw-networking-DImPxe0H.js → shadow-claw-networking-Df85tCbO.js} +2 -2
  107. package/dist/lib/{shadow-claw-networking-DImPxe0H.js.map → shadow-claw-networking-Df85tCbO.js.map} +1 -1
  108. package/dist/lib/{shadow-claw-page-header-CcHUfFUx.js → shadow-claw-page-header-Cti2fzf-.js} +2 -2
  109. package/dist/lib/{shadow-claw-page-header-CcHUfFUx.js.map → shadow-claw-page-header-Cti2fzf-.js.map} +1 -1
  110. package/dist/lib/{shadow-claw-pages-D54jF1Qq.js → shadow-claw-pages-BgPyIEZO.js} +15 -11
  111. package/dist/lib/shadow-claw-pages-BgPyIEZO.js.map +1 -0
  112. package/dist/lib/{shadow-claw-peerjs-B9-T8Nlx.js → shadow-claw-peerjs-xkBXILed.js} +3 -3
  113. package/dist/lib/{shadow-claw-peerjs-B9-T8Nlx.js.map → shadow-claw-peerjs-xkBXILed.js.map} +1 -1
  114. package/dist/lib/{shadow-claw-settings-Bt1VAe-1.js → shadow-claw-settings-CN89xRVU.js} +4 -4
  115. package/dist/lib/{shadow-claw-settings-Bt1VAe-1.js.map → shadow-claw-settings-CN89xRVU.js.map} +1 -1
  116. package/dist/lib/{shadow-claw-storage-CFOjGf1d.js → shadow-claw-storage-VnhcObCe.js} +3 -3
  117. package/dist/lib/{shadow-claw-storage-CFOjGf1d.js.map → shadow-claw-storage-VnhcObCe.js.map} +1 -1
  118. package/dist/lib/{shadow-claw-task-server-BiKa2GOm.js → shadow-claw-task-server-jgEC2hHB.js} +2 -2
  119. package/dist/lib/{shadow-claw-task-server-BiKa2GOm.js.map → shadow-claw-task-server-jgEC2hHB.js.map} +1 -1
  120. package/dist/lib/{shadow-claw-tasks-DDHd8W4d.js → shadow-claw-tasks-i_evIufy.js} +6 -6
  121. package/dist/lib/{shadow-claw-tasks-DDHd8W4d.js.map → shadow-claw-tasks-i_evIufy.js.map} +1 -1
  122. package/dist/lib/{shadow-claw-terminal-kB6_tWKz.js → shadow-claw-terminal-CwScROlu.js} +2 -2
  123. package/dist/lib/{shadow-claw-terminal-kB6_tWKz.js.map → shadow-claw-terminal-CwScROlu.js.map} +1 -1
  124. package/dist/lib/{shadow-claw-tools-DxXIm0ku.js → shadow-claw-tools-DD3fyXP4.js} +5 -4
  125. package/dist/lib/{shadow-claw-tools-DxXIm0ku.js.map → shadow-claw-tools-DD3fyXP4.js.map} +1 -1
  126. package/dist/lib/{shadow-claw-webvm-Dc8oo7ao.js → shadow-claw-webvm-DbJq4I3-.js} +2 -2
  127. package/dist/lib/{shadow-claw-webvm-Dc8oo7ao.js.map → shadow-claw-webvm-DbJq4I3-.js.map} +1 -1
  128. package/dist/lib/{syncWebMcpRegistration-jyRGbC9w.js → syncWebMcpRegistration-DNLnQ-jz.js} +3 -2
  129. package/dist/lib/{syncWebMcpRegistration-jyRGbC9w.js.map → syncWebMcpRegistration-DNLnQ-jz.js.map} +1 -1
  130. package/dist/lib/tools-DwwB9RBa.js +546 -0
  131. package/dist/lib/tools-DwwB9RBa.js.map +1 -0
  132. package/dist/lib/{trusted-types-CkLDpLiZ.js → trusted-types-Dx0RZlrd.js} +19 -8
  133. package/dist/lib/trusted-types-Dx0RZlrd.js.map +1 -0
  134. package/dist/lib/utils/index.js +1 -1
  135. package/dist/lib/utils/utils.js +1 -1
  136. package/dist/public/.well-known/agent-skills/index.json +14 -0
  137. package/dist/public/AGENTS.md +5 -3
  138. package/dist/public/README.md +5 -3
  139. package/dist/public/agent.worker.js +1 -1
  140. package/dist/public/{configurePeerJs-COcwE0E7.js → configurePeerJs-BqgeBjP7.js} +1 -1
  141. package/dist/public/custom-element-security-FU04Cq05.js +1 -0
  142. package/dist/public/dist-B9m1QM9v.js +58 -0
  143. package/dist/public/docs/README.md +31 -31
  144. package/dist/public/docs/example/article/index.html +1 -1
  145. package/dist/public/docs/publishing/index.html +1 -1
  146. package/dist/public/docs/skill-creator/index.html +1 -1
  147. package/dist/public/docs/subsystems/a2ui.md +11 -1
  148. package/dist/public/docs/subsystems/cli.md +29 -0
  149. package/dist/public/docs/subsystems/control-plane.md +8 -2
  150. package/dist/public/docs/subsystems/custom-element-security.md +19 -9
  151. package/dist/public/docs/subsystems/mcp-server.md +39 -15
  152. package/dist/public/docs/subsystems/skills.md +30 -0
  153. package/dist/public/docs/subsystems/webmcp.md +9 -0
  154. package/dist/public/downloadGroupFile-D8KRJGGL.js +1 -0
  155. package/dist/public/e2e/README.md +7 -4
  156. package/dist/public/{e2e-bridge-CHARpbpW.js → e2e-bridge-Ceqr5kGc.js} +1 -1
  157. package/dist/public/effect-BJCrpFdp.js +1 -0
  158. package/dist/public/file-viewer-C-6Jc_tb.js +1 -0
  159. package/dist/public/index.html +1 -1
  160. package/dist/public/index.js +1 -1
  161. package/dist/public/initControlPlane-BN9cWyO0.js +1 -0
  162. package/dist/public/main/index.html +1 -1
  163. package/dist/public/main/memory/index.html +1 -1
  164. package/dist/public/{markdown-1I3O6Mmd.js → markdown-C3M4OW_A.js} +1 -1
  165. package/dist/public/{orchestrator-Cl95w2vb.js → orchestrator-CMbCTjBf.js} +7 -7
  166. package/dist/public/{orchestrator-D-xlXG92.js → orchestrator-DHjdLtqa.js} +663 -663
  167. package/dist/public/peerjs-DUCKH-m9.js +1 -0
  168. package/dist/public/service-worker.js +1 -1
  169. package/dist/public/{shadow-claw-CaoKmIIB.js → shadow-claw-EAt2ml5Y.js} +3 -3
  170. package/dist/public/{shadow-claw-accounts-CJvYC4li.js → shadow-claw-accounts-xUOLBsQZ.js} +1 -1
  171. package/dist/public/{shadow-claw-channels-3K62sU5f.js → shadow-claw-channels-XsfuWFF8.js} +4 -4
  172. package/dist/public/{shadow-claw-chat-Cu2keU2I.js → shadow-claw-chat-CbSaOZ4q.js} +7 -7
  173. package/dist/public/{shadow-claw-control-plane-D1OwlQI_.js → shadow-claw-control-plane-DHvN3Ukg.js} +2 -2
  174. package/dist/public/{shadow-claw-conversations-DDtg3BEZ.js → shadow-claw-conversations-BWs5VVfs.js} +2 -2
  175. package/dist/public/{shadow-claw-file-viewer-BR__1z9S.js → shadow-claw-file-viewer-BWsoW5QS.js} +5 -4
  176. package/dist/public/{shadow-claw-files-BJSyZ-Bl.js → shadow-claw-files-CG7MqWiV.js} +8 -8
  177. package/dist/public/{shadow-claw-git-MAjhXRLc.js → shadow-claw-git-DBRPZNav.js} +6 -6
  178. package/dist/public/{shadow-claw-integrations-82UoFuDR.js → shadow-claw-integrations-BBVnO0Fc.js} +8 -8
  179. package/dist/public/{shadow-claw-llm-R8j0lwPP.js → shadow-claw-llm-DMvLgKXo.js} +2 -2
  180. package/dist/public/{shadow-claw-mcp-remote-BzZoz4LX.js → shadow-claw-mcp-remote-Bkx0gsmF.js} +2 -2
  181. package/dist/public/{shadow-claw-networking-DLEd9cNm.js → shadow-claw-networking-Dd8Rw31D.js} +2 -2
  182. package/dist/public/{shadow-claw-notifications-1vwR7TbT.js → shadow-claw-notifications-Dbevj-lq.js} +2 -2
  183. package/dist/public/{shadow-claw-page-header-DMKbkv3s.js → shadow-claw-page-header-BccSHItx.js} +1 -1
  184. package/dist/public/{shadow-claw-pages-CjyeIV__.js → shadow-claw-pages-3_lQAv0t.js} +4 -3
  185. package/dist/public/{shadow-claw-settings-BfbT4dBU.js → shadow-claw-settings-t8TIlgrM.js} +5 -5
  186. package/dist/public/{shadow-claw-storage-C-mWQQML.js → shadow-claw-storage-CfEXoSIE.js} +2 -2
  187. package/dist/public/{shadow-claw-task-server-D3lHp0Nc.js → shadow-claw-task-server-DxQSsgRZ.js} +2 -2
  188. package/dist/public/{shadow-claw-tasks-DVVWEm-c.js → shadow-claw-tasks-DNpicQwz.js} +14 -14
  189. package/dist/public/{shadow-claw-terminal-BwuTRp-O.js → shadow-claw-terminal-DpY6zU_r.js} +1 -1
  190. package/dist/public/{shadow-claw-toast-ClCwgzFG.js → shadow-claw-toast-BkrQIP-3.js} +1 -1
  191. package/dist/public/{shadow-claw-tools-zFLk2nbV.js → shadow-claw-tools-WSwWohnk.js} +2 -2
  192. package/dist/public/{shadow-claw-webvm-qR9X7fg7.js → shadow-claw-webvm-CP6oFjg5.js} +2 -2
  193. package/dist/public/syncWebMcpRegistration-DOn9gLnD.js +1 -0
  194. package/dist/public/toast-BXgUfbyh.js +1 -0
  195. package/dist/public/tools-DvckJZG2.js +1 -0
  196. package/dist/server.js +188 -188
  197. package/package.json +3 -1
  198. package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.stories.ts +1380 -93
  199. package/src/components/shadow-claw-a2ui/shadow-claw-a2ui.ts +11 -6
  200. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +8 -1
  201. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +13 -5
  202. package/src/components/shadow-claw-pages/utils/buildHtmlPageSrcdoc.ts +13 -5
  203. package/src/core/control-plane-client.ts +15 -0
  204. package/src/core/utils/initControlPlane.test.ts +187 -0
  205. package/src/core/utils/initControlPlane.ts +194 -20
  206. package/src/security/custom-element-security.test.ts +51 -0
  207. package/src/security/custom-element-security.ts +33 -15
  208. package/src/server/control-plane-types.ts +1 -0
  209. package/src/server/control-plane.test.ts +69 -0
  210. package/src/server/control-plane.ts +45 -3
  211. package/src/server/mcp/tools/built-in-tools.ts +80 -5
  212. package/src/server/mcp/tools/client-tool-relay.ts +183 -26
  213. package/src/server/mcp/tools/mcp-tools.test.ts +140 -0
  214. package/src/server/middleware/static-files.test.ts +142 -0
  215. package/src/server/middleware/static-files.ts +66 -8
  216. package/src/testing/jest-setup.ts +1 -0
  217. package/src/worker/utils/handleMessage.ts +4 -1
  218. package/dist/lib/initControlPlane-CsO4UR6_.js.map +0 -1
  219. package/dist/lib/readGroupFileBytes-Bve-e5e_.js.map +0 -1
  220. package/dist/lib/shadow-claw-file-viewer-BfDHHgpA.js.map +0 -1
  221. package/dist/lib/shadow-claw-pages-D54jF1Qq.js.map +0 -1
  222. package/dist/lib/trusted-types-CkLDpLiZ.js.map +0 -1
  223. package/dist/public/custom-element-security-NCqQ5lmC.js +0 -1
  224. package/dist/public/downloadGroupFile-G0BZQgQg.js +0 -1
  225. package/dist/public/effect-rHYr4nfu.js +0 -1
  226. package/dist/public/file-viewer-8PdCURDD.js +0 -1
  227. package/dist/public/initControlPlane-CcGXax0A.js +0 -1
  228. package/dist/public/peerjs-BZdxWQFv.js +0 -1
  229. package/dist/public/syncWebMcpRegistration-DD42YsYV.js +0 -1
  230. package/dist/public/toast-HAq8XWFj.js +0 -58
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-mcp-remote-CYmhpg7a.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-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,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-DCfomsn9.js";
3
+ import { _ as setUseProxy, t as orchestratorStore, u as setProxyUrl } from "./orchestrator-KRjx0eba.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-DImPxe0H.js.map
236
+ //# sourceMappingURL=shadow-claw-networking-Df85tCbO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-networking-DImPxe0H.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-Df85tCbO.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,5 +1,5 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
- import { n as setSanitizedHtml } from "./trusted-types-CkLDpLiZ.js";
2
+ import { n as setSanitizedHtml } from "./trusted-types-Dx0RZlrd.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-CcHUfFUx.js.map
364
+ //# sourceMappingURL=shadow-claw-page-header-Cti2fzf-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-page-header-CcHUfFUx.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-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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"}
@@ -4,18 +4,19 @@ import { t as Signal } from "./dist-Bxg3C_zy.js";
4
4
  import { r as CONFIG_KEYS } from "./config--CFrw3J3.js";
5
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";
6
6
  import { t as getConfig } from "./getConfig-BxxXMyuM.js";
7
- import { t as readGroupFileBytes } from "./readGroupFileBytes-Bve-e5e_.js";
8
- import { bn as readGroupFile, ln as toolsStore, nn as writeGroupFile, r as getStaticPageContent, t as orchestratorStore } from "./orchestrator-DCfomsn9.js";
9
- import { t as fileViewerStore } from "./file-viewer-BrK2Wxgh.js";
10
- import { _ as getIframeSandboxPolicy, b as isAllowedCustomElement, g as getIframeCsp, h as getApprovedCustomElementScripts, n as setSanitizedHtml, r as setTrustedSrcdoc, t as sanitizeSrcdocHtml } from "./trusted-types-CkLDpLiZ.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-KRjx0eba.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";
11
12
  import { t as require_buffer } from "./buffer-BEXn271X.js";
12
13
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-DZ6r7_YI.js";
13
14
  import { getNamespacedItem, removeNamespacedItem, setNamespacedItem } from "./utils/namespacedStorage.js";
14
15
  import { t as effect } from "./effect-DL6j9HJp.js";
15
- import { n as splitFrontmatter, t as renderMarkdown } from "./markdown-eeSTFnMA.js";
16
+ import { n as splitFrontmatter, t as renderMarkdown } from "./markdown-C6EHl9zs.js";
16
17
  import { t as isTruthyConfigValue } from "./config-value-Cxggje2K.js";
17
18
  import "./shadow-claw-page-header-action-button-BXXm5b5N.js";
18
- import "./shadow-claw-page-header-CcHUfFUx.js";
19
+ import "./shadow-claw-page-header-Cti2fzf-.js";
19
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";
20
21
 
21
22
  //#region src/components/shadow-claw-pages/utils/announcePageChange.ts
@@ -133,13 +134,16 @@ async function buildHtmlPageSrcdoc({ content, filePath, searchParams = "", group
133
134
  const nonce = crypto.randomUUID().replace(/-/g, "");
134
135
  const bridgeScriptUrl = applyBasePath("/assets/file-viewer-preview-bridge.js");
135
136
  const storageBridgeScriptUrl = applyBasePath("/assets/iframe-storage-bridge.js");
136
- const approvedScripts = getApprovedCustomElementScripts();
137
+ const approvedScripts = getApprovedCustomElementScriptDescriptors();
137
138
  const cspContent = getIframeCsp(nonce);
138
139
  const configScript = typeof document !== "undefined" ? document.getElementById("shadow-claw-site-config") : null;
139
140
  const siteConfigHtml = configScript && configScript.textContent ? `<script id="shadow-claw-site-config" type="application/json">${configScript.textContent}<\/script>` : "";
140
- const searchScriptHtml = searchParams ? `<script nonce="${nonce}">(function(){try{Object.defineProperty(window.location,"search",{get:function(){return ${JSON.stringify(searchParams)};},configurable:true});}catch(e){}})();<\/script>` : "";
141
- const customElementScriptsHtml = approvedScripts.map((src) => {
142
- return `<script type="module" src="${src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//") ? src : applyBasePath(src.startsWith("/") ? src : `/${src.replace(/^pages\/main\//, "")}`)}" nonce="${nonce}"><\/script>`;
141
+ const searchScriptHtml = searchParams ? `<script nonce="${nonce}">(function(){try{Object.defineProperty(globalThis.location,"search",{get:function(){return ${JSON.stringify(searchParams)};},configurable:true});}catch(e){}})();<\/script>` : "";
142
+ const customElementScriptsHtml = approvedScripts.map(({ src, hasInit }) => {
143
+ const resolvedSrc = src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//") ? src : applyBasePath(src.startsWith("/") ? src : `/${src.replace(/^pages\/main\//, "")}`);
144
+ const tags = [`<script type="module" src="${resolvedSrc}" nonce="${nonce}"><\/script>`];
145
+ if (hasInit) tags.push(`<script type="module" nonce="${nonce}">import("${resolvedSrc}").then((m) => { try { if (typeof m?.init === "function") m.init(); } catch (e) { console.error("[ShadowClaw] Error executing init for " + ${JSON.stringify(resolvedSrc)}, e); } }).catch(() => {});<\/script>`);
146
+ return tags.join("\n");
143
147
  }).join("\n");
144
148
  const themeStylesheetLink = `<link rel="stylesheet" href="${applyBasePath("/theme.css")}">`;
145
149
  return [
@@ -2303,4 +2307,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
2303
2307
 
2304
2308
  //#endregion
2305
2309
  export { ShadowClawPages as t };
2306
- //# sourceMappingURL=shadow-claw-pages-D54jF1Qq.js.map
2310
+ //# sourceMappingURL=shadow-claw-pages-BgPyIEZO.js.map