@openhands/agent-canvas 1.7.2 → 1.8.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 (353) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DP5rcauH.js → Trans-B7lYw4uD.js} +1 -1
  4. package/build/assets/{acp-providers-BHKZvEm5.js → acp-providers-WUD4tfSq.js} +1 -1
  5. package/build/assets/active-backend-context-mY7Gff5c.js +2 -0
  6. package/build/assets/{agent-context-settings-CTaN-Iw9.js → agent-context-settings-BTUmWEzL.js} +1 -1
  7. package/build/assets/{agent-profiles-settings-CR4VTqv_.js → agent-profiles-settings-Ilqid_R5.js} +1 -1
  8. package/build/assets/agent-server-conversation-service.api-C_7YnjzP.js +41 -0
  9. package/build/assets/{agent-settings-BIOsUglV.js → agent-settings-BGTyoT6X.js} +2 -2
  10. package/build/assets/agent-settings-CxfT4ksO.js +1 -0
  11. package/build/assets/{alert-banner-C1nzoXBC.js → alert-banner-eRyIwDyU.js} +1 -1
  12. package/build/assets/api-key-entry-screen-JOx3SH1-.js +1 -0
  13. package/build/assets/app-settings-D53QZy5p.js +1 -0
  14. package/build/assets/automation-detail-nEflClmc.js +2 -0
  15. package/build/assets/{automation-export-Bu-r-EzL.js → automation-export-BO_kfqC8.js} +1 -1
  16. package/build/assets/{automations-list-CYw7_6FR.js → automations-list-BYncC7gv.js} +1 -1
  17. package/build/assets/{back-nav-button-Be_L157B.js → back-nav-button-C02hGa8t.js} +1 -1
  18. package/build/assets/backend-form-modal-CKrBF80P.js +1 -0
  19. package/build/assets/{backend-synced-settings-badge-BNpEylNP.js → backend-synced-settings-badge-CQ9xtNWm.js} +1 -1
  20. package/build/assets/{badge-DwgrwohM.js → badge-CzXbf7tR.js} +1 -1
  21. package/build/assets/{base-modal-CSHhJTSr.js → base-modal-DkVyzFMt.js} +1 -1
  22. package/build/assets/{brand-button-CQO8oqVo.js → brand-button-BUlDL-mz.js} +1 -1
  23. package/build/assets/{browser-BUDJnBg4.js → browser-3QjrEr1D.js} +1 -1
  24. package/build/assets/{browser-tab-CEApjoEV.js → browser-tab-BijpUbdt.js} +1 -1
  25. package/build/assets/{chat-send-button-D4614wUz.js → chat-send-button-BKsVjhtA.js} +1 -1
  26. package/build/assets/check-CrxQfJZ2.js +1 -0
  27. package/build/assets/chevron-down-D_LsyTA7.js +1 -0
  28. package/build/assets/circle-check-DZn9HkLE.js +1 -0
  29. package/build/assets/{circle-plus-check-toggle-E3Ecb_gg.js → circle-plus-check-toggle-DdjUiOo1.js} +1 -1
  30. package/build/assets/cloud-funnel-analytics-NlmDoeo2.js +1 -0
  31. package/build/assets/{combobox-caret-C8_eGdp2.js → combobox-caret-Dl9UtvD6.js} +1 -1
  32. package/build/assets/{command-menu-N_BriUy8.js → command-menu-CvLPs7dg.js} +1 -1
  33. package/build/assets/{condenser-settings-Czi8cKxV.js → condenser-settings-C4Y9CzQV.js} +1 -1
  34. package/build/assets/{confirmation-modal-gZtbojCm.js → confirmation-modal-CRBJSllP.js} +1 -1
  35. package/build/assets/{context-menu-list-item-BTHGFhIx.js → context-menu-list-item-FGaafXGh.js} +1 -1
  36. package/build/assets/conversation-D_ORtpKC.js +1 -0
  37. package/build/assets/conversation-Dpc5nmGi.js +90 -0
  38. package/build/assets/conversation-panel-D_ORtpKC.js +1 -0
  39. package/build/assets/conversation-state-store-CGRQemtx.js +1 -0
  40. package/build/assets/{conversation-tab-empty-state-BCMHkGQk.js → conversation-tab-empty-state-CDjvNgpG.js} +1 -1
  41. package/build/assets/{copy-B8Y5ufoR.js → copy-Drwu97Gx.js} +1 -1
  42. package/build/assets/{copy-to-clipboard-button-C4l3CMSd.js → copy-to-clipboard-button-NbN1clVr.js} +1 -1
  43. package/build/assets/{device-verify-C_M7Z8xs.js → device-verify-CDm_WrVu.js} +1 -1
  44. package/build/assets/{dropdown-classes-DQlj-MpS.js → dropdown-classes-CqA2BTCL.js} +1 -1
  45. package/build/assets/{entry.client-DETaouwO.js → entry.client-BO2KQj0y.js} +2 -2
  46. package/build/assets/{enum-filter-dropdown-paB-lFSP.js → enum-filter-dropdown-DSqPZnsD.js} +1 -1
  47. package/build/assets/{environment-switch-overlay-D0FgCMqs.js → environment-switch-overlay-mGl2pqqx.js} +1 -1
  48. package/build/assets/extensions-hub-Br3Lgynp.js +1 -0
  49. package/build/assets/extensions-navigation-BQmstKDZ.js +1 -0
  50. package/build/assets/{external-link-Cnnd6ikC.js → external-link-D9B2QMPf.js} +1 -1
  51. package/build/assets/files-tab-4c9HFSLo.js +1 -0
  52. package/build/assets/{form-control-classes-CSPevi7c.js → form-control-classes-CtVAktAy.js} +1 -1
  53. package/build/assets/{format-time-delta-DuhE50B-.js → format-time-delta-DICE64sz.js} +1 -1
  54. package/build/assets/git-provider-icon-0PqmIS_S.js +1 -0
  55. package/build/assets/{highlighted-source-view-suUKd5if.js → highlighted-source-view-KMsA9c4a.js} +1 -1
  56. package/build/assets/home-D9JsyEmE.js +1 -0
  57. package/build/assets/{home-sN90Xcxp.js → home-TFhnmZLx.js} +1 -1
  58. package/build/assets/index-home-D9JsyEmE.js +1 -0
  59. package/build/assets/install-server-modal-BgGRnqA0.js +1 -0
  60. package/build/assets/{launch-Ccnhte5b.js → launch-DjkKw55l.js} +1 -1
  61. package/build/assets/{list-todo-_BXQzOiB.js → list-todo-BpAf7aOT.js} +1 -1
  62. package/build/assets/{llm-not-configured-banner-DTWzISnk.js → llm-not-configured-banner-Y4W9-sar.js} +4 -4
  63. package/build/assets/llm-settings-D8zNkIlP.js +1 -0
  64. package/build/assets/llm-settings-nPwv7hKu.js +1 -0
  65. package/build/assets/{llm-subscription-service-W5BprsNA.js → llm-subscription-service-COTgZc1C.js} +1 -1
  66. package/build/assets/loader-circle-CGD6-Vak.js +1 -0
  67. package/build/assets/{loading-spinner-CcpnCr_d.js → loading-spinner-DRFyh6Iy.js} +1 -1
  68. package/build/assets/manage-backends-modal-DiRWE3tJ.js +1 -0
  69. package/build/assets/manifest-1cf33a7b.js +1 -0
  70. package/build/assets/markdown-renderer-U40HF0Ak.js +8 -0
  71. package/build/assets/mcp-xDMaHzOw.js +9 -0
  72. package/build/assets/{messages-DINDkPNK.js → messages-CdNfZPgd.js} +2 -2
  73. package/build/assets/{modal-body-DQhiw-AR.js → modal-body-C3bGicn4.js} +1 -1
  74. package/build/assets/{modal-classes-YaEEa5eZ.js → modal-classes-DFFO6BMU.js} +1 -1
  75. package/build/assets/{modal-close-button-turIYn0t.js → modal-close-button-vxkAIRyZ.js} +1 -1
  76. package/build/assets/{onboarding-BegDrOKn.js → onboarding-DWuFieEA.js} +1 -1
  77. package/build/assets/onboarding-modal-C8m72Dpb.js +1 -0
  78. package/build/assets/organization-service.api-CQ73CB-S.js +1 -0
  79. package/build/assets/{pencil-8_lvWDoZ.js → pencil-DzW2GB2M.js} +1 -1
  80. package/build/assets/{planner-tab-w6HT0N_A.js → planner-tab-YG0bGxDY.js} +1 -1
  81. package/build/assets/plugins-management-service-ijhH8OSh.js +1 -0
  82. package/build/assets/plus-CTGLo3aa.js +1 -0
  83. package/build/assets/profiles-service.api-C32pPm70.js +1 -0
  84. package/build/assets/providers-DuSn9s2i.js +1 -0
  85. package/build/assets/proxy-BiyDhMBd.js +1 -0
  86. package/build/assets/{puzzle-DXWdfaa7.js → puzzle-DlqT0yvr.js} +1 -1
  87. package/build/assets/{recommended-automations-launcher-BF2mtAKw.js → recommended-automations-launcher-Dru1yN46.js} +2 -2
  88. package/build/assets/{refresh-cw-D7CYLy-d.js → refresh-cw-Br5254f4.js} +1 -1
  89. package/build/assets/root-DOLLQteU.js +2 -0
  90. package/build/assets/root-layout-xmylWoew.js +3 -0
  91. package/build/assets/schema-field-htfNouTG.js +1 -0
  92. package/build/assets/{sdk-section-page-BW-i45yr.js → sdk-section-page-D0K1dBQY.js} +1 -1
  93. package/build/assets/search-BrpWXWUi.js +1 -0
  94. package/build/assets/secrets-service-Dbv5Zb8G.js +1 -0
  95. package/build/assets/{secrets-settings-D7U1ErCH.js → secrets-settings-Da4SSaX9.js} +1 -1
  96. package/build/assets/{segmented-toggle-DbbD3Tve.js → segmented-toggle-CZKOdIly.js} +1 -1
  97. package/build/assets/settings-F4a09IxY.js +1 -0
  98. package/build/assets/{settings-dropdown-input-Dx6vlkgf.js → settings-dropdown-input-jOiv5Yrk.js} +1 -1
  99. package/build/assets/{settings-index-COAdxm2Q.js → settings-index-CyJBf5NA.js} +1 -1
  100. package/build/assets/{settings-input-BjW_zyTN.js → settings-input-BEaTCem1.js} +1 -1
  101. package/build/assets/{settings-list-classes-gQdBahdt.js → settings-list-classes-VqMzkYYt.js} +1 -1
  102. package/build/assets/{settings-modal-CFnbQ8_4.js → settings-modal-C-S1NpbC.js} +1 -1
  103. package/build/assets/settings-service.api-CTJRrvMu.js +1 -0
  104. package/build/assets/{settings-switch-UNSf8K8I.js → settings-switch-B405oU_v.js} +1 -1
  105. package/build/assets/{shared-conversation-CnMxy7p_.js → shared-conversation-BvWtTwES.js} +1 -1
  106. package/build/assets/{sidebar-layout-DXHtbEj1.js → sidebar-layout-BGMuyC86.js} +1 -1
  107. package/build/assets/{sidebar-mobile-menu-toggle-U78hQRJ1.js → sidebar-mobile-menu-toggle-xiKoUfGa.js} +1 -1
  108. package/build/assets/{sidebar-nav-link-pvUivfK2.js → sidebar-nav-link-DA4_ct9G.js} +1 -1
  109. package/build/assets/{sidebar-store-DwrYKwYr.js → sidebar-store-FRJ3rADB.js} +1 -1
  110. package/build/assets/{skill-card-pill-row-D7XCz5uk.js → skill-card-pill-row-BMdhr_sd.js} +1 -1
  111. package/build/assets/{skill-icon-badge-HqBWZ2Eq.js → skill-icon-badge-CGUkgcVH.js} +1 -1
  112. package/build/assets/{skills-plugins-BPhaNpfx.js → skills-plugins-C5eJnyft.js} +1 -1
  113. package/build/assets/{skills-settings-CcwMtnnJ.js → skills-settings-pUxMr6WZ.js} +1 -1
  114. package/build/assets/{styled-tooltip-DsjDnR_W.js → styled-tooltip-B3kIdVyH.js} +1 -1
  115. package/build/assets/{task-list-tab-BmaTwjaS.js → task-list-tab-B3k4W1cK.js} +1 -1
  116. package/build/assets/{terminal-BRcoba5B.js → terminal-CBI_41Zc.js} +1 -1
  117. package/build/assets/{toggle-switch-BptY3XRG.js → toggle-switch-DYRr9CAR.js} +1 -1
  118. package/build/assets/{trash-2-Bq4lHbTB.js → trash-2-gZPlx23R.js} +1 -1
  119. package/build/assets/{typography-C6fuRTTT.js → typography-B1UxuuEC.js} +1 -1
  120. package/build/assets/{use-acp-credential-form-B0_pZ_uS.js → use-acp-credential-form-CjSvKWFH.js} +1 -1
  121. package/build/assets/use-activate-agent-profile-DCRf47e-.js +1 -0
  122. package/build/assets/use-agent-profiles-DmT9zxAN.js +1 -0
  123. package/build/assets/{use-can-manage-org-profiles-CrG1km7R.js → use-can-manage-org-profiles-vBiP7rHF.js} +1 -1
  124. package/build/assets/use-cloud-current-user-id-BMq9gw93.js +1 -0
  125. package/build/assets/use-config-C959QcRC.js +1 -0
  126. package/build/assets/{use-create-conversation-Dsa4nzU9.js → use-create-conversation-CakhLF0X.js} +1 -1
  127. package/build/assets/{use-create-secret-BnxuAjDt.js → use-create-secret-RT4QtSS9.js} +1 -1
  128. package/build/assets/use-llm-profiles-CdaxVpyY.js +1 -0
  129. package/build/assets/use-onboarding-completion-CJU4MNAY.js +1 -0
  130. package/build/assets/use-plugins-marketplace-D-93nqtJ.js +1 -0
  131. package/build/assets/{use-save-agent-profile-2Mk9ZX37.js → use-save-agent-profile-DGJ3-u0M.js} +1 -1
  132. package/build/assets/{use-save-settings-BRh9p_fv.js → use-save-settings--C6LZXfI.js} +1 -1
  133. package/build/assets/use-settings-DIAo5KFk.js +1 -0
  134. package/build/assets/use-settings-nav-items-DPK5sxvR.js +16 -0
  135. package/build/assets/use-skills-D_mLhYNa.js +1 -0
  136. package/build/assets/use-tracking-COqZLobY.js +1 -0
  137. package/build/assets/{use-user-conversation-GnGhs_Ob.js → use-user-conversation-DhcAEyJX.js} +1 -1
  138. package/build/assets/{useMutation-DyQXZFEF.js → useMutation-DHLpZ6J0.js} +1 -1
  139. package/build/assets/utils-DsWhWn2F.js +1 -0
  140. 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~g4xrpilz-CYPMCkX1.js} +1 -1
  141. package/build/assets/{vendor~files-tab-vm3f67Pz.js → vendor~files-tab-atebg0iG.js} +1 -1
  142. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-kX4LrGQC.js → vendor~index-home~home~conversation-panel~conversation-G9DMrR7m.js} +1 -1
  143. package/build/assets/{vendor~root-layout~conversation-panel~conversation-DpA6fir3.js → vendor~root-layout~conversation-panel~conversation-DEhW1h3I.js} +1 -1
  144. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-EShpjxey.js → vendor~root-layout~index-home~home~conversation-panel~conversation-Acmf1sKj.js} +1 -1
  145. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-DD_UNO02.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation-CmzCY1BT.js} +1 -1
  146. package/build/assets/{vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-Be63Q2Ln.js → vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C7Yh77RT.js} +1 -1
  147. 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~bi2r7bko-VFnwct3q.js} +1 -1
  148. package/build/assets/{verification-settings-CaCzojbc.js → verification-settings-Vr5cN4md.js} +1 -1
  149. package/build/assets/x-Dx_JbpHA.js +1 -0
  150. package/build/favicon-16x16.png +0 -0
  151. package/build/favicon-32x32.png +0 -0
  152. package/build/favicon.ico +0 -0
  153. package/build/index.html +4 -4
  154. package/build/locales/ar/openhands.json +2 -0
  155. package/build/locales/ca/openhands.json +2 -0
  156. package/build/locales/de/openhands.json +2 -0
  157. package/build/locales/en/openhands.json +2 -0
  158. package/build/locales/es/openhands.json +2 -0
  159. package/build/locales/fr/openhands.json +2 -0
  160. package/build/locales/it/openhands.json +2 -0
  161. package/build/locales/ja/openhands.json +2 -0
  162. package/build/locales/ko-KR/openhands.json +2 -0
  163. package/build/locales/no/openhands.json +2 -0
  164. package/build/locales/pt/openhands.json +2 -0
  165. package/build/locales/tr/openhands.json +2 -0
  166. package/build/locales/uk/openhands.json +2 -0
  167. package/build/locales/zh-CN/openhands.json +2 -0
  168. package/build/locales/zh-TW/openhands.json +2 -0
  169. package/config/defaults.json +4 -4
  170. package/dist/api/agent-server-adapter.cjs +1 -1
  171. package/dist/api/agent-server-adapter.cjs.map +1 -1
  172. package/dist/api/agent-server-adapter.js +7 -7
  173. package/dist/api/agent-server-adapter.js.map +1 -1
  174. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  175. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  176. package/dist/api/automation-service/automation-service.api.js +95 -95
  177. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  178. package/dist/api/backend-registry/storage.cjs +1 -1
  179. package/dist/api/backend-registry/storage.cjs.map +1 -1
  180. package/dist/api/backend-registry/storage.js +1 -1
  181. package/dist/api/backend-registry/storage.js.map +1 -1
  182. package/dist/api/backend-registry/types.d.ts +2 -0
  183. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  184. package/dist/api/cloud/conversation-service.api.js +22 -22
  185. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  186. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  187. package/dist/api/mcp-service/mcp-service.api.js +19 -19
  188. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  189. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  190. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  191. package/dist/api/settings-service/settings-service.api.js +26 -12
  192. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  193. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  194. package/dist/components/features/mcp-page/custom-server-editor.js +16 -16
  195. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  196. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  197. package/dist/components/features/mcp-page/installed-server-card.d.ts +2 -2
  198. package/dist/components/features/mcp-page/installed-server-card.js +6 -7
  199. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  200. package/dist/components/features/mcp-page/installed-servers-section.cjs +1 -1
  201. package/dist/components/features/mcp-page/installed-servers-section.cjs.map +1 -1
  202. package/dist/components/features/mcp-page/installed-servers-section.d.ts +2 -2
  203. package/dist/components/features/mcp-page/installed-servers-section.js +2 -2
  204. package/dist/components/features/mcp-page/installed-servers-section.js.map +1 -1
  205. package/dist/components/features/mcp-page/mcp-server-health.cjs +1 -1
  206. package/dist/components/features/mcp-page/mcp-server-health.js +4 -4
  207. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +1 -1
  208. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
  209. package/dist/components/features/settings/mcp-settings/mcp-server-form.js +2 -1
  210. package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
  211. package/dist/config/defaults.cjs +1 -1
  212. package/dist/config/defaults.cjs.map +1 -1
  213. package/dist/config/defaults.js +3 -3
  214. package/dist/config/defaults.js.map +1 -1
  215. package/dist/contexts/active-backend-context.cjs +1 -1
  216. package/dist/contexts/active-backend-context.cjs.map +1 -1
  217. package/dist/contexts/active-backend-context.d.ts +3 -2
  218. package/dist/contexts/active-backend-context.js +55 -42
  219. package/dist/contexts/active-backend-context.js.map +1 -1
  220. package/dist/favicon-16x16.png +0 -0
  221. package/dist/favicon-32x32.png +0 -0
  222. package/dist/favicon.ico +0 -0
  223. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  224. package/dist/hooks/mutation/use-update-mcp-server.js +5 -5
  225. package/dist/hooks/query/use-cloud-current-user-id.cjs +1 -1
  226. package/dist/hooks/query/use-cloud-current-user-id.cjs.map +1 -1
  227. package/dist/hooks/query/use-cloud-current-user-id.js +7 -5
  228. package/dist/hooks/query/use-cloud-current-user-id.js.map +1 -1
  229. package/dist/hooks/query/use-cloud-organizations.cjs +1 -1
  230. package/dist/hooks/query/use-cloud-organizations.cjs.map +1 -1
  231. package/dist/hooks/query/use-cloud-organizations.js +5 -1
  232. package/dist/hooks/query/use-cloud-organizations.js.map +1 -1
  233. package/dist/hooks/use-can-manage-org-profiles.cjs +1 -1
  234. package/dist/hooks/use-can-manage-org-profiles.cjs.map +1 -1
  235. package/dist/hooks/use-can-manage-org-profiles.js +2 -1
  236. package/dist/hooks/use-can-manage-org-profiles.js.map +1 -1
  237. package/dist/hooks/use-tracking.cjs +1 -1
  238. package/dist/hooks/use-tracking.js +9 -9
  239. package/dist/i18n/declaration.cjs +1 -1
  240. package/dist/i18n/declaration.cjs.map +1 -1
  241. package/dist/i18n/declaration.d.ts +2 -0
  242. package/dist/i18n/declaration.js +1 -1
  243. package/dist/i18n/declaration.js.map +1 -1
  244. package/dist/i18n/translation.cjs +1 -1
  245. package/dist/i18n/translation.cjs.map +1 -1
  246. package/dist/i18n/translation.js +34 -0
  247. package/dist/i18n/translation.js.map +1 -1
  248. package/dist/locales/ar/openhands.json +2 -0
  249. package/dist/locales/ca/openhands.json +2 -0
  250. package/dist/locales/de/openhands.json +2 -0
  251. package/dist/locales/en/openhands.json +2 -0
  252. package/dist/locales/es/openhands.json +2 -0
  253. package/dist/locales/fr/openhands.json +2 -0
  254. package/dist/locales/it/openhands.json +2 -0
  255. package/dist/locales/ja/openhands.json +2 -0
  256. package/dist/locales/ko-KR/openhands.json +2 -0
  257. package/dist/locales/no/openhands.json +2 -0
  258. package/dist/locales/pt/openhands.json +2 -0
  259. package/dist/locales/tr/openhands.json +2 -0
  260. package/dist/locales/uk/openhands.json +2 -0
  261. package/dist/locales/zh-CN/openhands.json +2 -0
  262. package/dist/locales/zh-TW/openhands.json +2 -0
  263. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs +1 -1
  264. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.cjs.map +1 -1
  265. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js +9 -0
  266. package/dist/node_modules/@openhands/typescript-client/dist/client/settings-client.js.map +1 -1
  267. package/dist/package.cjs +1 -1
  268. package/dist/package.cjs.map +1 -1
  269. package/dist/package.js +2 -2
  270. package/dist/package.js.map +1 -1
  271. package/dist/routes/app-settings.cjs +1 -1
  272. package/dist/routes/app-settings.js +5 -5
  273. package/dist/routes/mcp.cjs +1 -1
  274. package/dist/routes/mcp.cjs.map +1 -1
  275. package/dist/routes/mcp.js +73 -82
  276. package/dist/routes/mcp.js.map +1 -1
  277. package/dist/services/telemetry.cjs +1 -1
  278. package/dist/services/telemetry.cjs.map +1 -1
  279. package/dist/services/telemetry.d.ts +8 -0
  280. package/dist/services/telemetry.js +163 -116
  281. package/dist/services/telemetry.js.map +1 -1
  282. package/dist/types/mcp-server.d.ts +5 -0
  283. package/dist/types/settings.d.ts +3 -0
  284. package/dist/utils/mcp-config.cjs +1 -1
  285. package/dist/utils/mcp-config.cjs.map +1 -1
  286. package/dist/utils/mcp-config.d.ts +8 -0
  287. package/dist/utils/mcp-config.js +25 -20
  288. package/dist/utils/mcp-config.js.map +1 -1
  289. package/dist/utils/mcp-installed-servers.cjs +1 -1
  290. package/dist/utils/mcp-installed-servers.cjs.map +1 -1
  291. package/dist/utils/mcp-installed-servers.js +6 -3
  292. package/dist/utils/mcp-installed-servers.js.map +1 -1
  293. package/package.json +2 -2
  294. package/scripts/check-sdk-version-sync.mjs +6 -6
  295. package/scripts/dev-safe.mjs +2 -2
  296. package/build/assets/active-backend-context-BlZPzZNU.js +0 -1
  297. package/build/assets/agent-server-conversation-service.api-Btmi4q6d.js +0 -41
  298. package/build/assets/agent-settings-KQs-occT.js +0 -1
  299. package/build/assets/api-key-entry-screen-BhR24gkM.js +0 -1
  300. package/build/assets/app-settings-Bs4sY8WP.js +0 -1
  301. package/build/assets/automation-detail-CwDnJbYR.js +0 -2
  302. package/build/assets/backend-form-modal-Ce-KRHOJ.js +0 -1
  303. package/build/assets/check-BMOG005H.js +0 -1
  304. package/build/assets/chevron-down-CV1zZP_K.js +0 -1
  305. package/build/assets/circle-check-lvN_jFN5.js +0 -1
  306. package/build/assets/client-source-1v-kWLNU.js +0 -1
  307. package/build/assets/cloud-funnel-analytics-CasMM7EO.js +0 -1
  308. package/build/assets/conversation-C25pc2dT.js +0 -1
  309. package/build/assets/conversation-CObLYSJd.js +0 -90
  310. package/build/assets/conversation-panel-C25pc2dT.js +0 -1
  311. package/build/assets/conversation-state-store-DTq4hFoP.js +0 -1
  312. package/build/assets/extensions-hub-BKftOQ-X.js +0 -1
  313. package/build/assets/extensions-navigation-DF24q1H1.js +0 -1
  314. package/build/assets/files-tab-SAiFCnS5.js +0 -1
  315. package/build/assets/git-provider-icon-BREx-yUX.js +0 -1
  316. package/build/assets/home-EPNFgzUh.js +0 -1
  317. package/build/assets/index-home-EPNFgzUh.js +0 -1
  318. package/build/assets/install-server-modal-BI8yUfmr.js +0 -1
  319. package/build/assets/llm-settings-BXk5_Pac.js +0 -1
  320. package/build/assets/llm-settings-C1vpgWam.js +0 -1
  321. package/build/assets/loader-circle-6zlEYCJw.js +0 -1
  322. package/build/assets/manage-backends-modal-DhflyGTf.js +0 -1
  323. package/build/assets/manifest-8082e879.js +0 -1
  324. package/build/assets/markdown-renderer-CvOO0YIr.js +0 -8
  325. package/build/assets/mcp-CxLPda-W.js +0 -9
  326. package/build/assets/onboarding-modal-DdvE6rzw.js +0 -1
  327. package/build/assets/organization-service.api-CT2OQlLz.js +0 -1
  328. package/build/assets/plugins-management-service-DVkoM3eA.js +0 -1
  329. package/build/assets/plus-vIbGD459.js +0 -1
  330. package/build/assets/profiles-service.api-CBafmAPO.js +0 -1
  331. package/build/assets/providers-9UzRB9mT.js +0 -1
  332. package/build/assets/proxy-C79PCMjo.js +0 -1
  333. package/build/assets/root-Sj7W28yE.js +0 -2
  334. package/build/assets/root-layout-DbhKVoc7.js +0 -3
  335. package/build/assets/schema-field-CV6bFnoL.js +0 -1
  336. package/build/assets/search-sKuYKllf.js +0 -1
  337. package/build/assets/secrets-service-BjK-bPN2.js +0 -1
  338. package/build/assets/settings-Bj5Oo45A.js +0 -1
  339. package/build/assets/settings-service.api-DryhKdSr.js +0 -1
  340. package/build/assets/telemetry-cmCL3o6Z.js +0 -2
  341. package/build/assets/use-activate-agent-profile-DH33MvVj.js +0 -1
  342. package/build/assets/use-agent-profiles-Dmd_4H8q.js +0 -1
  343. package/build/assets/use-cloud-current-user-id-B6DP3s47.js +0 -1
  344. package/build/assets/use-config-Csy8EAP9.js +0 -1
  345. package/build/assets/use-llm-profiles-BMQoc612.js +0 -1
  346. package/build/assets/use-onboarding-completion-B-2BTS-y.js +0 -1
  347. package/build/assets/use-plugins-marketplace-PBc_XNz_.js +0 -1
  348. package/build/assets/use-settings-DBI44RnH.js +0 -1
  349. package/build/assets/use-settings-nav-items-Cva28C-c.js +0 -16
  350. package/build/assets/use-skills-RQsCtdzN.js +0 -1
  351. package/build/assets/use-tracking-CN1nIMnY.js +0 -1
  352. package/build/assets/utils-qjs_KuS4.js +0 -1
  353. package/build/assets/x-EjvKGawc.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-config.cjs","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-config.cjs","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\n/**\n * Only an explicit ``false`` is carried. Every mutation round-trips the whole\n * server map through these converters, so preserving the flag here is what\n * stops adding or deleting one server from silently re-enabling another.\n */\nfunction disabledField(server: { enabled?: boolean }) {\n return server.enabled === false ? { enabled: false as const } : {};\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n ...disabledField(server),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n ...disabledField(server),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n // The SDK omits ``enabled`` while it holds its default (true), so only an\n // explicit ``false`` marks a server as switched off.\n const disabled = serverConfig.enabled === false;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n if (disabled) stdioServer.enabled = false;\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n *\n * ``enabled`` is only emitted when a server is switched off — the SDK defaults\n * it to true. Omitting it is what *clears* a previously persisted\n * ``enabled: false``, and that only works because ``saveSettings`` pre-clears\n * ``mcp_config`` to null before every write (see\n * ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a\n * full replace. If that pre-clear is ever removed, re-enabling a server\n * becomes a silent no-op.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n Object.assign(server, disabledField(entry));\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
@@ -26,6 +26,14 @@ export declare function parseMcpConfig(value: unknown): MCPConfig;
26
26
  * persisted ahead of it, and shift the suffix on every save as the count
27
27
  * of other server types changes. With per-base collision suffixing,
28
28
  * unrelated entries keep their human-meaningful names stable across edits.
29
+ *
30
+ * ``enabled`` is only emitted when a server is switched off — the SDK defaults
31
+ * it to true. Omitting it is what *clears* a previously persisted
32
+ * ``enabled: false``, and that only works because ``saveSettings`` pre-clears
33
+ * ``mcp_config`` to null before every write (see
34
+ * ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a
35
+ * full replace. If that pre-clear is ever removed, re-enabling a server
36
+ * becomes a silent no-op.
29
37
  */
30
38
  export declare function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null;
31
39
  export {};
@@ -54,7 +54,7 @@ function l(e) {
54
54
  } : void 0;
55
55
  }
56
56
  case "oauth2": {
57
- let t = g(e.authentication), n = c(e.state);
57
+ let t = _(e.authentication), n = c(e.state);
58
58
  return {
59
59
  strategy: "oauth2",
60
60
  ...t && { authentication: t },
@@ -72,52 +72,57 @@ function d(e) {
72
72
  return e.auth && !s(e.auth) && (t.auth = e.auth), e.headers && Object.keys(e.headers).length > 0 && (t.headers = e.headers), t;
73
73
  }
74
74
  function f(e) {
75
+ return e.enabled === !1 ? { enabled: !1 } : {};
76
+ }
77
+ function p(e) {
75
78
  return {
76
79
  ...e.name && { name: e.name },
77
80
  url: e.url,
78
81
  ...e.headers && { headers: e.headers },
79
- ...e.auth && { auth: e.auth }
82
+ ...e.auth && { auth: e.auth },
83
+ ...f(e)
80
84
  };
81
85
  }
82
- function p(e) {
83
- return f(e);
84
- }
85
86
  function m(e) {
87
+ return p(e);
88
+ }
89
+ function h(e) {
86
90
  return {
87
- ...f(e),
91
+ ...p(e),
88
92
  ...e.timeout !== void 0 && { timeout: e.timeout }
89
93
  };
90
94
  }
91
- function h(e) {
95
+ function g(e) {
92
96
  return {
93
97
  name: e.name,
94
98
  command: e.command,
95
99
  ...e.args && { args: e.args },
96
- ...e.env && { env: e.env }
100
+ ...e.env && { env: e.env },
101
+ ...f(e)
97
102
  };
98
103
  }
99
- function g(e) {
104
+ function _(e) {
100
105
  if (!e || typeof e != "object") return;
101
106
  let t = e;
102
107
  if (t.type !== "oauth") return;
103
108
  let n = { type: "oauth" };
104
109
  return (t.client_auth_method === "none" || t.client_auth_method === "client_secret_post" || t.client_auth_method === "client_secret_basic" || t.client_auth_method === "private_key_jwt") && (n.client_auth_method = t.client_auth_method), (typeof t.scopes == "string" || Array.isArray(t.scopes) && t.scopes.every((e) => typeof e == "string")) && (n.scopes = t.scopes), typeof t.client_name == "string" && (n.client_name = t.client_name), typeof t.client_metadata_url == "string" && (n.client_metadata_url = t.client_metadata_url), typeof t.client_id == "string" && (n.client_id = t.client_id), typeof t.client_secret == "string" && (n.client_secret = t.client_secret), t.additional_client_metadata && typeof t.additional_client_metadata == "object" && !Array.isArray(t.additional_client_metadata) && (n.additional_client_metadata = t.additional_client_metadata), n;
105
110
  }
106
- function _(e) {
111
+ function v(e) {
107
112
  let n = a(e);
108
113
  if (!n) return { ...t };
109
114
  let s = [], c = [], l = [];
110
115
  for (let [e, t] of Object.entries(n)) {
111
116
  if (!i(t)) continue;
112
- let n = t.url;
117
+ let n = t.url, a = t.enabled === !1;
113
118
  if (n) {
114
- let i = t.transport, a = u(t), c = o(t.headers);
119
+ let i = t.transport, c = u(t), d = o(t.headers);
115
120
  if (i === "sse") {
116
121
  let t = r(e, "sse"), i = { url: n };
117
- t && (i.name = t), a && (i.auth = a), c && (i.headers = c), s.push(i);
122
+ t && (i.name = t), c && (i.auth = c), d && (i.headers = d), a && (i.enabled = !1), s.push(i);
118
123
  } else {
119
124
  let i = r(e, "shttp"), o = { url: n };
120
- i && (o.name = i), t.timeout != null && (o.timeout = t.timeout), a && (o.auth = a), c && (o.headers = c), l.push(o);
125
+ i && (o.name = i), t.timeout != null && (o.timeout = t.timeout), c && (o.auth = c), d && (o.headers = d), a && (o.enabled = !1), l.push(o);
121
126
  }
122
127
  } else {
123
128
  if (typeof t.command != "string") continue;
@@ -125,7 +130,7 @@ function _(e) {
125
130
  name: e,
126
131
  command: t.command
127
132
  };
128
- t.args && (n.args = t.args), t.env && (n.env = t.env), c.push(n);
133
+ t.args && (n.args = t.args), t.env && (n.env = t.env), a && (n.enabled = !1), c.push(n);
129
134
  }
130
135
  }
131
136
  return {
@@ -134,7 +139,7 @@ function _(e) {
134
139
  shttp_servers: l
135
140
  };
136
141
  }
137
- function v(t) {
142
+ function y(t) {
138
143
  let n = {}, r = (t) => {
139
144
  let r = e(t);
140
145
  if (!(r in n)) return r;
@@ -144,19 +149,19 @@ function v(t) {
144
149
  };
145
150
  for (let e of t.sse_servers) {
146
151
  let t = {}, i;
147
- typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e))), t.transport = "sse", n[r(i || "sse")] = t;
152
+ typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e), f(e))), t.transport = "sse", n[r(i || "sse")] = t;
148
153
  }
149
154
  for (let e of t.shttp_servers) {
150
155
  let t = { transport: "http" }, i;
151
- typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e)), e.timeout != null && (t.timeout = e.timeout)), n[r(i || "shttp")] = t;
156
+ typeof e == "string" ? t.url = e : (i = e.name, t.url = e.url, Object.assign(t, d(e), f(e)), e.timeout != null && (t.timeout = e.timeout)), n[r(i || "shttp")] = t;
152
157
  }
153
158
  for (let e of t.stdio_servers) {
154
159
  let t = { command: e.command };
155
- e.args && (t.args = e.args), e.env && (t.env = e.env), n[r(e.name || "stdio")] = t;
160
+ e.args && (t.args = e.args), e.env && (t.env = e.env), Object.assign(t, f(e)), n[r(e.name || "stdio")] = t;
156
161
  }
157
162
  return Object.keys(n).length > 0 ? n : null;
158
163
  }
159
164
  //#endregion
160
- export { n as REDACTED_MCP_SECRET_VALUE, a as getSdkMcpServerMap, s as hasRedactedMcpSecretLeaf, _ as parseMcpConfig, o as stringRecord, m as toMcpShttpServer, p as toMcpSseServer, h as toMcpStdioServer, v as toSdkMcpConfig };
165
+ export { n as REDACTED_MCP_SECRET_VALUE, a as getSdkMcpServerMap, s as hasRedactedMcpSecretLeaf, v as parseMcpConfig, o as stringRecord, h as toMcpShttpServer, m as toMcpSseServer, g as toMcpStdioServer, y as toSdkMcpConfig };
161
166
 
162
167
  //# sourceMappingURL=mcp-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-config.js","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-config.js","names":[],"sources":["../../src/utils/mcp-config.ts"],"sourcesContent":["import {\n MCPConfig,\n MCPSSEServer,\n MCPSHTTPServer,\n MCPStdioServer,\n SettingsValue,\n} from \"#/types/settings\";\nimport type {\n MCPAuthCredential,\n MCPAuthenticationConfig,\n MCPJsonValue,\n MCPOAuthState,\n} from \"#/types/mcp-auth\";\nimport type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { toMcpServerName } from \"#/utils/mcp-server-name\";\n\nconst EMPTY_MCP_CONFIG: MCPConfig = {\n sse_servers: [],\n stdio_servers: [],\n shttp_servers: [],\n};\n\nexport const REDACTED_MCP_SECRET_VALUE = \"**********\";\n\ntype SdkMcpServerConfig = Record<string, SettingsValue | MCPAuthCredential>;\ntype SdkMcpConfig = Record<string, SdkMcpServerConfig>;\n\n/**\n * The dict key for an SSE/SHTTP server doubles as its display name once a\n * user provides one. Keys that match the auto-generated fallback pattern\n * (``sse``, ``shttp``, ``shttp_1``, …) emitted by {@link toSdkMcpConfig}\n * carry no user intent, so we surface them as \"no name\" — re-serializing\n * regenerates the identical fallback key and existing configs are left\n * untouched.\n */\nfunction userGivenServerName(\n serverName: string,\n base: \"sse\" | \"shttp\",\n): string | undefined {\n const autoGenerated = new RegExp(`^${base}(_\\\\d+)?$`);\n return autoGenerated.test(serverName) ? undefined : serverName;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function getSdkMcpServerMap(\n value: unknown,\n): Record<string, unknown> | null {\n if (!isRecord(value)) return null;\n\n const mcpServers = value.mcpServers;\n if (\n isRecord(mcpServers) &&\n !(\"url\" in mcpServers) &&\n !(\"command\" in mcpServers)\n ) {\n return mcpServers;\n }\n\n return value;\n}\n\nexport function stringRecord(\n value: unknown,\n): Record<string, string> | undefined {\n if (!isRecord(value)) return undefined;\n const entries = Object.entries(value).filter(\n (entry): entry is [string, string] => typeof entry[1] === \"string\",\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nexport function hasRedactedMcpSecretLeaf(value: unknown): boolean {\n if (value === REDACTED_MCP_SECRET_VALUE) return true;\n if (Array.isArray(value)) return value.some(hasRedactedMcpSecretLeaf);\n if (isRecord(value))\n return Object.values(value).some(hasRedactedMcpSecretLeaf);\n return false;\n}\n\nfunction getOAuthState(value: unknown): MCPOAuthState | undefined {\n if (!isRecord(value)) return undefined;\n const state: MCPOAuthState = {};\n if (isRecord(value.tokens)) {\n state.tokens = value.tokens as NonNullable<MCPOAuthState[\"tokens\"]>;\n }\n if (isRecord(value.client_info)) {\n state.client_info = value.client_info as NonNullable<\n MCPOAuthState[\"client_info\"]\n >;\n }\n if (\n typeof value.token_expires_at === \"number\" ||\n value.token_expires_at === null\n ) {\n state.token_expires_at = value.token_expires_at;\n }\n return Object.keys(state).length > 0 ? state : undefined;\n}\n\nfunction normalizeTaggedAuthCredential(\n value: unknown,\n): MCPAuthCredential | undefined {\n if (!isRecord(value)) return undefined;\n switch (value.strategy) {\n case \"none\":\n return { strategy: \"none\" };\n case \"api_key\":\n if (typeof value.value !== \"string\") return undefined;\n return {\n strategy: \"api_key\",\n value: value.value,\n ...(typeof value.header_name === \"string\" && {\n header_name: value.header_name,\n }),\n };\n case \"bearer\":\n if (typeof value.value !== \"string\") return undefined;\n return { strategy: \"bearer\", value: value.value };\n case \"basic\":\n if (\n typeof value.username !== \"string\" ||\n typeof value.password !== \"string\"\n ) {\n return undefined;\n }\n return {\n strategy: \"basic\",\n username: value.username,\n password: value.password,\n };\n case \"header\": {\n const headers = stringRecord(value.headers);\n return headers ? { strategy: \"header\", headers } : undefined;\n }\n case \"oauth2\": {\n const authentication = getAuthenticationConfig(value.authentication);\n const state = getOAuthState(value.state);\n return {\n strategy: \"oauth2\",\n ...(authentication && { authentication }),\n ...(state && { state }),\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction authCredentialFromServerConfig(\n serverConfig: Record<string, unknown>,\n): MCPAuthCredential | undefined {\n return normalizeTaggedAuthCredential(serverConfig.auth);\n}\n\nfunction getRemoteSecretFields(entry: {\n auth?: MCPAuthCredential;\n headers?: Record<string, string>;\n}): Partial<SdkMcpServerConfig> {\n const fields: Partial<SdkMcpServerConfig> = {};\n if (entry.auth && !hasRedactedMcpSecretLeaf(entry.auth)) {\n fields.auth = entry.auth;\n }\n if (entry.headers && Object.keys(entry.headers).length > 0) {\n fields.headers = entry.headers;\n }\n return fields;\n}\n\n/**\n * Only an explicit ``false`` is carried. Every mutation round-trips the whole\n * server map through these converters, so preserving the flag here is what\n * stops adding or deleting one server from silently re-enabling another.\n */\nfunction disabledField(server: { enabled?: boolean }) {\n return server.enabled === false ? { enabled: false as const } : {};\n}\n\nfunction getRemoteServerFields(server: MCPServerConfig) {\n return {\n ...(server.name && { name: server.name }),\n url: server.url!,\n ...(server.headers && { headers: server.headers }),\n ...(server.auth && { auth: server.auth }),\n ...disabledField(server),\n };\n}\n\nexport function toMcpSseServer(server: MCPServerConfig): MCPSSEServer {\n return getRemoteServerFields(server);\n}\n\nexport function toMcpShttpServer(server: MCPServerConfig): MCPSHTTPServer {\n return {\n ...getRemoteServerFields(server),\n ...(server.timeout !== undefined && { timeout: server.timeout }),\n };\n}\n\nexport function toMcpStdioServer(server: MCPServerConfig): MCPStdioServer {\n return {\n name: server.name!,\n command: server.command!,\n ...(server.args && { args: server.args }),\n ...(server.env && { env: server.env }),\n ...disabledField(server),\n };\n}\n\nfunction getAuthenticationConfig(\n value: unknown,\n): MCPAuthenticationConfig | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n if (record.type !== \"oauth\") return undefined;\n const authentication: MCPAuthenticationConfig = { type: \"oauth\" };\n if (\n record.client_auth_method === \"none\" ||\n record.client_auth_method === \"client_secret_post\" ||\n record.client_auth_method === \"client_secret_basic\" ||\n record.client_auth_method === \"private_key_jwt\"\n ) {\n authentication.client_auth_method = record.client_auth_method;\n }\n if (typeof record.scopes === \"string\") {\n authentication.scopes = record.scopes;\n } else if (\n Array.isArray(record.scopes) &&\n record.scopes.every((scope) => typeof scope === \"string\")\n ) {\n authentication.scopes = record.scopes;\n }\n if (typeof record.client_name === \"string\") {\n authentication.client_name = record.client_name;\n }\n if (typeof record.client_metadata_url === \"string\") {\n authentication.client_metadata_url = record.client_metadata_url;\n }\n if (typeof record.client_id === \"string\") {\n authentication.client_id = record.client_id;\n }\n if (typeof record.client_secret === \"string\") {\n authentication.client_secret = record.client_secret;\n }\n if (\n record.additional_client_metadata &&\n typeof record.additional_client_metadata === \"object\" &&\n !Array.isArray(record.additional_client_metadata)\n ) {\n authentication.additional_client_metadata =\n record.additional_client_metadata as Record<string, MCPJsonValue>;\n }\n return authentication;\n}\n\n/**\n * Parse the SDK-native ``agent_settings.mcp_config`` value and convert it\n * to the frontend MCPConfig format used by UI components.\n */\nexport function parseMcpConfig(value: unknown): MCPConfig {\n const mcpConfig = getSdkMcpServerMap(value);\n if (!mcpConfig) {\n return { ...EMPTY_MCP_CONFIG };\n }\n\n const sseServers: (string | MCPSSEServer)[] = [];\n const stdioServers: MCPStdioServer[] = [];\n const shttpServers: (string | MCPSHTTPServer)[] = [];\n\n for (const [serverName, serverConfig] of Object.entries(mcpConfig)) {\n if (!isRecord(serverConfig)) continue;\n\n const url = serverConfig.url as string | undefined;\n\n // The SDK omits ``enabled`` while it holds its default (true), so only an\n // explicit ``false`` marks a server as switched off.\n const disabled = serverConfig.enabled === false;\n\n if (url) {\n const transport = serverConfig.transport as string | undefined;\n const auth = authCredentialFromServerConfig(serverConfig);\n const headers = stringRecord(serverConfig.headers);\n\n if (transport === \"sse\") {\n const name = userGivenServerName(serverName, \"sse\");\n const server: MCPSSEServer = { url };\n if (name) server.name = name;\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n sseServers.push(server);\n } else {\n const name = userGivenServerName(serverName, \"shttp\");\n const server: MCPSHTTPServer = { url };\n if (name) server.name = name;\n if (serverConfig.timeout != null) {\n server.timeout = serverConfig.timeout as number;\n }\n if (auth) server.auth = auth;\n if (headers) server.headers = headers;\n if (disabled) server.enabled = false;\n shttpServers.push(server);\n }\n } else {\n if (typeof serverConfig.command !== \"string\") continue;\n const stdioServer: MCPStdioServer = {\n name: serverName,\n command: serverConfig.command,\n };\n if (serverConfig.args) {\n stdioServer.args = serverConfig.args as string[];\n }\n if (serverConfig.env) {\n stdioServer.env = serverConfig.env as Record<string, string>;\n }\n if (disabled) stdioServer.enabled = false;\n stdioServers.push(stdioServer);\n }\n }\n\n return {\n sse_servers: sseServers,\n stdio_servers: stdioServers,\n shttp_servers: shttpServers,\n };\n}\n\n/**\n * Convert the frontend MCPConfig format back to the SDK-native server map\n * expected by agent_settings.mcp_config on the backend.\n *\n * Names are only suffixed (``_1``, ``_2``, …) when an earlier entry has\n * already claimed the bare base name. We intentionally do NOT use a single\n * monotonic counter across server types: that would, for example, rename a\n * stdio server \"myname\" to \"myname_1\" the moment any sse/shttp entry is\n * persisted ahead of it, and shift the suffix on every save as the count\n * of other server types changes. With per-base collision suffixing,\n * unrelated entries keep their human-meaningful names stable across edits.\n *\n * ``enabled`` is only emitted when a server is switched off — the SDK defaults\n * it to true. Omitting it is what *clears* a previously persisted\n * ``enabled: false``, and that only works because ``saveSettings`` pre-clears\n * ``mcp_config`` to null before every write (see\n * ``settings-service.api.ts``), turning the backend's RFC 7386 merge into a\n * full replace. If that pre-clear is ever removed, re-enabling a server\n * becomes a silent no-op.\n */\nexport function toSdkMcpConfig(config: MCPConfig): SdkMcpConfig | null {\n const mcpConfig: SdkMcpConfig = {};\n\n const reserve = (base: string): string => {\n const safeBase = toMcpServerName(base);\n if (!(safeBase in mcpConfig)) return safeBase;\n let i = 1;\n while (`${safeBase}_${i}` in mcpConfig) i += 1;\n return `${safeBase}_${i}`;\n };\n\n for (const entry of config.sse_servers) {\n const server: SdkMcpServerConfig = {};\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n }\n server.transport = \"sse\";\n mcpConfig[reserve(name || \"sse\")] = server;\n }\n\n for (const entry of config.shttp_servers) {\n const server: SdkMcpServerConfig = { transport: \"http\" };\n let name: string | undefined;\n if (typeof entry === \"string\") {\n server.url = entry;\n } else {\n name = entry.name;\n server.url = entry.url;\n Object.assign(server, getRemoteSecretFields(entry), disabledField(entry));\n if (entry.timeout != null) server.timeout = entry.timeout;\n }\n mcpConfig[reserve(name || \"shttp\")] = server;\n }\n\n for (const entry of config.stdio_servers) {\n const server: SdkMcpServerConfig = {\n command: entry.command,\n };\n if (entry.args) server.args = entry.args;\n if (entry.env) server.env = entry.env;\n Object.assign(server, disabledField(entry));\n mcpConfig[reserve(entry.name || \"stdio\")] = server;\n }\n\n return Object.keys(mcpConfig).length > 0 ? mcpConfig : null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../_virtual/_rolldown/runtime.cjs");function e(e){return[...e.sse_servers.map((e,t)=>({id:`sse-${t}`,type:`sse`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,auth:typeof e==`object`?e.auth:void 0})),...e.stdio_servers.map((e,t)=>({id:`stdio-${t}`,type:`stdio`,name:e.name,command:e.command,args:e.args,env:e.env})),...e.shttp_servers.map((e,t)=>({id:`shttp-${t}`,type:`shttp`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,timeout:typeof e==`object`?e.timeout:void 0,auth:typeof e==`object`?e.auth:void 0}))]}exports.flattenMcpConfig=e;
1
+ require("../_virtual/_rolldown/runtime.cjs");function e(e){return[...e.sse_servers.map((e,t)=>({id:`sse-${t}`,type:`sse`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,auth:typeof e==`object`?e.auth:void 0,enabled:typeof e==`object`?e.enabled:void 0})),...e.stdio_servers.map((e,t)=>({id:`stdio-${t}`,type:`stdio`,name:e.name,command:e.command,args:e.args,env:e.env,enabled:e.enabled})),...e.shttp_servers.map((e,t)=>({id:`shttp-${t}`,type:`shttp`,name:typeof e==`object`?e.name:void 0,url:typeof e==`string`?e:e.url,headers:typeof e==`object`?e.headers:void 0,timeout:typeof e==`object`?e.timeout:void 0,auth:typeof e==`object`?e.auth:void 0,enabled:typeof e==`object`?e.enabled:void 0}))]}exports.flattenMcpConfig=e;
2
2
  //# sourceMappingURL=mcp-installed-servers.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-installed-servers.cjs","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ];\n}\n"],"mappings":"6CAGA,SAAgB,EAAiB,EAAsC,CACrE,MAAO,CACL,GAAG,EAAO,YAAY,KAAK,EAAQ,KAAW,CAC5C,GAAI,OAAO,IACX,KAAM,MACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,EACnD,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,EAAO,KACb,QAAS,EAAO,QAChB,KAAM,EAAO,KACb,IAAK,EAAO,GACd,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,EACnD,EAAE,CACJ,CACF"}
1
+ {"version":3,"file":"mcp-installed-servers.cjs","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n enabled: server.enabled,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ];\n}\n"],"mappings":"6CAGA,SAAgB,EAAiB,EAAsC,CACrE,MAAO,CACL,GAAG,EAAO,YAAY,KAAK,EAAQ,KAAW,CAC5C,GAAI,OAAO,IACX,KAAM,MACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,EACzD,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,EAAO,KACb,QAAS,EAAO,QAChB,KAAM,EAAO,KACb,IAAK,EAAO,IACZ,QAAS,EAAO,OAClB,EAAE,EACF,GAAG,EAAO,cAAc,KAAK,EAAQ,KAAW,CAC9C,GAAI,SAAS,IACb,KAAM,QACN,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,IAAK,OAAO,GAAW,SAAW,EAAS,EAAO,IAClD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,GACvD,KAAM,OAAO,GAAW,SAAW,EAAO,KAAO,IAAA,GACjD,QAAS,OAAO,GAAW,SAAW,EAAO,QAAU,IAAA,EACzD,EAAE,CACJ,CACF"}
@@ -7,7 +7,8 @@ function e(e) {
7
7
  name: typeof e == "object" ? e.name : void 0,
8
8
  url: typeof e == "string" ? e : e.url,
9
9
  headers: typeof e == "object" ? e.headers : void 0,
10
- auth: typeof e == "object" ? e.auth : void 0
10
+ auth: typeof e == "object" ? e.auth : void 0,
11
+ enabled: typeof e == "object" ? e.enabled : void 0
11
12
  })),
12
13
  ...e.stdio_servers.map((e, t) => ({
13
14
  id: `stdio-${t}`,
@@ -15,7 +16,8 @@ function e(e) {
15
16
  name: e.name,
16
17
  command: e.command,
17
18
  args: e.args,
18
- env: e.env
19
+ env: e.env,
20
+ enabled: e.enabled
19
21
  })),
20
22
  ...e.shttp_servers.map((e, t) => ({
21
23
  id: `shttp-${t}`,
@@ -24,7 +26,8 @@ function e(e) {
24
26
  url: typeof e == "string" ? e : e.url,
25
27
  headers: typeof e == "object" ? e.headers : void 0,
26
28
  timeout: typeof e == "object" ? e.timeout : void 0,
27
- auth: typeof e == "object" ? e.auth : void 0
29
+ auth: typeof e == "object" ? e.auth : void 0,
30
+ enabled: typeof e == "object" ? e.enabled : void 0
28
31
  }))
29
32
  ];
30
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-installed-servers.js","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n })),\n ];\n}\n"],"mappings":";AAGA,SAAgB,EAAiB,GAAsC;CACrE,OAAO;EACL,GAAG,EAAO,YAAY,KAAK,GAAQ,OAAW;GAC5C,IAAI,OAAO;GACX,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;EACnD,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,EAAO;GACb,SAAS,EAAO;GAChB,MAAM,EAAO;GACb,KAAK,EAAO;EACd,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;EACnD,EAAE;CACJ;AACF"}
1
+ {"version":3,"file":"mcp-installed-servers.js","names":[],"sources":["../../src/utils/mcp-installed-servers.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport { MCPConfig } from \"#/types/settings\";\n\nexport function flattenMcpConfig(config: MCPConfig): MCPServerConfig[] {\n return [\n ...config.sse_servers.map((server, index) => ({\n id: `sse-${index}`,\n type: \"sse\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ...config.stdio_servers.map((server, index) => ({\n id: `stdio-${index}`,\n type: \"stdio\" as const,\n name: server.name,\n command: server.command,\n args: server.args,\n env: server.env,\n enabled: server.enabled,\n })),\n ...config.shttp_servers.map((server, index) => ({\n id: `shttp-${index}`,\n type: \"shttp\" as const,\n name: typeof server === \"object\" ? server.name : undefined,\n url: typeof server === \"string\" ? server : server.url,\n headers: typeof server === \"object\" ? server.headers : undefined,\n timeout: typeof server === \"object\" ? server.timeout : undefined,\n auth: typeof server === \"object\" ? server.auth : undefined,\n enabled: typeof server === \"object\" ? server.enabled : undefined,\n })),\n ];\n}\n"],"mappings":";AAGA,SAAgB,EAAiB,GAAsC;CACrE,OAAO;EACL,GAAG,EAAO,YAAY,KAAK,GAAQ,OAAW;GAC5C,IAAI,OAAO;GACX,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;EACzD,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,EAAO;GACb,SAAS,EAAO;GAChB,MAAM,EAAO;GACb,KAAK,EAAO;GACZ,SAAS,EAAO;EAClB,EAAE;EACF,GAAG,EAAO,cAAc,KAAK,GAAQ,OAAW;GAC9C,IAAI,SAAS;GACb,MAAM;GACN,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,KAAK,OAAO,KAAW,WAAW,IAAS,EAAO;GAClD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;GACvD,MAAM,OAAO,KAAW,WAAW,EAAO,OAAO,KAAA;GACjD,SAAS,OAAO,KAAW,WAAW,EAAO,UAAU,KAAA;EACzD,EAAE;CACJ;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/agent-canvas",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -24,7 +24,7 @@
24
24
  "@microlink/react-json-view": "1.31.20",
25
25
  "@monaco-editor/react": "4.7.0",
26
26
  "@openhands/extensions": "0.11.0",
27
- "@openhands/typescript-client": "1.34.0",
27
+ "@openhands/typescript-client": "1.36.1",
28
28
  "@react-router/node": "7.17.0",
29
29
  "@react-router/serve": "7.17.0",
30
30
  "@tailwindcss/vite": "4.2.4",
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * Usage:
21
21
  * node scripts/check-sdk-version-sync.mjs
22
- * EXPECTED_SDK_VERSION=1.38.0 node scripts/check-sdk-version-sync.mjs
22
+ * EXPECTED_SDK_VERSION=1.39.1 node scripts/check-sdk-version-sync.mjs
23
23
  * node scripts/check-sdk-version-sync.mjs --check-pypi
24
24
  *
25
25
  * Environment variables:
@@ -78,7 +78,7 @@ Triggering from other repos:
78
78
  -H "Authorization: token \$GITHUB_TOKEN" \\
79
79
  -H "Accept: application/vnd.github.v3+json" \\
80
80
  https://api.github.com/repos/OpenHands/OpenHands/dispatches \\
81
- -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.38.0"}}'
81
+ -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.39.1"}}'
82
82
  `);
83
83
  process.exit(0);
84
84
  }
@@ -260,9 +260,9 @@ async function fetchPyPIDependencies(packageName, version) {
260
260
  * Parse PyPI requires_dist array and extract SDK package versions
261
261
  *
262
262
  * PyPI returns dependencies in PEP 508 format like:
263
- * "openhands-sdk>=1.38.0,<2.0.0"
264
- * "openhands-tools==1.38.0"
265
- * "openhands-workspace (>=1.38.0)"
263
+ * "openhands-sdk>=1.39.1,<2.0.0"
264
+ * "openhands-tools==1.39.1"
265
+ * "openhands-workspace (>=1.39.1)"
266
266
  */
267
267
  function parseSdkVersionsFromRequiresDist(requiresDist) {
268
268
  const versions = {};
@@ -276,7 +276,7 @@ function parseSdkVersionsFromRequiresDist(requiresDist) {
276
276
  }
277
277
 
278
278
  // Extract the version number - look for patterns like:
279
- // ">=1.38.0", "==1.38.0", "(>=1.38.0)", "~=1.38.0"
279
+ // ">=1.39.1", "==1.39.1", "(>=1.39.1)", "~=1.39.1"
280
280
  // After the package name and before any comma or closing paren
281
281
  const versionPattern = /[><=~!]+\s*([0-9]+(?:\.[0-9]+)*)/;
282
282
  const match = dep.match(versionPattern);
@@ -48,7 +48,7 @@ const LOCAL_AGENT_SERVER_SUBDIRS = [
48
48
  "openhands-workspace",
49
49
  ];
50
50
  const DEFAULT_AGENT_SERVER_VERSION = SHARED_DEFAULTS.versions.agentServer;
51
- // Temporary transitive-dep pin: openhands-sdk 1.38.0 leaves agent-client-protocol
51
+ // Temporary transitive-dep pin: openhands-sdk 1.39.1 leaves agent-client-protocol
52
52
  // unbounded (>=0.10.1), but acp 0.11.0 reordered the ACP prompt() args and breaks
53
53
  // the SDK's ACP client. Hold acp <0.11 until a fixed SDK ships. See config/defaults.json.
54
54
  const AGENT_CLIENT_PROTOCOL_CONSTRAINT =
@@ -399,7 +399,7 @@ export function validateFrontendDependencies(
399
399
  * edits are picked up without a manual reinstall. The agent-server itself
400
400
  * is rebuilt from local source on each invocation (--reinstall).
401
401
  * - OH_AGENT_SERVER_GIT_REF: Git commit SHA or branch name
402
- * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.38.0")
402
+ * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.39.1")
403
403
  *
404
404
  * If none are set, defaults to the released version specified by
405
405
  * DEFAULT_AGENT_SERVER_VERSION. Set OH_AGENT_SERVER_GIT_REF to use a
@@ -1 +0,0 @@
1
- import{a as e}from"./rolldown-runtime-Cyuzqnbw.js";import{St as t,yt as n}from"./vendor-styling-Bcgpimp9.js";import{r}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~f9xdmd0z-DLMP7bZx.js";import{D as i,F as a,I as o,M as s,O as ee,P as te,T as ne,d as re,k as ie,w as c,y as ae}from"./vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~g4xrpilz-CJ7amdtQ.js";import{R as oe,t as se,z as l}from"./utils-qjs_KuS4.js";var u=e(t(),1),ce=`__AGENT_CANVAS_BASE_PATH__`;function le(e){let t=e?.trim();return!t||t===`/`?``:(t.startsWith(`/`)?t:`/${t}`).replace(/\/+$/,``)}function ue(){let e=le(void 0);if(e)return e;if(typeof window<`u`){let e=window[ce];if(typeof e==`string`)return le(e)}return``}function de(e){let t=ue();return t?`${t}${e.startsWith(`/`)?e:`/${e}`}`:e.startsWith(`/`)?e:`/${e}`}var d=`openhands`,fe=[{label:`English`,value:`en`},{label:`日本語`,value:`ja`},{label:`简体中文`,value:`zh-CN`},{label:`繁體中文`,value:`zh-TW`},{label:`한국어`,value:`ko-KR`},{label:`Norsk`,value:`no`},{label:`Arabic`,value:`ar`},{label:`Deutsch`,value:`de`},{label:`Français`,value:`fr`},{label:`Italiano`,value:`it`},{label:`Português`,value:`pt`},{label:`Español`,value:`es`},{label:`Català`,value:`ca`},{label:`Türkçe`,value:`tr`},{label:`Українська`,value:`uk`}],f=new WeakMap,pe=e=>{if(!f.has(e)){let t=e.use(ee).use(i).use(r).init({fallbackLng:`en`,debug:!1,supportedLngs:fe.map(e=>e.value),nonExplicitSupportedLngs:!1,ns:[d],defaultNS:d,fallbackNS:d,backend:{loadPath:de(`/locales/{{lng}}/{{ns}}.json`)},interpolation:{escapeValue:!1}});f.set(e,t)}return e},me=()=>pe(s()),he=null,p=null,m=()=>(he||=me(),he),ge=()=>p??m(),_e=e=>(p=e??m(),p),ve=async(e=m())=>(await f.get(e),e),ye=e=>e?typeof e==`object`&&!Array.isArray(e)?{ns:d,...e}:e:{ns:d},h=new Proxy({},{get:(e,t)=>{let n=ge();if(t===`t`)return(e,t)=>n.t(e,ye(t));if(t===`exists`)return(e,t)=>n.exists(e,ye(t));let r=Reflect.get(n,t,n);return typeof r==`function`?r.bind(n):r},set:(e,t,n)=>{let r=ge();return Reflect.set(r,t,n,r)}}),be=e=>typeof e.response?.data==`object`&&e.response?.data!==null&&`error`in e.response.data&&typeof e.response?.data?.error==`string`,xe=e=>typeof e.response?.data==`object`&&e.response?.data!==null&&`message`in e.response.data&&typeof e.response?.data?.message==`string`,Se=`Disconnected (check URL or network). Check that the backend URL is correct and the backend server is reachable. If the backend is on another origin, check that it allows this frontend origin.`,Ce=`Disconnected (request timed out). Check that the backend URL is correct and reachable.`,we=4;function Te(e){return typeof e==`object`&&!!e}function Ee(e){let t=[],n=new Set,r=e,i=0;for(;r!=null&&i<we&&!n.has(r);){if(n.add(r),r instanceof Error)r.message&&t.push(r.message),r=r.cause;else if(typeof r==`string`){r&&t.push(r);break}else if(Te(r)){let e=r.message;typeof e==`string`&&e&&t.push(e),r=r.cause}else break;i+=1}return t}function g(e){if(!e)return!1;let t=e.toLowerCase();return t.includes(`disconnected (check cors or network)`)||t.includes(`disconnected (check url or network)`)||t.includes(`blocked by cors`)||t.includes(`failed to fetch`)||t.includes(`network error`)||t.includes(`load failed`)||t.includes(`networkerror when attempting to fetch resource`)||t.includes(`cors`)&&t.includes(`blocked`)}function De(e){return Ee(e).some(g)}function _(e){if(!e)return!1;let t=e.toLowerCase();return t.includes(`request timeout`)||t.includes(`timeout after`)||t.includes(`backend request timed out`)}function v(e){let t=Ee(e);return t.some(g)?Se:t.some(_)?Ce:t[0]??null}function Oe(e){return typeof e==`object`&&!!e&&`isAxiosError`in e&&e.isAxiosError===!0}var y=e=>{let t=null,n=!1;return Oe(e)?(n=!0,t=be(e)&&e.response?.data.error?e.response?.data.error:xe(e)&&e.response?.data.message?e.response?.data.message:e.message):t=e instanceof Error?e.message:typeof e==`string`?e:null,v(n?t??e:e)??t??``},b=(e,t=5e3,n=1e4)=>{if(!e)return t;let r=e.length/(1e3/60)*1e3*1.5;return Math.min(Math.max(r,t),n)},x=n(),ke={background:`var(--oh-color-tertiary)`,border:`1px solid var(--oh-border-input)`,color:`#fff`,borderRadius:`var(--oh-radius)`,maxWidth:`400px`,wordBreak:`break-word`,overflowWrap:`anywhere`,whiteSpace:`pre-wrap`},S={position:`top-right`,style:ke},Ae={...ke,color:`var(--oh-muted)`};function je({message:e}){let t=u.useRef(null),[n,r]=u.useState(!1);return u.useLayoutEffect(()=>{let e=t.current;if(!e)return;let n=()=>{let t=Number.parseFloat(getComputedStyle(e).lineHeight);if(!Number.isFinite(t)||t<=0){r(!1);return}r(e.getBoundingClientRect().height>t*1.5)};n();let i=new ResizeObserver(n);return i.observe(e),()=>i.disconnect()},[e]),(0,x.jsxs)(`div`,{className:se(`flex min-w-0 gap-2`,n?`items-start`:`items-center`),children:[(0,x.jsx)(ne,{"aria-hidden":!0,className:`h-4 w-4 shrink-0`,strokeWidth:2,style:{color:oe}}),(0,x.jsx)(`span`,{ref:t,className:`min-w-0 flex-1 text-sm leading-5 [word-break:break-word] [overflow-wrap:anywhere]`,children:e})]})}var Me={...S,icon:null,style:Ae},Ne=e=>{let t=e||h.t(l.STATUS$ERROR);g(t)?t=h.t(l.ERROR$CORS_OR_NETWORK):_(t)&&(t=h.t(l.ERROR$BACKEND_REQUEST_TIMEOUT));let n=b(t,4e3);c((0,x.jsx)(je,{message:t}),{...Me,duration:n})},Pe=e=>{let t=b(e,5e3);c.success((0,x.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...S,duration:t})},Fe=(e,t,n)=>{let r=b(`${e} ${t}`,5e3);c.success((0,x.jsxs)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:[e,` `,(0,x.jsx)(`a`,{className:`underline hover:no-underline`,href:n,children:t})]}),{...S,duration:r})},Ie=e=>{let t=b(e,6e3);c((0,x.jsx)(`span`,{className:`[word-break:break-word] [overflow-wrap:anywhere]`,children:e}),{...S,icon:`⚠️`,duration:t})},Le=`openhands-backend-health`,Re=500;function ze(e){if(typeof e!=`object`||!e)return!1;let t=e;return Number.isInteger(t.consecutiveFailures)&&t.consecutiveFailures>=0&&t.consecutiveFailures<=5&&(t.lastError===null||typeof t.lastError==`string`)&&(t.lastFailureAt===null||typeof t.lastFailureAt==`number`)&&typeof t.disabled==`boolean`}function Be(){if(typeof window>`u`)return{};try{let e=window.localStorage.getItem(Le);if(!e)return{};let t=JSON.parse(e);if(typeof t!=`object`||!t)return{};let n={};for(let[e,r]of Object.entries(t))typeof e==`string`&&e.length>0&&ze(r)&&(n[e]=r);return n}catch{return{}}}function Ve(e){if(!(typeof window>`u`))try{if(Object.keys(e).length===0){window.localStorage.removeItem(Le);return}window.localStorage.setItem(Le,JSON.stringify(e))}catch{}}function He(e){let t=v(e)??`Unknown error`;return t.length>Re?`${t.slice(0,Re)}…`:t}var C=Be(),Ue=new Set;function We(){Ue.forEach(e=>e())}function w(e){C=e,Ve(e),We()}function Ge(){return C}function Ke(e){return C[e]??null}function qe(e){return Ue.add(e),()=>{Ue.delete(e)}}function Je(e,t){let n=C[e],r=Math.min((n?.consecutiveFailures??0)+1,5),i=n?.disabled===!0||r>=5,a={consecutiveFailures:r,lastError:He(t),lastFailureAt:Date.now(),disabled:i};w({...C,[e]:a})}function Ye(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}function Xe(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}function Ze(e){if(!(e in C))return;let{[e]:t,...n}=C;w(n)}var Qe=`workspace/project`,$e=`__AGENT_CANVAS_LOCK_TO_CLOUD__`,T=`all-hands.dev`,E=`openhands.dev`,et=`app.${T}`,tt=E,nt=`app.${E}`;function rt(e){return e?.trim()||null}function it(e){if(!e)return null;let t=e.trim().replace(/\/$/,``);return t?/^https?:\/\//i.test(t)?t:typeof window<`u`?`${window.location.protocol}//${t}`:`http://${t}`:null}function D(e){if(!e)return null;let t=e.trim().replace(/\/+$/,``);return t?/^https?:\/\//i.test(t)?t:`https://${t}`:null}function at(e){let t=e.toLowerCase();return t===et||t===nt?tt:t===T?E:t.endsWith(`.${T}`)?`${t.slice(0,-13)}${E}`:t}function ot(e){let t=D(e);if(!t)return null;try{let e=new URL(t),n=e.port?`:${e.port}`:``;return`${e.protocol}//${at(e.hostname)}${n}`}catch{return t.toLowerCase()}}function st(){let e=O();return!e||typeof window>`u`||!dt(window.location.origin,e)?null:window.location.origin}function ct(){return it(void 0)}function lt(){let e=rt(void 0);if(e)return e;if(typeof window<`u`){let e=window.__AGENT_CANVAS_SESSION_API_KEY__;if(typeof e==`string`)return rt(e)}return null}function ut(){return{baseUrl:k()??``,sessionApiKey:A()??``}}function O(){let e=D(void 0);if(e)return e;if(typeof window<`u`){let e=window[$e];if(typeof e==`string`)return D(e)}return null}function dt(e,t){let n=ot(e),r=ot(t);return!n||!r?!1:n===r}function ft(){return st()?`cookie`:`api-key`}function k(){return ct()||(typeof window<`u`?window.location.origin:null)}function A(){return lt()}function j(){return Qe}function pt(e){return`${j().replace(/\/+$/,``)}/${e.replace(/-/g,``)}`}function mt(){let e=A();return e?{"X-Session-API-Key":e}:{}}function M(){return typeof window<`u`&&window.__AGENT_CANVAS_AUTH_REQUIRED__===!0}function ht(){return M()?!A():!1}var gt=`default-local`,_t=`Local`,vt=`locked-cloud`,yt=`OpenHands Cloud`;function bt(){if(!O())return null;let e=st();return e?{id:vt,name:yt,host:e,apiKey:``,kind:`cloud`,authMode:`cookie`}:null}function N(){if(O())return null;let e=k(),t=A();return!e||!t?null:{id:gt,name:_t,host:e,apiKey:t,kind:`local`}}var xt=`openhands-backends`,P=`openhands-active-backend`;function St(e){return e===`local`||e===`cloud`}function Ct(e){return e===void 0||e===`api-key`||e===`cookie`}function wt(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.id==`string`&&t.id.length>0&&typeof t.name==`string`&&typeof t.host==`string`&&typeof t.apiKey==`string`&&St(t.kind)&&Ct(t.authMode)}function Tt(e){try{let{hostname:t}=new URL(e);return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function Et(e,t){return e.id!==`default-local`||e.kind!==`local`?!1:e.host===t.host||Tt(e.host)&&Tt(t.host)}function Dt(e){let t=N();if(!t)return e;let n=!1,r=e.map(e=>!Et(e,t)||e.apiKey===t.apiKey?e:(n=!0,{...e,apiKey:t.apiKey}));return n?(F(r),r):e}function F(e){if(!(typeof window>`u`))try{window.localStorage.setItem(xt,JSON.stringify(e))}catch{}}function Ot(){if(typeof window>`u`)return[];try{let e=bt();if(e)return F([e]),Nt()?.backendId!==e.id&&I({backendId:e.id}),[e];let t=window.localStorage.getItem(xt);if(t===null){let e=N();return e?(F([e]),[e]):[]}let n=JSON.parse(t);if(!Array.isArray(n))return[];let r=n.filter(wt);if(r.length===0){let e=N();return e?(F([e]),[e]):[]}return Dt(r)}catch{return[]}}function kt(e){if(!e)return null;try{let t=JSON.parse(e);if(typeof t!=`object`||!t||typeof t.backendId!=`string`)return null;let n=t.orgId;return{backendId:t.backendId,orgId:typeof n==`string`&&n.length>0?n:null}}catch{return null}}function At(e,t){try{return e?.getItem(t)??null}catch{return null}}function jt(e,t,n){try{e?.setItem(t,n)}catch{}}function Mt(e,t){try{e?.removeItem(t)}catch{}}function Nt(){return typeof window>`u`?null:kt(At(window.sessionStorage,P))||kt(At(window.localStorage,P))}function I(e){if(typeof window>`u`)return;if(!e){Mt(window.sessionStorage,P),Mt(window.localStorage,P);return}let t=JSON.stringify({backendId:e.backendId,orgId:e.orgId??null});jt(window.sessionStorage,P,t),jt(window.localStorage,P,t)}var Pt=`no-backend`,Ft={id:Pt,name:`No Backend Available`,host:``,apiKey:``,kind:`local`};function L(e){return e.id===Pt}function It(e){return e.find(e=>e.kind===`local`&&Ke(e.id)?.disabled!==!0)||(e.find(e=>e.kind===`local`)??e[0]??Ft)}function R(e,t){let n=null,r=null;if(t){let i=e.find(e=>e.id===t.backendId);i&&(n=i,r=t.orgId??null)}return n||(n=It(e),r=null),{backends:e,selection:t,active:{backend:n,orgId:r}}}var z=R(Ot(),Nt()),B=new Set;function Lt(){B.forEach(e=>e())}function V(){return z.active}function H(){let e=z.active.backend;return e.kind===`local`&&!L(e)?e:null}function U(){return z.backends}function W(){return z.selection}function Rt(){return z}function zt(e){I(e),z=R(z.backends,e),Lt()}function G(e){F(e);let t=z.selection;t&&!e.some(e=>e.id===t.backendId)&&(t=null,I(null)),z=R(e,t),Lt()}function Bt(e){return B.add(e),()=>{B.delete(e)}}var Vt=(e,t)=>{(e?.response?.status===401||e?.status===401)&&t.invalidateQueries({queryKey:[`user`,`authenticated`]})},Ht=e=>{if(!(e instanceof ie)||e.response?.status!==401&&e.status!==401)return!1;let t=V().backend;if(t.kind!==`cloud`)return!1;let n=e.config?.url;return!n||n.startsWith(t.host.replace(/\/+$/,``))},K=new Set,Ut=()=>{let e=new te({queryCache:new a({onSuccess:(e,t)=>{let n=t.meta?.backendId??t.options.meta?.backendId;typeof n==`string`&&Ye(n)},onError:(t,n)=>{if(n.queryKey[0]===`user`&&n.queryKey[1]===`authenticated`||Vt(t,e),!(n.meta?.disableToast??n.options.meta?.disableToast)&&!Ht(t)){let e=y(t);K.has(e||``)||(Ne(e||h.t(l.ERROR$GENERIC)),K.add(e||``),setTimeout(()=>{K.delete(e||``)},3e3))}}}),mutationCache:new o({onError:(t,n,r,i)=>{Vt(t,e),!(i?.meta?.disableToast??i?.options.meta?.disableToast)&&!Ht(t)&&Ne(y(t)||h.t(l.ERROR$GENERIC))}})});return e},Wt=null,Gt=null,Kt=()=>(Wt||=Ut(),Wt),qt=()=>Gt??Kt(),Jt=e=>(Gt=e??Kt(),Gt),Yt=new Proxy({},{get:(e,t)=>{let n=qt(),r=Reflect.get(n,t,n);return typeof r==`function`?r.bind(n):r},set:(e,t,n)=>{let r=qt();return Reflect.set(r,t,n,r)}});function Xt(e){if(e&&!e.startsWith(`/`))try{let t=new URL(e),n=t.hostname,r=window.location.hostname??window.location.host?.split(`:`)[0];return r&&(n===`localhost`||n===`127.0.0.1`)&&r!==`localhost`&&r!==`127.0.0.1`?`${r}:${t.port}`:t.host}catch{return window.location.host}return window.location.host}function Zt(e){if(e&&!e.startsWith(`/`))try{return(new URL(e).pathname.split(`/api/conversations`)[0]||``).replace(/\/$/,``)}catch{return``}return``}function Qt(e){let t=Xt(e),n=Zt(e),r=window.location.protocol===`https:`,i=$t(e)===`https:`;return`${r||i?`https:`:`http:`}//${t}${n}`}function $t(e){if(!e||e.startsWith(`/`))return null;try{return new URL(e).protocol}catch{return null}}function en(e){let t=Xt(e),n=Zt(e),r=window.location.protocol===`https:`,i=$t(e)===`https:`;return`${r||i?`wss:`:`ws:`}//${t}${n}/sockets/bash-events`}function tn(e,t){if(!e)return null;let n=Xt(t),r=Zt(t),i=window.location.protocol===`https:`,a=$t(t)===`https:`;return`${i||a?`wss:`:`ws:`}//${n}${r}/sockets/events/${e}`}var nn=class extends Error{constructor(){super(`No backend is configured.`),this.name=`NoBackendAvailableError`}};function rn(e){return e.replace(/\/+$/,``)}function an(e,t){return e.host?rn(e.host):e.conversationUrl?rn(Qt(e.conversationUrl)):rn(t?.host??``)}function q(e={}){let t=H();if(!t&&!e.host&&!e.conversationUrl)throw new nn;let n=e.sessionApiKey??e.apiKey??t?.apiKey??void 0;return{host:an(e,t),...n?{apiKey:n}:{},workingDir:e.workingDir??j(),...e.timeout===void 0?{}:{timeout:e.timeout}}}function on(e){let{host:t,apiKey:n,timeout:r}=q(e);return{baseUrl:t,...n?{apiKey:n}:{},timeout:r??6e4}}var sn={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.38.0`,agentCanvas:`1.7.2`,automation:`1.4.1`},compatibility:{minimumAgentServer:`1.28.0`},constraints:{_comment:`Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).`,agentClientProtocol:`agent-client-protocol<0.11`},images:{agentServer:`ghcr.io/openhands/agent-server`,agentCanvas:`ghcr.io/openhands/agent-canvas`},ports:{agentServer:18e3,automation:18001,proxy:8e3},paths:{stateSubdir:`agent-canvas`,conversations:`agent-canvas/conversations`,bashEvents:`agent-canvas/bash_events`,automationDb:`automation/automations.db`,canvasBasePath:`/canvas`},packages:{agentServer:`openhands-agent-server`,automation:`openhands-automation`,tools:`openhands-tools`,workspace:`openhands-workspace`},telemetry:{posthogApiKey:`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,posthogHost:`https://us.i.posthog.com`}},cn=5e3,ln=`unknown`,J=sn.compatibility.minimumAgentServer,un=`AGENT_SERVER_UNSUPPORTED_VERSION`,dn=`AGENT_SERVER_UNKNOWN_VERSION`,Y=null,fn=e=>Array.isArray(e?.usable_tools)?e.usable_tools:null,X=class extends Error{details;noBackendConfigured;constructor(e,t){let n=t?.noBackendConfigured??!1;super(n?`No agent server backend is configured yet. Add a backend to get started.`:`Could not connect to the configured agent server. Make sure it is running and reachable, then reload the page.`),this.name=`AgentServerUnavailableError`,this.details=e??null,this.noBackendConfigured=n}},pn=e=>e instanceof X||typeof e==`object`&&!!e&&`name`in e&&e.name===`AgentServerUnavailableError`,mn=class extends X{code=un;actualVersion;requiredVersion=J;constructor(e){let t=`Agent Canvas requires agent-server ${J} or newer; this backend is running ${e}. Please upgrade the agent-server backend.`;super(t),this.name=`AgentServerUnsupportedVersionError`,this.message=t,this.actualVersion=e}},hn=class extends X{code=dn;actualVersion;requiredVersion=J;constructor(e){let t=`Could not determine this backend's agent-server version.${e?` It reported "${e}".`:``} Agent Canvas requires agent-server ${J} or newer, but this backend did not return a valid version from /server_info. Restart or rebuild the agent-server backend, then try again.`;super(t),this.name=`AgentServerUnknownVersionError`,this.message=t,this.actualVersion=e}},gn=e=>M()&&Q(e,401);function Z(){Y=null}function _n(e){let t=fn(Y);return Array.isArray(t)?t.includes(e):!0}function vn(e){return e instanceof Error&&e.name===`HttpError`&&`status`in e&&typeof e.status==`number`}function Q(e,t){return vn(e)&&e.status===t}function yn(e){return typeof e==`string`&&e.trim()||null}function bn(e){return yn(e.sdk_version)}function xn(e){return yn(e.version)??bn(e)}function Sn(e){let t=xn(e);return!t||t.toLowerCase()===ln?null:t}function Cn(e){let t=Sn(e);return!t||!En(t)?null:t}function wn(e){return!Y||e&&H()?.host!==e?null:Cn(Y)}function Tn(e,t){let n=En(e),r=En(t);if(!n||!r)return null;for(let e of[`major`,`minor`,`patch`]){if(n[e]>r[e])return 1;if(n[e]<r[e])return-1}return n.prerelease&&!r.prerelease?-1:!n.prerelease&&r.prerelease?1:n.prerelease&&r.prerelease?n.prerelease.localeCompare(r.prerelease):0}function En(e){let[t]=e.trim().replace(/^v/,``).split(`+`),[n,r]=t.split(`-`,2),i=n.split(`.`);if(i.length!==3)return null;let[a,o,s]=i.map(e=>Number(e));return[a,o,s].every(e=>Number.isInteger(e)&&e>=0)?{major:a,minor:o,patch:s,prerelease:r}:null}function Dn(e){let t=Sn(e);if(!t)throw Z(),new hn(xn(e));let n=Tn(t,J);if(n===null)throw Z(),new hn(t);if(n<0)throw Z(),new mn(t)}async function On(){let e=H();if(!e){if(Z(),L(V().backend))throw new X(`No backend configured`,{noBackendConfigured:!0});return null}let t=q({host:e.host,sessionApiKey:e.apiKey||null,timeout:cn}),n;try{n=await new ae(t).getServerInfo()}catch(e){throw Z(),Q(e,401)?e:new X(e instanceof Error?e.message:null)}if(Dn(n),M())try{await new re(t).getSettings()}catch(e){if(Q(e,401))throw e;console.warn(`[agent-server] getSettings() probe failed (non-401):`,e)}return Y=n,n}var kn={WEB_CLIENT_CONFIG:[`web-client-config`],MAIN_APP_COOKIE_AUTH:[`main-app-cookie-auth`]},An={all:[`settings`],byScope:e=>[`settings`,e],personal:()=>[`settings`,`personal`]},jn={all:[`llm-profiles`]},Mn={all:[`agent-profiles`]},Nn={retry:!1},Pn={all:[`llm-subscription`],openaiStatus:[`llm-subscription`,`openai`,`status`],openaiModels:[`llm-subscription`,`openai`,`models`]},Fn={all:[`local-workspaces`]},In={marketplace:[`plugins-marketplace`],installed:[`plugins-installed`],local:[`plugins-local`]},Ln={latestVersion:[`agent-canvas-latest-version`]},Rn={staleTime:1e3*60*5,gcTime:1e3*60*15},$=u.createContext(null);function zn(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID():`backend-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Bn({children:e}){let t=u.useSyncExternalStore(Bt,Rt,Rt),n=u.useCallback(()=>{Z(),Yt.invalidateQueries({queryKey:kn.WEB_CLIENT_CONFIG})},[]),r=u.useCallback((e,t)=>{let r=W()?.backendId??null,i=W()?.orgId??null,a=t??null;e===r&&a===i||(zt({backendId:e,orgId:a}),n())},[n]),i=u.useCallback(e=>{let t={...e,id:zn()};return G([...U(),t]),zt({backendId:t.id}),n(),t},[n]),a=u.useCallback((e,t)=>{let r=U().find(t=>t.id===e),i=W()?.backendId??null;G(U().map(n=>n.id===e?{...n,...t}:n));let a=t.host!==void 0&&r!==void 0&&t.host!==r.host,o=t.apiKey!==void 0&&r!==void 0&&t.apiKey!==r.apiKey;(a||o)&&(Xe(e),i===e&&n())},[n]),o=u.useCallback(e=>{G(U().filter(t=>t.id!==e)),Ze(e),n()},[n]),s=u.useMemo(()=>({backends:t.backends,active:t.active,setActive:r,addBackend:i,updateBackend:a,removeBackend:o}),[t,r,i,a,o]);return(0,x.jsx)($.Provider,{value:s,children:e})}function Vn(){let e=u.useContext($);if(!e)throw Error(`useActiveBackendContext must be used inside <ActiveBackendProvider>`);return e}function Hn(){let e=u.useContext($);return e?e.active:{backend:N()??Ft,orgId:null}}export{Je as $,Qt as A,_t as B,Q as C,q as D,nn as E,Jt as F,mt as G,pt as H,V as I,O as J,j as K,H as L,Kt as M,qt as N,on as O,Yt as P,Ge as Q,U as R,vn as S,sn as T,k as U,Qe as V,ut as W,ht as X,M as Y,dt as Z,wn as _,_e as _t,Nn as a,Fe as at,_n as b,jn as c,v as ct,In as d,g as dt,Ye as et,kn as f,fe as ft,Tn as g,h as gt,Z as h,ge as ht,Mn as i,Pe as it,tn as j,en as k,Pn as l,_ as lt,Dn as m,m as mt,Hn as n,S as nt,Ln as o,Ie as ot,An as p,d as pt,ft as q,Vn as r,Ne as rt,Rn as s,y as st,Bn as t,qe as tt,Fn as u,De as ut,Cn as v,ve as vt,On as w,pn as x,gn as y,de as yt,L as z};