@openhands/agent-canvas 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (720) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{Trans-DqF_OEZB.js → Trans-52HCczKK.js} +1 -1
  4. package/build/assets/{acp-providers-DerAmTyY.js → acp-providers-xACMK9ZP.js} +1 -1
  5. package/build/assets/{active-backend-context-B8rMv0X9.js → active-backend-context-Cd1qcZsb.js} +1 -1
  6. package/build/assets/{add-backend-modal-CxC7BNEc.js → add-backend-modal-5chsfln3.js} +1 -1
  7. package/build/assets/{agent-profiles-settings-BJb8YXR1.js → agent-profiles-settings-BWK4H3kR.js} +1 -1
  8. package/build/assets/agent-server-compatibility-DMY0CihN.js +1 -0
  9. package/build/assets/agent-server-conversation-service.api-CI5-xmIX.js +41 -0
  10. package/build/assets/agent-settings-CMd8-O4f.js +2 -0
  11. package/build/assets/agent-settings-CdrhQJXX.js +1 -0
  12. package/build/assets/{alert-banner-Dh51WURQ.js → alert-banner-CLfWuIAX.js} +1 -1
  13. package/build/assets/api-key-entry-screen-Cc3aC7DZ.js +1 -0
  14. package/build/assets/app-settings-B-DQcBoB.js +1 -0
  15. package/build/assets/{automation-detail-CZsu2CoM.js → automation-detail-BgxBIpyK.js} +2 -2
  16. package/build/assets/automation-export-Dbur8OHa.js +2 -0
  17. package/build/assets/automations-list-BWfjizlp.js +1 -0
  18. package/build/assets/{back-nav-button-DVknCcSP.js → back-nav-button-CaKvsD1E.js} +1 -1
  19. package/build/assets/backend-form-modal-YcfpuBZo.js +1 -0
  20. package/build/assets/{backend-synced-settings-badge-BSfN0AZA.js → backend-synced-settings-badge-BellMmgC.js} +1 -1
  21. package/build/assets/{base-modal-CIF_785P.js → base-modal-Cw7enAHz.js} +1 -1
  22. package/build/assets/{brand-button-B1izLAdR.js → brand-button-BulEFHr3.js} +1 -1
  23. package/build/assets/{browser-DKaeq_sT.js → browser-DfVgUREb.js} +2 -2
  24. package/build/assets/browser-store-CBqI3tNR.js +1 -0
  25. package/build/assets/{browser-tab-qb_ftCxW.js → browser-tab-CmIKQB7S.js} +1 -1
  26. package/build/assets/chat-send-button-BchSSwuD.js +1 -0
  27. package/build/assets/circle-check-BXbQ5nEH.js +1 -0
  28. package/build/assets/{circle-plus-check-toggle-DoFIjVE0.js → circle-plus-check-toggle-BhpPjkh9.js} +1 -1
  29. package/build/assets/client-source-DAUgyJsi.js +1 -0
  30. package/build/assets/cloud-funnel-analytics-B5OeWh4y.js +1 -0
  31. package/build/assets/{color-themes-CHizm1xF.js → color-themes-QKMSVfDU.js} +1 -1
  32. package/build/assets/{combobox-caret-CxZpqoSR.js → combobox-caret-kNZtp53R.js} +1 -1
  33. package/build/assets/{command-menu-oTvKDU3Y.js → command-menu-tUsn23zy.js} +1 -1
  34. package/build/assets/{command-store-D8J5LMW1.js → command-store-B0hrIWMN.js} +1 -1
  35. package/build/assets/{condenser-settings-BGlWn93P.js → condenser-settings-BBizzfIH.js} +1 -1
  36. package/build/assets/{confirmation-modal-DGBWM2Ls.js → confirmation-modal-108xng7X.js} +1 -1
  37. package/build/assets/{context-menu-list-item-6psNyl7X.js → context-menu-list-item-BbKfFuN1.js} +1 -1
  38. package/build/assets/conversation-CTzSrLMq.js +1 -0
  39. package/build/assets/conversation-CgcXNb-Z.js +90 -0
  40. package/build/assets/conversation-panel-bscjGQda.js +1 -0
  41. package/build/assets/{conversation-service.api-_f9GlIEi.js → conversation-service.api-DbBvscJA.js} +1 -1
  42. package/build/assets/conversation-state-store-C5GagZHT.js +1 -0
  43. package/build/assets/{conversation-store-LptbOvKa.js → conversation-store-CyVqoa0d.js} +1 -1
  44. package/build/assets/{conversation-tab-empty-state-CNUmIms2.js → conversation-tab-empty-state-2KYlk5Bh.js} +1 -1
  45. package/build/assets/{copy-to-clipboard-button-CFzH_NOX.js → copy-to-clipboard-button-C54YRPMg.js} +1 -1
  46. package/build/assets/declaration-_yumYLEx.js +1 -0
  47. package/build/assets/{device-verify-WBSjJBLH.js → device-verify-D6FW_KZq.js} +1 -1
  48. package/build/assets/{dropdown-classes-D3wMJlXT.js → dropdown-classes-9uONlOg1.js} +1 -1
  49. package/build/assets/{ellipsis-button-CbNnHlIq.js → ellipsis-button-CoaUrKmQ.js} +1 -1
  50. package/build/assets/{entry.client-DNlPGxsu.js → entry.client-BJSVzw7V.js} +2 -2
  51. package/build/assets/{enum-filter-dropdown-JLYv1t8L.js → enum-filter-dropdown-qQzyjk_q.js} +1 -1
  52. package/build/assets/{environment-switch-overlay-B1PFO8P8.js → environment-switch-overlay-XRWCClLu.js} +1 -1
  53. package/build/assets/extensions-hub-DUp9sWQY.js +1 -0
  54. package/build/assets/extensions-navigation-DmkftjAx.js +1 -0
  55. package/build/assets/file-tUAzhmJ3.js +1 -0
  56. package/build/assets/files-tab-GV5hwiIM.js +1 -0
  57. package/build/assets/files-tab-store-DehyITNC.js +1 -0
  58. package/build/assets/{form-control-classes-CbdN5aO3.js → form-control-classes-BPUnoYyg.js} +1 -1
  59. package/build/assets/git-provider-icon-DDkru3b_.js +1 -0
  60. package/build/assets/highlighted-source-view-CYkPZUxr.js +1 -0
  61. package/build/assets/home-C53WekZ2.js +1 -0
  62. package/build/assets/home-EAwq8ah2.js +1 -0
  63. package/build/assets/index-home-kBdZGKtu.js +1 -0
  64. package/build/assets/install-server-modal-DYk4VP3-.js +1 -0
  65. package/build/assets/{launch-CAGavYl-.js → launch-CIecOy_y.js} +1 -1
  66. package/build/assets/lesson-plan-BSEUwflx.js +4 -0
  67. package/build/assets/llm-not-configured-banner-C8uv1PHT.js +27 -0
  68. package/build/assets/llm-settings-0Bb97NCk.js +1 -0
  69. package/build/assets/llm-settings-D4toJ90k.js +1 -0
  70. package/build/assets/{llm-subscription-service-Casyzgn1.js → llm-subscription-service-BPRw3u3H.js} +1 -1
  71. package/build/assets/{loading-spinner-BcdnT0mN.js → loading-spinner-BCInDEXB.js} +1 -1
  72. package/build/assets/manage-backends-modal-Bon32JYr.js +1 -0
  73. package/build/assets/manifest-ec000ae3.js +1 -0
  74. package/build/assets/markdown-renderer-BlaJOAI2.js +2 -0
  75. package/build/assets/mcp-CFIpOkn2.js +9 -0
  76. package/build/assets/messages-eRPeR4pW.js +40 -0
  77. package/build/assets/{modal-body-Cc2zp0xb.js → modal-body-Bg9UCeoV.js} +1 -1
  78. package/build/assets/{modal-classes-3qT9Ap7Q.js → modal-classes-H1KbJkeC.js} +1 -1
  79. package/build/assets/{modal-close-button-BcIBUdSq.js → modal-close-button-BMLYvo0C.js} +1 -1
  80. package/build/assets/{model-selector-DJrMrFAr.js → model-selector-BqX2RvEr.js} +1 -1
  81. package/build/assets/{navigation-link-D8hfwvxI.js → navigation-link-DoJzTCEz.js} +1 -1
  82. package/build/assets/onboarding-3KO4qE6R.js +1 -0
  83. package/build/assets/onboarding-modal-D4vqkJeT.js +1 -0
  84. package/build/assets/{organization-service.api-vrRNwOma.js → organization-service.api-CvfQugOt.js} +1 -1
  85. package/build/assets/{path-utils-PNfCKQDV.js → path-utils-DRgexxnX.js} +1 -1
  86. package/build/assets/{plan-components-BdZXPyZU.js → plan-components-qkMiGs_-.js} +1 -1
  87. package/build/assets/{planner-tab-ByOw1he8.js → planner-tab-ZrjiirRr.js} +1 -1
  88. package/build/assets/{plugins-management-service-B75jyC56.js → plugins-management-service-9qT-r_37.js} +1 -1
  89. package/build/assets/plus-CzE1b-wl.js +1 -0
  90. package/build/assets/{profiles-service.api-BQTklD5D.js → profiles-service.api-CRVlrQpT.js} +1 -1
  91. package/build/assets/{providers-DfTB2gPd.js → providers-C2DFGBrf.js} +1 -1
  92. package/build/assets/{proxy-B3tCGf0X.js → proxy-DnnDqkwn.js} +1 -1
  93. package/build/assets/puzzle-IHQnD54C.js +1 -0
  94. package/build/assets/recommended-automations-launcher-B97vgHuN.js +58 -0
  95. package/build/assets/refresh-cw-DxbAs3SK.js +1 -0
  96. package/build/assets/root-BbONavTg.css +1 -0
  97. package/build/assets/root-D01rpqZU.js +2 -0
  98. package/build/assets/root-layout-BiHbCIkS.js +2 -0
  99. package/build/assets/{runtime-waiting-state-CnyVhX4T.js → runtime-waiting-state-CbUV9txX.js} +1 -1
  100. package/build/assets/{schema-field-CUwk4wrQ.js → schema-field-B9-9Ta9u.js} +1 -1
  101. package/build/assets/sdk-section-page-DG1s25Pr.js +1 -0
  102. package/build/assets/{sdk-settings-schema-CLR01YIK.js → sdk-settings-schema-B42JFr5Y.js} +1 -1
  103. package/build/assets/{secrets-service-CvyPWJhg.js → secrets-service-DvyS6-mV.js} +1 -1
  104. package/build/assets/secrets-settings-CeSq6cQw.js +1 -0
  105. package/build/assets/{segmented-toggle-kzwZkLaj.js → segmented-toggle-DRVJBNy0.js} +1 -1
  106. package/build/assets/settings-Dzo0dJKM.js +1 -0
  107. package/build/assets/{settings-mQUckT0g.js → settings-HcwfqMjJ.js} +1 -1
  108. package/build/assets/{settings-dropdown-input-Dhx9ErGd.js → settings-dropdown-input-B6RL_mt0.js} +1 -1
  109. package/build/assets/settings-index-uAKHyijw.js +1 -0
  110. package/build/assets/{settings-input-BsgQWS5R.js → settings-input-ZoaAPNQh.js} +1 -1
  111. package/build/assets/{settings-list-classes-DSJJX99U.js → settings-list-classes-Dr8LgITi.js} +1 -1
  112. package/build/assets/settings-modal-BVX2G_IT.js +1 -0
  113. package/build/assets/{settings-service.api-DXk5TdeJ.js → settings-service.api-BY7ncxIz.js} +1 -1
  114. package/build/assets/{settings-switch-Bes8dIlV.js → settings-switch-DUlGnP0B.js} +1 -1
  115. package/build/assets/{settings-utils-DzCVfiR3.js → settings-utils-kWEEvcdv.js} +1 -1
  116. package/build/assets/shared-conversation-CV4Rtdz2.js +1 -0
  117. package/build/assets/{sidebar-layout-Bm7pa3Vk.js → sidebar-layout-BhGooCga.js} +1 -1
  118. package/build/assets/sidebar-mobile-menu-toggle-BntOJphE.js +1 -0
  119. package/build/assets/{sidebar-nav-link-CHqyFXwV.js → sidebar-nav-link-DkA1XWV8.js} +1 -1
  120. package/build/assets/{sidebar-store-uiUXBU1N.js → sidebar-store-CF3b12-m.js} +1 -1
  121. package/build/assets/{skill-card-pill-row-BPYKQ3IN.js → skill-card-pill-row-_gWe1Tws.js} +1 -1
  122. package/build/assets/skill-icon-badge-C-zbaXbD.js +1 -0
  123. package/build/assets/skills-plugins-BwoXKtrR.js +1 -0
  124. package/build/assets/skills-settings-Crq-fZSt.js +2 -0
  125. package/build/assets/{styled-tooltip-B14i_Uac.js → styled-tooltip-CdnCJ67u.js} +1 -1
  126. package/build/assets/syntax-highlighter-CZK2ab-O.js +1 -0
  127. package/build/assets/{task-list-tab-DyfgG4MC.js → task-list-tab-CONOO9iI.js} +1 -1
  128. package/build/assets/telemetry-CC32dJYW.js +2 -0
  129. package/build/assets/{terminal-DRXt2Lr4.js → terminal-CTkDpIU-.js} +1 -1
  130. package/build/assets/{toggle-switch-DX_k418f.js → toggle-switch-yVIzmJLM.js} +1 -1
  131. package/build/assets/{typography-CzfoD9DY.js → typography-BBVEW0un.js} +1 -1
  132. package/build/assets/{use-acp-credential-form-Bm8qXdlc.js → use-acp-credential-form-CIsp8hJe.js} +1 -1
  133. package/build/assets/use-activate-agent-profile-BfcTTJJG.js +1 -0
  134. package/build/assets/{use-active-agent-profile-hI-x-UBa.js → use-active-agent-profile-CCeFtmk9.js} +1 -1
  135. package/build/assets/{use-active-conversation-2qeez40F.js → use-active-conversation-Badxj8w4.js} +1 -1
  136. package/build/assets/{use-agent-profiles-0pr5bLS7.js → use-agent-profiles-BSWVN6hH.js} +1 -1
  137. package/build/assets/{use-agent-state-C6peDXUm.js → use-agent-state-BzRrhoPd.js} +1 -1
  138. package/build/assets/use-backends-health-BsZikyFW.js +1 -0
  139. package/build/assets/{use-can-manage-org-profiles-Ck_bsNbH.js → use-can-manage-org-profiles-Do6mYf6P.js} +1 -1
  140. package/build/assets/{use-cloud-current-user-id-DUCSxNjY.js → use-cloud-current-user-id-Cx3B_0-w.js} +1 -1
  141. package/build/assets/use-config-D9zUVw5b.js +1 -0
  142. package/build/assets/{use-create-conversation-r1JHfKO5.js → use-create-conversation-vvl0kvu7.js} +1 -1
  143. package/build/assets/{use-create-secret-Cf2N11d2.js → use-create-secret-CB7Dvd4s.js} +1 -1
  144. package/build/assets/use-event-store-BlpSUF7N.js +4 -0
  145. package/build/assets/{use-handle-plan-click-CsAW3FlH.js → use-handle-plan-click-DDZkew9p.js} +1 -1
  146. package/build/assets/use-is-creating-conversation-fxSzN778.js +1 -0
  147. package/build/assets/{use-launch-skill-in-chat-DJWEfVc5.js → use-launch-skill-in-chat-D6_n1fs3.js} +1 -1
  148. package/build/assets/use-llm-profiles-CNQm7HYS.js +1 -0
  149. package/build/assets/use-plugins-marketplace-CloojomS.js +1 -0
  150. package/build/assets/use-runtime-is-ready-Bx_4cfar.js +1 -0
  151. package/build/assets/{use-save-agent-profile-RqUGqTv6.js → use-save-agent-profile-Bj7N-1jS.js} +1 -1
  152. package/build/assets/{use-save-settings-Chvzeu2s.js → use-save-settings-BMsb2wk_.js} +1 -1
  153. package/build/assets/use-settings-B9XEmh7i.js +1 -0
  154. package/build/assets/use-settings-nav-items-BGfBS0yL.js +16 -0
  155. package/build/assets/{use-skills-xrVoKYrF.js → use-skills-CSRbvPle.js} +1 -1
  156. package/build/assets/{use-task-list-CfisapBW.js → use-task-list-CTIVLrQA.js} +1 -1
  157. package/build/assets/use-tracking-DjdCssvp.js +1 -0
  158. package/build/assets/{use-user-conversation-CnE4zhOA.js → use-user-conversation-BCpFn-Ei.js} +1 -1
  159. package/build/assets/{useTranslation-Cbf5AGg_.js → useTranslation-CHm_6BRr.js} +1 -1
  160. package/build/assets/{utils-DB9LsAzA.js → utils-CrRpzbM2.js} +1 -1
  161. package/build/assets/vendor-markdown-DzO4uO_0.js +37 -0
  162. package/build/assets/{vendor~browser-wXQ-WZEC.js → vendor~browser-Byfuq5J-.js} +1 -1
  163. package/build/assets/{vendor~browser-tab-CsMb-pta.js → vendor~browser-tab-BLk3qxhw.js} +1 -1
  164. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-eGLBu60s.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~dhilvkxv-DTJ_cjR5.js} +2 -2
  165. package/build/assets/{vendor~files-tab-B-5fBohe.js → vendor~files-tab-XmnauIZI.js} +1 -1
  166. package/build/assets/{vendor~launch-_Km3J77E.js → vendor~launch-DeC8QhXQ.js} +1 -1
  167. package/build/assets/{vendor~root-layout~conversation-panel~conversation~shared-conversation-BrguKXCn.js → vendor~root-layout~conversation-panel~conversation~shared-conversation-DDmLzCzm.js} +1 -1
  168. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-YrfJYTQw.js +1 -0
  169. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-mC0v44WR.js → vendor~root-layout~index-home~home~conversation-panel~conversation~launch~skills-settings~a~j2jlu22h-DoaS51iW.js} +123 -3
  170. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-BOKQkbc6.js → vendor~root-layout~index-home~home~conversation-panel~conversation~shared-conversation~aler~gfu7qdtz-DEYwoy8u.js} +1 -1
  171. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-DZHLw5Sr.js +1 -0
  172. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-cFNmfAE6.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~ftka0fnu-UJ4BNDJP.js} +1 -1
  173. package/build/assets/{verification-settings-CfkrXoSa.js → verification-settings-uwOfc16F.js} +1 -1
  174. package/build/index.html +4 -4
  175. package/build/locales/ar/openhands.json +38 -4
  176. package/build/locales/ca/openhands.json +38 -4
  177. package/build/locales/de/openhands.json +38 -4
  178. package/build/locales/en/openhands.json +38 -4
  179. package/build/locales/es/openhands.json +38 -4
  180. package/build/locales/fr/openhands.json +38 -4
  181. package/build/locales/it/openhands.json +38 -4
  182. package/build/locales/ja/openhands.json +38 -4
  183. package/build/locales/ko-KR/openhands.json +38 -4
  184. package/build/locales/no/openhands.json +38 -4
  185. package/build/locales/pt/openhands.json +38 -4
  186. package/build/locales/tr/openhands.json +38 -4
  187. package/build/locales/uk/openhands.json +38 -4
  188. package/build/locales/zh-CN/openhands.json +38 -4
  189. package/build/locales/zh-TW/openhands.json +38 -4
  190. package/config/defaults.json +7 -3
  191. package/dist/api/agent-canvas-updates.cjs +2 -0
  192. package/dist/api/agent-canvas-updates.cjs.map +1 -0
  193. package/dist/api/agent-canvas-updates.d.ts +7 -0
  194. package/dist/api/agent-canvas-updates.js +19 -0
  195. package/dist/api/agent-canvas-updates.js.map +1 -0
  196. package/dist/api/agent-server-adapter.cjs +1 -1
  197. package/dist/api/agent-server-adapter.cjs.map +1 -1
  198. package/dist/api/agent-server-adapter.d.ts +3 -0
  199. package/dist/api/agent-server-adapter.js +1 -0
  200. package/dist/api/agent-server-adapter.js.map +1 -1
  201. package/dist/api/agent-server-compatibility.cjs +1 -1
  202. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  203. package/dist/api/agent-server-compatibility.d.ts +5 -0
  204. package/dist/api/agent-server-compatibility.js +24 -15
  205. package/dist/api/agent-server-compatibility.js.map +1 -1
  206. package/dist/api/agent-server-config.cjs +1 -1
  207. package/dist/api/agent-server-config.cjs.map +1 -1
  208. package/dist/api/agent-server-config.js +11 -8
  209. package/dist/api/agent-server-config.js.map +1 -1
  210. package/dist/api/automation-service/automation-service.api.cjs +2 -0
  211. package/dist/api/automation-service/automation-service.api.cjs.map +1 -0
  212. package/dist/api/automation-service/automation-service.api.d.ts +3 -0
  213. package/dist/api/automation-service/automation-service.api.js +283 -0
  214. package/dist/api/automation-service/automation-service.api.js.map +1 -0
  215. package/dist/api/client-source.cjs +1 -1
  216. package/dist/api/client-source.cjs.map +1 -1
  217. package/dist/api/client-source.d.ts +3 -0
  218. package/dist/api/client-source.js +4 -4
  219. package/dist/api/client-source.js.map +1 -1
  220. package/dist/api/cloud/settings-service.api.cjs.map +1 -1
  221. package/dist/api/cloud/settings-service.api.js.map +1 -1
  222. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  223. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  224. package/dist/api/conversation-service/agent-server-conversation-service.api.js +111 -109
  225. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  226. package/dist/api/mcp-health/mcp-health-store.cjs +2 -0
  227. package/dist/api/mcp-health/mcp-health-store.cjs.map +1 -0
  228. package/dist/api/mcp-health/mcp-health-store.d.ts +22 -0
  229. package/dist/api/mcp-health/mcp-health-store.js +45 -0
  230. package/dist/api/mcp-health/mcp-health-store.js.map +1 -0
  231. package/dist/api/mcp-health/probe-mcp-server-health.cjs +2 -0
  232. package/dist/api/mcp-health/probe-mcp-server-health.cjs.map +1 -0
  233. package/dist/api/mcp-health/probe-mcp-server-health.d.ts +31 -0
  234. package/dist/api/mcp-health/probe-mcp-server-health.js +57 -0
  235. package/dist/api/mcp-health/probe-mcp-server-health.js.map +1 -0
  236. package/dist/api/mcp-service/mcp-service.api.cjs +1 -1
  237. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -1
  238. package/dist/api/mcp-service/mcp-service.api.js +66 -46
  239. package/dist/api/mcp-service/mcp-service.api.js.map +1 -1
  240. package/dist/api/plugins-management-service.cjs.map +1 -1
  241. package/dist/api/plugins-management-service.d.ts +6 -1
  242. package/dist/api/plugins-management-service.js.map +1 -1
  243. package/dist/api/plugins-service.d.ts +30 -2
  244. package/dist/api/secrets-service.cjs +1 -1
  245. package/dist/api/secrets-service.cjs.map +1 -1
  246. package/dist/api/secrets-service.d.ts +6 -6
  247. package/dist/api/secrets-service.js +8 -3
  248. package/dist/api/secrets-service.js.map +1 -1
  249. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  250. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  251. package/dist/api/settings-service/settings-service.api.d.ts +1 -1
  252. package/dist/api/settings-service/settings-service.api.js +1 -0
  253. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  254. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.cjs +1 -1
  255. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.js +5 -5
  256. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  257. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  258. package/dist/components/features/backends/backend-form-modal.d.ts +4 -1
  259. package/dist/components/features/backends/backend-form-modal.js +15 -16
  260. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  261. package/dist/components/features/backends/backend-selector.cjs +1 -1
  262. package/dist/components/features/backends/backend-selector.cjs.map +1 -1
  263. package/dist/components/features/backends/backend-selector.js +103 -102
  264. package/dist/components/features/backends/backend-selector.js.map +1 -1
  265. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  266. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  267. package/dist/components/features/backends/manage-backends-modal.js +85 -73
  268. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  269. package/dist/components/features/chat/chat-interface.cjs +2 -2
  270. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  271. package/dist/components/features/chat/chat-interface.js +131 -129
  272. package/dist/components/features/chat/chat-interface.js.map +1 -1
  273. package/dist/components/features/chat/confirmation-mode-enabled.cjs +1 -1
  274. package/dist/components/features/chat/confirmation-mode-enabled.js +4 -4
  275. package/dist/components/features/chat/skill-install-restart-banner.cjs +2 -0
  276. package/dist/components/features/chat/skill-install-restart-banner.cjs.map +1 -0
  277. package/dist/components/features/chat/skill-install-restart-banner.d.ts +11 -0
  278. package/dist/components/features/chat/skill-install-restart-banner.js +63 -0
  279. package/dist/components/features/chat/skill-install-restart-banner.js.map +1 -0
  280. package/dist/components/features/conversation/right-panel-toggle.cjs +1 -1
  281. package/dist/components/features/conversation/right-panel-toggle.cjs.map +1 -1
  282. package/dist/components/features/conversation/right-panel-toggle.js +1 -1
  283. package/dist/components/features/conversation/right-panel-toggle.js.map +1 -1
  284. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  285. package/dist/components/features/conversation-panel/conversation-panel.js +10 -10
  286. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  287. package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
  288. package/dist/components/features/mcp-page/custom-server-editor.js +78 -77
  289. package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
  290. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  291. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  292. package/dist/components/features/mcp-page/install-server-modal.d.ts +4 -1
  293. package/dist/components/features/mcp-page/install-server-modal.js +135 -136
  294. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  295. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  296. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  297. package/dist/components/features/mcp-page/installed-server-card.js +40 -34
  298. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  299. package/dist/components/features/mcp-page/mcp-server-health.cjs +2 -0
  300. package/dist/components/features/mcp-page/mcp-server-health.cjs.map +1 -0
  301. package/dist/components/features/mcp-page/mcp-server-health.d.ts +18 -0
  302. package/dist/components/features/mcp-page/mcp-server-health.js +117 -0
  303. package/dist/components/features/mcp-page/mcp-server-health.js.map +1 -0
  304. package/dist/components/features/plugins/build-plugins-view-model.d.ts +10 -1
  305. package/dist/components/features/plugins/plugin-files-section.d.ts +13 -0
  306. package/dist/components/features/settings/agent-canvas-update-card.cjs +2 -0
  307. package/dist/components/features/settings/agent-canvas-update-card.cjs.map +1 -0
  308. package/dist/components/features/settings/agent-canvas-update-card.d.ts +7 -0
  309. package/dist/components/features/settings/agent-canvas-update-card.js +170 -0
  310. package/dist/components/features/settings/agent-canvas-update-card.js.map +1 -0
  311. package/dist/components/features/settings/integrations-settings-link.cjs +2 -0
  312. package/dist/components/features/settings/integrations-settings-link.cjs.map +1 -0
  313. package/dist/components/features/settings/integrations-settings-link.d.ts +5 -0
  314. package/dist/components/features/settings/integrations-settings-link.js +41 -0
  315. package/dist/components/features/settings/integrations-settings-link.js.map +1 -0
  316. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  317. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +1 -1
  318. package/dist/components/features/settings/settings-desktop-sidebar.cjs +1 -1
  319. package/dist/components/features/settings/settings-desktop-sidebar.cjs.map +1 -1
  320. package/dist/components/features/settings/settings-desktop-sidebar.js +31 -21
  321. package/dist/components/features/settings/settings-desktop-sidebar.js.map +1 -1
  322. package/dist/components/features/settings/settings-mobile-drawer.cjs +1 -1
  323. package/dist/components/features/settings/settings-mobile-drawer.cjs.map +1 -1
  324. package/dist/components/features/settings/settings-mobile-drawer.js +40 -30
  325. package/dist/components/features/settings/settings-mobile-drawer.js.map +1 -1
  326. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  327. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  328. package/dist/components/features/skills/extensions-navigation.js +54 -33
  329. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  330. package/dist/config/defaults.cjs +1 -1
  331. package/dist/config/defaults.cjs.map +1 -1
  332. package/dist/config/defaults.js +7 -3
  333. package/dist/config/defaults.js.map +1 -1
  334. package/dist/constants/acp-providers.cjs.map +1 -1
  335. package/dist/constants/acp-providers.js.map +1 -1
  336. package/dist/contexts/conversation-websocket-context.cjs +2 -2
  337. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  338. package/dist/contexts/conversation-websocket-context.js +169 -166
  339. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  340. package/dist/hooks/mutation/use-delete-llm-profile.cjs +1 -1
  341. package/dist/hooks/mutation/use-delete-llm-profile.js +1 -0
  342. package/dist/hooks/mutation/use-delete-mcp-server.cjs +1 -1
  343. package/dist/hooks/mutation/use-delete-mcp-server.cjs.map +1 -1
  344. package/dist/hooks/mutation/use-delete-mcp-server.js +8 -6
  345. package/dist/hooks/mutation/use-delete-mcp-server.js.map +1 -1
  346. package/dist/hooks/mutation/use-rename-llm-profile.cjs +1 -1
  347. package/dist/hooks/mutation/use-rename-llm-profile.js +1 -0
  348. package/dist/hooks/mutation/use-save-settings.cjs +1 -1
  349. package/dist/hooks/mutation/use-save-settings.js +3 -3
  350. package/dist/hooks/mutation/use-update-mcp-server.cjs +1 -1
  351. package/dist/hooks/mutation/use-update-mcp-server.cjs.map +1 -1
  352. package/dist/hooks/mutation/use-update-mcp-server.js +11 -9
  353. package/dist/hooks/mutation/use-update-mcp-server.js.map +1 -1
  354. package/dist/hooks/query/query-keys.cjs +1 -1
  355. package/dist/hooks/query/query-keys.cjs.map +1 -1
  356. package/dist/hooks/query/query-keys.d.ts +4 -0
  357. package/dist/hooks/query/query-keys.js +2 -2
  358. package/dist/hooks/query/query-keys.js.map +1 -1
  359. package/dist/hooks/query/use-automation-sdk-version.cjs +2 -0
  360. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -0
  361. package/dist/hooks/query/use-automation-sdk-version.d.ts +3 -0
  362. package/dist/hooks/query/use-automation-sdk-version.js +63 -0
  363. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -0
  364. package/dist/hooks/query/use-latest-agent-canvas-version.cjs +2 -0
  365. package/dist/hooks/query/use-latest-agent-canvas-version.cjs.map +1 -0
  366. package/dist/hooks/query/use-latest-agent-canvas-version.d.ts +10 -0
  367. package/dist/hooks/query/use-latest-agent-canvas-version.js +19 -0
  368. package/dist/hooks/query/use-latest-agent-canvas-version.js.map +1 -0
  369. package/dist/hooks/query/use-plugin-file-content.d.ts +7 -0
  370. package/dist/hooks/query/use-resolved-workspaces.cjs +1 -1
  371. package/dist/hooks/query/use-resolved-workspaces.cjs.map +1 -1
  372. package/dist/hooks/query/use-resolved-workspaces.js +25 -26
  373. package/dist/hooks/query/use-resolved-workspaces.js.map +1 -1
  374. package/dist/hooks/query/use-search-subdirs.cjs +1 -1
  375. package/dist/hooks/query/use-search-subdirs.cjs.map +1 -1
  376. package/dist/hooks/query/use-search-subdirs.d.ts +5 -0
  377. package/dist/hooks/query/use-search-subdirs.js +16 -4
  378. package/dist/hooks/query/use-search-subdirs.js.map +1 -1
  379. package/dist/hooks/query/use-task-polling.cjs +1 -1
  380. package/dist/hooks/query/use-task-polling.cjs.map +1 -1
  381. package/dist/hooks/query/use-task-polling.d.ts +19 -3
  382. package/dist/hooks/query/use-task-polling.js +36 -35
  383. package/dist/hooks/query/use-task-polling.js.map +1 -1
  384. package/dist/hooks/use-device-flow.cjs +1 -1
  385. package/dist/hooks/use-device-flow.js +6 -6
  386. package/dist/hooks/use-llm-configured.cjs +1 -1
  387. package/dist/hooks/use-llm-configured.js +3 -3
  388. package/dist/hooks/use-mcp-server-health.cjs +2 -0
  389. package/dist/hooks/use-mcp-server-health.cjs.map +1 -0
  390. package/dist/hooks/use-mcp-server-health.d.ts +11 -0
  391. package/dist/hooks/use-mcp-server-health.js +18 -0
  392. package/dist/hooks/use-mcp-server-health.js.map +1 -0
  393. package/dist/hooks/use-skill-installs.cjs +2 -0
  394. package/dist/hooks/use-skill-installs.cjs.map +1 -0
  395. package/dist/hooks/use-skill-installs.d.ts +10 -0
  396. package/dist/hooks/use-skill-installs.js +21 -0
  397. package/dist/hooks/use-skill-installs.js.map +1 -0
  398. package/dist/hooks/use-tracking.cjs +1 -1
  399. package/dist/hooks/use-tracking.cjs.map +1 -1
  400. package/dist/hooks/use-tracking.d.ts +3 -3
  401. package/dist/hooks/use-tracking.js +67 -52
  402. package/dist/hooks/use-tracking.js.map +1 -1
  403. package/dist/i18n/declaration.cjs +1 -1
  404. package/dist/i18n/declaration.cjs.map +1 -1
  405. package/dist/i18n/declaration.d.ts +35 -1
  406. package/dist/i18n/declaration.js +1 -1
  407. package/dist/i18n/declaration.js.map +1 -1
  408. package/dist/i18n/translation.cjs +3 -3
  409. package/dist/i18n/translation.cjs.map +1 -1
  410. package/dist/i18n/translation.js +623 -45
  411. package/dist/i18n/translation.js.map +1 -1
  412. package/dist/index.cjs +1 -1
  413. package/dist/index.js +1 -2
  414. package/dist/lib/index.cjs +1 -1
  415. package/dist/lib/index.d.ts +0 -1
  416. package/dist/lib/index.js +0 -1
  417. package/dist/locales/ar/openhands.json +38 -4
  418. package/dist/locales/ca/openhands.json +38 -4
  419. package/dist/locales/de/openhands.json +38 -4
  420. package/dist/locales/en/openhands.json +38 -4
  421. package/dist/locales/es/openhands.json +38 -4
  422. package/dist/locales/fr/openhands.json +38 -4
  423. package/dist/locales/it/openhands.json +38 -4
  424. package/dist/locales/ja/openhands.json +38 -4
  425. package/dist/locales/ko-KR/openhands.json +38 -4
  426. package/dist/locales/no/openhands.json +38 -4
  427. package/dist/locales/pt/openhands.json +38 -4
  428. package/dist/locales/tr/openhands.json +38 -4
  429. package/dist/locales/uk/openhands.json +38 -4
  430. package/dist/locales/zh-CN/openhands.json +38 -4
  431. package/dist/locales/zh-TW/openhands.json +38 -4
  432. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.cjs +2 -0
  433. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.cjs.map +1 -0
  434. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.js +44 -0
  435. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian-rovo.js.map +1 -0
  436. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs +1 -1
  437. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs.map +1 -1
  438. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js +13 -0
  439. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js.map +1 -1
  440. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
  441. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
  442. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +21 -1
  443. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
  444. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs +1 -1
  445. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs.map +1 -1
  446. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js +1 -1
  447. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js.map +1 -1
  448. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.cjs +1 -1
  449. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.cjs.map +1 -1
  450. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.js +13 -0
  451. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-outlook.js.map +1 -1
  452. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.cjs +1 -1
  453. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.cjs.map +1 -1
  454. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.js +13 -0
  455. package/dist/node_modules/@openhands/extensions/integrations/catalog/microsoft-teams.js.map +1 -1
  456. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  457. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  458. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +13 -0
  459. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  460. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.cjs +1 -1
  461. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.cjs.map +1 -1
  462. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.js +13 -0
  463. package/dist/node_modules/@openhands/extensions/integrations/catalog/onedrive.js.map +1 -1
  464. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.cjs +1 -1
  465. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.cjs.map +1 -1
  466. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.js +13 -0
  467. package/dist/node_modules/@openhands/extensions/integrations/catalog/sharepoint.js.map +1 -1
  468. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +1 -1
  469. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -1
  470. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +16 -2
  471. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -1
  472. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.cjs +2 -0
  473. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.cjs.map +1 -0
  474. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.js +46 -0
  475. package/dist/node_modules/@openhands/extensions/integrations/catalog/vanta.js.map +1 -0
  476. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
  477. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
  478. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +74 -70
  479. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
  480. package/dist/node_modules/@openhands/extensions/skills/index.cjs +123 -3
  481. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  482. package/dist/node_modules/@openhands/extensions/skills/index.js +7 -1
  483. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  484. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +2 -0
  485. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs.map +1 -0
  486. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js +9 -0
  487. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js.map +1 -0
  488. package/dist/node_modules/lucide-react/dist/esm/icons/info.cjs +2 -0
  489. package/dist/node_modules/lucide-react/dist/esm/icons/info.cjs.map +1 -0
  490. package/dist/node_modules/lucide-react/dist/esm/icons/info.js +21 -0
  491. package/dist/node_modules/lucide-react/dist/esm/icons/info.js.map +1 -0
  492. package/dist/package.cjs +1 -1
  493. package/dist/package.cjs.map +1 -1
  494. package/dist/package.js +10 -3
  495. package/dist/package.js.map +1 -1
  496. package/dist/routes/app-settings.cjs +1 -1
  497. package/dist/routes/app-settings.cjs.map +1 -1
  498. package/dist/routes/app-settings.js +113 -67
  499. package/dist/routes/app-settings.js.map +1 -1
  500. package/dist/routes/conversation.cjs +1 -1
  501. package/dist/routes/conversation.cjs.map +1 -1
  502. package/dist/routes/conversation.js +1 -1
  503. package/dist/routes/conversation.js.map +1 -1
  504. package/dist/routes/mcp.cjs +1 -1
  505. package/dist/routes/mcp.cjs.map +1 -1
  506. package/dist/routes/mcp.js +1 -0
  507. package/dist/routes/mcp.js.map +1 -1
  508. package/dist/services/cloud-funnel-analytics.cjs +1 -1
  509. package/dist/services/cloud-funnel-analytics.cjs.map +1 -1
  510. package/dist/services/cloud-funnel-analytics.d.ts +2 -2
  511. package/dist/services/cloud-funnel-analytics.js +18 -16
  512. package/dist/services/cloud-funnel-analytics.js.map +1 -1
  513. package/dist/services/settings.cjs +1 -1
  514. package/dist/services/settings.cjs.map +1 -1
  515. package/dist/services/settings.js +1 -0
  516. package/dist/services/settings.js.map +1 -1
  517. package/dist/services/telemetry-context.cjs +2 -0
  518. package/dist/services/telemetry-context.cjs.map +1 -0
  519. package/dist/services/telemetry-context.d.ts +17 -0
  520. package/dist/services/telemetry-context.js +27 -0
  521. package/dist/services/telemetry-context.js.map +1 -0
  522. package/dist/services/telemetry.cjs +1 -1
  523. package/dist/services/telemetry.cjs.map +1 -1
  524. package/dist/services/telemetry.d.ts +7 -5
  525. package/dist/services/telemetry.js +132 -123
  526. package/dist/services/telemetry.js.map +1 -1
  527. package/dist/stores/skill-install-banner-store.cjs +2 -0
  528. package/dist/stores/skill-install-banner-store.cjs.map +1 -0
  529. package/dist/stores/skill-install-banner-store.d.ts +32 -0
  530. package/dist/stores/skill-install-banner-store.js +14 -0
  531. package/dist/stores/skill-install-banner-store.js.map +1 -0
  532. package/dist/stores/use-event-store.cjs +1 -1
  533. package/dist/stores/use-event-store.cjs.map +1 -1
  534. package/dist/stores/use-event-store.js +35 -35
  535. package/dist/stores/use-event-store.js.map +1 -1
  536. package/dist/types/mcp-health.cjs +2 -0
  537. package/dist/types/mcp-health.cjs.map +1 -0
  538. package/dist/types/mcp-health.d.ts +21 -0
  539. package/dist/types/mcp-health.js +6 -0
  540. package/dist/types/mcp-health.js.map +1 -0
  541. package/dist/types/settings.d.ts +1 -0
  542. package/dist/utils/handle-event-for-ui.cjs +1 -1
  543. package/dist/utils/handle-event-for-ui.cjs.map +1 -1
  544. package/dist/utils/handle-event-for-ui.d.ts +5 -0
  545. package/dist/utils/handle-event-for-ui.js +71 -57
  546. package/dist/utils/handle-event-for-ui.js.map +1 -1
  547. package/dist/utils/mcp-credential-validation.cjs +1 -1
  548. package/dist/utils/mcp-credential-validation.cjs.map +1 -1
  549. package/dist/utils/mcp-credential-validation.js +32 -16
  550. package/dist/utils/mcp-credential-validation.js.map +1 -1
  551. package/dist/utils/mcp-server-health-key.cjs +2 -0
  552. package/dist/utils/mcp-server-health-key.cjs.map +1 -0
  553. package/dist/utils/mcp-server-health-key.d.ts +16 -0
  554. package/dist/utils/mcp-server-health-key.js +23 -0
  555. package/dist/utils/mcp-server-health-key.js.map +1 -0
  556. package/dist/utils/mcp-test-error-message.cjs +2 -0
  557. package/dist/utils/mcp-test-error-message.cjs.map +1 -0
  558. package/dist/utils/mcp-test-error-message.d.ts +8 -0
  559. package/dist/utils/mcp-test-error-message.js +14 -0
  560. package/dist/utils/mcp-test-error-message.js.map +1 -0
  561. package/dist/utils/redact-mcp-secrets.cjs +2 -0
  562. package/dist/utils/redact-mcp-secrets.cjs.map +1 -0
  563. package/dist/utils/redact-mcp-secrets.d.ts +13 -0
  564. package/dist/utils/redact-mcp-secrets.js +57 -0
  565. package/dist/utils/redact-mcp-secrets.js.map +1 -0
  566. package/dist/utils/settings-utils.cjs.map +1 -1
  567. package/dist/utils/settings-utils.js.map +1 -1
  568. package/dist/utils/skill-install-events.cjs +3 -0
  569. package/dist/utils/skill-install-events.cjs.map +1 -0
  570. package/dist/utils/skill-install-events.d.ts +16 -0
  571. package/dist/utils/skill-install-events.js +26 -0
  572. package/dist/utils/skill-install-events.js.map +1 -0
  573. package/dist/utils/title-llm-profile.cjs +2 -0
  574. package/dist/utils/title-llm-profile.cjs.map +1 -0
  575. package/dist/utils/title-llm-profile.d.ts +2 -0
  576. package/dist/utils/title-llm-profile.js +11 -0
  577. package/dist/utils/title-llm-profile.js.map +1 -0
  578. package/package.json +10 -3
  579. package/scripts/check-sdk-version-sync.mjs +6 -6
  580. package/scripts/check-translation-completeness.cjs +2 -0
  581. package/scripts/dev-process-utils.mjs +62 -1
  582. package/scripts/dev-safe.mjs +2 -2
  583. package/scripts/dev-static.mjs +5 -3
  584. package/scripts/dev-with-automation.mjs +98 -14
  585. package/scripts/download-node.mjs +382 -0
  586. package/scripts/download-uv.mjs +204 -0
  587. package/scripts/logger.mjs +64 -35
  588. package/build/assets/agent-server-compatibility-BWN-EIQn.js +0 -1
  589. package/build/assets/agent-server-conversation-service.api-DSPIkMwJ.js +0 -41
  590. package/build/assets/agent-settings-CgCnqaAA.js +0 -2
  591. package/build/assets/agent-settings-DDkSavD7.js +0 -1
  592. package/build/assets/api-key-entry-screen-iZc7n8AI.js +0 -1
  593. package/build/assets/app-settings-B5zyipxJ.js +0 -1
  594. package/build/assets/automation-export-BwRX6H32.js +0 -2
  595. package/build/assets/automations-list-lHAVzMoA.js +0 -1
  596. package/build/assets/backend-form-modal-RGcu909r.js +0 -1
  597. package/build/assets/browser-store-BI6uklCG.js +0 -1
  598. package/build/assets/chat-send-button-BZHG2hAW.js +0 -1
  599. package/build/assets/client-source-BZK8vRs2.js +0 -1
  600. package/build/assets/cloud-funnel-analytics-Zcv57hfT.js +0 -1
  601. package/build/assets/conversation-BoCYx8n2.js +0 -89
  602. package/build/assets/conversation-DgHqMjnY.js +0 -1
  603. package/build/assets/conversation-panel-78Rxh_-I.js +0 -1
  604. package/build/assets/conversation-state-store-B2Bp32XI.js +0 -1
  605. package/build/assets/declaration-BGsHjPEW.js +0 -1
  606. package/build/assets/extensions-hub-CCbLA7IM.js +0 -1
  607. package/build/assets/extensions-navigation-CPNjMNvR.js +0 -1
  608. package/build/assets/files-tab-store-DJsPxYdg.js +0 -1
  609. package/build/assets/files-tab-y4K7EXBO.js +0 -1
  610. package/build/assets/git-provider-icon-ITvsH4Ko.js +0 -1
  611. package/build/assets/home-BwbeOWwU.js +0 -1
  612. package/build/assets/home-DKPGQ5P3.js +0 -1
  613. package/build/assets/index-home-Bko2Itv5.js +0 -1
  614. package/build/assets/install-server-modal-Qk1gwyI8.js +0 -1
  615. package/build/assets/lesson-plan-DMCPdtrf.js +0 -4
  616. package/build/assets/llm-not-configured-banner-C1ktyb3C.js +0 -27
  617. package/build/assets/llm-settings-BBsZFi9l.js +0 -1
  618. package/build/assets/llm-settings-DFkJQr_w.js +0 -1
  619. package/build/assets/manage-backends-modal-CKQ46rvw.js +0 -1
  620. package/build/assets/manifest-03478bbf.js +0 -1
  621. package/build/assets/markdown-renderer-B4V2OMFP.js +0 -2
  622. package/build/assets/mcp-BapoJsDc.js +0 -9
  623. package/build/assets/messages-CUBFMY5o.js +0 -40
  624. package/build/assets/objectWithoutPropertiesLoose-BgYIAs2y.js +0 -1
  625. package/build/assets/onboarding-6NMkdNxV.js +0 -1
  626. package/build/assets/onboarding-modal-Q4AnpIdg.js +0 -1
  627. package/build/assets/recommended-automations-launcher-Bj7PuHY1.js +0 -58
  628. package/build/assets/refresh-cw-B9B7-vsy.js +0 -1
  629. package/build/assets/root-CDnuTToz.js +0 -2
  630. package/build/assets/root-CYWeTrWE.css +0 -1
  631. package/build/assets/root-layout-DfYVlcRG.js +0 -2
  632. package/build/assets/sdk-section-page-DLLNrYjI.js +0 -1
  633. package/build/assets/secrets-settings-CHy72A5C.js +0 -1
  634. package/build/assets/settings-B9S8UVQr.js +0 -1
  635. package/build/assets/settings-index-BKDl2CQ-.js +0 -1
  636. package/build/assets/settings-modal-DeK11CyT.js +0 -1
  637. package/build/assets/shared-conversation-9atDzTR4.js +0 -1
  638. package/build/assets/sidebar-mobile-menu-toggle-giMMZctn.js +0 -1
  639. package/build/assets/skills-plugins-Tropusio.js +0 -1
  640. package/build/assets/skills-settings-BvzBBCWk.js +0 -2
  641. package/build/assets/telemetry-C5JMEfqB.js +0 -2
  642. package/build/assets/use-activate-agent-profile-DlykqEfN.js +0 -1
  643. package/build/assets/use-backends-health-CLHPitJM.js +0 -1
  644. package/build/assets/use-config-B5r8erYt.js +0 -1
  645. package/build/assets/use-event-store-Bbaz51GR.js +0 -4
  646. package/build/assets/use-llm-profiles-Dr5__SlZ.js +0 -1
  647. package/build/assets/use-plugins-marketplace-BplU65ae.js +0 -1
  648. package/build/assets/use-runtime-is-ready-vCFOcLFa.js +0 -1
  649. package/build/assets/use-settings-CyxSlyTQ.js +0 -1
  650. package/build/assets/use-settings-nav-items-zEkSO_Bf.js +0 -16
  651. package/build/assets/use-tracking-D2Qg5Lpd.js +0 -1
  652. package/build/assets/useMutationState-OnAsCLA_.js +0 -1
  653. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BD7v71DM.js +0 -2
  654. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-BT05Osu4.js +0 -28
  655. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-COhHANvV.js +0 -2
  656. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DgzWSMRc.js +0 -2
  657. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-DqZatR3B.js +0 -7
  658. package/build/assets/vendor~index-home~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-FghQ3Z1a.js +0 -1
  659. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-BTvhGHHG.js +0 -1
  660. package/build/assets/vendor~root-layout~index-home~home~mcp~automations-list~onboarding-modal-C4-GDgiF.js +0 -1
  661. package/dist/components/features/analytics/telemetry-consent-banner.cjs +0 -2
  662. package/dist/components/features/analytics/telemetry-consent-banner.cjs.map +0 -1
  663. package/dist/components/features/analytics/telemetry-consent-banner.d.ts +0 -29
  664. package/dist/components/features/analytics/telemetry-consent-banner.js +0 -59
  665. package/dist/components/features/analytics/telemetry-consent-banner.js.map +0 -1
  666. /package/build/assets/{__vite-browser-external-BQUj0sYu.js → __vite-browser-external-CKHVBTNC.js} +0 -0
  667. /package/build/assets/{agent-server-ui-style-scope-qhnhZHBV.js → agent-server-ui-style-scope-BvSa9on7.js} +0 -0
  668. /package/build/assets/{automation-LZB0MjdV.js → automation-BGiPmxFR.js} +0 -0
  669. /package/build/assets/{canvas-ui-COgjltGz.js → canvas-ui-CC4EJo-H.js} +0 -0
  670. /package/build/assets/{checkmark-h7udgXMM.js → checkmark-ygQB1AtV.js} +0 -0
  671. /package/build/assets/{close-DLFb5kfv.js → close-BjSA0HWT.js} +0 -0
  672. /package/build/assets/{code-tag-DYlAhEQY.js → code-tag-D9aPPbOe.js} +0 -0
  673. /package/build/assets/{common-CxbUL3nR.js → common-CCuqQy_S.js} +0 -0
  674. /package/build/assets/{conversation-local-storage-F6zVMM--.js → conversation-local-storage-BDjWPg0Z.js} +0 -0
  675. /package/build/assets/{copy-BLmGeJcd.js → copy-Dce7sOvS.js} +0 -0
  676. /package/build/assets/{copy-D1YGjP-C.js → copy-iPJAncAj.js} +0 -0
  677. /package/build/assets/{dist-CodhvuAP.js → dist-D9PhjOaq.js} +0 -0
  678. /package/build/assets/{environment-switch-store-DkjlKWzN.js → environment-switch-store-DHfcz4M4.js} +0 -0
  679. /package/build/assets/{extension-module-card-classes-9V3J9J_b.js → extension-module-card-classes-BpebKiN6.js} +0 -0
  680. /package/build/assets/{external-link-lhdITPqq.js → external-link-CpPMXxrV.js} +0 -0
  681. /package/build/assets/{folder-Bk311brm.js → folder-BabbYnbF.js} +0 -0
  682. /package/build/assets/{format-time-delta-DhDbkD7V.js → format-time-delta-BkAmJEPT.js} +0 -0
  683. /package/build/assets/{get-language-from-path-DBqBsCWH.js → get-language-from-path-CPNnuVhI.js} +0 -0
  684. /package/build/assets/{git-status-mapper-DnL9OC8_.js → git-status-mapper-BIXK0AAG.js} +0 -0
  685. /package/build/assets/{iconBase-Dz51Zn5x.js → iconBase-Ch-fOe8B.js} +0 -0
  686. /package/build/assets/{link-external-CaBmUEs_.js → link-external-DfKQroKX.js} +0 -0
  687. /package/build/assets/{list-todo-CAtvkzcy.js → list-todo-6J6zc8oS.js} +0 -0
  688. /package/build/assets/{llm-subscription-DtsX5Lhg.js → llm-subscription-Bvu8BLXc.js} +0 -0
  689. /package/build/assets/{loader-circle-CsAsfLIs.js → loader-circle-DGsqG5qw.js} +0 -0
  690. /package/build/assets/{map-provider-BbIb12oh.js → map-provider-BSvXvVR0.js} +0 -0
  691. /package/build/assets/{middleware-DYHYNAnP.js → middleware-_izt7V6U.js} +0 -0
  692. /package/build/assets/{modal-backdrop-zVwfOJZr.js → modal-backdrop-B7H42xHG.js} +0 -0
  693. /package/build/assets/{navigation-context-DPs2G0X8.js → navigation-context-cvyvI1WA.js} +0 -0
  694. /package/build/assets/{openhands-logo-bcNw5bkY.js → openhands-logo-pEw0nKFP.js} +0 -0
  695. /package/build/assets/{pencil-CWhApFIT.js → pencil-DmSqWUA3.js} +0 -0
  696. /package/build/assets/{react-DPDgL6du.js → react-MKQOkha9.js} +0 -0
  697. /package/build/assets/{search-BgOCR7_c.js → search-B5D5EuSn.js} +0 -0
  698. /package/build/assets/{search-dIQ09UY2.js → search-vnYL5jwV.js} +0 -0
  699. /package/build/assets/{settings-gear-MXCyZW0x.js → settings-gear-BOwF59Bs.js} +0 -0
  700. /package/build/assets/{settings-section-header-context-COMOIaxV.js → settings-section-header-context-CGgHZXrf.js} +0 -0
  701. /package/build/assets/{skills-EqzxYBvT.js → skills-arUOHLcS.js} +0 -0
  702. /package/build/assets/{square-chevron-right-DE-JN-2Z.js → square-chevron-right-EizCGtgq.js} +0 -0
  703. /package/build/assets/{switch-skeleton-DqQwalyu.js → switch-skeleton-BjPRx1QD.js} +0 -0
  704. /package/build/assets/{terminal-Cgf___rK.js → terminal-a57bHgZs.js} +0 -0
  705. /package/build/assets/{trash-2-BU6BlW4i.js → trash-2-CF3hilrY.js} +0 -0
  706. /package/build/assets/{u-check-circle-BqoIxNz_.js → u-check-circle-WGqHdtfO.js} +0 -0
  707. /package/build/assets/{u-check-circle-half-MsShT8Ec.js → u-check-circle-half-LiwZkuFe.js} +0 -0
  708. /package/build/assets/{u-edit-DL5LgKon.js → u-edit-BwHepAPi.js} +0 -0
  709. /package/build/assets/{use-breakpoint-BP3lqLMx.js → use-breakpoint-B-O0lQ84.js} +0 -0
  710. /package/build/assets/{use-click-outside-element-D9BYdANT.js → use-click-outside-element-DLQIMQrz.js} +0 -0
  711. /package/build/assets/{use-is-authed-BezEyfeh.js → use-is-authed-BSeo4coy.js} +0 -0
  712. /package/build/assets/{use-onboarding-completion-C_Swglzp.js → use-onboarding-completion-C0hPNGpw.js} +0 -0
  713. /package/build/assets/{v4-DbCkTSoU.js → v4-q4yWTlMz.js} +0 -0
  714. /package/build/assets/{vendor~browser-By2MVv_N.js → vendor~browser-UwB1jbAZ.js} +0 -0
  715. /package/build/assets/{vendor~conversation-panel~conversation~alert-banner-CxfzCmkN.js → vendor~conversation-panel~conversation~alert-banner-DHDkknt5.js} +0 -0
  716. /package/build/assets/{vendor~index-home~home~conversation-panel~conversation-ChmYLVgz.js → vendor~index-home~home~conversation-panel~conversation-Bff9cq5J.js} +0 -0
  717. /package/build/assets/{vendor~module-D5a_AClf.js → vendor~module-D4DeFV4J.js} +0 -0
  718. /package/build/assets/{vendor~terminal-CnKZILnC.js → vendor~terminal-B7Eiak0-.js} +0 -0
  719. /package/build/assets/{x-ZE4iplpF.js → x-DQB_00VJ.js} +0 -0
  720. /package/build/assets/{x-mark-Batp6gXa.js → x-mark-B32XuEwS.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-credential-validation.cjs","names":[],"sources":["../../src/utils/mcp-credential-validation.ts"],"sourcesContent":["import { INTEGRATION_CATALOG as MCP_MARKETPLACE } from \"@openhands/extensions/integrations\";\nimport {\n findCatalogEntryForServer,\n getMcpMarketplaceCatalog,\n} from \"#/utils/mcp-marketplace-utils\";\nimport type {\n MCPServerConfig,\n MCPTestToolCall,\n MCPTestToolResult,\n} from \"#/types/mcp-server\";\n\n/**\n * Credential validation specs for marketplace MCP servers whose credentials\n * are only exercised on tool invocation (listing tools succeeds with any\n * credentials). The test endpoint runs `toolCall` after listing and reports\n * the outcome verbatim; `interpret` decides whether that outcome proves the\n * credentials are invalid.\n *\n * `toolCall` MUST be read-only — it runs on every \"Test connection\" /\n * pre-save validation.\n */\nexport interface CredentialValidation {\n toolCall: MCPTestToolCall;\n /** Returns the provider's error code/message, or null when creds pass. */\n interpret: (toolResult: MCPTestToolResult) => string | null;\n}\n\n/**\n * Slack error codes that mean the credentials themselves are bad. Anything\n * else (e.g. `missing_scope`) proves the token *authenticated* — a valid\n * token lacking a scope must not be reported as invalid credentials.\n */\nconst SLACK_AUTH_FAILURES = new Set([\n \"invalid_auth\",\n \"not_authed\",\n \"account_inactive\",\n \"token_revoked\",\n \"token_expired\",\n]);\n\nconst VALIDATION_BY_ENTRY_ID: Record<string, CredentialValidation> = {\n slack: {\n // Read-only: lists at most one channel. The Slack MCP server returns\n // the raw Slack API JSON ({ok: boolean, error?: string}) as text.\n toolCall: { name: \"slack_list_channels\", arguments: { limit: 1 } },\n interpret: (toolResult) => {\n if (toolResult.is_error) {\n return toolResult.text || \"tool call failed\";\n }\n try {\n const parsed = JSON.parse(toolResult.text);\n if (parsed?.ok === false && SLACK_AUTH_FAILURES.has(parsed.error)) {\n return String(parsed.error);\n }\n } catch {\n // Non-JSON payload — make no claim about the credentials.\n }\n return null;\n },\n },\n};\n\n/**\n * Look up the credential validation for a server by matching it to its\n * marketplace catalog entry (same matching the MCP page uses for icons).\n * Returns undefined for custom servers — their test behaves as before.\n */\nexport function getCredentialValidationForServer(\n server: MCPServerConfig,\n): CredentialValidation | undefined {\n const entry = findCatalogEntryForServer(\n server,\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n );\n return entry ? VALIDATION_BY_ENTRY_ID[entry.id] : undefined;\n}\n"],"mappings":"sKAgCA,IAAM,EAAsB,IAAI,IAAI,CAClC,eACA,aACA,mBACA,gBACA,gBACD,CAAC,CAEI,EAA+D,CACnE,MAAO,CAGL,SAAU,CAAE,KAAM,sBAAuB,UAAW,CAAE,MAAO,EAAG,CAAE,CAClE,UAAY,GAAe,CACzB,GAAI,EAAW,SACb,OAAO,EAAW,MAAQ,mBAE5B,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,EAAW,KAAK,CAC1C,GAAI,GAAQ,KAAO,IAAS,EAAoB,IAAI,EAAO,MAAM,CAC/D,OAAO,OAAO,EAAO,MAAM,MAEvB,EAGR,OAAO,MAEV,CACF,CAOD,SAAgB,EACd,EACkC,CAClC,IAAM,EAAQ,EAAA,0BACZ,EACA,EAAA,yBAAyB,EAAA,QAAgB,CAC1C,CACD,OAAO,EAAQ,EAAuB,EAAM,IAAM,IAAA"}
1
+ {"version":3,"file":"mcp-credential-validation.cjs","names":[],"sources":["../../src/utils/mcp-credential-validation.ts"],"sourcesContent":["import { INTEGRATION_CATALOG as MCP_MARKETPLACE } from \"@openhands/extensions/integrations\";\nimport {\n findCatalogEntryForServer,\n getMcpMarketplaceCatalog,\n} from \"#/utils/mcp-marketplace-utils\";\nimport type {\n MCPServerConfig,\n MCPTestToolCall,\n MCPTestToolResult,\n} from \"#/types/mcp-server\";\n\n/**\n * Credential validation specs for marketplace MCP servers whose credentials\n * are only exercised on tool invocation (listing tools succeeds with any\n * credentials). The test endpoint runs `toolCall` after listing and reports\n * the outcome verbatim; `interpret` decides whether that outcome proves the\n * credentials are invalid.\n *\n * `toolCall` MUST be read-only — it runs on every \"Test connection\" /\n * pre-save validation.\n */\nexport interface CredentialValidation {\n toolCall: MCPTestToolCall;\n /** Returns the provider's error code/message, or null when creds pass. */\n interpret: (toolResult: MCPTestToolResult) => string | null;\n}\n\n/**\n * Slack error codes that mean the credentials themselves are bad. Anything\n * else (e.g. `missing_scope`) proves the token *authenticated* — a valid\n * token lacking a scope must not be reported as invalid credentials.\n */\nconst SLACK_AUTH_FAILURES = new Set([\n \"invalid_auth\",\n \"not_authed\",\n \"account_inactive\",\n \"token_revoked\",\n \"token_expired\",\n]);\n\n/**\n * Interpreter for hosted HTTP API servers (GitHub, Linear). The service only\n * calls `interpret` when the probe tool was advertised by the server AND\n * invoked, so `is_error` here means the read-only call itself failed — for a\n * \"who am I\" / \"list teams\" probe that is an auth/permission failure.\n */\nconst interpretReadOnlyToolResult = (\n toolResult: MCPTestToolResult,\n): string | null =>\n toolResult.is_error ? toolResult.text || \"tool call failed\" : null;\n\nconst VALIDATION_BY_ENTRY_ID: Record<string, CredentialValidation> = {\n github: {\n // Official GitHub MCP server (api.githubcopilot.com): read-only\n // \"get details of the authenticated user\".\n toolCall: { name: \"get_me\", arguments: {} },\n interpret: interpretReadOnlyToolResult,\n },\n linear: {\n // Linear hosted MCP (mcp.linear.app): read-only teams listing with no\n // required arguments.\n toolCall: { name: \"list_teams\", arguments: {} },\n interpret: interpretReadOnlyToolResult,\n },\n slack: {\n // Read-only: lists at most one channel. The Slack MCP server returns\n // the raw Slack API JSON ({ok: boolean, error?: string}) as text.\n toolCall: { name: \"slack_list_channels\", arguments: { limit: 1 } },\n interpret: (toolResult) => {\n if (toolResult.is_error) {\n return toolResult.text || \"tool call failed\";\n }\n try {\n const parsed = JSON.parse(toolResult.text);\n if (parsed?.ok === false && SLACK_AUTH_FAILURES.has(parsed.error)) {\n return String(parsed.error);\n }\n } catch {\n // Non-JSON payload — make no claim about the credentials.\n }\n return null;\n },\n },\n};\n\n/**\n * Look up the credential validation for a server by matching it to its\n * marketplace catalog entry (same matching the MCP page uses for icons).\n * Returns undefined for custom servers — their test behaves as before.\n */\nexport function getCredentialValidationForServer(\n server: MCPServerConfig,\n): CredentialValidation | undefined {\n const entry = findCatalogEntryForServer(\n server,\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n );\n return entry ? VALIDATION_BY_ENTRY_ID[entry.id] : undefined;\n}\n"],"mappings":"sKAgCA,IAAM,EAAsB,IAAI,IAAI,CAClC,eACA,aACA,mBACA,gBACA,gBACD,CAAC,CAQI,EACJ,GAEA,EAAW,SAAW,EAAW,MAAQ,mBAAqB,KAE1D,EAA+D,CACnE,OAAQ,CAGN,SAAU,CAAE,KAAM,SAAU,UAAW,EAAE,CAAE,CAC3C,UAAW,EACZ,CACD,OAAQ,CAGN,SAAU,CAAE,KAAM,aAAc,UAAW,EAAE,CAAE,CAC/C,UAAW,EACZ,CACD,MAAO,CAGL,SAAU,CAAE,KAAM,sBAAuB,UAAW,CAAE,MAAO,EAAG,CAAE,CAClE,UAAY,GAAe,CACzB,GAAI,EAAW,SACb,OAAO,EAAW,MAAQ,mBAE5B,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,EAAW,KAAK,CAC1C,GAAI,GAAQ,KAAO,IAAS,EAAoB,IAAI,EAAO,MAAM,CAC/D,OAAO,OAAO,EAAO,MAAM,MAEvB,EAGR,OAAO,MAEV,CACF,CAOD,SAAgB,EACd,EACkC,CAClC,IAAM,EAAQ,EAAA,0BACZ,EACA,EAAA,yBAAyB,EAAA,QAAgB,CAC1C,CACD,OAAO,EAAQ,EAAuB,EAAM,IAAM,IAAA"}
@@ -7,25 +7,41 @@ var r = new Set([
7
7
  "account_inactive",
8
8
  "token_revoked",
9
9
  "token_expired"
10
- ]), i = { slack: {
11
- toolCall: {
12
- name: "slack_list_channels",
13
- arguments: { limit: 1 }
10
+ ]), i = (e) => e.is_error ? e.text || "tool call failed" : null, a = {
11
+ github: {
12
+ toolCall: {
13
+ name: "get_me",
14
+ arguments: {}
15
+ },
16
+ interpret: i
14
17
  },
15
- interpret: (e) => {
16
- if (e.is_error) return e.text || "tool call failed";
17
- try {
18
- let t = JSON.parse(e.text);
19
- if (t?.ok === !1 && r.has(t.error)) return String(t.error);
20
- } catch {}
21
- return null;
18
+ linear: {
19
+ toolCall: {
20
+ name: "list_teams",
21
+ arguments: {}
22
+ },
23
+ interpret: i
24
+ },
25
+ slack: {
26
+ toolCall: {
27
+ name: "slack_list_channels",
28
+ arguments: { limit: 1 }
29
+ },
30
+ interpret: (e) => {
31
+ if (e.is_error) return e.text || "tool call failed";
32
+ try {
33
+ let t = JSON.parse(e.text);
34
+ if (t?.ok === !1 && r.has(t.error)) return String(t.error);
35
+ } catch {}
36
+ return null;
37
+ }
22
38
  }
23
- } };
24
- function a(r) {
25
- let a = e(r, t(n));
26
- return a ? i[a.id] : void 0;
39
+ };
40
+ function o(r) {
41
+ let i = e(r, t(n));
42
+ return i ? a[i.id] : void 0;
27
43
  }
28
44
  //#endregion
29
- export { a as getCredentialValidationForServer };
45
+ export { o as getCredentialValidationForServer };
30
46
 
31
47
  //# sourceMappingURL=mcp-credential-validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-credential-validation.js","names":[],"sources":["../../src/utils/mcp-credential-validation.ts"],"sourcesContent":["import { INTEGRATION_CATALOG as MCP_MARKETPLACE } from \"@openhands/extensions/integrations\";\nimport {\n findCatalogEntryForServer,\n getMcpMarketplaceCatalog,\n} from \"#/utils/mcp-marketplace-utils\";\nimport type {\n MCPServerConfig,\n MCPTestToolCall,\n MCPTestToolResult,\n} from \"#/types/mcp-server\";\n\n/**\n * Credential validation specs for marketplace MCP servers whose credentials\n * are only exercised on tool invocation (listing tools succeeds with any\n * credentials). The test endpoint runs `toolCall` after listing and reports\n * the outcome verbatim; `interpret` decides whether that outcome proves the\n * credentials are invalid.\n *\n * `toolCall` MUST be read-only — it runs on every \"Test connection\" /\n * pre-save validation.\n */\nexport interface CredentialValidation {\n toolCall: MCPTestToolCall;\n /** Returns the provider's error code/message, or null when creds pass. */\n interpret: (toolResult: MCPTestToolResult) => string | null;\n}\n\n/**\n * Slack error codes that mean the credentials themselves are bad. Anything\n * else (e.g. `missing_scope`) proves the token *authenticated* — a valid\n * token lacking a scope must not be reported as invalid credentials.\n */\nconst SLACK_AUTH_FAILURES = new Set([\n \"invalid_auth\",\n \"not_authed\",\n \"account_inactive\",\n \"token_revoked\",\n \"token_expired\",\n]);\n\nconst VALIDATION_BY_ENTRY_ID: Record<string, CredentialValidation> = {\n slack: {\n // Read-only: lists at most one channel. The Slack MCP server returns\n // the raw Slack API JSON ({ok: boolean, error?: string}) as text.\n toolCall: { name: \"slack_list_channels\", arguments: { limit: 1 } },\n interpret: (toolResult) => {\n if (toolResult.is_error) {\n return toolResult.text || \"tool call failed\";\n }\n try {\n const parsed = JSON.parse(toolResult.text);\n if (parsed?.ok === false && SLACK_AUTH_FAILURES.has(parsed.error)) {\n return String(parsed.error);\n }\n } catch {\n // Non-JSON payload — make no claim about the credentials.\n }\n return null;\n },\n },\n};\n\n/**\n * Look up the credential validation for a server by matching it to its\n * marketplace catalog entry (same matching the MCP page uses for icons).\n * Returns undefined for custom servers — their test behaves as before.\n */\nexport function getCredentialValidationForServer(\n server: MCPServerConfig,\n): CredentialValidation | undefined {\n const entry = findCatalogEntryForServer(\n server,\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n );\n return entry ? VALIDATION_BY_ENTRY_ID[entry.id] : undefined;\n}\n"],"mappings":";;;AAgCA,IAAM,IAAsB,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACD,CAAC,EAEI,IAA+D,EACnE,OAAO;CAGL,UAAU;EAAE,MAAM;EAAuB,WAAW,EAAE,OAAO,GAAG;EAAE;CAClE,YAAY,MAAe;AACzB,MAAI,EAAW,SACb,QAAO,EAAW,QAAQ;AAE5B,MAAI;GACF,IAAM,IAAS,KAAK,MAAM,EAAW,KAAK;AAC1C,OAAI,GAAQ,OAAO,MAAS,EAAoB,IAAI,EAAO,MAAM,CAC/D,QAAO,OAAO,EAAO,MAAM;UAEvB;AAGR,SAAO;;CAEV,EACF;AAOD,SAAgB,EACd,GACkC;CAClC,IAAM,IAAQ,EACZ,GACA,EAAyB,EAAgB,CAC1C;AACD,QAAO,IAAQ,EAAuB,EAAM,MAAM,KAAA"}
1
+ {"version":3,"file":"mcp-credential-validation.js","names":[],"sources":["../../src/utils/mcp-credential-validation.ts"],"sourcesContent":["import { INTEGRATION_CATALOG as MCP_MARKETPLACE } from \"@openhands/extensions/integrations\";\nimport {\n findCatalogEntryForServer,\n getMcpMarketplaceCatalog,\n} from \"#/utils/mcp-marketplace-utils\";\nimport type {\n MCPServerConfig,\n MCPTestToolCall,\n MCPTestToolResult,\n} from \"#/types/mcp-server\";\n\n/**\n * Credential validation specs for marketplace MCP servers whose credentials\n * are only exercised on tool invocation (listing tools succeeds with any\n * credentials). The test endpoint runs `toolCall` after listing and reports\n * the outcome verbatim; `interpret` decides whether that outcome proves the\n * credentials are invalid.\n *\n * `toolCall` MUST be read-only — it runs on every \"Test connection\" /\n * pre-save validation.\n */\nexport interface CredentialValidation {\n toolCall: MCPTestToolCall;\n /** Returns the provider's error code/message, or null when creds pass. */\n interpret: (toolResult: MCPTestToolResult) => string | null;\n}\n\n/**\n * Slack error codes that mean the credentials themselves are bad. Anything\n * else (e.g. `missing_scope`) proves the token *authenticated* — a valid\n * token lacking a scope must not be reported as invalid credentials.\n */\nconst SLACK_AUTH_FAILURES = new Set([\n \"invalid_auth\",\n \"not_authed\",\n \"account_inactive\",\n \"token_revoked\",\n \"token_expired\",\n]);\n\n/**\n * Interpreter for hosted HTTP API servers (GitHub, Linear). The service only\n * calls `interpret` when the probe tool was advertised by the server AND\n * invoked, so `is_error` here means the read-only call itself failed — for a\n * \"who am I\" / \"list teams\" probe that is an auth/permission failure.\n */\nconst interpretReadOnlyToolResult = (\n toolResult: MCPTestToolResult,\n): string | null =>\n toolResult.is_error ? toolResult.text || \"tool call failed\" : null;\n\nconst VALIDATION_BY_ENTRY_ID: Record<string, CredentialValidation> = {\n github: {\n // Official GitHub MCP server (api.githubcopilot.com): read-only\n // \"get details of the authenticated user\".\n toolCall: { name: \"get_me\", arguments: {} },\n interpret: interpretReadOnlyToolResult,\n },\n linear: {\n // Linear hosted MCP (mcp.linear.app): read-only teams listing with no\n // required arguments.\n toolCall: { name: \"list_teams\", arguments: {} },\n interpret: interpretReadOnlyToolResult,\n },\n slack: {\n // Read-only: lists at most one channel. The Slack MCP server returns\n // the raw Slack API JSON ({ok: boolean, error?: string}) as text.\n toolCall: { name: \"slack_list_channels\", arguments: { limit: 1 } },\n interpret: (toolResult) => {\n if (toolResult.is_error) {\n return toolResult.text || \"tool call failed\";\n }\n try {\n const parsed = JSON.parse(toolResult.text);\n if (parsed?.ok === false && SLACK_AUTH_FAILURES.has(parsed.error)) {\n return String(parsed.error);\n }\n } catch {\n // Non-JSON payload — make no claim about the credentials.\n }\n return null;\n },\n },\n};\n\n/**\n * Look up the credential validation for a server by matching it to its\n * marketplace catalog entry (same matching the MCP page uses for icons).\n * Returns undefined for custom servers — their test behaves as before.\n */\nexport function getCredentialValidationForServer(\n server: MCPServerConfig,\n): CredentialValidation | undefined {\n const entry = findCatalogEntryForServer(\n server,\n getMcpMarketplaceCatalog(MCP_MARKETPLACE),\n );\n return entry ? VALIDATION_BY_ENTRY_ID[entry.id] : undefined;\n}\n"],"mappings":";;;AAgCA,IAAM,IAAsB,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACD,CAAC,EAQI,KACJ,MAEA,EAAW,WAAW,EAAW,QAAQ,qBAAqB,MAE1D,IAA+D;CACnE,QAAQ;EAGN,UAAU;GAAE,MAAM;GAAU,WAAW,EAAE;GAAE;EAC3C,WAAW;EACZ;CACD,QAAQ;EAGN,UAAU;GAAE,MAAM;GAAc,WAAW,EAAE;GAAE;EAC/C,WAAW;EACZ;CACD,OAAO;EAGL,UAAU;GAAE,MAAM;GAAuB,WAAW,EAAE,OAAO,GAAG;GAAE;EAClE,YAAY,MAAe;AACzB,OAAI,EAAW,SACb,QAAO,EAAW,QAAQ;AAE5B,OAAI;IACF,IAAM,IAAS,KAAK,MAAM,EAAW,KAAK;AAC1C,QAAI,GAAQ,OAAO,MAAS,EAAoB,IAAI,EAAO,MAAM,CAC/D,QAAO,OAAO,EAAO,MAAM;WAEvB;AAGR,UAAO;;EAEV;CACF;AAOD,SAAgB,EACd,GACkC;CAClC,IAAM,IAAQ,EACZ,GACA,EAAyB,EAAgB,CAC1C;AACD,QAAO,IAAQ,EAAuB,EAAM,MAAM,KAAA"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);var e=e=>Object.keys(e??{}).sort();function t(t){return t.type===`stdio`?JSON.stringify({type:t.type,name:t.name??``,command:t.command??``,args:t.args??[],envKeys:e(t.env)}):JSON.stringify({type:t.type,name:t.name??``,url:t.url??``,headerKeys:e(t.headers),authStrategy:t.auth?.strategy??``,authHeaderName:t.auth?.strategy===`api_key`?t.auth.header_name??``:``,authHeaderKeys:t.auth?.strategy===`header`?e(t.auth.headers):[]})}exports.getMcpServerHealthKey=t;
2
+ //# sourceMappingURL=mcp-server-health-key.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server-health-key.cjs","names":[],"sources":["../../src/utils/mcp-server-health-key.ts"],"sourcesContent":["import type { MCPServerConfig } from \"#/types/mcp-server\";\n\nconst sortedKeys = (record?: Record<string, string> | null): string[] =>\n Object.keys(record ?? {}).sort();\n\n/**\n * Stable identity for a server's health entry.\n *\n * Built from the server's structural, non-secret fields. Names are included\n * because persisted configs are keyed by name (`toSdkMcpConfig` suffixes\n * duplicates `github` → `github_1`), which makes the key unique per stored\n * server and stable across list reordering — unlike the positional\n * `sse-0`/`stdio-1` ids from `flattenMcpConfig`. Secret VALUES are excluded:\n * the same credential legitimately appears as plaintext at install time,\n * `**********` in redacted settings, and ciphertext in test requests, so any\n * of them would make the key flap. A structural edit (URL, command, header\n * names, auth strategy, ...) therefore produces a new key, orphaning the old\n * health entry instead of misattributing it.\n */\nexport function getMcpServerHealthKey(server: MCPServerConfig): string {\n if (server.type === \"stdio\") {\n return JSON.stringify({\n type: server.type,\n name: server.name ?? \"\",\n command: server.command ?? \"\",\n args: server.args ?? [],\n envKeys: sortedKeys(server.env),\n });\n }\n return JSON.stringify({\n type: server.type,\n name: server.name ?? \"\",\n url: server.url ?? \"\",\n headerKeys: sortedKeys(server.headers),\n authStrategy: server.auth?.strategy ?? \"\",\n authHeaderName:\n server.auth?.strategy === \"api_key\"\n ? (server.auth.header_name ?? \"\")\n : \"\",\n authHeaderKeys:\n server.auth?.strategy === \"header\" ? sortedKeys(server.auth.headers) : [],\n });\n}\n"],"mappings":"6CAEA,IAAM,EAAc,GAClB,OAAO,KAAK,GAAU,EAAE,CAAC,CAAC,MAAM,CAgBlC,SAAgB,EAAsB,EAAiC,CAUrE,OATI,EAAO,OAAS,QACX,KAAK,UAAU,CACpB,KAAM,EAAO,KACb,KAAM,EAAO,MAAQ,GACrB,QAAS,EAAO,SAAW,GAC3B,KAAM,EAAO,MAAQ,EAAE,CACvB,QAAS,EAAW,EAAO,IAAI,CAChC,CAAC,CAEG,KAAK,UAAU,CACpB,KAAM,EAAO,KACb,KAAM,EAAO,MAAQ,GACrB,IAAK,EAAO,KAAO,GACnB,WAAY,EAAW,EAAO,QAAQ,CACtC,aAAc,EAAO,MAAM,UAAY,GACvC,eACE,EAAO,MAAM,WAAa,UACrB,EAAO,KAAK,aAAe,GAC5B,GACN,eACE,EAAO,MAAM,WAAa,SAAW,EAAW,EAAO,KAAK,QAAQ,CAAG,EAAE,CAC5E,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { MCPServerConfig } from "#/types/mcp-server";
2
+ /**
3
+ * Stable identity for a server's health entry.
4
+ *
5
+ * Built from the server's structural, non-secret fields. Names are included
6
+ * because persisted configs are keyed by name (`toSdkMcpConfig` suffixes
7
+ * duplicates `github` → `github_1`), which makes the key unique per stored
8
+ * server and stable across list reordering — unlike the positional
9
+ * `sse-0`/`stdio-1` ids from `flattenMcpConfig`. Secret VALUES are excluded:
10
+ * the same credential legitimately appears as plaintext at install time,
11
+ * `**********` in redacted settings, and ciphertext in test requests, so any
12
+ * of them would make the key flap. A structural edit (URL, command, header
13
+ * names, auth strategy, ...) therefore produces a new key, orphaning the old
14
+ * health entry instead of misattributing it.
15
+ */
16
+ export declare function getMcpServerHealthKey(server: MCPServerConfig): string;
@@ -0,0 +1,23 @@
1
+ //#region src/utils/mcp-server-health-key.ts
2
+ var e = (e) => Object.keys(e ?? {}).sort();
3
+ function t(t) {
4
+ return t.type === "stdio" ? JSON.stringify({
5
+ type: t.type,
6
+ name: t.name ?? "",
7
+ command: t.command ?? "",
8
+ args: t.args ?? [],
9
+ envKeys: e(t.env)
10
+ }) : JSON.stringify({
11
+ type: t.type,
12
+ name: t.name ?? "",
13
+ url: t.url ?? "",
14
+ headerKeys: e(t.headers),
15
+ authStrategy: t.auth?.strategy ?? "",
16
+ authHeaderName: t.auth?.strategy === "api_key" ? t.auth.header_name ?? "" : "",
17
+ authHeaderKeys: t.auth?.strategy === "header" ? e(t.auth.headers) : []
18
+ });
19
+ }
20
+ //#endregion
21
+ export { t as getMcpServerHealthKey };
22
+
23
+ //# sourceMappingURL=mcp-server-health-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server-health-key.js","names":[],"sources":["../../src/utils/mcp-server-health-key.ts"],"sourcesContent":["import type { MCPServerConfig } from \"#/types/mcp-server\";\n\nconst sortedKeys = (record?: Record<string, string> | null): string[] =>\n Object.keys(record ?? {}).sort();\n\n/**\n * Stable identity for a server's health entry.\n *\n * Built from the server's structural, non-secret fields. Names are included\n * because persisted configs are keyed by name (`toSdkMcpConfig` suffixes\n * duplicates `github` → `github_1`), which makes the key unique per stored\n * server and stable across list reordering — unlike the positional\n * `sse-0`/`stdio-1` ids from `flattenMcpConfig`. Secret VALUES are excluded:\n * the same credential legitimately appears as plaintext at install time,\n * `**********` in redacted settings, and ciphertext in test requests, so any\n * of them would make the key flap. A structural edit (URL, command, header\n * names, auth strategy, ...) therefore produces a new key, orphaning the old\n * health entry instead of misattributing it.\n */\nexport function getMcpServerHealthKey(server: MCPServerConfig): string {\n if (server.type === \"stdio\") {\n return JSON.stringify({\n type: server.type,\n name: server.name ?? \"\",\n command: server.command ?? \"\",\n args: server.args ?? [],\n envKeys: sortedKeys(server.env),\n });\n }\n return JSON.stringify({\n type: server.type,\n name: server.name ?? \"\",\n url: server.url ?? \"\",\n headerKeys: sortedKeys(server.headers),\n authStrategy: server.auth?.strategy ?? \"\",\n authHeaderName:\n server.auth?.strategy === \"api_key\"\n ? (server.auth.header_name ?? \"\")\n : \"\",\n authHeaderKeys:\n server.auth?.strategy === \"header\" ? sortedKeys(server.auth.headers) : [],\n });\n}\n"],"mappings":";AAEA,IAAM,KAAc,MAClB,OAAO,KAAK,KAAU,EAAE,CAAC,CAAC,MAAM;AAgBlC,SAAgB,EAAsB,GAAiC;AAUrE,QATI,EAAO,SAAS,UACX,KAAK,UAAU;EACpB,MAAM,EAAO;EACb,MAAM,EAAO,QAAQ;EACrB,SAAS,EAAO,WAAW;EAC3B,MAAM,EAAO,QAAQ,EAAE;EACvB,SAAS,EAAW,EAAO,IAAI;EAChC,CAAC,GAEG,KAAK,UAAU;EACpB,MAAM,EAAO;EACb,MAAM,EAAO,QAAQ;EACrB,KAAK,EAAO,OAAO;EACnB,YAAY,EAAW,EAAO,QAAQ;EACtC,cAAc,EAAO,MAAM,YAAY;EACvC,gBACE,EAAO,MAAM,aAAa,YACrB,EAAO,KAAK,eAAe,KAC5B;EACN,gBACE,EAAO,MAAM,aAAa,WAAW,EAAW,EAAO,KAAK,QAAQ,GAAG,EAAE;EAC5E,CAAC"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../i18n/declaration.cjs`);function t(t,n,r){switch(n){case`timeout`:return t(e.I18nKey.MCP$TEST_ERROR_TIMEOUT);case`connection`:return t(e.I18nKey.MCP$TEST_ERROR_CONNECTION);case`credentials`:return t(e.I18nKey.MCP$TEST_ERROR_CREDENTIALS,{error:r});default:return t(e.I18nKey.MCP$TEST_ERROR_UNKNOWN,{error:r})}}exports.makeMcpTestErrorMessage=t;
2
+ //# sourceMappingURL=mcp-test-error-message.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-test-error-message.cjs","names":[],"sources":["../../src/utils/mcp-test-error-message.ts"],"sourcesContent":["import type { TFunction } from \"i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { ExtendedMCPTestFailureKind } from \"#/types/mcp-server\";\n\n/**\n * Kind-specific, localized guidance for a failed MCP connection test.\n * `error` is interpolated for the kinds whose message surfaces the provider\n * detail — callers pass display-safe (redacted) text.\n */\nexport function makeMcpTestErrorMessage(\n t: TFunction<\"openhands\">,\n errorKind: ExtendedMCPTestFailureKind,\n error: string,\n): string {\n switch (errorKind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n case \"credentials\":\n return t(I18nKey.MCP$TEST_ERROR_CREDENTIALS, { error });\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error });\n }\n}\n"],"mappings":"wFASA,SAAgB,EACd,EACA,EACA,EACQ,CACR,OAAQ,EAAR,CACE,IAAK,UACH,OAAO,EAAE,EAAA,QAAQ,uBAAuB,CAC1C,IAAK,aACH,OAAO,EAAE,EAAA,QAAQ,0BAA0B,CAC7C,IAAK,cACH,OAAO,EAAE,EAAA,QAAQ,2BAA4B,CAAE,QAAO,CAAC,CACzD,QACE,OAAO,EAAE,EAAA,QAAQ,uBAAwB,CAAE,QAAO,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { TFunction } from "i18next";
2
+ import type { ExtendedMCPTestFailureKind } from "#/types/mcp-server";
3
+ /**
4
+ * Kind-specific, localized guidance for a failed MCP connection test.
5
+ * `error` is interpolated for the kinds whose message surfaces the provider
6
+ * detail — callers pass display-safe (redacted) text.
7
+ */
8
+ export declare function makeMcpTestErrorMessage(t: TFunction<"openhands">, errorKind: ExtendedMCPTestFailureKind, error: string): string;
@@ -0,0 +1,14 @@
1
+ import { I18nKey as e } from "../i18n/declaration.js";
2
+ //#region src/utils/mcp-test-error-message.ts
3
+ function t(t, n, r) {
4
+ switch (n) {
5
+ case "timeout": return t(e.MCP$TEST_ERROR_TIMEOUT);
6
+ case "connection": return t(e.MCP$TEST_ERROR_CONNECTION);
7
+ case "credentials": return t(e.MCP$TEST_ERROR_CREDENTIALS, { error: r });
8
+ default: return t(e.MCP$TEST_ERROR_UNKNOWN, { error: r });
9
+ }
10
+ }
11
+ //#endregion
12
+ export { t as makeMcpTestErrorMessage };
13
+
14
+ //# sourceMappingURL=mcp-test-error-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-test-error-message.js","names":[],"sources":["../../src/utils/mcp-test-error-message.ts"],"sourcesContent":["import type { TFunction } from \"i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { ExtendedMCPTestFailureKind } from \"#/types/mcp-server\";\n\n/**\n * Kind-specific, localized guidance for a failed MCP connection test.\n * `error` is interpolated for the kinds whose message surfaces the provider\n * detail — callers pass display-safe (redacted) text.\n */\nexport function makeMcpTestErrorMessage(\n t: TFunction<\"openhands\">,\n errorKind: ExtendedMCPTestFailureKind,\n error: string,\n): string {\n switch (errorKind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n case \"credentials\":\n return t(I18nKey.MCP$TEST_ERROR_CREDENTIALS, { error });\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error });\n }\n}\n"],"mappings":";;AASA,SAAgB,EACd,GACA,GACA,GACQ;AACR,SAAQ,GAAR;EACE,KAAK,UACH,QAAO,EAAE,EAAQ,uBAAuB;EAC1C,KAAK,aACH,QAAO,EAAE,EAAQ,0BAA0B;EAC7C,KAAK,cACH,QAAO,EAAE,EAAQ,4BAA4B,EAAE,UAAO,CAAC;EACzD,QACE,QAAO,EAAE,EAAQ,wBAAwB,EAAE,UAAO,CAAC"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`./mcp-config.cjs`);var t=4,n=/token|key|secret|auth/i,r=[/\bgh[pousr]_[A-Za-z0-9]{16,}\b/g,/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,/\bxox[a-z](?:-[A-Za-z0-9]+)+/g,/\blin_api_[A-Za-z0-9]{10,}\b/g,/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\b/g],i=/\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/gi;function a(e,n){typeof n==`string`&&(n.length<t||n!==`**********`&&e.add(n))}function o(e,t){for(let n of Object.values(t??{}))a(e,n)}function s(e,t){if(t)try{let r=new URL(t);a(e,r.username),a(e,r.password),a(e,decodeURIComponent(r.username)),a(e,decodeURIComponent(r.password)),r.searchParams.forEach((t,r)=>{n.test(r)&&a(e,t)})}catch{}}function c(e,t){if(t)switch(t.strategy){case`api_key`:case`bearer`:a(e,t.value);break;case`basic`:a(e,t.username),a(e,t.password);break;case`header`:o(e,t.headers);break;case`oauth2`:a(e,t.authentication?.client_secret),o(e,t.state?.tokens);break;default:break}}function l(e){let t=new Set;return o(t,e.env),o(t,e.headers),c(t,e.auth),s(t,e.url),[...t].sort((e,t)=>t.length-e.length)}function u(t,...n){if(!t)return t;let a=t;for(let t of n)if(t)for(let n of l(t))a=a.split(n).join(e.REDACTED_MCP_SECRET_VALUE);a=a.replace(i,`Bearer ${e.REDACTED_MCP_SECRET_VALUE}`);for(let t of r)a=a.replace(t,e.REDACTED_MCP_SECRET_VALUE);return a}exports.redactMcpSecrets=u;
2
+ //# sourceMappingURL=redact-mcp-secrets.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-mcp-secrets.cjs","names":[],"sources":["../../src/utils/redact-mcp-secrets.ts"],"sourcesContent":["import type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { REDACTED_MCP_SECRET_VALUE } from \"#/utils/mcp-config\";\n\n/**\n * Minimum length for a config value to be treated as a redactable secret.\n * Shorter strings are too likely to collide with ordinary words in an\n * error message and would mangle it without hiding anything meaningful.\n */\nconst MIN_SECRET_LENGTH = 4;\n\nconst SECRETLIKE_PARAM_NAME = /token|key|secret|auth/i;\n\n/**\n * Token shapes that may appear in backend error text even when the browser\n * never held the plaintext value (stored secrets round-trip encrypted and\n * are decrypted server-side, so a spawn/connect error can echo them back).\n */\nconst GENERIC_SECRET_PATTERNS: RegExp[] = [\n // GitHub personal access tokens (classic and fine-grained).\n /\\bgh[pousr]_[A-Za-z0-9]{16,}\\b/g,\n /\\bgithub_pat_[A-Za-z0-9_]{20,}\\b/g,\n // Slack workspace tokens (xoxb-, xoxp-, xoxs-, ...).\n /\\bxox[a-z](?:-[A-Za-z0-9]+)+/g,\n // Linear API keys.\n /\\blin_api_[A-Za-z0-9]{10,}\\b/g,\n // JWT-shaped values (three base64url segments starting with \"eyJ\").\n /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{5,}\\.[A-Za-z0-9_-]{5,}\\b/g,\n];\n\n// \"Bearer <token>\" keeps its prefix so the message stays readable.\nconst BEARER_PATTERN = /\\bBearer\\s+[A-Za-z0-9._~+/=-]{8,}/gi;\n\nfunction addValue(values: Set<string>, value: unknown): void {\n if (typeof value !== \"string\") return;\n if (value.length < MIN_SECRET_LENGTH) return;\n if (value === REDACTED_MCP_SECRET_VALUE) return;\n values.add(value);\n}\n\nfunction addRecordValues(\n values: Set<string>,\n record: Record<string, unknown> | null | undefined,\n): void {\n for (const value of Object.values(record ?? {})) {\n addValue(values, value);\n }\n}\n\nfunction addUrlSecrets(values: Set<string>, rawUrl: string | undefined): void {\n if (!rawUrl) return;\n try {\n const url = new URL(rawUrl);\n addValue(values, url.username);\n addValue(values, url.password);\n addValue(values, decodeURIComponent(url.username));\n addValue(values, decodeURIComponent(url.password));\n url.searchParams.forEach((value, name) => {\n if (SECRETLIKE_PARAM_NAME.test(name)) addValue(values, value);\n });\n } catch {\n // Not a parseable URL — nothing to collect.\n }\n}\n\nfunction addAuthSecrets(\n values: Set<string>,\n auth: MCPServerConfig[\"auth\"],\n): void {\n if (!auth) return;\n switch (auth.strategy) {\n case \"api_key\":\n case \"bearer\":\n addValue(values, auth.value);\n break;\n case \"basic\":\n addValue(values, auth.username);\n addValue(values, auth.password);\n break;\n case \"header\":\n addRecordValues(values, auth.headers);\n break;\n case \"oauth2\":\n addValue(values, auth.authentication?.client_secret);\n addRecordValues(values, auth.state?.tokens);\n break;\n default:\n break;\n }\n}\n\n/**\n * Collect every secret VALUE a server config may carry, longest first so\n * replacing a shorter secret can never split a longer one that contains it.\n */\nexport function collectMcpSecretValues(server: MCPServerConfig): string[] {\n const values = new Set<string>();\n addRecordValues(values, server.env);\n addRecordValues(values, server.headers);\n addAuthSecrets(values, server.auth);\n addUrlSecrets(values, server.url);\n return [...values].sort((a, b) => b.length - a.length);\n}\n\n/**\n * Scrub secrets from MCP test/probe error text before it is displayed.\n * Replaces every known secret value from the given server config(s), then\n * applies generic token patterns as a safety net for plaintext the browser\n * never saw (e.g. values decrypted server-side and echoed in an error).\n */\nexport function redactMcpSecrets(\n text: string,\n ...servers: (MCPServerConfig | undefined)[]\n): string {\n if (!text) return text;\n let redacted = text;\n for (const server of servers) {\n if (!server) continue;\n for (const value of collectMcpSecretValues(server)) {\n redacted = redacted.split(value).join(REDACTED_MCP_SECRET_VALUE);\n }\n }\n redacted = redacted.replace(\n BEARER_PATTERN,\n `Bearer ${REDACTED_MCP_SECRET_VALUE}`,\n );\n for (const pattern of GENERIC_SECRET_PATTERNS) {\n redacted = redacted.replace(pattern, REDACTED_MCP_SECRET_VALUE);\n }\n return redacted;\n}\n"],"mappings":"iFAQA,IAAM,EAAoB,EAEpB,EAAwB,yBAOxB,EAAoC,CAExC,kCACA,oCAEA,gCAEA,gCAEA,mEACD,CAGK,EAAiB,sCAEvB,SAAS,EAAS,EAAqB,EAAsB,CACvD,OAAO,GAAU,WACjB,EAAM,OAAS,GACf,IAAA,cACJ,EAAO,IAAI,EAAM,EAGnB,SAAS,EACP,EACA,EACM,CACN,IAAK,IAAM,KAAS,OAAO,OAAO,GAAU,EAAE,CAAC,CAC7C,EAAS,EAAQ,EAAM,CAI3B,SAAS,EAAc,EAAqB,EAAkC,CACvE,KACL,GAAI,CACF,IAAM,EAAM,IAAI,IAAI,EAAO,CAC3B,EAAS,EAAQ,EAAI,SAAS,CAC9B,EAAS,EAAQ,EAAI,SAAS,CAC9B,EAAS,EAAQ,mBAAmB,EAAI,SAAS,CAAC,CAClD,EAAS,EAAQ,mBAAmB,EAAI,SAAS,CAAC,CAClD,EAAI,aAAa,SAAS,EAAO,IAAS,CACpC,EAAsB,KAAK,EAAK,EAAE,EAAS,EAAQ,EAAM,EAC7D,MACI,GAKV,SAAS,EACP,EACA,EACM,CACD,KACL,OAAQ,EAAK,SAAb,CACE,IAAK,UACL,IAAK,SACH,EAAS,EAAQ,EAAK,MAAM,CAC5B,MACF,IAAK,QACH,EAAS,EAAQ,EAAK,SAAS,CAC/B,EAAS,EAAQ,EAAK,SAAS,CAC/B,MACF,IAAK,SACH,EAAgB,EAAQ,EAAK,QAAQ,CACrC,MACF,IAAK,SACH,EAAS,EAAQ,EAAK,gBAAgB,cAAc,CACpD,EAAgB,EAAQ,EAAK,OAAO,OAAO,CAC3C,MACF,QACE,OAQN,SAAgB,EAAuB,EAAmC,CACxE,IAAM,EAAS,IAAI,IAKnB,OAJA,EAAgB,EAAQ,EAAO,IAAI,CACnC,EAAgB,EAAQ,EAAO,QAAQ,CACvC,EAAe,EAAQ,EAAO,KAAK,CACnC,EAAc,EAAQ,EAAO,IAAI,CAC1B,CAAC,GAAG,EAAO,CAAC,MAAM,EAAG,IAAM,EAAE,OAAS,EAAE,OAAO,CASxD,SAAgB,EACd,EACA,GAAG,EACK,CACR,GAAI,CAAC,EAAM,OAAO,EAClB,IAAI,EAAW,EACf,IAAK,IAAM,KAAU,EACd,KACL,IAAK,IAAM,KAAS,EAAuB,EAAO,CAChD,EAAW,EAAS,MAAM,EAAM,CAAC,KAAK,EAAA,0BAA0B,CAGpE,EAAW,EAAS,QAClB,EACA,UAAU,EAAA,4BACX,CACD,IAAK,IAAM,KAAW,EACpB,EAAW,EAAS,QAAQ,EAAS,EAAA,0BAA0B,CAEjE,OAAO"}
@@ -0,0 +1,13 @@
1
+ import type { MCPServerConfig } from "#/types/mcp-server";
2
+ /**
3
+ * Collect every secret VALUE a server config may carry, longest first so
4
+ * replacing a shorter secret can never split a longer one that contains it.
5
+ */
6
+ export declare function collectMcpSecretValues(server: MCPServerConfig): string[];
7
+ /**
8
+ * Scrub secrets from MCP test/probe error text before it is displayed.
9
+ * Replaces every known secret value from the given server config(s), then
10
+ * applies generic token patterns as a safety net for plaintext the browser
11
+ * never saw (e.g. values decrypted server-side and echoed in an error).
12
+ */
13
+ export declare function redactMcpSecrets(text: string, ...servers: (MCPServerConfig | undefined)[]): string;
@@ -0,0 +1,57 @@
1
+ import { REDACTED_MCP_SECRET_VALUE as e } from "./mcp-config.js";
2
+ //#region src/utils/redact-mcp-secrets.ts
3
+ var t = 4, n = /token|key|secret|auth/i, r = [
4
+ /\bgh[pousr]_[A-Za-z0-9]{16,}\b/g,
5
+ /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
6
+ /\bxox[a-z](?:-[A-Za-z0-9]+)+/g,
7
+ /\blin_api_[A-Za-z0-9]{10,}\b/g,
8
+ /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\b/g
9
+ ], i = /\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/gi;
10
+ function a(e, n) {
11
+ typeof n == "string" && (n.length < t || n !== "**********" && e.add(n));
12
+ }
13
+ function o(e, t) {
14
+ for (let n of Object.values(t ?? {})) a(e, n);
15
+ }
16
+ function s(e, t) {
17
+ if (t) try {
18
+ let r = new URL(t);
19
+ a(e, r.username), a(e, r.password), a(e, decodeURIComponent(r.username)), a(e, decodeURIComponent(r.password)), r.searchParams.forEach((t, r) => {
20
+ n.test(r) && a(e, t);
21
+ });
22
+ } catch {}
23
+ }
24
+ function c(e, t) {
25
+ if (t) switch (t.strategy) {
26
+ case "api_key":
27
+ case "bearer":
28
+ a(e, t.value);
29
+ break;
30
+ case "basic":
31
+ a(e, t.username), a(e, t.password);
32
+ break;
33
+ case "header":
34
+ o(e, t.headers);
35
+ break;
36
+ case "oauth2":
37
+ a(e, t.authentication?.client_secret), o(e, t.state?.tokens);
38
+ break;
39
+ default: break;
40
+ }
41
+ }
42
+ function l(e) {
43
+ let t = /* @__PURE__ */ new Set();
44
+ return o(t, e.env), o(t, e.headers), c(t, e.auth), s(t, e.url), [...t].sort((e, t) => t.length - e.length);
45
+ }
46
+ function u(t, ...n) {
47
+ if (!t) return t;
48
+ let a = t;
49
+ for (let t of n) if (t) for (let n of l(t)) a = a.split(n).join(e);
50
+ a = a.replace(i, `Bearer ${e}`);
51
+ for (let t of r) a = a.replace(t, e);
52
+ return a;
53
+ }
54
+ //#endregion
55
+ export { u as redactMcpSecrets };
56
+
57
+ //# sourceMappingURL=redact-mcp-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-mcp-secrets.js","names":[],"sources":["../../src/utils/redact-mcp-secrets.ts"],"sourcesContent":["import type { MCPServerConfig } from \"#/types/mcp-server\";\nimport { REDACTED_MCP_SECRET_VALUE } from \"#/utils/mcp-config\";\n\n/**\n * Minimum length for a config value to be treated as a redactable secret.\n * Shorter strings are too likely to collide with ordinary words in an\n * error message and would mangle it without hiding anything meaningful.\n */\nconst MIN_SECRET_LENGTH = 4;\n\nconst SECRETLIKE_PARAM_NAME = /token|key|secret|auth/i;\n\n/**\n * Token shapes that may appear in backend error text even when the browser\n * never held the plaintext value (stored secrets round-trip encrypted and\n * are decrypted server-side, so a spawn/connect error can echo them back).\n */\nconst GENERIC_SECRET_PATTERNS: RegExp[] = [\n // GitHub personal access tokens (classic and fine-grained).\n /\\bgh[pousr]_[A-Za-z0-9]{16,}\\b/g,\n /\\bgithub_pat_[A-Za-z0-9_]{20,}\\b/g,\n // Slack workspace tokens (xoxb-, xoxp-, xoxs-, ...).\n /\\bxox[a-z](?:-[A-Za-z0-9]+)+/g,\n // Linear API keys.\n /\\blin_api_[A-Za-z0-9]{10,}\\b/g,\n // JWT-shaped values (three base64url segments starting with \"eyJ\").\n /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{5,}\\.[A-Za-z0-9_-]{5,}\\b/g,\n];\n\n// \"Bearer <token>\" keeps its prefix so the message stays readable.\nconst BEARER_PATTERN = /\\bBearer\\s+[A-Za-z0-9._~+/=-]{8,}/gi;\n\nfunction addValue(values: Set<string>, value: unknown): void {\n if (typeof value !== \"string\") return;\n if (value.length < MIN_SECRET_LENGTH) return;\n if (value === REDACTED_MCP_SECRET_VALUE) return;\n values.add(value);\n}\n\nfunction addRecordValues(\n values: Set<string>,\n record: Record<string, unknown> | null | undefined,\n): void {\n for (const value of Object.values(record ?? {})) {\n addValue(values, value);\n }\n}\n\nfunction addUrlSecrets(values: Set<string>, rawUrl: string | undefined): void {\n if (!rawUrl) return;\n try {\n const url = new URL(rawUrl);\n addValue(values, url.username);\n addValue(values, url.password);\n addValue(values, decodeURIComponent(url.username));\n addValue(values, decodeURIComponent(url.password));\n url.searchParams.forEach((value, name) => {\n if (SECRETLIKE_PARAM_NAME.test(name)) addValue(values, value);\n });\n } catch {\n // Not a parseable URL — nothing to collect.\n }\n}\n\nfunction addAuthSecrets(\n values: Set<string>,\n auth: MCPServerConfig[\"auth\"],\n): void {\n if (!auth) return;\n switch (auth.strategy) {\n case \"api_key\":\n case \"bearer\":\n addValue(values, auth.value);\n break;\n case \"basic\":\n addValue(values, auth.username);\n addValue(values, auth.password);\n break;\n case \"header\":\n addRecordValues(values, auth.headers);\n break;\n case \"oauth2\":\n addValue(values, auth.authentication?.client_secret);\n addRecordValues(values, auth.state?.tokens);\n break;\n default:\n break;\n }\n}\n\n/**\n * Collect every secret VALUE a server config may carry, longest first so\n * replacing a shorter secret can never split a longer one that contains it.\n */\nexport function collectMcpSecretValues(server: MCPServerConfig): string[] {\n const values = new Set<string>();\n addRecordValues(values, server.env);\n addRecordValues(values, server.headers);\n addAuthSecrets(values, server.auth);\n addUrlSecrets(values, server.url);\n return [...values].sort((a, b) => b.length - a.length);\n}\n\n/**\n * Scrub secrets from MCP test/probe error text before it is displayed.\n * Replaces every known secret value from the given server config(s), then\n * applies generic token patterns as a safety net for plaintext the browser\n * never saw (e.g. values decrypted server-side and echoed in an error).\n */\nexport function redactMcpSecrets(\n text: string,\n ...servers: (MCPServerConfig | undefined)[]\n): string {\n if (!text) return text;\n let redacted = text;\n for (const server of servers) {\n if (!server) continue;\n for (const value of collectMcpSecretValues(server)) {\n redacted = redacted.split(value).join(REDACTED_MCP_SECRET_VALUE);\n }\n }\n redacted = redacted.replace(\n BEARER_PATTERN,\n `Bearer ${REDACTED_MCP_SECRET_VALUE}`,\n );\n for (const pattern of GENERIC_SECRET_PATTERNS) {\n redacted = redacted.replace(pattern, REDACTED_MCP_SECRET_VALUE);\n }\n return redacted;\n}\n"],"mappings":";;AAQA,IAAM,IAAoB,GAEpB,IAAwB,0BAOxB,IAAoC;CAExC;CACA;CAEA;CAEA;CAEA;CACD,EAGK,IAAiB;AAEvB,SAAS,EAAS,GAAqB,GAAsB;AACvD,QAAO,KAAU,aACjB,EAAM,SAAS,KACf,MAAA,gBACJ,EAAO,IAAI,EAAM;;AAGnB,SAAS,EACP,GACA,GACM;AACN,MAAK,IAAM,KAAS,OAAO,OAAO,KAAU,EAAE,CAAC,CAC7C,GAAS,GAAQ,EAAM;;AAI3B,SAAS,EAAc,GAAqB,GAAkC;AACvE,OACL,KAAI;EACF,IAAM,IAAM,IAAI,IAAI,EAAO;AAK3B,EAJA,EAAS,GAAQ,EAAI,SAAS,EAC9B,EAAS,GAAQ,EAAI,SAAS,EAC9B,EAAS,GAAQ,mBAAmB,EAAI,SAAS,CAAC,EAClD,EAAS,GAAQ,mBAAmB,EAAI,SAAS,CAAC,EAClD,EAAI,aAAa,SAAS,GAAO,MAAS;AACxC,GAAI,EAAsB,KAAK,EAAK,IAAE,EAAS,GAAQ,EAAM;IAC7D;SACI;;AAKV,SAAS,EACP,GACA,GACM;AACD,OACL,SAAQ,EAAK,UAAb;EACE,KAAK;EACL,KAAK;AACH,KAAS,GAAQ,EAAK,MAAM;AAC5B;EACF,KAAK;AAEH,GADA,EAAS,GAAQ,EAAK,SAAS,EAC/B,EAAS,GAAQ,EAAK,SAAS;AAC/B;EACF,KAAK;AACH,KAAgB,GAAQ,EAAK,QAAQ;AACrC;EACF,KAAK;AAEH,GADA,EAAS,GAAQ,EAAK,gBAAgB,cAAc,EACpD,EAAgB,GAAQ,EAAK,OAAO,OAAO;AAC3C;EACF,QACE;;;AAQN,SAAgB,EAAuB,GAAmC;CACxE,IAAM,oBAAS,IAAI,KAAa;AAKhC,QAJA,EAAgB,GAAQ,EAAO,IAAI,EACnC,EAAgB,GAAQ,EAAO,QAAQ,EACvC,EAAe,GAAQ,EAAO,KAAK,EACnC,EAAc,GAAQ,EAAO,IAAI,EAC1B,CAAC,GAAG,EAAO,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO;;AASxD,SAAgB,EACd,GACA,GAAG,GACK;AACR,KAAI,CAAC,EAAM,QAAO;CAClB,IAAI,IAAW;AACf,MAAK,IAAM,KAAU,EACd,OACL,MAAK,IAAM,KAAS,EAAuB,EAAO,CAChD,KAAW,EAAS,MAAM,EAAM,CAAC,KAAK,EAA0B;AAGpE,KAAW,EAAS,QAClB,GACA,UAAU,IACX;AACD,MAAK,IAAM,KAAW,EACpB,KAAW,EAAS,QAAQ,GAAS,EAA0B;AAEjE,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"settings-utils.cjs","names":[],"sources":["../../src/utils/settings-utils.ts"],"sourcesContent":["import { WebClientFeatureFlags } from \"#/api/option-service/option.types\";\nimport { Settings, SettingsValue } from \"#/types/settings\";\nimport { getProviderId } from \"#/utils/map-provider\";\n\nconst extractBasicFormData = (formData: FormData) => {\n const providerDisplay = formData.get(\"llm-provider-input\")?.toString();\n const provider = providerDisplay ? getProviderId(providerDisplay) : undefined;\n const model = formData.get(\"llm-model-input\")?.toString();\n\n return {\n llmModel: provider && model ? `${provider}/${model}` : undefined,\n llmApiKey: formData.get(\"llm-api-key-input\")?.toString(),\n agent: formData.get(\"agent\")?.toString(),\n language: formData.get(\"language\")?.toString(),\n };\n};\n\nexport const parseMaxBudgetPerTask = (value: string): number | null => {\n if (!value) {\n return null;\n }\n\n const parsedValue = parseFloat(value);\n return parsedValue && parsedValue >= 1 && Number.isFinite(parsedValue)\n ? parsedValue\n : null;\n};\n\nexport const extractSettings = (\n formData: FormData,\n): Partial<Settings> & Record<string, unknown> => {\n const { llmModel, llmApiKey, agent, language } =\n extractBasicFormData(formData);\n\n const llm: Record<string, unknown> = {};\n if (llmModel) llm.model = llmModel;\n if (llmApiKey !== undefined) llm.api_key = llmApiKey;\n\n const agentSettings: Record<string, SettingsValue> = {};\n if (Object.keys(llm).length > 0)\n agentSettings.llm = llm as Record<string, SettingsValue>;\n if (agent) agentSettings.agent = agent;\n\n return {\n ...(Object.keys(agentSettings).length > 0\n ? { agent_settings_diff: agentSettings }\n : {}),\n ...(language ? { language } : {}),\n };\n};\n\nexport function isSettingsPageHidden(\n path: string,\n featureFlags: WebClientFeatureFlags | undefined,\n): boolean {\n if (featureFlags?.hide_llm_settings && path === \"/settings/llm\") return true;\n return false;\n}\n\nexport function getFirstAvailablePath(\n featureFlags: WebClientFeatureFlags | undefined,\n): string | null {\n // ``/settings/agents`` (the Agent Profile library — the \"Agent\" page) always\n // wins: it is where the agent is defined (OpenHands / ACP, via the active\n // profile) and is always available regardless of feature flags. Landing here\n // keeps routing simple — ACP users no longer have to bounce through\n // ``/settings/llm`` (which is disabled for them), and OpenHands users are one\n // nav-click away from the LLM page.\n const fallbackOrder = [\n { path: \"/settings/agents\", hidden: false },\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/app\", hidden: false },\n { path: \"/settings/secrets\", hidden: false },\n ];\n\n const firstAvailable = fallbackOrder.find((item) => !item.hidden);\n return firstAvailable?.path ?? null;\n}\n"],"mappings":"mFAIA,IAAM,EAAwB,GAAuB,CACnD,IAAM,EAAkB,EAAS,IAAI,qBAAqB,EAAE,UAAU,CAChE,EAAW,EAAkB,EAAA,cAAc,EAAgB,CAAG,IAAA,GAC9D,EAAQ,EAAS,IAAI,kBAAkB,EAAE,UAAU,CAEzD,MAAO,CACL,SAAU,GAAY,EAAQ,GAAG,EAAS,GAAG,IAAU,IAAA,GACvD,UAAW,EAAS,IAAI,oBAAoB,EAAE,UAAU,CACxD,MAAO,EAAS,IAAI,QAAQ,EAAE,UAAU,CACxC,SAAU,EAAS,IAAI,WAAW,EAAE,UAAU,CAC/C,EAcU,EACX,GACgD,CAChD,GAAM,CAAE,WAAU,YAAW,QAAO,YAClC,EAAqB,EAAS,CAE1B,EAA+B,EAAE,CACnC,IAAU,EAAI,MAAQ,GACtB,IAAc,IAAA,KAAW,EAAI,QAAU,GAE3C,IAAM,EAA+C,EAAE,CAKvD,OAJI,OAAO,KAAK,EAAI,CAAC,OAAS,IAC5B,EAAc,IAAM,GAClB,IAAO,EAAc,MAAQ,GAE1B,CACL,GAAI,OAAO,KAAK,EAAc,CAAC,OAAS,EACpC,CAAE,oBAAqB,EAAe,CACtC,EAAE,CACN,GAAI,EAAW,CAAE,WAAU,CAAG,EAAE,CACjC,EAGH,SAAgB,EACd,EACA,EACS,CAET,MADA,GAAI,GAAc,mBAAqB,IAAS"}
1
+ {"version":3,"file":"settings-utils.cjs","names":[],"sources":["../../src/utils/settings-utils.ts"],"sourcesContent":["import { WebClientFeatureFlags } from \"#/api/option-service/option.types\";\nimport { Settings, SettingsValue } from \"#/types/settings\";\nimport { getProviderId } from \"#/utils/map-provider\";\n\nconst extractBasicFormData = (formData: FormData) => {\n const providerDisplay = formData.get(\"llm-provider-input\")?.toString();\n const provider = providerDisplay ? getProviderId(providerDisplay) : undefined;\n const model = formData.get(\"llm-model-input\")?.toString();\n\n return {\n llmModel: provider && model ? `${provider}/${model}` : undefined,\n llmApiKey: formData.get(\"llm-api-key-input\")?.toString(),\n agent: formData.get(\"agent\")?.toString(),\n language: formData.get(\"language\")?.toString(),\n };\n};\n\nexport const parseMaxBudgetPerTask = (value: string): number | null => {\n if (!value) {\n return null;\n }\n\n const parsedValue = parseFloat(value);\n return parsedValue && parsedValue >= 1 && Number.isFinite(parsedValue)\n ? parsedValue\n : null;\n};\n\nexport const extractSettings = (\n formData: FormData,\n): Partial<Settings> & Record<string, unknown> => {\n const { llmModel, llmApiKey, agent, language } =\n extractBasicFormData(formData);\n\n const llm: Record<string, unknown> = {};\n if (llmModel) llm.model = llmModel;\n if (llmApiKey !== undefined) llm.api_key = llmApiKey;\n\n const agentSettings: Record<string, SettingsValue> = {};\n if (Object.keys(llm).length > 0)\n agentSettings.llm = llm as Record<string, SettingsValue>;\n if (agent) agentSettings.agent = agent;\n\n return {\n ...(Object.keys(agentSettings).length > 0\n ? { agent_settings_diff: agentSettings }\n : {}),\n ...(language ? { language } : {}),\n };\n};\n\nexport function isSettingsPageHidden(\n path: string,\n featureFlags: WebClientFeatureFlags | undefined,\n): boolean {\n if (featureFlags?.hide_llm_settings && path === \"/settings/llm\") return true;\n return false;\n}\n\nexport function getFirstAvailablePath(\n featureFlags: WebClientFeatureFlags | undefined,\n): string | null {\n // ``/settings/agents`` (the Agent Profile library — the \"Agent\" page) always\n // wins: it is where the agent is defined (OpenHands / ACP, via the active\n // profile) and is always available regardless of feature flags. Landing here\n // keeps routing simple — every user lands where the agent is chosen, and\n // the LLM page is one nav-click away.\n const fallbackOrder = [\n { path: \"/settings/agents\", hidden: false },\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/app\", hidden: false },\n { path: \"/settings/secrets\", hidden: false },\n ];\n\n const firstAvailable = fallbackOrder.find((item) => !item.hidden);\n return firstAvailable?.path ?? null;\n}\n"],"mappings":"mFAIA,IAAM,EAAwB,GAAuB,CACnD,IAAM,EAAkB,EAAS,IAAI,qBAAqB,EAAE,UAAU,CAChE,EAAW,EAAkB,EAAA,cAAc,EAAgB,CAAG,IAAA,GAC9D,EAAQ,EAAS,IAAI,kBAAkB,EAAE,UAAU,CAEzD,MAAO,CACL,SAAU,GAAY,EAAQ,GAAG,EAAS,GAAG,IAAU,IAAA,GACvD,UAAW,EAAS,IAAI,oBAAoB,EAAE,UAAU,CACxD,MAAO,EAAS,IAAI,QAAQ,EAAE,UAAU,CACxC,SAAU,EAAS,IAAI,WAAW,EAAE,UAAU,CAC/C,EAcU,EACX,GACgD,CAChD,GAAM,CAAE,WAAU,YAAW,QAAO,YAClC,EAAqB,EAAS,CAE1B,EAA+B,EAAE,CACnC,IAAU,EAAI,MAAQ,GACtB,IAAc,IAAA,KAAW,EAAI,QAAU,GAE3C,IAAM,EAA+C,EAAE,CAKvD,OAJI,OAAO,KAAK,EAAI,CAAC,OAAS,IAC5B,EAAc,IAAM,GAClB,IAAO,EAAc,MAAQ,GAE1B,CACL,GAAI,OAAO,KAAK,EAAc,CAAC,OAAS,EACpC,CAAE,oBAAqB,EAAe,CACtC,EAAE,CACN,GAAI,EAAW,CAAE,WAAU,CAAG,EAAE,CACjC,EAGH,SAAgB,EACd,EACA,EACS,CAET,MADA,GAAI,GAAc,mBAAqB,IAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"settings-utils.js","names":[],"sources":["../../src/utils/settings-utils.ts"],"sourcesContent":["import { WebClientFeatureFlags } from \"#/api/option-service/option.types\";\nimport { Settings, SettingsValue } from \"#/types/settings\";\nimport { getProviderId } from \"#/utils/map-provider\";\n\nconst extractBasicFormData = (formData: FormData) => {\n const providerDisplay = formData.get(\"llm-provider-input\")?.toString();\n const provider = providerDisplay ? getProviderId(providerDisplay) : undefined;\n const model = formData.get(\"llm-model-input\")?.toString();\n\n return {\n llmModel: provider && model ? `${provider}/${model}` : undefined,\n llmApiKey: formData.get(\"llm-api-key-input\")?.toString(),\n agent: formData.get(\"agent\")?.toString(),\n language: formData.get(\"language\")?.toString(),\n };\n};\n\nexport const parseMaxBudgetPerTask = (value: string): number | null => {\n if (!value) {\n return null;\n }\n\n const parsedValue = parseFloat(value);\n return parsedValue && parsedValue >= 1 && Number.isFinite(parsedValue)\n ? parsedValue\n : null;\n};\n\nexport const extractSettings = (\n formData: FormData,\n): Partial<Settings> & Record<string, unknown> => {\n const { llmModel, llmApiKey, agent, language } =\n extractBasicFormData(formData);\n\n const llm: Record<string, unknown> = {};\n if (llmModel) llm.model = llmModel;\n if (llmApiKey !== undefined) llm.api_key = llmApiKey;\n\n const agentSettings: Record<string, SettingsValue> = {};\n if (Object.keys(llm).length > 0)\n agentSettings.llm = llm as Record<string, SettingsValue>;\n if (agent) agentSettings.agent = agent;\n\n return {\n ...(Object.keys(agentSettings).length > 0\n ? { agent_settings_diff: agentSettings }\n : {}),\n ...(language ? { language } : {}),\n };\n};\n\nexport function isSettingsPageHidden(\n path: string,\n featureFlags: WebClientFeatureFlags | undefined,\n): boolean {\n if (featureFlags?.hide_llm_settings && path === \"/settings/llm\") return true;\n return false;\n}\n\nexport function getFirstAvailablePath(\n featureFlags: WebClientFeatureFlags | undefined,\n): string | null {\n // ``/settings/agents`` (the Agent Profile library — the \"Agent\" page) always\n // wins: it is where the agent is defined (OpenHands / ACP, via the active\n // profile) and is always available regardless of feature flags. Landing here\n // keeps routing simple — ACP users no longer have to bounce through\n // ``/settings/llm`` (which is disabled for them), and OpenHands users are one\n // nav-click away from the LLM page.\n const fallbackOrder = [\n { path: \"/settings/agents\", hidden: false },\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/app\", hidden: false },\n { path: \"/settings/secrets\", hidden: false },\n ];\n\n const firstAvailable = fallbackOrder.find((item) => !item.hidden);\n return firstAvailable?.path ?? null;\n}\n"],"mappings":";;AAIA,IAAM,KAAwB,MAAuB;CACnD,IAAM,IAAkB,EAAS,IAAI,qBAAqB,EAAE,UAAU,EAChE,IAAW,IAAkB,EAAc,EAAgB,GAAG,KAAA,GAC9D,IAAQ,EAAS,IAAI,kBAAkB,EAAE,UAAU;AAEzD,QAAO;EACL,UAAU,KAAY,IAAQ,GAAG,EAAS,GAAG,MAAU,KAAA;EACvD,WAAW,EAAS,IAAI,oBAAoB,EAAE,UAAU;EACxD,OAAO,EAAS,IAAI,QAAQ,EAAE,UAAU;EACxC,UAAU,EAAS,IAAI,WAAW,EAAE,UAAU;EAC/C;GAcU,KACX,MACgD;CAChD,IAAM,EAAE,aAAU,cAAW,UAAO,gBAClC,EAAqB,EAAS,EAE1B,IAA+B,EAAE;AAEvC,CADI,MAAU,EAAI,QAAQ,IACtB,MAAc,KAAA,MAAW,EAAI,UAAU;CAE3C,IAAM,IAA+C,EAAE;AAKvD,QAJI,OAAO,KAAK,EAAI,CAAC,SAAS,MAC5B,EAAc,MAAM,IAClB,MAAO,EAAc,QAAQ,IAE1B;EACL,GAAI,OAAO,KAAK,EAAc,CAAC,SAAS,IACpC,EAAE,qBAAqB,GAAe,GACtC,EAAE;EACN,GAAI,IAAW,EAAE,aAAU,GAAG,EAAE;EACjC;;AAGH,SAAgB,EACd,GACA,GACS;AAET,QADA,GAAI,GAAc,qBAAqB,MAAS"}
1
+ {"version":3,"file":"settings-utils.js","names":[],"sources":["../../src/utils/settings-utils.ts"],"sourcesContent":["import { WebClientFeatureFlags } from \"#/api/option-service/option.types\";\nimport { Settings, SettingsValue } from \"#/types/settings\";\nimport { getProviderId } from \"#/utils/map-provider\";\n\nconst extractBasicFormData = (formData: FormData) => {\n const providerDisplay = formData.get(\"llm-provider-input\")?.toString();\n const provider = providerDisplay ? getProviderId(providerDisplay) : undefined;\n const model = formData.get(\"llm-model-input\")?.toString();\n\n return {\n llmModel: provider && model ? `${provider}/${model}` : undefined,\n llmApiKey: formData.get(\"llm-api-key-input\")?.toString(),\n agent: formData.get(\"agent\")?.toString(),\n language: formData.get(\"language\")?.toString(),\n };\n};\n\nexport const parseMaxBudgetPerTask = (value: string): number | null => {\n if (!value) {\n return null;\n }\n\n const parsedValue = parseFloat(value);\n return parsedValue && parsedValue >= 1 && Number.isFinite(parsedValue)\n ? parsedValue\n : null;\n};\n\nexport const extractSettings = (\n formData: FormData,\n): Partial<Settings> & Record<string, unknown> => {\n const { llmModel, llmApiKey, agent, language } =\n extractBasicFormData(formData);\n\n const llm: Record<string, unknown> = {};\n if (llmModel) llm.model = llmModel;\n if (llmApiKey !== undefined) llm.api_key = llmApiKey;\n\n const agentSettings: Record<string, SettingsValue> = {};\n if (Object.keys(llm).length > 0)\n agentSettings.llm = llm as Record<string, SettingsValue>;\n if (agent) agentSettings.agent = agent;\n\n return {\n ...(Object.keys(agentSettings).length > 0\n ? { agent_settings_diff: agentSettings }\n : {}),\n ...(language ? { language } : {}),\n };\n};\n\nexport function isSettingsPageHidden(\n path: string,\n featureFlags: WebClientFeatureFlags | undefined,\n): boolean {\n if (featureFlags?.hide_llm_settings && path === \"/settings/llm\") return true;\n return false;\n}\n\nexport function getFirstAvailablePath(\n featureFlags: WebClientFeatureFlags | undefined,\n): string | null {\n // ``/settings/agents`` (the Agent Profile library — the \"Agent\" page) always\n // wins: it is where the agent is defined (OpenHands / ACP, via the active\n // profile) and is always available regardless of feature flags. Landing here\n // keeps routing simple — every user lands where the agent is chosen, and\n // the LLM page is one nav-click away.\n const fallbackOrder = [\n { path: \"/settings/agents\", hidden: false },\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/app\", hidden: false },\n { path: \"/settings/secrets\", hidden: false },\n ];\n\n const firstAvailable = fallbackOrder.find((item) => !item.hidden);\n return firstAvailable?.path ?? null;\n}\n"],"mappings":";;AAIA,IAAM,KAAwB,MAAuB;CACnD,IAAM,IAAkB,EAAS,IAAI,qBAAqB,EAAE,UAAU,EAChE,IAAW,IAAkB,EAAc,EAAgB,GAAG,KAAA,GAC9D,IAAQ,EAAS,IAAI,kBAAkB,EAAE,UAAU;AAEzD,QAAO;EACL,UAAU,KAAY,IAAQ,GAAG,EAAS,GAAG,MAAU,KAAA;EACvD,WAAW,EAAS,IAAI,oBAAoB,EAAE,UAAU;EACxD,OAAO,EAAS,IAAI,QAAQ,EAAE,UAAU;EACxC,UAAU,EAAS,IAAI,WAAW,EAAE,UAAU;EAC/C;GAcU,KACX,MACgD;CAChD,IAAM,EAAE,aAAU,cAAW,UAAO,gBAClC,EAAqB,EAAS,EAE1B,IAA+B,EAAE;AAEvC,CADI,MAAU,EAAI,QAAQ,IACtB,MAAc,KAAA,MAAW,EAAI,UAAU;CAE3C,IAAM,IAA+C,EAAE;AAKvD,QAJI,OAAO,KAAK,EAAI,CAAC,SAAS,MAC5B,EAAc,MAAM,IAClB,MAAO,EAAc,QAAQ,IAE1B;EACL,GAAI,OAAO,KAAK,EAAc,CAAC,SAAS,IACpC,EAAE,qBAAqB,GAAe,GACtC,EAAE;EACN,GAAI,IAAW,EAAE,aAAU,GAAG,EAAE;EACjC;;AAGH,SAAgB,EACd,GACA,GACS;AAET,QADA,GAAI,GAAc,qBAAqB,MAAS"}
@@ -0,0 +1,3 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../types/agent-server/type-guards.cjs`);var t=/^✅ Successfully installed '([^']+)' to (.+)$/m;function n(n){let r=new Map;for(let i of n){if(!e.isExecuteBashObservationEvent(i))continue;let n=i.observation.content.filter(e=>e.type===`text`).map(e=>e.text).join(`
2
+ `).match(t);if(!n)continue;let a=n[1],o=n[2].replace(/\\/g,`/`).replace(/\/+$/,``),s=`/.agents/skills/${a}`;if(!o.endsWith(s))continue;let c=o.slice(0,-s.length);if(!c)continue;let l=`${c}::${a}`;r.delete(l),r.set(l,{eventId:i.id,skillName:a,workspacePath:c})}return[...r.values()]}exports.detectSkillInstalls=n;
3
+ //# sourceMappingURL=skill-install-events.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-install-events.cjs","names":[],"sources":["../../src/utils/skill-install-events.ts"],"sourcesContent":["import { OpenHandsEvent } from \"#/types/agent-server/core\";\nimport { isExecuteBashObservationEvent } from \"#/types/agent-server/type-guards\";\n\nexport interface DetectedSkillInstall {\n /** Id of the bash observation event carrying the success marker. */\n eventId: string;\n skillName: string;\n /** Workspace root the skill was installed into (forward slashes). */\n workspacePath: string;\n}\n\n/**\n * Success marker printed by the bundled add-skill skill's fetch_skill.py:\n * ✅ Successfully installed '<name>' to <workspace>/.agents/skills/<name>\n * Failures exit 1 and never print this line. Matched on output alone —\n * `command` can be \"\" and `exit_code` can be -1 on soft-timeout\n * continuation observations that still carry the full output.\n */\nconst INSTALL_SUCCESS_PATTERN =\n /^✅ Successfully installed '([^']+)' to (.+)$/m;\n\n/**\n * Skills the agent installed during this conversation via the add-skill\n * flow. The SDK loads skills once at conversation start, so these are on\n * disk but inert until a new conversation starts in `workspacePath`.\n * Deduped per workspace+skill; a re-install (--force) keeps the latest\n * event id and moves the entry to the end.\n */\nexport function detectSkillInstalls(\n events: OpenHandsEvent[],\n): DetectedSkillInstall[] {\n const byKey = new Map<string, DetectedSkillInstall>();\n\n for (const event of events) {\n if (!isExecuteBashObservationEvent(event)) continue;\n\n const text = event.observation.content\n .filter((c) => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\\n\");\n const match = text.match(INSTALL_SUCCESS_PATTERN);\n if (!match) continue;\n\n const skillName = match[1];\n const dest = match[2].replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const suffix = `/.agents/skills/${skillName}`;\n if (!dest.endsWith(suffix)) continue;\n const workspacePath = dest.slice(0, -suffix.length);\n if (!workspacePath) continue;\n\n const key = `${workspacePath}::${skillName}`;\n byKey.delete(key);\n byKey.set(key, { eventId: event.id, skillName, workspacePath });\n }\n\n return [...byKey.values()];\n}\n"],"mappings":"sGAkBA,IAAM,EACJ,gDASF,SAAgB,EACd,EACwB,CACxB,IAAM,EAAQ,IAAI,IAElB,IAAK,IAAM,KAAS,EAAQ,CAC1B,GAAI,CAAC,EAAA,8BAA8B,EAAM,CAAE,SAM3C,IAAM,EAJO,EAAM,YAAY,QAC5B,OAAQ,GAAM,EAAE,OAAS,OAAO,CAChC,IAAK,GAAM,EAAE,KAAK,CAClB,KAAK;EACM,CAAK,MAAM,EAAwB,CACjD,GAAI,CAAC,EAAO,SAEZ,IAAM,EAAY,EAAM,GAClB,EAAO,EAAM,GAAG,QAAQ,MAAO,IAAI,CAAC,QAAQ,OAAQ,GAAG,CACvD,EAAS,mBAAmB,IAClC,GAAI,CAAC,EAAK,SAAS,EAAO,CAAE,SAC5B,IAAM,EAAgB,EAAK,MAAM,EAAG,CAAC,EAAO,OAAO,CACnD,GAAI,CAAC,EAAe,SAEpB,IAAM,EAAM,GAAG,EAAc,IAAI,IACjC,EAAM,OAAO,EAAI,CACjB,EAAM,IAAI,EAAK,CAAE,QAAS,EAAM,GAAI,YAAW,gBAAe,CAAC,CAGjE,MAAO,CAAC,GAAG,EAAM,QAAQ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { OpenHandsEvent } from "#/types/agent-server/core";
2
+ export interface DetectedSkillInstall {
3
+ /** Id of the bash observation event carrying the success marker. */
4
+ eventId: string;
5
+ skillName: string;
6
+ /** Workspace root the skill was installed into (forward slashes). */
7
+ workspacePath: string;
8
+ }
9
+ /**
10
+ * Skills the agent installed during this conversation via the add-skill
11
+ * flow. The SDK loads skills once at conversation start, so these are on
12
+ * disk but inert until a new conversation starts in `workspacePath`.
13
+ * Deduped per workspace+skill; a re-install (--force) keeps the latest
14
+ * event id and moves the entry to the end.
15
+ */
16
+ export declare function detectSkillInstalls(events: OpenHandsEvent[]): DetectedSkillInstall[];
@@ -0,0 +1,26 @@
1
+ import { isExecuteBashObservationEvent as e } from "../types/agent-server/type-guards.js";
2
+ //#region src/utils/skill-install-events.ts
3
+ var t = /^✅ Successfully installed '([^']+)' to (.+)$/m;
4
+ function n(n) {
5
+ let r = /* @__PURE__ */ new Map();
6
+ for (let i of n) {
7
+ if (!e(i)) continue;
8
+ let n = i.observation.content.filter((e) => e.type === "text").map((e) => e.text).join("\n").match(t);
9
+ if (!n) continue;
10
+ let a = n[1], o = n[2].replace(/\\/g, "/").replace(/\/+$/, ""), s = `/.agents/skills/${a}`;
11
+ if (!o.endsWith(s)) continue;
12
+ let c = o.slice(0, -s.length);
13
+ if (!c) continue;
14
+ let l = `${c}::${a}`;
15
+ r.delete(l), r.set(l, {
16
+ eventId: i.id,
17
+ skillName: a,
18
+ workspacePath: c
19
+ });
20
+ }
21
+ return [...r.values()];
22
+ }
23
+ //#endregion
24
+ export { n as detectSkillInstalls };
25
+
26
+ //# sourceMappingURL=skill-install-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-install-events.js","names":[],"sources":["../../src/utils/skill-install-events.ts"],"sourcesContent":["import { OpenHandsEvent } from \"#/types/agent-server/core\";\nimport { isExecuteBashObservationEvent } from \"#/types/agent-server/type-guards\";\n\nexport interface DetectedSkillInstall {\n /** Id of the bash observation event carrying the success marker. */\n eventId: string;\n skillName: string;\n /** Workspace root the skill was installed into (forward slashes). */\n workspacePath: string;\n}\n\n/**\n * Success marker printed by the bundled add-skill skill's fetch_skill.py:\n * ✅ Successfully installed '<name>' to <workspace>/.agents/skills/<name>\n * Failures exit 1 and never print this line. Matched on output alone —\n * `command` can be \"\" and `exit_code` can be -1 on soft-timeout\n * continuation observations that still carry the full output.\n */\nconst INSTALL_SUCCESS_PATTERN =\n /^✅ Successfully installed '([^']+)' to (.+)$/m;\n\n/**\n * Skills the agent installed during this conversation via the add-skill\n * flow. The SDK loads skills once at conversation start, so these are on\n * disk but inert until a new conversation starts in `workspacePath`.\n * Deduped per workspace+skill; a re-install (--force) keeps the latest\n * event id and moves the entry to the end.\n */\nexport function detectSkillInstalls(\n events: OpenHandsEvent[],\n): DetectedSkillInstall[] {\n const byKey = new Map<string, DetectedSkillInstall>();\n\n for (const event of events) {\n if (!isExecuteBashObservationEvent(event)) continue;\n\n const text = event.observation.content\n .filter((c) => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\\n\");\n const match = text.match(INSTALL_SUCCESS_PATTERN);\n if (!match) continue;\n\n const skillName = match[1];\n const dest = match[2].replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const suffix = `/.agents/skills/${skillName}`;\n if (!dest.endsWith(suffix)) continue;\n const workspacePath = dest.slice(0, -suffix.length);\n if (!workspacePath) continue;\n\n const key = `${workspacePath}::${skillName}`;\n byKey.delete(key);\n byKey.set(key, { eventId: event.id, skillName, workspacePath });\n }\n\n return [...byKey.values()];\n}\n"],"mappings":";;AAkBA,IAAM,IACJ;AASF,SAAgB,EACd,GACwB;CACxB,IAAM,oBAAQ,IAAI,KAAmC;AAErD,MAAK,IAAM,KAAS,GAAQ;AAC1B,MAAI,CAAC,EAA8B,EAAM,CAAE;EAM3C,IAAM,IAJO,EAAM,YAAY,QAC5B,QAAQ,MAAM,EAAE,SAAS,OAAO,CAChC,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,KACM,CAAK,MAAM,EAAwB;AACjD,MAAI,CAAC,EAAO;EAEZ,IAAM,IAAY,EAAM,IAClB,IAAO,EAAM,GAAG,QAAQ,OAAO,IAAI,CAAC,QAAQ,QAAQ,GAAG,EACvD,IAAS,mBAAmB;AAClC,MAAI,CAAC,EAAK,SAAS,EAAO,CAAE;EAC5B,IAAM,IAAgB,EAAK,MAAM,GAAG,CAAC,EAAO,OAAO;AACnD,MAAI,CAAC,EAAe;EAEpB,IAAM,IAAM,GAAG,EAAc,IAAI;AAEjC,EADA,EAAM,OAAO,EAAI,EACjB,EAAM,IAAI,GAAK;GAAE,SAAS,EAAM;GAAI;GAAW;GAAe,CAAC;;AAGjE,QAAO,CAAC,GAAG,EAAM,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);function e(e,t){if(!t)return;let n=new Set(t.profiles.map(e=>e.name));if(e&&n.has(e))return e;if(t.active_profile&&n.has(t.active_profile))return t.active_profile}exports.resolveTitleLlmProfile=e;
2
+ //# sourceMappingURL=title-llm-profile.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-llm-profile.cjs","names":[],"sources":["../../src/utils/title-llm-profile.ts"],"sourcesContent":["import type { ProfileListResponse } from \"#/api/profiles-service/profiles-service.api\";\n\nexport function resolveTitleLlmProfile(\n preference: string | null | undefined,\n profiles: ProfileListResponse | undefined,\n): string | undefined {\n if (!profiles) return undefined;\n\n const availableProfiles = new Set(\n profiles.profiles.map((profile) => profile.name),\n );\n if (preference && availableProfiles.has(preference)) {\n return preference;\n }\n if (\n profiles.active_profile &&\n availableProfiles.has(profiles.active_profile)\n ) {\n return profiles.active_profile;\n }\n return undefined;\n}\n"],"mappings":"6CAEA,SAAgB,EACd,EACA,EACoB,CACpB,GAAI,CAAC,EAAU,OAEf,IAAM,EAAoB,IAAI,IAC5B,EAAS,SAAS,IAAK,GAAY,EAAQ,KAAK,CACjD,CACD,GAAI,GAAc,EAAkB,IAAI,EAAW,CACjD,OAAO,EAET,GACE,EAAS,gBACT,EAAkB,IAAI,EAAS,eAAe,CAE9C,OAAO,EAAS"}
@@ -0,0 +1,2 @@
1
+ import type { ProfileListResponse } from "#/api/profiles-service/profiles-service.api";
2
+ export declare function resolveTitleLlmProfile(preference: string | null | undefined, profiles: ProfileListResponse | undefined): string | undefined;
@@ -0,0 +1,11 @@
1
+ //#region src/utils/title-llm-profile.ts
2
+ function e(e, t) {
3
+ if (!t) return;
4
+ let n = new Set(t.profiles.map((e) => e.name));
5
+ if (e && n.has(e)) return e;
6
+ if (t.active_profile && n.has(t.active_profile)) return t.active_profile;
7
+ }
8
+ //#endregion
9
+ export { e as resolveTitleLlmProfile };
10
+
11
+ //# sourceMappingURL=title-llm-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-llm-profile.js","names":[],"sources":["../../src/utils/title-llm-profile.ts"],"sourcesContent":["import type { ProfileListResponse } from \"#/api/profiles-service/profiles-service.api\";\n\nexport function resolveTitleLlmProfile(\n preference: string | null | undefined,\n profiles: ProfileListResponse | undefined,\n): string | undefined {\n if (!profiles) return undefined;\n\n const availableProfiles = new Set(\n profiles.profiles.map((profile) => profile.name),\n );\n if (preference && availableProfiles.has(preference)) {\n return preference;\n }\n if (\n profiles.active_profile &&\n availableProfiles.has(profiles.active_profile)\n ) {\n return profiles.active_profile;\n }\n return undefined;\n}\n"],"mappings":";AAEA,SAAgB,EACd,GACA,GACoB;AACpB,KAAI,CAAC,EAAU;CAEf,IAAM,IAAoB,IAAI,IAC5B,EAAS,SAAS,KAAK,MAAY,EAAQ,KAAK,CACjD;AACD,KAAI,KAAc,EAAkB,IAAI,EAAW,CACjD,QAAO;AAET,KACE,EAAS,kBACT,EAAkB,IAAI,EAAS,eAAe,CAE9C,QAAO,EAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/agent-canvas",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
4
4
  "description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -23,7 +23,7 @@
23
23
  "@heroui/react": "2.8.10",
24
24
  "@microlink/react-json-view": "1.31.20",
25
25
  "@monaco-editor/react": "4.7.0",
26
- "@openhands/extensions": "0.9.0",
26
+ "@openhands/extensions": "0.11.0",
27
27
  "@openhands/typescript-client": "1.34.0",
28
28
  "@react-router/node": "7.17.0",
29
29
  "@react-router/serve": "7.17.0",
@@ -100,7 +100,12 @@
100
100
  "build:app": "npm run make-i18n && react-router build",
101
101
  "build:lib": "npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json",
102
102
  "build:docker": "node scripts/docker-build.mjs",
103
- "example:acp-docker:env": "node scripts/gen-acp-docker-env.mjs"
103
+ "example:acp-docker:env": "node scripts/gen-acp-docker-env.mjs",
104
+ "desktop": "npm run build:app && electron electron/main.mjs",
105
+ "build:desktop": "npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && electron-builder --config electron-builder.config.mjs",
106
+ "build:desktop:universal": "npm run build:app && node scripts/download-uv.mjs && node scripts/download-node.mjs && cross-env ELECTRON_ARCH=universal electron-builder --config electron-builder.config.mjs",
107
+ "download-uv": "node scripts/download-uv.mjs",
108
+ "download-node": "node scripts/download-node.mjs"
104
109
  },
105
110
  "lint-staged": {
106
111
  "src/**/*.{ts,tsx,js}": [
@@ -136,6 +141,8 @@
136
141
  "@vercel/react-router": "1.3.0",
137
142
  "@vitest/coverage-v8": "4.1.5",
138
143
  "cross-env": "10.1.0",
144
+ "electron": "42.3.2",
145
+ "electron-builder": "26.8.1",
139
146
  "eslint": "9.39.4",
140
147
  "eslint-config-prettier": "10.1.8",
141
148
  "eslint-import-resolver-typescript": "4.4.4",
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * Usage:
21
21
  * node scripts/check-sdk-version-sync.mjs
22
- * EXPECTED_SDK_VERSION=1.36.1 node scripts/check-sdk-version-sync.mjs
22
+ * EXPECTED_SDK_VERSION=1.37.0 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/agent-canvas/dispatches \\
81
- -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.36.1"}}'
81
+ -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.37.0"}}'
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.36.1,<2.0.0"
264
- * "openhands-tools==1.36.1"
265
- * "openhands-workspace (>=1.36.1)"
263
+ * "openhands-sdk>=1.37.0,<2.0.0"
264
+ * "openhands-tools==1.37.0"
265
+ * "openhands-workspace (>=1.37.0)"
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.36.1", "==1.36.1", "(>=1.36.1)", "~=1.36.1"
279
+ // ">=1.37.0", "==1.37.0", "(>=1.37.0)", "~=1.37.0"
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);
@@ -34,6 +34,7 @@ const IDENTICAL_VALUE_ALLOWLIST = new Set([
34
34
  'SCHEMA$VERIFICATION$SECURITY_ANALYZER$CHOICE$LLM',
35
35
  'SETTINGS$AGENT_SERVER_URL_PLACEHOLDER',
36
36
  'SETTINGS$AGENT_TYPE_OPENHANDS',
37
+ 'SETTINGS$APP_UPDATE_CARD_TITLE',
37
38
  'SETTINGS$AZURE_DEVOPS',
38
39
  'SETTINGS$CLOUD_SETTINGS_LINK',
39
40
  'SETTINGS$GITHUB',
@@ -51,6 +52,7 @@ const IDENTICAL_VALUE_ALLOWLIST = new Set([
51
52
  'SETTINGS$SKILLS_PILLS_MORE',
52
53
  'SETTINGS$SKILLS_VERSION',
53
54
  'SETTINGS$SLACK',
55
+ 'SETTINGS$TITLE_GENERATION_PROFILE_OPTION',
54
56
  'VSCODE$TITLE',
55
57
  'WORKSPACE$JUPYTER_TAB_LABEL',
56
58
  ]);