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-integrations-NbcCx_ZI.js","names":["shadowClawIntegrationsStyles","shadowClawIntegrationsTemplate"],"sources":["../../src/components/settings/shadow-claw-integrations/connection-test-auth.ts","../../src/components/settings/shadow-claw-integrations/shadow-claw-integrations.ts"],"sourcesContent":["import type {\n ResolveConnectionTestAuthInput,\n ResolveConnectionTestAuthResult,\n} from \"../../types.js\";\n\nexport function resolveConnectionTestAuth(\n input: ResolveConnectionTestAuthInput,\n): ResolveConnectionTestAuthResult {\n if (input.authMode === \"oauth\") {\n const accessToken = (input.pendingOauthAccessToken || \"\").trim();\n if (accessToken) {\n return {\n authType: \"oauth\",\n accessToken,\n };\n }\n\n return {\n error:\n \"OAuth access token is missing. Click Connect OAuth first (or save and reconnect).\",\n };\n }\n\n const password = (input.passwordInput || \"\").trim();\n if (password) {\n return {\n authType: \"basic_userpass\",\n password,\n };\n }\n\n return {\n error:\n \"Password/app password is missing. Enter it to test this connection.\",\n };\n}\n","import { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\nimport { encryptValue } from \"../../../security/crypto.js\";\nimport { setSanitizedHtml } from \"../../../security/trusted-types.js\";\n\nimport {\n getEmailPluginManifest,\n listEmailPluginManifests,\n} from \"../../../subsystems/email/catalog.js\";\n\nimport {\n bindEmailCredentialRef,\n deleteEmailConnection,\n listEmailConnections,\n upsertEmailConnection,\n} from \"../../../subsystems/email/connections.js\";\n\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { resolveConnectionTestAuth } from \"./connection-test-auth.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { ServiceAccount } from \"../../../subsystems/accounts/service-accounts.js\";\nimport type { EmailPluginManifest } from \"../../../subsystems/email/catalog.js\";\nimport type {\n EmailConnectionRecord,\n EmailCredentialRef,\n} from \"../../../subsystems/email/connections.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawIntegrationsStyles from \"./shadow-claw-integrations.css\" with { type: \"css\" };\nimport shadowClawIntegrationsTemplate from \"./shadow-claw-integrations.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-integrations\";\n\ninterface ImapPreset {\n imapHost: string;\n imapPort: number;\n imapSecure: boolean;\n smtpHost: string;\n smtpPort: number;\n smtpSecure: boolean;\n}\n\ninterface EmailOAuthProviderConfig {\n id: string;\n label: string;\n serviceName: string;\n hostPattern: string;\n defaultScopes: string[];\n scopePlaceholder: string;\n scopeHelpText: string;\n connectButtonLabel: string;\n}\n\nconst EMAIL_OAUTH_PROVIDERS: Record<string, EmailOAuthProviderConfig> = {\n google: {\n id: \"google\",\n label: \"Gmail (Google OAuth)\",\n serviceName: \"Google\",\n hostPattern: \"gmail.com\",\n defaultScopes: [\"https://mail.google.com/\"],\n scopePlaceholder: \"https://mail.google.com/\",\n scopeHelpText: \"Use https://mail.google.com/ for Gmail IMAP/SMTP access.\",\n connectButtonLabel: \"Connect Google OAuth\",\n },\n microsoft_graph: {\n id: \"microsoft_graph\",\n label: \"Microsoft (Outlook / M365 OAuth)\",\n serviceName: \"Microsoft\",\n hostPattern: \"outlook.office365.com\",\n defaultScopes: [\n \"offline_access\",\n \"https://outlook.office.com/IMAP.AccessAsUser.All\",\n \"https://outlook.office.com/SMTP.Send\",\n ],\n scopePlaceholder:\n \"offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send\",\n scopeHelpText:\n \"For Outlook/M365 IMAP+SMTP, include offline_access plus IMAP.AccessAsUser.All and SMTP.Send scopes.\",\n connectButtonLabel: \"Connect Microsoft OAuth\",\n },\n yahoo_mail: {\n id: \"yahoo_mail\",\n label: \"Yahoo Mail OAuth\",\n serviceName: \"Yahoo\",\n hostPattern: \"mail.yahoo.com\",\n defaultScopes: [\"mail-r\", \"mail-w\"],\n scopePlaceholder: \"mail-r mail-w\",\n scopeHelpText:\n \"Yahoo commonly uses mail-r and mail-w scopes for IMAP/SMTP style access.\",\n connectButtonLabel: \"Connect Yahoo OAuth\",\n },\n};\n\nconst IMAP_PRESETS: Record<string, ImapPreset> = {\n gmail: {\n imapHost: \"imap.gmail.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.gmail.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n outlook: {\n imapHost: \"outlook.office365.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.office365.com\",\n smtpPort: 587,\n smtpSecure: false,\n },\n yahoo: {\n imapHost: \"imap.mail.yahoo.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.mail.yahoo.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n icloud: {\n imapHost: \"imap.mail.me.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.mail.me.com\",\n smtpPort: 587,\n smtpSecure: false,\n },\n fastmail: {\n imapHost: \"imap.fastmail.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.fastmail.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n};\n\nconst IMAP_FIELD_LABELS: Record<string, string> = {\n host: \"IMAP host\",\n port: \"IMAP port\",\n secure: \"IMAP TLS\",\n mailboxPath: \"Mailbox path\",\n smtpHost: \"SMTP host\",\n smtpPort: \"SMTP port\",\n smtpSecure: \"SMTP TLS\",\n fromAddress: \"From address\",\n executionMode: \"Execution mode\",\n pollIntervalSec: \"Poll interval (seconds)\",\n};\n\nconst IMAP_FIELD_PLACEHOLDERS: Record<string, string> = {\n host: \"imap.example.com\",\n port: \"993\",\n mailboxPath: \"INBOX\",\n smtpHost: \"smtp.example.com\",\n smtpPort: \"465\",\n fromAddress: \"you@example.com\",\n pollIntervalSec: \"300\",\n};\n\nexport class ShadowClawIntegrations extends ShadowClawElement {\n static styles = shadowClawIntegrationsStyles;\n static template = shadowClawIntegrationsTemplate;\n\n accounts: ServiceAccount[] = [];\n connections: EmailConnectionRecord[] = [];\n\n db: ShadowClawDatabase | null = null;\n editingConnectionId: string | null = null;\n manifests: EmailPluginManifest[] = [];\n pendingOauthResult: {\n providerId: string;\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n scope?: string;\n tokenType?: string;\n } | null = null;\n\n async connectedCallback() {\n this.db = await getDb();\n this.bindEventListeners();\n await this.reload();\n }\n\n applyImapPreset(slot: Element) {\n const presetSelect = slot.querySelector(\n \"#int-imap-preset\",\n ) as HTMLSelectElement | null;\n const usernameInput = slot.querySelector(\n \"#int-username\",\n ) as HTMLInputElement | null;\n\n const selectedPreset = presetSelect?.value || \"auto\";\n const preset = this.resolveImapPreset(\n selectedPreset,\n usernameInput?.value || \"\",\n );\n if (!preset) {\n showError(\n \"Could not auto-detect IMAP settings from this email domain. Choose a preset or enter settings manually.\",\n 5000,\n );\n\n return;\n }\n\n this.setConfigFieldValue(slot, \"host\", preset.imapHost);\n this.setConfigFieldValue(slot, \"port\", String(preset.imapPort));\n this.setConfigFieldValue(slot, \"secure\", String(preset.imapSecure));\n this.setConfigFieldValue(slot, \"smtpHost\", preset.smtpHost);\n this.setConfigFieldValue(slot, \"smtpPort\", String(preset.smtpPort));\n this.setConfigFieldValue(slot, \"smtpSecure\", String(preset.smtpSecure));\n\n const fromAddress = (usernameInput?.value || \"\").trim();\n if (fromAddress) {\n this.setConfigFieldValue(slot, \"fromAddress\", fromAddress);\n }\n\n const mailboxInput = slot.querySelector(\n \"#cfg-mailboxPath\",\n ) as HTMLInputElement | null;\n if (mailboxInput && !mailboxInput.value.trim()) {\n mailboxInput.value = \"INBOX\";\n }\n\n showSuccess(\"Applied IMAP preset defaults\", 2500);\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.showForm(null));\n }\n\n escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\\\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n }\n\n getEmailOAuthProvider(\n providerId: string | undefined,\n ): EmailOAuthProviderConfig {\n if (providerId && EMAIL_OAUTH_PROVIDERS[providerId]) {\n return EMAIL_OAUTH_PROVIDERS[providerId];\n }\n\n return EMAIL_OAUTH_PROVIDERS.google;\n }\n\n getInitialPluginId(existing: EmailConnectionRecord | null): string {\n if (existing?.pluginId) {\n return existing.pluginId;\n }\n\n if (this.manifests.some((item) => item.id === \"imap\")) {\n return \"imap\";\n }\n\n return this.manifests[0]?.id || \"\";\n }\n\n renderConfigFieldRows(\n manifest: EmailPluginManifest,\n cfg: Record<string, unknown>,\n ): string {\n return manifest.configurableFields\n .map((field) => {\n const value = cfg[field];\n const displayLabel =\n manifest.id === \"imap\" ? (IMAP_FIELD_LABELS[field] ?? field) : field;\n\n if (field === \"secure\" || field === \"smtpSecure\") {\n const selected = typeof value === \"boolean\" ? value : true;\n\n return `\n <div class=\"form-row\">\n <label for=\"cfg-${this.escapeHtml(field)}\">${this.escapeHtml(displayLabel)}</label>\n <select id=\"cfg-${this.escapeHtml(field)}\" data-config-field=\"${this.escapeHtml(field)}\">\n <option value=\"true\" ${selected ? \"selected\" : \"\"}>enabled</option>\n <option value=\"false\" ${selected ? \"\" : \"selected\"}>disabled</option>\n </select>\n </div>\n `;\n }\n\n const placeholder =\n manifest.id === \"imap\" ? (IMAP_FIELD_PLACEHOLDERS[field] ?? \"\") : \"\";\n\n return `\n <div class=\"form-row\">\n <label for=\"cfg-${this.escapeHtml(field)}\">${this.escapeHtml(displayLabel)}</label>\n <input\n id=\"cfg-${this.escapeHtml(field)}\"\n data-config-field=\"${this.escapeHtml(field)}\"\n value=\"${this.escapeHtml(typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? String(value) : \"\")}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n />\n </div>\n `;\n })\n .join(\"\");\n }\n\n renderConnectionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector('[data-region=\"connection-list\"]');\n if (!list) {\n return;\n }\n\n list.replaceChildren();\n\n if (!this.connections.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"empty\";\n empty.textContent =\n \"No email connections configured. Click Add Email Connection to start.\";\n list.append(empty);\n\n return;\n }\n\n const fragment = document.createDocumentFragment();\n\n for (const connection of this.connections) {\n const manifest = getEmailPluginManifest(connection.pluginId);\n const card = document.createElement(\"article\");\n card.className = \"connection-card\";\n\n const executionMode =\n typeof connection.config.executionMode === \"string\"\n ? connection.config.executionMode\n : \"manual\";\n const pollIntervalSec =\n typeof connection.config.pollIntervalSec === \"number\"\n ? connection.config.pollIntervalSec\n : null;\n const hasAuth =\n !!connection.credentialRef?.encryptedSecret ||\n (connection.credentialRef?.authType === \"oauth\" &&\n !!connection.credentialRef?.accountId);\n\n setSanitizedHtml(\n card,\n `\n <header>\n <div>\n <div class=\"connection-title\">${this.escapeHtml(connection.label)}</div>\n <div class=\"connection-meta\">\n ${this.escapeHtml(connection.pluginId)}${manifest ? ` · ${this.escapeHtml(manifest.name)}` : \"\"}\n </div>\n </div>\n <span class=\"connection-badge ${connection.enabled ? \"enabled\" : \"disabled\"}\">\n ${connection.enabled ? \"Enabled\" : \"Disabled\"}\n </span>\n </header>\n <div class=\"connection-meta\">Mode: ${this.escapeHtml(String(executionMode))}${pollIntervalSec ? ` · Poll: ${pollIntervalSec}s` : \"\"}${hasAuth ? \" · Auth: configured\" : \" · Auth: missing\"}</div>\n <div class=\"connection-actions\">\n <button class=\"btn secondary\" data-action=\"edit\" data-id=\"${this.escapeHtml(connection.id)}\">Edit</button>\n <button class=\"btn secondary\" data-action=\"toggle\" data-id=\"${this.escapeHtml(connection.id)}\">${connection.enabled ? \"Disable\" : \"Enable\"}</button>\n <button class=\"btn secondary\" data-action=\"delete\" data-id=\"${this.escapeHtml(connection.id)}\">Delete</button>\n </div>\n `,\n );\n\n card\n .querySelectorAll<HTMLButtonElement>(\"button[data-action]\")\n .forEach((button) => {\n button.addEventListener(\"click\", () => {\n const action = button.dataset.action;\n const id = button.dataset.id;\n if (!action || !id) {\n return;\n }\n\n if (action === \"edit\") {\n this.showForm(id);\n } else if (action === \"toggle\") {\n void this.toggleConnection(id);\n } else if (action === \"delete\") {\n void this.deleteConnection(id);\n }\n });\n });\n\n fragment.append(card);\n }\n\n list.append(fragment);\n }\n\n resolveImapPreset(selection: string, username: string): ImapPreset | null {\n if (selection !== \"auto\") {\n return IMAP_PRESETS[selection] || null;\n }\n\n const domain = username.split(\"@\")[1]?.trim().toLowerCase() || \"\";\n if (!domain) {\n return null;\n }\n\n if (\n domain === \"gmail.com\" ||\n domain.endsWith(\".gmail.com\") ||\n domain.endsWith(\".googlemail.com\")\n ) {\n return IMAP_PRESETS.gmail;\n }\n\n if (\n domain === \"outlook.com\" ||\n domain === \"hotmail.com\" ||\n domain === \"live.com\" ||\n domain === \"msn.com\" ||\n domain.endsWith(\".onmicrosoft.com\")\n ) {\n return IMAP_PRESETS.outlook;\n }\n\n if (domain === \"yahoo.com\" || domain.endsWith(\".yahoo.com\")) {\n return IMAP_PRESETS.yahoo;\n }\n\n if (\n domain === \"icloud.com\" ||\n domain === \"me.com\" ||\n domain === \"mac.com\"\n ) {\n return IMAP_PRESETS.icloud;\n }\n\n if (domain === \"fastmail.com\" || domain.endsWith(\".fastmail.com\")) {\n return IMAP_PRESETS.fastmail;\n }\n\n return null;\n }\n\n setConfigFieldValue(slot: Element, field: string, value: string) {\n const node = slot.querySelector(`#cfg-${field}`) as\n | HTMLInputElement\n | HTMLSelectElement\n | null;\n if (!node) {\n return;\n }\n\n node.value = value;\n }\n\n showForm(connectionId: string | null) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form\"]');\n if (!slot) {\n return;\n }\n\n this.editingConnectionId = connectionId;\n const existing = connectionId\n ? this.connections.find((item) => item.id === connectionId) || null\n : null;\n\n const pluginId = this.getInitialPluginId(existing);\n const manifest = getEmailPluginManifest(pluginId);\n\n const cfg = existing?.config || {};\n const linkedOauthAccount = existing?.credentialRef?.accountId\n ? this.accounts.find(\n (account) => account.id === existing.credentialRef?.accountId,\n ) || null\n : null;\n const executionMode =\n typeof cfg.executionMode === \"string\"\n ? String(cfg.executionMode)\n : \"manual\";\n const pollIntervalSec =\n typeof cfg.pollIntervalSec === \"number\" ? cfg.pollIntervalSec : 300;\n const authMode =\n existing?.credentialRef?.authType === \"oauth\"\n ? \"oauth\"\n : \"basic_userpass\";\n const oauthProviderId =\n existing?.credentialRef?.providerId ||\n linkedOauthAccount?.oauthProviderId ||\n \"google\";\n const oauthProvider = this.getEmailOAuthProvider(oauthProviderId);\n const oauthClientId = linkedOauthAccount?.oauthClientId || \"\";\n const oauthScope =\n linkedOauthAccount?.scopes?.join(\" \") ||\n oauthProvider.defaultScopes.join(\" \");\n const oauthStatus =\n authMode === \"oauth\"\n ? linkedOauthAccount?.oauthReauthRequired\n ? \"Reconnect required\"\n : linkedOauthAccount?.token\n ? \"OAuth token already saved\"\n : \"Not connected\"\n : \"Not connected\";\n\n const isImapPlugin = pluginId === \"imap\";\n setSanitizedHtml(\n slot,\n `\n <h4>${existing ? \"Edit Email Connection\" : \"Add Email Connection\"}</h4>\n <div class=\"form-row\">\n <label for=\"int-label\">Label</label>\n <input id=\"int-label\" value=\"${this.escapeHtml(existing?.label || \"\")}\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-mode\">Execution mode</label>\n <select id=\"int-mode\">\n <option value=\"manual\" ${executionMode === \"manual\" ? \"selected\" : \"\"}>manual</option>\n <option value=\"scheduled\" ${executionMode === \"scheduled\" ? \"selected\" : \"\"}>scheduled</option>\n <option value=\"event-driven\" ${executionMode === \"event-driven\" ? \"selected\" : \"\"}>event-driven</option>\n </select>\n </div>\n <div class=\"form-row\">\n <label for=\"int-poll\">Poll interval (seconds)</label>\n <input id=\"int-poll\" type=\"number\" min=\"5\" value=\"${this.escapeHtml(String(pollIntervalSec))}\" />\n </div>\n <div class=\"form-row checkbox-row\">\n <label class=\"checkbox-inline\" for=\"int-unread-only\">\n <input id=\"int-unread-only\" type=\"checkbox\" ${cfg.unreadOnly === true ? \"checked\" : \"\"} />\n <span>Get unread email only</span>\n </label>\n </div>\n <div class=\"form-row\">\n <label for=\"int-username\">Auth username (email login)</label>\n <input id=\"int-username\" value=\"${this.escapeHtml(existing?.credentialRef?.username || \"\")}\" placeholder=\"user@example.com\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-auth-mode\">Authentication</label>\n <select id=\"int-auth-mode\">\n <option value=\"basic_userpass\" ${authMode === \"basic_userpass\" ? \"selected\" : \"\"}>App password / password</option>\n <option value=\"oauth\" ${authMode === \"oauth\" ? \"selected\" : \"\"}>OAuth</option>\n </select>\n </div>\n <div data-region=\"password-auth-fields\">\n <div class=\"form-row\">\n <label for=\"int-password\">Auth password / app password</label>\n <input id=\"int-password\" type=\"password\" placeholder=\"${existing?.credentialRef?.encryptedSecret ? \"•••••••••••• (Saved)\" : \"Enter password\"}\" />\n </div>\n </div>\n <div class=\"oauth-auth-card\" data-region=\"oauth-auth-fields\">\n <div class=\"imap-setup-title\">Email OAuth</div>\n <div class=\"form-row\">\n <label for=\"int-oauth-provider\">OAuth provider</label>\n <select id=\"int-oauth-provider\">\n ${Object.values(EMAIL_OAUTH_PROVIDERS)\n .map(\n (provider) =>\n `<option value=\"${this.escapeHtml(provider.id)}\" ${provider.id === oauthProvider.id ? \"selected\" : \"\"}>${this.escapeHtml(provider.label)}</option>`,\n )\n .join(\"\")}\n </select>\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-client-id\">OAuth client ID</label>\n <input id=\"int-oauth-client-id\" value=\"${this.escapeHtml(oauthClientId)}\" placeholder=\"Enter OAuth client ID\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-client-secret\">OAuth client secret</label>\n <input id=\"int-oauth-client-secret\" type=\"password\" placeholder=\"${linkedOauthAccount?.oauthClientSecret ? \"•••••••••••• (Saved)\" : \"Enter client secret if required\"}\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-scope\">OAuth scope</label>\n <input id=\"int-oauth-scope\" value=\"${this.escapeHtml(oauthScope)}\" placeholder=\"${this.escapeHtml(oauthProvider.scopePlaceholder)}\" />\n <div class=\"imap-setup-help\" data-region=\"oauth-scope-help\">${this.escapeHtml(oauthProvider.scopeHelpText)}</div>\n </div>\n <div class=\"oauth-connect-row\">\n <button class=\"btn secondary\" type=\"button\" data-action=\"connect-oauth\">${this.escapeHtml(oauthProvider.connectButtonLabel)}</button>\n <span class=\"oauth-status\" data-region=\"oauth-status\">${this.escapeHtml(oauthStatus)}</span>\n </div>\n </div>\n ${\n isImapPlugin\n ? `<div class=\"imap-setup-card\">\n <div class=\"imap-setup-title\">Quick IMAP Setup</div>\n <div class=\"imap-setup-row\">\n <select id=\"int-imap-preset\">\n <option value=\"auto\" selected>Auto-detect from login email</option>\n <option value=\"gmail\">Gmail / Google Workspace</option>\n <option value=\"outlook\">Outlook / Microsoft 365</option>\n <option value=\"yahoo\">Yahoo</option>\n <option value=\"icloud\">iCloud</option>\n <option value=\"fastmail\">Fastmail</option>\n </select>\n <button class=\"btn secondary\" type=\"button\" data-action=\"imap-autofill\">Autofill</button>\n </div>\n <div class=\"imap-setup-help\">Uses common provider defaults. You can still override any field below.</div>\n </div>`\n : \"\"\n }\n\n ${manifest ? this.renderConfigFieldRows(manifest, cfg) : \"\"}\n\n <div class=\"form-row\">\n <label for=\"int-extra-config\">Extra config JSON (optional)</label>\n <textarea id=\"int-extra-config\" placeholder='{\"mailboxPath\":\"INBOX\"}'></textarea>\n </div>\n <div class=\"form-actions\">\n <button class=\"btn secondary\" data-action=\"cancel\">Cancel</button>\n <button class=\"btn secondary\" data-action=\"test-connection\">Test Connection</button>\n <button class=\"btn\" data-action=\"save\">Save</button>\n </div>\n `,\n );\n\n const formNode = slot as HTMLElement;\n formNode.hidden = false;\n\n this.pendingOauthResult = null;\n\n slot\n .querySelector(\"#int-auth-mode\")\n ?.addEventListener(\"change\", () => this.updateAuthModeVisibility(slot));\n\n slot\n .querySelector('[data-action=\"imap-autofill\"]')\n ?.addEventListener(\"click\", () => this.applyImapPreset(slot));\n slot\n .querySelector('[data-action=\"connect-oauth\"]')\n ?.addEventListener(\"click\", () => void this.connectOAuthFromForm(slot));\n slot\n .querySelector(\"#int-oauth-provider\")\n ?.addEventListener(\"change\", () => this.updateOAuthProviderHelp(slot));\n\n slot\n .querySelector('[data-action=\"cancel\"]')\n ?.addEventListener(\"click\", () => {\n formNode.hidden = true;\n formNode.replaceChildren();\n this.editingConnectionId = null;\n });\n\n slot\n .querySelector('[data-action=\"save\"]')\n ?.addEventListener(\"click\", () => {\n void this.saveForm();\n });\n\n slot\n .querySelector('[data-action=\"test-connection\"]')\n ?.addEventListener(\"click\", () => {\n void this.testConnectionFromForm(slot);\n });\n\n this.updateAuthModeVisibility(slot);\n this.updateOAuthProviderHelp(slot);\n }\n\n updateAuthModeVisibility(slot: Element) {\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n\n const passwordFields = slot.querySelector(\n '[data-region=\"password-auth-fields\"]',\n ) as HTMLElement | null;\n const oauthFields = slot.querySelector(\n '[data-region=\"oauth-auth-fields\"]',\n ) as HTMLElement | null;\n\n if (passwordFields) {\n passwordFields.style.display = authMode === \"oauth\" ? \"none\" : \"block\";\n }\n\n if (oauthFields) {\n oauthFields.style.display = authMode === \"oauth\" ? \"block\" : \"none\";\n }\n }\n\n updateOAuthProviderHelp(slot: Element) {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const provider = this.getEmailOAuthProvider(providerId);\n\n const scopeInput = slot.querySelector(\n \"#int-oauth-scope\",\n ) as HTMLInputElement | null;\n const scopeHelp = slot.querySelector(\n '[data-region=\"oauth-scope-help\"]',\n ) as HTMLElement | null;\n const connectBtn = slot.querySelector(\n '[data-action=\"connect-oauth\"]',\n ) as HTMLButtonElement | null;\n\n if (scopeInput) {\n scopeInput.placeholder = provider.scopePlaceholder;\n if (!scopeInput.value.trim()) {\n scopeInput.value = provider.defaultScopes.join(\" \");\n }\n }\n\n if (scopeHelp) {\n scopeHelp.textContent = provider.scopeHelpText;\n }\n\n if (connectBtn) {\n connectBtn.textContent = provider.connectButtonLabel;\n }\n }\n\n async buildCredentialRef(\n slot: Element,\n savedConnection: EmailConnectionRecord,\n ): Promise<EmailCredentialRef | null> {\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n const usernameInput = slot.querySelector(\n \"#int-username\",\n ) as HTMLInputElement | null;\n const passwordInput = slot.querySelector(\n \"#int-password\",\n ) as HTMLInputElement | null;\n\n const username = usernameInput?.value.trim() || \"\";\n const passwordRaw = passwordInput?.value.trim() || \"\";\n\n const existing = this.connections.find(\n (item) => item.id === savedConnection.id,\n );\n\n if (authMode === \"oauth\") {\n if (!username) {\n throw new Error(\n \"Email login address is required for OAuth authentication.\",\n );\n }\n\n const linkedAccount = await this.upsertLinkedOAuthAccount(\n slot,\n savedConnection,\n );\n\n return {\n serviceType: \"http_api\",\n authType: \"oauth\",\n providerId: linkedAccount.oauthProviderId || \"google\",\n accountId: linkedAccount.id,\n username,\n };\n }\n\n let encryptedSecret: string | undefined;\n if (passwordRaw) {\n encryptedSecret = (await encryptValue(passwordRaw)) || undefined;\n if (!encryptedSecret) {\n throw new Error(\"Could not encrypt email password.\");\n }\n } else {\n encryptedSecret = existing?.credentialRef?.encryptedSecret;\n }\n\n if (!username && !encryptedSecret) {\n return null;\n }\n\n if (!username) {\n throw new Error(\n \"Auth username is required when a password is configured.\",\n );\n }\n\n if (!encryptedSecret) {\n throw new Error(\"Auth password is required when username is configured.\");\n }\n\n return {\n serviceType: \"http_api\",\n authType: \"basic_userpass\",\n username,\n encryptedSecret,\n };\n }\n\n async connectOAuthFromForm(slot: Element) {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const provider = this.getEmailOAuthProvider(providerId);\n const clientId = (\n slot.querySelector(\"#int-oauth-client-id\") as HTMLInputElement | null\n )?.value.trim();\n const clientSecret = (\n slot.querySelector(\"#int-oauth-client-secret\") as HTMLInputElement | null\n )?.value.trim();\n const scopeRaw = (\n slot.querySelector(\"#int-oauth-scope\") as HTMLInputElement | null\n )?.value.trim();\n const oauthStatus = slot.querySelector(\n '[data-region=\"oauth-status\"]',\n ) as HTMLElement | null;\n const connectBtn = slot.querySelector(\n '[data-action=\"connect-oauth\"]',\n ) as HTMLButtonElement | null;\n\n if (!clientId) {\n showError(\"OAuth client ID is required.\", 4000);\n\n return;\n }\n\n if (oauthStatus) {\n oauthStatus.textContent = \"Starting OAuth...\";\n }\n\n if (connectBtn) {\n connectBtn.disabled = true;\n }\n\n try {\n const scope = scopeRaw\n ? scopeRaw\n .split(/[\\s,]+/)\n .map((token) => token.trim())\n .filter(Boolean)\n : provider.defaultScopes;\n const redirectUri = `${window.location.origin}/oauth/callback`;\n\n const authorizeRes = await fetch(\"/oauth/authorize\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n providerId: provider.id,\n clientId,\n clientSecret: clientSecret || undefined,\n redirectUri,\n scope,\n extraAuthorizeParams: {\n access_type: \"offline\",\n prompt: \"consent\",\n },\n }),\n });\n\n const authorizePayload = (await authorizeRes.json()) as {\n state?: string;\n authorizeUrl?: string;\n error?: string;\n };\n\n if (\n !authorizeRes.ok ||\n !authorizePayload.state ||\n !authorizePayload.authorizeUrl\n ) {\n throw new Error(authorizePayload.error || \"OAuth authorize failed\");\n }\n\n window.open(\n authorizePayload.authorizeUrl,\n \"shadowclaw-google-oauth\",\n \"popup=yes,width=540,height=720\",\n );\n\n const state = authorizePayload.state;\n let status = \"pending\";\n for (let attempt = 0; attempt < 60; attempt++) {\n const sessionRes = await fetch(\n `/oauth/session/${encodeURIComponent(state)}`,\n );\n const sessionPayload = (await sessionRes.json()) as {\n status?: string;\n error?: string;\n };\n\n if (!sessionRes.ok) {\n throw new Error(sessionPayload.error || \"OAuth session not found\");\n }\n\n status = sessionPayload.status || \"pending\";\n if (status === \"authorized\") {\n break;\n }\n\n if (status === \"error\") {\n throw new Error(sessionPayload.error || \"OAuth authorization failed\");\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n if (status !== \"authorized\") {\n throw new Error(\"OAuth authorization timed out\");\n }\n\n const tokenRes = await fetch(\"/oauth/token\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ state }),\n });\n\n const tokenPayload = (await tokenRes.json()) as {\n accessToken?: string;\n refreshToken?: string;\n expiresIn?: number;\n scope?: string;\n tokenType?: string;\n error?: string;\n };\n\n if (!tokenRes.ok || !tokenPayload.accessToken) {\n throw new Error(tokenPayload.error || \"OAuth token exchange failed\");\n }\n\n this.pendingOauthResult = {\n providerId: provider.id,\n accessToken: tokenPayload.accessToken,\n refreshToken: tokenPayload.refreshToken,\n expiresAt: tokenPayload.expiresIn\n ? Date.now() + tokenPayload.expiresIn * 1000\n : undefined,\n scope: tokenPayload.scope,\n tokenType: tokenPayload.tokenType,\n };\n\n if (oauthStatus) {\n oauthStatus.textContent = \"OAuth connected\";\n }\n\n showSuccess(`${provider.label} connected`, 3000);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (oauthStatus) {\n oauthStatus.textContent = \"OAuth failed\";\n }\n\n showError(`${provider.label} connect failed: ${message}`, 6000);\n } finally {\n if (connectBtn) {\n connectBtn.disabled = false;\n }\n }\n }\n\n async deleteConnection(id: string) {\n if (!this.db) {\n return;\n }\n\n const record = this.connections.find((item) => item.id === id);\n if (!record) {\n return;\n }\n\n const confirmed = await this.requestConfirmation({\n title: \"Delete Email Connection\",\n message: `Delete email connection \\\"${record.label}\\\"?`,\n confirmLabel: \"Delete\",\n cancelLabel: \"Cancel\",\n });\n\n if (!confirmed) {\n return;\n }\n\n try {\n const ok = await deleteEmailConnection(this.db, id);\n if (!ok) {\n showError(\"Failed to delete email connection.\", 5000);\n\n return;\n }\n\n showSuccess(\"Email connection deleted\", 2500);\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to delete email connection: ${message}`, 6000);\n }\n }\n\n async reload() {\n if (!this.db) {\n return;\n }\n\n this.manifests = listEmailPluginManifests().filter(\n (manifest) => manifest.id === \"imap\",\n );\n this.connections = await listEmailConnections(this.db);\n const rawAccounts = await getConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS);\n this.accounts = Array.isArray(rawAccounts) ? rawAccounts : [];\n this.renderConnectionList();\n }\n\n async requestConfirmation(options: {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n }): Promise<boolean> {\n const appShell = document.querySelector(\"shadow-claw\") as any;\n if (appShell && typeof appShell.requestDialog === \"function\") {\n return await appShell.requestDialog({ mode: \"confirm\", ...options });\n }\n\n return false;\n }\n\n async saveForm() {\n const root = this.shadowRoot;\n if (!root || !this.db) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form\"]');\n if (!slot) {\n return;\n }\n\n const labelInput = slot.querySelector(\n \"#int-label\",\n ) as HTMLInputElement | null;\n const modeInput = slot.querySelector(\n \"#int-mode\",\n ) as HTMLSelectElement | null;\n const pollInput = slot.querySelector(\n \"#int-poll\",\n ) as HTMLInputElement | null;\n const extraInput = slot.querySelector(\n \"#int-extra-config\",\n ) as HTMLTextAreaElement | null;\n\n if (!labelInput || !modeInput || !pollInput) {\n return;\n }\n\n const label = labelInput.value.trim();\n const pluginId = this.getInitialPluginId(null);\n\n if (!label || !pluginId) {\n showError(\"Label is required.\", 4000);\n\n return;\n }\n\n const config: Record<string, unknown> = {\n executionMode: modeInput.value,\n };\n\n const pollSec = Number(pollInput.value);\n if (Number.isFinite(pollSec) && pollSec > 0) {\n config.pollIntervalSec = Math.floor(pollSec);\n }\n\n const unreadOnlyInput = slot.querySelector(\n \"#int-unread-only\",\n ) as HTMLInputElement | null;\n config.unreadOnly = unreadOnlyInput?.checked === true;\n\n slot\n .querySelectorAll<HTMLInputElement>(\"[data-config-field]\")\n .forEach((input) => {\n const key = input.dataset.configField;\n if (!key) {\n return;\n }\n\n const value = input.value.trim();\n if (!value) {\n return;\n }\n\n if (/^\\d+$/.test(value)) {\n config[key] = Number(value);\n } else if (value === \"true\" || value === \"false\") {\n config[key] = value === \"true\";\n } else {\n config[key] = value;\n }\n });\n\n const extraRaw = extraInput?.value.trim() || \"\";\n if (extraRaw) {\n try {\n const parsed = JSON.parse(extraRaw);\n if (parsed && typeof parsed === \"object\") {\n Object.assign(config, parsed as Record<string, unknown>);\n }\n } catch {\n showError(\"Extra config JSON is invalid.\", 5000);\n\n return;\n }\n }\n\n try {\n const upserted = await upsertEmailConnection(this.db, {\n id: this.editingConnectionId || undefined,\n label,\n pluginId,\n config,\n });\n\n const credentialRef = await this.buildCredentialRef(slot, upserted);\n await bindEmailCredentialRef(this.db, upserted.id, credentialRef);\n\n showSuccess(\n this.editingConnectionId\n ? \"Email connection updated\"\n : \"Email connection created\",\n 3000,\n );\n\n (slot as HTMLElement).hidden = true;\n slot.replaceChildren();\n this.editingConnectionId = null;\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to save email connection: ${message}`, 6000);\n }\n }\n\n async testConnectionFromForm(slot: Element) {\n const testButton = slot.querySelector(\n '[data-action=\"test-connection\"]',\n ) as HTMLButtonElement | null;\n if (testButton) {\n testButton.disabled = true;\n }\n\n try {\n const username = (\n slot.querySelector(\"#int-username\") as HTMLInputElement | null\n )?.value.trim();\n const host = (\n slot.querySelector(\"#cfg-host\") as HTMLInputElement | null\n )?.value.trim();\n const mailboxPath =\n (\n slot.querySelector(\"#cfg-mailboxPath\") as HTMLInputElement | null\n )?.value.trim() || \"INBOX\";\n const portRaw = (\n slot.querySelector(\"#cfg-port\") as HTMLInputElement | null\n )?.value.trim();\n const secureRaw = (\n slot.querySelector(\"#cfg-secure\") as HTMLSelectElement | null\n )?.value;\n const unreadOnly = (\n slot.querySelector(\"#int-unread-only\") as HTMLInputElement | null\n )?.checked;\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n\n if (!username) {\n showError(\"Auth username (email login) is required.\", 4000);\n\n return;\n }\n\n if (!host) {\n showError(\"IMAP host is required.\", 4000);\n\n return;\n }\n\n const port = Number(portRaw);\n const resolvedPort = Number.isFinite(port) && port > 0 ? port : 993;\n const secure = secureRaw === \"false\" ? false : true;\n\n let authType: \"basic_userpass\" | \"oauth\" = \"basic_userpass\";\n let password: string | undefined;\n let accessToken: string | undefined;\n\n const existing = this.editingConnectionId\n ? this.connections.find((item) => item.id === this.editingConnectionId)\n : null;\n\n if (authMode === \"oauth\") {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const pendingOauthAccessToken =\n this.pendingOauthResult?.accessToken &&\n (!providerId || this.pendingOauthResult.providerId === providerId)\n ? this.pendingOauthResult.accessToken\n : \"\";\n\n const result = resolveConnectionTestAuth({\n authMode,\n pendingOauthAccessToken,\n hasStoredOauthCredential: Boolean(existing?.credentialRef?.accountId),\n });\n\n if (\"error\" in result) {\n showError(result.error, 6000);\n\n return;\n }\n\n authType = result.authType;\n if (result.authType === \"oauth\") {\n accessToken = result.accessToken;\n }\n } else {\n const passwordInput = (\n slot.querySelector(\"#int-password\") as HTMLInputElement | null\n )?.value;\n\n const result = resolveConnectionTestAuth({\n authMode,\n passwordInput,\n hasStoredPasswordCredential: Boolean(\n existing?.credentialRef?.encryptedSecret,\n ),\n });\n\n if (\"error\" in result) {\n showError(result.error, 6000);\n\n return;\n }\n\n authType = result.authType;\n if (result.authType === \"basic_userpass\") {\n password = result.password;\n }\n }\n\n const response = await fetch(\"/integrations/email/read\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n authType,\n host,\n port: resolvedPort,\n secure,\n username,\n password,\n accessToken,\n mailboxPath,\n limit: 1,\n unreadOnly: unreadOnly === true,\n }),\n });\n\n const payload = (await response.json().catch(() => ({}))) as {\n error?: string;\n count?: number;\n };\n\n if (!response.ok) {\n showError(\n `Connection test failed (${response.status}): ${payload.error || response.statusText}`,\n 7000,\n );\n\n return;\n }\n\n showSuccess(\n `Connection test passed. IMAP login succeeded${typeof payload.count === \"number\" ? ` (${payload.count} messages returned).` : \".\"}`,\n 4500,\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Connection test failed: ${message}`, 7000);\n } finally {\n if (testButton) {\n testButton.disabled = false;\n }\n }\n }\n\n async toggleConnection(id: string) {\n if (!this.db) {\n return;\n }\n\n const record = this.connections.find((item) => item.id === id);\n if (!record) {\n showError(\"Email connection not found.\", 4000);\n\n return;\n }\n\n try {\n await upsertEmailConnection(this.db, {\n id: record.id,\n label: record.label,\n pluginId: record.pluginId,\n enabled: !record.enabled,\n config: record.config,\n });\n\n showSuccess(`Email ${!record.enabled ? \"enabled\" : \"disabled\"}`, 2500);\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to update email connection: ${message}`, 6000);\n }\n }\n\n async upsertLinkedOAuthAccount(\n slot: Element,\n savedConnection: EmailConnectionRecord,\n ): Promise<ServiceAccount> {\n if (!this.db) {\n throw new Error(\"Database is not ready.\");\n }\n\n const username = (\n slot.querySelector(\"#int-username\") as HTMLInputElement | null\n )?.value.trim();\n const clientId = (\n slot.querySelector(\"#int-oauth-client-id\") as HTMLInputElement | null\n )?.value.trim();\n const clientSecretRaw = (\n slot.querySelector(\"#int-oauth-client-secret\") as HTMLInputElement | null\n )?.value.trim();\n const scopeRaw = (\n slot.querySelector(\"#int-oauth-scope\") as HTMLInputElement | null\n )?.value.trim();\n const selectedProviderId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const oauthProvider = this.getEmailOAuthProvider(selectedProviderId);\n\n if (!username) {\n throw new Error(\n \"Email login address is required for OAuth authentication.\",\n );\n }\n\n if (!clientId) {\n throw new Error(\"OAuth client ID is required for OAuth authentication.\");\n }\n\n const existingConnection = this.connections.find(\n (item) => item.id === savedConnection.id,\n );\n\n const existingAccountId = existingConnection?.credentialRef?.accountId;\n const existingAccount = existingAccountId\n ? this.accounts.find((account) => account.id === existingAccountId) ||\n null\n : null;\n\n let token = existingAccount?.token || \"\";\n let refreshToken = existingAccount?.refreshToken;\n let accessTokenExpiresAt = existingAccount?.accessTokenExpiresAt;\n let scopes = existingAccount?.scopes;\n let tokenType = existingAccount?.tokenType;\n let oauthClientSecret = existingAccount?.oauthClientSecret;\n let oauthRefreshFailureCount = existingAccount?.oauthRefreshFailureCount;\n let oauthReauthRequired = existingAccount?.oauthReauthRequired;\n let oauthReauthRequiredAt = existingAccount?.oauthReauthRequiredAt;\n\n if (clientSecretRaw) {\n const encryptedClientSecret = await encryptValue(clientSecretRaw);\n if (encryptedClientSecret) {\n oauthClientSecret = encryptedClientSecret;\n }\n }\n\n if (this.pendingOauthResult?.accessToken) {\n const encryptedAccessToken = await encryptValue(\n this.pendingOauthResult.accessToken,\n );\n if (!encryptedAccessToken) {\n throw new Error(\"Failed to encrypt OAuth access token.\");\n }\n\n token = encryptedAccessToken;\n\n if (this.pendingOauthResult.refreshToken) {\n const encryptedRefreshToken = await encryptValue(\n this.pendingOauthResult.refreshToken,\n );\n if (encryptedRefreshToken) {\n refreshToken = encryptedRefreshToken;\n }\n }\n\n accessTokenExpiresAt = this.pendingOauthResult.expiresAt;\n scopes = this.pendingOauthResult.scope\n ? this.pendingOauthResult.scope\n .split(/[\\s,]+/)\n .map((entry) => entry.trim())\n .filter(Boolean)\n : scopeRaw\n ? scopeRaw\n .split(/[\\s,]+/)\n .map((entry) => entry.trim())\n .filter(Boolean)\n : oauthProvider.defaultScopes;\n tokenType = this.pendingOauthResult.tokenType;\n oauthRefreshFailureCount = 0;\n oauthReauthRequired = false;\n oauthReauthRequiredAt = undefined;\n }\n\n if (!token) {\n throw new Error(\"Connect OAuth first to obtain an access token.\");\n }\n\n const accountId = existingAccount?.id || ulid();\n const account: ServiceAccount = {\n id: accountId,\n label: `${savedConnection.label} ${oauthProvider.label}`,\n service: oauthProvider.serviceName,\n hostPattern: oauthProvider.hostPattern,\n token,\n authMode: \"oauth\",\n oauthProviderId: oauthProvider.id,\n oauthClientId: clientId,\n oauthClientSecret,\n accessTokenExpiresAt,\n refreshToken,\n scopes: scopes || oauthProvider.defaultScopes,\n tokenType,\n oauthRefreshFailureCount,\n oauthReauthRequired,\n oauthReauthRequiredAt,\n };\n\n const accounts = [...this.accounts];\n const existingIdx = accounts.findIndex((item) => item.id === accountId);\n if (existingIdx === -1) {\n accounts.push(account);\n } else {\n accounts[existingIdx] = account;\n }\n\n await setConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS, accounts);\n this.accounts = accounts;\n\n return account;\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawIntegrations);\n}\n"],"mappings":";;;;;;;;;;;;AAKA,SAAgB,0BACd,OACiC;CACjC,IAAI,MAAM,aAAa,SAAS;EAC9B,MAAM,eAAe,MAAM,2BAA2B,GAAE,CAAE,KAAK;EAC/D,IAAI,aACF,OAAO;GACL,UAAU;GACV;EACF;EAGF,OAAO,EACL,OACE,oFACJ;CACF;CAEA,MAAM,YAAY,MAAM,iBAAiB,GAAE,CAAE,KAAK;CAClD,IAAI,UACF,OAAO;EACL,UAAU;EACV;CACF;CAGF,OAAO,EACL,OACE,sEACJ;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA,MAAM,cAAc;AAsBpB,MAAM,wBAAkE;CACtE,QAAQ;EACN,IAAI;EACJ,OAAO;EACP,aAAa;EACb,aAAa;EACb,eAAe,CAAC,0BAA0B;EAC1C,kBAAkB;EAClB,eAAe;EACf,oBAAoB;CACtB;CACA,iBAAiB;EACf,IAAI;EACJ,OAAO;EACP,aAAa;EACb,aAAa;EACb,eAAe;GACb;GACA;GACA;EACF;EACA,kBACE;EACF,eACE;EACF,oBAAoB;CACtB;CACA,YAAY;EACV,IAAI;EACJ,OAAO;EACP,aAAa;EACb,aAAa;EACb,eAAe,CAAC,UAAU,QAAQ;EAClC,kBAAkB;EAClB,eACE;EACF,oBAAoB;CACtB;AACF;AAEA,MAAM,eAA2C;CAC/C,OAAO;EACL,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;CACd;CACA,SAAS;EACP,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;CACd;CACA,OAAO;EACL,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;CACd;CACA,QAAQ;EACN,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;CACd;CACA,UAAU;EACR,UAAU;EACV,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;CACd;AACF;AAEA,MAAM,oBAA4C;CAChD,MAAM;CACN,MAAM;CACN,QAAQ;CACR,aAAa;CACb,UAAU;CACV,UAAU;CACV,YAAY;CACZ,aAAa;CACb,eAAe;CACf,iBAAiB;AACnB;AAEA,MAAM,0BAAkD;CACtD,MAAM;CACN,MAAM;CACN,aAAa;CACb,UAAU;CACV,UAAU;CACV,aAAa;CACb,iBAAiB;AACnB;AAEA,IAAa,yBAAb,cAA4C,kBAAkB;CAC5D,OAAO,SAASA;CAChB,OAAO,WAAWC;CAElB,WAA6B,CAAC;CAC9B,cAAuC,CAAC;CAExC,KAAgC;CAChC,sBAAqC;CACrC,YAAmC,CAAC;CACpC,qBAOW;CAEX,MAAM,oBAAoB;EACxB,KAAK,KAAK,MAAM,MAAM;EACtB,KAAK,mBAAmB;EACxB,MAAM,KAAK,OAAO;CACpB;CAEA,gBAAgB,MAAe;EAC7B,MAAM,eAAe,KAAK,cACxB,kBACF;EACA,MAAM,gBAAgB,KAAK,cACzB,eACF;EAEA,MAAM,iBAAiB,cAAc,SAAS;EAC9C,MAAM,SAAS,KAAK,kBAClB,gBACA,eAAe,SAAS,EAC1B;EACA,IAAI,CAAC,QAAQ;GACX,UACE,2GACA,GACF;GAEA;EACF;EAEA,KAAK,oBAAoB,MAAM,QAAQ,OAAO,QAAQ;EACtD,KAAK,oBAAoB,MAAM,QAAQ,OAAO,OAAO,QAAQ,CAAC;EAC9D,KAAK,oBAAoB,MAAM,UAAU,OAAO,OAAO,UAAU,CAAC;EAClE,KAAK,oBAAoB,MAAM,YAAY,OAAO,QAAQ;EAC1D,KAAK,oBAAoB,MAAM,YAAY,OAAO,OAAO,QAAQ,CAAC;EAClE,KAAK,oBAAoB,MAAM,cAAc,OAAO,OAAO,UAAU,CAAC;EAEtE,MAAM,eAAe,eAAe,SAAS,GAAE,CAAE,KAAK;EACtD,IAAI,aACF,KAAK,oBAAoB,MAAM,eAAe,WAAW;EAG3D,MAAM,eAAe,KAAK,cACxB,kBACF;EACA,IAAI,gBAAgB,CAAC,aAAa,MAAM,KAAK,GAC3C,aAAa,QAAQ;EAGvB,YAAY,gCAAgC,IAAI;CAClD;CAEA,qBAAqB;EACnB,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,KACG,cAAc,kCAAgC,CAAC,EAC9C,iBAAiB,eAAe,KAAK,SAAS,IAAI,CAAC;CACzD;CAEA,WAAW,OAAuB;EAChC,OAAO,MACJ,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,OAAO,QAAQ,CAAC,CACxB,QAAQ,MAAM,OAAO;CAC1B;CAEA,sBACE,YAC0B;EAC1B,IAAI,cAAc,sBAAsB,aACtC,OAAO,sBAAsB;EAG/B,OAAO,sBAAsB;CAC/B;CAEA,mBAAmB,UAAgD;EACjE,IAAI,UAAU,UACZ,OAAO,SAAS;EAGlB,IAAI,KAAK,UAAU,MAAM,SAAS,KAAK,OAAO,MAAM,GAClD,OAAO;EAGT,OAAO,KAAK,UAAU,EAAE,EAAE,MAAM;CAClC;CAEA,sBACE,UACA,KACQ;EACR,OAAO,SAAS,mBACb,KAAK,UAAU;GACd,MAAM,QAAQ,IAAI;GAClB,MAAM,eACJ,SAAS,OAAO,SAAU,kBAAkB,UAAU,QAAS;GAEjE,IAAI,UAAU,YAAY,UAAU,cAAc;IAChD,MAAM,WAAW,OAAO,UAAU,YAAY,QAAQ;IAEtD,OAAO;;gCAEe,KAAK,WAAW,KAAK,EAAE,IAAI,KAAK,WAAW,YAAY,EAAE;gCACzD,KAAK,WAAW,KAAK,EAAE,uBAAuB,KAAK,WAAW,KAAK,EAAE;uCAC9D,WAAW,aAAa,GAAG;wCAC1B,WAAW,KAAK,WAAW;;;;GAI3D;GAEA,MAAM,cACJ,SAAS,OAAO,SAAU,wBAAwB,UAAU,KAAM;GAEpE,OAAO;;8BAEe,KAAK,WAAW,KAAK,EAAE,IAAI,KAAK,WAAW,YAAY,EAAE;;wBAE/D,KAAK,WAAW,KAAK,EAAE;mCACZ,KAAK,WAAW,KAAK,EAAE;uBACnC,KAAK,WAAW,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,KAAK,IAAI,EAAE,EAAE;6BACrH,KAAK,WAAW,WAAW,EAAE;;;;EAIpD,CAAC,CAAC,CACD,KAAK,EAAE;CACZ;CAEA,uBAAuB;EACrB,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,OAAO,KAAK,cAAc,mCAAiC;EACjE,IAAI,CAAC,MACH;EAGF,KAAK,gBAAgB;EAErB,IAAI,CAAC,KAAK,YAAY,QAAQ;GAC5B,MAAM,QAAQ,SAAS,cAAc,KAAK;GAC1C,MAAM,YAAY;GAClB,MAAM,cACJ;GACF,KAAK,OAAO,KAAK;GAEjB;EACF;EAEA,MAAM,WAAW,SAAS,uBAAuB;EAEjD,KAAK,MAAM,cAAc,KAAK,aAAa;GACzC,MAAM,WAAW,uBAAuB,WAAW,QAAQ;GAC3D,MAAM,OAAO,SAAS,cAAc,SAAS;GAC7C,KAAK,YAAY;GAEjB,MAAM,gBACJ,OAAO,WAAW,OAAO,kBAAkB,WACvC,WAAW,OAAO,gBAClB;GACN,MAAM,kBACJ,OAAO,WAAW,OAAO,oBAAoB,WACzC,WAAW,OAAO,kBAClB;GACN,MAAM,UACJ,CAAC,CAAC,WAAW,eAAe,mBAC3B,WAAW,eAAe,aAAa,WACtC,CAAC,CAAC,WAAW,eAAe;GAEhC,iBACE,MACA;;;4CAGoC,KAAK,WAAW,WAAW,KAAK,EAAE;;gBAE9D,KAAK,WAAW,WAAW,QAAQ,IAAI,WAAW,MAAM,KAAK,WAAW,SAAS,IAAI,MAAM,GAAG;;;0CAGpE,WAAW,UAAU,YAAY,WAAW;cACxE,WAAW,UAAU,YAAY,WAAW;;;6CAGb,KAAK,WAAW,OAAO,aAAa,CAAC,IAAI,kBAAkB,YAAY,gBAAgB,KAAK,KAAK,UAAU,wBAAwB,mBAAmB;;sEAE7H,KAAK,WAAW,WAAW,EAAE,EAAE;wEAC7B,KAAK,WAAW,WAAW,EAAE,EAAE,IAAI,WAAW,UAAU,YAAY,SAAS;wEAC7E,KAAK,WAAW,WAAW,EAAE,EAAE;;OAGjG;GAEA,KACG,iBAAoC,qBAAqB,CAAC,CAC1D,SAAS,WAAW;IACnB,OAAO,iBAAiB,eAAe;KACrC,MAAM,SAAS,OAAO,QAAQ;KAC9B,MAAM,KAAK,OAAO,QAAQ;KAC1B,IAAI,CAAC,UAAU,CAAC,IACd;KAGF,IAAI,WAAW,QACb,KAAK,SAAS,EAAE;UACX,IAAI,WAAW,UACpB,AAAK,KAAK,iBAAiB,EAAE;UACxB,IAAI,WAAW,UACpB,AAAK,KAAK,iBAAiB,EAAE;IAEjC,CAAC;GACH,CAAC;GAEH,SAAS,OAAO,IAAI;EACtB;EAEA,KAAK,OAAO,QAAQ;CACtB;CAEA,kBAAkB,WAAmB,UAAqC;EACxE,IAAI,cAAc,QAChB,OAAO,aAAa,cAAc;EAGpC,MAAM,SAAS,SAAS,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,KAAK;EAC/D,IAAI,CAAC,QACH,OAAO;EAGT,IACE,WAAW,eACX,OAAO,SAAS,YAAY,KAC5B,OAAO,SAAS,iBAAiB,GAEjC,OAAO,aAAa;EAGtB,IACE,WAAW,iBACX,WAAW,iBACX,WAAW,cACX,WAAW,aACX,OAAO,SAAS,kBAAkB,GAElC,OAAO,aAAa;EAGtB,IAAI,WAAW,eAAe,OAAO,SAAS,YAAY,GACxD,OAAO,aAAa;EAGtB,IACE,WAAW,gBACX,WAAW,YACX,WAAW,WAEX,OAAO,aAAa;EAGtB,IAAI,WAAW,kBAAkB,OAAO,SAAS,eAAe,GAC9D,OAAO,aAAa;EAGtB,OAAO;CACT;CAEA,oBAAoB,MAAe,OAAe,OAAe;EAC/D,MAAM,OAAO,KAAK,cAAc,QAAQ,OAAO;EAI/C,IAAI,CAAC,MACH;EAGF,KAAK,QAAQ;CACf;CAEA,SAAS,cAA6B;EACpC,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MACH;EAGF,MAAM,OAAO,KAAK,cAAc,mCAAiC;EACjE,IAAI,CAAC,MACH;EAGF,KAAK,sBAAsB;EAC3B,MAAM,WAAW,eACb,KAAK,YAAY,MAAM,SAAS,KAAK,OAAO,YAAY,KAAK,OAC7D;EAEJ,MAAM,WAAW,KAAK,mBAAmB,QAAQ;EACjD,MAAM,WAAW,uBAAuB,QAAQ;EAEhD,MAAM,MAAM,UAAU,UAAU,CAAC;EACjC,MAAM,qBAAqB,UAAU,eAAe,YAChD,KAAK,SAAS,MACX,YAAY,QAAQ,OAAO,SAAS,eAAe,SACtD,KAAK,OACL;EACJ,MAAM,gBACJ,OAAO,IAAI,kBAAkB,WACzB,OAAO,IAAI,aAAa,IACxB;EACN,MAAM,kBACJ,OAAO,IAAI,oBAAoB,WAAW,IAAI,kBAAkB;EAClE,MAAM,WACJ,UAAU,eAAe,aAAa,UAClC,UACA;EACN,MAAM,kBACJ,UAAU,eAAe,cACzB,oBAAoB,mBACpB;EACF,MAAM,gBAAgB,KAAK,sBAAsB,eAAe;EAChE,MAAM,gBAAgB,oBAAoB,iBAAiB;EAC3D,MAAM,aACJ,oBAAoB,QAAQ,KAAK,GAAG,KACpC,cAAc,cAAc,KAAK,GAAG;EACtC,MAAM,cACJ,aAAa,UACT,oBAAoB,sBAClB,uBACA,oBAAoB,QAClB,8BACA,kBACJ;EAEN,MAAM,eAAe,aAAa;EAClC,iBACE,MACA;YACM,WAAW,0BAA0B,uBAAuB;;;uCAGjC,KAAK,WAAW,UAAU,SAAS,EAAE,EAAE;;;;;mCAK3C,kBAAkB,WAAW,aAAa,GAAG;sCAC1C,kBAAkB,cAAc,aAAa,GAAG;yCAC7C,kBAAkB,iBAAiB,aAAa,GAAG;;;;;4DAKhC,KAAK,WAAW,OAAO,eAAe,CAAC,EAAE;;;;wDAI7C,IAAI,eAAe,OAAO,YAAY,GAAG;;;;;;0CAMvD,KAAK,WAAW,UAAU,eAAe,YAAY,EAAE,EAAE;;;;;2CAKxD,aAAa,mBAAmB,aAAa,GAAG;kCACzD,aAAa,UAAU,aAAa,GAAG;;;;;;gEAMT,UAAU,eAAe,kBAAkB,yBAAyB,iBAAiB;;;;;;;;cAQvI,OAAO,OAAO,qBAAqB,CAAC,CACnC,KACE,aACC,kBAAkB,KAAK,WAAW,SAAS,EAAE,EAAE,IAAI,SAAS,OAAO,cAAc,KAAK,aAAa,GAAG,GAAG,KAAK,WAAW,SAAS,KAAK,EAAE,UAC7I,CAAC,CACA,KAAK,EAAE,EAAE;;;;;mDAK2B,KAAK,WAAW,aAAa,EAAE;;;;6EAIL,oBAAoB,oBAAoB,yBAAyB,kCAAkC;;;;+CAIjI,KAAK,WAAW,UAAU,EAAE,iBAAiB,KAAK,WAAW,cAAc,gBAAgB,EAAE;wEACpE,KAAK,WAAW,cAAc,aAAa,EAAE;;;oFAGjC,KAAK,WAAW,cAAc,kBAAkB,EAAE;kEACpE,KAAK,WAAW,WAAW,EAAE;;;QAIvF,eACI;;;;;;;;;;;;;;uBAeA,GACL;;QAEC,WAAW,KAAK,sBAAsB,UAAU,GAAG,IAAI,GAAG;;;;;;;;;;;KAY9D;EAEA,MAAM,WAAW;EACjB,SAAS,SAAS;EAElB,KAAK,qBAAqB;EAE1B,KACG,cAAc,gBAAgB,CAAC,EAC9B,iBAAiB,gBAAgB,KAAK,yBAAyB,IAAI,CAAC;EAExE,KACG,cAAc,iCAA+B,CAAC,EAC7C,iBAAiB,eAAe,KAAK,gBAAgB,IAAI,CAAC;EAC9D,KACG,cAAc,iCAA+B,CAAC,EAC7C,iBAAiB,eAAe,KAAK,KAAK,qBAAqB,IAAI,CAAC;EACxE,KACG,cAAc,qBAAqB,CAAC,EACnC,iBAAiB,gBAAgB,KAAK,wBAAwB,IAAI,CAAC;EAEvE,KACG,cAAc,0BAAwB,CAAC,EACtC,iBAAiB,eAAe;GAChC,SAAS,SAAS;GAClB,SAAS,gBAAgB;GACzB,KAAK,sBAAsB;EAC7B,CAAC;EAEH,KACG,cAAc,wBAAsB,CAAC,EACpC,iBAAiB,eAAe;GAChC,AAAK,KAAK,SAAS;EACrB,CAAC;EAEH,KACG,cAAc,mCAAiC,CAAC,EAC/C,iBAAiB,eAAe;GAChC,AAAK,KAAK,uBAAuB,IAAI;EACvC,CAAC;EAEH,KAAK,yBAAyB,IAAI;EAClC,KAAK,wBAAwB,IAAI;CACnC;CAEA,yBAAyB,MAAe;EACtC,MAAM,WACJ,KAAK,cAAc,gBAAgB,CAAC,EACnC;EAEH,MAAM,iBAAiB,KAAK,cAC1B,wCACF;EACA,MAAM,cAAc,KAAK,cACvB,qCACF;EAEA,IAAI,gBACF,eAAe,MAAM,UAAU,aAAa,UAAU,SAAS;EAGjE,IAAI,aACF,YAAY,MAAM,UAAU,aAAa,UAAU,UAAU;CAEjE;CAEA,wBAAwB,MAAe;EACrC,MAAM,aACJ,KAAK,cAAc,qBAAqB,CAAC,EACxC;EACH,MAAM,WAAW,KAAK,sBAAsB,UAAU;EAEtD,MAAM,aAAa,KAAK,cACtB,kBACF;EACA,MAAM,YAAY,KAAK,cACrB,oCACF;EACA,MAAM,aAAa,KAAK,cACtB,iCACF;EAEA,IAAI,YAAY;GACd,WAAW,cAAc,SAAS;GAClC,IAAI,CAAC,WAAW,MAAM,KAAK,GACzB,WAAW,QAAQ,SAAS,cAAc,KAAK,GAAG;EAEtD;EAEA,IAAI,WACF,UAAU,cAAc,SAAS;EAGnC,IAAI,YACF,WAAW,cAAc,SAAS;CAEtC;CAEA,MAAM,mBACJ,MACA,iBACoC;EACpC,MAAM,WACJ,KAAK,cAAc,gBAAgB,CAAC,EACnC;EACH,MAAM,gBAAgB,KAAK,cACzB,eACF;EACA,MAAM,gBAAgB,KAAK,cACzB,eACF;EAEA,MAAM,WAAW,eAAe,MAAM,KAAK,KAAK;EAChD,MAAM,cAAc,eAAe,MAAM,KAAK,KAAK;EAEnD,MAAM,WAAW,KAAK,YAAY,MAC/B,SAAS,KAAK,OAAO,gBAAgB,EACxC;EAEA,IAAI,aAAa,SAAS;GACxB,IAAI,CAAC,UACH,MAAM,IAAI,MACR,2DACF;GAGF,MAAM,gBAAgB,MAAM,KAAK,yBAC/B,MACA,eACF;GAEA,OAAO;IACL,aAAa;IACb,UAAU;IACV,YAAY,cAAc,mBAAmB;IAC7C,WAAW,cAAc;IACzB;GACF;EACF;EAEA,IAAI;EACJ,IAAI,aAAa;GACf,kBAAmB,MAAM,aAAa,WAAW,KAAM;GACvD,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,mCAAmC;EAEvD,OACE,kBAAkB,UAAU,eAAe;EAG7C,IAAI,CAAC,YAAY,CAAC,iBAChB,OAAO;EAGT,IAAI,CAAC,UACH,MAAM,IAAI,MACR,0DACF;EAGF,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,wDAAwD;EAG1E,OAAO;GACL,aAAa;GACb,UAAU;GACV;GACA;EACF;CACF;CAEA,MAAM,qBAAqB,MAAe;EACxC,MAAM,aACJ,KAAK,cAAc,qBAAqB,CAAC,EACxC;EACH,MAAM,WAAW,KAAK,sBAAsB,UAAU;EACtD,MAAM,WACJ,KAAK,cAAc,sBAAsB,CAAC,EACzC,MAAM,KAAK;EACd,MAAM,eACJ,KAAK,cAAc,0BAA0B,CAAC,EAC7C,MAAM,KAAK;EACd,MAAM,WACJ,KAAK,cAAc,kBAAkB,CAAC,EACrC,MAAM,KAAK;EACd,MAAM,cAAc,KAAK,cACvB,gCACF;EACA,MAAM,aAAa,KAAK,cACtB,iCACF;EAEA,IAAI,CAAC,UAAU;GACb,UAAU,gCAAgC,GAAI;GAE9C;EACF;EAEA,IAAI,aACF,YAAY,cAAc;EAG5B,IAAI,YACF,WAAW,WAAW;EAGxB,IAAI;GACF,MAAM,QAAQ,WACV,SACG,MAAM,QAAQ,CAAC,CACf,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,OAAO,OAAO,IACjB,SAAS;GACb,MAAM,cAAc,GAAG,OAAO,SAAS,OAAO;GAE9C,MAAM,eAAe,MAAM,MAAM,oBAAoB;IACnD,QAAQ;IACR,SAAS,EACP,gBAAgB,mBAClB;IACA,MAAM,KAAK,UAAU;KACnB,YAAY,SAAS;KACrB;KACA,cAAc,gBAAgB;KAC9B;KACA;KACA,sBAAsB;MACpB,aAAa;MACb,QAAQ;KACV;IACF,CAAC;GACH,CAAC;GAED,MAAM,mBAAoB,MAAM,aAAa,KAAK;GAMlD,IACE,CAAC,aAAa,MACd,CAAC,iBAAiB,SAClB,CAAC,iBAAiB,cAElB,MAAM,IAAI,MAAM,iBAAiB,SAAS,wBAAwB;GAGpE,OAAO,KACL,iBAAiB,cACjB,2BACA,gCACF;GAEA,MAAM,QAAQ,iBAAiB;GAC/B,IAAI,SAAS;GACb,KAAK,IAAI,UAAU,GAAG,UAAU,IAAI,WAAW;IAC7C,MAAM,aAAa,MAAM,MACvB,kBAAkB,mBAAmB,KAAK,GAC5C;IACA,MAAM,iBAAkB,MAAM,WAAW,KAAK;IAK9C,IAAI,CAAC,WAAW,IACd,MAAM,IAAI,MAAM,eAAe,SAAS,yBAAyB;IAGnE,SAAS,eAAe,UAAU;IAClC,IAAI,WAAW,cACb;IAGF,IAAI,WAAW,SACb,MAAM,IAAI,MAAM,eAAe,SAAS,4BAA4B;IAGtE,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,GAAI,CAAC;GAC1D;GAEA,IAAI,WAAW,cACb,MAAM,IAAI,MAAM,+BAA+B;GAGjD,MAAM,WAAW,MAAM,MAAM,gBAAgB;IAC3C,QAAQ;IACR,SAAS,EACP,gBAAgB,mBAClB;IACA,MAAM,KAAK,UAAU,EAAE,MAAM,CAAC;GAChC,CAAC;GAED,MAAM,eAAgB,MAAM,SAAS,KAAK;GAS1C,IAAI,CAAC,SAAS,MAAM,CAAC,aAAa,aAChC,MAAM,IAAI,MAAM,aAAa,SAAS,6BAA6B;GAGrE,KAAK,qBAAqB;IACxB,YAAY,SAAS;IACrB,aAAa,aAAa;IAC1B,cAAc,aAAa;IAC3B,WAAW,aAAa,YACpB,KAAK,IAAI,IAAI,aAAa,YAAY,MACtC;IACJ,OAAO,aAAa;IACpB,WAAW,aAAa;GAC1B;GAEA,IAAI,aACF,YAAY,cAAc;GAG5B,YAAY,GAAG,SAAS,MAAM,aAAa,GAAI;EACjD,SAAS,KAAK;GACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAC/D,IAAI,aACF,YAAY,cAAc;GAG5B,UAAU,GAAG,SAAS,MAAM,mBAAmB,WAAW,GAAI;EAChE,UAAU;GACR,IAAI,YACF,WAAW,WAAW;EAE1B;CACF;CAEA,MAAM,iBAAiB,IAAY;EACjC,IAAI,CAAC,KAAK,IACR;EAGF,MAAM,SAAS,KAAK,YAAY,MAAM,SAAS,KAAK,OAAO,EAAE;EAC7D,IAAI,CAAC,QACH;EAUF,IAAI,CAAC,MAPmB,KAAK,oBAAoB;GAC/C,OAAO;GACP,SAAS,6BAA6B,OAAO,MAAM;GACnD,cAAc;GACd,aAAa;EACf,CAAC,GAGC;EAGF,IAAI;GAEF,IAAI,CAAC,MADY,sBAAsB,KAAK,IAAI,EAAE,GACzC;IACP,UAAU,sCAAsC,GAAI;IAEpD;GACF;GAEA,YAAY,4BAA4B,IAAI;GAC5C,MAAM,KAAK,OAAO;EACpB,SAAS,OAAO;GAEd,UAAU,sCADM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACV,GAAI;EACjE;CACF;CAEA,MAAM,SAAS;EACb,IAAI,CAAC,KAAK,IACR;EAGF,KAAK,YAAY,yBAAyB,CAAC,CAAC,QACzC,aAAa,SAAS,OAAO,MAChC;EACA,KAAK,cAAc,MAAM,qBAAqB,KAAK,EAAE;EACrD,MAAM,cAAc,MAAM,UAAU,KAAK,IAAI,YAAY,gBAAgB;EACzE,KAAK,WAAW,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC;EAC5D,KAAK,qBAAqB;CAC5B;CAEA,MAAM,oBAAoB,SAKL;EACnB,MAAM,WAAW,SAAS,cAAc,aAAa;EACrD,IAAI,YAAY,OAAO,SAAS,kBAAkB,YAChD,OAAO,MAAM,SAAS,cAAc;GAAE,MAAM;GAAW,GAAG;EAAQ,CAAC;EAGrE,OAAO;CACT;CAEA,MAAM,WAAW;EACf,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,IACjB;EAGF,MAAM,OAAO,KAAK,cAAc,mCAAiC;EACjE,IAAI,CAAC,MACH;EAGF,MAAM,aAAa,KAAK,cACtB,YACF;EACA,MAAM,YAAY,KAAK,cACrB,WACF;EACA,MAAM,YAAY,KAAK,cACrB,WACF;EACA,MAAM,aAAa,KAAK,cACtB,mBACF;EAEA,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,WAChC;EAGF,MAAM,QAAQ,WAAW,MAAM,KAAK;EACpC,MAAM,WAAW,KAAK,mBAAmB,IAAI;EAE7C,IAAI,CAAC,SAAS,CAAC,UAAU;GACvB,UAAU,sBAAsB,GAAI;GAEpC;EACF;EAEA,MAAM,SAAkC,EACtC,eAAe,UAAU,MAC3B;EAEA,MAAM,UAAU,OAAO,UAAU,KAAK;EACtC,IAAI,OAAO,SAAS,OAAO,KAAK,UAAU,GACxC,OAAO,kBAAkB,KAAK,MAAM,OAAO;EAM7C,OAAO,aAHiB,KAAK,cAC3B,kBAEgC,CAAC,EAAE,YAAY;EAEjD,KACG,iBAAmC,qBAAqB,CAAC,CACzD,SAAS,UAAU;GAClB,MAAM,MAAM,MAAM,QAAQ;GAC1B,IAAI,CAAC,KACH;GAGF,MAAM,QAAQ,MAAM,MAAM,KAAK;GAC/B,IAAI,CAAC,OACH;GAGF,IAAI,QAAQ,KAAK,KAAK,GACpB,OAAO,OAAO,OAAO,KAAK;QACrB,IAAI,UAAU,UAAU,UAAU,SACvC,OAAO,OAAO,UAAU;QAExB,OAAO,OAAO;EAElB,CAAC;EAEH,MAAM,WAAW,YAAY,MAAM,KAAK,KAAK;EAC7C,IAAI,UACF,IAAI;GACF,MAAM,SAAS,KAAK,MAAM,QAAQ;GAClC,IAAI,UAAU,OAAO,WAAW,UAC9B,OAAO,OAAO,QAAQ,MAAiC;EAE3D,QAAQ;GACN,UAAU,iCAAiC,GAAI;GAE/C;EACF;EAGF,IAAI;GACF,MAAM,WAAW,MAAM,sBAAsB,KAAK,IAAI;IACpD,IAAI,KAAK,uBAAuB;IAChC;IACA;IACA;GACF,CAAC;GAED,MAAM,gBAAgB,MAAM,KAAK,mBAAmB,MAAM,QAAQ;GAClE,MAAM,uBAAuB,KAAK,IAAI,SAAS,IAAI,aAAa;GAEhE,YACE,KAAK,sBACD,6BACA,4BACJ,GACF;GAEA,AAAC,KAAqB,SAAS;GAC/B,KAAK,gBAAgB;GACrB,KAAK,sBAAsB;GAC3B,MAAM,KAAK,OAAO;EACpB,SAAS,OAAO;GAEd,UAAU,oCADM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACZ,GAAI;EAC/D;CACF;CAEA,MAAM,uBAAuB,MAAe;EAC1C,MAAM,aAAa,KAAK,cACtB,mCACF;EACA,IAAI,YACF,WAAW,WAAW;EAGxB,IAAI;GACF,MAAM,WACJ,KAAK,cAAc,eAAe,CAAC,EAClC,MAAM,KAAK;GACd,MAAM,OACJ,KAAK,cAAc,WAAW,CAAC,EAC9B,MAAM,KAAK;GACd,MAAM,cAEF,KAAK,cAAc,kBAAkB,CAAC,EACrC,MAAM,KAAK,KAAK;GACrB,MAAM,UACJ,KAAK,cAAc,WAAW,CAAC,EAC9B,MAAM,KAAK;GACd,MAAM,YACJ,KAAK,cAAc,aAAa,CAAC,EAChC;GACH,MAAM,aACJ,KAAK,cAAc,kBAAkB,CAAC,EACrC;GACH,MAAM,WACJ,KAAK,cAAc,gBAAgB,CAAC,EACnC;GAEH,IAAI,CAAC,UAAU;IACb,UAAU,4CAA4C,GAAI;IAE1D;GACF;GAEA,IAAI,CAAC,MAAM;IACT,UAAU,0BAA0B,GAAI;IAExC;GACF;GAEA,MAAM,OAAO,OAAO,OAAO;GAC3B,MAAM,eAAe,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,OAAO;GAChE,MAAM,SAAS,cAAc,UAAU,QAAQ;GAE/C,IAAI,WAAuC;GAC3C,IAAI;GACJ,IAAI;GAEJ,MAAM,WAAW,KAAK,sBAClB,KAAK,YAAY,MAAM,SAAS,KAAK,OAAO,KAAK,mBAAmB,IACpE;GAEJ,IAAI,aAAa,SAAS;IACxB,MAAM,aACJ,KAAK,cAAc,qBAAqB,CAAC,EACxC;IAOH,MAAM,SAAS,0BAA0B;KACvC;KACA,yBAPA,KAAK,oBAAoB,gBACxB,CAAC,cAAc,KAAK,mBAAmB,eAAe,cACnD,KAAK,mBAAmB,cACxB;KAKJ,0BAA0B,QAAQ,UAAU,eAAe,SAAS;IACtE,CAAC;IAED,IAAI,WAAW,QAAQ;KACrB,UAAU,OAAO,OAAO,GAAI;KAE5B;IACF;IAEA,WAAW,OAAO;IAClB,IAAI,OAAO,aAAa,SACtB,cAAc,OAAO;GAEzB,OAAO;IACL,MAAM,gBACJ,KAAK,cAAc,eAAe,CAAC,EAClC;IAEH,MAAM,SAAS,0BAA0B;KACvC;KACA;KACA,6BAA6B,QAC3B,UAAU,eAAe,eAC3B;IACF,CAAC;IAED,IAAI,WAAW,QAAQ;KACrB,UAAU,OAAO,OAAO,GAAI;KAE5B;IACF;IAEA,WAAW,OAAO;IAClB,IAAI,OAAO,aAAa,kBACtB,WAAW,OAAO;GAEtB;GAEA,MAAM,WAAW,MAAM,MAAM,4BAA4B;IACvD,QAAQ;IACR,SAAS,EACP,gBAAgB,mBAClB;IACA,MAAM,KAAK,UAAU;KACnB;KACA;KACA,MAAM;KACN;KACA;KACA;KACA;KACA;KACA,OAAO;KACP,YAAY,eAAe;IAC7B,CAAC;GACH,CAAC;GAED,MAAM,UAAW,MAAM,SAAS,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE;GAKvD,IAAI,CAAC,SAAS,IAAI;IAChB,UACE,2BAA2B,SAAS,OAAO,KAAK,QAAQ,SAAS,SAAS,cAC1E,GACF;IAEA;GACF;GAEA,YACE,+CAA+C,OAAO,QAAQ,UAAU,WAAW,KAAK,QAAQ,MAAM,wBAAwB,OAC9H,IACF;EACF,SAAS,OAAO;GAEd,UAAU,2BADM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACrB,GAAI;EACtD,UAAU;GACR,IAAI,YACF,WAAW,WAAW;EAE1B;CACF;CAEA,MAAM,iBAAiB,IAAY;EACjC,IAAI,CAAC,KAAK,IACR;EAGF,MAAM,SAAS,KAAK,YAAY,MAAM,SAAS,KAAK,OAAO,EAAE;EAC7D,IAAI,CAAC,QAAQ;GACX,UAAU,+BAA+B,GAAI;GAE7C;EACF;EAEA,IAAI;GACF,MAAM,sBAAsB,KAAK,IAAI;IACnC,IAAI,OAAO;IACX,OAAO,OAAO;IACd,UAAU,OAAO;IACjB,SAAS,CAAC,OAAO;IACjB,QAAQ,OAAO;GACjB,CAAC;GAED,YAAY,SAAS,CAAC,OAAO,UAAU,YAAY,cAAc,IAAI;GACrE,MAAM,KAAK,OAAO;EACpB,SAAS,OAAO;GAEd,UAAU,sCADM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACV,GAAI;EACjE;CACF;CAEA,MAAM,yBACJ,MACA,iBACyB;EACzB,IAAI,CAAC,KAAK,IACR,MAAM,IAAI,MAAM,wBAAwB;EAG1C,MAAM,WACJ,KAAK,cAAc,eAAe,CAAC,EAClC,MAAM,KAAK;EACd,MAAM,WACJ,KAAK,cAAc,sBAAsB,CAAC,EACzC,MAAM,KAAK;EACd,MAAM,kBACJ,KAAK,cAAc,0BAA0B,CAAC,EAC7C,MAAM,KAAK;EACd,MAAM,WACJ,KAAK,cAAc,kBAAkB,CAAC,EACrC,MAAM,KAAK;EACd,MAAM,qBACJ,KAAK,cAAc,qBAAqB,CAAC,EACxC;EACH,MAAM,gBAAgB,KAAK,sBAAsB,kBAAkB;EAEnE,IAAI,CAAC,UACH,MAAM,IAAI,MACR,2DACF;EAGF,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,uDAAuD;EAOzE,MAAM,oBAJqB,KAAK,YAAY,MACzC,SAAS,KAAK,OAAO,gBAAgB,EAGG,CAAC,EAAE,eAAe;EAC7D,MAAM,kBAAkB,oBACpB,KAAK,SAAS,MAAM,YAAY,QAAQ,OAAO,iBAAiB,KAChE,OACA;EAEJ,IAAI,QAAQ,iBAAiB,SAAS;EACtC,IAAI,eAAe,iBAAiB;EACpC,IAAI,uBAAuB,iBAAiB;EAC5C,IAAI,SAAS,iBAAiB;EAC9B,IAAI,YAAY,iBAAiB;EACjC,IAAI,oBAAoB,iBAAiB;EACzC,IAAI,2BAA2B,iBAAiB;EAChD,IAAI,sBAAsB,iBAAiB;EAC3C,IAAI,wBAAwB,iBAAiB;EAE7C,IAAI,iBAAiB;GACnB,MAAM,wBAAwB,MAAM,aAAa,eAAe;GAChE,IAAI,uBACF,oBAAoB;EAExB;EAEA,IAAI,KAAK,oBAAoB,aAAa;GACxC,MAAM,uBAAuB,MAAM,aACjC,KAAK,mBAAmB,WAC1B;GACA,IAAI,CAAC,sBACH,MAAM,IAAI,MAAM,uCAAuC;GAGzD,QAAQ;GAER,IAAI,KAAK,mBAAmB,cAAc;IACxC,MAAM,wBAAwB,MAAM,aAClC,KAAK,mBAAmB,YAC1B;IACA,IAAI,uBACF,eAAe;GAEnB;GAEA,uBAAuB,KAAK,mBAAmB;GAC/C,SAAS,KAAK,mBAAmB,QAC7B,KAAK,mBAAmB,MACrB,MAAM,QAAQ,CAAC,CACf,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,OAAO,OAAO,IACjB,WACE,SACG,MAAM,QAAQ,CAAC,CACf,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,OAAO,OAAO,IACjB,cAAc;GACpB,YAAY,KAAK,mBAAmB;GACpC,2BAA2B;GAC3B,sBAAsB;GACtB,wBAAwB;EAC1B;EAEA,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,gDAAgD;EAGlE,MAAM,YAAY,iBAAiB,MAAM,KAAK;EAC9C,MAAM,UAA0B;GAC9B,IAAI;GACJ,OAAO,GAAG,gBAAgB,MAAM,GAAG,cAAc;GACjD,SAAS,cAAc;GACvB,aAAa,cAAc;GAC3B;GACA,UAAU;GACV,iBAAiB,cAAc;GAC/B,eAAe;GACf;GACA;GACA;GACA,QAAQ,UAAU,cAAc;GAChC;GACA;GACA;GACA;EACF;EAEA,MAAM,WAAW,CAAC,GAAG,KAAK,QAAQ;EAClC,MAAM,cAAc,SAAS,WAAW,SAAS,KAAK,OAAO,SAAS;EACtE,IAAI,gBAAgB,IAClB,SAAS,KAAK,OAAO;OAErB,SAAS,eAAe;EAG1B,MAAM,UAAU,KAAK,IAAI,YAAY,kBAAkB,QAAQ;EAC/D,KAAK,WAAW;EAEhB,OAAO;CACT;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,WAAW,GACjC,eAAe,OAAO,aAAa,sBAAsB"}
1
+ {"version":3,"file":"shadow-claw-integrations-Ds-CLPhj.js","names":["shadowClawIntegrationsStyles","shadowClawIntegrationsTemplate"],"sources":["../../src/components/settings/shadow-claw-integrations/connection-test-auth.ts","../../src/components/settings/shadow-claw-integrations/shadow-claw-integrations.ts"],"sourcesContent":["import type {\n ResolveConnectionTestAuthInput,\n ResolveConnectionTestAuthResult,\n} from \"../../types.js\";\n\nexport function resolveConnectionTestAuth(\n input: ResolveConnectionTestAuthInput,\n): ResolveConnectionTestAuthResult {\n if (input.authMode === \"oauth\") {\n const accessToken = (input.pendingOauthAccessToken || \"\").trim();\n if (accessToken) {\n return {\n authType: \"oauth\",\n accessToken,\n };\n }\n\n return {\n error:\n \"OAuth access token is missing. Click Connect OAuth first (or save and reconnect).\",\n };\n }\n\n const password = (input.passwordInput || \"\").trim();\n if (password) {\n return {\n authType: \"basic_userpass\",\n password,\n };\n }\n\n return {\n error:\n \"Password/app password is missing. Enter it to test this connection.\",\n };\n}\n","import { CONFIG_KEYS } from \"../../../config/config.js\";\nimport { getDb } from \"../../../db/db.js\";\nimport { getConfig } from \"../../../db/getConfig.js\";\nimport { setConfig } from \"../../../db/setConfig.js\";\nimport { encryptValue } from \"../../../security/crypto.js\";\nimport { setSanitizedHtml } from \"../../../security/trusted-types.js\";\n\nimport {\n getEmailPluginManifest,\n listEmailPluginManifests,\n} from \"../../../subsystems/email/catalog.js\";\n\nimport {\n bindEmailCredentialRef,\n deleteEmailConnection,\n listEmailConnections,\n upsertEmailConnection,\n} from \"../../../subsystems/email/connections.js\";\n\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { resolveConnectionTestAuth } from \"./connection-test-auth.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { ServiceAccount } from \"../../../subsystems/accounts/service-accounts.js\";\nimport type { EmailPluginManifest } from \"../../../subsystems/email/catalog.js\";\nimport type {\n EmailConnectionRecord,\n EmailCredentialRef,\n} from \"../../../subsystems/email/connections.js\";\n\nimport ShadowClawElement from \"../../shadow-claw-element.js\";\nimport shadowClawIntegrationsStyles from \"./shadow-claw-integrations.css\" with { type: \"css\" };\nimport shadowClawIntegrationsTemplate from \"./shadow-claw-integrations.html\" with { type: \"html\" };\n\nconst elementName = \"shadow-claw-integrations\";\n\ninterface ImapPreset {\n imapHost: string;\n imapPort: number;\n imapSecure: boolean;\n smtpHost: string;\n smtpPort: number;\n smtpSecure: boolean;\n}\n\ninterface EmailOAuthProviderConfig {\n id: string;\n label: string;\n serviceName: string;\n hostPattern: string;\n defaultScopes: string[];\n scopePlaceholder: string;\n scopeHelpText: string;\n connectButtonLabel: string;\n}\n\nconst EMAIL_OAUTH_PROVIDERS: Record<string, EmailOAuthProviderConfig> = {\n google: {\n id: \"google\",\n label: \"Gmail (Google OAuth)\",\n serviceName: \"Google\",\n hostPattern: \"gmail.com\",\n defaultScopes: [\"https://mail.google.com/\"],\n scopePlaceholder: \"https://mail.google.com/\",\n scopeHelpText: \"Use https://mail.google.com/ for Gmail IMAP/SMTP access.\",\n connectButtonLabel: \"Connect Google OAuth\",\n },\n microsoft_graph: {\n id: \"microsoft_graph\",\n label: \"Microsoft (Outlook / M365 OAuth)\",\n serviceName: \"Microsoft\",\n hostPattern: \"outlook.office365.com\",\n defaultScopes: [\n \"offline_access\",\n \"https://outlook.office.com/IMAP.AccessAsUser.All\",\n \"https://outlook.office.com/SMTP.Send\",\n ],\n scopePlaceholder:\n \"offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send\",\n scopeHelpText:\n \"For Outlook/M365 IMAP+SMTP, include offline_access plus IMAP.AccessAsUser.All and SMTP.Send scopes.\",\n connectButtonLabel: \"Connect Microsoft OAuth\",\n },\n yahoo_mail: {\n id: \"yahoo_mail\",\n label: \"Yahoo Mail OAuth\",\n serviceName: \"Yahoo\",\n hostPattern: \"mail.yahoo.com\",\n defaultScopes: [\"mail-r\", \"mail-w\"],\n scopePlaceholder: \"mail-r mail-w\",\n scopeHelpText:\n \"Yahoo commonly uses mail-r and mail-w scopes for IMAP/SMTP style access.\",\n connectButtonLabel: \"Connect Yahoo OAuth\",\n },\n};\n\nconst IMAP_PRESETS: Record<string, ImapPreset> = {\n gmail: {\n imapHost: \"imap.gmail.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.gmail.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n outlook: {\n imapHost: \"outlook.office365.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.office365.com\",\n smtpPort: 587,\n smtpSecure: false,\n },\n yahoo: {\n imapHost: \"imap.mail.yahoo.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.mail.yahoo.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n icloud: {\n imapHost: \"imap.mail.me.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.mail.me.com\",\n smtpPort: 587,\n smtpSecure: false,\n },\n fastmail: {\n imapHost: \"imap.fastmail.com\",\n imapPort: 993,\n imapSecure: true,\n smtpHost: \"smtp.fastmail.com\",\n smtpPort: 465,\n smtpSecure: true,\n },\n};\n\nconst IMAP_FIELD_LABELS: Record<string, string> = {\n host: \"IMAP host\",\n port: \"IMAP port\",\n secure: \"IMAP TLS\",\n mailboxPath: \"Mailbox path\",\n smtpHost: \"SMTP host\",\n smtpPort: \"SMTP port\",\n smtpSecure: \"SMTP TLS\",\n fromAddress: \"From address\",\n executionMode: \"Execution mode\",\n pollIntervalSec: \"Poll interval (seconds)\",\n};\n\nconst IMAP_FIELD_PLACEHOLDERS: Record<string, string> = {\n host: \"imap.example.com\",\n port: \"993\",\n mailboxPath: \"INBOX\",\n smtpHost: \"smtp.example.com\",\n smtpPort: \"465\",\n fromAddress: \"you@example.com\",\n pollIntervalSec: \"300\",\n};\n\nexport class ShadowClawIntegrations extends ShadowClawElement {\n static styles = shadowClawIntegrationsStyles;\n static template = shadowClawIntegrationsTemplate;\n\n accounts: ServiceAccount[] = [];\n connections: EmailConnectionRecord[] = [];\n\n db: ShadowClawDatabase | null = null;\n editingConnectionId: string | null = null;\n manifests: EmailPluginManifest[] = [];\n pendingOauthResult: {\n providerId: string;\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n scope?: string;\n tokenType?: string;\n } | null = null;\n\n async connectedCallback() {\n this.db = await getDb();\n this.bindEventListeners();\n await this.reload();\n }\n\n applyImapPreset(slot: Element) {\n const presetSelect = slot.querySelector(\n \"#int-imap-preset\",\n ) as HTMLSelectElement | null;\n const usernameInput = slot.querySelector(\n \"#int-username\",\n ) as HTMLInputElement | null;\n\n const selectedPreset = presetSelect?.value || \"auto\";\n const preset = this.resolveImapPreset(\n selectedPreset,\n usernameInput?.value || \"\",\n );\n if (!preset) {\n showError(\n \"Could not auto-detect IMAP settings from this email domain. Choose a preset or enter settings manually.\",\n 5000,\n );\n\n return;\n }\n\n this.setConfigFieldValue(slot, \"host\", preset.imapHost);\n this.setConfigFieldValue(slot, \"port\", String(preset.imapPort));\n this.setConfigFieldValue(slot, \"secure\", String(preset.imapSecure));\n this.setConfigFieldValue(slot, \"smtpHost\", preset.smtpHost);\n this.setConfigFieldValue(slot, \"smtpPort\", String(preset.smtpPort));\n this.setConfigFieldValue(slot, \"smtpSecure\", String(preset.smtpSecure));\n\n const fromAddress = (usernameInput?.value || \"\").trim();\n if (fromAddress) {\n this.setConfigFieldValue(slot, \"fromAddress\", fromAddress);\n }\n\n const mailboxInput = slot.querySelector(\n \"#cfg-mailboxPath\",\n ) as HTMLInputElement | null;\n if (mailboxInput && !mailboxInput.value.trim()) {\n mailboxInput.value = \"INBOX\";\n }\n\n showSuccess(\"Applied IMAP preset defaults\", 2500);\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.showForm(null));\n }\n\n escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\\\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n }\n\n getEmailOAuthProvider(\n providerId: string | undefined,\n ): EmailOAuthProviderConfig {\n if (providerId && EMAIL_OAUTH_PROVIDERS[providerId]) {\n return EMAIL_OAUTH_PROVIDERS[providerId];\n }\n\n return EMAIL_OAUTH_PROVIDERS.google;\n }\n\n getInitialPluginId(existing: EmailConnectionRecord | null): string {\n if (existing?.pluginId) {\n return existing.pluginId;\n }\n\n if (this.manifests.some((item) => item.id === \"imap\")) {\n return \"imap\";\n }\n\n return this.manifests[0]?.id || \"\";\n }\n\n renderConfigFieldRows(\n manifest: EmailPluginManifest,\n cfg: Record<string, unknown>,\n ): string {\n return manifest.configurableFields\n .map((field) => {\n const value = cfg[field];\n const displayLabel =\n manifest.id === \"imap\" ? (IMAP_FIELD_LABELS[field] ?? field) : field;\n\n if (field === \"secure\" || field === \"smtpSecure\") {\n const selected = typeof value === \"boolean\" ? value : true;\n\n return `\n <div class=\"form-row\">\n <label for=\"cfg-${this.escapeHtml(field)}\">${this.escapeHtml(displayLabel)}</label>\n <select id=\"cfg-${this.escapeHtml(field)}\" data-config-field=\"${this.escapeHtml(field)}\">\n <option value=\"true\" ${selected ? \"selected\" : \"\"}>enabled</option>\n <option value=\"false\" ${selected ? \"\" : \"selected\"}>disabled</option>\n </select>\n </div>\n `;\n }\n\n const placeholder =\n manifest.id === \"imap\" ? (IMAP_FIELD_PLACEHOLDERS[field] ?? \"\") : \"\";\n\n return `\n <div class=\"form-row\">\n <label for=\"cfg-${this.escapeHtml(field)}\">${this.escapeHtml(displayLabel)}</label>\n <input\n id=\"cfg-${this.escapeHtml(field)}\"\n data-config-field=\"${this.escapeHtml(field)}\"\n value=\"${this.escapeHtml(typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? String(value) : \"\")}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n />\n </div>\n `;\n })\n .join(\"\");\n }\n\n renderConnectionList() {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const list = root.querySelector('[data-region=\"connection-list\"]');\n if (!list) {\n return;\n }\n\n list.replaceChildren();\n\n if (!this.connections.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"empty\";\n empty.textContent =\n \"No email connections configured. Click Add Email Connection to start.\";\n list.append(empty);\n\n return;\n }\n\n const fragment = document.createDocumentFragment();\n\n for (const connection of this.connections) {\n const manifest = getEmailPluginManifest(connection.pluginId);\n const card = document.createElement(\"article\");\n card.className = \"connection-card\";\n\n const executionMode =\n typeof connection.config.executionMode === \"string\"\n ? connection.config.executionMode\n : \"manual\";\n const pollIntervalSec =\n typeof connection.config.pollIntervalSec === \"number\"\n ? connection.config.pollIntervalSec\n : null;\n const hasAuth =\n !!connection.credentialRef?.encryptedSecret ||\n (connection.credentialRef?.authType === \"oauth\" &&\n !!connection.credentialRef?.accountId);\n\n setSanitizedHtml(\n card,\n `\n <header>\n <div>\n <div class=\"connection-title\">${this.escapeHtml(connection.label)}</div>\n <div class=\"connection-meta\">\n ${this.escapeHtml(connection.pluginId)}${manifest ? ` · ${this.escapeHtml(manifest.name)}` : \"\"}\n </div>\n </div>\n <span class=\"connection-badge ${connection.enabled ? \"enabled\" : \"disabled\"}\">\n ${connection.enabled ? \"Enabled\" : \"Disabled\"}\n </span>\n </header>\n <div class=\"connection-meta\">Mode: ${this.escapeHtml(String(executionMode))}${pollIntervalSec ? ` · Poll: ${pollIntervalSec}s` : \"\"}${hasAuth ? \" · Auth: configured\" : \" · Auth: missing\"}</div>\n <div class=\"connection-actions\">\n <button class=\"btn secondary\" data-action=\"edit\" data-id=\"${this.escapeHtml(connection.id)}\">Edit</button>\n <button class=\"btn secondary\" data-action=\"toggle\" data-id=\"${this.escapeHtml(connection.id)}\">${connection.enabled ? \"Disable\" : \"Enable\"}</button>\n <button class=\"btn secondary\" data-action=\"delete\" data-id=\"${this.escapeHtml(connection.id)}\">Delete</button>\n </div>\n `,\n );\n\n card\n .querySelectorAll<HTMLButtonElement>(\"button[data-action]\")\n .forEach((button) => {\n button.addEventListener(\"click\", () => {\n const action = button.dataset.action;\n const id = button.dataset.id;\n if (!action || !id) {\n return;\n }\n\n if (action === \"edit\") {\n this.showForm(id);\n } else if (action === \"toggle\") {\n void this.toggleConnection(id);\n } else if (action === \"delete\") {\n void this.deleteConnection(id);\n }\n });\n });\n\n fragment.append(card);\n }\n\n list.append(fragment);\n }\n\n resolveImapPreset(selection: string, username: string): ImapPreset | null {\n if (selection !== \"auto\") {\n return IMAP_PRESETS[selection] || null;\n }\n\n const domain = username.split(\"@\")[1]?.trim().toLowerCase() || \"\";\n if (!domain) {\n return null;\n }\n\n if (\n domain === \"gmail.com\" ||\n domain.endsWith(\".gmail.com\") ||\n domain.endsWith(\".googlemail.com\")\n ) {\n return IMAP_PRESETS.gmail;\n }\n\n if (\n domain === \"outlook.com\" ||\n domain === \"hotmail.com\" ||\n domain === \"live.com\" ||\n domain === \"msn.com\" ||\n domain.endsWith(\".onmicrosoft.com\")\n ) {\n return IMAP_PRESETS.outlook;\n }\n\n if (domain === \"yahoo.com\" || domain.endsWith(\".yahoo.com\")) {\n return IMAP_PRESETS.yahoo;\n }\n\n if (\n domain === \"icloud.com\" ||\n domain === \"me.com\" ||\n domain === \"mac.com\"\n ) {\n return IMAP_PRESETS.icloud;\n }\n\n if (domain === \"fastmail.com\" || domain.endsWith(\".fastmail.com\")) {\n return IMAP_PRESETS.fastmail;\n }\n\n return null;\n }\n\n setConfigFieldValue(slot: Element, field: string, value: string) {\n const node = slot.querySelector(`#cfg-${field}`) as\n | HTMLInputElement\n | HTMLSelectElement\n | null;\n if (!node) {\n return;\n }\n\n node.value = value;\n }\n\n showForm(connectionId: string | null) {\n const root = this.shadowRoot;\n if (!root) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form\"]');\n if (!slot) {\n return;\n }\n\n this.editingConnectionId = connectionId;\n const existing = connectionId\n ? this.connections.find((item) => item.id === connectionId) || null\n : null;\n\n const pluginId = this.getInitialPluginId(existing);\n const manifest = getEmailPluginManifest(pluginId);\n\n const cfg = existing?.config || {};\n const linkedOauthAccount = existing?.credentialRef?.accountId\n ? this.accounts.find(\n (account) => account.id === existing.credentialRef?.accountId,\n ) || null\n : null;\n const executionMode =\n typeof cfg.executionMode === \"string\"\n ? String(cfg.executionMode)\n : \"manual\";\n const pollIntervalSec =\n typeof cfg.pollIntervalSec === \"number\" ? cfg.pollIntervalSec : 300;\n const authMode =\n existing?.credentialRef?.authType === \"oauth\"\n ? \"oauth\"\n : \"basic_userpass\";\n const oauthProviderId =\n existing?.credentialRef?.providerId ||\n linkedOauthAccount?.oauthProviderId ||\n \"google\";\n const oauthProvider = this.getEmailOAuthProvider(oauthProviderId);\n const oauthClientId = linkedOauthAccount?.oauthClientId || \"\";\n const oauthScope =\n linkedOauthAccount?.scopes?.join(\" \") ||\n oauthProvider.defaultScopes.join(\" \");\n const oauthStatus =\n authMode === \"oauth\"\n ? linkedOauthAccount?.oauthReauthRequired\n ? \"Reconnect required\"\n : linkedOauthAccount?.token\n ? \"OAuth token already saved\"\n : \"Not connected\"\n : \"Not connected\";\n\n const isImapPlugin = pluginId === \"imap\";\n setSanitizedHtml(\n slot,\n `\n <h4>${existing ? \"Edit Email Connection\" : \"Add Email Connection\"}</h4>\n <div class=\"form-row\">\n <label for=\"int-label\">Label</label>\n <input id=\"int-label\" value=\"${this.escapeHtml(existing?.label || \"\")}\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-mode\">Execution mode</label>\n <select id=\"int-mode\">\n <option value=\"manual\" ${executionMode === \"manual\" ? \"selected\" : \"\"}>manual</option>\n <option value=\"scheduled\" ${executionMode === \"scheduled\" ? \"selected\" : \"\"}>scheduled</option>\n <option value=\"event-driven\" ${executionMode === \"event-driven\" ? \"selected\" : \"\"}>event-driven</option>\n </select>\n </div>\n <div class=\"form-row\">\n <label for=\"int-poll\">Poll interval (seconds)</label>\n <input id=\"int-poll\" type=\"number\" min=\"5\" value=\"${this.escapeHtml(String(pollIntervalSec))}\" />\n </div>\n <div class=\"form-row checkbox-row\">\n <label class=\"checkbox-inline\" for=\"int-unread-only\">\n <input id=\"int-unread-only\" type=\"checkbox\" ${cfg.unreadOnly === true ? \"checked\" : \"\"} />\n <span>Get unread email only</span>\n </label>\n </div>\n <div class=\"form-row\">\n <label for=\"int-username\">Auth username (email login)</label>\n <input id=\"int-username\" value=\"${this.escapeHtml(existing?.credentialRef?.username || \"\")}\" placeholder=\"user@example.com\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-auth-mode\">Authentication</label>\n <select id=\"int-auth-mode\">\n <option value=\"basic_userpass\" ${authMode === \"basic_userpass\" ? \"selected\" : \"\"}>App password / password</option>\n <option value=\"oauth\" ${authMode === \"oauth\" ? \"selected\" : \"\"}>OAuth</option>\n </select>\n </div>\n <div data-region=\"password-auth-fields\">\n <div class=\"form-row\">\n <label for=\"int-password\">Auth password / app password</label>\n <input id=\"int-password\" type=\"password\" placeholder=\"${existing?.credentialRef?.encryptedSecret ? \"•••••••••••• (Saved)\" : \"Enter password\"}\" />\n </div>\n </div>\n <div class=\"oauth-auth-card\" data-region=\"oauth-auth-fields\">\n <div class=\"imap-setup-title\">Email OAuth</div>\n <div class=\"form-row\">\n <label for=\"int-oauth-provider\">OAuth provider</label>\n <select id=\"int-oauth-provider\">\n ${Object.values(EMAIL_OAUTH_PROVIDERS)\n .map(\n (provider) =>\n `<option value=\"${this.escapeHtml(provider.id)}\" ${provider.id === oauthProvider.id ? \"selected\" : \"\"}>${this.escapeHtml(provider.label)}</option>`,\n )\n .join(\"\")}\n </select>\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-client-id\">OAuth client ID</label>\n <input id=\"int-oauth-client-id\" value=\"${this.escapeHtml(oauthClientId)}\" placeholder=\"Enter OAuth client ID\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-client-secret\">OAuth client secret</label>\n <input id=\"int-oauth-client-secret\" type=\"password\" placeholder=\"${linkedOauthAccount?.oauthClientSecret ? \"•••••••••••• (Saved)\" : \"Enter client secret if required\"}\" />\n </div>\n <div class=\"form-row\">\n <label for=\"int-oauth-scope\">OAuth scope</label>\n <input id=\"int-oauth-scope\" value=\"${this.escapeHtml(oauthScope)}\" placeholder=\"${this.escapeHtml(oauthProvider.scopePlaceholder)}\" />\n <div class=\"imap-setup-help\" data-region=\"oauth-scope-help\">${this.escapeHtml(oauthProvider.scopeHelpText)}</div>\n </div>\n <div class=\"oauth-connect-row\">\n <button class=\"btn secondary\" type=\"button\" data-action=\"connect-oauth\">${this.escapeHtml(oauthProvider.connectButtonLabel)}</button>\n <span class=\"oauth-status\" data-region=\"oauth-status\">${this.escapeHtml(oauthStatus)}</span>\n </div>\n </div>\n ${\n isImapPlugin\n ? `<div class=\"imap-setup-card\">\n <div class=\"imap-setup-title\">Quick IMAP Setup</div>\n <div class=\"imap-setup-row\">\n <select id=\"int-imap-preset\">\n <option value=\"auto\" selected>Auto-detect from login email</option>\n <option value=\"gmail\">Gmail / Google Workspace</option>\n <option value=\"outlook\">Outlook / Microsoft 365</option>\n <option value=\"yahoo\">Yahoo</option>\n <option value=\"icloud\">iCloud</option>\n <option value=\"fastmail\">Fastmail</option>\n </select>\n <button class=\"btn secondary\" type=\"button\" data-action=\"imap-autofill\">Autofill</button>\n </div>\n <div class=\"imap-setup-help\">Uses common provider defaults. You can still override any field below.</div>\n </div>`\n : \"\"\n }\n\n ${manifest ? this.renderConfigFieldRows(manifest, cfg) : \"\"}\n\n <div class=\"form-row\">\n <label for=\"int-extra-config\">Extra config JSON (optional)</label>\n <textarea id=\"int-extra-config\" placeholder='{\"mailboxPath\":\"INBOX\"}'></textarea>\n </div>\n <div class=\"form-actions\">\n <button class=\"btn secondary\" data-action=\"cancel\">Cancel</button>\n <button class=\"btn secondary\" data-action=\"test-connection\">Test Connection</button>\n <button class=\"btn\" data-action=\"save\">Save</button>\n </div>\n `,\n );\n\n const formNode = slot as HTMLElement;\n formNode.hidden = false;\n\n this.pendingOauthResult = null;\n\n slot\n .querySelector(\"#int-auth-mode\")\n ?.addEventListener(\"change\", () => this.updateAuthModeVisibility(slot));\n\n slot\n .querySelector('[data-action=\"imap-autofill\"]')\n ?.addEventListener(\"click\", () => this.applyImapPreset(slot));\n slot\n .querySelector('[data-action=\"connect-oauth\"]')\n ?.addEventListener(\"click\", () => void this.connectOAuthFromForm(slot));\n slot\n .querySelector(\"#int-oauth-provider\")\n ?.addEventListener(\"change\", () => this.updateOAuthProviderHelp(slot));\n\n slot\n .querySelector('[data-action=\"cancel\"]')\n ?.addEventListener(\"click\", () => {\n formNode.hidden = true;\n formNode.replaceChildren();\n this.editingConnectionId = null;\n });\n\n slot\n .querySelector('[data-action=\"save\"]')\n ?.addEventListener(\"click\", () => {\n void this.saveForm();\n });\n\n slot\n .querySelector('[data-action=\"test-connection\"]')\n ?.addEventListener(\"click\", () => {\n void this.testConnectionFromForm(slot);\n });\n\n this.updateAuthModeVisibility(slot);\n this.updateOAuthProviderHelp(slot);\n }\n\n updateAuthModeVisibility(slot: Element) {\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n\n const passwordFields = slot.querySelector(\n '[data-region=\"password-auth-fields\"]',\n ) as HTMLElement | null;\n const oauthFields = slot.querySelector(\n '[data-region=\"oauth-auth-fields\"]',\n ) as HTMLElement | null;\n\n if (passwordFields) {\n passwordFields.style.display = authMode === \"oauth\" ? \"none\" : \"block\";\n }\n\n if (oauthFields) {\n oauthFields.style.display = authMode === \"oauth\" ? \"block\" : \"none\";\n }\n }\n\n updateOAuthProviderHelp(slot: Element) {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const provider = this.getEmailOAuthProvider(providerId);\n\n const scopeInput = slot.querySelector(\n \"#int-oauth-scope\",\n ) as HTMLInputElement | null;\n const scopeHelp = slot.querySelector(\n '[data-region=\"oauth-scope-help\"]',\n ) as HTMLElement | null;\n const connectBtn = slot.querySelector(\n '[data-action=\"connect-oauth\"]',\n ) as HTMLButtonElement | null;\n\n if (scopeInput) {\n scopeInput.placeholder = provider.scopePlaceholder;\n if (!scopeInput.value.trim()) {\n scopeInput.value = provider.defaultScopes.join(\" \");\n }\n }\n\n if (scopeHelp) {\n scopeHelp.textContent = provider.scopeHelpText;\n }\n\n if (connectBtn) {\n connectBtn.textContent = provider.connectButtonLabel;\n }\n }\n\n async buildCredentialRef(\n slot: Element,\n savedConnection: EmailConnectionRecord,\n ): Promise<EmailCredentialRef | null> {\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n const usernameInput = slot.querySelector(\n \"#int-username\",\n ) as HTMLInputElement | null;\n const passwordInput = slot.querySelector(\n \"#int-password\",\n ) as HTMLInputElement | null;\n\n const username = usernameInput?.value.trim() || \"\";\n const passwordRaw = passwordInput?.value.trim() || \"\";\n\n const existing = this.connections.find(\n (item) => item.id === savedConnection.id,\n );\n\n if (authMode === \"oauth\") {\n if (!username) {\n throw new Error(\n \"Email login address is required for OAuth authentication.\",\n );\n }\n\n const linkedAccount = await this.upsertLinkedOAuthAccount(\n slot,\n savedConnection,\n );\n\n return {\n serviceType: \"http_api\",\n authType: \"oauth\",\n providerId: linkedAccount.oauthProviderId || \"google\",\n accountId: linkedAccount.id,\n username,\n };\n }\n\n let encryptedSecret: string | undefined;\n if (passwordRaw) {\n encryptedSecret = (await encryptValue(passwordRaw)) || undefined;\n if (!encryptedSecret) {\n throw new Error(\"Could not encrypt email password.\");\n }\n } else {\n encryptedSecret = existing?.credentialRef?.encryptedSecret;\n }\n\n if (!username && !encryptedSecret) {\n return null;\n }\n\n if (!username) {\n throw new Error(\n \"Auth username is required when a password is configured.\",\n );\n }\n\n if (!encryptedSecret) {\n throw new Error(\"Auth password is required when username is configured.\");\n }\n\n return {\n serviceType: \"http_api\",\n authType: \"basic_userpass\",\n username,\n encryptedSecret,\n };\n }\n\n async connectOAuthFromForm(slot: Element) {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const provider = this.getEmailOAuthProvider(providerId);\n const clientId = (\n slot.querySelector(\"#int-oauth-client-id\") as HTMLInputElement | null\n )?.value.trim();\n const clientSecret = (\n slot.querySelector(\"#int-oauth-client-secret\") as HTMLInputElement | null\n )?.value.trim();\n const scopeRaw = (\n slot.querySelector(\"#int-oauth-scope\") as HTMLInputElement | null\n )?.value.trim();\n const oauthStatus = slot.querySelector(\n '[data-region=\"oauth-status\"]',\n ) as HTMLElement | null;\n const connectBtn = slot.querySelector(\n '[data-action=\"connect-oauth\"]',\n ) as HTMLButtonElement | null;\n\n if (!clientId) {\n showError(\"OAuth client ID is required.\", 4000);\n\n return;\n }\n\n if (oauthStatus) {\n oauthStatus.textContent = \"Starting OAuth...\";\n }\n\n if (connectBtn) {\n connectBtn.disabled = true;\n }\n\n try {\n const scope = scopeRaw\n ? scopeRaw\n .split(/[\\s,]+/)\n .map((token) => token.trim())\n .filter(Boolean)\n : provider.defaultScopes;\n const redirectUri = `${window.location.origin}/oauth/callback`;\n\n const authorizeRes = await fetch(\"/oauth/authorize\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n providerId: provider.id,\n clientId,\n clientSecret: clientSecret || undefined,\n redirectUri,\n scope,\n extraAuthorizeParams: {\n access_type: \"offline\",\n prompt: \"consent\",\n },\n }),\n });\n\n const authorizePayload = (await authorizeRes.json()) as {\n state?: string;\n authorizeUrl?: string;\n error?: string;\n };\n\n if (\n !authorizeRes.ok ||\n !authorizePayload.state ||\n !authorizePayload.authorizeUrl\n ) {\n throw new Error(authorizePayload.error || \"OAuth authorize failed\");\n }\n\n window.open(\n authorizePayload.authorizeUrl,\n \"shadowclaw-google-oauth\",\n \"popup=yes,width=540,height=720\",\n );\n\n const state = authorizePayload.state;\n let status = \"pending\";\n for (let attempt = 0; attempt < 60; attempt++) {\n const sessionRes = await fetch(\n `/oauth/session/${encodeURIComponent(state)}`,\n );\n const sessionPayload = (await sessionRes.json()) as {\n status?: string;\n error?: string;\n };\n\n if (!sessionRes.ok) {\n throw new Error(sessionPayload.error || \"OAuth session not found\");\n }\n\n status = sessionPayload.status || \"pending\";\n if (status === \"authorized\") {\n break;\n }\n\n if (status === \"error\") {\n throw new Error(sessionPayload.error || \"OAuth authorization failed\");\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n\n if (status !== \"authorized\") {\n throw new Error(\"OAuth authorization timed out\");\n }\n\n const tokenRes = await fetch(\"/oauth/token\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ state }),\n });\n\n const tokenPayload = (await tokenRes.json()) as {\n accessToken?: string;\n refreshToken?: string;\n expiresIn?: number;\n scope?: string;\n tokenType?: string;\n error?: string;\n };\n\n if (!tokenRes.ok || !tokenPayload.accessToken) {\n throw new Error(tokenPayload.error || \"OAuth token exchange failed\");\n }\n\n this.pendingOauthResult = {\n providerId: provider.id,\n accessToken: tokenPayload.accessToken,\n refreshToken: tokenPayload.refreshToken,\n expiresAt: tokenPayload.expiresIn\n ? Date.now() + tokenPayload.expiresIn * 1000\n : undefined,\n scope: tokenPayload.scope,\n tokenType: tokenPayload.tokenType,\n };\n\n if (oauthStatus) {\n oauthStatus.textContent = \"OAuth connected\";\n }\n\n showSuccess(`${provider.label} connected`, 3000);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (oauthStatus) {\n oauthStatus.textContent = \"OAuth failed\";\n }\n\n showError(`${provider.label} connect failed: ${message}`, 6000);\n } finally {\n if (connectBtn) {\n connectBtn.disabled = false;\n }\n }\n }\n\n async deleteConnection(id: string) {\n if (!this.db) {\n return;\n }\n\n const record = this.connections.find((item) => item.id === id);\n if (!record) {\n return;\n }\n\n const confirmed = await this.requestConfirmation({\n title: \"Delete Email Connection\",\n message: `Delete email connection \\\"${record.label}\\\"?`,\n confirmLabel: \"Delete\",\n cancelLabel: \"Cancel\",\n });\n\n if (!confirmed) {\n return;\n }\n\n try {\n const ok = await deleteEmailConnection(this.db, id);\n if (!ok) {\n showError(\"Failed to delete email connection.\", 5000);\n\n return;\n }\n\n showSuccess(\"Email connection deleted\", 2500);\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to delete email connection: ${message}`, 6000);\n }\n }\n\n async reload() {\n if (!this.db) {\n return;\n }\n\n this.manifests = listEmailPluginManifests().filter(\n (manifest) => manifest.id === \"imap\",\n );\n this.connections = await listEmailConnections(this.db);\n const rawAccounts = await getConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS);\n this.accounts = Array.isArray(rawAccounts) ? rawAccounts : [];\n this.renderConnectionList();\n }\n\n async requestConfirmation(options: {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n }): Promise<boolean> {\n const appShell = document.querySelector(\"shadow-claw\") as any;\n if (appShell && typeof appShell.requestDialog === \"function\") {\n return await appShell.requestDialog({ mode: \"confirm\", ...options });\n }\n\n return false;\n }\n\n async saveForm() {\n const root = this.shadowRoot;\n if (!root || !this.db) {\n return;\n }\n\n const slot = root.querySelector('[data-region=\"connection-form\"]');\n if (!slot) {\n return;\n }\n\n const labelInput = slot.querySelector(\n \"#int-label\",\n ) as HTMLInputElement | null;\n const modeInput = slot.querySelector(\n \"#int-mode\",\n ) as HTMLSelectElement | null;\n const pollInput = slot.querySelector(\n \"#int-poll\",\n ) as HTMLInputElement | null;\n const extraInput = slot.querySelector(\n \"#int-extra-config\",\n ) as HTMLTextAreaElement | null;\n\n if (!labelInput || !modeInput || !pollInput) {\n return;\n }\n\n const label = labelInput.value.trim();\n const pluginId = this.getInitialPluginId(null);\n\n if (!label || !pluginId) {\n showError(\"Label is required.\", 4000);\n\n return;\n }\n\n const config: Record<string, unknown> = {\n executionMode: modeInput.value,\n };\n\n const pollSec = Number(pollInput.value);\n if (Number.isFinite(pollSec) && pollSec > 0) {\n config.pollIntervalSec = Math.floor(pollSec);\n }\n\n const unreadOnlyInput = slot.querySelector(\n \"#int-unread-only\",\n ) as HTMLInputElement | null;\n config.unreadOnly = unreadOnlyInput?.checked === true;\n\n slot\n .querySelectorAll<HTMLInputElement>(\"[data-config-field]\")\n .forEach((input) => {\n const key = input.dataset.configField;\n if (!key) {\n return;\n }\n\n const value = input.value.trim();\n if (!value) {\n return;\n }\n\n if (/^\\d+$/.test(value)) {\n config[key] = Number(value);\n } else if (value === \"true\" || value === \"false\") {\n config[key] = value === \"true\";\n } else {\n config[key] = value;\n }\n });\n\n const extraRaw = extraInput?.value.trim() || \"\";\n if (extraRaw) {\n try {\n const parsed = JSON.parse(extraRaw);\n if (parsed && typeof parsed === \"object\") {\n Object.assign(config, parsed as Record<string, unknown>);\n }\n } catch {\n showError(\"Extra config JSON is invalid.\", 5000);\n\n return;\n }\n }\n\n try {\n const upserted = await upsertEmailConnection(this.db, {\n id: this.editingConnectionId || undefined,\n label,\n pluginId,\n config,\n });\n\n const credentialRef = await this.buildCredentialRef(slot, upserted);\n await bindEmailCredentialRef(this.db, upserted.id, credentialRef);\n\n showSuccess(\n this.editingConnectionId\n ? \"Email connection updated\"\n : \"Email connection created\",\n 3000,\n );\n\n (slot as HTMLElement).hidden = true;\n slot.replaceChildren();\n this.editingConnectionId = null;\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to save email connection: ${message}`, 6000);\n }\n }\n\n async testConnectionFromForm(slot: Element) {\n const testButton = slot.querySelector(\n '[data-action=\"test-connection\"]',\n ) as HTMLButtonElement | null;\n if (testButton) {\n testButton.disabled = true;\n }\n\n try {\n const username = (\n slot.querySelector(\"#int-username\") as HTMLInputElement | null\n )?.value.trim();\n const host = (\n slot.querySelector(\"#cfg-host\") as HTMLInputElement | null\n )?.value.trim();\n const mailboxPath =\n (\n slot.querySelector(\"#cfg-mailboxPath\") as HTMLInputElement | null\n )?.value.trim() || \"INBOX\";\n const portRaw = (\n slot.querySelector(\"#cfg-port\") as HTMLInputElement | null\n )?.value.trim();\n const secureRaw = (\n slot.querySelector(\"#cfg-secure\") as HTMLSelectElement | null\n )?.value;\n const unreadOnly = (\n slot.querySelector(\"#int-unread-only\") as HTMLInputElement | null\n )?.checked;\n const authMode = (\n slot.querySelector(\"#int-auth-mode\") as HTMLSelectElement | null\n )?.value;\n\n if (!username) {\n showError(\"Auth username (email login) is required.\", 4000);\n\n return;\n }\n\n if (!host) {\n showError(\"IMAP host is required.\", 4000);\n\n return;\n }\n\n const port = Number(portRaw);\n const resolvedPort = Number.isFinite(port) && port > 0 ? port : 993;\n const secure = secureRaw === \"false\" ? false : true;\n\n let authType: \"basic_userpass\" | \"oauth\" = \"basic_userpass\";\n let password: string | undefined;\n let accessToken: string | undefined;\n\n const existing = this.editingConnectionId\n ? this.connections.find((item) => item.id === this.editingConnectionId)\n : null;\n\n if (authMode === \"oauth\") {\n const providerId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const pendingOauthAccessToken =\n this.pendingOauthResult?.accessToken &&\n (!providerId || this.pendingOauthResult.providerId === providerId)\n ? this.pendingOauthResult.accessToken\n : \"\";\n\n const result = resolveConnectionTestAuth({\n authMode,\n pendingOauthAccessToken,\n hasStoredOauthCredential: Boolean(existing?.credentialRef?.accountId),\n });\n\n if (\"error\" in result) {\n showError(result.error, 6000);\n\n return;\n }\n\n authType = result.authType;\n if (result.authType === \"oauth\") {\n accessToken = result.accessToken;\n }\n } else {\n const passwordInput = (\n slot.querySelector(\"#int-password\") as HTMLInputElement | null\n )?.value;\n\n const result = resolveConnectionTestAuth({\n authMode,\n passwordInput,\n hasStoredPasswordCredential: Boolean(\n existing?.credentialRef?.encryptedSecret,\n ),\n });\n\n if (\"error\" in result) {\n showError(result.error, 6000);\n\n return;\n }\n\n authType = result.authType;\n if (result.authType === \"basic_userpass\") {\n password = result.password;\n }\n }\n\n const response = await fetch(\"/integrations/email/read\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n authType,\n host,\n port: resolvedPort,\n secure,\n username,\n password,\n accessToken,\n mailboxPath,\n limit: 1,\n unreadOnly: unreadOnly === true,\n }),\n });\n\n const payload = (await response.json().catch(() => ({}))) as {\n error?: string;\n count?: number;\n };\n\n if (!response.ok) {\n showError(\n `Connection test failed (${response.status}): ${payload.error || response.statusText}`,\n 7000,\n );\n\n return;\n }\n\n showSuccess(\n `Connection test passed. IMAP login succeeded${typeof payload.count === \"number\" ? ` (${payload.count} messages returned).` : \".\"}`,\n 4500,\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Connection test failed: ${message}`, 7000);\n } finally {\n if (testButton) {\n testButton.disabled = false;\n }\n }\n }\n\n async toggleConnection(id: string) {\n if (!this.db) {\n return;\n }\n\n const record = this.connections.find((item) => item.id === id);\n if (!record) {\n showError(\"Email connection not found.\", 4000);\n\n return;\n }\n\n try {\n await upsertEmailConnection(this.db, {\n id: record.id,\n label: record.label,\n pluginId: record.pluginId,\n enabled: !record.enabled,\n config: record.config,\n });\n\n showSuccess(`Email ${!record.enabled ? \"enabled\" : \"disabled\"}`, 2500);\n await this.reload();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to update email connection: ${message}`, 6000);\n }\n }\n\n async upsertLinkedOAuthAccount(\n slot: Element,\n savedConnection: EmailConnectionRecord,\n ): Promise<ServiceAccount> {\n if (!this.db) {\n throw new Error(\"Database is not ready.\");\n }\n\n const username = (\n slot.querySelector(\"#int-username\") as HTMLInputElement | null\n )?.value.trim();\n const clientId = (\n slot.querySelector(\"#int-oauth-client-id\") as HTMLInputElement | null\n )?.value.trim();\n const clientSecretRaw = (\n slot.querySelector(\"#int-oauth-client-secret\") as HTMLInputElement | null\n )?.value.trim();\n const scopeRaw = (\n slot.querySelector(\"#int-oauth-scope\") as HTMLInputElement | null\n )?.value.trim();\n const selectedProviderId = (\n slot.querySelector(\"#int-oauth-provider\") as HTMLSelectElement | null\n )?.value;\n const oauthProvider = this.getEmailOAuthProvider(selectedProviderId);\n\n if (!username) {\n throw new Error(\n \"Email login address is required for OAuth authentication.\",\n );\n }\n\n if (!clientId) {\n throw new Error(\"OAuth client ID is required for OAuth authentication.\");\n }\n\n const existingConnection = this.connections.find(\n (item) => item.id === savedConnection.id,\n );\n\n const existingAccountId = existingConnection?.credentialRef?.accountId;\n const existingAccount = existingAccountId\n ? this.accounts.find((account) => account.id === existingAccountId) ||\n null\n : null;\n\n let token = existingAccount?.token || \"\";\n let refreshToken = existingAccount?.refreshToken;\n let accessTokenExpiresAt = existingAccount?.accessTokenExpiresAt;\n let scopes = existingAccount?.scopes;\n let tokenType = existingAccount?.tokenType;\n let oauthClientSecret = existingAccount?.oauthClientSecret;\n let oauthRefreshFailureCount = existingAccount?.oauthRefreshFailureCount;\n let oauthReauthRequired = existingAccount?.oauthReauthRequired;\n let oauthReauthRequiredAt = existingAccount?.oauthReauthRequiredAt;\n\n if (clientSecretRaw) {\n const encryptedClientSecret = await encryptValue(clientSecretRaw);\n if (encryptedClientSecret) {\n oauthClientSecret = encryptedClientSecret;\n }\n }\n\n if (this.pendingOauthResult?.accessToken) {\n const encryptedAccessToken = await encryptValue(\n this.pendingOauthResult.accessToken,\n );\n if (!encryptedAccessToken) {\n throw new Error(\"Failed to encrypt OAuth access token.\");\n }\n\n token = encryptedAccessToken;\n\n if (this.pendingOauthResult.refreshToken) {\n const encryptedRefreshToken = await encryptValue(\n this.pendingOauthResult.refreshToken,\n );\n if (encryptedRefreshToken) {\n refreshToken = encryptedRefreshToken;\n }\n }\n\n accessTokenExpiresAt = this.pendingOauthResult.expiresAt;\n scopes = this.pendingOauthResult.scope\n ? this.pendingOauthResult.scope\n .split(/[\\s,]+/)\n .map((entry) => entry.trim())\n .filter(Boolean)\n : scopeRaw\n ? scopeRaw\n .split(/[\\s,]+/)\n .map((entry) => entry.trim())\n .filter(Boolean)\n : oauthProvider.defaultScopes;\n tokenType = this.pendingOauthResult.tokenType;\n oauthRefreshFailureCount = 0;\n oauthReauthRequired = false;\n oauthReauthRequiredAt = undefined;\n }\n\n if (!token) {\n throw new Error(\"Connect OAuth first to obtain an access token.\");\n }\n\n const accountId = existingAccount?.id || ulid();\n const account: ServiceAccount = {\n id: accountId,\n label: `${savedConnection.label} ${oauthProvider.label}`,\n service: oauthProvider.serviceName,\n hostPattern: oauthProvider.hostPattern,\n token,\n authMode: \"oauth\",\n oauthProviderId: oauthProvider.id,\n oauthClientId: clientId,\n oauthClientSecret,\n accessTokenExpiresAt,\n refreshToken,\n scopes: scopes || oauthProvider.defaultScopes,\n tokenType,\n oauthRefreshFailureCount,\n oauthReauthRequired,\n oauthReauthRequiredAt,\n };\n\n const accounts = [...this.accounts];\n const existingIdx = accounts.findIndex((item) => item.id === accountId);\n if (existingIdx === -1) {\n accounts.push(account);\n } else {\n accounts[existingIdx] = account;\n }\n\n await setConfig(this.db, CONFIG_KEYS.SERVICE_ACCOUNTS, accounts);\n this.accounts = accounts;\n\n return account;\n }\n}\n\nif (!customElements.get(elementName)) {\n customElements.define(elementName, ShadowClawIntegrations);\n}\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { n as getDb } from "./txPromise-CuGh-TGK.js";
3
3
  import { P as getModelMaxTokens, R as modelRegistry, c as DEFAULT_PROMPT_API_FALLBACK_MODEL, r as CONFIG_KEYS, u as DEFAULT_SUBAGENT_WORKSPACE_MODE } from "./config--CFrw3J3.js";
4
4
  import { t as getConfig } from "./getConfig-BxxXMyuM.js";
5
- import { B as getApiKeyForHeaders, H as getAvailableProviders, J as setBedrockSettings, Ot as isPromptApiSupported, Rt as fetchTokenizerConfig, U as getBedrockSettings, W as getLlamafileSettings, X as setMeshLlmSettings, Y as setLlamafileSettings, Z as setModel, at as buildLlamafileHelpDialogOptions, c as setMaxIterations, d as setRateLimitAutoAdapt, et as setProvider, f as setRateLimitCallsPerMinute, it as LLAMAFILE_EXPECTED_DIR, l as setMaxTokens, m as setStreamingEnabled, p as setReasoningEffort, s as setContextCompressionEnabled, t as orchestratorStore } from "./orchestrator-DCfomsn9.js";
5
+ import { B as getApiKeyForHeaders, H as getAvailableProviders, J as setBedrockSettings, Ot as isPromptApiSupported, Rt as fetchTokenizerConfig, U as getBedrockSettings, W as getLlamafileSettings, X as setMeshLlmSettings, Y as setLlamafileSettings, Z as setModel, at as buildLlamafileHelpDialogOptions, c as setMaxIterations, d as setRateLimitAutoAdapt, et as setProvider, f as setRateLimitCallsPerMinute, it as LLAMAFILE_EXPECTED_DIR, l as setMaxTokens, m as setStreamingEnabled, p as setReasoningEffort, s as setContextCompressionEnabled, t as orchestratorStore } from "./orchestrator-KRjx0eba.js";
6
6
  import { t as setConfig } from "./setConfig-BFED5CXn.js";
7
- import { n as setSanitizedHtml } from "./trusted-types-CkLDpLiZ.js";
7
+ import { n as setSanitizedHtml } from "./trusted-types-Dx0RZlrd.js";
8
8
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-DZ6r7_YI.js";
9
9
  import { n as isNativePromptApiSupported, r as isPromptApiPotentiallySupported } from "./prompt-api-DJvb1BN7.js";
10
10
  import { t as effect } from "./effect-DL6j9HJp.js";
@@ -1777,4 +1777,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
1777
1777
 
1778
1778
  //#endregion
1779
1779
  export { ShadowClawLlm as t };
1780
- //# sourceMappingURL=shadow-claw-llm-BazJdD5f.js.map
1780
+ //# sourceMappingURL=shadow-claw-llm-CazBrVpM.js.map