@openhands/agent-canvas 1.15.0 → 1.16.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 (739) 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-CX3Lh9gj.js} +1 -1
  4. package/build/assets/active-backend-context-CrHTlgvN.js +2 -0
  5. package/build/assets/{agent-context-settings-D3PjSTU1.js → agent-context-settings-DSZlXrLj.js} +1 -1
  6. package/build/assets/{agent-profiles-settings-D4cY5U2T.js → agent-profiles-settings-Dzgb7G9z.js} +1 -1
  7. package/build/assets/agent-server-conversation-service.api-tnqNjbpE.js +86 -0
  8. package/build/assets/agent-settings-DLtsqaOs.js +2 -0
  9. package/build/assets/agent-settings-fFvR-XC2.js +1 -0
  10. package/build/assets/alert-banner-HP6mX-Vr.js +1 -0
  11. package/build/assets/{api-error-message-BJyfWp6p.js → api-error-message-B-XdSk3b.js} +1 -1
  12. package/build/assets/api-key-entry-screen-qTzrmJcr.js +1 -0
  13. package/build/assets/{app-settings-CbHqzQus.js → app-settings-dbnneVaV.js} +1 -1
  14. package/build/assets/automation-detail-BmwlCUAB.js +3 -0
  15. package/build/assets/{automation-export-BRopEHMu.js → automation-export-D3a3of4G.js} +1 -1
  16. package/build/assets/{automation-git-sync-CzyS4cn1.js → automation-git-sync-CprN5DcU.js} +1 -1
  17. package/build/assets/automation-setup-route-C40kXjMY.js +1 -0
  18. package/build/assets/{automation-templates-C_0FZgLG.js → automation-templates-BRppNh99.js} +1 -1
  19. package/build/assets/automations-list-DuNcRawl.js +1 -0
  20. package/build/assets/{back-nav-button-Dm9tIjVf.js → back-nav-button-Cjl_hoxq.js} +1 -1
  21. package/build/assets/backend-form-modal-lhGwzXFI.js +1 -0
  22. package/build/assets/{backend-synced-settings-badge-3fOwg6Bd.js → backend-synced-settings-badge-DPkz30BE.js} +1 -1
  23. package/build/assets/{badge-D4SqUCsR.js → badge-BU3S0VtE.js} +1 -1
  24. package/build/assets/{base-modal-C7_BDl_U.js → base-modal-D_L0oEbG.js} +1 -1
  25. package/build/assets/{bot-C-0Wu7vQ.js → bot-dMYHVfYM.js} +1 -1
  26. package/build/assets/{brand-button-Dxv6PDeN.js → brand-button-BAfk4wGP.js} +1 -1
  27. package/build/assets/browser-DSAo0tz1.js +46 -0
  28. package/build/assets/{browser-tab-BAl4ckJE.js → browser-tab-C9vy56R5.js} +1 -1
  29. package/build/assets/canvas-extension-page-dx1gFrfW.js +1 -0
  30. package/build/assets/canvas-extensions-8A-XhpgP.js +1 -0
  31. package/build/assets/canvas-extensions-runtime-2_x5Ezmi.js +1 -0
  32. package/build/assets/{chat-send-button-DWwR2cgI.js → chat-send-button-MUQqCZCS.js} +1 -1
  33. package/build/assets/check-CS0vmpQQ.js +1 -0
  34. package/build/assets/chevron-down-e1QBpjVy.js +1 -0
  35. package/build/assets/chevron-right-ZG4R5G4Q.js +1 -0
  36. package/build/assets/circle-check-DzWLNsbE.js +1 -0
  37. package/build/assets/{circle-plus-check-toggle-CBh_qomE.js → circle-plus-check-toggle-BO_kFZt3.js} +1 -1
  38. package/build/assets/{cloud-funnel-analytics-287iIERo.js → cloud-funnel-analytics-CztBCCPp.js} +1 -1
  39. package/build/assets/{cog-C4rrw-ZK.js → cog-D-MPQW6G.js} +1 -1
  40. package/build/assets/command-menu--UIlGL72.js +1 -0
  41. package/build/assets/{commits-tab-DZtJgaDM.js → commits-tab-AnZwLvh-.js} +1 -1
  42. package/build/assets/{condenser-settings-BcNmYR4s.js → condenser-settings-DmEOje-7.js} +1 -1
  43. package/build/assets/{confirmation-modal-Bk4JRcCM.js → confirmation-modal-Dv1ktp8K.js} +1 -1
  44. package/build/assets/{context-menu-list-item-lVYETtY5.js → context-menu-list-item-I86vKcmM.js} +1 -1
  45. package/build/assets/conversation-BbGrAO4Z.js +93 -0
  46. package/build/assets/conversation-mYT6NAoj.js +1 -0
  47. package/build/assets/conversation-panel-mYT6NAoj.js +1 -0
  48. package/build/assets/conversation-state-store-B0ImPLHO.js +1 -0
  49. package/build/assets/{conversation-tab-empty-state-HJtkmHZj.js → conversation-tab-empty-state-FIbh_lc8.js} +1 -1
  50. package/build/assets/{copy-to-clipboard-button-Cjkswvnj.js → copy-to-clipboard-button-Ca8iSkkA.js} +1 -1
  51. package/build/assets/{device-verify-EZhHhBT7.js → device-verify-Bhn2e_Ye.js} +1 -1
  52. package/build/assets/{dropdown-classes-DJe-E6MC.js → dropdown-classes-Bc1djN0-.js} +1 -1
  53. package/build/assets/{edit-automation-modal-D-urtv8n.js → edit-automation-modal-DadGbJ2u.js} +1 -1
  54. package/build/assets/empty-state-BoGVDecT.js +1 -0
  55. package/build/assets/{entry.client-C7Bi2tkU.js → entry.client-CqyPPjOq.js} +2 -2
  56. package/build/assets/{enum-filter-dropdown-DliX_Lo0.js → enum-filter-dropdown-Bgca129f.js} +1 -1
  57. package/build/assets/{environment-switch-overlay-CEKrFiMw.js → environment-switch-overlay-BmBRT7gv.js} +1 -1
  58. package/build/assets/{error-state-BALXiBNy.js → error-state-Body8Ngd.js} +1 -1
  59. package/build/assets/extensions-hub-CcDqq_vR.js +1 -0
  60. package/build/assets/extensions-navigation-Cr4yzYk4.js +1 -0
  61. package/build/assets/{external-link-DFpYunfj.js → external-link-DKUlnCQV.js} +1 -1
  62. package/build/assets/files-tab-D4o2VyE_.js +1 -0
  63. package/build/assets/{form-control-classes-CGw40z5h.js → form-control-classes-Bkh5FGrD.js} +1 -1
  64. package/build/assets/format-model-name-CasAP3nd.js +1 -0
  65. package/build/assets/get-git-path-ChKDVHZp.js +1 -0
  66. package/build/assets/{git-repo-dropdown-ai8qaNkD.js → git-repo-dropdown-4ROKl2cB.js} +1 -1
  67. package/build/assets/git-repo-dropdown-BkqzkMmM.js +1 -0
  68. package/build/assets/{highlighted-source-view-C3sxykQi.js → highlighted-source-view-BFRxGT_Q.js} +1 -1
  69. package/build/assets/home-ChpSuepX.js +1 -0
  70. package/build/assets/home-DIsB440S.js +1 -0
  71. package/build/assets/home-automation-run-tooltip-BVNDWjAH.js +1 -0
  72. package/build/assets/home-store-CY9Ej0ux.js +1 -0
  73. package/build/assets/index-home-BdlrFIif.js +1 -0
  74. package/build/assets/info-B6RQawoW.js +1 -0
  75. package/build/assets/install-server-modal-Dpy89p4g.js +1 -0
  76. package/build/assets/kebab-menu-item-content-D8hSNGmm.js +1 -0
  77. package/build/assets/{key-Cn5za3rg.js → key-BmVyxs-2.js} +1 -1
  78. package/build/assets/{launch-C1ieiOGe.js → launch-IrTDEFCs.js} +1 -1
  79. package/build/assets/list-filter-DsEK7NFC.js +1 -0
  80. package/build/assets/{list-todo-Cuu-STFc.js → list-todo-apgLVjMw.js} +1 -1
  81. package/build/assets/llm-not-configured-banner-CIFABh3K.js +27 -0
  82. package/build/assets/llm-settings-B9juXhIa.js +1 -0
  83. package/build/assets/llm-settings-De1d5dfr.js +1 -0
  84. package/build/assets/llm-subscription-service-BpJ0ouQo.js +1 -0
  85. package/build/assets/loader-circle-CC1au6hc.js +1 -0
  86. package/build/assets/{loading-spinner-0L3ZTToZ.js → loading-spinner-BY9N3pOe.js} +1 -1
  87. package/build/assets/manage-backends-modal-BrPV3oB-.js +1 -0
  88. package/build/assets/manifest-80fb1c29.js +1 -0
  89. package/build/assets/{manifest-subpage-layout-BGhiUQbA.js → manifest-subpage-layout-CAOYzrYp.js} +1 -1
  90. package/build/assets/{map-provider-B9LTm23I.js → map-provider-Cu3Zgumb.js} +1 -1
  91. package/build/assets/markdown-renderer-BzTlxI8x.js +8 -0
  92. package/build/assets/{mcp-CKbR4Vft.js → mcp-BTs_SXfZ.js} +1 -1
  93. package/build/assets/{mcp-marketplace-utils-C13fFccR.js → mcp-marketplace-utils-AIBzzHTO.js} +1 -1
  94. package/build/assets/{mcp-page-Bm4K2NQq.js → mcp-page-BEBYqH_K.js} +2 -2
  95. package/build/assets/messages-DKV9cRc2.js +41 -0
  96. package/build/assets/{modal-body-CMOc2tLl.js → modal-body-BxZjsju9.js} +1 -1
  97. package/build/assets/{modal-classes-BAb4Y_BG.js → modal-classes-C8eycCwG.js} +1 -1
  98. package/build/assets/{modal-close-button-CkJ0Ktjj.js → modal-close-button-DDzdRvCs.js} +1 -1
  99. package/build/assets/{mouse-pointer-click-CsgRs_-r.js → mouse-pointer-click-Co2uyaPA.js} +1 -1
  100. package/build/assets/onboarding-DV_OXoeP.js +1 -0
  101. package/build/assets/onboarding-modal-rkyBYkeQ.js +1 -0
  102. package/build/assets/{organization-service.api-C8XpQ0pM.js → organization-service.api-DrYNkEN_.js} +1 -1
  103. package/build/assets/{pencil-Clh1Wjvh.js → pencil-47jAZH_V.js} +1 -1
  104. package/build/assets/pin-By41Vl5J.js +1 -0
  105. package/build/assets/{planner-tab-DQvDU3ap.js → planner-tab-C9uZmhme.js} +1 -1
  106. package/build/assets/{plug-BuQhHSSG.js → plug-CG5HFcNG.js} +1 -1
  107. package/build/assets/plugins-management-service-BMJgC3Ga.js +1 -0
  108. package/build/assets/plus-C7Slq-0I.js +1 -0
  109. package/build/assets/profiles-service.api-ChoKrL0l.js +1 -0
  110. package/build/assets/providers-BhMcY5nv.js +1 -0
  111. package/build/assets/proxy-9Fe1v5na.js +1 -0
  112. package/build/assets/{puzzle-A9pGxxai.js → puzzle-JM_QaRm0.js} +1 -1
  113. package/build/assets/recommended-automations-launcher-6ABrI9Cy.js +1 -0
  114. package/build/assets/{refresh-cw-Bh69DyYO.js → refresh-cw-3q3Frrii.js} +1 -1
  115. package/build/assets/root-Dc8YmC9F.js +2 -0
  116. package/build/assets/root-VDaypvK4.css +1 -0
  117. package/build/assets/root-layout-CXkhSPYh.js +2 -0
  118. package/build/assets/schema-field-D-y9-LDb.js +1 -0
  119. package/build/assets/{sdk-section-page-HTffvm7Q.js → sdk-section-page-BlFiizlG.js} +1 -1
  120. package/build/assets/{secret-form-HTUbYw5o.js → secret-form-BB7the8W.js} +1 -1
  121. package/build/assets/secrets-service-ByZVENbp.js +1 -0
  122. package/build/assets/{secrets-settings-BizaTEr1.js → secrets-settings-B_GpxKW2.js} +1 -1
  123. package/build/assets/{settings-BlmrkwRi.js → settings-C0EWuBtA.js} +1 -1
  124. package/build/assets/settings-CKqk8ZnH.js +1 -0
  125. package/build/assets/{settings-dropdown-input-tM0A0ipy.js → settings-dropdown-input-BcwylHs2.js} +1 -1
  126. package/build/assets/{settings-index-CKq0b0Vg.js → settings-index-5w5UW2K3.js} +1 -1
  127. package/build/assets/{settings-input-C03KUoSC.js → settings-input-Db-1g8Ql.js} +1 -1
  128. package/build/assets/{settings-list-classes-BJ0g8rWj.js → settings-list-classes-BzeSZbF2.js} +1 -1
  129. package/build/assets/{settings-modal-AzEF1QPP.js → settings-modal-DfJ3tcJQ.js} +1 -1
  130. package/build/assets/settings-service.api-DJ1r62Zr.js +1 -0
  131. package/build/assets/{settings-switch-CQE0EGC-.js → settings-switch-CS-dJDmA.js} +1 -1
  132. package/build/assets/{settings-utils-ClYOkbbI.js → settings-utils-UYpEdPuD.js} +1 -1
  133. package/build/assets/shared-conversation-CA5ISEDy.js +1 -0
  134. package/build/assets/{shield-check-CFDViW82.js → shield-check-D2aCRd16.js} +1 -1
  135. package/build/assets/{sidebar-layout-D3hE08wK.js → sidebar-layout-D6fS8-Gl.js} +1 -1
  136. package/build/assets/{sidebar-mobile-menu-toggle-BOtyJHwE.js → sidebar-mobile-menu-toggle-C_fb0Jki.js} +1 -1
  137. package/build/assets/sidebar-nav-link-DQQcMf1A.js +1 -0
  138. package/build/assets/{sidebar-onboarding-checklist-storage-3qYflszY.js → sidebar-onboarding-checklist-storage-BBkeI6Bp.js} +1 -1
  139. package/build/assets/sidebar-store-DGqHkVLw.js +1 -0
  140. package/build/assets/{skill-card-pill-row-CFxjoqxn.js → skill-card-pill-row-B27-xyig.js} +1 -1
  141. package/build/assets/skill-enablement-DXeaImBz.js +1 -0
  142. package/build/assets/skill-filter-w__3UCEE.js +2 -0
  143. package/build/assets/{skill-icon-badge-CPQJ6A-I.js → skill-icon-badge-RQkq8wvl.js} +1 -1
  144. package/build/assets/skill-scope-B42H-XOc.js +1 -0
  145. package/build/assets/skills-plugins-tgF8EiXC.js +1 -0
  146. package/build/assets/skills-settings-BgJ9PaOe.js +1 -0
  147. package/build/assets/{styled-tooltip-Dl06rkpY.js → styled-tooltip-C4jf5Fv9.js} +1 -1
  148. package/build/assets/{task-list-tab-04GNQuii.js → task-list-tab-C5zcaktH.js} +1 -1
  149. package/build/assets/{terminal-Cj0iHIW7.js → terminal-CNElN42a.js} +2 -2
  150. package/build/assets/{toggle-switch-Fd_QGz0r.js → toggle-switch-ChOLXv2n.js} +1 -1
  151. package/build/assets/{trash-2-Dl8_RGz0.js → trash-2-D7K26eDO.js} +1 -1
  152. package/build/assets/{trash-_RMt7Ayc.js → trash-D-HYiVYM.js} +1 -1
  153. package/build/assets/{triangle-alert-SM-q4NU_.js → triangle-alert-CtdXWHUI.js} +1 -1
  154. package/build/assets/{typography-SgFy466J.js → typography-v1KN0tzi.js} +1 -1
  155. package/build/assets/usage-tab-CVDffLPt.js +1 -0
  156. package/build/assets/use-acp-credential-form-XIQmpX6M.js +1 -0
  157. package/build/assets/{use-activate-agent-profile-B2NS8nA5.js → use-activate-agent-profile-BLfmvDiG.js} +1 -1
  158. package/build/assets/use-agent-profiles-Bd9Bvvp1.js +1 -0
  159. package/build/assets/{use-automation-health-BxXdzZMP.js → use-automation-health-E6NZi9rb.js} +1 -1
  160. package/build/assets/{use-automations-zYb0dUny.js → use-automations-xijQKIl9.js} +1 -1
  161. package/build/assets/{use-can-manage-org-profiles-BWMahtUh.js → use-can-manage-org-profiles-CrJP5262.js} +1 -1
  162. package/build/assets/use-canvas-extensions-Bi693ujJ.js +1 -0
  163. package/build/assets/{use-cloud-current-user-id-CPHMDG-C.js → use-cloud-current-user-id-CDfAHpPX.js} +1 -1
  164. package/build/assets/use-config-A9QovgXO.js +1 -0
  165. package/build/assets/{use-create-conversation-DwN5vv2f.js → use-create-conversation-Dx3l7mFZ.js} +1 -1
  166. package/build/assets/use-create-secret-B9cUFWRG.js +1 -0
  167. package/build/assets/{use-get-secrets-BT4ihRwj.js → use-get-secrets-K3jmk-LH.js} +1 -1
  168. package/build/assets/use-is-authed-nTBcM7dE.js +1 -0
  169. package/build/assets/use-llm-configured-BV9nZ1_j.js +1 -0
  170. package/build/assets/use-llm-profiles-BO-P4Oyo.js +1 -0
  171. package/build/assets/use-manifest-capabilities-Cw_flwEz.js +1 -0
  172. package/build/assets/use-onboarding-completion-D8U7k4Qb.js +1 -0
  173. package/build/assets/use-pinned-home-route-CckOZrmb.js +1 -0
  174. package/build/assets/use-plugins-marketplace-7i94Zu3Z.js +1 -0
  175. package/build/assets/use-save-agent-profile-BUjSsDXK.js +1 -0
  176. package/build/assets/{use-save-settings-CUZW6yXP.js → use-save-settings-DYqkKv7T.js} +1 -1
  177. package/build/assets/{use-settings-C5VhGpqd.js → use-settings-DSXLbvBl.js} +1 -1
  178. package/build/assets/{use-settings-nav-items-DHaUu1Dg.js → use-settings-nav-items-CwRw-CmX.js} +1 -1
  179. package/build/assets/use-tracking-D53y3TH9.js +3 -0
  180. package/build/assets/{use-user-conversation-DT0_QCnL.js → use-user-conversation-B9Gebw_g.js} +1 -1
  181. package/build/assets/{useInfiniteQuery-CgeUQPfs.js → useInfiniteQuery-C926xzY4.js} +1 -1
  182. package/build/assets/{useMutation-DFnzkf6f.js → useMutation-B-qc391N.js} +1 -1
  183. package/build/assets/{useQueries-BhbrGEf1.js → useQueries-DlbhlH9I.js} +1 -1
  184. package/build/assets/{useQuery-BXWbZBZl.js → useQuery-BSTgq1rl.js} +1 -1
  185. package/build/assets/utils-CN5ZfZy1.js +1 -0
  186. package/build/assets/{vendor~conversation-panel~conversation-CTvDDiXg.js → vendor~conversation-panel~conversation-C8Fn4XOf.js} +1 -1
  187. package/build/assets/{vendor~entry.client-BFE7Llz9.js → vendor~entry.client-CoCfUXUF.js} +1 -1
  188. package/build/assets/{vendor~entry.client-BaKt_PIp.js → vendor~entry.client-DA2izTjq.js} +1 -1
  189. package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~kepq2zme-ZixYGy6E.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-DqZDXfg2.js} +1 -1
  190. package/build/assets/{vendor~index-home~home~conversation-panel~conversation-BTyukeM-.js → vendor~index-home~home~conversation-panel~conversation-hWywRBaR.js} +1 -1
  191. package/build/assets/{vendor~root-layout-BlUaZ18v.js → vendor~root-layout-C9Ju9DQg.js} +1 -1
  192. package/build/assets/{vendor~root-layout~conversation-panel~conversation-BYAWJwQX.js → vendor~root-layout~conversation-panel~conversation-BMbMgaGu.js} +1 -1
  193. 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-BWir3rJs.js} +1 -1
  194. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation-j5MFqfSy.js +1 -0
  195. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-cDuKr-WD.js +1 -0
  196. package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iw7io29p-Dz-MAyNb.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-Chf7vmKB.js} +1 -1
  197. 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~nj1hli3r-DP9wmsjo.js} +2 -2
  198. 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-CUmIwQCN.js} +117 -13
  199. 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
  200. package/build/assets/{verification-settings-Bj6bo097.js → verification-settings-gw_q6vkL.js} +1 -1
  201. package/build/assets/{wrench-hi7Q13dF.js → wrench-CUEI1krB.js} +1 -1
  202. package/build/assets/{x-DkgltWa0.js → x-DJdhbdmt.js} +1 -1
  203. package/build/index.html +4 -4
  204. package/build/locales/ar/openhands.json +32 -16
  205. package/build/locales/ca/openhands.json +32 -16
  206. package/build/locales/de/openhands.json +32 -16
  207. package/build/locales/en/openhands.json +32 -16
  208. package/build/locales/es/openhands.json +32 -16
  209. package/build/locales/fr/openhands.json +32 -16
  210. package/build/locales/it/openhands.json +32 -16
  211. package/build/locales/ja/openhands.json +32 -16
  212. package/build/locales/ko-KR/openhands.json +32 -16
  213. package/build/locales/no/openhands.json +32 -16
  214. package/build/locales/pt/openhands.json +32 -16
  215. package/build/locales/tr/openhands.json +32 -16
  216. package/build/locales/uk/openhands.json +32 -16
  217. package/build/locales/zh-CN/openhands.json +32 -16
  218. package/build/locales/zh-TW/openhands.json +32 -16
  219. package/config/defaults.json +9 -5
  220. package/dist/api/agent-profiles-service/profile-field-support.d.ts +26 -0
  221. package/dist/api/agent-server-adapter.cjs +3 -3
  222. package/dist/api/agent-server-adapter.cjs.map +1 -1
  223. package/dist/api/agent-server-adapter.js +118 -116
  224. package/dist/api/agent-server-adapter.js.map +1 -1
  225. package/dist/api/agent-server-compatibility.cjs +1 -1
  226. package/dist/api/agent-server-compatibility.cjs.map +1 -1
  227. package/dist/api/agent-server-compatibility.d.ts +21 -0
  228. package/dist/api/agent-server-compatibility.js +52 -38
  229. package/dist/api/agent-server-compatibility.js.map +1 -1
  230. package/dist/api/agent-server-config.cjs +1 -1
  231. package/dist/api/agent-server-config.cjs.map +1 -1
  232. package/dist/api/agent-server-config.d.ts +26 -0
  233. package/dist/api/agent-server-config.js +18 -5
  234. package/dist/api/agent-server-config.js.map +1 -1
  235. package/dist/api/canvas-extensions-service.cjs +1 -0
  236. package/dist/api/canvas-extensions-service.d.ts +22 -0
  237. package/dist/api/canvas-extensions-service.js +4 -0
  238. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  239. package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
  240. package/dist/api/cloud/conversation-service.api.d.ts +6 -0
  241. package/dist/api/cloud/conversation-service.api.js +14 -6
  242. package/dist/api/cloud/conversation-service.api.js.map +1 -1
  243. package/dist/api/conversation-file-upload.api.cjs +1 -1
  244. package/dist/api/conversation-file-upload.api.js +10 -10
  245. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  246. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  247. package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +11 -0
  248. package/dist/api/conversation-service/agent-server-conversation-service.api.js +129 -118
  249. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  250. package/dist/api/event-service/event-service.api.cjs +1 -1
  251. package/dist/api/event-service/event-service.api.js +12 -12
  252. package/dist/api/git-service/agent-server-git-service.api.cjs +1 -1
  253. package/dist/api/git-service/agent-server-git-service.api.js +8 -8
  254. package/dist/api/runtime-service/agent-server-runtime-service.cjs +1 -1
  255. package/dist/api/runtime-service/agent-server-runtime-service.js +8 -8
  256. package/dist/api/settings-service/settings-service.api.cjs +1 -1
  257. package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
  258. package/dist/api/settings-service/settings-service.api.d.ts +3 -2
  259. package/dist/api/settings-service/settings-service.api.js +2 -1
  260. package/dist/api/settings-service/settings-service.api.js.map +1 -1
  261. package/dist/components/conversation-events/chat/event-message-components/event-group.cjs +1 -1
  262. package/dist/components/conversation-events/chat/event-message-components/event-group.cjs.map +1 -1
  263. package/dist/components/conversation-events/chat/event-message-components/event-group.js +40 -36
  264. package/dist/components/conversation-events/chat/event-message-components/event-group.js.map +1 -1
  265. package/dist/components/features/automations/automation-card.cjs +1 -1
  266. package/dist/components/features/automations/automation-card.cjs.map +1 -1
  267. package/dist/components/features/automations/automation-card.js +114 -104
  268. package/dist/components/features/automations/automation-card.js.map +1 -1
  269. package/dist/components/features/automations/detail/run-phase.cjs +2 -0
  270. package/dist/components/features/automations/detail/run-phase.cjs.map +1 -0
  271. package/dist/components/features/automations/detail/run-phase.d.ts +89 -0
  272. package/dist/components/features/automations/detail/run-phase.js +72 -0
  273. package/dist/components/features/automations/detail/run-phase.js.map +1 -0
  274. package/dist/components/features/backends/backend-form-modal.cjs +1 -1
  275. package/dist/components/features/backends/backend-form-modal.cjs.map +1 -1
  276. package/dist/components/features/backends/backend-form-modal.js +5 -11
  277. package/dist/components/features/backends/backend-form-modal.js.map +1 -1
  278. package/dist/components/features/canvas-extensions/add-canvas-extension-modal.d.ts +6 -0
  279. package/dist/components/features/canvas-extensions/canvas-extension-card.d.ts +9 -0
  280. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs +2 -0
  281. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.cjs.map +1 -0
  282. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.d.ts +23 -0
  283. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js +19 -0
  284. package/dist/components/features/canvas-extensions/canvas-extensions-runtime.js.map +1 -0
  285. package/dist/components/features/chat/chat-interface.cjs +2 -2
  286. package/dist/components/features/chat/chat-interface.cjs.map +1 -1
  287. package/dist/components/features/chat/chat-interface.js +171 -168
  288. package/dist/components/features/chat/chat-interface.js.map +1 -1
  289. package/dist/components/features/chat/chat-markdown-path-code.cjs +3 -0
  290. package/dist/components/features/chat/chat-markdown-path-code.cjs.map +1 -0
  291. package/dist/components/features/chat/chat-markdown-path-code.d.ts +27 -0
  292. package/dist/components/features/chat/chat-markdown-path-code.js +72 -0
  293. package/dist/components/features/chat/chat-markdown-path-code.js.map +1 -0
  294. package/dist/components/features/chat/path-component.cjs +1 -1
  295. package/dist/components/features/chat/path-component.cjs.map +1 -1
  296. package/dist/components/features/chat/path-component.d.ts +8 -2
  297. package/dist/components/features/chat/path-component.js +33 -21
  298. package/dist/components/features/chat/path-component.js.map +1 -1
  299. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs +1 -1
  300. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.cjs.map +1 -1
  301. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js +38 -43
  302. package/dist/components/features/chat/tool-visualizers/file-editor/file-editor.js.map +1 -1
  303. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs +1 -1
  304. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.cjs.map +1 -1
  305. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.d.ts +8 -5
  306. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js +22 -16
  307. package/dist/components/features/chat/tool-visualizers/primitives/file-path-chip.js.map +1 -1
  308. package/dist/components/features/chat/user-message-body.cjs +1 -1
  309. package/dist/components/features/chat/user-message-body.cjs.map +1 -1
  310. package/dist/components/features/chat/user-message-body.d.ts +4 -0
  311. package/dist/components/features/chat/user-message-body.js +30 -24
  312. package/dist/components/features/chat/user-message-body.js.map +1 -1
  313. package/dist/components/features/conversation/conversation-overview-skills-panel.cjs +1 -1
  314. package/dist/components/features/conversation/conversation-overview-skills-panel.cjs.map +1 -1
  315. package/dist/components/features/conversation/conversation-overview-skills-panel.js +63 -81
  316. package/dist/components/features/conversation/conversation-overview-skills-panel.js.map +1 -1
  317. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
  318. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
  319. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +50 -50
  320. package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
  321. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs +1 -1
  322. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.cjs.map +1 -1
  323. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.d.ts +1 -1
  324. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js +3 -3
  325. package/dist/components/features/conversation/conversation-tabs/drawer-vscode-link.js.map +1 -1
  326. package/dist/components/features/conversation-panel/skills-modal.cjs +1 -1
  327. package/dist/components/features/conversation-panel/skills-modal.cjs.map +1 -1
  328. package/dist/components/features/conversation-panel/skills-modal.js +29 -28
  329. package/dist/components/features/conversation-panel/skills-modal.js.map +1 -1
  330. package/dist/components/features/files-tab/file-content-viewer.cjs +1 -1
  331. package/dist/components/features/files-tab/file-content-viewer.js +5 -5
  332. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
  333. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
  334. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +51 -29
  335. package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
  336. package/dist/components/features/onboarding/onboarding-host.d.ts +3 -4
  337. package/dist/components/features/onboarding/steps/setup-llm-step.d.ts +5 -9
  338. package/dist/components/features/settings/acp-auth-status-banner.d.ts +23 -6
  339. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
  340. package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +1 -0
  341. package/dist/components/features/settings/llm-profiles/provider-connection-modal.cjs +1 -1
  342. package/dist/components/features/settings/llm-profiles/provider-connection-modal.js +3 -0
  343. package/dist/components/features/settings/sdk-settings/field-help.cjs +1 -1
  344. package/dist/components/features/settings/sdk-settings/field-help.cjs.map +1 -1
  345. package/dist/components/features/settings/sdk-settings/field-help.d.ts +1 -1
  346. package/dist/components/features/settings/sdk-settings/field-help.js +1 -1
  347. package/dist/components/features/settings/sdk-settings/field-help.js.map +1 -1
  348. package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
  349. package/dist/components/features/settings/sdk-settings/sdk-section-page.js +6 -6
  350. package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
  351. package/dist/components/features/sidebar/sidebar-nav-link.cjs +1 -1
  352. package/dist/components/features/sidebar/sidebar-nav-link.cjs.map +1 -1
  353. package/dist/components/features/sidebar/sidebar-nav-link.d.ts +10 -1
  354. package/dist/components/features/sidebar/sidebar-nav-link.js +54 -36
  355. package/dist/components/features/sidebar/sidebar-nav-link.js.map +1 -1
  356. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  357. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  358. package/dist/components/features/sidebar/sidebar-rail-body.js +143 -120
  359. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  360. package/dist/components/features/sidebar/sidebar.cjs +1 -1
  361. package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
  362. package/dist/components/features/sidebar/sidebar.js +1 -1
  363. package/dist/components/features/sidebar/sidebar.js.map +1 -1
  364. package/dist/components/features/skills/build-skill-pills.cjs +1 -1
  365. package/dist/components/features/skills/build-skill-pills.cjs.map +1 -1
  366. package/dist/components/features/skills/build-skill-pills.js +60 -52
  367. package/dist/components/features/skills/build-skill-pills.js.map +1 -1
  368. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  369. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  370. package/dist/components/features/skills/extensions-navigation.js +54 -43
  371. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  372. package/dist/components/features/skills/skill-filter.cjs +1 -1
  373. package/dist/components/features/skills/skill-filter.cjs.map +1 -1
  374. package/dist/components/features/skills/skill-filter.d.ts +8 -3
  375. package/dist/components/features/skills/skill-filter.js +69 -52
  376. package/dist/components/features/skills/skill-filter.js.map +1 -1
  377. package/dist/components/shared/modals/settings/settings-form.cjs +1 -1
  378. package/dist/components/shared/modals/settings/settings-form.js +8 -8
  379. package/dist/config/defaults.cjs +1 -1
  380. package/dist/config/defaults.cjs.map +1 -1
  381. package/dist/config/defaults.js +9 -5
  382. package/dist/config/defaults.js.map +1 -1
  383. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  384. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  385. package/dist/contexts/conversation-websocket-context.js +5 -5
  386. package/dist/extensions/canvas-extension-module-loader.d.ts +11 -0
  387. package/dist/hooks/mutation/use-manage-canvas-extensions.d.ts +12 -0
  388. package/dist/hooks/query/concurrency-limiter.cjs +2 -0
  389. package/dist/hooks/query/concurrency-limiter.cjs.map +1 -0
  390. package/dist/hooks/query/concurrency-limiter.d.ts +22 -0
  391. package/dist/hooks/query/concurrency-limiter.js +29 -0
  392. package/dist/hooks/query/concurrency-limiter.js.map +1 -0
  393. package/dist/hooks/query/query-keys.cjs.map +1 -1
  394. package/dist/hooks/query/query-keys.d.ts +4 -0
  395. package/dist/hooks/query/query-keys.js.map +1 -1
  396. package/dist/hooks/query/use-active-conversation.cjs +1 -1
  397. package/dist/hooks/query/use-active-conversation.js +4 -4
  398. package/dist/hooks/query/use-automations.cjs.map +1 -1
  399. package/dist/hooks/query/use-automations.js.map +1 -1
  400. package/dist/hooks/query/use-backends-health.cjs +1 -1
  401. package/dist/hooks/query/use-backends-health.cjs.map +1 -1
  402. package/dist/hooks/query/use-backends-health.d.ts +1 -1
  403. package/dist/hooks/query/use-backends-health.js +50 -64
  404. package/dist/hooks/query/use-backends-health.js.map +1 -1
  405. package/dist/hooks/query/use-canvas-extensions.cjs +1 -0
  406. package/dist/hooks/query/use-canvas-extensions.d.ts +5 -0
  407. package/dist/hooks/query/use-canvas-extensions.js +3 -0
  408. package/dist/hooks/query/use-commit-changes.cjs +1 -1
  409. package/dist/hooks/query/use-commit-changes.js +4 -4
  410. package/dist/hooks/query/use-latest-automation-runs.cjs +1 -1
  411. package/dist/hooks/query/use-latest-automation-runs.js +1 -0
  412. package/dist/hooks/query/use-paginated-conversations.cjs +1 -1
  413. package/dist/hooks/query/use-paginated-conversations.cjs.map +1 -1
  414. package/dist/hooks/query/use-paginated-conversations.js +19 -16
  415. package/dist/hooks/query/use-paginated-conversations.js.map +1 -1
  416. package/dist/hooks/query/use-search-providers.cjs +1 -1
  417. package/dist/hooks/query/use-search-providers.cjs.map +1 -1
  418. package/dist/hooks/query/use-search-providers.js +17 -10
  419. package/dist/hooks/query/use-search-providers.js.map +1 -1
  420. package/dist/hooks/query/use-unified-get-git-changes.cjs +1 -1
  421. package/dist/hooks/query/use-unified-get-git-changes.js +4 -4
  422. package/dist/hooks/query/use-unified-git-commits.cjs +1 -1
  423. package/dist/hooks/query/use-unified-git-commits.js +4 -4
  424. package/dist/hooks/query/use-unified-git-diff.cjs +1 -1
  425. package/dist/hooks/query/use-unified-git-diff.js +4 -4
  426. package/dist/hooks/query/use-unified-vscode-url.cjs +1 -1
  427. package/dist/hooks/query/use-unified-vscode-url.cjs.map +1 -1
  428. package/dist/hooks/query/use-unified-vscode-url.d.ts +1 -0
  429. package/dist/hooks/query/use-unified-vscode-url.js +40 -26
  430. package/dist/hooks/query/use-unified-vscode-url.js.map +1 -1
  431. package/dist/hooks/query/use-workspace-file-content.cjs +1 -1
  432. package/dist/hooks/query/use-workspace-file-content.js +5 -5
  433. package/dist/hooks/query/use-workspace-files.cjs +1 -1
  434. package/dist/hooks/query/use-workspace-files.js +6 -6
  435. package/dist/hooks/use-acp-credential-form.d.ts +6 -0
  436. package/dist/hooks/use-conversation-overview-git-diff-stats.cjs +1 -1
  437. package/dist/hooks/use-conversation-overview-git-diff-stats.js +4 -4
  438. package/dist/hooks/use-pinned-home-route.cjs +2 -0
  439. package/dist/hooks/use-pinned-home-route.cjs.map +1 -0
  440. package/dist/hooks/use-pinned-home-route.d.ts +33 -0
  441. package/dist/hooks/use-pinned-home-route.js +34 -0
  442. package/dist/hooks/use-pinned-home-route.js.map +1 -0
  443. package/dist/hooks/use-skill-enablement.cjs +2 -0
  444. package/dist/hooks/use-skill-enablement.cjs.map +1 -0
  445. package/dist/hooks/use-skill-enablement.d.ts +14 -0
  446. package/dist/hooks/use-skill-enablement.js +80 -0
  447. package/dist/hooks/use-skill-enablement.js.map +1 -0
  448. package/dist/i18n/declaration.cjs +1 -1
  449. package/dist/i18n/declaration.cjs.map +1 -1
  450. package/dist/i18n/declaration.d.ts +29 -13
  451. package/dist/i18n/declaration.js +1 -1
  452. package/dist/i18n/declaration.js.map +1 -1
  453. package/dist/i18n/translation.cjs +3 -3
  454. package/dist/i18n/translation.cjs.map +1 -1
  455. package/dist/i18n/translation.js +538 -266
  456. package/dist/i18n/translation.js.map +1 -1
  457. package/dist/index.cjs +1 -1
  458. package/dist/index.js +15 -14
  459. package/dist/lib/index.cjs +1 -1
  460. package/dist/lib/index.d.ts +1 -0
  461. package/dist/lib/index.js +1 -0
  462. package/dist/locales/ar/openhands.json +32 -16
  463. package/dist/locales/ca/openhands.json +32 -16
  464. package/dist/locales/de/openhands.json +32 -16
  465. package/dist/locales/en/openhands.json +32 -16
  466. package/dist/locales/es/openhands.json +32 -16
  467. package/dist/locales/fr/openhands.json +32 -16
  468. package/dist/locales/it/openhands.json +32 -16
  469. package/dist/locales/ja/openhands.json +32 -16
  470. package/dist/locales/ko-KR/openhands.json +32 -16
  471. package/dist/locales/no/openhands.json +32 -16
  472. package/dist/locales/pt/openhands.json +32 -16
  473. package/dist/locales/tr/openhands.json +32 -16
  474. package/dist/locales/uk/openhands.json +32 -16
  475. package/dist/locales/zh-CN/openhands.json +32 -16
  476. package/dist/locales/zh-TW/openhands.json +32 -16
  477. package/dist/manifests/automation-interface.cjs +1 -1
  478. package/dist/manifests/automation-interface.cjs.map +1 -1
  479. package/dist/manifests/automation-interface.d.ts +6 -0
  480. package/dist/manifests/automation-interface.js +11 -8
  481. package/dist/manifests/automation-interface.js.map +1 -1
  482. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs +45 -4
  483. package/dist/node_modules/@openhands/extensions/automations/bundle-index.cjs.map +1 -1
  484. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js +1 -1
  485. package/dist/node_modules/@openhands/extensions/automations/bundle-index.js.map +1 -1
  486. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs +1 -1
  487. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.cjs.map +1 -1
  488. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js +5 -0
  489. package/dist/node_modules/@openhands/extensions/automations/catalog/github-agents-md-maintainer/manifest.js.map +1 -1
  490. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -1
  491. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
  492. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +5 -0
  493. package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
  494. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -1
  495. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
  496. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +5 -0
  497. package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
  498. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs +1 -1
  499. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.cjs.map +1 -1
  500. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js +5 -0
  501. package/dist/node_modules/@openhands/extensions/automations/catalog/github-repo-monitor/manifest.js.map +1 -1
  502. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs +9 -0
  503. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
  504. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js +21 -0
  505. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-bitbucket-pr/manifest.js.map +1 -0
  506. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs +9 -0
  507. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.cjs.map +1 -0
  508. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js +21 -0
  509. package/dist/node_modules/@openhands/extensions/automations/catalog/jira-issue-to-gitlab-mr/manifest.js.map +1 -0
  510. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs +9 -0
  511. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.cjs.map +1 -0
  512. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js +21 -0
  513. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-bitbucket-pr/manifest.js.map +1 -0
  514. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs +9 -0
  515. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.cjs.map +1 -0
  516. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js +21 -0
  517. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-github-pr/manifest.js.map +1 -0
  518. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs +9 -0
  519. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.cjs.map +1 -0
  520. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js +21 -0
  521. package/dist/node_modules/@openhands/extensions/automations/catalog/linear-issue-to-gitlab-mr/manifest.js.map +1 -0
  522. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs +1 -1
  523. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.cjs.map +1 -1
  524. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js +5 -0
  525. package/dist/node_modules/@openhands/extensions/automations/catalog/news-digest/manifest.js.map +1 -1
  526. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs +30 -0
  527. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs.map +1 -0
  528. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js +65 -0
  529. package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js.map +1 -0
  530. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
  531. package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
  532. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +21 -9
  533. package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
  534. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs +1 -1
  535. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.cjs.map +1 -1
  536. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js +2 -2
  537. package/dist/node_modules/@openhands/extensions/integrations/catalog/datadog.js.map +1 -1
  538. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs +2 -0
  539. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs.map +1 -0
  540. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js +40 -0
  541. package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js.map +1 -0
  542. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  543. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  544. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +1 -1
  545. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  546. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs +1 -1
  547. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.cjs.map +1 -1
  548. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js +74 -72
  549. package/dist/node_modules/@openhands/extensions/integrations/catalog-index.js.map +1 -1
  550. package/dist/node_modules/@openhands/extensions/skills/index.cjs +42 -3
  551. package/dist/node_modules/@openhands/extensions/skills/index.cjs.map +1 -1
  552. package/dist/node_modules/@openhands/extensions/skills/index.js +22 -3
  553. package/dist/node_modules/@openhands/extensions/skills/index.js.map +1 -1
  554. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.cjs +1 -1
  555. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-conversation.js +1 -1
  556. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs +1 -1
  557. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.cjs.map +1 -1
  558. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js +8 -7
  559. package/dist/node_modules/@openhands/typescript-client/dist/conversation/remote-state.js.map +1 -1
  560. package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
  561. package/dist/node_modules/@openhands/typescript-client/dist/index.js +2 -2
  562. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs +2 -0
  563. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.cjs.map +1 -0
  564. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js +16 -0
  565. package/dist/node_modules/lucide-react/dist/esm/icons/blocks.js.map +1 -0
  566. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs +2 -0
  567. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.cjs.map +1 -0
  568. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js +23 -0
  569. package/dist/node_modules/lucide-react/dist/esm/icons/panels-top-left.js.map +1 -0
  570. package/dist/package.cjs +1 -1
  571. package/dist/package.cjs.map +1 -1
  572. package/dist/package.js +3 -3
  573. package/dist/package.js.map +1 -1
  574. package/dist/routes/agent-settings.d.ts +10 -0
  575. package/dist/routes/app-settings.cjs +1 -1
  576. package/dist/routes/app-settings.cjs.map +1 -1
  577. package/dist/routes/app-settings.js +7 -7
  578. package/dist/routes/files-tab.cjs +1 -1
  579. package/dist/routes/files-tab.cjs.map +1 -1
  580. package/dist/routes/files-tab.js +14 -14
  581. package/dist/routes/files-tab.js.map +1 -1
  582. package/dist/routes/llm-settings.cjs +1 -1
  583. package/dist/routes/llm-settings.cjs.map +1 -1
  584. package/dist/routes/llm-settings.js +122 -114
  585. package/dist/routes/llm-settings.js.map +1 -1
  586. package/dist/services/canvas-ui.cjs +1 -1
  587. package/dist/services/canvas-ui.cjs.map +1 -1
  588. package/dist/services/canvas-ui.d.ts +5 -0
  589. package/dist/services/canvas-ui.js +24 -10
  590. package/dist/services/canvas-ui.js.map +1 -1
  591. package/dist/services/settings.cjs +1 -1
  592. package/dist/services/settings.cjs.map +1 -1
  593. package/dist/services/settings.js +3 -2
  594. package/dist/services/settings.js.map +1 -1
  595. package/dist/types/automation.cjs.map +1 -1
  596. package/dist/types/automation.d.ts +20 -0
  597. package/dist/types/automation.js.map +1 -1
  598. package/dist/types/canvas-extension.cjs +2 -0
  599. package/dist/types/canvas-extension.cjs.map +1 -0
  600. package/dist/types/canvas-extension.d.ts +77 -0
  601. package/dist/types/canvas-extension.js +6 -0
  602. package/dist/types/canvas-extension.js.map +1 -0
  603. package/dist/types/settings.d.ts +7 -0
  604. package/dist/ui/help-link.cjs +1 -1
  605. package/dist/ui/help-link.cjs.map +1 -1
  606. package/dist/ui/help-link.d.ts +6 -1
  607. package/dist/ui/help-link.js +32 -18
  608. package/dist/ui/help-link.js.map +1 -1
  609. package/dist/utils/acp-auth-display.d.ts +35 -0
  610. package/dist/utils/cache-utils.cjs +1 -1
  611. package/dist/utils/cache-utils.js +5 -5
  612. package/dist/utils/format-model-name.cjs +1 -1
  613. package/dist/utils/format-model-name.cjs.map +1 -1
  614. package/dist/utils/format-model-name.d.ts +7 -3
  615. package/dist/utils/format-model-name.js +6 -11
  616. package/dist/utils/format-model-name.js.map +1 -1
  617. package/dist/utils/format-relative-time.cjs +1 -1
  618. package/dist/utils/format-relative-time.cjs.map +1 -1
  619. package/dist/utils/format-relative-time.d.ts +7 -0
  620. package/dist/utils/format-relative-time.js +7 -2
  621. package/dist/utils/format-relative-time.js.map +1 -1
  622. package/dist/utils/path-utils.cjs +1 -1
  623. package/dist/utils/path-utils.cjs.map +1 -1
  624. package/dist/utils/path-utils.d.ts +15 -3
  625. package/dist/utils/path-utils.js +29 -3
  626. package/dist/utils/path-utils.js.map +1 -1
  627. package/dist/utils/skill-enablement.cjs +2 -0
  628. package/dist/utils/skill-enablement.cjs.map +1 -0
  629. package/dist/utils/skill-enablement.d.ts +51 -0
  630. package/dist/utils/skill-enablement.js +31 -0
  631. package/dist/utils/skill-enablement.js.map +1 -0
  632. package/dist/utils/vscode-origin.cjs +2 -0
  633. package/dist/utils/vscode-origin.cjs.map +1 -0
  634. package/dist/utils/vscode-origin.d.ts +55 -0
  635. package/dist/utils/vscode-origin.js +27 -0
  636. package/dist/utils/vscode-origin.js.map +1 -0
  637. package/dist/utils/workspace-mode.d.ts +4 -0
  638. package/package.json +3 -3
  639. package/scripts/check-sdk-version-sync.mjs +6 -6
  640. package/scripts/check-translation-completeness.cjs +1 -0
  641. package/scripts/dev-extra-backend.mjs +28 -9
  642. package/scripts/dev-safe.mjs +81 -8
  643. package/scripts/dev-static.mjs +35 -37
  644. package/scripts/dev-with-automation.mjs +82 -1
  645. package/scripts/ingress.mjs +27 -1
  646. package/scripts/static-server.mjs +74 -1
  647. package/tools/canvas_ui_tool.py +19 -0
  648. package/build/assets/active-backend-context-DKFSMbn3.js +0 -2
  649. package/build/assets/agent-server-conversation-service.api-DozDKIW_.js +0 -86
  650. package/build/assets/agent-settings-351vXWc9.js +0 -2
  651. package/build/assets/agent-settings-Ce7BDZ6I.js +0 -1
  652. package/build/assets/alert-banner-Kyy1YWZU.js +0 -1
  653. package/build/assets/api-key-entry-screen-INIxqAMs.js +0 -1
  654. package/build/assets/automation-detail-DXDhUwPq.js +0 -3
  655. package/build/assets/automation-setup-route-FRr05f_g.js +0 -1
  656. package/build/assets/automations-list-CERuQWE6.js +0 -1
  657. package/build/assets/backend-form-modal-DK78-jn1.js +0 -1
  658. package/build/assets/browser-11etCQ04.js +0 -7
  659. package/build/assets/check-Cf2YoT90.js +0 -1
  660. package/build/assets/chevron-down-C3OQ-ehx.js +0 -1
  661. package/build/assets/chevron-right-CN1uUiJ1.js +0 -1
  662. package/build/assets/circle-check-g5yeGMd-.js +0 -1
  663. package/build/assets/command-menu-BZQ8S3Ke.js +0 -1
  664. package/build/assets/conversation-CchMzpGl.js +0 -1
  665. package/build/assets/conversation-Dpzftz57.js +0 -93
  666. package/build/assets/conversation-panel-CchMzpGl.js +0 -1
  667. package/build/assets/conversation-state-store-a9d2fxRc.js +0 -1
  668. package/build/assets/empty-state-CvaVahVr.js +0 -1
  669. package/build/assets/extensions-hub-CFduxBnk.js +0 -1
  670. package/build/assets/extensions-navigation-BeC224yX.js +0 -1
  671. package/build/assets/files-tab-CL3J9b3p.js +0 -1
  672. package/build/assets/format-model-name-BNPKVsIq.js +0 -1
  673. package/build/assets/get-git-path-DlAJa_i6.js +0 -1
  674. package/build/assets/git-repo-dropdown-DGMEhz7d.js +0 -1
  675. package/build/assets/home-BCGlNJCA.js +0 -1
  676. package/build/assets/home-DB1pRqTC.js +0 -1
  677. package/build/assets/home-automation-run-tooltip-CooFQRIG.js +0 -1
  678. package/build/assets/home-store-Dl1dPE58.js +0 -1
  679. package/build/assets/index-home-DB1pRqTC.js +0 -1
  680. package/build/assets/info-uYSVzX86.js +0 -1
  681. package/build/assets/install-server-modal-BbJdhzet.js +0 -1
  682. package/build/assets/kebab-menu-item-content-BYokkRHi.js +0 -1
  683. package/build/assets/list-filter-OFkpRrmi.js +0 -1
  684. package/build/assets/llm-not-configured-banner-BqqYnJ1t.js +0 -27
  685. package/build/assets/llm-settings-CnDbbmVW.js +0 -1
  686. package/build/assets/llm-settings-S8Yjg__1.js +0 -1
  687. package/build/assets/llm-subscription-service-BpPfzW4x.js +0 -1
  688. package/build/assets/loader-circle-nvrwthvj.js +0 -1
  689. package/build/assets/manage-backends-modal-BCUPswyl.js +0 -1
  690. package/build/assets/manifest-58597dde.js +0 -1
  691. package/build/assets/markdown-renderer-Cb2sBWtV.js +0 -8
  692. package/build/assets/messages-BTN5thLe.js +0 -40
  693. package/build/assets/onboarding-Cx_kaiD1.js +0 -1
  694. package/build/assets/onboarding-modal-vMwn7ihv.js +0 -1
  695. package/build/assets/plugins-management-service-BjYeF0b0.js +0 -1
  696. package/build/assets/plus-CEKne-Yp.js +0 -1
  697. package/build/assets/profiles-service.api-QB-T_u-g.js +0 -1
  698. package/build/assets/providers-FfSZ5TXP.js +0 -1
  699. package/build/assets/proxy-tcFL2yTQ.js +0 -1
  700. package/build/assets/recommended-automations-launcher-Bw8uC4V6.js +0 -1
  701. package/build/assets/root-BLeQfBEq.css +0 -1
  702. package/build/assets/root-ZKKYPR1Z.js +0 -2
  703. package/build/assets/root-layout-luJoE9IG.js +0 -2
  704. package/build/assets/schema-field-Csw5fhtN.js +0 -1
  705. package/build/assets/secrets-service-BTor9uAU.js +0 -1
  706. package/build/assets/settings-DcNPxz0v.js +0 -1
  707. package/build/assets/settings-service.api-B2agVfjL.js +0 -1
  708. package/build/assets/shared-conversation-B55pCyBG.js +0 -1
  709. package/build/assets/sidebar-nav-link-CPzhyHQg.js +0 -1
  710. package/build/assets/sidebar-store-DtpU7zaI.js +0 -1
  711. package/build/assets/skill-filter-CWZ5kjcg.js +0 -2
  712. package/build/assets/skill-scope-CV1dkAbW.js +0 -1
  713. package/build/assets/skills-plugins-DGHULTq6.js +0 -1
  714. package/build/assets/skills-settings-CM1lFv3e.js +0 -1
  715. package/build/assets/usage-tab-BcfWV6db.js +0 -1
  716. package/build/assets/use-acp-credential-form-BsSW5NHG.js +0 -1
  717. package/build/assets/use-agent-profiles-DWBPC0Si.js +0 -1
  718. package/build/assets/use-config-Bft35DOK.js +0 -1
  719. package/build/assets/use-create-secret-BSxJMxHp.js +0 -1
  720. package/build/assets/use-is-authed-CFGkY3-Z.js +0 -1
  721. package/build/assets/use-llm-configured-BI6obxsc.js +0 -1
  722. package/build/assets/use-llm-profiles-djGAhTWL.js +0 -1
  723. package/build/assets/use-manifest-capabilities-3z0-1G59.js +0 -1
  724. package/build/assets/use-onboarding-completion-BXpyUSsJ.js +0 -1
  725. package/build/assets/use-plugins-marketplace-DI4_pK56.js +0 -1
  726. package/build/assets/use-save-agent-profile-DdBSTdpN.js +0 -1
  727. package/build/assets/use-tracking-D5t9otIF.js +0 -3
  728. package/build/assets/utils-DaCIEEQP.js +0 -1
  729. package/build/assets/vendor~index-home~home~conversation-panel~conversation~alert-banner-B3qC_oj8.js +0 -1
  730. package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-B2OLKL7N.js +0 -1
  731. package/dist/components/features/tips/random-tip.d.ts +0 -2
  732. package/dist/utils/tips.d.ts +0 -7
  733. package/dist/utils/workspace-relative-path.cjs +0 -2
  734. package/dist/utils/workspace-relative-path.cjs.map +0 -1
  735. package/dist/utils/workspace-relative-path.d.ts +0 -10
  736. package/dist/utils/workspace-relative-path.js +0 -22
  737. package/dist/utils/workspace-relative-path.js.map +0 -1
  738. /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-rfV8mQ9m.js} +0 -0
  739. /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":"conversation-tabs.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { LayoutGroup } from \"framer-motion\";\nimport { Gauge, Globe, ListTodo, SquareChevronRight } from \"lucide-react\";\nimport { LuFileDiff } from \"react-icons/lu\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { EllipsisButton } from \"#/components/features/conversation-panel/ellipsis-button\";\nimport { cn } from \"#/utils/utils\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport { ConversationTabNav } from \"./conversation-tab-nav\";\nimport { DrawerVSCodeLink } from \"./drawer-vscode-link\";\nimport { ChatActionTooltip } from \"../../chat/chat-action-tooltip\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { ConversationTabsContextMenu } from \"./conversation-tabs-context-menu\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useHandleBuildPlanClick } from \"#/hooks/use-handle-build-plan-click\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { Typography } from \"#/ui/typography\";\nimport { mobileTopBarIconClassName } from \"#/utils/mobile-top-bar-icon-button-classes\";\n\nexport function ConversationTabs({\n variant = \"default\",\n isPanelResizing = false,\n}: {\n variant?: \"default\" | \"compact\";\n /** True while the desktop drawer gripper is being dragged. */\n isPanelResizing?: boolean;\n}) {\n const { conversationId } = useConversationId();\n const { setSelectedTab, planContent } = useConversationStore();\n\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const { state: persistedState } =\n useConversationLocalStorageState(conversationId);\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const { handleBuildPlanClick } = useHandleBuildPlanClick();\n const { curAgentState } = useAgentState();\n\n const {\n selectTab,\n isTabActive,\n onTabChange,\n selectedTab,\n isRightPanelShown,\n } = useSelectConversationTab();\n\n // Restore the most-recently-used tab from localStorage so users don't\n // lose their tab selection across reloads.\n //\n // Note: we deliberately do NOT mirror `rightPanelShown` from\n // localStorage. The drawer's open/closed state is session-only — see\n // the comment in `useConversationStore` and the schema note in\n // `conversation-local-storage.ts` for the rationale.\n useEffect(() => {\n setSelectedTab(persistedState.selectedTab);\n }, [setSelectedTab, persistedState.selectedTab]);\n\n useEffect(() => {\n const handlePanelVisibilityChange = () => {\n if (isRightPanelShown) {\n // If no tab is selected, default to files tab\n if (!selectedTab) {\n onTabChange(\"files\");\n }\n }\n };\n\n handlePanelVisibilityChange();\n }, [isRightPanelShown, selectedTab, onTabChange]);\n\n const { t, i18n } = useTranslation(\"openhands\");\n\n // `files` is intentionally the leftmost tab — it's the primary entry\n // point for inspecting agent output (workspace files + git diff).\n const tabs = [\n {\n tabValue: \"files\",\n isActive: isTabActive(\"files\"),\n icon: DocumentIcon,\n onClick: () => selectTab(\"files\"),\n tooltipContent: t(I18nKey.COMMON$FILES),\n tooltipAriaLabel: t(I18nKey.COMMON$FILES),\n label: t(I18nKey.COMMON$FILES),\n },\n {\n tabValue: \"commits\",\n isActive: isTabActive(\"commits\"),\n icon: LuFileDiff,\n onClick: () => selectTab(\"commits\"),\n tooltipContent: t(I18nKey.DIFF_VIEWER$COMMITS),\n tooltipAriaLabel: t(I18nKey.DIFF_VIEWER$COMMITS),\n label: t(I18nKey.DIFF_VIEWER$COMMITS),\n },\n {\n tabValue: \"planner\",\n isActive: isTabActive(\"planner\"),\n icon: ListTodo,\n onClick: () => selectTab(\"planner\"),\n tooltipContent: t(I18nKey.COMMON$PLANNER),\n tooltipAriaLabel: t(I18nKey.COMMON$PLANNER),\n label: t(I18nKey.COMMON$PLANNER),\n },\n {\n tabValue: \"terminal\",\n isActive: isTabActive(\"terminal\"),\n icon: SquareChevronRight,\n onClick: () => selectTab(\"terminal\"),\n tooltipContent: t(I18nKey.COMMON$TERMINAL),\n tooltipAriaLabel: t(I18nKey.COMMON$TERMINAL),\n label: t(I18nKey.COMMON$TERMINAL),\n className: \"pl-2\",\n },\n {\n tabValue: \"browser\",\n isActive: isTabActive(\"browser\"),\n icon: Globe,\n onClick: () => selectTab(\"browser\"),\n tooltipContent: t(I18nKey.COMMON$BROWSER),\n tooltipAriaLabel: t(I18nKey.COMMON$BROWSER),\n label: t(I18nKey.COMMON$BROWSER),\n },\n {\n tabValue: \"usage\",\n isActive: isTabActive(\"usage\"),\n icon: Gauge,\n onClick: () => selectTab(\"usage\"),\n tooltipContent: t(I18nKey.COMMON$USAGE),\n tooltipAriaLabel: t(I18nKey.COMMON$USAGE),\n label: t(I18nKey.COMMON$USAGE),\n },\n ];\n\n if (hasTaskList) {\n // Insert after the file-related tabs.\n tabs.splice(2, 0, {\n tabValue: \"tasklist\",\n isActive: isTabActive(\"tasklist\"),\n icon: DoubleCheckIcon,\n onClick: () => selectTab(\"tasklist\"),\n tooltipContent: t(I18nKey.COMMON$TASK_LIST),\n tooltipAriaLabel: t(I18nKey.COMMON$TASK_LIST),\n label: t(I18nKey.COMMON$TASK_LIST),\n });\n }\n\n // Pinned tabs always show in the bar. Unpinned tabs stay hidden unless the\n // user has that tab selected — then it appears while active so the bar\n // matches the open panel. Hide Planner on local backends — the planning\n // agent isn't supported locally.\n const visibleTabs = tabs.filter((tab) => {\n if (tab.tabValue === \"planner\" && backend.kind !== \"cloud\") return false;\n if (!persistedState.unpinnedTabs.includes(tab.tabValue)) return true;\n return selectedTab === tab.tabValue;\n });\n\n const unpinnedSignature = persistedState.unpinnedTabs.join(\",\");\n\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n const isBuildDisabled = isAgentRunning || !planContent;\n\n const tabsRowInnerRef = useRef<HTMLDivElement>(null);\n const measureRowRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const vscodeButtonRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [inlineTabCount, setInlineTabCount] = useState(visibleTabs.length);\n\n useLayoutEffect(() => {\n const rowInner = tabsRowInnerRef.current;\n const measureRow = measureRowRef.current;\n const menuEl = menuRef.current;\n const vscodeEl = vscodeButtonRef.current;\n if (!rowInner || !measureRow || !menuEl || !vscodeEl) return undefined;\n\n const measure = () => {\n const measureButtons = measureRow.querySelectorAll<HTMLButtonElement>(\n '[data-tab-measure=\"true\"]',\n );\n const tabCount = measureButtons.length;\n\n const rowWidth = rowInner.getBoundingClientRect().width;\n if (rowWidth === 0) {\n setInlineTabCount(tabCount);\n return;\n }\n\n const widths = Array.from(measureButtons).map(\n (button) => button.getBoundingClientRect().width,\n );\n\n if (widths.length !== tabCount || tabCount === 0) {\n setInlineTabCount(Math.max(0, tabCount));\n return;\n }\n\n const menuWidth = menuEl.getBoundingClientRect().width;\n const vscodeWidth = vscodeEl.getBoundingClientRect().width;\n const gapCss =\n getComputedStyle(rowInner).columnGap || getComputedStyle(rowInner).gap;\n const gapPx = parseFloat(gapCss) || 6;\n\n let nextCount = 0;\n for (let k = tabCount; k >= 0; k -= 1) {\n let total = menuWidth + vscodeWidth;\n for (let i = 0; i < k; i += 1) {\n total += widths[i] ?? 0;\n }\n if (k > 0) {\n total += k * gapPx;\n }\n if (total <= rowWidth + 0.5) {\n nextCount = k;\n break;\n }\n }\n\n setInlineTabCount((prev) => (prev === nextCount ? prev : nextCount));\n };\n\n measure();\n if (typeof ResizeObserver === \"undefined\") return undefined;\n const ro = new ResizeObserver(measure);\n ro.observe(rowInner);\n return () => ro.disconnect();\n }, [\n unpinnedSignature,\n visibleTabs.length,\n hasTaskList,\n backend.kind,\n selectedTab,\n isRightPanelShown,\n i18n.language,\n ]);\n\n const safeInlineTabCount = Math.min(inlineTabCount, visibleTabs.length);\n\n return (\n <>\n <div\n className={cn(\n \"relative w-full min-w-0\",\n variant === \"compact\"\n ? \"flex h-full min-h-0 items-center py-0 pl-0 pr-1\"\n : \"min-h-10 p-1\",\n )}\n >\n <div\n ref={measureRowRef}\n aria-hidden\n className=\"pointer-events-none absolute top-0 left-[-10000px] flex flex-nowrap items-center gap-1.5\"\n >\n {visibleTabs.map(\n (\n {\n tabValue,\n icon,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`measure-${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={() => {}}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n measureOnly\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div\n ref={tabsRowInnerRef}\n className=\"flex w-full min-w-0 flex-nowrap items-center justify-start\"\n >\n <div className=\"flex min-w-0 flex-1 items-center justify-start overflow-hidden\">\n <div className=\"flex w-fit max-w-full min-w-0 items-center gap-1.5\">\n <LayoutGroup id=\"conversation-drawer-tabs\">\n <div className=\"flex w-fit max-w-full min-w-0 flex-nowrap items-center gap-1.5 overflow-x-hidden\">\n {visibleTabs\n .slice(0, safeInlineTabCount)\n .map(\n (\n {\n tabValue,\n icon,\n onClick,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={onClick}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n suppressLayoutAnimation={isPanelResizing}\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n </LayoutGroup>\n <div ref={menuRef} className=\"relative shrink-0\">\n <EllipsisButton\n ref={anchorRef}\n onClick={() => setIsMenuOpen(!isMenuOpen)}\n ariaLabel={t(I18nKey.COMMON$MORE_OPTIONS)}\n iconClassName={\n variant === \"compact\"\n ? mobileTopBarIconClassName\n : undefined\n }\n />\n <ConversationTabsContextMenu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n ignoreOutsideClickRef={anchorRef}\n anchorRef={anchorRef}\n />\n </div>\n </div>\n </div>\n {/* Keep the ref'd wrapper mounted on local backends too — the\n overflow measurement effect above bails if it's missing. */}\n <div\n ref={vscodeButtonRef}\n className={cn(\n \"ml-auto shrink-0\",\n backend.kind === \"cloud\" && \"pr-1\",\n )}\n >\n {backend.kind === \"cloud\" && <DrawerVSCodeLink />}\n </div>\n </div>\n </div>\n {isTabActive(\"planner\") && (\n <div\n className={cn(\n \"flex h-10 min-h-10 shrink-0 items-center border-t border-[var(--oh-border)] pl-[10px] pr-1\",\n )}\n >\n <button\n type=\"button\"\n onClick={handleBuildPlanClick}\n disabled={isBuildDisabled}\n className={cn(\n \"flex h-5 min-w-17 items-center justify-center rounded bg-white px-2 transition-opacity\",\n isBuildDisabled\n ? \"cursor-not-allowed opacity-50\"\n : \"cursor-pointer hover:opacity-90\",\n )}\n data-testid=\"planner-tab-build-button\"\n >\n <Typography.Text className=\"text-[11px] font-normal leading-5 text-black\">\n {/* eslint-disable-next-line i18next/no-literal-string */}\n {t(I18nKey.COMMON$BUILD)} ⌘↩\n </Typography.Text>\n </button>\n </div>\n )}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversation-tabs.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/conversation-tabs.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { LayoutGroup } from \"framer-motion\";\nimport { Gauge, Globe, ListTodo, SquareChevronRight } from \"lucide-react\";\nimport { LuFileDiff } from \"react-icons/lu\";\nimport DocumentIcon from \"#/icons/document.svg?react\";\nimport DoubleCheckIcon from \"#/icons/double-check.svg?react\";\nimport { EllipsisButton } from \"#/components/features/conversation-panel/ellipsis-button\";\nimport { cn } from \"#/utils/utils\";\nimport { useConversationLocalStorageState } from \"#/utils/conversation-local-storage\";\nimport { ConversationTabNav } from \"./conversation-tab-nav\";\nimport { DrawerVSCodeLink } from \"./drawer-vscode-link\";\nimport { ChatActionTooltip } from \"../../chat/chat-action-tooltip\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useConversationStore } from \"#/stores/conversation-store\";\nimport { ConversationTabsContextMenu } from \"./conversation-tabs-context-menu\";\nimport { useConversationId } from \"#/hooks/use-conversation-id\";\nimport { useSelectConversationTab } from \"#/hooks/use-select-conversation-tab\";\nimport { useTaskList } from \"#/hooks/use-task-list\";\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nimport { useHandleBuildPlanClick } from \"#/hooks/use-handle-build-plan-click\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { AgentState } from \"#/types/agent-state\";\nimport { Typography } from \"#/ui/typography\";\nimport { mobileTopBarIconClassName } from \"#/utils/mobile-top-bar-icon-button-classes\";\n\nexport function ConversationTabs({\n variant = \"default\",\n isPanelResizing = false,\n}: {\n variant?: \"default\" | \"compact\";\n /** True while the desktop drawer gripper is being dragged. */\n isPanelResizing?: boolean;\n}) {\n const { conversationId } = useConversationId();\n const { setSelectedTab, planContent } = useConversationStore();\n\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const { state: persistedState } =\n useConversationLocalStorageState(conversationId);\n\n const { hasTaskList } = useTaskList();\n const { backend } = useActiveBackend();\n\n const { handleBuildPlanClick } = useHandleBuildPlanClick();\n const { curAgentState } = useAgentState();\n\n const {\n selectTab,\n isTabActive,\n onTabChange,\n selectedTab,\n isRightPanelShown,\n } = useSelectConversationTab();\n\n // Restore the most-recently-used tab from localStorage so users don't\n // lose their tab selection across reloads.\n //\n // Note: we deliberately do NOT mirror `rightPanelShown` from\n // localStorage. The drawer's open/closed state is session-only — see\n // the comment in `useConversationStore` and the schema note in\n // `conversation-local-storage.ts` for the rationale.\n useEffect(() => {\n setSelectedTab(persistedState.selectedTab);\n }, [setSelectedTab, persistedState.selectedTab]);\n\n useEffect(() => {\n const handlePanelVisibilityChange = () => {\n if (isRightPanelShown) {\n // If no tab is selected, default to files tab\n if (!selectedTab) {\n onTabChange(\"files\");\n }\n }\n };\n\n handlePanelVisibilityChange();\n }, [isRightPanelShown, selectedTab, onTabChange]);\n\n const { t, i18n } = useTranslation(\"openhands\");\n\n // `files` is intentionally the leftmost tab — it's the primary entry\n // point for inspecting agent output (workspace files + git diff).\n const tabs = [\n {\n tabValue: \"files\",\n isActive: isTabActive(\"files\"),\n icon: DocumentIcon,\n onClick: () => selectTab(\"files\"),\n tooltipContent: t(I18nKey.COMMON$FILES),\n tooltipAriaLabel: t(I18nKey.COMMON$FILES),\n label: t(I18nKey.COMMON$FILES),\n },\n {\n tabValue: \"commits\",\n isActive: isTabActive(\"commits\"),\n icon: LuFileDiff,\n onClick: () => selectTab(\"commits\"),\n tooltipContent: t(I18nKey.DIFF_VIEWER$COMMITS),\n tooltipAriaLabel: t(I18nKey.DIFF_VIEWER$COMMITS),\n label: t(I18nKey.DIFF_VIEWER$COMMITS),\n },\n {\n tabValue: \"planner\",\n isActive: isTabActive(\"planner\"),\n icon: ListTodo,\n onClick: () => selectTab(\"planner\"),\n tooltipContent: t(I18nKey.COMMON$PLANNER),\n tooltipAriaLabel: t(I18nKey.COMMON$PLANNER),\n label: t(I18nKey.COMMON$PLANNER),\n },\n {\n tabValue: \"terminal\",\n isActive: isTabActive(\"terminal\"),\n icon: SquareChevronRight,\n onClick: () => selectTab(\"terminal\"),\n tooltipContent: t(I18nKey.COMMON$TERMINAL),\n tooltipAriaLabel: t(I18nKey.COMMON$TERMINAL),\n label: t(I18nKey.COMMON$TERMINAL),\n className: \"pl-2\",\n },\n {\n tabValue: \"browser\",\n isActive: isTabActive(\"browser\"),\n icon: Globe,\n onClick: () => selectTab(\"browser\"),\n tooltipContent: t(I18nKey.COMMON$BROWSER),\n tooltipAriaLabel: t(I18nKey.COMMON$BROWSER),\n label: t(I18nKey.COMMON$BROWSER),\n },\n {\n tabValue: \"usage\",\n isActive: isTabActive(\"usage\"),\n icon: Gauge,\n onClick: () => selectTab(\"usage\"),\n tooltipContent: t(I18nKey.COMMON$USAGE),\n tooltipAriaLabel: t(I18nKey.COMMON$USAGE),\n label: t(I18nKey.COMMON$USAGE),\n },\n ];\n\n if (hasTaskList) {\n // Insert after the file-related tabs.\n tabs.splice(2, 0, {\n tabValue: \"tasklist\",\n isActive: isTabActive(\"tasklist\"),\n icon: DoubleCheckIcon,\n onClick: () => selectTab(\"tasklist\"),\n tooltipContent: t(I18nKey.COMMON$TASK_LIST),\n tooltipAriaLabel: t(I18nKey.COMMON$TASK_LIST),\n label: t(I18nKey.COMMON$TASK_LIST),\n });\n }\n\n // Pinned tabs always show in the bar. Unpinned tabs stay hidden unless the\n // user has that tab selected — then it appears while active so the bar\n // matches the open panel. Hide Planner on local backends — the planning\n // agent isn't supported locally.\n const visibleTabs = tabs.filter((tab) => {\n if (tab.tabValue === \"planner\" && backend.kind !== \"cloud\") return false;\n if (!persistedState.unpinnedTabs.includes(tab.tabValue)) return true;\n return selectedTab === tab.tabValue;\n });\n\n const unpinnedSignature = persistedState.unpinnedTabs.join(\",\");\n\n const isAgentRunning =\n curAgentState === AgentState.RUNNING ||\n curAgentState === AgentState.LOADING;\n const isBuildDisabled = isAgentRunning || !planContent;\n\n const tabsRowInnerRef = useRef<HTMLDivElement>(null);\n const measureRowRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const vscodeButtonRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [inlineTabCount, setInlineTabCount] = useState(visibleTabs.length);\n\n useLayoutEffect(() => {\n const rowInner = tabsRowInnerRef.current;\n const measureRow = measureRowRef.current;\n const menuEl = menuRef.current;\n const vscodeEl = vscodeButtonRef.current;\n if (!rowInner || !measureRow || !menuEl || !vscodeEl) return undefined;\n\n const measure = () => {\n const measureButtons = measureRow.querySelectorAll<HTMLButtonElement>(\n '[data-tab-measure=\"true\"]',\n );\n const tabCount = measureButtons.length;\n\n const rowWidth = rowInner.getBoundingClientRect().width;\n if (rowWidth === 0) {\n setInlineTabCount(tabCount);\n return;\n }\n\n const widths = Array.from(measureButtons).map(\n (button) => button.getBoundingClientRect().width,\n );\n\n if (widths.length !== tabCount || tabCount === 0) {\n setInlineTabCount(Math.max(0, tabCount));\n return;\n }\n\n const menuWidth = menuEl.getBoundingClientRect().width;\n const vscodeWidth = vscodeEl.getBoundingClientRect().width;\n const gapCss =\n getComputedStyle(rowInner).columnGap || getComputedStyle(rowInner).gap;\n const gapPx = parseFloat(gapCss) || 6;\n\n let nextCount = 0;\n for (let k = tabCount; k >= 0; k -= 1) {\n let total = menuWidth + vscodeWidth;\n for (let i = 0; i < k; i += 1) {\n total += widths[i] ?? 0;\n }\n if (k > 0) {\n total += k * gapPx;\n }\n if (total <= rowWidth + 0.5) {\n nextCount = k;\n break;\n }\n }\n\n setInlineTabCount((prev) => (prev === nextCount ? prev : nextCount));\n };\n\n measure();\n if (typeof ResizeObserver === \"undefined\") return undefined;\n const ro = new ResizeObserver(measure);\n ro.observe(rowInner);\n // The editor button's presence is resolved asynchronously (the hook probes\n // /api/vscode/status), and it sits inside an `ml-auto shrink-0` wrapper, so\n // it appearing or disappearing does not change `rowInner`'s own box and\n // would not otherwise re-measure. Its width is folded into the fit\n // calculation above, so a stale value permanently costs an inline tab.\n ro.observe(vscodeEl);\n return () => ro.disconnect();\n }, [\n unpinnedSignature,\n visibleTabs.length,\n hasTaskList,\n backend.kind,\n selectedTab,\n isRightPanelShown,\n i18n.language,\n ]);\n\n const safeInlineTabCount = Math.min(inlineTabCount, visibleTabs.length);\n\n return (\n <>\n <div\n className={cn(\n \"relative w-full min-w-0\",\n variant === \"compact\"\n ? \"flex h-full min-h-0 items-center py-0 pl-0 pr-1\"\n : \"min-h-10 p-1\",\n )}\n >\n <div\n ref={measureRowRef}\n aria-hidden\n className=\"pointer-events-none absolute top-0 left-[-10000px] flex flex-nowrap items-center gap-1.5\"\n >\n {visibleTabs.map(\n (\n {\n tabValue,\n icon,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`measure-${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={() => {}}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n measureOnly\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n <div\n ref={tabsRowInnerRef}\n className=\"flex w-full min-w-0 flex-nowrap items-center justify-start\"\n >\n <div className=\"flex min-w-0 flex-1 items-center justify-start overflow-hidden\">\n <div className=\"flex w-fit max-w-full min-w-0 items-center gap-1.5\">\n <LayoutGroup id=\"conversation-drawer-tabs\">\n <div className=\"flex w-fit max-w-full min-w-0 flex-nowrap items-center gap-1.5 overflow-x-hidden\">\n {visibleTabs\n .slice(0, safeInlineTabCount)\n .map(\n (\n {\n tabValue,\n icon,\n onClick,\n isActive,\n tooltipContent,\n tooltipAriaLabel,\n label,\n className: tabClassName,\n },\n index,\n ) => (\n <ChatActionTooltip\n key={`${tabValue}-${index}`}\n tooltip={tooltipContent}\n ariaLabel={tooltipAriaLabel}\n >\n <ConversationTabNav\n tabValue={tabValue}\n icon={icon}\n onClick={onClick}\n isActive={isActive}\n label={label}\n className={cn(tabClassName, \"shrink-0\")}\n suppressLayoutAnimation={isPanelResizing}\n />\n </ChatActionTooltip>\n ),\n )}\n </div>\n </LayoutGroup>\n <div ref={menuRef} className=\"relative shrink-0\">\n <EllipsisButton\n ref={anchorRef}\n onClick={() => setIsMenuOpen(!isMenuOpen)}\n ariaLabel={t(I18nKey.COMMON$MORE_OPTIONS)}\n iconClassName={\n variant === \"compact\"\n ? mobileTopBarIconClassName\n : undefined\n }\n />\n <ConversationTabsContextMenu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n ignoreOutsideClickRef={anchorRef}\n anchorRef={anchorRef}\n />\n </div>\n </div>\n </div>\n {/* The ref'd wrapper must stay mounted — the overflow measurement\n effect above bails if it's missing. */}\n <div ref={vscodeButtonRef} className=\"ml-auto shrink-0 pr-1\">\n <DrawerVSCodeLink />\n </div>\n </div>\n </div>\n {isTabActive(\"planner\") && (\n <div\n className={cn(\n \"flex h-10 min-h-10 shrink-0 items-center border-t border-[var(--oh-border)] pl-[10px] pr-1\",\n )}\n >\n <button\n type=\"button\"\n onClick={handleBuildPlanClick}\n disabled={isBuildDisabled}\n className={cn(\n \"flex h-5 min-w-17 items-center justify-center rounded bg-white px-2 transition-opacity\",\n isBuildDisabled\n ? \"cursor-not-allowed opacity-50\"\n : \"cursor-pointer hover:opacity-90\",\n )}\n data-testid=\"planner-tab-build-button\"\n >\n <Typography.Text className=\"text-[11px] font-normal leading-5 text-black\">\n {/* eslint-disable-next-line i18next/no-literal-string */}\n {t(I18nKey.COMMON$BUILD)} ⌘↩\n </Typography.Text>\n </button>\n </div>\n )}\n </>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../../i18n/declaration.cjs"),n=require("../../../../node_modules/lucide-react/dist/esm/icons/external-link.cjs"),r=require("../../../../types/agent-state.cjs"),i=require("../../../../utils/utils.cjs"),a=require("../../../../hooks/use-agent-state.cjs"),o=require("../../../../icons/vscode.cjs"),s=require("../../../../hooks/query/use-unified-vscode-url.cjs");let c=require("react/jsx-runtime");function l(){let{t:l}=e.useTranslation(`openhands`),{curAgentState:u}=a.useAgentState(),{data:d,refetch:f,isLoading:p}=s.useUnifiedVSCodeUrl(),m=r.RUNTIME_STARTING_STATES.includes(u);return(0,c.jsxs)(`button`,{type:`button`,onClick:async()=>{let e=d?.url;e||=(await f()).data?.url??null,e&&window.open(e,`_blank`,`noopener,noreferrer`)},disabled:p||m,"aria-label":l(t.I18nKey.VSCODE$OPEN),title:l(t.I18nKey.VSCODE$OPEN),"data-testid":`drawer-vscode-link`,className:i.cn(`inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs`,`text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white`,`cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`),children:[(0,c.jsx)(o.default,{className:`h-[15px] w-[15px] shrink-0`,"aria-hidden":!0}),(0,c.jsx)(`span`,{children:l(t.I18nKey.FILES$VSCODE)}),(0,c.jsx)(n.ExternalLink,{className:`h-3.5 w-3.5 shrink-0`,"aria-hidden":!0,strokeWidth:2})]})}exports.DrawerVSCodeLink=l;
1
+ require("../../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../../i18n/declaration.cjs"),n=require("../../../../node_modules/lucide-react/dist/esm/icons/external-link.cjs"),r=require("../../../../types/agent-state.cjs"),i=require("../../../../utils/utils.cjs"),a=require("../../../../hooks/use-agent-state.cjs"),o=require("../../../../icons/vscode.cjs"),s=require("../../../../hooks/query/use-unified-vscode-url.cjs");let c=require("react/jsx-runtime");function l(){let{t:l}=e.useTranslation(`openhands`),{curAgentState:u}=a.useAgentState(),{data:d,refetch:f,isLoading:p,isUnavailable:m}=s.useUnifiedVSCodeUrl(),h=r.RUNTIME_STARTING_STATES.includes(u);return m?null:(0,c.jsxs)(`button`,{type:`button`,onClick:async()=>{let e=d?.url;e||=(await f()).data?.url??null,e&&window.open(e,`_blank`,`noopener,noreferrer`)},disabled:p||h,"aria-label":l(t.I18nKey.VSCODE$OPEN),title:l(t.I18nKey.VSCODE$OPEN),"data-testid":`drawer-vscode-link`,className:i.cn(`inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs`,`text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white`,`cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`),children:[(0,c.jsx)(o.default,{className:`h-[15px] w-[15px] shrink-0`,"aria-hidden":!0}),(0,c.jsx)(`span`,{children:l(t.I18nKey.FILES$VSCODE)}),(0,c.jsx)(n.ExternalLink,{className:`h-3.5 w-3.5 shrink-0`,"aria-hidden":!0,strokeWidth:2})]})}exports.DrawerVSCodeLink=l;
2
2
  //# sourceMappingURL=drawer-vscode-link.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"drawer-vscode-link.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/drawer-vscode-link.tsx"],"sourcesContent":["import { ExternalLink } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useUnifiedVSCodeUrl } from \"#/hooks/query/use-unified-vscode-url\";\nimport { RUNTIME_STARTING_STATES } from \"#/types/agent-state\";\nimport { cn } from \"#/utils/utils\";\n\nexport function DrawerVSCodeLink() {\n const { t } = useTranslation(\"openhands\");\n const { curAgentState } = useAgentState();\n const { data, refetch, isLoading } = useUnifiedVSCodeUrl();\n const isRuntimeStarting = RUNTIME_STARTING_STATES.includes(curAgentState);\n\n const handleClick = async () => {\n let vscodeUrl = data?.url;\n\n if (!vscodeUrl) {\n const result = await refetch();\n vscodeUrl = result.data?.url ?? null;\n }\n\n if (vscodeUrl) {\n window.open(vscodeUrl, \"_blank\", \"noopener,noreferrer\");\n }\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isLoading || isRuntimeStarting}\n aria-label={t(I18nKey.VSCODE$OPEN)}\n title={t(I18nKey.VSCODE$OPEN)}\n data-testid=\"drawer-vscode-link\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs\",\n \"text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white\",\n \"cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n <VSCodeIcon className=\"h-[15px] w-[15px] shrink-0\" aria-hidden />\n <span>{t(I18nKey.FILES$VSCODE)}</span>\n <ExternalLink\n className=\"h-3.5 w-3.5 shrink-0\"\n aria-hidden\n strokeWidth={2}\n />\n </button>\n );\n}\n"],"mappings":"qiBASA,SAAgB,GAAmB,CACjC,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,CAAE,iBAAkB,EAAA,cAAc,EAClC,CAAE,OAAM,UAAS,aAAc,EAAA,oBAAoB,EACnD,EAAoB,EAAA,wBAAwB,SAAS,CAAa,EAexE,OACE,EAAA,EAAA,MAAC,SAAD,CACE,KAAK,SACL,QAAS,SAhBmB,CAC9B,IAAI,EAAY,GAAM,IAEtB,AAEE,KAAY,MADS,EAAQ,GACV,MAAM,KAAO,KAG9B,GACF,OAAO,KAAK,EAAW,SAAU,qBAAqB,CAE1D,EAMI,SAAU,GAAa,EACvB,aAAY,EAAE,EAAA,QAAQ,WAAW,EACjC,MAAO,EAAE,EAAA,QAAQ,WAAW,EAC5B,cAAY,qBACZ,UAAW,EAAA,GACT,sHACA,oGACA,gEACF,WAXF,EAaE,EAAA,EAAA,KAAC,EAAA,QAAD,CAAY,UAAU,6BAA6B,cAAA,EAAa,CAAA,GAChE,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAE,EAAA,QAAQ,YAAY,CAAQ,CAAA,GACrC,EAAA,EAAA,KAAC,EAAA,aAAD,CACE,UAAU,uBACV,cAAA,GACA,YAAa,CACd,CAAA,CACK,GAEZ"}
1
+ {"version":3,"file":"drawer-vscode-link.cjs","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/drawer-vscode-link.tsx"],"sourcesContent":["import { ExternalLink } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useUnifiedVSCodeUrl } from \"#/hooks/query/use-unified-vscode-url\";\nimport { RUNTIME_STARTING_STATES } from \"#/types/agent-state\";\nimport { cn } from \"#/utils/utils\";\n\nexport function DrawerVSCodeLink() {\n const { t } = useTranslation(\"openhands\");\n const { curAgentState } = useAgentState();\n const { data, refetch, isLoading, isUnavailable } = useUnifiedVSCodeUrl();\n const isRuntimeStarting = RUNTIME_STARTING_STATES.includes(curAgentState);\n\n const handleClick = async () => {\n let vscodeUrl = data?.url;\n\n if (!vscodeUrl) {\n const result = await refetch();\n vscodeUrl = result.data?.url ?? null;\n }\n\n if (vscodeUrl) {\n window.open(vscodeUrl, \"_blank\", \"noopener,noreferrer\");\n }\n };\n\n // Backends that report no editor to open — `enable_vscode: false`, a\n // configured editor whose process is not running, or no URL reported — get\n // no button rather than one that does nothing when clicked.\n if (isUnavailable) {\n return null;\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isLoading || isRuntimeStarting}\n aria-label={t(I18nKey.VSCODE$OPEN)}\n title={t(I18nKey.VSCODE$OPEN)}\n data-testid=\"drawer-vscode-link\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs\",\n \"text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white\",\n \"cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n <VSCodeIcon className=\"h-[15px] w-[15px] shrink-0\" aria-hidden />\n <span>{t(I18nKey.FILES$VSCODE)}</span>\n <ExternalLink\n className=\"h-3.5 w-3.5 shrink-0\"\n aria-hidden\n strokeWidth={2}\n />\n </button>\n );\n}\n"],"mappings":"qiBASA,SAAgB,GAAmB,CACjC,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,CAAE,iBAAkB,EAAA,cAAc,EAClC,CAAE,OAAM,UAAS,YAAW,iBAAkB,EAAA,oBAAoB,EAClE,EAAoB,EAAA,wBAAwB,SAAS,CAAa,EAsBxE,OAJI,EACK,MAIP,EAAA,EAAA,MAAC,SAAD,CACE,KAAK,SACL,QAAS,SAvBmB,CAC9B,IAAI,EAAY,GAAM,IAEtB,AAEE,KAAY,MADS,EAAQ,GACV,MAAM,KAAO,KAG9B,GACF,OAAO,KAAK,EAAW,SAAU,qBAAqB,CAE1D,EAaI,SAAU,GAAa,EACvB,aAAY,EAAE,EAAA,QAAQ,WAAW,EACjC,MAAO,EAAE,EAAA,QAAQ,WAAW,EAC5B,cAAY,qBACZ,UAAW,EAAA,GACT,sHACA,oGACA,gEACF,WAXF,EAaE,EAAA,EAAA,KAAC,EAAA,QAAD,CAAY,UAAU,6BAA6B,cAAA,EAAa,CAAA,GAChE,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAE,EAAA,QAAQ,YAAY,CAAQ,CAAA,GACrC,EAAA,EAAA,KAAC,EAAA,aAAD,CACE,UAAU,uBACV,cAAA,GACA,YAAa,CACd,CAAA,CACK,GAEZ"}
@@ -1 +1 @@
1
- export declare function DrawerVSCodeLink(): import("react").JSX.Element;
1
+ export declare function DrawerVSCodeLink(): import("react").JSX.Element | null;
@@ -9,14 +9,14 @@ import { useUnifiedVSCodeUrl as s } from "../../../../hooks/query/use-unified-vs
9
9
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
10
10
  //#region src/components/features/conversation/conversation-tabs/drawer-vscode-link.tsx
11
11
  function u() {
12
- let { t: u } = e("openhands"), { curAgentState: d } = a(), { data: f, refetch: p, isLoading: m } = s(), h = r.includes(d);
13
- return /* @__PURE__ */ l("button", {
12
+ let { t: u } = e("openhands"), { curAgentState: d } = a(), { data: f, refetch: p, isLoading: m, isUnavailable: h } = s(), g = r.includes(d);
13
+ return h ? null : /* @__PURE__ */ l("button", {
14
14
  type: "button",
15
15
  onClick: async () => {
16
16
  let e = f?.url;
17
17
  e ||= (await p()).data?.url ?? null, e && window.open(e, "_blank", "noopener,noreferrer");
18
18
  },
19
- disabled: m || h,
19
+ disabled: m || g,
20
20
  "aria-label": u(t.VSCODE$OPEN),
21
21
  title: u(t.VSCODE$OPEN),
22
22
  "data-testid": "drawer-vscode-link",
@@ -1 +1 @@
1
- {"version":3,"file":"drawer-vscode-link.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/drawer-vscode-link.tsx"],"sourcesContent":["import { ExternalLink } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useUnifiedVSCodeUrl } from \"#/hooks/query/use-unified-vscode-url\";\nimport { RUNTIME_STARTING_STATES } from \"#/types/agent-state\";\nimport { cn } from \"#/utils/utils\";\n\nexport function DrawerVSCodeLink() {\n const { t } = useTranslation(\"openhands\");\n const { curAgentState } = useAgentState();\n const { data, refetch, isLoading } = useUnifiedVSCodeUrl();\n const isRuntimeStarting = RUNTIME_STARTING_STATES.includes(curAgentState);\n\n const handleClick = async () => {\n let vscodeUrl = data?.url;\n\n if (!vscodeUrl) {\n const result = await refetch();\n vscodeUrl = result.data?.url ?? null;\n }\n\n if (vscodeUrl) {\n window.open(vscodeUrl, \"_blank\", \"noopener,noreferrer\");\n }\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isLoading || isRuntimeStarting}\n aria-label={t(I18nKey.VSCODE$OPEN)}\n title={t(I18nKey.VSCODE$OPEN)}\n data-testid=\"drawer-vscode-link\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs\",\n \"text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white\",\n \"cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n <VSCodeIcon className=\"h-[15px] w-[15px] shrink-0\" aria-hidden />\n <span>{t(I18nKey.FILES$VSCODE)}</span>\n <ExternalLink\n className=\"h-3.5 w-3.5 shrink-0\"\n aria-hidden\n strokeWidth={2}\n />\n </button>\n );\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,IAAmB;CACjC,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,EAAE,qBAAkB,EAAc,GAClC,EAAE,SAAM,YAAS,iBAAc,EAAoB,GACnD,IAAoB,EAAwB,SAAS,CAAa;CAexE,OACE,kBAAC,UAAD;EACE,MAAK;EACL,SAAS,YAhBmB;GAC9B,IAAI,IAAY,GAAM;GAOtB,AALA,AAEE,OAAY,MADS,EAAQ,GACV,MAAM,OAAO,MAG9B,KACF,OAAO,KAAK,GAAW,UAAU,qBAAqB;EAE1D;EAMI,UAAU,KAAa;EACvB,cAAY,EAAE,EAAQ,WAAW;EACjC,OAAO,EAAE,EAAQ,WAAW;EAC5B,eAAY;EACZ,WAAW,EACT,uHACA,qGACA,gEACF;YAXF;GAaE,kBAAC,GAAD;IAAY,WAAU;IAA6B,eAAA;GAAa,CAAA;GAChE,kBAAC,QAAD,EAAA,UAAO,EAAE,EAAQ,YAAY,EAAQ,CAAA;GACrC,kBAAC,GAAD;IACE,WAAU;IACV,eAAA;IACA,aAAa;GACd,CAAA;EACK;;AAEZ"}
1
+ {"version":3,"file":"drawer-vscode-link.js","names":[],"sources":["../../../../../src/components/features/conversation/conversation-tabs/drawer-vscode-link.tsx"],"sourcesContent":["import { ExternalLink } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport VSCodeIcon from \"#/icons/vscode.svg?react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { useAgentState } from \"#/hooks/use-agent-state\";\nimport { useUnifiedVSCodeUrl } from \"#/hooks/query/use-unified-vscode-url\";\nimport { RUNTIME_STARTING_STATES } from \"#/types/agent-state\";\nimport { cn } from \"#/utils/utils\";\n\nexport function DrawerVSCodeLink() {\n const { t } = useTranslation(\"openhands\");\n const { curAgentState } = useAgentState();\n const { data, refetch, isLoading, isUnavailable } = useUnifiedVSCodeUrl();\n const isRuntimeStarting = RUNTIME_STARTING_STATES.includes(curAgentState);\n\n const handleClick = async () => {\n let vscodeUrl = data?.url;\n\n if (!vscodeUrl) {\n const result = await refetch();\n vscodeUrl = result.data?.url ?? null;\n }\n\n if (vscodeUrl) {\n window.open(vscodeUrl, \"_blank\", \"noopener,noreferrer\");\n }\n };\n\n // Backends that report no editor to open — `enable_vscode: false`, a\n // configured editor whose process is not running, or no URL reported — get\n // no button rather than one that does nothing when clicked.\n if (isUnavailable) {\n return null;\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isLoading || isRuntimeStarting}\n aria-label={t(I18nKey.VSCODE$OPEN)}\n title={t(I18nKey.VSCODE$OPEN)}\n data-testid=\"drawer-vscode-link\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-[7px] border border-[var(--oh-border)] bg-base-secondary px-2 py-1 text-xs\",\n \"text-[var(--oh-muted)] transition-colors hover:enabled:bg-surface-raised hover:enabled:text-white\",\n \"cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n <VSCodeIcon className=\"h-[15px] w-[15px] shrink-0\" aria-hidden />\n <span>{t(I18nKey.FILES$VSCODE)}</span>\n <ExternalLink\n className=\"h-3.5 w-3.5 shrink-0\"\n aria-hidden\n strokeWidth={2}\n />\n </button>\n );\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,IAAmB;CACjC,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,EAAE,qBAAkB,EAAc,GAClC,EAAE,SAAM,YAAS,cAAW,qBAAkB,EAAoB,GAClE,IAAoB,EAAwB,SAAS,CAAa;CAsBxE,OAJI,IACK,OAIP,kBAAC,UAAD;EACE,MAAK;EACL,SAAS,YAvBmB;GAC9B,IAAI,IAAY,GAAM;GAOtB,AALA,AAEE,OAAY,MADS,EAAQ,GACV,MAAM,OAAO,MAG9B,KACF,OAAO,KAAK,GAAW,UAAU,qBAAqB;EAE1D;EAaI,UAAU,KAAa;EACvB,cAAY,EAAE,EAAQ,WAAW;EACjC,OAAO,EAAE,EAAQ,WAAW;EAC5B,eAAY;EACZ,WAAW,EACT,uHACA,qGACA,gEACF;YAXF;GAaE,kBAAC,GAAD;IAAY,WAAU;IAA6B,eAAA;GAAa,CAAA;GAChE,kBAAC,QAAD,EAAA,UAAO,EAAE,EAAQ,YAAY,EAAQ,CAAA;GACrC,kBAAC,GAAD;IACE,WAAU;IACV,eAAA;IACA,aAAa;GACd,CAAA;EACK;;AAEZ"}
@@ -1,2 +1,2 @@
1
- require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../i18n/declaration.cjs"),n=require("../../../api/agent-server-config.cjs"),r=require("../../../hooks/query/use-conversation-skills.cjs"),i=require("../../shared/modals/modal-backdrop.cjs"),a=require("../../shared/modals/modal-body.cjs"),o=require("../../../utils/skill-scope.cjs"),s=require("./skills-modal-header.cjs"),c=require("./skills-modal-section.cjs"),l=require("./skills-loading-state.cjs"),u=require("./skills-empty-state.cjs"),d=require("./skill-item.cjs");let f=require("react"),p=require("react/jsx-runtime");var m={project:t.I18nKey.SKILLS_MODAL$SECTION_PROJECT,personal:t.I18nKey.SKILLS_MODAL$SECTION_USER,public:t.I18nKey.SKILLS_MODAL$SECTION_PUBLIC};function h({onClose:t}){let{t:h}=e.useTranslation(`openhands`),g=n.getAgentServerWorkingDir(),[_,v]=(0,f.useState)({}),{data:y,isLoading:b,isError:x,refetch:S,isRefetching:C}=r.useConversationSkills(),w=(0,f.useMemo)(()=>y?o.groupSkillsByScope(y,g):null,[y,g]),T=e=>{v(t=>({...t,[e]:!t[e]}))};return(0,p.jsx)(i.ModalBackdrop,{onClose:t,children:(0,p.jsxs)(a.ModalBody,{width:`lg`,className:`relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]`,testID:`skills-modal`,children:[(0,p.jsx)(s.SkillsModalHeader,{isLoading:b,isRefetching:C,onRefresh:S,onClose:t}),(0,p.jsx)(`div`,{className:`w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always`,children:b?(0,p.jsx)(l.SkillsLoadingState,{}):x||!y||y.length===0?(0,p.jsx)(u.SkillsEmptyState,{isError:x}):w&&(0,p.jsx)(`div`,{className:`divide-y divide-[var(--oh-border)]`,children:o.SKILL_SCOPE_ORDER.map(e=>{let t=w[e];return t.length===0?null:(0,p.jsx)(c.SkillsModalSection,{title:h(m[e]),count:t.length,children:t.map(t=>(0,p.jsx)(d.SkillItem,{skill:t,isExpanded:_[t.name]||!1,onToggle:T},`${e}-${t.name}`))},e)})})})]})})}exports.SkillsModal=h;
1
+ require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../i18n/declaration.cjs"),n=require("../../../api/agent-server-config.cjs"),r=require("../../../hooks/query/use-conversation-skills.cjs"),i=require("../../shared/modals/modal-backdrop.cjs"),a=require("../../shared/modals/modal-body.cjs"),o=require("../../../hooks/use-skill-enablement.cjs"),s=require("../../../utils/skill-scope.cjs"),c=require("./skills-modal-header.cjs"),l=require("./skills-modal-section.cjs"),u=require("./skills-loading-state.cjs"),d=require("./skills-empty-state.cjs"),f=require("./skill-item.cjs");let p=require("react"),m=require("react/jsx-runtime");var h={project:t.I18nKey.SKILLS_MODAL$SECTION_PROJECT,personal:t.I18nKey.SKILLS_MODAL$SECTION_USER,public:t.I18nKey.SKILLS_MODAL$SECTION_PUBLIC};function g({onClose:t}){let{t:g}=e.useTranslation(`openhands`),_=n.getAgentServerWorkingDir(),[v,y]=(0,p.useState)({}),{data:b,isLoading:x,isError:S,refetch:C,isRefetching:w}=r.useConversationSkills(),T=o.useSkillEnabledFilter(),E=(0,p.useMemo)(()=>(b??[]).filter(T),[b,T]),D=(0,p.useMemo)(()=>s.groupSkillsByScope(E,_),[E,_]),O=e=>{y(t=>({...t,[e]:!t[e]}))};return(0,m.jsx)(i.ModalBackdrop,{onClose:t,children:(0,m.jsxs)(a.ModalBody,{width:`lg`,className:`relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]`,testID:`skills-modal`,children:[(0,m.jsx)(c.SkillsModalHeader,{isLoading:x,isRefetching:w,onRefresh:C,onClose:t}),(0,m.jsx)(`div`,{className:`w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always`,children:x?(0,m.jsx)(u.SkillsLoadingState,{}):S||!b||E.length===0?(0,m.jsx)(d.SkillsEmptyState,{isError:S}):D&&(0,m.jsx)(`div`,{className:`divide-y divide-[var(--oh-border)]`,children:s.SKILL_SCOPE_ORDER.map(e=>{let t=D[e];return t.length===0?null:(0,m.jsx)(l.SkillsModalSection,{title:g(h[e]),count:t.length,children:t.map(t=>(0,m.jsx)(f.SkillItem,{skill:t,isExpanded:v[t.name]||!1,onToggle:O},`${e}-${t.name}`))},e)})})})]})})}exports.SkillsModal=g;
2
2
  //# sourceMappingURL=skills-modal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills-modal.cjs","names":[],"sources":["../../../../src/components/features/conversation-panel/skills-modal.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalBody } from \"#/components/shared/modals/modal-body\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport {\n groupSkillsByScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { SkillsModalHeader } from \"./skills-modal-header\";\nimport { SkillsModalSection } from \"./skills-modal-section\";\nimport { SkillsLoadingState } from \"./skills-loading-state\";\nimport { SkillsEmptyState } from \"./skills-empty-state\";\nimport { SkillItem } from \"./skill-item\";\n\ninterface SkillsModalProps {\n onClose: () => void;\n}\n\nconst SECTION_TITLE_KEY: Record<SkillScope, I18nKey> = {\n project: I18nKey.SKILLS_MODAL$SECTION_PROJECT,\n personal: I18nKey.SKILLS_MODAL$SECTION_USER,\n public: I18nKey.SKILLS_MODAL$SECTION_PUBLIC,\n};\n\nexport function SkillsModal({ onClose }: SkillsModalProps) {\n const { t } = useTranslation(\"openhands\");\n const projectDir = getAgentServerWorkingDir();\n const [expandedAgents, setExpandedAgents] = useState<Record<string, boolean>>(\n {},\n );\n // Scope the catalog to this conversation's attached workspace so the listed\n // skills match the project skills actually loaded into the conversation.\n const {\n data: skills,\n isLoading,\n isError,\n refetch,\n isRefetching,\n } = useConversationSkills();\n\n const groupedSkills = useMemo(\n () => (skills ? groupSkillsByScope(skills, projectDir) : null),\n [skills, projectDir],\n );\n\n const toggleAgent = (agentName: string) => {\n setExpandedAgents((prev) => ({\n ...prev,\n [agentName]: !prev[agentName],\n }));\n };\n\n return (\n <ModalBackdrop onClose={onClose}>\n <ModalBody\n width=\"lg\"\n className=\"relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]\"\n testID=\"skills-modal\"\n >\n <SkillsModalHeader\n isLoading={isLoading}\n isRefetching={isRefetching}\n onRefresh={refetch}\n onClose={onClose}\n />\n\n <div className=\"w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always\">\n {isLoading ? (\n <SkillsLoadingState />\n ) : isError || !skills || skills.length === 0 ? (\n <SkillsEmptyState isError={isError} />\n ) : (\n groupedSkills && (\n <div className=\"divide-y divide-[var(--oh-border)]\">\n {SKILL_SCOPE_ORDER.map((scope) => {\n const scopedSkills = groupedSkills[scope];\n if (scopedSkills.length === 0) {\n return null;\n }\n\n return (\n <SkillsModalSection\n key={scope}\n title={t(SECTION_TITLE_KEY[scope])}\n count={scopedSkills.length}\n >\n {scopedSkills.map((skill) => {\n const isExpanded = expandedAgents[skill.name] || false;\n\n return (\n <SkillItem\n key={`${scope}-${skill.name}`}\n skill={skill}\n isExpanded={isExpanded}\n onToggle={toggleAgent}\n />\n );\n })}\n </SkillsModalSection>\n );\n })}\n </div>\n )\n )}\n </div>\n </ModalBody>\n </ModalBackdrop>\n );\n}\n"],"mappings":"iqBAsBA,IAAM,EAAiD,CACrD,QAAS,EAAA,QAAQ,6BACjB,SAAU,EAAA,QAAQ,0BAClB,OAAQ,EAAA,QAAQ,2BAClB,EAEA,SAAgB,EAAY,CAAE,WAA6B,CACzD,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,EAAa,EAAA,yBAAyB,EACtC,CAAC,EAAgB,IAAA,EAAA,EAAA,UACrB,CAAC,CACH,EAGM,CACJ,KAAM,EACN,YACA,UACA,UACA,gBACE,EAAA,sBAAsB,EAEpB,GAAA,EAAA,EAAA,aACG,EAAS,EAAA,mBAAmB,EAAQ,CAAU,EAAI,KACzD,CAAC,EAAQ,CAAU,CACrB,EAEM,EAAe,GAAsB,CACzC,EAAmB,IAAU,CAC3B,GAAG,GACF,GAAY,CAAC,EAAK,EACrB,EAAE,CACJ,EAEA,OACE,EAAA,EAAA,KAAC,EAAA,cAAD,CAAwB,oBACtB,EAAA,EAAA,MAAC,EAAA,UAAD,CACE,MAAM,KACN,UAAU,mFACV,OAAO,wBAHT,EAKE,EAAA,EAAA,KAAC,EAAA,kBAAD,CACa,YACG,eACd,UAAW,EACF,SACV,CAAA,GAED,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,+HACZ,GACC,EAAA,EAAA,KAAC,EAAA,mBAAD,CAAqB,CAAA,EACnB,GAAW,CAAC,GAAU,EAAO,SAAW,GAC1C,EAAA,EAAA,KAAC,EAAA,iBAAD,CAA2B,SAAU,CAAA,EAErC,IACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,8CACZ,EAAA,kBAAkB,IAAK,GAAU,CAChC,IAAM,EAAe,EAAc,GAKnC,OAJI,EAAa,SAAW,EACnB,MAIP,EAAA,EAAA,KAAC,EAAA,mBAAD,CAEE,MAAO,EAAE,EAAkB,EAAM,EACjC,MAAO,EAAa,gBAEnB,EAAa,IAAK,IAIf,EAAA,EAAA,KAAC,EAAA,UAAD,CAES,QACK,WANG,EAAe,EAAM,OAAS,GAO7C,SAAU,CACX,EAJM,GAAG,EAAM,GAAG,EAAM,MAIxB,CAEJ,CACiB,EAhBb,CAgBa,CAExB,CAAC,CACE,CAAA,CAGN,CAAA,CACI,GACE,CAAA,CAEnB"}
1
+ {"version":3,"file":"skills-modal.cjs","names":[],"sources":["../../../../src/components/features/conversation-panel/skills-modal.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalBody } from \"#/components/shared/modals/modal-body\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport { useSkillEnabledFilter } from \"#/hooks/use-skill-enablement\";\nimport {\n groupSkillsByScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { SkillsModalHeader } from \"./skills-modal-header\";\nimport { SkillsModalSection } from \"./skills-modal-section\";\nimport { SkillsLoadingState } from \"./skills-loading-state\";\nimport { SkillsEmptyState } from \"./skills-empty-state\";\nimport { SkillItem } from \"./skill-item\";\n\ninterface SkillsModalProps {\n onClose: () => void;\n}\n\nconst SECTION_TITLE_KEY: Record<SkillScope, I18nKey> = {\n project: I18nKey.SKILLS_MODAL$SECTION_PROJECT,\n personal: I18nKey.SKILLS_MODAL$SECTION_USER,\n public: I18nKey.SKILLS_MODAL$SECTION_PUBLIC,\n};\n\nexport function SkillsModal({ onClose }: SkillsModalProps) {\n const { t } = useTranslation(\"openhands\");\n const projectDir = getAgentServerWorkingDir();\n const [expandedAgents, setExpandedAgents] = useState<Record<string, boolean>>(\n {},\n );\n // Scope the catalog to this conversation's attached workspace so the listed\n // skills match the project skills actually loaded into the conversation.\n const {\n data: skills,\n isLoading,\n isError,\n refetch,\n isRefetching,\n } = useConversationSkills();\n const isSkillEnabled = useSkillEnabledFilter();\n\n // The modal reports what the conversation actually has, so it lists the\n // enabled set rather than the whole catalog.\n const visibleSkills = useMemo(\n () => (skills ?? []).filter(isSkillEnabled),\n [skills, isSkillEnabled],\n );\n\n const groupedSkills = useMemo(\n () => groupSkillsByScope(visibleSkills, projectDir),\n [visibleSkills, projectDir],\n );\n\n const toggleAgent = (agentName: string) => {\n setExpandedAgents((prev) => ({\n ...prev,\n [agentName]: !prev[agentName],\n }));\n };\n\n return (\n <ModalBackdrop onClose={onClose}>\n <ModalBody\n width=\"lg\"\n className=\"relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]\"\n testID=\"skills-modal\"\n >\n <SkillsModalHeader\n isLoading={isLoading}\n isRefetching={isRefetching}\n onRefresh={refetch}\n onClose={onClose}\n />\n\n <div className=\"w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always\">\n {isLoading ? (\n <SkillsLoadingState />\n ) : isError || !skills || visibleSkills.length === 0 ? (\n <SkillsEmptyState isError={isError} />\n ) : (\n groupedSkills && (\n <div className=\"divide-y divide-[var(--oh-border)]\">\n {SKILL_SCOPE_ORDER.map((scope) => {\n const scopedSkills = groupedSkills[scope];\n if (scopedSkills.length === 0) {\n return null;\n }\n\n return (\n <SkillsModalSection\n key={scope}\n title={t(SECTION_TITLE_KEY[scope])}\n count={scopedSkills.length}\n >\n {scopedSkills.map((skill) => {\n const isExpanded = expandedAgents[skill.name] || false;\n\n return (\n <SkillItem\n key={`${scope}-${skill.name}`}\n skill={skill}\n isExpanded={isExpanded}\n onToggle={toggleAgent}\n />\n );\n })}\n </SkillsModalSection>\n );\n })}\n </div>\n )\n )}\n </div>\n </ModalBody>\n </ModalBackdrop>\n );\n}\n"],"mappings":"stBAuBA,IAAM,EAAiD,CACrD,QAAS,EAAA,QAAQ,6BACjB,SAAU,EAAA,QAAQ,0BAClB,OAAQ,EAAA,QAAQ,2BAClB,EAEA,SAAgB,EAAY,CAAE,WAA6B,CACzD,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,EAAa,EAAA,yBAAyB,EACtC,CAAC,EAAgB,IAAA,EAAA,EAAA,UACrB,CAAC,CACH,EAGM,CACJ,KAAM,EACN,YACA,UACA,UACA,gBACE,EAAA,sBAAsB,EACpB,EAAiB,EAAA,sBAAsB,EAIvC,GAAA,EAAA,EAAA,cACG,GAAU,CAAC,GAAG,OAAO,CAAc,EAC1C,CAAC,EAAQ,CAAc,CACzB,EAEM,GAAA,EAAA,EAAA,aACE,EAAA,mBAAmB,EAAe,CAAU,EAClD,CAAC,EAAe,CAAU,CAC5B,EAEM,EAAe,GAAsB,CACzC,EAAmB,IAAU,CAC3B,GAAG,GACF,GAAY,CAAC,EAAK,EACrB,EAAE,CACJ,EAEA,OACE,EAAA,EAAA,KAAC,EAAA,cAAD,CAAwB,oBACtB,EAAA,EAAA,MAAC,EAAA,UAAD,CACE,MAAM,KACN,UAAU,mFACV,OAAO,wBAHT,EAKE,EAAA,EAAA,KAAC,EAAA,kBAAD,CACa,YACG,eACd,UAAW,EACF,SACV,CAAA,GAED,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,+HACZ,GACC,EAAA,EAAA,KAAC,EAAA,mBAAD,CAAqB,CAAA,EACnB,GAAW,CAAC,GAAU,EAAc,SAAW,GACjD,EAAA,EAAA,KAAC,EAAA,iBAAD,CAA2B,SAAU,CAAA,EAErC,IACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,8CACZ,EAAA,kBAAkB,IAAK,GAAU,CAChC,IAAM,EAAe,EAAc,GAKnC,OAJI,EAAa,SAAW,EACnB,MAIP,EAAA,EAAA,KAAC,EAAA,mBAAD,CAEE,MAAO,EAAE,EAAkB,EAAM,EACjC,MAAO,EAAa,gBAEnB,EAAa,IAAK,IAIf,EAAA,EAAA,KAAC,EAAA,UAAD,CAES,QACK,WANG,EAAe,EAAM,OAAS,GAO7C,SAAU,CACX,EAJM,GAAG,EAAM,GAAG,EAAM,MAIxB,CAEJ,CACiB,EAhBb,CAgBa,CAExB,CAAC,CACE,CAAA,CAGN,CAAA,CACI,GACE,CAAA,CAEnB"}
@@ -4,51 +4,52 @@ import { getAgentServerWorkingDir as n } from "../../../api/agent-server-config.
4
4
  import { useConversationSkills as r } from "../../../hooks/query/use-conversation-skills.js";
5
5
  import { ModalBackdrop as i } from "../../shared/modals/modal-backdrop.js";
6
6
  import { ModalBody as a } from "../../shared/modals/modal-body.js";
7
- import { SKILL_SCOPE_ORDER as o, groupSkillsByScope as s } from "../../../utils/skill-scope.js";
8
- import { SkillsModalHeader as c } from "./skills-modal-header.js";
9
- import { SkillsModalSection as l } from "./skills-modal-section.js";
10
- import { SkillsLoadingState as u } from "./skills-loading-state.js";
11
- import { SkillsEmptyState as d } from "./skills-empty-state.js";
12
- import { SkillItem as f } from "./skill-item.js";
13
- import { useMemo as p, useState as m } from "react";
14
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
7
+ import { useSkillEnabledFilter as o } from "../../../hooks/use-skill-enablement.js";
8
+ import { SKILL_SCOPE_ORDER as s, groupSkillsByScope as c } from "../../../utils/skill-scope.js";
9
+ import { SkillsModalHeader as l } from "./skills-modal-header.js";
10
+ import { SkillsModalSection as u } from "./skills-modal-section.js";
11
+ import { SkillsLoadingState as d } from "./skills-loading-state.js";
12
+ import { SkillsEmptyState as f } from "./skills-empty-state.js";
13
+ import { SkillItem as p } from "./skill-item.js";
14
+ import { useMemo as m, useState as h } from "react";
15
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
15
16
  //#region src/components/features/conversation-panel/skills-modal.tsx
16
- var _ = {
17
+ var v = {
17
18
  project: t.SKILLS_MODAL$SECTION_PROJECT,
18
19
  personal: t.SKILLS_MODAL$SECTION_USER,
19
20
  public: t.SKILLS_MODAL$SECTION_PUBLIC
20
21
  };
21
- function v({ onClose: t }) {
22
- let { t: v } = e("openhands"), y = n(), [b, x] = m({}), { data: S, isLoading: C, isError: w, refetch: T, isRefetching: E } = r(), D = p(() => S ? s(S, y) : null, [S, y]), O = (e) => {
23
- x((t) => ({
22
+ function y({ onClose: t }) {
23
+ let { t: y } = e("openhands"), b = n(), [x, S] = h({}), { data: C, isLoading: w, isError: T, refetch: E, isRefetching: D } = r(), O = o(), k = m(() => (C ?? []).filter(O), [C, O]), A = m(() => c(k, b), [k, b]), j = (e) => {
24
+ S((t) => ({
24
25
  ...t,
25
26
  [e]: !t[e]
26
27
  }));
27
28
  };
28
- return /* @__PURE__ */ h(i, {
29
+ return /* @__PURE__ */ g(i, {
29
30
  onClose: t,
30
- children: /* @__PURE__ */ g(a, {
31
+ children: /* @__PURE__ */ _(a, {
31
32
  width: "lg",
32
33
  className: "relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]",
33
34
  testID: "skills-modal",
34
- children: [/* @__PURE__ */ h(c, {
35
- isLoading: C,
36
- isRefetching: E,
37
- onRefresh: T,
35
+ children: [/* @__PURE__ */ g(l, {
36
+ isLoading: w,
37
+ isRefetching: D,
38
+ onRefresh: E,
38
39
  onClose: t
39
- }), /* @__PURE__ */ h("div", {
40
+ }), /* @__PURE__ */ g("div", {
40
41
  className: "w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always",
41
- children: C ? /* @__PURE__ */ h(u, {}) : w || !S || S.length === 0 ? /* @__PURE__ */ h(d, { isError: w }) : D && /* @__PURE__ */ h("div", {
42
+ children: w ? /* @__PURE__ */ g(d, {}) : T || !C || k.length === 0 ? /* @__PURE__ */ g(f, { isError: T }) : A && /* @__PURE__ */ g("div", {
42
43
  className: "divide-y divide-[var(--oh-border)]",
43
- children: o.map((e) => {
44
- let t = D[e];
45
- return t.length === 0 ? null : /* @__PURE__ */ h(l, {
46
- title: v(_[e]),
44
+ children: s.map((e) => {
45
+ let t = A[e];
46
+ return t.length === 0 ? null : /* @__PURE__ */ g(u, {
47
+ title: y(v[e]),
47
48
  count: t.length,
48
- children: t.map((t) => /* @__PURE__ */ h(f, {
49
+ children: t.map((t) => /* @__PURE__ */ g(p, {
49
50
  skill: t,
50
- isExpanded: b[t.name] || !1,
51
- onToggle: O
51
+ isExpanded: x[t.name] || !1,
52
+ onToggle: j
52
53
  }, `${e}-${t.name}`))
53
54
  }, e);
54
55
  })
@@ -58,6 +59,6 @@ function v({ onClose: t }) {
58
59
  });
59
60
  }
60
61
  //#endregion
61
- export { v as SkillsModal };
62
+ export { y as SkillsModal };
62
63
 
63
64
  //# sourceMappingURL=skills-modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills-modal.js","names":[],"sources":["../../../../src/components/features/conversation-panel/skills-modal.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalBody } from \"#/components/shared/modals/modal-body\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport {\n groupSkillsByScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { SkillsModalHeader } from \"./skills-modal-header\";\nimport { SkillsModalSection } from \"./skills-modal-section\";\nimport { SkillsLoadingState } from \"./skills-loading-state\";\nimport { SkillsEmptyState } from \"./skills-empty-state\";\nimport { SkillItem } from \"./skill-item\";\n\ninterface SkillsModalProps {\n onClose: () => void;\n}\n\nconst SECTION_TITLE_KEY: Record<SkillScope, I18nKey> = {\n project: I18nKey.SKILLS_MODAL$SECTION_PROJECT,\n personal: I18nKey.SKILLS_MODAL$SECTION_USER,\n public: I18nKey.SKILLS_MODAL$SECTION_PUBLIC,\n};\n\nexport function SkillsModal({ onClose }: SkillsModalProps) {\n const { t } = useTranslation(\"openhands\");\n const projectDir = getAgentServerWorkingDir();\n const [expandedAgents, setExpandedAgents] = useState<Record<string, boolean>>(\n {},\n );\n // Scope the catalog to this conversation's attached workspace so the listed\n // skills match the project skills actually loaded into the conversation.\n const {\n data: skills,\n isLoading,\n isError,\n refetch,\n isRefetching,\n } = useConversationSkills();\n\n const groupedSkills = useMemo(\n () => (skills ? groupSkillsByScope(skills, projectDir) : null),\n [skills, projectDir],\n );\n\n const toggleAgent = (agentName: string) => {\n setExpandedAgents((prev) => ({\n ...prev,\n [agentName]: !prev[agentName],\n }));\n };\n\n return (\n <ModalBackdrop onClose={onClose}>\n <ModalBody\n width=\"lg\"\n className=\"relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]\"\n testID=\"skills-modal\"\n >\n <SkillsModalHeader\n isLoading={isLoading}\n isRefetching={isRefetching}\n onRefresh={refetch}\n onClose={onClose}\n />\n\n <div className=\"w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always\">\n {isLoading ? (\n <SkillsLoadingState />\n ) : isError || !skills || skills.length === 0 ? (\n <SkillsEmptyState isError={isError} />\n ) : (\n groupedSkills && (\n <div className=\"divide-y divide-[var(--oh-border)]\">\n {SKILL_SCOPE_ORDER.map((scope) => {\n const scopedSkills = groupedSkills[scope];\n if (scopedSkills.length === 0) {\n return null;\n }\n\n return (\n <SkillsModalSection\n key={scope}\n title={t(SECTION_TITLE_KEY[scope])}\n count={scopedSkills.length}\n >\n {scopedSkills.map((skill) => {\n const isExpanded = expandedAgents[skill.name] || false;\n\n return (\n <SkillItem\n key={`${scope}-${skill.name}`}\n skill={skill}\n isExpanded={isExpanded}\n onToggle={toggleAgent}\n />\n );\n })}\n </SkillsModalSection>\n );\n })}\n </div>\n )\n )}\n </div>\n </ModalBody>\n </ModalBackdrop>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsBA,IAAM,IAAiD;CACrD,SAAS,EAAQ;CACjB,UAAU,EAAQ;CAClB,QAAQ,EAAQ;AAClB;AAEA,SAAgB,EAAY,EAAE,cAA6B;CACzD,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,IAAa,EAAyB,GACtC,CAAC,GAAgB,KAAqB,EAC1C,CAAC,CACH,GAGM,EACJ,MAAM,GACN,cACA,YACA,YACA,oBACE,EAAsB,GAEpB,IAAgB,QACb,IAAS,EAAmB,GAAQ,CAAU,IAAI,MACzD,CAAC,GAAQ,CAAU,CACrB,GAEM,KAAe,MAAsB;EACzC,GAAmB,OAAU;GAC3B,GAAG;IACF,IAAY,CAAC,EAAK;EACrB,EAAE;CACJ;CAEA,OACE,kBAAC,GAAD;EAAwB;YACtB,kBAAC,GAAD;GACE,OAAM;GACN,WAAU;GACV,QAAO;aAHT,CAKE,kBAAC,GAAD;IACa;IACG;IACd,WAAW;IACF;GACV,CAAA,GAED,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,GAAD,CAAqB,CAAA,IACnB,KAAW,CAAC,KAAU,EAAO,WAAW,IAC1C,kBAAC,GAAD,EAA2B,WAAU,CAAA,IAErC,KACE,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAkB,KAAK,MAAU;MAChC,IAAM,IAAe,EAAc;MAKnC,OAJI,EAAa,WAAW,IACnB,OAIP,kBAAC,GAAD;OAEE,OAAO,EAAE,EAAkB,EAAM;OACjC,OAAO,EAAa;iBAEnB,EAAa,KAAK,MAIf,kBAAC,GAAD;QAES;QACK,YANG,EAAe,EAAM,SAAS;QAO7C,UAAU;OACX,GAJM,GAAG,EAAM,GAAG,EAAM,MAIxB,CAEJ;MACiB,GAhBb,CAgBa;KAExB,CAAC;IACE,CAAA;GAGN,CAAA,CACI;;CACE,CAAA;AAEnB"}
1
+ {"version":3,"file":"skills-modal.js","names":[],"sources":["../../../../src/components/features/conversation-panel/skills-modal.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalBody } from \"#/components/shared/modals/modal-body\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport { getAgentServerWorkingDir } from \"#/api/agent-server-config\";\nimport { useConversationSkills } from \"#/hooks/query/use-conversation-skills\";\nimport { useSkillEnabledFilter } from \"#/hooks/use-skill-enablement\";\nimport {\n groupSkillsByScope,\n SKILL_SCOPE_ORDER,\n type SkillScope,\n} from \"#/utils/skill-scope\";\nimport { SkillsModalHeader } from \"./skills-modal-header\";\nimport { SkillsModalSection } from \"./skills-modal-section\";\nimport { SkillsLoadingState } from \"./skills-loading-state\";\nimport { SkillsEmptyState } from \"./skills-empty-state\";\nimport { SkillItem } from \"./skill-item\";\n\ninterface SkillsModalProps {\n onClose: () => void;\n}\n\nconst SECTION_TITLE_KEY: Record<SkillScope, I18nKey> = {\n project: I18nKey.SKILLS_MODAL$SECTION_PROJECT,\n personal: I18nKey.SKILLS_MODAL$SECTION_USER,\n public: I18nKey.SKILLS_MODAL$SECTION_PUBLIC,\n};\n\nexport function SkillsModal({ onClose }: SkillsModalProps) {\n const { t } = useTranslation(\"openhands\");\n const projectDir = getAgentServerWorkingDir();\n const [expandedAgents, setExpandedAgents] = useState<Record<string, boolean>>(\n {},\n );\n // Scope the catalog to this conversation's attached workspace so the listed\n // skills match the project skills actually loaded into the conversation.\n const {\n data: skills,\n isLoading,\n isError,\n refetch,\n isRefetching,\n } = useConversationSkills();\n const isSkillEnabled = useSkillEnabledFilter();\n\n // The modal reports what the conversation actually has, so it lists the\n // enabled set rather than the whole catalog.\n const visibleSkills = useMemo(\n () => (skills ?? []).filter(isSkillEnabled),\n [skills, isSkillEnabled],\n );\n\n const groupedSkills = useMemo(\n () => groupSkillsByScope(visibleSkills, projectDir),\n [visibleSkills, projectDir],\n );\n\n const toggleAgent = (agentName: string) => {\n setExpandedAgents((prev) => ({\n ...prev,\n [agentName]: !prev[agentName],\n }));\n };\n\n return (\n <ModalBackdrop onClose={onClose}>\n <ModalBody\n width=\"lg\"\n className=\"relative max-h-[80vh] flex flex-col items-start border border-[var(--oh-border)]\"\n testID=\"skills-modal\"\n >\n <SkillsModalHeader\n isLoading={isLoading}\n isRefetching={isRefetching}\n onRefresh={refetch}\n onClose={onClose}\n />\n\n <div className=\"w-full h-[60vh] overflow-auto rounded-md border border-[var(--oh-border)] bg-surface-raised custom-scrollbar-always\">\n {isLoading ? (\n <SkillsLoadingState />\n ) : isError || !skills || visibleSkills.length === 0 ? (\n <SkillsEmptyState isError={isError} />\n ) : (\n groupedSkills && (\n <div className=\"divide-y divide-[var(--oh-border)]\">\n {SKILL_SCOPE_ORDER.map((scope) => {\n const scopedSkills = groupedSkills[scope];\n if (scopedSkills.length === 0) {\n return null;\n }\n\n return (\n <SkillsModalSection\n key={scope}\n title={t(SECTION_TITLE_KEY[scope])}\n count={scopedSkills.length}\n >\n {scopedSkills.map((skill) => {\n const isExpanded = expandedAgents[skill.name] || false;\n\n return (\n <SkillItem\n key={`${scope}-${skill.name}`}\n skill={skill}\n isExpanded={isExpanded}\n onToggle={toggleAgent}\n />\n );\n })}\n </SkillsModalSection>\n );\n })}\n </div>\n )\n )}\n </div>\n </ModalBody>\n </ModalBackdrop>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,IAAM,IAAiD;CACrD,SAAS,EAAQ;CACjB,UAAU,EAAQ;CAClB,QAAQ,EAAQ;AAClB;AAEA,SAAgB,EAAY,EAAE,cAA6B;CACzD,IAAM,EAAE,SAAM,EAAe,WAAW,GAClC,IAAa,EAAyB,GACtC,CAAC,GAAgB,KAAqB,EAC1C,CAAC,CACH,GAGM,EACJ,MAAM,GACN,cACA,YACA,YACA,oBACE,EAAsB,GACpB,IAAiB,EAAsB,GAIvC,IAAgB,SACb,KAAU,CAAC,GAAG,OAAO,CAAc,GAC1C,CAAC,GAAQ,CAAc,CACzB,GAEM,IAAgB,QACd,EAAmB,GAAe,CAAU,GAClD,CAAC,GAAe,CAAU,CAC5B,GAEM,KAAe,MAAsB;EACzC,GAAmB,OAAU;GAC3B,GAAG;IACF,IAAY,CAAC,EAAK;EACrB,EAAE;CACJ;CAEA,OACE,kBAAC,GAAD;EAAwB;YACtB,kBAAC,GAAD;GACE,OAAM;GACN,WAAU;GACV,QAAO;aAHT,CAKE,kBAAC,GAAD;IACa;IACG;IACd,WAAW;IACF;GACV,CAAA,GAED,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,GAAD,CAAqB,CAAA,IACnB,KAAW,CAAC,KAAU,EAAc,WAAW,IACjD,kBAAC,GAAD,EAA2B,WAAU,CAAA,IAErC,KACE,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAkB,KAAK,MAAU;MAChC,IAAM,IAAe,EAAc;MAKnC,OAJI,EAAa,WAAW,IACnB,OAIP,kBAAC,GAAD;OAEE,OAAO,EAAE,EAAkB,EAAM;OACjC,OAAO,EAAa;iBAEnB,EAAa,KAAK,MAIf,kBAAC,GAAD;QAES;QACK,YANG,EAAe,EAAM,SAAS;QAO7C,UAAU;OACX,GAJM,GAAG,EAAM,GAAG,EAAM,MAIxB,CAEJ;MACiB,GAhBb,CAgBa;KAExB,CAAC;IACE,CAAA;GAGN,CAAA,CACI;;CACE,CAAA;AAEnB"}
@@ -1,2 +1,2 @@
1
- require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../i18n/declaration.cjs"),n=require("../markdown/markdown-renderer.cjs"),r=require("../../../utils/is-markdown-file-path.cjs"),i=require("../../../stores/use-workspace-mutation-counter.cjs"),a=require("../../../hooks/query/use-workspace-file-content.cjs"),o=require("./highlighted-source-view.cjs");let s=require("react/jsx-runtime");var c=new Set([`html`,`htm`,`svg`]),l={pptx:`PowerPoint`,ppt:`PowerPoint`,docx:`Word`,doc:`Word`,xlsx:`Excel`,xls:`Excel`};function u(e){let t=e.lastIndexOf(`.`);return t===-1?``:e.slice(t+1).toLowerCase()}function d({path:n}){let{t:r}=e.useTranslation(`openhands`),i=l[u(n)];return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,"data-testid":i?`file-content-viewer-unsupported-document`:`file-content-viewer-binary-fallback`,children:i?r(t.I18nKey.FILES$UNSUPPORTED_DOCUMENT,{type:i}):r(t.I18nKey.FILES$BINARY_FALLBACK)})}function f({path:l,viewMode:f}){let{t:p}=e.useTranslation(`openhands`),m=a.useWorkspaceFileContent(l),h=i.useWorkspaceMutationCounter(e=>e.count);if(m.isLoading)return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,children:p(t.I18nKey.FILES$LOADING_FILES)});if(m.isError||!m.data)return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,"data-testid":`file-content-viewer-error`,children:m.error?.message??p(t.I18nKey.FILES$LOAD_ERROR)});let{kind:g,text:_,staticUrl:v,mimeType:y}=m.data,b=i.withWorkspaceCacheBuster(v,h);return f===`plain`?g===`text`&&_!==null?(0,s.jsx)(o.HighlightedSourceView,{path:l,text:_,mimeType:y??void 0}):(0,s.jsx)(d,{path:l}):g===`image`?(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center bg-[var(--oh-surface)] p-4`,"data-testid":`file-content-viewer-image`,children:(0,s.jsx)(`img`,{src:b,alt:l,className:`max-h-full max-w-full object-contain`})}):g===`pdf`?(0,s.jsx)(`iframe`,{title:l,src:b,"data-testid":`file-content-viewer-iframe`,className:`h-full w-full bg-white`}):g===`binary`?(0,s.jsx)(d,{path:l}):y===`text/html`||c.has(u(l))?(0,s.jsx)(`iframe`,{title:l,src:b,sandbox:`allow-same-origin`,"data-testid":`file-content-viewer-iframe`,className:`h-full w-full bg-white`}):g===`text`&&r.isMarkdownFilePath(l)?(0,s.jsx)(`div`,{"data-testid":`file-content-viewer-markdown`,className:`h-full w-full overflow-auto bg-[var(--oh-surface)] text-white custom-scrollbar-always [--oh-scroll-fade-from:var(--oh-surface)]`,children:(0,s.jsx)(`div`,{className:`prose prose-sm prose-invert max-w-none p-6 [--tw-prose-body:#fff] [--tw-prose-bold:#fff] [--tw-prose-headings:#fff] [--tw-prose-lead:#fff] [--tw-prose-counters:#fff] [--tw-prose-quotes:#fff] [--tw-prose-quote-borders:var(--oh-border-subtle)] [--tw-prose-bullets:var(--oh-muted)] [--tw-prose-hr:var(--oh-border-subtle)] [--tw-prose-captions:var(--oh-muted)] [--tw-prose-kbd:#fff]`,children:(0,s.jsx)(n.MarkdownRenderer,{content:_??``,includeStandard:!0,includeHeadings:!0})})}):g===`text`&&_!==null?(0,s.jsx)(o.HighlightedSourceView,{path:l,text:_,mimeType:y??void 0}):(0,s.jsx)(d,{path:l})}exports.FileContentViewer=f;
1
+ require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../i18n/declaration.cjs"),n=require("../markdown/markdown-renderer.cjs"),r=require("../../../stores/use-workspace-mutation-counter.cjs"),i=require("../../../utils/is-markdown-file-path.cjs"),a=require("../../../hooks/query/use-workspace-file-content.cjs"),o=require("./highlighted-source-view.cjs");let s=require("react/jsx-runtime");var c=new Set([`html`,`htm`,`svg`]),l={pptx:`PowerPoint`,ppt:`PowerPoint`,docx:`Word`,doc:`Word`,xlsx:`Excel`,xls:`Excel`};function u(e){let t=e.lastIndexOf(`.`);return t===-1?``:e.slice(t+1).toLowerCase()}function d({path:n}){let{t:r}=e.useTranslation(`openhands`),i=l[u(n)];return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,"data-testid":i?`file-content-viewer-unsupported-document`:`file-content-viewer-binary-fallback`,children:i?r(t.I18nKey.FILES$UNSUPPORTED_DOCUMENT,{type:i}):r(t.I18nKey.FILES$BINARY_FALLBACK)})}function f({path:l,viewMode:f}){let{t:p}=e.useTranslation(`openhands`),m=a.useWorkspaceFileContent(l),h=r.useWorkspaceMutationCounter(e=>e.count);if(m.isLoading)return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,children:p(t.I18nKey.FILES$LOADING_FILES)});if(m.isError||!m.data)return(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]`,"data-testid":`file-content-viewer-error`,children:m.error?.message??p(t.I18nKey.FILES$LOAD_ERROR)});let{kind:g,text:_,staticUrl:v,mimeType:y}=m.data,b=r.withWorkspaceCacheBuster(v,h);return f===`plain`?g===`text`&&_!==null?(0,s.jsx)(o.HighlightedSourceView,{path:l,text:_,mimeType:y??void 0}):(0,s.jsx)(d,{path:l}):g===`image`?(0,s.jsx)(`div`,{className:`flex h-full w-full items-center justify-center bg-[var(--oh-surface)] p-4`,"data-testid":`file-content-viewer-image`,children:(0,s.jsx)(`img`,{src:b,alt:l,className:`max-h-full max-w-full object-contain`})}):g===`pdf`?(0,s.jsx)(`iframe`,{title:l,src:b,"data-testid":`file-content-viewer-iframe`,className:`h-full w-full bg-white`}):g===`binary`?(0,s.jsx)(d,{path:l}):y===`text/html`||c.has(u(l))?(0,s.jsx)(`iframe`,{title:l,src:b,sandbox:`allow-same-origin`,"data-testid":`file-content-viewer-iframe`,className:`h-full w-full bg-white`}):g===`text`&&i.isMarkdownFilePath(l)?(0,s.jsx)(`div`,{"data-testid":`file-content-viewer-markdown`,className:`h-full w-full overflow-auto bg-[var(--oh-surface)] text-white custom-scrollbar-always [--oh-scroll-fade-from:var(--oh-surface)]`,children:(0,s.jsx)(`div`,{className:`prose prose-sm prose-invert max-w-none p-6 [--tw-prose-body:#fff] [--tw-prose-bold:#fff] [--tw-prose-headings:#fff] [--tw-prose-lead:#fff] [--tw-prose-counters:#fff] [--tw-prose-quotes:#fff] [--tw-prose-quote-borders:var(--oh-border-subtle)] [--tw-prose-bullets:var(--oh-muted)] [--tw-prose-hr:var(--oh-border-subtle)] [--tw-prose-captions:var(--oh-muted)] [--tw-prose-kbd:#fff]`,children:(0,s.jsx)(n.MarkdownRenderer,{content:_??``,includeStandard:!0,includeHeadings:!0})})}):g===`text`&&_!==null?(0,s.jsx)(o.HighlightedSourceView,{path:l,text:_,mimeType:y??void 0}):(0,s.jsx)(d,{path:l})}exports.FileContentViewer=f;
2
2
  //# sourceMappingURL=file-content-viewer.cjs.map
@@ -1,8 +1,8 @@
1
1
  import { useTranslation as e } from "../../../node_modules/react-i18next/dist/es/useTranslation.js";
2
2
  import { I18nKey as t } from "../../../i18n/declaration.js";
3
3
  import { MarkdownRenderer as n } from "../markdown/markdown-renderer.js";
4
- import { isMarkdownFilePath as r } from "../../../utils/is-markdown-file-path.js";
5
- import { useWorkspaceMutationCounter as i, withWorkspaceCacheBuster as a } from "../../../stores/use-workspace-mutation-counter.js";
4
+ import { useWorkspaceMutationCounter as r, withWorkspaceCacheBuster as i } from "../../../stores/use-workspace-mutation-counter.js";
5
+ import { isMarkdownFilePath as a } from "../../../utils/is-markdown-file-path.js";
6
6
  import { useWorkspaceFileContent as o } from "../../../hooks/query/use-workspace-file-content.js";
7
7
  import { HighlightedSourceView as s } from "./highlighted-source-view.js";
8
8
  import { jsx as c } from "react/jsx-runtime";
@@ -32,7 +32,7 @@ function f({ path: n }) {
32
32
  });
33
33
  }
34
34
  function p({ path: u, viewMode: p }) {
35
- let { t: m } = e("openhands"), h = o(u), g = i((e) => e.count);
35
+ let { t: m } = e("openhands"), h = o(u), g = r((e) => e.count);
36
36
  if (h.isLoading) return /* @__PURE__ */ c("div", {
37
37
  className: "flex h-full w-full items-center justify-center text-sm text-[var(--oh-muted)]",
38
38
  children: m(t.FILES$LOADING_FILES)
@@ -42,7 +42,7 @@ function p({ path: u, viewMode: p }) {
42
42
  "data-testid": "file-content-viewer-error",
43
43
  children: h.error?.message ?? m(t.FILES$LOAD_ERROR)
44
44
  });
45
- let { kind: _, text: v, staticUrl: y, mimeType: b } = h.data, x = a(y, g);
45
+ let { kind: _, text: v, staticUrl: y, mimeType: b } = h.data, x = i(y, g);
46
46
  return p === "plain" ? _ === "text" && v !== null ? /* @__PURE__ */ c(s, {
47
47
  path: u,
48
48
  text: v,
@@ -66,7 +66,7 @@ function p({ path: u, viewMode: p }) {
66
66
  sandbox: "allow-same-origin",
67
67
  "data-testid": "file-content-viewer-iframe",
68
68
  className: "h-full w-full bg-white"
69
- }) : _ === "text" && r(u) ? /* @__PURE__ */ c("div", {
69
+ }) : _ === "text" && a(u) ? /* @__PURE__ */ c("div", {
70
70
  "data-testid": "file-content-viewer-markdown",
71
71
  className: "h-full w-full overflow-auto bg-[var(--oh-surface)] text-white custom-scrollbar-always [--oh-scroll-fade-from:var(--oh-surface)]",
72
72
  children: /* @__PURE__ */ c("div", {
@@ -1,2 +1,2 @@
1
- require("../../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../../i18n/declaration.cjs"),n=require("../../../../node_modules/lucide-react/dist/esm/icons/zap.cjs"),r=require("../../../../types/automation.cjs"),i=require("../../../../utils/format-relative-time.cjs"),a=require("../../../../icons/clock.cjs"),o=require("./automation-run-health.cjs"),s=require("./automation-health-indicator.cjs");let c=require("react/jsx-runtime");function l(e){return e.isError?t.I18nKey.FEATURED_AUTOMATIONS$STATUS_UNAVAILABLE:o.getRunHealthLabelKey(o.deriveRunHealth(e))}function u({label:e,children:t}){return(0,c.jsxs)(`div`,{className:`flex items-start gap-2 text-xs`,children:[(0,c.jsx)(`span`,{className:`w-20 shrink-0 text-[var(--oh-muted)]`,children:e}),(0,c.jsx)(`span`,{className:`min-w-0 flex-1 break-words text-[var(--oh-foreground)]`,children:t})]})}function d({automation:d,runState:f}){let{t:p,i18n:m}=e.useTranslation(`openhands`),{latestRun:h}=f,g=h?o.getLastRunTimestamp(h):null,_=d.trigger.type===`event`?n.Zap:a.default,v=o.deriveRunHealth(f);return(0,c.jsxs)(`div`,{className:`flex w-[280px] flex-col gap-3 p-3`,children:[(0,c.jsx)(`span`,{className:`break-words text-sm font-medium text-white`,children:d.name}),(0,c.jsxs)(`dl`,{className:`flex flex-col gap-1.5`,children:[(0,c.jsx)(u,{label:p(t.I18nKey.AUTOMATIONS$DETAIL$TRIGGER),children:(0,c.jsxs)(`span`,{className:`inline-flex min-w-0 items-start gap-1.5`,children:[(0,c.jsx)(_,{className:`mt-0.5 size-3 shrink-0`,"aria-hidden":`true`}),(0,c.jsx)(`span`,{className:`break-all`,children:o.getTriggerSummary(d)})]})}),(0,c.jsx)(u,{label:p(t.I18nKey.COMMON$STATUS),children:(0,c.jsxs)(`span`,{className:`inline-flex min-w-0 items-center gap-1.5`,children:[(0,c.jsx)(s.AutomationHealthIndicator,{health:v}),(0,c.jsx)(`span`,{children:p(l(f))})]})}),g?(0,c.jsx)(u,{label:p(t.I18nKey.AUTOMATIONS$DETAIL$LAST_RUN),children:i.formatRelativeTime(g,m.language,p)}):null,h?.status===r.AutomationRunStatus.FAILED&&h.error_detail?(0,c.jsx)(u,{label:p(t.I18nKey.STATUS$ERROR),children:(0,c.jsx)(`span`,{className:`line-clamp-3 text-[var(--oh-status-error)]`,children:h.error_detail})}):null]})]})}exports.HomeAutomationRunTooltip=d,exports.getRunStatusLabelKey=l;
1
+ require("../../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),t=require("../../../../i18n/declaration.cjs"),n=require("../../../../node_modules/lucide-react/dist/esm/icons/zap.cjs"),r=require("../../../../types/automation.cjs"),i=require("../../../../utils/format-relative-time.cjs"),a=require("../../../../icons/clock.cjs"),o=require("./automation-run-health.cjs"),s=require("../../automations/detail/run-phase.cjs"),c=require("./automation-health-indicator.cjs");let l=require("react/jsx-runtime");function u(e){return e.isError?t.I18nKey.FEATURED_AUTOMATIONS$STATUS_UNAVAILABLE:o.getRunHealthLabelKey(o.deriveRunHealth(e))}function d({label:e,children:t}){return(0,l.jsxs)(`div`,{className:`flex items-start gap-2 text-xs`,children:[(0,l.jsx)(`span`,{className:`w-20 shrink-0 text-[var(--oh-muted)]`,children:e}),(0,l.jsx)(`span`,{className:`min-w-0 flex-1 break-words text-[var(--oh-foreground)]`,children:t})]})}function f({run:n}){let{t:r}=e.useTranslation(`openhands`),i=s.useRunPhase({status:n?.status,code:n?.phase_code,label:n?.phase_label,updatedAt:n?.phase_updated_at});if(!n||!s.shouldShowRunPhase(n.status)||!i)return null;let{text:a,age:o}=i;return(0,l.jsx)(d,{label:r(t.I18nKey.AUTOMATIONS$DETAIL$PHASE),children:(0,l.jsxs)(`span`,{"data-testid":`run-phase-row`,children:[a,o?(0,l.jsxs)(`span`,{className:`text-muted`,children:[` · `,o]}):null]})})}function p({automation:s,runState:p}){let{t:m,i18n:h}=e.useTranslation(`openhands`),{latestRun:g}=p,_=g?o.getLastRunTimestamp(g):null,v=s.trigger.type===`event`?n.Zap:a.default,y=o.deriveRunHealth(p);return(0,l.jsxs)(`div`,{className:`flex w-[280px] flex-col gap-3 p-3`,children:[(0,l.jsx)(`span`,{className:`break-words text-sm font-medium text-white`,children:s.name}),(0,l.jsxs)(`dl`,{className:`flex flex-col gap-1.5`,children:[(0,l.jsx)(d,{label:m(t.I18nKey.AUTOMATIONS$DETAIL$TRIGGER),children:(0,l.jsxs)(`span`,{className:`inline-flex min-w-0 items-start gap-1.5`,children:[(0,l.jsx)(v,{className:`mt-0.5 size-3 shrink-0`,"aria-hidden":`true`}),(0,l.jsx)(`span`,{className:`break-all`,children:o.getTriggerSummary(s)})]})}),(0,l.jsx)(d,{label:m(t.I18nKey.COMMON$STATUS),children:(0,l.jsxs)(`span`,{className:`inline-flex min-w-0 items-center gap-1.5`,children:[(0,l.jsx)(c.AutomationHealthIndicator,{health:y}),(0,l.jsx)(`span`,{children:m(u(p))})]})}),(0,l.jsx)(f,{run:g}),_?(0,l.jsx)(d,{label:m(t.I18nKey.AUTOMATIONS$DETAIL$LAST_RUN),children:i.formatRelativeTime(_,h.language,m)}):null,g?.status===r.AutomationRunStatus.FAILED&&g.error_detail?(0,l.jsx)(d,{label:m(t.I18nKey.STATUS$ERROR),children:(0,l.jsx)(`span`,{className:`line-clamp-3 text-[var(--oh-status-error)]`,children:g.error_detail})}):null]})]})}exports.HomeAutomationRunTooltip=p,exports.getRunStatusLabelKey=u;
2
2
  //# sourceMappingURL=home-automation-run-tooltip.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"home-automation-run-tooltip.cjs","names":[],"sources":["../../../../../src/components/features/home/featured-automations/home-automation-run-tooltip.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Zap } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { LatestAutomationRunState } from \"#/hooks/query/use-latest-automation-runs\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport ClockIcon from \"#/icons/clock.svg?react\";\nimport { AutomationRunStatus, type Automation } from \"#/types/automation\";\nimport { formatRelativeTime } from \"#/utils/format-relative-time\";\nimport { AutomationHealthIndicator } from \"./automation-health-indicator\";\nimport {\n deriveRunHealth,\n getLastRunTimestamp,\n getRunHealthLabelKey,\n getTriggerSummary,\n} from \"./automation-run-health\";\n\nexport function getRunStatusLabelKey(\n runState: LatestAutomationRunState,\n): I18nKey {\n if (runState.isError) return I18nKey.FEATURED_AUTOMATIONS$STATUS_UNAVAILABLE;\n return getRunHealthLabelKey(deriveRunHealth(runState));\n}\n\nfunction PreviewRow({\n label,\n children,\n}: {\n label: string;\n children: ReactNode;\n}) {\n return (\n <div className=\"flex items-start gap-2 text-xs\">\n <span className=\"w-20 shrink-0 text-[var(--oh-muted)]\">{label}</span>\n <span className=\"min-w-0 flex-1 break-words text-[var(--oh-foreground)]\">\n {children}\n </span>\n </div>\n );\n}\n\n/**\n * Left-nav-style hovercard body for an automation's latest-run health.\n * Matches `ConversationCardPreview` layout: title + label/value rows.\n */\nexport function HomeAutomationRunTooltip({\n automation,\n runState,\n}: {\n automation: Automation;\n runState: LatestAutomationRunState;\n}) {\n const { t, i18n } = useTranslation(\"openhands\");\n const { latestRun } = runState;\n const timestamp = latestRun ? getLastRunTimestamp(latestRun) : null;\n const TriggerIcon = automation.trigger.type === \"event\" ? Zap : ClockIcon;\n const health = deriveRunHealth(runState);\n\n return (\n <div className=\"flex w-[280px] flex-col gap-3 p-3\">\n <span className=\"break-words text-sm font-medium text-white\">\n {automation.name}\n </span>\n\n <dl className=\"flex flex-col gap-1.5\">\n <PreviewRow label={t(I18nKey.AUTOMATIONS$DETAIL$TRIGGER)}>\n <span className=\"inline-flex min-w-0 items-start gap-1.5\">\n <TriggerIcon\n className=\"mt-0.5 size-3 shrink-0\"\n aria-hidden=\"true\"\n />\n <span className=\"break-all\">{getTriggerSummary(automation)}</span>\n </span>\n </PreviewRow>\n\n <PreviewRow label={t(I18nKey.COMMON$STATUS)}>\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <AutomationHealthIndicator health={health} />\n <span>{t(getRunStatusLabelKey(runState))}</span>\n </span>\n </PreviewRow>\n\n {timestamp ? (\n <PreviewRow label={t(I18nKey.AUTOMATIONS$DETAIL$LAST_RUN)}>\n {formatRelativeTime(timestamp, i18n.language, t)}\n </PreviewRow>\n ) : null}\n\n {latestRun?.status === AutomationRunStatus.FAILED &&\n latestRun.error_detail ? (\n <PreviewRow label={t(I18nKey.STATUS$ERROR)}>\n <span className=\"line-clamp-3 text-[var(--oh-status-error)]\">\n {latestRun.error_detail}\n </span>\n </PreviewRow>\n ) : null}\n </dl>\n </div>\n );\n}\n"],"mappings":"6gBAgBA,SAAgB,EACd,EACS,CAET,OADI,EAAS,QAAgB,EAAA,QAAQ,wCAC9B,EAAA,qBAAqB,EAAA,gBAAgB,CAAQ,CAAC,CACvD,CAEA,SAAS,EAAW,CAClB,QACA,YAIC,CACD,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,0CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,gDAAwC,CAAY,CAAA,GACpE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,yDACb,UACG,CAAA,CACH,GAET,CAMA,SAAgB,EAAyB,CACvC,aACA,YAIC,CACD,GAAM,CAAE,IAAG,QAAS,EAAA,eAAe,WAAW,EACxC,CAAE,aAAc,EAChB,EAAY,EAAY,EAAA,oBAAoB,CAAS,EAAI,KACzD,EAAc,EAAW,QAAQ,OAAS,QAAU,EAAA,IAAM,EAAA,QAC1D,EAAS,EAAA,gBAAgB,CAAQ,EAEvC,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,sDACb,EAAW,IACR,CAAA,GAEN,EAAA,EAAA,MAAC,KAAD,CAAI,UAAU,iCAAd,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,0BAA0B,YACrD,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,mDAAhB,EACE,EAAA,EAAA,KAAC,EAAD,CACE,UAAU,yBACV,cAAY,MACb,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,qBAAa,EAAA,kBAAkB,CAAU,CAAQ,CAAA,CAC7D,GACI,CAAA,GAEZ,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,aAAa,YACxC,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,oDAAhB,EACE,EAAA,EAAA,KAAC,EAAA,0BAAD,CAAmC,QAAS,CAAA,GAC5C,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAE,EAAqB,CAAQ,CAAC,CAAQ,CAAA,CAC3C,GACI,CAAA,EAEX,GACC,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,2BAA2B,WACrD,EAAA,mBAAmB,EAAW,EAAK,SAAU,CAAC,CACrC,CAAA,EACV,KAEH,GAAW,SAAW,EAAA,oBAAoB,QAC3C,EAAU,cACR,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,YAAY,YACvC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,sDACb,EAAU,YACP,CAAA,CACI,CAAA,EACV,IACF,GACD,GAET"}
1
+ {"version":3,"file":"home-automation-run-tooltip.cjs","names":[],"sources":["../../../../../src/components/features/home/featured-automations/home-automation-run-tooltip.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Zap } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { LatestAutomationRunState } from \"#/hooks/query/use-latest-automation-runs\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport ClockIcon from \"#/icons/clock.svg?react\";\nimport {\n shouldShowRunPhase,\n useRunPhase,\n} from \"#/components/features/automations/detail/run-phase\";\nimport {\n AutomationRunStatus,\n type Automation,\n type AutomationRun,\n} from \"#/types/automation\";\nimport { formatRelativeTime } from \"#/utils/format-relative-time\";\nimport { AutomationHealthIndicator } from \"./automation-health-indicator\";\nimport {\n deriveRunHealth,\n getLastRunTimestamp,\n getRunHealthLabelKey,\n getTriggerSummary,\n} from \"./automation-run-health\";\n\nexport function getRunStatusLabelKey(\n runState: LatestAutomationRunState,\n): I18nKey {\n if (runState.isError) return I18nKey.FEATURED_AUTOMATIONS$STATUS_UNAVAILABLE;\n return getRunHealthLabelKey(deriveRunHealth(runState));\n}\n\nfunction PreviewRow({\n label,\n children,\n}: {\n label: string;\n children: ReactNode;\n}) {\n return (\n <div className=\"flex items-start gap-2 text-xs\">\n <span className=\"w-20 shrink-0 text-[var(--oh-muted)]\">{label}</span>\n <span className=\"min-w-0 flex-1 break-words text-[var(--oh-foreground)]\">\n {children}\n </span>\n </div>\n );\n}\n\n/**\n * The run's phase and how long it has held it. The row that opens this\n * hovercard has to clip a long phase; here there is room to wrap, so this is\n * where the whole thing is readable — and the age is what says whether the\n * run is moving through phases or sitting in one. Only the layout differs\n * from the row's: what the phase says, and whether its age is meaningful,\n * comes from the same hook the row uses.\n */\nfunction PhaseRow({ run }: { run: AutomationRun | null }) {\n const { t } = useTranslation(\"openhands\");\n const phase = useRunPhase({\n status: run?.status,\n code: run?.phase_code,\n label: run?.phase_label,\n updatedAt: run?.phase_updated_at,\n });\n\n if (!run || !shouldShowRunPhase(run.status) || !phase) return null;\n\n const { text, age } = phase;\n\n return (\n <PreviewRow label={t(I18nKey.AUTOMATIONS$DETAIL$PHASE)}>\n <span data-testid=\"run-phase-row\">\n {text}\n {age ? <span className=\"text-muted\"> · {age}</span> : null}\n </span>\n </PreviewRow>\n );\n}\n\n/**\n * Left-nav-style hovercard body for an automation's latest-run health.\n * Matches `ConversationCardPreview` layout: title + label/value rows.\n */\nexport function HomeAutomationRunTooltip({\n automation,\n runState,\n}: {\n automation: Automation;\n runState: LatestAutomationRunState;\n}) {\n const { t, i18n } = useTranslation(\"openhands\");\n const { latestRun } = runState;\n const timestamp = latestRun ? getLastRunTimestamp(latestRun) : null;\n const TriggerIcon = automation.trigger.type === \"event\" ? Zap : ClockIcon;\n const health = deriveRunHealth(runState);\n\n return (\n <div className=\"flex w-[280px] flex-col gap-3 p-3\">\n <span className=\"break-words text-sm font-medium text-white\">\n {automation.name}\n </span>\n\n <dl className=\"flex flex-col gap-1.5\">\n <PreviewRow label={t(I18nKey.AUTOMATIONS$DETAIL$TRIGGER)}>\n <span className=\"inline-flex min-w-0 items-start gap-1.5\">\n <TriggerIcon\n className=\"mt-0.5 size-3 shrink-0\"\n aria-hidden=\"true\"\n />\n <span className=\"break-all\">{getTriggerSummary(automation)}</span>\n </span>\n </PreviewRow>\n\n <PreviewRow label={t(I18nKey.COMMON$STATUS)}>\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <AutomationHealthIndicator health={health} />\n <span>{t(getRunStatusLabelKey(runState))}</span>\n </span>\n </PreviewRow>\n\n <PhaseRow run={latestRun} />\n\n {timestamp ? (\n <PreviewRow label={t(I18nKey.AUTOMATIONS$DETAIL$LAST_RUN)}>\n {formatRelativeTime(timestamp, i18n.language, t)}\n </PreviewRow>\n ) : null}\n\n {latestRun?.status === AutomationRunStatus.FAILED &&\n latestRun.error_detail ? (\n <PreviewRow label={t(I18nKey.STATUS$ERROR)}>\n <span className=\"line-clamp-3 text-[var(--oh-status-error)]\">\n {latestRun.error_detail}\n </span>\n </PreviewRow>\n ) : null}\n </dl>\n </div>\n );\n}\n"],"mappings":"ikBAwBA,SAAgB,EACd,EACS,CAET,OADI,EAAS,QAAgB,EAAA,QAAQ,wCAC9B,EAAA,qBAAqB,EAAA,gBAAgB,CAAQ,CAAC,CACvD,CAEA,SAAS,EAAW,CAClB,QACA,YAIC,CACD,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,0CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,gDAAwC,CAAY,CAAA,GACpE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,yDACb,UACG,CAAA,CACH,GAET,CAUA,SAAS,EAAS,CAAE,OAAsC,CACxD,GAAM,CAAE,KAAM,EAAA,eAAe,WAAW,EAClC,EAAQ,EAAA,YAAY,CACxB,OAAQ,GAAK,OACb,KAAM,GAAK,WACX,MAAO,GAAK,YACZ,UAAW,GAAK,gBAClB,CAAC,EAED,GAAI,CAAC,GAAO,CAAC,EAAA,mBAAmB,EAAI,MAAM,GAAK,CAAC,EAAO,OAAO,KAE9D,GAAM,CAAE,OAAM,OAAQ,EAEtB,OACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,wBAAwB,YACnD,EAAA,EAAA,MAAC,OAAD,CAAM,cAAY,yBAAlB,CACG,EACA,GAAM,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,sBAAhB,CAA6B,MAAI,CAAU,IAAI,IAClD,GACI,CAAA,CAEhB,CAMA,SAAgB,EAAyB,CACvC,aACA,YAIC,CACD,GAAM,CAAE,IAAG,QAAS,EAAA,eAAe,WAAW,EACxC,CAAE,aAAc,EAChB,EAAY,EAAY,EAAA,oBAAoB,CAAS,EAAI,KACzD,EAAc,EAAW,QAAQ,OAAS,QAAU,EAAA,IAAM,EAAA,QAC1D,EAAS,EAAA,gBAAgB,CAAQ,EAEvC,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,sDACb,EAAW,IACR,CAAA,GAEN,EAAA,EAAA,MAAC,KAAD,CAAI,UAAU,iCAAd,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,0BAA0B,YACrD,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,mDAAhB,EACE,EAAA,EAAA,KAAC,EAAD,CACE,UAAU,yBACV,cAAY,MACb,CAAA,GACD,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,qBAAa,EAAA,kBAAkB,CAAU,CAAQ,CAAA,CAC7D,GACI,CAAA,GAEZ,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,aAAa,YACxC,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,oDAAhB,EACE,EAAA,EAAA,KAAC,EAAA,0BAAD,CAAmC,QAAS,CAAA,GAC5C,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAE,EAAqB,CAAQ,CAAC,CAAQ,CAAA,CAC3C,GACI,CAAA,GAEZ,EAAA,EAAA,KAAC,EAAD,CAAU,IAAK,CAAY,CAAA,EAE1B,GACC,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,2BAA2B,WACrD,EAAA,mBAAmB,EAAW,EAAK,SAAU,CAAC,CACrC,CAAA,EACV,KAEH,GAAW,SAAW,EAAA,oBAAoB,QAC3C,EAAU,cACR,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAE,EAAA,QAAQ,YAAY,YACvC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,sDACb,EAAU,YACP,CAAA,CACI,CAAA,EACV,IACF,GACD,GAET"}
@@ -5,63 +5,85 @@ import { AutomationRunStatus as r } from "../../../../types/automation.js";
5
5
  import { formatRelativeTime as i } from "../../../../utils/format-relative-time.js";
6
6
  import a from "../../../../icons/clock.js";
7
7
  import { deriveRunHealth as o, getLastRunTimestamp as s, getRunHealthLabelKey as c, getTriggerSummary as l } from "./automation-run-health.js";
8
- import { AutomationHealthIndicator as u } from "./automation-health-indicator.js";
9
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
8
+ import { shouldShowRunPhase as u, useRunPhase as d } from "../../automations/detail/run-phase.js";
9
+ import { AutomationHealthIndicator as f } from "./automation-health-indicator.js";
10
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
10
11
  //#region src/components/features/home/featured-automations/home-automation-run-tooltip.tsx
11
- function p(e) {
12
+ function h(e) {
12
13
  return e.isError ? t.FEATURED_AUTOMATIONS$STATUS_UNAVAILABLE : c(o(e));
13
14
  }
14
- function m({ label: e, children: t }) {
15
- return /* @__PURE__ */ f("div", {
15
+ function g({ label: e, children: t }) {
16
+ return /* @__PURE__ */ m("div", {
16
17
  className: "flex items-start gap-2 text-xs",
17
- children: [/* @__PURE__ */ d("span", {
18
+ children: [/* @__PURE__ */ p("span", {
18
19
  className: "w-20 shrink-0 text-[var(--oh-muted)]",
19
20
  children: e
20
- }), /* @__PURE__ */ d("span", {
21
+ }), /* @__PURE__ */ p("span", {
21
22
  className: "min-w-0 flex-1 break-words text-[var(--oh-foreground)]",
22
23
  children: t
23
24
  })]
24
25
  });
25
26
  }
26
- function h({ automation: c, runState: h }) {
27
- let { t: g, i18n: _ } = e("openhands"), { latestRun: v } = h, y = v ? s(v) : null, b = c.trigger.type === "event" ? n : a, x = o(h);
28
- return /* @__PURE__ */ f("div", {
27
+ function _({ run: n }) {
28
+ let { t: r } = e("openhands"), i = d({
29
+ status: n?.status,
30
+ code: n?.phase_code,
31
+ label: n?.phase_label,
32
+ updatedAt: n?.phase_updated_at
33
+ });
34
+ if (!n || !u(n.status) || !i) return null;
35
+ let { text: a, age: o } = i;
36
+ return /* @__PURE__ */ p(g, {
37
+ label: r(t.AUTOMATIONS$DETAIL$PHASE),
38
+ children: /* @__PURE__ */ m("span", {
39
+ "data-testid": "run-phase-row",
40
+ children: [a, o ? /* @__PURE__ */ m("span", {
41
+ className: "text-muted",
42
+ children: [" · ", o]
43
+ }) : null]
44
+ })
45
+ });
46
+ }
47
+ function v({ automation: c, runState: u }) {
48
+ let { t: d, i18n: v } = e("openhands"), { latestRun: y } = u, b = y ? s(y) : null, x = c.trigger.type === "event" ? n : a, S = o(u);
49
+ return /* @__PURE__ */ m("div", {
29
50
  className: "flex w-[280px] flex-col gap-3 p-3",
30
- children: [/* @__PURE__ */ d("span", {
51
+ children: [/* @__PURE__ */ p("span", {
31
52
  className: "break-words text-sm font-medium text-white",
32
53
  children: c.name
33
- }), /* @__PURE__ */ f("dl", {
54
+ }), /* @__PURE__ */ m("dl", {
34
55
  className: "flex flex-col gap-1.5",
35
56
  children: [
36
- /* @__PURE__ */ d(m, {
37
- label: g(t.AUTOMATIONS$DETAIL$TRIGGER),
38
- children: /* @__PURE__ */ f("span", {
57
+ /* @__PURE__ */ p(g, {
58
+ label: d(t.AUTOMATIONS$DETAIL$TRIGGER),
59
+ children: /* @__PURE__ */ m("span", {
39
60
  className: "inline-flex min-w-0 items-start gap-1.5",
40
- children: [/* @__PURE__ */ d(b, {
61
+ children: [/* @__PURE__ */ p(x, {
41
62
  className: "mt-0.5 size-3 shrink-0",
42
63
  "aria-hidden": "true"
43
- }), /* @__PURE__ */ d("span", {
64
+ }), /* @__PURE__ */ p("span", {
44
65
  className: "break-all",
45
66
  children: l(c)
46
67
  })]
47
68
  })
48
69
  }),
49
- /* @__PURE__ */ d(m, {
50
- label: g(t.COMMON$STATUS),
51
- children: /* @__PURE__ */ f("span", {
70
+ /* @__PURE__ */ p(g, {
71
+ label: d(t.COMMON$STATUS),
72
+ children: /* @__PURE__ */ m("span", {
52
73
  className: "inline-flex min-w-0 items-center gap-1.5",
53
- children: [/* @__PURE__ */ d(u, { health: x }), /* @__PURE__ */ d("span", { children: g(p(h)) })]
74
+ children: [/* @__PURE__ */ p(f, { health: S }), /* @__PURE__ */ p("span", { children: d(h(u)) })]
54
75
  })
55
76
  }),
56
- y ? /* @__PURE__ */ d(m, {
57
- label: g(t.AUTOMATIONS$DETAIL$LAST_RUN),
58
- children: i(y, _.language, g)
77
+ /* @__PURE__ */ p(_, { run: y }),
78
+ b ? /* @__PURE__ */ p(g, {
79
+ label: d(t.AUTOMATIONS$DETAIL$LAST_RUN),
80
+ children: i(b, v.language, d)
59
81
  }) : null,
60
- v?.status === r.FAILED && v.error_detail ? /* @__PURE__ */ d(m, {
61
- label: g(t.STATUS$ERROR),
62
- children: /* @__PURE__ */ d("span", {
82
+ y?.status === r.FAILED && y.error_detail ? /* @__PURE__ */ p(g, {
83
+ label: d(t.STATUS$ERROR),
84
+ children: /* @__PURE__ */ p("span", {
63
85
  className: "line-clamp-3 text-[var(--oh-status-error)]",
64
- children: v.error_detail
86
+ children: y.error_detail
65
87
  })
66
88
  }) : null
67
89
  ]
@@ -69,6 +91,6 @@ function h({ automation: c, runState: h }) {
69
91
  });
70
92
  }
71
93
  //#endregion
72
- export { h as HomeAutomationRunTooltip, p as getRunStatusLabelKey };
94
+ export { v as HomeAutomationRunTooltip, h as getRunStatusLabelKey };
73
95
 
74
96
  //# sourceMappingURL=home-automation-run-tooltip.js.map