@openhands/agent-canvas 1.16.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.windows.md +2 -2
- package/build/assets/{acp-providers-CX3Lh9gj.js → acp-providers-DrjNsPOH.js} +1 -1
- package/build/assets/active-backend-context-rZiLJRUc.js +2 -0
- package/build/assets/{agent-context-settings-DSZlXrLj.js → agent-context-settings-CJUrcBut.js} +1 -1
- package/build/assets/agent-profiles-service.api-Biieml2L.js +1 -0
- package/build/assets/agent-profiles-settings-x6RvPsq7.js +1 -0
- package/build/assets/agent-server-client-options-BikiNwTa.js +1 -0
- package/build/assets/agent-server-conversation-service.api-DYFsNHKf.js +88 -0
- package/build/assets/agent-settings-BJyovpJ_.js +1 -0
- package/build/assets/agent-settings-CpY3zObk.js +2 -0
- package/build/assets/{alert-banner-HP6mX-Vr.js → alert-banner-vARz1idS.js} +1 -1
- package/build/assets/{api-error-message-B-XdSk3b.js → api-error-message-Ve79qDcN.js} +1 -1
- package/build/assets/api-key-entry-screen-CsMuBhoP.js +1 -0
- package/build/assets/{app-settings-dbnneVaV.js → app-settings-BaJ7nfHt.js} +1 -1
- package/build/assets/automation-detail-CVoGDrKq.js +3 -0
- package/build/assets/{automation-export-D3a3of4G.js → automation-export-DxY47m3T.js} +1 -1
- package/build/assets/automation-git-sync-CRMP9Bbm.js +1 -0
- package/build/assets/automation-setup-route-072beLz1.js +3 -0
- package/build/assets/{automation-templates-BRppNh99.js → automation-templates-4C4PM8K7.js} +1 -1
- package/build/assets/automations-list-xuqTSQL4.js +1 -0
- package/build/assets/{back-nav-button-Cjl_hoxq.js → back-nav-button-B8tH0BEp.js} +1 -1
- package/build/assets/backend-form-modal-0aJmWdsa.js +1 -0
- package/build/assets/{backend-synced-settings-badge-DPkz30BE.js → backend-synced-settings-badge-B7rKWBir.js} +1 -1
- package/build/assets/{badge-BU3S0VtE.js → badge-CcGx2TaV.js} +1 -1
- package/build/assets/{base-modal-D_L0oEbG.js → base-modal-DTULovNc.js} +1 -1
- package/build/assets/bot-CLMxGFaq.js +1 -0
- package/build/assets/{brand-button-BAfk4wGP.js → brand-button-DxPO4Lf8.js} +1 -1
- package/build/assets/{browser-DSAo0tz1.js → browser-C-_qBasq.js} +2 -2
- package/build/assets/{browser-tab-C9vy56R5.js → browser-tab-DZanIw5m.js} +1 -1
- package/build/assets/{canvas-extension-page-dx1gFrfW.js → canvas-extension-page-o_cWgE9B.js} +1 -1
- package/build/assets/canvas-extensions-DSgNlCha.js +1 -0
- package/build/assets/{canvas-extensions-runtime-2_x5Ezmi.js → canvas-extensions-runtime-DdnkgJXV.js} +1 -1
- package/build/assets/{chat-send-button-MUQqCZCS.js → chat-send-button-B3SFSIg5.js} +1 -1
- package/build/assets/check-fDEfgSzj.js +1 -0
- package/build/assets/chevron-down-CFrWHqu8.js +1 -0
- package/build/assets/chevron-right-C5roOrJu.js +1 -0
- package/build/assets/circle-check-ClTzJTdb.js +1 -0
- package/build/assets/{circle-plus-check-toggle-BO_kFZt3.js → circle-plus-check-toggle-Fr-h-mbL.js} +1 -1
- package/build/assets/{cloud-funnel-analytics-CztBCCPp.js → cloud-funnel-analytics-BQanUEEC.js} +1 -1
- package/build/assets/{cog-D-MPQW6G.js → cog-VBlRo6iw.js} +1 -1
- package/build/assets/command-menu-BT3Ia5Ru.js +1 -0
- package/build/assets/commits-tab-2jhtaohl.js +1 -0
- package/build/assets/{condenser-settings-DmEOje-7.js → condenser-settings-eVKFMvap.js} +1 -1
- package/build/assets/confirmation-modal-gIFHeZt6.js +1 -0
- package/build/assets/{context-menu-list-item-I86vKcmM.js → context-menu-list-item-DDROe12Z.js} +1 -1
- package/build/assets/conversation-BnjJSFf5.js +93 -0
- package/build/assets/conversation-DZ578rOX.js +1 -0
- package/build/assets/conversation-panel-DZ578rOX.js +1 -0
- package/build/assets/{conversation-state-store-B0ImPLHO.js → conversation-state-store-D1_G_9I-.js} +1 -1
- package/build/assets/{conversation-store-Ca3ghXap.js → conversation-store-DVVfkCsk.js} +1 -1
- package/build/assets/{conversation-tab-empty-state-FIbh_lc8.js → conversation-tab-empty-state-DKlzAz5c.js} +1 -1
- package/build/assets/{copy-to-clipboard-button-Ca8iSkkA.js → copy-to-clipboard-button-B3w0X7WH.js} +1 -1
- package/build/assets/{device-verify-Bhn2e_Ye.js → device-verify-BfkCzyFB.js} +1 -1
- package/build/assets/{dropdown-classes-Bc1djN0-.js → dropdown-classes-B9kJVDIk.js} +1 -1
- package/build/assets/edit-automation-modal-BwhJ39JT.js +1 -0
- package/build/assets/empty-state-RZz0OfnY.js +1 -0
- package/build/assets/{entry.client-CqyPPjOq.js → entry.client-Ds8LVp-E.js} +2 -2
- package/build/assets/enum-filter-dropdown-C4pW0ORd.js +1 -0
- package/build/assets/{environment-switch-overlay-BmBRT7gv.js → environment-switch-overlay-P2ZAuzov.js} +1 -1
- package/build/assets/{error-state-Body8Ngd.js → error-state-B_5cgNPJ.js} +1 -1
- package/build/assets/extensions-hub-DsaUr4ca.js +1 -0
- package/build/assets/extensions-navigation-CRMZd-FE.js +1 -0
- package/build/assets/external-link-DQtv7eTh.js +1 -0
- package/build/assets/files-tab-CCgAcVdc.js +1 -0
- package/build/assets/{form-control-classes-Bkh5FGrD.js → form-control-classes-B-z85REi.js} +1 -1
- package/build/assets/get-git-path-EHrSDxTM.js +1 -0
- package/build/assets/git-repo-dropdown-D2WEQ97X.js +1 -0
- package/build/assets/{git-repo-dropdown-4ROKl2cB.js → git-repo-dropdown-DVeCUUXG.js} +1 -1
- package/build/assets/{highlighted-source-view-BFRxGT_Q.js → highlighted-source-view-DjHO3SdW.js} +1 -1
- package/build/assets/home-BorS_vdS.js +1 -0
- package/build/assets/home-aIMbHw5M.js +1 -0
- package/build/assets/home-automation-run-tooltip-CpHNFiFl.js +1 -0
- package/build/assets/home-store-DyXz0w6d.js +1 -0
- package/build/assets/hooks-service-C6dpRtZM.js +1 -0
- package/build/assets/index-home-zKFuKK2B.js +1 -0
- package/build/assets/info-CTIdjttz.js +1 -0
- package/build/assets/install-server-modal-DUiZMc8u.js +1 -0
- package/build/assets/kebab-menu-item-content-mm04SBD3.js +1 -0
- package/build/assets/{key-BmVyxs-2.js → key-CfXbJa8w.js} +1 -1
- package/build/assets/{launch-IrTDEFCs.js → launch-BSIf9KEg.js} +1 -1
- package/build/assets/list-filter-CNpqTWVY.js +1 -0
- package/build/assets/{list-todo-apgLVjMw.js → list-todo-ByXMdY4W.js} +1 -1
- package/build/assets/llm-not-configured-banner-z_QRSeV0.js +27 -0
- package/build/assets/llm-settings-B-5AHMiX.js +1 -0
- package/build/assets/llm-settings-B3SjHDmA.js +1 -0
- package/build/assets/llm-subscription-service-aDNBQ7Gq.js +1 -0
- package/build/assets/loader-circle-Dex47vVW.js +1 -0
- package/build/assets/{loading-spinner-BY9N3pOe.js → loading-spinner-DfHI77BA.js} +1 -1
- package/build/assets/manage-backends-modal-q1NdFisr.js +1 -0
- package/build/assets/manifest-8920b615.js +1 -0
- package/build/assets/{manifest-subpage-layout-CAOYzrYp.js → manifest-subpage-layout-BQQy5ipR.js} +1 -1
- package/build/assets/{map-provider-Cu3Zgumb.js → map-provider-DXvssjw9.js} +1 -1
- package/build/assets/markdown-renderer-rivLvYh-.js +8 -0
- package/build/assets/{mcp-BTs_SXfZ.js → mcp-CEXDhQWn.js} +1 -1
- package/build/assets/{mcp-marketplace-utils-AIBzzHTO.js → mcp-marketplace-utils-Cn_NIMWM.js} +1 -1
- package/build/assets/mcp-page-LGYIICMG.js +9 -0
- package/build/assets/messages-DUSeANAh.js +41 -0
- package/build/assets/{modal-body-BxZjsju9.js → modal-body-DJw4xBki.js} +1 -1
- package/build/assets/{modal-classes-C8eycCwG.js → modal-classes-Dg0ngBPO.js} +1 -1
- package/build/assets/{modal-close-button-DDzdRvCs.js → modal-close-button-B9j4nasm.js} +1 -1
- package/build/assets/{mouse-pointer-click-Co2uyaPA.js → mouse-pointer-click-DEhsSUpu.js} +1 -1
- package/build/assets/onboarding-BjFebfs5.js +1 -0
- package/build/assets/onboarding-modal-DDTjOpyd.js +1 -0
- package/build/assets/organization-service.api-Cyg1Tn03.js +1 -0
- package/build/assets/pencil-D5c47kyN.js +1 -0
- package/build/assets/pin-C7vMagvf.js +1 -0
- package/build/assets/planner-tab-D8f2Y3rn.js +1 -0
- package/build/assets/plug-CeaqeF6u.js +1 -0
- package/build/assets/plugins-management-service-Bh_pBuf-.js +1 -0
- package/build/assets/plus-B3wvU06-.js +1 -0
- package/build/assets/profiles-service.api-BbOK0EkF.js +1 -0
- package/build/assets/{providers-BhMcY5nv.js → providers-2gIIkz2N.js} +1 -1
- package/build/assets/proxy-CBgMd2zf.js +1 -0
- package/build/assets/{puzzle-JM_QaRm0.js → puzzle-DdAqbUrb.js} +1 -1
- package/build/assets/recommended-automations-launcher-YLAQTp4s.js +1 -0
- package/build/assets/refresh-cw-DEQdPCpH.js +1 -0
- package/build/assets/root-Bye_XmEL.js +2 -0
- package/build/assets/root-Cnwwzgo0.css +1 -0
- package/build/assets/root-layout-CSAwxBGM.js +2 -0
- package/build/assets/schema-field-CK0xYNbO.js +1 -0
- package/build/assets/scroll-fade-state-Dt_fx2kf.js +1 -0
- package/build/assets/sdk-section-page-Da73Rs_o.js +1 -0
- package/build/assets/secret-form-CB2VwYYg.js +1 -0
- package/build/assets/secrets-service-Cr8g8xuv.js +1 -0
- package/build/assets/{secrets-settings-B_GpxKW2.js → secrets-settings-Bh0udeKv.js} +1 -1
- package/build/assets/settings-DmyIgRxO.js +1 -0
- package/build/assets/{settings-dropdown-input-BcwylHs2.js → settings-dropdown-input-DVpyD87C.js} +1 -1
- package/build/assets/settings-index-BSJUFmjE.js +1 -0
- package/build/assets/{settings-input-Db-1g8Ql.js → settings-input-C0dd8Utu.js} +1 -1
- package/build/assets/{settings-list-classes-BzeSZbF2.js → settings-list-classes-Ds4jPBHK.js} +1 -1
- package/build/assets/{settings-modal-DfJ3tcJQ.js → settings-modal-yStgEh2o.js} +1 -1
- package/build/assets/settings-service.api-9_xdv_mh.js +1 -0
- package/build/assets/{settings-switch-CS-dJDmA.js → settings-switch-B78Khmyz.js} +1 -1
- package/build/assets/{settings-utils-UYpEdPuD.js → settings-utils-8GIIgOQL.js} +1 -1
- package/build/assets/shared-conversation-DM96X4KV.js +1 -0
- package/build/assets/shield-check-DO7wa_eu.js +1 -0
- package/build/assets/{sidebar-layout-D6fS8-Gl.js → sidebar-layout-EPfWxk11.js} +1 -1
- package/build/assets/sidebar-mobile-menu-toggle-D5GR5xT9.js +1 -0
- package/build/assets/{sidebar-nav-link-DQQcMf1A.js → sidebar-nav-link-_t4_Ef-9.js} +1 -1
- package/build/assets/{sidebar-onboarding-checklist-storage-BBkeI6Bp.js → sidebar-onboarding-checklist-storage-DbDX-Wvj.js} +1 -1
- package/build/assets/{sidebar-store-DGqHkVLw.js → sidebar-store-CSDFK0W5.js} +1 -1
- package/build/assets/{skill-card-pill-row-B27-xyig.js → skill-card-pill-row-989y15jV.js} +1 -1
- package/build/assets/{skill-filter-w__3UCEE.js → skill-filter-BBeZ4JEP.js} +1 -1
- package/build/assets/{skill-icon-badge-RQkq8wvl.js → skill-icon-badge-BDhQ-tQ0.js} +1 -1
- package/build/assets/skill-scope-Dz3kPH3P.js +1 -0
- package/build/assets/skills-plugins-e3CYGdUJ.js +1 -0
- package/build/assets/skills-settings-3e-FuHw_.js +1 -0
- package/build/assets/styled-tooltip-Pd22BIvr.js +1 -0
- package/build/assets/{task-list-tab-C5zcaktH.js → task-list-tab-3Jg8ywch.js} +1 -1
- package/build/assets/{terminal-CNElN42a.js → terminal-onXx0_Qz.js} +2 -2
- package/build/assets/toggle-switch-lwQtxDcm.js +1 -0
- package/build/assets/trash-2-ZhKuTLiz.js +1 -0
- package/build/assets/trash-B6OIe4yX.js +1 -0
- package/build/assets/triangle-alert-BajLPpQg.js +1 -0
- package/build/assets/{typography-v1KN0tzi.js → typography-HLLg_FAn.js} +1 -1
- package/build/assets/usage-tab-Cm-9j3UK.js +1 -0
- package/build/assets/use-acp-credential-form-BARcvjYE.js +1 -0
- package/build/assets/use-activate-agent-profile-BLKML6vQ.js +1 -0
- package/build/assets/use-agent-profiles-1P91KSXz.js +1 -0
- package/build/assets/{use-automation-health-E6NZi9rb.js → use-automation-health-BZkQNEA8.js} +1 -1
- package/build/assets/use-automation-permissions-B_RpvL-s.js +1 -0
- package/build/assets/{use-automations-xijQKIl9.js → use-automations-Cg0PDIZr.js} +1 -1
- package/build/assets/{use-can-manage-org-profiles-CrJP5262.js → use-can-manage-org-profiles-BbN6KfDr.js} +1 -1
- package/build/assets/use-canvas-extensions-CFUpHat6.js +1 -0
- package/build/assets/{use-cloud-current-user-id-CDfAHpPX.js → use-cloud-current-user-id-Dk0rjr63.js} +1 -1
- package/build/assets/use-config-DpafU_QP.js +1 -0
- package/build/assets/use-create-conversation-1YgmAHt-.js +1 -0
- package/build/assets/use-create-secret-D8p9ybQj.js +1 -0
- package/build/assets/{use-get-secrets-K3jmk-LH.js → use-get-secrets-CQ4b0qK8.js} +1 -1
- package/build/assets/use-is-authed-BRPjCRKM.js +1 -0
- package/build/assets/{use-launch-skill-in-chat-BYjYihBP.js → use-launch-skill-in-chat-DeYa1tFM.js} +1 -1
- package/build/assets/use-llm-configured-DGm8FiRR.js +1 -0
- package/build/assets/use-llm-profiles-BTTtpW4z.js +1 -0
- package/build/assets/use-manifest-capabilities-AOWGcu0j.js +1 -0
- package/build/assets/use-onboarding-completion-CoINurkm.js +1 -0
- package/build/assets/use-pinned-home-route-D6krwXjy.js +1 -0
- package/build/assets/use-plugins-marketplace-mLsIDhBv.js +1 -0
- package/build/assets/use-save-agent-profile-CxyO9YG-.js +1 -0
- package/build/assets/{use-save-settings-DYqkKv7T.js → use-save-settings-3U5K9-8x.js} +1 -1
- package/build/assets/use-settings-Dn00UISA.js +1 -0
- package/build/assets/use-settings-nav-items-vrjxTqcu.js +16 -0
- package/build/assets/use-tracking-B9prBsrq.js +3 -0
- package/build/assets/{use-user-conversation-B9Gebw_g.js → use-user-conversation-ZWlXtbZb.js} +1 -1
- package/build/assets/{useInfiniteQuery-C926xzY4.js → useInfiniteQuery-BzrRqjLg.js} +1 -1
- package/build/assets/{useMutation-B-qc391N.js → useMutation-CJuK90oc.js} +1 -1
- package/build/assets/{useQueries-DlbhlH9I.js → useQueries-CykmpT-a.js} +1 -1
- package/build/assets/{useQuery-BSTgq1rl.js → useQuery-S6j94er1.js} +1 -1
- package/build/assets/utils-BOco8mxR.js +1 -0
- package/build/assets/{vendor~conversation-panel~conversation-C8Fn4XOf.js → vendor~conversation-panel~conversation-4eJ0tml3.js} +1 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~b0x1wrp2-Z0lly3FE.js +2 -0
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-BfkNGovw.js +185 -0
- package/build/assets/{vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-rfV8mQ9m.js → vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~ew9ih1s8-DnDoaYNi.js} +1 -1
- package/build/assets/{vendor~index-home~home~conversation-panel~conversation-hWywRBaR.js → vendor~index-home~home~conversation-panel~conversation-CSFLzmTN.js} +1 -1
- package/build/assets/vendor~root-layout-n8XCEXG8.js +1 -0
- package/build/assets/{vendor~root-layout~conversation-panel~conversation-BMbMgaGu.js → vendor~root-layout~conversation-panel~conversation-3Idg1_U3.js} +1 -1
- package/build/assets/{vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-BWir3rJs.js → vendor~root-layout~conversation-panel~conversation~skills-settings~automations-list~shared-~bovqqk8e-DkPlXWl9.js} +1 -1
- package/build/assets/{vendor~root-layout~index-home~home~conversation-panel~conversation-j5MFqfSy.js → vendor~root-layout~index-home~home~conversation-panel~conversation-DgQ564nC.js} +1 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-CxhwKuAd.js +1 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~nj1hli3r-DP9wmsjo.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~inibp4qe-CnsDDzeE.js} +1 -1
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-CV850oio.js +1 -0
- package/build/assets/{vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-CUmIwQCN.js → vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~skills-setti~eo2nf80n-BPjI-atc.js} +12 -6
- package/build/assets/{verification-settings-gw_q6vkL.js → verification-settings-u2POabjH.js} +1 -1
- package/build/assets/{wrench-CUEI1krB.js → wrench-CkgI4rxA.js} +1 -1
- package/build/assets/x-By6qCmtY.js +1 -0
- package/build/index.html +4 -4
- package/build/locales/ar/openhands.json +73 -20
- package/build/locales/ca/openhands.json +73 -20
- package/build/locales/de/openhands.json +73 -20
- package/build/locales/en/openhands.json +73 -20
- package/build/locales/es/openhands.json +73 -20
- package/build/locales/fr/openhands.json +73 -20
- package/build/locales/it/openhands.json +73 -20
- package/build/locales/ja/openhands.json +73 -20
- package/build/locales/ko-KR/openhands.json +73 -20
- package/build/locales/no/openhands.json +73 -20
- package/build/locales/pt/openhands.json +73 -20
- package/build/locales/tr/openhands.json +73 -20
- package/build/locales/uk/openhands.json +73 -20
- package/build/locales/zh-CN/openhands.json +73 -20
- package/build/locales/zh-TW/openhands.json +73 -20
- package/config/defaults.json +3 -3
- package/dist/api/agent-server-adapter.cjs +3 -3
- package/dist/api/agent-server-adapter.cjs.map +1 -1
- package/dist/api/agent-server-adapter.d.ts +72 -12
- package/dist/api/agent-server-adapter.js +234 -132
- package/dist/api/agent-server-adapter.js.map +1 -1
- package/dist/api/agent-server-config.cjs +1 -1
- package/dist/api/agent-server-config.cjs.map +1 -1
- package/dist/api/agent-server-config.d.ts +6 -0
- package/dist/api/agent-server-config.js +6 -3
- package/dist/api/agent-server-config.js.map +1 -1
- package/dist/api/automation-service/automation-service.api.cjs +1 -1
- package/dist/api/automation-service/automation-service.api.cjs.map +1 -1
- package/dist/api/automation-service/automation-service.api.d.ts +2 -2
- package/dist/api/automation-service/automation-service.api.js +7 -7
- package/dist/api/automation-service/automation-service.api.js.map +1 -1
- package/dist/api/cloud/provider-connections-service.api.cjs +2 -0
- package/dist/api/cloud/provider-connections-service.api.cjs.map +1 -0
- package/dist/api/cloud/provider-connections-service.api.d.ts +5 -0
- package/dist/api/cloud/provider-connections-service.api.js +50 -0
- package/dist/api/cloud/provider-connections-service.api.js.map +1 -0
- package/dist/api/cloud/skills-service.api.cjs +1 -1
- package/dist/api/cloud/skills-service.api.cjs.map +1 -1
- package/dist/api/cloud/skills-service.api.d.ts +10 -0
- package/dist/api/cloud/skills-service.api.js +11 -1
- package/dist/api/cloud/skills-service.api.js.map +1 -1
- package/dist/api/conversation-metadata-store.cjs +1 -1
- package/dist/api/conversation-metadata-store.cjs.map +1 -1
- package/dist/api/conversation-metadata-store.d.ts +24 -0
- package/dist/api/conversation-metadata-store.js +10 -2
- package/dist/api/conversation-metadata-store.js.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.cjs.map +1 -1
- package/dist/api/conversation-service/agent-server-conversation-service.api.d.ts +20 -0
- package/dist/api/conversation-service/agent-server-conversation-service.api.js +126 -77
- package/dist/api/conversation-service/agent-server-conversation-service.api.js.map +1 -1
- package/dist/api/hooks-service.cjs +2 -0
- package/dist/api/hooks-service.cjs.map +1 -0
- package/dist/api/hooks-service.d.ts +13 -0
- package/dist/api/hooks-service.js +20 -0
- package/dist/api/hooks-service.js.map +1 -0
- package/dist/api/provider-connections-service/provider-connections-service.api.cjs +1 -1
- package/dist/api/provider-connections-service/provider-connections-service.api.cjs.map +1 -1
- package/dist/api/provider-connections-service/provider-connections-service.api.js +25 -16
- package/dist/api/provider-connections-service/provider-connections-service.api.js.map +1 -1
- package/dist/api/settings-service/settings-service.api.cjs +1 -1
- package/dist/api/settings-service/settings-service.api.cjs.map +1 -1
- package/dist/api/settings-service/settings-service.api.d.ts +2 -0
- package/dist/api/settings-service/settings-service.api.js +18 -10
- package/dist/api/settings-service/settings-service.api.js.map +1 -1
- package/dist/api/skills-service.cjs +1 -1
- package/dist/api/skills-service.cjs.map +1 -1
- package/dist/api/skills-service.d.ts +7 -0
- package/dist/api/skills-service.js +11 -8
- package/dist/api/skills-service.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/critic-result-display.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/critic-result-display.js +5 -5
- package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/finish-event-message.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js +2 -1
- package/dist/components/conversation-events/chat/event-message-components/finish-event-message.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.d.ts +1 -1
- package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js +28 -28
- package/dist/components/conversation-events/chat/event-message-components/generic-event-message-wrapper.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/thought-event-message.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js +2 -1
- package/dist/components/conversation-events/chat/event-message-components/thought-event-message.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs +1 -1
- package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.d.ts +1 -1
- package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js +37 -37
- package/dist/components/conversation-events/chat/event-message-components/user-assistant-event-message.js.map +1 -1
- package/dist/components/conversation-events/chat/event-message.cjs +2 -2
- package/dist/components/conversation-events/chat/event-message.cjs.map +1 -1
- package/dist/components/conversation-events/chat/event-message.js +79 -70
- package/dist/components/conversation-events/chat/event-message.js.map +1 -1
- package/dist/components/conversation-events/chat/messages.cjs +1 -1
- package/dist/components/conversation-events/chat/messages.cjs.map +1 -1
- package/dist/components/conversation-events/chat/messages.js +28 -27
- package/dist/components/conversation-events/chat/messages.js.map +1 -1
- package/dist/components/features/automations/automation-card.cjs +1 -1
- package/dist/components/features/automations/automation-card.cjs.map +1 -1
- package/dist/components/features/automations/automation-card.js +100 -94
- package/dist/components/features/automations/automation-card.js.map +1 -1
- package/dist/components/features/automations/automation-list-row.cjs +1 -1
- package/dist/components/features/automations/automation-list-row.cjs.map +1 -1
- package/dist/components/features/automations/automation-list-row.js +88 -77
- package/dist/components/features/automations/automation-list-row.js.map +1 -1
- package/dist/components/features/automations/detail/detail-header.d.ts +3 -1
- package/dist/components/features/automations/detail/run-status-badge.cjs +1 -1
- package/dist/components/features/automations/detail/run-status-badge.cjs.map +1 -1
- package/dist/components/features/automations/detail/run-status-badge.d.ts +2 -2
- package/dist/components/features/automations/detail/run-status-badge.js +82 -53
- package/dist/components/features/automations/detail/run-status-badge.js.map +1 -1
- package/dist/components/features/automations/kebab-menu.cjs +1 -1
- package/dist/components/features/automations/kebab-menu.cjs.map +1 -1
- package/dist/components/features/automations/kebab-menu.js +9 -5
- package/dist/components/features/automations/kebab-menu.js.map +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.cjs +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.cjs.map +1 -1
- package/dist/components/features/automations/recommended-automations-launcher.js +12 -12
- package/dist/components/features/automations/recommended-automations-launcher.js.map +1 -1
- package/dist/components/features/automations/recommended-automations-section.cjs +1 -1
- package/dist/components/features/automations/recommended-automations-section.js +9 -9
- package/dist/components/features/backends/backend-selector.cjs +1 -1
- package/dist/components/features/backends/backend-selector.cjs.map +1 -1
- package/dist/components/features/backends/backend-selector.js +133 -122
- package/dist/components/features/backends/backend-selector.js.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs +1 -1
- package/dist/components/features/backends/manage-backends-modal.cjs.map +1 -1
- package/dist/components/features/backends/manage-backends-modal.js +29 -29
- package/dist/components/features/backends/manage-backends-modal.js.map +1 -1
- package/dist/components/features/chat/change-agent-button.cjs +1 -1
- package/dist/components/features/chat/change-agent-button.js +4 -4
- package/dist/components/features/chat/chat-interface.cjs +2 -2
- package/dist/components/features/chat/chat-interface.cjs.map +1 -1
- package/dist/components/features/chat/chat-interface.js +137 -137
- package/dist/components/features/chat/chat-interface.js.map +1 -1
- package/dist/components/features/chat/chat-message.cjs +1 -1
- package/dist/components/features/chat/chat-message.cjs.map +1 -1
- package/dist/components/features/chat/chat-message.d.ts +2 -1
- package/dist/components/features/chat/chat-message.js +88 -79
- package/dist/components/features/chat/chat-message.js.map +1 -1
- package/dist/components/features/chat/components/context-window-meter.cjs +1 -1
- package/dist/components/features/chat/components/context-window-meter.js +4 -4
- package/dist/components/features/chat/confirmation-mode-enabled.cjs +1 -1
- package/dist/components/features/chat/confirmation-mode-enabled.js +4 -4
- package/dist/components/features/chat/generic-event-message.cjs +1 -1
- package/dist/components/features/chat/generic-event-message.cjs.map +1 -1
- package/dist/components/features/chat/generic-event-message.d.ts +2 -1
- package/dist/components/features/chat/generic-event-message.js +41 -22
- package/dist/components/features/chat/generic-event-message.js.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs +1 -1
- package/dist/components/features/chat/interactive-chat-box.cjs.map +1 -1
- package/dist/components/features/chat/interactive-chat-box.js +20 -19
- package/dist/components/features/chat/interactive-chat-box.js.map +1 -1
- package/dist/components/features/conversation/conversation-overview-git-section.cjs +1 -1
- package/dist/components/features/conversation/conversation-overview-git-section.js +4 -4
- package/dist/components/features/conversation/conversation-overview-skills-panel.cjs +1 -1
- package/dist/components/features/conversation/conversation-overview-skills-panel.js +4 -4
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js +77 -78
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs-context-menu.js.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.cjs.map +1 -1
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js +88 -88
- package/dist/components/features/conversation/conversation-tabs/conversation-tabs.js.map +1 -1
- package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs +2 -0
- package/dist/components/features/conversation-panel/advanced-conversation-options-modal.cjs.map +1 -0
- package/dist/components/features/conversation-panel/advanced-conversation-options-modal.d.ts +21 -0
- package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js +239 -0
- package/dist/components/features/conversation-panel/advanced-conversation-options-modal.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-active-tag-filters.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-active-tag-filters.d.ts +28 -0
- package/dist/components/features/conversation-panel/conversation-active-tag-filters.js +69 -0
- package/dist/components/features/conversation-panel/conversation-active-tag-filters.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.d.ts +2 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js +19 -18
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-actions.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.d.ts +2 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js +91 -80
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-context-menu.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card-preview.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card.d.ts +7 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-card.js +87 -81
- package/dist/components/features/conversation-panel/conversation-card/conversation-card.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.d.ts +2 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-chips.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.d.ts +2 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js +2 -1
- package/dist/components/features/conversation-panel/conversation-card/conversation-tag-display.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs +2 -0
- package/dist/components/features/conversation-panel/conversation-layouts-menu.cjs.map +1 -0
- package/dist/components/features/conversation-panel/conversation-layouts-menu.d.ts +29 -0
- package/dist/components/features/conversation-panel/conversation-layouts-menu.js +177 -0
- package/dist/components/features/conversation-panel/conversation-layouts-menu.js.map +1 -0
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.d.ts +37 -0
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js +85 -45
- package/dist/components/features/conversation-panel/conversation-panel-list-helpers.js.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.cjs +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.cjs.map +1 -1
- package/dist/components/features/conversation-panel/conversation-panel.js +296 -290
- package/dist/components/features/conversation-panel/conversation-panel.js.map +1 -1
- package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs +2 -0
- package/dist/components/features/conversation-panel/edit-conversation-tags-modal.cjs.map +1 -0
- package/dist/components/features/conversation-panel/edit-conversation-tags-modal.d.ts +22 -0
- package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js +153 -0
- package/dist/components/features/conversation-panel/edit-conversation-tags-modal.js.map +1 -0
- package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs +2 -0
- package/dist/components/features/conversation-panel/hide-older-conversations-row.cjs.map +1 -0
- package/dist/components/features/conversation-panel/hide-older-conversations-row.d.ts +6 -0
- package/dist/components/features/conversation-panel/hide-older-conversations-row.js +65 -0
- package/dist/components/features/conversation-panel/hide-older-conversations-row.js.map +1 -0
- package/dist/components/features/conversation-panel/menu-row.cjs +1 -1
- package/dist/components/features/conversation-panel/menu-row.cjs.map +1 -1
- package/dist/components/features/conversation-panel/menu-row.d.ts +11 -1
- package/dist/components/features/conversation-panel/menu-row.js +27 -16
- package/dist/components/features/conversation-panel/menu-row.js.map +1 -1
- package/dist/components/features/home/featured-automations/automation-health-indicator.cjs +1 -1
- package/dist/components/features/home/featured-automations/automation-health-indicator.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/automation-health-indicator.js +1 -1
- package/dist/components/features/home/featured-automations/automation-health-indicator.js.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-metrics.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-metrics.d.ts +4 -3
- package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js +22 -25
- package/dist/components/features/home/featured-automations/automation-run-activity-metrics.js.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.d.ts +1 -1
- package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js +15 -15
- package/dist/components/features/home/featured-automations/automation-run-activity-sparkline.js.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-health.cjs +1 -1
- package/dist/components/features/home/featured-automations/automation-run-health.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/automation-run-health.d.ts +5 -3
- package/dist/components/features/home/featured-automations/automation-run-health.js +30 -23
- package/dist/components/features/home/featured-automations/automation-run-health.js.map +1 -1
- package/dist/components/features/home/featured-automations/home-automation-activity.d.ts +3 -2
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.cjs.map +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.d.ts +1 -1
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js +42 -42
- package/dist/components/features/home/featured-automations/home-automation-run-tooltip.js.map +1 -1
- package/dist/components/features/manifest/manifest-form-field.d.ts +3 -1
- package/dist/components/features/manifest/manifest-review-step.d.ts +3 -1
- package/dist/components/features/settings/cloud-settings-link.cjs +1 -1
- package/dist/components/features/settings/cloud-settings-link.cjs.map +1 -1
- package/dist/components/features/settings/cloud-settings-link.js +5 -3
- package/dist/components/features/settings/cloud-settings-link.js.map +1 -1
- package/dist/components/features/settings/integrations-settings-link.cjs +1 -1
- package/dist/components/features/settings/integrations-settings-link.cjs.map +1 -1
- package/dist/components/features/settings/integrations-settings-link.d.ts +3 -1
- package/dist/components/features/settings/integrations-settings-link.js +20 -17
- package/dist/components/features/settings/integrations-settings-link.js.map +1 -1
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.cjs +1 -1
- package/dist/components/features/settings/llm-profiles/llm-settings-local-view.js +1 -1
- package/dist/components/features/settings/llm-profiles/profiles-body.d.ts +2 -2
- package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.cjs.map +1 -1
- package/dist/components/features/settings/sdk-settings/sdk-section-page.d.ts +8 -7
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js +172 -142
- package/dist/components/features/settings/sdk-settings/sdk-section-page.js.map +1 -1
- package/dist/components/features/settings/secrets-settings/secret-form.cjs +1 -1
- package/dist/components/features/settings/secrets-settings/secret-form.cjs.map +1 -1
- package/dist/components/features/settings/secrets-settings/secret-form.js +38 -25
- package/dist/components/features/settings/secrets-settings/secret-form.js.map +1 -1
- package/dist/components/features/settings/settings-dropdown-input.cjs +1 -1
- package/dist/components/features/settings/settings-dropdown-input.js +6 -6
- package/dist/components/features/sidebar/sidebar-rail-body.cjs +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar-rail-body.d.ts +3 -1
- package/dist/components/features/sidebar/sidebar-rail-body.js +156 -139
- package/dist/components/features/sidebar/sidebar-rail-body.js.map +1 -1
- package/dist/components/features/sidebar/sidebar.cjs +1 -1
- package/dist/components/features/sidebar/sidebar.cjs.map +1 -1
- package/dist/components/features/sidebar/sidebar.js +44 -43
- package/dist/components/features/sidebar/sidebar.js.map +1 -1
- package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.cjs +1 -1
- package/dist/components/features/sidebar/use-sidebar-onboarding-checklist.js +3 -3
- package/dist/components/features/skills/extensions-navigation.cjs +1 -1
- package/dist/components/features/skills/extensions-navigation.cjs.map +1 -1
- package/dist/components/features/skills/extensions-navigation.js +3 -3
- package/dist/components/features/skills/extensions-navigation.js.map +1 -1
- package/dist/components/shared/buttons/styled-tooltip.cjs +1 -1
- package/dist/components/shared/buttons/styled-tooltip.cjs.map +1 -1
- package/dist/components/shared/buttons/styled-tooltip.d.ts +2 -1
- package/dist/components/shared/buttons/styled-tooltip.js +2 -1
- package/dist/components/shared/buttons/styled-tooltip.js.map +1 -1
- package/dist/components/shared/filters/enum-filter-dropdown.cjs +1 -1
- package/dist/components/shared/filters/enum-filter-dropdown.cjs.map +1 -1
- package/dist/components/shared/filters/enum-filter-dropdown.d.ts +5 -1
- package/dist/components/shared/filters/enum-filter-dropdown.js +14 -14
- package/dist/components/shared/filters/enum-filter-dropdown.js.map +1 -1
- package/dist/components/shared/modals/confirmation-modal.cjs +1 -1
- package/dist/components/shared/modals/confirmation-modal.cjs.map +1 -1
- package/dist/components/shared/modals/confirmation-modal.d.ts +2 -1
- package/dist/components/shared/modals/confirmation-modal.js +8 -8
- package/dist/components/shared/modals/confirmation-modal.js.map +1 -1
- package/dist/components/shared/modals/settings/model-selector.cjs +1 -1
- package/dist/components/shared/modals/settings/model-selector.js +27 -27
- package/dist/config/defaults.cjs +1 -1
- package/dist/config/defaults.cjs.map +1 -1
- package/dist/config/defaults.js +3 -3
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants/settings-nav.d.ts +8 -0
- package/dist/contexts/conversation-websocket-context.cjs +3 -3
- package/dist/contexts/conversation-websocket-context.cjs.map +1 -1
- package/dist/contexts/conversation-websocket-context.d.ts +5 -0
- package/dist/contexts/conversation-websocket-context.js +194 -198
- package/dist/contexts/conversation-websocket-context.js.map +1 -1
- package/dist/contexts/websocket-provider-wrapper.cjs +1 -1
- package/dist/contexts/websocket-provider-wrapper.cjs.map +1 -1
- package/dist/contexts/websocket-provider-wrapper.js +31 -15
- package/dist/contexts/websocket-provider-wrapper.js.map +1 -1
- package/dist/hooks/chat/record-model-switch-message.cjs +1 -1
- package/dist/hooks/chat/record-model-switch-message.cjs.map +1 -1
- package/dist/hooks/chat/record-model-switch-message.d.ts +31 -0
- package/dist/hooks/chat/record-model-switch-message.js +25 -12
- package/dist/hooks/chat/record-model-switch-message.js.map +1 -1
- package/dist/hooks/chat/use-plan-mode-interceptor.cjs +2 -0
- package/dist/hooks/chat/use-plan-mode-interceptor.cjs.map +1 -0
- package/dist/hooks/chat/use-plan-mode-interceptor.d.ts +16 -0
- package/dist/hooks/chat/use-plan-mode-interceptor.js +43 -0
- package/dist/hooks/chat/use-plan-mode-interceptor.js.map +1 -0
- package/dist/hooks/mutation/use-create-conversation.cjs +1 -1
- package/dist/hooks/mutation/use-create-conversation.cjs.map +1 -1
- package/dist/hooks/mutation/use-create-conversation.js +5 -1
- package/dist/hooks/mutation/use-create-conversation.js.map +1 -1
- package/dist/hooks/mutation/use-read-conversation-file.cjs +1 -1
- package/dist/hooks/mutation/use-read-conversation-file.cjs.map +1 -1
- package/dist/hooks/mutation/use-read-conversation-file.js +11 -4
- package/dist/hooks/mutation/use-read-conversation-file.js.map +1 -1
- package/dist/hooks/mutation/use-save-settings.cjs +1 -1
- package/dist/hooks/mutation/use-save-settings.js +3 -3
- package/dist/hooks/mutation/use-switch-llm-profile.cjs +1 -1
- package/dist/hooks/mutation/use-switch-llm-profile.cjs.map +1 -1
- package/dist/hooks/mutation/use-switch-llm-profile.js +13 -25
- package/dist/hooks/mutation/use-switch-llm-profile.js.map +1 -1
- package/dist/hooks/mutation/use-update-conversation-tags.cjs +2 -0
- package/dist/hooks/mutation/use-update-conversation-tags.cjs.map +1 -0
- package/dist/hooks/mutation/use-update-conversation-tags.d.ts +8 -0
- package/dist/hooks/mutation/use-update-conversation-tags.js +45 -0
- package/dist/hooks/mutation/use-update-conversation-tags.js.map +1 -0
- package/dist/hooks/query/query-keys.cjs +1 -1
- package/dist/hooks/query/query-keys.cjs.map +1 -1
- package/dist/hooks/query/query-keys.d.ts +6 -0
- package/dist/hooks/query/query-keys.js +2 -2
- package/dist/hooks/query/query-keys.js.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs +1 -1
- package/dist/hooks/query/use-automation-sdk-version.cjs.map +1 -1
- package/dist/hooks/query/use-automation-sdk-version.d.ts +0 -1
- package/dist/hooks/query/use-automation-sdk-version.js +30 -55
- package/dist/hooks/query/use-automation-sdk-version.js.map +1 -1
- package/dist/hooks/query/use-conversation-skills.cjs +1 -1
- package/dist/hooks/query/use-conversation-skills.cjs.map +1 -1
- package/dist/hooks/query/use-conversation-skills.d.ts +14 -5
- package/dist/hooks/query/use-conversation-skills.js +20 -4
- package/dist/hooks/query/use-conversation-skills.js.map +1 -1
- package/dist/hooks/query/use-provider-connections.cjs +1 -1
- package/dist/hooks/query/use-provider-connections.cjs.map +1 -1
- package/dist/hooks/query/use-provider-connections.d.ts +6 -3
- package/dist/hooks/query/use-provider-connections.js +7 -3
- package/dist/hooks/query/use-provider-connections.js.map +1 -1
- package/dist/hooks/query/use-sub-conversations.cjs +1 -1
- package/dist/hooks/query/use-sub-conversations.cjs.map +1 -1
- package/dist/hooks/query/use-sub-conversations.js +16 -16
- package/dist/hooks/query/use-sub-conversations.js.map +1 -1
- package/dist/hooks/use-acp-model-context.cjs +1 -1
- package/dist/hooks/use-acp-model-context.js +3 -3
- package/dist/hooks/use-agent-state.cjs +1 -1
- package/dist/hooks/use-agent-state.cjs.map +1 -1
- package/dist/hooks/use-agent-state.d.ts +17 -1
- package/dist/hooks/use-agent-state.js +19 -9
- package/dist/hooks/use-agent-state.js.map +1 -1
- package/dist/hooks/use-automation-permissions.cjs +2 -0
- package/dist/hooks/use-automation-permissions.cjs.map +1 -0
- package/dist/hooks/use-automation-permissions.d.ts +43 -0
- package/dist/hooks/use-automation-permissions.js +52 -0
- package/dist/hooks/use-automation-permissions.js.map +1 -0
- package/dist/hooks/use-chat-input-model-state.cjs +1 -1
- package/dist/hooks/use-chat-input-model-state.js +3 -3
- package/dist/hooks/use-handle-plan-click.cjs +1 -1
- package/dist/hooks/use-handle-plan-click.cjs.map +1 -1
- package/dist/hooks/use-handle-plan-click.d.ts +3 -1
- package/dist/hooks/use-handle-plan-click.js +85 -26
- package/dist/hooks/use-handle-plan-click.js.map +1 -1
- package/dist/hooks/use-home-automation-actions.cjs +1 -1
- package/dist/hooks/use-home-automation-actions.cjs.map +1 -1
- package/dist/hooks/use-home-automation-actions.js +1 -0
- package/dist/hooks/use-home-automation-actions.js.map +1 -1
- package/dist/hooks/use-llm-configured.cjs +1 -1
- package/dist/hooks/use-llm-configured.js +3 -3
- package/dist/hooks/use-manifest-preflight.d.ts +1 -1
- package/dist/hooks/use-unified-websocket-status.cjs +1 -1
- package/dist/hooks/use-unified-websocket-status.cjs.map +1 -1
- package/dist/hooks/use-unified-websocket-status.d.ts +7 -0
- package/dist/hooks/use-unified-websocket-status.js +5 -1
- package/dist/hooks/use-unified-websocket-status.js.map +1 -1
- package/dist/i18n/declaration.cjs +1 -1
- package/dist/i18n/declaration.cjs.map +1 -1
- package/dist/i18n/declaration.d.ts +65 -12
- package/dist/i18n/declaration.js +1 -1
- package/dist/i18n/declaration.js.map +1 -1
- package/dist/i18n/translation.cjs +2 -2
- package/dist/i18n/translation.cjs.map +1 -1
- package/dist/i18n/translation.js +1196 -295
- package/dist/i18n/translation.js.map +1 -1
- package/dist/locales/ar/openhands.json +73 -20
- package/dist/locales/ca/openhands.json +73 -20
- package/dist/locales/de/openhands.json +73 -20
- package/dist/locales/en/openhands.json +73 -20
- package/dist/locales/es/openhands.json +73 -20
- package/dist/locales/fr/openhands.json +73 -20
- package/dist/locales/it/openhands.json +73 -20
- package/dist/locales/ja/openhands.json +73 -20
- package/dist/locales/ko-KR/openhands.json +73 -20
- package/dist/locales/no/openhands.json +73 -20
- package/dist/locales/pt/openhands.json +73 -20
- package/dist/locales/tr/openhands.json +73 -20
- package/dist/locales/uk/openhands.json +73 -20
- package/dist/locales/zh-CN/openhands.json +73 -20
- package/dist/locales/zh-TW/openhands.json +73 -20
- package/dist/manifests/automation-insights.cjs.map +1 -1
- package/dist/manifests/automation-insights.d.ts +10 -2
- package/dist/manifests/automation-insights.js.map +1 -1
- package/dist/manifests/automation-setup.cjs +1 -1
- package/dist/manifests/automation-setup.cjs.map +1 -1
- package/dist/manifests/automation-setup.d.ts +9 -16
- package/dist/manifests/automation-setup.js +17 -7
- package/dist/manifests/automation-setup.js.map +1 -1
- package/dist/manifests/manifest-actions.d.ts +1 -1
- package/dist/manifests/manifest-capabilities.d.ts +3 -1
- package/dist/manifests/manifest-local-validation.cjs +2 -0
- package/dist/manifests/manifest-local-validation.cjs.map +1 -0
- package/dist/manifests/manifest-local-validation.d.ts +15 -11
- package/dist/manifests/manifest-local-validation.js +8 -0
- package/dist/manifests/manifest-local-validation.js.map +1 -0
- package/dist/manifests/manifest-template.cjs +2 -0
- package/dist/manifests/manifest-template.cjs.map +1 -0
- package/dist/manifests/manifest-template.d.ts +4 -4
- package/dist/manifests/manifest-template.js +12 -0
- package/dist/manifests/manifest-template.js.map +1 -0
- package/dist/manifests/manifest-validation.cjs +1 -1
- package/dist/manifests/manifest-validation.cjs.map +1 -1
- package/dist/manifests/manifest-validation.js +106 -28
- package/dist/manifests/manifest-validation.js.map +1 -1
- package/dist/manifests/types.cjs.map +1 -1
- package/dist/manifests/types.d.ts +39 -4
- package/dist/manifests/types.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs +8 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.cjs.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js +221 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/custom-automation/manifest.js.map +1 -0
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-issue-to-pr/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/github-pr-reviewer/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog/qa-changes/manifest.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js +22 -20
- package/dist/node_modules/@openhands/extensions/automations/catalog-index.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/automations/interface.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/automations/interface.js +2 -1
- package/dist/node_modules/@openhands/extensions/automations/interface.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js +24 -5
- package/dist/node_modules/@openhands/extensions/integrations/catalog/gitlab.js.map +1 -1
- package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.cjs +1 -1
- package/dist/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.js +1 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js +21 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle-question-mark.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/shrink.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js +23 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/shrink.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js +43 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/sliders-horizontal.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/tags.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/tags.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/tags.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +4 -4
- package/dist/package.js.map +1 -1
- package/dist/routes/agent-settings.d.ts +2 -0
- package/dist/routes/app-settings.cjs +1 -1
- package/dist/routes/app-settings.js +5 -5
- package/dist/routes/llm-settings.cjs +1 -1
- package/dist/routes/llm-settings.cjs.map +1 -1
- package/dist/routes/llm-settings.d.ts +3 -1
- package/dist/routes/llm-settings.js +88 -87
- package/dist/routes/llm-settings.js.map +1 -1
- package/dist/routes/planner-tab.cjs +1 -1
- package/dist/routes/planner-tab.cjs.map +1 -1
- package/dist/routes/planner-tab.js +44 -28
- package/dist/routes/planner-tab.js.map +1 -1
- package/dist/services/telemetry.cjs +1 -1
- package/dist/services/telemetry.cjs.map +1 -1
- package/dist/services/telemetry.d.ts +5 -0
- package/dist/services/telemetry.js +122 -115
- package/dist/services/telemetry.js.map +1 -1
- package/dist/stores/conversation-panel-preferences-store.cjs +1 -1
- package/dist/stores/conversation-panel-preferences-store.cjs.map +1 -1
- package/dist/stores/conversation-panel-preferences-store.d.ts +32 -5
- package/dist/stores/conversation-panel-preferences-store.js +29 -12
- package/dist/stores/conversation-panel-preferences-store.js.map +1 -1
- package/dist/stores/conversation-state-store.cjs +1 -1
- package/dist/stores/conversation-state-store.cjs.map +1 -1
- package/dist/stores/conversation-state-store.d.ts +9 -3
- package/dist/stores/conversation-state-store.js +6 -3
- package/dist/stores/conversation-state-store.js.map +1 -1
- package/dist/stores/conversation-store.cjs +1 -1
- package/dist/stores/conversation-store.cjs.map +1 -1
- package/dist/stores/conversation-store.d.ts +2 -0
- package/dist/stores/conversation-store.js +3 -0
- package/dist/stores/conversation-store.js.map +1 -1
- package/dist/stores/model-store.cjs +1 -1
- package/dist/stores/model-store.cjs.map +1 -1
- package/dist/stores/model-store.d.ts +7 -0
- package/dist/stores/model-store.js +4 -0
- package/dist/stores/model-store.js.map +1 -1
- package/dist/types/automation.cjs.map +1 -1
- package/dist/types/automation.d.ts +46 -1
- package/dist/types/automation.js.map +1 -1
- package/dist/ui/context-menu.d.ts +1 -1
- package/dist/ui/toggle-switch.cjs +1 -1
- package/dist/ui/toggle-switch.cjs.map +1 -1
- package/dist/ui/toggle-switch.d.ts +4 -1
- package/dist/ui/toggle-switch.js +4 -3
- package/dist/ui/toggle-switch.js.map +1 -1
- package/dist/utils/automation-catalog.cjs +1 -1
- package/dist/utils/automation-catalog.cjs.map +1 -1
- package/dist/utils/automation-catalog.d.ts +12 -1
- package/dist/utils/automation-catalog.js +42 -12
- package/dist/utils/automation-catalog.js.map +1 -1
- package/dist/utils/automation-run-display.cjs +2 -0
- package/dist/utils/automation-run-display.cjs.map +1 -0
- package/dist/utils/automation-run-display.d.ts +20 -0
- package/dist/utils/automation-run-display.js +85 -0
- package/dist/utils/automation-run-display.js.map +1 -0
- package/dist/utils/automation-schedule.cjs +1 -1
- package/dist/utils/automation-schedule.cjs.map +1 -1
- package/dist/utils/automation-schedule.d.ts +16 -0
- package/dist/utils/automation-schedule.js +2 -0
- package/dist/utils/automation-schedule.js.map +1 -1
- package/dist/utils/constants.cjs +1 -1
- package/dist/utils/constants.cjs.map +1 -1
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.js +23 -3
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/format-event-timestamp.cjs +2 -0
- package/dist/utils/format-event-timestamp.cjs.map +1 -0
- package/dist/utils/format-event-timestamp.d.ts +1 -0
- package/dist/utils/format-event-timestamp.js +13 -0
- package/dist/utils/format-event-timestamp.js.map +1 -0
- package/dist/utils/git-diff-stats.cjs +2 -2
- package/dist/utils/git-diff-stats.cjs.map +1 -1
- package/dist/utils/git-diff-stats.d.ts +4 -0
- package/dist/utils/git-diff-stats.js +12 -2
- package/dist/utils/git-diff-stats.js.map +1 -1
- package/dist/utils/plan-file.cjs +4 -0
- package/dist/utils/plan-file.cjs.map +1 -0
- package/dist/utils/plan-file.d.ts +18 -0
- package/dist/utils/plan-file.js +58 -0
- package/dist/utils/plan-file.js.map +1 -0
- package/dist/utils/recommended-automation-rail.cjs +1 -1
- package/dist/utils/recommended-automation-rail.cjs.map +1 -1
- package/dist/utils/recommended-automation-rail.js +1 -0
- package/dist/utils/recommended-automation-rail.js.map +1 -1
- package/dist/utils/scroll-fade-state.cjs +1 -1
- package/dist/utils/scroll-fade-state.cjs.map +1 -1
- package/dist/utils/scroll-fade-state.d.ts +6 -0
- package/dist/utils/scroll-fade-state.js +8 -1
- package/dist/utils/scroll-fade-state.js.map +1 -1
- package/dist/utils/sdk-settings-schema.cjs +1 -1
- package/dist/utils/sdk-settings-schema.cjs.map +1 -1
- package/dist/utils/sdk-settings-schema.d.ts +1 -0
- package/dist/utils/sdk-settings-schema.js +25 -22
- package/dist/utils/sdk-settings-schema.js.map +1 -1
- package/dist/utils/utils.cjs +1 -1
- package/dist/utils/utils.cjs.map +1 -1
- package/dist/utils/utils.js +11 -11
- package/dist/utils/utils.js.map +1 -1
- package/package.json +4 -4
- package/scripts/check-sdk-version-sync.mjs +6 -6
- package/scripts/dev-safe.mjs +1 -1
- package/scripts/dev-with-automation.mjs +1 -1
- package/scripts/static-server.mjs +33 -1
- package/build/assets/active-backend-context-CrHTlgvN.js +0 -2
- package/build/assets/agent-profiles-settings-Dzgb7G9z.js +0 -1
- package/build/assets/agent-server-conversation-service.api-tnqNjbpE.js +0 -86
- package/build/assets/agent-settings-DLtsqaOs.js +0 -2
- package/build/assets/agent-settings-fFvR-XC2.js +0 -1
- package/build/assets/api-key-entry-screen-qTzrmJcr.js +0 -1
- package/build/assets/automation-detail-BmwlCUAB.js +0 -3
- package/build/assets/automation-git-sync-CprN5DcU.js +0 -1
- package/build/assets/automation-setup-route-C40kXjMY.js +0 -1
- package/build/assets/automations-list-DuNcRawl.js +0 -1
- package/build/assets/backend-form-modal-lhGwzXFI.js +0 -1
- package/build/assets/bot-dMYHVfYM.js +0 -1
- package/build/assets/canvas-extensions-8A-XhpgP.js +0 -1
- package/build/assets/check-CS0vmpQQ.js +0 -1
- package/build/assets/chevron-down-e1QBpjVy.js +0 -1
- package/build/assets/chevron-right-ZG4R5G4Q.js +0 -1
- package/build/assets/circle-check-DzWLNsbE.js +0 -1
- package/build/assets/command-menu--UIlGL72.js +0 -1
- package/build/assets/commits-tab-AnZwLvh-.js +0 -1
- package/build/assets/confirmation-modal-Dv1ktp8K.js +0 -1
- package/build/assets/conversation-BbGrAO4Z.js +0 -93
- package/build/assets/conversation-mYT6NAoj.js +0 -1
- package/build/assets/conversation-panel-mYT6NAoj.js +0 -1
- package/build/assets/edit-automation-modal-DadGbJ2u.js +0 -1
- package/build/assets/empty-state-BoGVDecT.js +0 -1
- package/build/assets/enum-filter-dropdown-Bgca129f.js +0 -1
- package/build/assets/extensions-hub-CcDqq_vR.js +0 -1
- package/build/assets/extensions-navigation-Cr4yzYk4.js +0 -1
- package/build/assets/external-link-DKUlnCQV.js +0 -1
- package/build/assets/files-tab-D4o2VyE_.js +0 -1
- package/build/assets/get-git-path-ChKDVHZp.js +0 -1
- package/build/assets/git-repo-dropdown-BkqzkMmM.js +0 -1
- package/build/assets/home-ChpSuepX.js +0 -1
- package/build/assets/home-DIsB440S.js +0 -1
- package/build/assets/home-automation-run-tooltip-BVNDWjAH.js +0 -1
- package/build/assets/home-store-CY9Ej0ux.js +0 -1
- package/build/assets/index-home-BdlrFIif.js +0 -1
- package/build/assets/info-B6RQawoW.js +0 -1
- package/build/assets/install-server-modal-Dpy89p4g.js +0 -1
- package/build/assets/kebab-menu-item-content-D8hSNGmm.js +0 -1
- package/build/assets/list-filter-DsEK7NFC.js +0 -1
- package/build/assets/llm-not-configured-banner-CIFABh3K.js +0 -27
- package/build/assets/llm-settings-B9juXhIa.js +0 -1
- package/build/assets/llm-settings-De1d5dfr.js +0 -1
- package/build/assets/llm-subscription-service-BpJ0ouQo.js +0 -1
- package/build/assets/loader-circle-CC1au6hc.js +0 -1
- package/build/assets/manage-backends-modal-BrPV3oB-.js +0 -1
- package/build/assets/manifest-80fb1c29.js +0 -1
- package/build/assets/markdown-renderer-BzTlxI8x.js +0 -8
- package/build/assets/mcp-page-BEBYqH_K.js +0 -9
- package/build/assets/messages-DKV9cRc2.js +0 -41
- package/build/assets/onboarding-DV_OXoeP.js +0 -1
- package/build/assets/onboarding-modal-rkyBYkeQ.js +0 -1
- package/build/assets/organization-service.api-DrYNkEN_.js +0 -1
- package/build/assets/pencil-47jAZH_V.js +0 -1
- package/build/assets/pin-By41Vl5J.js +0 -1
- package/build/assets/planner-tab-C9uZmhme.js +0 -1
- package/build/assets/plug-CG5HFcNG.js +0 -1
- package/build/assets/plugins-management-service-BMJgC3Ga.js +0 -1
- package/build/assets/plus-C7Slq-0I.js +0 -1
- package/build/assets/profiles-service.api-ChoKrL0l.js +0 -1
- package/build/assets/proxy-9Fe1v5na.js +0 -1
- package/build/assets/recommended-automations-launcher-6ABrI9Cy.js +0 -1
- package/build/assets/refresh-cw-3q3Frrii.js +0 -1
- package/build/assets/root-Dc8YmC9F.js +0 -2
- package/build/assets/root-VDaypvK4.css +0 -1
- package/build/assets/root-layout-CXkhSPYh.js +0 -2
- package/build/assets/schema-field-D-y9-LDb.js +0 -1
- package/build/assets/scroll-fade-state-Dw-i4SGq.js +0 -1
- package/build/assets/sdk-section-page-BlFiizlG.js +0 -1
- package/build/assets/secret-form-BB7the8W.js +0 -1
- package/build/assets/secrets-service-ByZVENbp.js +0 -1
- package/build/assets/settings-C0EWuBtA.js +0 -1
- package/build/assets/settings-index-5w5UW2K3.js +0 -1
- package/build/assets/settings-service.api-DJ1r62Zr.js +0 -1
- package/build/assets/shared-conversation-CA5ISEDy.js +0 -1
- package/build/assets/shield-check-D2aCRd16.js +0 -1
- package/build/assets/sidebar-mobile-menu-toggle-C_fb0Jki.js +0 -1
- package/build/assets/skill-scope-B42H-XOc.js +0 -1
- package/build/assets/skills-plugins-tgF8EiXC.js +0 -1
- package/build/assets/skills-settings-BgJ9PaOe.js +0 -1
- package/build/assets/styled-tooltip-C4jf5Fv9.js +0 -1
- package/build/assets/toggle-switch-ChOLXv2n.js +0 -1
- package/build/assets/trash-2-D7K26eDO.js +0 -1
- package/build/assets/trash-D-HYiVYM.js +0 -1
- package/build/assets/triangle-alert-CtdXWHUI.js +0 -1
- package/build/assets/usage-tab-CVDffLPt.js +0 -1
- package/build/assets/use-acp-credential-form-XIQmpX6M.js +0 -1
- package/build/assets/use-activate-agent-profile-BLfmvDiG.js +0 -1
- package/build/assets/use-agent-profiles-Bd9Bvvp1.js +0 -1
- package/build/assets/use-canvas-extensions-Bi693ujJ.js +0 -1
- package/build/assets/use-config-A9QovgXO.js +0 -1
- package/build/assets/use-create-conversation-Dx3l7mFZ.js +0 -1
- package/build/assets/use-create-secret-B9cUFWRG.js +0 -1
- package/build/assets/use-has-permission-B3C8rQmR.js +0 -1
- package/build/assets/use-is-authed-nTBcM7dE.js +0 -1
- package/build/assets/use-llm-configured-BV9nZ1_j.js +0 -1
- package/build/assets/use-llm-profiles-BO-P4Oyo.js +0 -1
- package/build/assets/use-manifest-capabilities-Cw_flwEz.js +0 -1
- package/build/assets/use-onboarding-completion-D8U7k4Qb.js +0 -1
- package/build/assets/use-pinned-home-route-CckOZrmb.js +0 -1
- package/build/assets/use-plugins-marketplace-7i94Zu3Z.js +0 -1
- package/build/assets/use-save-agent-profile-BUjSsDXK.js +0 -1
- package/build/assets/use-settings-DSXLbvBl.js +0 -1
- package/build/assets/use-settings-nav-items-CwRw-CmX.js +0 -16
- package/build/assets/use-tracking-D53y3TH9.js +0 -3
- package/build/assets/utils-CN5ZfZy1.js +0 -1
- package/build/assets/vendor~entry.client~root~root-layout~index-home~home~conversation-panel~conversation~launch~czjee3a3-DqZDXfg2.js +0 -186
- package/build/assets/vendor~root-layout-C9Ju9DQg.js +0 -1
- package/build/assets/vendor~root-layout~index-home~home~conversation-panel~conversation~mcp~automations-list~aut~ibfbmr9f-cDuKr-WD.js +0 -1
- package/build/assets/vendor~root~root-layout~index-home~home~conversation-panel~conversation~launch~extensions-h~iyia17eu-Chf7vmKB.js +0 -1
- package/build/assets/x-DJdhbdmt.js +0 -1
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs +0 -2
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.cjs.map +0 -1
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.d.ts +0 -35
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js +0 -247
- package/dist/components/features/conversation-panel/conversation-panel-filter-menu.js.map +0 -1
- package/dist/hooks/query/use-skills.cjs +0 -2
- package/dist/hooks/query/use-skills.cjs.map +0 -1
- package/dist/hooks/query/use-skills.d.ts +0 -7
- package/dist/hooks/query/use-skills.js +0 -13
- package/dist/hooks/query/use-skills.js.map +0 -1
- package/dist/hooks/use-has-permission.cjs +0 -2
- package/dist/hooks/use-has-permission.cjs.map +0 -1
- package/dist/hooks/use-has-permission.d.ts +0 -1
- package/dist/hooks/use-has-permission.js +0 -8
- package/dist/hooks/use-has-permission.js.map +0 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs +0 -2
- package/dist/node_modules/lucide-react/dist/esm/icons/eye.cjs.map +0 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/eye.js +0 -14
- package/dist/node_modules/lucide-react/dist/esm/icons/eye.js.map +0 -1
|
@@ -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 { LocalWorkspace } from \"#/types/workspace\";\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 * When set, the collapsed preview is drawn only from these conversation IDs\n * (plus the active conversation when it belongs to the group). Expanding\n * still reveals every loaded conversation in `conversations`.\n */\n discoveryConversationIds?: ReadonlySet<string>;\n}\n\n/**\n * Builds the frozen collapsed-preview pool for a folder.\n *\n * Global \"Load more\" may fetch later pages that add conversations to an\n * already-visible folder; those rows stay out of the collapsed preview so the\n * folder's first impression stays stable until the user expands it.\n */\nfunction resolveCollapsedPreviewPool(\n conversations: readonly AppConversation[],\n discoveryConversationIds: ReadonlySet<string> | undefined,\n activeConversationId: string | null | undefined,\n): AppConversation[] {\n if (!discoveryConversationIds) {\n return [...conversations];\n }\n\n const pool = conversations.filter((conversation) =>\n discoveryConversationIds.has(conversation.id),\n );\n\n // The load-bearing active-conversation guarantee lives in\n // `getGroupDiscoveryConversationIds` (`forceIncludeConversationId`); this\n // fallback only covers callers that pass a discovery set built without it.\n if (\n activeConversationId != null &&\n !pool.some((conversation) => conversation.id === activeConversationId)\n ) {\n const activeConversation = conversations.find(\n (conversation) => conversation.id === activeConversationId,\n );\n if (activeConversation) {\n pool.push(activeConversation);\n }\n }\n\n return pool;\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 const pool = resolveCollapsedPreviewPool(\n conversations,\n options.discoveryConversationIds,\n options.activeConversationId,\n );\n\n let collapsedVisible: AppConversation[];\n if (pool.length <= limit) {\n collapsedVisible = pool;\n } else {\n const activeIndex =\n options.activeConversationId != null\n ? pool.findIndex(\n (conversation) => conversation.id === options.activeConversationId,\n )\n : -1;\n\n if (activeIndex >= limit) {\n collapsedVisible = [...pool.slice(0, limit - 1), pool[activeIndex]];\n } else {\n collapsedVisible = pool.slice(0, limit);\n }\n }\n\n const collapsedHidesSomething =\n collapsedVisible.length < conversations.length;\n\n if (options.expanded) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: true,\n };\n }\n\n return {\n visibleConversations: collapsedVisible,\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: !collapsedHidesSomething,\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\n/**\n * Resolves the stable folder identity used by grouped conversation views.\n *\n * Keeping this shared with `groupConversations` lets pagination reason about\n * folder discovery without duplicating workspace/repository normalization.\n */\nfunction getConversationGroupIdentity(\n conversation: AppConversation,\n backendKind: BackendKind,\n): { id: string; label: string } {\n return backendKind === \"local\"\n ? workspaceGroup(conversation)\n : repositoryGroup(conversation);\n}\n\n/**\n * Max backend pages fetched for a single grouped \"Load more\" click. The\n * driver walks past pages that only deepen already-visible folders looking\n * for a new folder, and this cap prevents one click from walking the entire\n * remaining cursor when no undiscovered folder exists. Chronological mode is\n * not capped — it keeps its pre-existing fetch-until-visible behavior.\n */\nexport const MAX_PAGES_PER_LOAD_MORE_CLICK = 3;\n\n/**\n * Conversation IDs that belong on each folder's discovery page — the first\n * backend page where that folder appeared.\n *\n * Global \"Load more\" still discovers folders from later pages, but the\n * collapsed preview for an already-visible folder stays frozen to this set.\n * Expanding the folder reads the full grouped `conversations` array instead.\n * `forceIncludeConversationId` keeps the active thread in the preview even\n * when it landed on a non-discovery page.\n */\nexport function getGroupDiscoveryConversationIds(\n items: readonly AppConversation[],\n pageByConversationId: ReadonlyMap<string, number>,\n backendKind: BackendKind,\n options?: { forceIncludeConversationId?: string | null },\n): Set<string> {\n // Resolve each conversation's folder identity exactly once; both passes\n // below (finding each folder's discovery page, then collecting the ids on\n // that page) read from this record instead of re-running the\n // workspace/repository normalization.\n const resolved = items.map((conversation) => ({\n conversationId: conversation.id,\n groupId: getConversationGroupIdentity(conversation, backendKind).id,\n page: pageByConversationId.get(conversation.id) ?? 0,\n }));\n\n const discoveryPageByGroupId = new Map<string, number>();\n for (const { groupId, page } of resolved) {\n const currentDiscoveryPage = discoveryPageByGroupId.get(groupId);\n if (currentDiscoveryPage === undefined || page < currentDiscoveryPage) {\n discoveryPageByGroupId.set(groupId, page);\n }\n }\n\n const discoveryIds = new Set<string>();\n for (const { conversationId, groupId, page } of resolved) {\n if (page === discoveryPageByGroupId.get(groupId)) {\n discoveryIds.add(conversationId);\n }\n }\n\n const forceIncludeId = options?.forceIncludeConversationId;\n if (\n forceIncludeId != null &&\n items.some((conversation) => conversation.id === forceIncludeId)\n ) {\n discoveryIds.add(forceIncludeId);\n }\n\n return discoveryIds;\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n knownWorkspaces?: readonly LocalWorkspace[],\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 if (backendKind === \"local\" && knownWorkspaces) {\n for (const ws of knownWorkspaces) {\n const normalized = ws.path.trim().replace(/\\/+$/, \"\");\n if (normalized) {\n byId.set(`ws:${normalized}`, { label: ws.name, conversations: [] });\n }\n }\n }\n\n for (const c of items) {\n const { id, label: rawLabel } = getConversationGroupIdentity(\n c,\n backendKind,\n );\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 { LocalWorkspace } from \"#/types/workspace\";\nimport type { Provider } from \"#/types/settings\";\nimport {\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_TAG_KEYS,\n getDisplayConversationTags,\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\";\nexport type OlderConversationCutoff = \"1h\" | \"1d\" | \"7d\" | \"30d\";\n\nexport const OLDER_CONVERSATION_CUTOFFS = [\n \"1h\",\n \"1d\",\n \"7d\",\n \"30d\",\n] as const satisfies readonly OlderConversationCutoff[];\n\nexport const DEFAULT_OLDER_CONVERSATION_CUTOFF: OlderConversationCutoff = \"7d\";\n\nexport const OLDER_CONVERSATION_CUTOFF_MS: Record<\n OlderConversationCutoff,\n number\n> = {\n \"1h\": 60 * 60 * 1000,\n \"1d\": 24 * 60 * 60 * 1000,\n \"7d\": 7 * 24 * 60 * 60 * 1000,\n \"30d\": 30 * 24 * 60 * 60 * 1000,\n};\n\nexport function isOlderConversationCutoff(\n value: unknown,\n): value is OlderConversationCutoff {\n return (\n typeof value === \"string\" &&\n (OLDER_CONVERSATION_CUTOFFS as readonly string[]).includes(value)\n );\n}\n\n/**\n * Splits conversations by last update relative to `nowMs`. Missing or\n * unparseable timestamps stay in `recent` so they are never hidden by the\n * hide-older toggle.\n */\nexport function partitionByCutoff<T extends { updated_at: string }>(\n items: readonly T[],\n cutoffMs: number,\n nowMs: number = Date.now(),\n): { recent: T[]; older: T[] } {\n const cutoff = nowMs - cutoffMs;\n const recent: T[] = [];\n const older: T[] = [];\n for (const item of items) {\n const updatedAt = item.updated_at ? Date.parse(item.updated_at) : NaN;\n if (Number.isFinite(updatedAt) && updatedAt < cutoff) {\n older.push(item);\n } else {\n recent.push(item);\n }\n }\n return { recent, older };\n}\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 * When set, the collapsed preview is drawn only from these conversation IDs\n * (plus the active conversation when it belongs to the group). Expanding\n * still reveals every loaded conversation in `conversations`.\n */\n discoveryConversationIds?: ReadonlySet<string>;\n}\n\n/**\n * Builds the frozen collapsed-preview pool for a folder.\n *\n * Global \"Load more\" may fetch later pages that add conversations to an\n * already-visible folder; those rows stay out of the collapsed preview so the\n * folder's first impression stays stable until the user expands it.\n */\nfunction resolveCollapsedPreviewPool(\n conversations: readonly AppConversation[],\n discoveryConversationIds: ReadonlySet<string> | undefined,\n activeConversationId: string | null | undefined,\n): AppConversation[] {\n if (!discoveryConversationIds) {\n return [...conversations];\n }\n\n const pool = conversations.filter((conversation) =>\n discoveryConversationIds.has(conversation.id),\n );\n\n // The load-bearing active-conversation guarantee lives in\n // `getGroupDiscoveryConversationIds` (`forceIncludeConversationId`); this\n // fallback only covers callers that pass a discovery set built without it.\n if (\n activeConversationId != null &&\n !pool.some((conversation) => conversation.id === activeConversationId)\n ) {\n const activeConversation = conversations.find(\n (conversation) => conversation.id === activeConversationId,\n );\n if (activeConversation) {\n pool.push(activeConversation);\n }\n }\n\n return pool;\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 const pool = resolveCollapsedPreviewPool(\n conversations,\n options.discoveryConversationIds,\n options.activeConversationId,\n );\n\n let collapsedVisible: AppConversation[];\n if (pool.length <= limit) {\n collapsedVisible = pool;\n } else {\n const activeIndex =\n options.activeConversationId != null\n ? pool.findIndex(\n (conversation) => conversation.id === options.activeConversationId,\n )\n : -1;\n\n if (activeIndex >= limit) {\n collapsedVisible = [...pool.slice(0, limit - 1), pool[activeIndex]];\n } else {\n collapsedVisible = pool.slice(0, limit);\n }\n }\n\n const collapsedHidesSomething =\n collapsedVisible.length < conversations.length;\n\n if (options.expanded) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: true,\n };\n }\n\n return {\n visibleConversations: collapsedVisible,\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: !collapsedHidesSomething,\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/**\n * Distinct user-facing `key=value` facets among the given conversations,\n * sorted A–Z for stable menu order. Reserved/internal tag keys are excluded\n * via `getDisplayConversationTags`; unlike the automation filter there is no\n * unnamed bucket — a conversation with no user tags simply yields no facet.\n */\nexport function collectTagFacets(\n conversations: readonly AppConversation[],\n): string[] {\n const facets = new Set<string>();\n for (const conversation of conversations) {\n for (const [key, value] of getDisplayConversationTags(conversation.tags)) {\n facets.add(`${key}=${value}`);\n }\n }\n return [...facets].sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Display form of a stored facet: a bare tag (empty value, stored as `key=`)\n * renders as just the key. Matching keeps the raw `key=value` form — this is\n * label-only.\n */\nexport function formatTagFacetLabel(facet: string): string {\n return facet.endsWith(\"=\") ? facet.slice(0, -1) : facet;\n}\n\n/**\n * Union semantics: a conversation matches when it carries ANY selected\n * facet, mirroring the automation multi-select. An empty selection — or one\n * that no longer intersects the available facets (tags edited away, stale\n * selections persisted from another backend) — leaves the list unfiltered\n * instead of yielding an unfillable empty list.\n */\nexport function applyTagConversationFilter(\n conversations: readonly AppConversation[],\n selectedFacets: readonly string[],\n availableFacets: readonly string[],\n): AppConversation[] {\n const facetSet = new Set(availableFacets);\n const effectiveFacets = selectedFacets.filter((facet) => facetSet.has(facet));\n if (effectiveFacets.length === 0) {\n return [...conversations];\n }\n const narrowing = new Set(effectiveFacets);\n return conversations.filter((conversation) =>\n getDisplayConversationTags(conversation.tags).some(([key, value]) =>\n narrowing.has(`${key}=${value}`),\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\n/**\n * Resolves the stable folder identity used by grouped conversation views.\n *\n * Keeping this shared with `groupConversations` lets pagination reason about\n * folder discovery without duplicating workspace/repository normalization.\n */\nfunction getConversationGroupIdentity(\n conversation: AppConversation,\n backendKind: BackendKind,\n): { id: string; label: string } {\n return backendKind === \"local\"\n ? workspaceGroup(conversation)\n : repositoryGroup(conversation);\n}\n\n/**\n * Max backend pages fetched for a single grouped \"Load more\" click. The\n * driver walks past pages that only deepen already-visible folders looking\n * for a new folder, and this cap prevents one click from walking the entire\n * remaining cursor when no undiscovered folder exists. Chronological mode is\n * not capped — it keeps its pre-existing fetch-until-visible behavior.\n */\nexport const MAX_PAGES_PER_LOAD_MORE_CLICK = 3;\n\n/**\n * Conversation IDs that belong on each folder's discovery page — the first\n * backend page where that folder appeared.\n *\n * Global \"Load more\" still discovers folders from later pages, but the\n * collapsed preview for an already-visible folder stays frozen to this set.\n * Expanding the folder reads the full grouped `conversations` array instead.\n * `forceIncludeConversationId` keeps the active thread in the preview even\n * when it landed on a non-discovery page.\n */\nexport function getGroupDiscoveryConversationIds(\n items: readonly AppConversation[],\n pageByConversationId: ReadonlyMap<string, number>,\n backendKind: BackendKind,\n options?: { forceIncludeConversationId?: string | null },\n): Set<string> {\n // Resolve each conversation's folder identity exactly once; both passes\n // below (finding each folder's discovery page, then collecting the ids on\n // that page) read from this record instead of re-running the\n // workspace/repository normalization.\n const resolved = items.map((conversation) => ({\n conversationId: conversation.id,\n groupId: getConversationGroupIdentity(conversation, backendKind).id,\n page: pageByConversationId.get(conversation.id) ?? 0,\n }));\n\n const discoveryPageByGroupId = new Map<string, number>();\n for (const { groupId, page } of resolved) {\n const currentDiscoveryPage = discoveryPageByGroupId.get(groupId);\n if (currentDiscoveryPage === undefined || page < currentDiscoveryPage) {\n discoveryPageByGroupId.set(groupId, page);\n }\n }\n\n const discoveryIds = new Set<string>();\n for (const { conversationId, groupId, page } of resolved) {\n if (page === discoveryPageByGroupId.get(groupId)) {\n discoveryIds.add(conversationId);\n }\n }\n\n const forceIncludeId = options?.forceIncludeConversationId;\n if (\n forceIncludeId != null &&\n items.some((conversation) => conversation.id === forceIncludeId)\n ) {\n discoveryIds.add(forceIncludeId);\n }\n\n return discoveryIds;\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n knownWorkspaces?: readonly LocalWorkspace[],\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 if (backendKind === \"local\" && knownWorkspaces) {\n for (const ws of knownWorkspaces) {\n const normalized = ws.path.trim().replace(/\\/+$/, \"\");\n if (normalized) {\n byId.set(`ws:${normalized}`, { label: ws.name, conversations: [] });\n }\n }\n }\n\n for (const c of items) {\n const { id, label: rawLabel } = getConversationGroupIdentity(\n c,\n backendKind,\n );\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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"}
|
|
@@ -6,6 +6,22 @@ export type ConversationSortField = "created" | "updated";
|
|
|
6
6
|
export type ThreadScope = "all" | "relevant";
|
|
7
7
|
export type OrganizeMode = "grouped" | "chronological";
|
|
8
8
|
export type AutomationFilterMode = "all" | "hide-automations" | "only-automations";
|
|
9
|
+
export type OlderConversationCutoff = "1h" | "1d" | "7d" | "30d";
|
|
10
|
+
export declare const OLDER_CONVERSATION_CUTOFFS: readonly ["1h", "1d", "7d", "30d"];
|
|
11
|
+
export declare const DEFAULT_OLDER_CONVERSATION_CUTOFF: OlderConversationCutoff;
|
|
12
|
+
export declare const OLDER_CONVERSATION_CUTOFF_MS: Record<OlderConversationCutoff, number>;
|
|
13
|
+
export declare function isOlderConversationCutoff(value: unknown): value is OlderConversationCutoff;
|
|
14
|
+
/**
|
|
15
|
+
* Splits conversations by last update relative to `nowMs`. Missing or
|
|
16
|
+
* unparseable timestamps stay in `recent` so they are never hidden by the
|
|
17
|
+
* hide-older toggle.
|
|
18
|
+
*/
|
|
19
|
+
export declare function partitionByCutoff<T extends {
|
|
20
|
+
updated_at: string;
|
|
21
|
+
}>(items: readonly T[], cutoffMs: number, nowMs?: number): {
|
|
22
|
+
recent: T[];
|
|
23
|
+
older: T[];
|
|
24
|
+
};
|
|
9
25
|
/** Max conversations shown under a workspace/repo folder before "View more". */
|
|
10
26
|
export declare const GROUP_CONVERSATIONS_PREVIEW_LIMIT = 5;
|
|
11
27
|
interface GroupConversationPreviewOptions {
|
|
@@ -45,6 +61,27 @@ export declare function getAutomationNameFacet(conversation: AppConversation): s
|
|
|
45
61
|
*/
|
|
46
62
|
export declare function collectAutomationNameFacets(conversations: readonly AppConversation[]): string[];
|
|
47
63
|
export declare function applyAutomationConversationFilter(conversations: readonly AppConversation[], mode: AutomationFilterMode, selectedNames: readonly string[], availableFacets: readonly string[]): AppConversation[];
|
|
64
|
+
/**
|
|
65
|
+
* Distinct user-facing `key=value` facets among the given conversations,
|
|
66
|
+
* sorted A–Z for stable menu order. Reserved/internal tag keys are excluded
|
|
67
|
+
* via `getDisplayConversationTags`; unlike the automation filter there is no
|
|
68
|
+
* unnamed bucket — a conversation with no user tags simply yields no facet.
|
|
69
|
+
*/
|
|
70
|
+
export declare function collectTagFacets(conversations: readonly AppConversation[]): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Display form of a stored facet: a bare tag (empty value, stored as `key=`)
|
|
73
|
+
* renders as just the key. Matching keeps the raw `key=value` form — this is
|
|
74
|
+
* label-only.
|
|
75
|
+
*/
|
|
76
|
+
export declare function formatTagFacetLabel(facet: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Union semantics: a conversation matches when it carries ANY selected
|
|
79
|
+
* facet, mirroring the automation multi-select. An empty selection — or one
|
|
80
|
+
* that no longer intersects the available facets (tags edited away, stale
|
|
81
|
+
* selections persisted from another backend) — leaves the list unfiltered
|
|
82
|
+
* instead of yielding an unfillable empty list.
|
|
83
|
+
*/
|
|
84
|
+
export declare function applyTagConversationFilter(conversations: readonly AppConversation[], selectedFacets: readonly string[], availableFacets: readonly string[]): AppConversation[];
|
|
48
85
|
/** Subset of `useCreateConversation` variables for launching from a group row */
|
|
49
86
|
export type ConversationGroupLaunch = {
|
|
50
87
|
workingDir?: string;
|
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
import { AUTOMATION_TAG_KEYS as e } from "../../../api/agent-server-adapter.js";
|
|
2
|
-
|
|
1
|
+
import { AUTOMATION_TAG_KEYS as e, getDisplayConversationTags as t } from "../../../api/agent-server-adapter.js";
|
|
2
|
+
//#region src/components/features/conversation-panel/conversation-panel-list-helpers.ts
|
|
3
|
+
var n = [
|
|
4
|
+
"1h",
|
|
5
|
+
"1d",
|
|
6
|
+
"7d",
|
|
7
|
+
"30d"
|
|
8
|
+
], r = {
|
|
9
|
+
"1h": 3600 * 1e3,
|
|
10
|
+
"1d": 1440 * 60 * 1e3,
|
|
11
|
+
"7d": 10080 * 60 * 1e3,
|
|
12
|
+
"30d": 720 * 60 * 60 * 1e3
|
|
13
|
+
};
|
|
14
|
+
function i(e) {
|
|
15
|
+
return typeof e == "string" && n.includes(e);
|
|
16
|
+
}
|
|
17
|
+
function a(e, t, n = Date.now()) {
|
|
18
|
+
let r = n - t, i = [], a = [];
|
|
19
|
+
for (let t of e) {
|
|
20
|
+
let e = t.updated_at ? Date.parse(t.updated_at) : NaN;
|
|
21
|
+
Number.isFinite(e) && e < r ? a.push(t) : i.push(t);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
recent: i,
|
|
25
|
+
older: a
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function o(e, t, n) {
|
|
3
29
|
if (!t) return [...e];
|
|
4
30
|
let r = e.filter((e) => t.has(e.id));
|
|
5
31
|
if (n != null && !r.some((e) => e.id === n)) {
|
|
@@ -8,59 +34,73 @@ function t(e, t, n) {
|
|
|
8
34
|
}
|
|
9
35
|
return r;
|
|
10
36
|
}
|
|
11
|
-
function
|
|
12
|
-
let
|
|
13
|
-
if (
|
|
37
|
+
function s(e, t) {
|
|
38
|
+
let n = t.limit ?? 5, r = o(e, t.discoveryConversationIds, t.activeConversationId), i;
|
|
39
|
+
if (r.length <= n) i = r;
|
|
14
40
|
else {
|
|
15
|
-
let e =
|
|
16
|
-
|
|
41
|
+
let e = t.activeConversationId == null ? -1 : r.findIndex((e) => e.id === t.activeConversationId);
|
|
42
|
+
i = e >= n ? [...r.slice(0, n - 1), r[e]] : r.slice(0, n);
|
|
17
43
|
}
|
|
18
|
-
let
|
|
19
|
-
return
|
|
44
|
+
let a = i.length < e.length;
|
|
45
|
+
return t.expanded ? {
|
|
20
46
|
visibleConversations: [...e],
|
|
21
|
-
isPreviewTruncated:
|
|
47
|
+
isPreviewTruncated: a,
|
|
22
48
|
isShowingAll: !0
|
|
23
49
|
} : {
|
|
24
|
-
visibleConversations:
|
|
25
|
-
isPreviewTruncated:
|
|
26
|
-
isShowingAll: !
|
|
50
|
+
visibleConversations: i,
|
|
51
|
+
isPreviewTruncated: a,
|
|
52
|
+
isShowingAll: !a
|
|
27
53
|
};
|
|
28
54
|
}
|
|
29
|
-
function
|
|
55
|
+
function c(e, t) {
|
|
30
56
|
let n = new Map(t.map((e) => [e.id, e]));
|
|
31
57
|
return e.map((e) => n.get(e)).filter((e) => e != null);
|
|
32
58
|
}
|
|
33
|
-
function
|
|
59
|
+
function l(e, t) {
|
|
34
60
|
if (t.length === 0) return [...e];
|
|
35
61
|
let n = new Set(t);
|
|
36
62
|
return e.filter((e) => !n.has(e.id));
|
|
37
63
|
}
|
|
38
|
-
var
|
|
39
|
-
function
|
|
64
|
+
var u = "__unnamed__";
|
|
65
|
+
function d(t) {
|
|
40
66
|
if (t.trigger === "automation") return !0;
|
|
41
67
|
let n = t.tags;
|
|
42
68
|
return n ? e.some((e) => !!n[e]) : !1;
|
|
43
69
|
}
|
|
44
|
-
function
|
|
70
|
+
function f(e) {
|
|
45
71
|
return e.tags?.automationname?.trim() || "__unnamed__";
|
|
46
72
|
}
|
|
47
|
-
function
|
|
73
|
+
function p(e) {
|
|
48
74
|
let t = /* @__PURE__ */ new Set(), n = !1;
|
|
49
75
|
for (let r of e) {
|
|
50
|
-
if (!
|
|
51
|
-
let e =
|
|
76
|
+
if (!d(r)) continue;
|
|
77
|
+
let e = f(r);
|
|
52
78
|
e === "__unnamed__" ? n = !0 : t.add(e);
|
|
53
79
|
}
|
|
54
80
|
let r = [...t].sort((e, t) => e.localeCompare(t));
|
|
55
|
-
return n && r.push(
|
|
81
|
+
return n && r.push(u), r;
|
|
56
82
|
}
|
|
57
|
-
function
|
|
83
|
+
function m(e, t, n, r) {
|
|
58
84
|
if (t === "all") return [...e];
|
|
59
|
-
if (t === "hide-automations") return e.filter((e) => !
|
|
60
|
-
let i = new Set(r), a = n.filter((e) => i.has(e)),
|
|
61
|
-
return e.filter((e) =>
|
|
85
|
+
if (t === "hide-automations") return e.filter((e) => !d(e));
|
|
86
|
+
let i = new Set(r), a = n.filter((e) => i.has(e)), o = a.length > 0 ? new Set(a) : null;
|
|
87
|
+
return e.filter((e) => d(e) ? o === null || o.has(f(e)) : !1);
|
|
62
88
|
}
|
|
63
|
-
function
|
|
89
|
+
function h(e) {
|
|
90
|
+
let n = /* @__PURE__ */ new Set();
|
|
91
|
+
for (let r of e) for (let [e, i] of t(r.tags)) n.add(`${e}=${i}`);
|
|
92
|
+
return [...n].sort((e, t) => e.localeCompare(t));
|
|
93
|
+
}
|
|
94
|
+
function g(e) {
|
|
95
|
+
return e.endsWith("=") ? e.slice(0, -1) : e;
|
|
96
|
+
}
|
|
97
|
+
function _(e, n, r) {
|
|
98
|
+
let i = new Set(r), a = n.filter((e) => i.has(e));
|
|
99
|
+
if (a.length === 0) return [...e];
|
|
100
|
+
let o = new Set(a);
|
|
101
|
+
return e.filter((e) => t(e.tags).some(([e, t]) => o.has(`${e}=${t}`)));
|
|
102
|
+
}
|
|
103
|
+
function v(e, t, n) {
|
|
64
104
|
if (t === "local") return e === "__none_workspace" ? {} : e.startsWith("ws:") ? { workingDir: e.slice(3) } : {};
|
|
65
105
|
if (e === "__none_repo") return {};
|
|
66
106
|
if (e.startsWith("repo:")) {
|
|
@@ -73,16 +113,16 @@ function u(e, t, n) {
|
|
|
73
113
|
}
|
|
74
114
|
return {};
|
|
75
115
|
}
|
|
76
|
-
function
|
|
116
|
+
function y(e) {
|
|
77
117
|
if (!e) return 0;
|
|
78
118
|
let t = Date.parse(e);
|
|
79
119
|
return Number.isFinite(t) ? t : 0;
|
|
80
120
|
}
|
|
81
|
-
function
|
|
121
|
+
function b(e, t) {
|
|
82
122
|
let n = t === "created" ? "created_at" : "updated_at";
|
|
83
|
-
return [...e].sort((e, t) =>
|
|
123
|
+
return [...e].sort((e, t) => y(t[n]) - y(e[n]));
|
|
84
124
|
}
|
|
85
|
-
function
|
|
125
|
+
function x(e) {
|
|
86
126
|
let t = e.selected_workspace?.trim().replace(/\/+$/, "");
|
|
87
127
|
if (!t) return {
|
|
88
128
|
id: "__none_workspace",
|
|
@@ -94,7 +134,7 @@ function p(e) {
|
|
|
94
134
|
label: n
|
|
95
135
|
};
|
|
96
136
|
}
|
|
97
|
-
function
|
|
137
|
+
function S(e) {
|
|
98
138
|
let t = e.selected_repository?.trim().replace(/\/+$/, "");
|
|
99
139
|
if (!t) return {
|
|
100
140
|
id: "__none_repo",
|
|
@@ -106,13 +146,13 @@ function m(e) {
|
|
|
106
146
|
label: r
|
|
107
147
|
};
|
|
108
148
|
}
|
|
109
|
-
function
|
|
110
|
-
return t === "local" ?
|
|
149
|
+
function C(e, t) {
|
|
150
|
+
return t === "local" ? x(e) : S(e);
|
|
111
151
|
}
|
|
112
|
-
function
|
|
152
|
+
function w(e, t, n, r) {
|
|
113
153
|
let i = e.map((e) => ({
|
|
114
154
|
conversationId: e.id,
|
|
115
|
-
groupId:
|
|
155
|
+
groupId: C(e, n).id,
|
|
116
156
|
page: t.get(e.id) ?? 0
|
|
117
157
|
})), a = /* @__PURE__ */ new Map();
|
|
118
158
|
for (let { groupId: e, page: t } of i) {
|
|
@@ -124,7 +164,7 @@ function g(e, t, n, r) {
|
|
|
124
164
|
let s = r?.forceIncludeConversationId;
|
|
125
165
|
return s != null && e.some((e) => e.id === s) && o.add(s), o;
|
|
126
166
|
}
|
|
127
|
-
function
|
|
167
|
+
function T(e, t, n, r, i) {
|
|
128
168
|
let a = /* @__PURE__ */ new Map();
|
|
129
169
|
if (t === "local" && i) for (let e of i) {
|
|
130
170
|
let t = e.path.trim().replace(/\/+$/, "");
|
|
@@ -134,24 +174,24 @@ function _(e, t, n, r, i) {
|
|
|
134
174
|
});
|
|
135
175
|
}
|
|
136
176
|
for (let n of e) {
|
|
137
|
-
let { id: e, label: i } =
|
|
177
|
+
let { id: e, label: i } = C(n, t), o = e === "__none_workspace" ? r.emptyWorkspace : e === "__none_repo" ? r.emptyRepository : i, s = a.get(e);
|
|
138
178
|
s ? s.conversations.push(n) : a.set(e, {
|
|
139
179
|
label: o,
|
|
140
180
|
conversations: [n]
|
|
141
181
|
});
|
|
142
182
|
}
|
|
143
183
|
let o = [...a.entries()].map(([e, r]) => {
|
|
144
|
-
let i =
|
|
184
|
+
let i = b(r.conversations, n);
|
|
145
185
|
return {
|
|
146
186
|
id: e,
|
|
147
187
|
label: r.label,
|
|
148
188
|
conversations: i,
|
|
149
|
-
launch:
|
|
189
|
+
launch: v(e, t, i)
|
|
150
190
|
};
|
|
151
|
-
}), s = (e) => e.conversations.reduce((e, t) => Math.max(e,
|
|
191
|
+
}), s = (e) => e.conversations.reduce((e, t) => Math.max(e, y(n === "created" ? t.created_at : t.updated_at)), 0);
|
|
152
192
|
return o.sort((e, t) => s(t) - s(e)), o;
|
|
153
193
|
}
|
|
154
|
-
function
|
|
194
|
+
function E(e, t) {
|
|
155
195
|
if (t.length === 0) return [...e];
|
|
156
196
|
let n = new Map(e.map((e) => [e.id, e])), r = [], i = /* @__PURE__ */ new Set();
|
|
157
197
|
for (let e of t) {
|
|
@@ -161,9 +201,9 @@ function v(e, t) {
|
|
|
161
201
|
for (let t of e) i.has(t.id) || r.push(t);
|
|
162
202
|
return r;
|
|
163
203
|
}
|
|
164
|
-
function
|
|
204
|
+
function D(e, t, n, r, i = "after") {
|
|
165
205
|
if (n === r) return [...e];
|
|
166
|
-
let a =
|
|
206
|
+
let a = E(t.map((e) => ({ id: e })), e).map((e) => e.id), o = a.indexOf(n), s = a.indexOf(r);
|
|
167
207
|
if (o < 0 || s < 0) return [...e];
|
|
168
208
|
let c = [...a];
|
|
169
209
|
c.splice(o, 1);
|
|
@@ -171,6 +211,6 @@ function y(e, t, n, r, i = "after") {
|
|
|
171
211
|
return c.splice(u, 0, n), c;
|
|
172
212
|
}
|
|
173
213
|
//#endregion
|
|
174
|
-
export {
|
|
214
|
+
export { n as OLDER_CONVERSATION_CUTOFFS, r as OLDER_CONVERSATION_CUTOFF_MS, u as UNNAMED_AUTOMATION_FACET, m as applyAutomationConversationFilter, E as applyGroupFolderOrder, _ as applyTagConversationFilter, p as collectAutomationNameFacets, h as collectTagFacets, l as filterOutPinnedConversations, g as formatTagFacetLabel, s as getGroupConversationPreview, w as getGroupDiscoveryConversationIds, T as groupConversations, i as isOlderConversationCutoff, D as moveGroupFolderOrder, a as partitionByCutoff, c as resolvePinnedConversations, b as sortConversationsByField };
|
|
175
215
|
|
|
176
216
|
//# 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 { LocalWorkspace } from \"#/types/workspace\";\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 * When set, the collapsed preview is drawn only from these conversation IDs\n * (plus the active conversation when it belongs to the group). Expanding\n * still reveals every loaded conversation in `conversations`.\n */\n discoveryConversationIds?: ReadonlySet<string>;\n}\n\n/**\n * Builds the frozen collapsed-preview pool for a folder.\n *\n * Global \"Load more\" may fetch later pages that add conversations to an\n * already-visible folder; those rows stay out of the collapsed preview so the\n * folder's first impression stays stable until the user expands it.\n */\nfunction resolveCollapsedPreviewPool(\n conversations: readonly AppConversation[],\n discoveryConversationIds: ReadonlySet<string> | undefined,\n activeConversationId: string | null | undefined,\n): AppConversation[] {\n if (!discoveryConversationIds) {\n return [...conversations];\n }\n\n const pool = conversations.filter((conversation) =>\n discoveryConversationIds.has(conversation.id),\n );\n\n // The load-bearing active-conversation guarantee lives in\n // `getGroupDiscoveryConversationIds` (`forceIncludeConversationId`); this\n // fallback only covers callers that pass a discovery set built without it.\n if (\n activeConversationId != null &&\n !pool.some((conversation) => conversation.id === activeConversationId)\n ) {\n const activeConversation = conversations.find(\n (conversation) => conversation.id === activeConversationId,\n );\n if (activeConversation) {\n pool.push(activeConversation);\n }\n }\n\n return pool;\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 const pool = resolveCollapsedPreviewPool(\n conversations,\n options.discoveryConversationIds,\n options.activeConversationId,\n );\n\n let collapsedVisible: AppConversation[];\n if (pool.length <= limit) {\n collapsedVisible = pool;\n } else {\n const activeIndex =\n options.activeConversationId != null\n ? pool.findIndex(\n (conversation) => conversation.id === options.activeConversationId,\n )\n : -1;\n\n if (activeIndex >= limit) {\n collapsedVisible = [...pool.slice(0, limit - 1), pool[activeIndex]];\n } else {\n collapsedVisible = pool.slice(0, limit);\n }\n }\n\n const collapsedHidesSomething =\n collapsedVisible.length < conversations.length;\n\n if (options.expanded) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: true,\n };\n }\n\n return {\n visibleConversations: collapsedVisible,\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: !collapsedHidesSomething,\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\n/**\n * Resolves the stable folder identity used by grouped conversation views.\n *\n * Keeping this shared with `groupConversations` lets pagination reason about\n * folder discovery without duplicating workspace/repository normalization.\n */\nfunction getConversationGroupIdentity(\n conversation: AppConversation,\n backendKind: BackendKind,\n): { id: string; label: string } {\n return backendKind === \"local\"\n ? workspaceGroup(conversation)\n : repositoryGroup(conversation);\n}\n\n/**\n * Max backend pages fetched for a single grouped \"Load more\" click. The\n * driver walks past pages that only deepen already-visible folders looking\n * for a new folder, and this cap prevents one click from walking the entire\n * remaining cursor when no undiscovered folder exists. Chronological mode is\n * not capped — it keeps its pre-existing fetch-until-visible behavior.\n */\nexport const MAX_PAGES_PER_LOAD_MORE_CLICK = 3;\n\n/**\n * Conversation IDs that belong on each folder's discovery page — the first\n * backend page where that folder appeared.\n *\n * Global \"Load more\" still discovers folders from later pages, but the\n * collapsed preview for an already-visible folder stays frozen to this set.\n * Expanding the folder reads the full grouped `conversations` array instead.\n * `forceIncludeConversationId` keeps the active thread in the preview even\n * when it landed on a non-discovery page.\n */\nexport function getGroupDiscoveryConversationIds(\n items: readonly AppConversation[],\n pageByConversationId: ReadonlyMap<string, number>,\n backendKind: BackendKind,\n options?: { forceIncludeConversationId?: string | null },\n): Set<string> {\n // Resolve each conversation's folder identity exactly once; both passes\n // below (finding each folder's discovery page, then collecting the ids on\n // that page) read from this record instead of re-running the\n // workspace/repository normalization.\n const resolved = items.map((conversation) => ({\n conversationId: conversation.id,\n groupId: getConversationGroupIdentity(conversation, backendKind).id,\n page: pageByConversationId.get(conversation.id) ?? 0,\n }));\n\n const discoveryPageByGroupId = new Map<string, number>();\n for (const { groupId, page } of resolved) {\n const currentDiscoveryPage = discoveryPageByGroupId.get(groupId);\n if (currentDiscoveryPage === undefined || page < currentDiscoveryPage) {\n discoveryPageByGroupId.set(groupId, page);\n }\n }\n\n const discoveryIds = new Set<string>();\n for (const { conversationId, groupId, page } of resolved) {\n if (page === discoveryPageByGroupId.get(groupId)) {\n discoveryIds.add(conversationId);\n }\n }\n\n const forceIncludeId = options?.forceIncludeConversationId;\n if (\n forceIncludeId != null &&\n items.some((conversation) => conversation.id === forceIncludeId)\n ) {\n discoveryIds.add(forceIncludeId);\n }\n\n return discoveryIds;\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n knownWorkspaces?: readonly LocalWorkspace[],\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 if (backendKind === \"local\" && knownWorkspaces) {\n for (const ws of knownWorkspaces) {\n const normalized = ws.path.trim().replace(/\\/+$/, \"\");\n if (normalized) {\n byId.set(`ws:${normalized}`, { label: ws.name, conversations: [] });\n }\n }\n }\n\n for (const c of items) {\n const { id, label: rawLabel } = getConversationGroupIdentity(\n c,\n backendKind,\n );\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 { LocalWorkspace } from \"#/types/workspace\";\nimport type { Provider } from \"#/types/settings\";\nimport {\n AUTOMATION_NAME_TAG_KEY,\n AUTOMATION_TAG_KEYS,\n getDisplayConversationTags,\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\";\nexport type OlderConversationCutoff = \"1h\" | \"1d\" | \"7d\" | \"30d\";\n\nexport const OLDER_CONVERSATION_CUTOFFS = [\n \"1h\",\n \"1d\",\n \"7d\",\n \"30d\",\n] as const satisfies readonly OlderConversationCutoff[];\n\nexport const DEFAULT_OLDER_CONVERSATION_CUTOFF: OlderConversationCutoff = \"7d\";\n\nexport const OLDER_CONVERSATION_CUTOFF_MS: Record<\n OlderConversationCutoff,\n number\n> = {\n \"1h\": 60 * 60 * 1000,\n \"1d\": 24 * 60 * 60 * 1000,\n \"7d\": 7 * 24 * 60 * 60 * 1000,\n \"30d\": 30 * 24 * 60 * 60 * 1000,\n};\n\nexport function isOlderConversationCutoff(\n value: unknown,\n): value is OlderConversationCutoff {\n return (\n typeof value === \"string\" &&\n (OLDER_CONVERSATION_CUTOFFS as readonly string[]).includes(value)\n );\n}\n\n/**\n * Splits conversations by last update relative to `nowMs`. Missing or\n * unparseable timestamps stay in `recent` so they are never hidden by the\n * hide-older toggle.\n */\nexport function partitionByCutoff<T extends { updated_at: string }>(\n items: readonly T[],\n cutoffMs: number,\n nowMs: number = Date.now(),\n): { recent: T[]; older: T[] } {\n const cutoff = nowMs - cutoffMs;\n const recent: T[] = [];\n const older: T[] = [];\n for (const item of items) {\n const updatedAt = item.updated_at ? Date.parse(item.updated_at) : NaN;\n if (Number.isFinite(updatedAt) && updatedAt < cutoff) {\n older.push(item);\n } else {\n recent.push(item);\n }\n }\n return { recent, older };\n}\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 * When set, the collapsed preview is drawn only from these conversation IDs\n * (plus the active conversation when it belongs to the group). Expanding\n * still reveals every loaded conversation in `conversations`.\n */\n discoveryConversationIds?: ReadonlySet<string>;\n}\n\n/**\n * Builds the frozen collapsed-preview pool for a folder.\n *\n * Global \"Load more\" may fetch later pages that add conversations to an\n * already-visible folder; those rows stay out of the collapsed preview so the\n * folder's first impression stays stable until the user expands it.\n */\nfunction resolveCollapsedPreviewPool(\n conversations: readonly AppConversation[],\n discoveryConversationIds: ReadonlySet<string> | undefined,\n activeConversationId: string | null | undefined,\n): AppConversation[] {\n if (!discoveryConversationIds) {\n return [...conversations];\n }\n\n const pool = conversations.filter((conversation) =>\n discoveryConversationIds.has(conversation.id),\n );\n\n // The load-bearing active-conversation guarantee lives in\n // `getGroupDiscoveryConversationIds` (`forceIncludeConversationId`); this\n // fallback only covers callers that pass a discovery set built without it.\n if (\n activeConversationId != null &&\n !pool.some((conversation) => conversation.id === activeConversationId)\n ) {\n const activeConversation = conversations.find(\n (conversation) => conversation.id === activeConversationId,\n );\n if (activeConversation) {\n pool.push(activeConversation);\n }\n }\n\n return pool;\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 const pool = resolveCollapsedPreviewPool(\n conversations,\n options.discoveryConversationIds,\n options.activeConversationId,\n );\n\n let collapsedVisible: AppConversation[];\n if (pool.length <= limit) {\n collapsedVisible = pool;\n } else {\n const activeIndex =\n options.activeConversationId != null\n ? pool.findIndex(\n (conversation) => conversation.id === options.activeConversationId,\n )\n : -1;\n\n if (activeIndex >= limit) {\n collapsedVisible = [...pool.slice(0, limit - 1), pool[activeIndex]];\n } else {\n collapsedVisible = pool.slice(0, limit);\n }\n }\n\n const collapsedHidesSomething =\n collapsedVisible.length < conversations.length;\n\n if (options.expanded) {\n return {\n visibleConversations: [...conversations],\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: true,\n };\n }\n\n return {\n visibleConversations: collapsedVisible,\n isPreviewTruncated: collapsedHidesSomething,\n isShowingAll: !collapsedHidesSomething,\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/**\n * Distinct user-facing `key=value` facets among the given conversations,\n * sorted A–Z for stable menu order. Reserved/internal tag keys are excluded\n * via `getDisplayConversationTags`; unlike the automation filter there is no\n * unnamed bucket — a conversation with no user tags simply yields no facet.\n */\nexport function collectTagFacets(\n conversations: readonly AppConversation[],\n): string[] {\n const facets = new Set<string>();\n for (const conversation of conversations) {\n for (const [key, value] of getDisplayConversationTags(conversation.tags)) {\n facets.add(`${key}=${value}`);\n }\n }\n return [...facets].sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Display form of a stored facet: a bare tag (empty value, stored as `key=`)\n * renders as just the key. Matching keeps the raw `key=value` form — this is\n * label-only.\n */\nexport function formatTagFacetLabel(facet: string): string {\n return facet.endsWith(\"=\") ? facet.slice(0, -1) : facet;\n}\n\n/**\n * Union semantics: a conversation matches when it carries ANY selected\n * facet, mirroring the automation multi-select. An empty selection — or one\n * that no longer intersects the available facets (tags edited away, stale\n * selections persisted from another backend) — leaves the list unfiltered\n * instead of yielding an unfillable empty list.\n */\nexport function applyTagConversationFilter(\n conversations: readonly AppConversation[],\n selectedFacets: readonly string[],\n availableFacets: readonly string[],\n): AppConversation[] {\n const facetSet = new Set(availableFacets);\n const effectiveFacets = selectedFacets.filter((facet) => facetSet.has(facet));\n if (effectiveFacets.length === 0) {\n return [...conversations];\n }\n const narrowing = new Set(effectiveFacets);\n return conversations.filter((conversation) =>\n getDisplayConversationTags(conversation.tags).some(([key, value]) =>\n narrowing.has(`${key}=${value}`),\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\n/**\n * Resolves the stable folder identity used by grouped conversation views.\n *\n * Keeping this shared with `groupConversations` lets pagination reason about\n * folder discovery without duplicating workspace/repository normalization.\n */\nfunction getConversationGroupIdentity(\n conversation: AppConversation,\n backendKind: BackendKind,\n): { id: string; label: string } {\n return backendKind === \"local\"\n ? workspaceGroup(conversation)\n : repositoryGroup(conversation);\n}\n\n/**\n * Max backend pages fetched for a single grouped \"Load more\" click. The\n * driver walks past pages that only deepen already-visible folders looking\n * for a new folder, and this cap prevents one click from walking the entire\n * remaining cursor when no undiscovered folder exists. Chronological mode is\n * not capped — it keeps its pre-existing fetch-until-visible behavior.\n */\nexport const MAX_PAGES_PER_LOAD_MORE_CLICK = 3;\n\n/**\n * Conversation IDs that belong on each folder's discovery page — the first\n * backend page where that folder appeared.\n *\n * Global \"Load more\" still discovers folders from later pages, but the\n * collapsed preview for an already-visible folder stays frozen to this set.\n * Expanding the folder reads the full grouped `conversations` array instead.\n * `forceIncludeConversationId` keeps the active thread in the preview even\n * when it landed on a non-discovery page.\n */\nexport function getGroupDiscoveryConversationIds(\n items: readonly AppConversation[],\n pageByConversationId: ReadonlyMap<string, number>,\n backendKind: BackendKind,\n options?: { forceIncludeConversationId?: string | null },\n): Set<string> {\n // Resolve each conversation's folder identity exactly once; both passes\n // below (finding each folder's discovery page, then collecting the ids on\n // that page) read from this record instead of re-running the\n // workspace/repository normalization.\n const resolved = items.map((conversation) => ({\n conversationId: conversation.id,\n groupId: getConversationGroupIdentity(conversation, backendKind).id,\n page: pageByConversationId.get(conversation.id) ?? 0,\n }));\n\n const discoveryPageByGroupId = new Map<string, number>();\n for (const { groupId, page } of resolved) {\n const currentDiscoveryPage = discoveryPageByGroupId.get(groupId);\n if (currentDiscoveryPage === undefined || page < currentDiscoveryPage) {\n discoveryPageByGroupId.set(groupId, page);\n }\n }\n\n const discoveryIds = new Set<string>();\n for (const { conversationId, groupId, page } of resolved) {\n if (page === discoveryPageByGroupId.get(groupId)) {\n discoveryIds.add(conversationId);\n }\n }\n\n const forceIncludeId = options?.forceIncludeConversationId;\n if (\n forceIncludeId != null &&\n items.some((conversation) => conversation.id === forceIncludeId)\n ) {\n discoveryIds.add(forceIncludeId);\n }\n\n return discoveryIds;\n}\n\nexport function groupConversations(\n items: readonly AppConversation[],\n backendKind: BackendKind,\n sortField: ConversationSortField,\n labels: { emptyWorkspace: string; emptyRepository: string },\n knownWorkspaces?: readonly LocalWorkspace[],\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 if (backendKind === \"local\" && knownWorkspaces) {\n for (const ws of knownWorkspaces) {\n const normalized = ws.path.trim().replace(/\\/+$/, \"\");\n if (normalized) {\n byId.set(`ws:${normalized}`, { label: ws.name, conversations: [] });\n }\n }\n }\n\n for (const c of items) {\n const { id, label: rawLabel } = getConversationGroupIdentity(\n c,\n backendKind,\n );\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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"}
|