@openhands/agent-canvas 1.0.0-alpha.7 → 1.0.0-alpha.9

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 (745) hide show
  1. package/README.md +25 -23
  2. package/bin/agent-canvas.mjs +27 -1
  3. package/build/assets/{QueryClientProvider-DITRCGAK.js → QueryClientProvider-B7kl84Kj.js} +1 -1
  4. package/build/assets/{Trans-D43bd3yR.js → Trans-1j65oy9O.js} +1 -1
  5. package/build/assets/{acp-providers-SCPK1BIU.js → acp-providers-DauuOsW9.js} +1 -1
  6. package/build/assets/{acp-route-guard-IWlFmS6x.js → acp-route-guard-CQTmeJwM.js} +1 -1
  7. package/build/assets/{active-backend-context-CkP3ZEJs.js → active-backend-context-TVbjnvmP.js} +1 -1
  8. package/build/assets/add-backend-modal-FsnpTTgO.js +1 -0
  9. package/build/assets/{agent-server-client-options-8OJSXbm8.js → agent-server-client-options-DT2GP6VJ.js} +1 -1
  10. package/build/assets/{agent-server-compatibility-DvKtnXHw.js → agent-server-compatibility-2aOx5iWd.js} +1 -1
  11. package/build/assets/agent-server-conversation-service.api-BZmUqtiO.js +5 -0
  12. package/build/assets/{agent-settings-DdisD2Xx.js → agent-settings-B247S9G3.js} +2 -2
  13. package/build/assets/{alert-banner-CvTYN73l.js → alert-banner-BWoqueRw.js} +1 -1
  14. package/build/assets/{analytics-consent-form-modal-BKgT9i2w.js → analytics-consent-form-modal-C7sXfxRh.js} +1 -1
  15. package/build/assets/{app-settings-DcYXtxGP.js → app-settings-BVeSaty9.js} +1 -1
  16. package/build/assets/{automation-detail-D7GEU0vR.js → automation-detail-R-99FUce.js} +1 -1
  17. package/build/assets/{automations-list-CkVNsgzm.js → automations-list-Dfu2c-_D.js} +1 -1
  18. package/build/assets/backend-form-modal-DxYjqqAK.js +1 -0
  19. package/build/assets/{backend-synced-settings-badge-BFy2HylT.js → backend-synced-settings-badge-nAfiUWvM.js} +1 -1
  20. package/build/assets/{base-modal-B4HvlFHE.js → base-modal-CQRvRHu1.js} +1 -1
  21. package/build/assets/{brand-button-8fVVei4i.js → brand-button-C2nEKopC.js} +1 -1
  22. package/build/assets/browser-HrYc5Gce.js +5 -0
  23. package/build/assets/{browser-tab-DTM6RyoV.js → browser-tab-B_BuTvrO.js} +1 -1
  24. package/build/assets/{checkmark-BcvXE9bf.js → checkmark-BJJrZUF8.js} +1 -1
  25. package/build/assets/{chevron-left-small-BqSkXTeq.js → chevron-left-small-CSh-sE9L.js} +1 -1
  26. package/build/assets/{circle-plus-check-toggle-DRvuu-RD.js → circle-plus-check-toggle-qs8Va1cC.js} +1 -1
  27. package/build/assets/{clock-DfoVUZVq.js → clock-ZR4Kn-_Y.js} +1 -1
  28. package/build/assets/{close-SnIy2eLD.js → close-BdmyeRqS.js} +1 -1
  29. package/build/assets/{combobox-caret-BMsz5mQX.js → combobox-caret-B53O9Hsq.js} +1 -1
  30. package/build/assets/{condenser-settings-DduLQcpV.js → condenser-settings-A35V3yng.js} +1 -1
  31. package/build/assets/{confirmation-modal-B-DOYMUH.js → confirmation-modal-C9-La0h3.js} +1 -1
  32. package/build/assets/{context-menu-list-item-DzjPB8aC.js → context-menu-list-item-Buu9nc0q.js} +1 -1
  33. package/build/assets/conversation--ldUK72N.js +19 -0
  34. package/build/assets/conversation-eNrhH94O.js +1 -0
  35. package/build/assets/conversation-panel-B49Jpqpb.js +1 -0
  36. package/build/assets/{conversation-service.api-YTGTw0pz.js → conversation-service.api--f8WglOC.js} +1 -1
  37. package/build/assets/{conversation-tab-empty-state-BtFDbyTe.js → conversation-tab-empty-state-D8dNvo-V.js} +1 -1
  38. package/build/assets/conversation-websocket-context-BW68-J8o.js +3 -0
  39. package/build/assets/{copy-BxgbrjDT.js → copy-C7Ti2d8C.js} +1 -1
  40. package/build/assets/{custom-toast-handlers-BYxhSr3t.js → custom-toast-handlers-BOc3qeQ7.js} +1 -1
  41. package/build/assets/declaration-D378OjpZ.js +1 -0
  42. package/build/assets/{device-verify-CTbXX9CQ.js → device-verify-CMusn8nX.js} +1 -1
  43. package/build/assets/edit-automation-modal-Dnjxbjn7.js +1 -0
  44. package/build/assets/{ellipsis-button-BoU2-xlG.js → ellipsis-button-ugUATsNo.js} +1 -1
  45. package/build/assets/{entry.client-DU7-q4ZU.js → entry.client-CqqXOSvd.js} +2 -2
  46. package/build/assets/{enum-filter-dropdown-BJt-NplD.js → enum-filter-dropdown-1vpOGySB.js} +1 -1
  47. package/build/assets/{environment-switch-overlay-DQ1n6Iu6.js → environment-switch-overlay-CTCTQikP.js} +1 -1
  48. package/build/assets/{extensions-hub-BW1FAKFJ.js → extensions-hub-BSUseHVF.js} +1 -1
  49. package/build/assets/{extensions-navigation-CbPMhSML.js → extensions-navigation-CT1kc1u_.js} +1 -1
  50. package/build/assets/files-tab-CQHdWpQt.js +1 -0
  51. package/build/assets/{folder-CerIk8uG.js → folder-0WSMImNX.js} +1 -1
  52. package/build/assets/git-control-bar-branch-button-C8u5rzjc.js +27 -0
  53. package/build/assets/{git-provider-icon-D8RE4unY.js → git-provider-icon-D-a-rcLm.js} +1 -1
  54. package/build/assets/{home-DR11ejqB.js → home-DD0GroCu.js} +1 -1
  55. package/build/assets/{i18n-DkYgs32x.js → i18n-DjAGhTis.js} +1 -1
  56. package/build/assets/install-server-modal-z5VaHeXd.js +1 -0
  57. package/build/assets/{launch-DKCU9uJH.js → launch-B2mbfOSm.js} +1 -1
  58. package/build/assets/{lesson-plan-CmkRbe6Z.js → lesson-plan-DRYG5SLI.js} +1 -1
  59. package/build/assets/{link-external-CvxB0BmI.js → link-external-C9d6Fo3x.js} +1 -1
  60. package/build/assets/{llm-client-BpIfxETv.js → llm-client-ChQzg4wX.js} +1 -1
  61. package/build/assets/llm-settings-BEyqixPI.js +1 -0
  62. package/build/assets/{llm-settings-BOJC4vD-.js → llm-settings-BdiaGFbg.js} +1 -1
  63. package/build/assets/{loading-spinner-91b5FiMQ.js → loading-spinner-C04FGh14.js} +1 -1
  64. package/build/assets/{manage-backends-modal-DqpzcxdI.js → manage-backends-modal-s22zCdEW.js} +1 -1
  65. package/build/assets/{manage-workspaces-modal-eG6XgAvw.js → manage-workspaces-modal-C5EuW8m1.js} +1 -1
  66. package/build/assets/manifest-9d1c34fb.js +1 -0
  67. package/build/assets/{markdown-renderer-wZnLDbA1.js → markdown-renderer-CEX4Becj.js} +1 -1
  68. package/build/assets/mcp-C06YssEI.js +9 -0
  69. package/build/assets/messages-6aOyUu3r.js +36 -0
  70. package/build/assets/{modal-backdrop-B04pVYAD.js → modal-backdrop-DTYGVmOR.js} +1 -1
  71. package/build/assets/{modal-body-CgUoFQA1.js → modal-body-YElmM1dV.js} +1 -1
  72. package/build/assets/{modal-close-button-SM_WXzDY.js → modal-close-button-C_GpQt9F.js} +1 -1
  73. package/build/assets/{model-selector-7id-Uirf.js → model-selector-DeMmw-Xa.js} +1 -1
  74. package/build/assets/{navigation-context-BFjstyH6.js → navigation-context-DeIPtGPp.js} +1 -1
  75. package/build/assets/{navigation-link-DFQ7YcWq.js → navigation-link-C9JD4PYD.js} +1 -1
  76. package/build/assets/{openhands-logo-DkDp75rC.js → openhands-logo-CI5Fhn1W.js} +1 -1
  77. package/build/assets/{option-service.api-DN0ZcGjw.js → option-service.api-DsI1UW7N.js} +1 -1
  78. package/build/assets/{organization-service.api-Ct2dZF8M.js → organization-service.api-COwMPFg5.js} +1 -1
  79. package/build/assets/{path-utils-D1ZtqFC7.js → path-utils-BVbe598W.js} +1 -1
  80. package/build/assets/{plan-components-gOm-daR3.js → plan-components-DEjMuDDG.js} +1 -1
  81. package/build/assets/{planner-tab-yubfN-6U.js → planner-tab-bN6r1G-1.js} +1 -1
  82. package/build/assets/{profiles-client-D4twHRVf.js → profiles-client-BGkKEV9j.js} +1 -1
  83. package/build/assets/{providers-C2T07PM3.js → providers-DXvCAN_u.js} +1 -1
  84. package/build/assets/{proxy-BMZyC45G.js → proxy-CurRmrqf.js} +1 -1
  85. package/build/assets/{query-client-config-CiK0GJJO.js → query-client-config-Ba7qAAoO.js} +1 -1
  86. package/build/assets/recommended-automations-launcher-mJhK6Atl.js +52 -0
  87. package/build/assets/root-3t9rxEpE.js +2 -0
  88. package/build/assets/root-DHeCXo9N.css +1 -0
  89. package/build/assets/{root-layout-B4QioBS6.js → root-layout-BjVwHmta.js} +2 -2
  90. package/build/assets/{sdk-section-page-03k88tIR.js → sdk-section-page-CJW0G04-.js} +1 -1
  91. package/build/assets/{sdk-settings-schema-BY8dOy3a.js → sdk-settings-schema-QBYH-ONX.js} +1 -1
  92. package/build/assets/{search-BCAF9EDS.js → search-Cq_cFrDt.js} +1 -1
  93. package/build/assets/{secrets-service-Z3qtRb_G.js → secrets-service-Bwd5DeUs.js} +1 -1
  94. package/build/assets/{secrets-settings-BnlByuMZ.js → secrets-settings-MLXqOtX2.js} +1 -1
  95. package/build/assets/{server-client-CG1zHqph.js → server-client-C3mC8Hl3.js} +1 -1
  96. package/build/assets/{settings-DyzGLF_d.js → settings-D7E2U5tK.js} +1 -1
  97. package/build/assets/{settings-client-CkXDJwIY.js → settings-client-CwjfwoiB.js} +1 -1
  98. package/build/assets/{settings-dropdown-input-CAQWQgx-.js → settings-dropdown-input-VwAXNrOb.js} +1 -1
  99. package/build/assets/{settings-gear-D4ZkEDGb.js → settings-gear-BJwWR1ej.js} +1 -1
  100. package/build/assets/{settings-index-KtTw49xL.js → settings-index-J-3BNR0W.js} +1 -1
  101. package/build/assets/{settings-input-BWCZt9g2.js → settings-input-DBywAnA7.js} +1 -1
  102. package/build/assets/{settings-list-classes-xMleGkTC.js → settings-list-classes-BOS092DR.js} +1 -1
  103. package/build/assets/{settings-modal-Cv2YWSUY.js → settings-modal-B8vgWDTe.js} +1 -1
  104. package/build/assets/{settings-section-header-context-1wfkgjZZ.js → settings-section-header-context-32x6WTyL.js} +1 -1
  105. package/build/assets/settings-service.api-FvJGK45W.js +1 -0
  106. package/build/assets/{settings-switch-CGap2LtG.js → settings-switch-DTKmHC8F.js} +1 -1
  107. package/build/assets/{settings-utils-BBozxqqi.js → settings-utils-BsvSU3OM.js} +1 -1
  108. package/build/assets/{shared-conversation-DQlzwdpo.js → shared-conversation-EZV0FRIf.js} +1 -1
  109. package/build/assets/{sidebar-mobile-menu-toggle-DXplko7u.js → sidebar-mobile-menu-toggle-BnbzzpQl.js} +1 -1
  110. package/build/assets/{sidebar-nav-link-B4h8naZ7.js → sidebar-nav-link-CnWoZcwc.js} +1 -1
  111. package/build/assets/{skill-card-pill-row-D0oTWx-a.js → skill-card-pill-row-tZ599jli.js} +1 -1
  112. package/build/assets/{skills-BN8atjgW.js → skills-ZyAO5dyK.js} +1 -1
  113. package/build/assets/{skills-plugins-BTnp7QcQ.js → skills-plugins-BSRz041I.js} +1 -1
  114. package/build/assets/{skills-settings-CbOQvzkR.js → skills-settings-CG2hu34D.js} +2 -2
  115. package/build/assets/{status-DDL-ipIP.js → status-CsatcFbK.js} +1 -1
  116. package/build/assets/{styled-tooltip-Awq4HMw3.js → styled-tooltip-CS3mB_1X.js} +1 -1
  117. package/build/assets/{switch-skeleton-Bv21RGWd.js → switch-skeleton-C-CfhYYV.js} +1 -1
  118. package/build/assets/{task-list-tab-B45ktzHM.js → task-list-tab-465DDju0.js} +1 -1
  119. package/build/assets/{terminal-D5pzR9Ru.js → terminal-CcgBEVnC.js} +1 -1
  120. package/build/assets/{terminal-DGuR4559.js → terminal-LNa-iU5c.js} +1 -1
  121. package/build/assets/{toggle-switch-gj6T-wsU.js → toggle-switch-k-IZCDbt.js} +1 -1
  122. package/build/assets/{typography-BbaUAC4V.js → typography-vVUMoNUg.js} +1 -1
  123. package/build/assets/{u-check-circle-DHGiAi-w.js → u-check-circle-DplbarS5.js} +1 -1
  124. package/build/assets/{u-check-circle-half-BPcWtWwv.js → u-check-circle-half-yDuiSZHC.js} +1 -1
  125. package/build/assets/{u-circuit-B_nK9hOu.js → u-circuit-C9tYkpeK.js} +1 -1
  126. package/build/assets/{u-edit-BPFJBd34.js → u-edit-KAUlufD8.js} +1 -1
  127. package/build/assets/{use-active-conversation-Bu5J9iLy.js → use-active-conversation-DS5j9R4q.js} +1 -1
  128. package/build/assets/{use-agent-settings-schema-BbtOsR7P.js → use-agent-settings-schema-Bvp5UzV8.js} +1 -1
  129. package/build/assets/{use-agent-state-DN9Nc5pP.js → use-agent-state-D2C9SeGw.js} +1 -1
  130. package/build/assets/{use-cloud-current-user-id-B_rMUiu8.js → use-cloud-current-user-id-DWVar4st.js} +1 -1
  131. package/build/assets/{use-config-Bcz2JL2t.js → use-config-BSu_53GL.js} +1 -1
  132. package/build/assets/{use-conversation-id-BOaaZahn.js → use-conversation-id-DajhCn2A.js} +1 -1
  133. package/build/assets/{use-create-conversation-BWFA_FId.js → use-create-conversation-BEZg__Vv.js} +1 -1
  134. package/build/assets/{use-event-store-CQZCcVz-.js → use-event-store-BT_gV3ut.js} +1 -1
  135. package/build/assets/{use-handle-plan-click-CgrCGmT1.js → use-handle-plan-click-uOpew2LO.js} +1 -1
  136. package/build/assets/use-is-authed-hXC8vxgT.js +1 -0
  137. package/build/assets/{use-is-creating-conversation-DhoM7UAB.js → use-is-creating-conversation-DhDeeWfA.js} +1 -1
  138. package/build/assets/{use-launch-skill-in-chat-DOyQsXFO.js → use-launch-skill-in-chat-DVGPFrbI.js} +1 -1
  139. package/build/assets/{use-llm-profiles-CAIzHJDX.js → use-llm-profiles-O4a9V6RC.js} +1 -1
  140. package/build/assets/use-runtime-is-ready-pGSbPddC.js +1 -0
  141. package/build/assets/{use-save-settings-5m3w89Ph.js → use-save-settings-CEEKSTWG.js} +1 -1
  142. package/build/assets/{use-settings-DzG0C3vO.js → use-settings-DQ7Oo1Hj.js} +1 -1
  143. package/build/assets/{use-settings-nav-items-BIsKeX52.js → use-settings-nav-items-YmrXrjn9.js} +2 -2
  144. package/build/assets/use-skills-BIvlWblA.js +1 -0
  145. package/build/assets/{use-task-list-Bs90uF2N.js → use-task-list-DDeNHprj.js} +1 -1
  146. package/build/assets/{use-unified-vscode-url-C5iI-Z5A.js → use-unified-vscode-url-wAMzv8Sn.js} +1 -1
  147. package/build/assets/use-user-conversation-B_zDoSeh.js +1 -0
  148. package/build/assets/{useMutation-CRJwk4cR.js → useMutation-B4OUESdw.js} +1 -1
  149. package/build/assets/{useTranslation-01pF7z10.js → useTranslation-CpIcQBq6.js} +1 -1
  150. package/build/assets/{utils-Czcl6buL.js → utils-D-HX7JCe.js} +1 -1
  151. package/build/assets/{vendor~conversation-panel~conversation-CbjvWBSu.js → vendor~conversation-panel~conversation-BlCIz9XQ.js} +1 -1
  152. package/build/assets/{vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-CofhIDpd.js → vendor~home~conversation-panel~conversation~shared-conversation~planner-tab~files-tab-Ds9quNZ9.js} +1 -1
  153. package/build/assets/vendor~home~mcp~automations-list-C5PoHCy6.js +1 -0
  154. package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-BQPOygpY.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CGlZoBKa.js} +1 -1
  155. package/build/assets/{vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-CyYIBiBk.js → vendor~home~mcp~llm-settings~agent-settings~condenser-settings~verification-settings~app-se~ocm3mykx-DE11mPxp.js} +1 -1
  156. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-CuGq_cxH.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-8b8V5bfO.js} +1 -1
  157. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-CFpDeb9o.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~iguv7bgw-Dy7L6fMG.js} +1 -1
  158. package/build/assets/{vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-C1p8-pMr.js → vendor~root-layout~home~conversation-panel~conversation~extensions-hub~skills-settings~skil~k776hupu-D40EXhZx.js} +1 -1
  159. package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-CHrEOFl6.js +48 -0
  160. package/build/assets/{vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-DlKA6SoO.js → vendor~root~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-s~kyz9p27j-CyUbhpbm.js} +1 -1
  161. package/build/assets/{verification-settings-DbziMp4K.js → verification-settings-BtlTiHP8.js} +1 -1
  162. package/build/assets/{vscode-tab-BVhQR2rt.js → vscode-tab-B0vdh9gU.js} +1 -1
  163. package/build/assets/{waiting-for-runtime-message-JotSOBdC.js → waiting-for-runtime-message-DWPl_Yby.js} +1 -1
  164. package/build/assets/{x-mark-CZ57VvRX.js → x-mark-CWI0f9yI.js} +1 -1
  165. package/build/favicon.svg +1 -0
  166. package/build/index.html +4 -4
  167. package/build/locales/ar/openhands.json +8 -0
  168. package/build/locales/ca/openhands.json +8 -0
  169. package/build/locales/de/openhands.json +8 -0
  170. package/build/locales/en/openhands.json +8 -0
  171. package/build/locales/es/openhands.json +8 -0
  172. package/build/locales/fr/openhands.json +8 -0
  173. package/build/locales/it/openhands.json +8 -0
  174. package/build/locales/ja/openhands.json +8 -0
  175. package/build/locales/ko-KR/openhands.json +8 -0
  176. package/build/locales/no/openhands.json +8 -0
  177. package/build/locales/pt/openhands.json +8 -0
  178. package/build/locales/tr/openhands.json +8 -0
  179. package/build/locales/uk/openhands.json +8 -0
  180. package/build/locales/zh-CN/openhands.json +8 -0
  181. package/build/locales/zh-TW/openhands.json +8 -0
  182. package/config/defaults.json +1 -1
  183. package/dist/api/agent-server-adapter.cjs +1 -1
  184. package/dist/api/agent-server-adapter.cjs.map +1 -1
  185. package/dist/api/agent-server-adapter.js +1 -0
  186. package/dist/api/agent-server-adapter.js.map +1 -1
  187. package/dist/api/agent-server-config.cjs +1 -1
  188. package/dist/api/agent-server-config.cjs.map +1 -1
  189. package/dist/api/agent-server-config.d.ts +1 -1
  190. package/dist/api/agent-server-config.js +1 -1
  191. package/dist/api/agent-server-config.js.map +1 -1
  192. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  193. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  194. package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +12 -0
  195. package/dist/api/conversation-service/agent-server-conversation-service.api.js +4 -0
  196. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  197. package/dist/api/mcp-service/mcp-service.api.cjs +2 -0
  198. package/dist/api/mcp-service/mcp-service.api.cjs.map +1 -0
  199. package/dist/api/mcp-service/mcp-service.api.d.ts +6 -0
  200. package/dist/api/mcp-service/mcp-service.api.js +36 -0
  201. package/dist/api/mcp-service/mcp-service.api.js.map +1 -0
  202. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  203. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  204. package/dist/api/settings-service/settings-service.api.d.ts +1 -0
  205. package/dist/api/settings-service/settings-service.api.js +59 -41
  206. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  207. package/dist/api/skills-service.cjs +1 -1
  208. package/dist/api/skills-service.cjs.map +1 -1
  209. package/dist/api/skills-service.d.ts +1 -1
  210. package/dist/api/skills-service.js +2 -2
  211. package/dist/api/skills-service.js.map +1 -1
  212. package/dist/components/features/automations/detail/activity-log-item.d.ts +1 -1
  213. package/dist/components/features/automations/recommended-automations-launcher.d.ts +1 -1
  214. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  215. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  216. package/dist/components/features/backends/backend-form-modal.js +149 -142
  217. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  218. package/dist/components/features/chat/change-agent-button.cjs +1 -1
  219. package/dist/components/features/chat/change-agent-button.cjs.map +1 -1
  220. package/dist/components/features/chat/change-agent-button.js +65 -59
  221. package/dist/components/features/chat/change-agent-button.js.map +1 -1
  222. package/dist/components/features/chat/chat-interface.cjs +2 -2
  223. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  224. package/dist/components/features/chat/chat-interface.js +15 -14
  225. package/dist/components/features/chat/chat-interface.js.map +1 -1
  226. package/dist/components/features/chat/components/chat-input-actions.cjs +1 -1
  227. package/dist/components/features/chat/components/chat-input-actions.cjs.map +1 -1
  228. package/dist/components/features/chat/components/chat-input-actions.js +127 -149
  229. package/dist/components/features/chat/components/chat-input-actions.js.map +1 -1
  230. package/dist/components/features/chat/components/chat-input-model.cjs +1 -1
  231. package/dist/components/features/chat/components/chat-input-model.cjs.map +1 -1
  232. package/dist/components/features/chat/components/chat-input-model.d.ts +10 -0
  233. package/dist/components/features/chat/components/chat-input-model.js +95 -60
  234. package/dist/components/features/chat/components/chat-input-model.js.map +1 -1
  235. package/dist/components/features/chat/git-control-bar.cjs +1 -1
  236. package/dist/components/features/chat/git-control-bar.cjs.map +1 -1
  237. package/dist/components/features/chat/git-control-bar.js +60 -59
  238. package/dist/components/features/chat/git-control-bar.js.map +1 -1
  239. package/dist/components/features/conversation/conversation-name-with-status.cjs +1 -1
  240. package/dist/components/features/conversation/conversation-name-with-status.cjs.map +1 -1
  241. package/dist/components/features/conversation/conversation-name-with-status.js +2 -2
  242. package/dist/components/features/conversation/conversation-name-with-status.js.map +1 -1
  243. package/dist/components/features/conversation/conversation-name.cjs +1 -1
  244. package/dist/components/features/conversation/conversation-name.cjs.map +1 -1
  245. package/dist/components/features/conversation/conversation-name.js +3 -3
  246. package/dist/components/features/conversation/conversation-name.js.map +1 -1
  247. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs +1 -1
  248. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs.map +1 -1
  249. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js +1 -1
  250. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js.map +1 -1
  251. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
  252. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
  253. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +16 -16
  254. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
  255. package/dist/components/features/conversation-panel/skills-modal.cjs +1 -1
  256. package/dist/components/features/conversation-panel/skills-modal.cjs.map +1 -1
  257. package/dist/components/features/conversation-panel/skills-modal.js +1 -1
  258. package/dist/components/features/conversation-panel/skills-modal.js.map +1 -1
  259. package/dist/components/features/mcp-logo-badge.cjs +1 -1
  260. package/dist/components/features/mcp-logo-badge.cjs.map +1 -1
  261. package/dist/components/features/mcp-logo-badge.d.ts +2 -2
  262. package/dist/components/features/mcp-logo-badge.js +1 -1
  263. package/dist/components/features/mcp-logo-badge.js.map +1 -1
  264. package/dist/components/features/mcp-page/custom-server-editor.cjs +1 -1
  265. package/dist/components/features/mcp-page/custom-server-editor.cjs.map +1 -1
  266. package/dist/components/features/mcp-page/custom-server-editor.js +64 -41
  267. package/dist/components/features/mcp-page/custom-server-editor.js.map +1 -1
  268. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  269. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  270. package/dist/components/features/mcp-page/install-server-modal.d.ts +1 -1
  271. package/dist/components/features/mcp-page/install-server-modal.js +126 -102
  272. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  273. package/dist/components/features/mcp-page/installed-server-card.cjs +1 -1
  274. package/dist/components/features/mcp-page/installed-server-card.cjs.map +1 -1
  275. package/dist/components/features/mcp-page/installed-server-card.js +1 -1
  276. package/dist/components/features/mcp-page/installed-server-card.js.map +1 -1
  277. package/dist/components/features/mcp-page/marketplace-card.cjs +1 -1
  278. package/dist/components/features/mcp-page/marketplace-card.cjs.map +1 -1
  279. package/dist/components/features/mcp-page/marketplace-card.d.ts +1 -1
  280. package/dist/components/features/mcp-page/marketplace-card.js +27 -25
  281. package/dist/components/features/mcp-page/marketplace-card.js.map +1 -1
  282. package/dist/components/features/mcp-page/marketplace-section.cjs +1 -1
  283. package/dist/components/features/mcp-page/marketplace-section.cjs.map +1 -1
  284. package/dist/components/features/mcp-page/marketplace-section.d.ts +1 -1
  285. package/dist/components/features/mcp-page/marketplace-section.js +1 -1
  286. package/dist/components/features/mcp-page/marketplace-section.js.map +1 -1
  287. package/dist/components/features/mcp-page/mcp-logo-stack-badge.d.ts +2 -2
  288. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs +7 -7
  289. package/dist/components/features/settings/mcp-settings/mcp-server-form.cjs.map +1 -1
  290. package/dist/components/features/settings/mcp-settings/mcp-server-form.d.ts +8 -12
  291. package/dist/components/features/settings/mcp-settings/mcp-server-form.js +114 -87
  292. package/dist/components/features/settings/mcp-settings/mcp-server-form.js.map +1 -1
  293. package/dist/context/scroll-context.cjs +1 -1
  294. package/dist/context/scroll-context.cjs.map +1 -1
  295. package/dist/context/scroll-context.d.ts +1 -0
  296. package/dist/context/scroll-context.js +4 -1
  297. package/dist/context/scroll-context.js.map +1 -1
  298. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  299. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  300. package/dist/contexts/conversation-websocket-context.js +97 -89
  301. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  302. package/dist/favicon.svg +1 -0
  303. package/dist/hooks/chat/use-slash-command.cjs +1 -1
  304. package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
  305. package/dist/hooks/chat/use-slash-command.js +1 -1
  306. package/dist/hooks/chat/use-slash-command.js.map +1 -1
  307. package/dist/hooks/mutation/use-switch-acp-model.cjs +2 -0
  308. package/dist/hooks/mutation/use-switch-acp-model.cjs.map +1 -0
  309. package/dist/hooks/mutation/use-switch-acp-model.d.ts +23 -0
  310. package/dist/hooks/mutation/use-switch-acp-model.js +26 -0
  311. package/dist/hooks/mutation/use-switch-acp-model.js.map +1 -0
  312. package/dist/hooks/mutation/use-test-mcp-server.cjs +2 -0
  313. package/dist/hooks/mutation/use-test-mcp-server.cjs.map +1 -0
  314. package/dist/hooks/mutation/use-test-mcp-server.d.ts +2 -0
  315. package/dist/hooks/mutation/use-test-mcp-server.js +10 -0
  316. package/dist/hooks/mutation/use-test-mcp-server.js.map +1 -0
  317. package/dist/hooks/query/use-automation-detail.d.ts +3 -2
  318. package/dist/hooks/query/use-conversation-skills.cjs +2 -0
  319. package/dist/hooks/query/use-conversation-skills.cjs.map +1 -0
  320. package/dist/hooks/query/use-conversation-skills.d.ts +7 -0
  321. package/dist/hooks/query/use-conversation-skills.js +8 -0
  322. package/dist/hooks/query/use-conversation-skills.js.map +1 -0
  323. package/dist/hooks/query/use-skills.cjs +1 -1
  324. package/dist/hooks/query/use-skills.cjs.map +1 -1
  325. package/dist/hooks/query/use-skills.d.ts +6 -1
  326. package/dist/hooks/query/use-skills.js +3 -3
  327. package/dist/hooks/query/use-skills.js.map +1 -1
  328. package/dist/hooks/use-acp-model-context.cjs.map +1 -1
  329. package/dist/hooks/use-acp-model-context.d.ts +3 -4
  330. package/dist/hooks/use-acp-model-context.js.map +1 -1
  331. package/dist/hooks/use-chat-input-model-state.cjs +2 -0
  332. package/dist/hooks/use-chat-input-model-state.cjs.map +1 -0
  333. package/dist/hooks/use-chat-input-model-state.d.ts +12 -0
  334. package/dist/hooks/use-chat-input-model-state.js +29 -0
  335. package/dist/hooks/use-chat-input-model-state.js.map +1 -0
  336. package/dist/i18n/declaration.cjs +1 -1
  337. package/dist/i18n/declaration.cjs.map +1 -1
  338. package/dist/i18n/declaration.d.ts +8 -0
  339. package/dist/i18n/declaration.js +1 -1
  340. package/dist/i18n/declaration.js.map +1 -1
  341. package/dist/i18n/translation.cjs +2 -2
  342. package/dist/i18n/translation.cjs.map +1 -1
  343. package/dist/i18n/translation.js +136 -0
  344. package/dist/i18n/translation.js.map +1 -1
  345. package/dist/locales/ar/openhands.json +8 -0
  346. package/dist/locales/ca/openhands.json +8 -0
  347. package/dist/locales/de/openhands.json +8 -0
  348. package/dist/locales/en/openhands.json +8 -0
  349. package/dist/locales/es/openhands.json +8 -0
  350. package/dist/locales/fr/openhands.json +8 -0
  351. package/dist/locales/it/openhands.json +8 -0
  352. package/dist/locales/ja/openhands.json +8 -0
  353. package/dist/locales/ko-KR/openhands.json +8 -0
  354. package/dist/locales/no/openhands.json +8 -0
  355. package/dist/locales/pt/openhands.json +8 -0
  356. package/dist/locales/tr/openhands.json +8 -0
  357. package/dist/locales/uk/openhands.json +8 -0
  358. package/dist/locales/zh-CN/openhands.json +8 -0
  359. package/dist/locales/zh-TW/openhands.json +8 -0
  360. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs +2 -0
  361. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs.map +1 -0
  362. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js +37 -0
  363. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js.map +1 -0
  364. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs +2 -0
  365. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs.map +1 -0
  366. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js +36 -0
  367. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js.map +1 -0
  368. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/atlassian.cjs +1 -1
  369. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.cjs.map +1 -0
  370. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/atlassian.js +15 -5
  371. package/dist/node_modules/@openhands/extensions/integrations/catalog/atlassian.js.map +1 -0
  372. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs +2 -0
  373. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs.map +1 -0
  374. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js +36 -0
  375. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js.map +1 -0
  376. package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.cjs +2 -0
  377. package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.cjs.map +1 -0
  378. package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.js +31 -0
  379. package/dist/node_modules/@openhands/extensions/integrations/catalog/browser-mcp.js.map +1 -0
  380. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs +2 -0
  381. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs.map +1 -0
  382. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js +52 -0
  383. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js.map +1 -0
  384. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-bindings.cjs +1 -1
  385. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-bindings.cjs.map +1 -0
  386. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-bindings.js +15 -5
  387. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-bindings.js.map +1 -0
  388. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.cjs +2 -0
  389. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.cjs.map +1 -0
  390. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-browser-rendering.js +15 -5
  391. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-browser-rendering.js.map +1 -0
  392. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-builds.cjs +1 -1
  393. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-builds.cjs.map +1 -0
  394. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-builds.js +15 -5
  395. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-builds.js.map +1 -0
  396. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-docs.cjs +1 -1
  397. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-docs.cjs.map +1 -0
  398. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-docs.js +15 -5
  399. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-docs.js.map +1 -0
  400. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.cjs +2 -0
  401. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.cjs.map +1 -0
  402. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/cloudflare-observability.js +15 -5
  403. package/dist/node_modules/@openhands/extensions/integrations/catalog/cloudflare-observability.js.map +1 -0
  404. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/deepwiki.cjs +1 -1
  405. package/dist/node_modules/@openhands/extensions/integrations/catalog/deepwiki.cjs.map +1 -0
  406. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/deepwiki.js +15 -5
  407. package/dist/node_modules/@openhands/extensions/integrations/catalog/deepwiki.js.map +1 -0
  408. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs +2 -0
  409. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs.map +1 -0
  410. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js +36 -0
  411. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js.map +1 -0
  412. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/everything.cjs +1 -1
  413. package/dist/node_modules/@openhands/extensions/integrations/catalog/everything.cjs.map +1 -0
  414. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/everything.js +13 -6
  415. package/dist/node_modules/@openhands/extensions/integrations/catalog/everything.js.map +1 -0
  416. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs +2 -0
  417. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs.map +1 -0
  418. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js +36 -0
  419. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js.map +1 -0
  420. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/fetch.cjs +1 -1
  421. package/dist/node_modules/@openhands/extensions/integrations/catalog/fetch.cjs.map +1 -0
  422. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/fetch.js +13 -6
  423. package/dist/node_modules/@openhands/extensions/integrations/catalog/fetch.js.map +1 -0
  424. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs +2 -0
  425. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs.map +1 -0
  426. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js +40 -0
  427. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js.map +1 -0
  428. package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.cjs +2 -0
  429. package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.cjs.map +1 -0
  430. package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.js +39 -0
  431. package/dist/node_modules/@openhands/extensions/integrations/catalog/filesystem.js.map +1 -0
  432. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs +2 -0
  433. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs.map +1 -0
  434. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js +36 -0
  435. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js.map +1 -0
  436. package/dist/node_modules/@openhands/extensions/integrations/catalog/git.cjs +2 -0
  437. package/dist/node_modules/@openhands/extensions/integrations/catalog/git.cjs.map +1 -0
  438. package/dist/node_modules/@openhands/extensions/integrations/catalog/git.js +40 -0
  439. package/dist/node_modules/@openhands/extensions/integrations/catalog/git.js.map +1 -0
  440. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +2 -0
  441. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -0
  442. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +47 -0
  443. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -0
  444. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/huggingface.cjs +1 -1
  445. package/dist/node_modules/@openhands/extensions/integrations/catalog/huggingface.cjs.map +1 -0
  446. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/huggingface.js +15 -5
  447. package/dist/node_modules/@openhands/extensions/integrations/catalog/huggingface.js.map +1 -0
  448. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs +2 -0
  449. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs.map +1 -0
  450. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js +36 -0
  451. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js.map +1 -0
  452. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/linear.cjs +1 -1
  453. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.cjs.map +1 -0
  454. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/linear.js +15 -5
  455. package/dist/node_modules/@openhands/extensions/integrations/catalog/linear.js.map +1 -0
  456. package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.cjs +2 -0
  457. package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.cjs.map +1 -0
  458. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/memory.js +13 -6
  459. package/dist/node_modules/@openhands/extensions/integrations/catalog/memory.js.map +1 -0
  460. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs +2 -0
  461. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs.map +1 -0
  462. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js +36 -0
  463. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js.map +1 -0
  464. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs +2 -0
  465. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs.map +1 -0
  466. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js +40 -0
  467. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js.map +1 -0
  468. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +2 -0
  469. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -0
  470. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +39 -0
  471. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -0
  472. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs +2 -0
  473. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs.map +1 -0
  474. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js +38 -0
  475. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js.map +1 -0
  476. package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.cjs +2 -0
  477. package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.cjs.map +1 -0
  478. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/paypal.js +15 -5
  479. package/dist/node_modules/@openhands/extensions/integrations/catalog/paypal.js.map +1 -0
  480. package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.cjs +2 -0
  481. package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.cjs.map +1 -0
  482. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/playwright.js +13 -6
  483. package/dist/node_modules/@openhands/extensions/integrations/catalog/playwright.js.map +1 -0
  484. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs +2 -0
  485. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs.map +1 -0
  486. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js +43 -0
  487. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js.map +1 -0
  488. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs +2 -0
  489. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs.map +1 -0
  490. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js +41 -0
  491. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js.map +1 -0
  492. package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.cjs +2 -0
  493. package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.cjs.map +1 -0
  494. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/sentry.js +15 -5
  495. package/dist/node_modules/@openhands/extensions/integrations/catalog/sentry.js.map +1 -0
  496. package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.cjs +2 -0
  497. package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.cjs.map +1 -0
  498. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/sequential-thinking.js +13 -6
  499. package/dist/node_modules/@openhands/extensions/integrations/catalog/sequential-thinking.js.map +1 -0
  500. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +2 -0
  501. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -0
  502. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +45 -0
  503. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -0
  504. package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.cjs +2 -0
  505. package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.cjs.map +1 -0
  506. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/stripe.js +15 -5
  507. package/dist/node_modules/@openhands/extensions/integrations/catalog/stripe.js.map +1 -0
  508. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs +2 -0
  509. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs.map +1 -0
  510. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js +37 -0
  511. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js.map +1 -0
  512. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/tavily.cjs +1 -1
  513. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs.map +1 -0
  514. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js +39 -0
  515. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js.map +1 -0
  516. package/dist/node_modules/@openhands/extensions/integrations/catalog/time.cjs +2 -0
  517. package/dist/node_modules/@openhands/extensions/integrations/catalog/time.cjs.map +1 -0
  518. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/catalog/time.js +13 -6
  519. package/dist/node_modules/@openhands/extensions/integrations/catalog/time.js.map +1 -0
  520. package/dist/node_modules/@openhands/extensions/integrations/index.cjs +2 -0
  521. package/dist/node_modules/@openhands/extensions/integrations/index.cjs.map +1 -0
  522. package/dist/node_modules/@openhands/extensions/integrations/index.js +175 -0
  523. package/dist/node_modules/@openhands/extensions/integrations/index.js.map +1 -0
  524. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/logos.cjs +1 -1
  525. package/dist/node_modules/@openhands/extensions/integrations/logos.cjs.map +1 -0
  526. package/dist/node_modules/@openhands/extensions/{mcps → integrations}/logos.js +2 -2
  527. package/dist/node_modules/@openhands/extensions/integrations/logos.js.map +1 -0
  528. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.cjs +2 -0
  529. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.cjs.map +1 -0
  530. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.js +548 -0
  531. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-catalog.js.map +1 -0
  532. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.cjs +2 -0
  533. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.cjs.map +1 -0
  534. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.js +482 -0
  535. package/dist/node_modules/@openhands/extensions/integrations/oauth-provider-registration-defaults.js.map +1 -0
  536. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
  537. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
  538. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +3 -0
  539. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
  540. package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs +2 -0
  541. package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.cjs.map +1 -0
  542. package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.js +22 -0
  543. package/dist/node_modules/@openhands/typescript-client/dist/client/mcp-client.js.map +1 -0
  544. package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
  545. package/dist/node_modules/@openhands/typescript-client/dist/index.js +1 -0
  546. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
  547. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
  548. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +3 -0
  549. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
  550. package/dist/package.cjs +1 -1
  551. package/dist/package.cjs.map +1 -1
  552. package/dist/package.js +6 -4
  553. package/dist/package.js.map +1 -1
  554. package/dist/routes/conversation.cjs +1 -1
  555. package/dist/routes/conversation.cjs.map +1 -1
  556. package/dist/routes/conversation.js +61 -63
  557. package/dist/routes/conversation.js.map +1 -1
  558. package/dist/routes/mcp.cjs +1 -1
  559. package/dist/routes/mcp.cjs.map +1 -1
  560. package/dist/routes/mcp.js +1 -1
  561. package/dist/routes/mcp.js.map +1 -1
  562. package/dist/stores/use-event-store.cjs +1 -1
  563. package/dist/stores/use-event-store.cjs.map +1 -1
  564. package/dist/stores/use-event-store.d.ts +22 -0
  565. package/dist/stores/use-event-store.js +9 -1
  566. package/dist/stores/use-event-store.js.map +1 -1
  567. package/dist/ui/context-menu.d.ts +1 -1
  568. package/dist/ui/help-link.d.ts +1 -1
  569. package/dist/utils/mcp-marketplace-utils.cjs +1 -1
  570. package/dist/utils/mcp-marketplace-utils.cjs.map +1 -1
  571. package/dist/utils/mcp-marketplace-utils.d.ts +21 -1
  572. package/dist/utils/mcp-marketplace-utils.js +23 -13
  573. package/dist/utils/mcp-marketplace-utils.js.map +1 -1
  574. package/dist/utils/settings-utils.cjs.map +1 -1
  575. package/dist/utils/settings-utils.js.map +1 -1
  576. package/package.json +6 -4
  577. package/scripts/check-sdk-version-sync.mjs +6 -6
  578. package/scripts/dev-safe.mjs +60 -24
  579. package/scripts/dev-with-automation.mjs +30 -50
  580. package/tools/canvas_ui_tool.py +129 -0
  581. package/build/assets/add-backend-modal-CqjNjGqY.js +0 -1
  582. package/build/assets/agent-server-conversation-service.api-BdEre_71.js +0 -5
  583. package/build/assets/backend-form-modal-KudhWUX8.js +0 -1
  584. package/build/assets/browser-vYpdU3CR.js +0 -5
  585. package/build/assets/conversation-COZAKz_K.js +0 -1
  586. package/build/assets/conversation-DWcvnmds.js +0 -19
  587. package/build/assets/conversation-panel-CZDStT0b.js +0 -1
  588. package/build/assets/conversation-websocket-context-DulnrIHh.js +0 -3
  589. package/build/assets/declaration-C9nuq2Dj.js +0 -1
  590. package/build/assets/edit-automation-modal-C3bFxS2f.js +0 -1
  591. package/build/assets/files-tab-CbJ4s7Ik.js +0 -1
  592. package/build/assets/git-control-bar-branch-button-Bm6rzSpo.js +0 -27
  593. package/build/assets/install-server-modal-VB5hOBpW.js +0 -1
  594. package/build/assets/llm-settings-CIdxmimN.js +0 -1
  595. package/build/assets/manifest-f041e61a.js +0 -1
  596. package/build/assets/mcp-BdfyCW1l.js +0 -9
  597. package/build/assets/messages-v-q35ObG.js +0 -36
  598. package/build/assets/recommended-automations-launcher-Cx7svuGE.js +0 -52
  599. package/build/assets/root-D2PVd51i.js +0 -2
  600. package/build/assets/root-DEotKI6b.css +0 -1
  601. package/build/assets/settings-service.api-Z6x0l0GU.js +0 -1
  602. package/build/assets/use-is-authed-BFoh8Ogh.js +0 -1
  603. package/build/assets/use-runtime-is-ready-BQWLEyqa.js +0 -1
  604. package/build/assets/use-skills-Cn-78xP1.js +0 -1
  605. package/build/assets/use-user-conversation-BCYpbPT1.js +0 -1
  606. package/build/assets/vendor~home~mcp~automations-list-DRfWZRnF.js +0 -1
  607. package/build/assets/vendor~root-layout~home~conversation-panel~conversation~launch~extensions-hub~skills-settin~dp08i1qy-BJm2mGIp.js +0 -48
  608. package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.cjs +0 -2
  609. package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.cjs.map +0 -1
  610. package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.js +0 -30
  611. package/dist/node_modules/@openhands/extensions/mcps/catalog/airtable.js.map +0 -1
  612. package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.cjs +0 -2
  613. package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.cjs.map +0 -1
  614. package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.js +0 -29
  615. package/dist/node_modules/@openhands/extensions/mcps/catalog/apify.js.map +0 -1
  616. package/dist/node_modules/@openhands/extensions/mcps/catalog/atlassian.cjs.map +0 -1
  617. package/dist/node_modules/@openhands/extensions/mcps/catalog/atlassian.js.map +0 -1
  618. package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.cjs +0 -2
  619. package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.cjs.map +0 -1
  620. package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.js +0 -29
  621. package/dist/node_modules/@openhands/extensions/mcps/catalog/brave-search.js.map +0 -1
  622. package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.cjs +0 -2
  623. package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.cjs.map +0 -1
  624. package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.js +0 -24
  625. package/dist/node_modules/@openhands/extensions/mcps/catalog/browser-mcp.js.map +0 -1
  626. package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.cjs +0 -2
  627. package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.cjs.map +0 -1
  628. package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.js +0 -45
  629. package/dist/node_modules/@openhands/extensions/mcps/catalog/clickhouse.js.map +0 -1
  630. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-bindings.cjs.map +0 -1
  631. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-bindings.js.map +0 -1
  632. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.cjs +0 -2
  633. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.cjs.map +0 -1
  634. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-browser-rendering.js.map +0 -1
  635. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-builds.cjs.map +0 -1
  636. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-builds.js.map +0 -1
  637. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-docs.cjs.map +0 -1
  638. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-docs.js.map +0 -1
  639. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.cjs +0 -2
  640. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.cjs.map +0 -1
  641. package/dist/node_modules/@openhands/extensions/mcps/catalog/cloudflare-observability.js.map +0 -1
  642. package/dist/node_modules/@openhands/extensions/mcps/catalog/deepwiki.cjs.map +0 -1
  643. package/dist/node_modules/@openhands/extensions/mcps/catalog/deepwiki.js.map +0 -1
  644. package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.cjs +0 -2
  645. package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.cjs.map +0 -1
  646. package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.js +0 -29
  647. package/dist/node_modules/@openhands/extensions/mcps/catalog/elevenlabs.js.map +0 -1
  648. package/dist/node_modules/@openhands/extensions/mcps/catalog/everything.cjs.map +0 -1
  649. package/dist/node_modules/@openhands/extensions/mcps/catalog/everything.js.map +0 -1
  650. package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.cjs +0 -2
  651. package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.cjs.map +0 -1
  652. package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.js +0 -29
  653. package/dist/node_modules/@openhands/extensions/mcps/catalog/exa.js.map +0 -1
  654. package/dist/node_modules/@openhands/extensions/mcps/catalog/fetch.cjs.map +0 -1
  655. package/dist/node_modules/@openhands/extensions/mcps/catalog/fetch.js.map +0 -1
  656. package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.cjs +0 -2
  657. package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.cjs.map +0 -1
  658. package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.js +0 -33
  659. package/dist/node_modules/@openhands/extensions/mcps/catalog/figma.js.map +0 -1
  660. package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.cjs +0 -2
  661. package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.cjs.map +0 -1
  662. package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.js +0 -32
  663. package/dist/node_modules/@openhands/extensions/mcps/catalog/filesystem.js.map +0 -1
  664. package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.cjs +0 -2
  665. package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.cjs.map +0 -1
  666. package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.js +0 -29
  667. package/dist/node_modules/@openhands/extensions/mcps/catalog/firecrawl.js.map +0 -1
  668. package/dist/node_modules/@openhands/extensions/mcps/catalog/git.cjs +0 -2
  669. package/dist/node_modules/@openhands/extensions/mcps/catalog/git.cjs.map +0 -1
  670. package/dist/node_modules/@openhands/extensions/mcps/catalog/git.js +0 -33
  671. package/dist/node_modules/@openhands/extensions/mcps/catalog/git.js.map +0 -1
  672. package/dist/node_modules/@openhands/extensions/mcps/catalog/github.cjs +0 -2
  673. package/dist/node_modules/@openhands/extensions/mcps/catalog/github.cjs.map +0 -1
  674. package/dist/node_modules/@openhands/extensions/mcps/catalog/github.js +0 -40
  675. package/dist/node_modules/@openhands/extensions/mcps/catalog/github.js.map +0 -1
  676. package/dist/node_modules/@openhands/extensions/mcps/catalog/huggingface.cjs.map +0 -1
  677. package/dist/node_modules/@openhands/extensions/mcps/catalog/huggingface.js.map +0 -1
  678. package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.cjs +0 -2
  679. package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.cjs.map +0 -1
  680. package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.js +0 -29
  681. package/dist/node_modules/@openhands/extensions/mcps/catalog/kagi.js.map +0 -1
  682. package/dist/node_modules/@openhands/extensions/mcps/catalog/linear.cjs.map +0 -1
  683. package/dist/node_modules/@openhands/extensions/mcps/catalog/linear.js.map +0 -1
  684. package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.cjs +0 -2
  685. package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.cjs.map +0 -1
  686. package/dist/node_modules/@openhands/extensions/mcps/catalog/memory.js.map +0 -1
  687. package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.cjs +0 -2
  688. package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.cjs.map +0 -1
  689. package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.js +0 -29
  690. package/dist/node_modules/@openhands/extensions/mcps/catalog/mongodb.js.map +0 -1
  691. package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.cjs +0 -2
  692. package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.cjs.map +0 -1
  693. package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.js +0 -33
  694. package/dist/node_modules/@openhands/extensions/mcps/catalog/neon.js.map +0 -1
  695. package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.cjs +0 -2
  696. package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.cjs.map +0 -1
  697. package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.js +0 -32
  698. package/dist/node_modules/@openhands/extensions/mcps/catalog/notion.js.map +0 -1
  699. package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.cjs +0 -2
  700. package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.cjs.map +0 -1
  701. package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.js +0 -31
  702. package/dist/node_modules/@openhands/extensions/mcps/catalog/obsidian.js.map +0 -1
  703. package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.cjs +0 -2
  704. package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.cjs.map +0 -1
  705. package/dist/node_modules/@openhands/extensions/mcps/catalog/paypal.js.map +0 -1
  706. package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.cjs +0 -2
  707. package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.cjs.map +0 -1
  708. package/dist/node_modules/@openhands/extensions/mcps/catalog/playwright.js.map +0 -1
  709. package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.cjs +0 -2
  710. package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.cjs.map +0 -1
  711. package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.js +0 -36
  712. package/dist/node_modules/@openhands/extensions/mcps/catalog/redis.js.map +0 -1
  713. package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.cjs +0 -2
  714. package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.cjs.map +0 -1
  715. package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.js +0 -34
  716. package/dist/node_modules/@openhands/extensions/mcps/catalog/resend.js.map +0 -1
  717. package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.cjs +0 -2
  718. package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.cjs.map +0 -1
  719. package/dist/node_modules/@openhands/extensions/mcps/catalog/sentry.js.map +0 -1
  720. package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.cjs +0 -2
  721. package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.cjs.map +0 -1
  722. package/dist/node_modules/@openhands/extensions/mcps/catalog/sequential-thinking.js.map +0 -1
  723. package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.cjs +0 -2
  724. package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.cjs.map +0 -1
  725. package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.js +0 -38
  726. package/dist/node_modules/@openhands/extensions/mcps/catalog/slack.js.map +0 -1
  727. package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.cjs +0 -2
  728. package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.cjs.map +0 -1
  729. package/dist/node_modules/@openhands/extensions/mcps/catalog/stripe.js.map +0 -1
  730. package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.cjs +0 -2
  731. package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.cjs.map +0 -1
  732. package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.js +0 -30
  733. package/dist/node_modules/@openhands/extensions/mcps/catalog/supabase.js.map +0 -1
  734. package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.cjs.map +0 -1
  735. package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.js +0 -32
  736. package/dist/node_modules/@openhands/extensions/mcps/catalog/tavily.js.map +0 -1
  737. package/dist/node_modules/@openhands/extensions/mcps/catalog/time.cjs +0 -2
  738. package/dist/node_modules/@openhands/extensions/mcps/catalog/time.cjs.map +0 -1
  739. package/dist/node_modules/@openhands/extensions/mcps/catalog/time.js.map +0 -1
  740. package/dist/node_modules/@openhands/extensions/mcps/index.cjs +0 -2
  741. package/dist/node_modules/@openhands/extensions/mcps/index.cjs.map +0 -1
  742. package/dist/node_modules/@openhands/extensions/mcps/index.js +0 -87
  743. package/dist/node_modules/@openhands/extensions/mcps/index.js.map +0 -1
  744. package/dist/node_modules/@openhands/extensions/mcps/logos.cjs.map +0 -1
  745. package/dist/node_modules/@openhands/extensions/mcps/logos.js.map +0 -1
@@ -6,6 +6,14 @@ export interface EventState {
6
6
  events: OHEvent[];
7
7
  eventIds: Set<string | number>;
8
8
  uiEvents: OHEvent[];
9
+ /**
10
+ * The conversation whose events currently populate the store. The store is
11
+ * global (not keyed by conversation), so the conversation route uses this to
12
+ * tell a genuine conversation switch apart from a remount of the *same*
13
+ * conversation (e.g. navigating to Settings and back) — only the former
14
+ * should clear the accumulated events.
15
+ */
16
+ loadedConversationId: string | null;
9
17
  addEvent: (event: OHEvent) => void;
10
18
  /**
11
19
  * Bulk-insert events. Used for the initial REST history load and for
@@ -14,6 +22,20 @@ export interface EventState {
14
22
  * timestamp so older pages drop into the correct position.
15
23
  */
16
24
  addEvents: (events: OHEvent[]) => void;
25
+ /**
26
+ * Clear all events. Also resets `loadedConversationId` to `null` so the
27
+ * store never claims to hold a conversation whose events have been wiped —
28
+ * the invariant (`loadedConversationId` reflects the conversation whose
29
+ * events are in the arrays) holds even for a standalone clear.
30
+ */
17
31
  clearEvents: () => void;
32
+ /**
33
+ * Atomically clear all events and record which conversation is now loaded.
34
+ * Collapsing the reset and the bookkeeping into a single `set` keeps the
35
+ * store invariant enforced at the boundary, rather than relying on every
36
+ * call-site to invoke a clear and a `loadedConversationId` setter in the
37
+ * right order.
38
+ */
39
+ clearEventsForConversation: (conversationId: string | null) => void;
18
40
  }
19
41
  export declare const useEventStore: import("zustand").UseBoundStore<import("zustand").StoreApi<EventState>>;
@@ -29,6 +29,7 @@ var n = (e) => "id" in e ? e.id : void 0, r = (e) => "timestamp" in e ? e.timest
29
29
  events: [],
30
30
  eventIds: /* @__PURE__ */ new Set(),
31
31
  uiEvents: [],
32
+ loadedConversationId: null,
32
33
  addEvent: (t) => e((e) => c(e, t)),
33
34
  addEvents: (r) => e((e) => {
34
35
  if (r.length === 0) return e;
@@ -47,7 +48,14 @@ var n = (e) => "id" in e ? e.id : void 0, r = (e) => "timestamp" in e ? e.timest
47
48
  clearEvents: () => e(() => ({
48
49
  events: [],
49
50
  eventIds: /* @__PURE__ */ new Set(),
50
- uiEvents: []
51
+ uiEvents: [],
52
+ loadedConversationId: null
53
+ })),
54
+ clearEventsForConversation: (t) => e(() => ({
55
+ events: [],
56
+ eventIds: /* @__PURE__ */ new Set(),
57
+ uiEvents: [],
58
+ loadedConversationId: t
51
59
  }))
52
60
  }));
53
61
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"use-event-store.js","names":[],"sources":["../../src/stores/use-event-store.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { OpenHandsEvent } from \"#/types/agent-server/core\";\nimport { handleEventForUI } from \"#/utils/handle-event-for-ui\";\n\nexport type OHEvent = OpenHandsEvent & {\n isFromPlanningAgent?: boolean;\n};\n\nconst getEventId = (event: OHEvent): string | number | undefined =>\n \"id\" in event ? event.id : undefined;\n\nconst getEventTimestamp = (event: OHEvent): string | undefined =>\n \"timestamp\" in event ? event.timestamp : undefined;\n\n/**\n * Compare two events by timestamp for sorting.\n * Events without timestamps are placed at the end.\n */\nconst compareEventsByTimestamp = (a: OHEvent, b: OHEvent): number => {\n const timestampA = getEventTimestamp(a);\n const timestampB = getEventTimestamp(b);\n\n // Events without timestamps go to the end\n if (!timestampA && !timestampB) return 0;\n if (!timestampA) return 1;\n if (!timestampB) return -1;\n\n // Compare ISO timestamp strings (lexicographic comparison works for ISO format)\n return timestampA.localeCompare(timestampB);\n};\n\n/**\n * Check if the new event needs sorting (i.e., it's out of order).\n * Returns true if the new event's timestamp is earlier than the last event's timestamp.\n */\nconst needsSorting = (events: OHEvent[], newEvent: OHEvent): boolean => {\n if (events.length === 0) return false;\n\n const lastEvent = events[events.length - 1];\n const lastTimestamp = getEventTimestamp(lastEvent);\n const newTimestamp = getEventTimestamp(newEvent);\n\n // If either event doesn't have a timestamp, don't sort\n if (!lastTimestamp || !newTimestamp) return false;\n\n // Sort needed if new event's timestamp is earlier than last event's timestamp\n return newTimestamp < lastTimestamp;\n};\n\nexport interface EventState {\n events: OHEvent[];\n eventIds: Set<string | number>;\n uiEvents: OHEvent[];\n addEvent: (event: OHEvent) => void;\n /**\n * Bulk-insert events. Used for the initial REST history load and for\n * \"scroll up to load older\" pagination. Newly-added events are de-duped\n * against the existing store and the combined list is re-sorted by\n * timestamp so older pages drop into the correct position.\n */\n addEvents: (events: OHEvent[]) => void;\n clearEvents: () => void;\n}\n\nconst appendEvent = (state: EventState, event: OHEvent): EventState => {\n // Deduplicate: skip if event with same id already exists (O(1) lookup)\n const eventId = getEventId(event);\n if (eventId !== undefined && state.eventIds.has(eventId)) {\n return state;\n }\n\n const newEventIds =\n eventId !== undefined\n ? new Set(state.eventIds).add(eventId)\n : state.eventIds;\n\n return {\n ...state,\n events: [...state.events, event],\n eventIds: newEventIds,\n uiEvents: handleEventForUI(event, state.uiEvents),\n };\n};\n\nconst sortEventState = (state: EventState): EventState => ({\n ...state,\n events: [...state.events].sort(compareEventsByTimestamp),\n uiEvents: [...state.uiEvents].sort(compareEventsByTimestamp),\n});\n\nconst applyAddEvent = (state: EventState, event: OHEvent): EventState => {\n const next = appendEvent(state, event);\n if (next === state) {\n return state;\n }\n\n if (\n !needsSorting(state.events, event) &&\n !needsSorting(state.uiEvents, event)\n ) {\n return next;\n }\n\n return sortEventState(next);\n};\n\nexport const useEventStore = create<EventState>()((set) => ({\n events: [],\n eventIds: new Set(),\n uiEvents: [],\n addEvent: (event: OHEvent) => set((state) => applyAddEvent(state, event)),\n addEvents: (incoming: OHEvent[]) =>\n set((state) => {\n if (incoming.length === 0) return state;\n\n const eventIds = new Set(state.eventIds);\n const events = [...state.events];\n let uiEvents = [...state.uiEvents];\n let added = false;\n\n for (const event of incoming) {\n const eventId = getEventId(event);\n const isDuplicate = eventId !== undefined && eventIds.has(eventId);\n\n if (!isDuplicate) {\n added = true;\n if (eventId !== undefined) {\n eventIds.add(eventId);\n }\n events.push(event);\n uiEvents = handleEventForUI(event, uiEvents);\n }\n }\n\n if (!added) {\n return state;\n }\n\n return sortEventState({\n ...state,\n events,\n eventIds,\n uiEvents,\n });\n }),\n clearEvents: () =>\n set(() => ({\n events: [],\n eventIds: new Set(),\n uiEvents: [],\n })),\n}));\n\n// In dev builds, expose the store on `window` so that fixture/preview\n// scripts (e.g. .pr/issue-132 demo capture) can inject synthetic events\n// without round-tripping through the agent-server. Tree-shaken in\n// production builds via `import.meta.env.DEV`.\nif (\n typeof window !== \"undefined\" &&\n typeof import.meta !== \"undefined\" &&\n (import.meta as { env?: { DEV?: boolean } }).env?.DEV\n) {\n (\n window as unknown as { __OH_EVENT_STORE__?: typeof useEventStore }\n ).__OH_EVENT_STORE__ = useEventStore;\n}\n"],"mappings":";;;AAQA,IAAM,KAAc,MAClB,QAAQ,IAAQ,EAAM,KAAK,KAAA,GAEvB,KAAqB,MACzB,eAAe,IAAQ,EAAM,YAAY,KAAA,GAMrC,KAA4B,GAAY,MAAuB;CACnE,IAAM,IAAa,EAAkB,EAAE,EACjC,IAAa,EAAkB,EAAE;AAQvC,QALI,CAAC,KAAc,CAAC,IAAmB,IAClC,IACA,IAGE,EAAW,cAAc,EAAW,GAHnB,KADA;GAWpB,KAAgB,GAAmB,MAA+B;AACtE,KAAI,EAAO,WAAW,EAAG,QAAO;CAEhC,IAAM,IAAY,EAAO,EAAO,SAAS,IACnC,IAAgB,EAAkB,EAAU,EAC5C,IAAe,EAAkB,EAAS;AAMhD,QAHI,CAAC,KAAiB,CAAC,IAAqB,KAGrC,IAAe;GAkBlB,KAAe,GAAmB,MAA+B;CAErE,IAAM,IAAU,EAAW,EAAM;AACjC,KAAI,MAAY,KAAA,KAAa,EAAM,SAAS,IAAI,EAAQ,CACtD,QAAO;CAGT,IAAM,IACJ,MAAY,KAAA,IAER,EAAM,WADN,IAAI,IAAI,EAAM,SAAS,CAAC,IAAI,EAAQ;AAG1C,QAAO;EACL,GAAG;EACH,QAAQ,CAAC,GAAG,EAAM,QAAQ,EAAM;EAChC,UAAU;EACV,UAAU,EAAiB,GAAO,EAAM,SAAS;EAClD;GAGG,KAAkB,OAAmC;CACzD,GAAG;CACH,QAAQ,CAAC,GAAG,EAAM,OAAO,CAAC,KAAK,EAAyB;CACxD,UAAU,CAAC,GAAG,EAAM,SAAS,CAAC,KAAK,EAAyB;CAC7D,GAEK,KAAiB,GAAmB,MAA+B;CACvE,IAAM,IAAO,EAAY,GAAO,EAAM;AAYtC,QAXI,MAAS,IACJ,IAIP,CAAC,EAAa,EAAM,QAAQ,EAAM,IAClC,CAAC,EAAa,EAAM,UAAU,EAAM,GAE7B,IAGF,EAAe,EAAK;GAGhB,IAAgB,GAAoB,EAAE,OAAS;CAC1D,QAAQ,EAAE;CACV,0BAAU,IAAI,KAAK;CACnB,UAAU,EAAE;CACZ,WAAW,MAAmB,GAAK,MAAU,EAAc,GAAO,EAAM,CAAC;CACzE,YAAY,MACV,GAAK,MAAU;AACb,MAAI,EAAS,WAAW,EAAG,QAAO;EAElC,IAAM,IAAW,IAAI,IAAI,EAAM,SAAS,EAClC,IAAS,CAAC,GAAG,EAAM,OAAO,EAC5B,IAAW,CAAC,GAAG,EAAM,SAAS,EAC9B,IAAQ;AAEZ,OAAK,IAAM,KAAS,GAAU;GAC5B,IAAM,IAAU,EAAW,EAAM;AAGjC,GAFoB,MAAY,KAAA,KAAa,EAAS,IAAI,EAAQ,KAGhE,IAAQ,IACJ,MAAY,KAAA,KACd,EAAS,IAAI,EAAQ,EAEvB,EAAO,KAAK,EAAM,EAClB,IAAW,EAAiB,GAAO,EAAS;;AAQhD,SAJK,IAIE,EAAe;GACpB,GAAG;GACH;GACA;GACA;GACD,CAAC,GARO;GAST;CACJ,mBACE,SAAW;EACT,QAAQ,EAAE;EACV,0BAAU,IAAI,KAAK;EACnB,UAAU,EAAE;EACb,EAAE;CACN,EAAE"}
1
+ {"version":3,"file":"use-event-store.js","names":[],"sources":["../../src/stores/use-event-store.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { OpenHandsEvent } from \"#/types/agent-server/core\";\nimport { handleEventForUI } from \"#/utils/handle-event-for-ui\";\n\nexport type OHEvent = OpenHandsEvent & {\n isFromPlanningAgent?: boolean;\n};\n\nconst getEventId = (event: OHEvent): string | number | undefined =>\n \"id\" in event ? event.id : undefined;\n\nconst getEventTimestamp = (event: OHEvent): string | undefined =>\n \"timestamp\" in event ? event.timestamp : undefined;\n\n/**\n * Compare two events by timestamp for sorting.\n * Events without timestamps are placed at the end.\n */\nconst compareEventsByTimestamp = (a: OHEvent, b: OHEvent): number => {\n const timestampA = getEventTimestamp(a);\n const timestampB = getEventTimestamp(b);\n\n // Events without timestamps go to the end\n if (!timestampA && !timestampB) return 0;\n if (!timestampA) return 1;\n if (!timestampB) return -1;\n\n // Compare ISO timestamp strings (lexicographic comparison works for ISO format)\n return timestampA.localeCompare(timestampB);\n};\n\n/**\n * Check if the new event needs sorting (i.e., it's out of order).\n * Returns true if the new event's timestamp is earlier than the last event's timestamp.\n */\nconst needsSorting = (events: OHEvent[], newEvent: OHEvent): boolean => {\n if (events.length === 0) return false;\n\n const lastEvent = events[events.length - 1];\n const lastTimestamp = getEventTimestamp(lastEvent);\n const newTimestamp = getEventTimestamp(newEvent);\n\n // If either event doesn't have a timestamp, don't sort\n if (!lastTimestamp || !newTimestamp) return false;\n\n // Sort needed if new event's timestamp is earlier than last event's timestamp\n return newTimestamp < lastTimestamp;\n};\n\nexport interface EventState {\n events: OHEvent[];\n eventIds: Set<string | number>;\n uiEvents: OHEvent[];\n /**\n * The conversation whose events currently populate the store. The store is\n * global (not keyed by conversation), so the conversation route uses this to\n * tell a genuine conversation switch apart from a remount of the *same*\n * conversation (e.g. navigating to Settings and back) — only the former\n * should clear the accumulated events.\n */\n loadedConversationId: string | null;\n addEvent: (event: OHEvent) => void;\n /**\n * Bulk-insert events. Used for the initial REST history load and for\n * \"scroll up to load older\" pagination. Newly-added events are de-duped\n * against the existing store and the combined list is re-sorted by\n * timestamp so older pages drop into the correct position.\n */\n addEvents: (events: OHEvent[]) => void;\n /**\n * Clear all events. Also resets `loadedConversationId` to `null` so the\n * store never claims to hold a conversation whose events have been wiped —\n * the invariant (`loadedConversationId` reflects the conversation whose\n * events are in the arrays) holds even for a standalone clear.\n */\n clearEvents: () => void;\n /**\n * Atomically clear all events and record which conversation is now loaded.\n * Collapsing the reset and the bookkeeping into a single `set` keeps the\n * store invariant enforced at the boundary, rather than relying on every\n * call-site to invoke a clear and a `loadedConversationId` setter in the\n * right order.\n */\n clearEventsForConversation: (conversationId: string | null) => void;\n}\n\nconst appendEvent = (state: EventState, event: OHEvent): EventState => {\n // Deduplicate: skip if event with same id already exists (O(1) lookup)\n const eventId = getEventId(event);\n if (eventId !== undefined && state.eventIds.has(eventId)) {\n return state;\n }\n\n const newEventIds =\n eventId !== undefined\n ? new Set(state.eventIds).add(eventId)\n : state.eventIds;\n\n return {\n ...state,\n events: [...state.events, event],\n eventIds: newEventIds,\n uiEvents: handleEventForUI(event, state.uiEvents),\n };\n};\n\nconst sortEventState = (state: EventState): EventState => ({\n ...state,\n events: [...state.events].sort(compareEventsByTimestamp),\n uiEvents: [...state.uiEvents].sort(compareEventsByTimestamp),\n});\n\nconst applyAddEvent = (state: EventState, event: OHEvent): EventState => {\n const next = appendEvent(state, event);\n if (next === state) {\n return state;\n }\n\n if (\n !needsSorting(state.events, event) &&\n !needsSorting(state.uiEvents, event)\n ) {\n return next;\n }\n\n return sortEventState(next);\n};\n\nexport const useEventStore = create<EventState>()((set) => ({\n events: [],\n eventIds: new Set(),\n uiEvents: [],\n loadedConversationId: null,\n addEvent: (event: OHEvent) => set((state) => applyAddEvent(state, event)),\n addEvents: (incoming: OHEvent[]) =>\n set((state) => {\n if (incoming.length === 0) return state;\n\n const eventIds = new Set(state.eventIds);\n const events = [...state.events];\n let uiEvents = [...state.uiEvents];\n let added = false;\n\n for (const event of incoming) {\n const eventId = getEventId(event);\n const isDuplicate = eventId !== undefined && eventIds.has(eventId);\n\n if (!isDuplicate) {\n added = true;\n if (eventId !== undefined) {\n eventIds.add(eventId);\n }\n events.push(event);\n uiEvents = handleEventForUI(event, uiEvents);\n }\n }\n\n if (!added) {\n return state;\n }\n\n return sortEventState({\n ...state,\n events,\n eventIds,\n uiEvents,\n });\n }),\n clearEvents: () =>\n set(() => ({\n events: [],\n eventIds: new Set(),\n uiEvents: [],\n loadedConversationId: null,\n })),\n clearEventsForConversation: (conversationId: string | null) =>\n set(() => ({\n events: [],\n eventIds: new Set(),\n uiEvents: [],\n loadedConversationId: conversationId,\n })),\n}));\n\n// In dev builds, expose the store on `window` so that fixture/preview\n// scripts (e.g. .pr/issue-132 demo capture) can inject synthetic events\n// without round-tripping through the agent-server. Tree-shaken in\n// production builds via `import.meta.env.DEV`.\nif (\n typeof window !== \"undefined\" &&\n typeof import.meta !== \"undefined\" &&\n (import.meta as { env?: { DEV?: boolean } }).env?.DEV\n) {\n (\n window as unknown as { __OH_EVENT_STORE__?: typeof useEventStore }\n ).__OH_EVENT_STORE__ = useEventStore;\n}\n"],"mappings":";;;AAQA,IAAM,KAAc,MAClB,QAAQ,IAAQ,EAAM,KAAK,KAAA,GAEvB,KAAqB,MACzB,eAAe,IAAQ,EAAM,YAAY,KAAA,GAMrC,KAA4B,GAAY,MAAuB;CACnE,IAAM,IAAa,EAAkB,EAAE,EACjC,IAAa,EAAkB,EAAE;AAQvC,QALI,CAAC,KAAc,CAAC,IAAmB,IAClC,IACA,IAGE,EAAW,cAAc,EAAW,GAHnB,KADA;GAWpB,KAAgB,GAAmB,MAA+B;AACtE,KAAI,EAAO,WAAW,EAAG,QAAO;CAEhC,IAAM,IAAY,EAAO,EAAO,SAAS,IACnC,IAAgB,EAAkB,EAAU,EAC5C,IAAe,EAAkB,EAAS;AAMhD,QAHI,CAAC,KAAiB,CAAC,IAAqB,KAGrC,IAAe;GAwClB,KAAe,GAAmB,MAA+B;CAErE,IAAM,IAAU,EAAW,EAAM;AACjC,KAAI,MAAY,KAAA,KAAa,EAAM,SAAS,IAAI,EAAQ,CACtD,QAAO;CAGT,IAAM,IACJ,MAAY,KAAA,IAER,EAAM,WADN,IAAI,IAAI,EAAM,SAAS,CAAC,IAAI,EAAQ;AAG1C,QAAO;EACL,GAAG;EACH,QAAQ,CAAC,GAAG,EAAM,QAAQ,EAAM;EAChC,UAAU;EACV,UAAU,EAAiB,GAAO,EAAM,SAAS;EAClD;GAGG,KAAkB,OAAmC;CACzD,GAAG;CACH,QAAQ,CAAC,GAAG,EAAM,OAAO,CAAC,KAAK,EAAyB;CACxD,UAAU,CAAC,GAAG,EAAM,SAAS,CAAC,KAAK,EAAyB;CAC7D,GAEK,KAAiB,GAAmB,MAA+B;CACvE,IAAM,IAAO,EAAY,GAAO,EAAM;AAYtC,QAXI,MAAS,IACJ,IAIP,CAAC,EAAa,EAAM,QAAQ,EAAM,IAClC,CAAC,EAAa,EAAM,UAAU,EAAM,GAE7B,IAGF,EAAe,EAAK;GAGhB,IAAgB,GAAoB,EAAE,OAAS;CAC1D,QAAQ,EAAE;CACV,0BAAU,IAAI,KAAK;CACnB,UAAU,EAAE;CACZ,sBAAsB;CACtB,WAAW,MAAmB,GAAK,MAAU,EAAc,GAAO,EAAM,CAAC;CACzE,YAAY,MACV,GAAK,MAAU;AACb,MAAI,EAAS,WAAW,EAAG,QAAO;EAElC,IAAM,IAAW,IAAI,IAAI,EAAM,SAAS,EAClC,IAAS,CAAC,GAAG,EAAM,OAAO,EAC5B,IAAW,CAAC,GAAG,EAAM,SAAS,EAC9B,IAAQ;AAEZ,OAAK,IAAM,KAAS,GAAU;GAC5B,IAAM,IAAU,EAAW,EAAM;AAGjC,GAFoB,MAAY,KAAA,KAAa,EAAS,IAAI,EAAQ,KAGhE,IAAQ,IACJ,MAAY,KAAA,KACd,EAAS,IAAI,EAAQ,EAEvB,EAAO,KAAK,EAAM,EAClB,IAAW,EAAiB,GAAO,EAAS;;AAQhD,SAJK,IAIE,EAAe;GACpB,GAAG;GACH;GACA;GACA;GACD,CAAC,GARO;GAST;CACJ,mBACE,SAAW;EACT,QAAQ,EAAE;EACV,0BAAU,IAAI,KAAK;EACnB,UAAU,EAAE;EACZ,sBAAsB;EACvB,EAAE;CACL,6BAA6B,MAC3B,SAAW;EACT,QAAQ,EAAE;EACV,0BAAU,IAAI,KAAK;EACnB,UAAU,EAAE;EACZ,sBAAsB;EACvB,EAAE;CACN,EAAE"}
@@ -5,7 +5,7 @@ declare const contextMenuVariants: (props?: ({
5
5
  size?: "default" | "compact" | null | undefined;
6
6
  layout?: "vertical" | null | undefined;
7
7
  position?: "none" | "top" | "bottom" | null | undefined;
8
- spacing?: "none" | "default" | null | undefined;
8
+ spacing?: "default" | "none" | null | undefined;
9
9
  alignment?: "none" | "left" | "right" | null | undefined;
10
10
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
11
  interface ContextMenuProps {
@@ -1,6 +1,6 @@
1
1
  import { type VariantProps } from "class-variance-authority";
2
2
  declare const helpLinkVariants: (props?: ({
3
- size?: "settings" | "default" | null | undefined;
3
+ size?: "default" | "settings" | null | undefined;
4
4
  linkColor?: "default" | "white" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface HelpLinkProps extends VariantProps<typeof helpLinkVariants> {
@@ -1,2 +1,2 @@
1
- require(`../_virtual/_rolldown/runtime.cjs`);var e=e=>{try{return new URL(e)}catch{return null}};function t(t,n){let r=typeof t==`string`?t:``,i=typeof n==`string`?n:``;if(!r||!i)return!1;let a=e(r),o=e(i);return!a||!o?r.replace(/\/+$/,``)===i.replace(/\/+$/,``):a.protocol===o.protocol&&a.host===o.host&&a.pathname.replace(/\/+$/,``)===o.pathname.replace(/\/+$/,``)}function n(e,t){return!e.availability||e.availability===`all`?!0:e.availability===t}function r(e){return e.trim().toLowerCase()}function i(e){return e.map((e,t)=>({entry:e,index:t})).sort((e,t)=>(t.entry.popularityRank??0)-(e.entry.popularityRank??0)||e.index-t.index).map(({entry:e})=>e)}function a(e,t){let n=r(t);return n?[e.name,e.description,e.id,...e.keywords??[]].join(` `).toLowerCase().includes(n):!0}function o(e,t,n){let i=r(n);return i?[e.type,`name`in e?e.name:void 0,`command`in e?e.command:void 0,`args`in e?e.args?.join(` `):void 0,`url`in e?e.url:void 0,t?.name,t?.description,t?.id,...t?.keywords??[]].filter(Boolean).join(` `).toLowerCase().includes(i):!0}function s(e,n){return n.find(n=>{let r=n.template;return r.kind===`stdio`?e.type===`stdio`&&e.name===r.serverName:r.kind===`shttp`?e.type===`shttp`&&t(e.url,r.url):r.kind===`sse`?e.type===`sse`&&t(e.url,r.url):!1})}exports.findCatalogEntryForServer=s,exports.getMarketplaceEntriesByPopularity=i,exports.installedServerMatchesQuery=o,exports.isMarketplaceEntryAvailable=n,exports.marketplaceEntryMatchesQuery=a;
1
+ require(`../_virtual/_rolldown/runtime.cjs`);var e=e=>{try{return new URL(e)}catch{return null}};function t(t,n){let r=typeof t==`string`?t:``,i=typeof n==`string`?n:``;if(!r||!i)return!1;let a=e(r),o=e(i);return!a||!o?r.replace(/\/+$/,``)===i.replace(/\/+$/,``):a.protocol===o.protocol&&a.host===o.host&&a.pathname.replace(/\/+$/,``)===o.pathname.replace(/\/+$/,``)}function n(e){return(e.connectionOptions.find(t=>t.id===e.defaultConnectionOptionId)??e.connectionOptions[0])?.transport}function r(e){let t=e.connectionOptions.find(e=>e.transport?.kind===`stdio`);return t?.transport?t.transport:n(e)}function i(e,t){return!e.runtimeAvailability||e.runtimeAvailability===`all`?!0:e.runtimeAvailability===t}function a(e){return e.trim().toLowerCase()}function o(e){return e.map((e,t)=>({entry:e,index:t})).sort((e,t)=>(t.entry.popularityRank??0)-(e.entry.popularityRank??0)||e.index-t.index).map(({entry:e})=>e)}function s(e,t){let n=a(t);return n?[e.name,e.description,e.id,...e.keywords??[]].join(` `).toLowerCase().includes(n):!0}function c(e,t,n){let r=a(n);return r?[e.type,`name`in e?e.name:void 0,`command`in e?e.command:void 0,`args`in e?e.args?.join(` `):void 0,`url`in e?e.url:void 0,t?.name,t?.description,t?.id,...t?.keywords??[]].filter(Boolean).join(` `).toLowerCase().includes(r):!0}function l(e,n){return n.find(n=>{for(let r of n.connectionOptions){let n=r.transport;if(n&&(n.kind===`stdio`&&e.type===`stdio`&&e.name===n.serverName||n.kind===`shttp`&&e.type===`shttp`&&t(e.url,n.url)||n.kind===`sse`&&e.type===`sse`&&t(e.url,n.url)))return!0}return!1})}exports.findCatalogEntryForServer=l,exports.getDefaultTemplate=n,exports.getInstallableTemplate=r,exports.getMarketplaceEntriesByPopularity=o,exports.installedServerMatchesQuery=c,exports.isMarketplaceEntryAvailable=i,exports.marketplaceEntryMatchesQuery=s;
2
2
  //# sourceMappingURL=mcp-marketplace-utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-marketplace-utils.cjs","names":[],"sources":["../../src/utils/mcp-marketplace-utils.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport type {\n McpCatalogEntry as MarketplaceEntry,\n MarketplaceTemplate,\n} from \"@openhands/extensions/mcps\";\n\nconst tryUrl = (raw: string): URL | null => {\n try {\n return new URL(raw);\n } catch {\n return null;\n }\n};\n\n/**\n * Loose URL match that ignores query strings, trailing slashes, and\n * default ports. We want clicking \"Linear\" to flag the entry as\n * installed even if the user pasted the URL with extra trailing slash\n * or a different port-equivalent variant.\n *\n * Defensive against runtime data that doesn't match the static type:\n * if either input is not a string (e.g. parsed from an older settings\n * blob), we fall through the URL parsing path and the safe trim\n * fallback below, never calling `.replace` on undefined.\n */\nexport function urlsMatch(a: unknown, b: unknown): boolean {\n const aStr = typeof a === \"string\" ? a : \"\";\n const bStr = typeof b === \"string\" ? b : \"\";\n if (!aStr || !bStr) return false;\n const left = tryUrl(aStr);\n const right = tryUrl(bStr);\n if (!left || !right) {\n return aStr.replace(/\\/+$/, \"\") === bStr.replace(/\\/+$/, \"\");\n }\n return (\n left.protocol === right.protocol &&\n left.host === right.host &&\n left.pathname.replace(/\\/+$/, \"\") === right.pathname.replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Decide whether a marketplace template is already represented by one\n * of the installed MCP servers. Used to render an \"Installed\" badge on\n * the marketplace tile. Returns the first matching server, or null.\n */\nexport function findInstalledMatch(\n template: MarketplaceTemplate,\n servers: MCPServerConfig[],\n): MCPServerConfig | null {\n if (template.kind === \"shttp\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"shttp\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n if (template.kind === \"sse\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"sse\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n // stdio: match on the registered server name.\n return (\n servers.find((s) => s.type === \"stdio\" && s.name === template.serverName) ??\n null\n );\n}\n\nexport function isMarketplaceEntryAvailable(\n entry: MarketplaceEntry,\n backendKind: \"local\" | \"cloud\",\n): boolean {\n if (!entry.availability || entry.availability === \"all\") return true;\n return entry.availability === backendKind;\n}\n\nfunction normalize(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/**\n * Case-insensitive substring match against the catalog entry's\n * user-visible identity (name, description, id, keywords). Empty\n * queries always match.\n */\nexport function getMarketplaceEntriesByPopularity(\n catalog: MarketplaceEntry[],\n): MarketplaceEntry[] {\n return catalog\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) => {\n const byPopularity =\n (b.entry.popularityRank ?? 0) - (a.entry.popularityRank ?? 0);\n return byPopularity || a.index - b.index;\n })\n .map(({ entry }) => entry);\n}\n\nexport function getMarketplaceEntryById(\n id: string,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => entry.id === id);\n}\n\nexport function marketplaceEntryMatchesQuery(\n entry: MarketplaceEntry,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n entry.name,\n entry.description,\n entry.id,\n ...(entry.keywords ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Search match for an installed (already-configured) server. We\n * search the server's own identifying fields and — if it's a catalog\n * entry — its catalog name/keywords too, so typing \"Slack\" matches\n * the installed Slack tile even though the persisted server is just\n * `{ type: \"stdio\", name: \"slack\", ... }`.\n */\nexport function installedServerMatchesQuery(\n server: MCPServerConfig,\n catalogEntry: MarketplaceEntry | undefined,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n server.type,\n \"name\" in server ? server.name : undefined,\n \"command\" in server ? server.command : undefined,\n \"args\" in server ? server.args?.join(\" \") : undefined,\n \"url\" in server ? server.url : undefined,\n catalogEntry?.name,\n catalogEntry?.description,\n catalogEntry?.id,\n ...(catalogEntry?.keywords ?? []),\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Look up the catalog entry that best matches an installed server.\n * Mirrors the lookup used in `installed-server-card.tsx` for\n * rendering the friendly icon.\n */\nexport function findCatalogEntryForServer(\n server: MCPServerConfig,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => {\n const tpl = entry.template;\n if (tpl.kind === \"stdio\")\n return server.type === \"stdio\" && server.name === tpl.serverName;\n // Reuse the same loose URL match as `findInstalledMatch` so a\n // server whose URL was normalized by the backend (trailing slash\n // stripped, query string dropped, etc.) still gets paired with\n // its catalog tile — otherwise the installed-servers list would\n // render the generic icon while the marketplace shows the\n // entry as installed, which is confusing.\n if (tpl.kind === \"shttp\")\n return server.type === \"shttp\" && urlsMatch(server.url, tpl.url);\n if (tpl.kind === \"sse\")\n return server.type === \"sse\" && urlsMatch(server.url, tpl.url);\n return false;\n });\n}\n"],"mappings":"6CAMA,IAAM,EAAU,GAA4B,CAC1C,GAAI,CACF,OAAO,IAAI,IAAI,EAAI,MACb,CACN,OAAO,OAeX,SAAgB,EAAU,EAAY,EAAqB,CACzD,IAAM,EAAO,OAAO,GAAM,SAAW,EAAI,GACnC,EAAO,OAAO,GAAM,SAAW,EAAI,GACzC,GAAI,CAAC,GAAQ,CAAC,EAAM,MAAO,GAC3B,IAAM,EAAO,EAAO,EAAK,CACnB,EAAQ,EAAO,EAAK,CAI1B,MAHI,CAAC,GAAQ,CAAC,EACL,EAAK,QAAQ,OAAQ,GAAG,GAAK,EAAK,QAAQ,OAAQ,GAAG,CAG5D,EAAK,WAAa,EAAM,UACxB,EAAK,OAAS,EAAM,MACpB,EAAK,SAAS,QAAQ,OAAQ,GAAG,GAAK,EAAM,SAAS,QAAQ,OAAQ,GAAG,CAwC5E,SAAgB,EACd,EACA,EACS,CAET,MADI,CAAC,EAAM,cAAgB,EAAM,eAAiB,MAAc,GACzD,EAAM,eAAiB,EAGhC,SAAS,EAAU,EAAuB,CACxC,OAAO,EAAM,MAAM,CAAC,aAAa,CAQnC,SAAgB,EACd,EACoB,CACpB,OAAO,EACJ,KAAK,EAAO,KAAW,CAAE,QAAO,QAAO,EAAE,CACzC,MAAM,EAAG,KAEL,EAAE,MAAM,gBAAkB,IAAM,EAAE,MAAM,gBAAkB,IACtC,EAAE,MAAQ,EAAE,MACnC,CACD,KAAK,CAAE,WAAY,EAAM,CAU9B,SAAgB,EACd,EACA,EACS,CACT,IAAM,EAAI,EAAU,EAAS,CAU7B,OATK,EACY,CACf,EAAM,KACN,EAAM,YACN,EAAM,GACN,GAAI,EAAM,UAAY,EAAE,CACzB,CACE,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,CATZ,GAmBjB,SAAgB,EACd,EACA,EACA,EACS,CACT,IAAM,EAAI,EAAU,EAAS,CAgB7B,OAfK,EACY,CACf,EAAO,KACP,SAAU,EAAS,EAAO,KAAO,IAAA,GACjC,YAAa,EAAS,EAAO,QAAU,IAAA,GACvC,SAAU,EAAS,EAAO,MAAM,KAAK,IAAI,CAAG,IAAA,GAC5C,QAAS,EAAS,EAAO,IAAM,IAAA,GAC/B,GAAc,KACd,GAAc,YACd,GAAc,GACd,GAAI,GAAc,UAAY,EAAE,CACjC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,CAfZ,GAuBjB,SAAgB,EACd,EACA,EAC8B,CAC9B,OAAO,EAAQ,KAAM,GAAU,CAC7B,IAAM,EAAM,EAAM,SAalB,OAZI,EAAI,OAAS,QACR,EAAO,OAAS,SAAW,EAAO,OAAS,EAAI,WAOpD,EAAI,OAAS,QACR,EAAO,OAAS,SAAW,EAAU,EAAO,IAAK,EAAI,IAAI,CAC9D,EAAI,OAAS,MACR,EAAO,OAAS,OAAS,EAAU,EAAO,IAAK,EAAI,IAAI,CACzD,IACP"}
1
+ {"version":3,"file":"mcp-marketplace-utils.cjs","names":[],"sources":["../../src/utils/mcp-marketplace-utils.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport type {\n IntegrationCatalogEntry as MarketplaceEntry,\n IntegrationTransport as MarketplaceTemplate,\n} from \"@openhands/extensions/integrations\";\n\nconst tryUrl = (raw: string): URL | null => {\n try {\n return new URL(raw);\n } catch {\n return null;\n }\n};\n\n/**\n * Loose URL match that ignores query strings, trailing slashes, and\n * default ports. We want clicking \"Linear\" to flag the entry as\n * installed even if the user pasted the URL with extra trailing slash\n * or a different port-equivalent variant.\n *\n * Defensive against runtime data that doesn't match the static type:\n * if either input is not a string (e.g. parsed from an older settings\n * blob), we fall through the URL parsing path and the safe trim\n * fallback below, never calling `.replace` on undefined.\n */\nexport function urlsMatch(a: unknown, b: unknown): boolean {\n const aStr = typeof a === \"string\" ? a : \"\";\n const bStr = typeof b === \"string\" ? b : \"\";\n if (!aStr || !bStr) return false;\n const left = tryUrl(aStr);\n const right = tryUrl(bStr);\n if (!left || !right) {\n return aStr.replace(/\\/+$/, \"\") === bStr.replace(/\\/+$/, \"\");\n }\n return (\n left.protocol === right.protocol &&\n left.host === right.host &&\n left.pathname.replace(/\\/+$/, \"\") === right.pathname.replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Get the default transport template from an integration catalog entry.\n * Integrations may have multiple connection options; we use the default\n * one (or the first if no default is specified). Only MCP-backed options\n * have a `transport` field.\n */\nexport function getDefaultTemplate(\n entry: MarketplaceEntry,\n): MarketplaceTemplate | undefined {\n const option =\n entry.connectionOptions.find(\n (o) => o.id === entry.defaultConnectionOptionId,\n ) ?? entry.connectionOptions[0];\n return option?.transport;\n}\n\n/**\n * Get the stdio (API key-based) transport template from an integration entry.\n * Many integrations have multiple connection options (e.g., OAuth + stdio).\n * Since OAuth isn't implemented in the UI yet, the install modal should use\n * this function to get the stdio-based option that can be configured with\n * API keys/tokens.\n *\n * Falls back to getDefaultTemplate if no stdio option exists.\n */\nexport function getInstallableTemplate(\n entry: MarketplaceEntry,\n): MarketplaceTemplate | undefined {\n // First, try to find a stdio option (API key-based, what we can actually install)\n const stdioOption = entry.connectionOptions.find(\n (o) => o.transport?.kind === \"stdio\",\n );\n if (stdioOption?.transport) return stdioOption.transport;\n\n // Fall back to the default template (could be shttp/sse with api_key)\n return getDefaultTemplate(entry);\n}\n\n/**\n * Decide whether a marketplace template is already represented by one\n * of the installed MCP servers. Used to render an \"Installed\" badge on\n * the marketplace tile. Returns the first matching server, or null.\n */\nexport function findInstalledMatch(\n template: MarketplaceTemplate,\n servers: MCPServerConfig[],\n): MCPServerConfig | null {\n if (template.kind === \"shttp\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"shttp\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n if (template.kind === \"sse\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"sse\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n // stdio: match on the registered server name.\n return (\n servers.find((s) => s.type === \"stdio\" && s.name === template.serverName) ??\n null\n );\n}\n\nexport function isMarketplaceEntryAvailable(\n entry: MarketplaceEntry,\n backendKind: \"local\" | \"cloud\",\n): boolean {\n if (!entry.runtimeAvailability || entry.runtimeAvailability === \"all\")\n return true;\n return entry.runtimeAvailability === backendKind;\n}\n\nfunction normalize(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/**\n * Case-insensitive substring match against the catalog entry's\n * user-visible identity (name, description, id, keywords). Empty\n * queries always match.\n */\nexport function getMarketplaceEntriesByPopularity(\n catalog: MarketplaceEntry[],\n): MarketplaceEntry[] {\n return catalog\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) => {\n const byPopularity =\n (b.entry.popularityRank ?? 0) - (a.entry.popularityRank ?? 0);\n return byPopularity || a.index - b.index;\n })\n .map(({ entry }) => entry);\n}\n\nexport function getMarketplaceEntryById(\n id: string,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => entry.id === id);\n}\n\nexport function marketplaceEntryMatchesQuery(\n entry: MarketplaceEntry,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n entry.name,\n entry.description,\n entry.id,\n ...(entry.keywords ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Search match for an installed (already-configured) server. We\n * search the server's own identifying fields and — if it's a catalog\n * entry — its catalog name/keywords too, so typing \"Slack\" matches\n * the installed Slack tile even though the persisted server is just\n * `{ type: \"stdio\", name: \"slack\", ... }`.\n */\nexport function installedServerMatchesQuery(\n server: MCPServerConfig,\n catalogEntry: MarketplaceEntry | undefined,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n server.type,\n \"name\" in server ? server.name : undefined,\n \"command\" in server ? server.command : undefined,\n \"args\" in server ? server.args?.join(\" \") : undefined,\n \"url\" in server ? server.url : undefined,\n catalogEntry?.name,\n catalogEntry?.description,\n catalogEntry?.id,\n ...(catalogEntry?.keywords ?? []),\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Look up the catalog entry that best matches an installed server.\n * Mirrors the lookup used in `installed-server-card.tsx` for\n * rendering the friendly icon.\n *\n * Since an entry may have multiple connection options (e.g., OAuth + stdio),\n * we check ALL templates in the entry's connectionOptions, not just the default.\n */\nexport function findCatalogEntryForServer(\n server: MCPServerConfig,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => {\n // Check all connection options, not just the default\n for (const option of entry.connectionOptions) {\n const tpl = option.transport;\n if (!tpl) continue;\n if (tpl.kind === \"stdio\") {\n if (server.type === \"stdio\" && server.name === tpl.serverName)\n return true;\n }\n // Reuse the same loose URL match as `findInstalledMatch` so a\n // server whose URL was normalized by the backend (trailing slash\n // stripped, query string dropped, etc.) still gets paired with\n // its catalog tile — otherwise the installed-servers list would\n // render the generic icon while the marketplace shows the\n // entry as installed, which is confusing.\n if (tpl.kind === \"shttp\") {\n if (server.type === \"shttp\" && urlsMatch(server.url, tpl.url))\n return true;\n }\n if (tpl.kind === \"sse\") {\n if (server.type === \"sse\" && urlsMatch(server.url, tpl.url))\n return true;\n }\n }\n return false;\n });\n}\n"],"mappings":"6CAMA,IAAM,EAAU,GAA4B,CAC1C,GAAI,CACF,OAAO,IAAI,IAAI,EAAI,MACb,CACN,OAAO,OAeX,SAAgB,EAAU,EAAY,EAAqB,CACzD,IAAM,EAAO,OAAO,GAAM,SAAW,EAAI,GACnC,EAAO,OAAO,GAAM,SAAW,EAAI,GACzC,GAAI,CAAC,GAAQ,CAAC,EAAM,MAAO,GAC3B,IAAM,EAAO,EAAO,EAAK,CACnB,EAAQ,EAAO,EAAK,CAI1B,MAHI,CAAC,GAAQ,CAAC,EACL,EAAK,QAAQ,OAAQ,GAAG,GAAK,EAAK,QAAQ,OAAQ,GAAG,CAG5D,EAAK,WAAa,EAAM,UACxB,EAAK,OAAS,EAAM,MACpB,EAAK,SAAS,QAAQ,OAAQ,GAAG,GAAK,EAAM,SAAS,QAAQ,OAAQ,GAAG,CAU5E,SAAgB,EACd,EACiC,CAKjC,OAHE,EAAM,kBAAkB,KACrB,GAAM,EAAE,KAAO,EAAM,0BACvB,EAAI,EAAM,kBAAkB,KAChB,UAYjB,SAAgB,EACd,EACiC,CAEjC,IAAM,EAAc,EAAM,kBAAkB,KACzC,GAAM,EAAE,WAAW,OAAS,QAC9B,CAID,OAHI,GAAa,UAAkB,EAAY,UAGxC,EAAmB,EAAM,CAuClC,SAAgB,EACd,EACA,EACS,CAGT,MAFI,CAAC,EAAM,qBAAuB,EAAM,sBAAwB,MACvD,GACF,EAAM,sBAAwB,EAGvC,SAAS,EAAU,EAAuB,CACxC,OAAO,EAAM,MAAM,CAAC,aAAa,CAQnC,SAAgB,EACd,EACoB,CACpB,OAAO,EACJ,KAAK,EAAO,KAAW,CAAE,QAAO,QAAO,EAAE,CACzC,MAAM,EAAG,KAEL,EAAE,MAAM,gBAAkB,IAAM,EAAE,MAAM,gBAAkB,IACtC,EAAE,MAAQ,EAAE,MACnC,CACD,KAAK,CAAE,WAAY,EAAM,CAU9B,SAAgB,EACd,EACA,EACS,CACT,IAAM,EAAI,EAAU,EAAS,CAU7B,OATK,EACY,CACf,EAAM,KACN,EAAM,YACN,EAAM,GACN,GAAI,EAAM,UAAY,EAAE,CACzB,CACE,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,CATZ,GAmBjB,SAAgB,EACd,EACA,EACA,EACS,CACT,IAAM,EAAI,EAAU,EAAS,CAgB7B,OAfK,EACY,CACf,EAAO,KACP,SAAU,EAAS,EAAO,KAAO,IAAA,GACjC,YAAa,EAAS,EAAO,QAAU,IAAA,GACvC,SAAU,EAAS,EAAO,MAAM,KAAK,IAAI,CAAG,IAAA,GAC5C,QAAS,EAAS,EAAO,IAAM,IAAA,GAC/B,GAAc,KACd,GAAc,YACd,GAAc,GACd,GAAI,GAAc,UAAY,EAAE,CACjC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,CAfZ,GA0BjB,SAAgB,EACd,EACA,EAC8B,CAC9B,OAAO,EAAQ,KAAM,GAAU,CAE7B,IAAK,IAAM,KAAU,EAAM,kBAAmB,CAC5C,IAAM,EAAM,EAAO,UACd,OACD,EAAI,OAAS,SACX,EAAO,OAAS,SAAW,EAAO,OAAS,EAAI,YASjD,EAAI,OAAS,SACX,EAAO,OAAS,SAAW,EAAU,EAAO,IAAK,EAAI,IAAI,EAG3D,EAAI,OAAS,OACX,EAAO,OAAS,OAAS,EAAU,EAAO,IAAK,EAAI,IAAI,EACzD,MAAO,GAGb,MAAO,IACP"}
@@ -1,5 +1,5 @@
1
1
  import { MCPServerConfig } from "#/types/mcp-server";
2
- import type { McpCatalogEntry as MarketplaceEntry, MarketplaceTemplate } from "@openhands/extensions/mcps";
2
+ import type { IntegrationCatalogEntry as MarketplaceEntry, IntegrationTransport as MarketplaceTemplate } from "@openhands/extensions/integrations";
3
3
  /**
4
4
  * Loose URL match that ignores query strings, trailing slashes, and
5
5
  * default ports. We want clicking "Linear" to flag the entry as
@@ -12,6 +12,23 @@ import type { McpCatalogEntry as MarketplaceEntry, MarketplaceTemplate } from "@
12
12
  * fallback below, never calling `.replace` on undefined.
13
13
  */
14
14
  export declare function urlsMatch(a: unknown, b: unknown): boolean;
15
+ /**
16
+ * Get the default transport template from an integration catalog entry.
17
+ * Integrations may have multiple connection options; we use the default
18
+ * one (or the first if no default is specified). Only MCP-backed options
19
+ * have a `transport` field.
20
+ */
21
+ export declare function getDefaultTemplate(entry: MarketplaceEntry): MarketplaceTemplate | undefined;
22
+ /**
23
+ * Get the stdio (API key-based) transport template from an integration entry.
24
+ * Many integrations have multiple connection options (e.g., OAuth + stdio).
25
+ * Since OAuth isn't implemented in the UI yet, the install modal should use
26
+ * this function to get the stdio-based option that can be configured with
27
+ * API keys/tokens.
28
+ *
29
+ * Falls back to getDefaultTemplate if no stdio option exists.
30
+ */
31
+ export declare function getInstallableTemplate(entry: MarketplaceEntry): MarketplaceTemplate | undefined;
15
32
  /**
16
33
  * Decide whether a marketplace template is already represented by one
17
34
  * of the installed MCP servers. Used to render an "Installed" badge on
@@ -39,5 +56,8 @@ export declare function installedServerMatchesQuery(server: MCPServerConfig, cat
39
56
  * Look up the catalog entry that best matches an installed server.
40
57
  * Mirrors the lookup used in `installed-server-card.tsx` for
41
58
  * rendering the friendly icon.
59
+ *
60
+ * Since an entry may have multiple connection options (e.g., OAuth + stdio),
61
+ * we check ALL templates in the entry's connectionOptions, not just the default.
42
62
  */
43
63
  export declare function findCatalogEntryForServer(server: MCPServerConfig, catalog: MarketplaceEntry[]): MarketplaceEntry | undefined;
@@ -12,20 +12,27 @@ function t(t, n) {
12
12
  let a = e(r), o = e(i);
13
13
  return !a || !o ? r.replace(/\/+$/, "") === i.replace(/\/+$/, "") : a.protocol === o.protocol && a.host === o.host && a.pathname.replace(/\/+$/, "") === o.pathname.replace(/\/+$/, "");
14
14
  }
15
- function n(e, t) {
16
- return !e.availability || e.availability === "all" ? !0 : e.availability === t;
15
+ function n(e) {
16
+ return (e.connectionOptions.find((t) => t.id === e.defaultConnectionOptionId) ?? e.connectionOptions[0])?.transport;
17
17
  }
18
18
  function r(e) {
19
+ let t = e.connectionOptions.find((e) => e.transport?.kind === "stdio");
20
+ return t?.transport ? t.transport : n(e);
21
+ }
22
+ function i(e, t) {
23
+ return !e.runtimeAvailability || e.runtimeAvailability === "all" ? !0 : e.runtimeAvailability === t;
24
+ }
25
+ function a(e) {
19
26
  return e.trim().toLowerCase();
20
27
  }
21
- function i(e) {
28
+ function o(e) {
22
29
  return e.map((e, t) => ({
23
30
  entry: e,
24
31
  index: t
25
32
  })).sort((e, t) => (t.entry.popularityRank ?? 0) - (e.entry.popularityRank ?? 0) || e.index - t.index).map(({ entry: e }) => e);
26
33
  }
27
- function a(e, t) {
28
- let n = r(t);
34
+ function s(e, t) {
35
+ let n = a(t);
29
36
  return n ? [
30
37
  e.name,
31
38
  e.description,
@@ -33,9 +40,9 @@ function a(e, t) {
33
40
  ...e.keywords ?? []
34
41
  ].join(" ").toLowerCase().includes(n) : !0;
35
42
  }
36
- function o(e, t, n) {
37
- let i = r(n);
38
- return i ? [
43
+ function c(e, t, n) {
44
+ let r = a(n);
45
+ return r ? [
39
46
  e.type,
40
47
  "name" in e ? e.name : void 0,
41
48
  "command" in e ? e.command : void 0,
@@ -45,15 +52,18 @@ function o(e, t, n) {
45
52
  t?.description,
46
53
  t?.id,
47
54
  ...t?.keywords ?? []
48
- ].filter(Boolean).join(" ").toLowerCase().includes(i) : !0;
55
+ ].filter(Boolean).join(" ").toLowerCase().includes(r) : !0;
49
56
  }
50
- function s(e, n) {
57
+ function l(e, n) {
51
58
  return n.find((n) => {
52
- let r = n.template;
53
- return r.kind === "stdio" ? e.type === "stdio" && e.name === r.serverName : r.kind === "shttp" ? e.type === "shttp" && t(e.url, r.url) : r.kind === "sse" ? e.type === "sse" && t(e.url, r.url) : !1;
59
+ for (let r of n.connectionOptions) {
60
+ let n = r.transport;
61
+ if (n && (n.kind === "stdio" && e.type === "stdio" && e.name === n.serverName || n.kind === "shttp" && e.type === "shttp" && t(e.url, n.url) || n.kind === "sse" && e.type === "sse" && t(e.url, n.url))) return !0;
62
+ }
63
+ return !1;
54
64
  });
55
65
  }
56
66
  //#endregion
57
- export { s as findCatalogEntryForServer, i as getMarketplaceEntriesByPopularity, o as installedServerMatchesQuery, n as isMarketplaceEntryAvailable, a as marketplaceEntryMatchesQuery };
67
+ export { l as findCatalogEntryForServer, n as getDefaultTemplate, r as getInstallableTemplate, o as getMarketplaceEntriesByPopularity, c as installedServerMatchesQuery, i as isMarketplaceEntryAvailable, s as marketplaceEntryMatchesQuery };
58
68
 
59
69
  //# sourceMappingURL=mcp-marketplace-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-marketplace-utils.js","names":[],"sources":["../../src/utils/mcp-marketplace-utils.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport type {\n McpCatalogEntry as MarketplaceEntry,\n MarketplaceTemplate,\n} from \"@openhands/extensions/mcps\";\n\nconst tryUrl = (raw: string): URL | null => {\n try {\n return new URL(raw);\n } catch {\n return null;\n }\n};\n\n/**\n * Loose URL match that ignores query strings, trailing slashes, and\n * default ports. We want clicking \"Linear\" to flag the entry as\n * installed even if the user pasted the URL with extra trailing slash\n * or a different port-equivalent variant.\n *\n * Defensive against runtime data that doesn't match the static type:\n * if either input is not a string (e.g. parsed from an older settings\n * blob), we fall through the URL parsing path and the safe trim\n * fallback below, never calling `.replace` on undefined.\n */\nexport function urlsMatch(a: unknown, b: unknown): boolean {\n const aStr = typeof a === \"string\" ? a : \"\";\n const bStr = typeof b === \"string\" ? b : \"\";\n if (!aStr || !bStr) return false;\n const left = tryUrl(aStr);\n const right = tryUrl(bStr);\n if (!left || !right) {\n return aStr.replace(/\\/+$/, \"\") === bStr.replace(/\\/+$/, \"\");\n }\n return (\n left.protocol === right.protocol &&\n left.host === right.host &&\n left.pathname.replace(/\\/+$/, \"\") === right.pathname.replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Decide whether a marketplace template is already represented by one\n * of the installed MCP servers. Used to render an \"Installed\" badge on\n * the marketplace tile. Returns the first matching server, or null.\n */\nexport function findInstalledMatch(\n template: MarketplaceTemplate,\n servers: MCPServerConfig[],\n): MCPServerConfig | null {\n if (template.kind === \"shttp\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"shttp\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n if (template.kind === \"sse\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"sse\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n // stdio: match on the registered server name.\n return (\n servers.find((s) => s.type === \"stdio\" && s.name === template.serverName) ??\n null\n );\n}\n\nexport function isMarketplaceEntryAvailable(\n entry: MarketplaceEntry,\n backendKind: \"local\" | \"cloud\",\n): boolean {\n if (!entry.availability || entry.availability === \"all\") return true;\n return entry.availability === backendKind;\n}\n\nfunction normalize(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/**\n * Case-insensitive substring match against the catalog entry's\n * user-visible identity (name, description, id, keywords). Empty\n * queries always match.\n */\nexport function getMarketplaceEntriesByPopularity(\n catalog: MarketplaceEntry[],\n): MarketplaceEntry[] {\n return catalog\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) => {\n const byPopularity =\n (b.entry.popularityRank ?? 0) - (a.entry.popularityRank ?? 0);\n return byPopularity || a.index - b.index;\n })\n .map(({ entry }) => entry);\n}\n\nexport function getMarketplaceEntryById(\n id: string,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => entry.id === id);\n}\n\nexport function marketplaceEntryMatchesQuery(\n entry: MarketplaceEntry,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n entry.name,\n entry.description,\n entry.id,\n ...(entry.keywords ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Search match for an installed (already-configured) server. We\n * search the server's own identifying fields and — if it's a catalog\n * entry — its catalog name/keywords too, so typing \"Slack\" matches\n * the installed Slack tile even though the persisted server is just\n * `{ type: \"stdio\", name: \"slack\", ... }`.\n */\nexport function installedServerMatchesQuery(\n server: MCPServerConfig,\n catalogEntry: MarketplaceEntry | undefined,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n server.type,\n \"name\" in server ? server.name : undefined,\n \"command\" in server ? server.command : undefined,\n \"args\" in server ? server.args?.join(\" \") : undefined,\n \"url\" in server ? server.url : undefined,\n catalogEntry?.name,\n catalogEntry?.description,\n catalogEntry?.id,\n ...(catalogEntry?.keywords ?? []),\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Look up the catalog entry that best matches an installed server.\n * Mirrors the lookup used in `installed-server-card.tsx` for\n * rendering the friendly icon.\n */\nexport function findCatalogEntryForServer(\n server: MCPServerConfig,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => {\n const tpl = entry.template;\n if (tpl.kind === \"stdio\")\n return server.type === \"stdio\" && server.name === tpl.serverName;\n // Reuse the same loose URL match as `findInstalledMatch` so a\n // server whose URL was normalized by the backend (trailing slash\n // stripped, query string dropped, etc.) still gets paired with\n // its catalog tile — otherwise the installed-servers list would\n // render the generic icon while the marketplace shows the\n // entry as installed, which is confusing.\n if (tpl.kind === \"shttp\")\n return server.type === \"shttp\" && urlsMatch(server.url, tpl.url);\n if (tpl.kind === \"sse\")\n return server.type === \"sse\" && urlsMatch(server.url, tpl.url);\n return false;\n });\n}\n"],"mappings":";AAMA,IAAM,KAAU,MAA4B;AAC1C,KAAI;AACF,SAAO,IAAI,IAAI,EAAI;SACb;AACN,SAAO;;;AAeX,SAAgB,EAAU,GAAY,GAAqB;CACzD,IAAM,IAAO,OAAO,KAAM,WAAW,IAAI,IACnC,IAAO,OAAO,KAAM,WAAW,IAAI;AACzC,KAAI,CAAC,KAAQ,CAAC,EAAM,QAAO;CAC3B,IAAM,IAAO,EAAO,EAAK,EACnB,IAAQ,EAAO,EAAK;AAI1B,QAHI,CAAC,KAAQ,CAAC,IACL,EAAK,QAAQ,QAAQ,GAAG,KAAK,EAAK,QAAQ,QAAQ,GAAG,GAG5D,EAAK,aAAa,EAAM,YACxB,EAAK,SAAS,EAAM,QACpB,EAAK,SAAS,QAAQ,QAAQ,GAAG,KAAK,EAAM,SAAS,QAAQ,QAAQ,GAAG;;AAwC5E,SAAgB,EACd,GACA,GACS;AAET,QADI,CAAC,EAAM,gBAAgB,EAAM,iBAAiB,QAAc,KACzD,EAAM,iBAAiB;;AAGhC,SAAS,EAAU,GAAuB;AACxC,QAAO,EAAM,MAAM,CAAC,aAAa;;AAQnC,SAAgB,EACd,GACoB;AACpB,QAAO,EACJ,KAAK,GAAO,OAAW;EAAE;EAAO;EAAO,EAAE,CACzC,MAAM,GAAG,OAEL,EAAE,MAAM,kBAAkB,MAAM,EAAE,MAAM,kBAAkB,MACtC,EAAE,QAAQ,EAAE,MACnC,CACD,KAAK,EAAE,eAAY,EAAM;;AAU9B,SAAgB,EACd,GACA,GACS;CACT,IAAM,IAAI,EAAU,EAAS;AAU7B,QATK,IACY;EACf,EAAM;EACN,EAAM;EACN,EAAM;EACN,GAAI,EAAM,YAAY,EAAE;EACzB,CACE,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,GATZ;;AAmBjB,SAAgB,EACd,GACA,GACA,GACS;CACT,IAAM,IAAI,EAAU,EAAS;AAgB7B,QAfK,IACY;EACf,EAAO;EACP,UAAU,IAAS,EAAO,OAAO,KAAA;EACjC,aAAa,IAAS,EAAO,UAAU,KAAA;EACvC,UAAU,IAAS,EAAO,MAAM,KAAK,IAAI,GAAG,KAAA;EAC5C,SAAS,IAAS,EAAO,MAAM,KAAA;EAC/B,GAAc;EACd,GAAc;EACd,GAAc;EACd,GAAI,GAAc,YAAY,EAAE;EACjC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,GAfZ;;AAuBjB,SAAgB,EACd,GACA,GAC8B;AAC9B,QAAO,EAAQ,MAAM,MAAU;EAC7B,IAAM,IAAM,EAAM;AAalB,SAZI,EAAI,SAAS,UACR,EAAO,SAAS,WAAW,EAAO,SAAS,EAAI,aAOpD,EAAI,SAAS,UACR,EAAO,SAAS,WAAW,EAAU,EAAO,KAAK,EAAI,IAAI,GAC9D,EAAI,SAAS,QACR,EAAO,SAAS,SAAS,EAAU,EAAO,KAAK,EAAI,IAAI,GACzD;GACP"}
1
+ {"version":3,"file":"mcp-marketplace-utils.js","names":[],"sources":["../../src/utils/mcp-marketplace-utils.ts"],"sourcesContent":["import { MCPServerConfig } from \"#/types/mcp-server\";\nimport type {\n IntegrationCatalogEntry as MarketplaceEntry,\n IntegrationTransport as MarketplaceTemplate,\n} from \"@openhands/extensions/integrations\";\n\nconst tryUrl = (raw: string): URL | null => {\n try {\n return new URL(raw);\n } catch {\n return null;\n }\n};\n\n/**\n * Loose URL match that ignores query strings, trailing slashes, and\n * default ports. We want clicking \"Linear\" to flag the entry as\n * installed even if the user pasted the URL with extra trailing slash\n * or a different port-equivalent variant.\n *\n * Defensive against runtime data that doesn't match the static type:\n * if either input is not a string (e.g. parsed from an older settings\n * blob), we fall through the URL parsing path and the safe trim\n * fallback below, never calling `.replace` on undefined.\n */\nexport function urlsMatch(a: unknown, b: unknown): boolean {\n const aStr = typeof a === \"string\" ? a : \"\";\n const bStr = typeof b === \"string\" ? b : \"\";\n if (!aStr || !bStr) return false;\n const left = tryUrl(aStr);\n const right = tryUrl(bStr);\n if (!left || !right) {\n return aStr.replace(/\\/+$/, \"\") === bStr.replace(/\\/+$/, \"\");\n }\n return (\n left.protocol === right.protocol &&\n left.host === right.host &&\n left.pathname.replace(/\\/+$/, \"\") === right.pathname.replace(/\\/+$/, \"\")\n );\n}\n\n/**\n * Get the default transport template from an integration catalog entry.\n * Integrations may have multiple connection options; we use the default\n * one (or the first if no default is specified). Only MCP-backed options\n * have a `transport` field.\n */\nexport function getDefaultTemplate(\n entry: MarketplaceEntry,\n): MarketplaceTemplate | undefined {\n const option =\n entry.connectionOptions.find(\n (o) => o.id === entry.defaultConnectionOptionId,\n ) ?? entry.connectionOptions[0];\n return option?.transport;\n}\n\n/**\n * Get the stdio (API key-based) transport template from an integration entry.\n * Many integrations have multiple connection options (e.g., OAuth + stdio).\n * Since OAuth isn't implemented in the UI yet, the install modal should use\n * this function to get the stdio-based option that can be configured with\n * API keys/tokens.\n *\n * Falls back to getDefaultTemplate if no stdio option exists.\n */\nexport function getInstallableTemplate(\n entry: MarketplaceEntry,\n): MarketplaceTemplate | undefined {\n // First, try to find a stdio option (API key-based, what we can actually install)\n const stdioOption = entry.connectionOptions.find(\n (o) => o.transport?.kind === \"stdio\",\n );\n if (stdioOption?.transport) return stdioOption.transport;\n\n // Fall back to the default template (could be shttp/sse with api_key)\n return getDefaultTemplate(entry);\n}\n\n/**\n * Decide whether a marketplace template is already represented by one\n * of the installed MCP servers. Used to render an \"Installed\" badge on\n * the marketplace tile. Returns the first matching server, or null.\n */\nexport function findInstalledMatch(\n template: MarketplaceTemplate,\n servers: MCPServerConfig[],\n): MCPServerConfig | null {\n if (template.kind === \"shttp\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"shttp\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n if (template.kind === \"sse\") {\n const tplUrl = template.url;\n if (!tplUrl) return null;\n return (\n servers.find(\n (s) => s.type === \"sse\" && !!s.url && urlsMatch(s.url, tplUrl),\n ) ?? null\n );\n }\n\n // stdio: match on the registered server name.\n return (\n servers.find((s) => s.type === \"stdio\" && s.name === template.serverName) ??\n null\n );\n}\n\nexport function isMarketplaceEntryAvailable(\n entry: MarketplaceEntry,\n backendKind: \"local\" | \"cloud\",\n): boolean {\n if (!entry.runtimeAvailability || entry.runtimeAvailability === \"all\")\n return true;\n return entry.runtimeAvailability === backendKind;\n}\n\nfunction normalize(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/**\n * Case-insensitive substring match against the catalog entry's\n * user-visible identity (name, description, id, keywords). Empty\n * queries always match.\n */\nexport function getMarketplaceEntriesByPopularity(\n catalog: MarketplaceEntry[],\n): MarketplaceEntry[] {\n return catalog\n .map((entry, index) => ({ entry, index }))\n .sort((a, b) => {\n const byPopularity =\n (b.entry.popularityRank ?? 0) - (a.entry.popularityRank ?? 0);\n return byPopularity || a.index - b.index;\n })\n .map(({ entry }) => entry);\n}\n\nexport function getMarketplaceEntryById(\n id: string,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => entry.id === id);\n}\n\nexport function marketplaceEntryMatchesQuery(\n entry: MarketplaceEntry,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n entry.name,\n entry.description,\n entry.id,\n ...(entry.keywords ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Search match for an installed (already-configured) server. We\n * search the server's own identifying fields and — if it's a catalog\n * entry — its catalog name/keywords too, so typing \"Slack\" matches\n * the installed Slack tile even though the persisted server is just\n * `{ type: \"stdio\", name: \"slack\", ... }`.\n */\nexport function installedServerMatchesQuery(\n server: MCPServerConfig,\n catalogEntry: MarketplaceEntry | undefined,\n rawQuery: string,\n): boolean {\n const q = normalize(rawQuery);\n if (!q) return true;\n const haystack = [\n server.type,\n \"name\" in server ? server.name : undefined,\n \"command\" in server ? server.command : undefined,\n \"args\" in server ? server.args?.join(\" \") : undefined,\n \"url\" in server ? server.url : undefined,\n catalogEntry?.name,\n catalogEntry?.description,\n catalogEntry?.id,\n ...(catalogEntry?.keywords ?? []),\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(q);\n}\n\n/**\n * Look up the catalog entry that best matches an installed server.\n * Mirrors the lookup used in `installed-server-card.tsx` for\n * rendering the friendly icon.\n *\n * Since an entry may have multiple connection options (e.g., OAuth + stdio),\n * we check ALL templates in the entry's connectionOptions, not just the default.\n */\nexport function findCatalogEntryForServer(\n server: MCPServerConfig,\n catalog: MarketplaceEntry[],\n): MarketplaceEntry | undefined {\n return catalog.find((entry) => {\n // Check all connection options, not just the default\n for (const option of entry.connectionOptions) {\n const tpl = option.transport;\n if (!tpl) continue;\n if (tpl.kind === \"stdio\") {\n if (server.type === \"stdio\" && server.name === tpl.serverName)\n return true;\n }\n // Reuse the same loose URL match as `findInstalledMatch` so a\n // server whose URL was normalized by the backend (trailing slash\n // stripped, query string dropped, etc.) still gets paired with\n // its catalog tile — otherwise the installed-servers list would\n // render the generic icon while the marketplace shows the\n // entry as installed, which is confusing.\n if (tpl.kind === \"shttp\") {\n if (server.type === \"shttp\" && urlsMatch(server.url, tpl.url))\n return true;\n }\n if (tpl.kind === \"sse\") {\n if (server.type === \"sse\" && urlsMatch(server.url, tpl.url))\n return true;\n }\n }\n return false;\n });\n}\n"],"mappings":";AAMA,IAAM,KAAU,MAA4B;AAC1C,KAAI;AACF,SAAO,IAAI,IAAI,EAAI;SACb;AACN,SAAO;;;AAeX,SAAgB,EAAU,GAAY,GAAqB;CACzD,IAAM,IAAO,OAAO,KAAM,WAAW,IAAI,IACnC,IAAO,OAAO,KAAM,WAAW,IAAI;AACzC,KAAI,CAAC,KAAQ,CAAC,EAAM,QAAO;CAC3B,IAAM,IAAO,EAAO,EAAK,EACnB,IAAQ,EAAO,EAAK;AAI1B,QAHI,CAAC,KAAQ,CAAC,IACL,EAAK,QAAQ,QAAQ,GAAG,KAAK,EAAK,QAAQ,QAAQ,GAAG,GAG5D,EAAK,aAAa,EAAM,YACxB,EAAK,SAAS,EAAM,QACpB,EAAK,SAAS,QAAQ,QAAQ,GAAG,KAAK,EAAM,SAAS,QAAQ,QAAQ,GAAG;;AAU5E,SAAgB,EACd,GACiC;AAKjC,SAHE,EAAM,kBAAkB,MACrB,MAAM,EAAE,OAAO,EAAM,0BACvB,IAAI,EAAM,kBAAkB,KAChB;;AAYjB,SAAgB,EACd,GACiC;CAEjC,IAAM,IAAc,EAAM,kBAAkB,MACzC,MAAM,EAAE,WAAW,SAAS,QAC9B;AAID,QAHI,GAAa,YAAkB,EAAY,YAGxC,EAAmB,EAAM;;AAuClC,SAAgB,EACd,GACA,GACS;AAGT,QAFI,CAAC,EAAM,uBAAuB,EAAM,wBAAwB,QACvD,KACF,EAAM,wBAAwB;;AAGvC,SAAS,EAAU,GAAuB;AACxC,QAAO,EAAM,MAAM,CAAC,aAAa;;AAQnC,SAAgB,EACd,GACoB;AACpB,QAAO,EACJ,KAAK,GAAO,OAAW;EAAE;EAAO;EAAO,EAAE,CACzC,MAAM,GAAG,OAEL,EAAE,MAAM,kBAAkB,MAAM,EAAE,MAAM,kBAAkB,MACtC,EAAE,QAAQ,EAAE,MACnC,CACD,KAAK,EAAE,eAAY,EAAM;;AAU9B,SAAgB,EACd,GACA,GACS;CACT,IAAM,IAAI,EAAU,EAAS;AAU7B,QATK,IACY;EACf,EAAM;EACN,EAAM;EACN,EAAM;EACN,GAAI,EAAM,YAAY,EAAE;EACzB,CACE,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,GATZ;;AAmBjB,SAAgB,EACd,GACA,GACA,GACS;CACT,IAAM,IAAI,EAAU,EAAS;AAgB7B,QAfK,IACY;EACf,EAAO;EACP,UAAU,IAAS,EAAO,OAAO,KAAA;EACjC,aAAa,IAAS,EAAO,UAAU,KAAA;EACvC,UAAU,IAAS,EAAO,MAAM,KAAK,IAAI,GAAG,KAAA;EAC5C,SAAS,IAAS,EAAO,MAAM,KAAA;EAC/B,GAAc;EACd,GAAc;EACd,GAAc;EACd,GAAI,GAAc,YAAY,EAAE;EACjC,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACT,aACI,CAAS,SAAS,EAAE,GAfZ;;AA0BjB,SAAgB,EACd,GACA,GAC8B;AAC9B,QAAO,EAAQ,MAAM,MAAU;AAE7B,OAAK,IAAM,KAAU,EAAM,mBAAmB;GAC5C,IAAM,IAAM,EAAO;AACd,aACD,EAAI,SAAS,WACX,EAAO,SAAS,WAAW,EAAO,SAAS,EAAI,cASjD,EAAI,SAAS,WACX,EAAO,SAAS,WAAW,EAAU,EAAO,KAAK,EAAI,IAAI,IAG3D,EAAI,SAAS,SACX,EAAO,SAAS,SAAS,EAAU,EAAO,KAAK,EAAI,IAAI,EACzD,QAAO;;AAGb,SAAO;GACP"}
@@ -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/agent`` precedes ``/settings`` because it is the ACP\n // landing page and is always available (no feature flag hides it).\n // When ``hide_llm_settings`` is on, the user is steered there rather\n // than to ``/settings/app`` (an unrelated section that used to win the\n // fallback). For OpenHands-agent users this is also a sensible landing\n // the Agent page is the single place to switch kinds.\n const fallbackOrder = [\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/agent\", hidden: false },\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"}
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/agent`` always wins: it is the single place to switch\n // agent kinds (OpenHands / ACP) and the only sub-page that is always\n // available regardless of feature flags. Landing here keeps the\n // routing simple ACP users no longer have to bounce through\n // ``/settings/llm`` (which is disabled for them), and OpenHands users\n // are one nav-click away from the LLM page.\n const fallbackOrder = [\n { path: \"/settings/agent\", 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"}
@@ -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/agent`` precedes ``/settings`` because it is the ACP\n // landing page and is always available (no feature flag hides it).\n // When ``hide_llm_settings`` is on, the user is steered there rather\n // than to ``/settings/app`` (an unrelated section that used to win the\n // fallback). For OpenHands-agent users this is also a sensible landing\n // the Agent page is the single place to switch kinds.\n const fallbackOrder = [\n { path: \"/settings/llm\", hidden: !!featureFlags?.hide_llm_settings },\n { path: \"/settings/agent\", hidden: false },\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"}
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/agent`` always wins: it is the single place to switch\n // agent kinds (OpenHands / ACP) and the only sub-page that is always\n // available regardless of feature flags. Landing here keeps the\n // routing simple ACP users no longer have to bounce through\n // ``/settings/llm`` (which is disabled for them), and OpenHands users\n // are one nav-click away from the LLM page.\n const fallbackOrder = [\n { path: \"/settings/agent\", 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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/agent-canvas",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.9",
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,8 +23,8 @@
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": "git+https://github.com/OpenHands/extensions.git#b8c1869ec9dea4467bb27d5754dc695d14e27889",
27
- "@openhands/typescript-client": "1.23.3",
26
+ "@openhands/extensions": "git+https://github.com/OpenHands/extensions.git#e14f740c59b4bfd7369d4bb6aea5eeb33dd05909",
27
+ "@openhands/typescript-client": "1.24.3",
28
28
  "@react-router/node": "7.14.2",
29
29
  "@react-router/serve": "7.14.2",
30
30
  "@tailwindcss/vite": "4.2.4",
@@ -80,6 +80,7 @@
80
80
  "test": "npm run make-i18n && vitest run",
81
81
  "test:e2e": "playwright test --pass-with-no-tests",
82
82
  "test:e2e:live": "node --env-file-if-exists=.env tests/e2e/live/scripts/run-live-e2e.mjs",
83
+ "test:e2e:mock-llm": "playwright test --config=playwright.mock-llm.config.ts",
83
84
  "test:e2e:snapshots": "playwright test tests/e2e/snapshots --project=chromium --retries=0",
84
85
  "test:e2e:snapshots:update": "playwright test tests/e2e/snapshots --project=chromium --update-snapshots",
85
86
  "test:coverage": "npm run make-i18n && vitest run --coverage",
@@ -173,7 +174,8 @@
173
174
  "bin",
174
175
  "build",
175
176
  "config",
176
- "scripts"
177
+ "scripts",
178
+ "tools"
177
179
  ],
178
180
  "exports": {
179
181
  ".": {
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * Usage:
21
21
  * node scripts/check-sdk-version-sync.mjs
22
- * EXPECTED_SDK_VERSION=1.23.1 node scripts/check-sdk-version-sync.mjs
22
+ * EXPECTED_SDK_VERSION=1.24.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:
@@ -79,7 +79,7 @@ Triggering from other repos:
79
79
  -H "Authorization: token \$GITHUB_TOKEN" \\
80
80
  -H "Accept: application/vnd.github.v3+json" \\
81
81
  https://api.github.com/repos/OpenHands/agent-canvas/dispatches \\
82
- -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.23.1"}}'
82
+ -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.24.0"}}'
83
83
  `);
84
84
  process.exit(0);
85
85
  }
@@ -268,9 +268,9 @@ async function fetchPyPIDependencies(packageName, version) {
268
268
  * Parse PyPI requires_dist array and extract SDK package versions
269
269
  *
270
270
  * PyPI returns dependencies in PEP 508 format like:
271
- * "openhands-sdk>=1.23.1,<2.0.0"
272
- * "openhands-tools==1.23.1"
273
- * "openhands-workspace (>=1.23.1)"
271
+ * "openhands-sdk>=1.24.0,<2.0.0"
272
+ * "openhands-tools==1.24.0"
273
+ * "openhands-workspace (>=1.24.0)"
274
274
  */
275
275
  function parseSdkVersionsFromRequiresDist(requiresDist) {
276
276
  const versions = {};
@@ -284,7 +284,7 @@ function parseSdkVersionsFromRequiresDist(requiresDist) {
284
284
  }
285
285
 
286
286
  // Extract the version number - look for patterns like:
287
- // ">=1.23.1", "==1.23.1", "(>=1.23.1)", "~=1.23.1"
287
+ // ">=1.24.0", "==1.24.0", "(>=1.24.0)", "~=1.24.0"
288
288
  // After the package name and before any comma or closing paren
289
289
  const versionPattern = /[><=~!]+\s*([0-9]+(?:\.[0-9]+)*)/;
290
290
  const match = dep.match(versionPattern);
@@ -210,6 +210,36 @@ function tryPort(port, host = "127.0.0.1") {
210
210
  });
211
211
  }
212
212
 
213
+ /**
214
+ * Assert that all listed ports are available, throwing a descriptive error if
215
+ * any are already in use.
216
+ *
217
+ * Intended as a pre-flight check before spawning services so that a concurrent
218
+ * agent-canvas instance is detected immediately rather than silently starting
219
+ * on a different port.
220
+ *
221
+ * @param {Array<{name: string, port: number}>} portConfigs - Named port list
222
+ * @param {string} [host]
223
+ */
224
+ export async function assertPortsFree(portConfigs, host = "127.0.0.1") {
225
+ const results = await Promise.all(
226
+ portConfigs.map(async ({ name, port }) => ({
227
+ name,
228
+ port,
229
+ free: await tryPort(port, host),
230
+ })),
231
+ );
232
+ const busy = results.filter(({ free }) => !free);
233
+ if (busy.length === 0) return;
234
+
235
+ const lines = busy.map(({ name, port }) => ` • ${name}: port ${port}`).join("\n");
236
+ throw new Error(
237
+ `Cannot start: the following ports are already in use:\n\n${lines}\n\n` +
238
+ `Another agent-canvas instance may already be running.\n` +
239
+ `Stop it first, or override the port via environment variables (e.g. PORT=<other>).`,
240
+ );
241
+ }
242
+
213
243
  /**
214
244
  * Find multiple free ports at once, each preferring its specified default.
215
245
  *
@@ -337,7 +367,7 @@ export function validateFrontendDependencies(
337
367
  * edits are picked up without a manual reinstall. The agent-server itself
338
368
  * is rebuilt from local source on each invocation (--reinstall).
339
369
  * - OH_AGENT_SERVER_GIT_REF: Git commit SHA or branch name
340
- * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.23.1")
370
+ * - OH_AGENT_SERVER_VERSION: Specific PyPI version (e.g., "1.24.0")
341
371
  *
342
372
  * If none are set, defaults to the released version specified by
343
373
  * DEFAULT_AGENT_SERVER_VERSION. Set OH_AGENT_SERVER_GIT_REF to use a
@@ -491,26 +521,14 @@ export async function buildSafeDevConfigAsync(
491
521
  preferredBackendPort + 1,
492
522
  );
493
523
 
494
- // Find available ports, preferring the defaults
495
- const ports = await findFreePorts([
496
- { name: "backend", preferred: preferredBackendPort },
497
- { name: "vscode", preferred: preferredVscodePort },
524
+ // Fail fast if any required port is already in use.
525
+ await assertPortsFree([
526
+ { name: "agent-server", port: preferredBackendPort },
527
+ { name: "vscode", port: preferredVscodePort },
498
528
  ]);
499
529
 
500
- // Log if we're using non-default ports
501
- if (ports.backend !== preferredBackendPort) {
502
- console.log(
503
- ` ℹ Port ${preferredBackendPort} busy, using ${ports.backend} for agent-server`,
504
- );
505
- }
506
- if (ports.vscode !== preferredVscodePort) {
507
- console.log(
508
- ` ℹ Port ${preferredVscodePort} busy, using ${ports.vscode} for vscode`,
509
- );
510
- }
511
-
512
530
  return buildConfigFromPorts(
513
- { backendPort: ports.backend, vscodePort: ports.vscode },
531
+ { backendPort: preferredBackendPort, vscodePort: preferredVscodePort },
514
532
  cwd,
515
533
  env,
516
534
  );
@@ -606,6 +624,17 @@ function buildConfigFromPorts(ports, cwd, env) {
606
624
  */
607
625
  export function buildAgentServerEnv(config) {
608
626
  return {
627
+ // Force Python to use UTF-8 for all file I/O and streams.
628
+ //
629
+ // On Windows, Python defaults to the system ANSI codepage (e.g. cp1252).
630
+ // The agent-server writes conversation metadata JSON that can contain
631
+ // emoji (e.g. ✅ U+2705) which cp1252 cannot encode, producing:
632
+ // UnicodeEncodeError: 'charmap' codec can't encode character '\u2705'
633
+ // Setting PYTHONUTF8=1 enables Python's UTF-8 mode (PEP 540) for the
634
+ // entire agent-server process, matching the behaviour on Linux/macOS
635
+ // where the locale is already UTF-8.
636
+ // This is a no-op on Linux/macOS where the locale is already UTF-8.
637
+ PYTHONUTF8: "1",
609
638
  TMUX_TMPDIR: config.tmuxTmpDir,
610
639
  OH_CONVERSATIONS_PATH: config.conversationsPath,
611
640
  OH_BASH_EVENTS_DIR: config.bashEventsDir,
@@ -753,17 +782,24 @@ export function buildNpmScriptCommand(
753
782
  env = process.env,
754
783
  nodeExecPath = process.execPath,
755
784
  ) {
756
- if (env.npm_execpath) {
785
+ // On Windows, always use cmd.exe regardless of whether npm_execpath is set.
786
+ // npm_execpath points to a path like
787
+ // "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" which contains
788
+ // spaces. When that path is passed as an argument with shell:true in
789
+ // spawnService, cmd.exe splits on the space and tries to run "C:\Program"
790
+ // as a command, producing "not recognized as an internal or external command".
791
+ // Using "npm" via cmd.exe avoids the problem entirely.
792
+ if (platform === "win32") {
757
793
  return {
758
- command: env.npm_node_execpath || nodeExecPath,
759
- args: [env.npm_execpath, "run", scriptName],
794
+ command: env.ComSpec || "cmd.exe",
795
+ args: ["/d", "/s", "/c", "npm", "run", scriptName],
760
796
  };
761
797
  }
762
798
 
763
- if (platform === "win32") {
799
+ if (env.npm_execpath) {
764
800
  return {
765
- command: env.ComSpec || "cmd.exe",
766
- args: ["/d", "/s", "/c", "npm", "run", scriptName],
801
+ command: env.npm_node_execpath || nodeExecPath,
802
+ args: [env.npm_execpath, "run", scriptName],
767
803
  };
768
804
  }
769
805