@openhands/agent-canvas 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{acp-providers-DLe_gVDY.js → acp-providers-BkL3HWa3.js} +1 -1
  4. package/build/assets/{active-backend-context-B0wI7OzM.js → active-backend-context-B_bg5h9O.js} +1 -1
  5. package/build/assets/{agent-context-settings-CaQtdNA-.js → agent-context-settings-CzWS1DgR.js} +1 -1
  6. package/build/assets/{agent-profiles-settings-CvuErjp6.js → agent-profiles-settings-hd2cAIZM.js} +1 -1
  7. package/build/assets/agent-server-conversation-service.api-BheU4HX3.js +86 -0
  8. package/build/assets/{agent-settings-UE-U4Xii.js → agent-settings-D2J1dKVd.js} +1 -1
  9. package/build/assets/agent-settings-D_SVrWhI.js +1 -0
  10. package/build/assets/{alert-banner-BMaOtTCG.js → alert-banner-lrK-2_0Y.js} +1 -1
  11. package/build/assets/{api-key-entry-screen-Cy66vT4D.js → api-key-entry-screen-D70oJj2c.js} +1 -1
  12. package/build/assets/app-settings-D0OKHB3M.js +1 -0
  13. package/build/assets/{automation-detail-fuITm6i3.js → automation-detail-C0SxWTnQ.js} +3 -3
  14. package/build/assets/{automation-export-CRq40mux.js → automation-export-BjQa_fT6.js} +1 -1
  15. package/build/assets/{automation-setup-route-EXDazOHW.js → automation-setup-route-BzCNpljP.js} +1 -1
  16. package/build/assets/{automation-templates-BArZsaxP.js → automation-templates-D9gs6ihu.js} +1 -1
  17. package/build/assets/{automations-list-CG4HKOTn.js → automations-list-dZg8zOCl.js} +1 -1
  18. package/build/assets/{back-nav-button-BZB6H7xz.js → back-nav-button-B3pYwmUJ.js} +1 -1
  19. package/build/assets/{backend-form-modal-B_lXjOGa.js → backend-form-modal-HwclKrUS.js} +1 -1
  20. package/build/assets/{backend-synced-settings-badge-B_NXJ3u1.js → backend-synced-settings-badge-YI3k09Wr.js} +1 -1
  21. package/build/assets/{badge-C64c-7PO.js → badge-Dpn3-LTV.js} +1 -1
  22. package/build/assets/{base-modal-C0RQPug5.js → base-modal-3NmIOKDm.js} +1 -1
  23. package/build/assets/{brand-button-DJmFCyMK.js → brand-button-CJcwjnfb.js} +1 -1
  24. package/build/assets/{browser-D3gd2n83.js → browser--eoQOo4M.js} +1 -1
  25. package/build/assets/{browser-tab-BicAWuJ1.js → browser-tab-4CPdj3J3.js} +1 -1
  26. package/build/assets/{chat-send-button-CCrH1E8u.js → chat-send-button-B8n6-DQA.js} +1 -1
  27. package/build/assets/{circle-plus-check-toggle-CB_sNERY.js → circle-plus-check-toggle-BVzv5EkZ.js} +1 -1
  28. package/build/assets/{cloud-funnel-analytics-XynamQGU.js → cloud-funnel-analytics-CcSez21r.js} +1 -1
  29. package/build/assets/{combobox-caret-Bwiifgjs.js → combobox-caret-BlmRwiM8.js} +1 -1
  30. package/build/assets/command-menu-BKOLj-TC.js +1 -0
  31. package/build/assets/{condenser-settings-cNGy75gq.js → condenser-settings-DLQogFnB.js} +1 -1
  32. package/build/assets/{confirmation-modal-BATFmFyP.js → confirmation-modal-DAH0XtOp.js} +1 -1
  33. package/build/assets/{context-menu-list-item-DhJCcBA0.js → context-menu-list-item-BQhmFVEK.js} +1 -1
  34. package/build/assets/{conversation-Csdxh9Xt.js → conversation-Cmyw9bFh.js} +4 -4
  35. package/build/assets/conversation-CvoGZ5vC.js +1 -0
  36. package/build/assets/conversation-panel-CvoGZ5vC.js +1 -0
  37. package/build/assets/{conversation-state-store-C2QzhPaK.js → conversation-state-store-CtgILxWF.js} +1 -1
  38. package/build/assets/{conversation-tab-empty-state-D3fb5xIA.js → conversation-tab-empty-state-C9sfDOlt.js} +1 -1
  39. package/build/assets/{copy-to-clipboard-button-c4MQwKGj.js → copy-to-clipboard-button-DatoElj8.js} +1 -1
  40. package/build/assets/{device-verify-oFpQoLgm.js → device-verify-BIjXeW9N.js} +1 -1
  41. package/build/assets/{dropdown-classes-f91ARMV1.js → dropdown-classes-zFW7qPSK.js} +1 -1
  42. package/build/assets/{entry.client-BCzY2Bf3.js → entry.client-EBn3ZtNP.js} +2 -2
  43. package/build/assets/{enum-filter-dropdown-HG3q3rkV.js → enum-filter-dropdown-CctILg5t.js} +1 -1
  44. package/build/assets/{environment-switch-overlay-CquZXolz.js → environment-switch-overlay-Cvmo6clk.js} +1 -1
  45. package/build/assets/{extensions-hub-BeweE0PW.js → extensions-hub-BZ3HYztk.js} +1 -1
  46. package/build/assets/{extensions-navigation-Dd58NlUF.js → extensions-navigation-Bnx32WAb.js} +1 -1
  47. package/build/assets/{files-tab-CLLG55-q.js → files-tab-D5zuU5TY.js} +1 -1
  48. package/build/assets/{form-control-classes-pHtZUI6K.js → form-control-classes-DLN3Qgub.js} +1 -1
  49. package/build/assets/format-model-name-BN_rx1Y3.js +1 -0
  50. package/build/assets/{format-relative-time-6-3uvOXe.js → format-relative-time-BerVamGl.js} +1 -1
  51. package/build/assets/{git-provider-icon-wg7ShB98.js → git-provider-icon-zuKz2cwo.js} +1 -1
  52. package/build/assets/{git-repo-dropdown-CWnaUyxL.js → git-repo-dropdown-B5VnMftu.js} +1 -1
  53. package/build/assets/git-repo-dropdown-Bo7ciSNX.js +1 -0
  54. package/build/assets/{highlighted-source-view-DBtI3por.js → highlighted-source-view-CgJfD5VT.js} +1 -1
  55. package/build/assets/home-DqyeeFA_.js +1 -0
  56. package/build/assets/{home-BpZQkDWM.js → home-Y0aDou-a.js} +1 -1
  57. package/build/assets/{home-store-DM4qw1lF.js → home-store-Cubdq0uP.js} +1 -1
  58. package/build/assets/index-home-DqyeeFA_.js +1 -0
  59. package/build/assets/install-server-modal-DW6dSyGr.js +1 -0
  60. package/build/assets/{kebab-menu-item-content-By16Tm_0.js → kebab-menu-item-content-CKydZrbH.js} +1 -1
  61. package/build/assets/{launch-C9uijypN.js → launch-c4GEP8oo.js} +1 -1
  62. package/build/assets/llm-not-configured-banner-DCE_0B4I.js +27 -0
  63. package/build/assets/llm-settings-8eWBF3Ij.js +1 -0
  64. package/build/assets/llm-settings-D9ko42Pi.js +1 -0
  65. package/build/assets/{llm-subscription-service-DwjJ8-_X.js → llm-subscription-service-B3K-97lP.js} +1 -1
  66. package/build/assets/{loading-spinner-6Yj-YyoS.js → loading-spinner-CN3riY7k.js} +1 -1
  67. package/build/assets/{manage-backends-modal-DrwErS0N.js → manage-backends-modal-DTCME_Pu.js} +1 -1
  68. package/build/assets/manifest-e1c3bc3b.js +1 -0
  69. package/build/assets/{manifest-subpage-layout-CtqVwIvJ.js → manifest-subpage-layout-Ds7G5GZ8.js} +1 -1
  70. package/build/assets/map-provider-7Bp2aih5.js +1 -0
  71. package/build/assets/markdown-renderer-DzvgdZey.js +8 -0
  72. package/build/assets/mcp-Da7wFU7A.js +9 -0
  73. package/build/assets/{mcp-marketplace-utils-BMnYz0Gc.js → mcp-marketplace-utils-DSLou4n7.js} +1 -1
  74. package/build/assets/messages-B2l0qLVk.js +40 -0
  75. package/build/assets/{modal-body-BHGCSAtj.js → modal-body-duRaxj_K.js} +1 -1
  76. package/build/assets/{modal-classes-DSTLuxkA.js → modal-classes-CLEXO6dj.js} +1 -1
  77. package/build/assets/{modal-close-button-dheWZ2ys.js → modal-close-button-D0aT02hs.js} +1 -1
  78. package/build/assets/npm-Cswluf6-.js +1 -0
  79. package/build/assets/{onboarding-5CZvRBbh.js → onboarding-BKbTYlW1.js} +1 -1
  80. package/build/assets/{onboarding-modal-CD2ehuxt.js → onboarding-modal-DrrGlEQq.js} +1 -1
  81. package/build/assets/{organization-service.api-Dsuoep0g.js → organization-service.api-DK8csGvK.js} +1 -1
  82. package/build/assets/{planner-tab-DeO7Thb0.js → planner-tab-D-mZ1I7n.js} +1 -1
  83. package/build/assets/{plugins-management-service-C9f75R6X.js → plugins-management-service-CywqyfLK.js} +1 -1
  84. package/build/assets/{profiles-service.api-Dl20_2IM.js → profiles-service.api-vcE_jJCe.js} +1 -1
  85. package/build/assets/{providers-CeuhK46N.js → providers-CdrPPm0z.js} +1 -1
  86. package/build/assets/{proxy-CIGI9zQC.js → proxy-b4aqL4SX.js} +1 -1
  87. package/build/assets/recommended-automations-launcher-DIYgUdMm.js +1 -0
  88. package/build/assets/{root-BQPNqNvD.js → root-CBBi6IAe.js} +2 -2
  89. package/build/assets/root-CRK9fOFd.css +1 -0
  90. package/build/assets/root-layout-BFN2rCOy.js +2 -0
  91. package/build/assets/{schema-field-z2vSLuLo.js → schema-field-Z-rMg9ti.js} +1 -1
  92. package/build/assets/{sdk-section-page-BnCXAytf.js → sdk-section-page-m_cjygxR.js} +1 -1
  93. package/build/assets/{secrets-service-DGUNlwQd.js → secrets-service-BHF4fxML.js} +1 -1
  94. package/build/assets/{secrets-settings-DUmML_dK.js → secrets-settings-aBGXtQhX.js} +1 -1
  95. package/build/assets/{segmented-toggle-eSofF7gn.js → segmented-toggle-SmvsR3jW.js} +1 -1
  96. package/build/assets/settings-CZPGNens.js +1 -0
  97. package/build/assets/{settings-dropdown-input-Cx4g7Xfl.js → settings-dropdown-input-TWIeiG02.js} +1 -1
  98. package/build/assets/{settings-index-BECdgecg.js → settings-index-Dtlegd6s.js} +1 -1
  99. package/build/assets/{settings-input-BQY115xH.js → settings-input-D61Vzp9e.js} +1 -1
  100. package/build/assets/{settings-list-classes-C9cLrrcc.js → settings-list-classes-sE0ASr1s.js} +1 -1
  101. package/build/assets/{settings-modal-ChBJNTdd.js → settings-modal-CalzJP2l.js} +1 -1
  102. package/build/assets/{settings-service.api-Dz9cZyvx.js → settings-service.api-DfPYaxZJ.js} +1 -1
  103. package/build/assets/{settings-switch-BIodMVz9.js → settings-switch-Drt-rF5s.js} +1 -1
  104. package/build/assets/{settings-utils-BL_Z9uIe.js → settings-utils-gw2ppAvw.js} +1 -1
  105. package/build/assets/{shared-conversation-CSF0aTuE.js → shared-conversation-BIAcuORk.js} +1 -1
  106. package/build/assets/{wrench-DRitTfwe.js → shield-check-D2cpEpv3.js} +1 -1
  107. package/build/assets/{sidebar-layout-DEycoFd_.js → sidebar-layout-Dxg6zc2K.js} +1 -1
  108. package/build/assets/{sidebar-mobile-menu-toggle-DeRvTupV.js → sidebar-mobile-menu-toggle-C6HpQ55l.js} +1 -1
  109. package/build/assets/{sidebar-nav-link-BjpQ-NVc.js → sidebar-nav-link-CxLoG-dG.js} +1 -1
  110. package/build/assets/sidebar-store-BJeYY-E9.js +1 -0
  111. package/build/assets/{skill-card-pill-row-BH6fPGba.js → skill-card-pill-row-B_BYBONu.js} +1 -1
  112. package/build/assets/{skill-icon-badge-D4uznfjU.js → skill-icon-badge-CN41Hy9l.js} +1 -1
  113. package/build/assets/{skill-scope-DH_AUUUP.js → skill-scope-Dt1V5X2p.js} +1 -1
  114. package/build/assets/{skills-plugins-vfvOk34h.js → skills-plugins-B-H0cCOP.js} +1 -1
  115. package/build/assets/skills-settings-DthdIDUb.js +2 -0
  116. package/build/assets/{styled-tooltip-CQ9JEFiO.js → styled-tooltip-C5C07RQC.js} +1 -1
  117. package/build/assets/{task-list-tab-DeF_uXdw.js → task-list-tab-BTde81Iu.js} +1 -1
  118. package/build/assets/{terminal-DRc4rup7.js → terminal-DRrJo-cR.js} +1 -1
  119. package/build/assets/{toggle-switch--8n8NeV_.js → toggle-switch-CIioisto.js} +1 -1
  120. package/build/assets/{typography-BSbUhJPn.js → typography-D9tiHct7.js} +1 -1
  121. package/build/assets/{use-acp-credential-form-BGKFi1VL.js → use-acp-credential-form-DGyo0QvL.js} +1 -1
  122. package/build/assets/{use-activate-agent-profile-2nvALjC-.js → use-activate-agent-profile-DrPzIKJF.js} +1 -1
  123. package/build/assets/{use-agent-profiles-BlQA67MW.js → use-agent-profiles-B37XWDLq.js} +1 -1
  124. package/build/assets/{use-can-manage-org-profiles-Clw5Dh1s.js → use-can-manage-org-profiles-BzE28H3x.js} +1 -1
  125. package/build/assets/{use-cloud-current-user-id-B8AQSQFM.js → use-cloud-current-user-id-U6HPjy50.js} +1 -1
  126. package/build/assets/{use-config-C3zGuUQI.js → use-config-DapX3pjC.js} +1 -1
  127. package/build/assets/{use-create-conversation-FaP0kUpg.js → use-create-conversation-CRf1dCm5.js} +1 -1
  128. package/build/assets/{use-create-secret-CgQ3pXd6.js → use-create-secret-DcpT3RPw.js} +1 -1
  129. package/build/assets/{use-llm-profiles-C-tDO6UB.js → use-llm-profiles-CHxqoHiN.js} +1 -1
  130. package/build/assets/{use-manifest-capabilities-DLP5wCxp.js → use-manifest-capabilities-zihHDbMW.js} +1 -1
  131. package/build/assets/{use-onboarding-completion-BiCdXvlU.js → use-onboarding-completion-6kWOW3ul.js} +1 -1
  132. package/build/assets/{use-plugins-marketplace-DRFNLBlr.js → use-plugins-marketplace-CqkR8kLE.js} +1 -1
  133. package/build/assets/{use-save-agent-profile-CaGVAudI.js → use-save-agent-profile-CH9_EXQG.js} +1 -1
  134. package/build/assets/{use-save-settings-C9B8Y-h3.js → use-save-settings-DIEurJ3D.js} +1 -1
  135. package/build/assets/{use-settings-3RcgdUuZ.js → use-settings-BmLzQjnC.js} +1 -1
  136. package/build/assets/use-settings-nav-items-DV9qgeu7.js +16 -0
  137. package/build/assets/{use-tracking-CTtkLAmx.js → use-tracking-salbPJxT.js} +1 -1
  138. package/build/assets/{use-user-conversation-Bei82QsZ.js → use-user-conversation-Dt-W6uNw.js} +1 -1
  139. package/build/assets/utils-DPQfkd-7.js +1 -0
  140. package/build/assets/{verification-settings-nD61Ijph.js → verification-settings-oi54wEc1.js} +1 -1
  141. package/build/assets/wrench-B1_H-tL1.js +1 -0
  142. package/build/index.html +4 -4
  143. package/build/locales/ar/openhands.json +39 -2
  144. package/build/locales/ca/openhands.json +39 -2
  145. package/build/locales/de/openhands.json +39 -2
  146. package/build/locales/en/openhands.json +39 -2
  147. package/build/locales/es/openhands.json +39 -2
  148. package/build/locales/fr/openhands.json +39 -2
  149. package/build/locales/it/openhands.json +39 -2
  150. package/build/locales/ja/openhands.json +39 -2
  151. package/build/locales/ko-KR/openhands.json +39 -2
  152. package/build/locales/no/openhands.json +39 -2
  153. package/build/locales/pt/openhands.json +39 -2
  154. package/build/locales/tr/openhands.json +39 -2
  155. package/build/locales/uk/openhands.json +39 -2
  156. package/build/locales/zh-CN/openhands.json +39 -2
  157. package/build/locales/zh-TW/openhands.json +39 -2
  158. package/config/defaults.json +1 -1
  159. package/dist/api/agent-server-adapter.cjs +3 -3
  160. package/dist/api/agent-server-adapter.cjs.map +1 -1
  161. package/dist/api/agent-server-adapter.d.ts +32 -5
  162. package/dist/api/agent-server-adapter.js +120 -91
  163. package/dist/api/agent-server-adapter.js.map +1 -1
  164. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  165. package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
  166. package/dist/api/cloud/conversation-service.api.d.ts +19 -2
  167. package/dist/api/cloud/conversation-service.api.js +51 -47
  168. package/dist/api/cloud/conversation-service.api.js.map +1 -1
  169. package/dist/api/conversation-file-upload.api.cjs +1 -1
  170. package/dist/api/conversation-file-upload.api.js +10 -10
  171. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  172. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  173. package/dist/api/conversation-service/agent-server-conversation-service.api.js +55 -61
  174. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  175. package/dist/api/event-service/event-service.api.cjs +1 -1
  176. package/dist/api/event-service/event-service.api.js +12 -12
  177. package/dist/api/launch-child-conversation-client-tool.cjs +47 -0
  178. package/dist/api/launch-child-conversation-client-tool.cjs.map +1 -0
  179. package/dist/api/launch-child-conversation-client-tool.d.ts +3 -0
  180. package/dist/api/launch-child-conversation-client-tool.js +93 -0
  181. package/dist/api/launch-child-conversation-client-tool.js.map +1 -0
  182. package/dist/api/open-hands.types.d.ts +1 -1
  183. package/dist/api/workspace-upload-path.cjs +1 -1
  184. package/dist/api/workspace-upload-path.js +8 -8
  185. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +1 -1
  186. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -1
  187. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +24 -18
  188. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -1
  189. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
  190. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
  191. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +5 -0
  192. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
  193. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs +2 -2
  194. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs.map +1 -1
  195. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js +11 -7
  196. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js.map +1 -1
  197. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
  198. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
  199. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +61 -60
  200. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
  201. package/dist/components/features/chat/model-messages.cjs +1 -1
  202. package/dist/components/features/chat/model-messages.cjs.map +1 -1
  203. package/dist/components/features/chat/model-messages.js +26 -25
  204. package/dist/components/features/chat/model-messages.js.map +1 -1
  205. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -2
  206. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
  207. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.d.ts +2 -8
  208. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +50 -53
  209. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
  210. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs +2 -0
  211. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs.map +1 -0
  212. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.d.ts +12 -0
  213. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js +6 -0
  214. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js.map +1 -0
  215. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
  216. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
  217. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.d.ts +16 -1
  218. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +95 -78
  219. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
  220. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs +1 -1
  221. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs.map +1 -1
  222. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js +40 -38
  223. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js.map +1 -1
  224. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +2 -0
  225. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -0
  226. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +14 -0
  227. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +167 -0
  228. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -0
  229. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +2 -0
  230. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -0
  231. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +63 -0
  232. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +66 -0
  233. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -0
  234. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs +2 -0
  235. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs.map +1 -0
  236. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.d.ts +15 -0
  237. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js +117 -0
  238. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js.map +1 -0
  239. package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs +1 -1
  240. package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs.map +1 -1
  241. package/dist/components/features/conversation-panel/conversation-card/no-repository.js +30 -19
  242. package/dist/components/features/conversation-panel/conversation-card/no-repository.js.map +1 -1
  243. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +1 -1
  244. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +1 -1
  245. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +7 -2
  246. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +146 -104
  247. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +1 -1
  248. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
  249. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
  250. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +20 -0
  251. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +53 -27
  252. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
  253. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  254. package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
  255. package/dist/components/features/conversation-panel/conversation-panel.js +226 -213
  256. package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
  257. package/dist/components/features/settings/agent-canvas-update-card.cjs +1 -1
  258. package/dist/components/features/settings/agent-canvas-update-card.cjs.map +1 -1
  259. package/dist/components/features/settings/agent-canvas-update-card.d.ts +10 -5
  260. package/dist/components/features/settings/agent-canvas-update-card.js +223 -149
  261. package/dist/components/features/settings/agent-canvas-update-card.js.map +1 -1
  262. package/dist/components/features/settings/agent-canvas-version-modal.cjs +2 -0
  263. package/dist/components/features/settings/agent-canvas-version-modal.cjs.map +1 -0
  264. package/dist/components/features/settings/agent-canvas-version-modal.d.ts +11 -0
  265. package/dist/components/features/settings/agent-canvas-version-modal.js +166 -0
  266. package/dist/components/features/settings/agent-canvas-version-modal.js.map +1 -0
  267. package/dist/components/features/settings/agent-canvas-version-tile.cjs +2 -0
  268. package/dist/components/features/settings/agent-canvas-version-tile.cjs.map +1 -0
  269. package/dist/components/features/settings/agent-canvas-version-tile.d.ts +13 -0
  270. package/dist/components/features/settings/agent-canvas-version-tile.js +60 -0
  271. package/dist/components/features/settings/agent-canvas-version-tile.js.map +1 -0
  272. package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
  273. package/dist/components/features/settings/llm-profiles/profile-row.js +1 -0
  274. package/dist/components/features/settings/settings-desktop-sidebar.cjs +1 -1
  275. package/dist/components/features/settings/settings-desktop-sidebar.cjs.map +1 -1
  276. package/dist/components/features/settings/settings-desktop-sidebar.js +1 -1
  277. package/dist/components/features/settings/settings-desktop-sidebar.js.map +1 -1
  278. package/dist/components/features/settings/settings-mobile-drawer.cjs +1 -1
  279. package/dist/components/features/settings/settings-mobile-drawer.cjs.map +1 -1
  280. package/dist/components/features/settings/settings-mobile-drawer.js +1 -1
  281. package/dist/components/features/settings/settings-mobile-drawer.js.map +1 -1
  282. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  283. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  284. package/dist/components/features/sidebar/sidebar-rail-body.js +109 -108
  285. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  286. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  287. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  288. package/dist/components/features/skills/extensions-navigation.js +9 -9
  289. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  290. package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
  291. package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
  292. package/dist/components/shared/modals/settings/model-selector.js +154 -98
  293. package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
  294. package/dist/config/defaults.cjs +1 -1
  295. package/dist/config/defaults.cjs.map +1 -1
  296. package/dist/config/defaults.js +1 -1
  297. package/dist/config/defaults.js.map +1 -1
  298. package/dist/constants/child-conversation.cjs +2 -0
  299. package/dist/constants/child-conversation.cjs.map +1 -0
  300. package/dist/constants/child-conversation.d.ts +29 -0
  301. package/dist/constants/child-conversation.js +6 -0
  302. package/dist/constants/child-conversation.js.map +1 -0
  303. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  304. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  305. package/dist/contexts/conversation-websocket-context.js +189 -188
  306. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  307. package/dist/hooks/chat/use-model-interceptor.cjs +1 -1
  308. package/dist/hooks/chat/use-model-interceptor.js +6 -6
  309. package/dist/hooks/chat/use-slash-command.cjs +1 -1
  310. package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
  311. package/dist/hooks/chat/use-slash-command.js +61 -60
  312. package/dist/hooks/chat/use-slash-command.js.map +1 -1
  313. package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
  314. package/dist/hooks/mutation/use-create-conversation.js +6 -6
  315. package/dist/i18n/declaration.cjs +1 -1
  316. package/dist/i18n/declaration.cjs.map +1 -1
  317. package/dist/i18n/declaration.d.ts +38 -1
  318. package/dist/i18n/declaration.js +1 -1
  319. package/dist/i18n/declaration.js.map +1 -1
  320. package/dist/i18n/translation.cjs +2 -2
  321. package/dist/i18n/translation.cjs.map +1 -1
  322. package/dist/i18n/translation.js +644 -15
  323. package/dist/i18n/translation.js.map +1 -1
  324. package/dist/icons/docker.cjs +2 -0
  325. package/dist/icons/docker.cjs.map +1 -0
  326. package/dist/icons/docker.js +19 -0
  327. package/dist/icons/docker.js.map +1 -0
  328. package/dist/icons/npm.cjs +2 -0
  329. package/dist/icons/npm.cjs.map +1 -0
  330. package/dist/icons/npm.js +19 -0
  331. package/dist/icons/npm.js.map +1 -0
  332. package/dist/locales/ar/openhands.json +39 -2
  333. package/dist/locales/ca/openhands.json +39 -2
  334. package/dist/locales/de/openhands.json +39 -2
  335. package/dist/locales/en/openhands.json +39 -2
  336. package/dist/locales/es/openhands.json +39 -2
  337. package/dist/locales/fr/openhands.json +39 -2
  338. package/dist/locales/it/openhands.json +39 -2
  339. package/dist/locales/ja/openhands.json +39 -2
  340. package/dist/locales/ko-KR/openhands.json +39 -2
  341. package/dist/locales/no/openhands.json +39 -2
  342. package/dist/locales/pt/openhands.json +39 -2
  343. package/dist/locales/tr/openhands.json +39 -2
  344. package/dist/locales/uk/openhands.json +39 -2
  345. package/dist/locales/zh-CN/openhands.json +39 -2
  346. package/dist/locales/zh-TW/openhands.json +39 -2
  347. package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
  348. package/dist/node_modules/@openhands/typescript-client/dist/index.js +1 -1
  349. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs +2 -0
  350. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs.map +1 -0
  351. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js +16 -0
  352. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js.map +1 -0
  353. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs +2 -0
  354. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs.map +1 -0
  355. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js +27 -0
  356. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js.map +1 -0
  357. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs +2 -0
  358. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs.map +1 -0
  359. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js +21 -0
  360. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js.map +1 -0
  361. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs +2 -0
  362. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs.map +1 -0
  363. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js +23 -0
  364. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js.map +1 -0
  365. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs +2 -0
  366. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs.map +1 -0
  367. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js +43 -0
  368. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js.map +1 -0
  369. package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs +2 -0
  370. package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs.map +1 -0
  371. package/dist/node_modules/lucide-react/dist/esm/icons/earth.js +25 -0
  372. package/dist/node_modules/lucide-react/dist/esm/icons/earth.js.map +1 -0
  373. package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs +2 -0
  374. package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs.map +1 -0
  375. package/dist/node_modules/lucide-react/dist/esm/icons/flag.js +9 -0
  376. package/dist/node_modules/lucide-react/dist/esm/icons/flag.js.map +1 -0
  377. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs +2 -0
  378. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs.map +1 -0
  379. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js +27 -0
  380. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js.map +1 -0
  381. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs +2 -0
  382. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs.map +1 -0
  383. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js +25 -0
  384. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js.map +1 -0
  385. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs +2 -0
  386. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs.map +1 -0
  387. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js +30 -0
  388. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js.map +1 -0
  389. package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs +2 -0
  390. package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs.map +1 -0
  391. package/dist/node_modules/lucide-react/dist/esm/icons/hash.js +35 -0
  392. package/dist/node_modules/lucide-react/dist/esm/icons/hash.js.map +1 -0
  393. package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs +2 -0
  394. package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs.map +1 -0
  395. package/dist/node_modules/lucide-react/dist/esm/icons/house.js +12 -0
  396. package/dist/node_modules/lucide-react/dist/esm/icons/house.js.map +1 -0
  397. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs +2 -0
  398. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs.map +1 -0
  399. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js +33 -0
  400. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js.map +1 -0
  401. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs +2 -0
  402. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs.map +1 -0
  403. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js +15 -0
  404. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js.map +1 -0
  405. package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs +2 -0
  406. package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs.map +1 -0
  407. package/dist/node_modules/lucide-react/dist/esm/icons/layers.js +19 -0
  408. package/dist/node_modules/lucide-react/dist/esm/icons/layers.js.map +1 -0
  409. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs +2 -0
  410. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs.map +1 -0
  411. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js +22 -0
  412. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js.map +1 -0
  413. package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs +2 -0
  414. package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs.map +1 -0
  415. package/dist/node_modules/lucide-react/dist/esm/icons/mails.js +23 -0
  416. package/dist/node_modules/lucide-react/dist/esm/icons/mails.js.map +1 -0
  417. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs +2 -0
  418. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs.map +1 -0
  419. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js +12 -0
  420. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js.map +1 -0
  421. package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs +2 -0
  422. package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs.map +1 -0
  423. package/dist/node_modules/lucide-react/dist/esm/icons/plug.js +23 -0
  424. package/dist/node_modules/lucide-react/dist/esm/icons/plug.js.map +1 -0
  425. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs +2 -0
  426. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs.map +1 -0
  427. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js +27 -0
  428. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js.map +1 -0
  429. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs +2 -0
  430. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs.map +1 -0
  431. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js +23 -0
  432. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js.map +1 -0
  433. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs +2 -0
  434. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs.map +1 -0
  435. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js +21 -0
  436. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js.map +1 -0
  437. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs +2 -0
  438. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs.map +1 -0
  439. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js +43 -0
  440. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js.map +1 -0
  441. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs +2 -0
  442. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs.map +1 -0
  443. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js +19 -0
  444. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js.map +1 -0
  445. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs +2 -0
  446. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs.map +1 -0
  447. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js +27 -0
  448. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js.map +1 -0
  449. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs +2 -0
  450. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs.map +1 -0
  451. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js +9 -0
  452. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js.map +1 -0
  453. package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs +2 -0
  454. package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs.map +1 -0
  455. package/dist/node_modules/lucide-react/dist/esm/icons/zap.js +9 -0
  456. package/dist/node_modules/lucide-react/dist/esm/icons/zap.js.map +1 -0
  457. package/dist/package.cjs +1 -1
  458. package/dist/package.cjs.map +1 -1
  459. package/dist/package.js +6 -3
  460. package/dist/package.js.map +1 -1
  461. package/dist/routes/app-settings.cjs +1 -1
  462. package/dist/routes/app-settings.cjs.map +1 -1
  463. package/dist/routes/app-settings.js +94 -93
  464. package/dist/routes/app-settings.js.map +1 -1
  465. package/dist/routes/llm-settings.cjs +1 -1
  466. package/dist/routes/llm-settings.cjs.map +1 -1
  467. package/dist/routes/llm-settings.js +131 -119
  468. package/dist/routes/llm-settings.js.map +1 -1
  469. package/dist/services/child-conversation-launch.cjs +2 -0
  470. package/dist/services/child-conversation-launch.cjs.map +1 -0
  471. package/dist/services/child-conversation-launch.d.ts +41 -0
  472. package/dist/services/child-conversation-launch.js +182 -0
  473. package/dist/services/child-conversation-launch.js.map +1 -0
  474. package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
  475. package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
  476. package/dist/stores/conversation-panel-preferences-store.d.ts +5 -1
  477. package/dist/stores/conversation-panel-preferences-store.js +8 -2
  478. package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
  479. package/dist/types/agent-server/core/base/action.d.ts +17 -1
  480. package/dist/types/agent-server/core/base/base.d.ts +2 -1
  481. package/dist/types/agent-server/type-guards.cjs +1 -1
  482. package/dist/types/agent-server/type-guards.cjs.map +1 -1
  483. package/dist/types/agent-server/type-guards.d.ts +8 -1
  484. package/dist/types/agent-server/type-guards.js +4 -3
  485. package/dist/types/agent-server/type-guards.js.map +1 -1
  486. package/dist/types/automation.d.ts +14 -0
  487. package/dist/utils/custom-toast-handlers.cjs +1 -1
  488. package/dist/utils/custom-toast-handlers.cjs.map +1 -1
  489. package/dist/utils/custom-toast-handlers.js +18 -1
  490. package/dist/utils/custom-toast-handlers.js.map +1 -1
  491. package/dist/utils/format-model-name.cjs +1 -1
  492. package/dist/utils/format-model-name.cjs.map +1 -1
  493. package/dist/utils/format-model-name.d.ts +11 -0
  494. package/dist/utils/format-model-name.js +11 -3
  495. package/dist/utils/format-model-name.js.map +1 -1
  496. package/package.json +6 -3
  497. package/scripts/brand-dev-electron.mjs +244 -0
  498. package/scripts/check-translation-completeness.cjs +4 -0
  499. package/scripts/generate-icons.mjs +109 -0
  500. package/build/assets/agent-server-conversation-service.api-km_8sOVf.js +0 -41
  501. package/build/assets/agent-settings-nmO-KSXr.js +0 -1
  502. package/build/assets/app-settings-9ok42bV6.js +0 -1
  503. package/build/assets/command-menu-CA3IjGNc.js +0 -1
  504. package/build/assets/conversation-B6t6EiVp.js +0 -1
  505. package/build/assets/conversation-panel-B6t6EiVp.js +0 -1
  506. package/build/assets/copy-DaHuDtG4.js +0 -1
  507. package/build/assets/git-repo-dropdown-TzOuG5Ef.js +0 -1
  508. package/build/assets/home-OEx0XtfP.js +0 -1
  509. package/build/assets/index-home-OEx0XtfP.js +0 -1
  510. package/build/assets/install-server-modal-DnjZrJUy.js +0 -1
  511. package/build/assets/list-filter-C86CBRDE.js +0 -1
  512. package/build/assets/llm-not-configured-banner-DrBrhfN0.js +0 -27
  513. package/build/assets/llm-settings-CRsLqxgu.js +0 -1
  514. package/build/assets/llm-settings-RBm_3kNm.js +0 -1
  515. package/build/assets/manifest-c352d453.js +0 -1
  516. package/build/assets/map-provider-CXU6issd.js +0 -1
  517. package/build/assets/markdown-renderer-lsvsp7jn.js +0 -8
  518. package/build/assets/mcp-DD4hPTRE.js +0 -9
  519. package/build/assets/messages-Dt77e0qi.js +0 -40
  520. package/build/assets/recommended-automations-launcher-6xmbf7lh.js +0 -1
  521. package/build/assets/root-BeuHFY2s.css +0 -1
  522. package/build/assets/root-layout-Dl_2CDoq.js +0 -3
  523. package/build/assets/settings-Co-M5bK9.js +0 -1
  524. package/build/assets/sidebar-store-B04sX8aP.js +0 -1
  525. package/build/assets/skills-settings-DnbIu2eO.js +0 -2
  526. package/build/assets/use-settings-nav-items-y-Oyc93G.js +0 -16
  527. package/build/assets/utils-BX9XJ0IE.js +0 -1
  528. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +0 -2
  529. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs.map +0 -1
  530. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js +0 -9
  531. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"extensions-navigation.js","names":[],"sources":["../../../../src/components/features/skills/extensions-navigation.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { ExternalLink } from \"lucide-react\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { cn } from \"#/utils/utils\";\nimport SkillsIcon from \"#/icons/skills.svg?react\";\nimport ServerProcessIcon from \"#/icons/server-process.svg?react\";\nimport { BackendSyncedSettingsBadge } from \"#/components/features/settings/backend-synced-settings-badge\";\nimport {\n SIDEBAR_ROW_INTERACTIVE_CLASS,\n sidebarNavRowClassName,\n} from \"#/components/features/sidebar/sidebar-layout\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useActiveBackendContext } from \"#/contexts/active-backend-context\";\nimport { isNoBackend } from \"#/api/backend-registry/active-store\";\n\n/** Only the Skills item points to a cloud-hosted page today. */\nconst CLOUD_LINKED_EXTENSION_PATH = \"/skills\";\n/** Plugins are not available on Cloud backends, so this item is hidden there. */\nconst CLOUD_HIDDEN_EXTENSION_PATH = \"/plugins\";\n\ninterface ExtensionNavItem {\n to: string;\n label: string;\n icon: React.ReactElement;\n end?: boolean;\n comingSoon?: boolean;\n}\n\nexport const EXTENSIONS_NAV_ITEMS: ExtensionNavItem[] = [\n {\n to: \"/skills\",\n label: \"Skills\",\n icon: <SkillsIcon width={16} height={16} aria-hidden=\"true\" />,\n end: true,\n },\n {\n to: \"/mcp\",\n label: \"MCP Servers\",\n icon: <ServerProcessIcon width={16} height={16} />,\n end: true,\n },\n {\n to: \"/plugins\",\n label: \"Plugins\",\n icon: (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={16}\n height={16}\n aria-hidden=\"true\"\n >\n <path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\" />\n <path d=\"m3.3 7 8.7 5 8.7-5\" />\n <path d=\"M12 22V12\" />\n </svg>\n ),\n end: true,\n },\n];\n\nexport function ExtensionsNavigation() {\n const { t } = useTranslation(\"openhands\");\n const { active } = useActiveBackendContext();\n const { backend } = active;\n const isCloudBackend = !isNoBackend(backend) && backend.kind === \"cloud\";\n\n return (\n <aside\n data-testid=\"extensions-navbar-desktop\"\n className=\"hidden md:flex md:w-[260px] md:shrink-0 md:flex-col md:gap-2 md:sticky md:top-8 md:self-start\"\n >\n <span className=\"px-2 text-sm font-normal text-white\">\n {t(I18nKey.NAV$CUSTOMIZE)}\n </span>\n <div className=\"flex flex-col gap-0.5 pt-0.5\">\n {EXTENSIONS_NAV_ITEMS.filter(\n (item) =>\n !(item.to === CLOUD_HIDDEN_EXTENSION_PATH && isCloudBackend),\n ).map((item) => {\n const isCloudSkillsLink =\n item.to === CLOUD_LINKED_EXTENSION_PATH && isCloudBackend;\n const baseRow = (\n <span className=\"shrink-0 flex items-center justify-center\">\n {item.icon}\n </span>\n );\n const label = (\n <span className=\"truncate\">\n {isCloudSkillsLink\n ? t(I18nKey.SIDEBAR$SKILLS_AND_PLUGINS_CLOUD_LINK)\n : item.label}\n </span>\n );\n const comingSoonBadge = item.comingSoon && (\n <span className=\"ml-auto shrink-0 rounded-full border border-white/20 bg-white/5 px-1.5 py-0.5 text-[10px] font-medium text-[var(--oh-text-dim)]\">\n {t(I18nKey.NAV$COMING_SOON)}\n </span>\n );\n\n if (isCloudSkillsLink) {\n const cloudSkillsUrl = `${backend.host.replace(/\\/+$/, \"\")}/settings/skills`;\n return (\n <a\n key={item.to}\n data-testid={`sidebar-extensions-${item.to}`}\n href={cloudSkillsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n sidebarNavRowClassName(),\n \"truncate\",\n SIDEBAR_ROW_INTERACTIVE_CLASS.idle,\n )}\n >\n {baseRow}\n {label}\n <ExternalLink\n className=\"ml-auto size-4 shrink-0 text-[var(--oh-muted)]\"\n aria-hidden\n />\n </a>\n );\n }\n\n return (\n <NavigationLink\n key={item.to}\n to={item.to}\n end={item.end}\n data-testid={`sidebar-extensions-${item.to}`}\n className={({ isActive }) =>\n cn(\n sidebarNavRowClassName(),\n \"truncate\",\n isActive\n ? SIDEBAR_ROW_INTERACTIVE_CLASS.active\n : SIDEBAR_ROW_INTERACTIVE_CLASS.idle,\n )\n }\n >\n {baseRow}\n {label}\n {comingSoonBadge}\n </NavigationLink>\n );\n })}\n </div>\n <div className=\"px-2 pt-3\">\n <BackendSyncedSettingsBadge />\n </div>\n </aside>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAM,IAA8B,WAE9B,IAA8B,YAUvB,IAA2C;CACtD;EACE,IAAI;EACJ,OAAO;EACP,MAAM,kBAAC,GAAD;GAAY,OAAO;GAAI,QAAQ;GAAI,eAAY;EAAQ,CAAA;EAC7D,KAAK;CACP;CACA;EACE,IAAI;EACJ,OAAO;EACP,MAAM,kBAAC,GAAD;GAAmB,OAAO;GAAI,QAAQ;EAAK,CAAA;EACjD,KAAK;CACP;CACA;EACE,IAAI;EACJ,OAAO;EACP,MACE,kBAAC,OAAD;GACE,OAAM;GACN,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;GACf,OAAO;GACP,QAAQ;GACR,eAAY;aAVd;IAYE,kBAAC,QAAD,EAAM,GAAE,yHAA0H,CAAA;IAClI,kBAAC,QAAD,EAAM,GAAE,qBAAsB,CAAA;IAC9B,kBAAC,QAAD,EAAM,GAAE,YAAa,CAAA;GAClB;;EAEP,KAAK;CACP;AACF;AAEA,SAAgB,IAAuB;CACrC,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,EAAE,cAAW,EAAwB,GACrC,EAAE,eAAY,GACd,IAAiB,CAAC,EAAY,CAAO,KAAK,EAAQ,SAAS;CAEjE,OACE,kBAAC,SAAD;EACE,eAAY;EACZ,WAAU;YAFZ;GAIE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAE,EAAQ,aAAa;GACpB,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAqB,QACnB,MACC,EAAE,EAAK,OAAO,KAA+B,EACjD,EAAE,KAAK,MAAS;KACd,IAAM,IACJ,EAAK,OAAO,KAA+B,GACvC,IACJ,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAK;KACF,CAAA,GAEF,IACJ,kBAAC,QAAD;MAAM,WAAU;gBACb,IACG,EAAE,EAAQ,qCAAqC,IAC/C,EAAK;KACL,CAAA,GAEF,IAAkB,EAAK,cAC3B,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAE,EAAQ,eAAe;KACtB,CAAA;KAGR,IAAI,GAAmB;MACrB,IAAM,IAAiB,GAAG,EAAQ,KAAK,QAAQ,QAAQ,EAAE,EAAE;MAC3D,OACE,kBAAC,KAAD;OAEE,eAAa,sBAAsB,EAAK;OACxC,MAAM;OACN,QAAO;OACP,KAAI;OACJ,WAAW,EACT,EAAuB,GACvB,YACA,EAA8B,IAChC;iBAVF;QAYG;QACA;QACD,kBAAC,GAAD;SACE,WAAU;SACV,eAAA;QACD,CAAA;OACA;SAjBI,EAAK,EAiBT;KAEP;KAEA,OACE,kBAAC,GAAD;MAEE,IAAI,EAAK;MACT,KAAK,EAAK;MACV,eAAa,sBAAsB,EAAK;MACxC,YAAY,EAAE,kBACZ,EACE,EAAuB,GACvB,YACA,IACI,EAA8B,SAC9B,EAA8B,IACpC;gBAZJ;OAeG;OACA;OACA;MACa;QAjBT,EAAK,EAiBI;IAEpB,CAAC;GACE,CAAA;GACL,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,CAA6B,CAAA;GAC1B,CAAA;EACA;;AAEX"}
1
+ {"version":3,"file":"extensions-navigation.js","names":[],"sources":["../../../../src/components/features/skills/extensions-navigation.tsx"],"sourcesContent":["import { useTranslation } from \"react-i18next\";\nimport { ExternalLink } from \"lucide-react\";\nimport { NavigationLink } from \"#/components/shared/navigation-link\";\nimport { cn } from \"#/utils/utils\";\nimport SkillsIcon from \"#/icons/skills.svg?react\";\nimport ServerProcessIcon from \"#/icons/server-process.svg?react\";\nimport { BackendSyncedSettingsBadge } from \"#/components/features/settings/backend-synced-settings-badge\";\nimport {\n SIDEBAR_ROW_INTERACTIVE_CLASS,\n sidebarNavRowClassName,\n} from \"#/components/features/sidebar/sidebar-layout\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useActiveBackendContext } from \"#/contexts/active-backend-context\";\nimport { isNoBackend } from \"#/api/backend-registry/active-store\";\n\n/** Only the Skills item points to a cloud-hosted page today. */\nconst CLOUD_LINKED_EXTENSION_PATH = \"/skills\";\n/** Plugins are not available on Cloud backends, so this item is hidden there. */\nconst CLOUD_HIDDEN_EXTENSION_PATH = \"/plugins\";\n\ninterface ExtensionNavItem {\n to: string;\n label: string;\n icon: React.ReactElement;\n end?: boolean;\n comingSoon?: boolean;\n}\n\nexport const EXTENSIONS_NAV_ITEMS: ExtensionNavItem[] = [\n {\n to: \"/mcp\",\n label: \"MCP Servers\",\n icon: <ServerProcessIcon width={16} height={16} />,\n end: true,\n },\n {\n to: \"/skills\",\n label: \"Skills\",\n icon: <SkillsIcon width={16} height={16} aria-hidden=\"true\" />,\n end: true,\n },\n {\n to: \"/plugins\",\n label: \"Plugins\",\n icon: (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={16}\n height={16}\n aria-hidden=\"true\"\n >\n <path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\" />\n <path d=\"m3.3 7 8.7 5 8.7-5\" />\n <path d=\"M12 22V12\" />\n </svg>\n ),\n end: true,\n },\n];\n\nexport function ExtensionsNavigation() {\n const { t } = useTranslation(\"openhands\");\n const { active } = useActiveBackendContext();\n const { backend } = active;\n const isCloudBackend = !isNoBackend(backend) && backend.kind === \"cloud\";\n\n return (\n <aside\n data-testid=\"extensions-navbar-desktop\"\n className=\"hidden md:flex md:w-[260px] md:shrink-0 md:flex-col md:gap-2 md:sticky md:top-8 md:self-start\"\n >\n <span className=\"px-2 text-sm font-normal text-white\">\n {t(I18nKey.NAV$CUSTOMIZE)}\n </span>\n <div className=\"flex flex-col gap-0.5 pt-0.5\">\n {EXTENSIONS_NAV_ITEMS.filter(\n (item) =>\n !(item.to === CLOUD_HIDDEN_EXTENSION_PATH && isCloudBackend),\n ).map((item) => {\n const isCloudSkillsLink =\n item.to === CLOUD_LINKED_EXTENSION_PATH && isCloudBackend;\n const baseRow = (\n <span className=\"shrink-0 flex items-center justify-center\">\n {item.icon}\n </span>\n );\n const label = (\n <span className=\"truncate\">\n {isCloudSkillsLink\n ? t(I18nKey.SIDEBAR$SKILLS_AND_PLUGINS_CLOUD_LINK)\n : item.label}\n </span>\n );\n const comingSoonBadge = item.comingSoon && (\n <span className=\"ml-auto shrink-0 rounded-full border border-white/20 bg-white/5 px-1.5 py-0.5 text-[10px] font-medium text-[var(--oh-text-dim)]\">\n {t(I18nKey.NAV$COMING_SOON)}\n </span>\n );\n\n if (isCloudSkillsLink) {\n const cloudSkillsUrl = `${backend.host.replace(/\\/+$/, \"\")}/settings/skills`;\n return (\n <a\n key={item.to}\n data-testid={`sidebar-extensions-${item.to}`}\n href={cloudSkillsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n sidebarNavRowClassName(),\n \"truncate\",\n SIDEBAR_ROW_INTERACTIVE_CLASS.idle,\n )}\n >\n {baseRow}\n {label}\n <ExternalLink\n className=\"ml-auto size-4 shrink-0 text-[var(--oh-muted)]\"\n aria-hidden\n />\n </a>\n );\n }\n\n return (\n <NavigationLink\n key={item.to}\n to={item.to}\n end={item.end}\n data-testid={`sidebar-extensions-${item.to}`}\n className={({ isActive }) =>\n cn(\n sidebarNavRowClassName(),\n \"truncate\",\n isActive\n ? SIDEBAR_ROW_INTERACTIVE_CLASS.active\n : SIDEBAR_ROW_INTERACTIVE_CLASS.idle,\n )\n }\n >\n {baseRow}\n {label}\n {comingSoonBadge}\n </NavigationLink>\n );\n })}\n </div>\n <div className=\"px-2 pt-3\">\n <BackendSyncedSettingsBadge />\n </div>\n </aside>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAM,IAA8B,WAE9B,IAA8B,YAUvB,IAA2C;CACtD;EACE,IAAI;EACJ,OAAO;EACP,MAAM,kBAAC,GAAD;GAAmB,OAAO;GAAI,QAAQ;EAAK,CAAA;EACjD,KAAK;CACP;CACA;EACE,IAAI;EACJ,OAAO;EACP,MAAM,kBAAC,GAAD;GAAY,OAAO;GAAI,QAAQ;GAAI,eAAY;EAAQ,CAAA;EAC7D,KAAK;CACP;CACA;EACE,IAAI;EACJ,OAAO;EACP,MACE,kBAAC,OAAD;GACE,OAAM;GACN,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;GACf,OAAO;GACP,QAAQ;GACR,eAAY;aAVd;IAYE,kBAAC,QAAD,EAAM,GAAE,yHAA0H,CAAA;IAClI,kBAAC,QAAD,EAAM,GAAE,qBAAsB,CAAA;IAC9B,kBAAC,QAAD,EAAM,GAAE,YAAa,CAAA;GAClB;;EAEP,KAAK;CACP;AACF;AAEA,SAAgB,IAAuB;CACrC,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,EAAE,cAAW,EAAwB,GACrC,EAAE,eAAY,GACd,IAAiB,CAAC,EAAY,CAAO,KAAK,EAAQ,SAAS;CAEjE,OACE,kBAAC,SAAD;EACE,eAAY;EACZ,WAAU;YAFZ;GAIE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAE,EAAQ,aAAa;GACpB,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAqB,QACnB,MACC,EAAE,EAAK,OAAO,KAA+B,EACjD,EAAE,KAAK,MAAS;KACd,IAAM,IACJ,EAAK,OAAO,KAA+B,GACvC,IACJ,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAK;KACF,CAAA,GAEF,IACJ,kBAAC,QAAD;MAAM,WAAU;gBACb,IACG,EAAE,EAAQ,qCAAqC,IAC/C,EAAK;KACL,CAAA,GAEF,IAAkB,EAAK,cAC3B,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAE,EAAQ,eAAe;KACtB,CAAA;KAGR,IAAI,GAAmB;MACrB,IAAM,IAAiB,GAAG,EAAQ,KAAK,QAAQ,QAAQ,EAAE,EAAE;MAC3D,OACE,kBAAC,KAAD;OAEE,eAAa,sBAAsB,EAAK;OACxC,MAAM;OACN,QAAO;OACP,KAAI;OACJ,WAAW,EACT,EAAuB,GACvB,YACA,EAA8B,IAChC;iBAVF;QAYG;QACA;QACD,kBAAC,GAAD;SACE,WAAU;SACV,eAAA;QACD,CAAA;OACA;SAjBI,EAAK,EAiBT;KAEP;KAEA,OACE,kBAAC,GAAD;MAEE,IAAI,EAAK;MACT,KAAK,EAAK;MACV,eAAa,sBAAsB,EAAK;MACxC,YAAY,EAAE,kBACZ,EACE,EAAuB,GACvB,YACA,IACI,EAA8B,SAC9B,EAA8B,IACpC;gBAZJ;OAeG;OACA;OACA;MACa;QAjBT,EAAK,EAiBI;IAEpB,CAAC;GACE,CAAA;GACL,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,CAA6B,CAAA;GAC1B,CAAA;EACA;;AAEX"}
@@ -1,2 +1,2 @@
1
- const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../utils/constants.cjs"),i=require("../../../../utils/utils.cjs"),a=require("../../../../utils/form-control-classes.cjs"),o=require("../../../../node_modules/@heroui/listbox/dist/chunk-BJFJ4DRR.cjs"),s=require("../../../../node_modules/@heroui/listbox/dist/chunk-ANTZPR32.cjs"),c=require("../../../../node_modules/@heroui/autocomplete/dist/chunk-3QKDXXDY.cjs"),l=require("../../../../ui/combobox-caret.cjs"),u=require("../../../../utils/map-provider.cjs"),d=require("../../../../utils/extract-model-and-provider.cjs"),f=require("../../../../ui/help-link.cjs"),p=require("../../../../hooks/query/use-search-providers.cjs"),m=require("../../../../hooks/query/use-provider-models.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");function _({isDisabled:e,currentModel:_,onChange:v,onDefaultValuesChanged:y,wrapperClassName:b,labelClassName:x}){let[,S]=h.default.useState(null),[C,w]=h.default.useState(null),[T,E]=h.default.useState(null),{data:D=[]}=p.useSearchProviders(),{data:O=[],isLoading:k,error:A}=m.useProviderModels(C),j=h.default.useMemo(()=>D.filter(e=>e.verified),[D]),M=h.default.useMemo(()=>D.filter(e=>!e.verified),[D]),N=h.default.useMemo(()=>O.filter(e=>e.verified),[O]),P=h.default.useMemo(()=>O.filter(e=>!e.verified),[O]);h.default.useEffect(()=>{if(_){let{provider:e,model:t}=d.extractModelAndProvider(_);S(_),w(e||null),E(t),y?.(e||null,t)}},[_]);let F=e=>{w(e),E(null),S(`${e}/`),v?.(e,null)},I=e=>{let t=`${C}/${e}`;C===`openai`&&(t=e),S(t),E(e),v?.(C,e)},L=()=>{w(null),S(null)},{t:R}=t.useTranslation(`openhands`);return(0,g.jsxs)(`div`,{className:i.cn(`flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]`,b),children:[(0,g.jsxs)(`fieldset`,{className:`flex flex-col gap-2.5 w-full`,children:[(0,g.jsx)(`label`,{className:i.cn(`text-sm`,x),children:R(n.I18nKey.LLM$PROVIDER)}),(0,g.jsxs)(c.autocomplete_default,{"data-testid":`llm-provider-input`,isRequired:!0,isVirtualized:!1,name:`llm-provider-input`,isDisabled:e,"aria-label":R(n.I18nKey.LLM$PROVIDER),isClearable:!1,onSelectionChange:e=>{e?.toString()&&F(e.toString())},onInputChange:e=>!e&&L(),defaultSelectedKey:C??void 0,selectedKey:C,classNames:{popoverContent:`bg-content1 rounded-xl border border-[var(--oh-border)]`,selectorButton:l.heroUiAutocompleteSelectorButtonClassName},selectorButtonProps:{disableRipple:!0},inputProps:{classNames:{inputWrapper:a.formControlSettingsFieldClassName}},children:[(0,g.jsx)(s.listbox_section_base_default,{title:R(n.I18nKey.MODEL_SELECTOR$VERIFIED),classNames:{heading:`text-[var(--oh-muted)]`},children:j.map(e=>(0,g.jsx)(o.listbox_item_base_default,{"data-testid":`provider-item-${e.name}`,children:u.mapProvider(e.name)},e.name))}),M.length>0?(0,g.jsx)(s.listbox_section_base_default,{title:R(n.I18nKey.MODEL_SELECTOR$OTHERS),classNames:{heading:`text-[var(--oh-muted)]`},children:M.map(e=>(0,g.jsx)(o.listbox_item_base_default,{children:u.mapProvider(e.name)},e.name))}):null]})]}),C===`openhands`&&(0,g.jsx)(f.HelpLink,{testId:`openhands-account-help`,text:R(n.I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT),linkText:R(n.I18nKey.SETTINGS$CLICK_HERE),href:r.PRODUCT_URL.PRODUCTION,size:`settings`,linkColor:`white`}),(0,g.jsxs)(`fieldset`,{className:`flex flex-col gap-2.5 w-full`,children:[(0,g.jsx)(`label`,{className:i.cn(`text-sm`,x),children:R(n.I18nKey.LLM$MODEL)}),(0,g.jsxs)(c.autocomplete_default,{"data-testid":`llm-model-input`,isRequired:!0,isVirtualized:!1,isLoading:k,name:`llm-model-input`,"aria-label":R(n.I18nKey.LLM$MODEL),isClearable:!1,onSelectionChange:e=>{e?.toString()&&I(e.toString())},isDisabled:e||!C,selectedKey:T,defaultSelectedKey:T??void 0,classNames:{popoverContent:`bg-content1 rounded-xl border border-[var(--oh-border)]`,selectorButton:l.heroUiAutocompleteSelectorButtonClassName},selectorButtonProps:{disableRipple:!0},inputProps:{classNames:{inputWrapper:a.formControlSettingsFieldClassName}},children:[(0,g.jsx)(s.listbox_section_base_default,{title:R(n.I18nKey.MODEL_SELECTOR$VERIFIED),classNames:{heading:`text-[var(--oh-muted)]`},children:N.map(e=>(0,g.jsx)(o.listbox_item_base_default,{children:e.name},e.name))}),P.length>0?(0,g.jsx)(s.listbox_section_base_default,{title:R(n.I18nKey.MODEL_SELECTOR$OTHERS),classNames:{heading:`text-[var(--oh-muted)]`},children:P.map(e=>(0,g.jsx)(o.listbox_item_base_default,{"data-testid":`model-item-${e.name}`,children:e.name},e.name))}):null]}),A&&(0,g.jsx)(`p`,{"data-testid":`models-error`,className:`text-danger text-xs`,children:R(n.I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)})]})]})}exports.ModelSelector=_;
1
+ const e=require("../../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../../i18n/declaration.cjs"),r=require("../../../../node_modules/lucide-react/dist/esm/icons/info.cjs"),i=require("../../../../utils/constants.cjs"),a=require("../../../../utils/utils.cjs"),o=require("../../../../utils/form-control-classes.cjs"),s=require("../../../../utils/format-model-name.cjs"),c=require("../../../../node_modules/@heroui/listbox/dist/chunk-BJFJ4DRR.cjs"),l=require("../../../../node_modules/@heroui/listbox/dist/chunk-ANTZPR32.cjs"),u=require("../../../../node_modules/@heroui/autocomplete/dist/chunk-3QKDXXDY.cjs"),d=require("../../../../ui/combobox-caret.cjs"),f=require("../../../../utils/map-provider.cjs"),p=require("../../../../utils/extract-model-and-provider.cjs"),m=require("../../../../ui/help-link.cjs"),h=require("../../../../hooks/query/use-search-providers.cjs"),g=require("../../../../hooks/query/use-provider-models.cjs");let _=require("react");_=e.__toESM(_,1);let v=require("react/jsx-runtime");var y=`shrink-0 rounded-full border border-warning/40 bg-warning/10 px-1.5 py-0.5 text-[10px] leading-none text-warning`;function b(){return(0,v.jsxs)(`p`,{"data-testid":`openhands-free-models-note`,className:`flex items-start gap-2 text-xs text-warning`,children:[(0,v.jsx)(r.Info,{className:`mt-0.5 size-4 shrink-0 text-warning`,"aria-hidden":!0}),(0,v.jsx)(`span`,{children:s.FREE_OPENHANDS_MODEL_NOTE})]})}function x({isDisabled:e,currentModel:r,onChange:x,onDefaultValuesChanged:S,wrapperClassName:C,labelClassName:w}){let[,T]=_.default.useState(null),[E,D]=_.default.useState(null),[O,k]=_.default.useState(null),{data:A=[]}=h.useSearchProviders(),{data:j=[],isLoading:M,error:N}=g.useProviderModels(E),P=_.default.useMemo(()=>A.filter(e=>e.verified),[A]),F=_.default.useMemo(()=>A.filter(e=>!e.verified),[A]),I=_.default.useMemo(()=>j.filter(e=>e.verified),[j]),L=_.default.useMemo(()=>j.filter(e=>!e.verified),[j]);_.default.useEffect(()=>{if(r){let{provider:e,model:t}=p.extractModelAndProvider(r);T(r),D(e||null),k(t),S?.(e||null,t)}},[r]);let R=e=>{D(e),k(null),T(`${e}/`),x?.(e,null)},z=e=>{let t=`${E}/${e}`;E===`openai`&&(t=e),T(t),k(e),x?.(E,e)},B=()=>{D(null),T(null)},V=s.isFreeOpenHandsModel(E&&O?`${E}/${O}`:null),H=_.default.useRef(null),[U,W]=_.default.useState(0);_.default.useLayoutEffect(()=>{if(!V||!H.current){W(0);return}let e=()=>{W(Math.ceil(H.current?.getBoundingClientRect().width??0))};if(e(),typeof ResizeObserver>`u`)return;let t=new ResizeObserver(e);return t.observe(H.current),()=>t.disconnect()},[V,O]);let{t:G}=t.useTranslation(`openhands`);return(0,v.jsxs)(`div`,{className:a.cn(`flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]`,C),children:[(0,v.jsxs)(`fieldset`,{className:`flex flex-col gap-2.5 w-full`,children:[(0,v.jsx)(`label`,{className:a.cn(`text-sm`,w),children:G(n.I18nKey.LLM$PROVIDER)}),(0,v.jsxs)(u.autocomplete_default,{"data-testid":`llm-provider-input`,isRequired:!0,isVirtualized:!1,name:`llm-provider-input`,isDisabled:e,"aria-label":G(n.I18nKey.LLM$PROVIDER),isClearable:!1,onSelectionChange:e=>{e?.toString()&&R(e.toString())},onInputChange:e=>!e&&B(),defaultSelectedKey:E??void 0,selectedKey:E,classNames:{popoverContent:`bg-content1 rounded-xl border border-[var(--oh-border)]`,selectorButton:d.heroUiAutocompleteSelectorButtonClassName},selectorButtonProps:{disableRipple:!0},inputProps:{classNames:{inputWrapper:o.formControlSettingsFieldClassName}},children:[(0,v.jsx)(l.listbox_section_base_default,{title:G(n.I18nKey.MODEL_SELECTOR$VERIFIED),classNames:{heading:`text-[var(--oh-muted)]`},children:P.map(e=>(0,v.jsx)(c.listbox_item_base_default,{"data-testid":`provider-item-${e.name}`,children:f.mapProvider(e.name)},e.name))}),F.length>0?(0,v.jsx)(l.listbox_section_base_default,{title:G(n.I18nKey.MODEL_SELECTOR$OTHERS),classNames:{heading:`text-[var(--oh-muted)]`},children:F.map(e=>(0,v.jsx)(c.listbox_item_base_default,{children:f.mapProvider(e.name)},e.name))}):null]})]}),E===`openhands`&&(0,v.jsx)(`div`,{className:`flex flex-col gap-2`,children:(0,v.jsx)(m.HelpLink,{testId:`openhands-account-help`,text:G(n.I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT),linkText:G(n.I18nKey.SETTINGS$CLICK_HERE),href:i.PRODUCT_URL.PRODUCTION,size:`settings`,linkColor:`white`})}),(0,v.jsxs)(`fieldset`,{className:`flex flex-col gap-2.5 w-full`,children:[(0,v.jsx)(`label`,{className:a.cn(`text-sm`,w),children:G(n.I18nKey.LLM$MODEL)}),(0,v.jsxs)(`div`,{className:`relative`,children:[(0,v.jsxs)(u.autocomplete_default,{"data-testid":`llm-model-input`,isRequired:!0,isVirtualized:!1,isLoading:M,name:`llm-model-input`,"aria-label":G(n.I18nKey.LLM$MODEL),isClearable:!1,onSelectionChange:e=>{e?.toString()&&z(e.toString())},isDisabled:e||!E,selectedKey:O,defaultSelectedKey:O??void 0,classNames:{popoverContent:`bg-content1 rounded-xl border border-[var(--oh-border)]`,selectorButton:d.heroUiAutocompleteSelectorButtonClassName},selectorButtonProps:{disableRipple:!0},inputProps:{classNames:{inputWrapper:o.formControlSettingsFieldClassName}},children:[(0,v.jsx)(l.listbox_section_base_default,{title:G(n.I18nKey.MODEL_SELECTOR$VERIFIED),classNames:{heading:`text-[var(--oh-muted)]`},children:I.map(e=>(0,v.jsx)(c.listbox_item_base_default,{textValue:e.name,children:(0,v.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2`,children:[(0,v.jsx)(`span`,{className:`truncate`,children:e.name}),s.isFreeOpenHandsModel(`${E}/${e.name}`)?(0,v.jsx)(`span`,{className:y,children:s.FREE_MODEL_BADGE_LABEL}):null]})},e.name))}),L.length>0?(0,v.jsx)(l.listbox_section_base_default,{title:G(n.I18nKey.MODEL_SELECTOR$OTHERS),classNames:{heading:`text-[var(--oh-muted)]`},children:L.map(e=>(0,v.jsx)(c.listbox_item_base_default,{"data-testid":`model-item-${e.name}`,textValue:e.name,children:e.name},e.name))}):null]}),V&&O?(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(`span`,{ref:H,className:`pointer-events-none absolute left-3 top-1/2 whitespace-pre text-sm opacity-0`,"aria-hidden":!0,children:O}),(0,v.jsx)(`span`,{"data-testid":`selected-free-model-badge`,className:a.cn(y,`pointer-events-none absolute top-1/2 z-10 -translate-y-1/2`),style:{left:`calc(0.75rem + ${U}px + 0.5rem)`},children:s.FREE_MODEL_BADGE_LABEL})]}):null]}),N&&(0,v.jsx)(`p`,{"data-testid":`models-error`,className:`text-danger text-xs`,children:G(n.I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)}),E===`openhands`?(0,v.jsx)(b,{}):null]})]})}exports.ModelSelector=x;
2
2
  //# sourceMappingURL=model-selector.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-selector.cjs","names":[],"sources":["../../../../../src/components/shared/modals/settings/model-selector.tsx"],"sourcesContent":["import {\n Autocomplete,\n AutocompleteItem,\n AutocompleteSection,\n} from \"@heroui/react\";\nimport React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { mapProvider } from \"#/utils/map-provider\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { cn } from \"#/utils/utils\";\nimport { formControlSettingsFieldClassName } from \"#/utils/form-control-classes\";\nimport { heroUiAutocompleteSelectorButtonClassName } from \"#/ui/combobox-caret\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { useSearchProviders } from \"#/hooks/query/use-search-providers\";\nimport { useProviderModels } from \"#/hooks/query/use-provider-models\";\n\ninterface ModelSelectorProps {\n isDisabled?: boolean;\n currentModel?: string;\n onChange?: (provider: string | null, model: string | null) => void;\n onDefaultValuesChanged?: (\n provider: string | null,\n model: string | null,\n ) => void;\n wrapperClassName?: string;\n labelClassName?: string;\n}\n\nexport function ModelSelector({\n isDisabled,\n currentModel,\n onChange,\n onDefaultValuesChanged,\n wrapperClassName,\n labelClassName,\n}: ModelSelectorProps) {\n const [, setLitellmId] = React.useState<string | null>(null);\n const [selectedProvider, setSelectedProvider] = React.useState<string | null>(\n null,\n );\n const [selectedModel, setSelectedModel] = React.useState<string | null>(null);\n\n const { data: providers = [] } = useSearchProviders();\n const {\n data: providerModels = [],\n isLoading: isLoadingModels,\n error: modelsError,\n } = useProviderModels(selectedProvider);\n\n const verifiedProviders = React.useMemo(\n () => providers.filter((p) => p.verified),\n [providers],\n );\n const unverifiedProviders = React.useMemo(\n () => providers.filter((p) => !p.verified),\n [providers],\n );\n\n const verifiedModels = React.useMemo(\n () => providerModels.filter((m) => m.verified),\n [providerModels],\n );\n const unverifiedModels = React.useMemo(\n () => providerModels.filter((m) => !m.verified),\n [providerModels],\n );\n\n React.useEffect(() => {\n if (currentModel) {\n const { provider, model } = extractModelAndProvider(currentModel);\n\n setLitellmId(currentModel);\n setSelectedProvider(provider || null);\n setSelectedModel(model);\n onDefaultValuesChanged?.(provider || null, model);\n }\n }, [currentModel]);\n\n const handleChangeProvider = (provider: string) => {\n setSelectedProvider(provider);\n setSelectedModel(null);\n setLitellmId(`${provider}/`);\n onChange?.(provider, null);\n };\n\n const handleChangeModel = (model: string) => {\n let fullModel = `${selectedProvider}/${model}`;\n if (selectedProvider === \"openai\") {\n fullModel = model;\n }\n setLitellmId(fullModel);\n setSelectedModel(model);\n onChange?.(selectedProvider, model);\n };\n\n const clear = () => {\n setSelectedProvider(null);\n setLitellmId(null);\n };\n\n const { t } = useTranslation(\"openhands\");\n\n return (\n <div\n className={cn(\n \"flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]\",\n wrapperClassName,\n )}\n >\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$PROVIDER)}\n </label>\n <Autocomplete\n data-testid=\"llm-provider-input\"\n isRequired\n isVirtualized={false}\n name=\"llm-provider-input\"\n isDisabled={isDisabled}\n aria-label={t(I18nKey.LLM$PROVIDER)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeProvider(e.toString());\n }}\n onInputChange={(value) => !value && clear()}\n defaultSelectedKey={selectedProvider ?? undefined}\n selectedKey={selectedProvider}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedProviders.map((provider) => (\n <AutocompleteItem\n data-testid={`provider-item-${provider.name}`}\n key={provider.name}\n >\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedProviders.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedProviders.map((provider) => (\n <AutocompleteItem key={provider.name}>\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n </fieldset>\n\n {selectedProvider === \"openhands\" && (\n <HelpLink\n testId=\"openhands-account-help\"\n text={t(I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT)}\n linkText={t(I18nKey.SETTINGS$CLICK_HERE)}\n href={PRODUCT_URL.PRODUCTION}\n size=\"settings\"\n linkColor=\"white\"\n />\n )}\n\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$MODEL)}\n </label>\n <Autocomplete\n data-testid=\"llm-model-input\"\n isRequired\n isVirtualized={false}\n isLoading={isLoadingModels}\n name=\"llm-model-input\"\n aria-label={t(I18nKey.LLM$MODEL)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeModel(e.toString());\n }}\n isDisabled={isDisabled || !selectedProvider}\n selectedKey={selectedModel}\n defaultSelectedKey={selectedModel ?? undefined}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedModels.map((model) => (\n <AutocompleteItem key={model.name}>{model.name}</AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedModels.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedModels.map((model) => (\n <AutocompleteItem\n data-testid={`model-item-${model.name}`}\n key={model.name}\n >\n {model.name}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n {modelsError && (\n <p data-testid=\"models-error\" className=\"text-danger text-xs\">\n {t(I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)}\n </p>\n )}\n </fieldset>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model-selector.cjs","names":[],"sources":["../../../../../src/components/shared/modals/settings/model-selector.tsx"],"sourcesContent":["import {\n Autocomplete,\n AutocompleteItem,\n AutocompleteSection,\n} from \"@heroui/react\";\nimport { Info } from \"lucide-react\";\nimport React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { mapProvider } from \"#/utils/map-provider\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { cn } from \"#/utils/utils\";\nimport { formControlSettingsFieldClassName } from \"#/utils/form-control-classes\";\nimport { heroUiAutocompleteSelectorButtonClassName } from \"#/ui/combobox-caret\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { useSearchProviders } from \"#/hooks/query/use-search-providers\";\nimport { useProviderModels } from \"#/hooks/query/use-provider-models\";\nimport {\n FREE_MODEL_BADGE_LABEL,\n FREE_OPENHANDS_MODEL_NOTE,\n isFreeOpenHandsModel,\n} from \"#/utils/format-model-name\";\n\nconst freeModelBadgeClassName =\n \"shrink-0 rounded-full border border-warning/40 bg-warning/10 px-1.5 py-0.5 text-[10px] leading-none text-warning\";\n\nfunction FreeOpenHandsModelsNote() {\n return (\n <p\n data-testid=\"openhands-free-models-note\"\n className=\"flex items-start gap-2 text-xs text-warning\"\n >\n <Info className=\"mt-0.5 size-4 shrink-0 text-warning\" aria-hidden />\n <span>{FREE_OPENHANDS_MODEL_NOTE}</span>\n </p>\n );\n}\n\ninterface ModelSelectorProps {\n isDisabled?: boolean;\n currentModel?: string;\n onChange?: (provider: string | null, model: string | null) => void;\n onDefaultValuesChanged?: (\n provider: string | null,\n model: string | null,\n ) => void;\n wrapperClassName?: string;\n labelClassName?: string;\n}\n\nexport function ModelSelector({\n isDisabled,\n currentModel,\n onChange,\n onDefaultValuesChanged,\n wrapperClassName,\n labelClassName,\n}: ModelSelectorProps) {\n const [, setLitellmId] = React.useState<string | null>(null);\n const [selectedProvider, setSelectedProvider] = React.useState<string | null>(\n null,\n );\n const [selectedModel, setSelectedModel] = React.useState<string | null>(null);\n\n const { data: providers = [] } = useSearchProviders();\n const {\n data: providerModels = [],\n isLoading: isLoadingModels,\n error: modelsError,\n } = useProviderModels(selectedProvider);\n\n const verifiedProviders = React.useMemo(\n () => providers.filter((p) => p.verified),\n [providers],\n );\n const unverifiedProviders = React.useMemo(\n () => providers.filter((p) => !p.verified),\n [providers],\n );\n\n const verifiedModels = React.useMemo(\n () => providerModels.filter((m) => m.verified),\n [providerModels],\n );\n const unverifiedModels = React.useMemo(\n () => providerModels.filter((m) => !m.verified),\n [providerModels],\n );\n\n React.useEffect(() => {\n if (currentModel) {\n const { provider, model } = extractModelAndProvider(currentModel);\n\n setLitellmId(currentModel);\n setSelectedProvider(provider || null);\n setSelectedModel(model);\n onDefaultValuesChanged?.(provider || null, model);\n }\n }, [currentModel]);\n\n const handleChangeProvider = (provider: string) => {\n setSelectedProvider(provider);\n setSelectedModel(null);\n setLitellmId(`${provider}/`);\n onChange?.(provider, null);\n };\n\n const handleChangeModel = (model: string) => {\n let fullModel = `${selectedProvider}/${model}`;\n if (selectedProvider === \"openai\") {\n fullModel = model;\n }\n setLitellmId(fullModel);\n setSelectedModel(model);\n onChange?.(selectedProvider, model);\n };\n\n const clear = () => {\n setSelectedProvider(null);\n setLitellmId(null);\n };\n\n const selectedFullModel =\n selectedProvider && selectedModel\n ? `${selectedProvider}/${selectedModel}`\n : null;\n const isSelectedModelFree = isFreeOpenHandsModel(selectedFullModel);\n const selectedModelMeasureRef = React.useRef<HTMLSpanElement>(null);\n const [selectedModelTextWidth, setSelectedModelTextWidth] = React.useState(0);\n\n React.useLayoutEffect(() => {\n if (!isSelectedModelFree || !selectedModelMeasureRef.current) {\n setSelectedModelTextWidth(0);\n return undefined;\n }\n\n const measureSelectedModel = () => {\n setSelectedModelTextWidth(\n Math.ceil(\n selectedModelMeasureRef.current?.getBoundingClientRect().width ?? 0,\n ),\n );\n };\n measureSelectedModel();\n\n if (typeof ResizeObserver === \"undefined\") {\n return undefined;\n }\n\n const observer = new ResizeObserver(measureSelectedModel);\n observer.observe(selectedModelMeasureRef.current);\n return () => observer.disconnect();\n }, [isSelectedModelFree, selectedModel]);\n\n const { t } = useTranslation(\"openhands\");\n\n return (\n <div\n className={cn(\n \"flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]\",\n wrapperClassName,\n )}\n >\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$PROVIDER)}\n </label>\n <Autocomplete\n data-testid=\"llm-provider-input\"\n isRequired\n isVirtualized={false}\n name=\"llm-provider-input\"\n isDisabled={isDisabled}\n aria-label={t(I18nKey.LLM$PROVIDER)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeProvider(e.toString());\n }}\n onInputChange={(value) => !value && clear()}\n defaultSelectedKey={selectedProvider ?? undefined}\n selectedKey={selectedProvider}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedProviders.map((provider) => (\n <AutocompleteItem\n data-testid={`provider-item-${provider.name}`}\n key={provider.name}\n >\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedProviders.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedProviders.map((provider) => (\n <AutocompleteItem key={provider.name}>\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n </fieldset>\n\n {selectedProvider === \"openhands\" && (\n <div className=\"flex flex-col gap-2\">\n <HelpLink\n testId=\"openhands-account-help\"\n text={t(I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT)}\n linkText={t(I18nKey.SETTINGS$CLICK_HERE)}\n href={PRODUCT_URL.PRODUCTION}\n size=\"settings\"\n linkColor=\"white\"\n />\n </div>\n )}\n\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$MODEL)}\n </label>\n <div className=\"relative\">\n <Autocomplete\n data-testid=\"llm-model-input\"\n isRequired\n isVirtualized={false}\n isLoading={isLoadingModels}\n name=\"llm-model-input\"\n aria-label={t(I18nKey.LLM$MODEL)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeModel(e.toString());\n }}\n isDisabled={isDisabled || !selectedProvider}\n selectedKey={selectedModel}\n defaultSelectedKey={selectedModel ?? undefined}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedModels.map((model) => (\n <AutocompleteItem key={model.name} textValue={model.name}>\n <span className=\"flex min-w-0 items-center gap-2\">\n <span className=\"truncate\">{model.name}</span>\n {isFreeOpenHandsModel(\n `${selectedProvider}/${model.name}`,\n ) ? (\n <span className={freeModelBadgeClassName}>\n {FREE_MODEL_BADGE_LABEL}\n </span>\n ) : null}\n </span>\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedModels.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedModels.map((model) => (\n <AutocompleteItem\n data-testid={`model-item-${model.name}`}\n key={model.name}\n textValue={model.name}\n >\n {model.name}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n {isSelectedModelFree && selectedModel ? (\n <>\n <span\n ref={selectedModelMeasureRef}\n className=\"pointer-events-none absolute left-3 top-1/2 whitespace-pre text-sm opacity-0\"\n aria-hidden\n >\n {selectedModel}\n </span>\n <span\n data-testid=\"selected-free-model-badge\"\n className={cn(\n freeModelBadgeClassName,\n \"pointer-events-none absolute top-1/2 z-10 -translate-y-1/2\",\n )}\n style={{\n left: `calc(0.75rem + ${selectedModelTextWidth}px + 0.5rem)`,\n }}\n >\n {FREE_MODEL_BADGE_LABEL}\n </span>\n </>\n ) : null}\n </div>\n {modelsError && (\n <p data-testid=\"models-error\" className=\"text-danger text-xs\">\n {t(I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)}\n </p>\n )}\n {selectedProvider === \"openhands\" ? <FreeOpenHandsModelsNote /> : null}\n </fieldset>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,137 +1,193 @@
1
1
  import { useTranslation as e } from "../../../../node_modules/react-i18next/dist/es/useTranslation.js";
2
2
  import { I18nKey as t } from "../../../../i18n/declaration.js";
3
- import { PRODUCT_URL as n } from "../../../../utils/constants.js";
4
- import { cn as r } from "../../../../utils/utils.js";
5
- import { formControlSettingsFieldClassName as i } from "../../../../utils/form-control-classes.js";
6
- import { listbox_item_base_default as a } from "../../../../node_modules/@heroui/listbox/dist/chunk-BJFJ4DRR.js";
7
- import { listbox_section_base_default as o } from "../../../../node_modules/@heroui/listbox/dist/chunk-ANTZPR32.js";
8
- import { autocomplete_default as s } from "../../../../node_modules/@heroui/autocomplete/dist/chunk-3QKDXXDY.js";
9
- import { heroUiAutocompleteSelectorButtonClassName as c } from "../../../../ui/combobox-caret.js";
10
- import { mapProvider as l } from "../../../../utils/map-provider.js";
11
- import { extractModelAndProvider as u } from "../../../../utils/extract-model-and-provider.js";
12
- import { HelpLink as d } from "../../../../ui/help-link.js";
13
- import { useSearchProviders as f } from "../../../../hooks/query/use-search-providers.js";
14
- import { useProviderModels as p } from "../../../../hooks/query/use-provider-models.js";
15
- import m from "react";
16
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
3
+ import { Info as n } from "../../../../node_modules/lucide-react/dist/esm/icons/info.js";
4
+ import { PRODUCT_URL as r } from "../../../../utils/constants.js";
5
+ import { cn as i } from "../../../../utils/utils.js";
6
+ import { formControlSettingsFieldClassName as a } from "../../../../utils/form-control-classes.js";
7
+ import { FREE_MODEL_BADGE_LABEL as o, FREE_OPENHANDS_MODEL_NOTE as s, isFreeOpenHandsModel as c } from "../../../../utils/format-model-name.js";
8
+ import { listbox_item_base_default as l } from "../../../../node_modules/@heroui/listbox/dist/chunk-BJFJ4DRR.js";
9
+ import { listbox_section_base_default as u } from "../../../../node_modules/@heroui/listbox/dist/chunk-ANTZPR32.js";
10
+ import { autocomplete_default as d } from "../../../../node_modules/@heroui/autocomplete/dist/chunk-3QKDXXDY.js";
11
+ import { heroUiAutocompleteSelectorButtonClassName as f } from "../../../../ui/combobox-caret.js";
12
+ import { mapProvider as p } from "../../../../utils/map-provider.js";
13
+ import { extractModelAndProvider as m } from "../../../../utils/extract-model-and-provider.js";
14
+ import { HelpLink as h } from "../../../../ui/help-link.js";
15
+ import { useSearchProviders as g } from "../../../../hooks/query/use-search-providers.js";
16
+ import { useProviderModels as _ } from "../../../../hooks/query/use-provider-models.js";
17
+ import v from "react";
18
+ import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
17
19
  //#region src/components/shared/modals/settings/model-selector.tsx
18
- function _({ isDisabled: _, currentModel: v, onChange: y, onDefaultValuesChanged: b, wrapperClassName: x, labelClassName: S }) {
19
- let [, C] = m.useState(null), [w, T] = m.useState(null), [E, D] = m.useState(null), { data: O = [] } = f(), { data: k = [], isLoading: A, error: j } = p(w), M = m.useMemo(() => O.filter((e) => e.verified), [O]), N = m.useMemo(() => O.filter((e) => !e.verified), [O]), P = m.useMemo(() => k.filter((e) => e.verified), [k]), F = m.useMemo(() => k.filter((e) => !e.verified), [k]);
20
- m.useEffect(() => {
21
- if (v) {
22
- let { provider: e, model: t } = u(v);
23
- C(v), T(e || null), D(t), b?.(e || null, t);
20
+ var S = "shrink-0 rounded-full border border-warning/40 bg-warning/10 px-1.5 py-0.5 text-[10px] leading-none text-warning";
21
+ function C() {
22
+ return /* @__PURE__ */ x("p", {
23
+ "data-testid": "openhands-free-models-note",
24
+ className: "flex items-start gap-2 text-xs text-warning",
25
+ children: [/* @__PURE__ */ b(n, {
26
+ className: "mt-0.5 size-4 shrink-0 text-warning",
27
+ "aria-hidden": !0
28
+ }), /* @__PURE__ */ b("span", { children: s })]
29
+ });
30
+ }
31
+ function w({ isDisabled: n, currentModel: s, onChange: w, onDefaultValuesChanged: T, wrapperClassName: E, labelClassName: D }) {
32
+ let [, O] = v.useState(null), [k, A] = v.useState(null), [j, M] = v.useState(null), { data: N = [] } = g(), { data: P = [], isLoading: F, error: I } = _(k), L = v.useMemo(() => N.filter((e) => e.verified), [N]), R = v.useMemo(() => N.filter((e) => !e.verified), [N]), z = v.useMemo(() => P.filter((e) => e.verified), [P]), B = v.useMemo(() => P.filter((e) => !e.verified), [P]);
33
+ v.useEffect(() => {
34
+ if (s) {
35
+ let { provider: e, model: t } = m(s);
36
+ O(s), A(e || null), M(t), T?.(e || null, t);
24
37
  }
25
- }, [v]);
26
- let I = (e) => {
27
- T(e), D(null), C(`${e}/`), y?.(e, null);
28
- }, L = (e) => {
29
- let t = `${w}/${e}`;
30
- w === "openai" && (t = e), C(t), D(e), y?.(w, e);
31
- }, R = () => {
32
- T(null), C(null);
33
- }, { t: z } = e("openhands");
34
- return /* @__PURE__ */ g("div", {
35
- className: r("flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]", x),
38
+ }, [s]);
39
+ let V = (e) => {
40
+ A(e), M(null), O(`${e}/`), w?.(e, null);
41
+ }, H = (e) => {
42
+ let t = `${k}/${e}`;
43
+ k === "openai" && (t = e), O(t), M(e), w?.(k, e);
44
+ }, U = () => {
45
+ A(null), O(null);
46
+ }, W = c(k && j ? `${k}/${j}` : null), G = v.useRef(null), [K, q] = v.useState(0);
47
+ v.useLayoutEffect(() => {
48
+ if (!W || !G.current) {
49
+ q(0);
50
+ return;
51
+ }
52
+ let e = () => {
53
+ q(Math.ceil(G.current?.getBoundingClientRect().width ?? 0));
54
+ };
55
+ if (e(), typeof ResizeObserver > "u") return;
56
+ let t = new ResizeObserver(e);
57
+ return t.observe(G.current), () => t.disconnect();
58
+ }, [W, j]);
59
+ let { t: J } = e("openhands");
60
+ return /* @__PURE__ */ x("div", {
61
+ className: i("flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]", E),
36
62
  children: [
37
- /* @__PURE__ */ g("fieldset", {
63
+ /* @__PURE__ */ x("fieldset", {
38
64
  className: "flex flex-col gap-2.5 w-full",
39
- children: [/* @__PURE__ */ h("label", {
40
- className: r("text-sm", S),
41
- children: z(t.LLM$PROVIDER)
42
- }), /* @__PURE__ */ g(s, {
65
+ children: [/* @__PURE__ */ b("label", {
66
+ className: i("text-sm", D),
67
+ children: J(t.LLM$PROVIDER)
68
+ }), /* @__PURE__ */ x(d, {
43
69
  "data-testid": "llm-provider-input",
44
70
  isRequired: !0,
45
71
  isVirtualized: !1,
46
72
  name: "llm-provider-input",
47
- isDisabled: _,
48
- "aria-label": z(t.LLM$PROVIDER),
73
+ isDisabled: n,
74
+ "aria-label": J(t.LLM$PROVIDER),
49
75
  isClearable: !1,
50
76
  onSelectionChange: (e) => {
51
- e?.toString() && I(e.toString());
77
+ e?.toString() && V(e.toString());
52
78
  },
53
- onInputChange: (e) => !e && R(),
54
- defaultSelectedKey: w ?? void 0,
55
- selectedKey: w,
79
+ onInputChange: (e) => !e && U(),
80
+ defaultSelectedKey: k ?? void 0,
81
+ selectedKey: k,
56
82
  classNames: {
57
83
  popoverContent: "bg-content1 rounded-xl border border-[var(--oh-border)]",
58
- selectorButton: c
84
+ selectorButton: f
59
85
  },
60
86
  selectorButtonProps: { disableRipple: !0 },
61
- inputProps: { classNames: { inputWrapper: i } },
62
- children: [/* @__PURE__ */ h(o, {
63
- title: z(t.MODEL_SELECTOR$VERIFIED),
87
+ inputProps: { classNames: { inputWrapper: a } },
88
+ children: [/* @__PURE__ */ b(u, {
89
+ title: J(t.MODEL_SELECTOR$VERIFIED),
64
90
  classNames: { heading: "text-[var(--oh-muted)]" },
65
- children: M.map((e) => /* @__PURE__ */ h(a, {
91
+ children: L.map((e) => /* @__PURE__ */ b(l, {
66
92
  "data-testid": `provider-item-${e.name}`,
67
- children: l(e.name)
93
+ children: p(e.name)
68
94
  }, e.name))
69
- }), N.length > 0 ? /* @__PURE__ */ h(o, {
70
- title: z(t.MODEL_SELECTOR$OTHERS),
95
+ }), R.length > 0 ? /* @__PURE__ */ b(u, {
96
+ title: J(t.MODEL_SELECTOR$OTHERS),
71
97
  classNames: { heading: "text-[var(--oh-muted)]" },
72
- children: N.map((e) => /* @__PURE__ */ h(a, { children: l(e.name) }, e.name))
98
+ children: R.map((e) => /* @__PURE__ */ b(l, { children: p(e.name) }, e.name))
73
99
  }) : null]
74
100
  })]
75
101
  }),
76
- w === "openhands" && /* @__PURE__ */ h(d, {
77
- testId: "openhands-account-help",
78
- text: z(t.SETTINGS$NEED_OPENHANDS_ACCOUNT),
79
- linkText: z(t.SETTINGS$CLICK_HERE),
80
- href: n.PRODUCTION,
81
- size: "settings",
82
- linkColor: "white"
102
+ k === "openhands" && /* @__PURE__ */ b("div", {
103
+ className: "flex flex-col gap-2",
104
+ children: /* @__PURE__ */ b(h, {
105
+ testId: "openhands-account-help",
106
+ text: J(t.SETTINGS$NEED_OPENHANDS_ACCOUNT),
107
+ linkText: J(t.SETTINGS$CLICK_HERE),
108
+ href: r.PRODUCTION,
109
+ size: "settings",
110
+ linkColor: "white"
111
+ })
83
112
  }),
84
- /* @__PURE__ */ g("fieldset", {
113
+ /* @__PURE__ */ x("fieldset", {
85
114
  className: "flex flex-col gap-2.5 w-full",
86
115
  children: [
87
- /* @__PURE__ */ h("label", {
88
- className: r("text-sm", S),
89
- children: z(t.LLM$MODEL)
116
+ /* @__PURE__ */ b("label", {
117
+ className: i("text-sm", D),
118
+ children: J(t.LLM$MODEL)
90
119
  }),
91
- /* @__PURE__ */ g(s, {
92
- "data-testid": "llm-model-input",
93
- isRequired: !0,
94
- isVirtualized: !1,
95
- isLoading: A,
96
- name: "llm-model-input",
97
- "aria-label": z(t.LLM$MODEL),
98
- isClearable: !1,
99
- onSelectionChange: (e) => {
100
- e?.toString() && L(e.toString());
101
- },
102
- isDisabled: _ || !w,
103
- selectedKey: E,
104
- defaultSelectedKey: E ?? void 0,
105
- classNames: {
106
- popoverContent: "bg-content1 rounded-xl border border-[var(--oh-border)]",
107
- selectorButton: c
108
- },
109
- selectorButtonProps: { disableRipple: !0 },
110
- inputProps: { classNames: { inputWrapper: i } },
111
- children: [/* @__PURE__ */ h(o, {
112
- title: z(t.MODEL_SELECTOR$VERIFIED),
113
- classNames: { heading: "text-[var(--oh-muted)]" },
114
- children: P.map((e) => /* @__PURE__ */ h(a, { children: e.name }, e.name))
115
- }), F.length > 0 ? /* @__PURE__ */ h(o, {
116
- title: z(t.MODEL_SELECTOR$OTHERS),
117
- classNames: { heading: "text-[var(--oh-muted)]" },
118
- children: F.map((e) => /* @__PURE__ */ h(a, {
119
- "data-testid": `model-item-${e.name}`,
120
- children: e.name
121
- }, e.name))
122
- }) : null]
120
+ /* @__PURE__ */ x("div", {
121
+ className: "relative",
122
+ children: [/* @__PURE__ */ x(d, {
123
+ "data-testid": "llm-model-input",
124
+ isRequired: !0,
125
+ isVirtualized: !1,
126
+ isLoading: F,
127
+ name: "llm-model-input",
128
+ "aria-label": J(t.LLM$MODEL),
129
+ isClearable: !1,
130
+ onSelectionChange: (e) => {
131
+ e?.toString() && H(e.toString());
132
+ },
133
+ isDisabled: n || !k,
134
+ selectedKey: j,
135
+ defaultSelectedKey: j ?? void 0,
136
+ classNames: {
137
+ popoverContent: "bg-content1 rounded-xl border border-[var(--oh-border)]",
138
+ selectorButton: f
139
+ },
140
+ selectorButtonProps: { disableRipple: !0 },
141
+ inputProps: { classNames: { inputWrapper: a } },
142
+ children: [/* @__PURE__ */ b(u, {
143
+ title: J(t.MODEL_SELECTOR$VERIFIED),
144
+ classNames: { heading: "text-[var(--oh-muted)]" },
145
+ children: z.map((e) => /* @__PURE__ */ b(l, {
146
+ textValue: e.name,
147
+ children: /* @__PURE__ */ x("span", {
148
+ className: "flex min-w-0 items-center gap-2",
149
+ children: [/* @__PURE__ */ b("span", {
150
+ className: "truncate",
151
+ children: e.name
152
+ }), c(`${k}/${e.name}`) ? /* @__PURE__ */ b("span", {
153
+ className: S,
154
+ children: o
155
+ }) : null]
156
+ })
157
+ }, e.name))
158
+ }), B.length > 0 ? /* @__PURE__ */ b(u, {
159
+ title: J(t.MODEL_SELECTOR$OTHERS),
160
+ classNames: { heading: "text-[var(--oh-muted)]" },
161
+ children: B.map((e) => /* @__PURE__ */ b(l, {
162
+ "data-testid": `model-item-${e.name}`,
163
+ textValue: e.name,
164
+ children: e.name
165
+ }, e.name))
166
+ }) : null]
167
+ }), W && j ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("span", {
168
+ ref: G,
169
+ className: "pointer-events-none absolute left-3 top-1/2 whitespace-pre text-sm opacity-0",
170
+ "aria-hidden": !0,
171
+ children: j
172
+ }), /* @__PURE__ */ b("span", {
173
+ "data-testid": "selected-free-model-badge",
174
+ className: i(S, "pointer-events-none absolute top-1/2 z-10 -translate-y-1/2"),
175
+ style: { left: `calc(0.75rem + ${K}px + 0.5rem)` },
176
+ children: o
177
+ })] }) : null]
123
178
  }),
124
- j && /* @__PURE__ */ h("p", {
179
+ I && /* @__PURE__ */ b("p", {
125
180
  "data-testid": "models-error",
126
181
  className: "text-danger text-xs",
127
- children: z(t.CONFIGURATION$ERROR_FETCH_MODELS)
128
- })
182
+ children: J(t.CONFIGURATION$ERROR_FETCH_MODELS)
183
+ }),
184
+ k === "openhands" ? /* @__PURE__ */ b(C, {}) : null
129
185
  ]
130
186
  })
131
187
  ]
132
188
  });
133
189
  }
134
190
  //#endregion
135
- export { _ as ModelSelector };
191
+ export { w as ModelSelector };
136
192
 
137
193
  //# sourceMappingURL=model-selector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-selector.js","names":[],"sources":["../../../../../src/components/shared/modals/settings/model-selector.tsx"],"sourcesContent":["import {\n Autocomplete,\n AutocompleteItem,\n AutocompleteSection,\n} from \"@heroui/react\";\nimport React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { mapProvider } from \"#/utils/map-provider\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { cn } from \"#/utils/utils\";\nimport { formControlSettingsFieldClassName } from \"#/utils/form-control-classes\";\nimport { heroUiAutocompleteSelectorButtonClassName } from \"#/ui/combobox-caret\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { useSearchProviders } from \"#/hooks/query/use-search-providers\";\nimport { useProviderModels } from \"#/hooks/query/use-provider-models\";\n\ninterface ModelSelectorProps {\n isDisabled?: boolean;\n currentModel?: string;\n onChange?: (provider: string | null, model: string | null) => void;\n onDefaultValuesChanged?: (\n provider: string | null,\n model: string | null,\n ) => void;\n wrapperClassName?: string;\n labelClassName?: string;\n}\n\nexport function ModelSelector({\n isDisabled,\n currentModel,\n onChange,\n onDefaultValuesChanged,\n wrapperClassName,\n labelClassName,\n}: ModelSelectorProps) {\n const [, setLitellmId] = React.useState<string | null>(null);\n const [selectedProvider, setSelectedProvider] = React.useState<string | null>(\n null,\n );\n const [selectedModel, setSelectedModel] = React.useState<string | null>(null);\n\n const { data: providers = [] } = useSearchProviders();\n const {\n data: providerModels = [],\n isLoading: isLoadingModels,\n error: modelsError,\n } = useProviderModels(selectedProvider);\n\n const verifiedProviders = React.useMemo(\n () => providers.filter((p) => p.verified),\n [providers],\n );\n const unverifiedProviders = React.useMemo(\n () => providers.filter((p) => !p.verified),\n [providers],\n );\n\n const verifiedModels = React.useMemo(\n () => providerModels.filter((m) => m.verified),\n [providerModels],\n );\n const unverifiedModels = React.useMemo(\n () => providerModels.filter((m) => !m.verified),\n [providerModels],\n );\n\n React.useEffect(() => {\n if (currentModel) {\n const { provider, model } = extractModelAndProvider(currentModel);\n\n setLitellmId(currentModel);\n setSelectedProvider(provider || null);\n setSelectedModel(model);\n onDefaultValuesChanged?.(provider || null, model);\n }\n }, [currentModel]);\n\n const handleChangeProvider = (provider: string) => {\n setSelectedProvider(provider);\n setSelectedModel(null);\n setLitellmId(`${provider}/`);\n onChange?.(provider, null);\n };\n\n const handleChangeModel = (model: string) => {\n let fullModel = `${selectedProvider}/${model}`;\n if (selectedProvider === \"openai\") {\n fullModel = model;\n }\n setLitellmId(fullModel);\n setSelectedModel(model);\n onChange?.(selectedProvider, model);\n };\n\n const clear = () => {\n setSelectedProvider(null);\n setLitellmId(null);\n };\n\n const { t } = useTranslation(\"openhands\");\n\n return (\n <div\n className={cn(\n \"flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]\",\n wrapperClassName,\n )}\n >\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$PROVIDER)}\n </label>\n <Autocomplete\n data-testid=\"llm-provider-input\"\n isRequired\n isVirtualized={false}\n name=\"llm-provider-input\"\n isDisabled={isDisabled}\n aria-label={t(I18nKey.LLM$PROVIDER)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeProvider(e.toString());\n }}\n onInputChange={(value) => !value && clear()}\n defaultSelectedKey={selectedProvider ?? undefined}\n selectedKey={selectedProvider}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedProviders.map((provider) => (\n <AutocompleteItem\n data-testid={`provider-item-${provider.name}`}\n key={provider.name}\n >\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedProviders.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedProviders.map((provider) => (\n <AutocompleteItem key={provider.name}>\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n </fieldset>\n\n {selectedProvider === \"openhands\" && (\n <HelpLink\n testId=\"openhands-account-help\"\n text={t(I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT)}\n linkText={t(I18nKey.SETTINGS$CLICK_HERE)}\n href={PRODUCT_URL.PRODUCTION}\n size=\"settings\"\n linkColor=\"white\"\n />\n )}\n\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$MODEL)}\n </label>\n <Autocomplete\n data-testid=\"llm-model-input\"\n isRequired\n isVirtualized={false}\n isLoading={isLoadingModels}\n name=\"llm-model-input\"\n aria-label={t(I18nKey.LLM$MODEL)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeModel(e.toString());\n }}\n isDisabled={isDisabled || !selectedProvider}\n selectedKey={selectedModel}\n defaultSelectedKey={selectedModel ?? undefined}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedModels.map((model) => (\n <AutocompleteItem key={model.name}>{model.name}</AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedModels.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedModels.map((model) => (\n <AutocompleteItem\n data-testid={`model-item-${model.name}`}\n key={model.name}\n >\n {model.name}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n {modelsError && (\n <p data-testid=\"models-error\" className=\"text-danger text-xs\">\n {t(I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)}\n </p>\n )}\n </fieldset>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model-selector.js","names":[],"sources":["../../../../../src/components/shared/modals/settings/model-selector.tsx"],"sourcesContent":["import {\n Autocomplete,\n AutocompleteItem,\n AutocompleteSection,\n} from \"@heroui/react\";\nimport { Info } from \"lucide-react\";\nimport React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { mapProvider } from \"#/utils/map-provider\";\nimport { extractModelAndProvider } from \"#/utils/extract-model-and-provider\";\nimport { cn } from \"#/utils/utils\";\nimport { formControlSettingsFieldClassName } from \"#/utils/form-control-classes\";\nimport { heroUiAutocompleteSelectorButtonClassName } from \"#/ui/combobox-caret\";\nimport { HelpLink } from \"#/ui/help-link\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { useSearchProviders } from \"#/hooks/query/use-search-providers\";\nimport { useProviderModels } from \"#/hooks/query/use-provider-models\";\nimport {\n FREE_MODEL_BADGE_LABEL,\n FREE_OPENHANDS_MODEL_NOTE,\n isFreeOpenHandsModel,\n} from \"#/utils/format-model-name\";\n\nconst freeModelBadgeClassName =\n \"shrink-0 rounded-full border border-warning/40 bg-warning/10 px-1.5 py-0.5 text-[10px] leading-none text-warning\";\n\nfunction FreeOpenHandsModelsNote() {\n return (\n <p\n data-testid=\"openhands-free-models-note\"\n className=\"flex items-start gap-2 text-xs text-warning\"\n >\n <Info className=\"mt-0.5 size-4 shrink-0 text-warning\" aria-hidden />\n <span>{FREE_OPENHANDS_MODEL_NOTE}</span>\n </p>\n );\n}\n\ninterface ModelSelectorProps {\n isDisabled?: boolean;\n currentModel?: string;\n onChange?: (provider: string | null, model: string | null) => void;\n onDefaultValuesChanged?: (\n provider: string | null,\n model: string | null,\n ) => void;\n wrapperClassName?: string;\n labelClassName?: string;\n}\n\nexport function ModelSelector({\n isDisabled,\n currentModel,\n onChange,\n onDefaultValuesChanged,\n wrapperClassName,\n labelClassName,\n}: ModelSelectorProps) {\n const [, setLitellmId] = React.useState<string | null>(null);\n const [selectedProvider, setSelectedProvider] = React.useState<string | null>(\n null,\n );\n const [selectedModel, setSelectedModel] = React.useState<string | null>(null);\n\n const { data: providers = [] } = useSearchProviders();\n const {\n data: providerModels = [],\n isLoading: isLoadingModels,\n error: modelsError,\n } = useProviderModels(selectedProvider);\n\n const verifiedProviders = React.useMemo(\n () => providers.filter((p) => p.verified),\n [providers],\n );\n const unverifiedProviders = React.useMemo(\n () => providers.filter((p) => !p.verified),\n [providers],\n );\n\n const verifiedModels = React.useMemo(\n () => providerModels.filter((m) => m.verified),\n [providerModels],\n );\n const unverifiedModels = React.useMemo(\n () => providerModels.filter((m) => !m.verified),\n [providerModels],\n );\n\n React.useEffect(() => {\n if (currentModel) {\n const { provider, model } = extractModelAndProvider(currentModel);\n\n setLitellmId(currentModel);\n setSelectedProvider(provider || null);\n setSelectedModel(model);\n onDefaultValuesChanged?.(provider || null, model);\n }\n }, [currentModel]);\n\n const handleChangeProvider = (provider: string) => {\n setSelectedProvider(provider);\n setSelectedModel(null);\n setLitellmId(`${provider}/`);\n onChange?.(provider, null);\n };\n\n const handleChangeModel = (model: string) => {\n let fullModel = `${selectedProvider}/${model}`;\n if (selectedProvider === \"openai\") {\n fullModel = model;\n }\n setLitellmId(fullModel);\n setSelectedModel(model);\n onChange?.(selectedProvider, model);\n };\n\n const clear = () => {\n setSelectedProvider(null);\n setLitellmId(null);\n };\n\n const selectedFullModel =\n selectedProvider && selectedModel\n ? `${selectedProvider}/${selectedModel}`\n : null;\n const isSelectedModelFree = isFreeOpenHandsModel(selectedFullModel);\n const selectedModelMeasureRef = React.useRef<HTMLSpanElement>(null);\n const [selectedModelTextWidth, setSelectedModelTextWidth] = React.useState(0);\n\n React.useLayoutEffect(() => {\n if (!isSelectedModelFree || !selectedModelMeasureRef.current) {\n setSelectedModelTextWidth(0);\n return undefined;\n }\n\n const measureSelectedModel = () => {\n setSelectedModelTextWidth(\n Math.ceil(\n selectedModelMeasureRef.current?.getBoundingClientRect().width ?? 0,\n ),\n );\n };\n measureSelectedModel();\n\n if (typeof ResizeObserver === \"undefined\") {\n return undefined;\n }\n\n const observer = new ResizeObserver(measureSelectedModel);\n observer.observe(selectedModelMeasureRef.current);\n return () => observer.disconnect();\n }, [isSelectedModelFree, selectedModel]);\n\n const { t } = useTranslation(\"openhands\");\n\n return (\n <div\n className={cn(\n \"flex flex-col md:flex-row w-full min-w-0 justify-between gap-4 md:gap-[46px]\",\n wrapperClassName,\n )}\n >\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$PROVIDER)}\n </label>\n <Autocomplete\n data-testid=\"llm-provider-input\"\n isRequired\n isVirtualized={false}\n name=\"llm-provider-input\"\n isDisabled={isDisabled}\n aria-label={t(I18nKey.LLM$PROVIDER)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeProvider(e.toString());\n }}\n onInputChange={(value) => !value && clear()}\n defaultSelectedKey={selectedProvider ?? undefined}\n selectedKey={selectedProvider}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedProviders.map((provider) => (\n <AutocompleteItem\n data-testid={`provider-item-${provider.name}`}\n key={provider.name}\n >\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedProviders.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedProviders.map((provider) => (\n <AutocompleteItem key={provider.name}>\n {mapProvider(provider.name)}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n </fieldset>\n\n {selectedProvider === \"openhands\" && (\n <div className=\"flex flex-col gap-2\">\n <HelpLink\n testId=\"openhands-account-help\"\n text={t(I18nKey.SETTINGS$NEED_OPENHANDS_ACCOUNT)}\n linkText={t(I18nKey.SETTINGS$CLICK_HERE)}\n href={PRODUCT_URL.PRODUCTION}\n size=\"settings\"\n linkColor=\"white\"\n />\n </div>\n )}\n\n <fieldset className=\"flex flex-col gap-2.5 w-full\">\n <label className={cn(\"text-sm\", labelClassName)}>\n {t(I18nKey.LLM$MODEL)}\n </label>\n <div className=\"relative\">\n <Autocomplete\n data-testid=\"llm-model-input\"\n isRequired\n isVirtualized={false}\n isLoading={isLoadingModels}\n name=\"llm-model-input\"\n aria-label={t(I18nKey.LLM$MODEL)}\n isClearable={false}\n onSelectionChange={(e) => {\n if (e?.toString()) handleChangeModel(e.toString());\n }}\n isDisabled={isDisabled || !selectedProvider}\n selectedKey={selectedModel}\n defaultSelectedKey={selectedModel ?? undefined}\n classNames={{\n popoverContent:\n \"bg-content1 rounded-xl border border-[var(--oh-border)]\",\n selectorButton: heroUiAutocompleteSelectorButtonClassName,\n }}\n selectorButtonProps={{ disableRipple: true }}\n inputProps={{\n classNames: {\n inputWrapper: formControlSettingsFieldClassName,\n },\n }}\n >\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$VERIFIED)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {verifiedModels.map((model) => (\n <AutocompleteItem key={model.name} textValue={model.name}>\n <span className=\"flex min-w-0 items-center gap-2\">\n <span className=\"truncate\">{model.name}</span>\n {isFreeOpenHandsModel(\n `${selectedProvider}/${model.name}`,\n ) ? (\n <span className={freeModelBadgeClassName}>\n {FREE_MODEL_BADGE_LABEL}\n </span>\n ) : null}\n </span>\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n {unverifiedModels.length > 0 ? (\n <AutocompleteSection\n title={t(I18nKey.MODEL_SELECTOR$OTHERS)}\n classNames={{ heading: \"text-[var(--oh-muted)]\" }}\n >\n {unverifiedModels.map((model) => (\n <AutocompleteItem\n data-testid={`model-item-${model.name}`}\n key={model.name}\n textValue={model.name}\n >\n {model.name}\n </AutocompleteItem>\n ))}\n </AutocompleteSection>\n ) : null}\n </Autocomplete>\n {isSelectedModelFree && selectedModel ? (\n <>\n <span\n ref={selectedModelMeasureRef}\n className=\"pointer-events-none absolute left-3 top-1/2 whitespace-pre text-sm opacity-0\"\n aria-hidden\n >\n {selectedModel}\n </span>\n <span\n data-testid=\"selected-free-model-badge\"\n className={cn(\n freeModelBadgeClassName,\n \"pointer-events-none absolute top-1/2 z-10 -translate-y-1/2\",\n )}\n style={{\n left: `calc(0.75rem + ${selectedModelTextWidth}px + 0.5rem)`,\n }}\n >\n {FREE_MODEL_BADGE_LABEL}\n </span>\n </>\n ) : null}\n </div>\n {modelsError && (\n <p data-testid=\"models-error\" className=\"text-danger text-xs\">\n {t(I18nKey.CONFIGURATION$ERROR_FETCH_MODELS)}\n </p>\n )}\n {selectedProvider === \"openhands\" ? <FreeOpenHandsModelsNote /> : null}\n </fieldset>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../_virtual/_rolldown/runtime.cjs");var e={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.40.1`,agentCanvas:`1.10.0`,automation:`1.6.0`},compatibility:{minimumAgentServer:`1.28.0`},constraints:{_comment:`Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).`,agentClientProtocol:`agent-client-protocol<0.11`},images:{agentServer:`ghcr.io/openhands/agent-server`,agentCanvas:`ghcr.io/openhands/agent-canvas`},ports:{agentServer:18e3,automation:18001,proxy:8e3},paths:{stateSubdir:`agent-canvas`,conversations:`agent-canvas/conversations`,bashEvents:`agent-canvas/bash_events`,automationDb:`automation/automations.db`,canvasBasePath:`/canvas`},packages:{agentServer:`openhands-agent-server`,automation:`openhands-automation`,tools:`openhands-tools`,workspace:`openhands-workspace`},telemetry:{posthogApiKey:`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,posthogHost:`https://us.i.posthog.com`}};exports.default=e;
1
+ require("../_virtual/_rolldown/runtime.cjs");var e={_comment:`Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.`,versions:{agentServer:`1.40.1`,agentCanvas:`1.12.0`,automation:`1.6.0`},compatibility:{minimumAgentServer:`1.28.0`},constraints:{_comment:`Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).`,agentClientProtocol:`agent-client-protocol<0.11`},images:{agentServer:`ghcr.io/openhands/agent-server`,agentCanvas:`ghcr.io/openhands/agent-canvas`},ports:{agentServer:18e3,automation:18001,proxy:8e3},paths:{stateSubdir:`agent-canvas`,conversations:`agent-canvas/conversations`,bashEvents:`agent-canvas/bash_events`,automationDb:`automation/automations.db`,canvasBasePath:`/canvas`},packages:{agentServer:`openhands-agent-server`,automation:`openhands-automation`,tools:`openhands-tools`,workspace:`openhands-workspace`},telemetry:{posthogApiKey:`phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U`,posthogHost:`https://us.i.posthog.com`}};exports.default=e;
2
2
  //# sourceMappingURL=defaults.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.cjs","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.40.1\",\n \"agentCanvas\": \"1.10.0\",\n \"automation\": \"1.6.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"defaults.cjs","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.40.1\",\n \"agentCanvas\": \"1.12.0\",\n \"automation\": \"1.6.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
@@ -2,7 +2,7 @@ var e = {
2
2
  _comment: "Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.",
3
3
  versions: {
4
4
  agentServer: "1.40.1",
5
- agentCanvas: "1.10.0",
5
+ agentCanvas: "1.12.0",
6
6
  automation: "1.6.0"
7
7
  },
8
8
  compatibility: { minimumAgentServer: "1.28.0" },
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.40.1\",\n \"agentCanvas\": \"1.10.0\",\n \"automation\": \"1.6.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"defaults.js","names":[],"sources":["../../config/defaults.json"],"sourcesContent":["{\n \"_comment\": \"Single source of truth for version pins, ports, paths, and defaults shared across the npm and Docker install paths. Read by scripts/dev-safe.mjs, scripts/dev-with-automation.mjs, docker/entrypoint.sh (via generated defaults.env), and .github/workflows/docker.yml.\",\n \"versions\": {\n \"agentServer\": \"1.40.1\",\n \"agentCanvas\": \"1.12.0\",\n \"automation\": \"1.6.0\"\n },\n \"compatibility\": {\n \"minimumAgentServer\": \"1.28.0\"\n },\n \"constraints\": {\n \"_comment\": \"Temporary upper bound on the agent-client-protocol (acp) transitive dependency. openhands-sdk 1.35.0 requires agent-client-protocol>=0.10.1 with no upper bound, but acp 0.11.0 reordered the ACP prompt() arguments and breaks the SDK's ACP client (a PromptRequest validation error surfaces as 'ACP error: 2 validation errors for PromptRequest'). Pin acp <0.11 until a fixed openhands-sdk ships. Consumed by scripts/dev-safe.mjs (agent-server uvx install) and .github/workflows/mock-llm-e2e.yml (mock ACP server venv).\",\n \"agentClientProtocol\": \"agent-client-protocol<0.11\"\n },\n \"images\": {\n \"agentServer\": \"ghcr.io/openhands/agent-server\",\n \"agentCanvas\": \"ghcr.io/openhands/agent-canvas\"\n },\n \"ports\": {\n \"agentServer\": 18000,\n \"automation\": 18001,\n \"proxy\": 8000\n },\n \"paths\": {\n \"stateSubdir\": \"agent-canvas\",\n \"conversations\": \"agent-canvas/conversations\",\n \"bashEvents\": \"agent-canvas/bash_events\",\n \"automationDb\": \"automation/automations.db\",\n \"canvasBasePath\": \"/canvas\"\n },\n \"packages\": {\n \"agentServer\": \"openhands-agent-server\",\n \"automation\": \"openhands-automation\",\n \"tools\": \"openhands-tools\",\n \"workspace\": \"openhands-workspace\"\n },\n \"telemetry\": {\n \"posthogApiKey\": \"phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U\",\n \"posthogHost\": \"https://us.i.posthog.com\"\n }\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");var e=`launch_child_conversation`,t=`ClientAction_${e}`,n=`[child-conversation] `,r=[`local`,`cloud`],i=[`worktree`,`shared`],a=`1.37.1`;exports.CHILD_CONVERSATION_ISOLATIONS=i,exports.CHILD_CONVERSATION_RESULT_PREFIX=n,exports.CHILD_CONVERSATION_TARGETS=r,exports.LAUNCH_CHILD_CONVERSATION_ACTION_KIND=t,exports.LAUNCH_CHILD_CONVERSATION_TOOL_NAME=e,exports.MIN_AGENT_SERVER_VERSION_FOR_PARENT_LINK=a;
2
+ //# sourceMappingURL=child-conversation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-conversation.cjs","names":[],"sources":["../../src/constants/child-conversation.ts"],"sourcesContent":["export const LAUNCH_CHILD_CONVERSATION_TOOL_NAME = \"launch_child_conversation\";\n\n/**\n * Action discriminator generated by the SDK for the client-defined launch tool\n * (`ClientAction_<tool-name>`). Keep the SDK naming convention contained here\n * instead of repeating its generated class name throughout the frontend.\n */\nexport const LAUNCH_CHILD_CONVERSATION_ACTION_KIND =\n `ClientAction_${LAUNCH_CHILD_CONVERSATION_TOOL_NAME}` as const;\n\n/**\n * Prefix of the machine-generated message the frontend posts back into the\n * parent conversation after a launch. Client tools are acknowledged by the\n * agent-server before the browser has done any work, so this message is the\n * only way to hand the agent the child's id, URL and status — or corrective\n * guidance when the call was malformed. The chat hides it (see\n * `should-render-event.ts`) because the agent relays the same information in\n * its own reply.\n */\nexport const CHILD_CONVERSATION_RESULT_PREFIX = \"[child-conversation] \";\n\nexport const CHILD_CONVERSATION_TARGETS = [\"local\", \"cloud\"] as const;\nexport type ChildConversationTarget =\n (typeof CHILD_CONVERSATION_TARGETS)[number];\n\nexport const CHILD_CONVERSATION_ISOLATIONS = [\"worktree\", \"shared\"] as const;\nexport type ChildConversationIsolation =\n (typeof CHILD_CONVERSATION_ISOLATIONS)[number];\n\n/**\n * `parent_conversation_id` on the local start-conversation request landed in\n * software-agent-sdk#4188. Older agent-servers accept the request and drop the\n * field (the pydantic model ignores extras), so the launch still succeeds — we\n * just tell the agent the relationship was not persisted instead of letting it\n * believe in a link that does not exist.\n */\nexport const MIN_AGENT_SERVER_VERSION_FOR_PARENT_LINK = \"1.37.1\";\n"],"mappings":"6CAAA,IAAa,EAAsC,4BAOtC,EACX,gBAAgB,IAWL,EAAmC,wBAEnC,EAA6B,CAAC,QAAS,OAAO,EAI9C,EAAgC,CAAC,WAAY,QAAQ,EAWrD,EAA2C"}