@openhands/agent-canvas 1.7.2 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (599) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DP5rcauH.js → Trans-Bwpzk1wT.js} +1 -1
  4. package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-C921BlYB.js} +1 -1
  5. package/build/assets/active-backend-context-BiwzkzDy.js +2 -0
  6. package/build/assets/agent-context-settings-DXNT_dcw.js +1 -0
  7. package/build/assets/agent-profiles-settings-BymJf3EP.js +1 -0
  8. package/build/assets/agent-server-conversation-service.api-CYSWw-2g.js +41 -0
  9. package/build/assets/agent-settings-BjgQQe-_.js +1 -0
  10. package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-WzqXk6B4.js} +2 -2
  11. package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-DR8EVyZM.js} +1 -1
  12. package/build/assets/api-error-message-e16L1kwH.js +1 -0
  13. package/build/assets/api-key-entry-screen-DI0I04O3.js +1 -0
  14. package/build/assets/app-settings-DGistSFV.js +1 -0
  15. package/build/assets/automation-C_eCrGyP.js +1 -0
  16. package/build/assets/automation-detail-DY6x2FW1.js +2 -0
  17. package/build/assets/automation-export-C09f-Lua.js +2 -0
  18. package/build/assets/automation-setup-route-CqKp0717.js +1 -0
  19. package/build/assets/automations-list-CqWJ7qXW.js +1 -0
  20. package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-D4ngzpSh.js} +1 -1
  21. package/build/assets/backend-form-modal-B8D5hBzK.js +1 -0
  22. package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-BnzI8Ysj.js} +1 -1
  23. package/build/assets/{badge-DwgrwohM.js → badge-1Mf1iPcX.js} +1 -1
  24. package/build/assets/{base-modal-CSHhJTSr.js → base-modal-BBuy0WQQ.js} +1 -1
  25. package/build/assets/{brand-button-CQO8oqVo.js → brand-button-DGN6Y9o6.js} +1 -1
  26. package/build/assets/browser-D_ekTlTS.js +6 -0
  27. package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-D4a4Ou_w.js} +1 -1
  28. package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-CgbcjD97.js} +1 -1
  29. package/build/assets/check-CPLXgluF.js +1 -0
  30. package/build/assets/chevron-down-CP4QHvyc.js +1 -0
  31. package/build/assets/circle-check-Dpy2_xSI.js +1 -0
  32. package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-yTAS-nX3.js} +1 -1
  33. package/build/assets/cloud-funnel-analytics-CEOl5Gxr.js +1 -0
  34. package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Bd2yySnF.js} +1 -1
  35. package/build/assets/command-menu-Bj6X4ckE.js +1 -0
  36. package/build/assets/condenser-settings-EAXQNR2E.js +1 -0
  37. package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-NCUPr2-O.js} +1 -1
  38. package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-CrCrYuPF.js} +1 -1
  39. package/build/assets/conversation-BzyIcSwr.js +1 -0
  40. package/build/assets/conversation-CUJ0Vo8g.js +90 -0
  41. package/build/assets/conversation-panel-BzyIcSwr.js +1 -0
  42. package/build/assets/conversation-state-store-F62HvuI1.js +1 -0
  43. package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-BCZ7rUMH.js} +1 -1
  44. package/build/assets/{copy-B8Y5ufoR.js → copy-DCmZtz6n.js} +1 -1
  45. package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-D_Lp6-Fl.js} +1 -1
  46. package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-DLmolX8Q.js} +1 -1
  47. package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-BB8rzqXL.js} +1 -1
  48. package/build/assets/{entry.client-DETaouwO.js → entry.client-BbIYOsIg.js} +2 -2
  49. package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-C08-srev.js} +1 -1
  50. package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-BepBBX66.js} +1 -1
  51. package/build/assets/extensions-hub-R3KNv-5V.js +1 -0
  52. package/build/assets/extensions-navigation-CfWFmI1I.js +1 -0
  53. package/build/assets/{external-link-Cnnd6ikC.js → external-link-BdBSg8rk.js} +1 -1
  54. package/build/assets/files-tab-DEq8MbHu.js +1 -0
  55. package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-DAfsCJTe.js} +1 -1
  56. package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-CxfPJpzC.js} +1 -1
  57. package/build/assets/git-provider-icon-BZqqUPlm.js +1 -0
  58. package/build/assets/git-repo-dropdown-9WKINV6J.js +1 -0
  59. package/build/assets/git-repo-dropdown-DEpOwUez.js +1 -0
  60. package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-CX9oIoVT.js} +1 -1
  61. package/build/assets/home-CY0JaxiY.js +1 -0
  62. package/build/assets/home-CaNWlVvB.js +1 -0
  63. package/build/assets/home-store-Ch1ErdBc.js +1 -0
  64. package/build/assets/index-home-CaNWlVvB.js +1 -0
  65. package/build/assets/info-CmWQXtRQ.js +1 -0
  66. package/build/assets/install-server-modal-BWrudmZU.js +1 -0
  67. package/build/assets/{launch-Ccnhte5b.js → launch-B1POpHuP.js} +1 -1
  68. package/build/assets/{list-todo-_BXQzOiB.js → list-todo-DtiL3lTp.js} +1 -1
  69. package/build/assets/llm-not-configured-banner-3tMsM4K6.js +27 -0
  70. package/build/assets/llm-settings-CXo8iPNW.js +1 -0
  71. package/build/assets/llm-settings-D0W8mJDk.js +1 -0
  72. package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-DBJbfd8Z.js} +1 -1
  73. package/build/assets/loader-circle-B4QDBARx.js +1 -0
  74. package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DfZ_bhV7.js} +1 -1
  75. package/build/assets/manage-backends-modal-CwyWsiag.js +1 -0
  76. package/build/assets/manifest-39f4789d.js +1 -0
  77. package/build/assets/{markdown-renderer-CvOO0YIr.js → markdown-renderer-DgiLLhW6.js} +6 -6
  78. package/build/assets/mcp-DXG9LWrI.js +9 -0
  79. package/build/assets/mcp-marketplace-utils-DFmhKc5s.js +1 -0
  80. package/build/assets/messages-kBjKaAeA.js +40 -0
  81. package/build/assets/{modal-body-DQhiw-AR.js → modal-body-CMsDpalT.js} +1 -1
  82. package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-B6PDrxXo.js} +1 -1
  83. package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-DyxBZaAb.js} +1 -1
  84. package/build/assets/{onboarding-BegDrOKn.js → onboarding-47hh2IHA.js} +1 -1
  85. package/build/assets/onboarding-modal-9BuvvROo.js +1 -0
  86. package/build/assets/organization-service.api-UDy63-oC.js +1 -0
  87. package/build/assets/{pencil-8_lvWDoZ.js → pencil-BjgtZmWp.js} +1 -1
  88. package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-BWk8885v.js} +1 -1
  89. package/build/assets/plugins-management-service-CjkgF2dd.js +1 -0
  90. package/build/assets/plus-DrKuuvMe.js +1 -0
  91. package/build/assets/profiles-service.api-CukSFLzz.js +1 -0
  92. package/build/assets/providers-CqUWC85T.js +1 -0
  93. package/build/assets/proxy-BBUG3sd2.js +1 -0
  94. package/build/assets/{puzzle-DXWdfaa7.js → puzzle-BoNc6zZ8.js} +1 -1
  95. package/build/assets/recommended-automations-launcher-ejxy1P27.js +1 -0
  96. package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-BrM5ZAZD.js} +1 -1
  97. package/build/assets/root-5S-M8SYa.js +2 -0
  98. package/build/assets/root-DZ39lS5f.css +1 -0
  99. package/build/assets/root-layout-BPqoa0gv.js +3 -0
  100. package/build/assets/schema-field-nImDoY6-.js +1 -0
  101. package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-BxMrtUNV.js} +1 -1
  102. package/build/assets/search-Dc2qR4O2.js +1 -0
  103. package/build/assets/secrets-service-Dhjh3HhH.js +1 -0
  104. package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-CPdxceT_.js} +1 -1
  105. package/build/assets/segmented-toggle-Do6oyepX.js +1 -0
  106. package/build/assets/settings-BRbnfKEm.js +1 -0
  107. package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-DYCULKpp.js} +1 -1
  108. package/build/assets/{settings-index-COAdxm2Q.js → settings-index-C9o2NBO0.js} +1 -1
  109. package/build/assets/settings-input-B-q2gkVy.js +1 -0
  110. package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-WpQi0q1L.js} +1 -1
  111. package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-CEK0AIx6.js} +1 -1
  112. package/build/assets/settings-service.api-CZiPD8__.js +1 -0
  113. package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-LqKdGxHL.js} +1 -1
  114. package/build/assets/shared-conversation-Bu-dQlgp.js +1 -0
  115. package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-oHBGQmLh.js} +1 -1
  116. package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-ND-hgygu.js} +1 -1
  117. package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-CrujNA09.js} +1 -1
  118. package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-Bui-WNEr.js} +1 -1
  119. package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-CZBI7OqH.js} +1 -1
  120. package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-BOov_phZ.js} +1 -1
  121. package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-D0PiHWAD.js} +1 -1
  122. package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-B43KArIz.js} +2 -2
  123. package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-C7grwnOX.js} +1 -1
  124. package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-R3ac6m7O.js} +1 -1
  125. package/build/assets/{terminal-BRcoba5B.js → terminal-yqkNdEAx.js} +1 -1
  126. package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-BeSrbgCg.js} +1 -1
  127. package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-wW5TWcdN.js} +1 -1
  128. package/build/assets/{typography-C6fuRTTT.js → typography-iYhzLlHO.js} +1 -1
  129. package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-DUxbxmbq.js} +1 -1
  130. package/build/assets/use-activate-agent-profile-CDHA52tC.js +1 -0
  131. package/build/assets/use-agent-profiles-TsOdIyw5.js +1 -0
  132. package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-Bt1M71u5.js} +1 -1
  133. package/build/assets/use-cloud-current-user-id-DWt7HCgf.js +1 -0
  134. package/build/assets/{use-config-Csy8EAP9.js → use-config-CxlEdf_v.js} +1 -1
  135. package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-nOJ6Um5h.js} +1 -1
  136. package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-Dj5ang9x.js} +1 -1
  137. package/build/assets/use-is-authed-BT7Iud4U.js +1 -0
  138. package/build/assets/{use-is-creating-conversation-CIAcnd8M.js → use-is-creating-conversation-CAggrM75.js} +1 -1
  139. package/build/assets/use-llm-profiles-2Wc2db8u.js +1 -0
  140. package/build/assets/use-onboarding-completion-gxQlcEy2.js +1 -0
  141. package/build/assets/use-plugins-marketplace-CVO7sXYR.js +1 -0
  142. package/build/assets/use-save-agent-profile-D0wC5ExW.js +1 -0
  143. package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings-L3aMaDeS.js} +1 -1
  144. package/build/assets/use-settings-8nt3DGxW.js +1 -0
  145. package/build/assets/use-settings-nav-items-DHAAD-zk.js +16 -0
  146. package/build/assets/use-skills-CE6miQ3r.js +1 -0
  147. package/build/assets/use-tracking-BGboadaZ.js +68 -0
  148. package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-BIIpGUgM.js} +1 -1
  149. package/build/assets/useInfiniteQuery-BLRVmVPU.js +1 -0
  150. package/build/assets/{useMutation-DyQXZFEF.js → useMutation-CaSHLnX0.js} +1 -1
  151. package/build/assets/{useQueries-B3T1a7qt.js → useQueries--d_WWAzc.js} +1 -1
  152. package/build/assets/{useQuery-B38jBavx.js → useQuery-DiPh8LRJ.js} +1 -1
  153. package/build/assets/utils-BgGG1znF.js +1 -0
  154. package/build/assets/{vendor~browser-CIoZCqGs.js → vendor~browser-IVYgIgG1.js} +1 -1
  155. package/build/assets/{vendor~entry.client-Di4qO77Y.js → vendor~entry.client-BcYIVQvB.js} +1 -1
  156. package/build/assets/{vendor~entry.client-BfviqoVc.js → vendor~entry.client-CXM9oiAk.js} +1 -1
  157. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0bpqexo-CbTboogo.js} +2 -2
  158. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~d4by102p-C2f0ZhS-.js} +1 -1
  159. package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-C7RmQJwN.js} +1 -1
  160. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-Bqp1ZqJM.js} +1 -1
  161. package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-BCn8lzeG.js} +1 -1
  162. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~automation-setup-route-B_L-gcOG.js +1 -0
  163. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-sjx0x5ac.js +1 -0
  164. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~automation-setup-route~onboarding-modal-D7IDevqN.js +1 -0
  165. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~bi2r7bko-Bw4AuHN1.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~dfc8ddxy-tTyxnjXT.js} +1 -1
  166. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hakxo2tj-ClV0p9g3.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~gy8zbn65-CGt6bWRT.js} +1 -1
  167. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~eywn6ulz-BKxxr74w.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~dufan6ng-Dtdw8H0q.js} +17 -4
  168. package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-DBsnSXC3.js} +1 -1
  169. package/build/assets/x-omAzpXkl.js +1 -0
  170. package/build/favicon-16x16.png +0 -0
  171. package/build/favicon-32x32.png +0 -0
  172. package/build/favicon.ico +0 -0
  173. package/build/index.html +4 -4
  174. package/build/locales/ar/openhands.json +39 -2
  175. package/build/locales/ca/openhands.json +39 -2
  176. package/build/locales/de/openhands.json +39 -2
  177. package/build/locales/en/openhands.json +40 -3
  178. package/build/locales/es/openhands.json +39 -2
  179. package/build/locales/fr/openhands.json +39 -2
  180. package/build/locales/it/openhands.json +39 -2
  181. package/build/locales/ja/openhands.json +39 -2
  182. package/build/locales/ko-KR/openhands.json +39 -2
  183. package/build/locales/no/openhands.json +39 -2
  184. package/build/locales/pt/openhands.json +39 -2
  185. package/build/locales/tr/openhands.json +39 -2
  186. package/build/locales/uk/openhands.json +39 -2
  187. package/build/locales/zh-CN/openhands.json +39 -2
  188. package/build/locales/zh-TW/openhands.json +39 -2
  189. package/config/defaults.json +4 -4
  190. package/dist/api/agent-server-adapter.cjs +3 -3
  191. package/dist/api/agent-server-adapter.cjs.map +1 -1
  192. package/dist/api/agent-server-adapter.d.ts +46 -6
  193. package/dist/api/agent-server-adapter.js +187 -168
  194. package/dist/api/agent-server-adapter.js.map +1 -1
  195. package/dist/api/agent-server-compatibility.cjs +1 -1
  196. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  197. package/dist/api/agent-server-compatibility.d.ts +4 -0
  198. package/dist/api/agent-server-compatibility.js +41 -38
  199. package/dist/api/agent-server-compatibility.js.map +1 -1
  200. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  201. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  202. package/dist/api/automation-service/automation-service.api.d.ts +20 -0
  203. package/dist/api/automation-service/automation-service.api.js +136 -99
  204. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  205. package/dist/api/backend-registry/storage.cjs +1 -1
  206. package/dist/api/backend-registry/storage.cjs.map +1 -1
  207. package/dist/api/backend-registry/storage.js +1 -1
  208. package/dist/api/backend-registry/storage.js.map +1 -1
  209. package/dist/api/backend-registry/types.d.ts +2 -0
  210. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  211. package/dist/api/cloud/conversation-service.api.js +22 -22
  212. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  213. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  214. package/dist/api/mcp-service/mcp-service.api.js +19 -19
  215. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  216. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  217. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  218. package/dist/api/settings-service/settings-service.api.js +26 -12
  219. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  220. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +2 -0
  221. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -0
  222. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.d.ts +12 -0
  223. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +94 -0
  224. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -0
  225. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
  226. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
  227. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +31 -90
  228. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
  229. package/dist/components/features/automations/recommended-automations-launcher.d.ts +0 -7
  230. package/dist/components/features/automations/recommended-automations-section.d.ts +0 -6
  231. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  232. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  233. package/dist/components/features/backends/backend-form-modal.js +568 -358
  234. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  235. package/dist/components/features/backends/device-flow-auth.cjs +1 -1
  236. package/dist/components/features/backends/device-flow-auth.cjs.map +1 -1
  237. package/dist/components/features/backends/device-flow-auth.d.ts +9 -1
  238. package/dist/components/features/backends/device-flow-auth.js +56 -55
  239. package/dist/components/features/backends/device-flow-auth.js.map +1 -1
  240. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  241. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  242. package/dist/components/features/backends/manage-backends-modal.js +1 -1
  243. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  244. package/dist/components/features/chat/chat-interface.cjs +1 -1
  245. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  246. package/dist/components/features/chat/chat-interface.js +105 -105
  247. package/dist/components/features/chat/chat-interface.js.map +1 -1
  248. package/dist/components/features/chat/chat-message.cjs +1 -1
  249. package/dist/components/features/chat/chat-message.cjs.map +1 -1
  250. package/dist/components/features/chat/chat-message.d.ts +2 -1
  251. package/dist/components/features/chat/chat-message.js +59 -49
  252. package/dist/components/features/chat/chat-message.js.map +1 -1
  253. package/dist/components/features/chat/pending-user-messages.cjs +1 -1
  254. package/dist/components/features/chat/pending-user-messages.cjs.map +1 -1
  255. package/dist/components/features/chat/pending-user-messages.js +4 -1
  256. package/dist/components/features/chat/pending-user-messages.js.map +1 -1
  257. package/dist/components/features/chat/typing-indicator.cjs +1 -1
  258. package/dist/components/features/chat/typing-indicator.cjs.map +1 -1
  259. package/dist/components/features/chat/typing-indicator.d.ts +8 -1
  260. package/dist/components/features/chat/typing-indicator.js +94 -10
  261. package/dist/components/features/chat/typing-indicator.js.map +1 -1
  262. package/dist/components/features/command-menu/command-menu-items.d.ts +5 -1
  263. package/dist/components/features/files-tab/segmented-toggle.cjs +1 -1
  264. package/dist/components/features/files-tab/segmented-toggle.cjs.map +1 -1
  265. package/dist/components/features/files-tab/segmented-toggle.d.ts +2 -0
  266. package/dist/components/features/files-tab/segmented-toggle.js +17 -14
  267. package/dist/components/features/files-tab/segmented-toggle.js.map +1 -1
  268. package/dist/components/features/manifest/manifest-form-field.d.ts +27 -0
  269. package/dist/components/features/manifest/manifest-prerequisites-step.d.ts +11 -0
  270. package/dist/components/features/manifest/manifest-review-step.d.ts +14 -0
  271. package/dist/components/features/manifest/manifest-setup-dialog.d.ts +14 -0
  272. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  273. package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
  274. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  275. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  276. package/dist/components/features/mcp-page/installed-server-card.d.ts +2 -2
  277. package/dist/components/features/mcp-page/installed-server-card.js +6 -7
  278. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  279. package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
  280. package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
  281. package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
  282. package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
  283. package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
  284. package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
  285. package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
  286. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
  287. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
  288. package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
  289. package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
  290. package/dist/components/features/settings/settings-input.cjs +1 -1
  291. package/dist/components/features/settings/settings-input.cjs.map +1 -1
  292. package/dist/components/features/settings/settings-input.d.ts +6 -0
  293. package/dist/components/features/settings/settings-input.js +13 -8
  294. package/dist/components/features/settings/settings-input.js.map +1 -1
  295. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  296. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  297. package/dist/components/features/sidebar/sidebar-rail-body.js +124 -123
  298. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  299. package/dist/config/defaults.cjs +1 -1
  300. package/dist/config/defaults.cjs.map +1 -1
  301. package/dist/config/defaults.js +3 -3
  302. package/dist/config/defaults.js.map +1 -1
  303. package/dist/contexts/active-backend-context.cjs +1 -1
  304. package/dist/contexts/active-backend-context.cjs.map +1 -1
  305. package/dist/contexts/active-backend-context.d.ts +3 -2
  306. package/dist/contexts/active-backend-context.js +55 -42
  307. package/dist/contexts/active-backend-context.js.map +1 -1
  308. package/dist/favicon-16x16.png +0 -0
  309. package/dist/favicon-32x32.png +0 -0
  310. package/dist/favicon.ico +0 -0
  311. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  312. package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
  313. package/dist/hooks/query/query-keys.cjs.map +1 -1
  314. package/dist/hooks/query/query-keys.d.ts +4 -0
  315. package/dist/hooks/query/query-keys.js.map +1 -1
  316. package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
  317. package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
  318. package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
  319. package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
  320. package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
  321. package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
  322. package/dist/hooks/query/use-cloud-organizations.js +5 -1
  323. package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
  324. package/dist/hooks/query/use-manifest-capabilities.d.ts +21 -0
  325. package/dist/hooks/query/use-manifest-prerequisites.d.ts +24 -0
  326. package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
  327. package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
  328. package/dist/hooks/use-can-manage-org-profiles.js +2 -1
  329. package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
  330. package/dist/hooks/use-llm-configured.cjs +1 -1
  331. package/dist/hooks/use-llm-configured.cjs.map +1 -1
  332. package/dist/hooks/use-llm-configured.js +2 -1
  333. package/dist/hooks/use-llm-configured.js.map +1 -1
  334. package/dist/hooks/use-manifest-preflight.d.ts +18 -0
  335. package/dist/hooks/use-tracking.cjs +1 -1
  336. package/dist/hooks/use-tracking.cjs.map +1 -1
  337. package/dist/hooks/use-tracking.d.ts +14 -0
  338. package/dist/hooks/use-tracking.js +28 -10
  339. package/dist/hooks/use-tracking.js.map +1 -1
  340. package/dist/i18n/declaration.cjs +1 -1
  341. package/dist/i18n/declaration.cjs.map +1 -1
  342. package/dist/i18n/declaration.d.ts +38 -1
  343. package/dist/i18n/declaration.js +1 -1
  344. package/dist/i18n/declaration.js.map +1 -1
  345. package/dist/i18n/translation.cjs +2 -2
  346. package/dist/i18n/translation.cjs.map +1 -1
  347. package/dist/i18n/translation.js +645 -16
  348. package/dist/i18n/translation.js.map +1 -1
  349. package/dist/icons/external-link.cjs +2 -0
  350. package/dist/icons/external-link.cjs.map +1 -0
  351. package/dist/icons/external-link.js +22 -0
  352. package/dist/icons/external-link.js.map +1 -0
  353. package/dist/icons/server.cjs +2 -0
  354. package/dist/icons/server.cjs.map +1 -0
  355. package/dist/icons/server.js +17 -0
  356. package/dist/icons/server.js.map +1 -0
  357. package/dist/locales/ar/openhands.json +39 -2
  358. package/dist/locales/ca/openhands.json +39 -2
  359. package/dist/locales/de/openhands.json +39 -2
  360. package/dist/locales/en/openhands.json +40 -3
  361. package/dist/locales/es/openhands.json +39 -2
  362. package/dist/locales/fr/openhands.json +39 -2
  363. package/dist/locales/it/openhands.json +39 -2
  364. package/dist/locales/ja/openhands.json +39 -2
  365. package/dist/locales/ko-KR/openhands.json +39 -2
  366. package/dist/locales/no/openhands.json +39 -2
  367. package/dist/locales/pt/openhands.json +39 -2
  368. package/dist/locales/tr/openhands.json +39 -2
  369. package/dist/locales/uk/openhands.json +39 -2
  370. package/dist/locales/zh-CN/openhands.json +39 -2
  371. package/dist/locales/zh-TW/openhands.json +39 -2
  372. package/dist/manifests/automation-interface.cjs +2 -0
  373. package/dist/manifests/automation-interface.cjs.map +1 -0
  374. package/dist/manifests/automation-interface.d.ts +44 -0
  375. package/dist/manifests/automation-interface.js +81 -0
  376. package/dist/manifests/automation-interface.js.map +1 -0
  377. package/dist/manifests/automation-setup.cjs +2 -0
  378. package/dist/manifests/automation-setup.cjs.map +1 -0
  379. package/dist/manifests/automation-setup.d.ts +52 -0
  380. package/dist/manifests/automation-setup.js +8 -0
  381. package/dist/manifests/automation-setup.js.map +1 -0
  382. package/dist/manifests/interface-validation.cjs +2 -0
  383. package/dist/manifests/interface-validation.cjs.map +1 -0
  384. package/dist/manifests/interface-validation.d.ts +27 -0
  385. package/dist/manifests/interface-validation.js +182 -0
  386. package/dist/manifests/interface-validation.js.map +1 -0
  387. package/dist/manifests/manifest-actions.d.ts +15 -0
  388. package/dist/manifests/manifest-capabilities.d.ts +25 -0
  389. package/dist/manifests/manifest-error-map.d.ts +40 -0
  390. package/dist/manifests/manifest-local-validation.d.ts +56 -0
  391. package/dist/manifests/manifest-registry.cjs +2 -0
  392. package/dist/manifests/manifest-registry.cjs.map +1 -0
  393. package/dist/manifests/manifest-registry.d.ts +15 -0
  394. package/dist/manifests/manifest-registry.js +26 -0
  395. package/dist/manifests/manifest-registry.js.map +1 -0
  396. package/dist/manifests/manifest-sources.cjs +2 -0
  397. package/dist/manifests/manifest-sources.cjs.map +1 -0
  398. package/dist/manifests/manifest-sources.d.ts +15 -0
  399. package/dist/manifests/manifest-sources.js +8 -0
  400. package/dist/manifests/manifest-sources.js.map +1 -0
  401. package/dist/manifests/manifest-template.d.ts +18 -0
  402. package/dist/manifests/manifest-validation.cjs +2 -0
  403. package/dist/manifests/manifest-validation.cjs.map +1 -0
  404. package/dist/manifests/manifest-validation.d.ts +30 -0
  405. package/dist/manifests/manifest-validation.js +145 -0
  406. package/dist/manifests/manifest-validation.js.map +1 -0
  407. package/dist/manifests/types.cjs +2 -0
  408. package/dist/manifests/types.cjs.map +1 -0
  409. package/dist/manifests/types.d.ts +227 -0
  410. package/dist/manifests/types.js +6 -0
  411. package/dist/manifests/types.js.map +1 -0
  412. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +9 -0
  413. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -0
  414. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +75 -0
  415. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -0
  416. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +9 -0
  417. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -0
  418. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +78 -0
  419. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -0
  420. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs +17 -0
  421. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.cjs.map +1 -0
  422. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js +89 -0
  423. package/dist/node_modules/@openhands/extensions/automations/catalog/incident-retrospective-drafter/manifest.js.map +1 -0
  424. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs +10 -0
  425. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.cjs.map +1 -0
  426. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js +17 -0
  427. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-pr/manifest.js.map +1 -0
  428. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs +9 -0
  429. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.cjs.map +1 -0
  430. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js +15 -0
  431. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-triage-assistant/manifest.js.map +1 -0
  432. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs +9 -0
  433. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.cjs.map +1 -0
  434. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js +18 -0
  435. package/dist/node_modules/@openhands/extensions/automations/catalog/research-brief-writer/manifest.js.map +1 -0
  436. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs +9 -0
  437. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.cjs.map +1 -0
  438. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js +14 -0
  439. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-channel-monitor/manifest.js.map +1 -0
  440. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs +9 -0
  441. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.cjs.map +1 -0
  442. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js +14 -0
  443. package/dist/node_modules/@openhands/extensions/automations/catalog/slack-standup-digest/manifest.js.map +1 -0
  444. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +2 -0
  445. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -0
  446. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +23 -0
  447. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -0
  448. package/dist/node_modules/@openhands/extensions/automations/index.cjs +2 -0
  449. package/dist/node_modules/@openhands/extensions/automations/index.cjs.map +1 -0
  450. package/dist/node_modules/@openhands/extensions/automations/index.js +18 -0
  451. package/dist/node_modules/@openhands/extensions/automations/index.js.map +1 -0
  452. package/dist/node_modules/@openhands/extensions/automations/interface.cjs +2 -0
  453. package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -0
  454. package/dist/node_modules/@openhands/extensions/automations/interface.js +89 -0
  455. package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -0
  456. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
  457. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
  458. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +3 -3
  459. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
  460. package/dist/node_modules/@openhands/extensions/skills/index.cjs +17 -4
  461. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  462. package/dist/node_modules/@openhands/extensions/skills/index.js +5 -5
  463. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  464. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
  465. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
  466. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
  467. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
  468. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs +2 -0
  469. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.cjs.map +1 -0
  470. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js +29 -0
  471. package/dist/node_modules/lucide-react/dist/esm/icons/monitor.js.map +1 -0
  472. package/dist/package.cjs +1 -1
  473. package/dist/package.cjs.map +1 -1
  474. package/dist/package.js +3 -3
  475. package/dist/package.js.map +1 -1
  476. package/dist/routes/app-settings.cjs +1 -1
  477. package/dist/routes/app-settings.js +5 -5
  478. package/dist/routes/mcp.cjs +1 -1
  479. package/dist/routes/mcp.cjs.map +1 -1
  480. package/dist/routes/mcp.js +73 -82
  481. package/dist/routes/mcp.js.map +1 -1
  482. package/dist/services/telemetry.cjs +1 -1
  483. package/dist/services/telemetry.cjs.map +1 -1
  484. package/dist/services/telemetry.d.ts +8 -0
  485. package/dist/services/telemetry.js +163 -116
  486. package/dist/services/telemetry.js.map +1 -1
  487. package/dist/types/agent-server/core/events/conversation-state-event.d.ts +2 -19
  488. package/dist/types/agent-server/core/events/observation-event.d.ts +2 -18
  489. package/dist/types/automation.d.ts +7 -3
  490. package/dist/types/mcp-server.d.ts +5 -0
  491. package/dist/types/settings.d.ts +3 -0
  492. package/dist/utils/api-error-message.d.ts +6 -2
  493. package/dist/utils/automation-catalog.cjs +2 -0
  494. package/dist/utils/automation-catalog.cjs.map +1 -0
  495. package/dist/utils/automation-catalog.d.ts +28 -0
  496. package/dist/utils/automation-catalog.js +5 -0
  497. package/dist/utils/automation-catalog.js.map +1 -0
  498. package/dist/utils/automation-timeout.d.ts +3 -2
  499. package/dist/utils/mcp-config.cjs +1 -1
  500. package/dist/utils/mcp-config.cjs.map +1 -1
  501. package/dist/utils/mcp-config.d.ts +8 -0
  502. package/dist/utils/mcp-config.js +25 -20
  503. package/dist/utils/mcp-config.js.map +1 -1
  504. package/dist/utils/mcp-installed-servers.cjs +1 -1
  505. package/dist/utils/mcp-installed-servers.cjs.map +1 -1
  506. package/dist/utils/mcp-installed-servers.js +6 -3
  507. package/dist/utils/mcp-installed-servers.js.map +1 -1
  508. package/dist/utils/responder-deployment.d.ts +5 -1
  509. package/dist/utils/transcript-export/index.cjs +5 -5
  510. package/dist/utils/transcript-export/index.js +12 -12
  511. package/package.json +3 -3
  512. package/scripts/check-sdk-version-sync.mjs +6 -6
  513. package/scripts/check-translation-completeness.cjs +1 -0
  514. package/scripts/dev-safe.mjs +17 -12
  515. package/scripts/dev-static.mjs +17 -0
  516. package/scripts/dev-with-automation.mjs +12 -14
  517. package/scripts/ingress.mjs +22 -0
  518. package/scripts/proxy-utils.mjs +157 -2
  519. package/scripts/runtime-services-info.mjs +6 -6
  520. package/scripts/static-build.mjs +0 -7
  521. package/scripts/static-server.mjs +10 -0
  522. package/build/assets/active-backend-context-BlZPzZNU.js +0 -1
  523. package/build/assets/agent-context-settings-CTaN-Iw9.js +0 -1
  524. package/build/assets/agent-profiles-settings-CR4VTqv_.js +0 -1
  525. package/build/assets/agent-server-conversation-service.api-Btmi4q6d.js +0 -41
  526. package/build/assets/agent-settings-KQs-occT.js +0 -1
  527. package/build/assets/api-key-entry-screen-BhR24gkM.js +0 -1
  528. package/build/assets/app-settings-Bs4sY8WP.js +0 -1
  529. package/build/assets/automation-BGP_I1RR.js +0 -1
  530. package/build/assets/automation-detail-CwDnJbYR.js +0 -2
  531. package/build/assets/automation-export-Bu-r-EzL.js +0 -2
  532. package/build/assets/automations-list-CYw7_6FR.js +0 -1
  533. package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
  534. package/build/assets/browser-BUDJnBg4.js +0 -6
  535. package/build/assets/check-BMOG005H.js +0 -1
  536. package/build/assets/chevron-down-CV1zZP_K.js +0 -1
  537. package/build/assets/circle-check-lvN_jFN5.js +0 -1
  538. package/build/assets/client-source-1v-kWLNU.js +0 -1
  539. package/build/assets/cloud-funnel-analytics-CasMM7EO.js +0 -1
  540. package/build/assets/command-menu-N_BriUy8.js +0 -1
  541. package/build/assets/condenser-settings-Czi8cKxV.js +0 -1
  542. package/build/assets/conversation-C25pc2dT.js +0 -1
  543. package/build/assets/conversation-CObLYSJd.js +0 -90
  544. package/build/assets/conversation-panel-C25pc2dT.js +0 -1
  545. package/build/assets/conversation-state-store-DTq4hFoP.js +0 -1
  546. package/build/assets/extensions-hub-BKftOQ-X.js +0 -1
  547. package/build/assets/extensions-navigation-DF24q1H1.js +0 -1
  548. package/build/assets/files-tab-SAiFCnS5.js +0 -1
  549. package/build/assets/git-provider-icon-BREx-yUX.js +0 -1
  550. package/build/assets/home-EPNFgzUh.js +0 -1
  551. package/build/assets/home-sN90Xcxp.js +0 -1
  552. package/build/assets/index-home-EPNFgzUh.js +0 -1
  553. package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
  554. package/build/assets/llm-not-configured-banner-DTWzISnk.js +0 -27
  555. package/build/assets/llm-settings-BXk5_Pac.js +0 -1
  556. package/build/assets/llm-settings-C1vpgWam.js +0 -1
  557. package/build/assets/loader-circle-6zlEYCJw.js +0 -1
  558. package/build/assets/manage-backends-modal-DhflyGTf.js +0 -1
  559. package/build/assets/manifest-8082e879.js +0 -1
  560. package/build/assets/mcp-CxLPda-W.js +0 -9
  561. package/build/assets/messages-DINDkPNK.js +0 -40
  562. package/build/assets/onboarding-modal-DdvE6rzw.js +0 -1
  563. package/build/assets/organization-service.api-CT2OQlLz.js +0 -1
  564. package/build/assets/plugins-management-service-DVkoM3eA.js +0 -1
  565. package/build/assets/plus-vIbGD459.js +0 -1
  566. package/build/assets/profiles-service.api-CBafmAPO.js +0 -1
  567. package/build/assets/providers-9UzRB9mT.js +0 -1
  568. package/build/assets/proxy-C79PCMjo.js +0 -1
  569. package/build/assets/recommended-automations-launcher-BF2mtAKw.js +0 -58
  570. package/build/assets/root-B5JXKp1P.css +0 -1
  571. package/build/assets/root-Sj7W28yE.js +0 -2
  572. package/build/assets/root-layout-DbhKVoc7.js +0 -3
  573. package/build/assets/schema-field-CV6bFnoL.js +0 -1
  574. package/build/assets/search-sKuYKllf.js +0 -1
  575. package/build/assets/secrets-service-BjK-bPN2.js +0 -1
  576. package/build/assets/segmented-toggle-DbbD3Tve.js +0 -1
  577. package/build/assets/settings-Bj5Oo45A.js +0 -1
  578. package/build/assets/settings-input-BjW_zyTN.js +0 -1
  579. package/build/assets/settings-service.api-DryhKdSr.js +0 -1
  580. package/build/assets/shared-conversation-CnMxy7p_.js +0 -1
  581. package/build/assets/telemetry-cmCL3o6Z.js +0 -2
  582. package/build/assets/use-activate-agent-profile-DH33MvVj.js +0 -1
  583. package/build/assets/use-agent-profiles-Dmd_4H8q.js +0 -1
  584. package/build/assets/use-cloud-current-user-id-B6DP3s47.js +0 -1
  585. package/build/assets/use-is-authed-BsS4XwSL.js +0 -1
  586. package/build/assets/use-llm-profiles-BMQoc612.js +0 -1
  587. package/build/assets/use-onboarding-completion-B-2BTS-y.js +0 -1
  588. package/build/assets/use-plugins-marketplace-PBc_XNz_.js +0 -1
  589. package/build/assets/use-save-agent-profile-2Mk9ZX37.js +0 -1
  590. package/build/assets/use-settings-DBI44RnH.js +0 -1
  591. package/build/assets/use-settings-nav-items-Cva28C-c.js +0 -16
  592. package/build/assets/use-skills-RQsCtdzN.js +0 -1
  593. package/build/assets/use-tracking-CN1nIMnY.js +0 -1
  594. package/build/assets/utils-qjs_KuS4.js +0 -1
  595. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js +0 -1
  596. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js +0 -1
  597. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js +0 -1
  598. package/build/assets/x-EjvKGawc.js +0 -1
  599. /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f1hl7voa-BrmgjeOw.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~emdr2jt4-BrmgjeOw.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode)\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"storage.js","names":[],"sources":["../../../src/api/backend-registry/storage.ts"],"sourcesContent":["import {\n SEEDED_DEFAULT_BACKEND_ID,\n makeDefaultLocalBackend,\n makeLockedCloudBackend,\n} from \"./default-backend\";\nimport type {\n Backend,\n BackendAuthMode,\n BackendKind,\n BackendSelection,\n} from \"./types\";\n\nexport const BACKENDS_STORAGE_KEY = \"openhands-backends\";\nexport const ACTIVE_BACKEND_STORAGE_KEY = \"openhands-active-backend\";\n\nfunction isValidKind(value: unknown): value is BackendKind {\n return value === \"local\" || value === \"cloud\";\n}\n\nfunction isValidAuthMode(value: unknown): value is BackendAuthMode {\n return value === undefined || value === \"api-key\" || value === \"cookie\";\n}\n\nfunction isValidBackend(value: unknown): value is Backend {\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as Partial<Backend>;\n return (\n typeof v.id === \"string\" &&\n v.id.length > 0 &&\n typeof v.name === \"string\" &&\n typeof v.host === \"string\" &&\n typeof v.apiKey === \"string\" &&\n isValidKind(v.kind) &&\n isValidAuthMode(v.authMode) &&\n (v.connectionRevision === undefined ||\n (typeof v.connectionRevision === \"number\" &&\n Number.isSafeInteger(v.connectionRevision) &&\n v.connectionRevision >= 0))\n );\n}\n\nfunction isLoopbackUrl(value: string): boolean {\n try {\n const { hostname } = new URL(value);\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nfunction shouldSyncLauncherDefaultLocalBackend(\n backend: Backend,\n defaultBackend: Backend,\n): boolean {\n if (backend.id !== SEEDED_DEFAULT_BACKEND_ID || backend.kind !== \"local\") {\n return false;\n }\n\n return (\n backend.host === defaultBackend.host ||\n (isLoopbackUrl(backend.host) && isLoopbackUrl(defaultBackend.host))\n );\n}\n\nfunction syncLauncherDefaultLocalBackend(backends: Backend[]): Backend[] {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return backends;\n\n let didSync = false;\n const syncedBackends = backends.map((backend) => {\n if (!shouldSyncLauncherDefaultLocalBackend(backend, defaultBackend)) {\n return backend;\n }\n\n if (backend.apiKey === defaultBackend.apiKey) return backend;\n\n didSync = true;\n return {\n ...backend,\n apiKey: defaultBackend.apiKey,\n };\n });\n\n if (!didSync) return backends;\n\n writeStoredBackends(syncedBackends);\n return syncedBackends;\n}\n\nexport function writeStoredBackends(backends: Backend[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(BACKENDS_STORAGE_KEY, JSON.stringify(backends));\n } catch {\n /* ignore quota / serialization errors */\n }\n}\n\nexport function readStoredBackends(): Backend[] {\n if (typeof window === \"undefined\") return [];\n\n try {\n const lockedCloudBackend = makeLockedCloudBackend();\n if (lockedCloudBackend) {\n writeStoredBackends([lockedCloudBackend]);\n const activeSelection = readStoredActiveBackend();\n if (activeSelection?.backendId !== lockedCloudBackend.id) {\n writeStoredActiveBackend({ backendId: lockedCloudBackend.id });\n }\n return [lockedCloudBackend];\n }\n\n const raw = window.localStorage.getItem(BACKENDS_STORAGE_KEY);\n\n // First install: seed only when the launcher supplied enough information\n // for a usable local backend.\n if (raw === null) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const valid = parsed.filter(isValidBackend);\n\n // If the stored array is empty (or everything in it failed validation),\n // only re-seed when the launcher supplied both a host and API key.\n if (valid.length === 0) {\n const defaultBackend = makeDefaultLocalBackend();\n if (!defaultBackend) return [];\n\n writeStoredBackends([defaultBackend]);\n return [defaultBackend];\n }\n\n const synced = syncLauncherDefaultLocalBackend(valid);\n return synced;\n } catch {\n return [];\n }\n}\n\nfunction parseBackendSelection(raw: string | null): BackendSelection | null {\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as BackendSelection).backendId !== \"string\"\n ) {\n return null;\n }\n const orgIdRaw = (parsed as BackendSelection).orgId;\n return {\n backendId: (parsed as BackendSelection).backendId,\n orgId:\n typeof orgIdRaw === \"string\" && orgIdRaw.length > 0 ? orgIdRaw : null,\n };\n } catch {\n return null;\n }\n}\n\nfunction readStorageItem(\n storage: Storage | undefined,\n key: string,\n): string | null {\n try {\n return storage?.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction writeStorageItem(\n storage: Storage | undefined,\n key: string,\n value: string,\n): void {\n try {\n storage?.setItem(key, value);\n } catch {\n /* ignore */\n }\n}\n\nfunction removeStorageItem(storage: Storage | undefined, key: string): void {\n try {\n storage?.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\nexport function readStoredActiveBackend(): BackendSelection | null {\n if (typeof window === \"undefined\") return null;\n\n // Active backend is tab-scoped so reloading tab A does not adopt tab B's\n // backend. localStorage remains a last-used fallback for fresh tabs and old\n // persisted state.\n const sessionSelection = parseBackendSelection(\n readStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n if (sessionSelection) return sessionSelection;\n\n return parseBackendSelection(\n readStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY),\n );\n}\n\nexport function writeStoredActiveBackend(\n selection: BackendSelection | null,\n): void {\n if (typeof window === \"undefined\") return;\n\n if (!selection) {\n removeStorageItem(window.sessionStorage, ACTIVE_BACKEND_STORAGE_KEY);\n removeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY);\n return;\n }\n\n const serialized = JSON.stringify({\n backendId: selection.backendId,\n orgId: selection.orgId ?? null,\n });\n // Mirror to localStorage only as the default for new tabs/backward\n // compatibility; reads in existing tabs prefer sessionStorage.\n writeStorageItem(\n window.sessionStorage,\n ACTIVE_BACKEND_STORAGE_KEY,\n serialized,\n );\n writeStorageItem(window.localStorage, ACTIVE_BACKEND_STORAGE_KEY, serialized);\n}\n"],"mappings":"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"}
@@ -7,6 +7,8 @@ export interface Backend {
7
7
  apiKey: string;
8
8
  kind: BackendKind;
9
9
  authMode?: BackendAuthMode;
10
+ /** Changes whenever connection credentials change, invalidating keyed data. */
11
+ connectionRevision?: number;
10
12
  }
11
13
  export interface BackendSelection {
12
14
  backendId: string;
@@ -1,2 +1,2 @@
1
- require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("./proxy.cjs"),n=require("../client-source.cjs"),r=require("../conversation-metadata-store.cjs");function i(e){if(!e?.id)return e;let t=r.getStoredConversationMetadata(e.id);return t?{...e,selected_repository:e.selected_repository??t.selected_repository??null,selected_branch:e.selected_branch??t.selected_branch??null,git_provider:e.git_provider??t.git_provider??null,selected_workspace:e.selected_workspace??t.selected_workspace??null}:e}function a(){let t=e.getActiveBackend().backend;if(t.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return t}async function o(e=20,n){let r=a(),o=new URLSearchParams;o.set(`limit`,String(e)),n&&o.set(`page_id`,n),o.set(`sort_order`,`UPDATED_AT_DESC`);let s=await t.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/search?${o.toString()}`});return{items:(s?.items??[]).map(e=>i(e)),next_page_id:s?.next_page_id??null}}async function s(e){if(e.length===0)return[];let n=a(),r=new URLSearchParams;for(let t of e)r.append(`ids`,t);return(await t.callCloudProxy({backend:n,method:`GET`,path:`/api/v1/app-conversations?${r.toString()}`})??[]).map(i)}async function c(e){return await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/app-conversations`,body:e,headers:n.AGENT_CANVAS_CLIENT_HEADERS})}async function l(e){return t.callCloudProxy({backend:a(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function u(e){await t.callCloudProxy({backend:a(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function d(e,n){return await t.callCloudProxy({backend:a(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:n}})}async function f(e){await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function p(e){await t.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function m(e,n){let r=a(),i=new URLSearchParams;return i.append(`file_path`,n),await t.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${i.toString()}`})??``}async function h(e){let n=a(),r=new URLSearchParams;return r.set(`ids`,e),(await t.callCloudProxy({backend:n,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${r.toString()}`}))?.[0]??null}exports.batchGetCloudConversations=s,exports.createCloudAppConversation=c,exports.deleteCloudConversation=u,exports.downloadCloudConversation=l,exports.getCloudAppConversationStartTask=h,exports.pauseCloudSandbox=f,exports.readCloudConversationFile=m,exports.resumeCloudSandbox=p,exports.searchCloudConversations=o,exports.updateCloudConversationPublicFlag=d;
1
+ require("../../_virtual/_rolldown/runtime.cjs");const e=require("../backend-registry/active-store.cjs"),t=require("../client-source.cjs"),n=require("./proxy.cjs"),r=require("../conversation-metadata-store.cjs");function i(e){if(!e?.id)return e;let t=r.getStoredConversationMetadata(e.id);return t?{...e,selected_repository:e.selected_repository??t.selected_repository??null,selected_branch:e.selected_branch??t.selected_branch??null,git_provider:e.git_provider??t.git_provider??null,selected_workspace:e.selected_workspace??t.selected_workspace??null}:e}function a(){let t=e.getActiveBackend().backend;if(t.kind!==`cloud`)throw Error(`Cloud conversations call requires a cloud backend.`);return t}async function o(e=20,t){let r=a(),o=new URLSearchParams;o.set(`limit`,String(e)),t&&o.set(`page_id`,t),o.set(`sort_order`,`UPDATED_AT_DESC`);let s=await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/search?${o.toString()}`});return{items:(s?.items??[]).map(e=>i(e)),next_page_id:s?.next_page_id??null}}async function s(e){if(e.length===0)return[];let t=a(),r=new URLSearchParams;for(let t of e)r.append(`ids`,t);return(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations?${r.toString()}`})??[]).map(i)}async function c(e){return await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/app-conversations`,body:e,headers:t.AGENT_CANVAS_CLIENT_HEADERS})}async function l(e){return n.callCloudProxy({backend:a(),method:`GET`,path:`/api/v1/app-conversations/${e}/download`,responseType:`blob`})}async function u(e){await n.callCloudProxy({backend:a(),method:`DELETE`,path:`/api/v1/app-conversations/${e}`})}async function d(e,t){return await n.callCloudProxy({backend:a(),method:`PATCH`,path:`/api/v1/app-conversations/${e}`,body:{public:t}})}async function f(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/pause`})}async function p(e){await n.callCloudProxy({backend:a(),method:`POST`,path:`/api/v1/sandboxes/${e}/resume`})}async function m(e,t){let r=a(),i=new URLSearchParams;return i.append(`file_path`,t),await n.callCloudProxy({backend:r,method:`GET`,path:`/api/v1/app-conversations/${e}/file?${i.toString()}`})??``}async function h(e){let t=a(),r=new URLSearchParams;return r.set(`ids`,e),(await n.callCloudProxy({backend:t,method:`GET`,path:`/api/v1/app-conversations/start-tasks?${r.toString()}`}))?.[0]??null}exports.batchGetCloudConversations=s,exports.createCloudAppConversation=c,exports.deleteCloudConversation=u,exports.downloadCloudConversation=l,exports.getCloudAppConversationStartTask=h,exports.pauseCloudSandbox=f,exports.readCloudConversationFile=m,exports.resumeCloudSandbox=p,exports.searchCloudConversations=o,exports.updateCloudConversationPublicFlag=d;
2
2
  //# sourceMappingURL=conversation-service.api.cjs.map
@@ -1,6 +1,6 @@
1
1
  import { getActiveBackend as e } from "../backend-registry/active-store.js";
2
- import { callCloudProxy as t } from "./proxy.js";
3
- import { AGENT_CANVAS_CLIENT_HEADERS as n } from "../client-source.js";
2
+ import { AGENT_CANVAS_CLIENT_HEADERS as t } from "../client-source.js";
3
+ import { callCloudProxy as n } from "./proxy.js";
4
4
  import { getStoredConversationMetadata as r } from "../conversation-metadata-store.js";
5
5
  //#region src/api/cloud/conversation-service.api.ts
6
6
  function i(e) {
@@ -19,10 +19,10 @@ function a() {
19
19
  if (t.kind !== "cloud") throw Error("Cloud conversations call requires a cloud backend.");
20
20
  return t;
21
21
  }
22
- async function o(e = 20, n) {
22
+ async function o(e = 20, t) {
23
23
  let r = a(), o = new URLSearchParams();
24
- o.set("limit", String(e)), n && o.set("page_id", n), o.set("sort_order", "UPDATED_AT_DESC");
25
- let s = await t({
24
+ o.set("limit", String(e)), t && o.set("page_id", t), o.set("sort_order", "UPDATED_AT_DESC");
25
+ let s = await n({
26
26
  backend: r,
27
27
  method: "GET",
28
28
  path: `/api/v1/app-conversations/search?${o.toString()}`
@@ -34,25 +34,25 @@ async function o(e = 20, n) {
34
34
  }
35
35
  async function s(e) {
36
36
  if (e.length === 0) return [];
37
- let n = a(), r = new URLSearchParams();
37
+ let t = a(), r = new URLSearchParams();
38
38
  for (let t of e) r.append("ids", t);
39
- return (await t({
40
- backend: n,
39
+ return (await n({
40
+ backend: t,
41
41
  method: "GET",
42
42
  path: `/api/v1/app-conversations?${r.toString()}`
43
43
  }) ?? []).map(i);
44
44
  }
45
45
  async function c(e) {
46
- return await t({
46
+ return await n({
47
47
  backend: a(),
48
48
  method: "POST",
49
49
  path: "/api/v1/app-conversations",
50
50
  body: e,
51
- headers: n
51
+ headers: t
52
52
  });
53
53
  }
54
54
  async function l(e) {
55
- return t({
55
+ return n({
56
56
  backend: a(),
57
57
  method: "GET",
58
58
  path: `/api/v1/app-conversations/${e}/download`,
@@ -60,46 +60,46 @@ async function l(e) {
60
60
  });
61
61
  }
62
62
  async function u(e) {
63
- await t({
63
+ await n({
64
64
  backend: a(),
65
65
  method: "DELETE",
66
66
  path: `/api/v1/app-conversations/${e}`
67
67
  });
68
68
  }
69
- async function d(e, n) {
70
- return await t({
69
+ async function d(e, t) {
70
+ return await n({
71
71
  backend: a(),
72
72
  method: "PATCH",
73
73
  path: `/api/v1/app-conversations/${e}`,
74
- body: { public: n }
74
+ body: { public: t }
75
75
  });
76
76
  }
77
77
  async function f(e) {
78
- await t({
78
+ await n({
79
79
  backend: a(),
80
80
  method: "POST",
81
81
  path: `/api/v1/sandboxes/${e}/pause`
82
82
  });
83
83
  }
84
84
  async function p(e) {
85
- await t({
85
+ await n({
86
86
  backend: a(),
87
87
  method: "POST",
88
88
  path: `/api/v1/sandboxes/${e}/resume`
89
89
  });
90
90
  }
91
- async function m(e, n) {
91
+ async function m(e, t) {
92
92
  let r = a(), i = new URLSearchParams();
93
- return i.append("file_path", n), await t({
93
+ return i.append("file_path", t), await n({
94
94
  backend: r,
95
95
  method: "GET",
96
96
  path: `/api/v1/app-conversations/${e}/file?${i.toString()}`
97
97
  }) ?? "";
98
98
  }
99
99
  async function h(e) {
100
- let n = a(), r = new URLSearchParams();
101
- return r.set("ids", e), (await t({
102
- backend: n,
100
+ let t = a(), r = new URLSearchParams();
101
+ return r.set("ids", e), (await n({
102
+ backend: t,
103
103
  method: "GET",
104
104
  path: `/api/v1/app-conversations/start-tasks?${r.toString()}`
105
105
  }))?.[0] ?? null;
@@ -1,2 +1,2 @@
1
- require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/mcp-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("../../utils/mcp-credential-validation.cjs"),i=require("../../utils/redact-mcp-secrets.cjs"),a=require("./mcp-redacted-credentials.cjs");var o=120;function s(e){return e.type===`stdio`?{transport:`stdio`,command:e.command,...e.args?.length&&{args:e.args},...e.env&&Object.keys(e.env).length>0&&{env:e.env}}:{transport:e.type===`sse`?`sse`:`http`,url:e.url,...e.headers&&Object.keys(e.headers).length>0&&{headers:e.headers},...e.auth?{auth:e.auth}:{}}}function c(e){return e.auth?.strategy===`oauth2`?o:e.timeout}async function l(e){let t=r.getCredentialValidationForServer(e),n=await a.substituteRedactedMcpCredentials(e),i=s(n),o=c(e);return{request:{server:i,...e.name?{name:e.name}:{},...o===void 0?{}:{timeout:o},...t?{tool_call:t.toolCall}:{}},substituted:n}}function u(e,t){return e.ok?e.tool_result?{...e,tool_result:{...e.tool_result,text:i.redactMcpSecrets(e.tool_result.text,...t)}}:e:{...e,error:i.redactMcpSecrets(e.error,...t)}}function d(e,t,n){let r=u(e,n);if(r.ok&&t&&r.tool_result&&r.tools.includes(t.toolCall.name)){let e=t.interpret(r.tool_result);if(e)return{ok:!1,error:e,error_kind:`credentials`}}return r}function f(){if(t.getActiveBackend().backend.kind===`local`){let{host:e,apiKey:t}=n.getAgentServerClientOptions();return{host:e,...t?{apiKey:t}:{}}}let e=t.getRegisteredBackends().find(e=>e.kind===`local`&&e.host);if(e)return{host:e.host.replace(/\/+$/,``),...e.apiKey?{apiKey:e.apiKey}:{}};throw Error(`OAuth authorization requires a reachable local backend.`)}function p(){let{host:t,apiKey:n}=f();return new e.MCPClient({host:t,...n?{apiKey:n}:{},timeout:125e3})}function m(e){return e.status===`succeeded`?{ok:!0,tools:e.tools??[],...e.tool_result!==void 0&&{tool_result:e.tool_result},...e.oauth_state!==void 0&&{oauth_state:e.oauth_state}}:{ok:!1,error:e.error||`OAuth authorization did not complete`,error_kind:e.error_kind||`unknown`}}var h=e=>new Promise(t=>{window.setTimeout(t,e)}),g=class i{static async testServer(i){if(t.getActiveBackend().backend.kind===`cloud`)return{ok:!0,tools:[]};let a=r.getCredentialValidationForServer(i),{host:o,apiKey:s}=n.getAgentServerClientOptions(),c=new e.MCPClient({host:o,...s?{apiKey:s}:{}});try{let{request:e,substituted:t}=await l(i);return d(await c.testServer(e),a,[t,i])}finally{c.close()}}static async startOAuth(e){let t=p();try{return await i.startOAuthWithClient(t,e)}finally{t.close()}}static async getOAuthStatus(e){let t=p();try{return await i.getOAuthStatusWithClient(t,e)}finally{t.close()}}static async submitOAuthCallback(e,t){let n=p();try{return await i.submitOAuthCallbackWithClient(n,e,t)}finally{n.close()}}static async authorizeOAuth(e){let t=r.getCredentialValidationForServer(e),n=n=>d(n,t,[e]),a=window.open(`about:blank`,`_blank`),s=p();try{let t=await i.startOAuthWithClient(s,e);if(!t.ok||!t.job_id||!t.authorization_url)return a?.close(),n({ok:!1,error:t.error||`Could not start OAuth authorization`,error_kind:t.error_kind||`unknown`});let r=await i.getOAuthStatusWithClient(s,t.job_id);for(let e=0;e<20;e+=1){if(r.status===`succeeded`||r.status===`failed`)return a?.close(),n(m(r));if(r.callback_ready)break;await h(250),r=await i.getOAuthStatusWithClient(s,t.job_id)}a&&(a.location.href=t.authorization_url);for(let e=0;e<o;e+=1)if(await h(1e3),r=await i.getOAuthStatusWithClient(s,t.job_id),r.status===`succeeded`||r.status===`failed`)return a?.close(),n(m(r));return{ok:!1,error:`OAuth authorization timed out`,error_kind:`timeout`}}finally{s.close()}}static async startOAuthWithClient(e,t){let{request:n}=await l(t);return e.startOAuth(n)}static async getOAuthStatusWithClient(e,t){return e.getOAuthStatus(t)}static async submitOAuthCallbackWithClient(e,t,n){return e.submitOAuthCallback(t,{callback_url:n})}};exports.default=g;
1
+ require("../../_virtual/_rolldown/runtime.cjs");const e=require("../../node_modules/@openhands/typescript-client/dist/client/mcp-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("./mcp-redacted-credentials.cjs"),i=require("../../utils/mcp-credential-validation.cjs"),a=require("../../utils/redact-mcp-secrets.cjs");var o=120;function s(e){return e.type===`stdio`?{transport:`stdio`,command:e.command,...e.args?.length&&{args:e.args},...e.env&&Object.keys(e.env).length>0&&{env:e.env}}:{transport:e.type===`sse`?`sse`:`http`,url:e.url,...e.headers&&Object.keys(e.headers).length>0&&{headers:e.headers},...e.auth?{auth:e.auth}:{}}}function c(e){return e.auth?.strategy===`oauth2`?o:e.timeout}async function l(e){let t=i.getCredentialValidationForServer(e),n=await r.substituteRedactedMcpCredentials(e),a=s(n),o=c(e);return{request:{server:a,...e.name?{name:e.name}:{},...o===void 0?{}:{timeout:o},...t?{tool_call:t.toolCall}:{}},substituted:n}}function u(e,t){return e.ok?e.tool_result?{...e,tool_result:{...e.tool_result,text:a.redactMcpSecrets(e.tool_result.text,...t)}}:e:{...e,error:a.redactMcpSecrets(e.error,...t)}}function d(e,t,n){let r=u(e,n);if(r.ok&&t&&r.tool_result&&r.tools.includes(t.toolCall.name)){let e=t.interpret(r.tool_result);if(e)return{ok:!1,error:e,error_kind:`credentials`}}return r}function f(){if(t.getActiveBackend().backend.kind===`local`){let{host:e,apiKey:t}=n.getAgentServerClientOptions();return{host:e,...t?{apiKey:t}:{}}}let e=t.getRegisteredBackends().find(e=>e.kind===`local`&&e.host);if(e)return{host:e.host.replace(/\/+$/,``),...e.apiKey?{apiKey:e.apiKey}:{}};throw Error(`OAuth authorization requires a reachable local backend.`)}function p(){let{host:t,apiKey:n}=f();return new e.MCPClient({host:t,...n?{apiKey:n}:{},timeout:125e3})}function m(e){return e.status===`succeeded`?{ok:!0,tools:e.tools??[],...e.tool_result!==void 0&&{tool_result:e.tool_result},...e.oauth_state!==void 0&&{oauth_state:e.oauth_state}}:{ok:!1,error:e.error||`OAuth authorization did not complete`,error_kind:e.error_kind||`unknown`}}var h=e=>new Promise(t=>{window.setTimeout(t,e)}),g=class r{static async testServer(r){if(t.getActiveBackend().backend.kind===`cloud`)return{ok:!0,tools:[]};let a=i.getCredentialValidationForServer(r),{host:o,apiKey:s}=n.getAgentServerClientOptions(),c=new e.MCPClient({host:o,...s?{apiKey:s}:{}});try{let{request:e,substituted:t}=await l(r);return d(await c.testServer(e),a,[t,r])}finally{c.close()}}static async startOAuth(e){let t=p();try{return await r.startOAuthWithClient(t,e)}finally{t.close()}}static async getOAuthStatus(e){let t=p();try{return await r.getOAuthStatusWithClient(t,e)}finally{t.close()}}static async submitOAuthCallback(e,t){let n=p();try{return await r.submitOAuthCallbackWithClient(n,e,t)}finally{n.close()}}static async authorizeOAuth(e){let t=i.getCredentialValidationForServer(e),n=n=>d(n,t,[e]),a=window.open(`about:blank`,`_blank`),s=p();try{let t=await r.startOAuthWithClient(s,e);if(!t.ok||!t.job_id||!t.authorization_url)return a?.close(),n({ok:!1,error:t.error||`Could not start OAuth authorization`,error_kind:t.error_kind||`unknown`});let i=await r.getOAuthStatusWithClient(s,t.job_id);for(let e=0;e<20;e+=1){if(i.status===`succeeded`||i.status===`failed`)return a?.close(),n(m(i));if(i.callback_ready)break;await h(250),i=await r.getOAuthStatusWithClient(s,t.job_id)}a&&(a.location.href=t.authorization_url);for(let e=0;e<o;e+=1)if(await h(1e3),i=await r.getOAuthStatusWithClient(s,t.job_id),i.status===`succeeded`||i.status===`failed`)return a?.close(),n(m(i));return{ok:!1,error:`OAuth authorization timed out`,error_kind:`timeout`}}finally{s.close()}}static async startOAuthWithClient(e,t){let{request:n}=await l(t);return e.startOAuth(n)}static async getOAuthStatusWithClient(e,t){return await e.getOAuthStatus(t)}static async submitOAuthCallbackWithClient(e,t,n){return await e.submitOAuthCallback(t,{callback_url:n})}};exports.default=g;
2
2
  //# sourceMappingURL=mcp-service.api.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-service.api.cjs","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
+ {"version":3,"file":"mcp-service.api.cjs","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 // typescript-client 1.36 types the OAuth probes with the generated\n // agent-server models, which describe the opaque `oauth_state` JSON blobs as\n // `unknown` rather than the recursive `MCPJsonValue` the local types use. The\n // wire shape is unchanged, so narrow back to the app's boundary type.\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.getOAuthStatus(jobId)) as MCPOAuthStatusResponse;\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.submitOAuthCallback(jobId, {\n callback_url: callbackUrl,\n })) as MCPOAuthStatusResponse;\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import { MCPClient as e } from "../../node_modules/@openhands/typescript-client/
2
2
  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
- import { getCredentialValidationForServer as i } from "../../utils/mcp-credential-validation.js";
6
- import { redactMcpSecrets as a } from "../../utils/redact-mcp-secrets.js";
7
- import { substituteRedactedMcpCredentials as o } from "./mcp-redacted-credentials.js";
5
+ import { substituteRedactedMcpCredentials as i } from "./mcp-redacted-credentials.js";
6
+ import { getCredentialValidationForServer as a } from "../../utils/mcp-credential-validation.js";
7
+ import { redactMcpSecrets as o } from "../../utils/redact-mcp-secrets.js";
8
8
  //#region src/api/mcp-service/mcp-service.api.ts
9
9
  var s = 120;
10
10
  function c(e) {
@@ -24,12 +24,12 @@ function l(e) {
24
24
  return e.auth?.strategy === "oauth2" ? s : e.timeout;
25
25
  }
26
26
  async function u(e) {
27
- let t = i(e), n = await o(e), r = c(n), a = l(e);
27
+ let t = a(e), n = await i(e), r = c(n), o = l(e);
28
28
  return {
29
29
  request: {
30
30
  server: r,
31
31
  ...e.name ? { name: e.name } : {},
32
- ...a === void 0 ? {} : { timeout: a },
32
+ ...o === void 0 ? {} : { timeout: o },
33
33
  ...t ? { tool_call: t.toolCall } : {}
34
34
  },
35
35
  substituted: n
@@ -40,11 +40,11 @@ function d(e, t) {
40
40
  ...e,
41
41
  tool_result: {
42
42
  ...e.tool_result,
43
- text: a(e.tool_result.text, ...t)
43
+ text: o(e.tool_result.text, ...t)
44
44
  }
45
45
  } : e : {
46
46
  ...e,
47
- error: a(e.error, ...t)
47
+ error: o(e.error, ...t)
48
48
  };
49
49
  }
50
50
  function f(e, t, n) {
@@ -102,13 +102,13 @@ var g = (e) => new Promise((t) => {
102
102
  ok: !0,
103
103
  tools: []
104
104
  };
105
- let a = i(n), { host: o, apiKey: s } = r(), c = new e({
105
+ let i = a(n), { host: o, apiKey: s } = r(), c = new e({
106
106
  host: o,
107
107
  ...s ? { apiKey: s } : {}
108
108
  });
109
109
  try {
110
110
  let { request: e, substituted: t } = await u(n);
111
- return f(await c.testServer(e), a, [t, n]);
111
+ return f(await c.testServer(e), i, [t, n]);
112
112
  } finally {
113
113
  c.close();
114
114
  }
@@ -138,22 +138,22 @@ var g = (e) => new Promise((t) => {
138
138
  }
139
139
  }
140
140
  static async authorizeOAuth(e) {
141
- let t = i(e), r = (n) => f(n, t, [e]), a = window.open("about:blank", "_blank"), o = m();
141
+ let t = a(e), r = (n) => f(n, t, [e]), i = window.open("about:blank", "_blank"), o = m();
142
142
  try {
143
143
  let t = await n.startOAuthWithClient(o, e);
144
- if (!t.ok || !t.job_id || !t.authorization_url) return a?.close(), r({
144
+ if (!t.ok || !t.job_id || !t.authorization_url) return i?.close(), r({
145
145
  ok: !1,
146
146
  error: t.error || "Could not start OAuth authorization",
147
147
  error_kind: t.error_kind || "unknown"
148
148
  });
149
- let i = await n.getOAuthStatusWithClient(o, t.job_id);
149
+ let a = await n.getOAuthStatusWithClient(o, t.job_id);
150
150
  for (let e = 0; e < 20; e += 1) {
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);
151
+ if (a.status === "succeeded" || a.status === "failed") return i?.close(), r(h(a));
152
+ if (a.callback_ready) break;
153
+ await g(250), a = await n.getOAuthStatusWithClient(o, t.job_id);
154
154
  }
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));
155
+ i && (i.location.href = t.authorization_url);
156
+ for (let e = 0; e < s; e += 1) if (await g(1e3), a = await n.getOAuthStatusWithClient(o, t.job_id), a.status === "succeeded" || a.status === "failed") return i?.close(), r(h(a));
157
157
  return {
158
158
  ok: !1,
159
159
  error: "OAuth authorization timed out",
@@ -168,10 +168,10 @@ var g = (e) => new Promise((t) => {
168
168
  return e.startOAuth(n);
169
169
  }
170
170
  static async getOAuthStatusWithClient(e, t) {
171
- return e.getOAuthStatus(t);
171
+ return await e.getOAuthStatus(t);
172
172
  }
173
173
  static async submitOAuthCallbackWithClient(e, t, n) {
174
- return e.submitOAuthCallback(t, { callback_url: n });
174
+ return await e.submitOAuthCallback(t, { callback_url: n });
175
175
  }
176
176
  };
177
177
  //#endregion
@@ -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 {\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
+ {"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 // typescript-client 1.36 types the OAuth probes with the generated\n // agent-server models, which describe the opaque `oauth_state` JSON blobs as\n // `unknown` rather than the recursive `MCPJsonValue` the local types use. The\n // wire shape is unchanged, so narrow back to the app's boundary type.\n private static async getOAuthStatusWithClient(\n client: MCPClient,\n jobId: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.getOAuthStatus(jobId)) as MCPOAuthStatusResponse;\n }\n\n private static async submitOAuthCallbackWithClient(\n client: MCPClient,\n jobId: string,\n callbackUrl: string,\n ): Promise<MCPOAuthStatusResponse> {\n return (await client.submitOAuthCallback(jobId, {\n callback_url: callbackUrl,\n })) as MCPOAuthStatusResponse;\n }\n}\n\nexport default McpService;\n"],"mappings":"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"}
@@ -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`,`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;
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=>{if(!_(e))return e;let t=_(e.mcpServers),n=t?e.mcpServers:e,r=Object.fromEntries(Object.entries(n).map(([e,t])=>_(t)?[e,{...t,enabled:t.enabled!==!1}]:[e,t]));return t?{...e,mcpServers:r}:r},S=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},C=(e,t)=>{let n=i.getSdkMcpServerMap(e),r=i.getSdkMcpServerMap(t);return!n||!r?!1:Object.keys(n).some(e=>!(e in r))},w=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},T=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},E=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 T(await f(()=>a.fetchCloudSettings()))}catch(e){return console.warn(`Failed to fetch cloud settings, using defaults:`,e),T({})}if(h()&&p.redacted)return T(w(p.redacted));try{let e=await this.fetchSettingsFromApi();return p.redacted=e,p.timestamp=Date.now(),T(w(e))}catch(e){return console.warn(`Failed to fetch settings from API, using defaults:`,e),T({})}}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&&_&&S(v)&&!C(v,h?.mcp_config),w=_&&!y;if(m){if(!(u.agent_settings_diff||u.conversation_settings_diff||c))return!0;w&&await f(()=>a.saveCloudSettings({agent_settings_diff:{mcp_config:null}}));let e={};if(u.agent_settings_diff&&(e.agent_settings_diff={...u.agent_settings_diff},`mcp_config`in e.agent_settings_diff)){let t=b(e.agent_settings_diff.mcp_config);e.agent_settings_diff.mcp_config=y?x(t):t}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(w&&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;w&&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(w&&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=E;
2
2
  //# sourceMappingURL=settings-service.api.cjs.map