@openhands/agent-canvas 1.10.0 → 1.11.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 (500) hide show
  1. package/README.md +1 -1
  2. package/README.windows.md +2 -2
  3. package/build/assets/{acp-providers-DLe_gVDY.js → acp-providers-BkL3HWa3.js} +1 -1
  4. package/build/assets/{active-backend-context-B0wI7OzM.js → active-backend-context-BBvP-bI2.js} +1 -1
  5. package/build/assets/{agent-context-settings-CaQtdNA-.js → agent-context-settings-Bno1nwPL.js} +1 -1
  6. package/build/assets/{agent-profiles-settings-CvuErjp6.js → agent-profiles-settings-DqoS7RL3.js} +1 -1
  7. package/build/assets/agent-server-conversation-service.api-0RztSdJJ.js +86 -0
  8. package/build/assets/agent-settings-BJHryp65.js +1 -0
  9. package/build/assets/{agent-settings-UE-U4Xii.js → agent-settings-h8hQz-IU.js} +1 -1
  10. package/build/assets/{alert-banner-BMaOtTCG.js → alert-banner-lrK-2_0Y.js} +1 -1
  11. package/build/assets/{api-key-entry-screen-Cy66vT4D.js → api-key-entry-screen-Qsb83VX1.js} +1 -1
  12. package/build/assets/{app-settings-9ok42bV6.js → app-settings-r1RUbgGi.js} +1 -1
  13. package/build/assets/{automation-detail-fuITm6i3.js → automation-detail-7LkL91j9.js} +3 -3
  14. package/build/assets/{automation-export-CRq40mux.js → automation-export-U2QNyNy6.js} +1 -1
  15. package/build/assets/{automation-setup-route-EXDazOHW.js → automation-setup-route-Bel9_Lue.js} +1 -1
  16. package/build/assets/{automation-templates-BArZsaxP.js → automation-templates-CRLDssaI.js} +1 -1
  17. package/build/assets/{automations-list-CG4HKOTn.js → automations-list-B2iV3ZKW.js} +1 -1
  18. package/build/assets/{back-nav-button-BZB6H7xz.js → back-nav-button-B3pYwmUJ.js} +1 -1
  19. package/build/assets/backend-form-modal-OroTqnAv.js +1 -0
  20. package/build/assets/{backend-synced-settings-badge-B_NXJ3u1.js → backend-synced-settings-badge-DB4717Iu.js} +1 -1
  21. package/build/assets/{badge-C64c-7PO.js → badge-yR53enbU.js} +1 -1
  22. package/build/assets/{base-modal-C0RQPug5.js → base-modal-3NmIOKDm.js} +1 -1
  23. package/build/assets/{brand-button-DJmFCyMK.js → brand-button-CJcwjnfb.js} +1 -1
  24. package/build/assets/{browser-D3gd2n83.js → browser--eoQOo4M.js} +1 -1
  25. package/build/assets/{browser-tab-BicAWuJ1.js → browser-tab-A94o33Vn.js} +1 -1
  26. package/build/assets/{chat-send-button-CCrH1E8u.js → chat-send-button-B8n6-DQA.js} +1 -1
  27. package/build/assets/{circle-plus-check-toggle-CB_sNERY.js → circle-plus-check-toggle-BVzv5EkZ.js} +1 -1
  28. package/build/assets/{cloud-funnel-analytics-XynamQGU.js → cloud-funnel-analytics-CBQdPZl_.js} +1 -1
  29. package/build/assets/{combobox-caret-Bwiifgjs.js → combobox-caret-BlmRwiM8.js} +1 -1
  30. package/build/assets/command-menu-PsRXVBz2.js +1 -0
  31. package/build/assets/{condenser-settings-cNGy75gq.js → condenser-settings-w7L3EFvm.js} +1 -1
  32. package/build/assets/{confirmation-modal-BATFmFyP.js → confirmation-modal-DAH0XtOp.js} +1 -1
  33. package/build/assets/{context-menu-list-item-DhJCcBA0.js → context-menu-list-item-BQhmFVEK.js} +1 -1
  34. package/build/assets/{conversation-Csdxh9Xt.js → conversation-BUzBZAc-.js} +4 -4
  35. package/build/assets/conversation-panel-pzAKsSDb.js +1 -0
  36. package/build/assets/conversation-pzAKsSDb.js +1 -0
  37. package/build/assets/{conversation-state-store-C2QzhPaK.js → conversation-state-store-Bs8gA263.js} +1 -1
  38. package/build/assets/{conversation-tab-empty-state-D3fb5xIA.js → conversation-tab-empty-state-C9sfDOlt.js} +1 -1
  39. package/build/assets/{copy-to-clipboard-button-c4MQwKGj.js → copy-to-clipboard-button-DatoElj8.js} +1 -1
  40. package/build/assets/{device-verify-oFpQoLgm.js → device-verify-BIjXeW9N.js} +1 -1
  41. package/build/assets/{dropdown-classes-f91ARMV1.js → dropdown-classes-zFW7qPSK.js} +1 -1
  42. package/build/assets/{entry.client-BCzY2Bf3.js → entry.client-DzbDyLkV.js} +2 -2
  43. package/build/assets/{enum-filter-dropdown-HG3q3rkV.js → enum-filter-dropdown-CctILg5t.js} +1 -1
  44. package/build/assets/{environment-switch-overlay-CquZXolz.js → environment-switch-overlay-Cvmo6clk.js} +1 -1
  45. package/build/assets/{extensions-hub-BeweE0PW.js → extensions-hub-DOmHPGTA.js} +1 -1
  46. package/build/assets/{extensions-navigation-Dd58NlUF.js → extensions-navigation-6zU5M1pa.js} +1 -1
  47. package/build/assets/{files-tab-CLLG55-q.js → files-tab-BzofBmF4.js} +1 -1
  48. package/build/assets/{form-control-classes-pHtZUI6K.js → form-control-classes-DLN3Qgub.js} +1 -1
  49. package/build/assets/{format-relative-time-6-3uvOXe.js → format-relative-time-DGPQlPx0.js} +1 -1
  50. package/build/assets/{git-provider-icon-wg7ShB98.js → git-provider-icon-BLMlwy02.js} +1 -1
  51. package/build/assets/{git-repo-dropdown-CWnaUyxL.js → git-repo-dropdown-B7RvO70z.js} +1 -1
  52. package/build/assets/git-repo-dropdown-B_PTq4ol.js +1 -0
  53. package/build/assets/{highlighted-source-view-DBtI3por.js → highlighted-source-view-CgJfD5VT.js} +1 -1
  54. package/build/assets/{home-BpZQkDWM.js → home-DEZaZqYv.js} +1 -1
  55. package/build/assets/home-r89Vj2td.js +1 -0
  56. package/build/assets/{home-store-DM4qw1lF.js → home-store-D7CjMN_-.js} +1 -1
  57. package/build/assets/index-home-r89Vj2td.js +1 -0
  58. package/build/assets/install-server-modal-BTwK5lbi.js +1 -0
  59. package/build/assets/{kebab-menu-item-content-By16Tm_0.js → kebab-menu-item-content-C4CkeiJO.js} +1 -1
  60. package/build/assets/{launch-C9uijypN.js → launch-DVlx4v9o.js} +1 -1
  61. package/build/assets/{llm-not-configured-banner-DrBrhfN0.js → llm-not-configured-banner-CwKu8C6g.js} +2 -2
  62. package/build/assets/llm-settings-BJotLQND.js +1 -0
  63. package/build/assets/llm-settings-CDM-5H2A.js +1 -0
  64. package/build/assets/{llm-subscription-service-DwjJ8-_X.js → llm-subscription-service-7eVfDIE1.js} +1 -1
  65. package/build/assets/{loading-spinner-6Yj-YyoS.js → loading-spinner-CN3riY7k.js} +1 -1
  66. package/build/assets/{manage-backends-modal-DrwErS0N.js → manage-backends-modal-HNWKLYhq.js} +1 -1
  67. package/build/assets/manifest-2a36a8f8.js +1 -0
  68. package/build/assets/{manifest-subpage-layout-CtqVwIvJ.js → manifest-subpage-layout-D-m-h8_t.js} +1 -1
  69. package/build/assets/map-provider-7Bp2aih5.js +1 -0
  70. package/build/assets/markdown-renderer-BiiiIznl.js +8 -0
  71. package/build/assets/mcp-gLgPP7AS.js +9 -0
  72. package/build/assets/{mcp-marketplace-utils-BMnYz0Gc.js → mcp-marketplace-utils-Dr_HG_ol.js} +1 -1
  73. package/build/assets/messages-D1cbVhRK.js +40 -0
  74. package/build/assets/{modal-body-BHGCSAtj.js → modal-body-duRaxj_K.js} +1 -1
  75. package/build/assets/{modal-classes-DSTLuxkA.js → modal-classes-CLEXO6dj.js} +1 -1
  76. package/build/assets/{modal-close-button-dheWZ2ys.js → modal-close-button-D0aT02hs.js} +1 -1
  77. package/build/assets/npm-DRzJF5Zn.js +1 -0
  78. package/build/assets/{onboarding-5CZvRBbh.js → onboarding-DSr8hOpk.js} +1 -1
  79. package/build/assets/{onboarding-modal-CD2ehuxt.js → onboarding-modal-C6Euf7N4.js} +1 -1
  80. package/build/assets/{organization-service.api-Dsuoep0g.js → organization-service.api-C4GYWwj9.js} +1 -1
  81. package/build/assets/{planner-tab-DeO7Thb0.js → planner-tab-CZcguxTK.js} +1 -1
  82. package/build/assets/{plugins-management-service-C9f75R6X.js → plugins-management-service-BmDzOQsd.js} +1 -1
  83. package/build/assets/{profiles-service.api-Dl20_2IM.js → profiles-service.api-CoLTwjc1.js} +1 -1
  84. package/build/assets/{providers-CeuhK46N.js → providers-tBzTpz1w.js} +1 -1
  85. package/build/assets/{proxy-CIGI9zQC.js → proxy-DCI9S-LA.js} +1 -1
  86. package/build/assets/recommended-automations-launcher-BbJAJVED.js +1 -0
  87. package/build/assets/root-BfM_kC_d.css +1 -0
  88. package/build/assets/root-gstBEjty.js +2 -0
  89. package/build/assets/root-layout-BIAFLP9p.js +2 -0
  90. package/build/assets/{schema-field-z2vSLuLo.js → schema-field-zhsVDllR.js} +1 -1
  91. package/build/assets/{sdk-section-page-BnCXAytf.js → sdk-section-page-CS4GWn0y.js} +1 -1
  92. package/build/assets/{secrets-service-DGUNlwQd.js → secrets-service-DjgGduXk.js} +1 -1
  93. package/build/assets/{secrets-settings-DUmML_dK.js → secrets-settings-f-qahfbi.js} +1 -1
  94. package/build/assets/{segmented-toggle-eSofF7gn.js → segmented-toggle-SmvsR3jW.js} +1 -1
  95. package/build/assets/settings-DQd0xLEw.js +1 -0
  96. package/build/assets/{settings-dropdown-input-Cx4g7Xfl.js → settings-dropdown-input-TWIeiG02.js} +1 -1
  97. package/build/assets/{settings-index-BECdgecg.js → settings-index-BVwy9JEp.js} +1 -1
  98. package/build/assets/{settings-input-BQY115xH.js → settings-input-D61Vzp9e.js} +1 -1
  99. package/build/assets/{settings-list-classes-C9cLrrcc.js → settings-list-classes-sE0ASr1s.js} +1 -1
  100. package/build/assets/{settings-modal-ChBJNTdd.js → settings-modal-D6D5ngET.js} +1 -1
  101. package/build/assets/{settings-service.api-Dz9cZyvx.js → settings-service.api-DZp7E7A9.js} +1 -1
  102. package/build/assets/{settings-switch-BIodMVz9.js → settings-switch-Drt-rF5s.js} +1 -1
  103. package/build/assets/{settings-utils-BL_Z9uIe.js → settings-utils-gw2ppAvw.js} +1 -1
  104. package/build/assets/{shared-conversation-CSF0aTuE.js → shared-conversation-DIxZjElr.js} +1 -1
  105. package/build/assets/{wrench-DRitTfwe.js → shield-check-D2cpEpv3.js} +1 -1
  106. package/build/assets/{sidebar-layout-DEycoFd_.js → sidebar-layout-Dxg6zc2K.js} +1 -1
  107. package/build/assets/{sidebar-mobile-menu-toggle-DeRvTupV.js → sidebar-mobile-menu-toggle-OoZBHxaT.js} +1 -1
  108. package/build/assets/{sidebar-nav-link-BjpQ-NVc.js → sidebar-nav-link-CxLoG-dG.js} +1 -1
  109. package/build/assets/sidebar-store-BJeYY-E9.js +1 -0
  110. package/build/assets/{skill-card-pill-row-BH6fPGba.js → skill-card-pill-row-B_BYBONu.js} +1 -1
  111. package/build/assets/{skill-icon-badge-D4uznfjU.js → skill-icon-badge-CN41Hy9l.js} +1 -1
  112. package/build/assets/{skill-scope-DH_AUUUP.js → skill-scope-B1Per5XI.js} +1 -1
  113. package/build/assets/{skills-plugins-vfvOk34h.js → skills-plugins-B3AO6sMz.js} +1 -1
  114. package/build/assets/skills-settings-DmmgJ6CT.js +2 -0
  115. package/build/assets/{styled-tooltip-CQ9JEFiO.js → styled-tooltip-C5C07RQC.js} +1 -1
  116. package/build/assets/{task-list-tab-DeF_uXdw.js → task-list-tab-C19Q_JNf.js} +1 -1
  117. package/build/assets/{terminal-DRc4rup7.js → terminal-CbuMRYal.js} +1 -1
  118. package/build/assets/{toggle-switch--8n8NeV_.js → toggle-switch-CIioisto.js} +1 -1
  119. package/build/assets/{typography-BSbUhJPn.js → typography-D9tiHct7.js} +1 -1
  120. package/build/assets/{use-acp-credential-form-BGKFi1VL.js → use-acp-credential-form-DJmmJKMo.js} +1 -1
  121. package/build/assets/{use-activate-agent-profile-2nvALjC-.js → use-activate-agent-profile-CeFfYwu_.js} +1 -1
  122. package/build/assets/{use-agent-profiles-BlQA67MW.js → use-agent-profiles-BHLkLbRR.js} +1 -1
  123. package/build/assets/{use-can-manage-org-profiles-Clw5Dh1s.js → use-can-manage-org-profiles-Bu4y8gSx.js} +1 -1
  124. package/build/assets/{use-cloud-current-user-id-B8AQSQFM.js → use-cloud-current-user-id-QD9x3ySO.js} +1 -1
  125. package/build/assets/{use-config-C3zGuUQI.js → use-config-CPwqciXN.js} +1 -1
  126. package/build/assets/{use-create-conversation-FaP0kUpg.js → use-create-conversation-DWaSVUOB.js} +1 -1
  127. package/build/assets/{use-create-secret-CgQ3pXd6.js → use-create-secret-BsOfOLvg.js} +1 -1
  128. package/build/assets/{use-llm-profiles-C-tDO6UB.js → use-llm-profiles-CU8ah1pz.js} +1 -1
  129. package/build/assets/{use-manifest-capabilities-DLP5wCxp.js → use-manifest-capabilities-DBYPjyV6.js} +1 -1
  130. package/build/assets/{use-onboarding-completion-BiCdXvlU.js → use-onboarding-completion-CtNJxkXG.js} +1 -1
  131. package/build/assets/{use-plugins-marketplace-DRFNLBlr.js → use-plugins-marketplace-ZEA-gyM9.js} +1 -1
  132. package/build/assets/{use-save-agent-profile-CaGVAudI.js → use-save-agent-profile-DgI_Uz9a.js} +1 -1
  133. package/build/assets/{use-save-settings-C9B8Y-h3.js → use-save-settings-pSjRhD_m.js} +1 -1
  134. package/build/assets/{use-settings-3RcgdUuZ.js → use-settings-BHWsOcIG.js} +1 -1
  135. package/build/assets/use-settings-nav-items-CQgkxUbV.js +16 -0
  136. package/build/assets/{use-tracking-CTtkLAmx.js → use-tracking-CGCsBWhg.js} +1 -1
  137. package/build/assets/{use-user-conversation-Bei82QsZ.js → use-user-conversation-DRfEU8x0.js} +1 -1
  138. package/build/assets/utils-DPQfkd-7.js +1 -0
  139. package/build/assets/{verification-settings-nD61Ijph.js → verification-settings-BItwt998.js} +1 -1
  140. package/build/assets/wrench-B1_H-tL1.js +1 -0
  141. package/build/index.html +4 -4
  142. package/build/locales/ar/openhands.json +39 -2
  143. package/build/locales/ca/openhands.json +39 -2
  144. package/build/locales/de/openhands.json +39 -2
  145. package/build/locales/en/openhands.json +39 -2
  146. package/build/locales/es/openhands.json +39 -2
  147. package/build/locales/fr/openhands.json +39 -2
  148. package/build/locales/it/openhands.json +39 -2
  149. package/build/locales/ja/openhands.json +39 -2
  150. package/build/locales/ko-KR/openhands.json +39 -2
  151. package/build/locales/no/openhands.json +39 -2
  152. package/build/locales/pt/openhands.json +39 -2
  153. package/build/locales/tr/openhands.json +39 -2
  154. package/build/locales/uk/openhands.json +39 -2
  155. package/build/locales/zh-CN/openhands.json +39 -2
  156. package/build/locales/zh-TW/openhands.json +39 -2
  157. package/config/defaults.json +1 -1
  158. package/dist/api/agent-server-adapter.cjs +3 -3
  159. package/dist/api/agent-server-adapter.cjs.map +1 -1
  160. package/dist/api/agent-server-adapter.d.ts +32 -5
  161. package/dist/api/agent-server-adapter.js +120 -91
  162. package/dist/api/agent-server-adapter.js.map +1 -1
  163. package/dist/api/cloud/conversation-service.api.cjs +1 -1
  164. package/dist/api/cloud/conversation-service.api.cjs.map +1 -1
  165. package/dist/api/cloud/conversation-service.api.d.ts +19 -2
  166. package/dist/api/cloud/conversation-service.api.js +51 -47
  167. package/dist/api/cloud/conversation-service.api.js.map +1 -1
  168. package/dist/api/conversation-file-upload.api.cjs +1 -1
  169. package/dist/api/conversation-file-upload.api.js +10 -10
  170. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
  171. package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
  172. package/dist/api/conversation-service/agent-server-conversation-service.api.js +55 -61
  173. package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
  174. package/dist/api/event-service/event-service.api.cjs +1 -1
  175. package/dist/api/event-service/event-service.api.js +12 -12
  176. package/dist/api/launch-child-conversation-client-tool.cjs +47 -0
  177. package/dist/api/launch-child-conversation-client-tool.cjs.map +1 -0
  178. package/dist/api/launch-child-conversation-client-tool.d.ts +3 -0
  179. package/dist/api/launch-child-conversation-client-tool.js +93 -0
  180. package/dist/api/launch-child-conversation-client-tool.js.map +1 -0
  181. package/dist/api/open-hands.types.d.ts +1 -1
  182. package/dist/api/workspace-upload-path.cjs +1 -1
  183. package/dist/api/workspace-upload-path.js +8 -8
  184. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs +1 -1
  185. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.cjs.map +1 -1
  186. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js +24 -18
  187. package/dist/components/conversation-events/chat/event-content-helpers/get-action-event-title.js.map +1 -1
  188. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs +1 -1
  189. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.cjs.map +1 -1
  190. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js +5 -0
  191. package/dist/components/conversation-events/chat/event-content-helpers/get-event-content.js.map +1 -1
  192. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs +2 -2
  193. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.cjs.map +1 -1
  194. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js +11 -7
  195. package/dist/components/conversation-events/chat/event-content-helpers/should-render-event.js.map +1 -1
  196. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs +1 -2
  197. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.cjs.map +1 -1
  198. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.d.ts +2 -8
  199. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js +48 -51
  200. package/dist/components/features/conversation-panel/conversation-card/conversation-card-footer.js.map +1 -1
  201. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs +2 -0
  202. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.cjs.map +1 -0
  203. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.d.ts +12 -0
  204. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js +6 -0
  205. package/dist/components/features/conversation-panel/conversation-card/conversation-card-meta-chip.js.map +1 -0
  206. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
  207. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
  208. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.d.ts +16 -1
  209. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +95 -78
  210. package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
  211. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs +1 -1
  212. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.cjs.map +1 -1
  213. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js +40 -38
  214. package/dist/components/features/conversation-panel/conversation-card/conversation-repo-link.js.map +1 -1
  215. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +2 -0
  216. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -0
  217. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +14 -0
  218. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +167 -0
  219. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -0
  220. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +2 -0
  221. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -0
  222. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +63 -0
  223. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +66 -0
  224. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -0
  225. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs +2 -0
  226. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.cjs.map +1 -0
  227. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.d.ts +15 -0
  228. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js +117 -0
  229. package/dist/components/features/conversation-panel/conversation-card/conversation-tag-icons.js.map +1 -0
  230. package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs +1 -1
  231. package/dist/components/features/conversation-panel/conversation-card/no-repository.cjs.map +1 -1
  232. package/dist/components/features/conversation-panel/conversation-card/no-repository.js +30 -19
  233. package/dist/components/features/conversation-panel/conversation-card/no-repository.js.map +1 -1
  234. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +1 -1
  235. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +1 -1
  236. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +7 -2
  237. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +146 -104
  238. package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +1 -1
  239. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
  240. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
  241. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +20 -0
  242. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +53 -27
  243. package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
  244. package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
  245. package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
  246. package/dist/components/features/conversation-panel/conversation-panel.js +226 -213
  247. package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
  248. package/dist/components/features/settings/agent-canvas-update-card.cjs +1 -1
  249. package/dist/components/features/settings/agent-canvas-update-card.cjs.map +1 -1
  250. package/dist/components/features/settings/agent-canvas-update-card.d.ts +10 -5
  251. package/dist/components/features/settings/agent-canvas-update-card.js +223 -149
  252. package/dist/components/features/settings/agent-canvas-update-card.js.map +1 -1
  253. package/dist/components/features/settings/agent-canvas-version-modal.cjs +2 -0
  254. package/dist/components/features/settings/agent-canvas-version-modal.cjs.map +1 -0
  255. package/dist/components/features/settings/agent-canvas-version-modal.d.ts +11 -0
  256. package/dist/components/features/settings/agent-canvas-version-modal.js +166 -0
  257. package/dist/components/features/settings/agent-canvas-version-modal.js.map +1 -0
  258. package/dist/components/features/settings/agent-canvas-version-tile.cjs +2 -0
  259. package/dist/components/features/settings/agent-canvas-version-tile.cjs.map +1 -0
  260. package/dist/components/features/settings/agent-canvas-version-tile.d.ts +13 -0
  261. package/dist/components/features/settings/agent-canvas-version-tile.js +60 -0
  262. package/dist/components/features/settings/agent-canvas-version-tile.js.map +1 -0
  263. package/dist/components/features/settings/settings-desktop-sidebar.cjs +1 -1
  264. package/dist/components/features/settings/settings-desktop-sidebar.cjs.map +1 -1
  265. package/dist/components/features/settings/settings-desktop-sidebar.js +1 -1
  266. package/dist/components/features/settings/settings-desktop-sidebar.js.map +1 -1
  267. package/dist/components/features/settings/settings-mobile-drawer.cjs +1 -1
  268. package/dist/components/features/settings/settings-mobile-drawer.cjs.map +1 -1
  269. package/dist/components/features/settings/settings-mobile-drawer.js +1 -1
  270. package/dist/components/features/settings/settings-mobile-drawer.js.map +1 -1
  271. package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
  272. package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
  273. package/dist/components/features/sidebar/sidebar-rail-body.js +109 -108
  274. package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
  275. package/dist/components/features/skills/extensions-navigation.cjs +1 -1
  276. package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
  277. package/dist/components/features/skills/extensions-navigation.js +9 -9
  278. package/dist/components/features/skills/extensions-navigation.js.map +1 -1
  279. package/dist/config/defaults.cjs +1 -1
  280. package/dist/config/defaults.cjs.map +1 -1
  281. package/dist/config/defaults.js +1 -1
  282. package/dist/config/defaults.js.map +1 -1
  283. package/dist/constants/child-conversation.cjs +2 -0
  284. package/dist/constants/child-conversation.cjs.map +1 -0
  285. package/dist/constants/child-conversation.d.ts +29 -0
  286. package/dist/constants/child-conversation.js +6 -0
  287. package/dist/constants/child-conversation.js.map +1 -0
  288. package/dist/contexts/conversation-websocket-context.cjs +3 -3
  289. package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
  290. package/dist/contexts/conversation-websocket-context.js +189 -188
  291. package/dist/contexts/conversation-websocket-context.js.map +1 -1
  292. package/dist/hooks/chat/use-model-interceptor.cjs +1 -1
  293. package/dist/hooks/chat/use-model-interceptor.js +6 -6
  294. package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
  295. package/dist/hooks/mutation/use-create-conversation.js +6 -6
  296. package/dist/i18n/declaration.cjs +1 -1
  297. package/dist/i18n/declaration.cjs.map +1 -1
  298. package/dist/i18n/declaration.d.ts +38 -1
  299. package/dist/i18n/declaration.js +1 -1
  300. package/dist/i18n/declaration.js.map +1 -1
  301. package/dist/i18n/translation.cjs +2 -2
  302. package/dist/i18n/translation.cjs.map +1 -1
  303. package/dist/i18n/translation.js +644 -15
  304. package/dist/i18n/translation.js.map +1 -1
  305. package/dist/icons/docker.cjs +2 -0
  306. package/dist/icons/docker.cjs.map +1 -0
  307. package/dist/icons/docker.js +19 -0
  308. package/dist/icons/docker.js.map +1 -0
  309. package/dist/icons/npm.cjs +2 -0
  310. package/dist/icons/npm.cjs.map +1 -0
  311. package/dist/icons/npm.js +19 -0
  312. package/dist/icons/npm.js.map +1 -0
  313. package/dist/locales/ar/openhands.json +39 -2
  314. package/dist/locales/ca/openhands.json +39 -2
  315. package/dist/locales/de/openhands.json +39 -2
  316. package/dist/locales/en/openhands.json +39 -2
  317. package/dist/locales/es/openhands.json +39 -2
  318. package/dist/locales/fr/openhands.json +39 -2
  319. package/dist/locales/it/openhands.json +39 -2
  320. package/dist/locales/ja/openhands.json +39 -2
  321. package/dist/locales/ko-KR/openhands.json +39 -2
  322. package/dist/locales/no/openhands.json +39 -2
  323. package/dist/locales/pt/openhands.json +39 -2
  324. package/dist/locales/tr/openhands.json +39 -2
  325. package/dist/locales/uk/openhands.json +39 -2
  326. package/dist/locales/zh-CN/openhands.json +39 -2
  327. package/dist/locales/zh-TW/openhands.json +39 -2
  328. package/dist/node_modules/@openhands/typescript-client/dist/index.cjs +1 -1
  329. package/dist/node_modules/@openhands/typescript-client/dist/index.js +1 -1
  330. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs +2 -0
  331. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.cjs.map +1 -0
  332. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js +16 -0
  333. package/dist/node_modules/lucide-react/dist/esm/icons/briefcase.js.map +1 -0
  334. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs +2 -0
  335. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.cjs.map +1 -0
  336. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js +27 -0
  337. package/dist/node_modules/lucide-react/dist/esm/icons/building-2.js.map +1 -0
  338. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs +2 -0
  339. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.cjs.map +1 -0
  340. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js +21 -0
  341. package/dist/node_modules/lucide-react/dist/esm/icons/circle-arrow-up.js.map +1 -0
  342. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs +2 -0
  343. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.cjs.map +1 -0
  344. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js +23 -0
  345. package/dist/node_modules/lucide-react/dist/esm/icons/circle-user-round.js.map +1 -0
  346. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs +2 -0
  347. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.cjs.map +1 -0
  348. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js +43 -0
  349. package/dist/node_modules/lucide-react/dist/esm/icons/cloud-cog.js.map +1 -0
  350. package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs +2 -0
  351. package/dist/node_modules/lucide-react/dist/esm/icons/earth.cjs.map +1 -0
  352. package/dist/node_modules/lucide-react/dist/esm/icons/earth.js +25 -0
  353. package/dist/node_modules/lucide-react/dist/esm/icons/earth.js.map +1 -0
  354. package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs +2 -0
  355. package/dist/node_modules/lucide-react/dist/esm/icons/flag.cjs.map +1 -0
  356. package/dist/node_modules/lucide-react/dist/esm/icons/flag.js +9 -0
  357. package/dist/node_modules/lucide-react/dist/esm/icons/flag.js.map +1 -0
  358. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs +2 -0
  359. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.cjs.map +1 -0
  360. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js +27 -0
  361. package/dist/node_modules/lucide-react/dist/esm/icons/folder-git-2.js.map +1 -0
  362. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs +2 -0
  363. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.cjs.map +1 -0
  364. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js +25 -0
  365. package/dist/node_modules/lucide-react/dist/esm/icons/folder-key.js.map +1 -0
  366. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs +2 -0
  367. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.cjs.map +1 -0
  368. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js +30 -0
  369. package/dist/node_modules/lucide-react/dist/esm/icons/git-pull-request.js.map +1 -0
  370. package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs +2 -0
  371. package/dist/node_modules/lucide-react/dist/esm/icons/hash.cjs.map +1 -0
  372. package/dist/node_modules/lucide-react/dist/esm/icons/hash.js +35 -0
  373. package/dist/node_modules/lucide-react/dist/esm/icons/hash.js.map +1 -0
  374. package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs +2 -0
  375. package/dist/node_modules/lucide-react/dist/esm/icons/house.cjs.map +1 -0
  376. package/dist/node_modules/lucide-react/dist/esm/icons/house.js +12 -0
  377. package/dist/node_modules/lucide-react/dist/esm/icons/house.js.map +1 -0
  378. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs +2 -0
  379. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.cjs.map +1 -0
  380. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js +33 -0
  381. package/dist/node_modules/lucide-react/dist/esm/icons/id-card.js.map +1 -0
  382. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs +2 -0
  383. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.cjs.map +1 -0
  384. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js +15 -0
  385. package/dist/node_modules/lucide-react/dist/esm/icons/key-round.js.map +1 -0
  386. package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs +2 -0
  387. package/dist/node_modules/lucide-react/dist/esm/icons/layers.cjs.map +1 -0
  388. package/dist/node_modules/lucide-react/dist/esm/icons/layers.js +19 -0
  389. package/dist/node_modules/lucide-react/dist/esm/icons/layers.js.map +1 -0
  390. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs +2 -0
  391. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.cjs.map +1 -0
  392. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js +22 -0
  393. package/dist/node_modules/lucide-react/dist/esm/icons/link-2.js.map +1 -0
  394. package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs +2 -0
  395. package/dist/node_modules/lucide-react/dist/esm/icons/mails.cjs.map +1 -0
  396. package/dist/node_modules/lucide-react/dist/esm/icons/mails.js +23 -0
  397. package/dist/node_modules/lucide-react/dist/esm/icons/mails.js.map +1 -0
  398. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs +2 -0
  399. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.cjs.map +1 -0
  400. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js +12 -0
  401. package/dist/node_modules/lucide-react/dist/esm/icons/messages-square.js.map +1 -0
  402. package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs +2 -0
  403. package/dist/node_modules/lucide-react/dist/esm/icons/plug.cjs.map +1 -0
  404. package/dist/node_modules/lucide-react/dist/esm/icons/plug.js +23 -0
  405. package/dist/node_modules/lucide-react/dist/esm/icons/plug.js.map +1 -0
  406. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs +2 -0
  407. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.cjs.map +1 -0
  408. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js +27 -0
  409. package/dist/node_modules/lucide-react/dist/esm/icons/square-kanban.js.map +1 -0
  410. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs +2 -0
  411. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.cjs.map +1 -0
  412. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js +23 -0
  413. package/dist/node_modules/lucide-react/dist/esm/icons/ticket.js.map +1 -0
  414. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs +2 -0
  415. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.cjs.map +1 -0
  416. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js +21 -0
  417. package/dist/node_modules/lucide-react/dist/esm/icons/users-round.js.map +1 -0
  418. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs +2 -0
  419. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.cjs.map +1 -0
  420. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js +43 -0
  421. package/dist/node_modules/lucide-react/dist/esm/icons/waypoints.js.map +1 -0
  422. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs +2 -0
  423. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.cjs.map +1 -0
  424. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js +19 -0
  425. package/dist/node_modules/lucide-react/dist/esm/icons/webhook.js.map +1 -0
  426. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs +2 -0
  427. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.cjs.map +1 -0
  428. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js +27 -0
  429. package/dist/node_modules/lucide-react/dist/esm/icons/workflow.js.map +1 -0
  430. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs +2 -0
  431. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.cjs.map +1 -0
  432. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js +9 -0
  433. package/dist/node_modules/lucide-react/dist/esm/icons/wrench.js.map +1 -0
  434. package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs +2 -0
  435. package/dist/node_modules/lucide-react/dist/esm/icons/zap.cjs.map +1 -0
  436. package/dist/node_modules/lucide-react/dist/esm/icons/zap.js +9 -0
  437. package/dist/node_modules/lucide-react/dist/esm/icons/zap.js.map +1 -0
  438. package/dist/package.cjs +1 -1
  439. package/dist/package.cjs.map +1 -1
  440. package/dist/package.js +6 -3
  441. package/dist/package.js.map +1 -1
  442. package/dist/services/child-conversation-launch.cjs +2 -0
  443. package/dist/services/child-conversation-launch.cjs.map +1 -0
  444. package/dist/services/child-conversation-launch.d.ts +41 -0
  445. package/dist/services/child-conversation-launch.js +182 -0
  446. package/dist/services/child-conversation-launch.js.map +1 -0
  447. package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
  448. package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
  449. package/dist/stores/conversation-panel-preferences-store.d.ts +5 -1
  450. package/dist/stores/conversation-panel-preferences-store.js +8 -2
  451. package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
  452. package/dist/types/agent-server/core/base/action.d.ts +17 -1
  453. package/dist/types/agent-server/core/base/base.d.ts +2 -1
  454. package/dist/types/agent-server/type-guards.cjs +1 -1
  455. package/dist/types/agent-server/type-guards.cjs.map +1 -1
  456. package/dist/types/agent-server/type-guards.d.ts +8 -1
  457. package/dist/types/agent-server/type-guards.js +4 -3
  458. package/dist/types/agent-server/type-guards.js.map +1 -1
  459. package/dist/types/automation.d.ts +14 -0
  460. package/dist/utils/custom-toast-handlers.cjs +1 -1
  461. package/dist/utils/custom-toast-handlers.cjs.map +1 -1
  462. package/dist/utils/custom-toast-handlers.js +18 -1
  463. package/dist/utils/custom-toast-handlers.js.map +1 -1
  464. package/package.json +6 -3
  465. package/scripts/brand-dev-electron.mjs +244 -0
  466. package/scripts/check-translation-completeness.cjs +4 -0
  467. package/scripts/generate-icons.mjs +109 -0
  468. package/build/assets/agent-server-conversation-service.api-km_8sOVf.js +0 -41
  469. package/build/assets/agent-settings-nmO-KSXr.js +0 -1
  470. package/build/assets/backend-form-modal-B_lXjOGa.js +0 -1
  471. package/build/assets/command-menu-CA3IjGNc.js +0 -1
  472. package/build/assets/conversation-B6t6EiVp.js +0 -1
  473. package/build/assets/conversation-panel-B6t6EiVp.js +0 -1
  474. package/build/assets/copy-DaHuDtG4.js +0 -1
  475. package/build/assets/git-repo-dropdown-TzOuG5Ef.js +0 -1
  476. package/build/assets/home-OEx0XtfP.js +0 -1
  477. package/build/assets/index-home-OEx0XtfP.js +0 -1
  478. package/build/assets/info-C9lpK5pw.js +0 -1
  479. package/build/assets/install-server-modal-DnjZrJUy.js +0 -1
  480. package/build/assets/list-filter-C86CBRDE.js +0 -1
  481. package/build/assets/llm-settings-CRsLqxgu.js +0 -1
  482. package/build/assets/llm-settings-RBm_3kNm.js +0 -1
  483. package/build/assets/manifest-c352d453.js +0 -1
  484. package/build/assets/map-provider-CXU6issd.js +0 -1
  485. package/build/assets/markdown-renderer-lsvsp7jn.js +0 -8
  486. package/build/assets/mcp-DD4hPTRE.js +0 -9
  487. package/build/assets/messages-Dt77e0qi.js +0 -40
  488. package/build/assets/recommended-automations-launcher-6xmbf7lh.js +0 -1
  489. package/build/assets/root-BQPNqNvD.js +0 -2
  490. package/build/assets/root-BeuHFY2s.css +0 -1
  491. package/build/assets/root-layout-Dl_2CDoq.js +0 -3
  492. package/build/assets/settings-Co-M5bK9.js +0 -1
  493. package/build/assets/sidebar-store-B04sX8aP.js +0 -1
  494. package/build/assets/skills-settings-DnbIu2eO.js +0 -2
  495. package/build/assets/use-settings-nav-items-y-Oyc93G.js +0 -16
  496. package/build/assets/utils-BX9XJ0IE.js +0 -1
  497. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs +0 -2
  498. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.cjs.map +0 -1
  499. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js +0 -9
  500. package/dist/node_modules/lucide-react/dist/esm/icons/chevron-up.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-panel-filter-menu.js","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-filter-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n Bot,\n CalendarArrowDown,\n Clock3,\n ClockArrowDown,\n Eye,\n EyeOff,\n Folder,\n GitBranch,\n ListFilter,\n MessageCircle,\n MousePointerClick,\n Star,\n Tag,\n Trash2,\n} from \"lucide-react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport { cn } from \"#/utils/utils\";\nimport {\n dropdownInstantColorClassName,\n dropdownMenuListClassName,\n dropdownMenuViewportScrollClassName,\n} from \"#/utils/dropdown-classes\";\nimport type {\n ConversationSortField,\n OrganizeMode,\n ThreadScope,\n} from \"./conversation-panel-list-helpers\";\nimport { MenuHeading } from \"./menu-heading\";\nimport { MenuSeparator } from \"./menu-separator\";\nimport { MenuRow } from \"./menu-row\";\n\nconst capitalizeLabel = (label: string) =>\n label.length > 0 ? label.charAt(0).toUpperCase() + label.slice(1) : label;\n\nexport interface ConversationPanelFilterMenuProps {\n filterMenuOpen: boolean;\n setFilterMenuOpen: (open: boolean) => void;\n menuRef: React.RefObject<HTMLDivElement | null>;\n backendKind: BackendKind;\n organizeMode: OrganizeMode;\n setOrganizeMode: (mode: OrganizeMode) => void;\n conversationSort: ConversationSortField;\n setConversationSort: (sort: ConversationSortField) => void;\n threadScope: ThreadScope;\n setThreadScope: (scope: ThreadScope) => void;\n showOlderConversations: boolean;\n toggleShowOlderConversations: () => void;\n showRepoBranchMetadata: boolean;\n toggleShowRepoBranchMetadata: () => void;\n showLlmProfiles: boolean;\n toggleShowLlmProfiles: () => void;\n showTagsMetadata: boolean;\n toggleShowTagsMetadata: () => void;\n showHoverMetadata: boolean;\n toggleShowHoverMetadata: () => void;\n totalConversationsCount: number;\n onRequestDeleteAll: () => void;\n}\n\nexport function ConversationPanelFilterMenu({\n filterMenuOpen,\n setFilterMenuOpen,\n menuRef,\n backendKind,\n organizeMode,\n setOrganizeMode,\n conversationSort,\n setConversationSort,\n threadScope,\n setThreadScope,\n showOlderConversations,\n toggleShowOlderConversations,\n showRepoBranchMetadata,\n toggleShowRepoBranchMetadata,\n showLlmProfiles,\n toggleShowLlmProfiles,\n showTagsMetadata,\n toggleShowTagsMetadata,\n showHoverMetadata,\n toggleShowHoverMetadata,\n totalConversationsCount,\n onRequestDeleteAll,\n}: ConversationPanelFilterMenuProps) {\n const { t } = useTranslation(\"openhands\");\n\n const groupedLabel =\n backendKind === \"local\"\n ? t(I18nKey.CONVERSATION_PANEL$BY_WORKSPACE)\n : t(I18nKey.CONVERSATION_PANEL$BY_REPOSITORY);\n\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const menuContentRef = React.useRef<HTMLDivElement>(null);\n\n // When the menu opens, move keyboard focus into it so screen-reader /\n // keyboard-only users can interact with the options immediately. When\n // it closes, return focus to the trigger so Tab order picks up where\n // the user left off.\n const wasOpenRef = React.useRef(filterMenuOpen);\n React.useEffect(() => {\n if (filterMenuOpen) {\n const firstItem =\n menuContentRef.current?.querySelector<HTMLButtonElement>(\n '[role=\"menuitem\"], [role=\"menuitemradio\"]',\n );\n firstItem?.focus();\n } else if (wasOpenRef.current) {\n // Only return focus on a real open→close transition (not the\n // mount-with-open=false case).\n triggerRef.current?.focus();\n }\n wasOpenRef.current = filterMenuOpen;\n }, [filterMenuOpen]);\n\n // Roving Arrow Up/Down + Escape across the menu items. Tab still works\n // natively; Escape closes the menu and returns focus to the trigger\n // (via the effect above).\n const handleMenuKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setFilterMenuOpen(false);\n return;\n }\n if (event.key !== \"ArrowDown\" && event.key !== \"ArrowUp\") return;\n const container = menuContentRef.current;\n if (!container) return;\n const items = Array.from(\n container.querySelectorAll<HTMLButtonElement>(\n '[role=\"menuitem\"], [role=\"menuitemradio\"]',\n ),\n ).filter((el) => !el.disabled);\n if (items.length === 0) return;\n const currentIdx = items.indexOf(\n document.activeElement as HTMLButtonElement,\n );\n const delta = event.key === \"ArrowDown\" ? 1 : -1;\n const start = currentIdx === -1 ? 0 : currentIdx;\n const nextIdx = (start + delta + items.length) % items.length;\n event.preventDefault();\n items[nextIdx]?.focus();\n };\n\n return (\n <div ref={menuRef} className=\"relative shrink-0 pr-0.5\">\n <button\n ref={triggerRef}\n type=\"button\"\n data-testid=\"older-conversations-filter-toggle\"\n aria-label={t(I18nKey.CONVERSATION_PANEL$FILTER_LABEL)}\n aria-haspopup=\"menu\"\n aria-expanded={filterMenuOpen}\n onClick={() => setFilterMenuOpen(!filterMenuOpen)}\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md text-[var(--oh-muted)] hover:text-white hover:bg-[var(--oh-surface-raised)]\",\n dropdownInstantColorClassName,\n )}\n >\n <ListFilter\n className=\"lucide lucide-list-filter shrink-0\"\n width={14}\n height={14}\n strokeWidth={2}\n aria-hidden\n />\n </button>\n\n {filterMenuOpen ? (\n <div\n ref={menuContentRef}\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-label={t(I18nKey.CONVERSATION_PANEL$FILTER_LABEL)}\n // `role=\"menu\"` is an interactive ARIA role, so the container\n // must be focusable to satisfy jsx-a11y. `-1` keeps it out of\n // the natural Tab order (the menu items themselves are\n // `<button>`s and tabbable on their own) but still allows the\n // open-effect to focus it / its children programmatically.\n tabIndex={-1}\n data-testid=\"older-conversations-filter-menu\"\n onKeyDown={handleMenuKeyDown}\n className={cn(\n \"absolute right-0 top-full z-50 mt-0 w-64 rounded-md border border-[var(--oh-border-subtle)] bg-tertiary px-1 py-1 text-[var(--oh-foreground)] shadow-lg\",\n dropdownMenuListClassName,\n dropdownMenuViewportScrollClassName,\n )}\n >\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$ORGANIZE)}</MenuHeading>\n <MenuRow\n icon={Folder}\n label={groupedLabel}\n selected={organizeMode === \"grouped\"}\n onClick={() => {\n setOrganizeMode(\"grouped\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Clock3}\n label={t(I18nKey.CONVERSATION_PANEL$CHRONOLOGICAL)}\n selected={organizeMode === \"chronological\"}\n onClick={() => {\n setOrganizeMode(\"chronological\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$SORT_BY)}</MenuHeading>\n <MenuRow\n icon={CalendarArrowDown}\n label={t(I18nKey.CONVERSATION_PANEL$SORT_CREATED)}\n selected={conversationSort === \"created\"}\n onClick={() => {\n setConversationSort(\"created\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={ClockArrowDown}\n label={t(I18nKey.CONVERSATION_PANEL$SORT_UPDATED)}\n selected={conversationSort === \"updated\"}\n onClick={() => {\n setConversationSort(\"updated\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$SHOW)}</MenuHeading>\n <MenuRow\n icon={MessageCircle}\n label={t(I18nKey.CONVERSATION_PANEL$ALL_THREADS)}\n selected={threadScope === \"all\"}\n onClick={() => {\n setThreadScope(\"all\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Star}\n label={t(I18nKey.CONVERSATION_PANEL$RELEVANT_THREADS)}\n selected={threadScope === \"relevant\"}\n onClick={() => {\n setThreadScope(\"relevant\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$METADATA)}</MenuHeading>\n <MenuRow\n icon={Bot}\n label={t(I18nKey.CONVERSATION_PANEL$LLM_MODEL)}\n selected={showLlmProfiles}\n testId=\"toggle-llm-profiles\"\n onClick={() => {\n toggleShowLlmProfiles();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={GitBranch}\n label={t(I18nKey.CONVERSATION_PANEL$REPO_BRANCH)}\n selected={showRepoBranchMetadata}\n testId=\"toggle-repo-branch-metadata\"\n onClick={() => {\n toggleShowRepoBranchMetadata();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Tag}\n label={t(I18nKey.CONVERSATION_PANEL$TAGS)}\n selected={showTagsMetadata}\n testId=\"toggle-tags-metadata\"\n onClick={() => {\n toggleShowTagsMetadata();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={MousePointerClick}\n label={t(I18nKey.CONVERSATION_PANEL$HOVER_METADATA)}\n selected={showHoverMetadata}\n testId=\"toggle-hover-metadata\"\n onClick={() => {\n toggleShowHoverMetadata();\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading\n suffix={\n <span className=\"shrink-0 text-right text-[10px] font-medium normal-case tracking-normal text-[var(--oh-muted)]/70\">\n {t(I18nKey.CONVERSATION_PANEL$OLDER_OVER_ONE_HOUR)}\n </span>\n }\n >\n {t(I18nKey.CONVERSATION_PANEL$OLDER_SECTION)}\n </MenuHeading>\n <MenuRow\n testId=\"toggle-older-conversations\"\n icon={showOlderConversations ? EyeOff : Eye}\n label={\n showOlderConversations\n ? capitalizeLabel(t(I18nKey.CONVERSATION$HIDE))\n : capitalizeLabel(t(I18nKey.CONVERSATION$SHOW_ALL))\n }\n onClick={() => {\n toggleShowOlderConversations();\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuRow\n testId=\"delete-all-conversations\"\n icon={Trash2}\n label={capitalizeLabel(t(I18nKey.CONVERSATION$DELETE_ALL))}\n disabled={totalConversationsCount === 0}\n onClick={() => {\n if (totalConversationsCount === 0) return;\n onRequestDeleteAll();\n setFilterMenuOpen(false);\n }}\n />\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversation-panel-filter-menu.js","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-filter-menu.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n Bot,\n CalendarArrowDown,\n Clock3,\n ClockArrowDown,\n Eye,\n EyeOff,\n Folder,\n GitBranch,\n ListFilter,\n MessageCircle,\n MousePointerClick,\n Star,\n Tag,\n Trash2,\n Workflow,\n} from \"lucide-react\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport { cn } from \"#/utils/utils\";\nimport {\n dropdownInstantColorClassName,\n dropdownMenuListClassName,\n dropdownMenuViewportScrollClassName,\n} from \"#/utils/dropdown-classes\";\nimport {\n UNNAMED_AUTOMATION_FACET,\n type AutomationFilterMode,\n type ConversationSortField,\n type OrganizeMode,\n type ThreadScope,\n} from \"./conversation-panel-list-helpers\";\nimport { MenuHeading } from \"./menu-heading\";\nimport { MenuSeparator } from \"./menu-separator\";\nimport { MenuRow } from \"./menu-row\";\n\nconst capitalizeLabel = (label: string) =>\n label.length > 0 ? label.charAt(0).toUpperCase() + label.slice(1) : label;\n\nexport interface ConversationPanelFilterMenuProps {\n filterMenuOpen: boolean;\n setFilterMenuOpen: (open: boolean) => void;\n menuRef: React.RefObject<HTMLDivElement | null>;\n backendKind: BackendKind;\n organizeMode: OrganizeMode;\n setOrganizeMode: (mode: OrganizeMode) => void;\n conversationSort: ConversationSortField;\n setConversationSort: (sort: ConversationSortField) => void;\n threadScope: ThreadScope;\n setThreadScope: (scope: ThreadScope) => void;\n automationFilterMode: AutomationFilterMode;\n setAutomationFilterMode: (mode: AutomationFilterMode) => void;\n selectedAutomationNames: string[];\n onToggleAutomationName: (name: string) => void;\n automationNameFacets: string[];\n showOlderConversations: boolean;\n toggleShowOlderConversations: () => void;\n showRepoBranchMetadata: boolean;\n toggleShowRepoBranchMetadata: () => void;\n showLlmProfiles: boolean;\n toggleShowLlmProfiles: () => void;\n showTagsMetadata: boolean;\n toggleShowTagsMetadata: () => void;\n showHoverMetadata: boolean;\n toggleShowHoverMetadata: () => void;\n totalConversationsCount: number;\n onRequestDeleteAll: () => void;\n}\n\nexport function ConversationPanelFilterMenu({\n filterMenuOpen,\n setFilterMenuOpen,\n menuRef,\n backendKind,\n organizeMode,\n setOrganizeMode,\n conversationSort,\n setConversationSort,\n threadScope,\n setThreadScope,\n automationFilterMode,\n setAutomationFilterMode,\n selectedAutomationNames,\n onToggleAutomationName,\n automationNameFacets,\n showOlderConversations,\n toggleShowOlderConversations,\n showRepoBranchMetadata,\n toggleShowRepoBranchMetadata,\n showLlmProfiles,\n toggleShowLlmProfiles,\n showTagsMetadata,\n toggleShowTagsMetadata,\n showHoverMetadata,\n toggleShowHoverMetadata,\n totalConversationsCount,\n onRequestDeleteAll,\n}: ConversationPanelFilterMenuProps) {\n const { t } = useTranslation(\"openhands\");\n\n const groupedLabel =\n backendKind === \"local\"\n ? t(I18nKey.CONVERSATION_PANEL$BY_WORKSPACE)\n : t(I18nKey.CONVERSATION_PANEL$BY_REPOSITORY);\n\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const menuContentRef = React.useRef<HTMLDivElement>(null);\n\n // When the menu opens, move keyboard focus into it so screen-reader /\n // keyboard-only users can interact with the options immediately. When\n // it closes, return focus to the trigger so Tab order picks up where\n // the user left off.\n const wasOpenRef = React.useRef(filterMenuOpen);\n React.useEffect(() => {\n if (filterMenuOpen) {\n const firstItem =\n menuContentRef.current?.querySelector<HTMLButtonElement>(\n '[role=\"menuitem\"], [role=\"menuitemradio\"]',\n );\n firstItem?.focus();\n } else if (wasOpenRef.current) {\n // Only return focus on a real open→close transition (not the\n // mount-with-open=false case).\n triggerRef.current?.focus();\n }\n wasOpenRef.current = filterMenuOpen;\n }, [filterMenuOpen]);\n\n // Roving Arrow Up/Down + Escape across the menu items. Tab still works\n // natively; Escape closes the menu and returns focus to the trigger\n // (via the effect above).\n const handleMenuKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n setFilterMenuOpen(false);\n return;\n }\n if (event.key !== \"ArrowDown\" && event.key !== \"ArrowUp\") return;\n const container = menuContentRef.current;\n if (!container) return;\n const items = Array.from(\n container.querySelectorAll<HTMLButtonElement>(\n '[role=\"menuitem\"], [role=\"menuitemradio\"]',\n ),\n ).filter((el) => !el.disabled);\n if (items.length === 0) return;\n const currentIdx = items.indexOf(\n document.activeElement as HTMLButtonElement,\n );\n const delta = event.key === \"ArrowDown\" ? 1 : -1;\n const start = currentIdx === -1 ? 0 : currentIdx;\n const nextIdx = (start + delta + items.length) % items.length;\n event.preventDefault();\n items[nextIdx]?.focus();\n };\n\n return (\n <div ref={menuRef} className=\"relative shrink-0 pr-0.5\">\n <button\n ref={triggerRef}\n type=\"button\"\n data-testid=\"older-conversations-filter-toggle\"\n aria-label={t(I18nKey.CONVERSATION_PANEL$FILTER_LABEL)}\n aria-haspopup=\"menu\"\n aria-expanded={filterMenuOpen}\n onClick={() => setFilterMenuOpen(!filterMenuOpen)}\n className={cn(\n \"relative inline-flex h-7 w-7 items-center justify-center rounded-md text-[var(--oh-muted)] hover:text-white hover:bg-[var(--oh-surface-raised)]\",\n dropdownInstantColorClassName,\n )}\n >\n <ListFilter\n className=\"lucide lucide-list-filter shrink-0\"\n width={14}\n height={14}\n strokeWidth={2}\n aria-hidden\n />\n {automationFilterMode !== \"all\" ? (\n <span\n aria-hidden\n data-testid=\"automation-filter-active-indicator\"\n className=\"absolute right-0.5 top-0.5 h-1.5 w-1.5 rounded-full bg-[var(--oh-accent)]\"\n />\n ) : null}\n </button>\n\n {filterMenuOpen ? (\n <div\n ref={menuContentRef}\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-label={t(I18nKey.CONVERSATION_PANEL$FILTER_LABEL)}\n // `role=\"menu\"` is an interactive ARIA role, so the container\n // must be focusable to satisfy jsx-a11y. `-1` keeps it out of\n // the natural Tab order (the menu items themselves are\n // `<button>`s and tabbable on their own) but still allows the\n // open-effect to focus it / its children programmatically.\n tabIndex={-1}\n data-testid=\"older-conversations-filter-menu\"\n onKeyDown={handleMenuKeyDown}\n className={cn(\n \"absolute right-0 top-full z-50 mt-0 w-64 rounded-md border border-[var(--oh-border-subtle)] bg-tertiary px-1 py-1 text-[var(--oh-foreground)] shadow-lg\",\n dropdownMenuListClassName,\n dropdownMenuViewportScrollClassName,\n )}\n >\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$ORGANIZE)}</MenuHeading>\n <MenuRow\n icon={Folder}\n label={groupedLabel}\n selected={organizeMode === \"grouped\"}\n onClick={() => {\n setOrganizeMode(\"grouped\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Clock3}\n label={t(I18nKey.CONVERSATION_PANEL$CHRONOLOGICAL)}\n selected={organizeMode === \"chronological\"}\n onClick={() => {\n setOrganizeMode(\"chronological\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$SORT_BY)}</MenuHeading>\n <MenuRow\n icon={CalendarArrowDown}\n label={t(I18nKey.CONVERSATION_PANEL$SORT_CREATED)}\n selected={conversationSort === \"created\"}\n onClick={() => {\n setConversationSort(\"created\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={ClockArrowDown}\n label={t(I18nKey.CONVERSATION_PANEL$SORT_UPDATED)}\n selected={conversationSort === \"updated\"}\n onClick={() => {\n setConversationSort(\"updated\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$SHOW)}</MenuHeading>\n <MenuRow\n icon={MessageCircle}\n label={t(I18nKey.CONVERSATION_PANEL$ALL_THREADS)}\n selected={threadScope === \"all\"}\n onClick={() => {\n setThreadScope(\"all\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Star}\n label={t(I18nKey.CONVERSATION_PANEL$RELEVANT_THREADS)}\n selected={threadScope === \"relevant\"}\n onClick={() => {\n setThreadScope(\"relevant\");\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$AUTOMATIONS)}</MenuHeading>\n <MenuRow\n icon={MessageCircle}\n label={t(I18nKey.CONVERSATION_PANEL$AUTOMATIONS_ALL)}\n selected={automationFilterMode === \"all\"}\n testId=\"automation-filter-all\"\n onClick={() => {\n setAutomationFilterMode(\"all\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={EyeOff}\n label={t(I18nKey.CONVERSATION_PANEL$AUTOMATIONS_HIDE)}\n selected={automationFilterMode === \"hide-automations\"}\n testId=\"automation-filter-hide\"\n onClick={() => {\n setAutomationFilterMode(\"hide-automations\");\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Workflow}\n label={t(I18nKey.CONVERSATION_PANEL$AUTOMATIONS_ONLY)}\n selected={automationFilterMode === \"only-automations\"}\n testId=\"automation-filter-only\"\n onClick={() => {\n setAutomationFilterMode(\"only-automations\");\n setFilterMenuOpen(false);\n }}\n />\n {automationFilterMode === \"only-automations\"\n ? automationNameFacets.map((facet) => (\n <MenuRow\n key={facet}\n icon={Tag}\n label={\n facet === UNNAMED_AUTOMATION_FACET\n ? t(I18nKey.CONVERSATION_PANEL$AUTOMATION_UNNAMED)\n : facet\n }\n selected={selectedAutomationNames.includes(facet)}\n testId={`automation-name-filter-${facet}`}\n // Multi-select name rows keep the menu open (unlike the\n // mode radios above) so several names can be toggled in\n // one visit.\n onClick={() => onToggleAutomationName(facet)}\n />\n ))\n : null}\n\n <MenuSeparator />\n <MenuHeading>{t(I18nKey.CONVERSATION_PANEL$METADATA)}</MenuHeading>\n <MenuRow\n icon={GitBranch}\n label={t(I18nKey.CONVERSATION_PANEL$REPO_BRANCH)}\n selected={showRepoBranchMetadata}\n testId=\"toggle-repo-branch-metadata\"\n onClick={() => {\n toggleShowRepoBranchMetadata();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Bot}\n label={t(I18nKey.CONVERSATION_PANEL$LLM_MODEL)}\n selected={showLlmProfiles}\n testId=\"toggle-llm-profiles\"\n onClick={() => {\n toggleShowLlmProfiles();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={Tag}\n label={t(I18nKey.CONVERSATION_PANEL$TAGS)}\n selected={showTagsMetadata}\n testId=\"toggle-tags-metadata\"\n onClick={() => {\n toggleShowTagsMetadata();\n setFilterMenuOpen(false);\n }}\n />\n <MenuRow\n icon={MousePointerClick}\n label={t(I18nKey.CONVERSATION_PANEL$HOVER_METADATA)}\n selected={showHoverMetadata}\n testId=\"toggle-hover-metadata\"\n onClick={() => {\n toggleShowHoverMetadata();\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuHeading\n suffix={\n <span className=\"shrink-0 text-right text-[10px] font-medium normal-case tracking-normal text-[var(--oh-muted)]/70\">\n {t(I18nKey.CONVERSATION_PANEL$OLDER_OVER_ONE_HOUR)}\n </span>\n }\n >\n {t(I18nKey.CONVERSATION_PANEL$OLDER_SECTION)}\n </MenuHeading>\n <MenuRow\n testId=\"toggle-older-conversations\"\n icon={showOlderConversations ? EyeOff : Eye}\n label={\n showOlderConversations\n ? capitalizeLabel(t(I18nKey.CONVERSATION$HIDE))\n : capitalizeLabel(t(I18nKey.CONVERSATION$SHOW_ALL))\n }\n onClick={() => {\n toggleShowOlderConversations();\n setFilterMenuOpen(false);\n }}\n />\n\n <MenuSeparator />\n <MenuRow\n testId=\"delete-all-conversations\"\n icon={Trash2}\n label={capitalizeLabel(t(I18nKey.CONVERSATION$DELETE_ALL))}\n disabled={totalConversationsCount === 0}\n onClick={() => {\n if (totalConversationsCount === 0) return;\n onRequestDeleteAll();\n setFilterMenuOpen(false);\n }}\n />\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../../_virtual/_rolldown/runtime.cjs");function e(e,t){let n=t.limit??5;if(t.expanded||e.length<=n)return{visibleConversations:[...e],isPreviewTruncated:e.length>n,isShowingAll:!0};let r=t.activeConversationId==null?-1:e.findIndex(e=>e.id===t.activeConversationId);if(r>=n){let t=e[r];return{visibleConversations:[...e.slice(0,n-1),t],isPreviewTruncated:!0,isShowingAll:!1}}return{visibleConversations:e.slice(0,n),isPreviewTruncated:e.length>n,isShowingAll:!1}}function t(e,t){let n=new Map(t.map(e=>[e.id,e]));return e.map(e=>n.get(e)).filter(e=>e!=null)}function n(e,t){if(t.length===0)return[...e];let n=new Set(t);return e.filter(e=>!n.has(e.id))}function r(e,t,n){if(t===`local`)return e===`__none_workspace`?{}:e.startsWith(`ws:`)?{workingDir:e.slice(3)}:{};if(e===`__none_repo`)return{};if(e.startsWith(`repo:`)){let t=e.slice(5),r=n[0];return{repository:{name:t,gitProvider:r?.git_provider??`github`,branch:r?.selected_branch??`main`}}}return{}}function i(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function a(e,t){let n=t===`created`?`created_at`:`updated_at`;return[...e].sort((e,t)=>i(t[n])-i(e[n]))}function o(e){let t=e.selected_workspace?.trim().replace(/\/+$/,``);if(!t)return{id:`__none_workspace`,label:``};let n=t.split(`/`).filter(Boolean).pop()??t;return{id:`ws:${t}`,label:n}}function s(e){let t=e.selected_repository?.trim().replace(/\/+$/,``);if(!t)return{id:`__none_repo`,label:``};let n=t.split(`/`).filter(Boolean),r=n.length?(n[n.length-1]??t).replace(/\.git$/,``):t.replace(/\.git$/,``);return{id:`repo:${t}`,label:r}}function c(e,t,n,c){let l=new Map;for(let n of e){let{id:e,label:r}=t===`local`?o(n):s(n),i=e===`__none_workspace`?c.emptyWorkspace:e===`__none_repo`?c.emptyRepository:r,a=l.get(e);a?a.conversations.push(n):l.set(e,{label:i,conversations:[n]})}let u=[...l.entries()].map(([e,i])=>{let o=a(i.conversations,n);return{id:e,label:i.label,conversations:o,launch:r(e,t,o)}}),d=e=>e.conversations.reduce((e,t)=>Math.max(e,i(n===`created`?t.created_at:t.updated_at)),0);return u.sort((e,t)=>d(t)-d(e)),u}function l(e,t){if(t.length===0)return[...e];let n=new Map(e.map(e=>[e.id,e])),r=[],i=new Set;for(let e of t){let t=n.get(e);t&&(r.push(t),i.add(e))}for(let t of e)i.has(t.id)||r.push(t);return r}function u(e,t,n,r,i=`after`){if(n===r)return[...e];let a=l(t.map(e=>({id:e})),e).map(e=>e.id),o=a.indexOf(n),s=a.indexOf(r);if(o<0||s<0)return[...e];let c=[...a];c.splice(o,1);let u=c.indexOf(r),d=i===`before`?u:u+1;return c.splice(d,0,n),c}exports.applyGroupFolderOrder=l,exports.filterOutPinnedConversations=n,exports.getGroupConversationPreview=e,exports.groupConversations=c,exports.moveGroupFolderOrder=u,exports.resolvePinnedConversations=t,exports.sortConversationsByField=a;
1
+ require("../../../_virtual/_rolldown/runtime.cjs");const e=require("../../../api/agent-server-adapter.cjs");function t(e,t){let n=t.limit??5;if(t.expanded||e.length<=n)return{visibleConversations:[...e],isPreviewTruncated:e.length>n,isShowingAll:!0};let r=t.activeConversationId==null?-1:e.findIndex(e=>e.id===t.activeConversationId);if(r>=n){let t=e[r];return{visibleConversations:[...e.slice(0,n-1),t],isPreviewTruncated:!0,isShowingAll:!1}}return{visibleConversations:e.slice(0,n),isPreviewTruncated:e.length>n,isShowingAll:!1}}function n(e,t){let n=new Map(t.map(e=>[e.id,e]));return e.map(e=>n.get(e)).filter(e=>e!=null)}function r(e,t){if(t.length===0)return[...e];let n=new Set(t);return e.filter(e=>!n.has(e.id))}var i=`__unnamed__`;function a(t){if(t.trigger===`automation`)return!0;let n=t.tags;return n?e.AUTOMATION_TAG_KEYS.some(e=>!!n[e]):!1}function o(e){return e.tags?.automationname?.trim()||`__unnamed__`}function s(e){let t=new Set,n=!1;for(let r of e){if(!a(r))continue;let e=o(r);e===`__unnamed__`?n=!0:t.add(e)}let r=[...t].sort((e,t)=>e.localeCompare(t));return n&&r.push(i),r}function c(e,t,n,r){if(t===`all`)return[...e];if(t===`hide-automations`)return e.filter(e=>!a(e));let i=new Set(r),s=n.filter(e=>i.has(e)),c=s.length>0?new Set(s):null;return e.filter(e=>a(e)?c===null||c.has(o(e)):!1)}function l(e,t,n){if(t===`local`)return e===`__none_workspace`?{}:e.startsWith(`ws:`)?{workingDir:e.slice(3)}:{};if(e===`__none_repo`)return{};if(e.startsWith(`repo:`)){let t=e.slice(5),r=n[0];return{repository:{name:t,gitProvider:r?.git_provider??`github`,branch:r?.selected_branch??`main`}}}return{}}function u(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function d(e,t){let n=t===`created`?`created_at`:`updated_at`;return[...e].sort((e,t)=>u(t[n])-u(e[n]))}function f(e){let t=e.selected_workspace?.trim().replace(/\/+$/,``);if(!t)return{id:`__none_workspace`,label:``};let n=t.split(`/`).filter(Boolean).pop()??t;return{id:`ws:${t}`,label:n}}function p(e){let t=e.selected_repository?.trim().replace(/\/+$/,``);if(!t)return{id:`__none_repo`,label:``};let n=t.split(`/`).filter(Boolean),r=n.length?(n[n.length-1]??t).replace(/\.git$/,``):t.replace(/\.git$/,``);return{id:`repo:${t}`,label:r}}function m(e,t,n,r){let i=new Map;for(let n of e){let{id:e,label:a}=t===`local`?f(n):p(n),o=e===`__none_workspace`?r.emptyWorkspace:e===`__none_repo`?r.emptyRepository:a,s=i.get(e);s?s.conversations.push(n):i.set(e,{label:o,conversations:[n]})}let a=[...i.entries()].map(([e,r])=>{let i=d(r.conversations,n);return{id:e,label:r.label,conversations:i,launch:l(e,t,i)}}),o=e=>e.conversations.reduce((e,t)=>Math.max(e,u(n===`created`?t.created_at:t.updated_at)),0);return a.sort((e,t)=>o(t)-o(e)),a}function h(e,t){if(t.length===0)return[...e];let n=new Map(e.map(e=>[e.id,e])),r=[],i=new Set;for(let e of t){let t=n.get(e);t&&(r.push(t),i.add(e))}for(let t of e)i.has(t.id)||r.push(t);return r}function g(e,t,n,r,i=`after`){if(n===r)return[...e];let a=h(t.map(e=>({id:e})),e).map(e=>e.id),o=a.indexOf(n),s=a.indexOf(r);if(o<0||s<0)return[...e];let c=[...a];c.splice(o,1);let l=c.indexOf(r),u=i===`before`?l:l+1;return c.splice(u,0,n),c}exports.UNNAMED_AUTOMATION_FACET=i,exports.applyAutomationConversationFilter=c,exports.applyGroupFolderOrder=h,exports.collectAutomationNameFacets=s,exports.filterOutPinnedConversations=r,exports.getGroupConversationPreview=t,exports.groupConversations=m,exports.moveGroupFolderOrder=g,exports.resolvePinnedConversations=n,exports.sortConversationsByField=d;
2
2
  //# sourceMappingURL=conversation-panel-list-helpers.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-panel-list-helpers.cjs","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-list-helpers.ts"],"sourcesContent":["import type { AppConversation } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport type { Provider } from \"#/types/settings\";\n\nexport type ConversationSortField = \"created\" | \"updated\";\nexport type ThreadScope = \"all\" | \"relevant\";\nexport type OrganizeMode = \"grouped\" | \"chronological\";\n\n/** Max conversations shown under a workspace/repo folder before \"View more\". */\nexport const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;\n\ninterface GroupConversationPreviewOptions {\n limit?: number;\n expanded: boolean;\n activeConversationId?: string | null;\n}\n\nexport function getGroupConversationPreview(\n conversations: readonly AppConversation[],\n options: GroupConversationPreviewOptions,\n): {\n visibleConversations: AppConversation[];\n isPreviewTruncated: boolean;\n isShowingAll: boolean;\n} {\n const limit = options.limit ?? GROUP_CONVERSATIONS_PREVIEW_LIMIT;\n\n if (options.expanded || conversations.length <= limit) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: true,\n };\n }\n\n const activeIndex =\n options.activeConversationId != null\n ? conversations.findIndex((c) => c.id === options.activeConversationId)\n : -1;\n\n if (activeIndex >= limit) {\n const activeConversation = conversations[activeIndex];\n return {\n visibleConversations: [\n ...conversations.slice(0, limit - 1),\n activeConversation,\n ],\n isPreviewTruncated: true,\n isShowingAll: false,\n };\n }\n\n return {\n visibleConversations: conversations.slice(0, limit),\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: false,\n };\n}\n\nexport function resolvePinnedConversations(\n pinnedIds: readonly string[],\n conversations: readonly AppConversation[],\n): AppConversation[] {\n const byId = new Map(\n conversations.map((conversation) => [conversation.id, conversation]),\n );\n return pinnedIds\n .map((id) => byId.get(id))\n .filter(\n (conversation): conversation is AppConversation => conversation != null,\n );\n}\n\nexport function filterOutPinnedConversations(\n conversations: readonly AppConversation[],\n pinnedIds: readonly string[],\n): AppConversation[] {\n if (pinnedIds.length === 0) {\n return [...conversations];\n }\n\n const pinnedSet = new Set(pinnedIds);\n return conversations.filter(\n (conversation) => !pinnedSet.has(conversation.id),\n );\n}\n\n/** Subset of `useCreateConversation` variables for launching from a group row */\nexport type ConversationGroupLaunch = {\n workingDir?: string;\n repository?: {\n name: string;\n gitProvider: Provider;\n branch?: string;\n };\n};\n\nfunction buildGroupLaunch(\n id: string,\n backendKind: BackendKind,\n conversations: AppConversation[],\n): ConversationGroupLaunch {\n if (backendKind === \"local\") {\n if (id === \"__none_workspace\") {\n return {};\n }\n if (id.startsWith(\"ws:\")) {\n return { workingDir: id.slice(3) };\n }\n return {};\n }\n\n if (id === \"__none_repo\") {\n return {};\n }\n if (id.startsWith(\"repo:\")) {\n const name = id.slice(5);\n const sample = conversations[0];\n const gitProvider = (sample?.git_provider ?? \"github\") as Provider;\n const branch = sample?.selected_branch ?? \"main\";\n return {\n repository: {\n name,\n gitProvider,\n branch,\n },\n };\n }\n\n return {};\n}\n\nexport function parseConversationTimeMs(iso: string | undefined): number {\n if (!iso) return 0;\n const t = Date.parse(iso);\n return Number.isFinite(t) ? t : 0;\n}\n\nexport function sortConversationsByField(\n items: readonly AppConversation[],\n field: ConversationSortField,\n): AppConversation[] {\n const key = field === \"created\" ? \"created_at\" : \"updated_at\";\n return [...items].sort(\n (a, b) => parseConversationTimeMs(b[key]) - parseConversationTimeMs(a[key]),\n );\n}\n\nfunction workspaceGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Group by the user-selected workspace (a stable identifier shared by\n // every conversation launched from the same picker selection), not\n // `workspace.working_dir` — that field holds the per-conversation\n // worktree path the agent-server creates, which is unique per\n // conversation and would fragment the grouping.\n //\n // Normalize first, then check emptiness: inputs like \"/\", \"///\", or\n // \" ///\" trim+strip to \"\" and must fall back to the \"no workspace\"\n // bucket rather than producing a stray `ws:` group with no label.\n const normalized = conversation.selected_workspace\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_workspace\", label: \"\" };\n }\n const label = normalized.split(\"/\").filter(Boolean).pop() ?? normalized;\n return { id: `ws:${normalized}`, label };\n}\n\nfunction repositoryGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Mirror `workspaceGroup`'s normalize-then-check order so \"/\", \"///\",\n // and trailing-slash variants of the same repo all collapse to one\n // group instead of producing a stray `repo:/` bucket.\n const normalized = conversation.selected_repository\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_repo\", label: \"\" };\n }\n const parts = normalized.split(\"/\").filter(Boolean);\n const label = parts.length\n ? (parts[parts.length - 1] ?? normalized).replace(/\\.git$/, \"\")\n : normalized.replace(/\\.git$/, \"\");\n return { id: `repo:${normalized}`, label };\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n): {\n id: string;\n label: string;\n conversations: AppConversation[];\n launch: ConversationGroupLaunch;\n}[] {\n const byId = new Map<\n string,\n { label: string; conversations: AppConversation[] }\n >();\n\n for (const c of items) {\n const { id, label: rawLabel } =\n backendKind === \"local\" ? workspaceGroup(c) : repositoryGroup(c);\n const label =\n id === \"__none_workspace\"\n ? labels.emptyWorkspace\n : id === \"__none_repo\"\n ? labels.emptyRepository\n : rawLabel;\n const bucket = byId.get(id);\n if (bucket) {\n bucket.conversations.push(c);\n } else {\n byId.set(id, { label, conversations: [c] });\n }\n }\n\n const groups = [...byId.entries()].map(([id, g]) => {\n const conversations = sortConversationsByField(g.conversations, sortField);\n return {\n id,\n label: g.label,\n conversations,\n launch: buildGroupLaunch(id, backendKind, conversations),\n };\n });\n\n // Use reduce instead of `Math.max(...arr)` — the spread form would push\n // every conversation onto the call stack as a separate argument, which\n // hits JS engines' ~100k-arg limit on very large buckets.\n const groupOrderKey = (g: (typeof groups)[number]) =>\n g.conversations.reduce(\n (max, c) =>\n Math.max(\n max,\n parseConversationTimeMs(\n sortField === \"created\" ? c.created_at : c.updated_at,\n ),\n ),\n 0,\n );\n\n groups.sort((a, b) => groupOrderKey(b) - groupOrderKey(a));\n return groups;\n}\n\nexport function applyGroupFolderOrder<T extends { id: string }>(\n groups: readonly T[],\n order: readonly string[],\n): T[] {\n if (order.length === 0) {\n return [...groups];\n }\n\n const byId = new Map(groups.map((group) => [group.id, group]));\n const ordered: T[] = [];\n const seen = new Set<string>();\n\n for (const id of order) {\n const group = byId.get(id);\n if (group) {\n ordered.push(group);\n seen.add(id);\n }\n }\n\n for (const group of groups) {\n if (!seen.has(group.id)) {\n ordered.push(group);\n }\n }\n\n return ordered;\n}\n\nexport type GroupFolderDropPosition = \"before\" | \"after\";\n\nexport function moveGroupFolderOrder(\n order: readonly string[],\n groupIds: readonly string[],\n activeGroupId: string,\n targetGroupId: string,\n position: GroupFolderDropPosition = \"after\",\n): string[] {\n if (activeGroupId === targetGroupId) {\n return [...order];\n }\n\n const effectiveOrder = applyGroupFolderOrder(\n groupIds.map((id) => ({ id })),\n order,\n ).map((group) => group.id);\n const fromIndex = effectiveOrder.indexOf(activeGroupId);\n const toIndex = effectiveOrder.indexOf(targetGroupId);\n if (fromIndex < 0 || toIndex < 0) {\n return [...order];\n }\n\n const nextOrder = [...effectiveOrder];\n nextOrder.splice(fromIndex, 1);\n const adjustedTargetIndex = nextOrder.indexOf(targetGroupId);\n const insertIndex =\n position === \"before\" ? adjustedTargetIndex : adjustedTargetIndex + 1;\n nextOrder.splice(insertIndex, 0, activeGroupId);\n return nextOrder;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversation-panel-list-helpers.cjs","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-list-helpers.ts"],"sourcesContent":["import type { AppConversation } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport type { Provider } from \"#/types/settings\";\nimport {\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_TAG_KEYS,\n} from \"#/api/agent-server-adapter\";\n\nexport type ConversationSortField = \"created\" | \"updated\";\nexport type ThreadScope = \"all\" | \"relevant\";\nexport type OrganizeMode = \"grouped\" | \"chronological\";\nexport type AutomationFilterMode =\n | \"all\"\n | \"hide-automations\"\n | \"only-automations\";\n\n/** Max conversations shown under a workspace/repo folder before \"View more\". */\nexport const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;\n\ninterface GroupConversationPreviewOptions {\n limit?: number;\n expanded: boolean;\n activeConversationId?: string | null;\n}\n\nexport function getGroupConversationPreview(\n conversations: readonly AppConversation[],\n options: GroupConversationPreviewOptions,\n): {\n visibleConversations: AppConversation[];\n isPreviewTruncated: boolean;\n isShowingAll: boolean;\n} {\n const limit = options.limit ?? GROUP_CONVERSATIONS_PREVIEW_LIMIT;\n\n if (options.expanded || conversations.length <= limit) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: true,\n };\n }\n\n const activeIndex =\n options.activeConversationId != null\n ? conversations.findIndex((c) => c.id === options.activeConversationId)\n : -1;\n\n if (activeIndex >= limit) {\n const activeConversation = conversations[activeIndex];\n return {\n visibleConversations: [\n ...conversations.slice(0, limit - 1),\n activeConversation,\n ],\n isPreviewTruncated: true,\n isShowingAll: false,\n };\n }\n\n return {\n visibleConversations: conversations.slice(0, limit),\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: false,\n };\n}\n\nexport function resolvePinnedConversations(\n pinnedIds: readonly string[],\n conversations: readonly AppConversation[],\n): AppConversation[] {\n const byId = new Map(\n conversations.map((conversation) => [conversation.id, conversation]),\n );\n return pinnedIds\n .map((id) => byId.get(id))\n .filter(\n (conversation): conversation is AppConversation => conversation != null,\n );\n}\n\nexport function filterOutPinnedConversations(\n conversations: readonly AppConversation[],\n pinnedIds: readonly string[],\n): AppConversation[] {\n if (pinnedIds.length === 0) {\n return [...conversations];\n }\n\n const pinnedSet = new Set(pinnedIds);\n return conversations.filter(\n (conversation) => !pinnedSet.has(conversation.id),\n );\n}\n\n/**\n * Facet bucket for automation-born conversations that carry no\n * `automationname` tag (double-underscore prefix mirrors the\n * `__none_workspace` group-id idiom).\n */\nexport const UNNAMED_AUTOMATION_FACET = \"__unnamed__\";\n\n/**\n * Whether a conversation was created by an automation run: the cloud backend\n * stamps `trigger: \"automation\"`, while local agent-server conversations are\n * recognized by the automation tags the SDK workspace attaches at creation.\n */\nexport function isAutomationConversation(\n conversation: AppConversation,\n): boolean {\n if (conversation.trigger === \"automation\") {\n return true;\n }\n const tags = conversation.tags;\n if (!tags) {\n return false;\n }\n return AUTOMATION_TAG_KEYS.some((key) => Boolean(tags[key]));\n}\n\nexport function getAutomationNameFacet(conversation: AppConversation): string {\n const name = conversation.tags?.[AUTOMATION_NAME_TAG_KEY]?.trim();\n return name || UNNAMED_AUTOMATION_FACET;\n}\n\n/**\n * Unique automation names among the given conversations, sorted for stable\n * menu order; the unnamed bucket (if present) is appended last.\n */\nexport function collectAutomationNameFacets(\n conversations: readonly AppConversation[],\n): string[] {\n const names = new Set<string>();\n let hasUnnamed = false;\n for (const conversation of conversations) {\n if (!isAutomationConversation(conversation)) {\n continue;\n }\n const facet = getAutomationNameFacet(conversation);\n if (facet === UNNAMED_AUTOMATION_FACET) {\n hasUnnamed = true;\n } else {\n names.add(facet);\n }\n }\n const sorted = [...names].sort((a, b) => a.localeCompare(b));\n if (hasUnnamed) {\n sorted.push(UNNAMED_AUTOMATION_FACET);\n }\n return sorted;\n}\n\nexport function applyAutomationConversationFilter(\n conversations: readonly AppConversation[],\n mode: AutomationFilterMode,\n selectedNames: readonly string[],\n availableFacets: readonly string[],\n): AppConversation[] {\n if (mode === \"all\") {\n return [...conversations];\n }\n if (mode === \"hide-automations\") {\n return conversations.filter(\n (conversation) => !isAutomationConversation(conversation),\n );\n }\n // \"only-automations\": an empty selection means every automation run, and a\n // selection that no longer intersects the available facets (stale names\n // persisted from another backend, renamed automations) degrades the same\n // way instead of yielding an unfillable empty list.\n const facetSet = new Set(availableFacets);\n const effectiveNames = selectedNames.filter((name) => facetSet.has(name));\n const narrowing = effectiveNames.length > 0 ? new Set(effectiveNames) : null;\n return conversations.filter((conversation) => {\n if (!isAutomationConversation(conversation)) {\n return false;\n }\n return (\n narrowing === null || narrowing.has(getAutomationNameFacet(conversation))\n );\n });\n}\n\n/** Subset of `useCreateConversation` variables for launching from a group row */\nexport type ConversationGroupLaunch = {\n workingDir?: string;\n repository?: {\n name: string;\n gitProvider: Provider;\n branch?: string;\n };\n};\n\nfunction buildGroupLaunch(\n id: string,\n backendKind: BackendKind,\n conversations: AppConversation[],\n): ConversationGroupLaunch {\n if (backendKind === \"local\") {\n if (id === \"__none_workspace\") {\n return {};\n }\n if (id.startsWith(\"ws:\")) {\n return { workingDir: id.slice(3) };\n }\n return {};\n }\n\n if (id === \"__none_repo\") {\n return {};\n }\n if (id.startsWith(\"repo:\")) {\n const name = id.slice(5);\n const sample = conversations[0];\n const gitProvider = (sample?.git_provider ?? \"github\") as Provider;\n const branch = sample?.selected_branch ?? \"main\";\n return {\n repository: {\n name,\n gitProvider,\n branch,\n },\n };\n }\n\n return {};\n}\n\nexport function parseConversationTimeMs(iso: string | undefined): number {\n if (!iso) return 0;\n const t = Date.parse(iso);\n return Number.isFinite(t) ? t : 0;\n}\n\nexport function sortConversationsByField(\n items: readonly AppConversation[],\n field: ConversationSortField,\n): AppConversation[] {\n const key = field === \"created\" ? \"created_at\" : \"updated_at\";\n return [...items].sort(\n (a, b) => parseConversationTimeMs(b[key]) - parseConversationTimeMs(a[key]),\n );\n}\n\nfunction workspaceGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Group by the user-selected workspace (a stable identifier shared by\n // every conversation launched from the same picker selection), not\n // `workspace.working_dir` — that field holds the per-conversation\n // worktree path the agent-server creates, which is unique per\n // conversation and would fragment the grouping.\n //\n // Normalize first, then check emptiness: inputs like \"/\", \"///\", or\n // \" ///\" trim+strip to \"\" and must fall back to the \"no workspace\"\n // bucket rather than producing a stray `ws:` group with no label.\n const normalized = conversation.selected_workspace\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_workspace\", label: \"\" };\n }\n const label = normalized.split(\"/\").filter(Boolean).pop() ?? normalized;\n return { id: `ws:${normalized}`, label };\n}\n\nfunction repositoryGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Mirror `workspaceGroup`'s normalize-then-check order so \"/\", \"///\",\n // and trailing-slash variants of the same repo all collapse to one\n // group instead of producing a stray `repo:/` bucket.\n const normalized = conversation.selected_repository\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_repo\", label: \"\" };\n }\n const parts = normalized.split(\"/\").filter(Boolean);\n const label = parts.length\n ? (parts[parts.length - 1] ?? normalized).replace(/\\.git$/, \"\")\n : normalized.replace(/\\.git$/, \"\");\n return { id: `repo:${normalized}`, label };\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n): {\n id: string;\n label: string;\n conversations: AppConversation[];\n launch: ConversationGroupLaunch;\n}[] {\n const byId = new Map<\n string,\n { label: string; conversations: AppConversation[] }\n >();\n\n for (const c of items) {\n const { id, label: rawLabel } =\n backendKind === \"local\" ? workspaceGroup(c) : repositoryGroup(c);\n const label =\n id === \"__none_workspace\"\n ? labels.emptyWorkspace\n : id === \"__none_repo\"\n ? labels.emptyRepository\n : rawLabel;\n const bucket = byId.get(id);\n if (bucket) {\n bucket.conversations.push(c);\n } else {\n byId.set(id, { label, conversations: [c] });\n }\n }\n\n const groups = [...byId.entries()].map(([id, g]) => {\n const conversations = sortConversationsByField(g.conversations, sortField);\n return {\n id,\n label: g.label,\n conversations,\n launch: buildGroupLaunch(id, backendKind, conversations),\n };\n });\n\n // Use reduce instead of `Math.max(...arr)` — the spread form would push\n // every conversation onto the call stack as a separate argument, which\n // hits JS engines' ~100k-arg limit on very large buckets.\n const groupOrderKey = (g: (typeof groups)[number]) =>\n g.conversations.reduce(\n (max, c) =>\n Math.max(\n max,\n parseConversationTimeMs(\n sortField === \"created\" ? c.created_at : c.updated_at,\n ),\n ),\n 0,\n );\n\n groups.sort((a, b) => groupOrderKey(b) - groupOrderKey(a));\n return groups;\n}\n\nexport function applyGroupFolderOrder<T extends { id: string }>(\n groups: readonly T[],\n order: readonly string[],\n): T[] {\n if (order.length === 0) {\n return [...groups];\n }\n\n const byId = new Map(groups.map((group) => [group.id, group]));\n const ordered: T[] = [];\n const seen = new Set<string>();\n\n for (const id of order) {\n const group = byId.get(id);\n if (group) {\n ordered.push(group);\n seen.add(id);\n }\n }\n\n for (const group of groups) {\n if (!seen.has(group.id)) {\n ordered.push(group);\n }\n }\n\n return ordered;\n}\n\nexport type GroupFolderDropPosition = \"before\" | \"after\";\n\nexport function moveGroupFolderOrder(\n order: readonly string[],\n groupIds: readonly string[],\n activeGroupId: string,\n targetGroupId: string,\n position: GroupFolderDropPosition = \"after\",\n): string[] {\n if (activeGroupId === targetGroupId) {\n return [...order];\n }\n\n const effectiveOrder = applyGroupFolderOrder(\n groupIds.map((id) => ({ id })),\n order,\n ).map((group) => group.id);\n const fromIndex = effectiveOrder.indexOf(activeGroupId);\n const toIndex = effectiveOrder.indexOf(targetGroupId);\n if (fromIndex < 0 || toIndex < 0) {\n return [...order];\n }\n\n const nextOrder = [...effectiveOrder];\n nextOrder.splice(fromIndex, 1);\n const adjustedTargetIndex = nextOrder.indexOf(targetGroupId);\n const insertIndex =\n position === \"before\" ? adjustedTargetIndex : adjustedTargetIndex + 1;\n nextOrder.splice(insertIndex, 0, activeGroupId);\n return nextOrder;\n}\n"],"mappings":"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"}
@@ -4,6 +4,7 @@ import type { Provider } from "#/types/settings";
4
4
  export type ConversationSortField = "created" | "updated";
5
5
  export type ThreadScope = "all" | "relevant";
6
6
  export type OrganizeMode = "grouped" | "chronological";
7
+ export type AutomationFilterMode = "all" | "hide-automations" | "only-automations";
7
8
  /** Max conversations shown under a workspace/repo folder before "View more". */
8
9
  export declare const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;
9
10
  interface GroupConversationPreviewOptions {
@@ -18,6 +19,25 @@ export declare function getGroupConversationPreview(conversations: readonly AppC
18
19
  };
19
20
  export declare function resolvePinnedConversations(pinnedIds: readonly string[], conversations: readonly AppConversation[]): AppConversation[];
20
21
  export declare function filterOutPinnedConversations(conversations: readonly AppConversation[], pinnedIds: readonly string[]): AppConversation[];
22
+ /**
23
+ * Facet bucket for automation-born conversations that carry no
24
+ * `automationname` tag (double-underscore prefix mirrors the
25
+ * `__none_workspace` group-id idiom).
26
+ */
27
+ export declare const UNNAMED_AUTOMATION_FACET = "__unnamed__";
28
+ /**
29
+ * Whether a conversation was created by an automation run: the cloud backend
30
+ * stamps `trigger: "automation"`, while local agent-server conversations are
31
+ * recognized by the automation tags the SDK workspace attaches at creation.
32
+ */
33
+ export declare function isAutomationConversation(conversation: AppConversation): boolean;
34
+ export declare function getAutomationNameFacet(conversation: AppConversation): string;
35
+ /**
36
+ * Unique automation names among the given conversations, sorted for stable
37
+ * menu order; the unnamed bucket (if present) is appended last.
38
+ */
39
+ export declare function collectAutomationNameFacets(conversations: readonly AppConversation[]): string[];
40
+ export declare function applyAutomationConversationFilter(conversations: readonly AppConversation[], mode: AutomationFilterMode, selectedNames: readonly string[], availableFacets: readonly string[]): AppConversation[];
21
41
  /** Subset of `useCreateConversation` variables for launching from a group row */
22
42
  export type ConversationGroupLaunch = {
23
43
  workingDir?: string;
@@ -1,4 +1,5 @@
1
- function e(e, t) {
1
+ import { AUTOMATION_TAG_KEYS as e } from "../../../api/agent-server-adapter.js";
2
+ function t(e, t) {
2
3
  let n = t.limit ?? 5;
3
4
  if (t.expanded || e.length <= n) return {
4
5
  visibleConversations: [...e],
@@ -20,16 +21,41 @@ function e(e, t) {
20
21
  isShowingAll: !1
21
22
  };
22
23
  }
23
- function t(e, t) {
24
+ function n(e, t) {
24
25
  let n = new Map(t.map((e) => [e.id, e]));
25
26
  return e.map((e) => n.get(e)).filter((e) => e != null);
26
27
  }
27
- function n(e, t) {
28
+ function r(e, t) {
28
29
  if (t.length === 0) return [...e];
29
30
  let n = new Set(t);
30
31
  return e.filter((e) => !n.has(e.id));
31
32
  }
32
- function r(e, t, n) {
33
+ var i = "__unnamed__";
34
+ function a(t) {
35
+ if (t.trigger === "automation") return !0;
36
+ let n = t.tags;
37
+ return n ? e.some((e) => !!n[e]) : !1;
38
+ }
39
+ function o(e) {
40
+ return e.tags?.automationname?.trim() || "__unnamed__";
41
+ }
42
+ function s(e) {
43
+ let t = /* @__PURE__ */ new Set(), n = !1;
44
+ for (let r of e) {
45
+ if (!a(r)) continue;
46
+ let e = o(r);
47
+ e === "__unnamed__" ? n = !0 : t.add(e);
48
+ }
49
+ let r = [...t].sort((e, t) => e.localeCompare(t));
50
+ return n && r.push(i), r;
51
+ }
52
+ function c(e, t, n, r) {
53
+ if (t === "all") return [...e];
54
+ if (t === "hide-automations") return e.filter((e) => !a(e));
55
+ let i = new Set(r), s = n.filter((e) => i.has(e)), c = s.length > 0 ? new Set(s) : null;
56
+ return e.filter((e) => a(e) ? c === null || c.has(o(e)) : !1);
57
+ }
58
+ function l(e, t, n) {
33
59
  if (t === "local") return e === "__none_workspace" ? {} : e.startsWith("ws:") ? { workingDir: e.slice(3) } : {};
34
60
  if (e === "__none_repo") return {};
35
61
  if (e.startsWith("repo:")) {
@@ -42,16 +68,16 @@ function r(e, t, n) {
42
68
  }
43
69
  return {};
44
70
  }
45
- function i(e) {
71
+ function u(e) {
46
72
  if (!e) return 0;
47
73
  let t = Date.parse(e);
48
74
  return Number.isFinite(t) ? t : 0;
49
75
  }
50
- function a(e, t) {
76
+ function d(e, t) {
51
77
  let n = t === "created" ? "created_at" : "updated_at";
52
- return [...e].sort((e, t) => i(t[n]) - i(e[n]));
78
+ return [...e].sort((e, t) => u(t[n]) - u(e[n]));
53
79
  }
54
- function o(e) {
80
+ function f(e) {
55
81
  let t = e.selected_workspace?.trim().replace(/\/+$/, "");
56
82
  if (!t) return {
57
83
  id: "__none_workspace",
@@ -63,7 +89,7 @@ function o(e) {
63
89
  label: n
64
90
  };
65
91
  }
66
- function s(e) {
92
+ function p(e) {
67
93
  let t = e.selected_repository?.trim().replace(/\/+$/, "");
68
94
  if (!t) return {
69
95
  id: "__none_repo",
@@ -75,27 +101,27 @@ function s(e) {
75
101
  label: r
76
102
  };
77
103
  }
78
- function c(e, t, n, c) {
79
- let l = /* @__PURE__ */ new Map();
104
+ function m(e, t, n, r) {
105
+ let i = /* @__PURE__ */ new Map();
80
106
  for (let n of e) {
81
- let { id: e, label: r } = t === "local" ? o(n) : s(n), i = e === "__none_workspace" ? c.emptyWorkspace : e === "__none_repo" ? c.emptyRepository : r, a = l.get(e);
82
- a ? a.conversations.push(n) : l.set(e, {
83
- label: i,
107
+ let { id: e, label: a } = t === "local" ? f(n) : p(n), o = e === "__none_workspace" ? r.emptyWorkspace : e === "__none_repo" ? r.emptyRepository : a, s = i.get(e);
108
+ s ? s.conversations.push(n) : i.set(e, {
109
+ label: o,
84
110
  conversations: [n]
85
111
  });
86
112
  }
87
- let u = [...l.entries()].map(([e, i]) => {
88
- let o = a(i.conversations, n);
113
+ let a = [...i.entries()].map(([e, r]) => {
114
+ let i = d(r.conversations, n);
89
115
  return {
90
116
  id: e,
91
- label: i.label,
92
- conversations: o,
93
- launch: r(e, t, o)
117
+ label: r.label,
118
+ conversations: i,
119
+ launch: l(e, t, i)
94
120
  };
95
- }), d = (e) => e.conversations.reduce((e, t) => Math.max(e, i(n === "created" ? t.created_at : t.updated_at)), 0);
96
- return u.sort((e, t) => d(t) - d(e)), u;
121
+ }), o = (e) => e.conversations.reduce((e, t) => Math.max(e, u(n === "created" ? t.created_at : t.updated_at)), 0);
122
+ return a.sort((e, t) => o(t) - o(e)), a;
97
123
  }
98
- function l(e, t) {
124
+ function h(e, t) {
99
125
  if (t.length === 0) return [...e];
100
126
  let n = new Map(e.map((e) => [e.id, e])), r = [], i = /* @__PURE__ */ new Set();
101
127
  for (let e of t) {
@@ -105,16 +131,16 @@ function l(e, t) {
105
131
  for (let t of e) i.has(t.id) || r.push(t);
106
132
  return r;
107
133
  }
108
- function u(e, t, n, r, i = "after") {
134
+ function g(e, t, n, r, i = "after") {
109
135
  if (n === r) return [...e];
110
- let a = l(t.map((e) => ({ id: e })), e).map((e) => e.id), o = a.indexOf(n), s = a.indexOf(r);
136
+ let a = h(t.map((e) => ({ id: e })), e).map((e) => e.id), o = a.indexOf(n), s = a.indexOf(r);
111
137
  if (o < 0 || s < 0) return [...e];
112
138
  let c = [...a];
113
139
  c.splice(o, 1);
114
- let u = c.indexOf(r), d = i === "before" ? u : u + 1;
115
- return c.splice(d, 0, n), c;
140
+ let l = c.indexOf(r), u = i === "before" ? l : l + 1;
141
+ return c.splice(u, 0, n), c;
116
142
  }
117
143
  //#endregion
118
- export { l as applyGroupFolderOrder, n as filterOutPinnedConversations, e as getGroupConversationPreview, c as groupConversations, u as moveGroupFolderOrder, t as resolvePinnedConversations, a as sortConversationsByField };
144
+ export { i as UNNAMED_AUTOMATION_FACET, c as applyAutomationConversationFilter, h as applyGroupFolderOrder, s as collectAutomationNameFacets, r as filterOutPinnedConversations, t as getGroupConversationPreview, m as groupConversations, g as moveGroupFolderOrder, n as resolvePinnedConversations, d as sortConversationsByField };
119
145
 
120
146
  //# sourceMappingURL=conversation-panel-list-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-panel-list-helpers.js","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-list-helpers.ts"],"sourcesContent":["import type { AppConversation } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport type { Provider } from \"#/types/settings\";\n\nexport type ConversationSortField = \"created\" | \"updated\";\nexport type ThreadScope = \"all\" | \"relevant\";\nexport type OrganizeMode = \"grouped\" | \"chronological\";\n\n/** Max conversations shown under a workspace/repo folder before \"View more\". */\nexport const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;\n\ninterface GroupConversationPreviewOptions {\n limit?: number;\n expanded: boolean;\n activeConversationId?: string | null;\n}\n\nexport function getGroupConversationPreview(\n conversations: readonly AppConversation[],\n options: GroupConversationPreviewOptions,\n): {\n visibleConversations: AppConversation[];\n isPreviewTruncated: boolean;\n isShowingAll: boolean;\n} {\n const limit = options.limit ?? GROUP_CONVERSATIONS_PREVIEW_LIMIT;\n\n if (options.expanded || conversations.length <= limit) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: true,\n };\n }\n\n const activeIndex =\n options.activeConversationId != null\n ? conversations.findIndex((c) => c.id === options.activeConversationId)\n : -1;\n\n if (activeIndex >= limit) {\n const activeConversation = conversations[activeIndex];\n return {\n visibleConversations: [\n ...conversations.slice(0, limit - 1),\n activeConversation,\n ],\n isPreviewTruncated: true,\n isShowingAll: false,\n };\n }\n\n return {\n visibleConversations: conversations.slice(0, limit),\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: false,\n };\n}\n\nexport function resolvePinnedConversations(\n pinnedIds: readonly string[],\n conversations: readonly AppConversation[],\n): AppConversation[] {\n const byId = new Map(\n conversations.map((conversation) => [conversation.id, conversation]),\n );\n return pinnedIds\n .map((id) => byId.get(id))\n .filter(\n (conversation): conversation is AppConversation => conversation != null,\n );\n}\n\nexport function filterOutPinnedConversations(\n conversations: readonly AppConversation[],\n pinnedIds: readonly string[],\n): AppConversation[] {\n if (pinnedIds.length === 0) {\n return [...conversations];\n }\n\n const pinnedSet = new Set(pinnedIds);\n return conversations.filter(\n (conversation) => !pinnedSet.has(conversation.id),\n );\n}\n\n/** Subset of `useCreateConversation` variables for launching from a group row */\nexport type ConversationGroupLaunch = {\n workingDir?: string;\n repository?: {\n name: string;\n gitProvider: Provider;\n branch?: string;\n };\n};\n\nfunction buildGroupLaunch(\n id: string,\n backendKind: BackendKind,\n conversations: AppConversation[],\n): ConversationGroupLaunch {\n if (backendKind === \"local\") {\n if (id === \"__none_workspace\") {\n return {};\n }\n if (id.startsWith(\"ws:\")) {\n return { workingDir: id.slice(3) };\n }\n return {};\n }\n\n if (id === \"__none_repo\") {\n return {};\n }\n if (id.startsWith(\"repo:\")) {\n const name = id.slice(5);\n const sample = conversations[0];\n const gitProvider = (sample?.git_provider ?? \"github\") as Provider;\n const branch = sample?.selected_branch ?? \"main\";\n return {\n repository: {\n name,\n gitProvider,\n branch,\n },\n };\n }\n\n return {};\n}\n\nexport function parseConversationTimeMs(iso: string | undefined): number {\n if (!iso) return 0;\n const t = Date.parse(iso);\n return Number.isFinite(t) ? t : 0;\n}\n\nexport function sortConversationsByField(\n items: readonly AppConversation[],\n field: ConversationSortField,\n): AppConversation[] {\n const key = field === \"created\" ? \"created_at\" : \"updated_at\";\n return [...items].sort(\n (a, b) => parseConversationTimeMs(b[key]) - parseConversationTimeMs(a[key]),\n );\n}\n\nfunction workspaceGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Group by the user-selected workspace (a stable identifier shared by\n // every conversation launched from the same picker selection), not\n // `workspace.working_dir` — that field holds the per-conversation\n // worktree path the agent-server creates, which is unique per\n // conversation and would fragment the grouping.\n //\n // Normalize first, then check emptiness: inputs like \"/\", \"///\", or\n // \" ///\" trim+strip to \"\" and must fall back to the \"no workspace\"\n // bucket rather than producing a stray `ws:` group with no label.\n const normalized = conversation.selected_workspace\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_workspace\", label: \"\" };\n }\n const label = normalized.split(\"/\").filter(Boolean).pop() ?? normalized;\n return { id: `ws:${normalized}`, label };\n}\n\nfunction repositoryGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Mirror `workspaceGroup`'s normalize-then-check order so \"/\", \"///\",\n // and trailing-slash variants of the same repo all collapse to one\n // group instead of producing a stray `repo:/` bucket.\n const normalized = conversation.selected_repository\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_repo\", label: \"\" };\n }\n const parts = normalized.split(\"/\").filter(Boolean);\n const label = parts.length\n ? (parts[parts.length - 1] ?? normalized).replace(/\\.git$/, \"\")\n : normalized.replace(/\\.git$/, \"\");\n return { id: `repo:${normalized}`, label };\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n): {\n id: string;\n label: string;\n conversations: AppConversation[];\n launch: ConversationGroupLaunch;\n}[] {\n const byId = new Map<\n string,\n { label: string; conversations: AppConversation[] }\n >();\n\n for (const c of items) {\n const { id, label: rawLabel } =\n backendKind === \"local\" ? workspaceGroup(c) : repositoryGroup(c);\n const label =\n id === \"__none_workspace\"\n ? labels.emptyWorkspace\n : id === \"__none_repo\"\n ? labels.emptyRepository\n : rawLabel;\n const bucket = byId.get(id);\n if (bucket) {\n bucket.conversations.push(c);\n } else {\n byId.set(id, { label, conversations: [c] });\n }\n }\n\n const groups = [...byId.entries()].map(([id, g]) => {\n const conversations = sortConversationsByField(g.conversations, sortField);\n return {\n id,\n label: g.label,\n conversations,\n launch: buildGroupLaunch(id, backendKind, conversations),\n };\n });\n\n // Use reduce instead of `Math.max(...arr)` — the spread form would push\n // every conversation onto the call stack as a separate argument, which\n // hits JS engines' ~100k-arg limit on very large buckets.\n const groupOrderKey = (g: (typeof groups)[number]) =>\n g.conversations.reduce(\n (max, c) =>\n Math.max(\n max,\n parseConversationTimeMs(\n sortField === \"created\" ? c.created_at : c.updated_at,\n ),\n ),\n 0,\n );\n\n groups.sort((a, b) => groupOrderKey(b) - groupOrderKey(a));\n return groups;\n}\n\nexport function applyGroupFolderOrder<T extends { id: string }>(\n groups: readonly T[],\n order: readonly string[],\n): T[] {\n if (order.length === 0) {\n return [...groups];\n }\n\n const byId = new Map(groups.map((group) => [group.id, group]));\n const ordered: T[] = [];\n const seen = new Set<string>();\n\n for (const id of order) {\n const group = byId.get(id);\n if (group) {\n ordered.push(group);\n seen.add(id);\n }\n }\n\n for (const group of groups) {\n if (!seen.has(group.id)) {\n ordered.push(group);\n }\n }\n\n return ordered;\n}\n\nexport type GroupFolderDropPosition = \"before\" | \"after\";\n\nexport function moveGroupFolderOrder(\n order: readonly string[],\n groupIds: readonly string[],\n activeGroupId: string,\n targetGroupId: string,\n position: GroupFolderDropPosition = \"after\",\n): string[] {\n if (activeGroupId === targetGroupId) {\n return [...order];\n }\n\n const effectiveOrder = applyGroupFolderOrder(\n groupIds.map((id) => ({ id })),\n order,\n ).map((group) => group.id);\n const fromIndex = effectiveOrder.indexOf(activeGroupId);\n const toIndex = effectiveOrder.indexOf(targetGroupId);\n if (fromIndex < 0 || toIndex < 0) {\n return [...order];\n }\n\n const nextOrder = [...effectiveOrder];\n nextOrder.splice(fromIndex, 1);\n const adjustedTargetIndex = nextOrder.indexOf(targetGroupId);\n const insertIndex =\n position === \"before\" ? adjustedTargetIndex : adjustedTargetIndex + 1;\n nextOrder.splice(insertIndex, 0, activeGroupId);\n return nextOrder;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversation-panel-list-helpers.js","names":[],"sources":["../../../../src/components/features/conversation-panel/conversation-panel-list-helpers.ts"],"sourcesContent":["import type { AppConversation } from \"#/api/conversation-service/agent-server-conversation-service.types\";\nimport type { BackendKind } from \"#/api/backend-registry/types\";\nimport type { Provider } from \"#/types/settings\";\nimport {\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_TAG_KEYS,\n} from \"#/api/agent-server-adapter\";\n\nexport type ConversationSortField = \"created\" | \"updated\";\nexport type ThreadScope = \"all\" | \"relevant\";\nexport type OrganizeMode = \"grouped\" | \"chronological\";\nexport type AutomationFilterMode =\n | \"all\"\n | \"hide-automations\"\n | \"only-automations\";\n\n/** Max conversations shown under a workspace/repo folder before \"View more\". */\nexport const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;\n\ninterface GroupConversationPreviewOptions {\n limit?: number;\n expanded: boolean;\n activeConversationId?: string | null;\n}\n\nexport function getGroupConversationPreview(\n conversations: readonly AppConversation[],\n options: GroupConversationPreviewOptions,\n): {\n visibleConversations: AppConversation[];\n isPreviewTruncated: boolean;\n isShowingAll: boolean;\n} {\n const limit = options.limit ?? GROUP_CONVERSATIONS_PREVIEW_LIMIT;\n\n if (options.expanded || conversations.length <= limit) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: true,\n };\n }\n\n const activeIndex =\n options.activeConversationId != null\n ? conversations.findIndex((c) => c.id === options.activeConversationId)\n : -1;\n\n if (activeIndex >= limit) {\n const activeConversation = conversations[activeIndex];\n return {\n visibleConversations: [\n ...conversations.slice(0, limit - 1),\n activeConversation,\n ],\n isPreviewTruncated: true,\n isShowingAll: false,\n };\n }\n\n return {\n visibleConversations: conversations.slice(0, limit),\n isPreviewTruncated: conversations.length > limit,\n isShowingAll: false,\n };\n}\n\nexport function resolvePinnedConversations(\n pinnedIds: readonly string[],\n conversations: readonly AppConversation[],\n): AppConversation[] {\n const byId = new Map(\n conversations.map((conversation) => [conversation.id, conversation]),\n );\n return pinnedIds\n .map((id) => byId.get(id))\n .filter(\n (conversation): conversation is AppConversation => conversation != null,\n );\n}\n\nexport function filterOutPinnedConversations(\n conversations: readonly AppConversation[],\n pinnedIds: readonly string[],\n): AppConversation[] {\n if (pinnedIds.length === 0) {\n return [...conversations];\n }\n\n const pinnedSet = new Set(pinnedIds);\n return conversations.filter(\n (conversation) => !pinnedSet.has(conversation.id),\n );\n}\n\n/**\n * Facet bucket for automation-born conversations that carry no\n * `automationname` tag (double-underscore prefix mirrors the\n * `__none_workspace` group-id idiom).\n */\nexport const UNNAMED_AUTOMATION_FACET = \"__unnamed__\";\n\n/**\n * Whether a conversation was created by an automation run: the cloud backend\n * stamps `trigger: \"automation\"`, while local agent-server conversations are\n * recognized by the automation tags the SDK workspace attaches at creation.\n */\nexport function isAutomationConversation(\n conversation: AppConversation,\n): boolean {\n if (conversation.trigger === \"automation\") {\n return true;\n }\n const tags = conversation.tags;\n if (!tags) {\n return false;\n }\n return AUTOMATION_TAG_KEYS.some((key) => Boolean(tags[key]));\n}\n\nexport function getAutomationNameFacet(conversation: AppConversation): string {\n const name = conversation.tags?.[AUTOMATION_NAME_TAG_KEY]?.trim();\n return name || UNNAMED_AUTOMATION_FACET;\n}\n\n/**\n * Unique automation names among the given conversations, sorted for stable\n * menu order; the unnamed bucket (if present) is appended last.\n */\nexport function collectAutomationNameFacets(\n conversations: readonly AppConversation[],\n): string[] {\n const names = new Set<string>();\n let hasUnnamed = false;\n for (const conversation of conversations) {\n if (!isAutomationConversation(conversation)) {\n continue;\n }\n const facet = getAutomationNameFacet(conversation);\n if (facet === UNNAMED_AUTOMATION_FACET) {\n hasUnnamed = true;\n } else {\n names.add(facet);\n }\n }\n const sorted = [...names].sort((a, b) => a.localeCompare(b));\n if (hasUnnamed) {\n sorted.push(UNNAMED_AUTOMATION_FACET);\n }\n return sorted;\n}\n\nexport function applyAutomationConversationFilter(\n conversations: readonly AppConversation[],\n mode: AutomationFilterMode,\n selectedNames: readonly string[],\n availableFacets: readonly string[],\n): AppConversation[] {\n if (mode === \"all\") {\n return [...conversations];\n }\n if (mode === \"hide-automations\") {\n return conversations.filter(\n (conversation) => !isAutomationConversation(conversation),\n );\n }\n // \"only-automations\": an empty selection means every automation run, and a\n // selection that no longer intersects the available facets (stale names\n // persisted from another backend, renamed automations) degrades the same\n // way instead of yielding an unfillable empty list.\n const facetSet = new Set(availableFacets);\n const effectiveNames = selectedNames.filter((name) => facetSet.has(name));\n const narrowing = effectiveNames.length > 0 ? new Set(effectiveNames) : null;\n return conversations.filter((conversation) => {\n if (!isAutomationConversation(conversation)) {\n return false;\n }\n return (\n narrowing === null || narrowing.has(getAutomationNameFacet(conversation))\n );\n });\n}\n\n/** Subset of `useCreateConversation` variables for launching from a group row */\nexport type ConversationGroupLaunch = {\n workingDir?: string;\n repository?: {\n name: string;\n gitProvider: Provider;\n branch?: string;\n };\n};\n\nfunction buildGroupLaunch(\n id: string,\n backendKind: BackendKind,\n conversations: AppConversation[],\n): ConversationGroupLaunch {\n if (backendKind === \"local\") {\n if (id === \"__none_workspace\") {\n return {};\n }\n if (id.startsWith(\"ws:\")) {\n return { workingDir: id.slice(3) };\n }\n return {};\n }\n\n if (id === \"__none_repo\") {\n return {};\n }\n if (id.startsWith(\"repo:\")) {\n const name = id.slice(5);\n const sample = conversations[0];\n const gitProvider = (sample?.git_provider ?? \"github\") as Provider;\n const branch = sample?.selected_branch ?? \"main\";\n return {\n repository: {\n name,\n gitProvider,\n branch,\n },\n };\n }\n\n return {};\n}\n\nexport function parseConversationTimeMs(iso: string | undefined): number {\n if (!iso) return 0;\n const t = Date.parse(iso);\n return Number.isFinite(t) ? t : 0;\n}\n\nexport function sortConversationsByField(\n items: readonly AppConversation[],\n field: ConversationSortField,\n): AppConversation[] {\n const key = field === \"created\" ? \"created_at\" : \"updated_at\";\n return [...items].sort(\n (a, b) => parseConversationTimeMs(b[key]) - parseConversationTimeMs(a[key]),\n );\n}\n\nfunction workspaceGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Group by the user-selected workspace (a stable identifier shared by\n // every conversation launched from the same picker selection), not\n // `workspace.working_dir` — that field holds the per-conversation\n // worktree path the agent-server creates, which is unique per\n // conversation and would fragment the grouping.\n //\n // Normalize first, then check emptiness: inputs like \"/\", \"///\", or\n // \" ///\" trim+strip to \"\" and must fall back to the \"no workspace\"\n // bucket rather than producing a stray `ws:` group with no label.\n const normalized = conversation.selected_workspace\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_workspace\", label: \"\" };\n }\n const label = normalized.split(\"/\").filter(Boolean).pop() ?? normalized;\n return { id: `ws:${normalized}`, label };\n}\n\nfunction repositoryGroup(conversation: AppConversation): {\n id: string;\n label: string;\n} {\n // Mirror `workspaceGroup`'s normalize-then-check order so \"/\", \"///\",\n // and trailing-slash variants of the same repo all collapse to one\n // group instead of producing a stray `repo:/` bucket.\n const normalized = conversation.selected_repository\n ?.trim()\n .replace(/\\/+$/, \"\");\n if (!normalized) {\n return { id: \"__none_repo\", label: \"\" };\n }\n const parts = normalized.split(\"/\").filter(Boolean);\n const label = parts.length\n ? (parts[parts.length - 1] ?? normalized).replace(/\\.git$/, \"\")\n : normalized.replace(/\\.git$/, \"\");\n return { id: `repo:${normalized}`, label };\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n): {\n id: string;\n label: string;\n conversations: AppConversation[];\n launch: ConversationGroupLaunch;\n}[] {\n const byId = new Map<\n string,\n { label: string; conversations: AppConversation[] }\n >();\n\n for (const c of items) {\n const { id, label: rawLabel } =\n backendKind === \"local\" ? workspaceGroup(c) : repositoryGroup(c);\n const label =\n id === \"__none_workspace\"\n ? labels.emptyWorkspace\n : id === \"__none_repo\"\n ? labels.emptyRepository\n : rawLabel;\n const bucket = byId.get(id);\n if (bucket) {\n bucket.conversations.push(c);\n } else {\n byId.set(id, { label, conversations: [c] });\n }\n }\n\n const groups = [...byId.entries()].map(([id, g]) => {\n const conversations = sortConversationsByField(g.conversations, sortField);\n return {\n id,\n label: g.label,\n conversations,\n launch: buildGroupLaunch(id, backendKind, conversations),\n };\n });\n\n // Use reduce instead of `Math.max(...arr)` — the spread form would push\n // every conversation onto the call stack as a separate argument, which\n // hits JS engines' ~100k-arg limit on very large buckets.\n const groupOrderKey = (g: (typeof groups)[number]) =>\n g.conversations.reduce(\n (max, c) =>\n Math.max(\n max,\n parseConversationTimeMs(\n sortField === \"created\" ? c.created_at : c.updated_at,\n ),\n ),\n 0,\n );\n\n groups.sort((a, b) => groupOrderKey(b) - groupOrderKey(a));\n return groups;\n}\n\nexport function applyGroupFolderOrder<T extends { id: string }>(\n groups: readonly T[],\n order: readonly string[],\n): T[] {\n if (order.length === 0) {\n return [...groups];\n }\n\n const byId = new Map(groups.map((group) => [group.id, group]));\n const ordered: T[] = [];\n const seen = new Set<string>();\n\n for (const id of order) {\n const group = byId.get(id);\n if (group) {\n ordered.push(group);\n seen.add(id);\n }\n }\n\n for (const group of groups) {\n if (!seen.has(group.id)) {\n ordered.push(group);\n }\n }\n\n return ordered;\n}\n\nexport type GroupFolderDropPosition = \"before\" | \"after\";\n\nexport function moveGroupFolderOrder(\n order: readonly string[],\n groupIds: readonly string[],\n activeGroupId: string,\n targetGroupId: string,\n position: GroupFolderDropPosition = \"after\",\n): string[] {\n if (activeGroupId === targetGroupId) {\n return [...order];\n }\n\n const effectiveOrder = applyGroupFolderOrder(\n groupIds.map((id) => ({ id })),\n order,\n ).map((group) => group.id);\n const fromIndex = effectiveOrder.indexOf(activeGroupId);\n const toIndex = effectiveOrder.indexOf(targetGroupId);\n if (fromIndex < 0 || toIndex < 0) {\n return [...order];\n }\n\n const nextOrder = [...effectiveOrder];\n nextOrder.splice(fromIndex, 1);\n const adjustedTargetIndex = nextOrder.indexOf(targetGroupId);\n const insertIndex =\n position === \"before\" ? adjustedTargetIndex : adjustedTargetIndex + 1;\n nextOrder.splice(insertIndex, 0, activeGroupId);\n return nextOrder;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../utils/status.cjs"),i=require("../../../utils/utils.cjs"),ee=require("../../../context/navigation-context.cjs"),te=require("../../../utils/custom-toast-handlers.cjs"),ne=require("../../../contexts/active-backend-context.cjs"),re=require("../../../node_modules/@heroui/tooltip/dist/chunk-AUA5GDXN.cjs"),ie=require("../../../hooks/use-click-outside-element.cjs"),ae=require("../../../hooks/mutation/use-create-conversation.cjs"),oe=require("../../shared/navigation-link.cjs"),se=require("../../../hooks/mutation/use-delete-conversation.cjs"),ce=require("../../../hooks/mutation/use-unified-stop-conversation.cjs"),le=require("../../../hooks/use-is-creating-conversation.cjs"),ue=require("../../../hooks/mutation/use-update-conversation.cjs"),a=require("./confirm-delete-modal.cjs"),de=require("./confirm-stop-modal.cjs"),fe=require("../../../hooks/use-backend-scoped-path.cjs"),pe=require("../../../hooks/query/use-paginated-conversations.cjs"),me=require("../../../hooks/query/use-start-tasks.cjs"),he=require("./exit-conversation-modal.cjs"),ge=require("./conversation-card/conversation-card.cjs"),_e=require("./conversation-card/conversation-card-preview.cjs"),ve=require("./start-task-card/start-task-card.cjs"),o=require("./conversation-card/conversation-card-skeleton.cjs"),ye=require("./compact-conversation-row.cjs"),s=require("../../../stores/conversation-panel-preferences-store.cjs"),be=require("./conversation-panel-filter-menu.cjs"),xe=require("./conversation-panel-new-thread-picker.cjs"),c=require("./conversation-panel-list-helpers.cjs"),Se=require("./conversation-group-folder-list.cjs"),Ce=require("./conversation-panel-pinned-section.cjs"),l=require("../../../stores/pinned-conversations-store.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("react/jsx-runtime");var we=()=>{},Te=[],f=3600*1e3,Ee=e=>{let t=Date.now()-f,n=[],r=[];for(let i of e){let e=i.updated_at?Date.parse(i.updated_at):NaN;Number.isFinite(e)&&e<t?r.push(i):n.push(i)}return{recent:n,older:r}};function p({onClose:e,compact:f=!1}){let{t:p}=t.useTranslation(`openhands`),{conversationId:m,navigate:h}=ee.useNavigation(),{backend:g}=ne.useActiveBackend(),De=fe.useBackendScopedPath(),Oe=ie.useClickOutsideElement(e??we),[ke,_]=u.default.useState(!1),[Ae,v]=u.default.useState(!1),[je,y]=u.default.useState(!1),[Me,b]=u.default.useState(!1),x=s.useConversationPanelPreferencesStore(e=>e.showOlderConversations),Ne=s.useConversationPanelPreferencesStore(e=>e.toggleShowOlderConversations),S=s.useConversationPanelPreferencesStore(e=>e.showRepoBranchMetadata),Pe=s.useConversationPanelPreferencesStore(e=>e.toggleShowRepoBranchMetadata),C=s.useConversationPanelPreferencesStore(e=>e.showLlmProfiles),Fe=s.useConversationPanelPreferencesStore(e=>e.toggleShowLlmProfiles),w=s.useConversationPanelPreferencesStore(e=>e.showTagsMetadata),Ie=s.useConversationPanelPreferencesStore(e=>e.toggleShowTagsMetadata),T=s.useConversationPanelPreferencesStore(e=>e.showHoverMetadata),Le=s.useConversationPanelPreferencesStore(e=>e.toggleShowHoverMetadata),E=s.useConversationPanelPreferencesStore(e=>e.organizeMode),Re=s.useConversationPanelPreferencesStore(e=>e.setOrganizeMode),D=s.useConversationPanelPreferencesStore(e=>e.conversationSort),ze=s.useConversationPanelPreferencesStore(e=>e.setConversationSort),O=s.useConversationPanelPreferencesStore(e=>e.threadScope),Be=s.useConversationPanelPreferencesStore(e=>e.setThreadScope),k=s.useConversationPanelPreferencesStore(e=>e.groupFolderOrder),Ve=s.useConversationPanelPreferencesStore(e=>e.setGroupFolderOrder),[He,A]=u.default.useState(!1),[Ue,We]=u.default.useState(!1),Ge=ie.useClickOutsideElement(()=>{A(!1)}),[Ke,j]=u.default.useState(()=>new Set),[qe,M]=u.default.useState(()=>new Set),[Je,N]=u.default.useState(!1),P=l.usePinnedConversationsStore(e=>e.pinsByBackendId[g.id]??Te),F=l.usePinnedConversationsStore(e=>e.togglePin),Ye=l.usePinnedConversationsStore(e=>e.pruneMissingConversations),Xe=u.default.useCallback(e=>{j(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),Ze=u.default.useCallback(e=>{M(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]);u.default.useEffect(()=>{E!==`grouped`&&(j(new Set),M(new Set))},[E]);let Qe=u.default.useRef(null),[I,$e]=u.default.useState(null),[et,L]=u.default.useState(null),[R,tt]=u.default.useState(null),{data:nt,isLoading:rt,isFetched:z,hasNextPage:B,isFetching:it,isFetchingNextPage:V,fetchNextPage:at}=pe.usePaginatedConversations(),{data:ot}=me.useStartTasks(),H=u.default.useMemo(()=>{let e=nt?.pages.flatMap(e=>e.items)??[],t=new Set;return e.filter(e=>t.has(e.id)?!1:(t.add(e.id),!0))},[nt]),st=u.default.useMemo(()=>c.resolvePinnedConversations(P,H),[H,P]);u.default.useEffect(()=>{z&&Ye(g.id,H.map(e=>e.id))},[g.id,H,z,Ye]),u.default.useEffect(()=>{P.length===0&&N(!1)},[P.length]);let ct=u.default.useMemo(()=>{let e=O===`relevant`?H.filter(e=>r.isExecutionActive(e.execution_status)):H;return f?e:c.filterOutPinnedConversations(e,P)},[f,H,P,O]),{recent:U,older:W}=u.default.useMemo(()=>Ee(ct),[ct]),lt=u.default.useMemo(()=>c.sortConversationsByField(x?[...U,...W]:U,D),[U,W,x,D]),ut=u.default.useMemo(()=>({emptyWorkspace:p(n.I18nKey.CONVERSATION_PANEL$NO_WORKSPACE),emptyRepository:p(n.I18nKey.CONVERSATION_PANEL$NO_REPOSITORY)}),[p]),G=u.default.useMemo(()=>f||E!==`grouped`?null:c.groupConversations([...U,...x?W:[]],g.kind,D,ut),[g.kind,f,D,ut,W,E,U,x]),K=u.default.useMemo(()=>G?c.applyGroupFolderOrder(G,k):null,[G,k]),dt=u.default.useMemo(()=>G?.map(e=>e.id)??[],[G]),ft=u.default.useMemo(()=>c.sortConversationsByField(U.filter(e=>r.isExecutionActive(e.execution_status)),D),[D,U]),pt=lt.length,mt=u.default.useMemo(()=>K?K.reduce((e,t)=>e+t.conversations.length,0):0,[K]),ht=E===`grouped`&&!f?mt===0:pt===0,q=E===`grouped`&&!f?mt:pt,[J,Y]=u.default.useState(null),gt=u.default.useRef(q);gt.current=q;let _t=u.default.useCallback(()=>{B&&Y(gt.current)},[B]);u.default.useEffect(()=>{if(J!==null){if(q>J){Y(null);return}if(!B){Y(null);return}it||V||at()}},[J,q,B,it,V,at]);let vt=J!==null||V,{mutate:yt,mutateAsync:bt}=se.useDeleteConversation(),{mutate:xt}=ce.useUnifiedPauseConversation(),{mutate:St}=ue.useUpdateConversation(),Ct=W.length>0&&!x,wt=!!B&&!Ct&&!f&&!ht,{mutate:Tt}=ae.useCreateConversation(),X=le.useIsCreatingConversation(),Et=u.default.useCallback(e=>{X||Tt({workingDir:e.workingDir,repository:e.repository,entryPoint:`sidebar_relaunch_project`},{onSuccess:e=>{h(`/conversations/${e.conversation_id}`)}})},[Tt,X,h]),Dt=u.default.useCallback((e,t)=>{_(!0),$e(e),L(t)},[]),Ot=u.default.useCallback(e=>{v(!0),$e(e)},[]),kt=u.default.useCallback((e,t)=>{St({conversationId:e,newTitle:t},{onSuccess:()=>{te.displaySuccessToast(p(n.I18nKey.CONVERSATION$TITLE_UPDATED))}})},[p,St]),At=()=>{I&&yt({conversationId:I},{onSuccess:()=>{I===m&&h(`/conversations`)}})},jt=()=>{I&&xt({conversationId:I})},Mt=async()=>{let e=H.map(e=>e.id),t=await Promise.allSettled(e.map(e=>bt({conversationId:e}))),n=t.flatMap((t,n)=>t.status===`fulfilled`?[e[n]]:[]),r=t.length-n.length;m!==null&&n.includes(m)&&h(`/conversations`),r>0&&te.displayErrorToast(`${r} conversation${r===1?``:`s`} could not be deleted.`)},Z=u.default.useCallback((t,n)=>{let r=P.includes(t.id);return f?(0,d.jsx)(ye.CompactConversationRow,{conversationId:t.id,title:t.title??``,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,lastUpdatedAt:t.updated_at,createdAt:t.created_at,workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,isActive:t.id===m,onClose:e,showRepositoryMetadata:S,llmModel:t.llm_model,showLlmProfiles:C,agentKind:t.agent_kind,acpServer:t.acp_server,tags:t.tags,showTags:w},t.id):(0,d.jsx)(re.tooltip_default,{placement:`right-start`,delay:1e3,closeDelay:100,isDisabled:!T||R===t.id,disableAnimation:!1,className:`rounded-xl border border-[var(--oh-border)] bg-base-secondary p-0 text-white shadow-xl`,content:(0,d.jsx)(_e.ConversationCardPreview,{title:t.title??``,executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,llmModel:t.llm_model,createdAt:t.created_at}),children:(0,d.jsx)(oe.NavigationLink,{to:De(`/conversations/${t.id}`),onClick:e,className:i.cn(`block rounded-md transition-colors`,R!==t.id&&`hover:bg-[var(--oh-surface)]`,(t.id===m||R===t.id)&&`bg-[var(--oh-surface)]`),children:(0,d.jsx)(ge.ConversationCard,{onDelete:()=>Dt(t.id,t.title??``),onStop:()=>Ot(t.id),onChangeTitle:e=>kt(t.id,e),title:t.title??``,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},lastUpdatedAt:t.updated_at,createdAt:t.created_at,executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,conversationId:t.id,contextMenuOpen:R===t.id,onContextMenuToggle:e=>tt(e?t.id:null),isActive:t.id===m,workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,showRepositoryMetadata:S,llmModel:t.llm_model,showLlmProfiles:C,agentKind:t.agent_kind,acpServer:t.acp_server,tags:t.tags,showTags:w,isPinned:r,onTogglePin:()=>F(g.id,t.id),alwaysShowPinIcon:r&&!n?.inPinnedSection})})},t.id)},[g.id,f,m,kt,Dt,Ot,e,R,P,S,C,w,T,F]),Q=rt||!z,$=!f&&!Q&&st.length>0,Nt=z&&!rt&&!f&&ht&&!$&&!ot?.length;return(0,d.jsxs)(`div`,{ref:Oe,"data-testid":`conversation-panel`,className:`flex h-full min-h-0 w-full flex-col`,children:[!f&&(0,d.jsx)(`div`,{className:i.cn(`-ml-2.5 w-[calc(100%+0.625rem)] max-w-none box-border border-b`,Ue?`border-[var(--oh-border)]`:`border-transparent`),children:(0,d.jsxs)(`div`,{"data-testid":`older-conversations-summary`,className:`flex min-w-0 flex-nowrap items-center gap-x-2 py-2 pl-4 pr-2.5 text-[var(--oh-muted)]`,children:[(0,d.jsx)(`span`,{className:`min-w-0 truncate text-sm font-medium text-[var(--oh-muted)]`,children:p(n.I18nKey.SIDEBAR$CONVERSATIONS)}),(0,d.jsxs)(`div`,{className:`ml-auto flex shrink-0 items-center gap-0.5`,children:[(0,d.jsx)(xe.ConversationPanelNewThreadPicker,{backendKind:g.kind}),(0,d.jsx)(be.ConversationPanelFilterMenu,{filterMenuOpen:He,setFilterMenuOpen:A,menuRef:Ge,backendKind:g.kind,organizeMode:E,setOrganizeMode:Re,conversationSort:D,setConversationSort:ze,threadScope:O,setThreadScope:Be,showOlderConversations:x,toggleShowOlderConversations:Ne,showRepoBranchMetadata:S,toggleShowRepoBranchMetadata:Pe,showLlmProfiles:C,toggleShowLlmProfiles:Fe,showTagsMetadata:w,toggleShowTagsMetadata:Ie,showHoverMetadata:T,toggleShowHoverMetadata:Le,totalConversationsCount:H.length,onRequestDeleteAll:()=>b(!0)})]})]})}),(0,d.jsxs)(`div`,{ref:Qe,"data-testid":`conversation-panel-list-scroll`,onScroll:e=>{We(e.currentTarget.scrollTop>0)},className:i.cn(`flex min-h-0 flex-1 flex-col overflow-y-auto overflow-x-hidden overscroll-contain custom-scrollbar-always`,!f&&`conversation-panel-list-scroll`),children:[Q&&(0,d.jsx)(o.ConversationCardSkeleton,{compact:f}),!f&&Nt&&(0,d.jsx)(`div`,{"data-testid":`conversation-panel-empty-state`,className:`flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-8`,children:(0,d.jsx)(`p`,{className:`text-xs text-[var(--oh-muted)]`,children:p(n.I18nKey.CONVERSATION$NO_CONVERSATIONS)})}),$?(0,d.jsx)(Ce.ConversationPanelPinnedSection,{pinnedConversations:st,isPreviewExpanded:Je,onTogglePreviewExpanded:()=>N(e=>!e),activeConversationId:m,showDivider:!f&&E===`chronological`,renderConversationCard:e=>Z(e,{inPinnedSection:!0})}):null,!f&&ot?.map(t=>(0,d.jsx)(oe.NavigationLink,{to:De(`/conversations/task-${t.id}`),onClick:e,className:`block`,children:(0,d.jsx)(ve.StartTaskCard,{task:t})},t.id)),!Q&&f?ft.map(e=>Z(e)):null,!Q&&!f&&E===`grouped`&&K&&K.length>0?(0,d.jsx)(Se.ConversationGroupFolderList,{groups:K,groupIds:dt,groupFolderOrder:k,setGroupFolderOrder:Ve,collapsedGroupIds:Ke,expandedGroupPreviewIds:qe,onToggleGroupCollapsed:Xe,onToggleGroupPreviewExpanded:Ze,isCreatingConversationFlow:X,activeConversationId:m,onLaunchFromGroup:Et,renderConversationCard:e=>Z(e)}):null,!Q&&!f&&E===`chronological`?(0,d.jsx)(`div`,{className:`space-y-0.5`,children:lt.map(e=>Z(e))}):null,wt&&(vt?(0,d.jsx)(`div`,{className:`py-1`,children:(0,d.jsx)(o.ConversationCardSkeleton,{compact:f})}):(0,d.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,d.jsx)(`button`,{type:`button`,"data-testid":`load-more-conversations`,onClick:_t,className:`text-xs text-[var(--oh-muted)] hover:text-white`,children:p(n.I18nKey.CONVERSATION$LOAD_MORE)})}))]}),ke&&(0,d.jsx)(a.ConfirmDeleteModal,{onConfirm:()=>{At(),_(!1),L(null)},onCancel:()=>{_(!1),L(null)},conversationTitle:et??void 0}),Me&&(0,d.jsx)(a.ConfirmDeleteModal,{title:p(n.I18nKey.CONVERSATION$CONFIRM_DELETE_ALL_TITLE),description:p(n.I18nKey.CONVERSATION$CONFIRM_DELETE_ALL_DESC,{count:H.length}),onConfirm:async()=>{await Mt(),b(!1)},onCancel:()=>b(!1)}),Ae&&(0,d.jsx)(de.ConfirmStopModal,{onConfirm:()=>{jt(),v(!1)},onCancel:()=>v(!1)}),je&&(0,d.jsx)(he.ExitConversationModal,{onConfirm:()=>{e?.()},onClose:()=>y(!1),onCancel:()=>y(!1)})]})}exports.ConversationPanel=p;
1
+ const e=require("../../../_virtual/_rolldown/runtime.cjs"),t=require("../../../node_modules/react-i18next/dist/es/useTranslation.cjs"),n=require("../../../i18n/declaration.cjs"),r=require("../../../utils/status.cjs"),i=require("../../../utils/utils.cjs"),ee=require("../../../context/navigation-context.cjs"),a=require("../../../utils/custom-toast-handlers.cjs"),te=require("../../../contexts/active-backend-context.cjs"),ne=require("../../../node_modules/@heroui/tooltip/dist/chunk-AUA5GDXN.cjs"),re=require("../../../hooks/use-click-outside-element.cjs"),ie=require("../../../hooks/mutation/use-create-conversation.cjs"),ae=require("../../shared/navigation-link.cjs"),oe=require("../../../hooks/mutation/use-delete-conversation.cjs"),se=require("../../../hooks/mutation/use-unified-stop-conversation.cjs"),ce=require("../../../hooks/use-is-creating-conversation.cjs"),le=require("../../../hooks/mutation/use-update-conversation.cjs"),ue=require("./confirm-delete-modal.cjs"),de=require("./confirm-stop-modal.cjs"),fe=require("../../../hooks/use-backend-scoped-path.cjs"),pe=require("../../../hooks/query/use-paginated-conversations.cjs"),me=require("../../../hooks/query/use-start-tasks.cjs"),he=require("./exit-conversation-modal.cjs"),ge=require("./conversation-card/conversation-card.cjs"),_e=require("./conversation-card/conversation-card-preview.cjs"),ve=require("./start-task-card/start-task-card.cjs"),o=require("./conversation-card/conversation-card-skeleton.cjs"),ye=require("./compact-conversation-row.cjs"),s=require("../../../stores/conversation-panel-preferences-store.cjs"),c=require("./conversation-panel-list-helpers.cjs"),be=require("./conversation-panel-filter-menu.cjs"),xe=require("./conversation-panel-new-thread-picker.cjs"),Se=require("./conversation-group-folder-list.cjs"),Ce=require("./conversation-panel-pinned-section.cjs"),l=require("../../../stores/pinned-conversations-store.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("react/jsx-runtime");var we=()=>{},Te=[],f=3600*1e3,Ee=e=>{let t=Date.now()-f,n=[],r=[];for(let i of e){let e=i.updated_at?Date.parse(i.updated_at):NaN;Number.isFinite(e)&&e<t?r.push(i):n.push(i)}return{recent:n,older:r}};function p({onClose:e,compact:f=!1}){let{t:p}=t.useTranslation(`openhands`),{conversationId:m,navigate:h}=ee.useNavigation(),{backend:g}=te.useActiveBackend(),De=fe.useBackendScopedPath(),Oe=re.useClickOutsideElement(e??we),[ke,_]=u.default.useState(!1),[Ae,v]=u.default.useState(!1),[je,Me]=u.default.useState(!1),[Ne,y]=u.default.useState(!1),b=s.useConversationPanelPreferencesStore(e=>e.showOlderConversations),Pe=s.useConversationPanelPreferencesStore(e=>e.toggleShowOlderConversations),x=s.useConversationPanelPreferencesStore(e=>e.showRepoBranchMetadata),Fe=s.useConversationPanelPreferencesStore(e=>e.toggleShowRepoBranchMetadata),S=s.useConversationPanelPreferencesStore(e=>e.showLlmProfiles),Ie=s.useConversationPanelPreferencesStore(e=>e.toggleShowLlmProfiles),C=s.useConversationPanelPreferencesStore(e=>e.showTagsMetadata),Le=s.useConversationPanelPreferencesStore(e=>e.toggleShowTagsMetadata),w=s.useConversationPanelPreferencesStore(e=>e.showHoverMetadata),Re=s.useConversationPanelPreferencesStore(e=>e.toggleShowHoverMetadata),T=s.useConversationPanelPreferencesStore(e=>e.organizeMode),ze=s.useConversationPanelPreferencesStore(e=>e.setOrganizeMode),E=s.useConversationPanelPreferencesStore(e=>e.conversationSort),Be=s.useConversationPanelPreferencesStore(e=>e.setConversationSort),D=s.useConversationPanelPreferencesStore(e=>e.threadScope),Ve=s.useConversationPanelPreferencesStore(e=>e.setThreadScope),O=s.useConversationPanelPreferencesStore(e=>e.automationFilterMode),He=s.useConversationPanelPreferencesStore(e=>e.setAutomationFilterMode),k=s.useConversationPanelPreferencesStore(e=>e.selectedAutomationNames),Ue=s.useConversationPanelPreferencesStore(e=>e.toggleAutomationName),A=s.useConversationPanelPreferencesStore(e=>e.groupFolderOrder),We=s.useConversationPanelPreferencesStore(e=>e.setGroupFolderOrder),[Ge,Ke]=u.default.useState(!1),[qe,Je]=u.default.useState(!1),Ye=re.useClickOutsideElement(()=>{Ke(!1)}),[Xe,Ze]=u.default.useState(()=>new Set),[Qe,$e]=u.default.useState(()=>new Set),[et,j]=u.default.useState(!1),M=l.usePinnedConversationsStore(e=>e.pinsByBackendId[g.id]??Te),tt=l.usePinnedConversationsStore(e=>e.togglePin),nt=l.usePinnedConversationsStore(e=>e.pruneMissingConversations),rt=u.default.useCallback(e=>{Ze(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]),it=u.default.useCallback(e=>{$e(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},[]);u.default.useEffect(()=>{T!==`grouped`&&(Ze(new Set),$e(new Set))},[T]);let at=u.default.useRef(null),[N,ot]=u.default.useState(null),[st,P]=u.default.useState(null),[F,ct]=u.default.useState(null),{data:lt,isLoading:ut,isFetched:I,hasNextPage:L,isFetching:dt,isFetchingNextPage:R,fetchNextPage:ft}=pe.usePaginatedConversations(),{data:pt}=me.useStartTasks(),z=u.default.useMemo(()=>{let e=lt?.pages.flatMap(e=>e.items)??[],t=new Set;return e.filter(e=>t.has(e.id)?!1:(t.add(e.id),!0))},[lt]),B=u.default.useMemo(()=>c.collectAutomationNameFacets(z),[z]),V=u.default.useMemo(()=>c.applyAutomationConversationFilter(z,O,k,B),[O,B,z,k]),mt=u.default.useMemo(()=>c.resolvePinnedConversations(M,z),[z,M]);u.default.useEffect(()=>{I&&nt(g.id,z.map(e=>e.id))},[g.id,z,I,nt]),u.default.useEffect(()=>{M.length===0&&j(!1)},[M.length]);let ht=u.default.useMemo(()=>{let e=D===`relevant`?V.filter(e=>r.isExecutionActive(e.execution_status)):V;return f?e:c.filterOutPinnedConversations(e,M)},[V,f,M,D]),{recent:H,older:U}=u.default.useMemo(()=>Ee(ht),[ht]),gt=u.default.useMemo(()=>c.sortConversationsByField(b?[...H,...U]:H,E),[H,U,b,E]),_t=u.default.useMemo(()=>({emptyWorkspace:p(n.I18nKey.CONVERSATION_PANEL$NO_WORKSPACE),emptyRepository:p(n.I18nKey.CONVERSATION_PANEL$NO_REPOSITORY)}),[p]),W=u.default.useMemo(()=>f||T!==`grouped`?null:c.groupConversations([...H,...b?U:[]],g.kind,E,_t),[g.kind,f,E,_t,U,T,H,b]),G=u.default.useMemo(()=>W?c.applyGroupFolderOrder(W,A):null,[W,A]),vt=u.default.useMemo(()=>W?.map(e=>e.id)??[],[W]),yt=u.default.useMemo(()=>c.sortConversationsByField(H.filter(e=>r.isExecutionActive(e.execution_status)),E),[E,H]),bt=gt.length,xt=u.default.useMemo(()=>G?G.reduce((e,t)=>e+t.conversations.length,0):0,[G]),K=T===`grouped`&&!f?xt===0:bt===0,St=K&&O!==`all`&&z.length>0&&V.length===0,q=T===`grouped`&&!f?xt:bt,[J,Y]=u.default.useState(null),Ct=u.default.useRef(q);Ct.current=q;let wt=u.default.useCallback(()=>{L&&Y(Ct.current)},[L]);u.default.useEffect(()=>{if(J!==null){if(q>J){Y(null);return}if(!L){Y(null);return}dt||R||ft()}},[J,q,L,dt,R,ft]);let Tt=J!==null||R,{mutate:Et,mutateAsync:Dt}=oe.useDeleteConversation(),{mutate:Ot}=se.useUnifiedPauseConversation(),{mutate:kt}=le.useUpdateConversation(),At=U.length>0&&!b,jt=!!L&&!At&&!f&&(!K||St),{mutate:Mt}=ie.useCreateConversation(),X=ce.useIsCreatingConversation(),Nt=u.default.useCallback(e=>{X||Mt({workingDir:e.workingDir,repository:e.repository,entryPoint:`sidebar_relaunch_project`},{onSuccess:e=>{h(`/conversations/${e.conversation_id}`)}})},[Mt,X,h]),Pt=u.default.useCallback((e,t)=>{_(!0),ot(e),P(t)},[]),Ft=u.default.useCallback(e=>{v(!0),ot(e)},[]),It=u.default.useCallback((e,t)=>{kt({conversationId:e,newTitle:t},{onSuccess:()=>{a.displaySuccessToast(p(n.I18nKey.CONVERSATION$TITLE_UPDATED))}})},[p,kt]),Lt=()=>{N&&Et({conversationId:N},{onSuccess:()=>{N===m&&h(`/conversations`)}})},Rt=()=>{N&&Ot({conversationId:N})},zt=async()=>{let e=z.map(e=>e.id),t=await Promise.allSettled(e.map(e=>Dt({conversationId:e}))),n=t.flatMap((t,n)=>t.status===`fulfilled`?[e[n]]:[]),r=t.length-n.length;m!==null&&n.includes(m)&&h(`/conversations`),r>0&&a.displayErrorToast(`${r} conversation${r===1?``:`s`} could not be deleted.`)},Z=u.default.useCallback((t,n)=>{let r=M.includes(t.id);return f?(0,d.jsx)(ye.CompactConversationRow,{conversationId:t.id,title:t.title??``,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,lastUpdatedAt:t.updated_at,createdAt:t.created_at,workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,isActive:t.id===m,onClose:e,showRepositoryMetadata:x,llmModel:t.llm_model,showLlmProfiles:S,agentKind:t.agent_kind,acpServer:t.acp_server,tags:t.tags,showTags:C},t.id):(0,d.jsx)(ne.tooltip_default,{placement:`right-start`,delay:1e3,closeDelay:100,isDisabled:!w||F===t.id,disableAnimation:!1,className:`max-w-none overflow-visible rounded-xl border border-[var(--oh-border)] bg-base-secondary p-0 text-white shadow-xl`,content:(0,d.jsx)(_e.ConversationCardPreview,{title:t.title??``,executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,llmModel:t.llm_model,agentKind:t.agent_kind,acpServer:t.acp_server,createdAt:t.created_at,tags:t.tags}),children:(0,d.jsx)(ae.NavigationLink,{to:De(`/conversations/${t.id}`),onClick:e,className:i.cn(`block rounded-md transition-colors`,F!==t.id&&`hover:bg-[var(--oh-surface)]`,(t.id===m||F===t.id)&&`bg-[var(--oh-surface)]`),children:(0,d.jsx)(ge.ConversationCard,{onDelete:()=>Pt(t.id,t.title??``),onStop:()=>Ft(t.id),onChangeTitle:e=>It(t.id,e),title:t.title??``,selectedRepository:{selected_repository:t.selected_repository,selected_branch:t.selected_branch,git_provider:t.git_provider},lastUpdatedAt:t.updated_at,createdAt:t.created_at,executionStatus:t.execution_status,sandboxStatus:t.sandbox_status,conversationId:t.id,contextMenuOpen:F===t.id,onContextMenuToggle:e=>ct(e?t.id:null),isActive:t.id===m,workspaceWorkingDir:t.selected_workspace??t.workspace?.working_dir,showRepositoryMetadata:x,llmModel:t.llm_model,showLlmProfiles:S,agentKind:t.agent_kind,acpServer:t.acp_server,tags:t.tags,showTags:C,isPinned:r,onTogglePin:()=>tt(g.id,t.id),alwaysShowPinIcon:r&&!n?.inPinnedSection})})},t.id)},[g.id,f,m,It,Pt,Ft,e,F,M,x,S,C,w,tt]),Q=ut||!I,$=!f&&!Q&&mt.length>0,Bt=I&&!ut&&!f&&K&&!$&&!pt?.length;return(0,d.jsxs)(`div`,{ref:Oe,"data-testid":`conversation-panel`,className:`flex h-full min-h-0 w-full flex-col`,children:[!f&&(0,d.jsx)(`div`,{className:i.cn(`-ml-2.5 w-[calc(100%+0.625rem)] max-w-none box-border border-b`,qe?`border-[var(--oh-border)]`:`border-transparent`),children:(0,d.jsxs)(`div`,{"data-testid":`older-conversations-summary`,className:`flex min-w-0 flex-nowrap items-center gap-x-2 py-2 pl-4 pr-2.5 text-[var(--oh-muted)]`,children:[(0,d.jsx)(`span`,{className:`min-w-0 truncate text-sm font-medium text-[var(--oh-muted)]`,children:p(n.I18nKey.SIDEBAR$CONVERSATIONS)}),(0,d.jsxs)(`div`,{className:`ml-auto flex shrink-0 items-center gap-0.5`,children:[(0,d.jsx)(xe.ConversationPanelNewThreadPicker,{backendKind:g.kind}),(0,d.jsx)(be.ConversationPanelFilterMenu,{filterMenuOpen:Ge,setFilterMenuOpen:Ke,menuRef:Ye,backendKind:g.kind,organizeMode:T,setOrganizeMode:ze,conversationSort:E,setConversationSort:Be,threadScope:D,setThreadScope:Ve,automationFilterMode:O,setAutomationFilterMode:He,selectedAutomationNames:k,onToggleAutomationName:Ue,automationNameFacets:B,showOlderConversations:b,toggleShowOlderConversations:Pe,showRepoBranchMetadata:x,toggleShowRepoBranchMetadata:Fe,showLlmProfiles:S,toggleShowLlmProfiles:Ie,showTagsMetadata:C,toggleShowTagsMetadata:Le,showHoverMetadata:w,toggleShowHoverMetadata:Re,totalConversationsCount:z.length,onRequestDeleteAll:()=>y(!0)})]})]})}),(0,d.jsxs)(`div`,{ref:at,"data-testid":`conversation-panel-list-scroll`,onScroll:e=>{Je(e.currentTarget.scrollTop>0)},className:i.cn(`flex min-h-0 flex-1 flex-col overflow-y-auto overflow-x-hidden overscroll-contain custom-scrollbar-always`,!f&&`conversation-panel-list-scroll`),children:[Q&&(0,d.jsx)(o.ConversationCardSkeleton,{compact:f}),!f&&Bt&&(0,d.jsx)(`div`,{"data-testid":`conversation-panel-empty-state`,className:`flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-8`,children:(0,d.jsx)(`p`,{className:`text-xs text-[var(--oh-muted)]`,children:p(St?n.I18nKey.CONVERSATION_PANEL$NO_AUTOMATION_MATCHES:n.I18nKey.CONVERSATION$NO_CONVERSATIONS)})}),$?(0,d.jsx)(Ce.ConversationPanelPinnedSection,{pinnedConversations:mt,isPreviewExpanded:et,onTogglePreviewExpanded:()=>j(e=>!e),activeConversationId:m,showDivider:!f&&T===`chronological`,renderConversationCard:e=>Z(e,{inPinnedSection:!0})}):null,!f&&pt?.map(t=>(0,d.jsx)(ae.NavigationLink,{to:De(`/conversations/task-${t.id}`),onClick:e,className:`block`,children:(0,d.jsx)(ve.StartTaskCard,{task:t})},t.id)),!Q&&f?yt.map(e=>Z(e)):null,!Q&&!f&&T===`grouped`&&G&&G.length>0?(0,d.jsx)(Se.ConversationGroupFolderList,{groups:G,groupIds:vt,groupFolderOrder:A,setGroupFolderOrder:We,collapsedGroupIds:Xe,expandedGroupPreviewIds:Qe,onToggleGroupCollapsed:rt,onToggleGroupPreviewExpanded:it,isCreatingConversationFlow:X,activeConversationId:m,onLaunchFromGroup:Nt,renderConversationCard:e=>Z(e)}):null,!Q&&!f&&T===`chronological`?(0,d.jsx)(`div`,{className:`space-y-0.5`,children:gt.map(e=>Z(e))}):null,jt&&(Tt?(0,d.jsx)(`div`,{className:`py-1`,children:(0,d.jsx)(o.ConversationCardSkeleton,{compact:f})}):(0,d.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,d.jsx)(`button`,{type:`button`,"data-testid":`load-more-conversations`,onClick:wt,className:`text-xs text-[var(--oh-muted)] hover:text-white`,children:p(n.I18nKey.CONVERSATION$LOAD_MORE)})}))]}),ke&&(0,d.jsx)(ue.ConfirmDeleteModal,{onConfirm:()=>{Lt(),_(!1),P(null)},onCancel:()=>{_(!1),P(null)},conversationTitle:st??void 0}),Ne&&(0,d.jsx)(ue.ConfirmDeleteModal,{title:p(n.I18nKey.CONVERSATION$CONFIRM_DELETE_ALL_TITLE),description:p(n.I18nKey.CONVERSATION$CONFIRM_DELETE_ALL_DESC,{count:z.length}),onConfirm:async()=>{await zt(),y(!1)},onCancel:()=>y(!1)}),Ae&&(0,d.jsx)(de.ConfirmStopModal,{onConfirm:()=>{Rt(),v(!1)},onCancel:()=>v(!1)}),je&&(0,d.jsx)(he.ExitConversationModal,{onConfirm:()=>{e?.()},onClose:()=>Me(!1),onCancel:()=>Me(!1)})]})}exports.ConversationPanel=p;
2
2
  //# sourceMappingURL=conversation-panel.cjs.map