shadow-claw 1.51.0 → 1.52.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 (296) hide show
  1. package/.well-known/mcp/server-card.json +1 -1
  2. package/.well-known/mcp.json +1 -1
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-Dtse8rAn.js → chunk-5ryVpyup.js} +1 -1
  5. package/dist/cli/chunk-Aq3057Xo.js +1 -0
  6. package/dist/cli/{chunk-4CZJpLqA.js → chunk-BV9JBYpl.js} +2 -2
  7. package/dist/cli/{chunk-mbFAP9Ev.js → chunk-BZI3bWDA.js} +1 -1
  8. package/dist/cli/chunk-BaUCHRPD.js +1 -0
  9. package/dist/cli/{chunk-vzUrhBN5.js → chunk-BdbEt6gM.js} +1 -1
  10. package/dist/cli/{chunk-BU8UG4L_.js → chunk-BiWLawPV.js} +1 -1
  11. package/dist/cli/chunk-BkLnHJeo.js +1 -0
  12. package/dist/cli/{chunk-BqfPWIBf.js → chunk-BzWY1sKE.js} +1 -1
  13. package/dist/cli/{chunk-DajM7Kro.js → chunk-C79eIU-4.js} +1 -1
  14. package/dist/cli/{chunk-CI9r1AM5.js → chunk-CDw214Zi.js} +1 -1
  15. package/dist/cli/chunk-CNqc7LLn.js +1 -0
  16. package/dist/cli/{chunk-CEhU-Ah-.js → chunk-CWW7dqIv.js} +1 -1
  17. package/dist/cli/{chunk-BT_C3OlA.js → chunk-CcSTYHtR.js} +1 -1
  18. package/dist/cli/chunk-ClOfk6Ga.js +1 -0
  19. package/dist/cli/chunk-ComXUwW0.js +1 -0
  20. package/dist/cli/{chunk-lL1BhHVe.js → chunk-CooeO4UQ.js} +1 -1
  21. package/dist/cli/{chunk-khr7--yI.js → chunk-CtfWY4G6.js} +1 -1
  22. package/dist/cli/{chunk-C4iW1XuQ.js → chunk-DFgSiYMW.js} +1 -1
  23. package/dist/cli/chunk-DGBnjngK.js +1 -0
  24. package/dist/cli/{chunk-D7bFIUK3.js → chunk-DGu1OhJs.js} +1 -1
  25. package/dist/cli/{chunk-CzfOerQR.js → chunk-DIjCY0Wf.js} +1 -1
  26. package/dist/cli/{chunk-D-iqEY5G.js → chunk-DJ_LeQtz.js} +1 -1
  27. package/dist/cli/{chunk-BmEsDkRK.js → chunk-DQRu-9wO.js} +1 -1
  28. package/dist/cli/{chunk-DojiYody.js → chunk-DToVgO9a.js} +1 -1
  29. package/dist/cli/{chunk-De5a_Rlp.js → chunk-DVbNkQRL.js} +1 -1
  30. package/dist/cli/{chunk-c8MIYB2y.js → chunk-Ddtzaj43.js} +1 -1
  31. package/dist/cli/{chunk-aJ6fufe-.js → chunk-DiqS56rD.js} +1 -1
  32. package/dist/cli/{chunk-CeUEmZNt.js → chunk-DnRcu9b4.js} +1 -1
  33. package/dist/cli/chunk-DtgZDsJA.js +1 -0
  34. package/dist/cli/{chunk-DVMcK7g6.js → chunk-Du4qvxo_.js} +2 -2
  35. package/dist/cli/{chunk-CegcvNc9.js → chunk-Dz5_hgvL.js} +8 -8
  36. package/dist/cli/{chunk-Cd4Dv5Eq.js → chunk-I3mxEelq.js} +1 -1
  37. package/dist/cli/{chunk-Do3VICh1.js → chunk-IU2SH_ti.js} +1 -1
  38. package/dist/cli/{chunk-BQveaAaD.js → chunk-NC8XsSSA.js} +1 -1
  39. package/dist/cli/{chunk-D702W_Ry.js → chunk-Q4BZ9QN9.js} +1 -1
  40. package/dist/cli/chunk-WTlDd4Ou.js +1 -0
  41. package/dist/cli/chunk-XGzq5joC.js +1 -0
  42. package/dist/cli/{chunk-ar7eAlxK.js → chunk-aJfaGe2s.js} +8 -8
  43. package/dist/cli/chunk-bPVrFlmk.js +1 -0
  44. package/dist/cli/chunk-jXJHKxdR.js +1 -0
  45. package/dist/cli/{chunk-C3dTAmV_.js → chunk-rstVU7U0.js} +1 -1
  46. package/dist/cli/{chunk-DGfTzQui.js → chunk-t72uObQ7.js} +1 -1
  47. package/dist/cli/{chunk-DDgfljzN.js → chunk-vq8xlroY.js} +1 -1
  48. package/dist/cli/cli.js +1 -1
  49. package/dist/headless-agent.js +1 -1
  50. package/dist/lib/components/common/shadow-claw-provider-model-picker.js +1 -1
  51. package/dist/lib/components/index.js +27 -27
  52. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  53. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  54. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  55. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  56. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  57. package/dist/lib/components/settings/shadow-claw-llm/model-ranking.d.ts +12 -0
  58. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  59. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  60. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  61. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  62. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  63. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  64. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  65. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  66. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  67. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  68. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  69. package/dist/lib/components/shadow-claw-channels.js +1 -1
  70. package/dist/lib/components/shadow-claw-chat/shadow-claw-chat.d.ts +1 -0
  71. package/dist/lib/components/shadow-claw-chat.js +1 -1
  72. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  73. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  74. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  75. package/dist/lib/components/shadow-claw-files.js +1 -1
  76. package/dist/lib/components/shadow-claw-git.js +1 -1
  77. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  78. package/dist/lib/components/shadow-claw-llm.js +1 -1
  79. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  80. package/dist/lib/components/shadow-claw-networking.js +1 -1
  81. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  82. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  83. package/dist/lib/components/shadow-claw-pages.js +1 -1
  84. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  85. package/dist/lib/components/shadow-claw-provider-model-picker.js +1 -1
  86. package/dist/lib/components/shadow-claw-settings.js +1 -1
  87. package/dist/lib/components/shadow-claw-storage.js +1 -1
  88. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  89. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  90. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  91. package/dist/lib/components/shadow-claw-tools.js +1 -1
  92. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  93. package/dist/lib/components/shadow-claw.js +1 -1
  94. package/dist/lib/config/config.d.ts +2 -1
  95. package/dist/lib/{config-DxDaVDTn.js → config-DFLs7eoC.js} +3 -2
  96. package/dist/lib/config-DFLs7eoC.js.map +1 -0
  97. package/dist/lib/{configurePeerJs-ScwZiGbF.js → configurePeerJs-DJ0H6e6s.js} +3 -3
  98. package/dist/lib/{configurePeerJs-ScwZiGbF.js.map → configurePeerJs-DJ0H6e6s.js.map} +1 -1
  99. package/dist/lib/{connections-D82zele0.js → connections-DT3nPylw.js} +2 -2
  100. package/dist/lib/{connections-D82zele0.js.map → connections-DT3nPylw.js.map} +1 -1
  101. package/dist/lib/{downloadGroupFile-D7-5y6NI.js → downloadGroupFile-DMnAiPj4.js} +2 -2
  102. package/dist/lib/{downloadGroupFile-D7-5y6NI.js.map → downloadGroupFile-DMnAiPj4.js.map} +1 -1
  103. package/dist/lib/{file-viewer-BMvvndPQ.js → file-viewer-OHmGC_l7.js} +5 -5
  104. package/dist/lib/{file-viewer-BMvvndPQ.js.map → file-viewer-OHmGC_l7.js.map} +1 -1
  105. package/dist/lib/{getGroupDir-BidwYPfP.js → getGroupDir-mTV2Iz2b.js} +3 -3
  106. package/dist/lib/{getGroupDir-BidwYPfP.js.map → getGroupDir-mTV2Iz2b.js.map} +1 -1
  107. package/dist/lib/{git-CXmWufWS.js → git-CGdKghMC.js} +3 -3
  108. package/dist/lib/{git-CXmWufWS.js.map → git-CGdKghMC.js.map} +1 -1
  109. package/dist/lib/index.js +28 -28
  110. package/dist/lib/{initChatSplitResize-tvUZ-wsp.js → initChatSplitResize-B8zHHQdm.js} +2 -2
  111. package/dist/lib/{initChatSplitResize-tvUZ-wsp.js.map → initChatSplitResize-B8zHHQdm.js.map} +1 -1
  112. package/dist/lib/{initControlPlane-Dnjkb-6J.js → initControlPlane-BczrlTf3.js} +14 -14
  113. package/dist/lib/{initControlPlane-Dnjkb-6J.js.map → initControlPlane-BczrlTf3.js.map} +1 -1
  114. package/dist/lib/{markdown-WCXar9C8.js → markdown-D-7Cjyye.js} +3 -3
  115. package/dist/lib/{markdown-WCXar9C8.js.map → markdown-D-7Cjyye.js.map} +1 -1
  116. package/dist/lib/{mcp-reconnect-WTOQONHZ.js → mcp-reconnect-Czf7QCCv.js} +2 -2
  117. package/dist/lib/{mcp-reconnect-WTOQONHZ.js.map → mcp-reconnect-Czf7QCCv.js.map} +1 -1
  118. package/dist/lib/{memoryStorage-Bo2Wpfmg.js → memoryStorage-CXyKsKMo.js} +2 -2
  119. package/dist/lib/{memoryStorage-Bo2Wpfmg.js.map → memoryStorage-CXyKsKMo.js.map} +1 -1
  120. package/dist/lib/model-ranking-Bo8CpGH1.js +116 -0
  121. package/dist/lib/model-ranking-Bo8CpGH1.js.map +1 -0
  122. package/dist/lib/{orchestrator-Crw4btGn.js → orchestrator-BK138MkV.js} +10 -10
  123. package/dist/lib/{orchestrator-Crw4btGn.js.map → orchestrator-BK138MkV.js.map} +1 -1
  124. package/dist/lib/{orchestrator-Dro541iH.js → orchestrator-BtbxiPQB.js} +17 -16
  125. package/dist/lib/{orchestrator-Dro541iH.js.map → orchestrator-BtbxiPQB.js.map} +1 -1
  126. package/dist/lib/{peerjs-D741bHrf.js → peerjs-QJr03K9F.js} +7 -7
  127. package/dist/lib/{peerjs-D741bHrf.js.map → peerjs-QJr03K9F.js.map} +1 -1
  128. package/dist/lib/{prompt-api-D9XdrCep.js → prompt-api-vf351sf2.js} +2 -19
  129. package/dist/lib/{prompt-api-D9XdrCep.js.map → prompt-api-vf351sf2.js.map} +1 -1
  130. package/dist/lib/{push-client-DKFUY_Ti.js → push-client-BOHgqHbk.js} +4 -4
  131. package/dist/lib/{push-client-DKFUY_Ti.js.map → push-client-BOHgqHbk.js.map} +1 -1
  132. package/dist/lib/{readGroupFileBytes-C8Xqlb8l.js → readGroupFileBytes-CRA6dmgT.js} +2 -2
  133. package/dist/lib/{readGroupFileBytes-C8Xqlb8l.js.map → readGroupFileBytes-CRA6dmgT.js.map} +1 -1
  134. package/dist/lib/{shadow-claw-a2ui-CPydWVdW.js → shadow-claw-a2ui-DbZa4Gxp.js} +2 -2
  135. package/dist/lib/{shadow-claw-a2ui-CPydWVdW.js.map → shadow-claw-a2ui-DbZa4Gxp.js.map} +1 -1
  136. package/dist/lib/{shadow-claw-accounts-CUypXc3I.js → shadow-claw-accounts-B6OW2NVD.js} +3 -3
  137. package/dist/lib/{shadow-claw-accounts-CUypXc3I.js.map → shadow-claw-accounts-B6OW2NVD.js.map} +1 -1
  138. package/dist/lib/{shadow-claw-channel-config-D_Vb2ous.js → shadow-claw-channel-config-F_EJ-uK2.js} +3 -3
  139. package/dist/lib/{shadow-claw-channel-config-D_Vb2ous.js.map → shadow-claw-channel-config-F_EJ-uK2.js.map} +1 -1
  140. package/dist/lib/{shadow-claw-channels-hgjjzvRr.js → shadow-claw-channels-XYylMpjg.js} +3 -3
  141. package/dist/lib/{shadow-claw-channels-hgjjzvRr.js.map → shadow-claw-channels-XYylMpjg.js.map} +1 -1
  142. package/dist/lib/{shadow-claw-chat-D69IiLXd.js → shadow-claw-chat-dbK_DGO_.js} +124 -38
  143. package/dist/lib/shadow-claw-chat-dbK_DGO_.js.map +1 -0
  144. package/dist/lib/{shadow-claw-control-plane-zBYlFvzQ.js → shadow-claw-control-plane-BJKkmahQ.js} +7 -7
  145. package/dist/lib/{shadow-claw-control-plane-zBYlFvzQ.js.map → shadow-claw-control-plane-BJKkmahQ.js.map} +1 -1
  146. package/dist/lib/{shadow-claw-conversations-1GW8_e8o.js → shadow-claw-conversations-BKSsMYTc.js} +6 -6
  147. package/dist/lib/{shadow-claw-conversations-1GW8_e8o.js.map → shadow-claw-conversations-BKSsMYTc.js.map} +1 -1
  148. package/dist/lib/{shadow-claw-D3z3tFyE.js → shadow-claw-eBB2dbpd.js} +11 -11
  149. package/dist/lib/{shadow-claw-D3z3tFyE.js.map → shadow-claw-eBB2dbpd.js.map} +1 -1
  150. package/dist/lib/{shadow-claw-file-viewer-DI4r7Th9.js → shadow-claw-file-viewer-BqChtTvM.js} +8 -8
  151. package/dist/lib/{shadow-claw-file-viewer-DI4r7Th9.js.map → shadow-claw-file-viewer-BqChtTvM.js.map} +1 -1
  152. package/dist/lib/{shadow-claw-files-BM7qW3TW.js → shadow-claw-files-Bu7VCQw6.js} +9 -9
  153. package/dist/lib/{shadow-claw-files-BM7qW3TW.js.map → shadow-claw-files-Bu7VCQw6.js.map} +1 -1
  154. package/dist/lib/{shadow-claw-git-BBTiTYIn.js → shadow-claw-git-CdPPN6Qb.js} +6 -6
  155. package/dist/lib/{shadow-claw-git-BBTiTYIn.js.map → shadow-claw-git-CdPPN6Qb.js.map} +1 -1
  156. package/dist/lib/{shadow-claw-integrations-DTY3E545.js → shadow-claw-integrations-DehqBSRe.js} +4 -4
  157. package/dist/lib/{shadow-claw-integrations-DTY3E545.js.map → shadow-claw-integrations-DehqBSRe.js.map} +1 -1
  158. package/dist/lib/{shadow-claw-llm-AJwzkOGo.js → shadow-claw-llm-COZkufA8.js} +13 -11
  159. package/dist/lib/shadow-claw-llm-COZkufA8.js.map +1 -0
  160. package/dist/lib/{shadow-claw-mcp-remote-n7YXKxmv.js → shadow-claw-mcp-remote-axF50-le.js} +4 -4
  161. package/dist/lib/{shadow-claw-mcp-remote-n7YXKxmv.js.map → shadow-claw-mcp-remote-axF50-le.js.map} +1 -1
  162. package/dist/lib/{shadow-claw-networking-B3leDgZ4.js → shadow-claw-networking-BT_Rxj36.js} +2 -2
  163. package/dist/lib/{shadow-claw-networking-B3leDgZ4.js.map → shadow-claw-networking-BT_Rxj36.js.map} +1 -1
  164. package/dist/lib/{shadow-claw-notifications-Bm2aHQ0U.js → shadow-claw-notifications-ClqAXDDN.js} +3 -3
  165. package/dist/lib/{shadow-claw-notifications-Bm2aHQ0U.js.map → shadow-claw-notifications-ClqAXDDN.js.map} +1 -1
  166. package/dist/lib/{shadow-claw-page-header-BBqSWlhP.js → shadow-claw-page-header-bigC_h6U.js} +2 -2
  167. package/dist/lib/{shadow-claw-page-header-BBqSWlhP.js.map → shadow-claw-page-header-bigC_h6U.js.map} +1 -1
  168. package/dist/lib/{shadow-claw-pages-BFOcluFY.js → shadow-claw-pages-kA2qa-4B.js} +9 -9
  169. package/dist/lib/{shadow-claw-pages-BFOcluFY.js.map → shadow-claw-pages-kA2qa-4B.js.map} +1 -1
  170. package/dist/lib/{shadow-claw-peerjs-BvD_MH_l.js → shadow-claw-peerjs-CvcH2DkA.js} +3 -3
  171. package/dist/lib/{shadow-claw-peerjs-BvD_MH_l.js.map → shadow-claw-peerjs-CvcH2DkA.js.map} +1 -1
  172. package/dist/lib/{shadow-claw-provider-model-picker-CsA-507a.js → shadow-claw-provider-model-picker-fcVQdDtQ.js} +2 -2
  173. package/dist/lib/{shadow-claw-provider-model-picker-CsA-507a.js.map → shadow-claw-provider-model-picker-fcVQdDtQ.js.map} +1 -1
  174. package/dist/lib/{shadow-claw-settings-CZgGMz0a.js → shadow-claw-settings-CkO6JjA4.js} +6 -6
  175. package/dist/lib/{shadow-claw-settings-CZgGMz0a.js.map → shadow-claw-settings-CkO6JjA4.js.map} +1 -1
  176. package/dist/lib/{shadow-claw-storage-BTUpEKO0.js → shadow-claw-storage-10w-y8vL.js} +5 -5
  177. package/dist/lib/{shadow-claw-storage-BTUpEKO0.js.map → shadow-claw-storage-10w-y8vL.js.map} +1 -1
  178. package/dist/lib/{shadow-claw-task-server-B1X2AYyZ.js → shadow-claw-task-server-U98sZxPu.js} +2 -2
  179. package/dist/lib/{shadow-claw-task-server-B1X2AYyZ.js.map → shadow-claw-task-server-U98sZxPu.js.map} +1 -1
  180. package/dist/lib/{shadow-claw-tasks-BYtaRUAd.js → shadow-claw-tasks-DrSVUOsP.js} +8 -8
  181. package/dist/lib/{shadow-claw-tasks-BYtaRUAd.js.map → shadow-claw-tasks-DrSVUOsP.js.map} +1 -1
  182. package/dist/lib/{shadow-claw-terminal-LGuXKu77.js → shadow-claw-terminal-B7HYLuce.js} +2 -2
  183. package/dist/lib/{shadow-claw-terminal-LGuXKu77.js.map → shadow-claw-terminal-B7HYLuce.js.map} +1 -1
  184. package/dist/lib/{shadow-claw-tools-C_S-xXVG.js → shadow-claw-tools-BKrXzZfF.js} +7 -7
  185. package/dist/lib/{shadow-claw-tools-C_S-xXVG.js.map → shadow-claw-tools-BKrXzZfF.js.map} +1 -1
  186. package/dist/lib/{shadow-claw-webvm-Cab1n1bu.js → shadow-claw-webvm-Duwa5oiW.js} +3 -3
  187. package/dist/lib/{shadow-claw-webvm-Cab1n1bu.js.map → shadow-claw-webvm-Duwa5oiW.js.map} +1 -1
  188. package/dist/lib/{syncWebMcpRegistration-Dy5NS_4G.js → syncWebMcpRegistration-BOx-0F6_.js} +5 -5
  189. package/dist/lib/{syncWebMcpRegistration-Dy5NS_4G.js.map → syncWebMcpRegistration-BOx-0F6_.js.map} +1 -1
  190. package/dist/lib/{tools-B7gC1eb_.js → tools-BEuBatUs.js} +4 -4
  191. package/dist/lib/{tools-B7gC1eb_.js.map → tools-BEuBatUs.js.map} +1 -1
  192. package/dist/lib/utils/index.js +1 -1
  193. package/dist/lib/utils/utils.js +1 -1
  194. package/dist/lib/{utils-D_ylqOY-.js → utils-D8AxCH6m.js} +2 -2
  195. package/dist/lib/{utils-D_ylqOY-.js.map → utils-D8AxCH6m.js.map} +1 -1
  196. package/dist/lib/{webmcp-CkYINKJj.js → webmcp-BjfVWX1K.js} +2 -2
  197. package/dist/lib/{webmcp-CkYINKJj.js.map → webmcp-BjfVWX1K.js.map} +1 -1
  198. package/dist/public/.well-known/mcp/server-card.json +1 -1
  199. package/dist/public/.well-known/mcp.json +1 -1
  200. package/dist/public/README.md +1 -1
  201. package/dist/public/agent.worker.js +1 -1
  202. package/dist/public/components/shadow-claw-chat/shadow-claw-chat.html +1 -1
  203. package/dist/public/config-071HSho8.js +1 -0
  204. package/dist/public/{configurePeerJs-DQQ6YL-5.js → configurePeerJs-DL-LurJY.js} +1 -1
  205. package/dist/public/{connections-CRNk2FxF.js → connections-Bb0rBpV-.js} +1 -1
  206. package/dist/public/{custom-element-security-3_FKCXcg.js → custom-element-security-Td4vrRc_.js} +1 -1
  207. package/dist/public/docs/example/article/index.html +1 -1
  208. package/dist/public/docs/example/article.html +1 -1
  209. package/dist/public/docs/publishing/index.html +1 -1
  210. package/dist/public/docs/publishing.html +1 -1
  211. package/dist/public/docs/skill-creator/index.html +1 -1
  212. package/dist/public/docs/skill-creator.html +1 -1
  213. package/dist/public/docs/subsystems/providers.md +1 -1
  214. package/dist/public/{downloadGroupFile-wkdhVgrZ.js → downloadGroupFile-Unq8_7D9.js} +1 -1
  215. package/dist/public/{e2e-bridge-DnFHPuwg.js → e2e-bridge-Dbc9fCDq.js} +1 -1
  216. package/dist/public/{file-viewer-C92v4Ggd.js → file-viewer-QkCuknFn.js} +1 -1
  217. package/dist/public/{getGroupDir-BGGIJL4Y.js → getGroupDir-Bj5XCflQ.js} +1 -1
  218. package/dist/public/{git-BH6qyToB.js → git-Bhz4YHc8.js} +2 -2
  219. package/dist/public/index.html +1 -1
  220. package/dist/public/index.js +1 -1
  221. package/dist/public/{initChatSplitResize--RH5kzVF.js → initChatSplitResize-KNL9Oh7s.js} +1 -1
  222. package/dist/public/{initControlPlane-yPJ3ajkj.js → initControlPlane-D2fVhRFC.js} +1 -1
  223. package/dist/public/main/index.html +1 -1
  224. package/dist/public/main/memory/index.html +1 -1
  225. package/dist/public/main/memory.html +1 -1
  226. package/dist/public/main.html +1 -1
  227. package/dist/public/{markdown-CA0v11cd.js → markdown-By6gdUvF.js} +1 -1
  228. package/dist/public/{mcp-reconnect-uyNSigzu.js → mcp-reconnect-CDRJPuoN.js} +1 -1
  229. package/dist/public/{memoryStorage-DjPNAT5t.js → memoryStorage-C-ao9y-j.js} +1 -1
  230. package/dist/public/model-ranking-DUdrFOcC.js +1 -0
  231. package/dist/public/{orchestrator-DTzgyL23.js → orchestrator-B7MpomoG.js} +2 -2
  232. package/dist/public/{orchestrator-Cmr69pMC.js → orchestrator-C8aIHbDy.js} +2 -2
  233. package/dist/public/{peerjs-Br38mUFC.js → peerjs-DwGjY5VX.js} +1 -1
  234. package/dist/public/prompt-api-BWe_j3Wg.js +1 -0
  235. package/dist/public/{push-client-CB8haOGC.js → push-client-o8g5_EOe.js} +1 -1
  236. package/dist/public/service-worker.js +1 -1
  237. package/dist/public/{shadow-claw-RuFQ2Ej5.js → shadow-claw-Ba2ZFE9m.js} +2 -2
  238. package/dist/public/{shadow-claw-accounts-BMsEItB6.js → shadow-claw-accounts-BbNPiiaV.js} +1 -1
  239. package/dist/public/{shadow-claw-channels-Q_AXuEaI.js → shadow-claw-channels-CHGtPkfY.js} +1 -1
  240. package/dist/public/{shadow-claw-chat-DZQ3OaH7.js → shadow-claw-chat-3TmjJA6-.js} +90 -23
  241. package/dist/public/{shadow-claw-control-plane-CyXA8tB8.js → shadow-claw-control-plane-BAFT06LL.js} +2 -2
  242. package/dist/public/{shadow-claw-conversations-BLKtlvHe.js → shadow-claw-conversations-DsQ_kxWm.js} +1 -1
  243. package/dist/public/{shadow-claw-file-viewer-CVLDfpZe.js → shadow-claw-file-viewer-hBxTknL2.js} +1 -1
  244. package/dist/public/{shadow-claw-files-DB6VVjir.js → shadow-claw-files-Daw6IIrJ.js} +1 -1
  245. package/dist/public/{shadow-claw-git-D57bTSMF.js → shadow-claw-git-CxGwyxim.js} +2 -2
  246. package/dist/public/{shadow-claw-integrations-BOwhUY-4.js → shadow-claw-integrations-DnIr6xp-.js} +1 -1
  247. package/dist/public/{shadow-claw-llm-CYenm-mm.js → shadow-claw-llm-Bc6tZ8kk.js} +3 -3
  248. package/dist/public/{shadow-claw-mcp-remote-CJ-Ckl0j.js → shadow-claw-mcp-remote-nGPpFpI-.js} +1 -1
  249. package/dist/public/{shadow-claw-networking-Cut76YQL.js → shadow-claw-networking-B6YgtiA7.js} +1 -1
  250. package/dist/public/{shadow-claw-notifications-C3kYCrIa.js → shadow-claw-notifications-BSxifptS.js} +1 -1
  251. package/dist/public/{shadow-claw-page-header-Dd7QafUk.js → shadow-claw-page-header-LzVgEn46.js} +1 -1
  252. package/dist/public/{shadow-claw-pages-BWtVtwTG.js → shadow-claw-pages-Cy6T0G9y.js} +1 -1
  253. package/dist/public/{shadow-claw-settings-Bj7jnngO.js → shadow-claw-settings-DGkwt1ge.js} +2 -2
  254. package/dist/public/{shadow-claw-storage-CMSzQs1-.js → shadow-claw-storage-DX_4T7KR.js} +1 -1
  255. package/dist/public/{shadow-claw-task-server-CFclo7UX.js → shadow-claw-task-server-DTsbEs5z.js} +1 -1
  256. package/dist/public/{shadow-claw-tasks-ClDdeB6Z.js → shadow-claw-tasks-rr6fMxAM.js} +1 -1
  257. package/dist/public/{shadow-claw-terminal-3ysWZJix.js → shadow-claw-terminal-C7DhrrX6.js} +1 -1
  258. package/dist/public/{shadow-claw-tools-DQVwpTcZ.js → shadow-claw-tools-DcQroojH.js} +1 -1
  259. package/dist/public/{shadow-claw-webvm-Cnxz04Fk.js → shadow-claw-webvm-bZj44Did.js} +1 -1
  260. package/dist/public/{syncWebMcpRegistration-QwnLMAK3.js → syncWebMcpRegistration-XJjIlDNO.js} +1 -1
  261. package/dist/public/{tools-DvQ_ngXn.js → tools-BpZh7hgB.js} +1 -1
  262. package/dist/public/{webmcp-CJymew4t.js → webmcp-CkfDZfZ0.js} +1 -1
  263. package/dist/server.js +1 -1
  264. package/package.json +1 -1
  265. package/src/components/settings/shadow-claw-llm/model-ranking.test.ts +121 -7
  266. package/src/components/settings/shadow-claw-llm/model-ranking.ts +97 -0
  267. package/src/components/settings/shadow-claw-llm/shadow-claw-llm.test.ts +35 -0
  268. package/src/components/settings/shadow-claw-llm/shadow-claw-llm.ts +15 -5
  269. package/src/components/shadow-claw-chat/shadow-claw-chat.html +81 -14
  270. package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +73 -0
  271. package/src/components/shadow-claw-chat/shadow-claw-chat.trusted-types.test.ts +3 -0
  272. package/src/components/shadow-claw-chat/shadow-claw-chat.ts +79 -32
  273. package/src/config/config.test.ts +4 -4
  274. package/src/config/config.ts +2 -1
  275. package/src/core/orchestrator/orchestrator.test.ts +2 -1
  276. package/src/core/orchestrator/utils/initTasks.ts +5 -4
  277. package/dist/cli/chunk-B3S061IE.js +0 -1
  278. package/dist/cli/chunk-BUJdF9o3.js +0 -1
  279. package/dist/cli/chunk-BX0R2gIY.js +0 -1
  280. package/dist/cli/chunk-BoiPfhwJ.js +0 -1
  281. package/dist/cli/chunk-BtJYj7vB.js +0 -1
  282. package/dist/cli/chunk-BwXrZVeU.js +0 -1
  283. package/dist/cli/chunk-CaWh9Pru.js +0 -1
  284. package/dist/cli/chunk-Ck4ePI8z.js +0 -1
  285. package/dist/cli/chunk-Ctg-SXcP.js +0 -1
  286. package/dist/cli/chunk-DTKv1-tk.js +0 -1
  287. package/dist/cli/chunk-DdYpd9Nu.js +0 -1
  288. package/dist/cli/chunk-DflhmBY2.js +0 -1
  289. package/dist/lib/config-DxDaVDTn.js.map +0 -1
  290. package/dist/lib/model-ranking-CDXs7hkK.js +0 -57
  291. package/dist/lib/model-ranking-CDXs7hkK.js.map +0 -1
  292. package/dist/lib/shadow-claw-chat-D69IiLXd.js.map +0 -1
  293. package/dist/lib/shadow-claw-llm-AJwzkOGo.js.map +0 -1
  294. package/dist/public/config-Dqn5OMfC.js +0 -1
  295. package/dist/public/model-ranking-DLIC9IDU.js +0 -1
  296. package/dist/public/prompt-api-B-8N-MRY.js +0 -11
@@ -1 +1 @@
1
- {"version":3,"file":"shadow-claw-integrations-DTY3E545.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 | HTMLSelectElement | 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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"}
1
+ {"version":3,"file":"shadow-claw-integrations-DehqBSRe.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 | HTMLSelectElement | 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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"}
@@ -1,14 +1,14 @@
1
1
  import ShadowClawElement from "./components/shadow-claw-element.js";
2
2
  import { r as getDb } from "./txPromise-DdeRXi7G.js";
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-DxDaVDTn.js";
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-DFLs7eoC.js";
4
4
  import { t as getConfig } from "./getConfig-SElp6VJW.js";
5
- import { Ct as isPromptApiSupported, G as getLlamafileSettings, Q as setModel, U as getAvailableProviders, V as getApiKeyForHeaders, W as getBedrockSettings, X as setLlamafileSettings, Y as setBedrockSettings, Z as setMeshLlmSettings, at as LLAMAFILE_EXPECTED_DIR, c as setContextCompressionEnabled, f as setRateLimitAutoAdapt, h as setStreamingEnabled, l as setMaxIterations, m as setReasoningEffort, ot as buildLlamafileHelpDialogOptions, p as setRateLimitCallsPerMinute, t as orchestratorStore, tt as setProvider, u as setMaxTokens, wt as fetchTokenizerConfig } from "./orchestrator-Crw4btGn.js";
5
+ import { Ct as isPromptApiSupported, G as getLlamafileSettings, Q as setModel, U as getAvailableProviders, V as getApiKeyForHeaders, W as getBedrockSettings, X as setLlamafileSettings, Y as setBedrockSettings, Z as setMeshLlmSettings, at as LLAMAFILE_EXPECTED_DIR, c as setContextCompressionEnabled, f as setRateLimitAutoAdapt, h as setStreamingEnabled, l as setMaxIterations, m as setReasoningEffort, ot as buildLlamafileHelpDialogOptions, p as setRateLimitCallsPerMinute, t as orchestratorStore, tt as setProvider, u as setMaxTokens, wt as fetchTokenizerConfig } from "./orchestrator-BK138MkV.js";
6
6
  import { t as setConfig } from "./setConfig-8FMUTIJ1.js";
7
- import { S as setSanitizedHtml } from "./utils-D_ylqOY-.js";
7
+ import { S as setSanitizedHtml } from "./utils-D8AxCH6m.js";
8
8
  import { a as showSuccess, r as showError, s as showWarning } from "./toast-Ck7OIKDf.js";
9
- import { n as isNativePromptApiAvailable, r as isNativePromptApiSupported } from "./prompt-api-D9XdrCep.js";
9
+ import { n as isNativePromptApiAvailable, r as isNativePromptApiSupported } from "./prompt-api-vf351sf2.js";
10
10
  import { t as effect } from "./effect-DL6j9HJp.js";
11
- import { n as isLikelyInstructionModelId, t as compareLocalModelCandidates } from "./model-ranking-CDXs7hkK.js";
11
+ import { i as renderTransformersJsBrowserModelOptions, n as getSortedTransformersJsBrowserModelIds, r as isLikelyInstructionModelId, t as compareLocalModelCandidates } from "./model-ranking-Bo8CpGH1.js";
12
12
 
13
13
  //#region src/components/settings/shadow-claw-llm/utils/getRecommendedMaxTokens.ts
14
14
  /**
@@ -1182,13 +1182,15 @@ var ShadowClawLlm = class extends ShadowClawElement {
1182
1182
  return `<option value="${escapeHtml(id)}">${escapeHtml(label)}${ctxStr}${toolsBadge}</option>`;
1183
1183
  };
1184
1184
  let html = "";
1185
- if (localOnlyProviderIds.has(currentProvider)) {
1185
+ if (currentProvider === "transformers_js_browser") html = renderTransformersJsBrowserModelOptions(currentModel, modelItems, { includeCustom: true });
1186
+ else if (localOnlyProviderIds.has(currentProvider)) {
1186
1187
  const localModels = [...freeModels, ...paidModels].sort(modelComparator);
1187
1188
  if (localModels.length > 0) {
1188
1189
  html += `<optgroup label="${currentProvider === "prompt_api" ? "Built-in" : "Local / Self-hosted"}">`;
1189
1190
  html += localModels.map(toOption).join("");
1190
1191
  html += `</optgroup>`;
1191
1192
  }
1193
+ html += `<option value="__custom__">-- Custom Model ID --</option>`;
1192
1194
  } else {
1193
1195
  if (freeModels.length > 0) {
1194
1196
  html += `<optgroup label="Free / Included">`;
@@ -1200,10 +1202,10 @@ var ShadowClawLlm = class extends ShadowClawElement {
1200
1202
  html += paidModels.map(toOption).join("");
1201
1203
  html += `</optgroup>`;
1202
1204
  }
1205
+ html += `<option value="__custom__">-- Custom Model ID --</option>`;
1203
1206
  }
1204
- html += `<option value="__custom__">-- Custom Model ID --</option>`;
1205
1207
  setSanitizedHtml(modelSelect, html);
1206
- if (modelItems.map((m) => typeof m === "string" ? m : m.id || m.name).includes(currentModel)) {
1208
+ if ((currentProvider === "transformers_js_browser" ? getSortedTransformersJsBrowserModelIds(modelItems) : modelItems.map((m) => typeof m === "string" ? m : m.id || m.name)).includes(currentModel)) {
1207
1209
  modelSelect.value = currentModel;
1208
1210
  customModelInput.style.display = "none";
1209
1211
  } else {
@@ -1458,7 +1460,7 @@ var ShadowClawLlm = class extends ShadowClawElement {
1458
1460
  const root = this.shadowRoot;
1459
1461
  if (!root) return;
1460
1462
  const { getConfig } = await import("./getConfig-SElp6VJW.js").then((n) => n.n);
1461
- const { CONFIG_KEYS } = await import("./config-DxDaVDTn.js").then((n) => n.k);
1463
+ const { CONFIG_KEYS } = await import("./config-DFLs7eoC.js").then((n) => n.k);
1462
1464
  const backend = await getConfig(this.db, CONFIG_KEYS.TRANSFORMERS_JS_BACKEND) || "auto";
1463
1465
  const dtypeStrategy = await getConfig(this.db, CONFIG_KEYS.TRANSFORMERS_JS_DTYPE_STRATEGY) || "auto";
1464
1466
  const backendSelect = root.querySelector("[data-setting=\"transformers-js-backend\"], [data-setting=\"transformers-js-device-select\"]");
@@ -1793,7 +1795,7 @@ var ShadowClawLlm = class extends ShadowClawElement {
1793
1795
  const backend = root.querySelector("[data-setting=\"transformers-js-backend\"], [data-setting=\"transformers-js-device-select\"]")?.value || "auto";
1794
1796
  const dtypeStrategy = root.querySelector("[data-setting=\"transformers-js-dtype-strategy\"], [data-setting=\"transformers-js-dtype-select\"]")?.value || "auto";
1795
1797
  const { setConfig } = await import("./setConfig-8FMUTIJ1.js").then((n) => n.n);
1796
- const { CONFIG_KEYS } = await import("./config-DxDaVDTn.js").then((n) => n.k);
1798
+ const { CONFIG_KEYS } = await import("./config-DFLs7eoC.js").then((n) => n.k);
1797
1799
  await setConfig(this.db, CONFIG_KEYS.TRANSFORMERS_JS_BACKEND, backend);
1798
1800
  await setConfig(this.db, CONFIG_KEYS.TRANSFORMERS_JS_DTYPE_STRATEGY, dtypeStrategy);
1799
1801
  showSuccess("Transformers.js settings saved.");
@@ -1809,4 +1811,4 @@ if (!customElements.get(elementName)) customElements.define(elementName, ShadowC
1809
1811
 
1810
1812
  //#endregion
1811
1813
  export { ShadowClawLlm as t };
1812
- //# sourceMappingURL=shadow-claw-llm-AJwzkOGo.js.map
1814
+ //# sourceMappingURL=shadow-claw-llm-COZkufA8.js.map