@openhands/agent-canvas 1.15.0 → 1.17.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 (1277) hide show
  1. package/README.md +15 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{acp-providers-BKvmTf82.js → acp-providers-DrjNsPOH.js} +1 -1
  4. package/build/assets/active-backend-context-rZiLJRUc.js +2 -0
  5. package/build/assets/{agent-context-settings-D3PjSTU1.js → agent-context-settings-CJUrcBut.js} +1 -1
  6. package/build/assets/agent-profiles-service.api-Biieml2L.js +1 -0
  7. package/build/assets/agent-profiles-settings-x6RvPsq7.js +1 -0
  8. package/build/assets/agent-server-client-options-BikiNwTa.js +1 -0
  9. package/build/assets/agent-server-conversation-service.api-DYFsNHKf.js +88 -0
  10. package/build/assets/agent-settings-BJyovpJ_.js +1 -0
  11. package/build/assets/agent-settings-CpY3zObk.js +2 -0
  12. package/build/assets/alert-banner-vARz1idS.js +1 -0
  13. package/build/assets/{api-error-message-BJyfWp6p.js → api-error-message-Ve79qDcN.js} +1 -1
  14. package/build/assets/api-key-entry-screen-CsMuBhoP.js +1 -0
  15. package/build/assets/{app-settings-CbHqzQus.js → app-settings-BaJ7nfHt.js} +1 -1
  16. package/build/assets/automation-detail-CVoGDrKq.js +3 -0
  17. package/build/assets/{automation-export-BRopEHMu.js → automation-export-DxY47m3T.js} +1 -1
  18. package/build/assets/automation-git-sync-CRMP9Bbm.js +1 -0
  19. package/build/assets/automation-setup-route-072beLz1.js +3 -0
  20. package/build/assets/{automation-templates-C_0FZgLG.js → automation-templates-4C4PM8K7.js} +1 -1
  21. package/build/assets/automations-list-xuqTSQL4.js +1 -0
  22. package/build/assets/{back-nav-button-Dm9tIjVf.js → back-nav-button-B8tH0BEp.js} +1 -1
  23. package/build/assets/backend-form-modal-0aJmWdsa.js +1 -0
  24. package/build/assets/{backend-synced-settings-badge-3fOwg6Bd.js → backend-synced-settings-badge-B7rKWBir.js} +1 -1
  25. package/build/assets/{badge-D4SqUCsR.js → badge-CcGx2TaV.js} +1 -1
  26. package/build/assets/{base-modal-C7_BDl_U.js → base-modal-DTULovNc.js} +1 -1
  27. package/build/assets/bot-CLMxGFaq.js +1 -0
  28. package/build/assets/{brand-button-Dxv6PDeN.js → brand-button-DxPO4Lf8.js} +1 -1
  29. package/build/assets/browser-C-_qBasq.js +46 -0
  30. package/build/assets/{browser-tab-BAl4ckJE.js → browser-tab-DZanIw5m.js} +1 -1
  31. package/build/assets/canvas-extension-page-o_cWgE9B.js +1 -0
  32. package/build/assets/canvas-extensions-DSgNlCha.js +1 -0
  33. package/build/assets/canvas-extensions-runtime-DdnkgJXV.js +1 -0
  34. package/build/assets/{chat-send-button-DWwR2cgI.js → chat-send-button-B3SFSIg5.js} +1 -1
  35. package/build/assets/check-fDEfgSzj.js +1 -0
  36. package/build/assets/chevron-down-CFrWHqu8.js +1 -0
  37. package/build/assets/chevron-right-C5roOrJu.js +1 -0
  38. package/build/assets/circle-check-ClTzJTdb.js +1 -0
  39. package/build/assets/{circle-plus-check-toggle-CBh_qomE.js → circle-plus-check-toggle-Fr-h-mbL.js} +1 -1
  40. package/build/assets/{cloud-funnel-analytics-287iIERo.js → cloud-funnel-analytics-BQanUEEC.js} +1 -1
  41. package/build/assets/{cog-C4rrw-ZK.js → cog-VBlRo6iw.js} +1 -1
  42. package/build/assets/command-menu-BT3Ia5Ru.js +1 -0
  43. package/build/assets/commits-tab-2jhtaohl.js +1 -0
  44. package/build/assets/{condenser-settings-BcNmYR4s.js → condenser-settings-eVKFMvap.js} +1 -1
  45. package/build/assets/confirmation-modal-gIFHeZt6.js +1 -0
  46. package/build/assets/{context-menu-list-item-lVYETtY5.js → context-menu-list-item-DDROe12Z.js} +1 -1
  47. package/build/assets/conversation-BnjJSFf5.js +93 -0
  48. package/build/assets/conversation-DZ578rOX.js +1 -0
  49. package/build/assets/conversation-panel-DZ578rOX.js +1 -0
  50. package/build/assets/conversation-state-store-D1_G_9I-.js +1 -0
  51. package/build/assets/{conversation-store-Ca3ghXap.js → conversation-store-DVVfkCsk.js} +1 -1
  52. package/build/assets/{conversation-tab-empty-state-HJtkmHZj.js → conversation-tab-empty-state-DKlzAz5c.js} +1 -1
  53. package/build/assets/{copy-to-clipboard-button-Cjkswvnj.js → copy-to-clipboard-button-B3w0X7WH.js} +1 -1
  54. package/build/assets/{device-verify-EZhHhBT7.js → device-verify-BfkCzyFB.js} +1 -1
  55. package/build/assets/{dropdown-classes-DJe-E6MC.js → dropdown-classes-B9kJVDIk.js} +1 -1
  56. package/build/assets/edit-automation-modal-BwhJ39JT.js +1 -0
  57. package/build/assets/empty-state-RZz0OfnY.js +1 -0
  58. package/build/assets/{entry.client-C7Bi2tkU.js → entry.client-Ds8LVp-E.js} +2 -2
  59. package/build/assets/enum-filter-dropdown-C4pW0ORd.js +1 -0
  60. package/build/assets/{environment-switch-overlay-CEKrFiMw.js → environment-switch-overlay-P2ZAuzov.js} +1 -1
  61. package/build/assets/{error-state-BALXiBNy.js → error-state-B_5cgNPJ.js} +1 -1
  62. package/build/assets/extensions-hub-DsaUr4ca.js +1 -0
  63. package/build/assets/extensions-navigation-CRMZd-FE.js +1 -0
  64. package/build/assets/external-link-DQtv7eTh.js +1 -0
  65. package/build/assets/files-tab-CCgAcVdc.js +1 -0
  66. package/build/assets/{form-control-classes-CGw40z5h.js → form-control-classes-B-z85REi.js} +1 -1
  67. package/build/assets/format-model-name-CasAP3nd.js +1 -0
  68. package/build/assets/get-git-path-EHrSDxTM.js +1 -0
  69. package/build/assets/git-repo-dropdown-D2WEQ97X.js +1 -0
  70. package/build/assets/{git-repo-dropdown-ai8qaNkD.js → git-repo-dropdown-DVeCUUXG.js} +1 -1
  71. package/build/assets/{highlighted-source-view-C3sxykQi.js → highlighted-source-view-DjHO3SdW.js} +1 -1
  72. package/build/assets/home-BorS_vdS.js +1 -0
  73. package/build/assets/home-aIMbHw5M.js +1 -0
  74. package/build/assets/home-automation-run-tooltip-CpHNFiFl.js +1 -0
  75. package/build/assets/home-store-DyXz0w6d.js +1 -0
  76. package/build/assets/hooks-service-C6dpRtZM.js +1 -0
  77. package/build/assets/index-home-zKFuKK2B.js +1 -0
  78. package/build/assets/info-CTIdjttz.js +1 -0
  79. package/build/assets/install-server-modal-DUiZMc8u.js +1 -0
  80. package/build/assets/kebab-menu-item-content-mm04SBD3.js +1 -0
  81. package/build/assets/{key-Cn5za3rg.js → key-CfXbJa8w.js} +1 -1
  82. package/build/assets/{launch-C1ieiOGe.js → launch-BSIf9KEg.js} +1 -1
  83. package/build/assets/list-filter-CNpqTWVY.js +1 -0
  84. package/build/assets/{list-todo-Cuu-STFc.js → list-todo-ByXMdY4W.js} +1 -1
  85. package/build/assets/llm-not-configured-banner-z_QRSeV0.js +27 -0
  86. package/build/assets/llm-settings-B-5AHMiX.js +1 -0
  87. package/build/assets/llm-settings-B3SjHDmA.js +1 -0
  88. package/build/assets/llm-subscription-service-aDNBQ7Gq.js +1 -0
  89. package/build/assets/loader-circle-Dex47vVW.js +1 -0
  90. package/build/assets/{loading-spinner-0L3ZTToZ.js → loading-spinner-DfHI77BA.js} +1 -1
  91. package/build/assets/manage-backends-modal-q1NdFisr.js +1 -0
  92. package/build/assets/manifest-8920b615.js +1 -0
  93. package/build/assets/{manifest-subpage-layout-BGhiUQbA.js → manifest-subpage-layout-BQQy5ipR.js} +1 -1
  94. package/build/assets/{map-provider-B9LTm23I.js → map-provider-DXvssjw9.js} +1 -1
  95. package/build/assets/markdown-renderer-rivLvYh-.js +8 -0
  96. package/build/assets/{mcp-CKbR4Vft.js → mcp-CEXDhQWn.js} +1 -1
  97. package/build/assets/{mcp-marketplace-utils-C13fFccR.js → mcp-marketplace-utils-Cn_NIMWM.js} +1 -1
  98. package/build/assets/mcp-page-LGYIICMG.js +9 -0
  99. package/build/assets/messages-DUSeANAh.js +41 -0
  100. package/build/assets/{modal-body-CMOc2tLl.js → modal-body-DJw4xBki.js} +1 -1
  101. package/build/assets/{modal-classes-BAb4Y_BG.js → modal-classes-Dg0ngBPO.js} +1 -1
  102. package/build/assets/{modal-close-button-CkJ0Ktjj.js → modal-close-button-B9j4nasm.js} +1 -1
  103. package/build/assets/{mouse-pointer-click-CsgRs_-r.js → mouse-pointer-click-DEhsSUpu.js} +1 -1
  104. package/build/assets/onboarding-BjFebfs5.js +1 -0
  105. package/build/assets/onboarding-modal-DDTjOpyd.js +1 -0
  106. package/build/assets/organization-service.api-Cyg1Tn03.js +1 -0
  107. package/build/assets/pencil-D5c47kyN.js +1 -0
  108. package/build/assets/pin-C7vMagvf.js +1 -0
  109. package/build/assets/planner-tab-D8f2Y3rn.js +1 -0
  110. package/build/assets/plug-CeaqeF6u.js +1 -0
  111. package/build/assets/plugins-management-service-Bh_pBuf-.js +1 -0
  112. package/build/assets/plus-B3wvU06-.js +1 -0
  113. package/build/assets/profiles-service.api-BbOK0EkF.js +1 -0
  114. package/build/assets/providers-2gIIkz2N.js +1 -0
  115. package/build/assets/proxy-CBgMd2zf.js +1 -0
  116. package/build/assets/{puzzle-A9pGxxai.js → puzzle-DdAqbUrb.js} +1 -1
  117. package/build/assets/recommended-automations-launcher-YLAQTp4s.js +1 -0
  118. package/build/assets/refresh-cw-DEQdPCpH.js +1 -0
  119. package/build/assets/root-Bye_XmEL.js +2 -0
  120. package/build/assets/root-Cnwwzgo0.css +1 -0
  121. package/build/assets/root-layout-CSAwxBGM.js +2 -0
  122. package/build/assets/schema-field-CK0xYNbO.js +1 -0
  123. package/build/assets/scroll-fade-state-Dt_fx2kf.js +1 -0
  124. package/build/assets/sdk-section-page-Da73Rs_o.js +1 -0
  125. package/build/assets/secret-form-CB2VwYYg.js +1 -0
  126. package/build/assets/secrets-service-Cr8g8xuv.js +1 -0
  127. package/build/assets/{secrets-settings-BizaTEr1.js → secrets-settings-Bh0udeKv.js} +1 -1
  128. package/build/assets/settings-CKqk8ZnH.js +1 -0
  129. package/build/assets/settings-DmyIgRxO.js +1 -0
  130. package/build/assets/{settings-dropdown-input-tM0A0ipy.js → settings-dropdown-input-DVpyD87C.js} +1 -1
  131. package/build/assets/settings-index-BSJUFmjE.js +1 -0
  132. package/build/assets/{settings-input-C03KUoSC.js → settings-input-C0dd8Utu.js} +1 -1
  133. package/build/assets/{settings-list-classes-BJ0g8rWj.js → settings-list-classes-Ds4jPBHK.js} +1 -1
  134. package/build/assets/{settings-modal-AzEF1QPP.js → settings-modal-yStgEh2o.js} +1 -1
  135. package/build/assets/settings-service.api-9_xdv_mh.js +1 -0
  136. package/build/assets/{settings-switch-CQE0EGC-.js → settings-switch-B78Khmyz.js} +1 -1
  137. package/build/assets/{settings-utils-ClYOkbbI.js → settings-utils-8GIIgOQL.js} +1 -1
  138. package/build/assets/shared-conversation-DM96X4KV.js +1 -0
  139. package/build/assets/shield-check-DO7wa_eu.js +1 -0
  140. package/build/assets/{sidebar-layout-D3hE08wK.js → sidebar-layout-EPfWxk11.js} +1 -1
  141. package/build/assets/sidebar-mobile-menu-toggle-D5GR5xT9.js +1 -0
  142. package/build/assets/sidebar-nav-link-_t4_Ef-9.js +1 -0
  143. package/build/assets/{sidebar-onboarding-checklist-storage-3qYflszY.js → sidebar-onboarding-checklist-storage-DbDX-Wvj.js} +1 -1
  144. package/build/assets/sidebar-store-CSDFK0W5.js +1 -0
  145. package/build/assets/{skill-card-pill-row-CFxjoqxn.js → skill-card-pill-row-989y15jV.js} +1 -1
  146. package/build/assets/skill-enablement-DXeaImBz.js +1 -0
  147. package/build/assets/skill-filter-BBeZ4JEP.js +2 -0
  148. package/build/assets/{skill-icon-badge-CPQJ6A-I.js → skill-icon-badge-BDhQ-tQ0.js} +1 -1
  149. package/build/assets/skill-scope-Dz3kPH3P.js +1 -0
  150. package/build/assets/skills-plugins-e3CYGdUJ.js +1 -0
  151. package/build/assets/skills-settings-3e-FuHw_.js +1 -0
  152. package/build/assets/styled-tooltip-Pd22BIvr.js +1 -0
  153. package/build/assets/{task-list-tab-04GNQuii.js → task-list-tab-3Jg8ywch.js} +1 -1
  154. package/build/assets/{terminal-Cj0iHIW7.js → terminal-onXx0_Qz.js} +1 -1
  155. package/build/assets/toggle-switch-lwQtxDcm.js +1 -0
  156. package/build/assets/trash-2-ZhKuTLiz.js +1 -0
  157. package/build/assets/trash-B6OIe4yX.js +1 -0
  158. package/build/assets/triangle-alert-BajLPpQg.js +1 -0
  159. package/build/assets/{typography-SgFy466J.js → typography-HLLg_FAn.js} +1 -1
  160. package/build/assets/usage-tab-Cm-9j3UK.js +1 -0
  161. package/build/assets/use-acp-credential-form-BARcvjYE.js +1 -0
  162. package/build/assets/use-activate-agent-profile-BLKML6vQ.js +1 -0
  163. package/build/assets/use-agent-profiles-1P91KSXz.js +1 -0
  164. package/build/assets/{use-automation-health-BxXdzZMP.js → use-automation-health-BZkQNEA8.js} +1 -1
  165. package/build/assets/use-automation-permissions-B_RpvL-s.js +1 -0
  166. package/build/assets/{use-automations-zYb0dUny.js → use-automations-Cg0PDIZr.js} +1 -1
  167. package/build/assets/{use-can-manage-org-profiles-BWMahtUh.js → use-can-manage-org-profiles-BbN6KfDr.js} +1 -1
  168. package/build/assets/use-canvas-extensions-CFUpHat6.js +1 -0
  169. package/build/assets/{use-cloud-current-user-id-CPHMDG-C.js → use-cloud-current-user-id-Dk0rjr63.js} +1 -1
  170. package/build/assets/use-config-DpafU_QP.js +1 -0
  171. package/build/assets/use-create-conversation-1YgmAHt-.js +1 -0
  172. package/build/assets/use-create-secret-D8p9ybQj.js +1 -0
  173. package/build/assets/{use-get-secrets-BT4ihRwj.js → use-get-secrets-CQ4b0qK8.js} +1 -1
  174. package/build/assets/use-is-authed-BRPjCRKM.js +1 -0
  175. package/build/assets/{use-launch-skill-in-chat-BYjYihBP.js → use-launch-skill-in-chat-DeYa1tFM.js} +1 -1
  176. package/build/assets/use-llm-configured-DGm8FiRR.js +1 -0
  177. package/build/assets/use-llm-profiles-BTTtpW4z.js +1 -0
  178. package/build/assets/use-manifest-capabilities-AOWGcu0j.js +1 -0
  179. package/build/assets/use-onboarding-completion-CoINurkm.js +1 -0
  180. package/build/assets/use-pinned-home-route-D6krwXjy.js +1 -0
  181. package/build/assets/use-plugins-marketplace-mLsIDhBv.js +1 -0
  182. package/build/assets/use-save-agent-profile-CxyO9YG-.js +1 -0
  183. package/build/assets/{use-save-settings-CUZW6yXP.js → use-save-settings-3U5K9-8x.js} +1 -1
  184. package/build/assets/use-settings-Dn00UISA.js +1 -0
  185. package/build/assets/use-settings-nav-items-vrjxTqcu.js +16 -0
  186. package/build/assets/use-tracking-B9prBsrq.js +3 -0
  187. package/build/assets/{use-user-conversation-DT0_QCnL.js → use-user-conversation-ZWlXtbZb.js} +1 -1
  188. package/build/assets/{useInfiniteQuery-CgeUQPfs.js → useInfiniteQuery-BzrRqjLg.js} +1 -1
  189. package/build/assets/{useMutation-DFnzkf6f.js → useMutation-CJuK90oc.js} +1 -1
  190. package/build/assets/{useQueries-BhbrGEf1.js → useQueries-CykmpT-a.js} +1 -1
  191. package/build/assets/{useQuery-BXWbZBZl.js → useQuery-S6j94er1.js} +1 -1
  192. package/build/assets/utils-BOco8mxR.js +1 -0
  193. package/build/assets/{vendor~conversation-panel~conversation-CTvDDiXg.js → vendor~conversation-panel~conversation-4eJ0tml3.js} +1 -1
  194. package/build/assets/{vendor~entry.client-BFE7Llz9.js → vendor~entry.client-CoCfUXUF.js} +1 -1
  195. package/build/assets/{vendor~entry.client-BaKt_PIp.js → vendor~entry.client-DA2izTjq.js} +1 -1
  196. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +2 -0
  197. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BfkNGovw.js +185 -0
  198. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew3u153i-rfV8mQ9m.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-DnDoaYNi.js} +1 -1
  199. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-BTyukeM-.js → vendor~index-home~home~conversation-panel~conversation-CSFLzmTN.js} +1 -1
  200. package/build/assets/vendor~root-layout-n8XCEXG8.js +1 -0
  201. package/build/assets/{vendor~root-layout~conversation-panel~conversation-BYAWJwQX.js → vendor~root-layout~conversation-panel~conversation-3Idg1_U3.js} +1 -1
  202. package/build/assets/{vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-CHaLEBVR.js → vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-DkPlXWl9.js} +1 -1
  203. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-DgQ564nC.js +1 -0
  204. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-CxhwKuAd.js +1 -0
  205. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~hjcjabwg-Dtu7BpYk.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js} +2 -2
  206. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-CV850oio.js +1 -0
  207. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-DonTKfQD.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-BPjI-atc.js} +125 -15
  208. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-BgxDvUcf.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~jz4f6vo2-C7HiY4Ae.js} +42 -3
  209. package/build/assets/{verification-settings-Bj6bo097.js → verification-settings-u2POabjH.js} +1 -1
  210. package/build/assets/{wrench-hi7Q13dF.js → wrench-CkgI4rxA.js} +1 -1
  211. package/build/assets/x-By6qCmtY.js +1 -0
  212. package/build/index.html +4 -4
  213. package/build/locales/ar/openhands.json +94 -25
  214. package/build/locales/ca/openhands.json +94 -25
  215. package/build/locales/de/openhands.json +94 -25
  216. package/build/locales/en/openhands.json +94 -25
  217. package/build/locales/es/openhands.json +94 -25
  218. package/build/locales/fr/openhands.json +94 -25
  219. package/build/locales/it/openhands.json +94 -25
  220. package/build/locales/ja/openhands.json +94 -25
  221. package/build/locales/ko-KR/openhands.json +94 -25
  222. package/build/locales/no/openhands.json +94 -25
  223. package/build/locales/pt/openhands.json +94 -25
  224. package/build/locales/tr/openhands.json +94 -25
  225. package/build/locales/uk/openhands.json +94 -25
  226. package/build/locales/zh-CN/openhands.json +94 -25
  227. package/build/locales/zh-TW/openhands.json +94 -25
  228. package/config/defaults.json +9 -5
  229. package/dist/api/agent-profiles-service/profile-field-support.d.ts +26 -0
  230. package/dist/api/agent-server-adapter.cjs +3 -3
  231. package/dist/api/agent-server-adapter.cjs.map +1 -1
  232. package/dist/api/agent-server-adapter.d.ts +72 -12
  233. package/dist/api/agent-server-adapter.js +249 -145
  234. package/dist/api/agent-server-adapter.js.map +1 -1
  235. package/dist/api/agent-server-compatibility.cjs +1 -1
  236. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  237. package/dist/api/agent-server-compatibility.d.ts +21 -0
  238. package/dist/api/agent-server-compatibility.js +52 -38
  239. package/dist/api/agent-server-compatibility.js.map +1 -1
  240. package/dist/api/agent-server-config.cjs +1 -1
  241. package/dist/api/agent-server-config.cjs.map +1 -1
  242. package/dist/api/agent-server-config.d.ts +32 -0
  243. package/dist/api/agent-server-config.js +21 -5
  244. package/dist/api/agent-server-config.js.map +1 -1
  245. package/dist/api/automation-service/automation-service.api.cjs +1 -1
  246. package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
  247. package/dist/api/automation-service/automation-service.api.d.ts +2 -2
  248. package/dist/api/automation-service/automation-service.api.js +7 -7
  249. package/dist/api/automation-service/automation-service.api.js.map +1 -1
  250. package/dist/api/canvas-extensions-service.cjs +1 -0
  251. package/dist/api/canvas-extensions-service.d.ts +22 -0
  252. package/dist/api/canvas-extensions-service.js +4 -0
  253. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  254. package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
  255. package/dist/api/cloud/conversation-service.api.d.ts +6 -0
  256. package/dist/api/cloud/conversation-service.api.js +14 -6
  257. package/dist/api/cloud/conversation-service.api.js.map +1 -1
  258. package/dist/api/cloud/provider-connections-service.api.cjs +2 -0
  259. package/dist/api/cloud/provider-connections-service.api.cjs.map +1 -0
  260. package/dist/api/cloud/provider-connections-service.api.d.ts +5 -0
  261. package/dist/api/cloud/provider-connections-service.api.js +50 -0
  262. package/dist/api/cloud/provider-connections-service.api.js.map +1 -0
  263. package/dist/api/cloud/skills-service.api.cjs +1 -1
  264. package/dist/api/cloud/skills-service.api.cjs.map +1 -1
  265. package/dist/api/cloud/skills-service.api.d.ts +10 -0
  266. package/dist/api/cloud/skills-service.api.js +11 -1
  267. package/dist/api/cloud/skills-service.api.js.map +1 -1
  268. package/dist/api/conversation-file-upload.api.cjs +1 -1
  269. package/dist/api/conversation-file-upload.api.js +10 -10
  270. package/dist/api/conversation-metadata-store.cjs +1 -1
  271. package/dist/api/conversation-metadata-store.cjs.map +1 -1
  272. package/dist/api/conversation-metadata-store.d.ts +24 -0
  273. package/dist/api/conversation-metadata-store.js +10 -2
  274. package/dist/api/conversation-metadata-store.js.map +1 -1
  275. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  276. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  277. package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +31 -0
  278. package/dist/api/conversation-service/agent-server-conversation-service.api.js +188 -128
  279. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  280. package/dist/api/event-service/event-service.api.cjs +1 -1
  281. package/dist/api/event-service/event-service.api.js +12 -12
  282. package/dist/api/git-service/agent-server-git-service.api.cjs +1 -1
  283. package/dist/api/git-service/agent-server-git-service.api.js +8 -8
  284. package/dist/api/hooks-service.cjs +2 -0
  285. package/dist/api/hooks-service.cjs.map +1 -0
  286. package/dist/api/hooks-service.d.ts +13 -0
  287. package/dist/api/hooks-service.js +20 -0
  288. package/dist/api/hooks-service.js.map +1 -0
  289. package/dist/api/provider-connections-service/provider-connections-service.api.cjs +1 -1
  290. package/dist/api/provider-connections-service/provider-connections-service.api.cjs.map +1 -1
  291. package/dist/api/provider-connections-service/provider-connections-service.api.js +25 -16
  292. package/dist/api/provider-connections-service/provider-connections-service.api.js.map +1 -1
  293. package/dist/api/runtime-service/agent-server-runtime-service.cjs +1 -1
  294. package/dist/api/runtime-service/agent-server-runtime-service.js +8 -8
  295. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  296. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  297. package/dist/api/settings-service/settings-service.api.d.ts +5 -2
  298. package/dist/api/settings-service/settings-service.api.js +20 -11
  299. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  300. package/dist/api/skills-service.cjs +1 -1
  301. package/dist/api/skills-service.cjs.map +1 -1
  302. package/dist/api/skills-service.d.ts +7 -0
  303. package/dist/api/skills-service.js +11 -8
  304. package/dist/api/skills-service.js.map +1 -1
  305. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.cjs +1 -1
  306. package/dist/components/conversation-events/chat/event-message-components/critic-result-display.js +5 -5
  307. package/dist/components/conversation-events/chat/event-message-components/event-group.cjs +1 -1
  308. package/dist/components/conversation-events/chat/event-message-components/event-group.cjs.map +1 -1
  309. package/dist/components/conversation-events/chat/event-message-components/event-group.js +40 -36
  310. package/dist/components/conversation-events/chat/event-message-components/event-group.js.map +1 -1
  311. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs +1 -1
  312. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs.map +1 -1
  313. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js +2 -1
  314. package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js.map +1 -1
  315. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs +1 -1
  316. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs.map +1 -1
  317. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.d.ts +1 -1
  318. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js +28 -28
  319. package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js.map +1 -1
  320. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs +1 -1
  321. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs.map +1 -1
  322. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js +2 -1
  323. package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js.map +1 -1
  324. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs +1 -1
  325. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs.map +1 -1
  326. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.d.ts +1 -1
  327. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js +37 -37
  328. package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js.map +1 -1
  329. package/dist/components/conversation-events/chat/event-message.cjs +2 -2
  330. package/dist/components/conversation-events/chat/event-message.cjs.map +1 -1
  331. package/dist/components/conversation-events/chat/event-message.js +79 -70
  332. package/dist/components/conversation-events/chat/event-message.js.map +1 -1
  333. package/dist/components/conversation-events/chat/messages.cjs +1 -1
  334. package/dist/components/conversation-events/chat/messages.cjs.map +1 -1
  335. package/dist/components/conversation-events/chat/messages.js +28 -27
  336. package/dist/components/conversation-events/chat/messages.js.map +1 -1
  337. package/dist/components/features/automations/automation-card.cjs +1 -1
  338. package/dist/components/features/automations/automation-card.cjs.map +1 -1
  339. package/dist/components/features/automations/automation-card.js +118 -102
  340. package/dist/components/features/automations/automation-card.js.map +1 -1
  341. package/dist/components/features/automations/automation-list-row.cjs +1 -1
  342. package/dist/components/features/automations/automation-list-row.cjs.map +1 -1
  343. package/dist/components/features/automations/automation-list-row.js +88 -77
  344. package/dist/components/features/automations/automation-list-row.js.map +1 -1
  345. package/dist/components/features/automations/detail/detail-header.d.ts +3 -1
  346. package/dist/components/features/automations/detail/run-phase.cjs +2 -0
  347. package/dist/components/features/automations/detail/run-phase.cjs.map +1 -0
  348. package/dist/components/features/automations/detail/run-phase.d.ts +89 -0
  349. package/dist/components/features/automations/detail/run-phase.js +72 -0
  350. package/dist/components/features/automations/detail/run-phase.js.map +1 -0
  351. package/dist/components/features/automations/detail/run-status-badge.cjs +1 -1
  352. package/dist/components/features/automations/detail/run-status-badge.cjs.map +1 -1
  353. package/dist/components/features/automations/detail/run-status-badge.d.ts +2 -2
  354. package/dist/components/features/automations/detail/run-status-badge.js +82 -53
  355. package/dist/components/features/automations/detail/run-status-badge.js.map +1 -1
  356. package/dist/components/features/automations/kebab-menu.cjs +1 -1
  357. package/dist/components/features/automations/kebab-menu.cjs.map +1 -1
  358. package/dist/components/features/automations/kebab-menu.js +9 -5
  359. package/dist/components/features/automations/kebab-menu.js.map +1 -1
  360. package/dist/components/features/automations/recommended-automations-launcher.cjs +1 -1
  361. package/dist/components/features/automations/recommended-automations-launcher.cjs.map +1 -1
  362. package/dist/components/features/automations/recommended-automations-launcher.js +12 -12
  363. package/dist/components/features/automations/recommended-automations-launcher.js.map +1 -1
  364. package/dist/components/features/automations/recommended-automations-section.cjs +1 -1
  365. package/dist/components/features/automations/recommended-automations-section.js +9 -9
  366. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  367. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  368. package/dist/components/features/backends/backend-form-modal.js +5 -11
  369. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  370. package/dist/components/features/backends/backend-selector.cjs +1 -1
  371. package/dist/components/features/backends/backend-selector.cjs.map +1 -1
  372. package/dist/components/features/backends/backend-selector.js +133 -122
  373. package/dist/components/features/backends/backend-selector.js.map +1 -1
  374. package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
  375. package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
  376. package/dist/components/features/backends/manage-backends-modal.js +29 -29
  377. package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
  378. package/dist/components/features/canvas-extensions/add-canvas-extension-modal.d.ts +6 -0
  379. package/dist/components/features/canvas-extensions/canvas-extension-card.d.ts +9 -0
  380. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs +2 -0
  381. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs.map +1 -0
  382. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.d.ts +23 -0
  383. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js +19 -0
  384. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js.map +1 -0
  385. package/dist/components/features/chat/change-agent-button.cjs +1 -1
  386. package/dist/components/features/chat/change-agent-button.js +4 -4
  387. package/dist/components/features/chat/chat-interface.cjs +2 -2
  388. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  389. package/dist/components/features/chat/chat-interface.js +107 -104
  390. package/dist/components/features/chat/chat-interface.js.map +1 -1
  391. package/dist/components/features/chat/chat-markdown-path-code.cjs +3 -0
  392. package/dist/components/features/chat/chat-markdown-path-code.cjs.map +1 -0
  393. package/dist/components/features/chat/chat-markdown-path-code.d.ts +27 -0
  394. package/dist/components/features/chat/chat-markdown-path-code.js +72 -0
  395. package/dist/components/features/chat/chat-markdown-path-code.js.map +1 -0
  396. package/dist/components/features/chat/chat-message.cjs +1 -1
  397. package/dist/components/features/chat/chat-message.cjs.map +1 -1
  398. package/dist/components/features/chat/chat-message.d.ts +2 -1
  399. package/dist/components/features/chat/chat-message.js +88 -79
  400. package/dist/components/features/chat/chat-message.js.map +1 -1
  401. package/dist/components/features/chat/components/context-window-meter.cjs +1 -1
  402. package/dist/components/features/chat/components/context-window-meter.js +4 -4
  403. package/dist/components/features/chat/confirmation-mode-enabled.cjs +1 -1
  404. package/dist/components/features/chat/confirmation-mode-enabled.js +4 -4
  405. package/dist/components/features/chat/generic-event-message.cjs +1 -1
  406. package/dist/components/features/chat/generic-event-message.cjs.map +1 -1
  407. package/dist/components/features/chat/generic-event-message.d.ts +2 -1
  408. package/dist/components/features/chat/generic-event-message.js +41 -22
  409. package/dist/components/features/chat/generic-event-message.js.map +1 -1
  410. package/dist/components/features/chat/interactive-chat-box.cjs +1 -1
  411. package/dist/components/features/chat/interactive-chat-box.cjs.map +1 -1
  412. package/dist/components/features/chat/interactive-chat-box.js +20 -19
  413. package/dist/components/features/chat/interactive-chat-box.js.map +1 -1
  414. package/dist/components/features/chat/path-component.cjs +1 -1
  415. package/dist/components/features/chat/path-component.cjs.map +1 -1
  416. package/dist/components/features/chat/path-component.d.ts +8 -2
  417. package/dist/components/features/chat/path-component.js +33 -21
  418. package/dist/components/features/chat/path-component.js.map +1 -1
  419. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs +1 -1
  420. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs.map +1 -1
  421. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js +38 -43
  422. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js.map +1 -1
  423. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs +1 -1
  424. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs.map +1 -1
  425. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.d.ts +8 -5
  426. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js +22 -16
  427. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js.map +1 -1
  428. package/dist/components/features/chat/user-message-body.cjs +1 -1
  429. package/dist/components/features/chat/user-message-body.cjs.map +1 -1
  430. package/dist/components/features/chat/user-message-body.d.ts +4 -0
  431. package/dist/components/features/chat/user-message-body.js +30 -24
  432. package/dist/components/features/chat/user-message-body.js.map +1 -1
  433. package/dist/components/features/conversation/conversation-overview-git-section.cjs +1 -1
  434. package/dist/components/features/conversation/conversation-overview-git-section.js +4 -4
  435. package/dist/components/features/conversation/conversation-overview-skills-panel.cjs +1 -1
  436. package/dist/components/features/conversation/conversation-overview-skills-panel.cjs.map +1 -1
  437. package/dist/components/features/conversation/conversation-overview-skills-panel.js +63 -81
  438. package/dist/components/features/conversation/conversation-overview-skills-panel.js.map +1 -1
  439. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs +1 -1
  440. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs.map +1 -1
  441. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js +77 -78
  442. package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js.map +1 -1
  443. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
  444. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
  445. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +96 -96
  446. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
  447. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs +1 -1
  448. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs.map +1 -1
  449. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.d.ts +1 -1
  450. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js +3 -3
  451. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js.map +1 -1
  452. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs +2 -0
  453. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs.map +1 -0
  454. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.d.ts +21 -0
  455. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js +239 -0
  456. package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js.map +1 -0
  457. package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs +2 -0
  458. package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs.map +1 -0
  459. package/dist/components/features/conversation-panel/conversation-active-tag-filters.d.ts +28 -0
  460. package/dist/components/features/conversation-panel/conversation-active-tag-filters.js +69 -0
  461. package/dist/components/features/conversation-panel/conversation-active-tag-filters.js.map +1 -0
  462. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs +1 -1
  463. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs.map +1 -1
  464. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.d.ts +2 -1
  465. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js +19 -18
  466. package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js.map +1 -1
  467. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs +1 -1
  468. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs.map +1 -1
  469. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.d.ts +2 -1
  470. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js +91 -80
  471. package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js.map +1 -1
  472. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
  473. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
  474. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +1 -1
  475. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
  476. package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs +1 -1
  477. package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs.map +1 -1
  478. package/dist/components/features/conversation-panel/conversation-card/conversation-card.d.ts +7 -1
  479. package/dist/components/features/conversation-panel/conversation-card/conversation-card.js +87 -81
  480. package/dist/components/features/conversation-panel/conversation-card/conversation-card.js.map +1 -1
  481. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +1 -1
  482. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -1
  483. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +2 -1
  484. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +1 -1
  485. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -1
  486. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +1 -1
  487. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -1
  488. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +2 -1
  489. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +2 -1
  490. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -1
  491. package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs +2 -0
  492. package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs.map +1 -0
  493. package/dist/components/features/conversation-panel/conversation-layouts-menu.d.ts +29 -0
  494. package/dist/components/features/conversation-panel/conversation-layouts-menu.js +177 -0
  495. package/dist/components/features/conversation-panel/conversation-layouts-menu.js.map +1 -0
  496. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
  497. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
  498. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +37 -0
  499. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +85 -45
  500. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
  501. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  502. package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
  503. package/dist/components/features/conversation-panel/conversation-panel.js +296 -290
  504. package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
  505. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs +2 -0
  506. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs.map +1 -0
  507. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.d.ts +22 -0
  508. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js +153 -0
  509. package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js.map +1 -0
  510. package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs +2 -0
  511. package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs.map +1 -0
  512. package/dist/components/features/conversation-panel/hide-older-conversations-row.d.ts +6 -0
  513. package/dist/components/features/conversation-panel/hide-older-conversations-row.js +65 -0
  514. package/dist/components/features/conversation-panel/hide-older-conversations-row.js.map +1 -0
  515. package/dist/components/features/conversation-panel/menu-row.cjs +1 -1
  516. package/dist/components/features/conversation-panel/menu-row.cjs.map +1 -1
  517. package/dist/components/features/conversation-panel/menu-row.d.ts +11 -1
  518. package/dist/components/features/conversation-panel/menu-row.js +27 -16
  519. package/dist/components/features/conversation-panel/menu-row.js.map +1 -1
  520. package/dist/components/features/conversation-panel/skills-modal.cjs +1 -1
  521. package/dist/components/features/conversation-panel/skills-modal.cjs.map +1 -1
  522. package/dist/components/features/conversation-panel/skills-modal.js +29 -28
  523. package/dist/components/features/conversation-panel/skills-modal.js.map +1 -1
  524. package/dist/components/features/files-tab/file-content-viewer.cjs +1 -1
  525. package/dist/components/features/files-tab/file-content-viewer.js +5 -5
  526. package/dist/components/features/home/featured-automations/automation-health-indicator.cjs +1 -1
  527. package/dist/components/features/home/featured-automations/automation-health-indicator.cjs.map +1 -1
  528. package/dist/components/features/home/featured-automations/automation-health-indicator.js +1 -1
  529. package/dist/components/features/home/featured-automations/automation-health-indicator.js.map +1 -1
  530. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs +1 -1
  531. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs.map +1 -1
  532. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.d.ts +4 -3
  533. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js +22 -25
  534. package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js.map +1 -1
  535. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs +1 -1
  536. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs.map +1 -1
  537. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.d.ts +1 -1
  538. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js +15 -15
  539. package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js.map +1 -1
  540. package/dist/components/features/home/featured-automations/automation-run-health.cjs +1 -1
  541. package/dist/components/features/home/featured-automations/automation-run-health.cjs.map +1 -1
  542. package/dist/components/features/home/featured-automations/automation-run-health.d.ts +5 -3
  543. package/dist/components/features/home/featured-automations/automation-run-health.js +30 -23
  544. package/dist/components/features/home/featured-automations/automation-run-health.js.map +1 -1
  545. package/dist/components/features/home/featured-automations/home-automation-activity.d.ts +3 -2
  546. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
  547. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
  548. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.d.ts +1 -1
  549. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +59 -37
  550. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
  551. package/dist/components/features/manifest/manifest-form-field.d.ts +3 -1
  552. package/dist/components/features/manifest/manifest-review-step.d.ts +3 -1
  553. package/dist/components/features/onboarding/onboarding-host.d.ts +3 -4
  554. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +5 -9
  555. package/dist/components/features/settings/acp-auth-status-banner.d.ts +23 -6
  556. package/dist/components/features/settings/cloud-settings-link.cjs +1 -1
  557. package/dist/components/features/settings/cloud-settings-link.cjs.map +1 -1
  558. package/dist/components/features/settings/cloud-settings-link.js +5 -3
  559. package/dist/components/features/settings/cloud-settings-link.js.map +1 -1
  560. package/dist/components/features/settings/integrations-settings-link.cjs +1 -1
  561. package/dist/components/features/settings/integrations-settings-link.cjs.map +1 -1
  562. package/dist/components/features/settings/integrations-settings-link.d.ts +3 -1
  563. package/dist/components/features/settings/integrations-settings-link.js +20 -17
  564. package/dist/components/features/settings/integrations-settings-link.js.map +1 -1
  565. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  566. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +2 -1
  567. package/dist/components/features/settings/llm-profiles/profiles-body.d.ts +2 -2
  568. package/dist/components/features/settings/llm-profiles/provider-connection-modal.cjs +1 -1
  569. package/dist/components/features/settings/llm-profiles/provider-connection-modal.js +3 -0
  570. package/dist/components/features/settings/sdk-settings/field-help.cjs +1 -1
  571. package/dist/components/features/settings/sdk-settings/field-help.cjs.map +1 -1
  572. package/dist/components/features/settings/sdk-settings/field-help.d.ts +1 -1
  573. package/dist/components/features/settings/sdk-settings/field-help.js +1 -1
  574. package/dist/components/features/settings/sdk-settings/field-help.js.map +1 -1
  575. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
  576. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs.map +1 -1
  577. package/dist/components/features/settings/sdk-settings/sdk-section-page.d.ts +8 -7
  578. package/dist/components/features/settings/sdk-settings/sdk-section-page.js +172 -142
  579. package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
  580. package/dist/components/features/settings/secrets-settings/secret-form.cjs +1 -1
  581. package/dist/components/features/settings/secrets-settings/secret-form.cjs.map +1 -1
  582. package/dist/components/features/settings/secrets-settings/secret-form.js +38 -25
  583. package/dist/components/features/settings/secrets-settings/secret-form.js.map +1 -1
  584. package/dist/components/features/settings/settings-dropdown-input.cjs +1 -1
  585. package/dist/components/features/settings/settings-dropdown-input.js +6 -6
  586. package/dist/components/features/sidebar/sidebar-nav-link.cjs +1 -1
  587. package/dist/components/features/sidebar/sidebar-nav-link.cjs.map +1 -1
  588. package/dist/components/features/sidebar/sidebar-nav-link.d.ts +10 -1
  589. package/dist/components/features/sidebar/sidebar-nav-link.js +54 -36
  590. package/dist/components/features/sidebar/sidebar-nav-link.js.map +1 -1
  591. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  592. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  593. package/dist/components/features/sidebar/sidebar-rail-body.d.ts +3 -1
  594. package/dist/components/features/sidebar/sidebar-rail-body.js +98 -58
  595. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  596. package/dist/components/features/sidebar/sidebar.cjs +1 -1
  597. package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
  598. package/dist/components/features/sidebar/sidebar.js +44 -43
  599. package/dist/components/features/sidebar/sidebar.js.map +1 -1
  600. package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.cjs +1 -1
  601. package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.js +3 -3
  602. package/dist/components/features/skills/build-skill-pills.cjs +1 -1
  603. package/dist/components/features/skills/build-skill-pills.cjs.map +1 -1
  604. package/dist/components/features/skills/build-skill-pills.js +60 -52
  605. package/dist/components/features/skills/build-skill-pills.js.map +1 -1
  606. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  607. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  608. package/dist/components/features/skills/extensions-navigation.js +54 -43
  609. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  610. package/dist/components/features/skills/skill-filter.cjs +1 -1
  611. package/dist/components/features/skills/skill-filter.cjs.map +1 -1
  612. package/dist/components/features/skills/skill-filter.d.ts +8 -3
  613. package/dist/components/features/skills/skill-filter.js +69 -52
  614. package/dist/components/features/skills/skill-filter.js.map +1 -1
  615. package/dist/components/shared/buttons/styled-tooltip.cjs +1 -1
  616. package/dist/components/shared/buttons/styled-tooltip.cjs.map +1 -1
  617. package/dist/components/shared/buttons/styled-tooltip.d.ts +2 -1
  618. package/dist/components/shared/buttons/styled-tooltip.js +2 -1
  619. package/dist/components/shared/buttons/styled-tooltip.js.map +1 -1
  620. package/dist/components/shared/filters/enum-filter-dropdown.cjs +1 -1
  621. package/dist/components/shared/filters/enum-filter-dropdown.cjs.map +1 -1
  622. package/dist/components/shared/filters/enum-filter-dropdown.d.ts +5 -1
  623. package/dist/components/shared/filters/enum-filter-dropdown.js +14 -14
  624. package/dist/components/shared/filters/enum-filter-dropdown.js.map +1 -1
  625. package/dist/components/shared/modals/confirmation-modal.cjs +1 -1
  626. package/dist/components/shared/modals/confirmation-modal.cjs.map +1 -1
  627. package/dist/components/shared/modals/confirmation-modal.d.ts +2 -1
  628. package/dist/components/shared/modals/confirmation-modal.js +8 -8
  629. package/dist/components/shared/modals/confirmation-modal.js.map +1 -1
  630. package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
  631. package/dist/components/shared/modals/settings/model-selector.js +27 -27
  632. package/dist/components/shared/modals/settings/settings-form.cjs +1 -1
  633. package/dist/components/shared/modals/settings/settings-form.js +8 -8
  634. package/dist/config/defaults.cjs +1 -1
  635. package/dist/config/defaults.cjs.map +1 -1
  636. package/dist/config/defaults.js +9 -5
  637. package/dist/config/defaults.js.map +1 -1
  638. package/dist/constants/settings-nav.d.ts +8 -0
  639. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  640. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  641. package/dist/contexts/conversation-websocket-context.d.ts +5 -0
  642. package/dist/contexts/conversation-websocket-context.js +194 -198
  643. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  644. package/dist/contexts/websocket-provider-wrapper.cjs +1 -1
  645. package/dist/contexts/websocket-provider-wrapper.cjs.map +1 -1
  646. package/dist/contexts/websocket-provider-wrapper.js +31 -15
  647. package/dist/contexts/websocket-provider-wrapper.js.map +1 -1
  648. package/dist/extensions/canvas-extension-module-loader.d.ts +11 -0
  649. package/dist/hooks/chat/record-model-switch-message.cjs +1 -1
  650. package/dist/hooks/chat/record-model-switch-message.cjs.map +1 -1
  651. package/dist/hooks/chat/record-model-switch-message.d.ts +31 -0
  652. package/dist/hooks/chat/record-model-switch-message.js +25 -12
  653. package/dist/hooks/chat/record-model-switch-message.js.map +1 -1
  654. package/dist/hooks/chat/use-plan-mode-interceptor.cjs +2 -0
  655. package/dist/hooks/chat/use-plan-mode-interceptor.cjs.map +1 -0
  656. package/dist/hooks/chat/use-plan-mode-interceptor.d.ts +16 -0
  657. package/dist/hooks/chat/use-plan-mode-interceptor.js +43 -0
  658. package/dist/hooks/chat/use-plan-mode-interceptor.js.map +1 -0
  659. package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
  660. package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
  661. package/dist/hooks/mutation/use-create-conversation.js +5 -1
  662. package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
  663. package/dist/hooks/mutation/use-manage-canvas-extensions.d.ts +12 -0
  664. package/dist/hooks/mutation/use-read-conversation-file.cjs +1 -1
  665. package/dist/hooks/mutation/use-read-conversation-file.cjs.map +1 -1
  666. package/dist/hooks/mutation/use-read-conversation-file.js +11 -4
  667. package/dist/hooks/mutation/use-read-conversation-file.js.map +1 -1
  668. package/dist/hooks/mutation/use-save-settings.cjs +1 -1
  669. package/dist/hooks/mutation/use-save-settings.js +3 -3
  670. package/dist/hooks/mutation/use-switch-llm-profile.cjs +1 -1
  671. package/dist/hooks/mutation/use-switch-llm-profile.cjs.map +1 -1
  672. package/dist/hooks/mutation/use-switch-llm-profile.js +13 -25
  673. package/dist/hooks/mutation/use-switch-llm-profile.js.map +1 -1
  674. package/dist/hooks/mutation/use-update-conversation-tags.cjs +2 -0
  675. package/dist/hooks/mutation/use-update-conversation-tags.cjs.map +1 -0
  676. package/dist/hooks/mutation/use-update-conversation-tags.d.ts +8 -0
  677. package/dist/hooks/mutation/use-update-conversation-tags.js +45 -0
  678. package/dist/hooks/mutation/use-update-conversation-tags.js.map +1 -0
  679. package/dist/hooks/query/concurrency-limiter.cjs +2 -0
  680. package/dist/hooks/query/concurrency-limiter.cjs.map +1 -0
  681. package/dist/hooks/query/concurrency-limiter.d.ts +22 -0
  682. package/dist/hooks/query/concurrency-limiter.js +29 -0
  683. package/dist/hooks/query/concurrency-limiter.js.map +1 -0
  684. package/dist/hooks/query/query-keys.cjs +1 -1
  685. package/dist/hooks/query/query-keys.cjs.map +1 -1
  686. package/dist/hooks/query/query-keys.d.ts +10 -0
  687. package/dist/hooks/query/query-keys.js +2 -2
  688. package/dist/hooks/query/query-keys.js.map +1 -1
  689. package/dist/hooks/query/use-active-conversation.cjs +1 -1
  690. package/dist/hooks/query/use-active-conversation.js +4 -4
  691. package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
  692. package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
  693. package/dist/hooks/query/use-automation-sdk-version.d.ts +0 -1
  694. package/dist/hooks/query/use-automation-sdk-version.js +30 -55
  695. package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
  696. package/dist/hooks/query/use-automations.cjs.map +1 -1
  697. package/dist/hooks/query/use-automations.js.map +1 -1
  698. package/dist/hooks/query/use-backends-health.cjs +1 -1
  699. package/dist/hooks/query/use-backends-health.cjs.map +1 -1
  700. package/dist/hooks/query/use-backends-health.d.ts +1 -1
  701. package/dist/hooks/query/use-backends-health.js +50 -64
  702. package/dist/hooks/query/use-backends-health.js.map +1 -1
  703. package/dist/hooks/query/use-canvas-extensions.cjs +1 -0
  704. package/dist/hooks/query/use-canvas-extensions.d.ts +5 -0
  705. package/dist/hooks/query/use-canvas-extensions.js +3 -0
  706. package/dist/hooks/query/use-commit-changes.cjs +1 -1
  707. package/dist/hooks/query/use-commit-changes.js +4 -4
  708. package/dist/hooks/query/use-conversation-skills.cjs +1 -1
  709. package/dist/hooks/query/use-conversation-skills.cjs.map +1 -1
  710. package/dist/hooks/query/use-conversation-skills.d.ts +14 -5
  711. package/dist/hooks/query/use-conversation-skills.js +20 -4
  712. package/dist/hooks/query/use-conversation-skills.js.map +1 -1
  713. package/dist/hooks/query/use-latest-automation-runs.cjs +1 -1
  714. package/dist/hooks/query/use-latest-automation-runs.js +1 -0
  715. package/dist/hooks/query/use-paginated-conversations.cjs +1 -1
  716. package/dist/hooks/query/use-paginated-conversations.cjs.map +1 -1
  717. package/dist/hooks/query/use-paginated-conversations.js +19 -16
  718. package/dist/hooks/query/use-paginated-conversations.js.map +1 -1
  719. package/dist/hooks/query/use-provider-connections.cjs +1 -1
  720. package/dist/hooks/query/use-provider-connections.cjs.map +1 -1
  721. package/dist/hooks/query/use-provider-connections.d.ts +6 -3
  722. package/dist/hooks/query/use-provider-connections.js +7 -3
  723. package/dist/hooks/query/use-provider-connections.js.map +1 -1
  724. package/dist/hooks/query/use-search-providers.cjs +1 -1
  725. package/dist/hooks/query/use-search-providers.cjs.map +1 -1
  726. package/dist/hooks/query/use-search-providers.js +17 -10
  727. package/dist/hooks/query/use-search-providers.js.map +1 -1
  728. package/dist/hooks/query/use-sub-conversations.cjs +1 -1
  729. package/dist/hooks/query/use-sub-conversations.cjs.map +1 -1
  730. package/dist/hooks/query/use-sub-conversations.js +16 -16
  731. package/dist/hooks/query/use-sub-conversations.js.map +1 -1
  732. package/dist/hooks/query/use-unified-get-git-changes.cjs +1 -1
  733. package/dist/hooks/query/use-unified-get-git-changes.js +4 -4
  734. package/dist/hooks/query/use-unified-git-commits.cjs +1 -1
  735. package/dist/hooks/query/use-unified-git-commits.js +4 -4
  736. package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
  737. package/dist/hooks/query/use-unified-git-diff.js +4 -4
  738. package/dist/hooks/query/use-unified-vscode-url.cjs +1 -1
  739. package/dist/hooks/query/use-unified-vscode-url.cjs.map +1 -1
  740. package/dist/hooks/query/use-unified-vscode-url.d.ts +1 -0
  741. package/dist/hooks/query/use-unified-vscode-url.js +40 -26
  742. package/dist/hooks/query/use-unified-vscode-url.js.map +1 -1
  743. package/dist/hooks/query/use-workspace-file-content.cjs +1 -1
  744. package/dist/hooks/query/use-workspace-file-content.js +5 -5
  745. package/dist/hooks/query/use-workspace-files.cjs +1 -1
  746. package/dist/hooks/query/use-workspace-files.js +6 -6
  747. package/dist/hooks/use-acp-credential-form.d.ts +6 -0
  748. package/dist/hooks/use-acp-model-context.cjs +1 -1
  749. package/dist/hooks/use-acp-model-context.js +3 -3
  750. package/dist/hooks/use-agent-state.cjs +1 -1
  751. package/dist/hooks/use-agent-state.cjs.map +1 -1
  752. package/dist/hooks/use-agent-state.d.ts +17 -1
  753. package/dist/hooks/use-agent-state.js +19 -9
  754. package/dist/hooks/use-agent-state.js.map +1 -1
  755. package/dist/hooks/use-automation-permissions.cjs +2 -0
  756. package/dist/hooks/use-automation-permissions.cjs.map +1 -0
  757. package/dist/hooks/use-automation-permissions.d.ts +43 -0
  758. package/dist/hooks/use-automation-permissions.js +52 -0
  759. package/dist/hooks/use-automation-permissions.js.map +1 -0
  760. package/dist/hooks/use-chat-input-model-state.cjs +1 -1
  761. package/dist/hooks/use-chat-input-model-state.js +3 -3
  762. package/dist/hooks/use-conversation-overview-git-diff-stats.cjs +1 -1
  763. package/dist/hooks/use-conversation-overview-git-diff-stats.js +4 -4
  764. package/dist/hooks/use-handle-plan-click.cjs +1 -1
  765. package/dist/hooks/use-handle-plan-click.cjs.map +1 -1
  766. package/dist/hooks/use-handle-plan-click.d.ts +3 -1
  767. package/dist/hooks/use-handle-plan-click.js +85 -26
  768. package/dist/hooks/use-handle-plan-click.js.map +1 -1
  769. package/dist/hooks/use-home-automation-actions.cjs +1 -1
  770. package/dist/hooks/use-home-automation-actions.cjs.map +1 -1
  771. package/dist/hooks/use-home-automation-actions.js +1 -0
  772. package/dist/hooks/use-home-automation-actions.js.map +1 -1
  773. package/dist/hooks/use-llm-configured.cjs +1 -1
  774. package/dist/hooks/use-llm-configured.js +3 -3
  775. package/dist/hooks/use-manifest-preflight.d.ts +1 -1
  776. package/dist/hooks/use-pinned-home-route.cjs +2 -0
  777. package/dist/hooks/use-pinned-home-route.cjs.map +1 -0
  778. package/dist/hooks/use-pinned-home-route.d.ts +33 -0
  779. package/dist/hooks/use-pinned-home-route.js +34 -0
  780. package/dist/hooks/use-pinned-home-route.js.map +1 -0
  781. package/dist/hooks/use-skill-enablement.cjs +2 -0
  782. package/dist/hooks/use-skill-enablement.cjs.map +1 -0
  783. package/dist/hooks/use-skill-enablement.d.ts +14 -0
  784. package/dist/hooks/use-skill-enablement.js +80 -0
  785. package/dist/hooks/use-skill-enablement.js.map +1 -0
  786. package/dist/hooks/use-unified-websocket-status.cjs +1 -1
  787. package/dist/hooks/use-unified-websocket-status.cjs.map +1 -1
  788. package/dist/hooks/use-unified-websocket-status.d.ts +7 -0
  789. package/dist/hooks/use-unified-websocket-status.js +5 -1
  790. package/dist/hooks/use-unified-websocket-status.js.map +1 -1
  791. package/dist/i18n/declaration.cjs +1 -1
  792. package/dist/i18n/declaration.cjs.map +1 -1
  793. package/dist/i18n/declaration.d.ts +83 -14
  794. package/dist/i18n/declaration.js +1 -1
  795. package/dist/i18n/declaration.js.map +1 -1
  796. package/dist/i18n/translation.cjs +3 -3
  797. package/dist/i18n/translation.cjs.map +1 -1
  798. package/dist/i18n/translation.js +1575 -402
  799. package/dist/i18n/translation.js.map +1 -1
  800. package/dist/index.cjs +1 -1
  801. package/dist/index.js +15 -14
  802. package/dist/lib/index.cjs +1 -1
  803. package/dist/lib/index.d.ts +1 -0
  804. package/dist/lib/index.js +1 -0
  805. package/dist/locales/ar/openhands.json +94 -25
  806. package/dist/locales/ca/openhands.json +94 -25
  807. package/dist/locales/de/openhands.json +94 -25
  808. package/dist/locales/en/openhands.json +94 -25
  809. package/dist/locales/es/openhands.json +94 -25
  810. package/dist/locales/fr/openhands.json +94 -25
  811. package/dist/locales/it/openhands.json +94 -25
  812. package/dist/locales/ja/openhands.json +94 -25
  813. package/dist/locales/ko-KR/openhands.json +94 -25
  814. package/dist/locales/no/openhands.json +94 -25
  815. package/dist/locales/pt/openhands.json +94 -25
  816. package/dist/locales/tr/openhands.json +94 -25
  817. package/dist/locales/uk/openhands.json +94 -25
  818. package/dist/locales/zh-CN/openhands.json +94 -25
  819. package/dist/locales/zh-TW/openhands.json +94 -25
  820. package/dist/manifests/automation-insights.cjs.map +1 -1
  821. package/dist/manifests/automation-insights.d.ts +10 -2
  822. package/dist/manifests/automation-insights.js.map +1 -1
  823. package/dist/manifests/automation-interface.cjs +1 -1
  824. package/dist/manifests/automation-interface.cjs.map +1 -1
  825. package/dist/manifests/automation-interface.d.ts +6 -0
  826. package/dist/manifests/automation-interface.js +11 -8
  827. package/dist/manifests/automation-interface.js.map +1 -1
  828. package/dist/manifests/automation-setup.cjs +1 -1
  829. package/dist/manifests/automation-setup.cjs.map +1 -1
  830. package/dist/manifests/automation-setup.d.ts +9 -16
  831. package/dist/manifests/automation-setup.js +17 -7
  832. package/dist/manifests/automation-setup.js.map +1 -1
  833. package/dist/manifests/manifest-actions.d.ts +1 -1
  834. package/dist/manifests/manifest-capabilities.d.ts +3 -1
  835. package/dist/manifests/manifest-local-validation.cjs +2 -0
  836. package/dist/manifests/manifest-local-validation.cjs.map +1 -0
  837. package/dist/manifests/manifest-local-validation.d.ts +15 -11
  838. package/dist/manifests/manifest-local-validation.js +8 -0
  839. package/dist/manifests/manifest-local-validation.js.map +1 -0
  840. package/dist/manifests/manifest-template.cjs +2 -0
  841. package/dist/manifests/manifest-template.cjs.map +1 -0
  842. package/dist/manifests/manifest-template.d.ts +4 -4
  843. package/dist/manifests/manifest-template.js +12 -0
  844. package/dist/manifests/manifest-template.js.map +1 -0
  845. package/dist/manifests/manifest-validation.cjs +1 -1
  846. package/dist/manifests/manifest-validation.cjs.map +1 -1
  847. package/dist/manifests/manifest-validation.js +106 -28
  848. package/dist/manifests/manifest-validation.js.map +1 -1
  849. package/dist/manifests/types.cjs.map +1 -1
  850. package/dist/manifests/types.d.ts +39 -4
  851. package/dist/manifests/types.js.map +1 -1
  852. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs +45 -4
  853. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs.map +1 -1
  854. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js +1 -1
  855. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js.map +1 -1
  856. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs +8 -0
  857. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs.map +1 -0
  858. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js +221 -0
  859. package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js.map +1 -0
  860. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs +1 -1
  861. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs.map +1 -1
  862. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js +5 -0
  863. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js.map +1 -1
  864. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +2 -2
  865. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
  866. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +6 -1
  867. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
  868. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +2 -2
  869. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
  870. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +6 -1
  871. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
  872. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +1 -1
  873. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -1
  874. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +5 -0
  875. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -1
  876. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs +9 -0
  877. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
  878. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js +21 -0
  879. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js.map +1 -0
  880. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs +9 -0
  881. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs.map +1 -0
  882. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js +21 -0
  883. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js.map +1 -0
  884. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs +9 -0
  885. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
  886. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js +21 -0
  887. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js.map +1 -0
  888. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs +9 -0
  889. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs.map +1 -0
  890. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js +21 -0
  891. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js.map +1 -0
  892. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs +9 -0
  893. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs.map +1 -0
  894. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js +21 -0
  895. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js.map +1 -0
  896. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs +1 -1
  897. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs.map +1 -1
  898. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js +5 -0
  899. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js.map +1 -1
  900. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs +30 -0
  901. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs.map +1 -0
  902. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js +65 -0
  903. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js.map +1 -0
  904. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
  905. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
  906. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +28 -14
  907. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
  908. package/dist/node_modules/@openhands/extensions/automations/interface.cjs +1 -1
  909. package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -1
  910. package/dist/node_modules/@openhands/extensions/automations/interface.js +2 -1
  911. package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -1
  912. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
  913. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
  914. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +2 -2
  915. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
  916. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs +2 -0
  917. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs.map +1 -0
  918. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js +59 -0
  919. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js.map +1 -0
  920. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  921. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  922. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +1 -1
  923. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  924. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
  925. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
  926. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +74 -72
  927. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
  928. package/dist/node_modules/@openhands/extensions/skills/index.cjs +42 -3
  929. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  930. package/dist/node_modules/@openhands/extensions/skills/index.js +22 -3
  931. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  932. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.cjs +1 -1
  933. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.js +1 -1
  934. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs +1 -1
  935. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs.map +1 -1
  936. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js +8 -7
  937. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js.map +1 -1
  938. package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
  939. package/dist/node_modules/@openhands/typescript-client/dist/index.js +2 -2
  940. package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.cjs +1 -1
  941. package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.js +1 -1
  942. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs +2 -0
  943. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs.map +1 -0
  944. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js +16 -0
  945. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js.map +1 -0
  946. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs +2 -0
  947. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs.map +1 -0
  948. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js +21 -0
  949. package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js.map +1 -0
  950. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs +2 -0
  951. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs.map +1 -0
  952. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js +23 -0
  953. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js.map +1 -0
  954. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs +2 -0
  955. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs.map +1 -0
  956. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js +23 -0
  957. package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js.map +1 -0
  958. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs +2 -0
  959. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs.map +1 -0
  960. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js +43 -0
  961. package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js.map +1 -0
  962. package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs +2 -0
  963. package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs.map +1 -0
  964. package/dist/node_modules/lucide-react/dist/esm/icons/tags.js +22 -0
  965. package/dist/node_modules/lucide-react/dist/esm/icons/tags.js.map +1 -0
  966. package/dist/package.cjs +1 -1
  967. package/dist/package.cjs.map +1 -1
  968. package/dist/package.js +5 -5
  969. package/dist/package.js.map +1 -1
  970. package/dist/routes/agent-settings.d.ts +12 -0
  971. package/dist/routes/app-settings.cjs +1 -1
  972. package/dist/routes/app-settings.cjs.map +1 -1
  973. package/dist/routes/app-settings.js +11 -11
  974. package/dist/routes/files-tab.cjs +1 -1
  975. package/dist/routes/files-tab.cjs.map +1 -1
  976. package/dist/routes/files-tab.js +14 -14
  977. package/dist/routes/files-tab.js.map +1 -1
  978. package/dist/routes/llm-settings.cjs +1 -1
  979. package/dist/routes/llm-settings.cjs.map +1 -1
  980. package/dist/routes/llm-settings.d.ts +3 -1
  981. package/dist/routes/llm-settings.js +100 -91
  982. package/dist/routes/llm-settings.js.map +1 -1
  983. package/dist/routes/planner-tab.cjs +1 -1
  984. package/dist/routes/planner-tab.cjs.map +1 -1
  985. package/dist/routes/planner-tab.js +44 -28
  986. package/dist/routes/planner-tab.js.map +1 -1
  987. package/dist/services/canvas-ui.cjs +1 -1
  988. package/dist/services/canvas-ui.cjs.map +1 -1
  989. package/dist/services/canvas-ui.d.ts +5 -0
  990. package/dist/services/canvas-ui.js +24 -10
  991. package/dist/services/canvas-ui.js.map +1 -1
  992. package/dist/services/settings.cjs +1 -1
  993. package/dist/services/settings.cjs.map +1 -1
  994. package/dist/services/settings.js +3 -2
  995. package/dist/services/settings.js.map +1 -1
  996. package/dist/services/telemetry.cjs +1 -1
  997. package/dist/services/telemetry.cjs.map +1 -1
  998. package/dist/services/telemetry.d.ts +5 -0
  999. package/dist/services/telemetry.js +122 -115
  1000. package/dist/services/telemetry.js.map +1 -1
  1001. package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
  1002. package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
  1003. package/dist/stores/conversation-panel-preferences-store.d.ts +32 -5
  1004. package/dist/stores/conversation-panel-preferences-store.js +29 -12
  1005. package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
  1006. package/dist/stores/conversation-state-store.cjs +1 -1
  1007. package/dist/stores/conversation-state-store.cjs.map +1 -1
  1008. package/dist/stores/conversation-state-store.d.ts +9 -3
  1009. package/dist/stores/conversation-state-store.js +6 -3
  1010. package/dist/stores/conversation-state-store.js.map +1 -1
  1011. package/dist/stores/conversation-store.cjs +1 -1
  1012. package/dist/stores/conversation-store.cjs.map +1 -1
  1013. package/dist/stores/conversation-store.d.ts +2 -0
  1014. package/dist/stores/conversation-store.js +3 -0
  1015. package/dist/stores/conversation-store.js.map +1 -1
  1016. package/dist/stores/model-store.cjs +1 -1
  1017. package/dist/stores/model-store.cjs.map +1 -1
  1018. package/dist/stores/model-store.d.ts +7 -0
  1019. package/dist/stores/model-store.js +4 -0
  1020. package/dist/stores/model-store.js.map +1 -1
  1021. package/dist/types/automation.cjs.map +1 -1
  1022. package/dist/types/automation.d.ts +66 -1
  1023. package/dist/types/automation.js.map +1 -1
  1024. package/dist/types/canvas-extension.cjs +2 -0
  1025. package/dist/types/canvas-extension.cjs.map +1 -0
  1026. package/dist/types/canvas-extension.d.ts +77 -0
  1027. package/dist/types/canvas-extension.js +6 -0
  1028. package/dist/types/canvas-extension.js.map +1 -0
  1029. package/dist/types/settings.d.ts +7 -0
  1030. package/dist/ui/context-menu.d.ts +1 -1
  1031. package/dist/ui/help-link.cjs +1 -1
  1032. package/dist/ui/help-link.cjs.map +1 -1
  1033. package/dist/ui/help-link.d.ts +6 -1
  1034. package/dist/ui/help-link.js +32 -18
  1035. package/dist/ui/help-link.js.map +1 -1
  1036. package/dist/ui/toggle-switch.cjs +1 -1
  1037. package/dist/ui/toggle-switch.cjs.map +1 -1
  1038. package/dist/ui/toggle-switch.d.ts +4 -1
  1039. package/dist/ui/toggle-switch.js +4 -3
  1040. package/dist/ui/toggle-switch.js.map +1 -1
  1041. package/dist/utils/acp-auth-display.d.ts +35 -0
  1042. package/dist/utils/automation-catalog.cjs +1 -1
  1043. package/dist/utils/automation-catalog.cjs.map +1 -1
  1044. package/dist/utils/automation-catalog.d.ts +12 -1
  1045. package/dist/utils/automation-catalog.js +42 -12
  1046. package/dist/utils/automation-catalog.js.map +1 -1
  1047. package/dist/utils/automation-run-display.cjs +2 -0
  1048. package/dist/utils/automation-run-display.cjs.map +1 -0
  1049. package/dist/utils/automation-run-display.d.ts +20 -0
  1050. package/dist/utils/automation-run-display.js +85 -0
  1051. package/dist/utils/automation-run-display.js.map +1 -0
  1052. package/dist/utils/automation-schedule.cjs +1 -1
  1053. package/dist/utils/automation-schedule.cjs.map +1 -1
  1054. package/dist/utils/automation-schedule.d.ts +16 -0
  1055. package/dist/utils/automation-schedule.js +2 -0
  1056. package/dist/utils/automation-schedule.js.map +1 -1
  1057. package/dist/utils/cache-utils.cjs +1 -1
  1058. package/dist/utils/cache-utils.js +5 -5
  1059. package/dist/utils/constants.cjs +1 -1
  1060. package/dist/utils/constants.cjs.map +1 -1
  1061. package/dist/utils/constants.d.ts +4 -0
  1062. package/dist/utils/constants.js +23 -3
  1063. package/dist/utils/constants.js.map +1 -1
  1064. package/dist/utils/format-event-timestamp.cjs +2 -0
  1065. package/dist/utils/format-event-timestamp.cjs.map +1 -0
  1066. package/dist/utils/format-event-timestamp.d.ts +1 -0
  1067. package/dist/utils/format-event-timestamp.js +13 -0
  1068. package/dist/utils/format-event-timestamp.js.map +1 -0
  1069. package/dist/utils/format-model-name.cjs +1 -1
  1070. package/dist/utils/format-model-name.cjs.map +1 -1
  1071. package/dist/utils/format-model-name.d.ts +7 -3
  1072. package/dist/utils/format-model-name.js +6 -11
  1073. package/dist/utils/format-model-name.js.map +1 -1
  1074. package/dist/utils/format-relative-time.cjs +1 -1
  1075. package/dist/utils/format-relative-time.cjs.map +1 -1
  1076. package/dist/utils/format-relative-time.d.ts +7 -0
  1077. package/dist/utils/format-relative-time.js +7 -2
  1078. package/dist/utils/format-relative-time.js.map +1 -1
  1079. package/dist/utils/git-diff-stats.cjs +2 -2
  1080. package/dist/utils/git-diff-stats.cjs.map +1 -1
  1081. package/dist/utils/git-diff-stats.d.ts +4 -0
  1082. package/dist/utils/git-diff-stats.js +12 -2
  1083. package/dist/utils/git-diff-stats.js.map +1 -1
  1084. package/dist/utils/path-utils.cjs +1 -1
  1085. package/dist/utils/path-utils.cjs.map +1 -1
  1086. package/dist/utils/path-utils.d.ts +15 -3
  1087. package/dist/utils/path-utils.js +29 -3
  1088. package/dist/utils/path-utils.js.map +1 -1
  1089. package/dist/utils/plan-file.cjs +4 -0
  1090. package/dist/utils/plan-file.cjs.map +1 -0
  1091. package/dist/utils/plan-file.d.ts +18 -0
  1092. package/dist/utils/plan-file.js +58 -0
  1093. package/dist/utils/plan-file.js.map +1 -0
  1094. package/dist/utils/recommended-automation-rail.cjs +1 -1
  1095. package/dist/utils/recommended-automation-rail.cjs.map +1 -1
  1096. package/dist/utils/recommended-automation-rail.js +1 -0
  1097. package/dist/utils/recommended-automation-rail.js.map +1 -1
  1098. package/dist/utils/scroll-fade-state.cjs +1 -1
  1099. package/dist/utils/scroll-fade-state.cjs.map +1 -1
  1100. package/dist/utils/scroll-fade-state.d.ts +6 -0
  1101. package/dist/utils/scroll-fade-state.js +8 -1
  1102. package/dist/utils/scroll-fade-state.js.map +1 -1
  1103. package/dist/utils/sdk-settings-schema.cjs +1 -1
  1104. package/dist/utils/sdk-settings-schema.cjs.map +1 -1
  1105. package/dist/utils/sdk-settings-schema.d.ts +1 -0
  1106. package/dist/utils/sdk-settings-schema.js +25 -22
  1107. package/dist/utils/sdk-settings-schema.js.map +1 -1
  1108. package/dist/utils/skill-enablement.cjs +2 -0
  1109. package/dist/utils/skill-enablement.cjs.map +1 -0
  1110. package/dist/utils/skill-enablement.d.ts +51 -0
  1111. package/dist/utils/skill-enablement.js +31 -0
  1112. package/dist/utils/skill-enablement.js.map +1 -0
  1113. package/dist/utils/utils.cjs +1 -1
  1114. package/dist/utils/utils.cjs.map +1 -1
  1115. package/dist/utils/utils.js +11 -11
  1116. package/dist/utils/utils.js.map +1 -1
  1117. package/dist/utils/vscode-origin.cjs +2 -0
  1118. package/dist/utils/vscode-origin.cjs.map +1 -0
  1119. package/dist/utils/vscode-origin.d.ts +55 -0
  1120. package/dist/utils/vscode-origin.js +27 -0
  1121. package/dist/utils/vscode-origin.js.map +1 -0
  1122. package/dist/utils/workspace-mode.d.ts +4 -0
  1123. package/package.json +5 -5
  1124. package/scripts/check-sdk-version-sync.mjs +6 -6
  1125. package/scripts/check-translation-completeness.cjs +1 -0
  1126. package/scripts/dev-extra-backend.mjs +28 -9
  1127. package/scripts/dev-safe.mjs +81 -8
  1128. package/scripts/dev-static.mjs +35 -37
  1129. package/scripts/dev-with-automation.mjs +83 -2
  1130. package/scripts/ingress.mjs +27 -1
  1131. package/scripts/static-server.mjs +107 -2
  1132. package/tools/canvas_ui_tool.py +19 -0
  1133. package/build/assets/active-backend-context-DKFSMbn3.js +0 -2
  1134. package/build/assets/agent-profiles-settings-D4cY5U2T.js +0 -1
  1135. package/build/assets/agent-server-conversation-service.api-DozDKIW_.js +0 -86
  1136. package/build/assets/agent-settings-351vXWc9.js +0 -2
  1137. package/build/assets/agent-settings-Ce7BDZ6I.js +0 -1
  1138. package/build/assets/alert-banner-Kyy1YWZU.js +0 -1
  1139. package/build/assets/api-key-entry-screen-INIxqAMs.js +0 -1
  1140. package/build/assets/automation-detail-DXDhUwPq.js +0 -3
  1141. package/build/assets/automation-git-sync-CzyS4cn1.js +0 -1
  1142. package/build/assets/automation-setup-route-FRr05f_g.js +0 -1
  1143. package/build/assets/automations-list-CERuQWE6.js +0 -1
  1144. package/build/assets/backend-form-modal-DK78-jn1.js +0 -1
  1145. package/build/assets/bot-C-0Wu7vQ.js +0 -1
  1146. package/build/assets/browser-11etCQ04.js +0 -7
  1147. package/build/assets/check-Cf2YoT90.js +0 -1
  1148. package/build/assets/chevron-down-C3OQ-ehx.js +0 -1
  1149. package/build/assets/chevron-right-CN1uUiJ1.js +0 -1
  1150. package/build/assets/circle-check-g5yeGMd-.js +0 -1
  1151. package/build/assets/command-menu-BZQ8S3Ke.js +0 -1
  1152. package/build/assets/commits-tab-DZtJgaDM.js +0 -1
  1153. package/build/assets/confirmation-modal-Bk4JRcCM.js +0 -1
  1154. package/build/assets/conversation-CchMzpGl.js +0 -1
  1155. package/build/assets/conversation-Dpzftz57.js +0 -93
  1156. package/build/assets/conversation-panel-CchMzpGl.js +0 -1
  1157. package/build/assets/conversation-state-store-a9d2fxRc.js +0 -1
  1158. package/build/assets/edit-automation-modal-D-urtv8n.js +0 -1
  1159. package/build/assets/empty-state-CvaVahVr.js +0 -1
  1160. package/build/assets/enum-filter-dropdown-DliX_Lo0.js +0 -1
  1161. package/build/assets/extensions-hub-CFduxBnk.js +0 -1
  1162. package/build/assets/extensions-navigation-BeC224yX.js +0 -1
  1163. package/build/assets/external-link-DFpYunfj.js +0 -1
  1164. package/build/assets/files-tab-CL3J9b3p.js +0 -1
  1165. package/build/assets/format-model-name-BNPKVsIq.js +0 -1
  1166. package/build/assets/get-git-path-DlAJa_i6.js +0 -1
  1167. package/build/assets/git-repo-dropdown-DGMEhz7d.js +0 -1
  1168. package/build/assets/home-BCGlNJCA.js +0 -1
  1169. package/build/assets/home-DB1pRqTC.js +0 -1
  1170. package/build/assets/home-automation-run-tooltip-CooFQRIG.js +0 -1
  1171. package/build/assets/home-store-Dl1dPE58.js +0 -1
  1172. package/build/assets/index-home-DB1pRqTC.js +0 -1
  1173. package/build/assets/info-uYSVzX86.js +0 -1
  1174. package/build/assets/install-server-modal-BbJdhzet.js +0 -1
  1175. package/build/assets/kebab-menu-item-content-BYokkRHi.js +0 -1
  1176. package/build/assets/list-filter-OFkpRrmi.js +0 -1
  1177. package/build/assets/llm-not-configured-banner-BqqYnJ1t.js +0 -27
  1178. package/build/assets/llm-settings-CnDbbmVW.js +0 -1
  1179. package/build/assets/llm-settings-S8Yjg__1.js +0 -1
  1180. package/build/assets/llm-subscription-service-BpPfzW4x.js +0 -1
  1181. package/build/assets/loader-circle-nvrwthvj.js +0 -1
  1182. package/build/assets/manage-backends-modal-BCUPswyl.js +0 -1
  1183. package/build/assets/manifest-58597dde.js +0 -1
  1184. package/build/assets/markdown-renderer-Cb2sBWtV.js +0 -8
  1185. package/build/assets/mcp-page-Bm4K2NQq.js +0 -9
  1186. package/build/assets/messages-BTN5thLe.js +0 -40
  1187. package/build/assets/onboarding-Cx_kaiD1.js +0 -1
  1188. package/build/assets/onboarding-modal-vMwn7ihv.js +0 -1
  1189. package/build/assets/organization-service.api-C8XpQ0pM.js +0 -1
  1190. package/build/assets/pencil-Clh1Wjvh.js +0 -1
  1191. package/build/assets/planner-tab-DQvDU3ap.js +0 -1
  1192. package/build/assets/plug-BuQhHSSG.js +0 -1
  1193. package/build/assets/plugins-management-service-BjYeF0b0.js +0 -1
  1194. package/build/assets/plus-CEKne-Yp.js +0 -1
  1195. package/build/assets/profiles-service.api-QB-T_u-g.js +0 -1
  1196. package/build/assets/providers-FfSZ5TXP.js +0 -1
  1197. package/build/assets/proxy-tcFL2yTQ.js +0 -1
  1198. package/build/assets/recommended-automations-launcher-Bw8uC4V6.js +0 -1
  1199. package/build/assets/refresh-cw-Bh69DyYO.js +0 -1
  1200. package/build/assets/root-BLeQfBEq.css +0 -1
  1201. package/build/assets/root-ZKKYPR1Z.js +0 -2
  1202. package/build/assets/root-layout-luJoE9IG.js +0 -2
  1203. package/build/assets/schema-field-Csw5fhtN.js +0 -1
  1204. package/build/assets/scroll-fade-state-Dw-i4SGq.js +0 -1
  1205. package/build/assets/sdk-section-page-HTffvm7Q.js +0 -1
  1206. package/build/assets/secret-form-HTUbYw5o.js +0 -1
  1207. package/build/assets/secrets-service-BTor9uAU.js +0 -1
  1208. package/build/assets/settings-BlmrkwRi.js +0 -1
  1209. package/build/assets/settings-DcNPxz0v.js +0 -1
  1210. package/build/assets/settings-index-CKq0b0Vg.js +0 -1
  1211. package/build/assets/settings-service.api-B2agVfjL.js +0 -1
  1212. package/build/assets/shared-conversation-B55pCyBG.js +0 -1
  1213. package/build/assets/shield-check-CFDViW82.js +0 -1
  1214. package/build/assets/sidebar-mobile-menu-toggle-BOtyJHwE.js +0 -1
  1215. package/build/assets/sidebar-nav-link-CPzhyHQg.js +0 -1
  1216. package/build/assets/sidebar-store-DtpU7zaI.js +0 -1
  1217. package/build/assets/skill-filter-CWZ5kjcg.js +0 -2
  1218. package/build/assets/skill-scope-CV1dkAbW.js +0 -1
  1219. package/build/assets/skills-plugins-DGHULTq6.js +0 -1
  1220. package/build/assets/skills-settings-CM1lFv3e.js +0 -1
  1221. package/build/assets/styled-tooltip-Dl06rkpY.js +0 -1
  1222. package/build/assets/toggle-switch-Fd_QGz0r.js +0 -1
  1223. package/build/assets/trash-2-Dl8_RGz0.js +0 -1
  1224. package/build/assets/trash-_RMt7Ayc.js +0 -1
  1225. package/build/assets/triangle-alert-SM-q4NU_.js +0 -1
  1226. package/build/assets/usage-tab-BcfWV6db.js +0 -1
  1227. package/build/assets/use-acp-credential-form-BsSW5NHG.js +0 -1
  1228. package/build/assets/use-activate-agent-profile-B2NS8nA5.js +0 -1
  1229. package/build/assets/use-agent-profiles-DWBPC0Si.js +0 -1
  1230. package/build/assets/use-config-Bft35DOK.js +0 -1
  1231. package/build/assets/use-create-conversation-DwN5vv2f.js +0 -1
  1232. package/build/assets/use-create-secret-BSxJMxHp.js +0 -1
  1233. package/build/assets/use-has-permission-B3C8rQmR.js +0 -1
  1234. package/build/assets/use-is-authed-CFGkY3-Z.js +0 -1
  1235. package/build/assets/use-llm-configured-BI6obxsc.js +0 -1
  1236. package/build/assets/use-llm-profiles-djGAhTWL.js +0 -1
  1237. package/build/assets/use-manifest-capabilities-3z0-1G59.js +0 -1
  1238. package/build/assets/use-onboarding-completion-BXpyUSsJ.js +0 -1
  1239. package/build/assets/use-plugins-marketplace-DI4_pK56.js +0 -1
  1240. package/build/assets/use-save-agent-profile-DdBSTdpN.js +0 -1
  1241. package/build/assets/use-settings-C5VhGpqd.js +0 -1
  1242. package/build/assets/use-settings-nav-items-DHaUu1Dg.js +0 -16
  1243. package/build/assets/use-tracking-D5t9otIF.js +0 -3
  1244. package/build/assets/utils-DaCIEEQP.js +0 -1
  1245. package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kepq2zme-ZixYGy6E.js +0 -186
  1246. package/build/assets/vendor~index-home~home~conversation-panel~conversation~alert-banner-B3qC_oj8.js +0 -1
  1247. package/build/assets/vendor~root-layout-BlUaZ18v.js +0 -1
  1248. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-B2OLKL7N.js +0 -1
  1249. package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iw7io29p-Dz-MAyNb.js +0 -1
  1250. package/build/assets/x-DkgltWa0.js +0 -1
  1251. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +0 -2
  1252. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +0 -1
  1253. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +0 -35
  1254. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +0 -247
  1255. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +0 -1
  1256. package/dist/components/features/tips/random-tip.d.ts +0 -2
  1257. package/dist/hooks/query/use-skills.cjs +0 -2
  1258. package/dist/hooks/query/use-skills.cjs.map +0 -1
  1259. package/dist/hooks/query/use-skills.d.ts +0 -7
  1260. package/dist/hooks/query/use-skills.js +0 -13
  1261. package/dist/hooks/query/use-skills.js.map +0 -1
  1262. package/dist/hooks/use-has-permission.cjs +0 -2
  1263. package/dist/hooks/use-has-permission.cjs.map +0 -1
  1264. package/dist/hooks/use-has-permission.d.ts +0 -1
  1265. package/dist/hooks/use-has-permission.js +0 -8
  1266. package/dist/hooks/use-has-permission.js.map +0 -1
  1267. package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs +0 -2
  1268. package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs.map +0 -1
  1269. package/dist/node_modules/lucide-react/dist/esm/icons/eye.js +0 -14
  1270. package/dist/node_modules/lucide-react/dist/esm/icons/eye.js.map +0 -1
  1271. package/dist/utils/tips.d.ts +0 -7
  1272. package/dist/utils/workspace-relative-path.cjs +0 -2
  1273. package/dist/utils/workspace-relative-path.cjs.map +0 -1
  1274. package/dist/utils/workspace-relative-path.d.ts +0 -10
  1275. package/dist/utils/workspace-relative-path.js +0 -22
  1276. package/dist/utils/workspace-relative-path.js.map +0 -1
  1277. /package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ox0jfsa0-cHFhpUBq.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~i58xkef6-cHFhpUBq.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":[],"sources":["../../src/utils/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Provider } from \"#/types/settings\";\nimport { SuggestedTaskGroup } from \"#/utils/types\";\nimport { ConversationStatus } from \"#/types/conversation-status\";\nimport { GitRepository } from \"#/types/git\";\nimport { sanitizeQuery } from \"#/utils/sanitize-query\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getTaskStatusI18nKey } from \"#/utils/status\";\nimport type { AppConversationStartTaskStatus } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport {\n OH_STATUS_ERROR_COLOR,\n OH_STATUS_SUCCESS_COLOR,\n} from \"#/constants/status-colors\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Trigger a download for a provided Blob with the given filename\n */\nexport const downloadBlob = (blob: Blob, filename: string): void => {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(url);\n};\n\n/**\n * Get the numeric height value from an element's style property\n * @param el The HTML element to get the height from\n * @param fallback The fallback value to return if style height is invalid\n * @returns The numeric height value in pixels, or the fallback value\n *\n * @example\n * getStyleHeightPx(element, 20) // Returns 20 if element.style.height is \"auto\" or invalid\n * getStyleHeightPx(element, 20) // Returns 100 if element.style.height is \"100px\"\n */\nexport const getStyleHeightPx = (el: HTMLElement, fallback: number): number => {\n const elementHeight = parseFloat(el.style.height || \"\");\n return Number.isFinite(elementHeight) ? elementHeight : fallback;\n};\n\n/**\n * Set the height style property of an element to a specific pixel value\n * @param el The HTML element to set the height for\n * @param height The height value in pixels to set\n *\n * @example\n * setStyleHeightPx(element, 100) // Sets element.style.height to \"100px\"\n * setStyleHeightPx(textarea, 200) // Sets textarea.style.height to \"200px\"\n */\nexport const setStyleHeightPx = (el: HTMLElement, height: number): void => {\n el.style.setProperty(\"height\", `${height}px`);\n};\n\n/**\n * Detect a phone/tablet user agent (Android, iPhone, iPad, …).\n * Unlike isMobileDevice, this ignores touch capability, so a desktop OS with\n * a touchscreen (e.g. a Windows 2-in-1) is NOT matched. Use this when the\n * decision depends on having a physical keyboard rather than on touch input.\n */\nexport const isMobileUserAgent = (): boolean =>\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n\n/**\n * Detect if the user is on a mobile device.\n * Touch support alone is not sufficient — touchscreen laptops have touch\n * but use a mouse/trackpad as primary input. We check that the primary\n * pointing device is coarse (finger) to avoid false positives.\n */\nexport const isMobileDevice = (): boolean => {\n if (isMobileUserAgent()) return true;\n\n const hasTouch = \"ontouchstart\" in window || navigator.maxTouchPoints > 0;\n if (!hasTouch) return false;\n\n // If matchMedia is available, check whether the primary pointer is fine\n // (mouse/trackpad). Touchscreen laptops report fine, real mobile devices don't.\n if (typeof window.matchMedia === \"function\") {\n return !window.matchMedia(\"(pointer: fine)\").matches;\n }\n\n // Fallback: touch present but no matchMedia — assume mobile\n return true;\n};\n\n/**\n * Checks if the current domain is the production domain\n * @returns True if the current domain matches the production URL\n */\nexport const isProductionDomain = (): boolean =>\n window.location.origin === PRODUCT_URL.PRODUCTION;\n\ninterface EventActionHistory {\n args?: {\n LLM_API_KEY?: string;\n [key: string]: unknown;\n };\n extras?: {\n open_page_urls: string[];\n active_page_index: number;\n dom_object: Record<string, unknown>;\n axtree_object: Record<string, unknown>;\n extra_element_properties: Record<string, unknown>;\n last_browser_action: string;\n last_browser_action_error: unknown;\n focused_element_bid: string;\n };\n [key: string]: unknown;\n}\n\nexport const removeUnwantedKeys = (\n data: EventActionHistory[],\n): EventActionHistory[] => {\n const UNDESIRED_KEYS = [\n \"open_page_urls\",\n \"active_page_index\",\n \"dom_object\",\n \"axtree_object\",\n \"extra_element_properties\",\n \"last_browser_action\",\n \"last_browser_action_error\",\n \"focused_element_bid\",\n ];\n\n return data\n .filter((item) => {\n // Skip items that have a status key\n if (\"status\" in item) {\n return false;\n }\n return true;\n })\n .map((item) => {\n // Create a shallow copy of item\n const newItem = { ...item };\n\n // Check if extras exists and delete it from a new extras object\n if (newItem.extras) {\n const newExtras = { ...newItem.extras };\n UNDESIRED_KEYS.forEach((key) => {\n delete newExtras[key as keyof typeof newExtras];\n });\n newItem.extras = newExtras;\n }\n\n return newItem;\n });\n};\n\n/**\n * Get file extension from file name in uppercase format\n * @param fileName The file name to extract extension from\n * @returns The file extension in uppercase, or \"FILE\" if no extension found\n *\n * @example\n * getFileExtension(\"document.pdf\") // \"PDF\"\n * getFileExtension(\"image.jpeg\") // \"JPEG\"\n * getFileExtension(\"noextension\") // \"FILE\"\n */\nexport const getFileExtension = (fileName: string): string => {\n const extension = fileName.split(\".\").pop()?.toUpperCase();\n return extension || \"FILE\";\n};\n\n/**\n * Whether to use the installation-scoped repo flow\n * (`/api/v1/git/installations/search` → `/api/v1/git/repositories/search?installation_id=…`)\n * for the given provider/backend combo.\n *\n * Mirrors OpenHands' cloud frontend (parameterized by `app_mode`):\n * - bitbucket / bitbucket_data_center → always installation-based\n * - github → installation-based ONLY when the active backend is cloud\n * - gitlab / azure_devops / forgejo → direct (search) flow\n *\n * `appMode` accepts the active backend `kind` (\"local\" | \"cloud\") so call\n * sites can hand it through directly.\n */\nexport const shouldUseInstallationRepos = (\n provider: Provider | null | undefined,\n appMode?: \"local\" | \"cloud\",\n) => {\n if (!provider) return false;\n\n switch (provider) {\n case \"bitbucket\":\n case \"bitbucket_data_center\":\n return true;\n case \"github\":\n return appMode === \"cloud\";\n default:\n return false;\n }\n};\n\nexport const getGitProviderBaseUrl = (\n gitProvider: Provider,\n host?: string | null,\n): string => {\n // If custom host provided, use it (with https:// prefix if needed)\n if (host && host.trim() !== \"\") {\n return host.startsWith(\"http\") ? host : `https://${host}`;\n }\n\n // Fall back to defaults\n switch (gitProvider) {\n case \"github\":\n return \"https://github.com\";\n case \"gitlab\":\n return \"https://gitlab.com\";\n case \"bitbucket\":\n return \"https://bitbucket.org\";\n case \"azure_devops\":\n return \"https://dev.azure.com\";\n case \"forgejo\":\n // Default UI links to Codeberg unless a custom host is available in settings\n // Note: UI link builders don't currently receive host; consider plumbing settings if needed\n return \"https://codeberg.org\";\n default:\n return \"\";\n }\n};\n\n/**\n * Get the name of the git provider\n * @param gitProvider The git provider\n * @returns The name of the git provider\n */\nexport const getProviderName = (gitProvider: Provider) => {\n if (gitProvider === \"gitlab\") return \"GitLab\";\n if (gitProvider === \"bitbucket\") return \"Bitbucket\";\n if (gitProvider === \"bitbucket_data_center\") return \"Bitbucket Data Center\";\n if (gitProvider === \"azure_devops\") return \"Azure DevOps\";\n if (gitProvider === \"forgejo\") return \"Forgejo\";\n return \"GitHub\";\n};\n\n/**\n * Get the name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The name of the PR\n */\nexport const getPR = (isGitLab: boolean) =>\n isGitLab ? \"merge request\" : \"pull request\";\n\n/**\n * Get the short name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The short name of the PR\n */\nexport const getPRShort = (isGitLab: boolean) => (isGitLab ? \"MR\" : \"PR\");\n\n/**\n * Construct the pull request (merge request) URL for different providers\n * @param prNumber The pull request number\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The pull request URL\n *\n * @example\n * constructPullRequestUrl(123, \"github\", \"owner/repo\") // \"https://github.com/owner/repo/pull/123\"\n * constructPullRequestUrl(456, \"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo/-/merge_requests/456\"\n * constructPullRequestUrl(789, \"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo/pull-requests/789\"\n * constructPullRequestUrl(789, \"bitbucket\", \"PROJECT/repo\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/pull-requests/789\"\n */\nexport const constructPullRequestUrl = (\n prNumber: number,\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/merge_requests/${prNumber}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/pull-requests/${prNumber}`;\n case \"bitbucket_data_center\": {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}/pull-requests/${prNumber}`;\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}/pullrequest/${prNumber}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n/**\n * Construct the repository URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The repository URL\n *\n * @example\n * constructRepositoryUrl(\"github\", \"owner/repo\") // \"https://github.com/owner/repo\"\n * constructRepositoryUrl(\"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo\"\n * constructRepositoryUrl(\"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo\"\n */\nexport const constructRepositoryUrl = (\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n if (provider === \"bitbucket_data_center\") {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}`;\n }\n return `${baseUrl}/${repositoryName}`;\n};\n\n/**\n * Construct the branch URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @param branchName The branch name\n * @param host Optional custom host for self-hosted instances\n * @returns The branch URL\n *\n * @example\n * constructBranchUrl(\"github\", \"owner/repo\", \"main\") // \"https://github.com/owner/repo/tree/main\"\n * constructBranchUrl(\"gitlab\", \"owner/repo\", \"develop\") // \"https://gitlab.com/owner/repo/-/tree/develop\"\n * constructBranchUrl(\"bitbucket\", \"owner/repo\", \"feature\") // \"https://bitbucket.org/owner/repo/src/feature\"\n * constructBranchUrl(\"bitbucket\", \"PROJECT/repo\", \"feature\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/browse?at=refs/heads/feature\"\n */\nexport const constructBranchUrl = (\n provider: Provider,\n repositoryName: string,\n branchName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/tree/${branchName}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/src/branch/${branchName}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/tree/${branchName}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/src/${branchName}`;\n case \"bitbucket_data_center\": {\n // Bitbucket Server format: /projects/{PROJECT}/repos/{repo}/browse?at=refs/heads/{branch}\n const parts = repositoryName.split(\"/\");\n if (parts.length >= 2) {\n const [project, repo] = parts;\n return `${baseUrl}/projects/${project}/repos/${repo}/browse?at=refs/heads/${branchName}`;\n }\n return \"\";\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}?version=GB${branchName}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n// Git Action Prompts\n\nconst GIT_COMMIT_PROMPT =\n \"Please review the current changes and create a git commit with a concise, descriptive message.\";\n\nexport const getGitCommitPrompt = (): string => GIT_COMMIT_PROMPT;\n\n/**\n * Generate a git pull prompt\n * @returns The git pull prompt\n */\nexport const getGitPullPrompt = (): string =>\n \"Please pull the latest code from the repository.\";\n\n/**\n * Generate a git push prompt\n * @param gitProvider The git provider\n * @returns The git push prompt\n */\nexport const getGitPushPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the changes to a remote branch on ${providerName}, but do NOT create a ${pr}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`;\n};\n\n/**\n * Generate a create pull request prompt\n * @param gitProvider The git provider\n * @returns The create PR prompt\n */\nexport const getCreatePRPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n const prShort = getPRShort(gitProvider === \"gitlab\");\n\n return `Please push the changes to ${providerName} and open a ${pr}. If you're on a default branch (e.g., main, master, deploy), create a new branch with a descriptive name otherwise use the current branch. If a ${pr} template exists in the repository, please follow it when creating the ${prShort} description.`;\n};\n\n/**\n * Generate a push to existing PR prompt\n * @param gitProvider The git provider\n * @returns The push to PR prompt\n */\nexport const getPushToPRPrompt = (gitProvider: Provider): string => {\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the latest changes to the existing ${pr}.`;\n};\n\n/**\n * Generate a create new branch prompt\n * @returns The create new branch prompt\n */\nexport const getCreateNewBranchPrompt = (): string =>\n \"Please create a new branch with a descriptive name related to the work you plan to do.\";\n\n// Helper functions\nexport function getTotalTaskCount(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n): number {\n if (!suggestedTasks) return 0;\n return suggestedTasks.flatMap((group) => group.tasks).length;\n}\n\nexport function getLimitedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[],\n maxTasks: number,\n): SuggestedTaskGroup[] {\n const limitedGroups: SuggestedTaskGroup[] = [];\n let taskCount = 0;\n\n for (const group of suggestedTasks) {\n if (taskCount >= maxTasks) break;\n\n const remainingTasksNeeded = maxTasks - taskCount;\n const tasksToShow = group.tasks.slice(0, remainingTasksNeeded);\n\n if (tasksToShow.length > 0) {\n limitedGroups.push({\n ...group,\n tasks: tasksToShow,\n });\n taskCount += tasksToShow.length;\n }\n }\n\n return limitedGroups;\n}\n\nexport function getDisplayedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n isExpanded: boolean,\n): SuggestedTaskGroup[] {\n if (!suggestedTasks || suggestedTasks.length === 0) {\n return [];\n }\n\n if (isExpanded) {\n return suggestedTasks;\n }\n\n return getLimitedTaskGroups(suggestedTasks, 3);\n}\n\n/**\n * Get the label for a conversation status\n * @param status The conversation status\n * @returns The localized label for the status\n */\nexport const getConversationStatusLabel = (\n status: ConversationStatus,\n): string => {\n switch (status) {\n case \"STOPPED\":\n return \"COMMON$STOPPED\";\n case \"RUNNING\":\n return \"COMMON$RUNNING\";\n case \"STARTING\":\n return \"COMMON$STARTING\";\n case \"ERROR\":\n return \"COMMON$ERROR\";\n case \"ARCHIVED\":\n return \"COMMON$ARCHIVED\"; // Use STOPPED for archived conversations\n default:\n return \"COMMON$UNKNOWN\";\n }\n};\n\n// Task Tracking Utility Functions\n\n/**\n * Get the status icon for a task status\n * @param status The task status\n * @returns The emoji icon for the status\n */\nexport const getStatusIcon = (status: string) => {\n switch (status) {\n case \"todo\":\n return \"⏳\";\n case \"in_progress\":\n return \"🔄\";\n case \"done\":\n return \"✅\";\n default:\n return \"❓\";\n }\n};\n\n/**\n * Get the CSS class names for a task status badge\n * @param status The task status\n * @returns The CSS class names for styling the status badge\n */\nexport const getStatusClassName = (status: string) => {\n if (status === \"done\") {\n return \"bg-green-800 text-green-200\";\n }\n if (status === \"in_progress\") {\n return \"bg-yellow-800 text-yellow-200\";\n }\n return \"bg-tertiary text-[var(--oh-text-tertiary)]\";\n};\n\n/**\n * Helper function to apply client-side filtering based on search query\n * @param repo The Git repository to check\n * @param searchQuery The search query string\n * @returns True if the repository should be included based on the search query\n */\nexport const shouldIncludeRepository = (\n repo: GitRepository,\n searchQuery: string,\n): boolean => {\n if (!searchQuery.trim()) {\n return true;\n }\n\n const sanitizedQuery = sanitizeQuery(searchQuery);\n const sanitizedRepoName = sanitizeQuery(repo.full_name);\n return sanitizedRepoName.includes(sanitizedQuery);\n};\n\n/**\n * Get the OpenHands query string based on the provider\n * @param provider The git provider\n * @returns The query string for searching OpenHands repositories\n */\nexport const getOpenHandsQuery = (provider: Provider | null): string => {\n const providerRepositorySuffix: Record<string, string> = {\n gitlab: \"openhands-config\",\n azure_devops: \"openhands-config\",\n default: \".openhands\",\n } as const;\n\n return provider && provider in providerRepositorySuffix\n ? providerRepositorySuffix[provider]\n : providerRepositorySuffix.default;\n};\n\n/**\n * Check if a repository has the OpenHands suffix based on the provider\n * @param repo The Git repository to check\n * @param provider The git provider\n * @returns True if the repository has the OpenHands suffix\n */\nexport const hasOpenHandsSuffix = (\n repo: GitRepository,\n provider: Provider | null,\n): boolean => repo.full_name.endsWith(`/${getOpenHandsQuery(provider)}`);\n\n/**\n * Build headers for V1 API requests that require session authentication\n * @param sessionApiKey Session API key for authentication\n * @returns Headers object with X-Session-API-Key if provided\n */\nexport const buildSessionHeaders = (\n sessionApiKey?: string | null,\n): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (sessionApiKey) {\n headers[\"X-Session-API-Key\"] = sessionApiKey;\n }\n return headers;\n};\n\n/**\n * Check if a task is currently being polled (loading state)\n * @param taskStatus The task status string (e.g., \"WORKING\", \"ERROR\", \"READY\")\n * @returns True if the task is in a loading state (not ERROR and not READY)\n *\n * @example\n * isTaskPolling(\"WORKING\") // Returns true\n * isTaskPolling(\"PREPARING_REPOSITORY\") // Returns true\n * isTaskPolling(\"READY\") // Returns false\n * isTaskPolling(\"ERROR\") // Returns false\n * isTaskPolling(null) // Returns false\n * isTaskPolling(undefined) // Returns false\n */\nexport const isTaskPolling = (taskStatus: string | null | undefined): boolean =>\n !!taskStatus && taskStatus !== \"ERROR\" && taskStatus !== \"READY\";\n\n/**\n * Get the appropriate color based on agent status\n * @param options Configuration object for status color calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.isStartingStatus Whether the agent is in a starting state (LOADING or INIT)\n * @param options.isStopStatus Whether the conversation status is STOPPED\n * @param options.curAgentState The current agent state\n * @returns The hex color code for the status\n *\n * @example\n * getStatusColor({\n * isPausing: false,\n * isTask: false,\n * taskStatus: undefined,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"var(--oh-status-success)\"\n */\nexport const getStatusColor = (options: {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n}): string => {\n const {\n isPausing,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n } = options;\n\n // Show pausing status\n if (isPausing) {\n return \"#FFD600\";\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return OH_STATUS_ERROR_COLOR;\n }\n return \"#FFD600\";\n }\n\n if (isStartingStatus) {\n return \"#FFD600\";\n }\n if (isStopStatus) {\n return \"#ffffff\";\n }\n if (curAgentState === AgentState.ERROR) {\n return OH_STATUS_ERROR_COLOR;\n }\n return OH_STATUS_SUCCESS_COLOR;\n};\n\ninterface GetStatusTextArgs {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: AppConversationStartTaskStatus | null;\n taskDetail?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n errorMessage?: string | null;\n t: (t: string) => string;\n}\n\n/**\n * Get the server status text based on agent and task state\n *\n * @param options Configuration object for status text calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.taskDetail Optional task-specific detail text\n * @param options.isStartingStatus Whether the conversation is in STARTING state\n * @param options.isStopStatus Whether the conversation is STOPPED\n * @param options.curAgentState The current agent state\n * @param options.errorMessage Optional agent error message\n * @returns Localized human-readable status text\n *\n * @example\n * getStatusText({\n * isPausing: false,\n * isTask: true,\n * taskStatus: \"STARTING_CONVERSATION\",\n * taskDetail: null,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"Starting conversation\"\n */\nexport function getStatusText({\n isPausing = false,\n isTask,\n taskStatus,\n taskDetail,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n errorMessage,\n t,\n}: GetStatusTextArgs): string {\n // Show pausing status\n if (isPausing) {\n return t(I18nKey.COMMON$STOPPING);\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION);\n }\n\n if (taskStatus === \"READY\") {\n return t(I18nKey.CONVERSATION$READY);\n }\n\n return taskDetail || t(getTaskStatusI18nKey(taskStatus));\n }\n\n if (isStartingStatus) {\n return t(I18nKey.COMMON$STARTING);\n }\n\n if (isStopStatus) {\n return t(I18nKey.COMMON$SERVER_STOPPED);\n }\n\n if (curAgentState === AgentState.ERROR) {\n return errorMessage || t(I18nKey.COMMON$ERROR);\n }\n\n return t(I18nKey.COMMON$RUNNING);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","names":[],"sources":["../../src/utils/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Provider } from \"#/types/settings\";\nimport { SuggestedTaskGroup } from \"#/utils/types\";\nimport { ConversationStatus } from \"#/types/conversation-status\";\nimport { GitRepository } from \"#/types/git\";\nimport { sanitizeQuery } from \"#/utils/sanitize-query\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getTaskStatusI18nKey } from \"#/utils/status\";\nimport type { AppConversationStartTaskStatus } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport {\n OH_STATUS_ERROR_COLOR,\n OH_STATUS_SUCCESS_COLOR,\n} from \"#/constants/status-colors\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Trigger a download for a provided Blob with the given filename\n */\nexport const downloadBlob = (blob: Blob, filename: string): void => {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(url);\n};\n\n/**\n * Get the numeric height value from an element's style property\n * @param el The HTML element to get the height from\n * @param fallback The fallback value to return if style height is invalid\n * @returns The numeric height value in pixels, or the fallback value\n *\n * @example\n * getStyleHeightPx(element, 20) // Returns 20 if element.style.height is \"auto\" or invalid\n * getStyleHeightPx(element, 20) // Returns 100 if element.style.height is \"100px\"\n */\nexport const getStyleHeightPx = (el: HTMLElement, fallback: number): number => {\n const elementHeight = parseFloat(el.style.height || \"\");\n return Number.isFinite(elementHeight) ? elementHeight : fallback;\n};\n\n/**\n * Set the height style property of an element to a specific pixel value\n * @param el The HTML element to set the height for\n * @param height The height value in pixels to set\n *\n * @example\n * setStyleHeightPx(element, 100) // Sets element.style.height to \"100px\"\n * setStyleHeightPx(textarea, 200) // Sets textarea.style.height to \"200px\"\n */\nexport const setStyleHeightPx = (el: HTMLElement, height: number): void => {\n el.style.setProperty(\"height\", `${height}px`);\n};\n\n/**\n * Detect a phone/tablet user agent (Android, iPhone, iPad, …).\n * Unlike isMobileDevice, this ignores touch capability, so a desktop OS with\n * a touchscreen (e.g. a Windows 2-in-1) is NOT matched. Use this when the\n * decision depends on having a physical keyboard rather than on touch input.\n */\nexport const isMobileUserAgent = (): boolean =>\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n\n/**\n * Detect if the user is on a mobile device.\n * Touch support alone is not sufficient — touchscreen laptops have touch\n * but use a mouse/trackpad as primary input. We check that the primary\n * pointing device is coarse (finger) to avoid false positives.\n */\nexport const isMobileDevice = (): boolean => {\n if (isMobileUserAgent()) return true;\n\n const hasTouch = \"ontouchstart\" in window || navigator.maxTouchPoints > 0;\n if (!hasTouch) return false;\n\n // If matchMedia is available, check whether the primary pointer is fine\n // (mouse/trackpad). Touchscreen laptops report fine, real mobile devices don't.\n if (typeof window.matchMedia === \"function\") {\n return !window.matchMedia(\"(pointer: fine)\").matches;\n }\n\n // Fallback: touch present but no matchMedia — assume mobile\n return true;\n};\n\n/**\n * Checks if the current domain is the production domain\n * @returns True if the current domain matches the production URL\n */\nexport const isProductionDomain = (): boolean =>\n window.location.origin === PRODUCT_URL.PRODUCTION;\n\ninterface EventActionHistory {\n args?: {\n LLM_API_KEY?: string;\n [key: string]: unknown;\n };\n extras?: {\n open_page_urls: string[];\n active_page_index: number;\n dom_object: Record<string, unknown>;\n axtree_object: Record<string, unknown>;\n extra_element_properties: Record<string, unknown>;\n last_browser_action: string;\n last_browser_action_error: unknown;\n focused_element_bid: string;\n };\n [key: string]: unknown;\n}\n\nexport const removeUnwantedKeys = (\n data: EventActionHistory[],\n): EventActionHistory[] => {\n const UNDESIRED_KEYS = [\n \"open_page_urls\",\n \"active_page_index\",\n \"dom_object\",\n \"axtree_object\",\n \"extra_element_properties\",\n \"last_browser_action\",\n \"last_browser_action_error\",\n \"focused_element_bid\",\n ];\n\n return data\n .filter((item) => {\n // Skip items that have a status key\n if (\"status\" in item) {\n return false;\n }\n return true;\n })\n .map((item) => {\n // Create a shallow copy of item\n const newItem = { ...item };\n\n // Check if extras exists and delete it from a new extras object\n if (newItem.extras) {\n const newExtras = { ...newItem.extras };\n UNDESIRED_KEYS.forEach((key) => {\n delete newExtras[key as keyof typeof newExtras];\n });\n newItem.extras = newExtras;\n }\n\n return newItem;\n });\n};\n\n/**\n * Get file extension from file name in uppercase format\n * @param fileName The file name to extract extension from\n * @returns The file extension in uppercase, or \"FILE\" if no extension found\n *\n * @example\n * getFileExtension(\"document.pdf\") // \"PDF\"\n * getFileExtension(\"image.jpeg\") // \"JPEG\"\n * getFileExtension(\"noextension\") // \"FILE\"\n */\nexport const getFileExtension = (fileName: string): string => {\n const extension = fileName.split(\".\").pop()?.toUpperCase();\n return extension || \"FILE\";\n};\n\n/**\n * Whether to use the installation-scoped repo flow\n * (`/api/v1/git/installations/search` → `/api/v1/git/repositories/search?installation_id=…`)\n * for the given provider/backend combo.\n *\n * Mirrors OpenHands' cloud frontend (parameterized by `app_mode`):\n * - bitbucket / bitbucket_data_center → always installation-based\n * - github → installation-based ONLY when the active backend is cloud\n * - gitlab / azure_devops / forgejo → direct (search) flow\n *\n * `appMode` accepts the active backend `kind` (\"local\" | \"cloud\") so call\n * sites can hand it through directly.\n */\nexport const shouldUseInstallationRepos = (\n provider: Provider | null | undefined,\n appMode?: \"local\" | \"cloud\",\n) => {\n if (!provider) return false;\n\n switch (provider) {\n case \"bitbucket\":\n case \"bitbucket_data_center\":\n return true;\n case \"github\":\n return appMode === \"cloud\";\n default:\n return false;\n }\n};\n\nexport const getGitProviderBaseUrl = (\n gitProvider: Provider,\n host?: string | null,\n): string => {\n // If custom host provided, use it (with https:// prefix if needed)\n if (host && host.trim() !== \"\") {\n return host.startsWith(\"http\") ? host : `https://${host}`;\n }\n\n // Fall back to defaults\n switch (gitProvider) {\n case \"github\":\n return \"https://github.com\";\n case \"gitlab\":\n return \"https://gitlab.com\";\n case \"bitbucket\":\n return \"https://bitbucket.org\";\n case \"azure_devops\":\n return \"https://dev.azure.com\";\n case \"forgejo\":\n // Default UI links to Codeberg unless a custom host is available in settings\n // Note: UI link builders don't currently receive host; consider plumbing settings if needed\n return \"https://codeberg.org\";\n default:\n return \"\";\n }\n};\n\n/**\n * Get the name of the git provider\n * @param gitProvider The git provider\n * @returns The name of the git provider\n */\nexport const getProviderName = (gitProvider: Provider) => {\n if (gitProvider === \"gitlab\") return \"GitLab\";\n if (gitProvider === \"bitbucket\") return \"Bitbucket\";\n if (gitProvider === \"bitbucket_data_center\") return \"Bitbucket Data Center\";\n if (gitProvider === \"azure_devops\") return \"Azure DevOps\";\n if (gitProvider === \"forgejo\") return \"Forgejo\";\n return \"GitHub\";\n};\n\n/**\n * Get the name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The name of the PR\n */\nexport const getPR = (isGitLab: boolean) =>\n isGitLab ? \"merge request\" : \"pull request\";\n\n/**\n * Get the short name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The short name of the PR\n */\nexport const getPRShort = (isGitLab: boolean) => (isGitLab ? \"MR\" : \"PR\");\n\n/**\n * Construct the pull request (merge request) URL for different providers\n * @param prNumber The pull request number\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The pull request URL\n *\n * @example\n * constructPullRequestUrl(123, \"github\", \"owner/repo\") // \"https://github.com/owner/repo/pull/123\"\n * constructPullRequestUrl(456, \"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo/-/merge_requests/456\"\n * constructPullRequestUrl(789, \"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo/pull-requests/789\"\n * constructPullRequestUrl(789, \"bitbucket\", \"PROJECT/repo\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/pull-requests/789\"\n */\nexport const constructPullRequestUrl = (\n prNumber: number,\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/merge_requests/${prNumber}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/pull-requests/${prNumber}`;\n case \"bitbucket_data_center\": {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}/pull-requests/${prNumber}`;\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}/pullrequest/${prNumber}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n/**\n * Construct the repository URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The repository URL\n *\n * @example\n * constructRepositoryUrl(\"github\", \"owner/repo\") // \"https://github.com/owner/repo\"\n * constructRepositoryUrl(\"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo\"\n * constructRepositoryUrl(\"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo\"\n */\nexport const constructRepositoryUrl = (\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n if (provider === \"bitbucket_data_center\") {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}`;\n }\n return `${baseUrl}/${repositoryName}`;\n};\n\n/**\n * Percent-encode a branch name for use as a URL path component. Each\n * `/`-separated segment is encoded on its own so nested branch names such as\n * `release/1.0` keep their slashes while `#`, `%` and `&` are escaped.\n */\nconst encodeBranchPath = (branchName: string): string =>\n branchName.split(\"/\").map(encodeURIComponent).join(\"/\");\n\n/**\n * Construct the branch URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @param branchName The branch name\n * @param host Optional custom host for self-hosted instances\n * @returns The branch URL\n *\n * @example\n * constructBranchUrl(\"github\", \"owner/repo\", \"main\") // \"https://github.com/owner/repo/tree/main\"\n * constructBranchUrl(\"gitlab\", \"owner/repo\", \"develop\") // \"https://gitlab.com/owner/repo/-/tree/develop\"\n * constructBranchUrl(\"bitbucket\", \"owner/repo\", \"feature\") // \"https://bitbucket.org/owner/repo/src/feature\"\n * constructBranchUrl(\"bitbucket\", \"PROJECT/repo\", \"feature\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/browse?at=refs/heads/feature\"\n */\nexport const constructBranchUrl = (\n provider: Provider,\n repositoryName: string,\n branchName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/tree/${encodeBranchPath(branchName)}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/src/branch/${encodeBranchPath(branchName)}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/tree/${encodeBranchPath(branchName)}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/src/${encodeBranchPath(branchName)}`;\n case \"bitbucket_data_center\": {\n // Bitbucket Server format: /projects/{PROJECT}/repos/{repo}/browse?at=refs/heads/{branch}\n const parts = repositoryName.split(\"/\");\n if (parts.length >= 2) {\n const [project, repo] = parts;\n // The branch is one query value here, so encode it whole: an\n // unencoded `&` would start a new query parameter.\n return `${baseUrl}/projects/${project}/repos/${repo}/browse?at=refs/heads/${encodeURIComponent(branchName)}`;\n }\n return \"\";\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n // The branch is one query value here, so encode it whole: an\n // unencoded `&` would start a new query parameter.\n return `${baseUrl}/${org}/${project}/_git/${repo}?version=GB${encodeURIComponent(branchName)}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n// Git Action Prompts\n\nconst GIT_COMMIT_PROMPT =\n \"Please review the current changes and create a git commit with a concise, descriptive message.\";\n\nexport const getGitCommitPrompt = (): string => GIT_COMMIT_PROMPT;\n\n/**\n * Generate a git pull prompt\n * @returns The git pull prompt\n */\nexport const getGitPullPrompt = (): string =>\n \"Please pull the latest code from the repository.\";\n\n/**\n * Generate a git push prompt\n * @param gitProvider The git provider\n * @returns The git push prompt\n */\nexport const getGitPushPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the changes to a remote branch on ${providerName}, but do NOT create a ${pr}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`;\n};\n\n/**\n * Generate a create pull request prompt\n * @param gitProvider The git provider\n * @returns The create PR prompt\n */\nexport const getCreatePRPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n const prShort = getPRShort(gitProvider === \"gitlab\");\n\n return `Please push the changes to ${providerName} and open a ${pr}. If you're on a default branch (e.g., main, master, deploy), create a new branch with a descriptive name otherwise use the current branch. If a ${pr} template exists in the repository, please follow it when creating the ${prShort} description.`;\n};\n\n/**\n * Generate a push to existing PR prompt\n * @param gitProvider The git provider\n * @returns The push to PR prompt\n */\nexport const getPushToPRPrompt = (gitProvider: Provider): string => {\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the latest changes to the existing ${pr}.`;\n};\n\n/**\n * Generate a create new branch prompt\n * @returns The create new branch prompt\n */\nexport const getCreateNewBranchPrompt = (): string =>\n \"Please create a new branch with a descriptive name related to the work you plan to do.\";\n\n// Helper functions\nexport function getTotalTaskCount(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n): number {\n if (!suggestedTasks) return 0;\n return suggestedTasks.flatMap((group) => group.tasks).length;\n}\n\nexport function getLimitedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[],\n maxTasks: number,\n): SuggestedTaskGroup[] {\n const limitedGroups: SuggestedTaskGroup[] = [];\n let taskCount = 0;\n\n for (const group of suggestedTasks) {\n if (taskCount >= maxTasks) break;\n\n const remainingTasksNeeded = maxTasks - taskCount;\n const tasksToShow = group.tasks.slice(0, remainingTasksNeeded);\n\n if (tasksToShow.length > 0) {\n limitedGroups.push({\n ...group,\n tasks: tasksToShow,\n });\n taskCount += tasksToShow.length;\n }\n }\n\n return limitedGroups;\n}\n\nexport function getDisplayedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n isExpanded: boolean,\n): SuggestedTaskGroup[] {\n if (!suggestedTasks || suggestedTasks.length === 0) {\n return [];\n }\n\n if (isExpanded) {\n return suggestedTasks;\n }\n\n return getLimitedTaskGroups(suggestedTasks, 3);\n}\n\n/**\n * Get the label for a conversation status\n * @param status The conversation status\n * @returns The localized label for the status\n */\nexport const getConversationStatusLabel = (\n status: ConversationStatus,\n): string => {\n switch (status) {\n case \"STOPPED\":\n return \"COMMON$STOPPED\";\n case \"RUNNING\":\n return \"COMMON$RUNNING\";\n case \"STARTING\":\n return \"COMMON$STARTING\";\n case \"ERROR\":\n return \"COMMON$ERROR\";\n case \"ARCHIVED\":\n return \"COMMON$ARCHIVED\"; // Use STOPPED for archived conversations\n default:\n return \"COMMON$UNKNOWN\";\n }\n};\n\n// Task Tracking Utility Functions\n\n/**\n * Get the status icon for a task status\n * @param status The task status\n * @returns The emoji icon for the status\n */\nexport const getStatusIcon = (status: string) => {\n switch (status) {\n case \"todo\":\n return \"⏳\";\n case \"in_progress\":\n return \"🔄\";\n case \"done\":\n return \"✅\";\n default:\n return \"❓\";\n }\n};\n\n/**\n * Get the CSS class names for a task status badge\n * @param status The task status\n * @returns The CSS class names for styling the status badge\n */\nexport const getStatusClassName = (status: string) => {\n if (status === \"done\") {\n return \"bg-green-800 text-green-200\";\n }\n if (status === \"in_progress\") {\n return \"bg-yellow-800 text-yellow-200\";\n }\n return \"bg-tertiary text-[var(--oh-text-tertiary)]\";\n};\n\n/**\n * Helper function to apply client-side filtering based on search query\n * @param repo The Git repository to check\n * @param searchQuery The search query string\n * @returns True if the repository should be included based on the search query\n */\nexport const shouldIncludeRepository = (\n repo: GitRepository,\n searchQuery: string,\n): boolean => {\n if (!searchQuery.trim()) {\n return true;\n }\n\n const sanitizedQuery = sanitizeQuery(searchQuery);\n const sanitizedRepoName = sanitizeQuery(repo.full_name);\n return sanitizedRepoName.includes(sanitizedQuery);\n};\n\n/**\n * Get the OpenHands query string based on the provider\n * @param provider The git provider\n * @returns The query string for searching OpenHands repositories\n */\nexport const getOpenHandsQuery = (provider: Provider | null): string => {\n const providerRepositorySuffix: Record<string, string> = {\n gitlab: \"openhands-config\",\n azure_devops: \"openhands-config\",\n default: \".openhands\",\n } as const;\n\n return provider && provider in providerRepositorySuffix\n ? providerRepositorySuffix[provider]\n : providerRepositorySuffix.default;\n};\n\n/**\n * Check if a repository has the OpenHands suffix based on the provider\n * @param repo The Git repository to check\n * @param provider The git provider\n * @returns True if the repository has the OpenHands suffix\n */\nexport const hasOpenHandsSuffix = (\n repo: GitRepository,\n provider: Provider | null,\n): boolean => repo.full_name.endsWith(`/${getOpenHandsQuery(provider)}`);\n\n/**\n * Build headers for V1 API requests that require session authentication\n * @param sessionApiKey Session API key for authentication\n * @returns Headers object with X-Session-API-Key if provided\n */\nexport const buildSessionHeaders = (\n sessionApiKey?: string | null,\n): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (sessionApiKey) {\n headers[\"X-Session-API-Key\"] = sessionApiKey;\n }\n return headers;\n};\n\n/**\n * Check if a task is currently being polled (loading state)\n * @param taskStatus The task status string (e.g., \"WORKING\", \"ERROR\", \"READY\")\n * @returns True if the task is in a loading state (not ERROR and not READY)\n *\n * @example\n * isTaskPolling(\"WORKING\") // Returns true\n * isTaskPolling(\"PREPARING_REPOSITORY\") // Returns true\n * isTaskPolling(\"READY\") // Returns false\n * isTaskPolling(\"ERROR\") // Returns false\n * isTaskPolling(null) // Returns false\n * isTaskPolling(undefined) // Returns false\n */\nexport const isTaskPolling = (taskStatus: string | null | undefined): boolean =>\n !!taskStatus && taskStatus !== \"ERROR\" && taskStatus !== \"READY\";\n\n/**\n * Get the appropriate color based on agent status\n * @param options Configuration object for status color calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.isStartingStatus Whether the agent is in a starting state (LOADING or INIT)\n * @param options.isStopStatus Whether the conversation status is STOPPED\n * @param options.curAgentState The current agent state\n * @returns The hex color code for the status\n *\n * @example\n * getStatusColor({\n * isPausing: false,\n * isTask: false,\n * taskStatus: undefined,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"var(--oh-status-success)\"\n */\nexport const getStatusColor = (options: {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n}): string => {\n const {\n isPausing,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n } = options;\n\n // Show pausing status\n if (isPausing) {\n return \"#FFD600\";\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return OH_STATUS_ERROR_COLOR;\n }\n return \"#FFD600\";\n }\n\n if (isStartingStatus) {\n return \"#FFD600\";\n }\n if (isStopStatus) {\n return \"#ffffff\";\n }\n if (curAgentState === AgentState.ERROR) {\n return OH_STATUS_ERROR_COLOR;\n }\n return OH_STATUS_SUCCESS_COLOR;\n};\n\ninterface GetStatusTextArgs {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: AppConversationStartTaskStatus | null;\n taskDetail?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n errorMessage?: string | null;\n t: (t: string) => string;\n}\n\n/**\n * Get the server status text based on agent and task state\n *\n * @param options Configuration object for status text calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.taskDetail Optional task-specific detail text\n * @param options.isStartingStatus Whether the conversation is in STARTING state\n * @param options.isStopStatus Whether the conversation is STOPPED\n * @param options.curAgentState The current agent state\n * @param options.errorMessage Optional agent error message\n * @returns Localized human-readable status text\n *\n * @example\n * getStatusText({\n * isPausing: false,\n * isTask: true,\n * taskStatus: \"STARTING_CONVERSATION\",\n * taskDetail: null,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"Starting conversation\"\n */\nexport function getStatusText({\n isPausing = false,\n isTask,\n taskStatus,\n taskDetail,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n errorMessage,\n t,\n}: GetStatusTextArgs): string {\n // Show pausing status\n if (isPausing) {\n return t(I18nKey.COMMON$STOPPING);\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION);\n }\n\n if (taskStatus === \"READY\") {\n return t(I18nKey.CONVERSATION$READY);\n }\n\n return taskDetail || t(getTaskStatusI18nKey(taskStatus));\n }\n\n if (isStartingStatus) {\n return t(I18nKey.COMMON$STARTING);\n }\n\n if (isStopStatus) {\n return t(I18nKey.COMMON$SERVER_STOPPED);\n }\n\n if (curAgentState === AgentState.ERROR) {\n return errorMessage || t(I18nKey.COMMON$ERROR);\n }\n\n return t(I18nKey.COMMON$RUNNING);\n}\n"],"mappings":"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"}
@@ -62,18 +62,18 @@ var c = (e, t) => {
62
62
  return `${r}/projects/${e}/repos/${n}`;
63
63
  }
64
64
  return `${r}/${t}`;
65
- }, x = (e, t, n, r) => {
65
+ }, x = (e) => e.split("/").map(encodeURIComponent).join("/"), S = (e, t, n, r) => {
66
66
  let i = h(e, r);
67
67
  switch (e) {
68
- case "github": return `${i}/${t}/tree/${n}`;
69
- case "forgejo": return `${i}/${t}/src/branch/${n}`;
70
- case "gitlab": return `${i}/${t}/-/tree/${n}`;
71
- case "bitbucket": return `${i}/${t}/src/${n}`;
68
+ case "github": return `${i}/${t}/tree/${x(n)}`;
69
+ case "forgejo": return `${i}/${t}/src/branch/${x(n)}`;
70
+ case "gitlab": return `${i}/${t}/-/tree/${x(n)}`;
71
+ case "bitbucket": return `${i}/${t}/src/${x(n)}`;
72
72
  case "bitbucket_data_center": {
73
73
  let e = t.split("/");
74
74
  if (e.length >= 2) {
75
75
  let [t, r] = e;
76
- return `${i}/projects/${t}/repos/${r}/browse?at=refs/heads/${n}`;
76
+ return `${i}/projects/${t}/repos/${r}/browse?at=refs/heads/${encodeURIComponent(n)}`;
77
77
  }
78
78
  return "";
79
79
  }
@@ -81,23 +81,23 @@ var c = (e, t) => {
81
81
  let e = t.split("/");
82
82
  if (e.length === 3) {
83
83
  let [t, r, a] = e;
84
- return `${i}/${t}/${r}/_git/${a}?version=GB${n}`;
84
+ return `${i}/${t}/${r}/_git/${a}?version=GB${encodeURIComponent(n)}`;
85
85
  }
86
86
  return "";
87
87
  }
88
88
  default: return "";
89
89
  }
90
- }, S = "Please review the current changes and create a git commit with a concise, descriptive message.", C = () => S, w = () => "Please pull the latest code from the repository.", T = (e) => `Please push the changes to a remote branch on ${g(e)}, but do NOT create a ${_(e === "gitlab")}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`, E = (e) => {
90
+ }, C = "Please review the current changes and create a git commit with a concise, descriptive message.", w = () => C, T = () => "Please pull the latest code from the repository.", E = (e) => `Please push the changes to a remote branch on ${g(e)}, but do NOT create a ${_(e === "gitlab")}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`, D = (e) => {
91
91
  let t = g(e), n = _(e === "gitlab");
92
92
  return `Please push the changes to ${t} and open a ${n}. If you're on a default branch (e.g., main, master, deploy), create a new branch with a descriptive name otherwise use the current branch. If a ${n} template exists in the repository, please follow it when creating the ${v(e === "gitlab")} description.`;
93
- }, D = () => "Please create a new branch with a descriptive name related to the work you plan to do.", O = (e) => !!e && e !== "ERROR" && e !== "READY", k = (e) => {
93
+ }, O = () => "Please create a new branch with a descriptive name related to the work you plan to do.", k = (e) => !!e && e !== "ERROR" && e !== "READY", A = (e) => {
94
94
  let { isPausing: t, isTask: n, taskStatus: i, isStartingStatus: s, isStopStatus: c, curAgentState: l } = e;
95
95
  return t ? "#FFD600" : n && i ? i === "ERROR" ? a : "#FFD600" : s ? "#FFD600" : c ? "#ffffff" : l === r.ERROR ? a : o;
96
96
  };
97
- function A({ isPausing: t = !1, isTask: n, taskStatus: a, taskDetail: o, isStartingStatus: s, isStopStatus: c, curAgentState: l, errorMessage: u, t: d }) {
97
+ function j({ isPausing: t = !1, isTask: n, taskStatus: a, taskDetail: o, isStartingStatus: s, isStopStatus: c, curAgentState: l, errorMessage: u, t: d }) {
98
98
  return t ? d(e.COMMON$STOPPING) : n && a ? a === "ERROR" ? o || d(e.CONVERSATION$ERROR_STARTING_CONVERSATION) : a === "READY" ? d(e.CONVERSATION$READY) : o || d(i(a)) : s ? d(e.COMMON$STARTING) : c ? d(e.COMMON$SERVER_STOPPED) : l === r.ERROR ? u || d(e.COMMON$ERROR) : d(e.COMMON$RUNNING);
99
99
  }
100
100
  //#endregion
101
- export { s as cn, x as constructBranchUrl, y as constructPullRequestUrl, b as constructRepositoryUrl, c as downloadBlob, D as getCreateNewBranchPrompt, E as getCreatePRPrompt, p as getFileExtension, C as getGitCommitPrompt, h as getGitProviderBaseUrl, w as getGitPullPrompt, T as getGitPushPrompt, g as getProviderName, k as getStatusColor, A as getStatusText, l as getStyleHeightPx, f as isMobileDevice, d as isMobileUserAgent, O as isTaskPolling, u as setStyleHeightPx, m as shouldUseInstallationRepos };
101
+ export { s as cn, S as constructBranchUrl, y as constructPullRequestUrl, b as constructRepositoryUrl, c as downloadBlob, O as getCreateNewBranchPrompt, D as getCreatePRPrompt, p as getFileExtension, w as getGitCommitPrompt, h as getGitProviderBaseUrl, T as getGitPullPrompt, E as getGitPushPrompt, g as getProviderName, A as getStatusColor, j as getStatusText, l as getStyleHeightPx, f as isMobileDevice, d as isMobileUserAgent, k as isTaskPolling, u as setStyleHeightPx, m as shouldUseInstallationRepos };
102
102
 
103
103
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../src/utils/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Provider } from \"#/types/settings\";\nimport { SuggestedTaskGroup } from \"#/utils/types\";\nimport { ConversationStatus } from \"#/types/conversation-status\";\nimport { GitRepository } from \"#/types/git\";\nimport { sanitizeQuery } from \"#/utils/sanitize-query\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getTaskStatusI18nKey } from \"#/utils/status\";\nimport type { AppConversationStartTaskStatus } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport {\n OH_STATUS_ERROR_COLOR,\n OH_STATUS_SUCCESS_COLOR,\n} from \"#/constants/status-colors\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Trigger a download for a provided Blob with the given filename\n */\nexport const downloadBlob = (blob: Blob, filename: string): void => {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(url);\n};\n\n/**\n * Get the numeric height value from an element's style property\n * @param el The HTML element to get the height from\n * @param fallback The fallback value to return if style height is invalid\n * @returns The numeric height value in pixels, or the fallback value\n *\n * @example\n * getStyleHeightPx(element, 20) // Returns 20 if element.style.height is \"auto\" or invalid\n * getStyleHeightPx(element, 20) // Returns 100 if element.style.height is \"100px\"\n */\nexport const getStyleHeightPx = (el: HTMLElement, fallback: number): number => {\n const elementHeight = parseFloat(el.style.height || \"\");\n return Number.isFinite(elementHeight) ? elementHeight : fallback;\n};\n\n/**\n * Set the height style property of an element to a specific pixel value\n * @param el The HTML element to set the height for\n * @param height The height value in pixels to set\n *\n * @example\n * setStyleHeightPx(element, 100) // Sets element.style.height to \"100px\"\n * setStyleHeightPx(textarea, 200) // Sets textarea.style.height to \"200px\"\n */\nexport const setStyleHeightPx = (el: HTMLElement, height: number): void => {\n el.style.setProperty(\"height\", `${height}px`);\n};\n\n/**\n * Detect a phone/tablet user agent (Android, iPhone, iPad, …).\n * Unlike isMobileDevice, this ignores touch capability, so a desktop OS with\n * a touchscreen (e.g. a Windows 2-in-1) is NOT matched. Use this when the\n * decision depends on having a physical keyboard rather than on touch input.\n */\nexport const isMobileUserAgent = (): boolean =>\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n\n/**\n * Detect if the user is on a mobile device.\n * Touch support alone is not sufficient — touchscreen laptops have touch\n * but use a mouse/trackpad as primary input. We check that the primary\n * pointing device is coarse (finger) to avoid false positives.\n */\nexport const isMobileDevice = (): boolean => {\n if (isMobileUserAgent()) return true;\n\n const hasTouch = \"ontouchstart\" in window || navigator.maxTouchPoints > 0;\n if (!hasTouch) return false;\n\n // If matchMedia is available, check whether the primary pointer is fine\n // (mouse/trackpad). Touchscreen laptops report fine, real mobile devices don't.\n if (typeof window.matchMedia === \"function\") {\n return !window.matchMedia(\"(pointer: fine)\").matches;\n }\n\n // Fallback: touch present but no matchMedia — assume mobile\n return true;\n};\n\n/**\n * Checks if the current domain is the production domain\n * @returns True if the current domain matches the production URL\n */\nexport const isProductionDomain = (): boolean =>\n window.location.origin === PRODUCT_URL.PRODUCTION;\n\ninterface EventActionHistory {\n args?: {\n LLM_API_KEY?: string;\n [key: string]: unknown;\n };\n extras?: {\n open_page_urls: string[];\n active_page_index: number;\n dom_object: Record<string, unknown>;\n axtree_object: Record<string, unknown>;\n extra_element_properties: Record<string, unknown>;\n last_browser_action: string;\n last_browser_action_error: unknown;\n focused_element_bid: string;\n };\n [key: string]: unknown;\n}\n\nexport const removeUnwantedKeys = (\n data: EventActionHistory[],\n): EventActionHistory[] => {\n const UNDESIRED_KEYS = [\n \"open_page_urls\",\n \"active_page_index\",\n \"dom_object\",\n \"axtree_object\",\n \"extra_element_properties\",\n \"last_browser_action\",\n \"last_browser_action_error\",\n \"focused_element_bid\",\n ];\n\n return data\n .filter((item) => {\n // Skip items that have a status key\n if (\"status\" in item) {\n return false;\n }\n return true;\n })\n .map((item) => {\n // Create a shallow copy of item\n const newItem = { ...item };\n\n // Check if extras exists and delete it from a new extras object\n if (newItem.extras) {\n const newExtras = { ...newItem.extras };\n UNDESIRED_KEYS.forEach((key) => {\n delete newExtras[key as keyof typeof newExtras];\n });\n newItem.extras = newExtras;\n }\n\n return newItem;\n });\n};\n\n/**\n * Get file extension from file name in uppercase format\n * @param fileName The file name to extract extension from\n * @returns The file extension in uppercase, or \"FILE\" if no extension found\n *\n * @example\n * getFileExtension(\"document.pdf\") // \"PDF\"\n * getFileExtension(\"image.jpeg\") // \"JPEG\"\n * getFileExtension(\"noextension\") // \"FILE\"\n */\nexport const getFileExtension = (fileName: string): string => {\n const extension = fileName.split(\".\").pop()?.toUpperCase();\n return extension || \"FILE\";\n};\n\n/**\n * Whether to use the installation-scoped repo flow\n * (`/api/v1/git/installations/search` → `/api/v1/git/repositories/search?installation_id=…`)\n * for the given provider/backend combo.\n *\n * Mirrors OpenHands' cloud frontend (parameterized by `app_mode`):\n * - bitbucket / bitbucket_data_center → always installation-based\n * - github → installation-based ONLY when the active backend is cloud\n * - gitlab / azure_devops / forgejo → direct (search) flow\n *\n * `appMode` accepts the active backend `kind` (\"local\" | \"cloud\") so call\n * sites can hand it through directly.\n */\nexport const shouldUseInstallationRepos = (\n provider: Provider | null | undefined,\n appMode?: \"local\" | \"cloud\",\n) => {\n if (!provider) return false;\n\n switch (provider) {\n case \"bitbucket\":\n case \"bitbucket_data_center\":\n return true;\n case \"github\":\n return appMode === \"cloud\";\n default:\n return false;\n }\n};\n\nexport const getGitProviderBaseUrl = (\n gitProvider: Provider,\n host?: string | null,\n): string => {\n // If custom host provided, use it (with https:// prefix if needed)\n if (host && host.trim() !== \"\") {\n return host.startsWith(\"http\") ? host : `https://${host}`;\n }\n\n // Fall back to defaults\n switch (gitProvider) {\n case \"github\":\n return \"https://github.com\";\n case \"gitlab\":\n return \"https://gitlab.com\";\n case \"bitbucket\":\n return \"https://bitbucket.org\";\n case \"azure_devops\":\n return \"https://dev.azure.com\";\n case \"forgejo\":\n // Default UI links to Codeberg unless a custom host is available in settings\n // Note: UI link builders don't currently receive host; consider plumbing settings if needed\n return \"https://codeberg.org\";\n default:\n return \"\";\n }\n};\n\n/**\n * Get the name of the git provider\n * @param gitProvider The git provider\n * @returns The name of the git provider\n */\nexport const getProviderName = (gitProvider: Provider) => {\n if (gitProvider === \"gitlab\") return \"GitLab\";\n if (gitProvider === \"bitbucket\") return \"Bitbucket\";\n if (gitProvider === \"bitbucket_data_center\") return \"Bitbucket Data Center\";\n if (gitProvider === \"azure_devops\") return \"Azure DevOps\";\n if (gitProvider === \"forgejo\") return \"Forgejo\";\n return \"GitHub\";\n};\n\n/**\n * Get the name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The name of the PR\n */\nexport const getPR = (isGitLab: boolean) =>\n isGitLab ? \"merge request\" : \"pull request\";\n\n/**\n * Get the short name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The short name of the PR\n */\nexport const getPRShort = (isGitLab: boolean) => (isGitLab ? \"MR\" : \"PR\");\n\n/**\n * Construct the pull request (merge request) URL for different providers\n * @param prNumber The pull request number\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The pull request URL\n *\n * @example\n * constructPullRequestUrl(123, \"github\", \"owner/repo\") // \"https://github.com/owner/repo/pull/123\"\n * constructPullRequestUrl(456, \"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo/-/merge_requests/456\"\n * constructPullRequestUrl(789, \"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo/pull-requests/789\"\n * constructPullRequestUrl(789, \"bitbucket\", \"PROJECT/repo\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/pull-requests/789\"\n */\nexport const constructPullRequestUrl = (\n prNumber: number,\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/merge_requests/${prNumber}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/pull-requests/${prNumber}`;\n case \"bitbucket_data_center\": {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}/pull-requests/${prNumber}`;\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}/pullrequest/${prNumber}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n/**\n * Construct the repository URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The repository URL\n *\n * @example\n * constructRepositoryUrl(\"github\", \"owner/repo\") // \"https://github.com/owner/repo\"\n * constructRepositoryUrl(\"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo\"\n * constructRepositoryUrl(\"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo\"\n */\nexport const constructRepositoryUrl = (\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n if (provider === \"bitbucket_data_center\") {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}`;\n }\n return `${baseUrl}/${repositoryName}`;\n};\n\n/**\n * Construct the branch URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @param branchName The branch name\n * @param host Optional custom host for self-hosted instances\n * @returns The branch URL\n *\n * @example\n * constructBranchUrl(\"github\", \"owner/repo\", \"main\") // \"https://github.com/owner/repo/tree/main\"\n * constructBranchUrl(\"gitlab\", \"owner/repo\", \"develop\") // \"https://gitlab.com/owner/repo/-/tree/develop\"\n * constructBranchUrl(\"bitbucket\", \"owner/repo\", \"feature\") // \"https://bitbucket.org/owner/repo/src/feature\"\n * constructBranchUrl(\"bitbucket\", \"PROJECT/repo\", \"feature\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/browse?at=refs/heads/feature\"\n */\nexport const constructBranchUrl = (\n provider: Provider,\n repositoryName: string,\n branchName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/tree/${branchName}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/src/branch/${branchName}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/tree/${branchName}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/src/${branchName}`;\n case \"bitbucket_data_center\": {\n // Bitbucket Server format: /projects/{PROJECT}/repos/{repo}/browse?at=refs/heads/{branch}\n const parts = repositoryName.split(\"/\");\n if (parts.length >= 2) {\n const [project, repo] = parts;\n return `${baseUrl}/projects/${project}/repos/${repo}/browse?at=refs/heads/${branchName}`;\n }\n return \"\";\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}?version=GB${branchName}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n// Git Action Prompts\n\nconst GIT_COMMIT_PROMPT =\n \"Please review the current changes and create a git commit with a concise, descriptive message.\";\n\nexport const getGitCommitPrompt = (): string => GIT_COMMIT_PROMPT;\n\n/**\n * Generate a git pull prompt\n * @returns The git pull prompt\n */\nexport const getGitPullPrompt = (): string =>\n \"Please pull the latest code from the repository.\";\n\n/**\n * Generate a git push prompt\n * @param gitProvider The git provider\n * @returns The git push prompt\n */\nexport const getGitPushPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the changes to a remote branch on ${providerName}, but do NOT create a ${pr}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`;\n};\n\n/**\n * Generate a create pull request prompt\n * @param gitProvider The git provider\n * @returns The create PR prompt\n */\nexport const getCreatePRPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n const prShort = getPRShort(gitProvider === \"gitlab\");\n\n return `Please push the changes to ${providerName} and open a ${pr}. If you're on a default branch (e.g., main, master, deploy), create a new branch with a descriptive name otherwise use the current branch. If a ${pr} template exists in the repository, please follow it when creating the ${prShort} description.`;\n};\n\n/**\n * Generate a push to existing PR prompt\n * @param gitProvider The git provider\n * @returns The push to PR prompt\n */\nexport const getPushToPRPrompt = (gitProvider: Provider): string => {\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the latest changes to the existing ${pr}.`;\n};\n\n/**\n * Generate a create new branch prompt\n * @returns The create new branch prompt\n */\nexport const getCreateNewBranchPrompt = (): string =>\n \"Please create a new branch with a descriptive name related to the work you plan to do.\";\n\n// Helper functions\nexport function getTotalTaskCount(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n): number {\n if (!suggestedTasks) return 0;\n return suggestedTasks.flatMap((group) => group.tasks).length;\n}\n\nexport function getLimitedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[],\n maxTasks: number,\n): SuggestedTaskGroup[] {\n const limitedGroups: SuggestedTaskGroup[] = [];\n let taskCount = 0;\n\n for (const group of suggestedTasks) {\n if (taskCount >= maxTasks) break;\n\n const remainingTasksNeeded = maxTasks - taskCount;\n const tasksToShow = group.tasks.slice(0, remainingTasksNeeded);\n\n if (tasksToShow.length > 0) {\n limitedGroups.push({\n ...group,\n tasks: tasksToShow,\n });\n taskCount += tasksToShow.length;\n }\n }\n\n return limitedGroups;\n}\n\nexport function getDisplayedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n isExpanded: boolean,\n): SuggestedTaskGroup[] {\n if (!suggestedTasks || suggestedTasks.length === 0) {\n return [];\n }\n\n if (isExpanded) {\n return suggestedTasks;\n }\n\n return getLimitedTaskGroups(suggestedTasks, 3);\n}\n\n/**\n * Get the label for a conversation status\n * @param status The conversation status\n * @returns The localized label for the status\n */\nexport const getConversationStatusLabel = (\n status: ConversationStatus,\n): string => {\n switch (status) {\n case \"STOPPED\":\n return \"COMMON$STOPPED\";\n case \"RUNNING\":\n return \"COMMON$RUNNING\";\n case \"STARTING\":\n return \"COMMON$STARTING\";\n case \"ERROR\":\n return \"COMMON$ERROR\";\n case \"ARCHIVED\":\n return \"COMMON$ARCHIVED\"; // Use STOPPED for archived conversations\n default:\n return \"COMMON$UNKNOWN\";\n }\n};\n\n// Task Tracking Utility Functions\n\n/**\n * Get the status icon for a task status\n * @param status The task status\n * @returns The emoji icon for the status\n */\nexport const getStatusIcon = (status: string) => {\n switch (status) {\n case \"todo\":\n return \"⏳\";\n case \"in_progress\":\n return \"🔄\";\n case \"done\":\n return \"✅\";\n default:\n return \"❓\";\n }\n};\n\n/**\n * Get the CSS class names for a task status badge\n * @param status The task status\n * @returns The CSS class names for styling the status badge\n */\nexport const getStatusClassName = (status: string) => {\n if (status === \"done\") {\n return \"bg-green-800 text-green-200\";\n }\n if (status === \"in_progress\") {\n return \"bg-yellow-800 text-yellow-200\";\n }\n return \"bg-tertiary text-[var(--oh-text-tertiary)]\";\n};\n\n/**\n * Helper function to apply client-side filtering based on search query\n * @param repo The Git repository to check\n * @param searchQuery The search query string\n * @returns True if the repository should be included based on the search query\n */\nexport const shouldIncludeRepository = (\n repo: GitRepository,\n searchQuery: string,\n): boolean => {\n if (!searchQuery.trim()) {\n return true;\n }\n\n const sanitizedQuery = sanitizeQuery(searchQuery);\n const sanitizedRepoName = sanitizeQuery(repo.full_name);\n return sanitizedRepoName.includes(sanitizedQuery);\n};\n\n/**\n * Get the OpenHands query string based on the provider\n * @param provider The git provider\n * @returns The query string for searching OpenHands repositories\n */\nexport const getOpenHandsQuery = (provider: Provider | null): string => {\n const providerRepositorySuffix: Record<string, string> = {\n gitlab: \"openhands-config\",\n azure_devops: \"openhands-config\",\n default: \".openhands\",\n } as const;\n\n return provider && provider in providerRepositorySuffix\n ? providerRepositorySuffix[provider]\n : providerRepositorySuffix.default;\n};\n\n/**\n * Check if a repository has the OpenHands suffix based on the provider\n * @param repo The Git repository to check\n * @param provider The git provider\n * @returns True if the repository has the OpenHands suffix\n */\nexport const hasOpenHandsSuffix = (\n repo: GitRepository,\n provider: Provider | null,\n): boolean => repo.full_name.endsWith(`/${getOpenHandsQuery(provider)}`);\n\n/**\n * Build headers for V1 API requests that require session authentication\n * @param sessionApiKey Session API key for authentication\n * @returns Headers object with X-Session-API-Key if provided\n */\nexport const buildSessionHeaders = (\n sessionApiKey?: string | null,\n): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (sessionApiKey) {\n headers[\"X-Session-API-Key\"] = sessionApiKey;\n }\n return headers;\n};\n\n/**\n * Check if a task is currently being polled (loading state)\n * @param taskStatus The task status string (e.g., \"WORKING\", \"ERROR\", \"READY\")\n * @returns True if the task is in a loading state (not ERROR and not READY)\n *\n * @example\n * isTaskPolling(\"WORKING\") // Returns true\n * isTaskPolling(\"PREPARING_REPOSITORY\") // Returns true\n * isTaskPolling(\"READY\") // Returns false\n * isTaskPolling(\"ERROR\") // Returns false\n * isTaskPolling(null) // Returns false\n * isTaskPolling(undefined) // Returns false\n */\nexport const isTaskPolling = (taskStatus: string | null | undefined): boolean =>\n !!taskStatus && taskStatus !== \"ERROR\" && taskStatus !== \"READY\";\n\n/**\n * Get the appropriate color based on agent status\n * @param options Configuration object for status color calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.isStartingStatus Whether the agent is in a starting state (LOADING or INIT)\n * @param options.isStopStatus Whether the conversation status is STOPPED\n * @param options.curAgentState The current agent state\n * @returns The hex color code for the status\n *\n * @example\n * getStatusColor({\n * isPausing: false,\n * isTask: false,\n * taskStatus: undefined,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"var(--oh-status-success)\"\n */\nexport const getStatusColor = (options: {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n}): string => {\n const {\n isPausing,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n } = options;\n\n // Show pausing status\n if (isPausing) {\n return \"#FFD600\";\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return OH_STATUS_ERROR_COLOR;\n }\n return \"#FFD600\";\n }\n\n if (isStartingStatus) {\n return \"#FFD600\";\n }\n if (isStopStatus) {\n return \"#ffffff\";\n }\n if (curAgentState === AgentState.ERROR) {\n return OH_STATUS_ERROR_COLOR;\n }\n return OH_STATUS_SUCCESS_COLOR;\n};\n\ninterface GetStatusTextArgs {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: AppConversationStartTaskStatus | null;\n taskDetail?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n errorMessage?: string | null;\n t: (t: string) => string;\n}\n\n/**\n * Get the server status text based on agent and task state\n *\n * @param options Configuration object for status text calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.taskDetail Optional task-specific detail text\n * @param options.isStartingStatus Whether the conversation is in STARTING state\n * @param options.isStopStatus Whether the conversation is STOPPED\n * @param options.curAgentState The current agent state\n * @param options.errorMessage Optional agent error message\n * @returns Localized human-readable status text\n *\n * @example\n * getStatusText({\n * isPausing: false,\n * isTask: true,\n * taskStatus: \"STARTING_CONVERSATION\",\n * taskDetail: null,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"Starting conversation\"\n */\nexport function getStatusText({\n isPausing = false,\n isTask,\n taskStatus,\n taskDetail,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n errorMessage,\n t,\n}: GetStatusTextArgs): string {\n // Show pausing status\n if (isPausing) {\n return t(I18nKey.COMMON$STOPPING);\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION);\n }\n\n if (taskStatus === \"READY\") {\n return t(I18nKey.CONVERSATION$READY);\n }\n\n return taskDetail || t(getTaskStatusI18nKey(taskStatus));\n }\n\n if (isStartingStatus) {\n return t(I18nKey.COMMON$STARTING);\n }\n\n if (isStopStatus) {\n return t(I18nKey.COMMON$SERVER_STOPPED);\n }\n\n if (curAgentState === AgentState.ERROR) {\n return errorMessage || t(I18nKey.COMMON$ERROR);\n }\n\n return t(I18nKey.COMMON$RUNNING);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../src/utils/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Provider } from \"#/types/settings\";\nimport { SuggestedTaskGroup } from \"#/utils/types\";\nimport { ConversationStatus } from \"#/types/conversation-status\";\nimport { GitRepository } from \"#/types/git\";\nimport { sanitizeQuery } from \"#/utils/sanitize-query\";\nimport { PRODUCT_URL } from \"#/utils/constants\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getTaskStatusI18nKey } from \"#/utils/status\";\nimport type { AppConversationStartTaskStatus } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport {\n OH_STATUS_ERROR_COLOR,\n OH_STATUS_SUCCESS_COLOR,\n} from \"#/constants/status-colors\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Trigger a download for a provided Blob with the given filename\n */\nexport const downloadBlob = (blob: Blob, filename: string): void => {\n const url = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(url);\n};\n\n/**\n * Get the numeric height value from an element's style property\n * @param el The HTML element to get the height from\n * @param fallback The fallback value to return if style height is invalid\n * @returns The numeric height value in pixels, or the fallback value\n *\n * @example\n * getStyleHeightPx(element, 20) // Returns 20 if element.style.height is \"auto\" or invalid\n * getStyleHeightPx(element, 20) // Returns 100 if element.style.height is \"100px\"\n */\nexport const getStyleHeightPx = (el: HTMLElement, fallback: number): number => {\n const elementHeight = parseFloat(el.style.height || \"\");\n return Number.isFinite(elementHeight) ? elementHeight : fallback;\n};\n\n/**\n * Set the height style property of an element to a specific pixel value\n * @param el The HTML element to set the height for\n * @param height The height value in pixels to set\n *\n * @example\n * setStyleHeightPx(element, 100) // Sets element.style.height to \"100px\"\n * setStyleHeightPx(textarea, 200) // Sets textarea.style.height to \"200px\"\n */\nexport const setStyleHeightPx = (el: HTMLElement, height: number): void => {\n el.style.setProperty(\"height\", `${height}px`);\n};\n\n/**\n * Detect a phone/tablet user agent (Android, iPhone, iPad, …).\n * Unlike isMobileDevice, this ignores touch capability, so a desktop OS with\n * a touchscreen (e.g. a Windows 2-in-1) is NOT matched. Use this when the\n * decision depends on having a physical keyboard rather than on touch input.\n */\nexport const isMobileUserAgent = (): boolean =>\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent,\n );\n\n/**\n * Detect if the user is on a mobile device.\n * Touch support alone is not sufficient — touchscreen laptops have touch\n * but use a mouse/trackpad as primary input. We check that the primary\n * pointing device is coarse (finger) to avoid false positives.\n */\nexport const isMobileDevice = (): boolean => {\n if (isMobileUserAgent()) return true;\n\n const hasTouch = \"ontouchstart\" in window || navigator.maxTouchPoints > 0;\n if (!hasTouch) return false;\n\n // If matchMedia is available, check whether the primary pointer is fine\n // (mouse/trackpad). Touchscreen laptops report fine, real mobile devices don't.\n if (typeof window.matchMedia === \"function\") {\n return !window.matchMedia(\"(pointer: fine)\").matches;\n }\n\n // Fallback: touch present but no matchMedia — assume mobile\n return true;\n};\n\n/**\n * Checks if the current domain is the production domain\n * @returns True if the current domain matches the production URL\n */\nexport const isProductionDomain = (): boolean =>\n window.location.origin === PRODUCT_URL.PRODUCTION;\n\ninterface EventActionHistory {\n args?: {\n LLM_API_KEY?: string;\n [key: string]: unknown;\n };\n extras?: {\n open_page_urls: string[];\n active_page_index: number;\n dom_object: Record<string, unknown>;\n axtree_object: Record<string, unknown>;\n extra_element_properties: Record<string, unknown>;\n last_browser_action: string;\n last_browser_action_error: unknown;\n focused_element_bid: string;\n };\n [key: string]: unknown;\n}\n\nexport const removeUnwantedKeys = (\n data: EventActionHistory[],\n): EventActionHistory[] => {\n const UNDESIRED_KEYS = [\n \"open_page_urls\",\n \"active_page_index\",\n \"dom_object\",\n \"axtree_object\",\n \"extra_element_properties\",\n \"last_browser_action\",\n \"last_browser_action_error\",\n \"focused_element_bid\",\n ];\n\n return data\n .filter((item) => {\n // Skip items that have a status key\n if (\"status\" in item) {\n return false;\n }\n return true;\n })\n .map((item) => {\n // Create a shallow copy of item\n const newItem = { ...item };\n\n // Check if extras exists and delete it from a new extras object\n if (newItem.extras) {\n const newExtras = { ...newItem.extras };\n UNDESIRED_KEYS.forEach((key) => {\n delete newExtras[key as keyof typeof newExtras];\n });\n newItem.extras = newExtras;\n }\n\n return newItem;\n });\n};\n\n/**\n * Get file extension from file name in uppercase format\n * @param fileName The file name to extract extension from\n * @returns The file extension in uppercase, or \"FILE\" if no extension found\n *\n * @example\n * getFileExtension(\"document.pdf\") // \"PDF\"\n * getFileExtension(\"image.jpeg\") // \"JPEG\"\n * getFileExtension(\"noextension\") // \"FILE\"\n */\nexport const getFileExtension = (fileName: string): string => {\n const extension = fileName.split(\".\").pop()?.toUpperCase();\n return extension || \"FILE\";\n};\n\n/**\n * Whether to use the installation-scoped repo flow\n * (`/api/v1/git/installations/search` → `/api/v1/git/repositories/search?installation_id=…`)\n * for the given provider/backend combo.\n *\n * Mirrors OpenHands' cloud frontend (parameterized by `app_mode`):\n * - bitbucket / bitbucket_data_center → always installation-based\n * - github → installation-based ONLY when the active backend is cloud\n * - gitlab / azure_devops / forgejo → direct (search) flow\n *\n * `appMode` accepts the active backend `kind` (\"local\" | \"cloud\") so call\n * sites can hand it through directly.\n */\nexport const shouldUseInstallationRepos = (\n provider: Provider | null | undefined,\n appMode?: \"local\" | \"cloud\",\n) => {\n if (!provider) return false;\n\n switch (provider) {\n case \"bitbucket\":\n case \"bitbucket_data_center\":\n return true;\n case \"github\":\n return appMode === \"cloud\";\n default:\n return false;\n }\n};\n\nexport const getGitProviderBaseUrl = (\n gitProvider: Provider,\n host?: string | null,\n): string => {\n // If custom host provided, use it (with https:// prefix if needed)\n if (host && host.trim() !== \"\") {\n return host.startsWith(\"http\") ? host : `https://${host}`;\n }\n\n // Fall back to defaults\n switch (gitProvider) {\n case \"github\":\n return \"https://github.com\";\n case \"gitlab\":\n return \"https://gitlab.com\";\n case \"bitbucket\":\n return \"https://bitbucket.org\";\n case \"azure_devops\":\n return \"https://dev.azure.com\";\n case \"forgejo\":\n // Default UI links to Codeberg unless a custom host is available in settings\n // Note: UI link builders don't currently receive host; consider plumbing settings if needed\n return \"https://codeberg.org\";\n default:\n return \"\";\n }\n};\n\n/**\n * Get the name of the git provider\n * @param gitProvider The git provider\n * @returns The name of the git provider\n */\nexport const getProviderName = (gitProvider: Provider) => {\n if (gitProvider === \"gitlab\") return \"GitLab\";\n if (gitProvider === \"bitbucket\") return \"Bitbucket\";\n if (gitProvider === \"bitbucket_data_center\") return \"Bitbucket Data Center\";\n if (gitProvider === \"azure_devops\") return \"Azure DevOps\";\n if (gitProvider === \"forgejo\") return \"Forgejo\";\n return \"GitHub\";\n};\n\n/**\n * Get the name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The name of the PR\n */\nexport const getPR = (isGitLab: boolean) =>\n isGitLab ? \"merge request\" : \"pull request\";\n\n/**\n * Get the short name of the PR\n * @param isGitLab Whether the git provider is GitLab\n * @returns The short name of the PR\n */\nexport const getPRShort = (isGitLab: boolean) => (isGitLab ? \"MR\" : \"PR\");\n\n/**\n * Construct the pull request (merge request) URL for different providers\n * @param prNumber The pull request number\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The pull request URL\n *\n * @example\n * constructPullRequestUrl(123, \"github\", \"owner/repo\") // \"https://github.com/owner/repo/pull/123\"\n * constructPullRequestUrl(456, \"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo/-/merge_requests/456\"\n * constructPullRequestUrl(789, \"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo/pull-requests/789\"\n * constructPullRequestUrl(789, \"bitbucket\", \"PROJECT/repo\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/pull-requests/789\"\n */\nexport const constructPullRequestUrl = (\n prNumber: number,\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/pull/${prNumber}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/merge_requests/${prNumber}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/pull-requests/${prNumber}`;\n case \"bitbucket_data_center\": {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}/pull-requests/${prNumber}`;\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n return `${baseUrl}/${org}/${project}/_git/${repo}/pullrequest/${prNumber}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n/**\n * Construct the repository URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @returns The repository URL\n *\n * @example\n * constructRepositoryUrl(\"github\", \"owner/repo\") // \"https://github.com/owner/repo\"\n * constructRepositoryUrl(\"gitlab\", \"owner/repo\") // \"https://gitlab.com/owner/repo\"\n * constructRepositoryUrl(\"bitbucket\", \"owner/repo\") // \"https://bitbucket.org/owner/repo\"\n */\nexport const constructRepositoryUrl = (\n provider: Provider,\n repositoryName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n if (provider === \"bitbucket_data_center\") {\n const [project, repo] = repositoryName.split(\"/\");\n return `${baseUrl}/projects/${project}/repos/${repo}`;\n }\n return `${baseUrl}/${repositoryName}`;\n};\n\n/**\n * Percent-encode a branch name for use as a URL path component. Each\n * `/`-separated segment is encoded on its own so nested branch names such as\n * `release/1.0` keep their slashes while `#`, `%` and `&` are escaped.\n */\nconst encodeBranchPath = (branchName: string): string =>\n branchName.split(\"/\").map(encodeURIComponent).join(\"/\");\n\n/**\n * Construct the branch URL for different providers\n * @param provider The git provider\n * @param repositoryName The repository name in format \"owner/repo\"\n * @param branchName The branch name\n * @param host Optional custom host for self-hosted instances\n * @returns The branch URL\n *\n * @example\n * constructBranchUrl(\"github\", \"owner/repo\", \"main\") // \"https://github.com/owner/repo/tree/main\"\n * constructBranchUrl(\"gitlab\", \"owner/repo\", \"develop\") // \"https://gitlab.com/owner/repo/-/tree/develop\"\n * constructBranchUrl(\"bitbucket\", \"owner/repo\", \"feature\") // \"https://bitbucket.org/owner/repo/src/feature\"\n * constructBranchUrl(\"bitbucket\", \"PROJECT/repo\", \"feature\", \"server.com\") // \"https://server.com/projects/PROJECT/repos/repo/browse?at=refs/heads/feature\"\n */\nexport const constructBranchUrl = (\n provider: Provider,\n repositoryName: string,\n branchName: string,\n host?: string | null,\n): string => {\n const baseUrl = getGitProviderBaseUrl(provider, host);\n\n switch (provider) {\n case \"github\":\n return `${baseUrl}/${repositoryName}/tree/${encodeBranchPath(branchName)}`;\n case \"forgejo\":\n return `${baseUrl}/${repositoryName}/src/branch/${encodeBranchPath(branchName)}`;\n case \"gitlab\":\n return `${baseUrl}/${repositoryName}/-/tree/${encodeBranchPath(branchName)}`;\n case \"bitbucket\":\n return `${baseUrl}/${repositoryName}/src/${encodeBranchPath(branchName)}`;\n case \"bitbucket_data_center\": {\n // Bitbucket Server format: /projects/{PROJECT}/repos/{repo}/browse?at=refs/heads/{branch}\n const parts = repositoryName.split(\"/\");\n if (parts.length >= 2) {\n const [project, repo] = parts;\n // The branch is one query value here, so encode it whole: an\n // unencoded `&` would start a new query parameter.\n return `${baseUrl}/projects/${project}/repos/${repo}/browse?at=refs/heads/${encodeURIComponent(branchName)}`;\n }\n return \"\";\n }\n case \"azure_devops\": {\n // Azure DevOps format: org/project/repo\n const parts = repositoryName.split(\"/\");\n if (parts.length === 3) {\n const [org, project, repo] = parts;\n // The branch is one query value here, so encode it whole: an\n // unencoded `&` would start a new query parameter.\n return `${baseUrl}/${org}/${project}/_git/${repo}?version=GB${encodeURIComponent(branchName)}`;\n }\n return \"\";\n }\n default:\n return \"\";\n }\n};\n\n// Git Action Prompts\n\nconst GIT_COMMIT_PROMPT =\n \"Please review the current changes and create a git commit with a concise, descriptive message.\";\n\nexport const getGitCommitPrompt = (): string => GIT_COMMIT_PROMPT;\n\n/**\n * Generate a git pull prompt\n * @returns The git pull prompt\n */\nexport const getGitPullPrompt = (): string =>\n \"Please pull the latest code from the repository.\";\n\n/**\n * Generate a git push prompt\n * @param gitProvider The git provider\n * @returns The git push prompt\n */\nexport const getGitPushPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the changes to a remote branch on ${providerName}, but do NOT create a ${pr}. Check your current branch name first - if it's main, master, deploy, or another common default branch name, create a new branch with a descriptive name related to your changes. Otherwise, use the exact SAME branch name as the one you are currently on.`;\n};\n\n/**\n * Generate a create pull request prompt\n * @param gitProvider The git provider\n * @returns The create PR prompt\n */\nexport const getCreatePRPrompt = (gitProvider: Provider): string => {\n const providerName = getProviderName(gitProvider);\n const pr = getPR(gitProvider === \"gitlab\");\n const prShort = getPRShort(gitProvider === \"gitlab\");\n\n return `Please push the changes to ${providerName} and open a ${pr}. If you're on a default branch (e.g., main, master, deploy), create a new branch with a descriptive name otherwise use the current branch. If a ${pr} template exists in the repository, please follow it when creating the ${prShort} description.`;\n};\n\n/**\n * Generate a push to existing PR prompt\n * @param gitProvider The git provider\n * @returns The push to PR prompt\n */\nexport const getPushToPRPrompt = (gitProvider: Provider): string => {\n const pr = getPR(gitProvider === \"gitlab\");\n\n return `Please push the latest changes to the existing ${pr}.`;\n};\n\n/**\n * Generate a create new branch prompt\n * @returns The create new branch prompt\n */\nexport const getCreateNewBranchPrompt = (): string =>\n \"Please create a new branch with a descriptive name related to the work you plan to do.\";\n\n// Helper functions\nexport function getTotalTaskCount(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n): number {\n if (!suggestedTasks) return 0;\n return suggestedTasks.flatMap((group) => group.tasks).length;\n}\n\nexport function getLimitedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[],\n maxTasks: number,\n): SuggestedTaskGroup[] {\n const limitedGroups: SuggestedTaskGroup[] = [];\n let taskCount = 0;\n\n for (const group of suggestedTasks) {\n if (taskCount >= maxTasks) break;\n\n const remainingTasksNeeded = maxTasks - taskCount;\n const tasksToShow = group.tasks.slice(0, remainingTasksNeeded);\n\n if (tasksToShow.length > 0) {\n limitedGroups.push({\n ...group,\n tasks: tasksToShow,\n });\n taskCount += tasksToShow.length;\n }\n }\n\n return limitedGroups;\n}\n\nexport function getDisplayedTaskGroups(\n suggestedTasks: SuggestedTaskGroup[] | undefined,\n isExpanded: boolean,\n): SuggestedTaskGroup[] {\n if (!suggestedTasks || suggestedTasks.length === 0) {\n return [];\n }\n\n if (isExpanded) {\n return suggestedTasks;\n }\n\n return getLimitedTaskGroups(suggestedTasks, 3);\n}\n\n/**\n * Get the label for a conversation status\n * @param status The conversation status\n * @returns The localized label for the status\n */\nexport const getConversationStatusLabel = (\n status: ConversationStatus,\n): string => {\n switch (status) {\n case \"STOPPED\":\n return \"COMMON$STOPPED\";\n case \"RUNNING\":\n return \"COMMON$RUNNING\";\n case \"STARTING\":\n return \"COMMON$STARTING\";\n case \"ERROR\":\n return \"COMMON$ERROR\";\n case \"ARCHIVED\":\n return \"COMMON$ARCHIVED\"; // Use STOPPED for archived conversations\n default:\n return \"COMMON$UNKNOWN\";\n }\n};\n\n// Task Tracking Utility Functions\n\n/**\n * Get the status icon for a task status\n * @param status The task status\n * @returns The emoji icon for the status\n */\nexport const getStatusIcon = (status: string) => {\n switch (status) {\n case \"todo\":\n return \"⏳\";\n case \"in_progress\":\n return \"🔄\";\n case \"done\":\n return \"✅\";\n default:\n return \"❓\";\n }\n};\n\n/**\n * Get the CSS class names for a task status badge\n * @param status The task status\n * @returns The CSS class names for styling the status badge\n */\nexport const getStatusClassName = (status: string) => {\n if (status === \"done\") {\n return \"bg-green-800 text-green-200\";\n }\n if (status === \"in_progress\") {\n return \"bg-yellow-800 text-yellow-200\";\n }\n return \"bg-tertiary text-[var(--oh-text-tertiary)]\";\n};\n\n/**\n * Helper function to apply client-side filtering based on search query\n * @param repo The Git repository to check\n * @param searchQuery The search query string\n * @returns True if the repository should be included based on the search query\n */\nexport const shouldIncludeRepository = (\n repo: GitRepository,\n searchQuery: string,\n): boolean => {\n if (!searchQuery.trim()) {\n return true;\n }\n\n const sanitizedQuery = sanitizeQuery(searchQuery);\n const sanitizedRepoName = sanitizeQuery(repo.full_name);\n return sanitizedRepoName.includes(sanitizedQuery);\n};\n\n/**\n * Get the OpenHands query string based on the provider\n * @param provider The git provider\n * @returns The query string for searching OpenHands repositories\n */\nexport const getOpenHandsQuery = (provider: Provider | null): string => {\n const providerRepositorySuffix: Record<string, string> = {\n gitlab: \"openhands-config\",\n azure_devops: \"openhands-config\",\n default: \".openhands\",\n } as const;\n\n return provider && provider in providerRepositorySuffix\n ? providerRepositorySuffix[provider]\n : providerRepositorySuffix.default;\n};\n\n/**\n * Check if a repository has the OpenHands suffix based on the provider\n * @param repo The Git repository to check\n * @param provider The git provider\n * @returns True if the repository has the OpenHands suffix\n */\nexport const hasOpenHandsSuffix = (\n repo: GitRepository,\n provider: Provider | null,\n): boolean => repo.full_name.endsWith(`/${getOpenHandsQuery(provider)}`);\n\n/**\n * Build headers for V1 API requests that require session authentication\n * @param sessionApiKey Session API key for authentication\n * @returns Headers object with X-Session-API-Key if provided\n */\nexport const buildSessionHeaders = (\n sessionApiKey?: string | null,\n): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (sessionApiKey) {\n headers[\"X-Session-API-Key\"] = sessionApiKey;\n }\n return headers;\n};\n\n/**\n * Check if a task is currently being polled (loading state)\n * @param taskStatus The task status string (e.g., \"WORKING\", \"ERROR\", \"READY\")\n * @returns True if the task is in a loading state (not ERROR and not READY)\n *\n * @example\n * isTaskPolling(\"WORKING\") // Returns true\n * isTaskPolling(\"PREPARING_REPOSITORY\") // Returns true\n * isTaskPolling(\"READY\") // Returns false\n * isTaskPolling(\"ERROR\") // Returns false\n * isTaskPolling(null) // Returns false\n * isTaskPolling(undefined) // Returns false\n */\nexport const isTaskPolling = (taskStatus: string | null | undefined): boolean =>\n !!taskStatus && taskStatus !== \"ERROR\" && taskStatus !== \"READY\";\n\n/**\n * Get the appropriate color based on agent status\n * @param options Configuration object for status color calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.isStartingStatus Whether the agent is in a starting state (LOADING or INIT)\n * @param options.isStopStatus Whether the conversation status is STOPPED\n * @param options.curAgentState The current agent state\n * @returns The hex color code for the status\n *\n * @example\n * getStatusColor({\n * isPausing: false,\n * isTask: false,\n * taskStatus: undefined,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"var(--oh-status-success)\"\n */\nexport const getStatusColor = (options: {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n}): string => {\n const {\n isPausing,\n isTask,\n taskStatus,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n } = options;\n\n // Show pausing status\n if (isPausing) {\n return \"#FFD600\";\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return OH_STATUS_ERROR_COLOR;\n }\n return \"#FFD600\";\n }\n\n if (isStartingStatus) {\n return \"#FFD600\";\n }\n if (isStopStatus) {\n return \"#ffffff\";\n }\n if (curAgentState === AgentState.ERROR) {\n return OH_STATUS_ERROR_COLOR;\n }\n return OH_STATUS_SUCCESS_COLOR;\n};\n\ninterface GetStatusTextArgs {\n isPausing: boolean;\n isTask: boolean;\n taskStatus?: AppConversationStartTaskStatus | null;\n taskDetail?: string | null;\n isStartingStatus: boolean;\n isStopStatus: boolean;\n curAgentState: AgentState;\n errorMessage?: string | null;\n t: (t: string) => string;\n}\n\n/**\n * Get the server status text based on agent and task state\n *\n * @param options Configuration object for status text calculation\n * @param options.isPausing Whether the agent is currently pausing\n * @param options.isTask Whether we're polling a task\n * @param options.taskStatus The task status string (e.g., \"ERROR\", \"READY\")\n * @param options.taskDetail Optional task-specific detail text\n * @param options.isStartingStatus Whether the conversation is in STARTING state\n * @param options.isStopStatus Whether the conversation is STOPPED\n * @param options.curAgentState The current agent state\n * @param options.errorMessage Optional agent error message\n * @returns Localized human-readable status text\n *\n * @example\n * getStatusText({\n * isPausing: false,\n * isTask: true,\n * taskStatus: \"STARTING_CONVERSATION\",\n * taskDetail: null,\n * isStartingStatus: false,\n * isStopStatus: false,\n * curAgentState: AgentState.RUNNING\n * }) // Returns \"Starting conversation\"\n */\nexport function getStatusText({\n isPausing = false,\n isTask,\n taskStatus,\n taskDetail,\n isStartingStatus,\n isStopStatus,\n curAgentState,\n errorMessage,\n t,\n}: GetStatusTextArgs): string {\n // Show pausing status\n if (isPausing) {\n return t(I18nKey.COMMON$STOPPING);\n }\n\n // Show task status if we're polling a task\n if (isTask && taskStatus) {\n if (taskStatus === \"ERROR\") {\n return taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION);\n }\n\n if (taskStatus === \"READY\") {\n return t(I18nKey.CONVERSATION$READY);\n }\n\n return taskDetail || t(getTaskStatusI18nKey(taskStatus));\n }\n\n if (isStartingStatus) {\n return t(I18nKey.COMMON$STARTING);\n }\n\n if (isStopStatus) {\n return t(I18nKey.COMMON$SERVER_STOPPED);\n }\n\n if (curAgentState === AgentState.ERROR) {\n return errorMessage || t(I18nKey.COMMON$ERROR);\n }\n\n return t(I18nKey.COMMON$RUNNING);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");var e=`__AGENT_CANVAS_VSCODE_BASE_PATH__`;function t(){if(typeof window<`u`){let t=window[e];if(typeof t==`string`&&t.trim())return n(t.trim())}return null}function n(e){let t=e.startsWith(`/`)?e:`/${e}`;return t.length>1?t.replace(/\/+$/,``):t}function r(e,t){if(!e||!t)return!1;let n;try{n=new URL(e,typeof window<`u`?window.location.href:void 0)}catch{return!1}return typeof window<`u`&&n.origin!==window.location.origin?!1:n.pathname===t||n.pathname.startsWith(`${t}/`)}exports.getOriginVSCodeBasePath=t,exports.isVSCodeUrlServedByOrigin=r;
2
+ //# sourceMappingURL=vscode-origin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscode-origin.cjs","names":[],"sources":["../../src/utils/vscode-origin.ts"],"sourcesContent":["/**\n * Whether *this browser origin* can serve the editor, and whether a given\n * editor URL is one it will actually route.\n *\n * Editor availability is not a property of the agent-server process alone. The\n * agent-server answers `/api/vscode/status` for whatever conversation you ask\n * about, and builds `/api/vscode/url` from the `base_url` the caller sends —\n * which is always `window.location.origin`. So a server can truthfully report\n * an editor that the page's own origin has no route to. Two supported layouts\n * hit that:\n *\n * - **Public mode** (`docker/entrypoint.sh`, `--auth-required`): a second\n * static server on its own port, sharing the same agent-server but\n * deliberately without the editor route, because the editor's connection\n * token is the session API key (OpenHands/software-agent-sdk#4317) and that\n * origin exists to test the *unauthenticated* case.\n * - **Extra backends** (`scripts/dev-extra-backend.mjs`): a second\n * agent-server registered from a browser whose origin belongs to another\n * stack. That origin's editor route, if any, points at the *bundled*\n * stack's editor — a different container's workspace.\n *\n * In both cases a control gated only on the server probe renders and then\n * resolves to the canvas SPA or, worse, someone else's workspace. So the\n * frontend has to intersect the server's capability with the origin's route\n * table, and this module is the origin half of that.\n */\n\nconst VSCODE_BASE_PATH_WINDOW_KEY = \"__AGENT_CANVAS_VSCODE_BASE_PATH__\";\n\n/**\n * The path prefix this origin serves the editor under, or `null` if it serves\n * no editor at all.\n *\n * Two sources, in order — mirroring `getRawRuntimeServicesInfo` in\n * `agent-server-adapter.ts`:\n * 1. `VITE_VSCODE_BASE_PATH` — baked in at build time by the dev launchers\n * that proxy the editor (`npm run dev`, dev:static).\n * 2. `window.__AGENT_CANVAS_VSCODE_BASE_PATH__` — injected into index.html at\n * serve time by `scripts/static-server.mjs --vscode-base-path <path>`,\n * which refuses to start unless a matching `--route` exists. That is the\n * path used by static builds (the Docker image, the published binary),\n * where the env var is empty in the prebuilt bundle.\n *\n * Absent from both means \"this origin does not serve the editor\" and the\n * control is hidden. That is the pre-existing behavior for every local backend,\n * so a deployment this cannot detect is no worse off than before.\n */\nexport function getOriginVSCodeBasePath(): string | null {\n const envRaw = import.meta.env.VITE_VSCODE_BASE_PATH?.trim();\n if (envRaw) return normalizePrefix(envRaw);\n\n if (typeof window !== \"undefined\") {\n const injected = (window as unknown as Record<string, unknown>)[\n VSCODE_BASE_PATH_WINDOW_KEY\n ];\n if (typeof injected === \"string\" && injected.trim()) {\n return normalizePrefix(injected.trim());\n }\n }\n\n return null;\n}\n\nfunction normalizePrefix(value: string): string {\n const withLeadingSlash = value.startsWith(\"/\") ? value : `/${value}`;\n return withLeadingSlash.length > 1\n ? withLeadingSlash.replace(/\\/+$/, \"\")\n : withLeadingSlash;\n}\n\n/**\n * Whether `url` is an editor URL this origin will actually route.\n *\n * The agent-server appends its own `vscode_base_path` to the origin we send it,\n * so the returned URL carries the prefix of the server that answered — not\n * necessarily the prefix this origin routes. An extra backend that configures\n * no prefix yields `<origin>/?tkn=…`, which is the canvas root: same origin,\n * wrong destination. Comparing paths is what separates the two.\n */\nexport function isVSCodeUrlServedByOrigin(\n url: string | null | undefined,\n basePath: string | null,\n): boolean {\n if (!url || !basePath) return false;\n\n let parsed: URL;\n try {\n parsed = new URL(\n url,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n );\n } catch {\n return false;\n }\n\n // A cross-origin URL is somebody else's problem to route, not ours to vouch\n // for. The local path always builds on `window.location.origin`, so this only\n // fires on a value we did not construct.\n if (\n typeof window !== \"undefined\" &&\n parsed.origin !== window.location.origin\n ) {\n return false;\n }\n\n return (\n parsed.pathname === basePath || parsed.pathname.startsWith(`${basePath}/`)\n );\n}\n"],"mappings":"6CA2BA,IAAM,EAA8B,oCAoBpC,SAAgB,GAAyC,CAIvD,GAAI,OAAO,OAAW,IAAa,CACjC,IAAM,EAAY,OAChB,GAEF,GAAI,OAAO,GAAa,UAAY,EAAS,KAAK,EAChD,OAAO,EAAgB,EAAS,KAAK,CAAC,CAE1C,CAEA,OAAO,IACT,CAEA,SAAS,EAAgB,EAAuB,CAC9C,IAAM,EAAmB,EAAM,WAAW,GAAG,EAAI,EAAQ,IAAI,IAC7D,OAAO,EAAiB,OAAS,EAC7B,EAAiB,QAAQ,OAAQ,EAAE,EACnC,CACN,CAWA,SAAgB,EACd,EACA,EACS,CACT,GAAI,CAAC,GAAO,CAAC,EAAU,MAAO,GAE9B,IAAI,EACJ,GAAI,CACF,EAAS,IAAI,IACX,EACA,OAAO,OAAW,IAAc,OAAO,SAAS,KAAO,IAAA,EACzD,CACF,MAAQ,CACN,MAAO,EACT,CAYA,OANE,OAAO,OAAW,KAClB,EAAO,SAAW,OAAO,SAAS,OAE3B,GAIP,EAAO,WAAa,GAAY,EAAO,SAAS,WAAW,GAAG,EAAS,EAAE,CAE7E"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Whether *this browser origin* can serve the editor, and whether a given
3
+ * editor URL is one it will actually route.
4
+ *
5
+ * Editor availability is not a property of the agent-server process alone. The
6
+ * agent-server answers `/api/vscode/status` for whatever conversation you ask
7
+ * about, and builds `/api/vscode/url` from the `base_url` the caller sends —
8
+ * which is always `window.location.origin`. So a server can truthfully report
9
+ * an editor that the page's own origin has no route to. Two supported layouts
10
+ * hit that:
11
+ *
12
+ * - **Public mode** (`docker/entrypoint.sh`, `--auth-required`): a second
13
+ * static server on its own port, sharing the same agent-server but
14
+ * deliberately without the editor route, because the editor's connection
15
+ * token is the session API key (OpenHands/software-agent-sdk#4317) and that
16
+ * origin exists to test the *unauthenticated* case.
17
+ * - **Extra backends** (`scripts/dev-extra-backend.mjs`): a second
18
+ * agent-server registered from a browser whose origin belongs to another
19
+ * stack. That origin's editor route, if any, points at the *bundled*
20
+ * stack's editor — a different container's workspace.
21
+ *
22
+ * In both cases a control gated only on the server probe renders and then
23
+ * resolves to the canvas SPA or, worse, someone else's workspace. So the
24
+ * frontend has to intersect the server's capability with the origin's route
25
+ * table, and this module is the origin half of that.
26
+ */
27
+ /**
28
+ * The path prefix this origin serves the editor under, or `null` if it serves
29
+ * no editor at all.
30
+ *
31
+ * Two sources, in order — mirroring `getRawRuntimeServicesInfo` in
32
+ * `agent-server-adapter.ts`:
33
+ * 1. `VITE_VSCODE_BASE_PATH` — baked in at build time by the dev launchers
34
+ * that proxy the editor (`npm run dev`, dev:static).
35
+ * 2. `window.__AGENT_CANVAS_VSCODE_BASE_PATH__` — injected into index.html at
36
+ * serve time by `scripts/static-server.mjs --vscode-base-path <path>`,
37
+ * which refuses to start unless a matching `--route` exists. That is the
38
+ * path used by static builds (the Docker image, the published binary),
39
+ * where the env var is empty in the prebuilt bundle.
40
+ *
41
+ * Absent from both means "this origin does not serve the editor" and the
42
+ * control is hidden. That is the pre-existing behavior for every local backend,
43
+ * so a deployment this cannot detect is no worse off than before.
44
+ */
45
+ export declare function getOriginVSCodeBasePath(): string | null;
46
+ /**
47
+ * Whether `url` is an editor URL this origin will actually route.
48
+ *
49
+ * The agent-server appends its own `vscode_base_path` to the origin we send it,
50
+ * so the returned URL carries the prefix of the server that answered — not
51
+ * necessarily the prefix this origin routes. An extra backend that configures
52
+ * no prefix yields `<origin>/?tkn=…`, which is the canvas root: same origin,
53
+ * wrong destination. Comparing paths is what separates the two.
54
+ */
55
+ export declare function isVSCodeUrlServedByOrigin(url: string | null | undefined, basePath: string | null): boolean;
@@ -0,0 +1,27 @@
1
+ //#region src/utils/vscode-origin.ts
2
+ var e = "__AGENT_CANVAS_VSCODE_BASE_PATH__";
3
+ function t() {
4
+ if (typeof window < "u") {
5
+ let t = window[e];
6
+ if (typeof t == "string" && t.trim()) return n(t.trim());
7
+ }
8
+ return null;
9
+ }
10
+ function n(e) {
11
+ let t = e.startsWith("/") ? e : `/${e}`;
12
+ return t.length > 1 ? t.replace(/\/+$/, "") : t;
13
+ }
14
+ function r(e, t) {
15
+ if (!e || !t) return !1;
16
+ let n;
17
+ try {
18
+ n = new URL(e, typeof window < "u" ? window.location.href : void 0);
19
+ } catch {
20
+ return !1;
21
+ }
22
+ return typeof window < "u" && n.origin !== window.location.origin ? !1 : n.pathname === t || n.pathname.startsWith(`${t}/`);
23
+ }
24
+ //#endregion
25
+ export { t as getOriginVSCodeBasePath, r as isVSCodeUrlServedByOrigin };
26
+
27
+ //# sourceMappingURL=vscode-origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscode-origin.js","names":[],"sources":["../../src/utils/vscode-origin.ts"],"sourcesContent":["/**\n * Whether *this browser origin* can serve the editor, and whether a given\n * editor URL is one it will actually route.\n *\n * Editor availability is not a property of the agent-server process alone. The\n * agent-server answers `/api/vscode/status` for whatever conversation you ask\n * about, and builds `/api/vscode/url` from the `base_url` the caller sends —\n * which is always `window.location.origin`. So a server can truthfully report\n * an editor that the page's own origin has no route to. Two supported layouts\n * hit that:\n *\n * - **Public mode** (`docker/entrypoint.sh`, `--auth-required`): a second\n * static server on its own port, sharing the same agent-server but\n * deliberately without the editor route, because the editor's connection\n * token is the session API key (OpenHands/software-agent-sdk#4317) and that\n * origin exists to test the *unauthenticated* case.\n * - **Extra backends** (`scripts/dev-extra-backend.mjs`): a second\n * agent-server registered from a browser whose origin belongs to another\n * stack. That origin's editor route, if any, points at the *bundled*\n * stack's editor — a different container's workspace.\n *\n * In both cases a control gated only on the server probe renders and then\n * resolves to the canvas SPA or, worse, someone else's workspace. So the\n * frontend has to intersect the server's capability with the origin's route\n * table, and this module is the origin half of that.\n */\n\nconst VSCODE_BASE_PATH_WINDOW_KEY = \"__AGENT_CANVAS_VSCODE_BASE_PATH__\";\n\n/**\n * The path prefix this origin serves the editor under, or `null` if it serves\n * no editor at all.\n *\n * Two sources, in order — mirroring `getRawRuntimeServicesInfo` in\n * `agent-server-adapter.ts`:\n * 1. `VITE_VSCODE_BASE_PATH` — baked in at build time by the dev launchers\n * that proxy the editor (`npm run dev`, dev:static).\n * 2. `window.__AGENT_CANVAS_VSCODE_BASE_PATH__` — injected into index.html at\n * serve time by `scripts/static-server.mjs --vscode-base-path <path>`,\n * which refuses to start unless a matching `--route` exists. That is the\n * path used by static builds (the Docker image, the published binary),\n * where the env var is empty in the prebuilt bundle.\n *\n * Absent from both means \"this origin does not serve the editor\" and the\n * control is hidden. That is the pre-existing behavior for every local backend,\n * so a deployment this cannot detect is no worse off than before.\n */\nexport function getOriginVSCodeBasePath(): string | null {\n const envRaw = import.meta.env.VITE_VSCODE_BASE_PATH?.trim();\n if (envRaw) return normalizePrefix(envRaw);\n\n if (typeof window !== \"undefined\") {\n const injected = (window as unknown as Record<string, unknown>)[\n VSCODE_BASE_PATH_WINDOW_KEY\n ];\n if (typeof injected === \"string\" && injected.trim()) {\n return normalizePrefix(injected.trim());\n }\n }\n\n return null;\n}\n\nfunction normalizePrefix(value: string): string {\n const withLeadingSlash = value.startsWith(\"/\") ? value : `/${value}`;\n return withLeadingSlash.length > 1\n ? withLeadingSlash.replace(/\\/+$/, \"\")\n : withLeadingSlash;\n}\n\n/**\n * Whether `url` is an editor URL this origin will actually route.\n *\n * The agent-server appends its own `vscode_base_path` to the origin we send it,\n * so the returned URL carries the prefix of the server that answered — not\n * necessarily the prefix this origin routes. An extra backend that configures\n * no prefix yields `<origin>/?tkn=…`, which is the canvas root: same origin,\n * wrong destination. Comparing paths is what separates the two.\n */\nexport function isVSCodeUrlServedByOrigin(\n url: string | null | undefined,\n basePath: string | null,\n): boolean {\n if (!url || !basePath) return false;\n\n let parsed: URL;\n try {\n parsed = new URL(\n url,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n );\n } catch {\n return false;\n }\n\n // A cross-origin URL is somebody else's problem to route, not ours to vouch\n // for. The local path always builds on `window.location.origin`, so this only\n // fires on a value we did not construct.\n if (\n typeof window !== \"undefined\" &&\n parsed.origin !== window.location.origin\n ) {\n return false;\n }\n\n return (\n parsed.pathname === basePath || parsed.pathname.startsWith(`${basePath}/`)\n );\n}\n"],"mappings":";AA2BA,IAAM,IAA8B;AAoBpC,SAAgB,IAAyC;CAIvD,IAAI,OAAO,SAAW,KAAa;EACjC,IAAM,IAAY,OAChB;EAEF,IAAI,OAAO,KAAa,YAAY,EAAS,KAAK,GAChD,OAAO,EAAgB,EAAS,KAAK,CAAC;CAE1C;CAEA,OAAO;AACT;AAEA,SAAS,EAAgB,GAAuB;CAC9C,IAAM,IAAmB,EAAM,WAAW,GAAG,IAAI,IAAQ,IAAI;CAC7D,OAAO,EAAiB,SAAS,IAC7B,EAAiB,QAAQ,QAAQ,EAAE,IACnC;AACN;AAWA,SAAgB,EACd,GACA,GACS;CACT,IAAI,CAAC,KAAO,CAAC,GAAU,OAAO;CAE9B,IAAI;CACJ,IAAI;EACF,IAAS,IAAI,IACX,GACA,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,KAAA,CACzD;CACF,QAAQ;EACN,OAAO;CACT;CAYA,OANE,OAAO,SAAW,OAClB,EAAO,WAAW,OAAO,SAAS,SAE3B,KAIP,EAAO,aAAa,KAAY,EAAO,SAAS,WAAW,GAAG,EAAS,EAAE;AAE7E"}
@@ -1,4 +1,8 @@
1
1
  import type { BackendKind } from "#/api/backend-registry/types";
2
2
  import type { WorkspaceMode } from "#/api/conversation-metadata-store";
3
3
  import { I18nKey } from "#/i18n/declaration";
4
+ export declare const DEFAULT_WORKSPACE_MODE: WorkspaceMode;
5
+ export declare const LAST_LOCAL_WORKSPACE_MODE_STORAGE_KEY = "openhands-last-local-workspace-mode";
6
+ export declare function readStoredLocalWorkspaceMode(): WorkspaceMode;
7
+ export declare function writeStoredLocalWorkspaceMode(mode: WorkspaceMode): void;
4
8
  export declare function getWorkspaceModeI18nKey(mode: WorkspaceMode, backendKind: BackendKind): I18nKey;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openhands/agent-canvas",
3
- "version": "1.15.0",
3
+ "version": "1.17.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,
@@ -17,14 +17,14 @@
17
17
  "agent-canvas": "bin/agent-canvas.mjs"
18
18
  },
19
19
  "engines": {
20
- "node": ">=22.12.0"
20
+ "node": ">=24"
21
21
  },
22
22
  "dependencies": {
23
23
  "@heroui/react": "2.8.10",
24
24
  "@microlink/react-json-view": "1.31.25",
25
25
  "@monaco-editor/react": "4.7.0",
26
- "@openhands/extensions": "0.18.0",
27
- "@openhands/typescript-client": "1.38.1",
26
+ "@openhands/extensions": "0.20.0",
27
+ "@openhands/typescript-client": "1.39.0",
28
28
  "@react-router/node": "7.18.2",
29
29
  "@react-router/serve": "7.18.2",
30
30
  "@tailwindcss/vite": "4.3.3",
@@ -187,7 +187,7 @@
187
187
  "@vercel/static-config": {
188
188
  "ajv": "8.20.0"
189
189
  },
190
- "dompurify": "3.4.12",
190
+ "dompurify": "3.4.14",
191
191
  "typed-rest-client": {
192
192
  "qs": "6.15.3"
193
193
  }
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * Usage:
21
21
  * node scripts/check-sdk-version-sync.mjs
22
- * EXPECTED_SDK_VERSION=1.42.1 node scripts/check-sdk-version-sync.mjs
22
+ * EXPECTED_SDK_VERSION=1.46.0 node scripts/check-sdk-version-sync.mjs
23
23
  * node scripts/check-sdk-version-sync.mjs --check-pypi
24
24
  *
25
25
  * Environment variables:
@@ -78,7 +78,7 @@ Triggering from other repos:
78
78
  -H "Authorization: token \$GITHUB_TOKEN" \\
79
79
  -H "Accept: application/vnd.github.v3+json" \\
80
80
  https://api.github.com/repos/OpenHands/OpenHands/dispatches \\
81
- -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.42.1"}}'
81
+ -d '{"event_type": "sdk-version-check", "client_payload": {"version": "1.46.0"}}'
82
82
  `);
83
83
  process.exit(0);
84
84
  }
@@ -260,9 +260,9 @@ async function fetchPyPIDependencies(packageName, version) {
260
260
  * Parse PyPI requires_dist array and extract SDK package versions
261
261
  *
262
262
  * PyPI returns dependencies in PEP 508 format like:
263
- * "openhands-sdk>=1.42.1,<2.0.0"
264
- * "openhands-tools==1.42.1"
265
- * "openhands-workspace (>=1.42.1)"
263
+ * "openhands-sdk>=1.46.0,<2.0.0"
264
+ * "openhands-tools==1.46.0"
265
+ * "openhands-workspace (>=1.46.0)"
266
266
  */
267
267
  function parseSdkVersionsFromRequiresDist(requiresDist) {
268
268
  const versions = {};
@@ -276,7 +276,7 @@ function parseSdkVersionsFromRequiresDist(requiresDist) {
276
276
  }
277
277
 
278
278
  // Extract the version number - look for patterns like:
279
- // ">=1.42.1", "==1.42.1", "(>=1.42.1)", "~=1.42.1"
279
+ // ">=1.46.0", "==1.46.0", "(>=1.46.0)", "~=1.46.0"
280
280
  // After the package name and before any comma or closing paren
281
281
  const versionPattern = /[><=~!]+\s*([0-9]+(?:\.[0-9]+)*)/;
282
282
  const match = dep.match(versionPattern);
@@ -60,6 +60,7 @@ const IDENTICAL_VALUE_ALLOWLIST = new Set([
60
60
  'SETTINGS$MCP_SERVER_TYPE_SSE',
61
61
  'SETTINGS$MCP_SERVER_TYPE_STDIO',
62
62
  'SETTINGS$NAV_LLM',
63
+ 'SETTINGS$OPENHANDS_API_KEY_HELP_LINK',
63
64
  'SETTINGS$SKILLS_PILLS_MORE',
64
65
  'SETTINGS$SKILLS_VERSION',
65
66
  'SETTINGS$SLACK',