@openhands/agent-canvas 1.5.1 → 1.6.1

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 (720) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DqF_OEZB.js → Trans-52HCczKK.js} +1 -1
  4. package/build/assets/{acp-providers-DerAmTyY.js → acp-providers-xACMK9ZP.js} +1 -1
  5. package/build/assets/{active-backend-context-B8rMv0X9.js → active-backend-context-Cd1qcZsb.js} +1 -1
  6. package/build/assets/{add-backend-modal-CxC7BNEc.js → add-backend-modal-5chsfln3.js} +1 -1
  7. package/build/assets/{agent-profiles-settings-BJb8YXR1.js → agent-profiles-settings-BWK4H3kR.js} +1 -1
  8. package/build/assets/agent-server-compatibility-DMY0CihN.js +1 -0
  9. package/build/assets/agent-server-conversation-service.api-CI5-xmIX.js +41 -0
  10. package/build/assets/agent-settings-CMd8-O4f.js +2 -0
  11. package/build/assets/agent-settings-CdrhQJXX.js +1 -0
  12. package/build/assets/{alert-banner-Dh51WURQ.js → alert-banner-CLfWuIAX.js} +1 -1
  13. package/build/assets/api-key-entry-screen-Cc3aC7DZ.js +1 -0
  14. package/build/assets/app-settings-B-DQcBoB.js +1 -0
  15. package/build/assets/{automation-detail-CZsu2CoM.js → automation-detail-BgxBIpyK.js} +2 -2
  16. package/build/assets/automation-export-Dbur8OHa.js +2 -0
  17. package/build/assets/automations-list-BWfjizlp.js +1 -0
  18. package/build/assets/{back-nav-button-DVknCcSP.js → back-nav-button-CaKvsD1E.js} +1 -1
  19. package/build/assets/backend-form-modal-YcfpuBZo.js +1 -0
  20. package/build/assets/{backend-synced-settings-badge-BSfN0AZA.js → backend-synced-settings-badge-BellMmgC.js} +1 -1
  21. package/build/assets/{base-modal-CIF_785P.js → base-modal-Cw7enAHz.js} +1 -1
  22. package/build/assets/{brand-button-B1izLAdR.js → brand-button-BulEFHr3.js} +1 -1
  23. package/build/assets/{browser-DKaeq_sT.js → browser-DfVgUREb.js} +2 -2
  24. package/build/assets/browser-store-CBqI3tNR.js +1 -0
  25. package/build/assets/{browser-tab-qb_ftCxW.js → browser-tab-CmIKQB7S.js} +1 -1
  26. package/build/assets/chat-send-button-BchSSwuD.js +1 -0
  27. package/build/assets/circle-check-BXbQ5nEH.js +1 -0
  28. package/build/assets/{circle-plus-check-toggle-DoFIjVE0.js → circle-plus-check-toggle-BhpPjkh9.js} +1 -1
  29. package/build/assets/client-source-DAUgyJsi.js +1 -0
  30. package/build/assets/cloud-funnel-analytics-B5OeWh4y.js +1 -0
  31. package/build/assets/{color-themes-CHizm1xF.js → color-themes-QKMSVfDU.js} +1 -1
  32. package/build/assets/{combobox-caret-CxZpqoSR.js → combobox-caret-kNZtp53R.js} +1 -1
  33. package/build/assets/{command-menu-oTvKDU3Y.js → command-menu-tUsn23zy.js} +1 -1
  34. package/build/assets/{command-store-D8J5LMW1.js → command-store-B0hrIWMN.js} +1 -1
  35. package/build/assets/{condenser-settings-BGlWn93P.js → condenser-settings-BBizzfIH.js} +1 -1
  36. package/build/assets/{confirmation-modal-DGBWM2Ls.js → confirmation-modal-108xng7X.js} +1 -1
  37. package/build/assets/{context-menu-list-item-6psNyl7X.js → context-menu-list-item-BbKfFuN1.js} +1 -1
  38. package/build/assets/conversation-CTzSrLMq.js +1 -0
  39. package/build/assets/conversation-CgcXNb-Z.js +90 -0
  40. package/build/assets/conversation-panel-bscjGQda.js +1 -0
  41. package/build/assets/{conversation-service.api-_f9GlIEi.js → conversation-service.api-DbBvscJA.js} +1 -1
  42. package/build/assets/conversation-state-store-C5GagZHT.js +1 -0
  43. package/build/assets/{conversation-store-LptbOvKa.js → conversation-store-CyVqoa0d.js} +1 -1
  44. package/build/assets/{conversation-tab-empty-state-CNUmIms2.js → conversation-tab-empty-state-2KYlk5Bh.js} +1 -1
  45. package/build/assets/{copy-to-clipboard-button-CFzH_NOX.js → copy-to-clipboard-button-C54YRPMg.js} +1 -1
  46. package/build/assets/declaration-_yumYLEx.js +1 -0
  47. package/build/assets/{device-verify-WBSjJBLH.js → device-verify-D6FW_KZq.js} +1 -1
  48. package/build/assets/{dropdown-classes-D3wMJlXT.js → dropdown-classes-9uONlOg1.js} +1 -1
  49. package/build/assets/{ellipsis-button-CbNnHlIq.js → ellipsis-button-CoaUrKmQ.js} +1 -1
  50. package/build/assets/{entry.client-DNlPGxsu.js → entry.client-BJSVzw7V.js} +2 -2
  51. package/build/assets/{enum-filter-dropdown-JLYv1t8L.js → enum-filter-dropdown-qQzyjk_q.js} +1 -1
  52. package/build/assets/{environment-switch-overlay-B1PFO8P8.js → environment-switch-overlay-XRWCClLu.js} +1 -1
  53. package/build/assets/extensions-hub-DUp9sWQY.js +1 -0
  54. package/build/assets/extensions-navigation-DmkftjAx.js +1 -0
  55. package/build/assets/file-tUAzhmJ3.js +1 -0
  56. package/build/assets/files-tab-GV5hwiIM.js +1 -0
  57. package/build/assets/files-tab-store-DehyITNC.js +1 -0
  58. package/build/assets/{form-control-classes-CbdN5aO3.js → form-control-classes-BPUnoYyg.js} +1 -1
  59. package/build/assets/git-provider-icon-DDkru3b_.js +1 -0
  60. package/build/assets/highlighted-source-view-CYkPZUxr.js +1 -0
  61. package/build/assets/home-C53WekZ2.js +1 -0
  62. package/build/assets/home-EAwq8ah2.js +1 -0
  63. package/build/assets/index-home-kBdZGKtu.js +1 -0
  64. package/build/assets/install-server-modal-DYk4VP3-.js +1 -0
  65. package/build/assets/{launch-CAGavYl-.js → launch-CIecOy_y.js} +1 -1
  66. package/build/assets/lesson-plan-BSEUwflx.js +4 -0
  67. package/build/assets/llm-not-configured-banner-C8uv1PHT.js +27 -0
  68. package/build/assets/llm-settings-0Bb97NCk.js +1 -0
  69. package/build/assets/llm-settings-D4toJ90k.js +1 -0
  70. package/build/assets/{llm-subscription-service-Casyzgn1.js → llm-subscription-service-BPRw3u3H.js} +1 -1
  71. package/build/assets/{loading-spinner-BcdnT0mN.js → loading-spinner-BCInDEXB.js} +1 -1
  72. package/build/assets/manage-backends-modal-Bon32JYr.js +1 -0
  73. package/build/assets/manifest-ec000ae3.js +1 -0
  74. package/build/assets/markdown-renderer-BlaJOAI2.js +2 -0
  75. package/build/assets/mcp-CFIpOkn2.js +9 -0
  76. package/build/assets/messages-eRPeR4pW.js +40 -0
  77. package/build/assets/{modal-body-Cc2zp0xb.js → modal-body-Bg9UCeoV.js} +1 -1
  78. package/build/assets/{modal-classes-3qT9Ap7Q.js → modal-classes-H1KbJkeC.js} +1 -1
  79. package/build/assets/{modal-close-button-BcIBUdSq.js → modal-close-button-BMLYvo0C.js} +1 -1
  80. package/build/assets/{model-selector-DJrMrFAr.js → model-selector-BqX2RvEr.js} +1 -1
  81. package/build/assets/{navigation-link-D8hfwvxI.js → navigation-link-DoJzTCEz.js} +1 -1
  82. package/build/assets/onboarding-3KO4qE6R.js +1 -0
  83. package/build/assets/onboarding-modal-D4vqkJeT.js +1 -0
  84. package/build/assets/{organization-service.api-vrRNwOma.js → organization-service.api-CvfQugOt.js} +1 -1
  85. package/build/assets/{path-utils-PNfCKQDV.js → path-utils-DRgexxnX.js} +1 -1
  86. package/build/assets/{plan-components-BdZXPyZU.js → plan-components-qkMiGs_-.js} +1 -1
  87. package/build/assets/{planner-tab-ByOw1he8.js → planner-tab-ZrjiirRr.js} +1 -1
  88. package/build/assets/{plugins-management-service-B75jyC56.js → plugins-management-service-9qT-r_37.js} +1 -1
  89. package/build/assets/plus-CzE1b-wl.js +1 -0
  90. package/build/assets/{profiles-service.api-BQTklD5D.js → profiles-service.api-CRVlrQpT.js} +1 -1
  91. package/build/assets/{providers-DfTB2gPd.js → providers-C2DFGBrf.js} +1 -1
  92. package/build/assets/{proxy-B3tCGf0X.js → proxy-DnnDqkwn.js} +1 -1
  93. package/build/assets/puzzle-IHQnD54C.js +1 -0
  94. package/build/assets/recommended-automations-launcher-B97vgHuN.js +58 -0
  95. package/build/assets/refresh-cw-DxbAs3SK.js +1 -0
  96. package/build/assets/root-BbONavTg.css +1 -0
  97. package/build/assets/root-D01rpqZU.js +2 -0
  98. package/build/assets/root-layout-BiHbCIkS.js +2 -0
  99. package/build/assets/{runtime-waiting-state-CnyVhX4T.js → runtime-waiting-state-CbUV9txX.js} +1 -1
  100. package/build/assets/{schema-field-CUwk4wrQ.js → schema-field-B9-9Ta9u.js} +1 -1
  101. package/build/assets/sdk-section-page-DG1s25Pr.js +1 -0
  102. package/build/assets/{sdk-settings-schema-CLR01YIK.js → sdk-settings-schema-B42JFr5Y.js} +1 -1
  103. package/build/assets/{secrets-service-CvyPWJhg.js → secrets-service-DvyS6-mV.js} +1 -1
  104. package/build/assets/secrets-settings-CeSq6cQw.js +1 -0
  105. package/build/assets/{segmented-toggle-kzwZkLaj.js → segmented-toggle-DRVJBNy0.js} +1 -1
  106. package/build/assets/settings-Dzo0dJKM.js +1 -0
  107. package/build/assets/{settings-mQUckT0g.js → settings-HcwfqMjJ.js} +1 -1
  108. package/build/assets/{settings-dropdown-input-Dhx9ErGd.js → settings-dropdown-input-B6RL_mt0.js} +1 -1
  109. package/build/assets/settings-index-uAKHyijw.js +1 -0
  110. package/build/assets/{settings-input-BsgQWS5R.js → settings-input-ZoaAPNQh.js} +1 -1
  111. package/build/assets/{settings-list-classes-DSJJX99U.js → settings-list-classes-Dr8LgITi.js} +1 -1
  112. package/build/assets/settings-modal-BVX2G_IT.js +1 -0
  113. package/build/assets/{settings-service.api-DXk5TdeJ.js → settings-service.api-BY7ncxIz.js} +1 -1
  114. package/build/assets/{settings-switch-Bes8dIlV.js → settings-switch-DUlGnP0B.js} +1 -1
  115. package/build/assets/{settings-utils-DzCVfiR3.js → settings-utils-kWEEvcdv.js} +1 -1
  116. package/build/assets/shared-conversation-CV4Rtdz2.js +1 -0
  117. package/build/assets/{sidebar-layout-Bm7pa3Vk.js → sidebar-layout-BhGooCga.js} +1 -1
  118. package/build/assets/sidebar-mobile-menu-toggle-BntOJphE.js +1 -0
  119. package/build/assets/{sidebar-nav-link-CHqyFXwV.js → sidebar-nav-link-DkA1XWV8.js} +1 -1
  120. package/build/assets/{sidebar-store-uiUXBU1N.js → sidebar-store-CF3b12-m.js} +1 -1
  121. package/build/assets/{skill-card-pill-row-BPYKQ3IN.js → skill-card-pill-row-_gWe1Tws.js} +1 -1
  122. package/build/assets/skill-icon-badge-C-zbaXbD.js +1 -0
  123. package/build/assets/skills-plugins-BwoXKtrR.js +1 -0
  124. package/build/assets/skills-settings-Crq-fZSt.js +2 -0
  125. package/build/assets/{styled-tooltip-B14i_Uac.js → styled-tooltip-CdnCJ67u.js} +1 -1
  126. package/build/assets/syntax-highlighter-CZK2ab-O.js +1 -0
  127. package/build/assets/{task-list-tab-DyfgG4MC.js → task-list-tab-CONOO9iI.js} +1 -1
  128. package/build/assets/telemetry-CC32dJYW.js +2 -0
  129. package/build/assets/{terminal-DRXt2Lr4.js → terminal-CTkDpIU-.js} +1 -1
  130. package/build/assets/{toggle-switch-DX_k418f.js → toggle-switch-yVIzmJLM.js} +1 -1
  131. package/build/assets/{typography-CzfoD9DY.js → typography-BBVEW0un.js} +1 -1
  132. package/build/assets/{use-acp-credential-form-Bm8qXdlc.js → use-acp-credential-form-CIsp8hJe.js} +1 -1
  133. package/build/assets/use-activate-agent-profile-BfcTTJJG.js +1 -0
  134. package/build/assets/{use-active-agent-profile-hI-x-UBa.js → use-active-agent-profile-CCeFtmk9.js} +1 -1
  135. package/build/assets/{use-active-conversation-2qeez40F.js → use-active-conversation-Badxj8w4.js} +1 -1
  136. package/build/assets/{use-agent-profiles-0pr5bLS7.js → use-agent-profiles-BSWVN6hH.js} +1 -1
  137. package/build/assets/{use-agent-state-C6peDXUm.js → use-agent-state-BzRrhoPd.js} +1 -1
  138. package/build/assets/use-backends-health-BsZikyFW.js +1 -0
  139. package/build/assets/{use-can-manage-org-profiles-Ck_bsNbH.js → use-can-manage-org-profiles-Do6mYf6P.js} +1 -1
  140. package/build/assets/{use-cloud-current-user-id-DUCSxNjY.js → use-cloud-current-user-id-Cx3B_0-w.js} +1 -1
  141. package/build/assets/use-config-D9zUVw5b.js +1 -0
  142. package/build/assets/{use-create-conversation-r1JHfKO5.js → use-create-conversation-vvl0kvu7.js} +1 -1
  143. package/build/assets/{use-create-secret-Cf2N11d2.js → use-create-secret-CB7Dvd4s.js} +1 -1
  144. package/build/assets/use-event-store-BlpSUF7N.js +4 -0
  145. package/build/assets/{use-handle-plan-click-CsAW3FlH.js → use-handle-plan-click-DDZkew9p.js} +1 -1
  146. package/build/assets/use-is-creating-conversation-fxSzN778.js +1 -0
  147. package/build/assets/{use-launch-skill-in-chat-DJWEfVc5.js → use-launch-skill-in-chat-D6_n1fs3.js} +1 -1
  148. package/build/assets/use-llm-profiles-CNQm7HYS.js +1 -0
  149. package/build/assets/use-plugins-marketplace-CloojomS.js +1 -0
  150. package/build/assets/use-runtime-is-ready-Bx_4cfar.js +1 -0
  151. package/build/assets/{use-save-agent-profile-RqUGqTv6.js → use-save-agent-profile-Bj7N-1jS.js} +1 -1
  152. package/build/assets/{use-save-settings-Chvzeu2s.js → use-save-settings-BMsb2wk_.js} +1 -1
  153. package/build/assets/use-settings-B9XEmh7i.js +1 -0
  154. package/build/assets/use-settings-nav-items-BGfBS0yL.js +16 -0
  155. package/build/assets/{use-skills-xrVoKYrF.js → use-skills-CSRbvPle.js} +1 -1
  156. package/build/assets/{use-task-list-CfisapBW.js → use-task-list-CTIVLrQA.js} +1 -1
  157. package/build/assets/use-tracking-DjdCssvp.js +1 -0
  158. package/build/assets/{use-user-conversation-CnE4zhOA.js → use-user-conversation-BCpFn-Ei.js} +1 -1
  159. package/build/assets/{useTranslation-Cbf5AGg_.js → useTranslation-CHm_6BRr.js} +1 -1
  160. package/build/assets/{utils-DB9LsAzA.js → utils-CrRpzbM2.js} +1 -1
  161. package/build/assets/vendor-markdown-DzO4uO_0.js +37 -0
  162. package/build/assets/{vendor~browser-wXQ-WZEC.js → vendor~browser-Byfuq5J-.js} +1 -1
  163. package/build/assets/{vendor~browser-tab-CsMb-pta.js → vendor~browser-tab-BLk3qxhw.js} +1 -1
  164. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-eGLBu60s.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-DTJ_cjR5.js} +2 -2
  165. package/build/assets/{vendor~files-tab-B-5fBohe.js → vendor~files-tab-XmnauIZI.js} +1 -1
  166. package/build/assets/{vendor~launch-_Km3J77E.js → vendor~launch-DeC8QhXQ.js} +1 -1
  167. package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-BrguKXCn.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-DDmLzCzm.js} +1 -1
  168. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-YrfJYTQw.js +1 -0
  169. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-mC0v44WR.js → vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-DoaS51iW.js} +123 -3
  170. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-BOKQkbc6.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-DEYwoy8u.js} +1 -1
  171. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-DZHLw5Sr.js +1 -0
  172. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-cFNmfAE6.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-UJ4BNDJP.js} +1 -1
  173. package/build/assets/{verification-settings-CfkrXoSa.js → verification-settings-uwOfc16F.js} +1 -1
  174. package/build/index.html +4 -4
  175. package/build/locales/ar/openhands.json +38 -4
  176. package/build/locales/ca/openhands.json +38 -4
  177. package/build/locales/de/openhands.json +38 -4
  178. package/build/locales/en/openhands.json +38 -4
  179. package/build/locales/es/openhands.json +38 -4
  180. package/build/locales/fr/openhands.json +38 -4
  181. package/build/locales/it/openhands.json +38 -4
  182. package/build/locales/ja/openhands.json +38 -4
  183. package/build/locales/ko-KR/openhands.json +38 -4
  184. package/build/locales/no/openhands.json +38 -4
  185. package/build/locales/pt/openhands.json +38 -4
  186. package/build/locales/tr/openhands.json +38 -4
  187. package/build/locales/uk/openhands.json +38 -4
  188. package/build/locales/zh-CN/openhands.json +38 -4
  189. package/build/locales/zh-TW/openhands.json +38 -4
  190. package/config/defaults.json +7 -3
  191. package/dist/api/agent-canvas-updates.cjs +2 -0
  192. package/dist/api/agent-canvas-updates.cjs.map +1 -0
  193. package/dist/api/agent-canvas-updates.d.ts +7 -0
  194. package/dist/api/agent-canvas-updates.js +19 -0
  195. package/dist/api/agent-canvas-updates.js.map +1 -0
  196. package/dist/api/agent-server-adapter.cjs +1 -1
  197. package/dist/api/agent-server-adapter.cjs.map +1 -1
  198. package/dist/api/agent-server-adapter.d.ts +3 -0
  199. package/dist/api/agent-server-adapter.js +1 -0
  200. package/dist/api/agent-server-adapter.js.map +1 -1
  201. package/dist/api/agent-server-compatibility.cjs +1 -1
  202. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  203. package/dist/api/agent-server-compatibility.d.ts +5 -0
  204. package/dist/api/agent-server-compatibility.js +24 -15
  205. package/dist/api/agent-server-compatibility.js.map +1 -1
  206. package/dist/api/agent-server-config.cjs +1 -1
  207. package/dist/api/agent-server-config.cjs.map +1 -1
  208. package/dist/api/agent-server-config.js +11 -8
  209. package/dist/api/agent-server-config.js.map +1 -1
  210. package/dist/api/automation-service/automation-service.api.cjs +2 -0
  211. package/dist/api/automation-service/automation-service.api.cjs.map +1 -0
  212. package/dist/api/automation-service/automation-service.api.d.ts +3 -0
  213. package/dist/api/automation-service/automation-service.api.js +283 -0
  214. package/dist/api/automation-service/automation-service.api.js.map +1 -0
  215. package/dist/api/client-source.cjs +1 -1
  216. package/dist/api/client-source.cjs.map +1 -1
  217. package/dist/api/client-source.d.ts +3 -0
  218. package/dist/api/client-source.js +4 -4
  219. package/dist/api/client-source.js.map +1 -1
  220. package/dist/api/cloud/settings-service.api.cjs.map +1 -1
  221. package/dist/api/cloud/settings-service.api.js.map +1 -1
  222. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  223. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  224. package/dist/api/conversation-service/agent-server-conversation-service.api.js +111 -109
  225. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  226. package/dist/api/mcp-health/mcp-health-store.cjs +2 -0
  227. package/dist/api/mcp-health/mcp-health-store.cjs.map +1 -0
  228. package/dist/api/mcp-health/mcp-health-store.d.ts +22 -0
  229. package/dist/api/mcp-health/mcp-health-store.js +45 -0
  230. package/dist/api/mcp-health/mcp-health-store.js.map +1 -0
  231. package/dist/api/mcp-health/probe-mcp-server-health.cjs +2 -0
  232. package/dist/api/mcp-health/probe-mcp-server-health.cjs.map +1 -0
  233. package/dist/api/mcp-health/probe-mcp-server-health.d.ts +31 -0
  234. package/dist/api/mcp-health/probe-mcp-server-health.js +57 -0
  235. package/dist/api/mcp-health/probe-mcp-server-health.js.map +1 -0
  236. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  237. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  238. package/dist/api/mcp-service/mcp-service.api.js +66 -46
  239. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  240. package/dist/api/plugins-management-service.cjs.map +1 -1
  241. package/dist/api/plugins-management-service.d.ts +6 -1
  242. package/dist/api/plugins-management-service.js.map +1 -1
  243. package/dist/api/plugins-service.d.ts +30 -2
  244. package/dist/api/secrets-service.cjs +1 -1
  245. package/dist/api/secrets-service.cjs.map +1 -1
  246. package/dist/api/secrets-service.d.ts +6 -6
  247. package/dist/api/secrets-service.js +8 -3
  248. package/dist/api/secrets-service.js.map +1 -1
  249. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  250. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  251. package/dist/api/settings-service/settings-service.api.d.ts +1 -1
  252. package/dist/api/settings-service/settings-service.api.js +1 -0
  253. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  254. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.cjs +1 -1
  255. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.js +5 -5
  256. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  257. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  258. package/dist/components/features/backends/backend-form-modal.d.ts +4 -1
  259. package/dist/components/features/backends/backend-form-modal.js +15 -16
  260. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  261. package/dist/components/features/backends/backend-selector.cjs +1 -1
  262. package/dist/components/features/backends/backend-selector.cjs.map +1 -1
  263. package/dist/components/features/backends/backend-selector.js +103 -102
  264. package/dist/components/features/backends/backend-selector.js.map +1 -1
  265. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  266. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  267. package/dist/components/features/backends/manage-backends-modal.js +85 -73
  268. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  269. package/dist/components/features/chat/chat-interface.cjs +2 -2
  270. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  271. package/dist/components/features/chat/chat-interface.js +131 -129
  272. package/dist/components/features/chat/chat-interface.js.map +1 -1
  273. package/dist/components/features/chat/confirmation-mode-enabled.cjs +1 -1
  274. package/dist/components/features/chat/confirmation-mode-enabled.js +4 -4
  275. package/dist/components/features/chat/skill-install-restart-banner.cjs +2 -0
  276. package/dist/components/features/chat/skill-install-restart-banner.cjs.map +1 -0
  277. package/dist/components/features/chat/skill-install-restart-banner.d.ts +11 -0
  278. package/dist/components/features/chat/skill-install-restart-banner.js +63 -0
  279. package/dist/components/features/chat/skill-install-restart-banner.js.map +1 -0
  280. package/dist/components/features/conversation/right-panel-toggle.cjs +1 -1
  281. package/dist/components/features/conversation/right-panel-toggle.cjs.map +1 -1
  282. package/dist/components/features/conversation/right-panel-toggle.js +1 -1
  283. package/dist/components/features/conversation/right-panel-toggle.js.map +1 -1
  284. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  285. package/dist/components/features/conversation-panel/conversation-panel.js +10 -10
  286. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  287. package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
  288. package/dist/components/features/mcp-page/custom-server-editor.js +78 -77
  289. package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
  290. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  291. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  292. package/dist/components/features/mcp-page/install-server-modal.d.ts +4 -1
  293. package/dist/components/features/mcp-page/install-server-modal.js +135 -136
  294. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  295. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  296. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  297. package/dist/components/features/mcp-page/installed-server-card.js +40 -34
  298. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  299. package/dist/components/features/mcp-page/mcp-server-health.cjs +2 -0
  300. package/dist/components/features/mcp-page/mcp-server-health.cjs.map +1 -0
  301. package/dist/components/features/mcp-page/mcp-server-health.d.ts +18 -0
  302. package/dist/components/features/mcp-page/mcp-server-health.js +117 -0
  303. package/dist/components/features/mcp-page/mcp-server-health.js.map +1 -0
  304. package/dist/components/features/plugins/build-plugins-view-model.d.ts +10 -1
  305. package/dist/components/features/plugins/plugin-files-section.d.ts +13 -0
  306. package/dist/components/features/settings/agent-canvas-update-card.cjs +2 -0
  307. package/dist/components/features/settings/agent-canvas-update-card.cjs.map +1 -0
  308. package/dist/components/features/settings/agent-canvas-update-card.d.ts +7 -0
  309. package/dist/components/features/settings/agent-canvas-update-card.js +170 -0
  310. package/dist/components/features/settings/agent-canvas-update-card.js.map +1 -0
  311. package/dist/components/features/settings/integrations-settings-link.cjs +2 -0
  312. package/dist/components/features/settings/integrations-settings-link.cjs.map +1 -0
  313. package/dist/components/features/settings/integrations-settings-link.d.ts +5 -0
  314. package/dist/components/features/settings/integrations-settings-link.js +41 -0
  315. package/dist/components/features/settings/integrations-settings-link.js.map +1 -0
  316. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  317. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +1 -1
  318. package/dist/components/features/settings/settings-desktop-sidebar.cjs +1 -1
  319. package/dist/components/features/settings/settings-desktop-sidebar.cjs.map +1 -1
  320. package/dist/components/features/settings/settings-desktop-sidebar.js +31 -21
  321. package/dist/components/features/settings/settings-desktop-sidebar.js.map +1 -1
  322. package/dist/components/features/settings/settings-mobile-drawer.cjs +1 -1
  323. package/dist/components/features/settings/settings-mobile-drawer.cjs.map +1 -1
  324. package/dist/components/features/settings/settings-mobile-drawer.js +40 -30
  325. package/dist/components/features/settings/settings-mobile-drawer.js.map +1 -1
  326. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  327. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  328. package/dist/components/features/skills/extensions-navigation.js +54 -33
  329. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  330. package/dist/config/defaults.cjs +1 -1
  331. package/dist/config/defaults.cjs.map +1 -1
  332. package/dist/config/defaults.js +7 -3
  333. package/dist/config/defaults.js.map +1 -1
  334. package/dist/constants/acp-providers.cjs.map +1 -1
  335. package/dist/constants/acp-providers.js.map +1 -1
  336. package/dist/contexts/conversation-websocket-context.cjs +2 -2
  337. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  338. package/dist/contexts/conversation-websocket-context.js +169 -166
  339. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  340. package/dist/hooks/mutation/use-delete-llm-profile.cjs +1 -1
  341. package/dist/hooks/mutation/use-delete-llm-profile.js +1 -0
  342. package/dist/hooks/mutation/use-delete-mcp-server.cjs +1 -1
  343. package/dist/hooks/mutation/use-delete-mcp-server.cjs.map +1 -1
  344. package/dist/hooks/mutation/use-delete-mcp-server.js +8 -6
  345. package/dist/hooks/mutation/use-delete-mcp-server.js.map +1 -1
  346. package/dist/hooks/mutation/use-rename-llm-profile.cjs +1 -1
  347. package/dist/hooks/mutation/use-rename-llm-profile.js +1 -0
  348. package/dist/hooks/mutation/use-save-settings.cjs +1 -1
  349. package/dist/hooks/mutation/use-save-settings.js +3 -3
  350. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  351. package/dist/hooks/mutation/use-update-mcp-server.cjs.map +1 -1
  352. package/dist/hooks/mutation/use-update-mcp-server.js +11 -9
  353. package/dist/hooks/mutation/use-update-mcp-server.js.map +1 -1
  354. package/dist/hooks/query/query-keys.cjs +1 -1
  355. package/dist/hooks/query/query-keys.cjs.map +1 -1
  356. package/dist/hooks/query/query-keys.d.ts +4 -0
  357. package/dist/hooks/query/query-keys.js +2 -2
  358. package/dist/hooks/query/query-keys.js.map +1 -1
  359. package/dist/hooks/query/use-automation-sdk-version.cjs +2 -0
  360. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -0
  361. package/dist/hooks/query/use-automation-sdk-version.d.ts +3 -0
  362. package/dist/hooks/query/use-automation-sdk-version.js +63 -0
  363. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -0
  364. package/dist/hooks/query/use-latest-agent-canvas-version.cjs +2 -0
  365. package/dist/hooks/query/use-latest-agent-canvas-version.cjs.map +1 -0
  366. package/dist/hooks/query/use-latest-agent-canvas-version.d.ts +10 -0
  367. package/dist/hooks/query/use-latest-agent-canvas-version.js +19 -0
  368. package/dist/hooks/query/use-latest-agent-canvas-version.js.map +1 -0
  369. package/dist/hooks/query/use-plugin-file-content.d.ts +7 -0
  370. package/dist/hooks/query/use-resolved-workspaces.cjs +1 -1
  371. package/dist/hooks/query/use-resolved-workspaces.cjs.map +1 -1
  372. package/dist/hooks/query/use-resolved-workspaces.js +25 -26
  373. package/dist/hooks/query/use-resolved-workspaces.js.map +1 -1
  374. package/dist/hooks/query/use-search-subdirs.cjs +1 -1
  375. package/dist/hooks/query/use-search-subdirs.cjs.map +1 -1
  376. package/dist/hooks/query/use-search-subdirs.d.ts +5 -0
  377. package/dist/hooks/query/use-search-subdirs.js +16 -4
  378. package/dist/hooks/query/use-search-subdirs.js.map +1 -1
  379. package/dist/hooks/query/use-task-polling.cjs +1 -1
  380. package/dist/hooks/query/use-task-polling.cjs.map +1 -1
  381. package/dist/hooks/query/use-task-polling.d.ts +19 -3
  382. package/dist/hooks/query/use-task-polling.js +36 -35
  383. package/dist/hooks/query/use-task-polling.js.map +1 -1
  384. package/dist/hooks/use-device-flow.cjs +1 -1
  385. package/dist/hooks/use-device-flow.js +6 -6
  386. package/dist/hooks/use-llm-configured.cjs +1 -1
  387. package/dist/hooks/use-llm-configured.js +3 -3
  388. package/dist/hooks/use-mcp-server-health.cjs +2 -0
  389. package/dist/hooks/use-mcp-server-health.cjs.map +1 -0
  390. package/dist/hooks/use-mcp-server-health.d.ts +11 -0
  391. package/dist/hooks/use-mcp-server-health.js +18 -0
  392. package/dist/hooks/use-mcp-server-health.js.map +1 -0
  393. package/dist/hooks/use-skill-installs.cjs +2 -0
  394. package/dist/hooks/use-skill-installs.cjs.map +1 -0
  395. package/dist/hooks/use-skill-installs.d.ts +10 -0
  396. package/dist/hooks/use-skill-installs.js +21 -0
  397. package/dist/hooks/use-skill-installs.js.map +1 -0
  398. package/dist/hooks/use-tracking.cjs +1 -1
  399. package/dist/hooks/use-tracking.cjs.map +1 -1
  400. package/dist/hooks/use-tracking.d.ts +3 -3
  401. package/dist/hooks/use-tracking.js +67 -52
  402. package/dist/hooks/use-tracking.js.map +1 -1
  403. package/dist/i18n/declaration.cjs +1 -1
  404. package/dist/i18n/declaration.cjs.map +1 -1
  405. package/dist/i18n/declaration.d.ts +35 -1
  406. package/dist/i18n/declaration.js +1 -1
  407. package/dist/i18n/declaration.js.map +1 -1
  408. package/dist/i18n/translation.cjs +3 -3
  409. package/dist/i18n/translation.cjs.map +1 -1
  410. package/dist/i18n/translation.js +623 -45
  411. package/dist/i18n/translation.js.map +1 -1
  412. package/dist/index.cjs +1 -1
  413. package/dist/index.js +1 -2
  414. package/dist/lib/index.cjs +1 -1
  415. package/dist/lib/index.d.ts +0 -1
  416. package/dist/lib/index.js +0 -1
  417. package/dist/locales/ar/openhands.json +38 -4
  418. package/dist/locales/ca/openhands.json +38 -4
  419. package/dist/locales/de/openhands.json +38 -4
  420. package/dist/locales/en/openhands.json +38 -4
  421. package/dist/locales/es/openhands.json +38 -4
  422. package/dist/locales/fr/openhands.json +38 -4
  423. package/dist/locales/it/openhands.json +38 -4
  424. package/dist/locales/ja/openhands.json +38 -4
  425. package/dist/locales/ko-KR/openhands.json +38 -4
  426. package/dist/locales/no/openhands.json +38 -4
  427. package/dist/locales/pt/openhands.json +38 -4
  428. package/dist/locales/tr/openhands.json +38 -4
  429. package/dist/locales/uk/openhands.json +38 -4
  430. package/dist/locales/zh-CN/openhands.json +38 -4
  431. package/dist/locales/zh-TW/openhands.json +38 -4
  432. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.cjs +2 -0
  433. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.cjs.map +1 -0
  434. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.js +44 -0
  435. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.js.map +1 -0
  436. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs +1 -1
  437. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs.map +1 -1
  438. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js +13 -0
  439. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js.map +1 -1
  440. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
  441. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
  442. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +21 -1
  443. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
  444. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs +1 -1
  445. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs.map +1 -1
  446. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js +1 -1
  447. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js.map +1 -1
  448. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.cjs +1 -1
  449. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.cjs.map +1 -1
  450. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.js +13 -0
  451. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.js.map +1 -1
  452. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.cjs +1 -1
  453. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.cjs.map +1 -1
  454. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.js +13 -0
  455. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.js.map +1 -1
  456. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  457. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  458. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +13 -0
  459. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  460. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.cjs +1 -1
  461. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.cjs.map +1 -1
  462. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.js +13 -0
  463. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.js.map +1 -1
  464. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.cjs +1 -1
  465. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.cjs.map +1 -1
  466. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.js +13 -0
  467. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.js.map +1 -1
  468. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +1 -1
  469. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -1
  470. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +16 -2
  471. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -1
  472. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.cjs +2 -0
  473. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.cjs.map +1 -0
  474. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.js +46 -0
  475. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.js.map +1 -0
  476. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
  477. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
  478. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +74 -70
  479. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
  480. package/dist/node_modules/@openhands/extensions/skills/index.cjs +123 -3
  481. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  482. package/dist/node_modules/@openhands/extensions/skills/index.js +7 -1
  483. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  484. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +2 -0
  485. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs.map +1 -0
  486. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js +9 -0
  487. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js.map +1 -0
  488. package/dist/node_modules/lucide-react/dist/esm/icons/info.cjs +2 -0
  489. package/dist/node_modules/lucide-react/dist/esm/icons/info.cjs.map +1 -0
  490. package/dist/node_modules/lucide-react/dist/esm/icons/info.js +21 -0
  491. package/dist/node_modules/lucide-react/dist/esm/icons/info.js.map +1 -0
  492. package/dist/package.cjs +1 -1
  493. package/dist/package.cjs.map +1 -1
  494. package/dist/package.js +10 -3
  495. package/dist/package.js.map +1 -1
  496. package/dist/routes/app-settings.cjs +1 -1
  497. package/dist/routes/app-settings.cjs.map +1 -1
  498. package/dist/routes/app-settings.js +113 -67
  499. package/dist/routes/app-settings.js.map +1 -1
  500. package/dist/routes/conversation.cjs +1 -1
  501. package/dist/routes/conversation.cjs.map +1 -1
  502. package/dist/routes/conversation.js +1 -1
  503. package/dist/routes/conversation.js.map +1 -1
  504. package/dist/routes/mcp.cjs +1 -1
  505. package/dist/routes/mcp.cjs.map +1 -1
  506. package/dist/routes/mcp.js +1 -0
  507. package/dist/routes/mcp.js.map +1 -1
  508. package/dist/services/cloud-funnel-analytics.cjs +1 -1
  509. package/dist/services/cloud-funnel-analytics.cjs.map +1 -1
  510. package/dist/services/cloud-funnel-analytics.d.ts +2 -2
  511. package/dist/services/cloud-funnel-analytics.js +18 -16
  512. package/dist/services/cloud-funnel-analytics.js.map +1 -1
  513. package/dist/services/settings.cjs +1 -1
  514. package/dist/services/settings.cjs.map +1 -1
  515. package/dist/services/settings.js +1 -0
  516. package/dist/services/settings.js.map +1 -1
  517. package/dist/services/telemetry-context.cjs +2 -0
  518. package/dist/services/telemetry-context.cjs.map +1 -0
  519. package/dist/services/telemetry-context.d.ts +17 -0
  520. package/dist/services/telemetry-context.js +27 -0
  521. package/dist/services/telemetry-context.js.map +1 -0
  522. package/dist/services/telemetry.cjs +1 -1
  523. package/dist/services/telemetry.cjs.map +1 -1
  524. package/dist/services/telemetry.d.ts +7 -5
  525. package/dist/services/telemetry.js +132 -123
  526. package/dist/services/telemetry.js.map +1 -1
  527. package/dist/stores/skill-install-banner-store.cjs +2 -0
  528. package/dist/stores/skill-install-banner-store.cjs.map +1 -0
  529. package/dist/stores/skill-install-banner-store.d.ts +32 -0
  530. package/dist/stores/skill-install-banner-store.js +14 -0
  531. package/dist/stores/skill-install-banner-store.js.map +1 -0
  532. package/dist/stores/use-event-store.cjs +1 -1
  533. package/dist/stores/use-event-store.cjs.map +1 -1
  534. package/dist/stores/use-event-store.js +35 -35
  535. package/dist/stores/use-event-store.js.map +1 -1
  536. package/dist/types/mcp-health.cjs +2 -0
  537. package/dist/types/mcp-health.cjs.map +1 -0
  538. package/dist/types/mcp-health.d.ts +21 -0
  539. package/dist/types/mcp-health.js +6 -0
  540. package/dist/types/mcp-health.js.map +1 -0
  541. package/dist/types/settings.d.ts +1 -0
  542. package/dist/utils/handle-event-for-ui.cjs +1 -1
  543. package/dist/utils/handle-event-for-ui.cjs.map +1 -1
  544. package/dist/utils/handle-event-for-ui.d.ts +5 -0
  545. package/dist/utils/handle-event-for-ui.js +71 -57
  546. package/dist/utils/handle-event-for-ui.js.map +1 -1
  547. package/dist/utils/mcp-credential-validation.cjs +1 -1
  548. package/dist/utils/mcp-credential-validation.cjs.map +1 -1
  549. package/dist/utils/mcp-credential-validation.js +32 -16
  550. package/dist/utils/mcp-credential-validation.js.map +1 -1
  551. package/dist/utils/mcp-server-health-key.cjs +2 -0
  552. package/dist/utils/mcp-server-health-key.cjs.map +1 -0
  553. package/dist/utils/mcp-server-health-key.d.ts +16 -0
  554. package/dist/utils/mcp-server-health-key.js +23 -0
  555. package/dist/utils/mcp-server-health-key.js.map +1 -0
  556. package/dist/utils/mcp-test-error-message.cjs +2 -0
  557. package/dist/utils/mcp-test-error-message.cjs.map +1 -0
  558. package/dist/utils/mcp-test-error-message.d.ts +8 -0
  559. package/dist/utils/mcp-test-error-message.js +14 -0
  560. package/dist/utils/mcp-test-error-message.js.map +1 -0
  561. package/dist/utils/redact-mcp-secrets.cjs +2 -0
  562. package/dist/utils/redact-mcp-secrets.cjs.map +1 -0
  563. package/dist/utils/redact-mcp-secrets.d.ts +13 -0
  564. package/dist/utils/redact-mcp-secrets.js +57 -0
  565. package/dist/utils/redact-mcp-secrets.js.map +1 -0
  566. package/dist/utils/settings-utils.cjs.map +1 -1
  567. package/dist/utils/settings-utils.js.map +1 -1
  568. package/dist/utils/skill-install-events.cjs +3 -0
  569. package/dist/utils/skill-install-events.cjs.map +1 -0
  570. package/dist/utils/skill-install-events.d.ts +16 -0
  571. package/dist/utils/skill-install-events.js +26 -0
  572. package/dist/utils/skill-install-events.js.map +1 -0
  573. package/dist/utils/title-llm-profile.cjs +2 -0
  574. package/dist/utils/title-llm-profile.cjs.map +1 -0
  575. package/dist/utils/title-llm-profile.d.ts +2 -0
  576. package/dist/utils/title-llm-profile.js +11 -0
  577. package/dist/utils/title-llm-profile.js.map +1 -0
  578. package/package.json +10 -3
  579. package/scripts/check-sdk-version-sync.mjs +6 -6
  580. package/scripts/check-translation-completeness.cjs +2 -0
  581. package/scripts/dev-process-utils.mjs +62 -1
  582. package/scripts/dev-safe.mjs +2 -2
  583. package/scripts/dev-static.mjs +5 -3
  584. package/scripts/dev-with-automation.mjs +98 -14
  585. package/scripts/download-node.mjs +382 -0
  586. package/scripts/download-uv.mjs +204 -0
  587. package/scripts/logger.mjs +64 -35
  588. package/build/assets/agent-server-compatibility-BWN-EIQn.js +0 -1
  589. package/build/assets/agent-server-conversation-service.api-DSPIkMwJ.js +0 -41
  590. package/build/assets/agent-settings-CgCnqaAA.js +0 -2
  591. package/build/assets/agent-settings-DDkSavD7.js +0 -1
  592. package/build/assets/api-key-entry-screen-iZc7n8AI.js +0 -1
  593. package/build/assets/app-settings-B5zyipxJ.js +0 -1
  594. package/build/assets/automation-export-BwRX6H32.js +0 -2
  595. package/build/assets/automations-list-lHAVzMoA.js +0 -1
  596. package/build/assets/backend-form-modal-RGcu909r.js +0 -1
  597. package/build/assets/browser-store-BI6uklCG.js +0 -1
  598. package/build/assets/chat-send-button-BZHG2hAW.js +0 -1
  599. package/build/assets/client-source-BZK8vRs2.js +0 -1
  600. package/build/assets/cloud-funnel-analytics-Zcv57hfT.js +0 -1
  601. package/build/assets/conversation-BoCYx8n2.js +0 -89
  602. package/build/assets/conversation-DgHqMjnY.js +0 -1
  603. package/build/assets/conversation-panel-78Rxh_-I.js +0 -1
  604. package/build/assets/conversation-state-store-B2Bp32XI.js +0 -1
  605. package/build/assets/declaration-BGsHjPEW.js +0 -1
  606. package/build/assets/extensions-hub-CCbLA7IM.js +0 -1
  607. package/build/assets/extensions-navigation-CPNjMNvR.js +0 -1
  608. package/build/assets/files-tab-store-DJsPxYdg.js +0 -1
  609. package/build/assets/files-tab-y4K7EXBO.js +0 -1
  610. package/build/assets/git-provider-icon-ITvsH4Ko.js +0 -1
  611. package/build/assets/home-BwbeOWwU.js +0 -1
  612. package/build/assets/home-DKPGQ5P3.js +0 -1
  613. package/build/assets/index-home-Bko2Itv5.js +0 -1
  614. package/build/assets/install-server-modal-Qk1gwyI8.js +0 -1
  615. package/build/assets/lesson-plan-DMCPdtrf.js +0 -4
  616. package/build/assets/llm-not-configured-banner-C1ktyb3C.js +0 -27
  617. package/build/assets/llm-settings-BBsZFi9l.js +0 -1
  618. package/build/assets/llm-settings-DFkJQr_w.js +0 -1
  619. package/build/assets/manage-backends-modal-CKQ46rvw.js +0 -1
  620. package/build/assets/manifest-03478bbf.js +0 -1
  621. package/build/assets/markdown-renderer-B4V2OMFP.js +0 -2
  622. package/build/assets/mcp-BapoJsDc.js +0 -9
  623. package/build/assets/messages-CUBFMY5o.js +0 -40
  624. package/build/assets/objectWithoutPropertiesLoose-BgYIAs2y.js +0 -1
  625. package/build/assets/onboarding-6NMkdNxV.js +0 -1
  626. package/build/assets/onboarding-modal-Q4AnpIdg.js +0 -1
  627. package/build/assets/recommended-automations-launcher-Bj7PuHY1.js +0 -58
  628. package/build/assets/refresh-cw-B9B7-vsy.js +0 -1
  629. package/build/assets/root-CDnuTToz.js +0 -2
  630. package/build/assets/root-CYWeTrWE.css +0 -1
  631. package/build/assets/root-layout-DfYVlcRG.js +0 -2
  632. package/build/assets/sdk-section-page-DLLNrYjI.js +0 -1
  633. package/build/assets/secrets-settings-CHy72A5C.js +0 -1
  634. package/build/assets/settings-B9S8UVQr.js +0 -1
  635. package/build/assets/settings-index-BKDl2CQ-.js +0 -1
  636. package/build/assets/settings-modal-DeK11CyT.js +0 -1
  637. package/build/assets/shared-conversation-9atDzTR4.js +0 -1
  638. package/build/assets/sidebar-mobile-menu-toggle-giMMZctn.js +0 -1
  639. package/build/assets/skills-plugins-Tropusio.js +0 -1
  640. package/build/assets/skills-settings-BvzBBCWk.js +0 -2
  641. package/build/assets/telemetry-C5JMEfqB.js +0 -2
  642. package/build/assets/use-activate-agent-profile-DlykqEfN.js +0 -1
  643. package/build/assets/use-backends-health-CLHPitJM.js +0 -1
  644. package/build/assets/use-config-B5r8erYt.js +0 -1
  645. package/build/assets/use-event-store-Bbaz51GR.js +0 -4
  646. package/build/assets/use-llm-profiles-Dr5__SlZ.js +0 -1
  647. package/build/assets/use-plugins-marketplace-BplU65ae.js +0 -1
  648. package/build/assets/use-runtime-is-ready-vCFOcLFa.js +0 -1
  649. package/build/assets/use-settings-CyxSlyTQ.js +0 -1
  650. package/build/assets/use-settings-nav-items-zEkSO_Bf.js +0 -16
  651. package/build/assets/use-tracking-D2Qg5Lpd.js +0 -1
  652. package/build/assets/useMutationState-OnAsCLA_.js +0 -1
  653. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BD7v71DM.js +0 -2
  654. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BT05Osu4.js +0 -28
  655. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-COhHANvV.js +0 -2
  656. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DgzWSMRc.js +0 -2
  657. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DqZatR3B.js +0 -7
  658. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-FghQ3Z1a.js +0 -1
  659. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-BTvhGHHG.js +0 -1
  660. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C4-GDgiF.js +0 -1
  661. package/dist/components/features/analytics/telemetry-consent-banner.cjs +0 -2
  662. package/dist/components/features/analytics/telemetry-consent-banner.cjs.map +0 -1
  663. package/dist/components/features/analytics/telemetry-consent-banner.d.ts +0 -29
  664. package/dist/components/features/analytics/telemetry-consent-banner.js +0 -59
  665. package/dist/components/features/analytics/telemetry-consent-banner.js.map +0 -1
  666. /package/build/assets/{__vite-browser-external-BQUj0sYu.js → __vite-browser-external-CKHVBTNC.js} +0 -0
  667. /package/build/assets/{agent-server-ui-style-scope-qhnhZHBV.js → agent-server-ui-style-scope-BvSa9on7.js} +0 -0
  668. /package/build/assets/{automation-LZB0MjdV.js → automation-BGiPmxFR.js} +0 -0
  669. /package/build/assets/{canvas-ui-COgjltGz.js → canvas-ui-CC4EJo-H.js} +0 -0
  670. /package/build/assets/{checkmark-h7udgXMM.js → checkmark-ygQB1AtV.js} +0 -0
  671. /package/build/assets/{close-DLFb5kfv.js → close-BjSA0HWT.js} +0 -0
  672. /package/build/assets/{code-tag-DYlAhEQY.js → code-tag-D9aPPbOe.js} +0 -0
  673. /package/build/assets/{common-CxbUL3nR.js → common-CCuqQy_S.js} +0 -0
  674. /package/build/assets/{conversation-local-storage-F6zVMM--.js → conversation-local-storage-BDjWPg0Z.js} +0 -0
  675. /package/build/assets/{copy-BLmGeJcd.js → copy-Dce7sOvS.js} +0 -0
  676. /package/build/assets/{copy-D1YGjP-C.js → copy-iPJAncAj.js} +0 -0
  677. /package/build/assets/{dist-CodhvuAP.js → dist-D9PhjOaq.js} +0 -0
  678. /package/build/assets/{environment-switch-store-DkjlKWzN.js → environment-switch-store-DHfcz4M4.js} +0 -0
  679. /package/build/assets/{extension-module-card-classes-9V3J9J_b.js → extension-module-card-classes-BpebKiN6.js} +0 -0
  680. /package/build/assets/{external-link-lhdITPqq.js → external-link-CpPMXxrV.js} +0 -0
  681. /package/build/assets/{folder-Bk311brm.js → folder-BabbYnbF.js} +0 -0
  682. /package/build/assets/{format-time-delta-DhDbkD7V.js → format-time-delta-BkAmJEPT.js} +0 -0
  683. /package/build/assets/{get-language-from-path-DBqBsCWH.js → get-language-from-path-CPNnuVhI.js} +0 -0
  684. /package/build/assets/{git-status-mapper-DnL9OC8_.js → git-status-mapper-BIXK0AAG.js} +0 -0
  685. /package/build/assets/{iconBase-Dz51Zn5x.js → iconBase-Ch-fOe8B.js} +0 -0
  686. /package/build/assets/{link-external-CaBmUEs_.js → link-external-DfKQroKX.js} +0 -0
  687. /package/build/assets/{list-todo-CAtvkzcy.js → list-todo-6J6zc8oS.js} +0 -0
  688. /package/build/assets/{llm-subscription-DtsX5Lhg.js → llm-subscription-Bvu8BLXc.js} +0 -0
  689. /package/build/assets/{loader-circle-CsAsfLIs.js → loader-circle-DGsqG5qw.js} +0 -0
  690. /package/build/assets/{map-provider-BbIb12oh.js → map-provider-BSvXvVR0.js} +0 -0
  691. /package/build/assets/{middleware-DYHYNAnP.js → middleware-_izt7V6U.js} +0 -0
  692. /package/build/assets/{modal-backdrop-zVwfOJZr.js → modal-backdrop-B7H42xHG.js} +0 -0
  693. /package/build/assets/{navigation-context-DPs2G0X8.js → navigation-context-cvyvI1WA.js} +0 -0
  694. /package/build/assets/{openhands-logo-bcNw5bkY.js → openhands-logo-pEw0nKFP.js} +0 -0
  695. /package/build/assets/{pencil-CWhApFIT.js → pencil-DmSqWUA3.js} +0 -0
  696. /package/build/assets/{react-DPDgL6du.js → react-MKQOkha9.js} +0 -0
  697. /package/build/assets/{search-BgOCR7_c.js → search-B5D5EuSn.js} +0 -0
  698. /package/build/assets/{search-dIQ09UY2.js → search-vnYL5jwV.js} +0 -0
  699. /package/build/assets/{settings-gear-MXCyZW0x.js → settings-gear-BOwF59Bs.js} +0 -0
  700. /package/build/assets/{settings-section-header-context-COMOIaxV.js → settings-section-header-context-CGgHZXrf.js} +0 -0
  701. /package/build/assets/{skills-EqzxYBvT.js → skills-arUOHLcS.js} +0 -0
  702. /package/build/assets/{square-chevron-right-DE-JN-2Z.js → square-chevron-right-EizCGtgq.js} +0 -0
  703. /package/build/assets/{switch-skeleton-DqQwalyu.js → switch-skeleton-BjPRx1QD.js} +0 -0
  704. /package/build/assets/{terminal-Cgf___rK.js → terminal-a57bHgZs.js} +0 -0
  705. /package/build/assets/{trash-2-BU6BlW4i.js → trash-2-CF3hilrY.js} +0 -0
  706. /package/build/assets/{u-check-circle-BqoIxNz_.js → u-check-circle-WGqHdtfO.js} +0 -0
  707. /package/build/assets/{u-check-circle-half-MsShT8Ec.js → u-check-circle-half-LiwZkuFe.js} +0 -0
  708. /package/build/assets/{u-edit-DL5LgKon.js → u-edit-BwHepAPi.js} +0 -0
  709. /package/build/assets/{use-breakpoint-BP3lqLMx.js → use-breakpoint-B-O0lQ84.js} +0 -0
  710. /package/build/assets/{use-click-outside-element-D9BYdANT.js → use-click-outside-element-DLQIMQrz.js} +0 -0
  711. /package/build/assets/{use-is-authed-BezEyfeh.js → use-is-authed-BSeo4coy.js} +0 -0
  712. /package/build/assets/{use-onboarding-completion-C_Swglzp.js → use-onboarding-completion-C0hPNGpw.js} +0 -0
  713. /package/build/assets/{v4-DbCkTSoU.js → v4-q4yWTlMz.js} +0 -0
  714. /package/build/assets/{vendor~browser-By2MVv_N.js → vendor~browser-UwB1jbAZ.js} +0 -0
  715. /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-CxfzCmkN.js → vendor~conversation-panel~conversation~alert-banner-DHDkknt5.js} +0 -0
  716. /package/build/assets/{vendor~index-home~home~conversation-panel~conversation-ChmYLVgz.js → vendor~index-home~home~conversation-panel~conversation-Bff9cq5J.js} +0 -0
  717. /package/build/assets/{vendor~module-D5a_AClf.js → vendor~module-D4DeFV4J.js} +0 -0
  718. /package/build/assets/{vendor~terminal-CnKZILnC.js → vendor~terminal-B7Eiak0-.js} +0 -0
  719. /package/build/assets/{x-ZE4iplpF.js → x-DQB_00VJ.js} +0 -0
  720. /package/build/assets/{x-mark-Batp6gXa.js → x-mark-B32XuEwS.js} +0 -0
@@ -3,10 +3,11 @@ import "../../node_modules/@openhands/typescript-client/dist/clients.js";
3
3
  import { getActiveBackend as t, getRegisteredBackends as n } from "../backend-registry/active-store.js";
4
4
  import { getAgentServerClientOptions as r } from "../agent-server-client-options.js";
5
5
  import { getCredentialValidationForServer as i } from "../../utils/mcp-credential-validation.js";
6
- import { substituteRedactedMcpCredentials as a } from "./mcp-redacted-credentials.js";
6
+ import { redactMcpSecrets as a } from "../../utils/redact-mcp-secrets.js";
7
+ import { substituteRedactedMcpCredentials as o } from "./mcp-redacted-credentials.js";
7
8
  //#region src/api/mcp-service/mcp-service.api.ts
8
- var o = 120;
9
- function s(e) {
9
+ var s = 120;
10
+ function c(e) {
10
11
  return e.type === "stdio" ? {
11
12
  transport: "stdio",
12
13
  command: e.command,
@@ -19,19 +20,46 @@ function s(e) {
19
20
  ...e.auth ? { auth: e.auth } : {}
20
21
  };
21
22
  }
22
- function c(e) {
23
- return e.auth?.strategy === "oauth2" ? o : e.timeout;
23
+ function l(e) {
24
+ return e.auth?.strategy === "oauth2" ? s : e.timeout;
24
25
  }
25
- async function l(e) {
26
- let t = i(e), n = s(await a(e)), r = c(e);
26
+ async function u(e) {
27
+ let t = i(e), n = await o(e), r = c(n), a = l(e);
27
28
  return {
28
- server: n,
29
- ...e.name ? { name: e.name } : {},
30
- ...r === void 0 ? {} : { timeout: r },
31
- ...t ? { tool_call: t.toolCall } : {}
29
+ request: {
30
+ server: r,
31
+ ...e.name ? { name: e.name } : {},
32
+ ...a === void 0 ? {} : { timeout: a },
33
+ ...t ? { tool_call: t.toolCall } : {}
34
+ },
35
+ substituted: n
36
+ };
37
+ }
38
+ function d(e, t) {
39
+ return e.ok ? e.tool_result ? {
40
+ ...e,
41
+ tool_result: {
42
+ ...e.tool_result,
43
+ text: a(e.tool_result.text, ...t)
44
+ }
45
+ } : e : {
46
+ ...e,
47
+ error: a(e.error, ...t)
32
48
  };
33
49
  }
34
- function u() {
50
+ function f(e, t, n) {
51
+ let r = d(e, n);
52
+ if (r.ok && t && r.tool_result && r.tools.includes(t.toolCall.name)) {
53
+ let e = t.interpret(r.tool_result);
54
+ if (e) return {
55
+ ok: !1,
56
+ error: e,
57
+ error_kind: "credentials"
58
+ };
59
+ }
60
+ return r;
61
+ }
62
+ function p() {
35
63
  if (t().backend.kind === "local") {
36
64
  let { host: e, apiKey: t } = r();
37
65
  return {
@@ -46,15 +74,15 @@ function u() {
46
74
  };
47
75
  throw Error("OAuth authorization requires a reachable local backend.");
48
76
  }
49
- function d() {
50
- let { host: t, apiKey: n } = u();
77
+ function m() {
78
+ let { host: t, apiKey: n } = p();
51
79
  return new e({
52
80
  host: t,
53
81
  ...n ? { apiKey: n } : {},
54
- timeout: o * 1e3 + 5e3
82
+ timeout: s * 1e3 + 5e3
55
83
  });
56
84
  }
57
- function f(e) {
85
+ function h(e) {
58
86
  return e.status === "succeeded" ? {
59
87
  ok: !0,
60
88
  tools: e.tools ?? [],
@@ -66,9 +94,9 @@ function f(e) {
66
94
  error_kind: e.error_kind || "unknown"
67
95
  };
68
96
  }
69
- var p = (e) => new Promise((t) => {
97
+ var g = (e) => new Promise((t) => {
70
98
  window.setTimeout(t, e);
71
- }), m = class n {
99
+ }), _ = class n {
72
100
  static async testServer(n) {
73
101
  if (t().backend.kind === "cloud") return {
74
102
  ok: !0,
@@ -79,22 +107,14 @@ var p = (e) => new Promise((t) => {
79
107
  ...s ? { apiKey: s } : {}
80
108
  });
81
109
  try {
82
- let e = await l(n), t = await c.testServer(e);
83
- if (t.ok && a && t.tool_result) {
84
- let e = a.interpret(t.tool_result);
85
- if (e) return {
86
- ok: !1,
87
- error: e,
88
- error_kind: "credentials"
89
- };
90
- }
91
- return t;
110
+ let { request: e, substituted: t } = await u(n);
111
+ return f(await c.testServer(e), a, [t, n]);
92
112
  } finally {
93
113
  c.close();
94
114
  }
95
115
  }
96
116
  static async startOAuth(e) {
97
- let t = d();
117
+ let t = m();
98
118
  try {
99
119
  return await n.startOAuthWithClient(t, e);
100
120
  } finally {
@@ -102,7 +122,7 @@ var p = (e) => new Promise((t) => {
102
122
  }
103
123
  }
104
124
  static async getOAuthStatus(e) {
105
- let t = d();
125
+ let t = m();
106
126
  try {
107
127
  return await n.getOAuthStatusWithClient(t, e);
108
128
  } finally {
@@ -110,7 +130,7 @@ var p = (e) => new Promise((t) => {
110
130
  }
111
131
  }
112
132
  static async submitOAuthCallback(e, t) {
113
- let r = d();
133
+ let r = m();
114
134
  try {
115
135
  return await n.submitOAuthCallbackWithClient(r, e, t);
116
136
  } finally {
@@ -118,33 +138,33 @@ var p = (e) => new Promise((t) => {
118
138
  }
119
139
  }
120
140
  static async authorizeOAuth(e) {
121
- let t = window.open("about:blank", "_blank"), r = d();
141
+ let t = i(e), r = (n) => f(n, t, [e]), a = window.open("about:blank", "_blank"), o = m();
122
142
  try {
123
- let i = await n.startOAuthWithClient(r, e);
124
- if (!i.ok || !i.job_id || !i.authorization_url) return t?.close(), {
143
+ let t = await n.startOAuthWithClient(o, e);
144
+ if (!t.ok || !t.job_id || !t.authorization_url) return a?.close(), r({
125
145
  ok: !1,
126
- error: i.error || "Could not start OAuth authorization",
127
- error_kind: i.error_kind || "unknown"
128
- };
129
- let a = await n.getOAuthStatusWithClient(r, i.job_id);
146
+ error: t.error || "Could not start OAuth authorization",
147
+ error_kind: t.error_kind || "unknown"
148
+ });
149
+ let i = await n.getOAuthStatusWithClient(o, t.job_id);
130
150
  for (let e = 0; e < 20; e += 1) {
131
- if (a.status === "succeeded" || a.status === "failed") return t?.close(), f(a);
132
- if (a.callback_ready) break;
133
- await p(250), a = await n.getOAuthStatusWithClient(r, i.job_id);
151
+ if (i.status === "succeeded" || i.status === "failed") return a?.close(), r(h(i));
152
+ if (i.callback_ready) break;
153
+ await g(250), i = await n.getOAuthStatusWithClient(o, t.job_id);
134
154
  }
135
- t && (t.location.href = i.authorization_url);
136
- for (let e = 0; e < o; e += 1) if (await p(1e3), a = await n.getOAuthStatusWithClient(r, i.job_id), a.status === "succeeded" || a.status === "failed") return t?.close(), f(a);
155
+ a && (a.location.href = t.authorization_url);
156
+ for (let e = 0; e < s; e += 1) if (await g(1e3), i = await n.getOAuthStatusWithClient(o, t.job_id), i.status === "succeeded" || i.status === "failed") return a?.close(), r(h(i));
137
157
  return {
138
158
  ok: !1,
139
159
  error: "OAuth authorization timed out",
140
160
  error_kind: "timeout"
141
161
  };
142
162
  } finally {
143
- r.close();
163
+ o.close();
144
164
  }
145
165
  }
146
166
  static async startOAuthWithClient(e, t) {
147
- let n = await l(t);
167
+ let { request: n } = await u(t);
148
168
  return e.startOAuth(n);
149
169
  }
150
170
  static async getOAuthStatusWithClient(e, t) {
@@ -155,6 +175,6 @@ var p = (e) => new Promise((t) => {
155
175
  }
156
176
  };
157
177
  //#endregion
158
- export { m as default };
178
+ export { _ as default };
159
179
 
160
180
  //# sourceMappingURL=mcp-service.api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-service.api.js","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport { getCredentialValidationForServer } from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(\n server: MCPServerConfig,\n): Promise<ExtendedMCPTestRequest> {\n const validation = getCredentialValidationForServer(server);\n const serverSpec = toMcpServer(\n await substituteRedactedMcpCredentials(server),\n );\n const timeout = getMcpTestTimeout(server);\n return {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n };\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const request = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n if (result.ok && validation && result.tool_result) {\n const credentialError = validation.interpret(result.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return result;\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return {\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n };\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return oauthStatusToTestResponse(status);\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return oauthStatusToTestResponse(status);\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const request = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.getOAuthStatus(jobId);\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.submitOAuthCallback(jobId, { callback_url: callbackUrl });\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-service.api.js","names":[],"sources":["../../../src/api/mcp-service/mcp-service.api.ts"],"sourcesContent":["import { MCPClient } from \"@openhands/typescript-client/clients\";\nimport type { MCPTestRequest } from \"@openhands/typescript-client\";\nimport { getAgentServerClientOptions } from \"../agent-server-client-options\";\nimport {\n getActiveBackend,\n getRegisteredBackends,\n} from \"../backend-registry/active-store\";\nimport {\n getCredentialValidationForServer,\n type CredentialValidation,\n} from \"#/utils/mcp-credential-validation\";\nimport type { MCPAuthCredential } from \"#/types/mcp-auth\";\nimport type {\n ExtendedMCPTestResponse,\n MCPOAuthStartResponse,\n MCPOAuthStatusResponse,\n MCPServerConfig,\n} from \"#/types/mcp-server\";\nimport { redactMcpSecrets } from \"#/utils/redact-mcp-secrets\";\nimport { substituteRedactedMcpCredentials } from \"./mcp-redacted-credentials\";\n\nconst OAUTH_MCP_TEST_TIMEOUT_SECONDS = 120;\n\ntype MCPTestServer = {\n transport?: \"stdio\" | \"http\" | \"sse\";\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n headers?: Record<string, string>;\n auth?: MCPAuthCredential;\n};\n\ninterface ExtendedMCPTestRequest {\n server: MCPTestServer;\n name?: string;\n timeout?: number;\n tool_call?: {\n name: string;\n arguments: Record<string, unknown>;\n };\n}\n\nfunction toMcpServer(server: MCPServerConfig): MCPTestServer {\n if (server.type === \"stdio\") {\n return {\n transport: \"stdio\",\n command: server.command!,\n ...(server.args?.length && { args: server.args }),\n ...(server.env &&\n Object.keys(server.env).length > 0 && { env: server.env }),\n };\n }\n return {\n transport: server.type === \"sse\" ? \"sse\" : \"http\",\n url: server.url!,\n ...(server.headers &&\n Object.keys(server.headers).length > 0 && { headers: server.headers }),\n ...(server.auth ? { auth: server.auth } : {}),\n };\n}\n\nfunction getMcpTestTimeout(server: MCPServerConfig): number | undefined {\n if (server.auth?.strategy !== \"oauth2\") return server.timeout;\n return OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n}\n\nasync function buildMcpTestRequest(server: MCPServerConfig): Promise<{\n request: ExtendedMCPTestRequest;\n substituted: MCPServerConfig;\n}> {\n const validation = getCredentialValidationForServer(server);\n const substituted = await substituteRedactedMcpCredentials(server);\n const serverSpec = toMcpServer(substituted);\n const timeout = getMcpTestTimeout(server);\n return {\n request: {\n server: serverSpec,\n ...(server.name ? { name: server.name } : {}),\n ...(timeout !== undefined ? { timeout } : {}),\n ...(validation ? { tool_call: validation.toolCall } : {}),\n },\n substituted,\n };\n}\n\nfunction redactMcpTestResponse(\n result: ExtendedMCPTestResponse,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n if (!result.ok) {\n return {\n ...result,\n error: redactMcpSecrets(result.error, ...redactionSources),\n };\n }\n if (result.tool_result) {\n return {\n ...result,\n tool_result: {\n ...result.tool_result,\n text: redactMcpSecrets(result.tool_result.text, ...redactionSources),\n },\n };\n }\n return result;\n}\n\n/**\n * Display-boundary post-processing shared by the test and OAuth probes:\n * scrub secrets from error/tool-result text, then let the catalog entry's\n * credential validation turn a failed read-only tool call into a\n * `credentials` failure. The interpretation only runs when the probe tool\n * is actually advertised in `tools` — a server variant that doesn't expose\n * the tool (e.g. a hosted alternative to the stdio server the spec was\n * written for) must degrade to a connectivity-only success, not be\n * misreported as bad credentials.\n */\nfunction finalizeMcpTestResponse(\n result: ExtendedMCPTestResponse,\n validation: CredentialValidation | undefined,\n redactionSources: (MCPServerConfig | undefined)[],\n): ExtendedMCPTestResponse {\n const redacted = redactMcpTestResponse(result, redactionSources);\n if (\n redacted.ok &&\n validation &&\n redacted.tool_result &&\n redacted.tools.includes(validation.toolCall.name)\n ) {\n const credentialError = validation.interpret(redacted.tool_result);\n if (credentialError) {\n return {\n ok: false,\n error: credentialError,\n error_kind: \"credentials\",\n };\n }\n }\n return redacted;\n}\n\nfunction getMcpProbeOptions(): { host: string; apiKey?: string } {\n const active = getActiveBackend().backend;\n if (active.kind === \"local\") {\n const { host, apiKey } = getAgentServerClientOptions();\n return { host, ...(apiKey ? { apiKey } : {}) };\n }\n\n const localBackend = getRegisteredBackends().find(\n (backend) => backend.kind === \"local\" && backend.host,\n );\n if (localBackend) {\n return {\n host: localBackend.host.replace(/\\/+$/, \"\"),\n ...(localBackend.apiKey ? { apiKey: localBackend.apiKey } : {}),\n };\n }\n throw new Error(\"OAuth authorization requires a reachable local backend.\");\n}\n\nfunction createMcpProbeClient(): MCPClient {\n const { host, apiKey } = getMcpProbeOptions();\n return new MCPClient({\n host,\n ...(apiKey ? { apiKey } : {}),\n timeout: OAUTH_MCP_TEST_TIMEOUT_SECONDS * 1000 + 5000,\n });\n}\n\nfunction oauthStatusToTestResponse(\n status: MCPOAuthStatusResponse,\n): ExtendedMCPTestResponse {\n if (status.status === \"succeeded\") {\n return {\n ok: true,\n tools: status.tools ?? [],\n ...(status.tool_result !== undefined && {\n tool_result: status.tool_result,\n }),\n ...(status.oauth_state !== undefined && {\n oauth_state: status.oauth_state,\n }),\n };\n }\n return {\n ok: false,\n error: status.error || \"OAuth authorization did not complete\",\n error_kind: status.error_kind || \"unknown\",\n };\n}\n\nconst sleep = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, ms);\n });\n\nclass McpService {\n static async testServer(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n // The MCP connectivity-test endpoint lives on the local agent-server. It\n // spawns the configured stdio command / opens an SSE-or-SHTTP connection\n // from that process's environment. Cloud backends don't expose this\n // endpoint to the frontend — the MCP server would actually run inside the\n // cloud sandbox, which isn't reachable from the browser before the user\n // starts a conversation. Calling `getAgentServerClientOptions()` here for\n // a cloud-active session would throw `NoBackendAvailableError(\"No backend\n // is configured.\")` and block the install flow entirely. Short-circuit\n // with a synthetic success so saving proceeds; any real connection\n // failure surfaces inside the conversation runtime instead.\n if (getActiveBackend().backend.kind === \"cloud\") {\n return { ok: true, tools: [] };\n }\n const validation = getCredentialValidationForServer(server);\n const { host, apiKey } = getAgentServerClientOptions();\n const client = new MCPClient({ host, ...(apiKey ? { apiKey } : {}) });\n try {\n const { request, substituted } = await buildMcpTestRequest(server);\n const result = (await client.testServer(\n request as MCPTestRequest,\n )) as ExtendedMCPTestResponse;\n // Redact against both config forms: `server` may hold fresh plaintext\n // input, `substituted` the stored (encrypted) round-trip values.\n return finalizeMcpTestResponse(result, validation, [substituted, server]);\n } finally {\n client.close();\n }\n }\n\n static async startOAuth(\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.startOAuthWithClient(client, server);\n } finally {\n client.close();\n }\n }\n\n static async getOAuthStatus(jobId: string): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.getOAuthStatusWithClient(client, jobId);\n } finally {\n client.close();\n }\n }\n\n static async submitOAuthCallback(\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n const client = createMcpProbeClient();\n try {\n return await McpService.submitOAuthCallbackWithClient(\n client,\n jobId,\n callbackUrl,\n );\n } finally {\n client.close();\n }\n }\n\n static async authorizeOAuth(\n server: MCPServerConfig,\n ): Promise<ExtendedMCPTestResponse> {\n const validation = getCredentialValidationForServer(server);\n const finalize = (result: ExtendedMCPTestResponse) =>\n finalizeMcpTestResponse(result, validation, [server]);\n const popup = window.open(\"about:blank\", \"_blank\");\n const client = createMcpProbeClient();\n try {\n const start = await McpService.startOAuthWithClient(client, server);\n if (!start.ok || !start.job_id || !start.authorization_url) {\n popup?.close();\n return finalize({\n ok: false,\n error: start.error || \"Could not start OAuth authorization\",\n error_kind: start.error_kind || \"unknown\",\n });\n }\n\n let status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n if (status.callback_ready) break;\n await sleep(250);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n }\n\n if (popup) {\n popup.location.href = start.authorization_url;\n }\n\n for (\n let attempt = 0;\n attempt < OAUTH_MCP_TEST_TIMEOUT_SECONDS;\n attempt += 1\n ) {\n await sleep(1000);\n status = await McpService.getOAuthStatusWithClient(\n client,\n start.job_id,\n );\n if (status.status === \"succeeded\" || status.status === \"failed\") {\n popup?.close();\n return finalize(oauthStatusToTestResponse(status));\n }\n }\n\n return {\n ok: false,\n error: \"OAuth authorization timed out\",\n error_kind: \"timeout\",\n };\n } finally {\n client.close();\n }\n }\n\n private static async startOAuthWithClient(\n client: MCPClient,\n server: MCPServerConfig,\n ): Promise<MCPOAuthStartResponse> {\n const { request } = await buildMcpTestRequest(server);\n return client.startOAuth(request as MCPTestRequest);\n }\n\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.getOAuthStatus(jobId);\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return client.submitOAuthCallback(jobId, { callback_url: callbackUrl });\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugins-management-service.cjs","names":[],"sources":["../../src/api/plugins-management-service.ts"],"sourcesContent":["import { PluginsClient } from \"@openhands/typescript-client/clients\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\n\n/**\n * An installed plugin, as returned by the agent-server management router\n * (`GET /api/plugins/installed`). Matches the typescript-client\n * `InstalledPluginInfo`.\n */\nexport interface InstalledPluginInfo {\n name: string;\n version: string;\n description: string | null;\n enabled: boolean;\n source: string;\n resolved_ref?: string | null;\n repo_path?: string | null;\n installed_at: string;\n install_path: string;\n}\n\n/** Coordinates for installing a plugin from a git source or local path. */\nexport interface InstallPluginRequest {\n source: string;\n ref?: string | null;\n repo_path?: string | null;\n force?: boolean;\n}\n\n/**\n * The slice of the typescript-client `PluginsClient` this service drives. The\n * installed `@openhands/typescript-client` package does not yet export these\n * management methods (they ship in typescript-client PRs #222/#223); narrowing\n * to this local interface keeps `vitest` (types stripped) and `eslint` green\n * until the client is republished, at which point the cast below can be dropped.\n */\ninterface PluginsManagementClient {\n listInstalledPlugins(): Promise<{ plugins: InstalledPluginInfo[] }>;\n installPlugin(request: InstallPluginRequest): Promise<InstalledPluginInfo>;\n setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }>;\n uninstallPlugin(name: string): Promise<{ message: string }>;\n refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }>;\n}\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction getManagementClient(): PluginsManagementClient {\n return new PluginsClient(\n getAgentServerClientOptions(),\n ) as unknown as PluginsManagementClient;\n}\n\n/**\n * Front-end management layer for installed plugins: list / install / enable /\n * disable / uninstall / refresh. Kept separate from the read-only catalog\n * service (`plugins-service.ts`), exactly as skills separate the marketplace\n * catalog from install actions.\n *\n * Local backend only for now (per Appendix C Q5): installed plugins live on the\n * local agent-server's `~/.openhands/plugins/installed/`. A cloud backend has no\n * per-user installed store yet, so reads return an empty list and mutating\n * actions throw (the UI also disables them on cloud).\n */\nclass PluginsManagementService {\n static async listInstalledPlugins(): Promise<InstalledPluginInfo[]> {\n if (isCloudBackend()) {\n return [];\n }\n\n try {\n const response = await getManagementClient().listInstalledPlugins();\n return response.plugins ?? [];\n } catch {\n // Agent-server may predate the plugins router or be unreachable; surface\n // an empty list rather than throwing (mirrors the catalog service).\n return [];\n }\n }\n\n static async installPlugin(\n request: InstallPluginRequest,\n ): Promise<InstalledPluginInfo> {\n if (isCloudBackend()) {\n throw new Error(\n \"Installing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().installPlugin(request);\n }\n\n static async setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Enabling and disabling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().setPluginEnabled(name, enabled);\n }\n\n static async uninstallPlugin(name: string): Promise<{ message: string }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Uninstalling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().uninstallPlugin(name);\n }\n\n static async refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Refreshing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().refreshPlugin(name);\n }\n}\n\nexport default PluginsManagementService;\n"],"mappings":"2TAiDA,SAAS,GAA0B,CACjC,OAAO,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAG7C,SAAS,GAA+C,CACtD,OAAO,IAAI,EAAA,cACT,EAAA,6BAA6B,CAC9B,CAcH,IAAM,EAAN,KAA+B,CAC7B,aAAa,sBAAuD,CAClE,GAAI,GAAgB,CAClB,MAAO,EAAE,CAGX,GAAI,CAEF,OAAO,MADgB,GAAqB,CAAC,sBAAsB,EACnD,SAAW,EAAE,MACvB,CAGN,MAAO,EAAE,EAIb,aAAa,cACX,EAC8B,CAC9B,GAAI,GAAgB,CAClB,MAAU,MACR,2DACD,CAEH,OAAO,GAAqB,CAAC,cAAc,EAAQ,CAGrD,aAAa,iBACX,EACA,EAC6C,CAC7C,GAAI,GAAgB,CAClB,MAAU,MACR,uEACD,CAEH,OAAO,GAAqB,CAAC,iBAAiB,EAAM,EAAQ,CAG9D,aAAa,gBAAgB,EAA4C,CACvE,GAAI,GAAgB,CAClB,MAAU,MACR,6DACD,CAEH,OAAO,GAAqB,CAAC,gBAAgB,EAAK,CAGpD,aAAa,cACX,EAC2D,CAC3D,GAAI,GAAgB,CAClB,MAAU,MACR,2DACD,CAEH,OAAO,GAAqB,CAAC,cAAc,EAAK"}
1
+ {"version":3,"file":"plugins-management-service.cjs","names":[],"sources":["../../src/api/plugins-management-service.ts"],"sourcesContent":["import { PluginsClient } from \"@openhands/typescript-client/clients\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport type { PluginBundledSkill } from \"./plugins-service\";\n\n/**\n * An installed plugin, as returned by the agent-server management router\n * (`GET /api/plugins/installed`). Matches the typescript-client\n * `InstalledPluginInfo`. The contents fields (`skills`, `files`, relative to\n * `install_path`) are absent on older agent-servers and null when the\n * installed plugin directory failed to load.\n */\nexport interface InstalledPluginInfo {\n name: string;\n version: string;\n description: string | null;\n enabled: boolean;\n source: string;\n resolved_ref?: string | null;\n repo_path?: string | null;\n installed_at: string;\n install_path: string;\n skills?: PluginBundledSkill[] | null;\n files?: string[] | null;\n}\n\n/** Coordinates for installing a plugin from a git source or local path. */\nexport interface InstallPluginRequest {\n source: string;\n ref?: string | null;\n repo_path?: string | null;\n force?: boolean;\n}\n\n/**\n * The slice of the typescript-client `PluginsClient` this service drives. The\n * installed `@openhands/typescript-client` package does not yet export these\n * management methods (they ship in typescript-client PRs #222/#223); narrowing\n * to this local interface keeps `vitest` (types stripped) and `eslint` green\n * until the client is republished, at which point the cast below can be dropped.\n */\ninterface PluginsManagementClient {\n listInstalledPlugins(): Promise<{ plugins: InstalledPluginInfo[] }>;\n installPlugin(request: InstallPluginRequest): Promise<InstalledPluginInfo>;\n setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }>;\n uninstallPlugin(name: string): Promise<{ message: string }>;\n refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }>;\n}\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction getManagementClient(): PluginsManagementClient {\n return new PluginsClient(\n getAgentServerClientOptions(),\n ) as unknown as PluginsManagementClient;\n}\n\n/**\n * Front-end management layer for installed plugins: list / install / enable /\n * disable / uninstall / refresh. Kept separate from the read-only catalog\n * service (`plugins-service.ts`), exactly as skills separate the marketplace\n * catalog from install actions.\n *\n * Local backend only for now (per Appendix C Q5): installed plugins live on the\n * local agent-server's `~/.openhands/plugins/installed/`. A cloud backend has no\n * per-user installed store yet, so reads return an empty list and mutating\n * actions throw (the UI also disables them on cloud).\n */\nclass PluginsManagementService {\n static async listInstalledPlugins(): Promise<InstalledPluginInfo[]> {\n if (isCloudBackend()) {\n return [];\n }\n\n try {\n const response = await getManagementClient().listInstalledPlugins();\n return response.plugins ?? [];\n } catch {\n // Agent-server may predate the plugins router or be unreachable; surface\n // an empty list rather than throwing (mirrors the catalog service).\n return [];\n }\n }\n\n static async installPlugin(\n request: InstallPluginRequest,\n ): Promise<InstalledPluginInfo> {\n if (isCloudBackend()) {\n throw new Error(\n \"Installing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().installPlugin(request);\n }\n\n static async setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Enabling and disabling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().setPluginEnabled(name, enabled);\n }\n\n static async uninstallPlugin(name: string): Promise<{ message: string }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Uninstalling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().uninstallPlugin(name);\n }\n\n static async refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Refreshing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().refreshPlugin(name);\n }\n}\n\nexport default PluginsManagementService;\n"],"mappings":"2TAsDA,SAAS,GAA0B,CACjC,OAAO,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAG7C,SAAS,GAA+C,CACtD,OAAO,IAAI,EAAA,cACT,EAAA,6BAA6B,CAC9B,CAcH,IAAM,EAAN,KAA+B,CAC7B,aAAa,sBAAuD,CAClE,GAAI,GAAgB,CAClB,MAAO,EAAE,CAGX,GAAI,CAEF,OAAO,MADgB,GAAqB,CAAC,sBAAsB,EACnD,SAAW,EAAE,MACvB,CAGN,MAAO,EAAE,EAIb,aAAa,cACX,EAC8B,CAC9B,GAAI,GAAgB,CAClB,MAAU,MACR,2DACD,CAEH,OAAO,GAAqB,CAAC,cAAc,EAAQ,CAGrD,aAAa,iBACX,EACA,EAC6C,CAC7C,GAAI,GAAgB,CAClB,MAAU,MACR,uEACD,CAEH,OAAO,GAAqB,CAAC,iBAAiB,EAAM,EAAQ,CAG9D,aAAa,gBAAgB,EAA4C,CACvE,GAAI,GAAgB,CAClB,MAAU,MACR,6DACD,CAEH,OAAO,GAAqB,CAAC,gBAAgB,EAAK,CAGpD,aAAa,cACX,EAC2D,CAC3D,GAAI,GAAgB,CAClB,MAAU,MACR,2DACD,CAEH,OAAO,GAAqB,CAAC,cAAc,EAAK"}
@@ -1,7 +1,10 @@
1
+ import type { PluginBundledSkill } from "./plugins-service";
1
2
  /**
2
3
  * An installed plugin, as returned by the agent-server management router
3
4
  * (`GET /api/plugins/installed`). Matches the typescript-client
4
- * `InstalledPluginInfo`.
5
+ * `InstalledPluginInfo`. The contents fields (`skills`, `files`, relative to
6
+ * `install_path`) are absent on older agent-servers and null when the
7
+ * installed plugin directory failed to load.
5
8
  */
6
9
  export interface InstalledPluginInfo {
7
10
  name: string;
@@ -13,6 +16,8 @@ export interface InstalledPluginInfo {
13
16
  repo_path?: string | null;
14
17
  installed_at: string;
15
18
  install_path: string;
19
+ skills?: PluginBundledSkill[] | null;
20
+ files?: string[] | null;
16
21
  }
17
22
  /** Coordinates for installing a plugin from a git source or local path. */
18
23
  export interface InstallPluginRequest {
@@ -1 +1 @@
1
- {"version":3,"file":"plugins-management-service.js","names":[],"sources":["../../src/api/plugins-management-service.ts"],"sourcesContent":["import { PluginsClient } from \"@openhands/typescript-client/clients\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\n\n/**\n * An installed plugin, as returned by the agent-server management router\n * (`GET /api/plugins/installed`). Matches the typescript-client\n * `InstalledPluginInfo`.\n */\nexport interface InstalledPluginInfo {\n name: string;\n version: string;\n description: string | null;\n enabled: boolean;\n source: string;\n resolved_ref?: string | null;\n repo_path?: string | null;\n installed_at: string;\n install_path: string;\n}\n\n/** Coordinates for installing a plugin from a git source or local path. */\nexport interface InstallPluginRequest {\n source: string;\n ref?: string | null;\n repo_path?: string | null;\n force?: boolean;\n}\n\n/**\n * The slice of the typescript-client `PluginsClient` this service drives. The\n * installed `@openhands/typescript-client` package does not yet export these\n * management methods (they ship in typescript-client PRs #222/#223); narrowing\n * to this local interface keeps `vitest` (types stripped) and `eslint` green\n * until the client is republished, at which point the cast below can be dropped.\n */\ninterface PluginsManagementClient {\n listInstalledPlugins(): Promise<{ plugins: InstalledPluginInfo[] }>;\n installPlugin(request: InstallPluginRequest): Promise<InstalledPluginInfo>;\n setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }>;\n uninstallPlugin(name: string): Promise<{ message: string }>;\n refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }>;\n}\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction getManagementClient(): PluginsManagementClient {\n return new PluginsClient(\n getAgentServerClientOptions(),\n ) as unknown as PluginsManagementClient;\n}\n\n/**\n * Front-end management layer for installed plugins: list / install / enable /\n * disable / uninstall / refresh. Kept separate from the read-only catalog\n * service (`plugins-service.ts`), exactly as skills separate the marketplace\n * catalog from install actions.\n *\n * Local backend only for now (per Appendix C Q5): installed plugins live on the\n * local agent-server's `~/.openhands/plugins/installed/`. A cloud backend has no\n * per-user installed store yet, so reads return an empty list and mutating\n * actions throw (the UI also disables them on cloud).\n */\nclass PluginsManagementService {\n static async listInstalledPlugins(): Promise<InstalledPluginInfo[]> {\n if (isCloudBackend()) {\n return [];\n }\n\n try {\n const response = await getManagementClient().listInstalledPlugins();\n return response.plugins ?? [];\n } catch {\n // Agent-server may predate the plugins router or be unreachable; surface\n // an empty list rather than throwing (mirrors the catalog service).\n return [];\n }\n }\n\n static async installPlugin(\n request: InstallPluginRequest,\n ): Promise<InstalledPluginInfo> {\n if (isCloudBackend()) {\n throw new Error(\n \"Installing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().installPlugin(request);\n }\n\n static async setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Enabling and disabling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().setPluginEnabled(name, enabled);\n }\n\n static async uninstallPlugin(name: string): Promise<{ message: string }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Uninstalling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().uninstallPlugin(name);\n }\n\n static async refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Refreshing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().refreshPlugin(name);\n }\n}\n\nexport default PluginsManagementService;\n"],"mappings":";;;;;AAiDA,SAAS,IAA0B;AACjC,QAAO,GAAkB,CAAC,QAAQ,SAAS;;AAG7C,SAAS,IAA+C;AACtD,QAAO,IAAI,EACT,GAA6B,CAC9B;;AAcH,IAAM,IAAN,MAA+B;CAC7B,aAAa,uBAAuD;AAClE,MAAI,GAAgB,CAClB,QAAO,EAAE;AAGX,MAAI;AAEF,WAAO,MADgB,GAAqB,CAAC,sBAAsB,EACnD,WAAW,EAAE;UACvB;AAGN,UAAO,EAAE;;;CAIb,aAAa,cACX,GAC8B;AAC9B,MAAI,GAAgB,CAClB,OAAU,MACR,2DACD;AAEH,SAAO,GAAqB,CAAC,cAAc,EAAQ;;CAGrD,aAAa,iBACX,GACA,GAC6C;AAC7C,MAAI,GAAgB,CAClB,OAAU,MACR,uEACD;AAEH,SAAO,GAAqB,CAAC,iBAAiB,GAAM,EAAQ;;CAG9D,aAAa,gBAAgB,GAA4C;AACvE,MAAI,GAAgB,CAClB,OAAU,MACR,6DACD;AAEH,SAAO,GAAqB,CAAC,gBAAgB,EAAK;;CAGpD,aAAa,cACX,GAC2D;AAC3D,MAAI,GAAgB,CAClB,OAAU,MACR,2DACD;AAEH,SAAO,GAAqB,CAAC,cAAc,EAAK"}
1
+ {"version":3,"file":"plugins-management-service.js","names":[],"sources":["../../src/api/plugins-management-service.ts"],"sourcesContent":["import { PluginsClient } from \"@openhands/typescript-client/clients\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport type { PluginBundledSkill } from \"./plugins-service\";\n\n/**\n * An installed plugin, as returned by the agent-server management router\n * (`GET /api/plugins/installed`). Matches the typescript-client\n * `InstalledPluginInfo`. The contents fields (`skills`, `files`, relative to\n * `install_path`) are absent on older agent-servers and null when the\n * installed plugin directory failed to load.\n */\nexport interface InstalledPluginInfo {\n name: string;\n version: string;\n description: string | null;\n enabled: boolean;\n source: string;\n resolved_ref?: string | null;\n repo_path?: string | null;\n installed_at: string;\n install_path: string;\n skills?: PluginBundledSkill[] | null;\n files?: string[] | null;\n}\n\n/** Coordinates for installing a plugin from a git source or local path. */\nexport interface InstallPluginRequest {\n source: string;\n ref?: string | null;\n repo_path?: string | null;\n force?: boolean;\n}\n\n/**\n * The slice of the typescript-client `PluginsClient` this service drives. The\n * installed `@openhands/typescript-client` package does not yet export these\n * management methods (they ship in typescript-client PRs #222/#223); narrowing\n * to this local interface keeps `vitest` (types stripped) and `eslint` green\n * until the client is republished, at which point the cast below can be dropped.\n */\ninterface PluginsManagementClient {\n listInstalledPlugins(): Promise<{ plugins: InstalledPluginInfo[] }>;\n installPlugin(request: InstallPluginRequest): Promise<InstalledPluginInfo>;\n setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }>;\n uninstallPlugin(name: string): Promise<{ message: string }>;\n refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }>;\n}\n\nfunction isCloudBackend(): boolean {\n return getActiveBackend().backend.kind === \"cloud\";\n}\n\nfunction getManagementClient(): PluginsManagementClient {\n return new PluginsClient(\n getAgentServerClientOptions(),\n ) as unknown as PluginsManagementClient;\n}\n\n/**\n * Front-end management layer for installed plugins: list / install / enable /\n * disable / uninstall / refresh. Kept separate from the read-only catalog\n * service (`plugins-service.ts`), exactly as skills separate the marketplace\n * catalog from install actions.\n *\n * Local backend only for now (per Appendix C Q5): installed plugins live on the\n * local agent-server's `~/.openhands/plugins/installed/`. A cloud backend has no\n * per-user installed store yet, so reads return an empty list and mutating\n * actions throw (the UI also disables them on cloud).\n */\nclass PluginsManagementService {\n static async listInstalledPlugins(): Promise<InstalledPluginInfo[]> {\n if (isCloudBackend()) {\n return [];\n }\n\n try {\n const response = await getManagementClient().listInstalledPlugins();\n return response.plugins ?? [];\n } catch {\n // Agent-server may predate the plugins router or be unreachable; surface\n // an empty list rather than throwing (mirrors the catalog service).\n return [];\n }\n }\n\n static async installPlugin(\n request: InstallPluginRequest,\n ): Promise<InstalledPluginInfo> {\n if (isCloudBackend()) {\n throw new Error(\n \"Installing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().installPlugin(request);\n }\n\n static async setPluginEnabled(\n name: string,\n enabled: boolean,\n ): Promise<{ name: string; enabled: boolean }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Enabling and disabling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().setPluginEnabled(name, enabled);\n }\n\n static async uninstallPlugin(name: string): Promise<{ message: string }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Uninstalling plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().uninstallPlugin(name);\n }\n\n static async refreshPlugin(\n name: string,\n ): Promise<{ message: string; plugin: InstalledPluginInfo }> {\n if (isCloudBackend()) {\n throw new Error(\n \"Refreshing plugins is only available on a local backend.\",\n );\n }\n return getManagementClient().refreshPlugin(name);\n }\n}\n\nexport default PluginsManagementService;\n"],"mappings":";;;;;AAsDA,SAAS,IAA0B;AACjC,QAAO,GAAkB,CAAC,QAAQ,SAAS;;AAG7C,SAAS,IAA+C;AACtD,QAAO,IAAI,EACT,GAA6B,CAC9B;;AAcH,IAAM,IAAN,MAA+B;CAC7B,aAAa,uBAAuD;AAClE,MAAI,GAAgB,CAClB,QAAO,EAAE;AAGX,MAAI;AAEF,WAAO,MADgB,GAAqB,CAAC,sBAAsB,EACnD,WAAW,EAAE;UACvB;AAGN,UAAO,EAAE;;;CAIb,aAAa,cACX,GAC8B;AAC9B,MAAI,GAAgB,CAClB,OAAU,MACR,2DACD;AAEH,SAAO,GAAqB,CAAC,cAAc,EAAQ;;CAGrD,aAAa,iBACX,GACA,GAC6C;AAC7C,MAAI,GAAgB,CAClB,OAAU,MACR,uEACD;AAEH,SAAO,GAAqB,CAAC,iBAAiB,GAAM,EAAQ;;CAG9D,aAAa,gBAAgB,GAA4C;AACvE,MAAI,GAAgB,CAClB,OAAU,MACR,6DACD;AAEH,SAAO,GAAqB,CAAC,gBAAgB,EAAK;;CAGpD,aAAa,cACX,GAC2D;AAC3D,MAAI,GAAgB,CAClB,OAAU,MACR,2DACD;AAEH,SAAO,GAAqB,CAAC,cAAc,EAAK"}
@@ -1,7 +1,14 @@
1
+ /** Summary of a skill bundled in a plugin (agent-server `PluginSkillSummary`). */
2
+ export interface PluginBundledSkill {
3
+ name: string;
4
+ description?: string | null;
5
+ }
1
6
  /**
2
7
  * A plugin in the dynamic marketplace catalog, with attachable coordinates and
3
8
  * install state. Matches the agent-server `MarketplacePluginInfo` / the
4
- * typescript-client `MarketplacePlugin`.
9
+ * typescript-client `MarketplacePlugin`. The contents fields (`path`, `skills`,
10
+ * `files`) are populated when the entry resolves to a directory in the
11
+ * server's local marketplace clone, and are absent on older agent-servers.
5
12
  */
6
13
  export interface MarketplacePlugin {
7
14
  name: string;
@@ -10,18 +17,30 @@ export interface MarketplacePlugin {
10
17
  ref?: string | null;
11
18
  repo_path?: string | null;
12
19
  installed: boolean;
20
+ path?: string | null;
21
+ skills?: PluginBundledSkill[] | null;
22
+ files?: string[] | null;
13
23
  }
14
24
  /**
15
25
  * A locally-discovered ("ambient") plugin reported by the agent-server — one
16
26
  * found in the user's local plugin directories (e.g. `~/.agents/plugins`).
17
27
  * These auto-load into conversations and are not managed via install/uninstall,
18
28
  * so the Plugins page renders them as a read-only "Local" group. Matches the
19
- * typescript-client `PluginInfo`.
29
+ * typescript-client `PluginInfo`; the contents fields are absent on older
30
+ * agent-servers.
20
31
  */
21
32
  export interface LocalPlugin {
22
33
  name: string;
23
34
  version: string;
24
35
  description: string;
36
+ path?: string;
37
+ skills?: PluginBundledSkill[];
38
+ files?: string[];
39
+ }
40
+ /** Content of a single plugin file fetched for the detail-modal viewer. */
41
+ export interface PluginFileContent {
42
+ kind: "text" | "binary";
43
+ text: string | null;
25
44
  }
26
45
  declare class PluginsService {
27
46
  /**
@@ -45,5 +64,14 @@ declare class PluginsService {
45
64
  * catalog) rather than throwing.
46
65
  */
47
66
  static getLocalPlugins(): Promise<LocalPlugin[]>;
67
+ /**
68
+ * Fetch one plugin file's content for the detail-modal viewer. `basePath` is
69
+ * the plugin directory reported by the agent-server (`path`/`install_path`)
70
+ * and `relativePath` a POSIX path from the plugin's `files` listing.
71
+ *
72
+ * Local backend only — plugin files live on the local agent-server's disk.
73
+ * Errors propagate so the caller can render a load-error state.
74
+ */
75
+ static getPluginFileContent(basePath: string, relativePath: string): Promise<PluginFileContent>;
48
76
  }
49
77
  export default PluginsService;
@@ -1,2 +1,2 @@
1
- require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs`);require(`../node_modules/@openhands/typescript-client/dist/clients.cjs`);const t=require(`./backend-registry/active-store.cjs`),n=require(`./agent-server-client-options.cjs`),r=require(`./agent-server-compatibility.cjs`),i=require(`./cloud/secrets-service.api.cjs`);async function a(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var o=class{static async getSecrets(){try{return t.getActiveBackend().backend.kind===`cloud`?await a(()=>i.fetchCloudSecrets()):(await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).listSecrets())).secrets.map(e=>({name:e.name,description:e.description}))}catch(e){return console.error(`Failed to fetch secrets after retries:`,e),[]}}static async createSecret(r,o,s){if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.createCloudSecret(r,o,s));return}await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).upsertSecret({name:r,value:o,description:s}))}static async updateSecret(e,n,r){if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.updateCloudSecret(e,n,r));return}await this.createSecret(e,n,r)}static async deleteSecret(o){try{if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.deleteCloudSecret(o));return}await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).deleteSecret(o))}catch(e){if(r.isSdkHttpStatusError(e,404)||e&&typeof e==`object`&&`response`in e&&e.response?.status===404)return;throw e}}};exports.SecretsService=o;
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs`);require(`../node_modules/@openhands/typescript-client/dist/clients.cjs`);const t=require(`./backend-registry/active-store.cjs`),n=require(`./agent-server-client-options.cjs`),r=require(`./agent-server-compatibility.cjs`),i=require(`./cloud/secrets-service.api.cjs`);async function a(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var o=class{static async getSecrets(){try{return t.getActiveBackend().backend.kind===`cloud`?await a(()=>i.fetchCloudSecrets()):(await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).listSecrets())).secrets.map(e=>({name:e.name,description:e.description}))}catch(e){return console.error(`Failed to fetch secrets after retries:`,e),[]}}static async createSecret(r,o,s){if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.createCloudSecret(r,o,s));return}await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).upsertSecret({name:r,value:o,description:s}))}static async updateSecret(r,o,s){if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.updateCloudSecret(r,o,s));return}let c=new e.SettingsClient(n.getAgentServerClientOptions()),l=await a(()=>c.getSecret(r));await a(()=>c.upsertSecret({name:o,value:l,description:s})),o!==r&&await this.deleteSecret(r)}static async deleteSecret(o){try{if(t.getActiveBackend().backend.kind===`cloud`){await a(()=>i.deleteCloudSecret(o));return}await a(()=>new e.SettingsClient(n.getAgentServerClientOptions()).deleteSecret(o))}catch(e){if(r.isSdkHttpStatusError(e,404)||e&&typeof e==`object`&&`response`in e&&e.response?.status===404)return;throw e}}};exports.SecretsService=o;
2
2
  //# sourceMappingURL=secrets-service.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"secrets-service.cjs","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n createCloudSecret,\n deleteCloudSecret,\n fetchCloudSecrets,\n updateCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\n\n/**\n * Retry helper for API calls with exponential backoff.\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelayMs: number = 500,\n): Promise<T> {\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= maxRetries - 1) {\n throw error;\n }\n\n const delay = baseDelayMs * 2 ** attempt;\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delay);\n });\n }\n }\n\n throw new Error(\"Retry attempts exhausted\");\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => createCloudSecret(name, value, description));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's value and/or description.\n * Uses the same upsert endpoint as createSecret since agent-server\n * doesn't have a separate update endpoint.\n *\n * @param name - Secret name (used as identifier)\n * @param value - New secret value\n * @param description - Optional new description\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n // The cloud PUT endpoint renames + redescribes only (no value field),\n // matching what `useUpdateSecret` actually sends:\n // (secretToEdit=name, newName=value, description).\n await withRetry(() => updateCloudSecret(name, value, description));\n return;\n }\n // Agent-server uses upsert, so update is the same as create\n await this.createSecret(name, value, description);\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":"uZAeA,eAAe,EACb,EACA,EAAqB,EACrB,EAAsB,IACV,CACZ,IAAK,IAAI,EAAU,EAAG,EAAU,EAAY,GAAW,EACrD,GAAI,CACF,OAAO,MAAM,GAAI,OACV,EAAO,CACd,GAAI,GAAW,EAAa,EAC1B,MAAM,EAGR,IAAM,EAAQ,EAAc,GAAK,EAEjC,MAAM,IAAI,QAAe,GAAY,CACnC,WAAW,EAAS,EAAM,EAC1B,CAIN,MAAU,MAAM,2BAA2B,CAG7C,IAAa,EAAb,KAA4B,CAQ1B,aAAa,YAAkD,CAC7D,GAAI,CAOF,OANI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAC/B,MAAM,MAAgB,EAAA,mBAAmB,CAAC,EAK5C,MAHgB,MACrB,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,CAChE,EACe,QAAQ,IAAK,IAAO,CAClC,KAAM,EAAE,KACR,YAAa,EAAE,YAChB,EAAE,OACI,EAAO,CAEd,OADA,QAAQ,MAAM,yCAA0C,EAAM,CACvD,EAAE,EAab,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAC/C,MAAM,MAAgB,EAAA,kBAAkB,EAAM,EAAO,EAAY,CAAC,CAClE,OAEF,MAAM,MACJ,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,CAC7D,OACA,QACA,cACD,CAAC,CACH,CAaH,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAI/C,MAAM,MAAgB,EAAA,kBAAkB,EAAM,EAAO,EAAY,CAAC,CAClE,OAGF,MAAM,KAAK,aAAa,EAAM,EAAO,EAAY,CAUnD,aAAa,aAAa,EAA6B,CACrD,GAAI,CACF,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAC/C,MAAM,MAAgB,EAAA,kBAAkB,EAAK,CAAC,CAC9C,OAEF,MAAM,MACJ,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,EAAK,CACrE,OACM,EAAO,CAId,GACE,EAAA,qBAAqB,EAAO,IAAI,EAC/B,GACC,OAAO,GAAU,UACjB,aAAc,GACb,EAA6C,UAAU,SACtD,IAEJ,OAEF,MAAM"}
1
+ {"version":3,"file":"secrets-service.cjs","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n createCloudSecret,\n deleteCloudSecret,\n fetchCloudSecrets,\n updateCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\n\n/**\n * Retry helper for API calls with exponential backoff.\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelayMs: number = 500,\n): Promise<T> {\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= maxRetries - 1) {\n throw error;\n }\n\n const delay = baseDelayMs * 2 ** attempt;\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delay);\n });\n }\n }\n\n throw new Error(\"Retry attempts exhausted\");\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => createCloudSecret(name, value, description));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description while preserving its value.\n * The agent-server only exposes an upsert endpoint, so we fetch the\n * existing value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => updateCloudSecret(secretToEdit, name, description));\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const value = await withRetry(() => client.getSecret(secretToEdit));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":"uZAeA,eAAe,EACb,EACA,EAAqB,EACrB,EAAsB,IACV,CACZ,IAAK,IAAI,EAAU,EAAG,EAAU,EAAY,GAAW,EACrD,GAAI,CACF,OAAO,MAAM,GAAI,OACV,EAAO,CACd,GAAI,GAAW,EAAa,EAC1B,MAAM,EAGR,IAAM,EAAQ,EAAc,GAAK,EAEjC,MAAM,IAAI,QAAe,GAAY,CACnC,WAAW,EAAS,EAAM,EAC1B,CAIN,MAAU,MAAM,2BAA2B,CAG7C,IAAa,EAAb,KAA4B,CAQ1B,aAAa,YAAkD,CAC7D,GAAI,CAOF,OANI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAC/B,MAAM,MAAgB,EAAA,mBAAmB,CAAC,EAK5C,MAHgB,MACrB,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,CAChE,EACe,QAAQ,IAAK,IAAO,CAClC,KAAM,EAAE,KACR,YAAa,EAAE,YAChB,EAAE,OACI,EAAO,CAEd,OADA,QAAQ,MAAM,yCAA0C,EAAM,CACvD,EAAE,EAab,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAC/C,MAAM,MAAgB,EAAA,kBAAkB,EAAM,EAAO,EAAY,CAAC,CAClE,OAEF,MAAM,MACJ,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,CAC7D,OACA,QACA,cACD,CAAC,CACH,CAaH,aAAa,aACX,EACA,EACA,EACe,CACf,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAC/C,MAAM,MAAgB,EAAA,kBAAkB,EAAc,EAAM,EAAY,CAAC,CACzE,OAGF,IAAM,EAAS,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAC1D,EAAQ,MAAM,MAAgB,EAAO,UAAU,EAAa,CAAC,CAEnE,MAAM,MACJ,EAAO,aAAa,CAClB,OACA,QACA,cACD,CAAC,CACH,CAEG,IAAS,GACX,MAAM,KAAK,aAAa,EAAa,CAWzC,aAAa,aAAa,EAA6B,CACrD,GAAI,CACF,GAAI,EAAA,kBAAkB,CAAC,QAAQ,OAAS,QAAS,CAC/C,MAAM,MAAgB,EAAA,kBAAkB,EAAK,CAAC,CAC9C,OAEF,MAAM,MACJ,IAAI,EAAA,eAAe,EAAA,6BAA6B,CAAC,CAAC,aAAa,EAAK,CACrE,OACM,EAAO,CAId,GACE,EAAA,qBAAqB,EAAO,IAAI,EAC/B,GACC,OAAO,GAAU,UACjB,aAAc,GACb,EAA6C,UAAU,SACtD,IAEJ,OAEF,MAAM"}
@@ -19,16 +19,16 @@ export declare class SecretsService {
19
19
  */
20
20
  static createSecret(name: string, value: string, description?: string): Promise<void>;
21
21
  /**
22
- * Update a secret's value and/or description.
23
- * Uses the same upsert endpoint as createSecret since agent-server
24
- * doesn't have a separate update endpoint.
22
+ * Update a secret's name and/or description while preserving its value.
23
+ * The agent-server only exposes an upsert endpoint, so we fetch the
24
+ * existing value and re-upsert it under the updated name/description.
25
25
  *
26
- * @param name - Secret name (used as identifier)
27
- * @param value - New secret value
26
+ * @param secretToEdit - Existing secret name
27
+ * @param name - New (or same) secret name
28
28
  * @param description - Optional new description
29
29
  * @throws Error if the API call fails after retries
30
30
  */
31
- static updateSecret(name: string, value: string, description?: string): Promise<void>;
31
+ static updateSecret(secretToEdit: string, name: string, description?: string): Promise<void>;
32
32
  /**
33
33
  * Delete a custom secret by name.
34
34
  * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}
@@ -39,12 +39,17 @@ var l = class {
39
39
  description: o
40
40
  }));
41
41
  }
42
- static async updateSecret(e, n, r) {
42
+ static async updateSecret(r, i, a) {
43
43
  if (t().backend.kind === "cloud") {
44
- await c(() => s(e, n, r));
44
+ await c(() => s(r, i, a));
45
45
  return;
46
46
  }
47
- await this.createSecret(e, n, r);
47
+ let o = new e(n()), l = await c(() => o.getSecret(r));
48
+ await c(() => o.upsertSecret({
49
+ name: i,
50
+ value: l,
51
+ description: a
52
+ })), i !== r && await this.deleteSecret(r);
48
53
  }
49
54
  static async deleteSecret(i) {
50
55
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"secrets-service.js","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n createCloudSecret,\n deleteCloudSecret,\n fetchCloudSecrets,\n updateCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\n\n/**\n * Retry helper for API calls with exponential backoff.\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelayMs: number = 500,\n): Promise<T> {\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= maxRetries - 1) {\n throw error;\n }\n\n const delay = baseDelayMs * 2 ** attempt;\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delay);\n });\n }\n }\n\n throw new Error(\"Retry attempts exhausted\");\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => createCloudSecret(name, value, description));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's value and/or description.\n * Uses the same upsert endpoint as createSecret since agent-server\n * doesn't have a separate update endpoint.\n *\n * @param name - Secret name (used as identifier)\n * @param value - New secret value\n * @param description - Optional new description\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n // The cloud PUT endpoint renames + redescribes only (no value field),\n // matching what `useUpdateSecret` actually sends:\n // (secretToEdit=name, newName=value, description).\n await withRetry(() => updateCloudSecret(name, value, description));\n return;\n }\n // Agent-server uses upsert, so update is the same as create\n await this.createSecret(name, value, description);\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":";;;;;;;AAeA,eAAe,EACb,GACA,IAAqB,GACrB,IAAsB,KACV;AACZ,MAAK,IAAI,IAAU,GAAG,IAAU,GAAY,KAAW,EACrD,KAAI;AACF,SAAO,MAAM,GAAI;UACV,GAAO;AACd,MAAI,KAAW,IAAa,EAC1B,OAAM;EAGR,IAAM,IAAQ,IAAc,KAAK;AAEjC,QAAM,IAAI,SAAe,MAAY;AACnC,cAAW,GAAS,EAAM;IAC1B;;AAIN,OAAU,MAAM,2BAA2B;;AAG7C,IAAa,IAAb,MAA4B;CAQ1B,aAAa,aAAkD;AAC7D,MAAI;AAOF,UANI,GAAkB,CAAC,QAAQ,SAAS,UAC/B,MAAM,QAAgB,GAAmB,CAAC,IAK5C,MAHgB,QACrB,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa,CAChE,EACe,QAAQ,KAAK,OAAO;IAClC,MAAM,EAAE;IACR,aAAa,EAAE;IAChB,EAAE;WACI,GAAO;AAEd,UADA,QAAQ,MAAM,0CAA0C,EAAM,EACvD,EAAE;;;CAab,aAAa,aACX,GACA,GACA,GACe;AACf,MAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAC/C,SAAM,QAAgB,EAAkB,GAAM,GAAO,EAAY,CAAC;AAClE;;AAEF,QAAM,QACJ,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa;GAC7D;GACA;GACA;GACD,CAAC,CACH;;CAaH,aAAa,aACX,GACA,GACA,GACe;AACf,MAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAI/C,SAAM,QAAgB,EAAkB,GAAM,GAAO,EAAY,CAAC;AAClE;;AAGF,QAAM,KAAK,aAAa,GAAM,GAAO,EAAY;;CAUnD,aAAa,aAAa,GAA6B;AACrD,MAAI;AACF,OAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAC/C,UAAM,QAAgB,EAAkB,EAAK,CAAC;AAC9C;;AAEF,SAAM,QACJ,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa,EAAK,CACrE;WACM,GAAO;AAId,OACE,EAAqB,GAAO,IAAI,IAC/B,KACC,OAAO,KAAU,YACjB,cAAc,KACb,EAA6C,UAAU,WACtD,IAEJ;AAEF,SAAM"}
1
+ {"version":3,"file":"secrets-service.js","names":[],"sources":["../../src/api/secrets-service.ts"],"sourcesContent":["import { SettingsClient } from \"@openhands/typescript-client/clients\";\nimport { isSdkHttpStatusError } from \"./agent-server-compatibility\";\nimport { getActiveBackend } from \"./backend-registry/active-store\";\nimport {\n createCloudSecret,\n deleteCloudSecret,\n fetchCloudSecrets,\n updateCloudSecret,\n} from \"./cloud/secrets-service.api\";\nimport { getAgentServerClientOptions } from \"./agent-server-client-options\";\nimport { CustomSecretWithoutValue } from \"./secrets-service.types\";\n\n/**\n * Retry helper for API calls with exponential backoff.\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelayMs: number = 500,\n): Promise<T> {\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= maxRetries - 1) {\n throw error;\n }\n\n const delay = baseDelayMs * 2 ** attempt;\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delay);\n });\n }\n }\n\n throw new Error(\"Retry attempts exhausted\");\n}\n\nexport class SecretsService {\n /**\n * List all custom secrets (names and descriptions only, no values).\n * Uses the agent-server API endpoint: GET /api/settings/secrets\n *\n * Note: The agent-server API doesn't support pagination or search filtering.\n * All secrets are returned in a single response.\n */\n static async getSecrets(): Promise<CustomSecretWithoutValue[]> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n return await withRetry(() => fetchCloudSecrets());\n }\n const response = await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).listSecrets(),\n );\n return response.secrets.map((s) => ({\n name: s.name,\n description: s.description,\n }));\n } catch (error) {\n console.error(\"Failed to fetch secrets after retries:\", error);\n return [];\n }\n }\n\n /**\n * Create or update a custom secret (upsert by name).\n * Uses the agent-server API endpoint: PUT /api/settings/secrets\n *\n * @param name - Secret name (must start with letter, contain only letters/numbers/underscores, 1-64 chars)\n * @param value - Secret value\n * @param description - Optional description\n * @throws Error if the API call fails after retries\n */\n static async createSecret(\n name: string,\n value: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => createCloudSecret(name, value, description));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).upsertSecret({\n name,\n value,\n description,\n }),\n );\n }\n\n /**\n * Update a secret's name and/or description while preserving its value.\n * The agent-server only exposes an upsert endpoint, so we fetch the\n * existing value and re-upsert it under the updated name/description.\n *\n * @param secretToEdit - Existing secret name\n * @param name - New (or same) secret name\n * @param description - Optional new description\n * @throws Error if the API call fails after retries\n */\n static async updateSecret(\n secretToEdit: string,\n name: string,\n description?: string,\n ): Promise<void> {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => updateCloudSecret(secretToEdit, name, description));\n return;\n }\n\n const client = new SettingsClient(getAgentServerClientOptions());\n const value = await withRetry(() => client.getSecret(secretToEdit));\n\n await withRetry(() =>\n client.upsertSecret({\n name,\n value,\n description,\n }),\n );\n\n if (name !== secretToEdit) {\n await this.deleteSecret(secretToEdit);\n }\n }\n\n /**\n * Delete a custom secret by name.\n * Uses the agent-server API endpoint: DELETE /api/settings/secrets/{name}\n *\n * @param name - Secret name to delete\n * @throws Error if the API call fails (except 404, which is treated as success)\n */\n static async deleteSecret(name: string): Promise<void> {\n try {\n if (getActiveBackend().backend.kind === \"cloud\") {\n await withRetry(() => deleteCloudSecret(name));\n return;\n }\n await withRetry(() =>\n new SettingsClient(getAgentServerClientOptions()).deleteSecret(name),\n );\n } catch (error) {\n // 404 means secret doesn't exist - treat as successful deletion.\n // Both the SDK's HttpError (status on the error itself) and\n // axios-style errors (status under `response`) count.\n if (\n isSdkHttpStatusError(error, 404) ||\n (error &&\n typeof error === \"object\" &&\n \"response\" in error &&\n (error as { response?: { status?: number } }).response?.status ===\n 404)\n ) {\n return;\n }\n throw error;\n }\n }\n}\n"],"mappings":";;;;;;;AAeA,eAAe,EACb,GACA,IAAqB,GACrB,IAAsB,KACV;AACZ,MAAK,IAAI,IAAU,GAAG,IAAU,GAAY,KAAW,EACrD,KAAI;AACF,SAAO,MAAM,GAAI;UACV,GAAO;AACd,MAAI,KAAW,IAAa,EAC1B,OAAM;EAGR,IAAM,IAAQ,IAAc,KAAK;AAEjC,QAAM,IAAI,SAAe,MAAY;AACnC,cAAW,GAAS,EAAM;IAC1B;;AAIN,OAAU,MAAM,2BAA2B;;AAG7C,IAAa,IAAb,MAA4B;CAQ1B,aAAa,aAAkD;AAC7D,MAAI;AAOF,UANI,GAAkB,CAAC,QAAQ,SAAS,UAC/B,MAAM,QAAgB,GAAmB,CAAC,IAK5C,MAHgB,QACrB,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa,CAChE,EACe,QAAQ,KAAK,OAAO;IAClC,MAAM,EAAE;IACR,aAAa,EAAE;IAChB,EAAE;WACI,GAAO;AAEd,UADA,QAAQ,MAAM,0CAA0C,EAAM,EACvD,EAAE;;;CAab,aAAa,aACX,GACA,GACA,GACe;AACf,MAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAC/C,SAAM,QAAgB,EAAkB,GAAM,GAAO,EAAY,CAAC;AAClE;;AAEF,QAAM,QACJ,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa;GAC7D;GACA;GACA;GACD,CAAC,CACH;;CAaH,aAAa,aACX,GACA,GACA,GACe;AACf,MAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAC/C,SAAM,QAAgB,EAAkB,GAAc,GAAM,EAAY,CAAC;AACzE;;EAGF,IAAM,IAAS,IAAI,EAAe,GAA6B,CAAC,EAC1D,IAAQ,MAAM,QAAgB,EAAO,UAAU,EAAa,CAAC;AAUnE,EARA,MAAM,QACJ,EAAO,aAAa;GAClB;GACA;GACA;GACD,CAAC,CACH,EAEG,MAAS,KACX,MAAM,KAAK,aAAa,EAAa;;CAWzC,aAAa,aAAa,GAA6B;AACrD,MAAI;AACF,OAAI,GAAkB,CAAC,QAAQ,SAAS,SAAS;AAC/C,UAAM,QAAgB,EAAkB,EAAK,CAAC;AAC9C;;AAEF,SAAM,QACJ,IAAI,EAAe,GAA6B,CAAC,CAAC,aAAa,EAAK,CACrE;WACM,GAAO;AAId,OACE,EAAqB,GAAO,IAAI,IAC/B,KACC,OAAO,KAAU,YACjB,cAAc,KACb,EAA6C,UAAU,WACtD,IAEJ;AAEF,SAAM"}
@@ -1,2 +1,2 @@
1
- require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs`);require(`../../node_modules/@openhands/typescript-client/dist/clients.cjs`);const t=require(`../backend-registry/active-store.cjs`),n=require(`../agent-server-client-options.cjs`),r=require(`../../services/settings.cjs`),i=require(`../../utils/mcp-config.cjs`),a=require(`../cloud/settings-service.api.cjs`);var o=[`language`,`user_consents_to_analytics`,`enable_sound_notifications`,`git_user_name`,`git_user_email`,`disabled_skills`],s=new Set(o),c=e=>s.has(e),l=e=>{let t={},n={};for(let[r,i]of Object.entries(e))c(r)?t[r]=i:n[r]=i;return{extracted:t,rest:n}},u=e=>JSON.parse(JSON.stringify(e)),d=(e,t)=>({...e??{},...t??{}});async function f(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var p={redacted:null,encrypted:null,timestamp:0},m=300*1e3,h=()=>Date.now()-p.timestamp<m,g=()=>{p={redacted:null,encrypted:null,timestamp:0}},_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),v=(e,t)=>`Basic ${btoa(`${e}:${t}`)}`,y=e=>{switch(e.strategy){case`none`:return{};case`api_key`:{if(typeof e.value!=`string`||!e.value)return null;let t=typeof e.header_name==`string`&&e.header_name?e.header_name:`Authorization`,n=t===`Authorization`?`Bearer ${e.value}`:e.value;return{[t]:n}}case`bearer`:return typeof e.value!=`string`||!e.value?null:{Authorization:`Bearer ${e.value}`};case`basic`:return typeof e.username!=`string`||typeof e.password!=`string`?null:{Authorization:v(e.username,e.password)};case`header`:return i.stringRecord(e.headers)??{};case`oauth2`:{let t=_(e.state)?e.state.tokens:void 0;return!_(t)||typeof t.access_token!=`string`?null:{Authorization:`Bearer ${t.access_token}`}}default:return null}},b=e=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>{if(!_(t)||!_(t.auth))return[e,t];let n=y(t.auth);if(n===null)return[e,t];let r={...t},a={...i.stringRecord(t.headers)??{},...n};return delete r.auth,Object.keys(a).length>0?r.headers=a:delete r.headers,[e,r]}));return t?{...e,mcpServers:r}:r},x=e=>{let t=i.getSdkMcpServerMap(e);return t?Object.values(t).some(e=>i.hasRedactedMcpSecretLeaf(_(e)?e.auth:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.headers:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.env:void 0)):!1},S=(e,t)=>{let n=i.getSdkMcpServerMap(e),r=i.getSdkMcpServerMap(t);return!n||!r?!1:Object.keys(n).some(e=>!(e in r))},C=e=>{let t={agent_settings:e.agent_settings??{},conversation_settings:e.conversation_settings??{},llm_api_key_set:e.llm_api_key_is_set},n=e.misc_settings?.app_preferences;if(n)for(let e of o){let r=n[e];r!==void 0&&(t[e]=r)}return t},w=e=>{let t=d(r.DEFAULT_SETTINGS.agent_settings??{},e.agent_settings??{}),n=d(r.DEFAULT_SETTINGS.conversation_settings??{},e.conversation_settings??{}),i={...u(r.DEFAULT_SETTINGS),...e,provider_tokens_set:{...r.DEFAULT_SETTINGS.provider_tokens_set??{},...e.provider_tokens_set??{}},agent_settings:t,conversation_settings:n},a=t.llm,o=t.condenser;return typeof t.agent==`string`&&(i.agent=t.agent),typeof a?.model==`string`&&a.model.length>0&&(i.llm_model=a.model),typeof a?.base_url==`string`&&(i.llm_base_url=a.base_url),typeof o?.enabled==`boolean`&&(i.enable_default_condenser=o.enabled),typeof o?.max_size==`number`&&(i.condenser_max_size=o.max_size),typeof n.confirmation_mode==`boolean`&&(i.confirmation_mode=n.confirmation_mode),(typeof n.security_analyzer==`string`||n.security_analyzer===null)&&(i.security_analyzer=n.security_analyzer),typeof n.max_iterations==`number`&&(i.max_iterations=n.max_iterations),i.search_api_key_set=!!i.search_api_key,i},T=class r{static async fetchSettingsFromApi(t){return f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).getSettings({exposeSecrets:t}))}static async getSettings(){if(t.getActiveBackend().backend.kind===`cloud`)try{return w(await f(()=>a.fetchCloudSettings()))}catch(e){return console.warn(`Failed to fetch cloud settings, using defaults:`,e),w({})}if(h()&&p.redacted)return w(C(p.redacted));try{let e=await this.fetchSettingsFromApi();return p.redacted=e,p.timestamp=Date.now(),w(C(e))}catch(e){return console.warn(`Failed to fetch settings from API, using defaults:`,e),w({})}}static async getSettingsForConversation(){if(h()&&p.encrypted)return{agentSettings:p.encrypted.agent_settings,conversationSettings:p.encrypted.conversation_settings,secretsEncrypted:!0};let e=await this.fetchSettingsFromApi(`encrypted`);return p.encrypted=e,p.timestamp||=Date.now(),{agentSettings:e.agent_settings,conversationSettings:e.conversation_settings,secretsEncrypted:!0}}static async getSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getAgentSchema()}static async getConversationSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudConversationSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getConversationSchema()}static async saveSettings(i){let{extracted:o,rest:s}=l(i),c=Object.keys(o).length>0,u={},d=s.agent_settings_diff;d&&Object.keys(d).length>0&&(u.agent_settings_diff=d);let p=s.conversation_settings_diff;p&&Object.keys(p).length>0&&(u.conversation_settings_diff=p),c&&(u.misc_settings_diff={app_preferences:o});let m=t.getActiveBackend().backend.kind===`cloud`,h=u.agent_settings_diff,_=!!h&&`mcp_config`in h&&h.mcp_config!==null,v;if(_)try{v=m?(await a.fetchCloudSettings())?.agent_settings?.mcp_config:(await r.fetchSettingsFromApi())?.agent_settings?.mcp_config}catch{}let y=m&&_&&x(v)&&!S(v,h?.mcp_config),C=_&&!y;if(m){if(!(u.agent_settings_diff||u.conversation_settings_diff||c))return!0;C&&await f(()=>a.saveCloudSettings({agent_settings_diff:{mcp_config:null}}));let e={};u.agent_settings_diff&&(e.agent_settings_diff={...u.agent_settings_diff},`mcp_config`in e.agent_settings_diff&&(e.agent_settings_diff.mcp_config=b(e.agent_settings_diff.mcp_config))),u.conversation_settings_diff&&(e.conversation_settings_diff=u.conversation_settings_diff),c&&(e.app_preferences=o);try{await f(()=>a.saveCloudSettings(e))}catch(e){if(C&&v)try{await a.saveCloudSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw e}}else{if(!(u.agent_settings_diff||u.conversation_settings_diff||u.misc_settings_diff))return!0;C&&await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:null}}));try{await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings(u))}catch(t){if(C&&v)try{await new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw t}}return g(),!0}static invalidateCache(){g()}};exports.default=T;
1
+ require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../node_modules/@openhands/typescript-client/dist/client/settings-client.cjs`);require(`../../node_modules/@openhands/typescript-client/dist/clients.cjs`);const t=require(`../backend-registry/active-store.cjs`),n=require(`../agent-server-client-options.cjs`),r=require(`../../services/settings.cjs`),i=require(`../../utils/mcp-config.cjs`),a=require(`../cloud/settings-service.api.cjs`);var o=[`language`,`user_consents_to_analytics`,`enable_sound_notifications`,`git_user_name`,`git_user_email`,`title_llm_profile`,`disabled_skills`],s=new Set(o),c=e=>s.has(e),l=e=>{let t={},n={};for(let[r,i]of Object.entries(e))c(r)?t[r]=i:n[r]=i;return{extracted:t,rest:n}},u=e=>JSON.parse(JSON.stringify(e)),d=(e,t)=>({...e??{},...t??{}});async function f(e,t=3,n=500){for(let r=0;r<t;r+=1)try{return await e()}catch(e){if(r>=t-1)throw e;let i=n*2**r;await new Promise(e=>{setTimeout(e,i)})}throw Error(`Retry attempts exhausted`)}var p={redacted:null,encrypted:null,timestamp:0},m=300*1e3,h=()=>Date.now()-p.timestamp<m,g=()=>{p={redacted:null,encrypted:null,timestamp:0}},_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),v=(e,t)=>`Basic ${btoa(`${e}:${t}`)}`,y=e=>{switch(e.strategy){case`none`:return{};case`api_key`:{if(typeof e.value!=`string`||!e.value)return null;let t=typeof e.header_name==`string`&&e.header_name?e.header_name:`Authorization`,n=t===`Authorization`?`Bearer ${e.value}`:e.value;return{[t]:n}}case`bearer`:return typeof e.value!=`string`||!e.value?null:{Authorization:`Bearer ${e.value}`};case`basic`:return typeof e.username!=`string`||typeof e.password!=`string`?null:{Authorization:v(e.username,e.password)};case`header`:return i.stringRecord(e.headers)??{};case`oauth2`:{let t=_(e.state)?e.state.tokens:void 0;return!_(t)||typeof t.access_token!=`string`?null:{Authorization:`Bearer ${t.access_token}`}}default:return null}},b=e=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>{if(!_(t)||!_(t.auth))return[e,t];let n=y(t.auth);if(n===null)return[e,t];let r={...t},a={...i.stringRecord(t.headers)??{},...n};return delete r.auth,Object.keys(a).length>0?r.headers=a:delete r.headers,[e,r]}));return t?{...e,mcpServers:r}:r},x=e=>{let t=i.getSdkMcpServerMap(e);return t?Object.values(t).some(e=>i.hasRedactedMcpSecretLeaf(_(e)?e.auth:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.headers:void 0)||i.hasRedactedMcpSecretLeaf(_(e)?e.env:void 0)):!1},S=(e,t)=>{let n=i.getSdkMcpServerMap(e),r=i.getSdkMcpServerMap(t);return!n||!r?!1:Object.keys(n).some(e=>!(e in r))},C=e=>{let t={agent_settings:e.agent_settings??{},conversation_settings:e.conversation_settings??{},llm_api_key_set:e.llm_api_key_is_set},n=e.misc_settings?.app_preferences;if(n)for(let e of o){let r=n[e];r!==void 0&&(t[e]=r)}return t},w=e=>{let t=d(r.DEFAULT_SETTINGS.agent_settings??{},e.agent_settings??{}),n=d(r.DEFAULT_SETTINGS.conversation_settings??{},e.conversation_settings??{}),i={...u(r.DEFAULT_SETTINGS),...e,provider_tokens_set:{...r.DEFAULT_SETTINGS.provider_tokens_set??{},...e.provider_tokens_set??{}},agent_settings:t,conversation_settings:n},a=t.llm,o=t.condenser;return typeof t.agent==`string`&&(i.agent=t.agent),typeof a?.model==`string`&&a.model.length>0&&(i.llm_model=a.model),typeof a?.base_url==`string`&&(i.llm_base_url=a.base_url),typeof o?.enabled==`boolean`&&(i.enable_default_condenser=o.enabled),typeof o?.max_size==`number`&&(i.condenser_max_size=o.max_size),typeof n.confirmation_mode==`boolean`&&(i.confirmation_mode=n.confirmation_mode),(typeof n.security_analyzer==`string`||n.security_analyzer===null)&&(i.security_analyzer=n.security_analyzer),typeof n.max_iterations==`number`&&(i.max_iterations=n.max_iterations),i.search_api_key_set=!!i.search_api_key,i},T=class r{static async fetchSettingsFromApi(t){return f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).getSettings({exposeSecrets:t}))}static async getSettings(){if(t.getActiveBackend().backend.kind===`cloud`)try{return w(await f(()=>a.fetchCloudSettings()))}catch(e){return console.warn(`Failed to fetch cloud settings, using defaults:`,e),w({})}if(h()&&p.redacted)return w(C(p.redacted));try{let e=await this.fetchSettingsFromApi();return p.redacted=e,p.timestamp=Date.now(),w(C(e))}catch(e){return console.warn(`Failed to fetch settings from API, using defaults:`,e),w({})}}static async getSettingsForConversation(){if(h()&&p.encrypted)return{agentSettings:p.encrypted.agent_settings,conversationSettings:p.encrypted.conversation_settings,secretsEncrypted:!0};let e=await this.fetchSettingsFromApi(`encrypted`);return p.encrypted=e,p.timestamp||=Date.now(),{agentSettings:e.agent_settings,conversationSettings:e.conversation_settings,secretsEncrypted:!0}}static async getSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getAgentSchema()}static async getConversationSettingsSchema(){return t.getActiveBackend().backend.kind===`cloud`?await a.fetchCloudConversationSettingsSchema():await new e.SettingsClient(n.getAgentServerClientOptions()).getConversationSchema()}static async saveSettings(i){let{extracted:o,rest:s}=l(i),c=Object.keys(o).length>0,u={},d=s.agent_settings_diff;d&&Object.keys(d).length>0&&(u.agent_settings_diff=d);let p=s.conversation_settings_diff;p&&Object.keys(p).length>0&&(u.conversation_settings_diff=p),c&&(u.misc_settings_diff={app_preferences:o});let m=t.getActiveBackend().backend.kind===`cloud`,h=u.agent_settings_diff,_=!!h&&`mcp_config`in h&&h.mcp_config!==null,v;if(_)try{v=m?(await a.fetchCloudSettings())?.agent_settings?.mcp_config:(await r.fetchSettingsFromApi())?.agent_settings?.mcp_config}catch{}let y=m&&_&&x(v)&&!S(v,h?.mcp_config),C=_&&!y;if(m){if(!(u.agent_settings_diff||u.conversation_settings_diff||c))return!0;C&&await f(()=>a.saveCloudSettings({agent_settings_diff:{mcp_config:null}}));let e={};u.agent_settings_diff&&(e.agent_settings_diff={...u.agent_settings_diff},`mcp_config`in e.agent_settings_diff&&(e.agent_settings_diff.mcp_config=b(e.agent_settings_diff.mcp_config))),u.conversation_settings_diff&&(e.conversation_settings_diff=u.conversation_settings_diff),c&&(e.app_preferences=o);try{await f(()=>a.saveCloudSettings(e))}catch(e){if(C&&v)try{await a.saveCloudSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw e}}else{if(!(u.agent_settings_diff||u.conversation_settings_diff||u.misc_settings_diff))return!0;C&&await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:null}}));try{await f(()=>new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings(u))}catch(t){if(C&&v)try{await new e.SettingsClient(n.getAgentServerClientOptions()).updateSettings({agent_settings_diff:{mcp_config:v}})}catch{}throw t}}return g(),!0}static invalidateCache(){g()}};exports.default=T;
2
2
  //# sourceMappingURL=settings-service.api.cjs.map