@nextclaw/ui 0.15.4 → 0.15.5
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 +17 -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-BOXOrpcJ.js → api-IlX_CbwU.js} +2 -2
- package/dist/assets/app-presenter-provider-Bbl_MVbg.js +106 -0
- package/dist/assets/{appearance-settings-page-fLIJbx1C.js → appearance-settings-page-80fLa4-9.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-CN7Shpij.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-R7M6pzp6.js} +1 -1
- package/dist/assets/{chat-page-B42UUIFR.js → chat-page-152YuwfU.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-BlfvfmTm.js} +1 -1
- package/dist/assets/{confirm-dialog-GSXIvoRU.js → confirm-dialog-Dt8Kdbgp.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-7bmNeWIC.js → desktop-update-config-DreMJu9z.js} +1 -1
- 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-D5ycbwCo.js} +1 -1
- package/dist/assets/dist-dw-gAfM_.js +1 -0
- package/dist/assets/{doc-browser-D0monHjG.js → doc-browser-C9u7N9vH.js} +1 -1
- package/dist/assets/doc-browser-DJQ5XPsi2.js +1 -0
- package/dist/assets/{doc-browser-context-CGwEOhBy.js → doc-browser-context-CCdW9TJf.js} +1 -1
- package/dist/assets/{docx-preview-eFH9DRsS.js → docx-preview-zis3U0Fa.js} +1 -1
- package/dist/assets/{download-DiP9zx-J.js → download-CyPgglKr.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-BahW1sl3.js} +1 -1
- package/dist/assets/{eye-suvKmtwn.js → eye-D8gGXMkD.js} +1 -1
- package/dist/assets/flowDiagram-23GEKE2U-BoKk8RRq.js +1 -0
- package/dist/assets/{folder-CMELbQGG.js → folder-DGWqFDvE.js} +1 -1
- package/dist/assets/{form-actions-CUAzpNe_.js → form-actions-D2imZLnU.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-0av6WO9-.css +1 -0
- package/dist/assets/index-CT0iYlxV.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-DtKek-qG.js +1 -0
- package/dist/assets/{logo-badge-Cu5UGH_4.js → logo-badge-CuPetu-v.js} +1 -1
- package/dist/assets/map-Bdri5UL5.js +1 -0
- package/dist/assets/mcp-marketplace-page-4qMwFDpz.js +1 -0
- package/dist/assets/{mcp-marketplace-page-BUzHDwW6.js → mcp-marketplace-page-BbxN5aZF.js} +1 -1
- 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-DiJcvBML.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-BwgE-Zwf.js +1 -0
- package/dist/assets/{popover-DImguRok.js → popover-Btp7KVc3.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-DZMtoAJG.js} +1 -1
- package/dist/assets/{providers-config-page-BKPo8SjH.js → providers-config-page-DfiWveEF.js} +1 -1
- 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-BY-U3h3t.js} +1 -1
- package/dist/assets/{refresh-cw-CHLBzWWj.js → refresh-cw-Cme5qFej.js} +1 -1
- package/dist/assets/remote-BaVECEZw.js +1 -0
- package/dist/assets/requirementDiagram-TGXJPOKE-EmFph0H_.js +84 -0
- package/dist/assets/rotate-cw-CMRZxIkH.js +1 -0
- package/dist/assets/rough.esm-wJ1d3nQl.js +1 -0
- package/dist/assets/{runtime-config-page-1Axv4QGu.js → runtime-config-page-wygwvMB4.js} +1 -1
- package/dist/assets/sankeyDiagram-HTMAVEWB-BXWB5Ugi.js +40 -0
- package/dist/assets/{save-BABzyrjB.js → save-DNg2yJTS.js} +1 -1
- package/dist/assets/{search-BTqxG3ZG.js → search-3ykfrAFt.js} +1 -1
- package/dist/assets/{search-config-page-BkKKmxmS.js → search-config-page-DrVKa_Ls.js} +1 -1
- package/dist/assets/{secrets-config-page-CWJMyu-k.js → secrets-config-page-B39uQ5kF.js} +1 -1
- package/dist/assets/security-config-BPzet76z.js +1 -0
- package/dist/assets/{select-TYZDBNmq.js → select-B5EecXJt.js} +1 -1
- package/dist/assets/sequenceDiagram-DBY2YBRQ-ClKnO7v0.js +162 -0
- package/dist/assets/{setting-row-DR23Z_5I.js → setting-row-Qv1Ps79v.js} +1 -1
- package/dist/assets/{settings-2-D8WWcBnw.js → settings-2-D-3um9Az.js} +1 -1
- package/dist/assets/sizeCapture-X5ZJPWSS-DSo-t5ou.js +1 -0
- package/dist/assets/{skeleton-CloHeg0S.js → skeleton-BgkzQd4U.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-BVD8gp3y.js} +1 -1
- package/dist/assets/{tag-chip-mCc23Rhb.js → tag-chip-0qn-f3Bo.js} +1 -1
- package/dist/assets/timeline-definition-FHXFAJF6-D4ar8IQY.js +120 -0
- package/dist/assets/{trash-2-SAW1Z4Po.js → trash-2-cnsMppRC.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-BucdaK23.js → use-config-D6yx0lb0.js} +1 -1
- package/dist/assets/{use-confirm-dialog-C95F6sT1.js → use-confirm-dialog-C_o0eQeH.js} +1 -1
- package/dist/assets/{use-viewport-layout-C6m3Nte7.js → use-viewport-layout-BWav4KCL.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-B3o1dWR5.js +1 -0
- package/dist/assets/xychartDiagram-FW5EYKEG-C9JCzsZF.js +7 -0
- package/dist/index.html +33 -32
- package/package.json +5 -5
- package/src/features/chat/components/chat-popover-content.tsx +1 -26
- package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +28 -11
- package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +43 -0
- package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +14 -10
- package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +51 -0
- package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +61 -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/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/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/shared/components/common/__tests__/brand-header.test.tsx +17 -7
- package/src/shared/components/common/brand-header.tsx +34 -34
- package/src/shared/hooks/use-server-path-read.ts +10 -5
- package/src/shared/lib/api/types.ts +3 -3
- package/src/shared/lib/api/utils/server-path.utils.ts +1 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +8 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +8 -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/app-presenter-provider-CkHLbvZQ.js +0 -106
- 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-ohUAdfqJ.js +0 -1
- package/dist/assets/plus-tywizkeY.js +0 -1
- package/dist/assets/remote-DXJryUxB.js +0 -1
- package/dist/assets/rotate-cw-BefO5brU.js +0 -1
- package/dist/assets/security-config-DeQUIXfi.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/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
|
@@ -24,6 +24,7 @@ describe('ChatThreadManager workspace pages', () => {
|
|
|
24
24
|
activeWorkspacePanelKind: null,
|
|
25
25
|
activeChildSessionKey: null,
|
|
26
26
|
activeWorkspaceFileKey: null,
|
|
27
|
+
closedWorkspaceTabEntries: [],
|
|
27
28
|
workspaceNavigationHistory: [],
|
|
28
29
|
workspaceNavigationHistoryIndex: 0,
|
|
29
30
|
},
|
|
@@ -73,4 +74,28 @@ describe('ChatThreadManager workspace pages', () => {
|
|
|
73
74
|
activeWorkspacePanelKind: null,
|
|
74
75
|
});
|
|
75
76
|
});
|
|
77
|
+
|
|
78
|
+
it('closes a workspace page, restores overview, and reopens the page on demand', () => {
|
|
79
|
+
const manager = new ChatThreadManager(
|
|
80
|
+
createUiManager(),
|
|
81
|
+
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
manager.openWorkspaceOverview('parent-session-1');
|
|
85
|
+
manager.openProjectFiles('parent-session-1');
|
|
86
|
+
manager.closeWorkspaceTab({ kind: 'project-files' });
|
|
87
|
+
|
|
88
|
+
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
89
|
+
activeWorkspacePanelKind: 'overview',
|
|
90
|
+
closedWorkspaceTabEntries: [{ kind: 'project-files' }],
|
|
91
|
+
workspaceNavigationHistory: [{ kind: 'overview' }],
|
|
92
|
+
workspaceNavigationHistoryIndex: 0,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
manager.openProjectFiles('parent-session-1');
|
|
96
|
+
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
97
|
+
activeWorkspacePanelKind: 'project-files',
|
|
98
|
+
closedWorkspaceTabEntries: [],
|
|
99
|
+
});
|
|
100
|
+
});
|
|
76
101
|
});
|
|
@@ -60,6 +60,7 @@ beforeEach(() => {
|
|
|
60
60
|
activeSideChatDraft: null,
|
|
61
61
|
workspaceFileTabs: [],
|
|
62
62
|
activeWorkspaceFileKey: null,
|
|
63
|
+
closedWorkspaceTabEntries: [],
|
|
63
64
|
workspaceNavigationHistory: [],
|
|
64
65
|
workspaceNavigationHistoryIndex: 0,
|
|
65
66
|
},
|
|
@@ -504,7 +505,10 @@ describe('ChatThreadManager workspace navigation', () => {
|
|
|
504
505
|
label: 'README.md',
|
|
505
506
|
viewMode: 'preview',
|
|
506
507
|
});
|
|
507
|
-
manager.
|
|
508
|
+
manager.closeWorkspaceTab({
|
|
509
|
+
kind: 'file',
|
|
510
|
+
key: 'parent-session-1::preview:rendered::README.md',
|
|
511
|
+
});
|
|
508
512
|
|
|
509
513
|
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
510
514
|
activeWorkspacePanelKind: 'child-session',
|
|
@@ -24,13 +24,13 @@ import { normalizeChatWorkspacePanelWidth } from '@/features/chat/features/works
|
|
|
24
24
|
import { t } from '@/shared/lib/i18n';
|
|
25
25
|
import {
|
|
26
26
|
areWorkspaceNavigationEntriesEqual,
|
|
27
|
+
closeWorkspaceTabSnapshot,
|
|
27
28
|
createWorkspaceSelectionPatch,
|
|
28
29
|
createSideChatDraft,
|
|
29
30
|
materializeSideChatDraftSnapshot,
|
|
30
31
|
upsertChildSessionTab,
|
|
31
32
|
} from '@/features/chat/features/workspace/utils/chat-thread-workspace-session.utils';
|
|
32
33
|
import {
|
|
33
|
-
filterNavigationHistoryEntries,
|
|
34
34
|
pushNavigationHistoryEntry,
|
|
35
35
|
stepNavigationHistory,
|
|
36
36
|
} from '@/shared/lib/navigation-history';
|
|
@@ -96,6 +96,7 @@ export class ChatThreadManager {
|
|
|
96
96
|
activeSideChatDraft: null,
|
|
97
97
|
workspaceFileTabs: [],
|
|
98
98
|
activeWorkspaceFileKey: null,
|
|
99
|
+
closedWorkspaceTabEntries: [],
|
|
99
100
|
workspaceNavigationHistory: [],
|
|
100
101
|
workspaceNavigationHistoryIndex: 0,
|
|
101
102
|
});
|
|
@@ -163,8 +164,16 @@ export class ChatThreadManager {
|
|
|
163
164
|
entry,
|
|
164
165
|
areWorkspaceNavigationEntriesEqual,
|
|
165
166
|
);
|
|
167
|
+
const closedWorkspaceTabEntries =
|
|
168
|
+
patch.workspacePanelParentKey &&
|
|
169
|
+
patch.workspacePanelParentKey !== snapshot.workspacePanelParentKey
|
|
170
|
+
? []
|
|
171
|
+
: snapshot.closedWorkspaceTabEntries.filter(
|
|
172
|
+
(candidate) => !areWorkspaceNavigationEntriesEqual(candidate, entry),
|
|
173
|
+
);
|
|
166
174
|
useChatThreadStore.getState().setSnapshot({
|
|
167
175
|
...patch,
|
|
176
|
+
closedWorkspaceTabEntries,
|
|
168
177
|
workspaceNavigationHistory: [...history.entries],
|
|
169
178
|
workspaceNavigationHistoryIndex: history.index,
|
|
170
179
|
});
|
|
@@ -461,44 +470,12 @@ export class ChatThreadManager {
|
|
|
461
470
|
});
|
|
462
471
|
};
|
|
463
472
|
|
|
464
|
-
|
|
465
|
-
const normalizedFileKey = fileKey.trim();
|
|
466
|
-
if (!normalizedFileKey) {
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
473
|
+
closeWorkspaceTab = (entry: ChatWorkspaceNavigationEntry) => {
|
|
469
474
|
const { snapshot } = useChatThreadStore.getState();
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
(
|
|
473
|
-
);
|
|
474
|
-
const history = filterNavigationHistoryEntries(
|
|
475
|
-
{
|
|
476
|
-
entries: snapshot.workspaceNavigationHistory,
|
|
477
|
-
index: snapshot.workspaceNavigationHistoryIndex,
|
|
478
|
-
},
|
|
479
|
-
(entry) => entry.kind !== 'file' || entry.key !== normalizedFileKey,
|
|
480
|
-
);
|
|
481
|
-
const nextPatch: Partial<ChatThreadSnapshot> = {
|
|
482
|
-
workspaceFileTabs: nextTabs,
|
|
483
|
-
workspaceNavigationHistory: [...history.entries],
|
|
484
|
-
workspaceNavigationHistoryIndex: history.index,
|
|
485
|
-
};
|
|
486
|
-
if (activeWorkspaceFileKey === normalizedFileKey) {
|
|
487
|
-
const nextSnapshot = {
|
|
488
|
-
...snapshot,
|
|
489
|
-
workspaceFileTabs: nextTabs,
|
|
490
|
-
};
|
|
491
|
-
const restoreEntry = history.entries[history.index];
|
|
492
|
-
const restorePatch = restoreEntry
|
|
493
|
-
? createWorkspaceSelectionPatch(restoreEntry, nextSnapshot)
|
|
494
|
-
: null;
|
|
495
|
-
Object.assign(nextPatch, restorePatch ?? {
|
|
496
|
-
activeWorkspacePanelKind: null,
|
|
497
|
-
activeSideChatDraft: null,
|
|
498
|
-
activeWorkspaceFileKey: null,
|
|
499
|
-
});
|
|
475
|
+
const patch = closeWorkspaceTabSnapshot(snapshot, entry);
|
|
476
|
+
if (patch) {
|
|
477
|
+
useChatThreadStore.getState().setSnapshot(patch);
|
|
500
478
|
}
|
|
501
|
-
useChatThreadStore.getState().setSnapshot(nextPatch);
|
|
502
479
|
};
|
|
503
480
|
|
|
504
481
|
closeWorkspacePanel = () => {
|
|
@@ -508,6 +485,7 @@ export class ChatThreadManager {
|
|
|
508
485
|
activeChildSessionKey: null,
|
|
509
486
|
activeSideChatDraft: null,
|
|
510
487
|
activeWorkspaceFileKey: null,
|
|
488
|
+
closedWorkspaceTabEntries: [],
|
|
511
489
|
workspaceNavigationHistory: [],
|
|
512
490
|
workspaceNavigationHistoryIndex: 0,
|
|
513
491
|
});
|
|
@@ -28,6 +28,7 @@ function resetChatThreadStore() {
|
|
|
28
28
|
activeSideChatDraft: null,
|
|
29
29
|
workspaceFileTabs: [],
|
|
30
30
|
activeWorkspaceFileKey: null,
|
|
31
|
+
closedWorkspaceTabEntries: [],
|
|
31
32
|
workspaceNavigationHistory: [],
|
|
32
33
|
workspaceNavigationHistoryIndex: 0,
|
|
33
34
|
workspacePanelWidth: CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
|
|
@@ -64,6 +65,10 @@ describe('chat thread workspace panel persistence', () => {
|
|
|
64
65
|
},
|
|
65
66
|
],
|
|
66
67
|
activeWorkspaceFileKey: 'session-1::preview::README.md',
|
|
68
|
+
closedWorkspaceTabEntries: [
|
|
69
|
+
{ kind: 'project-files' },
|
|
70
|
+
{ kind: 'child-session', key: 'child-session-2' },
|
|
71
|
+
],
|
|
67
72
|
workspaceNavigationHistory: [
|
|
68
73
|
{ kind: 'child-session', key: 'child-session-1' },
|
|
69
74
|
{ kind: 'file', key: 'session-1::preview::README.md' },
|
|
@@ -79,6 +84,10 @@ describe('chat thread workspace panel persistence', () => {
|
|
|
79
84
|
workspacePanelParentKey: 'session-1',
|
|
80
85
|
activeWorkspacePanelKind: 'file',
|
|
81
86
|
activeWorkspaceFileKey: 'session-1::preview::README.md',
|
|
87
|
+
closedWorkspaceTabEntries: [
|
|
88
|
+
{ kind: 'project-files' },
|
|
89
|
+
{ kind: 'child-session', key: 'child-session-2' },
|
|
90
|
+
],
|
|
82
91
|
workspaceNavigationHistory: [
|
|
83
92
|
{ kind: 'child-session', key: 'child-session-1' },
|
|
84
93
|
{ kind: 'file', key: 'session-1::preview::README.md' },
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
|
|
16
16
|
normalizeChatWorkspacePanelWidth,
|
|
17
17
|
} from '@/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils';
|
|
18
|
+
import { createWorkspaceNavigationEntryFromSnapshot } from '@/features/chat/features/workspace/utils/chat-thread-workspace-session.utils';
|
|
18
19
|
|
|
19
20
|
export type ChatChildSessionTab = {
|
|
20
21
|
sessionKey: string;
|
|
@@ -92,6 +93,7 @@ export type ChatThreadSnapshot = {
|
|
|
92
93
|
activeSideChatDraft?: ChatWorkspaceSideChatDraft | null;
|
|
93
94
|
workspaceFileTabs: ChatWorkspaceFileTab[];
|
|
94
95
|
activeWorkspaceFileKey?: string | null;
|
|
96
|
+
closedWorkspaceTabEntries: ChatWorkspaceNavigationEntry[];
|
|
95
97
|
workspaceNavigationHistory: ChatWorkspaceNavigationEntry[];
|
|
96
98
|
workspaceNavigationHistoryIndex: number;
|
|
97
99
|
workspacePanelWidth: number;
|
|
@@ -114,6 +116,7 @@ type PersistedChatThreadStore = {
|
|
|
114
116
|
activeChildSessionKey?: unknown;
|
|
115
117
|
workspaceFileTabs?: unknown;
|
|
116
118
|
activeWorkspaceFileKey?: unknown;
|
|
119
|
+
closedWorkspaceTabEntries?: unknown;
|
|
117
120
|
workspaceNavigationHistory?: unknown;
|
|
118
121
|
workspaceNavigationHistoryIndex?: unknown;
|
|
119
122
|
workspacePanelWidth?: unknown;
|
|
@@ -127,6 +130,7 @@ type PersistedChatWorkspaceSnapshot = Pick<
|
|
|
127
130
|
| 'activeChildSessionKey'
|
|
128
131
|
| 'workspaceFileTabs'
|
|
129
132
|
| 'activeWorkspaceFileKey'
|
|
133
|
+
| 'closedWorkspaceTabEntries'
|
|
130
134
|
| 'workspaceNavigationHistory'
|
|
131
135
|
| 'workspaceNavigationHistoryIndex'
|
|
132
136
|
| 'workspacePanelWidth'
|
|
@@ -159,6 +163,7 @@ const initialSnapshot: ChatThreadSnapshot = {
|
|
|
159
163
|
activeSideChatDraft: null,
|
|
160
164
|
workspaceFileTabs: [],
|
|
161
165
|
activeWorkspaceFileKey: null,
|
|
166
|
+
closedWorkspaceTabEntries: [],
|
|
162
167
|
workspaceNavigationHistory: [],
|
|
163
168
|
workspaceNavigationHistoryIndex: 0,
|
|
164
169
|
workspacePanelWidth: CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
|
|
@@ -218,42 +223,6 @@ function normalizePersistedWorkspaceNavigationEntry(
|
|
|
218
223
|
};
|
|
219
224
|
}
|
|
220
225
|
|
|
221
|
-
function createWorkspaceNavigationEntryFromSnapshot({
|
|
222
|
-
activeChildSessionKey,
|
|
223
|
-
activeWorkspaceFileKey,
|
|
224
|
-
activeWorkspacePanelKind,
|
|
225
|
-
}: {
|
|
226
|
-
activeWorkspacePanelKind: ChatThreadSnapshot['activeWorkspacePanelKind'];
|
|
227
|
-
activeChildSessionKey: string | null;
|
|
228
|
-
activeWorkspaceFileKey: string | null;
|
|
229
|
-
}): ChatWorkspaceNavigationEntry | null {
|
|
230
|
-
if (activeWorkspacePanelKind === 'overview') {
|
|
231
|
-
return { kind: 'overview' };
|
|
232
|
-
}
|
|
233
|
-
if (activeWorkspacePanelKind === 'child-sessions') {
|
|
234
|
-
return { kind: 'child-sessions' };
|
|
235
|
-
}
|
|
236
|
-
if (activeWorkspacePanelKind === 'project-files') {
|
|
237
|
-
return { kind: 'project-files' };
|
|
238
|
-
}
|
|
239
|
-
if (activeWorkspacePanelKind === 'cron') {
|
|
240
|
-
return { kind: 'cron' };
|
|
241
|
-
}
|
|
242
|
-
if (activeWorkspacePanelKind === 'child-session' && activeChildSessionKey) {
|
|
243
|
-
return {
|
|
244
|
-
kind: 'child-session',
|
|
245
|
-
key: activeChildSessionKey,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
if (activeWorkspacePanelKind === 'file' && activeWorkspaceFileKey) {
|
|
249
|
-
return {
|
|
250
|
-
kind: 'file',
|
|
251
|
-
key: activeWorkspaceFileKey,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
226
|
function normalizePersistedWorkspaceSnapshot(
|
|
258
227
|
value: unknown,
|
|
259
228
|
): PersistedChatWorkspaceSnapshot | null {
|
|
@@ -287,9 +256,17 @@ function normalizePersistedWorkspaceSnapshot(
|
|
|
287
256
|
? null
|
|
288
257
|
: activeWorkspacePanelKind;
|
|
289
258
|
const activeChildSessionKey = normalizeOptionalString(value.activeChildSessionKey);
|
|
259
|
+
const closedWorkspaceTabEntries = Array.isArray(value.closedWorkspaceTabEntries)
|
|
260
|
+
? value.closedWorkspaceTabEntries
|
|
261
|
+
.map(normalizePersistedWorkspaceNavigationEntry)
|
|
262
|
+
.filter((entry): entry is ChatWorkspaceNavigationEntry =>
|
|
263
|
+
entry !== null && entry.kind !== 'overview',
|
|
264
|
+
)
|
|
265
|
+
: [];
|
|
290
266
|
const fallbackHistoryEntry = createWorkspaceNavigationEntryFromSnapshot({
|
|
291
267
|
activeWorkspacePanelKind: resolvedActiveWorkspacePanelKind,
|
|
292
268
|
activeChildSessionKey,
|
|
269
|
+
activeSideChatDraft: null,
|
|
293
270
|
activeWorkspaceFileKey: resolvedActiveWorkspaceFileKey,
|
|
294
271
|
});
|
|
295
272
|
const normalizedNavigationHistory = Array.isArray(value.workspaceNavigationHistory)
|
|
@@ -320,6 +297,7 @@ function normalizePersistedWorkspaceSnapshot(
|
|
|
320
297
|
activeChildSessionKey,
|
|
321
298
|
workspaceFileTabs,
|
|
322
299
|
activeWorkspaceFileKey: resolvedActiveWorkspaceFileKey,
|
|
300
|
+
closedWorkspaceTabEntries,
|
|
323
301
|
workspaceNavigationHistory,
|
|
324
302
|
workspaceNavigationHistoryIndex,
|
|
325
303
|
workspacePanelWidth: normalizeChatWorkspacePanelWidth(
|
|
@@ -369,6 +347,8 @@ export const useChatThreadStore = create<ChatThreadStore>()(
|
|
|
369
347
|
)
|
|
370
348
|
.map(toPersistedWorkspaceFileTab),
|
|
371
349
|
activeWorkspaceFileKey: state.snapshot.activeWorkspaceFileKey,
|
|
350
|
+
closedWorkspaceTabEntries: state.snapshot.closedWorkspaceTabEntries
|
|
351
|
+
.filter((entry) => entry.kind !== 'overview' && entry.kind !== 'side-chat-draft'),
|
|
372
352
|
workspaceNavigationHistory,
|
|
373
353
|
workspaceNavigationHistoryIndex,
|
|
374
354
|
workspacePanelWidth: state.snapshot.workspacePanelWidth,
|
|
@@ -100,7 +100,7 @@ describe('BrandHeader', () => {
|
|
|
100
100
|
expect(version).toBeTruthy();
|
|
101
101
|
expect(screen.getAllByText('v0.18.11')).toHaveLength(1);
|
|
102
102
|
await user.hover(version);
|
|
103
|
-
expect(await screen.
|
|
103
|
+
expect((await screen.findByRole('tooltip')).textContent).toBe('v0.18.11');
|
|
104
104
|
expect(screen.getByText('下载 50%')).toBeTruthy();
|
|
105
105
|
expect(screen.queryByRole('button', { name: '更新' })).toBeNull();
|
|
106
106
|
});
|
|
@@ -145,6 +145,7 @@ describe('BrandHeader', () => {
|
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
it('shows a warning icon with the blocked update reason instead of a visible failure label', async () => {
|
|
148
|
+
const user = userEvent.setup();
|
|
148
149
|
useRuntimeUpdateStore.setState({
|
|
149
150
|
supported: true,
|
|
150
151
|
initialized: true,
|
|
@@ -180,13 +181,19 @@ describe('BrandHeader', () => {
|
|
|
180
181
|
const issueIcon = screen.getByLabelText('更新被阻塞');
|
|
181
182
|
|
|
182
183
|
expect(issueIcon.textContent).toBe('!');
|
|
183
|
-
expect(issueIcon.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
expect(issueIcon.hasAttribute('title')).toBe(false);
|
|
185
|
+
|
|
186
|
+
await user.hover(issueIcon);
|
|
187
|
+
|
|
188
|
+
const tooltip = await screen.findByRole('tooltip');
|
|
189
|
+
expect(tooltip.textContent).toContain('更新被阻塞');
|
|
190
|
+
expect(tooltip.textContent).toContain('根因:缺少更新签名公钥,无法验证更新包来源');
|
|
191
|
+
expect(tooltip.textContent).toContain('Runtime bundle updates require a configured update public key.');
|
|
192
|
+
expect(tooltip.textContent).toContain('Set NEXTCLAW_UPDATE_BUNDLE_PUBLIC_KEY');
|
|
187
193
|
});
|
|
188
194
|
|
|
189
195
|
it('uses the failed update wording only for failed snapshots', async () => {
|
|
196
|
+
const user = userEvent.setup();
|
|
190
197
|
useRuntimeUpdateStore.setState({
|
|
191
198
|
supported: true,
|
|
192
199
|
initialized: true,
|
|
@@ -221,8 +228,11 @@ describe('BrandHeader', () => {
|
|
|
221
228
|
const issueIcon = screen.getByLabelText('更新失败');
|
|
222
229
|
|
|
223
230
|
expect(issueIcon.textContent).toBe('!');
|
|
224
|
-
|
|
225
|
-
|
|
231
|
+
await user.hover(issueIcon);
|
|
232
|
+
|
|
233
|
+
const tooltip = await screen.findByRole('tooltip');
|
|
234
|
+
expect(tooltip.textContent).toContain('更新失败');
|
|
235
|
+
expect(tooltip.textContent).toContain('runtime bundle sha256 mismatch');
|
|
226
236
|
expect(screen.queryByText('更新被阻塞')).toBeNull();
|
|
227
237
|
});
|
|
228
238
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { UpdateSnapshot } from '@nextclaw/shared';
|
|
2
2
|
import { runtimeUpdateManager, useRuntimeUpdateStore } from '@/features/system-status';
|
|
3
3
|
import { useAppMeta } from '@/shared/hooks/use-app-meta';
|
|
4
|
-
import {
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
5
|
import { RuntimeStatusEntry } from '@/app/components/layout/runtime-status-entry';
|
|
6
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/shared/components/ui/tooltip';
|
|
6
7
|
import { t } from '@/shared/lib/i18n';
|
|
7
8
|
import { cn } from '@/shared/lib/utils';
|
|
8
9
|
|
|
@@ -57,33 +58,26 @@ function BrandVersionLabel({
|
|
|
57
58
|
versionLabel: string;
|
|
58
59
|
density: BrandHeaderProps['density'];
|
|
59
60
|
}) {
|
|
60
|
-
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
|
|
61
61
|
const isChromeDensity = density === 'chrome';
|
|
62
62
|
|
|
63
63
|
return (
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{isTooltipOpen ? (
|
|
82
|
-
<span className="pointer-events-none absolute left-0 top-full z-[var(--z-tooltip)] mt-1 w-max max-w-none whitespace-nowrap rounded-md border bg-popover px-3 py-1.5 text-xs font-medium text-popover-foreground shadow-md">
|
|
83
|
-
{versionLabel}
|
|
84
|
-
</span>
|
|
85
|
-
) : null}
|
|
86
|
-
</span>
|
|
64
|
+
<TooltipProvider delayDuration={250}>
|
|
65
|
+
<Tooltip>
|
|
66
|
+
<TooltipTrigger asChild>
|
|
67
|
+
<span
|
|
68
|
+
tabIndex={0}
|
|
69
|
+
aria-label={versionLabel}
|
|
70
|
+
className={cn(
|
|
71
|
+
'block min-w-0 flex-1 truncate font-medium text-gray-500 outline-none',
|
|
72
|
+
isChromeDensity ? 'text-[12px]' : 'text-[12px]',
|
|
73
|
+
)}
|
|
74
|
+
>
|
|
75
|
+
{versionLabel}
|
|
76
|
+
</span>
|
|
77
|
+
</TooltipTrigger>
|
|
78
|
+
<TooltipContent side="bottom" className="text-xs">{versionLabel}</TooltipContent>
|
|
79
|
+
</Tooltip>
|
|
80
|
+
</TooltipProvider>
|
|
87
81
|
);
|
|
88
82
|
}
|
|
89
83
|
|
|
@@ -149,15 +143,21 @@ function RuntimeUpdateIssueIcon({ snapshot }: { snapshot: UpdateSnapshot }) {
|
|
|
149
143
|
: null;
|
|
150
144
|
const tooltip = [title, rootCause, diagnostic, recoveryCommand].filter(Boolean).join('\n');
|
|
151
145
|
return (
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
146
|
+
<TooltipProvider delayDuration={250}>
|
|
147
|
+
<Tooltip>
|
|
148
|
+
<TooltipTrigger asChild>
|
|
149
|
+
<span
|
|
150
|
+
role="img"
|
|
151
|
+
aria-label={title}
|
|
152
|
+
tabIndex={0}
|
|
153
|
+
className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-amber-50 text-[13px] font-bold leading-none text-amber-700 ring-1 ring-amber-100 outline-none focus-visible:ring-2 focus-visible:ring-amber-300"
|
|
154
|
+
>
|
|
155
|
+
!
|
|
156
|
+
</span>
|
|
157
|
+
</TooltipTrigger>
|
|
158
|
+
<TooltipContent side="bottom" className="max-w-80 whitespace-pre-line break-words text-xs leading-relaxed">{tooltip}</TooltipContent>
|
|
159
|
+
</Tooltip>
|
|
160
|
+
</TooltipProvider>
|
|
161
161
|
);
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -4,27 +4,32 @@ import { fetchServerPathRead } from '@/shared/lib/api';
|
|
|
4
4
|
export function buildServerPathReadQueryKey(params: {
|
|
5
5
|
path?: string | null;
|
|
6
6
|
basePath?: string | null;
|
|
7
|
+
line?: number | null;
|
|
7
8
|
}) {
|
|
8
|
-
return ['server-path-read', params.path?.trim() ?? '', params.basePath ?? null] as const;
|
|
9
|
+
return ['server-path-read', params.path?.trim() ?? '', params.basePath ?? null, params.line ?? null] as const;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export function useServerPathRead(params: {
|
|
12
13
|
path?: string | null;
|
|
13
14
|
basePath?: string | null;
|
|
15
|
+
line?: number | null;
|
|
14
16
|
enabled?: boolean;
|
|
15
17
|
}) {
|
|
16
|
-
const
|
|
18
|
+
const { basePath, enabled = true, line, path } = params;
|
|
19
|
+
const normalizedPath = path?.trim() ?? '';
|
|
17
20
|
return useQuery({
|
|
18
21
|
queryKey: buildServerPathReadQueryKey({
|
|
19
22
|
path: normalizedPath,
|
|
20
|
-
basePath
|
|
23
|
+
basePath,
|
|
24
|
+
line,
|
|
21
25
|
}),
|
|
22
26
|
queryFn: () =>
|
|
23
27
|
fetchServerPathRead({
|
|
24
28
|
path: normalizedPath,
|
|
25
|
-
basePath
|
|
29
|
+
basePath,
|
|
30
|
+
line,
|
|
26
31
|
}),
|
|
27
|
-
enabled:
|
|
32
|
+
enabled: enabled && normalizedPath.length > 0,
|
|
28
33
|
staleTime: 0,
|
|
29
34
|
});
|
|
30
35
|
}
|
|
@@ -316,8 +316,8 @@ export type SessionSkillEntryView = {
|
|
|
316
316
|
ref: string;
|
|
317
317
|
name: string;
|
|
318
318
|
path: string;
|
|
319
|
-
scope: 'builtin' | 'project' | 'workspace';
|
|
320
|
-
source: 'builtin' | 'project' | 'workspace';
|
|
319
|
+
scope: 'builtin' | 'global' | 'project' | 'workspace';
|
|
320
|
+
source: 'builtin' | 'global' | 'project' | 'workspace';
|
|
321
321
|
available: boolean;
|
|
322
322
|
description?: string;
|
|
323
323
|
descriptionZh?: string;
|
|
@@ -367,7 +367,7 @@ export type ServerPathBrowseView = {
|
|
|
367
367
|
entries: ServerPathEntryView[];
|
|
368
368
|
};
|
|
369
369
|
|
|
370
|
-
export type ServerPathReadView = { requestedPath: string; resolvedPath: string; kind: "text" | "markdown" | "binary"; sizeBytes: number; truncated: boolean; text?: string; languageHint?: string | null };
|
|
370
|
+
export type ServerPathReadView = { requestedPath: string; resolvedPath: string; kind: "text" | "markdown" | "binary"; sizeBytes: number; startLine?: number; truncated: boolean; text?: string; languageHint?: string | null };
|
|
371
371
|
|
|
372
372
|
export type PanelAppEntryView = {
|
|
373
373
|
id: string;
|
|
@@ -15,6 +15,7 @@ export async function fetchServerPathBrowse(params?: {
|
|
|
15
15
|
export async function fetchServerPathRead(params: {
|
|
16
16
|
path: string;
|
|
17
17
|
basePath?: string | null;
|
|
18
|
+
line?: number | null;
|
|
18
19
|
}): Promise<ServerPathReadView> {
|
|
19
20
|
return await nextclawClient.serverPaths.read(params);
|
|
20
21
|
}
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"chatWorkspaceFileMoreActions": "File actions",
|
|
66
66
|
"chatWorkspaceDiff": "Diff",
|
|
67
67
|
"chatWorkspaceCloseFile": "Close file",
|
|
68
|
+
"chatWorkspaceCloseTab": "Close tab",
|
|
68
69
|
"chatWorkspaceLoadingPreview": "Loading preview…",
|
|
69
70
|
"chatWorkspaceLoadingFile": "Loading file…",
|
|
70
71
|
"chatWorkspaceLoadingDirectory": "Loading directory…",
|
|
@@ -201,8 +202,13 @@
|
|
|
201
202
|
"chatPanelAppReferenceFile": "File",
|
|
202
203
|
"chatPanelAppReferenceNoDescription": "No panel app description",
|
|
203
204
|
"chatSkillScopeBuiltin": "Built-in",
|
|
205
|
+
"chatSkillScopeGlobal": "Global",
|
|
204
206
|
"chatSkillScopeProject": "Project",
|
|
205
207
|
"chatSkillScopeWorkspace": "Workspace",
|
|
208
|
+
"chatSkillGroupBuiltin": "Built-in skills",
|
|
209
|
+
"chatSkillGroupGlobal": "Global skills",
|
|
210
|
+
"chatSkillGroupProject": "Project skills",
|
|
211
|
+
"chatSkillGroupWorkspace": "NextClaw skills",
|
|
206
212
|
"chatPickerRecent": "Recent",
|
|
207
213
|
"chatPickerFavoriteModels": "Favorites",
|
|
208
214
|
"chatPickerRecentModels": "Recent",
|
|
@@ -296,6 +302,8 @@
|
|
|
296
302
|
"chatCodeCopied": "Copied",
|
|
297
303
|
"chatMessageCopy": "Copy",
|
|
298
304
|
"chatMessageCopied": "Copied",
|
|
305
|
+
"chatMermaidDiagram": "Diagram",
|
|
306
|
+
"chatMermaidRenderError": "Diagram could not be rendered; showing source instead",
|
|
299
307
|
"chatSidebarNewTask": "New Task",
|
|
300
308
|
"chatSidebarSearchPlaceholder": "Search conversations...",
|
|
301
309
|
"chatSidebarScheduledTasks": "Scheduled Tasks",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"chatWorkspaceFileMoreActions": "文件操作",
|
|
66
66
|
"chatWorkspaceDiff": "Diff",
|
|
67
67
|
"chatWorkspaceCloseFile": "关闭文件",
|
|
68
|
+
"chatWorkspaceCloseTab": "关闭标签页",
|
|
68
69
|
"chatWorkspaceLoadingPreview": "正在加载预览…",
|
|
69
70
|
"chatWorkspaceLoadingFile": "正在加载文件…",
|
|
70
71
|
"chatWorkspaceLoadingDirectory": "正在加载目录…",
|
|
@@ -201,8 +202,13 @@
|
|
|
201
202
|
"chatPanelAppReferenceFile": "文件",
|
|
202
203
|
"chatPanelAppReferenceNoDescription": "暂无面板应用描述",
|
|
203
204
|
"chatSkillScopeBuiltin": "内建",
|
|
205
|
+
"chatSkillScopeGlobal": "全局",
|
|
204
206
|
"chatSkillScopeProject": "项目",
|
|
205
207
|
"chatSkillScopeWorkspace": "工作区",
|
|
208
|
+
"chatSkillGroupBuiltin": "内建技能",
|
|
209
|
+
"chatSkillGroupGlobal": "全局技能",
|
|
210
|
+
"chatSkillGroupProject": "项目技能",
|
|
211
|
+
"chatSkillGroupWorkspace": "NextClaw 技能",
|
|
206
212
|
"chatPickerRecent": "最近使用",
|
|
207
213
|
"chatPickerFavoriteModels": "收藏模型",
|
|
208
214
|
"chatPickerRecentModels": "最近选择",
|
|
@@ -296,6 +302,8 @@
|
|
|
296
302
|
"chatCodeCopied": "已复制",
|
|
297
303
|
"chatMessageCopy": "复制",
|
|
298
304
|
"chatMessageCopied": "已复制",
|
|
305
|
+
"chatMermaidDiagram": "图表",
|
|
306
|
+
"chatMermaidRenderError": "图表无法渲染,已显示源代码",
|
|
299
307
|
"chatSidebarNewTask": "新任务",
|
|
300
308
|
"chatSidebarSearchPlaceholder": "搜索对话...",
|
|
301
309
|
"chatSidebarScheduledTasks": "定时任务",
|
|
@@ -80,16 +80,13 @@ describe("buildWorkspaceFileBreadcrumb", () => {
|
|
|
80
80
|
]);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
it("
|
|
83
|
+
it("keeps truncation status separate from path segments", () => {
|
|
84
84
|
const breadcrumb = buildWorkspaceFileBreadcrumb({
|
|
85
85
|
path: "README.md",
|
|
86
86
|
sessionProjectRoot: "/Users/demo/project-alpha",
|
|
87
|
-
line: 12,
|
|
88
|
-
column: 4,
|
|
89
87
|
truncated: true,
|
|
90
88
|
});
|
|
91
89
|
|
|
92
|
-
expect(breadcrumb.locationLabel).toBe("L12:4");
|
|
93
90
|
expect(breadcrumb.truncated).toBe(true);
|
|
94
91
|
expect(breadcrumb.segments[0]?.label).toBe("project-alpha");
|
|
95
92
|
expect(breadcrumb.segments[1]?.label).toBe("README.md");
|
|
@@ -11,7 +11,6 @@ export type WorkspaceFileBreadcrumbSegmentViewModel = {
|
|
|
11
11
|
|
|
12
12
|
export type WorkspaceFileBreadcrumbViewModel = {
|
|
13
13
|
fullPath: string;
|
|
14
|
-
locationLabel: string | null;
|
|
15
14
|
truncated: boolean;
|
|
16
15
|
segments: WorkspaceFileBreadcrumbSegmentViewModel[];
|
|
17
16
|
};
|
|
@@ -153,28 +152,13 @@ function buildSegmentsFromLabels(params: {
|
|
|
153
152
|
return leading ? [leading, ...items] : items;
|
|
154
153
|
}
|
|
155
154
|
|
|
156
|
-
function buildLocationLabel(params: {
|
|
157
|
-
line?: number | null;
|
|
158
|
-
column?: number | null;
|
|
159
|
-
}): string | null {
|
|
160
|
-
const { column, line } = params;
|
|
161
|
-
|
|
162
|
-
if (typeof line !== "number") {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return `L${line}${typeof column === "number" ? `:${column}` : ""}`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
155
|
export function buildWorkspaceFileBreadcrumb(params: {
|
|
170
156
|
path: string;
|
|
171
157
|
kind?: "file" | "directory";
|
|
172
158
|
sessionProjectRoot: string | null;
|
|
173
|
-
line?: number | null;
|
|
174
|
-
column?: number | null;
|
|
175
159
|
truncated: boolean;
|
|
176
160
|
}): WorkspaceFileBreadcrumbViewModel {
|
|
177
|
-
const {
|
|
161
|
+
const { kind = "file", path, sessionProjectRoot, truncated } = params;
|
|
178
162
|
const fullPath = path.trim();
|
|
179
163
|
const relativeSegments =
|
|
180
164
|
sessionProjectRoot?.trim() && fullPath
|
|
@@ -239,7 +223,6 @@ export function buildWorkspaceFileBreadcrumb(params: {
|
|
|
239
223
|
|
|
240
224
|
return {
|
|
241
225
|
fullPath,
|
|
242
|
-
locationLabel: buildLocationLabel({ line, column }),
|
|
243
226
|
truncated,
|
|
244
227
|
segments,
|
|
245
228
|
};
|