@nextclaw/ui 0.15.4 → 0.15.6
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/CHANGELOG.md +41 -0
- package/dist/assets/abnfDiagram-VRR7QNED-BYpK0F5F.js +1 -0
- package/dist/assets/{aiden0z-pptx-renderer.es-Bd99vut2.js → aiden0z-pptx-renderer.es-D87ywFdC.js} +1 -1
- package/dist/assets/api-Dyb5rgh0.js +13 -0
- package/dist/assets/app-presenter-provider-7jV0nPiL.js +106 -0
- package/dist/assets/{appearance-settings-page-fLIJbx1C.js → appearance-settings-page-DFm3BbEb.js} +1 -1
- package/dist/assets/arc-DFELHWM2.js +1 -0
- package/dist/assets/architecture-TIHT7OUA-ClwVFq-K.js +1 -0
- package/dist/assets/architectureDiagram-ZJ3FMSHR-CvRhdovL.js +36 -0
- package/dist/assets/array-BqYdCIE6.js +1 -0
- package/dist/assets/blockDiagram-677ZJIJ3-DVYNkbR_.js +132 -0
- package/dist/assets/{book-open-DWUjS6aW.js → book-open-L6LCuqOr.js} +1 -1
- package/dist/assets/c4Diagram-LMCZKHZV-B1w-iwRe.js +10 -0
- package/dist/assets/channel-BEHOSFc5.js +1 -0
- package/dist/assets/{channels-list-page-CvCTJraa.js → channels-list-page-DOaPKNJA.js} +2 -2
- package/dist/assets/{chat-page-B42UUIFR.js → chat-page-Cw9uDhD_.js} +1 -1
- package/dist/assets/chunk-2Q5K7J3B-DrIhesSX.js +1 -0
- package/dist/assets/chunk-32BRIVSS-kG3lg0bC.js +1 -0
- package/dist/assets/chunk-52WLFC77-BLeB7iGk.js +10 -0
- package/dist/assets/chunk-5FCAYU7R-BQga1Rr7.js +1 -0
- package/dist/assets/chunk-5HE753X5-DU81hkcF.js +1 -0
- package/dist/assets/chunk-5JV3BV7I-C2bAx0m7.js +1 -0
- package/dist/assets/chunk-5TONJI2A-BExIIgWY.js +2 -0
- package/dist/assets/chunk-5VM5RSS4-C3XB05yh.js +15 -0
- package/dist/assets/chunk-7BUUIJ7U-JiyRtrGu.js +1 -0
- package/dist/assets/chunk-BIQX33UG-BZRV20pI.js +1 -0
- package/dist/assets/chunk-C7G6YPKG-AsyDSQ9j.js +1 -0
- package/dist/assets/chunk-CQNSW5MT-iN-fiXVA.js +1 -0
- package/dist/assets/chunk-CYSBUYHQ-DhC_TRzI.js +1 -0
- package/dist/assets/chunk-EMLP6XTP-QFLK8R6d.js +1 -0
- package/dist/assets/chunk-EX3LRPZG-DzUwhkCz.js +231 -0
- package/dist/assets/chunk-FWX5IMBZ-DFelpZBy.js +2 -0
- package/dist/assets/chunk-HOUHSVGY-BMPwFEwN.js +1 -0
- package/dist/assets/chunk-ICXQ74PX-DH8NJMok.js +2 -0
- package/dist/assets/chunk-JG7HCLWE-D-95AsO4.js +2 -0
- package/dist/assets/chunk-JWPE2WC7-DIaTv8kx.js +1 -0
- package/dist/assets/chunk-KEIR6QF5-A3jEqwzn.js +161 -0
- package/dist/assets/chunk-MOJQB5TN-BPFLzWgj.js +88 -0
- package/dist/assets/chunk-MOZMSUNE-DR_fzxG0.js +1 -0
- package/dist/assets/chunk-OGEWGWER-TIcEoPPH.js +1 -0
- package/dist/assets/chunk-OSBZ3O6U-BALNvSfG.js +1 -0
- package/dist/assets/chunk-PUDLZKDR-I-EXhf_k.js +156 -0
- package/dist/assets/chunk-Q4XR5HBZ-uvIGstBS.js +70 -0
- package/dist/assets/chunk-QBLGF6JB-r-TjLdxa.js +1 -0
- package/dist/assets/chunk-R7FJI6CG-N-1LDgvy.js +1 -0
- package/dist/assets/chunk-RYQCIY6F-jxNASx65.js +1 -0
- package/dist/assets/chunk-U6XO7XAA-Cphbuc7q.js +2 -0
- package/dist/assets/chunk-V7JOEXUC-BLEuBf1s.js +206 -0
- package/dist/assets/chunk-VAUOI2AC-Dpcz6BhT.js +1 -0
- package/dist/assets/chunk-VR4S4FIN-BAUbR0ke.js +1 -0
- package/dist/assets/chunk-WYO6CB5R-Do6SJrnY.js +127 -0
- package/dist/assets/chunk-XXDRQBXY-C2QjjwYX.js +1 -0
- package/dist/assets/chunk-Y2CYZVJY-BGrd8tLy.js +1 -0
- package/dist/assets/chunk-YOTPTUD7-CQqvMTCr.js +1 -0
- package/dist/assets/chunk-ZGVPDNZ5-B7kWWaXv.js +62 -0
- package/dist/assets/chunk-ZIRB5QZD-DTU0cDNh.js +32 -0
- package/dist/assets/classDiagram-OUVF2IWQ-DESMaY3_.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-DwOlByYH.js +1 -0
- package/dist/assets/{config-split-page-DBgt9S8b.js → config-split-page-CqlqjnCK.js} +1 -1
- package/dist/assets/{confirm-dialog-GSXIvoRU.js → confirm-dialog-bAp8NU93.js} +1 -1
- package/dist/assets/cose-bilkent-JH36ORCC-B9LrtV-q.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-CzjeeOq9.js +1 -0
- package/dist/assets/cynefinDiagram-TSTJHNR4-BfjvW4su.js +62 -0
- package/dist/assets/cytoscape.esm-CRW8q92n.js +321 -0
- package/dist/assets/dagre-DkiXZKkL.js +1 -0
- package/dist/assets/dagre-VKFMJZFB-B1pQKQSY.js +4 -0
- package/dist/assets/defaultLocale-Cdv9x6q7.js +1 -0
- package/dist/assets/desktop-update-config-2SjMfCMl.js +1 -0
- package/dist/assets/diagram-FQU43EPY-cB4EZdaP.js +3 -0
- package/dist/assets/diagram-G47NLZAW-CtW8im1B.js +24 -0
- package/dist/assets/diagram-NH7WQ7WH-BDCtrCCm.js +24 -0
- package/dist/assets/diagram-OA4YK3LP-DEMJ42Gt.js +30 -0
- package/dist/assets/diagram-WEI45ONY-CdCcxSYU.js +41 -0
- package/dist/assets/{dist-DC7f4TJH.js → dist-CrtbGLlh.js} +1 -1
- package/dist/assets/dist-dw-gAfM_.js +1 -0
- package/dist/assets/doc-browser-A5IRyDXQ2.js +1 -0
- package/dist/assets/{doc-browser-D0monHjG.js → doc-browser-BmnQa30-.js} +1 -1
- package/dist/assets/{doc-browser-context-CGwEOhBy.js → doc-browser-context-BlpUUFrR.js} +1 -1
- package/dist/assets/{docx-preview-eFH9DRsS.js → docx-preview-zis3U0Fa.js} +1 -1
- package/dist/assets/{download-DiP9zx-J.js → download-BhZZNXD8.js} +1 -1
- package/dist/assets/ebnfDiagram-CCIWWBDH-DBZETBwE.js +1 -0
- package/dist/assets/erDiagram-Q63AITRT-y2zDXprP.js +85 -0
- package/dist/assets/eventmodeling-45OFAUF4-C38BqG8w.js +1 -0
- package/dist/assets/{external-link-C6ZeSPef.js → external-link-B9Uoq5J7.js} +1 -1
- package/dist/assets/{eye-suvKmtwn.js → eye-K5knauEM.js} +1 -1
- package/dist/assets/flowDiagram-23GEKE2U-BoKk8RRq.js +1 -0
- package/dist/assets/{folder-CMELbQGG.js → folder-BIYZZWJv.js} +1 -1
- package/dist/assets/{form-actions-CUAzpNe_.js → form-actions-CKprWFeM.js} +1 -1
- package/dist/assets/ganttDiagram-NO4QXBWP-D2DP344e.js +292 -0
- package/dist/assets/gitGraph-TEB2WS4Q-IsQHHJuS.js +1 -0
- package/dist/assets/gitGraphDiagram-IHSO6WYX-D37uiwA2.js +106 -0
- package/dist/assets/graphlib-BcNFQr5y.js +1 -0
- package/dist/assets/index-BVn702m4.css +1 -0
- package/dist/assets/index-CFxJ1Fkg.js +2 -0
- package/dist/assets/info-DKCQHKI2-ofy2qlHI.js +1 -0
- package/dist/assets/infoDiagram-FWYZ7A6U-CG-WAIRi.js +2 -0
- package/dist/assets/init-D8TjIqfm.js +1 -0
- package/dist/assets/ishikawaDiagram-FXEZZL3T-WeCTnW0f.js +70 -0
- package/dist/assets/journeyDiagram-5HDEW3XC-DUFBW9Td.js +139 -0
- package/dist/assets/kanban-definition-HUTT4EX6-B0lxgMpg.js +89 -0
- package/dist/assets/katex-wEmrEFTg.js +257 -0
- package/dist/assets/line-B78frP_c.js +1 -0
- package/dist/assets/linear-C6lVEcb2.js +1 -0
- package/dist/assets/loader-circle-Bj2RMrCR.js +1 -0
- package/dist/assets/{logo-badge-Cu5UGH_4.js → logo-badge-BQ-XFZod.js} +1 -1
- package/dist/assets/map-Bdri5UL5.js +1 -0
- package/dist/assets/mcp-marketplace-page-BfA7A3n4.js +9 -0
- package/dist/assets/mcp-marketplace-page-CXHYO95j.js +1 -0
- package/dist/assets/mermaid-parser.core-Cue18vLo.js +4 -0
- package/dist/assets/mermaid.core-CXwWRh5i.js +11 -0
- package/dist/assets/mindmap-definition-LN4V7U3C-CFxz0P0-.js +96 -0
- package/dist/assets/{model-config-page-CWP6pyBm.js → model-config-page-BbWbW_qM.js} +1 -1
- package/dist/assets/ordinal-Cbd8t4LB.js +1 -0
- package/dist/assets/packet-7NZHBO7P-Rfopfa1o.js +1 -0
- package/dist/assets/path-DzBnMI1r.js +1 -0
- package/dist/assets/pegDiagram-2B236MQR-B_Qt9zyT.js +1 -0
- package/dist/assets/pie-RZYD4A2V-CJR1xKEv.js +1 -0
- package/dist/assets/pieDiagram-ENE6RG2P-CRQdSuwS.js +39 -0
- package/dist/assets/plus-TmFdwO3P.js +1 -0
- package/dist/assets/{popover-DImguRok.js → popover-CX9zFsuc.js} +1 -1
- package/dist/assets/preload-helper-D4M6sveU.js +1 -0
- package/dist/assets/{provider-scoped-model-input-CE7p4SbJ.js → provider-scoped-model-input-B-9_DtIP.js} +1 -1
- package/dist/assets/providers-config-page-xwIjGur2.js +1 -0
- package/dist/assets/quadrantDiagram-ABIIQ3AL-D5kPpttq.js +7 -0
- package/dist/assets/radar-I7S5WNFK-CDg8Z-1r.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-BHnNmjxO.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-DGtNcusW.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-BRFtsQmm.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-Bj5IypCA.js +1 -0
- package/dist/assets/railroadDiagram-RFXS5EU6-DGh_TGlQ.js +1 -0
- package/dist/assets/{react-5sjAT_6d.js → react-DsgudwpT.js} +1 -1
- package/dist/assets/{refresh-cw-CHLBzWWj.js → refresh-cw-kXdvbhFf.js} +1 -1
- package/dist/assets/remote-B9F2uCk9.js +1 -0
- package/dist/assets/requirementDiagram-TGXJPOKE-EmFph0H_.js +84 -0
- package/dist/assets/rotate-cw-DEc6aihr.js +1 -0
- package/dist/assets/rough.esm-wJ1d3nQl.js +1 -0
- package/dist/assets/runtime-config-page-DTsi7czJ.js +1 -0
- package/dist/assets/sankeyDiagram-HTMAVEWB-BXWB5Ugi.js +40 -0
- package/dist/assets/{save-BABzyrjB.js → save-C9qpz2_2.js} +1 -1
- package/dist/assets/{search-BTqxG3ZG.js → search-_kEi29qo.js} +1 -1
- package/dist/assets/{search-config-page-BkKKmxmS.js → search-config-page-H7ug8f4D.js} +1 -1
- package/dist/assets/{secrets-config-page-CWJMyu-k.js → secrets-config-page-C1_6rINu.js} +2 -2
- package/dist/assets/security-config-Cr2ERKLu.js +1 -0
- package/dist/assets/{select-TYZDBNmq.js → select-MJKhKAWR.js} +1 -1
- package/dist/assets/sequenceDiagram-DBY2YBRQ-ClKnO7v0.js +162 -0
- package/dist/assets/{setting-row-DR23Z_5I.js → setting-row-DA3tJuew.js} +1 -1
- package/dist/assets/{settings-2-D8WWcBnw.js → settings-2-D_y7zXJz.js} +1 -1
- package/dist/assets/sizeCapture-X5ZJPWSS-DSo-t5ou.js +1 -0
- package/dist/assets/{skeleton-CloHeg0S.js → skeleton-0uTLUhm9.js} +1 -1
- package/dist/assets/src-Dad2ZbCt.js +1 -0
- package/dist/assets/stateDiagram-2N3HPSRC-BvAalBfz.js +1 -0
- package/dist/assets/stateDiagram-v2-6OUMAXLB-CfMU38yc.js +1 -0
- package/dist/assets/swimlanes-5IMT3BWC-DdVqVa1a.js +2 -0
- package/dist/assets/swimlanesDiagram-G3AALYLV-D9Zb9X57.js +8 -0
- package/dist/assets/{tabs-CX-ckWoo.js → tabs-h44XPocd.js} +1 -1
- package/dist/assets/{tag-chip-mCc23Rhb.js → tag-chip-bRZ04q3C.js} +1 -1
- package/dist/assets/timeline-definition-FHXFAJF6-D4ar8IQY.js +120 -0
- package/dist/assets/{trash-2-SAW1Z4Po.js → trash-2-BRpSE-Wt.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-Uy7M0WvH.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-BJfGV7KX.js +1 -0
- package/dist/assets/use-config-CwDEAl6f.js +1 -0
- package/dist/assets/{use-confirm-dialog-C95F6sT1.js → use-confirm-dialog-BbnWw-8c.js} +1 -1
- package/dist/assets/{use-viewport-layout-C6m3Nte7.js → use-viewport-layout-CqgIMDQL.js} +1 -1
- package/dist/assets/vennDiagram-L72KCM5P-CDXJ_i3p.js +34 -0
- package/dist/assets/wardley-OPB4EBWU-q263iF3K.js +1 -0
- package/dist/assets/wardleyDiagram-EHGQE667-D-dSuT_7.js +78 -0
- package/dist/assets/x-DdEDL6ju.js +1 -0
- package/dist/assets/xychartDiagram-FW5EYKEG-C9JCzsZF.js +7 -0
- package/dist/index.html +33 -32
- package/package.json +8 -8
- package/src/features/chat/components/chat-popover-content.tsx +1 -26
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +84 -1
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +13 -2
- package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
- package/src/features/chat/components/layout/__tests__/chat-sidebar-test.utils.ts +22 -0
- package/src/features/chat/components/layout/__tests__/chat-sidebar.test.tsx +13 -24
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +16 -4
- package/src/features/chat/components/layout/chat-sidebar.tsx +38 -2
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +1 -0
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +52 -2
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +22 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +36 -20
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +55 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +12 -11
- package/src/features/chat/features/conversation/hooks/use-session-conversation-preference-actions.ts +94 -0
- package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +37 -0
- package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +140 -63
- package/src/features/chat/features/input/input-surface-plugins/__tests__/context-reference-plugin.test.ts +175 -0
- package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +66 -0
- package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +8 -1
- package/src/features/chat/features/input/input-surface-plugins/context-reference-plugin.utils.ts +274 -0
- package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +18 -11
- package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +26 -0
- package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +50 -4
- package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +51 -0
- package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +4 -10
- package/src/features/chat/features/input/utils/chat-composer-token-protocol.utils.ts +29 -0
- package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +66 -8
- package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +62 -21
- package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +42 -10
- package/src/features/chat/features/message/components/chat-inline-file-preview.tsx +80 -0
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +55 -60
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +2 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +41 -3
- package/src/features/chat/features/project/components/__tests__/chat-project-create-dialog.test.tsx +67 -0
- package/src/features/chat/features/project/components/chat-project-create-dialog.tsx +203 -0
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +7 -7
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-project-dialog.test.tsx +47 -0
- package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +6 -3
- package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +3 -0
- package/src/features/chat/features/session/components/session-header/chat-session-project-dialog.tsx +3 -0
- package/src/features/chat/features/session/components/session-header/chat-session-switcher-groups.tsx +245 -0
- package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +81 -127
- package/src/features/chat/features/session/utils/__tests__/chat-sidebar-session-groups.utils.test.ts +22 -0
- package/src/features/chat/features/session/utils/chat-run-metadata.utils.ts +6 -6
- package/src/features/chat/features/session/utils/chat-sidebar-session-groups.utils.ts +12 -1
- package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +3 -0
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +1 -0
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-project-options.utils.test.ts +20 -0
- package/src/features/chat/features/welcome/utils/chat-welcome-project-options.utils.ts +15 -2
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +22 -24
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +2 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +6 -17
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +41 -19
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +5 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +5 -1
- package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +104 -3
- package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +83 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +4 -1
- package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +96 -25
- package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +25 -0
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +5 -1
- package/src/features/chat/managers/chat-session-list.manager.ts +1 -0
- package/src/features/chat/managers/chat-thread.manager.ts +15 -37
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +23 -0
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +9 -0
- package/src/features/chat/stores/chat-thread.store.ts +16 -36
- package/src/features/chat/types/chat-input-bar.types.ts +2 -0
- package/src/features/settings/components/config/provider-form.tsx +0 -4
- package/src/features/settings/utils/__tests__/provider-form-support.utils.test.ts +7 -9
- package/src/features/settings/utils/provider-form-model.utils.ts +0 -4
- package/src/features/system-status/hooks/use-current-version-release-notes-link.ts +33 -0
- package/src/features/system-status/index.ts +9 -0
- package/src/features/system-status/utils/update-release-notes.utils.ts +44 -3
- package/src/index.css +10 -16
- package/src/shared/components/common/__tests__/brand-header.test.tsx +127 -10
- package/src/shared/components/common/brand-header.tsx +142 -56
- package/src/shared/components/path-picker/__tests__/server-path-picker-dialog.test.tsx +288 -38
- package/src/shared/components/path-picker/server-path-picker-dialog.tsx +290 -199
- package/src/shared/components/path-picker/server-path-picker-directory-list.tsx +103 -0
- package/src/shared/components/path-picker/server-path-picker-footer.tsx +58 -0
- package/src/shared/components/path-picker/server-path-picker-locations.tsx +148 -0
- package/src/shared/components/path-picker/server-path-picker-navigation-bar.tsx +198 -0
- package/src/shared/components/path-picker/server-path-picker-new-folder.tsx +59 -0
- package/src/shared/components/path-picker/server-path-picker-toolbar.tsx +25 -0
- package/src/shared/hooks/use-projects.ts +28 -0
- package/src/shared/hooks/use-server-path-create-directory.ts +6 -0
- package/src/shared/hooks/use-server-path-read.ts +10 -5
- package/src/shared/hooks/use-server-path-search.ts +40 -0
- package/src/shared/lib/api/index.ts +1 -0
- package/src/shared/lib/api/projects/project.utils.ts +14 -0
- package/src/shared/lib/api/types.ts +30 -3
- package/src/shared/lib/api/utils/server-path.utils.ts +22 -1
- package/src/shared/lib/i18n/locales/en-US/chat.json +43 -2
- package/src/shared/lib/i18n/locales/en-US/core.json +2 -3
- package/src/shared/lib/i18n/locales/en-US/desktop-update.json +4 -0
- package/src/shared/lib/i18n/locales/en-US/path-picker.json +25 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +43 -2
- package/src/shared/lib/i18n/locales/zh-CN/core.json +2 -3
- package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +4 -0
- package/src/shared/lib/i18n/locales/zh-CN/path-picker.json +25 -0
- package/src/shared/lib/session-project/__tests__/workspace-file-breadcrumb.test.ts +1 -4
- package/src/shared/lib/session-project/workspace-file-breadcrumb.utils.ts +1 -18
- package/dist/assets/api-BOXOrpcJ.js +0 -13
- package/dist/assets/app-presenter-provider-CkHLbvZQ.js +0 -106
- package/dist/assets/desktop-update-config-7bmNeWIC.js +0 -1
- package/dist/assets/doc-browser-CgdoLUT92.js +0 -1
- package/dist/assets/index-BFeNDQ4R.css +0 -1
- package/dist/assets/index-D_6U-M94.js +0 -2
- package/dist/assets/loader-circle-tYHStefV.js +0 -1
- package/dist/assets/mcp-marketplace-page-BUzHDwW6.js +0 -9
- package/dist/assets/mcp-marketplace-page-ohUAdfqJ.js +0 -1
- package/dist/assets/plus-tywizkeY.js +0 -1
- package/dist/assets/providers-config-page-BKPo8SjH.js +0 -1
- package/dist/assets/remote-DXJryUxB.js +0 -1
- package/dist/assets/rotate-cw-BefO5brU.js +0 -1
- package/dist/assets/runtime-config-page-1Axv4QGu.js +0 -1
- package/dist/assets/security-config-DeQUIXfi.js +0 -1
- package/dist/assets/use-config-BucdaK23.js +0 -1
- package/dist/assets/x-DtCPHwCu.js +0 -1
- package/src/features/chat/components/__tests__/chat-popover-content.test.tsx +0 -41
- package/src/features/chat/components/layout/__tests__/chat-sidebar-utility-menu.test.tsx +0 -55
- package/src/features/chat/features/input/input-surface-plugins/__tests__/panel-app-reference-plugin.test.ts +0 -77
- package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +0 -144
- /package/dist/assets/{config-hints-fDrYfl0l.js → config-hints-LxG80Uj5.js} +0 -0
- /package/dist/assets/{host-capabilities-zZvY9U63.js → host-capabilities-CFbAfrrA.js} +0 -0
- /package/dist/assets/{jszip.min-Das2IAnb.js → jszip.min-CP5uPNQa.js} +0 -0
- /package/dist/assets/{middleware-BLMHv9YF.js → middleware-CAXxl-af.js} +0 -0
- /package/dist/assets/{provider-models-C_yOh6DE.js → provider-models-BoUhFo9R.js} +0 -0
- /package/dist/assets/{xlsx-B6zVt1RK.js → xlsx-DUqJhg5u.js} +0 -0
|
@@ -16,6 +16,7 @@ import { useChatQueryStore } from "@/features/chat/stores/ncp-chat-query.store";
|
|
|
16
16
|
import { useChatSessionListStore } from "@/features/chat/stores/chat-session-list.store";
|
|
17
17
|
import { useChatThreadStore } from "@/features/chat/stores/chat-thread.store";
|
|
18
18
|
import { useAgents } from "@/shared/hooks/use-agents";
|
|
19
|
+
import { useProjects } from "@/shared/hooks/use-projects";
|
|
19
20
|
import type { NcpSessionSummaryView } from "@/shared/lib/api";
|
|
20
21
|
import { normalizeSessionProjectRootValue } from "@/shared/lib/session-project";
|
|
21
22
|
|
|
@@ -55,6 +56,7 @@ export function ChatConversationWelcome({
|
|
|
55
56
|
(state) => state.snapshot.sessionTypesQuery?.data ?? null,
|
|
56
57
|
);
|
|
57
58
|
const agentsQuery = useAgents();
|
|
59
|
+
const projectsQuery = useProjects();
|
|
58
60
|
const draftAgentId = threadSnapshot.agentId ?? selectedAgentId;
|
|
59
61
|
const availableAgents = resolveChatWelcomeAgents({
|
|
60
62
|
agents: agentsQuery.data?.agents,
|
|
@@ -80,6 +82,7 @@ export function ChatConversationWelcome({
|
|
|
80
82
|
});
|
|
81
83
|
const projectOptions = buildChatWelcomeProjectOptions({
|
|
82
84
|
defaultProjectRoot,
|
|
85
|
+
projects: projectsQuery.data?.projects ?? [],
|
|
83
86
|
sessionSummaries,
|
|
84
87
|
});
|
|
85
88
|
const selectDraftAgent = (agentId: string) => {
|
|
@@ -106,6 +106,7 @@ export function ChatWelcome({
|
|
|
106
106
|
<ChatSessionProjectDialog
|
|
107
107
|
open={isProjectDialogOpen}
|
|
108
108
|
currentProjectRoot={resolvedProjectRoot}
|
|
109
|
+
defaultWorkspacePath={defaultProjectRoot}
|
|
109
110
|
isSaving={isProjectSaving}
|
|
110
111
|
onOpenChange={setIsProjectDialogOpen}
|
|
111
112
|
onSave={saveProjectRoot}
|
|
@@ -48,4 +48,24 @@ describe("buildChatWelcomeProjectOptions", () => {
|
|
|
48
48
|
},
|
|
49
49
|
]);
|
|
50
50
|
});
|
|
51
|
+
|
|
52
|
+
it("includes a registered project before it has any sessions", () => {
|
|
53
|
+
const options = buildChatWelcomeProjectOptions({
|
|
54
|
+
defaultProjectRoot: "/Users/demo/.nextclaw/workspace",
|
|
55
|
+
projects: [{
|
|
56
|
+
name: "Knowledge",
|
|
57
|
+
rootPath: "/tmp/knowledge",
|
|
58
|
+
template: "knowledge-base",
|
|
59
|
+
createdAt: "2026-07-15T00:00:00.000Z",
|
|
60
|
+
updatedAt: "2026-07-15T00:00:00.000Z",
|
|
61
|
+
}],
|
|
62
|
+
sessionSummaries: [],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
expect(options).toEqual([{
|
|
66
|
+
projectRoot: "/tmp/knowledge",
|
|
67
|
+
projectName: "Knowledge",
|
|
68
|
+
sessionCount: 0,
|
|
69
|
+
}]);
|
|
70
|
+
});
|
|
51
71
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NcpSessionSummaryView } from "@/shared/lib/api";
|
|
1
|
+
import type { NcpSessionSummaryView, ProjectView } from "@/shared/lib/api";
|
|
2
2
|
import { adaptNcpSessionSummaries } from "@/features/chat/features/session/utils/ncp-session-adapter.utils";
|
|
3
3
|
import { getSessionProjectName } from "@/shared/lib/session-project";
|
|
4
4
|
|
|
@@ -17,14 +17,27 @@ function readSessionActivityAt(session: {
|
|
|
17
17
|
|
|
18
18
|
export function buildChatWelcomeProjectOptions(params: {
|
|
19
19
|
defaultProjectRoot: string | null;
|
|
20
|
+
projects?: readonly ProjectView[];
|
|
20
21
|
sessionSummaries: readonly NcpSessionSummaryView[];
|
|
21
22
|
}): ChatWelcomeProjectOption[] {
|
|
22
|
-
const { defaultProjectRoot, sessionSummaries } = params;
|
|
23
|
+
const { defaultProjectRoot, projects = [], sessionSummaries } = params;
|
|
23
24
|
const groups = new Map<
|
|
24
25
|
string,
|
|
25
26
|
ChatWelcomeProjectOption & { latestUpdatedAt: number }
|
|
26
27
|
>();
|
|
27
28
|
|
|
29
|
+
for (const project of projects) {
|
|
30
|
+
if (project.rootPath === defaultProjectRoot) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
groups.set(project.rootPath, {
|
|
34
|
+
projectRoot: project.rootPath,
|
|
35
|
+
projectName: project.name,
|
|
36
|
+
sessionCount: 0,
|
|
37
|
+
latestUpdatedAt: new Date(project.updatedAt).getTime(),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
for (const session of adaptNcpSessionSummaries([...sessionSummaries])) {
|
|
29
42
|
const projectRoot = session.projectRoot?.trim();
|
|
30
43
|
if (!projectRoot || projectRoot === defaultProjectRoot) {
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from "@nextclaw/agent-chat-ui";
|
|
7
7
|
import { ChatSessionWorkspaceFilePreview } from "@/features/chat/features/workspace/components/chat-session-workspace-file-preview";
|
|
8
8
|
import type { ChatWorkspaceFileTab } from "@/features/chat/stores/chat-thread.store";
|
|
9
|
+
import type { ServerPathReadView } from "@/shared/lib/api";
|
|
9
10
|
import { t } from "@/shared/lib/i18n";
|
|
10
11
|
|
|
11
12
|
const serverPathReadMock = vi.fn();
|
|
@@ -22,15 +23,10 @@ type RenderWorkspaceFilePreviewOptions = {
|
|
|
22
23
|
refreshVersion?: number;
|
|
23
24
|
sessionProjectRoot?: string | null;
|
|
24
25
|
sessionWorkingDir?: string | null;
|
|
26
|
+
showBreadcrumbs?: boolean;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
type TextReadDataOverrides =
|
|
28
|
-
kind?: "text" | "markdown" | "binary";
|
|
29
|
-
languageHint?: string;
|
|
30
|
-
resolvedPath?: string;
|
|
31
|
-
text?: string;
|
|
32
|
-
truncated?: boolean;
|
|
33
|
-
};
|
|
29
|
+
type TextReadDataOverrides = Partial<ServerPathReadView>;
|
|
34
30
|
|
|
35
31
|
vi.mock("@/shared/hooks/use-server-path-read", () => ({
|
|
36
32
|
useServerPathRead: (...args: unknown[]) => serverPathReadMock(...args),
|
|
@@ -97,6 +93,7 @@ function mockTextRead(overrides: TextReadDataOverrides = {}) {
|
|
|
97
93
|
data: {
|
|
98
94
|
kind: "text",
|
|
99
95
|
resolvedPath: "/tmp/example.ts",
|
|
96
|
+
startLine: 1,
|
|
100
97
|
text: "const answer = 42;\n",
|
|
101
98
|
truncated: false,
|
|
102
99
|
...overrides,
|
|
@@ -110,6 +107,7 @@ function renderWorkspaceFilePreview({
|
|
|
110
107
|
refreshVersion,
|
|
111
108
|
sessionProjectRoot = "/tmp",
|
|
112
109
|
sessionWorkingDir = "/tmp",
|
|
110
|
+
showBreadcrumbs,
|
|
113
111
|
}: RenderWorkspaceFilePreviewOptions = {}) {
|
|
114
112
|
const view = render(
|
|
115
113
|
<ChatSessionWorkspaceFilePreview
|
|
@@ -117,6 +115,7 @@ function renderWorkspaceFilePreview({
|
|
|
117
115
|
sessionProjectRoot={sessionProjectRoot}
|
|
118
116
|
sessionWorkingDir={sessionWorkingDir}
|
|
119
117
|
refreshVersion={refreshVersion}
|
|
118
|
+
showBreadcrumbs={showBreadcrumbs}
|
|
120
119
|
onFileOpen={onFileOpen}
|
|
121
120
|
/>,
|
|
122
121
|
);
|
|
@@ -525,11 +524,16 @@ describe("ChatSessionWorkspaceFilePreview text rendering", () => {
|
|
|
525
524
|
).toBe("workspace");
|
|
526
525
|
});
|
|
527
526
|
|
|
528
|
-
it("passes server language hints
|
|
529
|
-
mockTextRead({
|
|
527
|
+
it("passes server language hints and keeps location out of breadcrumbs", () => {
|
|
528
|
+
mockTextRead({
|
|
529
|
+
languageHint: "js",
|
|
530
|
+
resolvedPath: "/tmp/example.js",
|
|
531
|
+
});
|
|
530
532
|
renderWorkspaceFilePreview({
|
|
531
533
|
file: {
|
|
534
|
+
column: 4,
|
|
532
535
|
label: "example.js",
|
|
536
|
+
line: 12,
|
|
533
537
|
path: "/tmp/example.js",
|
|
534
538
|
viewMode: "preview",
|
|
535
539
|
},
|
|
@@ -540,6 +544,7 @@ describe("ChatSessionWorkspaceFilePreview text rendering", () => {
|
|
|
540
544
|
.getByTestId("file-code-surface")
|
|
541
545
|
.getAttribute("data-language-hint"),
|
|
542
546
|
).toBe("js");
|
|
547
|
+
expect(screen.queryByText("L12:4")).toBeNull();
|
|
543
548
|
});
|
|
544
549
|
|
|
545
550
|
it("renders Markdown by default and keeps source view explicit", () => {
|
|
@@ -761,6 +766,14 @@ describe("ChatSessionWorkspaceFilePreview text rendering", () => {
|
|
|
761
766
|
});
|
|
762
767
|
|
|
763
768
|
describe("ChatSessionWorkspaceFilePreview breadcrumbs", () => {
|
|
769
|
+
it("can hide workspace breadcrumbs for inline placements", () => {
|
|
770
|
+
mockTextRead();
|
|
771
|
+
renderWorkspaceFilePreview({ showBreadcrumbs: false });
|
|
772
|
+
|
|
773
|
+
expect(screen.queryByTestId("workspace-file-breadcrumbs")).toBeNull();
|
|
774
|
+
expect(screen.getByTestId("file-code-surface")).toBeTruthy();
|
|
775
|
+
});
|
|
776
|
+
|
|
764
777
|
it("renders project-relative breadcrumbs when the file is inside the workspace", () => {
|
|
765
778
|
mockTextRead({ resolvedPath: "/tmp/workspace/src/example.ts" });
|
|
766
779
|
renderWorkspaceFilePreview({
|
|
@@ -832,21 +845,6 @@ describe("ChatSessionWorkspaceFilePreview breadcrumbs", () => {
|
|
|
832
845
|
).toContain("h-6");
|
|
833
846
|
});
|
|
834
847
|
|
|
835
|
-
it("keeps line and truncation metadata without the duplicated type badge", () => {
|
|
836
|
-
mockTextRead({ truncated: true });
|
|
837
|
-
renderWorkspaceFilePreview({
|
|
838
|
-
file: {
|
|
839
|
-
viewMode: "preview",
|
|
840
|
-
line: 12,
|
|
841
|
-
column: 4,
|
|
842
|
-
},
|
|
843
|
-
});
|
|
844
|
-
|
|
845
|
-
expect(screen.getByText("L12:4")).toBeTruthy();
|
|
846
|
-
expect(screen.getByText(t("chatWorkspacePreviewTruncated"))).toBeTruthy();
|
|
847
|
-
expect(screen.queryByText(t("chatWorkspacePreview"))).toBeNull();
|
|
848
|
-
});
|
|
849
|
-
|
|
850
848
|
it("uses the session working directory as the base path when no project root is set", () => {
|
|
851
849
|
mockTextRead({
|
|
852
850
|
resolvedPath: "/tmp/agent-workspace/AGENTS.md",
|
|
@@ -9,7 +9,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
9
9
|
syncVisibleWorkspaceSelection: vi.fn(),
|
|
10
10
|
selectChildSessionDetail: vi.fn(),
|
|
11
11
|
selectWorkspaceFile: vi.fn(),
|
|
12
|
-
|
|
12
|
+
closeWorkspaceTab: vi.fn(),
|
|
13
13
|
openSessionCronPanel: vi.fn(),
|
|
14
14
|
goBackWorkspacePanel: vi.fn(),
|
|
15
15
|
goForwardWorkspacePanel: vi.fn(),
|
|
@@ -72,6 +72,7 @@ function renderPanel(displayMode: "docked" | "overlay" = "docked") {
|
|
|
72
72
|
activeSideChatDraft={null}
|
|
73
73
|
workspaceFileTabs={[fileTab]}
|
|
74
74
|
activeWorkspaceFileKey={fileTab.key}
|
|
75
|
+
closedWorkspaceTabEntries={[]}
|
|
75
76
|
workspaceNavigationHistory={[{ kind: "file", key: fileTab.key }]}
|
|
76
77
|
workspaceNavigationHistoryIndex={0}
|
|
77
78
|
activePanelKind="file"
|
package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx
CHANGED
|
@@ -12,15 +12,10 @@ import type {
|
|
|
12
12
|
import { t } from "@/shared/lib/i18n";
|
|
13
13
|
import { cn } from "@/shared/lib/utils";
|
|
14
14
|
|
|
15
|
-
function
|
|
15
|
+
function WorkspaceBreadcrumbWarningChip({ value }: { value: string }) {
|
|
16
16
|
return (
|
|
17
17
|
<span
|
|
18
|
-
className=
|
|
19
|
-
"inline-flex h-5 items-center rounded-sm border px-1.5 text-[10px] font-medium leading-none",
|
|
20
|
-
tone === "warning"
|
|
21
|
-
? "border-amber-200 bg-amber-50 text-amber-700"
|
|
22
|
-
: "border-gray-200 bg-gray-50 text-gray-500",
|
|
23
|
-
)}
|
|
18
|
+
className="inline-flex h-5 items-center rounded-sm border border-amber-200 bg-amber-50 px-1.5 text-[10px] font-medium leading-none text-amber-700"
|
|
24
19
|
>
|
|
25
20
|
{value}
|
|
26
21
|
</span>
|
|
@@ -116,17 +111,11 @@ export function ChatSessionWorkspaceFileBreadcrumbs({
|
|
|
116
111
|
))}
|
|
117
112
|
</div>
|
|
118
113
|
|
|
119
|
-
{breadcrumb.
|
|
114
|
+
{breadcrumb.truncated ? (
|
|
120
115
|
<div className="flex shrink-0 flex-wrap items-center justify-end gap-1">
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{breadcrumb.truncated ? (
|
|
125
|
-
<WorkspaceBreadcrumbMetaChip
|
|
126
|
-
tone="warning"
|
|
127
|
-
value={t("chatWorkspacePreviewTruncated")}
|
|
128
|
-
/>
|
|
129
|
-
) : null}
|
|
116
|
+
<WorkspaceBreadcrumbWarningChip
|
|
117
|
+
value={t("chatWorkspacePreviewTruncated")}
|
|
118
|
+
/>
|
|
130
119
|
</div>
|
|
131
120
|
) : null}
|
|
132
121
|
</div>
|
package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx
CHANGED
|
@@ -51,10 +51,10 @@ function buildPreviewBlock(params: {
|
|
|
51
51
|
path: string;
|
|
52
52
|
text: string;
|
|
53
53
|
languageHint?: string | null;
|
|
54
|
-
|
|
54
|
+
startLine?: number | null;
|
|
55
55
|
}): ChatFileOperationBlockViewModel {
|
|
56
|
-
const { languageHint,
|
|
57
|
-
const
|
|
56
|
+
const { languageHint, path, startLine, text } = params;
|
|
57
|
+
const normalizedStartLine = startLine ?? 1;
|
|
58
58
|
return {
|
|
59
59
|
key: `preview:${path}`,
|
|
60
60
|
path,
|
|
@@ -62,13 +62,13 @@ function buildPreviewBlock(params: {
|
|
|
62
62
|
lines: buildPreviewLines({
|
|
63
63
|
text,
|
|
64
64
|
kind: "context",
|
|
65
|
-
oldStartLine:
|
|
66
|
-
newStartLine:
|
|
65
|
+
oldStartLine: normalizedStartLine,
|
|
66
|
+
newStartLine: normalizedStartLine,
|
|
67
67
|
}),
|
|
68
68
|
rawText: text,
|
|
69
69
|
languageHint: languageHint ?? null,
|
|
70
|
-
oldStartLine:
|
|
71
|
-
newStartLine:
|
|
70
|
+
oldStartLine: normalizedStartLine,
|
|
71
|
+
newStartLine: normalizedStartLine,
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -154,12 +154,21 @@ function WorkspaceDiffBody({
|
|
|
154
154
|
|
|
155
155
|
function WorkspaceCodeSurface({
|
|
156
156
|
block,
|
|
157
|
+
targetColumn,
|
|
158
|
+
targetLine,
|
|
157
159
|
}: {
|
|
158
160
|
block: ChatFileOperationBlockViewModel;
|
|
161
|
+
targetColumn?: number | null;
|
|
162
|
+
targetLine?: number | null;
|
|
159
163
|
}) {
|
|
160
164
|
return (
|
|
161
165
|
<div className="h-full overflow-auto custom-scrollbar bg-white">
|
|
162
|
-
<FileOperationCodeSurface
|
|
166
|
+
<FileOperationCodeSurface
|
|
167
|
+
block={block}
|
|
168
|
+
layout="workspace"
|
|
169
|
+
targetColumn={targetColumn}
|
|
170
|
+
targetLine={targetLine}
|
|
171
|
+
/>
|
|
163
172
|
</div>
|
|
164
173
|
);
|
|
165
174
|
}
|
|
@@ -176,6 +185,8 @@ function WorkspacePreviewBody({
|
|
|
176
185
|
previewViewer,
|
|
177
186
|
previewQuery,
|
|
178
187
|
previewText,
|
|
188
|
+
targetColumn,
|
|
189
|
+
targetLine,
|
|
179
190
|
}: {
|
|
180
191
|
contentUrl: string | null;
|
|
181
192
|
contentUrlKind: WorkspaceFileContentKind | null;
|
|
@@ -188,6 +199,8 @@ function WorkspacePreviewBody({
|
|
|
188
199
|
previewViewer: "source" | "rendered" | null;
|
|
189
200
|
previewQuery: ReturnType<typeof useServerPathRead> | null | undefined;
|
|
190
201
|
previewText: string | null;
|
|
202
|
+
targetColumn?: number | null;
|
|
203
|
+
targetLine?: number | null;
|
|
191
204
|
}) {
|
|
192
205
|
if (contentUrl && contentUrlKind) {
|
|
193
206
|
return (
|
|
@@ -260,7 +273,13 @@ function WorkspacePreviewBody({
|
|
|
260
273
|
}
|
|
261
274
|
|
|
262
275
|
if (previewBlock) {
|
|
263
|
-
return
|
|
276
|
+
return (
|
|
277
|
+
<WorkspaceCodeSurface
|
|
278
|
+
block={previewBlock}
|
|
279
|
+
targetColumn={targetColumn}
|
|
280
|
+
targetLine={targetLine}
|
|
281
|
+
/>
|
|
282
|
+
);
|
|
264
283
|
}
|
|
265
284
|
|
|
266
285
|
return <WorkspaceFilePreviewStatus text={t("chatWorkspacePreviewEmpty")} />;
|
|
@@ -271,6 +290,7 @@ type ChatSessionWorkspaceFilePreviewProps = {
|
|
|
271
290
|
refreshVersion?: number;
|
|
272
291
|
sessionProjectRoot: string | null;
|
|
273
292
|
sessionWorkingDir: string | null;
|
|
293
|
+
showBreadcrumbs?: boolean;
|
|
274
294
|
onFileOpen: (action: ChatFileOpenActionViewModel) => void;
|
|
275
295
|
};
|
|
276
296
|
|
|
@@ -279,6 +299,7 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
279
299
|
refreshVersion = 0,
|
|
280
300
|
sessionProjectRoot,
|
|
281
301
|
sessionWorkingDir,
|
|
302
|
+
showBreadcrumbs = true,
|
|
282
303
|
onFileOpen,
|
|
283
304
|
}: ChatSessionWorkspaceFilePreviewProps) {
|
|
284
305
|
const isPreviewMode = file.viewMode === "preview";
|
|
@@ -287,6 +308,7 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
287
308
|
const previewQuery = useServerPathRead({
|
|
288
309
|
path: file.path,
|
|
289
310
|
basePath: sessionWorkingDir,
|
|
311
|
+
line: file.line,
|
|
290
312
|
enabled: usesServerPath,
|
|
291
313
|
});
|
|
292
314
|
const directoryQuery = useServerPathBrowse({
|
|
@@ -351,15 +373,15 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
351
373
|
path: previewQuery?.data?.resolvedPath ?? file.path,
|
|
352
374
|
text: previewText,
|
|
353
375
|
languageHint: previewQuery?.data?.languageHint ?? null,
|
|
354
|
-
|
|
376
|
+
startLine: previewQuery?.data?.startLine ?? 1,
|
|
355
377
|
});
|
|
356
378
|
}, [
|
|
357
379
|
contentUrl,
|
|
358
|
-
file.line,
|
|
359
380
|
file.path,
|
|
360
381
|
isPreviewMode,
|
|
361
382
|
previewQuery?.data?.languageHint,
|
|
362
383
|
previewQuery?.data?.resolvedPath,
|
|
384
|
+
previewQuery?.data?.startLine,
|
|
363
385
|
previewText,
|
|
364
386
|
]);
|
|
365
387
|
const isTextPreviewTruncated = !contentUrl && Boolean(previewQuery?.data?.truncated);
|
|
@@ -370,14 +392,10 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
370
392
|
path: resolvedPath,
|
|
371
393
|
kind: previewPathKind,
|
|
372
394
|
sessionProjectRoot: breadcrumbBasePath,
|
|
373
|
-
line: file.line,
|
|
374
|
-
column: file.column,
|
|
375
395
|
truncated: isTextPreviewTruncated,
|
|
376
396
|
}),
|
|
377
397
|
[
|
|
378
398
|
breadcrumbBasePath,
|
|
379
|
-
file.column,
|
|
380
|
-
file.line,
|
|
381
399
|
isTextPreviewTruncated,
|
|
382
400
|
previewPathKind,
|
|
383
401
|
resolvedPath,
|
|
@@ -386,10 +404,12 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
386
404
|
|
|
387
405
|
return (
|
|
388
406
|
<div className="flex h-full min-h-0 flex-col bg-white">
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
407
|
+
{showBreadcrumbs ? (
|
|
408
|
+
<ChatSessionWorkspaceFileBreadcrumbs
|
|
409
|
+
breadcrumb={breadcrumb}
|
|
410
|
+
onFileOpen={onFileOpen}
|
|
411
|
+
/>
|
|
412
|
+
) : null}
|
|
393
413
|
|
|
394
414
|
<div className="flex-1 min-h-0 overflow-hidden">
|
|
395
415
|
{file.viewMode === "diff" ? (
|
|
@@ -407,6 +427,8 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
407
427
|
previewViewer={previewViewer}
|
|
408
428
|
previewQuery={previewQuery}
|
|
409
429
|
previewText={previewText}
|
|
430
|
+
targetColumn={file.column}
|
|
431
|
+
targetLine={file.line}
|
|
410
432
|
/>
|
|
411
433
|
)}
|
|
412
434
|
</div>
|
package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx
CHANGED
|
@@ -84,7 +84,11 @@ function buildCompactWorkspaceTabs(
|
|
|
84
84
|
</span>
|
|
85
85
|
) : null,
|
|
86
86
|
unreadIndicator: tab.showUnreadDot ? <span aria-label={t("chatSessionUnread")} className="h-2 w-2 shrink-0 rounded-full bg-primary" /> : null,
|
|
87
|
-
closeLabel:
|
|
87
|
+
closeLabel: `${
|
|
88
|
+
tab.kind === "file"
|
|
89
|
+
? t("chatWorkspaceCloseFile")
|
|
90
|
+
: t("chatWorkspaceCloseTab")
|
|
91
|
+
}: ${tab.title}`,
|
|
88
92
|
closePlacement: "leading-hover",
|
|
89
93
|
onSelect: tab.onSelect,
|
|
90
94
|
onClose: tab.onClose,
|
|
@@ -39,6 +39,7 @@ type ChatSessionWorkspacePanelProps = {
|
|
|
39
39
|
activeSideChatDraft: ChatWorkspaceSideChatDraft | null;
|
|
40
40
|
workspaceFileTabs: readonly ChatWorkspaceFileTab[];
|
|
41
41
|
activeWorkspaceFileKey: string | null;
|
|
42
|
+
closedWorkspaceTabEntries: readonly ChatWorkspaceNavigationEntry[];
|
|
42
43
|
workspaceNavigationHistory?: readonly ChatWorkspaceNavigationEntry[];
|
|
43
44
|
workspaceNavigationHistoryIndex?: number;
|
|
44
45
|
activePanelKind?: ChatWorkspacePanelKind | null;
|
|
@@ -56,6 +57,7 @@ export function ChatSessionWorkspacePanel({
|
|
|
56
57
|
activeSideChatDraft,
|
|
57
58
|
workspaceFileTabs,
|
|
58
59
|
activeWorkspaceFileKey,
|
|
60
|
+
closedWorkspaceTabEntries,
|
|
59
61
|
workspaceNavigationHistory = [],
|
|
60
62
|
workspaceNavigationHistoryIndex = 0,
|
|
61
63
|
activePanelKind,
|
|
@@ -95,13 +97,14 @@ export function ChatSessionWorkspacePanel({
|
|
|
95
97
|
buildWorkspaceTabsViewModel({
|
|
96
98
|
resolvedChildTabs,
|
|
97
99
|
activeSideChatDraft,
|
|
100
|
+
closedWorkspaceTabEntries,
|
|
98
101
|
workspaceFileTabs,
|
|
99
102
|
activeSelection,
|
|
100
103
|
optimisticReadAtBySessionKey,
|
|
101
104
|
onSelectSession: presenter.chatThreadManager.selectChildSessionDetail,
|
|
102
105
|
onSelectFile: presenter.chatThreadManager.selectWorkspaceFile,
|
|
103
106
|
onOpenFileViewer: presenter.chatThreadManager.openWorkspaceFileViewer,
|
|
104
|
-
|
|
107
|
+
onCloseTab: presenter.chatThreadManager.closeWorkspaceTab,
|
|
105
108
|
onSelectOverview: () => {
|
|
106
109
|
if (sessionKey)
|
|
107
110
|
presenter.chatThreadManager.openWorkspaceOverview(sessionKey);
|
|
@@ -122,6 +125,7 @@ export function ChatSessionWorkspacePanel({
|
|
|
122
125
|
[
|
|
123
126
|
activeSelection,
|
|
124
127
|
activeSideChatDraft,
|
|
128
|
+
closedWorkspaceTabEntries,
|
|
125
129
|
optimisticReadAtBySessionKey,
|
|
126
130
|
presenter.chatThreadManager,
|
|
127
131
|
resolvedChildTabs,
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
buildWorkspaceTabsViewModel,
|
|
5
5
|
resolveWorkspaceSelection,
|
|
6
6
|
} from "@/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils";
|
|
7
|
+
import { createWorkspaceFileTab } from "@/features/chat/features/workspace/utils/chat-workspace-file-tab.utils";
|
|
7
8
|
import { t } from "@/shared/lib/i18n";
|
|
8
9
|
|
|
9
10
|
function createChildTab(
|
|
@@ -104,7 +105,104 @@ describe("resolveWorkspaceSelection", () => {
|
|
|
104
105
|
});
|
|
105
106
|
});
|
|
106
107
|
|
|
108
|
+
describe("createWorkspaceFileTab", () => {
|
|
109
|
+
it("uses source view for located Markdown unless rendered view is explicit", () => {
|
|
110
|
+
const locatedSource = createWorkspaceFileTab(
|
|
111
|
+
{
|
|
112
|
+
path: "README.md",
|
|
113
|
+
viewMode: "preview",
|
|
114
|
+
line: 12,
|
|
115
|
+
},
|
|
116
|
+
"parent-1",
|
|
117
|
+
);
|
|
118
|
+
const explicitRendered = createWorkspaceFileTab(
|
|
119
|
+
{
|
|
120
|
+
path: "README.md",
|
|
121
|
+
viewMode: "preview",
|
|
122
|
+
previewViewer: "rendered",
|
|
123
|
+
line: 12,
|
|
124
|
+
},
|
|
125
|
+
"parent-1",
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect(locatedSource).toMatchObject({
|
|
129
|
+
previewViewer: "source",
|
|
130
|
+
line: 12,
|
|
131
|
+
});
|
|
132
|
+
expect(explicitRendered).toMatchObject({
|
|
133
|
+
previewViewer: "rendered",
|
|
134
|
+
line: 12,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
107
139
|
describe("buildWorkspaceTabsViewModel", () => {
|
|
140
|
+
it("keeps overview fixed while every other visible workspace tab is closable", () => {
|
|
141
|
+
const childTab = createChildTab();
|
|
142
|
+
const draft = {
|
|
143
|
+
draftKey: "draft-1",
|
|
144
|
+
parentSessionKey: "parent-1",
|
|
145
|
+
};
|
|
146
|
+
const fileTab = {
|
|
147
|
+
key: "file-1",
|
|
148
|
+
parentSessionKey: "parent-1",
|
|
149
|
+
path: "README.md",
|
|
150
|
+
viewMode: "preview" as const,
|
|
151
|
+
};
|
|
152
|
+
const onCloseTab = vi.fn();
|
|
153
|
+
const tabs = buildWorkspaceTabsViewModel({
|
|
154
|
+
resolvedChildTabs: [childTab],
|
|
155
|
+
activeSideChatDraft: draft,
|
|
156
|
+
closedWorkspaceTabEntries: [],
|
|
157
|
+
workspaceFileTabs: [fileTab],
|
|
158
|
+
activeSelection: { kind: "overview" },
|
|
159
|
+
optimisticReadAtBySessionKey: {},
|
|
160
|
+
onSelectSession: vi.fn(),
|
|
161
|
+
onSelectFile: vi.fn(),
|
|
162
|
+
onOpenFileViewer: vi.fn(),
|
|
163
|
+
onCloseTab,
|
|
164
|
+
onSelectOverview: vi.fn(),
|
|
165
|
+
onSelectChildSessions: vi.fn(),
|
|
166
|
+
onSelectProjectFiles: vi.fn(),
|
|
167
|
+
onSelectCronJobs: vi.fn(),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
expect(tabs.find((tab) => tab.kind === "overview")?.onClose).toBeUndefined();
|
|
171
|
+
expect(
|
|
172
|
+
tabs.filter((tab) => tab.kind !== "overview").every((tab) => tab.onClose),
|
|
173
|
+
).toBe(true);
|
|
174
|
+
tabs.find((tab) => tab.kind === "cron")?.onClose?.();
|
|
175
|
+
expect(onCloseTab).toHaveBeenCalledWith({ kind: "cron" });
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("does not project workspace tabs that the user closed", () => {
|
|
179
|
+
const tabs = buildWorkspaceTabsViewModel({
|
|
180
|
+
resolvedChildTabs: [createChildTab()],
|
|
181
|
+
activeSideChatDraft: null,
|
|
182
|
+
closedWorkspaceTabEntries: [
|
|
183
|
+
{ kind: "project-files" },
|
|
184
|
+
{ kind: "child-session", key: "child-1" },
|
|
185
|
+
],
|
|
186
|
+
workspaceFileTabs: [],
|
|
187
|
+
activeSelection: { kind: "overview" },
|
|
188
|
+
optimisticReadAtBySessionKey: {},
|
|
189
|
+
onSelectSession: vi.fn(),
|
|
190
|
+
onSelectFile: vi.fn(),
|
|
191
|
+
onOpenFileViewer: vi.fn(),
|
|
192
|
+
onCloseTab: vi.fn(),
|
|
193
|
+
onSelectOverview: vi.fn(),
|
|
194
|
+
onSelectChildSessions: vi.fn(),
|
|
195
|
+
onSelectProjectFiles: vi.fn(),
|
|
196
|
+
onSelectCronJobs: vi.fn(),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
expect(tabs.map((tab) => tab.key)).toEqual([
|
|
200
|
+
"overview",
|
|
201
|
+
"child-sessions",
|
|
202
|
+
"cron:session",
|
|
203
|
+
]);
|
|
204
|
+
});
|
|
205
|
+
|
|
108
206
|
it("builds active and unread state from resolved tabs", () => {
|
|
109
207
|
const childTab = createChildTab({
|
|
110
208
|
lastMessageAt: "2026-06-09T10:00:00.000Z",
|
|
@@ -115,13 +213,14 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
115
213
|
const tabs = buildWorkspaceTabsViewModel({
|
|
116
214
|
resolvedChildTabs: [childTab],
|
|
117
215
|
activeSideChatDraft: null,
|
|
216
|
+
closedWorkspaceTabEntries: [],
|
|
118
217
|
workspaceFileTabs: [],
|
|
119
218
|
activeSelection: null,
|
|
120
219
|
optimisticReadAtBySessionKey: {},
|
|
121
220
|
onSelectSession,
|
|
122
221
|
onSelectFile: vi.fn(),
|
|
123
222
|
onOpenFileViewer: vi.fn(),
|
|
124
|
-
|
|
223
|
+
onCloseTab: vi.fn(),
|
|
125
224
|
onSelectOverview: vi.fn(),
|
|
126
225
|
onSelectChildSessions: vi.fn(),
|
|
127
226
|
onSelectProjectFiles: vi.fn(),
|
|
@@ -150,6 +249,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
150
249
|
const tabs = buildWorkspaceTabsViewModel({
|
|
151
250
|
resolvedChildTabs: [childTab],
|
|
152
251
|
activeSideChatDraft: draft,
|
|
252
|
+
closedWorkspaceTabEntries: [],
|
|
153
253
|
workspaceFileTabs: [],
|
|
154
254
|
activeSelection: {
|
|
155
255
|
kind: "side-chat-draft",
|
|
@@ -159,7 +259,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
159
259
|
onSelectSession: vi.fn(),
|
|
160
260
|
onSelectFile: vi.fn(),
|
|
161
261
|
onOpenFileViewer: vi.fn(),
|
|
162
|
-
|
|
262
|
+
onCloseTab: vi.fn(),
|
|
163
263
|
onSelectOverview: vi.fn(),
|
|
164
264
|
onSelectChildSessions: vi.fn(),
|
|
165
265
|
onSelectProjectFiles: vi.fn(),
|
|
@@ -202,6 +302,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
202
302
|
const tabs = buildWorkspaceTabsViewModel({
|
|
203
303
|
resolvedChildTabs: [],
|
|
204
304
|
activeSideChatDraft: null,
|
|
305
|
+
closedWorkspaceTabEntries: [],
|
|
205
306
|
workspaceFileTabs: [sourceTab, renderedTab],
|
|
206
307
|
activeSelection: {
|
|
207
308
|
kind: "file",
|
|
@@ -211,7 +312,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
211
312
|
onSelectSession: vi.fn(),
|
|
212
313
|
onSelectFile: vi.fn(),
|
|
213
314
|
onOpenFileViewer,
|
|
214
|
-
|
|
315
|
+
onCloseTab: vi.fn(),
|
|
215
316
|
onSelectOverview: vi.fn(),
|
|
216
317
|
onSelectChildSessions: vi.fn(),
|
|
217
318
|
onSelectProjectFiles: vi.fn(),
|