@openhands/agent-canvas 1.17.0 → 1.19.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 (601) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/acp-providers-BQ4o4vqy.js +1 -0
  4. package/build/assets/active-backend-context-BsLfwrXB.js +2 -0
  5. package/build/assets/{agent-context-settings-CJUrcBut.js → agent-context-settings-D9i6ezoJ.js} +1 -1
  6. package/build/assets/{agent-profiles-service.api-Biieml2L.js → agent-profiles-service.api-U-9YzDFU.js} +1 -1
  7. package/build/assets/agent-profiles-settings-D-bUV2PX.js +1 -0
  8. package/build/assets/agent-server-client-options-EHB23gyx.js +1 -0
  9. package/build/assets/agent-server-config-C_x8Otd9.js +1 -0
  10. package/build/assets/agent-server-conversation-service.api-BaVQ6NpE.js +88 -0
  11. package/build/assets/agent-settings-BZJHtaIK.js +2 -0
  12. package/build/assets/agent-settings-D4snDd6u.js +1 -0
  13. package/build/assets/alert-banner-BkVt_8Or.js +1 -0
  14. package/build/assets/{api-error-message-Ve79qDcN.js → api-error-message-BXo0lCI5.js} +1 -1
  15. package/build/assets/api-key-entry-screen-fAIld-n7.js +1 -0
  16. package/build/assets/app-settings-DITbrM2u.js +1 -0
  17. package/build/assets/automation-detail-DawHmaOl.js +3 -0
  18. package/build/assets/automation-disabled-reason-DtgC8Ppt.js +1 -0
  19. package/build/assets/{automation-export-DxY47m3T.js → automation-export-Kv6e0bHx.js} +1 -1
  20. package/build/assets/automation-git-sync-Dd98G_Oz.js +1 -0
  21. package/build/assets/automation-setup-route-Cdc109ZD.js +3 -0
  22. package/build/assets/{automation-templates-4C4PM8K7.js → automation-templates-Xhr-FDAB.js} +1 -1
  23. package/build/assets/automations-list-BeP1LuzQ.js +1 -0
  24. package/build/assets/{back-nav-button-B8tH0BEp.js → back-nav-button-DWNiN277.js} +1 -1
  25. package/build/assets/backend-form-modal-DeaUJIik.js +1 -0
  26. package/build/assets/backend-synced-settings-badge-Br85iWIY.js +1 -0
  27. package/build/assets/badge-Cdnei7Ly.js +1 -0
  28. package/build/assets/{base-modal-DTULovNc.js → base-modal-Ds7grR67.js} +1 -1
  29. package/build/assets/{bot-CLMxGFaq.js → bot-ByolqPEr.js} +1 -1
  30. package/build/assets/{brand-button-DxPO4Lf8.js → brand-button-mQq2Ld1I.js} +1 -1
  31. package/build/assets/browser-Bfum8fkE.js +46 -0
  32. package/build/assets/browser-tab-CmYT4j_r.js +1 -0
  33. package/build/assets/canvas-extension-page-CokKSVRG.js +1 -0
  34. package/build/assets/canvas-extensions-BoQEYG-2.js +1 -0
  35. package/build/assets/{canvas-extensions-runtime-DdnkgJXV.js → canvas-extensions-runtime-Du2M5iEX.js} +1 -1
  36. package/build/assets/{chat-send-button-B3SFSIg5.js → chat-send-button-DM3JgMc2.js} +1 -1
  37. package/build/assets/check-Bo8s5Ylg.js +1 -0
  38. package/build/assets/chevron-down-Cr6Fn_wS.js +1 -0
  39. package/build/assets/chevron-right-CfdfRn-8.js +1 -0
  40. package/build/assets/circle-check-5pH3qCji.js +1 -0
  41. package/build/assets/circle-plus-check-toggle-BbYBiUwv.js +1 -0
  42. package/build/assets/{cloud-funnel-analytics-BQanUEEC.js → cloud-funnel-analytics-D02kgq1s.js} +1 -1
  43. package/build/assets/{cog-VBlRo6iw.js → cog-Dy1eWbSZ.js} +1 -1
  44. package/build/assets/command-menu-mehU3Evb.js +1 -0
  45. package/build/assets/commits-tab-DhQW8CXi.js +1 -0
  46. package/build/assets/{condenser-settings-eVKFMvap.js → condenser-settings-eRk6Fkx6.js} +1 -1
  47. package/build/assets/confirmation-modal-BmVt_c0I.js +1 -0
  48. package/build/assets/{context-menu-list-item-DDROe12Z.js → context-menu-list-item-lx2zk9G7.js} +1 -1
  49. package/build/assets/{conversation-BnjJSFf5.js → conversation-BOj0ENI6.js} +8 -8
  50. package/build/assets/conversation-SouWlGvs.js +1 -0
  51. package/build/assets/conversation-panel-SouWlGvs.js +1 -0
  52. package/build/assets/conversation-state-store-C6YncQNo.js +1 -0
  53. package/build/assets/conversation-store-DC-JlJuq.js +6 -0
  54. package/build/assets/{conversation-tab-empty-state-DKlzAz5c.js → conversation-tab-empty-state-DIhwCC2J.js} +1 -1
  55. package/build/assets/copy-to-clipboard-button-DVNXLylP.js +1 -0
  56. package/build/assets/device-verify-LP-x7nra.js +1 -0
  57. package/build/assets/{dropdown-classes-B9kJVDIk.js → dropdown-classes-goDldkiu.js} +1 -1
  58. package/build/assets/edit-automation-modal-BJJR9wSW.js +1 -0
  59. package/build/assets/empty-state-Cd-TFe7i.js +1 -0
  60. package/build/assets/{entry.client-Ds8LVp-E.js → entry.client-CJdjIvMZ.js} +2 -2
  61. package/build/assets/enum-filter-dropdown-pocrz9AL.js +1 -0
  62. package/build/assets/environment-switch-overlay-Dwe78wRl.js +1 -0
  63. package/build/assets/error-state-SuWwztxV.js +1 -0
  64. package/build/assets/extensions-hub-O0esK3Er.js +1 -0
  65. package/build/assets/extensions-navigation-CgCVSXje.js +1 -0
  66. package/build/assets/{external-link-DQtv7eTh.js → external-link-Bd7Tga-1.js} +1 -1
  67. package/build/assets/files-tab-B_6t8ljw.js +1 -0
  68. package/build/assets/{form-control-classes-B-z85REi.js → form-control-classes-lQfLxzH4.js} +1 -1
  69. package/build/assets/format-model-name-Dfh9Udrx.js +1 -0
  70. package/build/assets/get-git-path-Bp5rsUkl.js +1 -0
  71. package/build/assets/git-repo-dropdown-CbD0_LPN.js +1 -0
  72. package/build/assets/git-repo-dropdown-DPQVumZg.js +1 -0
  73. package/build/assets/highlighted-source-view-Bp0sgK-f.js +1 -0
  74. package/build/assets/home-BghzJd-D.js +1 -0
  75. package/build/assets/home-CXZ8zawS.js +1 -0
  76. package/build/assets/home-automation-run-tooltip-BdpCckKO.js +1 -0
  77. package/build/assets/home-store-DNQpfIEO.js +1 -0
  78. package/build/assets/hooks-service-DkxnQa4N.js +1 -0
  79. package/build/assets/index-home-Ca6Q5CtT.js +1 -0
  80. package/build/assets/info-BcajzHn1.js +1 -0
  81. package/build/assets/install-server-modal-DvxxYKia.js +1 -0
  82. package/build/assets/{key-CfXbJa8w.js → key-CwTE6XJj.js} +1 -1
  83. package/build/assets/launch-jsRGPRBx.js +1 -0
  84. package/build/assets/link-external-B4gx3EeM.js +1 -0
  85. package/build/assets/list-filter-B8PQk3RA.js +1 -0
  86. package/build/assets/{list-todo-ByXMdY4W.js → list-todo-Caa8E1X_.js} +1 -1
  87. package/build/assets/llm-not-configured-banner-DMdL1vaX.js +27 -0
  88. package/build/assets/llm-settings-dkQ5Oq7W.js +1 -0
  89. package/build/assets/llm-settings-lNDerSlu.js +1 -0
  90. package/build/assets/{llm-subscription-service-aDNBQ7Gq.js → llm-subscription-service-BiQaZbvv.js} +1 -1
  91. package/build/assets/loader-circle-BxJgk73D.js +1 -0
  92. package/build/assets/{loading-spinner-DfHI77BA.js → loading-spinner-DK1sAwVg.js} +1 -1
  93. package/build/assets/manage-backends-modal-DqCJohsX.js +1 -0
  94. package/build/assets/manifest-ff93dc8c.js +1 -0
  95. package/build/assets/manifest-subpage-layout-sxuPqfUr.js +1 -0
  96. package/build/assets/{map-provider-DXvssjw9.js → map-provider-iRs80q_6.js} +1 -1
  97. package/build/assets/markdown-renderer-BH5pqDuJ.js +8 -0
  98. package/build/assets/mcp-BtaJDXnP.js +1 -0
  99. package/build/assets/mcp-installed-servers-Br4ZLsjr.js +1 -0
  100. package/build/assets/mcp-marketplace-utils-BwEnDYqm.js +1 -0
  101. package/build/assets/mcp-page-DwbnQpVs.js +9 -0
  102. package/build/assets/messages-DmFJlW6c.js +41 -0
  103. package/build/assets/{modal-body-DJw4xBki.js → modal-body-DBweM2EN.js} +1 -1
  104. package/build/assets/{modal-classes-Dg0ngBPO.js → modal-classes-jvG85nkU.js} +1 -1
  105. package/build/assets/modal-close-button-BrM5fNnn.js +1 -0
  106. package/build/assets/{mouse-pointer-click-DEhsSUpu.js → mouse-pointer-click-BXlRN92t.js} +1 -1
  107. package/build/assets/onboarding-CQ8T6T0U.js +1 -0
  108. package/build/assets/onboarding-modal-CnliiaSN.js +1 -0
  109. package/build/assets/{organization-service.api-Cyg1Tn03.js → organization-service.api-DmFUEmu5.js} +1 -1
  110. package/build/assets/parse-git-remote-url-BG8pcKL8.js +1 -0
  111. package/build/assets/{pencil-D5c47kyN.js → pencil-q-ihqDYv.js} +1 -1
  112. package/build/assets/{pin-C7vMagvf.js → pin-BdroVQdN.js} +1 -1
  113. package/build/assets/planner-tab-CXph_C9F.js +1 -0
  114. package/build/assets/{plug-CeaqeF6u.js → plug-7ACOEbMs.js} +1 -1
  115. package/build/assets/{plugins-management-service-Bh_pBuf-.js → plugins-management-service-CcEpfNKz.js} +1 -1
  116. package/build/assets/plus-C2e21TFC.js +1 -0
  117. package/build/assets/{profiles-service.api-BbOK0EkF.js → profiles-service.api-DdF_4Zhe.js} +1 -1
  118. package/build/assets/providers-BWRnl31s.js +1 -0
  119. package/build/assets/proxy-DbEf3Nqr.js +1 -0
  120. package/build/assets/{puzzle-DdAqbUrb.js → puzzle-LJYnuxKe.js} +1 -1
  121. package/build/assets/react-BX7IV650.js +1 -0
  122. package/build/assets/recommended-automations-launcher-r0oI91HN.js +1 -0
  123. package/build/assets/{refresh-cw-DEQdPCpH.js → refresh-cw-BtdC3T8P.js} +1 -1
  124. package/build/assets/root-j2fFRlWS.js +2 -0
  125. package/build/assets/root-layout-CfGgm2lo.js +2 -0
  126. package/build/assets/root-sEWn3ha1.css +1 -0
  127. package/build/assets/schema-field-c3Ncgm4x.js +1 -0
  128. package/build/assets/sdk-section-page-DFEiuiFQ.js +1 -0
  129. package/build/assets/secret-form-WXXNFqTM.js +1 -0
  130. package/build/assets/{secrets-service-Cr8g8xuv.js → secrets-service-DU6wh3wX.js} +1 -1
  131. package/build/assets/secrets-settings-BEqbPvjy.js +1 -0
  132. package/build/assets/settings-DjaSQwFh.js +1 -0
  133. package/build/assets/settings-dropdown-input-BRR2OZwi.js +1 -0
  134. package/build/assets/settings-index-DHv4XFcM.js +1 -0
  135. package/build/assets/settings-input-Cm4VxUon.js +1 -0
  136. package/build/assets/{settings-list-classes-Ds4jPBHK.js → settings-list-classes-CaUfKZ33.js} +1 -1
  137. package/build/assets/settings-modal-djXuAnBO.js +1 -0
  138. package/build/assets/settings-nav-DFb3hBMr.js +16 -0
  139. package/build/assets/{settings-service.api-9_xdv_mh.js → settings-service.api-Q9lKW1TX.js} +1 -1
  140. package/build/assets/settings-switch-seaSJc7t.js +1 -0
  141. package/build/assets/{settings-utils-8GIIgOQL.js → settings-utils-BTaaRhLZ.js} +1 -1
  142. package/build/assets/shared-conversation-x3rxVCon.js +1 -0
  143. package/build/assets/{shield-check-DO7wa_eu.js → shield-check-C3Rl0NF8.js} +1 -1
  144. package/build/assets/{sidebar-layout-EPfWxk11.js → sidebar-layout-B6mcvvdV.js} +1 -1
  145. package/build/assets/sidebar-mobile-menu-toggle-CEqS8KnA.js +1 -0
  146. package/build/assets/{sidebar-nav-link-_t4_Ef-9.js → sidebar-nav-link-BTHX11LG.js} +1 -1
  147. package/build/assets/{sidebar-onboarding-checklist-storage-DbDX-Wvj.js → sidebar-onboarding-checklist-storage-BP1kzn6p.js} +1 -1
  148. package/build/assets/sidebar-store-DAZVH-DR.js +1 -0
  149. package/build/assets/skill-card-pill-row-TD39nfP3.js +1 -0
  150. package/build/assets/{skill-filter-BBeZ4JEP.js → skill-filter-CdBbbwjm.js} +2 -2
  151. package/build/assets/{skill-icon-badge-BDhQ-tQ0.js → skill-icon-badge-vUEp7gsC.js} +1 -1
  152. package/build/assets/skill-scope-BTRBQt0-.js +1 -0
  153. package/build/assets/skills-plugins-k1tUNAw4.js +1 -0
  154. package/build/assets/skills-settings-CENviPT7.js +1 -0
  155. package/build/assets/{styled-tooltip-Pd22BIvr.js → styled-tooltip-DVAlWYnL.js} +1 -1
  156. package/build/assets/task-list-tab-BLKF_x9f.js +1 -0
  157. package/build/assets/{terminal-onXx0_Qz.js → terminal-Ckbnqb23.js} +1 -1
  158. package/build/assets/{toggle-switch-lwQtxDcm.js → toggle-switch-DeiG9Mf6.js} +1 -1
  159. package/build/assets/{trash-2-ZhKuTLiz.js → trash-2-Bb40zQzs.js} +1 -1
  160. package/build/assets/trash-CXN2R54L.js +1 -0
  161. package/build/assets/{triangle-alert-BajLPpQg.js → triangle-alert-DEdu-b_L.js} +1 -1
  162. package/build/assets/{typography-HLLg_FAn.js → typography-NarNyelM.js} +1 -1
  163. package/build/assets/usage-tab-Drd3O006.js +1 -0
  164. package/build/assets/use-acp-credential-form-CJ5wPsQm.js +1 -0
  165. package/build/assets/{use-activate-agent-profile-BLKML6vQ.js → use-activate-agent-profile-iQZ0U3qV.js} +1 -1
  166. package/build/assets/use-agent-profiles-LCvb5OXT.js +1 -0
  167. package/build/assets/{use-automation-health-BZkQNEA8.js → use-automation-health-DdgSa8sA.js} +1 -1
  168. package/build/assets/{use-automation-permissions-B_RpvL-s.js → use-automation-permissions-D3kEeieu.js} +1 -1
  169. package/build/assets/{use-automations-Cg0PDIZr.js → use-automations-CEubcYTD.js} +1 -1
  170. package/build/assets/{use-can-manage-org-profiles-BbN6KfDr.js → use-can-manage-org-profiles-CB8ybxFK.js} +1 -1
  171. package/build/assets/{use-canvas-extensions-CFUpHat6.js → use-canvas-extensions-BMacwi2v.js} +1 -1
  172. package/build/assets/{use-cloud-current-user-id-Dk0rjr63.js → use-cloud-current-user-id-BEKRd6XZ.js} +1 -1
  173. package/build/assets/{use-config-DpafU_QP.js → use-config-3WYcJsgC.js} +1 -1
  174. package/build/assets/{use-create-conversation-1YgmAHt-.js → use-create-conversation-Be-eVpFp.js} +1 -1
  175. package/build/assets/use-create-secret-Bk9ZxTjl.js +1 -0
  176. package/build/assets/use-free-models-Ci3FkKEm.js +1 -0
  177. package/build/assets/{use-get-secrets-CQ4b0qK8.js → use-get-secrets-fqS0kxt6.js} +1 -1
  178. package/build/assets/use-is-authed-A2Yinlt0.js +1 -0
  179. package/build/assets/{use-launch-skill-in-chat-DeYa1tFM.js → use-launch-skill-in-chat-QbXDhiHr.js} +1 -1
  180. package/build/assets/use-llm-configured-B71ZEVg2.js +1 -0
  181. package/build/assets/use-llm-profiles-xtCBMbef.js +1 -0
  182. package/build/assets/{use-manifest-capabilities-AOWGcu0j.js → use-manifest-capabilities-Bso6A_-A.js} +1 -1
  183. package/build/assets/{use-onboarding-completion-CoINurkm.js → use-onboarding-completion-CEgjL02y.js} +1 -1
  184. package/build/assets/{use-pinned-home-route-D6krwXjy.js → use-pinned-home-route-pK4IlJ-p.js} +1 -1
  185. package/build/assets/{use-plugins-marketplace-mLsIDhBv.js → use-plugins-marketplace-B8-ZEB34.js} +1 -1
  186. package/build/assets/use-save-agent-profile-D7hJuW_u.js +1 -0
  187. package/build/assets/{use-save-settings-3U5K9-8x.js → use-save-settings-CikTu5xV.js} +1 -1
  188. package/build/assets/{use-settings-Dn00UISA.js → use-settings-BWIH5EuN.js} +1 -1
  189. package/build/assets/use-settings-nav-items-DSKwLDnd.js +1 -0
  190. package/build/assets/use-tracking-ChnSFChv.js +3 -0
  191. package/build/assets/{use-user-conversation-ZWlXtbZb.js → use-user-conversation-C_l65DqW.js} +1 -1
  192. package/build/assets/{useInfiniteQuery-BzrRqjLg.js → useInfiniteQuery-CtSRG7uW.js} +1 -1
  193. package/build/assets/{useMutation-CJuK90oc.js → useMutation-Cszf8mKy.js} +1 -1
  194. package/build/assets/useQueries-pUohFMSP.js +1 -0
  195. package/build/assets/useQuery-DAAacS7O.js +1 -0
  196. package/build/assets/useTranslation-CCgUjPJF.js +1 -0
  197. package/build/assets/utils-D-gOfhmN.js +1 -0
  198. package/build/assets/{vendor~conversation-panel~conversation-4eJ0tml3.js → vendor~conversation-panel~conversation-C22sJuWZ.js} +1 -1
  199. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-D6owle9R.js +2 -0
  200. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BXXGJNDU.js +185 -0
  201. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-40UR63Gt.js +1 -0
  202. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-CSFLzmTN.js → vendor~index-home~home~conversation-panel~conversation-UTl7gUo9.js} +1 -1
  203. package/build/assets/{vendor~root-layout-n8XCEXG8.js → vendor~root-layout-CcdIqs-C.js} +1 -1
  204. package/build/assets/{vendor~root-layout~conversation-panel~conversation-3Idg1_U3.js → vendor~root-layout~conversation-panel~conversation-C3EBV3kp.js} +1 -1
  205. package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BCe0JJVy.js +1 -0
  206. package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-DgQ564nC.js → vendor~root-layout~index-home~home~conversation-panel~conversation-BGGbPcYh.js} +1 -1
  207. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-BFRW8wt-.js +48 -0
  208. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-BPjI-atc.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-3eJ4ExtV.js} +1 -1
  209. package/build/assets/{verification-settings-u2POabjH.js → verification-settings-PKtoIUUY.js} +1 -1
  210. package/build/assets/{wrench-CkgI4rxA.js → wrench-B8Wg_nbp.js} +1 -1
  211. package/build/assets/{x-By6qCmtY.js → x-CX8lVGwm.js} +1 -1
  212. package/build/index.html +4 -4
  213. package/build/locales/ar/openhands.json +16 -2
  214. package/build/locales/ca/openhands.json +16 -2
  215. package/build/locales/de/openhands.json +16 -2
  216. package/build/locales/en/openhands.json +16 -2
  217. package/build/locales/es/openhands.json +16 -2
  218. package/build/locales/fr/openhands.json +16 -2
  219. package/build/locales/it/openhands.json +16 -2
  220. package/build/locales/ja/openhands.json +16 -2
  221. package/build/locales/ko-KR/openhands.json +16 -2
  222. package/build/locales/no/openhands.json +16 -2
  223. package/build/locales/pt/openhands.json +16 -2
  224. package/build/locales/tr/openhands.json +16 -2
  225. package/build/locales/uk/openhands.json +16 -2
  226. package/build/locales/zh-CN/openhands.json +16 -2
  227. package/build/locales/zh-TW/openhands.json +16 -2
  228. package/config/defaults.json +3 -3
  229. package/dist/api/cloud/organization-service.api.cjs.map +1 -1
  230. package/dist/api/cloud/organization-service.api.d.ts +9 -1
  231. package/dist/api/cloud/organization-service.api.js.map +1 -1
  232. package/dist/api/config-service/config-service.api.cjs +1 -1
  233. package/dist/api/config-service/config-service.api.cjs.map +1 -1
  234. package/dist/api/config-service/config-service.api.js +6 -2
  235. package/dist/api/config-service/config-service.api.js.map +1 -1
  236. package/dist/api/config-service/config-service.types.d.ts +13 -0
  237. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs +3 -3
  238. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.cjs.map +1 -1
  239. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js +12 -16
  240. package/dist/components/conversation-events/chat/event-content-helpers/get-skill-ready-content.js.map +1 -1
  241. package/dist/components/features/automations/automation-card.cjs +1 -1
  242. package/dist/components/features/automations/automation-card.cjs.map +1 -1
  243. package/dist/components/features/automations/automation-card.js +39 -38
  244. package/dist/components/features/automations/automation-card.js.map +1 -1
  245. package/dist/components/features/automations/automation-list-row.cjs +1 -1
  246. package/dist/components/features/automations/automation-list-row.cjs.map +1 -1
  247. package/dist/components/features/automations/automation-list-row.js +73 -72
  248. package/dist/components/features/automations/automation-list-row.js.map +1 -1
  249. package/dist/components/features/automations/build-automation-menu-items.cjs +1 -1
  250. package/dist/components/features/automations/build-automation-menu-items.cjs.map +1 -1
  251. package/dist/components/features/automations/build-automation-menu-items.d.ts +3 -1
  252. package/dist/components/features/automations/build-automation-menu-items.js +12 -11
  253. package/dist/components/features/automations/build-automation-menu-items.js.map +1 -1
  254. package/dist/components/features/automations/detail/configuration-section.d.ts +7 -1
  255. package/dist/components/features/automations/detail/detail-header.d.ts +8 -5
  256. package/dist/components/features/automations/detail/disabled-reason-banner.d.ts +16 -0
  257. package/dist/components/features/backends/backend-selector.cjs +1 -1
  258. package/dist/components/features/backends/backend-selector.cjs.map +1 -1
  259. package/dist/components/features/backends/backend-selector.js +112 -112
  260. package/dist/components/features/backends/backend-selector.js.map +1 -1
  261. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs +1 -1
  262. package/dist/components/features/chat/components/chat-input-llm-profile-picker.cjs.map +1 -1
  263. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js +62 -61
  264. package/dist/components/features/chat/components/chat-input-llm-profile-picker.js.map +1 -1
  265. package/dist/components/features/chat/model-messages.cjs +1 -1
  266. package/dist/components/features/chat/model-messages.cjs.map +1 -1
  267. package/dist/components/features/chat/model-messages.js +27 -26
  268. package/dist/components/features/chat/model-messages.js.map +1 -1
  269. package/dist/components/features/conversation-panel/budget-display.cjs +1 -1
  270. package/dist/components/features/conversation-panel/budget-display.cjs.map +1 -1
  271. package/dist/components/features/conversation-panel/budget-display.d.ts +1 -2
  272. package/dist/components/features/conversation-panel/budget-display.js +12 -19
  273. package/dist/components/features/conversation-panel/budget-display.js.map +1 -1
  274. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -1
  275. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
  276. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +45 -44
  277. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
  278. package/dist/components/features/home/featured-automations/build-home-automation-menu-items.d.ts +1 -2
  279. package/dist/components/features/home/featured-automations/build-pinned-automation-menu-items.d.ts +0 -1
  280. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
  281. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
  282. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +38 -29
  283. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
  284. package/dist/components/features/images/image-lightbox.cjs +2 -0
  285. package/dist/components/features/images/image-lightbox.cjs.map +1 -0
  286. package/dist/components/features/images/image-lightbox.d.ts +11 -0
  287. package/dist/components/features/images/image-lightbox.js +37 -0
  288. package/dist/components/features/images/image-lightbox.js.map +1 -0
  289. package/dist/components/features/images/image-preview.cjs +1 -1
  290. package/dist/components/features/images/image-preview.cjs.map +1 -1
  291. package/dist/components/features/images/image-preview.d.ts +2 -1
  292. package/dist/components/features/images/image-preview.js +33 -13
  293. package/dist/components/features/images/image-preview.js.map +1 -1
  294. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +3 -4
  295. package/dist/components/features/settings/agent-profiles/profile-scope-list.d.ts +20 -0
  296. package/dist/components/features/settings/cloud-settings-link.cjs +1 -1
  297. package/dist/components/features/settings/cloud-settings-link.cjs.map +1 -1
  298. package/dist/components/features/settings/cloud-settings-link.d.ts +3 -1
  299. package/dist/components/features/settings/cloud-settings-link.js +22 -21
  300. package/dist/components/features/settings/cloud-settings-link.js.map +1 -1
  301. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  302. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +2 -1
  303. package/dist/components/features/settings/llm-profiles/profile-row.cjs +1 -1
  304. package/dist/components/features/settings/llm-profiles/profile-row.js +1 -1
  305. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  306. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  307. package/dist/components/features/sidebar/sidebar-rail-body.d.ts +2 -1
  308. package/dist/components/features/sidebar/sidebar-rail-body.js +143 -142
  309. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  310. package/dist/components/features/sidebar/sidebar.cjs +1 -1
  311. package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
  312. package/dist/components/features/sidebar/sidebar.js +28 -27
  313. package/dist/components/features/sidebar/sidebar.js.map +1 -1
  314. package/dist/components/providers/agent-server-ui-providers.cjs +1 -1
  315. package/dist/components/providers/agent-server-ui-providers.cjs.map +1 -1
  316. package/dist/components/providers/agent-server-ui-providers.js +33 -29
  317. package/dist/components/providers/agent-server-ui-providers.js.map +1 -1
  318. package/dist/components/shared/buttons/remove-button.cjs +1 -1
  319. package/dist/components/shared/buttons/remove-button.cjs.map +1 -1
  320. package/dist/components/shared/buttons/remove-button.d.ts +2 -1
  321. package/dist/components/shared/buttons/remove-button.js +2 -1
  322. package/dist/components/shared/buttons/remove-button.js.map +1 -1
  323. package/dist/components/shared/free-models-note.cjs +2 -0
  324. package/dist/components/shared/free-models-note.cjs.map +1 -0
  325. package/dist/components/shared/free-models-note.d.ts +3 -0
  326. package/dist/components/shared/free-models-note.js +20 -0
  327. package/dist/components/shared/free-models-note.js.map +1 -0
  328. package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
  329. package/dist/components/shared/modals/settings/model-selector.cjs.map +1 -1
  330. package/dist/components/shared/modals/settings/model-selector.js +102 -112
  331. package/dist/components/shared/modals/settings/model-selector.js.map +1 -1
  332. package/dist/config/defaults.cjs +1 -1
  333. package/dist/config/defaults.cjs.map +1 -1
  334. package/dist/config/defaults.js +3 -3
  335. package/dist/config/defaults.js.map +1 -1
  336. package/dist/constants/acp-providers.cjs +1 -1
  337. package/dist/constants/acp-providers.cjs.map +1 -1
  338. package/dist/constants/acp-providers.d.ts +7 -0
  339. package/dist/constants/acp-providers.js +20 -16
  340. package/dist/constants/acp-providers.js.map +1 -1
  341. package/dist/constants/profile-scope.d.ts +21 -0
  342. package/dist/hooks/chat/use-slash-command.cjs +1 -1
  343. package/dist/hooks/chat/use-slash-command.cjs.map +1 -1
  344. package/dist/hooks/chat/use-slash-command.js +63 -62
  345. package/dist/hooks/chat/use-slash-command.js.map +1 -1
  346. package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
  347. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
  348. package/dist/hooks/query/use-automation-sdk-version.js +3 -1
  349. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
  350. package/dist/hooks/query/use-free-models.cjs +2 -0
  351. package/dist/hooks/query/use-free-models.cjs.map +1 -0
  352. package/dist/hooks/query/use-free-models.d.ts +23 -0
  353. package/dist/hooks/query/use-free-models.js +67 -0
  354. package/dist/hooks/query/use-free-models.js.map +1 -0
  355. package/dist/hooks/query/use-local-git-info.cjs.map +1 -1
  356. package/dist/hooks/query/use-local-git-info.js.map +1 -1
  357. package/dist/hooks/query/use-provider-models.cjs +1 -1
  358. package/dist/hooks/query/use-provider-models.cjs.map +1 -1
  359. package/dist/hooks/query/use-provider-models.js +34 -25
  360. package/dist/hooks/query/use-provider-models.js.map +1 -1
  361. package/dist/hooks/query/use-search-providers.cjs +1 -1
  362. package/dist/hooks/query/use-search-providers.cjs.map +1 -1
  363. package/dist/hooks/query/use-search-providers.js +31 -19
  364. package/dist/hooks/query/use-search-providers.js.map +1 -1
  365. package/dist/hooks/use-drag-resize.cjs +1 -1
  366. package/dist/hooks/use-drag-resize.cjs.map +1 -1
  367. package/dist/hooks/use-drag-resize.js +8 -9
  368. package/dist/hooks/use-drag-resize.js.map +1 -1
  369. package/dist/hooks/use-home-automation-actions.cjs +1 -1
  370. package/dist/hooks/use-home-automation-actions.cjs.map +1 -1
  371. package/dist/hooks/use-home-automation-actions.d.ts +1 -2
  372. package/dist/hooks/use-home-automation-actions.js +0 -1
  373. package/dist/hooks/use-home-automation-actions.js.map +1 -1
  374. package/dist/i18n/declaration.cjs +1 -1
  375. package/dist/i18n/declaration.cjs.map +1 -1
  376. package/dist/i18n/declaration.d.ts +16 -2
  377. package/dist/i18n/declaration.js +1 -1
  378. package/dist/i18n/declaration.js.map +1 -1
  379. package/dist/i18n/translation.cjs +3 -3
  380. package/dist/i18n/translation.cjs.map +1 -1
  381. package/dist/i18n/translation.js +255 -17
  382. package/dist/i18n/translation.js.map +1 -1
  383. package/dist/locales/ar/openhands.json +16 -2
  384. package/dist/locales/ca/openhands.json +16 -2
  385. package/dist/locales/de/openhands.json +16 -2
  386. package/dist/locales/en/openhands.json +16 -2
  387. package/dist/locales/es/openhands.json +16 -2
  388. package/dist/locales/fr/openhands.json +16 -2
  389. package/dist/locales/it/openhands.json +16 -2
  390. package/dist/locales/ja/openhands.json +16 -2
  391. package/dist/locales/ko-KR/openhands.json +16 -2
  392. package/dist/locales/no/openhands.json +16 -2
  393. package/dist/locales/pt/openhands.json +16 -2
  394. package/dist/locales/tr/openhands.json +16 -2
  395. package/dist/locales/uk/openhands.json +16 -2
  396. package/dist/locales/zh-CN/openhands.json +16 -2
  397. package/dist/locales/zh-TW/openhands.json +16 -2
  398. package/dist/manifests/manifest-validation.cjs +1 -1
  399. package/dist/manifests/manifest-validation.cjs.map +1 -1
  400. package/dist/manifests/manifest-validation.js +2 -2
  401. package/dist/manifests/manifest-validation.js.map +1 -1
  402. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs +1 -1
  403. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.cjs.map +1 -1
  404. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js +15 -8
  405. package/dist/node_modules/@openhands/typescript-client/dist/client/agent-server-compatibility.js.map +1 -1
  406. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs +1 -1
  407. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.cjs.map +1 -1
  408. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js +11 -13
  409. package/dist/node_modules/@openhands/typescript-client/dist/client/bash-client.js.map +1 -1
  410. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs +1 -1
  411. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.cjs.map +1 -1
  412. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js +6 -0
  413. package/dist/node_modules/@openhands/typescript-client/dist/client/conversation-client.js.map +1 -1
  414. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs +1 -1
  415. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.cjs.map +1 -1
  416. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js +3 -6
  417. package/dist/node_modules/@openhands/typescript-client/dist/client/desktop-client.js.map +1 -1
  418. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs +1 -1
  419. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.cjs.map +1 -1
  420. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js +9 -12
  421. package/dist/node_modules/@openhands/typescript-client/dist/client/file-client.js.map +1 -1
  422. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs +2 -0
  423. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.cjs.map +1 -0
  424. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js +41 -0
  425. package/dist/node_modules/@openhands/typescript-client/dist/client/runtime-transport.js.map +1 -0
  426. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs +1 -1
  427. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.cjs.map +1 -1
  428. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js +3 -6
  429. package/dist/node_modules/@openhands/typescript-client/dist/client/vscode-client.js.map +1 -1
  430. package/dist/node_modules/@openhands/typescript-client/dist/clients.cjs +1 -1
  431. package/dist/node_modules/@openhands/typescript-client/dist/clients.js +1 -1
  432. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs +1 -1
  433. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.cjs.map +1 -1
  434. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js +199 -61
  435. package/dist/node_modules/@openhands/typescript-client/dist/models/acp-providers.js.map +1 -1
  436. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs +1 -1
  437. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.cjs.map +1 -1
  438. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js +9 -8
  439. package/dist/node_modules/@openhands/typescript-client/dist/workspace/remote-workspace.js.map +1 -1
  440. package/dist/package.cjs +1 -1
  441. package/dist/package.cjs.map +1 -1
  442. package/dist/package.js +2 -2
  443. package/dist/package.js.map +1 -1
  444. package/dist/routes/agent-settings.d.ts +5 -0
  445. package/dist/routes/app-settings.cjs +1 -1
  446. package/dist/routes/app-settings.cjs.map +1 -1
  447. package/dist/routes/app-settings.js +52 -47
  448. package/dist/routes/app-settings.js.map +1 -1
  449. package/dist/routes/llm-settings.cjs +1 -1
  450. package/dist/routes/llm-settings.cjs.map +1 -1
  451. package/dist/routes/llm-settings.js +137 -145
  452. package/dist/routes/llm-settings.js.map +1 -1
  453. package/dist/stores/free-models-store.cjs +2 -0
  454. package/dist/stores/free-models-store.cjs.map +1 -0
  455. package/dist/stores/free-models-store.d.ts +30 -0
  456. package/dist/stores/free-models-store.js +22 -0
  457. package/dist/stores/free-models-store.js.map +1 -0
  458. package/dist/types/automation.cjs.map +1 -1
  459. package/dist/types/automation.d.ts +23 -1
  460. package/dist/types/automation.js.map +1 -1
  461. package/dist/utils/automation-disabled-reason.cjs +2 -0
  462. package/dist/utils/automation-disabled-reason.cjs.map +1 -0
  463. package/dist/utils/automation-disabled-reason.d.ts +32 -0
  464. package/dist/utils/automation-disabled-reason.js +19 -0
  465. package/dist/utils/automation-disabled-reason.js.map +1 -0
  466. package/dist/utils/format-model-name.cjs +1 -1
  467. package/dist/utils/format-model-name.cjs.map +1 -1
  468. package/dist/utils/format-model-name.d.ts +27 -6
  469. package/dist/utils/format-model-name.js +14 -6
  470. package/dist/utils/format-model-name.js.map +1 -1
  471. package/dist/utils/parse-git-remote-url.cjs +1 -1
  472. package/dist/utils/parse-git-remote-url.cjs.map +1 -1
  473. package/dist/utils/parse-git-remote-url.d.ts +5 -1
  474. package/dist/utils/parse-git-remote-url.js +20 -13
  475. package/dist/utils/parse-git-remote-url.js.map +1 -1
  476. package/package.json +2 -2
  477. package/scripts/check-sdk-version-sync.mjs +79 -8
  478. package/scripts/dev-safe.mjs +1 -1
  479. package/scripts/static-server.mjs +24 -7
  480. package/build/assets/acp-providers-DrjNsPOH.js +0 -1
  481. package/build/assets/active-backend-context-rZiLJRUc.js +0 -2
  482. package/build/assets/agent-profiles-settings-x6RvPsq7.js +0 -1
  483. package/build/assets/agent-server-client-options-BikiNwTa.js +0 -1
  484. package/build/assets/agent-server-conversation-service.api-DYFsNHKf.js +0 -88
  485. package/build/assets/agent-settings-BJyovpJ_.js +0 -1
  486. package/build/assets/agent-settings-CpY3zObk.js +0 -2
  487. package/build/assets/alert-banner-vARz1idS.js +0 -1
  488. package/build/assets/api-key-entry-screen-CsMuBhoP.js +0 -1
  489. package/build/assets/app-settings-BaJ7nfHt.js +0 -1
  490. package/build/assets/automation-detail-CVoGDrKq.js +0 -3
  491. package/build/assets/automation-git-sync-CRMP9Bbm.js +0 -1
  492. package/build/assets/automation-setup-route-072beLz1.js +0 -3
  493. package/build/assets/automations-list-xuqTSQL4.js +0 -1
  494. package/build/assets/backend-form-modal-0aJmWdsa.js +0 -1
  495. package/build/assets/backend-synced-settings-badge-B7rKWBir.js +0 -1
  496. package/build/assets/badge-CcGx2TaV.js +0 -1
  497. package/build/assets/browser-C-_qBasq.js +0 -46
  498. package/build/assets/browser-tab-DZanIw5m.js +0 -1
  499. package/build/assets/canvas-extension-page-o_cWgE9B.js +0 -1
  500. package/build/assets/canvas-extensions-DSgNlCha.js +0 -1
  501. package/build/assets/check-fDEfgSzj.js +0 -1
  502. package/build/assets/chevron-down-CFrWHqu8.js +0 -1
  503. package/build/assets/chevron-right-C5roOrJu.js +0 -1
  504. package/build/assets/circle-check-ClTzJTdb.js +0 -1
  505. package/build/assets/circle-plus-check-toggle-Fr-h-mbL.js +0 -1
  506. package/build/assets/command-menu-BT3Ia5Ru.js +0 -1
  507. package/build/assets/commits-tab-2jhtaohl.js +0 -1
  508. package/build/assets/confirmation-modal-gIFHeZt6.js +0 -1
  509. package/build/assets/conversation-DZ578rOX.js +0 -1
  510. package/build/assets/conversation-panel-DZ578rOX.js +0 -1
  511. package/build/assets/conversation-state-store-D1_G_9I-.js +0 -1
  512. package/build/assets/conversation-store-DVVfkCsk.js +0 -6
  513. package/build/assets/copy-to-clipboard-button-B3w0X7WH.js +0 -1
  514. package/build/assets/device-verify-BfkCzyFB.js +0 -1
  515. package/build/assets/edit-automation-modal-BwhJ39JT.js +0 -1
  516. package/build/assets/empty-state-RZz0OfnY.js +0 -1
  517. package/build/assets/enum-filter-dropdown-C4pW0ORd.js +0 -1
  518. package/build/assets/environment-switch-overlay-P2ZAuzov.js +0 -1
  519. package/build/assets/error-state-B_5cgNPJ.js +0 -1
  520. package/build/assets/extensions-hub-DsaUr4ca.js +0 -1
  521. package/build/assets/extensions-navigation-CRMZd-FE.js +0 -1
  522. package/build/assets/files-tab-CCgAcVdc.js +0 -1
  523. package/build/assets/format-model-name-CasAP3nd.js +0 -1
  524. package/build/assets/get-git-path-EHrSDxTM.js +0 -1
  525. package/build/assets/git-repo-dropdown-D2WEQ97X.js +0 -1
  526. package/build/assets/git-repo-dropdown-DVeCUUXG.js +0 -1
  527. package/build/assets/highlighted-source-view-DjHO3SdW.js +0 -1
  528. package/build/assets/home-BorS_vdS.js +0 -1
  529. package/build/assets/home-aIMbHw5M.js +0 -1
  530. package/build/assets/home-automation-run-tooltip-CpHNFiFl.js +0 -1
  531. package/build/assets/home-store-DyXz0w6d.js +0 -1
  532. package/build/assets/hooks-service-C6dpRtZM.js +0 -1
  533. package/build/assets/index-home-zKFuKK2B.js +0 -1
  534. package/build/assets/info-CTIdjttz.js +0 -1
  535. package/build/assets/install-server-modal-DUiZMc8u.js +0 -1
  536. package/build/assets/kebab-menu-item-content-mm04SBD3.js +0 -1
  537. package/build/assets/launch-BSIf9KEg.js +0 -1
  538. package/build/assets/link-external-BNZzCM1I.js +0 -1
  539. package/build/assets/list-filter-CNpqTWVY.js +0 -1
  540. package/build/assets/llm-not-configured-banner-z_QRSeV0.js +0 -27
  541. package/build/assets/llm-settings-B-5AHMiX.js +0 -1
  542. package/build/assets/llm-settings-B3SjHDmA.js +0 -1
  543. package/build/assets/loader-circle-Dex47vVW.js +0 -1
  544. package/build/assets/manage-backends-modal-q1NdFisr.js +0 -1
  545. package/build/assets/manifest-8920b615.js +0 -1
  546. package/build/assets/manifest-subpage-layout-BQQy5ipR.js +0 -1
  547. package/build/assets/markdown-renderer-rivLvYh-.js +0 -8
  548. package/build/assets/mcp-CEXDhQWn.js +0 -1
  549. package/build/assets/mcp-marketplace-utils-Cn_NIMWM.js +0 -1
  550. package/build/assets/mcp-page-LGYIICMG.js +0 -9
  551. package/build/assets/messages-DUSeANAh.js +0 -41
  552. package/build/assets/modal-close-button-B9j4nasm.js +0 -1
  553. package/build/assets/onboarding-BjFebfs5.js +0 -1
  554. package/build/assets/onboarding-modal-DDTjOpyd.js +0 -1
  555. package/build/assets/parse-git-remote-url-DpDM9bK6.js +0 -1
  556. package/build/assets/planner-tab-D8f2Y3rn.js +0 -1
  557. package/build/assets/plus-B3wvU06-.js +0 -1
  558. package/build/assets/providers-2gIIkz2N.js +0 -1
  559. package/build/assets/proxy-CBgMd2zf.js +0 -1
  560. package/build/assets/recommended-automations-launcher-YLAQTp4s.js +0 -1
  561. package/build/assets/root-Bye_XmEL.js +0 -2
  562. package/build/assets/root-Cnwwzgo0.css +0 -1
  563. package/build/assets/root-layout-CSAwxBGM.js +0 -2
  564. package/build/assets/schema-field-CK0xYNbO.js +0 -1
  565. package/build/assets/sdk-section-page-Da73Rs_o.js +0 -1
  566. package/build/assets/secret-form-CB2VwYYg.js +0 -1
  567. package/build/assets/secrets-settings-Bh0udeKv.js +0 -1
  568. package/build/assets/settings-DmyIgRxO.js +0 -1
  569. package/build/assets/settings-dropdown-input-DVpyD87C.js +0 -1
  570. package/build/assets/settings-index-BSJUFmjE.js +0 -1
  571. package/build/assets/settings-input-C0dd8Utu.js +0 -1
  572. package/build/assets/settings-modal-yStgEh2o.js +0 -1
  573. package/build/assets/settings-switch-B78Khmyz.js +0 -1
  574. package/build/assets/shared-conversation-DM96X4KV.js +0 -1
  575. package/build/assets/sidebar-mobile-menu-toggle-D5GR5xT9.js +0 -1
  576. package/build/assets/sidebar-store-CSDFK0W5.js +0 -1
  577. package/build/assets/skill-card-pill-row-989y15jV.js +0 -1
  578. package/build/assets/skill-scope-Dz3kPH3P.js +0 -1
  579. package/build/assets/skills-plugins-e3CYGdUJ.js +0 -1
  580. package/build/assets/skills-settings-3e-FuHw_.js +0 -1
  581. package/build/assets/task-list-tab-3Jg8ywch.js +0 -1
  582. package/build/assets/trash-B6OIe4yX.js +0 -1
  583. package/build/assets/usage-tab-Cm-9j3UK.js +0 -1
  584. package/build/assets/use-acp-credential-form-BARcvjYE.js +0 -1
  585. package/build/assets/use-agent-profiles-1P91KSXz.js +0 -1
  586. package/build/assets/use-create-secret-D8p9ybQj.js +0 -1
  587. package/build/assets/use-is-authed-BRPjCRKM.js +0 -1
  588. package/build/assets/use-llm-configured-DGm8FiRR.js +0 -1
  589. package/build/assets/use-llm-profiles-BTTtpW4z.js +0 -1
  590. package/build/assets/use-save-agent-profile-CxyO9YG-.js +0 -1
  591. package/build/assets/use-settings-nav-items-vrjxTqcu.js +0 -16
  592. package/build/assets/use-tracking-B9prBsrq.js +0 -3
  593. package/build/assets/useQueries-CykmpT-a.js +0 -1
  594. package/build/assets/useQuery-S6j94er1.js +0 -1
  595. package/build/assets/utils-BOco8mxR.js +0 -1
  596. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +0 -2
  597. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BfkNGovw.js +0 -185
  598. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-DnDoaYNi.js +0 -1
  599. package/build/assets/vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-DkPlXWl9.js +0 -1
  600. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js +0 -48
  601. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-CV850oio.js +0 -1
@@ -0,0 +1,22 @@
1
+ import { create as e } from "../node_modules/zustand/esm/react.js";
2
+ //#region src/stores/free-models-store.ts
3
+ var t = /* @__PURE__ */ new Set(), n = e()((e) => ({
4
+ freeModels: t,
5
+ defaultModel: null,
6
+ defaultModelReady: !1,
7
+ setFlags: (t) => e({
8
+ freeModels: t.freeModels,
9
+ defaultModel: t.defaultModel,
10
+ defaultModelReady: !0
11
+ }),
12
+ markDefaultModelReady: () => e({ defaultModelReady: !0 }),
13
+ resetFlags: () => e({
14
+ freeModels: t,
15
+ defaultModel: null,
16
+ defaultModelReady: !1
17
+ })
18
+ }));
19
+ //#endregion
20
+ export { n as useFreeModelsStore };
21
+
22
+ //# sourceMappingURL=free-models-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"free-models-store.js","names":[],"sources":["../../src/stores/free-models-store.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport type { FreeModelSet } from \"#/utils/format-model-name\";\n\ninterface FreeModelsState {\n /**\n * DB-driven set of free ``provider/model`` ids (the same channel that carries\n * `verified`). Empty on backends without free metadata (e.g. the local\n * agent-server), so consumers uniformly treat \"not in set\" as paid.\n */\n freeModels: FreeModelSet;\n /** DB-driven default OpenHands model id (``openhands/<model>``), or null. */\n defaultModel: string | null;\n /** True once the backend flags query has settled at least once. */\n defaultModelReady: boolean;\n}\n\ninterface FreeModelsActions {\n /**\n * Replaces the DB-driven flags. Called once by the app-level hydrator\n * ({@link useHydrateFreeModels}) after the backend model list is fetched, so\n * leaf components can read the flags synchronously via zustand selectors\n * without needing a QueryClientProvider in scope.\n */\n setFlags: (flags: {\n freeModels: FreeModelSet;\n defaultModel: string | null;\n }) => void;\n markDefaultModelReady: () => void;\n resetFlags: () => void;\n}\n\ntype FreeModelsStore = FreeModelsState & FreeModelsActions;\n\nconst EMPTY_FREE_MODELS: FreeModelSet = new Set<string>();\n\nexport const useFreeModelsStore = create<FreeModelsStore>()((set) => ({\n freeModels: EMPTY_FREE_MODELS,\n defaultModel: null,\n defaultModelReady: false,\n setFlags: (flags) =>\n set({\n freeModels: flags.freeModels,\n defaultModel: flags.defaultModel,\n defaultModelReady: true,\n }),\n markDefaultModelReady: () => set({ defaultModelReady: true }),\n resetFlags: () =>\n set({\n freeModels: EMPTY_FREE_MODELS,\n defaultModel: null,\n defaultModelReady: false,\n }),\n}));\n"],"mappings":";;AAiCA,IAAM,oBAAkC,IAAI,IAAY,GAE3C,IAAqB,EAAwB,GAAG,OAAS;CACpE,YAAY;CACZ,cAAc;CACd,mBAAmB;CACnB,WAAW,MACT,EAAI;EACF,YAAY,EAAM;EAClB,cAAc,EAAM;EACpB,mBAAmB;CACrB,CAAC;CACH,6BAA6B,EAAI,EAAE,mBAAmB,GAAK,CAAC;CAC5D,kBACE,EAAI;EACF,YAAY;EACZ,cAAc;EACd,mBAAmB;CACrB,CAAC;AACL,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"automation.cjs","names":[],"sources":["../../src/types/automation.ts"],"sourcesContent":["export interface AutomationTrigger {\n /**\n * Trigger kind. Known values are the schedule aliases \"cron\" / \"schedule\"\n * (time-based) and \"event\" (webhook/event-driven). Kept as `string` rather\n * than a closed union on purpose: the backend emits more than one\n * scheduled-trigger alias and may introduce new kinds, so UI code branches\n * on `type === \"event\"` and treats every other value as a schedule.\n */\n type: string;\n /** Cron expression (schedule triggers only). */\n schedule?: string;\n /** Human-readable schedule description (schedule triggers only). */\n schedule_human?: string;\n /** IANA timezone name (schedule triggers only). */\n timezone?: string;\n /** Event source, e.g. \"github\" (event triggers only). */\n source?: string;\n /** Event key pattern(s) to match, e.g. \"pull_request.opened\" or [\"push\", \"release.*\"]. */\n on?: string | string[];\n /** JMESPath filter expression evaluated against the raw webhook payload. */\n filter?: string;\n}\n\nexport interface Automation {\n id: string;\n name: string;\n trigger: AutomationTrigger;\n enabled: boolean;\n /**\n * UUID of the user who created this automation. The backend returns it in\n * `AutomationResponse.user_id`; the frontend uses it to implement the\n * \"creator escape hatch\" — a member (view-only) may still edit their own\n * automations even without `manage_automations`.\n */\n user_id?: string;\n repository?: string;\n /** LLM/model profile name used for automation runs. */\n model?: string | null;\n /**\n * Maximum run time in seconds. `null`/omitted uses the server default\n * (600s, 10 min); the deployment reports the maximum it accepts.\n */\n timeout?: number | null;\n\n created_at: string;\n updated_at: string;\n prompt: string | null;\n branch?: string;\n plugins?: string[];\n notification?: string;\n timezone?: string;\n last_triggered_at?: string | null;\n /**\n * Service-owned preset state, returned verbatim. The GUI reads only the\n * `template` provenance block inside it ({id, version, config}, written at\n * setup time), and only through the guarded helper in\n * `#/utils/automation-catalog`.\n */\n preset_metadata?: Record<string, unknown> | null;\n}\n\nexport type AutomationSpec = Omit<\n Automation,\n \"id\" | \"created_at\" | \"updated_at\" | \"last_triggered_at\" | \"preset_metadata\"\n>;\n\n/** The envelope constants come from the interface manifest's import/export spec. */\nexport interface AutomationExportFile {\n version: number;\n kind: string;\n spec: AutomationSpec;\n}\n\nexport interface AutomationsResponse {\n automations: Automation[];\n total: number;\n}\n\n/** Mirrors `RunStatus` in the automation service's OpenAPI schema. */\nexport enum AutomationRunStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n SKIPPED = \"SKIPPED\",\n}\n\nexport type AutomationTaskOutcomeStatus =\n | \"success\"\n | \"partial_success\"\n | \"blocked\"\n | \"failed\"\n | \"unknown\";\n\nexport interface AutomationFinishToolResponse {\n status?: AutomationTaskOutcomeStatus | string;\n outcome_summary?: string;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunMetadata {\n finish_tool_response?: AutomationFinishToolResponse | string | null;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunStatusDetail {\n phase?: string;\n kind?: string;\n detail?: string;\n formatted_detail?: string;\n transient?: boolean;\n source?: string;\n operation?: string;\n code?: string;\n status_code?: number;\n [key: string]: unknown;\n}\n\nexport interface AutomationRun {\n id: string;\n status: AutomationRunStatus;\n conversation_id: string | null;\n /**\n * ID of the bash command that ran the automation inside the agent-server\n * sandbox. Used to fetch run logs from\n * `/api/bash/bash_events/{bash_command_id}` and the matching\n * `BashOutput` events. Null when the run failed before a command was\n * dispatched (e.g. sandbox provisioning errors).\n */\n bash_command_id: string | null;\n error_detail: string | null;\n status_detail?: AutomationRunStatusDetail | null;\n run_metadata?: AutomationRunMetadata | null;\n /**\n * Accumulated LLM cost of the run in USD, reported by the SDK in the\n * completion callback. `null` means unknown — the run predates cost\n * tracking, or ended without a callback (cancelled, watchdog timeout).\n * Absent entirely when the automation service is older than the release\n * that added the field, hence optional.\n */\n cost?: number | null;\n /**\n * Machine-readable code for the run's current or last-known phase (e.g.\n * \"sandbox_provisioning\"). `null` means nothing has reported one; absent\n * entirely against an automation service that predates phase reporting.\n * Code and label are one value, always written together.\n */\n phase_code?: string | null;\n /**\n * Author-supplied description of the phase (at most 200 characters, no\n * control or separator characters, emoji and non-Latin text allowed).\n * Data, not translatable interface copy.\n */\n phase_label?: string | null;\n /** UTC datetime the phase was last written. Same nullability as `phase_code`. */\n phase_updated_at?: string | null;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface AutomationRunsResponse {\n runs: AutomationRun[];\n total: number;\n /**\n * Lifetime run counts by status, unaffected by pagination. Sparse — a\n * status with no runs has no key, so when the field is present a missing\n * key means zero. Absent entirely when the automation service is older\n * than the release that added it.\n */\n status_counts?: Partial<Record<AutomationRunStatus, number>>;\n}\n\nexport type ActivityLogExportFormat = \"json\" | \"csv\";\n\n/** Client-built Activity Log export row (from list runs + automation detail). */\nexport interface AutomationRunExportRow {\n run_id: string;\n automation_id: string;\n automation_name: string;\n trigger: AutomationTrigger | Record<string, unknown>;\n start_time: string | null;\n end_time: string | null;\n duration_seconds: number | null;\n status: AutomationRunStatus;\n conversation_id: string | null;\n conversation_url: string | null;\n error: string | null;\n /**\n * Accumulated LLM cost in USD, or null when unknown. Unlike\n * `AutomationRun[\"cost\"]` this is always present: the row normalizes a\n * missing field to null so every exported record has the same shape.\n */\n cost: number | null;\n /**\n * The raw `phase_code`, like `status`, falling back to `phase_label` for a\n * phase reported without a code. Null only when the run has no phase.\n */\n phase: string | null;\n}\n"],"mappings":"6CA+EA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,UAAA,YACA,EAAA,OAAA,SACA,EAAA,UAAA,YACA,EAAA,QAAA,WACF,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"automation.cjs","names":[],"sources":["../../src/types/automation.ts"],"sourcesContent":["export interface AutomationTrigger {\n /**\n * Trigger kind. Known values are the schedule aliases \"cron\" / \"schedule\"\n * (time-based) and \"event\" (webhook/event-driven). Kept as `string` rather\n * than a closed union on purpose: the backend emits more than one\n * scheduled-trigger alias and may introduce new kinds, so UI code branches\n * on `type === \"event\"` and treats every other value as a schedule.\n */\n type: string;\n /** Cron expression (schedule triggers only). */\n schedule?: string;\n /** Human-readable schedule description (schedule triggers only). */\n schedule_human?: string;\n /** IANA timezone name (schedule triggers only). */\n timezone?: string;\n /** Event source, e.g. \"github\" (event triggers only). */\n source?: string;\n /** Event key pattern(s) to match, e.g. \"pull_request.opened\" or [\"push\", \"release.*\"]. */\n on?: string | string[];\n /** JMESPath filter expression evaluated against the raw webhook payload. */\n filter?: string;\n}\n\nexport interface Automation {\n id: string;\n name: string;\n trigger: AutomationTrigger;\n enabled: boolean;\n /**\n * Human-readable reason the automation was last disabled (the latest\n * disablement event overwrites this). Mirrors the automation service's\n * `AutomationResponse.disabled_reason`. `null`/absent for enabled automations\n * or an automation service older than the release that started recording it.\n */\n disabled_reason?: string | null;\n /**\n * Structured disablement metadata from the automation service\n * (`AutomationResponse.disabled_detail`): `{reason, source, run_id, ...}`\n * plus rule-specific fields (threshold, consecutive counts, status_detail).\n * Used to tell user-initiated (\"manual\") disables from automatic ones\n * (consecutive failures, permanent config faults).\n */\n disabled_detail?: {\n reason?: string;\n source?: string;\n run_id?: string | null;\n [key: string]: unknown;\n } | null;\n /** UTC timestamp the automation was last disabled. */\n disabled_at?: string | null;\n /**\n * UUID of the user who created this automation. The backend returns it in\n * `AutomationResponse.user_id`; the frontend uses it to implement the\n * \"creator escape hatch\" — a member (view-only) may still edit their own\n * automations even without `manage_automations`.\n */\n user_id?: string;\n repository?: string;\n /** LLM/model profile name used for automation runs. */\n model?: string | null;\n /**\n * Maximum run time in seconds. `null`/omitted uses the server default\n * (600s, 10 min); the deployment reports the maximum it accepts.\n */\n timeout?: number | null;\n\n created_at: string;\n updated_at: string;\n prompt: string | null;\n branch?: string;\n plugins?: string[];\n notification?: string;\n timezone?: string;\n last_triggered_at?: string | null;\n /**\n * Service-owned preset state, returned verbatim. The GUI reads only the\n * `template` provenance block inside it ({id, version, config}, written at\n * setup time), and only through the guarded helper in\n * `#/utils/automation-catalog`.\n */\n preset_metadata?: Record<string, unknown> | null;\n}\n\nexport type AutomationSpec = Omit<\n Automation,\n | \"id\"\n | \"created_at\"\n | \"updated_at\"\n | \"last_triggered_at\"\n | \"preset_metadata\"\n | \"disabled_reason\"\n | \"disabled_detail\"\n | \"disabled_at\"\n>;\n\n/** The envelope constants come from the interface manifest's import/export spec. */\nexport interface AutomationExportFile {\n version: number;\n kind: string;\n spec: AutomationSpec;\n}\n\nexport interface AutomationsResponse {\n automations: Automation[];\n total: number;\n}\n\n/** Mirrors `RunStatus` in the automation service's OpenAPI schema. */\nexport enum AutomationRunStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n SKIPPED = \"SKIPPED\",\n}\n\nexport type AutomationTaskOutcomeStatus =\n | \"success\"\n | \"partial_success\"\n | \"blocked\"\n | \"failed\"\n | \"unknown\";\n\nexport interface AutomationFinishToolResponse {\n status?: AutomationTaskOutcomeStatus | string;\n outcome_summary?: string;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunMetadata {\n finish_tool_response?: AutomationFinishToolResponse | string | null;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunStatusDetail {\n phase?: string;\n kind?: string;\n detail?: string;\n formatted_detail?: string;\n transient?: boolean;\n source?: string;\n operation?: string;\n code?: string;\n status_code?: number;\n [key: string]: unknown;\n}\n\nexport interface AutomationRun {\n id: string;\n status: AutomationRunStatus;\n conversation_id: string | null;\n /**\n * ID of the bash command that ran the automation inside the agent-server\n * sandbox. Used to fetch run logs from\n * `/api/bash/bash_events/{bash_command_id}` and the matching\n * `BashOutput` events. Null when the run failed before a command was\n * dispatched (e.g. sandbox provisioning errors).\n */\n bash_command_id: string | null;\n error_detail: string | null;\n status_detail?: AutomationRunStatusDetail | null;\n run_metadata?: AutomationRunMetadata | null;\n /**\n * Accumulated LLM cost of the run in USD, reported by the SDK in the\n * completion callback. `null` means unknown — the run predates cost\n * tracking, or ended without a callback (cancelled, watchdog timeout).\n * Absent entirely when the automation service is older than the release\n * that added the field, hence optional.\n */\n cost?: number | null;\n /**\n * Machine-readable code for the run's current or last-known phase (e.g.\n * \"sandbox_provisioning\"). `null` means nothing has reported one; absent\n * entirely against an automation service that predates phase reporting.\n * Code and label are one value, always written together.\n */\n phase_code?: string | null;\n /**\n * Author-supplied description of the phase (at most 200 characters, no\n * control or separator characters, emoji and non-Latin text allowed).\n * Data, not translatable interface copy.\n */\n phase_label?: string | null;\n /** UTC datetime the phase was last written. Same nullability as `phase_code`. */\n phase_updated_at?: string | null;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface AutomationRunsResponse {\n runs: AutomationRun[];\n total: number;\n /**\n * Lifetime run counts by status, unaffected by pagination. Sparse — a\n * status with no runs has no key, so when the field is present a missing\n * key means zero. Absent entirely when the automation service is older\n * than the release that added it.\n */\n status_counts?: Partial<Record<AutomationRunStatus, number>>;\n}\n\nexport type ActivityLogExportFormat = \"json\" | \"csv\";\n\n/** Client-built Activity Log export row (from list runs + automation detail). */\nexport interface AutomationRunExportRow {\n run_id: string;\n automation_id: string;\n automation_name: string;\n trigger: AutomationTrigger | Record<string, unknown>;\n start_time: string | null;\n end_time: string | null;\n duration_seconds: number | null;\n status: AutomationRunStatus;\n conversation_id: string | null;\n conversation_url: string | null;\n error: string | null;\n /**\n * Accumulated LLM cost in USD, or null when unknown. Unlike\n * `AutomationRun[\"cost\"]` this is always present: the row normalizes a\n * missing field to null so every exported record has the same shape.\n */\n cost: number | null;\n /**\n * The raw `phase_code`, like `status`, falling back to `phase_label` for a\n * phase reported without a code. Null only when the run has no phase.\n */\n phase: string | null;\n}\n"],"mappings":"6CA4GA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,UAAA,YACA,EAAA,OAAA,SACA,EAAA,UAAA,YACA,EAAA,QAAA,WACF,EAAA,CAAA,CAAA"}
@@ -25,6 +25,28 @@ export interface Automation {
25
25
  name: string;
26
26
  trigger: AutomationTrigger;
27
27
  enabled: boolean;
28
+ /**
29
+ * Human-readable reason the automation was last disabled (the latest
30
+ * disablement event overwrites this). Mirrors the automation service's
31
+ * `AutomationResponse.disabled_reason`. `null`/absent for enabled automations
32
+ * or an automation service older than the release that started recording it.
33
+ */
34
+ disabled_reason?: string | null;
35
+ /**
36
+ * Structured disablement metadata from the automation service
37
+ * (`AutomationResponse.disabled_detail`): `{reason, source, run_id, ...}`
38
+ * plus rule-specific fields (threshold, consecutive counts, status_detail).
39
+ * Used to tell user-initiated ("manual") disables from automatic ones
40
+ * (consecutive failures, permanent config faults).
41
+ */
42
+ disabled_detail?: {
43
+ reason?: string;
44
+ source?: string;
45
+ run_id?: string | null;
46
+ [key: string]: unknown;
47
+ } | null;
48
+ /** UTC timestamp the automation was last disabled. */
49
+ disabled_at?: string | null;
28
50
  /**
29
51
  * UUID of the user who created this automation. The backend returns it in
30
52
  * `AutomationResponse.user_id`; the frontend uses it to implement the
@@ -56,7 +78,7 @@ export interface Automation {
56
78
  */
57
79
  preset_metadata?: Record<string, unknown> | null;
58
80
  }
59
- export type AutomationSpec = Omit<Automation, "id" | "created_at" | "updated_at" | "last_triggered_at" | "preset_metadata">;
81
+ export type AutomationSpec = Omit<Automation, "id" | "created_at" | "updated_at" | "last_triggered_at" | "preset_metadata" | "disabled_reason" | "disabled_detail" | "disabled_at">;
60
82
  /** The envelope constants come from the interface manifest's import/export spec. */
61
83
  export interface AutomationExportFile {
62
84
  version: number;
@@ -1 +1 @@
1
- {"version":3,"file":"automation.js","names":[],"sources":["../../src/types/automation.ts"],"sourcesContent":["export interface AutomationTrigger {\n /**\n * Trigger kind. Known values are the schedule aliases \"cron\" / \"schedule\"\n * (time-based) and \"event\" (webhook/event-driven). Kept as `string` rather\n * than a closed union on purpose: the backend emits more than one\n * scheduled-trigger alias and may introduce new kinds, so UI code branches\n * on `type === \"event\"` and treats every other value as a schedule.\n */\n type: string;\n /** Cron expression (schedule triggers only). */\n schedule?: string;\n /** Human-readable schedule description (schedule triggers only). */\n schedule_human?: string;\n /** IANA timezone name (schedule triggers only). */\n timezone?: string;\n /** Event source, e.g. \"github\" (event triggers only). */\n source?: string;\n /** Event key pattern(s) to match, e.g. \"pull_request.opened\" or [\"push\", \"release.*\"]. */\n on?: string | string[];\n /** JMESPath filter expression evaluated against the raw webhook payload. */\n filter?: string;\n}\n\nexport interface Automation {\n id: string;\n name: string;\n trigger: AutomationTrigger;\n enabled: boolean;\n /**\n * UUID of the user who created this automation. The backend returns it in\n * `AutomationResponse.user_id`; the frontend uses it to implement the\n * \"creator escape hatch\" — a member (view-only) may still edit their own\n * automations even without `manage_automations`.\n */\n user_id?: string;\n repository?: string;\n /** LLM/model profile name used for automation runs. */\n model?: string | null;\n /**\n * Maximum run time in seconds. `null`/omitted uses the server default\n * (600s, 10 min); the deployment reports the maximum it accepts.\n */\n timeout?: number | null;\n\n created_at: string;\n updated_at: string;\n prompt: string | null;\n branch?: string;\n plugins?: string[];\n notification?: string;\n timezone?: string;\n last_triggered_at?: string | null;\n /**\n * Service-owned preset state, returned verbatim. The GUI reads only the\n * `template` provenance block inside it ({id, version, config}, written at\n * setup time), and only through the guarded helper in\n * `#/utils/automation-catalog`.\n */\n preset_metadata?: Record<string, unknown> | null;\n}\n\nexport type AutomationSpec = Omit<\n Automation,\n \"id\" | \"created_at\" | \"updated_at\" | \"last_triggered_at\" | \"preset_metadata\"\n>;\n\n/** The envelope constants come from the interface manifest's import/export spec. */\nexport interface AutomationExportFile {\n version: number;\n kind: string;\n spec: AutomationSpec;\n}\n\nexport interface AutomationsResponse {\n automations: Automation[];\n total: number;\n}\n\n/** Mirrors `RunStatus` in the automation service's OpenAPI schema. */\nexport enum AutomationRunStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n SKIPPED = \"SKIPPED\",\n}\n\nexport type AutomationTaskOutcomeStatus =\n | \"success\"\n | \"partial_success\"\n | \"blocked\"\n | \"failed\"\n | \"unknown\";\n\nexport interface AutomationFinishToolResponse {\n status?: AutomationTaskOutcomeStatus | string;\n outcome_summary?: string;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunMetadata {\n finish_tool_response?: AutomationFinishToolResponse | string | null;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunStatusDetail {\n phase?: string;\n kind?: string;\n detail?: string;\n formatted_detail?: string;\n transient?: boolean;\n source?: string;\n operation?: string;\n code?: string;\n status_code?: number;\n [key: string]: unknown;\n}\n\nexport interface AutomationRun {\n id: string;\n status: AutomationRunStatus;\n conversation_id: string | null;\n /**\n * ID of the bash command that ran the automation inside the agent-server\n * sandbox. Used to fetch run logs from\n * `/api/bash/bash_events/{bash_command_id}` and the matching\n * `BashOutput` events. Null when the run failed before a command was\n * dispatched (e.g. sandbox provisioning errors).\n */\n bash_command_id: string | null;\n error_detail: string | null;\n status_detail?: AutomationRunStatusDetail | null;\n run_metadata?: AutomationRunMetadata | null;\n /**\n * Accumulated LLM cost of the run in USD, reported by the SDK in the\n * completion callback. `null` means unknown — the run predates cost\n * tracking, or ended without a callback (cancelled, watchdog timeout).\n * Absent entirely when the automation service is older than the release\n * that added the field, hence optional.\n */\n cost?: number | null;\n /**\n * Machine-readable code for the run's current or last-known phase (e.g.\n * \"sandbox_provisioning\"). `null` means nothing has reported one; absent\n * entirely against an automation service that predates phase reporting.\n * Code and label are one value, always written together.\n */\n phase_code?: string | null;\n /**\n * Author-supplied description of the phase (at most 200 characters, no\n * control or separator characters, emoji and non-Latin text allowed).\n * Data, not translatable interface copy.\n */\n phase_label?: string | null;\n /** UTC datetime the phase was last written. Same nullability as `phase_code`. */\n phase_updated_at?: string | null;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface AutomationRunsResponse {\n runs: AutomationRun[];\n total: number;\n /**\n * Lifetime run counts by status, unaffected by pagination. Sparse — a\n * status with no runs has no key, so when the field is present a missing\n * key means zero. Absent entirely when the automation service is older\n * than the release that added it.\n */\n status_counts?: Partial<Record<AutomationRunStatus, number>>;\n}\n\nexport type ActivityLogExportFormat = \"json\" | \"csv\";\n\n/** Client-built Activity Log export row (from list runs + automation detail). */\nexport interface AutomationRunExportRow {\n run_id: string;\n automation_id: string;\n automation_name: string;\n trigger: AutomationTrigger | Record<string, unknown>;\n start_time: string | null;\n end_time: string | null;\n duration_seconds: number | null;\n status: AutomationRunStatus;\n conversation_id: string | null;\n conversation_url: string | null;\n error: string | null;\n /**\n * Accumulated LLM cost in USD, or null when unknown. Unlike\n * `AutomationRun[\"cost\"]` this is always present: the row normalizes a\n * missing field to null so every exported record has the same shape.\n */\n cost: number | null;\n /**\n * The raw `phase_code`, like `status`, falling back to `phase_label` for a\n * phase reported without a code. Null only when the run has no phase.\n */\n phase: string | null;\n}\n"],"mappings":";AA+EA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,UAAA,WACA,EAAA,UAAA,WACA,EAAA,YAAA,aACA,EAAA,SAAA,UACA,EAAA,YAAA,aACA,EAAA,UAAA;AACF,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"automation.js","names":[],"sources":["../../src/types/automation.ts"],"sourcesContent":["export interface AutomationTrigger {\n /**\n * Trigger kind. Known values are the schedule aliases \"cron\" / \"schedule\"\n * (time-based) and \"event\" (webhook/event-driven). Kept as `string` rather\n * than a closed union on purpose: the backend emits more than one\n * scheduled-trigger alias and may introduce new kinds, so UI code branches\n * on `type === \"event\"` and treats every other value as a schedule.\n */\n type: string;\n /** Cron expression (schedule triggers only). */\n schedule?: string;\n /** Human-readable schedule description (schedule triggers only). */\n schedule_human?: string;\n /** IANA timezone name (schedule triggers only). */\n timezone?: string;\n /** Event source, e.g. \"github\" (event triggers only). */\n source?: string;\n /** Event key pattern(s) to match, e.g. \"pull_request.opened\" or [\"push\", \"release.*\"]. */\n on?: string | string[];\n /** JMESPath filter expression evaluated against the raw webhook payload. */\n filter?: string;\n}\n\nexport interface Automation {\n id: string;\n name: string;\n trigger: AutomationTrigger;\n enabled: boolean;\n /**\n * Human-readable reason the automation was last disabled (the latest\n * disablement event overwrites this). Mirrors the automation service's\n * `AutomationResponse.disabled_reason`. `null`/absent for enabled automations\n * or an automation service older than the release that started recording it.\n */\n disabled_reason?: string | null;\n /**\n * Structured disablement metadata from the automation service\n * (`AutomationResponse.disabled_detail`): `{reason, source, run_id, ...}`\n * plus rule-specific fields (threshold, consecutive counts, status_detail).\n * Used to tell user-initiated (\"manual\") disables from automatic ones\n * (consecutive failures, permanent config faults).\n */\n disabled_detail?: {\n reason?: string;\n source?: string;\n run_id?: string | null;\n [key: string]: unknown;\n } | null;\n /** UTC timestamp the automation was last disabled. */\n disabled_at?: string | null;\n /**\n * UUID of the user who created this automation. The backend returns it in\n * `AutomationResponse.user_id`; the frontend uses it to implement the\n * \"creator escape hatch\" — a member (view-only) may still edit their own\n * automations even without `manage_automations`.\n */\n user_id?: string;\n repository?: string;\n /** LLM/model profile name used for automation runs. */\n model?: string | null;\n /**\n * Maximum run time in seconds. `null`/omitted uses the server default\n * (600s, 10 min); the deployment reports the maximum it accepts.\n */\n timeout?: number | null;\n\n created_at: string;\n updated_at: string;\n prompt: string | null;\n branch?: string;\n plugins?: string[];\n notification?: string;\n timezone?: string;\n last_triggered_at?: string | null;\n /**\n * Service-owned preset state, returned verbatim. The GUI reads only the\n * `template` provenance block inside it ({id, version, config}, written at\n * setup time), and only through the guarded helper in\n * `#/utils/automation-catalog`.\n */\n preset_metadata?: Record<string, unknown> | null;\n}\n\nexport type AutomationSpec = Omit<\n Automation,\n | \"id\"\n | \"created_at\"\n | \"updated_at\"\n | \"last_triggered_at\"\n | \"preset_metadata\"\n | \"disabled_reason\"\n | \"disabled_detail\"\n | \"disabled_at\"\n>;\n\n/** The envelope constants come from the interface manifest's import/export spec. */\nexport interface AutomationExportFile {\n version: number;\n kind: string;\n spec: AutomationSpec;\n}\n\nexport interface AutomationsResponse {\n automations: Automation[];\n total: number;\n}\n\n/** Mirrors `RunStatus` in the automation service's OpenAPI schema. */\nexport enum AutomationRunStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n SKIPPED = \"SKIPPED\",\n}\n\nexport type AutomationTaskOutcomeStatus =\n | \"success\"\n | \"partial_success\"\n | \"blocked\"\n | \"failed\"\n | \"unknown\";\n\nexport interface AutomationFinishToolResponse {\n status?: AutomationTaskOutcomeStatus | string;\n outcome_summary?: string;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunMetadata {\n finish_tool_response?: AutomationFinishToolResponse | string | null;\n [key: string]: unknown;\n}\n\nexport interface AutomationRunStatusDetail {\n phase?: string;\n kind?: string;\n detail?: string;\n formatted_detail?: string;\n transient?: boolean;\n source?: string;\n operation?: string;\n code?: string;\n status_code?: number;\n [key: string]: unknown;\n}\n\nexport interface AutomationRun {\n id: string;\n status: AutomationRunStatus;\n conversation_id: string | null;\n /**\n * ID of the bash command that ran the automation inside the agent-server\n * sandbox. Used to fetch run logs from\n * `/api/bash/bash_events/{bash_command_id}` and the matching\n * `BashOutput` events. Null when the run failed before a command was\n * dispatched (e.g. sandbox provisioning errors).\n */\n bash_command_id: string | null;\n error_detail: string | null;\n status_detail?: AutomationRunStatusDetail | null;\n run_metadata?: AutomationRunMetadata | null;\n /**\n * Accumulated LLM cost of the run in USD, reported by the SDK in the\n * completion callback. `null` means unknown — the run predates cost\n * tracking, or ended without a callback (cancelled, watchdog timeout).\n * Absent entirely when the automation service is older than the release\n * that added the field, hence optional.\n */\n cost?: number | null;\n /**\n * Machine-readable code for the run's current or last-known phase (e.g.\n * \"sandbox_provisioning\"). `null` means nothing has reported one; absent\n * entirely against an automation service that predates phase reporting.\n * Code and label are one value, always written together.\n */\n phase_code?: string | null;\n /**\n * Author-supplied description of the phase (at most 200 characters, no\n * control or separator characters, emoji and non-Latin text allowed).\n * Data, not translatable interface copy.\n */\n phase_label?: string | null;\n /** UTC datetime the phase was last written. Same nullability as `phase_code`. */\n phase_updated_at?: string | null;\n started_at: string;\n completed_at: string | null;\n}\n\nexport interface AutomationRunsResponse {\n runs: AutomationRun[];\n total: number;\n /**\n * Lifetime run counts by status, unaffected by pagination. Sparse — a\n * status with no runs has no key, so when the field is present a missing\n * key means zero. Absent entirely when the automation service is older\n * than the release that added it.\n */\n status_counts?: Partial<Record<AutomationRunStatus, number>>;\n}\n\nexport type ActivityLogExportFormat = \"json\" | \"csv\";\n\n/** Client-built Activity Log export row (from list runs + automation detail). */\nexport interface AutomationRunExportRow {\n run_id: string;\n automation_id: string;\n automation_name: string;\n trigger: AutomationTrigger | Record<string, unknown>;\n start_time: string | null;\n end_time: string | null;\n duration_seconds: number | null;\n status: AutomationRunStatus;\n conversation_id: string | null;\n conversation_url: string | null;\n error: string | null;\n /**\n * Accumulated LLM cost in USD, or null when unknown. Unlike\n * `AutomationRun[\"cost\"]` this is always present: the row normalizes a\n * missing field to null so every exported record has the same shape.\n */\n cost: number | null;\n /**\n * The raw `phase_code`, like `status`, falling back to `phase_label` for a\n * phase reported without a code. Null only when the run has no phase.\n */\n phase: string | null;\n}\n"],"mappings":";AA4GA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,UAAA,WACA,EAAA,UAAA,WACA,EAAA,YAAA,aACA,EAAA,SAAA,UACA,EAAA,YAAA,aACA,EAAA,UAAA;AACF,EAAA,CAAA,CAAA"}
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");const e=require("../i18n/declaration.cjs");var t=new Set([`user`]),n=new Set([`manual`,`manual_delete`]);function r(e){return!e.enabled&&!!e.disabled_reason}function i(e){let r=e.disabled_reason;if(r&&n.has(r))return!0;let i=e.disabled_detail?.source;return!!(i&&t.has(i))}function a(t,n){return r(t)?i(t)?{text:n(e.I18nKey.AUTOMATIONS$DETAIL$DISABLED_MANUAL)}:{text:t.disabled_reason}:null}exports.getDisablementReasonDisplay=a,exports.hasDisablementReason=r;
2
+ //# sourceMappingURL=automation-disabled-reason.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-disabled-reason.cjs","names":[],"sources":["../../src/utils/automation-disabled-reason.ts"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { Automation } from \"#/types/automation\";\n\n/** Detail `source` values written by the automation service on disable. */\nconst MANUAL_DETAIL_SOURCES = new Set([\"user\"]);\n/** Top-level `disabled_reason` values written for user-initiated disables. */\nconst MANUAL_REASON_VALUES = new Set([\"manual\", \"manual_delete\"]);\n\n/**\n * Whether an automation is inactive *because* of a recorded disablement\n * reason (vs. simply toggled off by an older client path, or an automation\n * service that predates disablement tracking).\n *\n * The automation service overwrites `disabled_reason`/`disabled_detail`/\n * `disabled_at` on every disable and clears them on every re-enable, so when\n * an automation is `enabled === false` and carries a `disabled_reason`, that\n * reason is the latest reason it went inactive.\n */\nexport function hasDisablementReason(\n automation: Pick<Automation, \"enabled\" | \"disabled_reason\">,\n): boolean {\n return !automation.enabled && Boolean(automation.disabled_reason);\n}\n\n/**\n * Whether the recorded disablement was user-initiated (manual toggle / delete)\n * rather than an automatic pause for failing runs.\n */\nexport function isManualDisable(\n automation: Pick<Automation, \"disabled_reason\" | \"disabled_detail\">,\n): boolean {\n const reason = automation.disabled_reason;\n if (reason && MANUAL_REASON_VALUES.has(reason)) return true;\n const source = automation.disabled_detail?.source;\n if (source && MANUAL_DETAIL_SOURCES.has(source)) return true;\n return false;\n}\n\nexport interface DisablementReasonDisplay {\n /**\n * Full reason text to render. For automatic disables this is the backend's\n * human-readable `disabled_reason` (already phrased for users, e.g.\n * \"Paused automatically: auth — ...\"). For manual disables the backend\n * stores the opaque \"manual\" string, so we substitute a localized label.\n */\n text: string;\n}\n\n/**\n * Resolve the disablement reason into display text. Returns `null` when the\n * automation is not inactive-for-a-recorded-reason.\n */\nexport function getDisablementReasonDisplay(\n automation: Pick<\n Automation,\n \"enabled\" | \"disabled_reason\" | \"disabled_detail\"\n >,\n t: (key: I18nKey) => string,\n): DisablementReasonDisplay | null {\n if (!hasDisablementReason(automation)) return null;\n if (isManualDisable(automation)) {\n return { text: t(I18nKey.AUTOMATIONS$DETAIL$DISABLED_MANUAL) };\n }\n return { text: automation.disabled_reason as string };\n}\n"],"mappings":"wFAIA,IAAM,EAAwB,IAAI,IAAI,CAAC,MAAM,CAAC,EAExC,EAAuB,IAAI,IAAI,CAAC,SAAU,eAAe,CAAC,EAYhE,SAAgB,EACd,EACS,CACT,MAAO,CAAC,EAAW,SAAW,EAAQ,EAAW,eACnD,CAMA,SAAgB,EACd,EACS,CACT,IAAM,EAAS,EAAW,gBAC1B,GAAI,GAAU,EAAqB,IAAI,CAAM,EAAG,MAAO,GACvD,IAAM,EAAS,EAAW,iBAAiB,OAE3C,MADA,GAAI,GAAU,EAAsB,IAAI,CAAM,EAEhD,CAgBA,SAAgB,EACd,EAIA,EACiC,CAKjC,OAJK,EAAqB,CAAU,EAChC,EAAgB,CAAU,EACrB,CAAE,KAAM,EAAE,EAAA,QAAQ,kCAAkC,CAAE,EAExD,CAAE,KAAM,EAAW,eAA0B,EAJN,IAKhD"}
@@ -0,0 +1,32 @@
1
+ import { I18nKey } from "#/i18n/declaration";
2
+ import type { Automation } from "#/types/automation";
3
+ /**
4
+ * Whether an automation is inactive *because* of a recorded disablement
5
+ * reason (vs. simply toggled off by an older client path, or an automation
6
+ * service that predates disablement tracking).
7
+ *
8
+ * The automation service overwrites `disabled_reason`/`disabled_detail`/
9
+ * `disabled_at` on every disable and clears them on every re-enable, so when
10
+ * an automation is `enabled === false` and carries a `disabled_reason`, that
11
+ * reason is the latest reason it went inactive.
12
+ */
13
+ export declare function hasDisablementReason(automation: Pick<Automation, "enabled" | "disabled_reason">): boolean;
14
+ /**
15
+ * Whether the recorded disablement was user-initiated (manual toggle / delete)
16
+ * rather than an automatic pause for failing runs.
17
+ */
18
+ export declare function isManualDisable(automation: Pick<Automation, "disabled_reason" | "disabled_detail">): boolean;
19
+ export interface DisablementReasonDisplay {
20
+ /**
21
+ * Full reason text to render. For automatic disables this is the backend's
22
+ * human-readable `disabled_reason` (already phrased for users, e.g.
23
+ * "Paused automatically: auth — ..."). For manual disables the backend
24
+ * stores the opaque "manual" string, so we substitute a localized label.
25
+ */
26
+ text: string;
27
+ }
28
+ /**
29
+ * Resolve the disablement reason into display text. Returns `null` when the
30
+ * automation is not inactive-for-a-recorded-reason.
31
+ */
32
+ export declare function getDisablementReasonDisplay(automation: Pick<Automation, "enabled" | "disabled_reason" | "disabled_detail">, t: (key: I18nKey) => string): DisablementReasonDisplay | null;
@@ -0,0 +1,19 @@
1
+ import { I18nKey as e } from "../i18n/declaration.js";
2
+ //#region src/utils/automation-disabled-reason.ts
3
+ var t = new Set(["user"]), n = new Set(["manual", "manual_delete"]);
4
+ function r(e) {
5
+ return !e.enabled && !!e.disabled_reason;
6
+ }
7
+ function i(e) {
8
+ let r = e.disabled_reason;
9
+ if (r && n.has(r)) return !0;
10
+ let i = e.disabled_detail?.source;
11
+ return !!(i && t.has(i));
12
+ }
13
+ function a(t, n) {
14
+ return r(t) ? i(t) ? { text: n(e.AUTOMATIONS$DETAIL$DISABLED_MANUAL) } : { text: t.disabled_reason } : null;
15
+ }
16
+ //#endregion
17
+ export { a as getDisablementReasonDisplay, r as hasDisablementReason };
18
+
19
+ //# sourceMappingURL=automation-disabled-reason.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation-disabled-reason.js","names":[],"sources":["../../src/utils/automation-disabled-reason.ts"],"sourcesContent":["import { I18nKey } from \"#/i18n/declaration\";\nimport type { Automation } from \"#/types/automation\";\n\n/** Detail `source` values written by the automation service on disable. */\nconst MANUAL_DETAIL_SOURCES = new Set([\"user\"]);\n/** Top-level `disabled_reason` values written for user-initiated disables. */\nconst MANUAL_REASON_VALUES = new Set([\"manual\", \"manual_delete\"]);\n\n/**\n * Whether an automation is inactive *because* of a recorded disablement\n * reason (vs. simply toggled off by an older client path, or an automation\n * service that predates disablement tracking).\n *\n * The automation service overwrites `disabled_reason`/`disabled_detail`/\n * `disabled_at` on every disable and clears them on every re-enable, so when\n * an automation is `enabled === false` and carries a `disabled_reason`, that\n * reason is the latest reason it went inactive.\n */\nexport function hasDisablementReason(\n automation: Pick<Automation, \"enabled\" | \"disabled_reason\">,\n): boolean {\n return !automation.enabled && Boolean(automation.disabled_reason);\n}\n\n/**\n * Whether the recorded disablement was user-initiated (manual toggle / delete)\n * rather than an automatic pause for failing runs.\n */\nexport function isManualDisable(\n automation: Pick<Automation, \"disabled_reason\" | \"disabled_detail\">,\n): boolean {\n const reason = automation.disabled_reason;\n if (reason && MANUAL_REASON_VALUES.has(reason)) return true;\n const source = automation.disabled_detail?.source;\n if (source && MANUAL_DETAIL_SOURCES.has(source)) return true;\n return false;\n}\n\nexport interface DisablementReasonDisplay {\n /**\n * Full reason text to render. For automatic disables this is the backend's\n * human-readable `disabled_reason` (already phrased for users, e.g.\n * \"Paused automatically: auth — ...\"). For manual disables the backend\n * stores the opaque \"manual\" string, so we substitute a localized label.\n */\n text: string;\n}\n\n/**\n * Resolve the disablement reason into display text. Returns `null` when the\n * automation is not inactive-for-a-recorded-reason.\n */\nexport function getDisablementReasonDisplay(\n automation: Pick<\n Automation,\n \"enabled\" | \"disabled_reason\" | \"disabled_detail\"\n >,\n t: (key: I18nKey) => string,\n): DisablementReasonDisplay | null {\n if (!hasDisablementReason(automation)) return null;\n if (isManualDisable(automation)) {\n return { text: t(I18nKey.AUTOMATIONS$DETAIL$DISABLED_MANUAL) };\n }\n return { text: automation.disabled_reason as string };\n}\n"],"mappings":";;AAIA,IAAM,IAAwB,IAAI,IAAI,CAAC,MAAM,CAAC,GAExC,IAAuB,IAAI,IAAI,CAAC,UAAU,eAAe,CAAC;AAYhE,SAAgB,EACd,GACS;CACT,OAAO,CAAC,EAAW,WAAW,EAAQ,EAAW;AACnD;AAMA,SAAgB,EACd,GACS;CACT,IAAM,IAAS,EAAW;CAC1B,IAAI,KAAU,EAAqB,IAAI,CAAM,GAAG,OAAO;CACvD,IAAM,IAAS,EAAW,iBAAiB;CAE3C,OADA,GAAI,KAAU,EAAsB,IAAI,CAAM;AAEhD;AAgBA,SAAgB,EACd,GAIA,GACiC;CAKjC,OAJK,EAAqB,CAAU,IAChC,EAAgB,CAAU,IACrB,EAAE,MAAM,EAAE,EAAQ,kCAAkC,EAAE,IAExD,EAAE,MAAM,EAAW,gBAA0B,IAJN;AAKhD"}
@@ -1,2 +1,2 @@
1
- require("../_virtual/_rolldown/runtime.cjs");var e=`Free`,t={"openhands/deepseek-v4-flash":`OpenHands DeepSeek V4 Flash (free)`},n=Object.keys(t),r=e=>!!e?.startsWith(`openhands/`),i=`Free OpenHands models: ${n.join(`, `)}. Other provider endpoints with similar model names may require separate billing.`,a=e=>!!(e&&e in t);function o(e){return e?a(e)?t[e]:e:null}function s(e){return e?a(e)?t[e]:e.split(`/`).pop()||e:null}exports.FREE_MODEL_BADGE_LABEL=e,exports.FREE_OPENHANDS_MODEL_NOTE=i,exports.formatModelNameForDisplay=o,exports.formatNativeModelName=s,exports.isFreeOpenHandsModel=a,exports.isOpenHandsProviderModel=r;
1
+ require("../_virtual/_rolldown/runtime.cjs");var e=`Free`,t=` (free)`,n={"openhands/deepseek-v4-flash":`OpenHands DeepSeek V4 Flash`},r=new Set,i=e=>!!e?.startsWith(`openhands/`),a=(e,t=r)=>!!(e&&t.has(e));function o(e,n){return n?`${e}${t}`:e}function s(e,t=r){return e?o(e,a(e,t)):null}function c(e,t=r){if(!e)return null;let n=a(e,t);return o(e.split(`/`).pop()||e,n)}function l(e,t=r){return e?o(e in n?n[e]:e,a(e,t)):null}exports.FREE_MODEL_BADGE_LABEL=e,exports.formatModelNameForDisplay=s,exports.formatModelPillLabel=l,exports.formatNativeModelName=c,exports.isFreeOpenHandsModel=a,exports.isOpenHandsProviderModel=i;
2
2
  //# sourceMappingURL=format-model-name.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-model-name.cjs","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash (free)\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\n\n/**\n * Whether a model id routes through the OpenHands provider (the `openhands/`\n * prefix). On cloud the OpenHands provider is backed by a server-minted LLM\n * key rather than a user-supplied one, so callers use this to hide the inline\n * API key / base URL inputs and strip those fields from the save payload.\n */\nexport const isOpenHandsProviderModel = (\n model: string | null | undefined,\n): boolean => Boolean(model?.startsWith(\"openhands/\"));\n\nexport const FREE_OPENHANDS_MODEL_NOTE = `Free OpenHands models: ${FREE_OPENHANDS_MODEL_IDS.join(\n \", \",\n)}. Other provider endpoints with similar model names may require separate billing.`;\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n): model is keyof typeof FREE_OPENHANDS_MODELS =>\n Boolean(model && model in FREE_OPENHANDS_MODELS);\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n return isFreeOpenHandsModel(model) ? FREE_OPENHANDS_MODELS[model] : model;\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return isFreeOpenHandsModel(fullModel)\n ? FREE_OPENHANDS_MODELS[fullModel]\n : model;\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n if (isFreeOpenHandsModel(model)) return FREE_OPENHANDS_MODELS[model];\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":"6CAAA,IAAa,EAAyB,OAEzB,EAAwB,CACnC,8BAA+B,oCACjC,EAEa,EAA2B,OAAO,KAAK,CAAqB,EAQ5D,EACX,GACY,EAAQ,GAAO,WAAW,YAAY,EAEvC,EAA4B,0BAA0B,EAAyB,KAC1F,IACF,EAAE,mFAEW,EACX,GAEA,GAAQ,GAAS,KAAS,GAE5B,SAAgB,EACd,EACe,CAEf,OADK,EACE,EAAqB,CAAK,EAAI,EAAsB,GAAS,EADjD,IAErB,CA2BA,SAAgB,EACd,EACe,CAIf,OAHK,EACD,EAAqB,CAAK,EAAU,EAAsB,GAC1C,EAAM,MAAM,GAAG,EAAE,IAC9B,GAAe,EAHH,IAIrB"}
1
+ {"version":3,"file":"format-model-name.cjs","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\n/** Suffix appended to a display name for a DB-flagged free OpenHands model. */\nexport const FREE_MODEL_SUFFIX = \" (free)\";\n\n/**\n * Static pretty-print labels for OpenHands models known at build time. Free\n * status still comes only from the backend-provided `freeModels` set.\n */\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\n\n/**\n * Set of free ``provider/model`` ids. The frontend no longer hardcodes which\n * OpenHands models are free — the set is sourced from the backend model list\n * (DB-driven), the same channel that carries `verified`. See\n * {@link useFreeModels}. Callers that lack the set treat every model as paid.\n */\nexport type FreeModelSet = ReadonlySet<string>;\n\nconst EMPTY_FREE_MODELS: FreeModelSet = new Set<string>();\n\n/**\n * Whether a model id routes through the OpenHands provider (the `openhands/`\n * prefix). On cloud the OpenHands provider is backed by a server-minted LLM\n * key rather than a user-supplied one, so callers use this to hide the inline\n * API key / base URL inputs and strip those fields from the save payload.\n */\nexport const isOpenHandsProviderModel = (\n model: string | null | undefined,\n): boolean => Boolean(model?.startsWith(\"openhands/\"));\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): boolean => Boolean(model && freeModels.has(model));\n\nfunction appendFreeSuffix(display: string, isFree: boolean): string {\n return isFree ? `${display}${FREE_MODEL_SUFFIX}` : display;\n}\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n return appendFreeSuffix(model, isFreeOpenHandsModel(model, freeModels));\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return appendFreeSuffix(model, isFreeOpenHandsModel(fullModel, freeModels));\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * A DB-flagged free model (matched against ``freeModels`` on its full id) keeps\n * the free suffix so the chip still signals it is free.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const isFree = isFreeOpenHandsModel(model, freeModels);\n const lastSegment = model.split(\"/\").pop();\n return appendFreeSuffix(lastSegment || model, isFree);\n}\n\n/**\n * Display label used by the LLM-profile picker sub-line. Looks up the model in\n * the static label table for a prettier name, but appends `(free)` only when the\n * backend-provided `freeModels` set marks the concrete model free.\n */\nexport function formatModelPillLabel(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const display =\n model in FREE_OPENHANDS_MODELS\n ? FREE_OPENHANDS_MODELS[model as keyof typeof FREE_OPENHANDS_MODELS]\n : model;\n return appendFreeSuffix(display, isFreeOpenHandsModel(model, freeModels));\n}\n"],"mappings":"6CAAA,IAAa,EAAyB,OAGzB,EAAoB,UAMpB,EAAwB,CACnC,8BAA+B,6BACjC,EAYM,EAAkC,IAAI,IAQ/B,EACX,GACY,EAAQ,GAAO,WAAW,YAAY,EAEvC,GACX,EACA,EAA2B,IACf,GAAQ,GAAS,EAAW,IAAI,CAAK,GAEnD,SAAS,EAAiB,EAAiB,EAAyB,CAClE,OAAO,EAAS,GAAG,IAAU,IAAsB,CACrD,CAEA,SAAgB,EACd,EACA,EAA2B,EACZ,CAEf,OADK,EACE,EAAiB,EAAO,EAAqB,EAAO,CAAU,CAAC,EADnD,IAErB,CA6BA,SAAgB,EACd,EACA,EAA2B,EACZ,CACf,GAAI,CAAC,EAAO,OAAO,KACnB,IAAM,EAAS,EAAqB,EAAO,CAAU,EAErD,OAAO,EADa,EAAM,MAAM,GAAG,EAAE,IACb,GAAe,EAAO,CAAM,CACtD,CAOA,SAAgB,EACd,EACA,EAA2B,EACZ,CAMf,OALK,EAKE,EAHL,KAAS,EACL,EAAsB,GACtB,EAC2B,EAAqB,EAAO,CAAU,CAAC,EALrD,IAMrB"}
@@ -1,8 +1,21 @@
1
1
  export declare const FREE_MODEL_BADGE_LABEL = "Free";
2
+ /** Suffix appended to a display name for a DB-flagged free OpenHands model. */
3
+ export declare const FREE_MODEL_SUFFIX = " (free)";
4
+ /**
5
+ * Static pretty-print labels for OpenHands models known at build time. Free
6
+ * status still comes only from the backend-provided `freeModels` set.
7
+ */
2
8
  export declare const FREE_OPENHANDS_MODELS: {
3
- readonly "openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash (free)";
9
+ readonly "openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash";
4
10
  };
5
11
  export declare const FREE_OPENHANDS_MODEL_IDS: string[];
12
+ /**
13
+ * Set of free ``provider/model`` ids. The frontend no longer hardcodes which
14
+ * OpenHands models are free — the set is sourced from the backend model list
15
+ * (DB-driven), the same channel that carries `verified`. See
16
+ * {@link useFreeModels}. Callers that lack the set treat every model as paid.
17
+ */
18
+ export type FreeModelSet = ReadonlySet<string>;
6
19
  /**
7
20
  * Whether a model id routes through the OpenHands provider (the `openhands/`
8
21
  * prefix). On cloud the OpenHands provider is backed by a server-minted LLM
@@ -10,10 +23,9 @@ export declare const FREE_OPENHANDS_MODEL_IDS: string[];
10
23
  * API key / base URL inputs and strip those fields from the save payload.
11
24
  */
12
25
  export declare const isOpenHandsProviderModel: (model: string | null | undefined) => boolean;
13
- export declare const FREE_OPENHANDS_MODEL_NOTE: string;
14
- export declare const isFreeOpenHandsModel: (model: string | null | undefined) => model is keyof typeof FREE_OPENHANDS_MODELS;
15
- export declare function formatModelNameForDisplay(model: string | null | undefined): string | null;
16
- export declare function formatProviderModelNameForDisplay(provider: string | null | undefined, model: string | null | undefined): string | null;
26
+ export declare const isFreeOpenHandsModel: (model: string | null | undefined, freeModels?: FreeModelSet) => boolean;
27
+ export declare function formatModelNameForDisplay(model: string | null | undefined, freeModels?: FreeModelSet): string | null;
28
+ export declare function formatProviderModelNameForDisplay(provider: string | null | undefined, model: string | null | undefined, freeModels?: FreeModelSet): string | null;
17
29
  /**
18
30
  * Format a native (OpenHands-kind) routing model string for display, stripping
19
31
  * the provider route prefix (e.g. ``"anthropic/claude-sonnet-4-5-20250929"`` →
@@ -25,7 +37,16 @@ export declare function formatProviderModelNameForDisplay(provider: string | nul
25
37
  * string when stripping the prefix would leave nothing (e.g. a trailing slash)
26
38
  * — never an empty string, which would collapse the chip text.
27
39
  *
40
+ * A DB-flagged free model (matched against ``freeModels`` on its full id) keeps
41
+ * the free suffix so the chip still signals it is free.
42
+ *
28
43
  * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize
29
44
  * to an identifier, so it keeps the real model id intact for the chip.
30
45
  */
31
- export declare function formatNativeModelName(model: string | null | undefined): string | null;
46
+ export declare function formatNativeModelName(model: string | null | undefined, freeModels?: FreeModelSet): string | null;
47
+ /**
48
+ * Display label used by the LLM-profile picker sub-line. Looks up the model in
49
+ * the static label table for a prettier name, but appends `(free)` only when the
50
+ * backend-provided `freeModels` set marks the concrete model free.
51
+ */
52
+ export declare function formatModelPillLabel(model: string | null | undefined, freeModels?: FreeModelSet): string | null;
@@ -1,12 +1,20 @@
1
1
  //#region src/utils/format-model-name.ts
2
- var e = "Free", t = { "openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash (free)" }, n = Object.keys(t), r = (e) => !!e?.startsWith("openhands/"), i = `Free OpenHands models: ${n.join(", ")}. Other provider endpoints with similar model names may require separate billing.`, a = (e) => !!(e && e in t);
3
- function o(e) {
4
- return e ? a(e) ? t[e] : e : null;
2
+ var e = "Free", t = " (free)", n = { "openhands/deepseek-v4-flash": "OpenHands DeepSeek V4 Flash" }, r = /* @__PURE__ */ new Set(), i = (e) => !!e?.startsWith("openhands/"), a = (e, t = r) => !!(e && t.has(e));
3
+ function o(e, n) {
4
+ return n ? `${e}${t}` : e;
5
5
  }
6
- function s(e) {
7
- return e ? a(e) ? t[e] : e.split("/").pop() || e : null;
6
+ function s(e, t = r) {
7
+ return e ? o(e, a(e, t)) : null;
8
+ }
9
+ function c(e, t = r) {
10
+ if (!e) return null;
11
+ let n = a(e, t);
12
+ return o(e.split("/").pop() || e, n);
13
+ }
14
+ function l(e, t = r) {
15
+ return e ? o(e in n ? n[e] : e, a(e, t)) : null;
8
16
  }
9
17
  //#endregion
10
- export { e as FREE_MODEL_BADGE_LABEL, i as FREE_OPENHANDS_MODEL_NOTE, o as formatModelNameForDisplay, s as formatNativeModelName, a as isFreeOpenHandsModel, r as isOpenHandsProviderModel };
18
+ export { e as FREE_MODEL_BADGE_LABEL, s as formatModelNameForDisplay, l as formatModelPillLabel, c as formatNativeModelName, a as isFreeOpenHandsModel, i as isOpenHandsProviderModel };
11
19
 
12
20
  //# sourceMappingURL=format-model-name.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-model-name.js","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash (free)\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\n\n/**\n * Whether a model id routes through the OpenHands provider (the `openhands/`\n * prefix). On cloud the OpenHands provider is backed by a server-minted LLM\n * key rather than a user-supplied one, so callers use this to hide the inline\n * API key / base URL inputs and strip those fields from the save payload.\n */\nexport const isOpenHandsProviderModel = (\n model: string | null | undefined,\n): boolean => Boolean(model?.startsWith(\"openhands/\"));\n\nexport const FREE_OPENHANDS_MODEL_NOTE = `Free OpenHands models: ${FREE_OPENHANDS_MODEL_IDS.join(\n \", \",\n)}. Other provider endpoints with similar model names may require separate billing.`;\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n): model is keyof typeof FREE_OPENHANDS_MODELS =>\n Boolean(model && model in FREE_OPENHANDS_MODELS);\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n return isFreeOpenHandsModel(model) ? FREE_OPENHANDS_MODELS[model] : model;\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return isFreeOpenHandsModel(fullModel)\n ? FREE_OPENHANDS_MODELS[fullModel]\n : model;\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n): string | null {\n if (!model) return null;\n if (isFreeOpenHandsModel(model)) return FREE_OPENHANDS_MODELS[model];\n const lastSegment = model.split(\"/\").pop();\n return lastSegment || model;\n}\n"],"mappings":";AAAA,IAAa,IAAyB,QAEzB,IAAwB,EACnC,+BAA+B,qCACjC,GAEa,IAA2B,OAAO,KAAK,CAAqB,GAQ5D,KACX,MACY,EAAQ,GAAO,WAAW,YAAY,GAEvC,IAA4B,0BAA0B,EAAyB,KAC1F,IACF,EAAE,oFAEW,KACX,MAEA,GAAQ,KAAS,KAAS;AAE5B,SAAgB,EACd,GACe;CAEf,OADK,IACE,EAAqB,CAAK,IAAI,EAAsB,KAAS,IADjD;AAErB;AA2BA,SAAgB,EACd,GACe;CAIf,OAHK,IACD,EAAqB,CAAK,IAAU,EAAsB,KAC1C,EAAM,MAAM,GAAG,EAAE,IAC9B,KAAe,IAHH;AAIrB"}
1
+ {"version":3,"file":"format-model-name.js","names":[],"sources":["../../src/utils/format-model-name.ts"],"sourcesContent":["export const FREE_MODEL_BADGE_LABEL = \"Free\";\n\n/** Suffix appended to a display name for a DB-flagged free OpenHands model. */\nexport const FREE_MODEL_SUFFIX = \" (free)\";\n\n/**\n * Static pretty-print labels for OpenHands models known at build time. Free\n * status still comes only from the backend-provided `freeModels` set.\n */\nexport const FREE_OPENHANDS_MODELS = {\n \"openhands/deepseek-v4-flash\": \"OpenHands DeepSeek V4 Flash\",\n} as const;\n\nexport const FREE_OPENHANDS_MODEL_IDS = Object.keys(FREE_OPENHANDS_MODELS);\n\n/**\n * Set of free ``provider/model`` ids. The frontend no longer hardcodes which\n * OpenHands models are free — the set is sourced from the backend model list\n * (DB-driven), the same channel that carries `verified`. See\n * {@link useFreeModels}. Callers that lack the set treat every model as paid.\n */\nexport type FreeModelSet = ReadonlySet<string>;\n\nconst EMPTY_FREE_MODELS: FreeModelSet = new Set<string>();\n\n/**\n * Whether a model id routes through the OpenHands provider (the `openhands/`\n * prefix). On cloud the OpenHands provider is backed by a server-minted LLM\n * key rather than a user-supplied one, so callers use this to hide the inline\n * API key / base URL inputs and strip those fields from the save payload.\n */\nexport const isOpenHandsProviderModel = (\n model: string | null | undefined,\n): boolean => Boolean(model?.startsWith(\"openhands/\"));\n\nexport const isFreeOpenHandsModel = (\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): boolean => Boolean(model && freeModels.has(model));\n\nfunction appendFreeSuffix(display: string, isFree: boolean): string {\n return isFree ? `${display}${FREE_MODEL_SUFFIX}` : display;\n}\n\nexport function formatModelNameForDisplay(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n return appendFreeSuffix(model, isFreeOpenHandsModel(model, freeModels));\n}\n\nexport function formatProviderModelNameForDisplay(\n provider: string | null | undefined,\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const fullModel = provider ? `${provider}/${model}` : model;\n return appendFreeSuffix(model, isFreeOpenHandsModel(fullModel, freeModels));\n}\n\n/**\n * Format a native (OpenHands-kind) routing model string for display, stripping\n * the provider route prefix (e.g. ``\"anthropic/claude-sonnet-4-5-20250929\"`` →\n * ``\"claude-sonnet-4-5-20250929\"``, ``\"litellm_proxy/openai/gpt-4o\"`` →\n * ``\"gpt-4o\"``) so a conversation chip shows a meaningful model name rather than\n * the full routing path.\n *\n * Returns ``null`` for an empty/nullish input, and falls back to the original\n * string when stripping the prefix would leave nothing (e.g. a trailing slash)\n * — never an empty string, which would collapse the chip text.\n *\n * A DB-flagged free model (matched against ``freeModels`` on its full id) keeps\n * the free suffix so the chip still signals it is free.\n *\n * Display-only: unlike {@link deriveProfileNameFromModel} this does not sanitize\n * to an identifier, so it keeps the real model id intact for the chip.\n */\nexport function formatNativeModelName(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const isFree = isFreeOpenHandsModel(model, freeModels);\n const lastSegment = model.split(\"/\").pop();\n return appendFreeSuffix(lastSegment || model, isFree);\n}\n\n/**\n * Display label used by the LLM-profile picker sub-line. Looks up the model in\n * the static label table for a prettier name, but appends `(free)` only when the\n * backend-provided `freeModels` set marks the concrete model free.\n */\nexport function formatModelPillLabel(\n model: string | null | undefined,\n freeModels: FreeModelSet = EMPTY_FREE_MODELS,\n): string | null {\n if (!model) return null;\n const display =\n model in FREE_OPENHANDS_MODELS\n ? FREE_OPENHANDS_MODELS[model as keyof typeof FREE_OPENHANDS_MODELS]\n : model;\n return appendFreeSuffix(display, isFreeOpenHandsModel(model, freeModels));\n}\n"],"mappings":";AAAA,IAAa,IAAyB,QAGzB,IAAoB,WAMpB,IAAwB,EACnC,+BAA+B,8BACjC,GAYM,oBAAkC,IAAI,IAAY,GAQ3C,KACX,MACY,EAAQ,GAAO,WAAW,YAAY,GAEvC,KACX,GACA,IAA2B,MACf,GAAQ,KAAS,EAAW,IAAI,CAAK;AAEnD,SAAS,EAAiB,GAAiB,GAAyB;CAClE,OAAO,IAAS,GAAG,IAAU,MAAsB;AACrD;AAEA,SAAgB,EACd,GACA,IAA2B,GACZ;CAEf,OADK,IACE,EAAiB,GAAO,EAAqB,GAAO,CAAU,CAAC,IADnD;AAErB;AA6BA,SAAgB,EACd,GACA,IAA2B,GACZ;CACf,IAAI,CAAC,GAAO,OAAO;CACnB,IAAM,IAAS,EAAqB,GAAO,CAAU;CAErD,OAAO,EADa,EAAM,MAAM,GAAG,EAAE,IACb,KAAe,GAAO,CAAM;AACtD;AAOA,SAAgB,EACd,GACA,IAA2B,GACZ;CAMf,OALK,IAKE,EAHL,KAAS,IACL,EAAsB,KACtB,GAC2B,EAAqB,GAAO,CAAU,CAAC,IALrD;AAMrB"}
@@ -1,2 +1,2 @@
1
- require("../_virtual/_rolldown/runtime.cjs");var e={"github.com":`github`,"gitlab.com":`gitlab`,"bitbucket.org":`bitbucket`,"dev.azure.com":`azure_devops`};function t(e){return e.replace(/\.git$/,``)}function n(t){return t?e[t.toLowerCase()]??null:null}function r(e){let t=e.split(`/`).filter(Boolean),n=t.indexOf(`_git`);return n===-1?t.join(`/`):[...t.slice(0,n),...t.slice(n+1)].join(`/`)}function i(e,i,a){let o=t(a.replace(/^\/+|\/+$/g,``)),s=n(i);return{url:e,host:i,repository:(s===`azure_devops`?r(o):o)||null,provider:s}}function a(e){let t=e?.trim();if(!t)return null;try{let e=new URL(t);if(e.hostname)return i(t,e.hostname,e.pathname)}catch{}let n=t.match(/^[^@\s]+@([^:\s]+):(.+)$/);if(n){let e=n[1];return i(t,e,n[2])}return null}exports.parseGitRemoteUrl=a;
1
+ require("../_virtual/_rolldown/runtime.cjs");var e={"github.com":`github`,"gitlab.com":`gitlab`,"bitbucket.org":`bitbucket`,"dev.azure.com":`azure_devops`},t={"ssh.dev.azure.com":`dev.azure.com`,"vs-ssh.visualstudio.com":`dev.azure.com`};function n(e){let n=e.toLowerCase();return Object.hasOwn(t,n)?t[n]:e}function r(e){return e.replace(/\.git$/,``)}function i(t){return t?e[t.toLowerCase()]??null:null}function a(e){let t=e.split(`/`).filter(Boolean),n=t.indexOf(`_git`);return n===-1?(t[0]===`v3`&&t.shift(),t.join(`/`)):[...t.slice(0,n),...t.slice(n+1)].join(`/`)}function o(e,t,o){let s=t&&n(t),c=r(o.replace(/^\/+|\/+$/g,``)),l=i(s);return{url:e,host:s,repository:(l===`azure_devops`?a(c):c)||null,provider:l}}function s(e){let t=e?.trim();if(!t)return null;try{let e=new URL(t);if(e.hostname)return o(t,e.hostname,e.pathname)}catch{}let n=t.match(/^[^@\s]+@([^:\s]+):(.+)$/);if(n){let e=n[1];return o(t,e,n[2])}return null}exports.parseGitRemoteUrl=s;
2
2
  //# sourceMappingURL=parse-git-remote-url.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-git-remote-url.cjs","names":[],"sources":["../../src/utils/parse-git-remote-url.ts"],"sourcesContent":["import { Provider } from \"#/types/settings\";\n\nexport interface ParsedGitRemoteUrl {\n /** Original URL, trimmed. */\n url: string;\n /** Hostname of the remote (e.g. `github.com`, `git.example.com`). */\n host: string | null;\n /** Path-style identifier, normalized to `owner/repo` (no leading slash, no `.git` suffix). */\n repository: string | null;\n /** Best-effort provider detection from the host. `null` for unrecognized/self-hosted hosts. */\n provider: Provider | null;\n}\n\nconst KNOWN_HOSTS: Record<string, Provider> = {\n \"github.com\": \"github\",\n \"gitlab.com\": \"gitlab\",\n \"bitbucket.org\": \"bitbucket\",\n \"dev.azure.com\": \"azure_devops\",\n};\n\nfunction stripGitSuffix(path: string): string {\n return path.replace(/\\.git$/, \"\");\n}\n\nfunction detectProvider(host: string | null): Provider | null {\n if (!host) return null;\n return KNOWN_HOSTS[host.toLowerCase()] ?? null;\n}\n\nfunction normalizeAzureDevOpsPath(path: string): string {\n // Azure paths look like `org/project/_git/repo` or `org/_git/repo`.\n // Normalize to `org/project/repo` (or `org/repo`) so it lines up with\n // constructBranchUrl's expectations.\n const segments = path.split(\"/\").filter(Boolean);\n const gitIndex = segments.indexOf(\"_git\");\n if (gitIndex === -1) return segments.join(\"/\");\n return [...segments.slice(0, gitIndex), ...segments.slice(gitIndex + 1)].join(\n \"/\",\n );\n}\n\nfunction buildParsedGitRemoteUrl(\n url: string,\n host: string | null,\n rawPath: string,\n): ParsedGitRemoteUrl {\n const path = stripGitSuffix(rawPath.replace(/^\\/+|\\/+$/g, \"\"));\n const provider = detectProvider(host);\n const repository =\n provider === \"azure_devops\" ? normalizeAzureDevOpsPath(path) : path;\n\n return {\n url,\n host,\n repository: repository || null,\n provider,\n };\n}\n\n/**\n * Parse a git remote URL (HTTPS, SSH, or `git@host:path` shorthand) into its\n * host, repository (`owner/repo`), and best-effort provider.\n *\n * Returns `null` if the URL is empty or unparseable. Unknown hosts still\n * resolve `host` and `repository`; only `provider` is left `null`.\n */\nexport function parseGitRemoteUrl(\n remoteUrl: string | null | undefined,\n): ParsedGitRemoteUrl | null {\n const url = remoteUrl?.trim();\n if (!url) return null;\n\n // ssh://, https://, http://, git://. Tried before the shorthand match\n // below, whose `[^@\\s]+` would otherwise swallow `ssh://git` and read the\n // port in `ssh://git@host:2222/owner/repo` as the first path segment.\n try {\n const parsed = new URL(url);\n // A bare Windows path (`C:/src/repo`) parses as a `c:` scheme with an\n // empty host, so it is left to the shorthand match below.\n if (parsed.hostname) {\n return buildParsedGitRemoteUrl(url, parsed.hostname, parsed.pathname);\n }\n } catch {\n // Not a URL the WHATWG parser accepts, so try the shorthand form.\n }\n\n // git@host:owner/repo(.git)\n const scpMatch = url.match(/^[^@\\s]+@([^:\\s]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n return buildParsedGitRemoteUrl(url, host, scpMatch[2]);\n }\n\n return null;\n}\n"],"mappings":"6CAaA,IAAM,EAAwC,CAC5C,aAAc,SACd,aAAc,SACd,gBAAiB,YACjB,gBAAiB,cACnB,EAEA,SAAS,EAAe,EAAsB,CAC5C,OAAO,EAAK,QAAQ,SAAU,EAAE,CAClC,CAEA,SAAS,EAAe,EAAsC,CAE5D,OADK,EACE,EAAY,EAAK,YAAY,IAAM,KADxB,IAEpB,CAEA,SAAS,EAAyB,EAAsB,CAItD,IAAM,EAAW,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EACzC,EAAW,EAAS,QAAQ,MAAM,EAExC,OADI,IAAa,GAAW,EAAS,KAAK,GAAG,EACtC,CAAC,GAAG,EAAS,MAAM,EAAG,CAAQ,EAAG,GAAG,EAAS,MAAM,EAAW,CAAC,CAAC,EAAE,KACvE,GACF,CACF,CAEA,SAAS,EACP,EACA,EACA,EACoB,CACpB,IAAM,EAAO,EAAe,EAAQ,QAAQ,aAAc,EAAE,CAAC,EACvD,EAAW,EAAe,CAAI,EAIpC,MAAO,CACL,MACA,OACA,YALA,IAAa,eAAiB,EAAyB,CAAI,EAAI,IAKrC,KAC1B,UACF,CACF,CASA,SAAgB,EACd,EAC2B,CAC3B,IAAM,EAAM,GAAW,KAAK,EAC5B,GAAI,CAAC,EAAK,OAAO,KAKjB,GAAI,CACF,IAAM,EAAS,IAAI,IAAI,CAAG,EAG1B,GAAI,EAAO,SACT,OAAO,EAAwB,EAAK,EAAO,SAAU,EAAO,QAAQ,CAExE,MAAQ,CAER,CAGA,IAAM,EAAW,EAAI,MAAM,0BAA0B,EACrD,GAAI,EAAU,CACZ,IAAM,EAAO,EAAS,GACtB,OAAO,EAAwB,EAAK,EAAM,EAAS,EAAE,CACvD,CAEA,OAAO,IACT"}
1
+ {"version":3,"file":"parse-git-remote-url.cjs","names":[],"sources":["../../src/utils/parse-git-remote-url.ts"],"sourcesContent":["import { Provider } from \"#/types/settings\";\n\nexport interface ParsedGitRemoteUrl {\n /** Original URL, trimmed. */\n url: string;\n /**\n * Browsable hostname of the remote (e.g. `github.com`, `git.example.com`).\n * Hosts that only serve SSH are mapped to their web equivalent, so callers\n * can build links from this directly. `url` keeps the original remote.\n */\n host: string | null;\n /** Path-style identifier, normalized to `owner/repo` (no leading slash, no `.git` suffix). */\n repository: string | null;\n /** Best-effort provider detection from the host. `null` for unrecognized/self-hosted hosts. */\n provider: Provider | null;\n}\n\nconst KNOWN_HOSTS: Record<string, Provider> = {\n \"github.com\": \"github\",\n \"gitlab.com\": \"gitlab\",\n \"bitbucket.org\": \"bitbucket\",\n \"dev.azure.com\": \"azure_devops\",\n};\n\n// Hosts that serve git over SSH only, mapped to the host that serves the same\n// repositories over the web. Azure DevOps hands out `ssh.dev.azure.com` (and\n// `vs-ssh.visualstudio.com` for legacy organizations) in its SSH clone URLs,\n// neither of which resolves a browsable page.\nconst SSH_WEB_HOSTS: Record<string, string> = {\n \"ssh.dev.azure.com\": \"dev.azure.com\",\n \"vs-ssh.visualstudio.com\": \"dev.azure.com\",\n};\n\nfunction toWebHost(host: string): string {\n const lower = host.toLowerCase();\n // hasOwn, so a host named after an Object.prototype member (`constructor`)\n // resolves to itself rather than to an inherited value.\n return Object.hasOwn(SSH_WEB_HOSTS, lower) ? SSH_WEB_HOSTS[lower] : host;\n}\n\nfunction stripGitSuffix(path: string): string {\n return path.replace(/\\.git$/, \"\");\n}\n\nfunction detectProvider(host: string | null): Provider | null {\n if (!host) return null;\n return KNOWN_HOSTS[host.toLowerCase()] ?? null;\n}\n\nfunction normalizeAzureDevOpsPath(path: string): string {\n // Azure paths look like `org/project/_git/repo` or `org/_git/repo` over\n // HTTPS, and `v3/org/project/repo` over SSH. Normalize to `org/project/repo`\n // (or `org/repo`) so it lines up with constructBranchUrl's expectations.\n const segments = path.split(\"/\").filter(Boolean);\n const gitIndex = segments.indexOf(\"_git\");\n if (gitIndex === -1) {\n // Only the SSH form carries the `v3` prefix, and it never carries `_git`.\n // Checking that first leaves an organization actually named `v3` alone.\n if (segments[0] === \"v3\") segments.shift();\n return segments.join(\"/\");\n }\n return [...segments.slice(0, gitIndex), ...segments.slice(gitIndex + 1)].join(\n \"/\",\n );\n}\n\nfunction buildParsedGitRemoteUrl(\n url: string,\n rawHost: string | null,\n rawPath: string,\n): ParsedGitRemoteUrl {\n const host = rawHost ? toWebHost(rawHost) : rawHost;\n const path = stripGitSuffix(rawPath.replace(/^\\/+|\\/+$/g, \"\"));\n const provider = detectProvider(host);\n const repository =\n provider === \"azure_devops\" ? normalizeAzureDevOpsPath(path) : path;\n\n return {\n url,\n host,\n repository: repository || null,\n provider,\n };\n}\n\n/**\n * Parse a git remote URL (HTTPS, SSH, or `git@host:path` shorthand) into its\n * host, repository (`owner/repo`), and best-effort provider.\n *\n * Returns `null` if the URL is empty or unparseable. Unknown hosts still\n * resolve `host` and `repository`; only `provider` is left `null`.\n */\nexport function parseGitRemoteUrl(\n remoteUrl: string | null | undefined,\n): ParsedGitRemoteUrl | null {\n const url = remoteUrl?.trim();\n if (!url) return null;\n\n // ssh://, https://, http://, git://. Tried before the shorthand match\n // below, whose `[^@\\s]+` would otherwise swallow `ssh://git` and read the\n // port in `ssh://git@host:2222/owner/repo` as the first path segment.\n try {\n const parsed = new URL(url);\n // A bare Windows path (`C:/src/repo`) parses as a `c:` scheme with an\n // empty host, so it is left to the shorthand match below.\n if (parsed.hostname) {\n return buildParsedGitRemoteUrl(url, parsed.hostname, parsed.pathname);\n }\n } catch {\n // Not a URL the WHATWG parser accepts, so try the shorthand form.\n }\n\n // git@host:owner/repo(.git)\n const scpMatch = url.match(/^[^@\\s]+@([^:\\s]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n return buildParsedGitRemoteUrl(url, host, scpMatch[2]);\n }\n\n return null;\n}\n"],"mappings":"6CAiBA,IAAM,EAAwC,CAC5C,aAAc,SACd,aAAc,SACd,gBAAiB,YACjB,gBAAiB,cACnB,EAMM,EAAwC,CAC5C,oBAAqB,gBACrB,0BAA2B,eAC7B,EAEA,SAAS,EAAU,EAAsB,CACvC,IAAM,EAAQ,EAAK,YAAY,EAG/B,OAAO,OAAO,OAAO,EAAe,CAAK,EAAI,EAAc,GAAS,CACtE,CAEA,SAAS,EAAe,EAAsB,CAC5C,OAAO,EAAK,QAAQ,SAAU,EAAE,CAClC,CAEA,SAAS,EAAe,EAAsC,CAE5D,OADK,EACE,EAAY,EAAK,YAAY,IAAM,KADxB,IAEpB,CAEA,SAAS,EAAyB,EAAsB,CAItD,IAAM,EAAW,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EACzC,EAAW,EAAS,QAAQ,MAAM,EAOxC,OANI,IAAa,IAGX,EAAS,KAAO,MAAM,EAAS,MAAM,EAClC,EAAS,KAAK,GAAG,GAEnB,CAAC,GAAG,EAAS,MAAM,EAAG,CAAQ,EAAG,GAAG,EAAS,MAAM,EAAW,CAAC,CAAC,EAAE,KACvE,GACF,CACF,CAEA,SAAS,EACP,EACA,EACA,EACoB,CACpB,IAAM,EAAO,GAAU,EAAU,CAAO,EAClC,EAAO,EAAe,EAAQ,QAAQ,aAAc,EAAE,CAAC,EACvD,EAAW,EAAe,CAAI,EAIpC,MAAO,CACL,MACA,OACA,YALA,IAAa,eAAiB,EAAyB,CAAI,EAAI,IAKrC,KAC1B,UACF,CACF,CASA,SAAgB,EACd,EAC2B,CAC3B,IAAM,EAAM,GAAW,KAAK,EAC5B,GAAI,CAAC,EAAK,OAAO,KAKjB,GAAI,CACF,IAAM,EAAS,IAAI,IAAI,CAAG,EAG1B,GAAI,EAAO,SACT,OAAO,EAAwB,EAAK,EAAO,SAAU,EAAO,QAAQ,CAExE,MAAQ,CAER,CAGA,IAAM,EAAW,EAAI,MAAM,0BAA0B,EACrD,GAAI,EAAU,CACZ,IAAM,EAAO,EAAS,GACtB,OAAO,EAAwB,EAAK,EAAM,EAAS,EAAE,CACvD,CAEA,OAAO,IACT"}
@@ -2,7 +2,11 @@ import { Provider } from "#/types/settings";
2
2
  export interface ParsedGitRemoteUrl {
3
3
  /** Original URL, trimmed. */
4
4
  url: string;
5
- /** Hostname of the remote (e.g. `github.com`, `git.example.com`). */
5
+ /**
6
+ * Browsable hostname of the remote (e.g. `github.com`, `git.example.com`).
7
+ * Hosts that only serve SSH are mapped to their web equivalent, so callers
8
+ * can build links from this directly. `url` keeps the original remote.
9
+ */
6
10
  host: string | null;
7
11
  /** Path-style identifier, normalized to `owner/repo` (no leading slash, no `.git` suffix). */
8
12
  repository: string | null;
@@ -4,41 +4,48 @@ var e = {
4
4
  "gitlab.com": "gitlab",
5
5
  "bitbucket.org": "bitbucket",
6
6
  "dev.azure.com": "azure_devops"
7
+ }, t = {
8
+ "ssh.dev.azure.com": "dev.azure.com",
9
+ "vs-ssh.visualstudio.com": "dev.azure.com"
7
10
  };
8
- function t(e) {
11
+ function n(e) {
12
+ let n = e.toLowerCase();
13
+ return Object.hasOwn(t, n) ? t[n] : e;
14
+ }
15
+ function r(e) {
9
16
  return e.replace(/\.git$/, "");
10
17
  }
11
- function n(t) {
18
+ function i(t) {
12
19
  return t ? e[t.toLowerCase()] ?? null : null;
13
20
  }
14
- function r(e) {
21
+ function a(e) {
15
22
  let t = e.split("/").filter(Boolean), n = t.indexOf("_git");
16
- return n === -1 ? t.join("/") : [...t.slice(0, n), ...t.slice(n + 1)].join("/");
23
+ return n === -1 ? (t[0] === "v3" && t.shift(), t.join("/")) : [...t.slice(0, n), ...t.slice(n + 1)].join("/");
17
24
  }
18
- function i(e, i, a) {
19
- let o = t(a.replace(/^\/+|\/+$/g, "")), s = n(i);
25
+ function o(e, t, o) {
26
+ let s = t && n(t), c = r(o.replace(/^\/+|\/+$/g, "")), l = i(s);
20
27
  return {
21
28
  url: e,
22
- host: i,
23
- repository: (s === "azure_devops" ? r(o) : o) || null,
24
- provider: s
29
+ host: s,
30
+ repository: (l === "azure_devops" ? a(c) : c) || null,
31
+ provider: l
25
32
  };
26
33
  }
27
- function a(e) {
34
+ function s(e) {
28
35
  let t = e?.trim();
29
36
  if (!t) return null;
30
37
  try {
31
38
  let e = new URL(t);
32
- if (e.hostname) return i(t, e.hostname, e.pathname);
39
+ if (e.hostname) return o(t, e.hostname, e.pathname);
33
40
  } catch {}
34
41
  let n = t.match(/^[^@\s]+@([^:\s]+):(.+)$/);
35
42
  if (n) {
36
43
  let e = n[1];
37
- return i(t, e, n[2]);
44
+ return o(t, e, n[2]);
38
45
  }
39
46
  return null;
40
47
  }
41
48
  //#endregion
42
- export { a as parseGitRemoteUrl };
49
+ export { s as parseGitRemoteUrl };
43
50
 
44
51
  //# sourceMappingURL=parse-git-remote-url.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-git-remote-url.js","names":[],"sources":["../../src/utils/parse-git-remote-url.ts"],"sourcesContent":["import { Provider } from \"#/types/settings\";\n\nexport interface ParsedGitRemoteUrl {\n /** Original URL, trimmed. */\n url: string;\n /** Hostname of the remote (e.g. `github.com`, `git.example.com`). */\n host: string | null;\n /** Path-style identifier, normalized to `owner/repo` (no leading slash, no `.git` suffix). */\n repository: string | null;\n /** Best-effort provider detection from the host. `null` for unrecognized/self-hosted hosts. */\n provider: Provider | null;\n}\n\nconst KNOWN_HOSTS: Record<string, Provider> = {\n \"github.com\": \"github\",\n \"gitlab.com\": \"gitlab\",\n \"bitbucket.org\": \"bitbucket\",\n \"dev.azure.com\": \"azure_devops\",\n};\n\nfunction stripGitSuffix(path: string): string {\n return path.replace(/\\.git$/, \"\");\n}\n\nfunction detectProvider(host: string | null): Provider | null {\n if (!host) return null;\n return KNOWN_HOSTS[host.toLowerCase()] ?? null;\n}\n\nfunction normalizeAzureDevOpsPath(path: string): string {\n // Azure paths look like `org/project/_git/repo` or `org/_git/repo`.\n // Normalize to `org/project/repo` (or `org/repo`) so it lines up with\n // constructBranchUrl's expectations.\n const segments = path.split(\"/\").filter(Boolean);\n const gitIndex = segments.indexOf(\"_git\");\n if (gitIndex === -1) return segments.join(\"/\");\n return [...segments.slice(0, gitIndex), ...segments.slice(gitIndex + 1)].join(\n \"/\",\n );\n}\n\nfunction buildParsedGitRemoteUrl(\n url: string,\n host: string | null,\n rawPath: string,\n): ParsedGitRemoteUrl {\n const path = stripGitSuffix(rawPath.replace(/^\\/+|\\/+$/g, \"\"));\n const provider = detectProvider(host);\n const repository =\n provider === \"azure_devops\" ? normalizeAzureDevOpsPath(path) : path;\n\n return {\n url,\n host,\n repository: repository || null,\n provider,\n };\n}\n\n/**\n * Parse a git remote URL (HTTPS, SSH, or `git@host:path` shorthand) into its\n * host, repository (`owner/repo`), and best-effort provider.\n *\n * Returns `null` if the URL is empty or unparseable. Unknown hosts still\n * resolve `host` and `repository`; only `provider` is left `null`.\n */\nexport function parseGitRemoteUrl(\n remoteUrl: string | null | undefined,\n): ParsedGitRemoteUrl | null {\n const url = remoteUrl?.trim();\n if (!url) return null;\n\n // ssh://, https://, http://, git://. Tried before the shorthand match\n // below, whose `[^@\\s]+` would otherwise swallow `ssh://git` and read the\n // port in `ssh://git@host:2222/owner/repo` as the first path segment.\n try {\n const parsed = new URL(url);\n // A bare Windows path (`C:/src/repo`) parses as a `c:` scheme with an\n // empty host, so it is left to the shorthand match below.\n if (parsed.hostname) {\n return buildParsedGitRemoteUrl(url, parsed.hostname, parsed.pathname);\n }\n } catch {\n // Not a URL the WHATWG parser accepts, so try the shorthand form.\n }\n\n // git@host:owner/repo(.git)\n const scpMatch = url.match(/^[^@\\s]+@([^:\\s]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n return buildParsedGitRemoteUrl(url, host, scpMatch[2]);\n }\n\n return null;\n}\n"],"mappings":";AAaA,IAAM,IAAwC;CAC5C,cAAc;CACd,cAAc;CACd,iBAAiB;CACjB,iBAAiB;AACnB;AAEA,SAAS,EAAe,GAAsB;CAC5C,OAAO,EAAK,QAAQ,UAAU,EAAE;AAClC;AAEA,SAAS,EAAe,GAAsC;CAE5D,OADK,IACE,EAAY,EAAK,YAAY,MAAM,OADxB;AAEpB;AAEA,SAAS,EAAyB,GAAsB;CAItD,IAAM,IAAW,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,GACzC,IAAW,EAAS,QAAQ,MAAM;CAExC,OADI,MAAa,KAAW,EAAS,KAAK,GAAG,IACtC,CAAC,GAAG,EAAS,MAAM,GAAG,CAAQ,GAAG,GAAG,EAAS,MAAM,IAAW,CAAC,CAAC,EAAE,KACvE,GACF;AACF;AAEA,SAAS,EACP,GACA,GACA,GACoB;CACpB,IAAM,IAAO,EAAe,EAAQ,QAAQ,cAAc,EAAE,CAAC,GACvD,IAAW,EAAe,CAAI;CAIpC,OAAO;EACL;EACA;EACA,aALA,MAAa,iBAAiB,EAAyB,CAAI,IAAI,MAKrC;EAC1B;CACF;AACF;AASA,SAAgB,EACd,GAC2B;CAC3B,IAAM,IAAM,GAAW,KAAK;CAC5B,IAAI,CAAC,GAAK,OAAO;CAKjB,IAAI;EACF,IAAM,IAAS,IAAI,IAAI,CAAG;EAG1B,IAAI,EAAO,UACT,OAAO,EAAwB,GAAK,EAAO,UAAU,EAAO,QAAQ;CAExE,QAAQ,CAER;CAGA,IAAM,IAAW,EAAI,MAAM,0BAA0B;CACrD,IAAI,GAAU;EACZ,IAAM,IAAO,EAAS;EACtB,OAAO,EAAwB,GAAK,GAAM,EAAS,EAAE;CACvD;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"parse-git-remote-url.js","names":[],"sources":["../../src/utils/parse-git-remote-url.ts"],"sourcesContent":["import { Provider } from \"#/types/settings\";\n\nexport interface ParsedGitRemoteUrl {\n /** Original URL, trimmed. */\n url: string;\n /**\n * Browsable hostname of the remote (e.g. `github.com`, `git.example.com`).\n * Hosts that only serve SSH are mapped to their web equivalent, so callers\n * can build links from this directly. `url` keeps the original remote.\n */\n host: string | null;\n /** Path-style identifier, normalized to `owner/repo` (no leading slash, no `.git` suffix). */\n repository: string | null;\n /** Best-effort provider detection from the host. `null` for unrecognized/self-hosted hosts. */\n provider: Provider | null;\n}\n\nconst KNOWN_HOSTS: Record<string, Provider> = {\n \"github.com\": \"github\",\n \"gitlab.com\": \"gitlab\",\n \"bitbucket.org\": \"bitbucket\",\n \"dev.azure.com\": \"azure_devops\",\n};\n\n// Hosts that serve git over SSH only, mapped to the host that serves the same\n// repositories over the web. Azure DevOps hands out `ssh.dev.azure.com` (and\n// `vs-ssh.visualstudio.com` for legacy organizations) in its SSH clone URLs,\n// neither of which resolves a browsable page.\nconst SSH_WEB_HOSTS: Record<string, string> = {\n \"ssh.dev.azure.com\": \"dev.azure.com\",\n \"vs-ssh.visualstudio.com\": \"dev.azure.com\",\n};\n\nfunction toWebHost(host: string): string {\n const lower = host.toLowerCase();\n // hasOwn, so a host named after an Object.prototype member (`constructor`)\n // resolves to itself rather than to an inherited value.\n return Object.hasOwn(SSH_WEB_HOSTS, lower) ? SSH_WEB_HOSTS[lower] : host;\n}\n\nfunction stripGitSuffix(path: string): string {\n return path.replace(/\\.git$/, \"\");\n}\n\nfunction detectProvider(host: string | null): Provider | null {\n if (!host) return null;\n return KNOWN_HOSTS[host.toLowerCase()] ?? null;\n}\n\nfunction normalizeAzureDevOpsPath(path: string): string {\n // Azure paths look like `org/project/_git/repo` or `org/_git/repo` over\n // HTTPS, and `v3/org/project/repo` over SSH. Normalize to `org/project/repo`\n // (or `org/repo`) so it lines up with constructBranchUrl's expectations.\n const segments = path.split(\"/\").filter(Boolean);\n const gitIndex = segments.indexOf(\"_git\");\n if (gitIndex === -1) {\n // Only the SSH form carries the `v3` prefix, and it never carries `_git`.\n // Checking that first leaves an organization actually named `v3` alone.\n if (segments[0] === \"v3\") segments.shift();\n return segments.join(\"/\");\n }\n return [...segments.slice(0, gitIndex), ...segments.slice(gitIndex + 1)].join(\n \"/\",\n );\n}\n\nfunction buildParsedGitRemoteUrl(\n url: string,\n rawHost: string | null,\n rawPath: string,\n): ParsedGitRemoteUrl {\n const host = rawHost ? toWebHost(rawHost) : rawHost;\n const path = stripGitSuffix(rawPath.replace(/^\\/+|\\/+$/g, \"\"));\n const provider = detectProvider(host);\n const repository =\n provider === \"azure_devops\" ? normalizeAzureDevOpsPath(path) : path;\n\n return {\n url,\n host,\n repository: repository || null,\n provider,\n };\n}\n\n/**\n * Parse a git remote URL (HTTPS, SSH, or `git@host:path` shorthand) into its\n * host, repository (`owner/repo`), and best-effort provider.\n *\n * Returns `null` if the URL is empty or unparseable. Unknown hosts still\n * resolve `host` and `repository`; only `provider` is left `null`.\n */\nexport function parseGitRemoteUrl(\n remoteUrl: string | null | undefined,\n): ParsedGitRemoteUrl | null {\n const url = remoteUrl?.trim();\n if (!url) return null;\n\n // ssh://, https://, http://, git://. Tried before the shorthand match\n // below, whose `[^@\\s]+` would otherwise swallow `ssh://git` and read the\n // port in `ssh://git@host:2222/owner/repo` as the first path segment.\n try {\n const parsed = new URL(url);\n // A bare Windows path (`C:/src/repo`) parses as a `c:` scheme with an\n // empty host, so it is left to the shorthand match below.\n if (parsed.hostname) {\n return buildParsedGitRemoteUrl(url, parsed.hostname, parsed.pathname);\n }\n } catch {\n // Not a URL the WHATWG parser accepts, so try the shorthand form.\n }\n\n // git@host:owner/repo(.git)\n const scpMatch = url.match(/^[^@\\s]+@([^:\\s]+):(.+)$/);\n if (scpMatch) {\n const host = scpMatch[1];\n return buildParsedGitRemoteUrl(url, host, scpMatch[2]);\n }\n\n return null;\n}\n"],"mappings":";AAiBA,IAAM,IAAwC;CAC5C,cAAc;CACd,cAAc;CACd,iBAAiB;CACjB,iBAAiB;AACnB,GAMM,IAAwC;CAC5C,qBAAqB;CACrB,2BAA2B;AAC7B;AAEA,SAAS,EAAU,GAAsB;CACvC,IAAM,IAAQ,EAAK,YAAY;CAG/B,OAAO,OAAO,OAAO,GAAe,CAAK,IAAI,EAAc,KAAS;AACtE;AAEA,SAAS,EAAe,GAAsB;CAC5C,OAAO,EAAK,QAAQ,UAAU,EAAE;AAClC;AAEA,SAAS,EAAe,GAAsC;CAE5D,OADK,IACE,EAAY,EAAK,YAAY,MAAM,OADxB;AAEpB;AAEA,SAAS,EAAyB,GAAsB;CAItD,IAAM,IAAW,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,GACzC,IAAW,EAAS,QAAQ,MAAM;CAOxC,OANI,MAAa,MAGX,EAAS,OAAO,QAAM,EAAS,MAAM,GAClC,EAAS,KAAK,GAAG,KAEnB,CAAC,GAAG,EAAS,MAAM,GAAG,CAAQ,GAAG,GAAG,EAAS,MAAM,IAAW,CAAC,CAAC,EAAE,KACvE,GACF;AACF;AAEA,SAAS,EACP,GACA,GACA,GACoB;CACpB,IAAM,IAAO,KAAU,EAAU,CAAO,GAClC,IAAO,EAAe,EAAQ,QAAQ,cAAc,EAAE,CAAC,GACvD,IAAW,EAAe,CAAI;CAIpC,OAAO;EACL;EACA;EACA,aALA,MAAa,iBAAiB,EAAyB,CAAI,IAAI,MAKrC;EAC1B;CACF;AACF;AASA,SAAgB,EACd,GAC2B;CAC3B,IAAM,IAAM,GAAW,KAAK;CAC5B,IAAI,CAAC,GAAK,OAAO;CAKjB,IAAI;EACF,IAAM,IAAS,IAAI,IAAI,CAAG;EAG1B,IAAI,EAAO,UACT,OAAO,EAAwB,GAAK,EAAO,UAAU,EAAO,QAAQ;CAExE,QAAQ,CAER;CAGA,IAAM,IAAW,EAAI,MAAM,0BAA0B;CACrD,IAAI,GAAU;EACZ,IAAM,IAAO,EAAS;EACtB,OAAO,EAAwB,GAAK,GAAM,EAAS,EAAE;CACvD;CAEA,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/agent-canvas",
3
- "version": "1.17.0",
3
+ "version": "1.19.0",
4
4
  "description": "Agent Canvas UI for OpenHands - run AI coding agents with a visual interface",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -24,7 +24,7 @@
24
24
  "@microlink/react-json-view": "1.31.25",
25
25
  "@monaco-editor/react": "4.7.0",
26
26
  "@openhands/extensions": "0.20.0",
27
- "@openhands/typescript-client": "1.39.0",
27
+ "@openhands/typescript-client": "1.48.0",
28
28
  "@react-router/node": "7.18.2",
29
29
  "@react-router/serve": "7.18.2",
30
30
  "@tailwindcss/vite": "4.3.3",