@nextclaw/ui 0.14.1 → 0.14.2
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 +29 -0
- package/dist/assets/{api-DPcvCLfa.js → api-a14tR_z1.js} +7 -7
- package/dist/assets/channels-list-page-CFGkm4DT.js +8 -0
- package/dist/assets/chat-page-CEdavJXc.js +105 -0
- package/dist/assets/{config-split-page-BCJhqdK9.js → config-split-page-B5b9B0uE.js} +1 -1
- package/dist/assets/{confirm-dialog-CWh5FfK2.js → confirm-dialog-ClH_Ec7n.js} +1 -1
- package/dist/assets/{desktop-update-config-DsRhBizi.js → desktop-update-config-DPNDnVpk.js} +1 -1
- package/dist/assets/{dist-DPrgcEC0.js → dist-BtCS2Ucq.js} +1 -1
- package/dist/assets/{dist-DsE4OsSS.js → dist-CLGGLm8b.js} +1 -1
- package/dist/assets/doc-browser-5nMWYKBD.js +1 -0
- package/dist/assets/doc-browser-BJRLhztv.js +1 -0
- package/dist/assets/doc-browser-context-D4JwMMxK.js +1 -0
- package/dist/assets/{ellipsis-B81FStLm.js → ellipsis-CtJXjIol.js} +1 -1
- package/dist/assets/{external-link-C_dmG-WJ.js → external-link-CdJiG13p.js} +1 -1
- package/dist/assets/index-BDN1zzMQ.js +105 -0
- package/dist/assets/index-g3uSZXoc.css +1 -0
- package/dist/assets/mcp-marketplace-page-BU0kIjhR.js +40 -0
- package/dist/assets/mcp-marketplace-page-sMNFSq_T.js +1 -0
- package/dist/assets/middleware-CkFT3R4v.js +1 -0
- package/dist/assets/model-config-page-D6hYXROd.js +1 -0
- package/dist/assets/plus-DPjb0piO.js +1 -0
- package/dist/assets/provider-scoped-model-input-DAX2HgmR.js +1 -0
- package/dist/assets/providers-config-page-BzAeaACA.js +1 -0
- package/dist/assets/{react-sZz5HSCm.js → react-C6cZgP44.js} +1 -1
- package/dist/assets/remote-B0G80uPr.js +1 -0
- package/dist/assets/rotate-cw-DnEB1Rju.js +1 -0
- package/dist/assets/runtime-config-page-C5xKaV3i.js +1 -0
- package/dist/assets/{save-MzjoiHri.js → save-DKA0x4zk.js} +1 -1
- package/dist/assets/{search-B29dE4GN.js → search-BNlcoj5c.js} +1 -1
- package/dist/assets/{search-config-page-Dl5sZzob.js → search-config-page-Cq9uJ-N8.js} +1 -1
- package/dist/assets/{secrets-config-page-C_l-IFCK.js → secrets-config-page-CxSbZLBo.js} +2 -2
- package/dist/assets/{select-BKmh05hd.js → select-CvTlDZTQ.js} +1 -1
- package/dist/assets/{tag-chip-BS_7Ueom.js → tag-chip-8ffF2y2C.js} +1 -1
- package/dist/assets/use-config-DmT0o1gv.js +1 -0
- package/dist/assets/x-BiSSpgqB.js +1 -0
- package/dist/index.html +15 -14
- package/package.json +9 -9
- package/src/app/components/app-presenter-provider.tsx +11 -2
- package/src/app/components/layout/__tests__/app-layout.test.tsx +11 -2
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +110 -79
- package/src/app/components/layout/app-layout.tsx +18 -4
- package/src/app/components/layout/sidebar-items.tsx +194 -71
- package/src/app/components/layout/sidebar-rail.styles.ts +15 -0
- package/src/app/components/layout/sidebar.tsx +340 -83
- package/src/app/managers/viewport-layout.manager.ts +10 -0
- package/src/app/stores/viewport-layout.store.ts +39 -3
- package/src/features/agents/components/__tests__/agents-page.test.tsx +62 -39
- package/src/features/agents/components/agents-page.tsx +10 -6
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +145 -0
- package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +69 -762
- package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +132 -0
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +22 -15
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +14 -15
- package/src/features/chat/components/conversation/chat-conversation-panel.tsx +18 -18
- package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +10 -4
- package/src/features/chat/components/layout/__tests__/chat-sidebar-read-state.test.tsx +52 -11
- package/src/features/chat/components/layout/__tests__/chat-sidebar.test.tsx +16 -14
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +247 -0
- package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +80 -7
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +82 -25
- package/src/features/chat/components/layout/chat-sidebar.tsx +59 -92
- package/src/features/chat/components/providers/chat-presenter.provider.tsx +0 -6
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +289 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +427 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +204 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-attachments.ts +66 -0
- package/src/features/chat/features/{input/hooks/use-chat-input-bar-query-state.ts → conversation/hooks/use-session-conversation-input-query.ts} +32 -17
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +281 -0
- package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +158 -0
- package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +56 -0
- package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +117 -0
- package/src/features/chat/features/input/input-surface-plugins/__tests__/panel-app-reference-plugin.test.ts +77 -0
- package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +10 -0
- package/src/features/chat/features/input/input-surface-plugins/input-surface-search.utils.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/panel-app-reference-plugin.utils.ts +108 -0
- package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +161 -0
- package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +22 -1
- package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +26 -13
- package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +7 -28
- package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +6 -0
- package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +26 -51
- package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +2 -0
- package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +5 -6
- package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +47 -12
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +93 -12
- package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +31 -12
- package/src/features/chat/features/message/utils/chat-message-markdown-part.utils.ts +38 -0
- package/src/features/chat/features/message/utils/chat-message-part.utils.ts +1 -1
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +2 -2
- package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +2 -2
- package/src/features/chat/features/session/hooks/__tests__/use-chat-session-project.test.tsx +3 -30
- package/src/features/chat/features/session/hooks/use-chat-session-project.ts +0 -5
- package/src/features/chat/features/session/utils/chat-run-metadata.utils.ts +8 -0
- package/src/features/chat/features/session-type/components/__tests__/chat-session-type-menu.test.tsx +2 -2
- package/src/features/chat/features/session-type/components/__tests__/chat-session-type-option-item.test.tsx +2 -0
- package/src/features/chat/features/session-type/components/chat-session-type-menu.tsx +2 -2
- package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +2 -2
- package/src/features/chat/features/welcome/components/__tests__/chat-conversation-welcome.test.tsx +49 -31
- package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +2 -2
- package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +21 -10
- package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +2 -2
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +2 -2
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +54 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +44 -76
- 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 +7 -1
- package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +40 -31
- package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +59 -1
- package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +109 -0
- package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +44 -4
- package/src/features/chat/index.ts +0 -1
- package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +51 -99
- package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +135 -21
- package/src/features/chat/managers/chat-session-list.manager.ts +12 -43
- package/src/features/chat/managers/chat-thread.manager.ts +108 -34
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +48 -1
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +72 -0
- package/src/features/chat/pages/ncp-chat-page.tsx +0 -122
- package/src/features/chat/presenters/chat.presenter.ts +2 -19
- package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +31 -0
- package/src/features/chat/stores/chat-thread.store.ts +42 -26
- package/src/features/panel-apps/hooks/use-panel-apps.ts +2 -1
- package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +50 -10
- package/src/platforms/desktop/components/desktop-app-shell.tsx +34 -10
- package/src/platforms/desktop/components/desktop-window-chrome.tsx +41 -16
- package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +24 -1
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -4
- package/src/shared/lib/i18n/locales/en-US/chat.json +20 -2
- package/src/shared/lib/i18n/locales/en-US/core.json +2 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +20 -2
- package/src/shared/lib/i18n/locales/zh-CN/core.json +2 -0
- package/src/shared/lib/ui-document-title/__tests__/ui-document-title.test.ts +49 -0
- package/src/shared/lib/ui-document-title/index.ts +50 -21
- package/dist/assets/channels-list-page-D6jtziu4.js +0 -8
- package/dist/assets/chat-page-BBnNJoKG.js +0 -105
- package/dist/assets/doc-browser-C8xOF_9F.js +0 -1
- package/dist/assets/doc-browser-DgQedeAn.js +0 -1
- package/dist/assets/doc-browser-context-B46tQGmO.js +0 -1
- package/dist/assets/index-7o1WdUbU.js +0 -103
- package/dist/assets/index-DQWmEWzk.css +0 -1
- package/dist/assets/mcp-marketplace-page-CWZN7ohK.js +0 -1
- package/dist/assets/mcp-marketplace-page-Dzull_4-.js +0 -40
- package/dist/assets/model-config-page-Cv0O3BIj.js +0 -1
- package/dist/assets/plus-Bnt56oqG.js +0 -1
- package/dist/assets/provider-scoped-model-input-Duuh7i3h.js +0 -1
- package/dist/assets/providers-config-page-CPDz0Lxc.js +0 -1
- package/dist/assets/remote-B0LMs8u7.js +0 -1
- package/dist/assets/rotate-cw-BfyG_KEF.js +0 -1
- package/dist/assets/runtime-config-page-q0fvv8ME.js +0 -1
- package/dist/assets/use-config-DZkBWIdL.js +0 -1
- package/dist/assets/x-CW2KO-Hz.js +0 -1
- package/src/features/chat/components/conversation/chat-conversation-alerts.tsx +0 -37
- package/src/features/chat/features/input/components/__tests__/chat-attachment-upload-limit.test.ts +0 -38
- package/src/features/chat/features/input/components/chat-input-bar.container.tsx +0 -496
- package/src/features/chat/features/message/utils/chat-message-inline-content.utils.ts +0 -95
- package/src/features/chat/managers/__tests__/chat-input.manager.test.ts +0 -448
- package/src/features/chat/managers/__tests__/chat-run-snapshot.manager.test.ts +0 -129
- package/src/features/chat/managers/__tests__/chat-run.manager.test.ts +0 -236
- package/src/features/chat/managers/__tests__/chat-session-preference-sync.manager.test.ts +0 -219
- package/src/features/chat/managers/chat-input.manager.ts +0 -430
- package/src/features/chat/managers/chat-run.manager.ts +0 -110
- package/src/features/chat/managers/chat-session-preference-sync.manager.ts +0 -142
- package/src/features/chat/stores/chat-input.store.ts +0 -104
- /package/dist/assets/{config-hints-CTqBnCDp.js → config-hints-BkYBc7z0.js} +0 -0
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import type * as SharedApi from '@/shared/lib/api';
|
|
3
3
|
import { ChatSessionListManager } from '@/features/chat/managers/chat-session-list.manager';
|
|
4
|
-
import { useChatInputStore } from '@/features/chat/stores/chat-input.store';
|
|
5
4
|
import { useChatSessionListStore } from '@/features/chat/stores/chat-session-list.store';
|
|
6
5
|
import { useChatThreadStore } from '@/features/chat/stores/chat-thread.store';
|
|
7
6
|
|
|
8
7
|
const chatSessionListModeStorageKey = 'nextclaw.chat.session-list.mode';
|
|
8
|
+
const persistStorage = new Map<string, unknown>();
|
|
9
9
|
|
|
10
10
|
function createLocalStoragePersistStorage() {
|
|
11
11
|
return {
|
|
12
|
-
getItem: (name: string) =>
|
|
13
|
-
setItem: (name: string, value: unknown) =>
|
|
14
|
-
|
|
12
|
+
getItem: (name: string) => persistStorage.get(name) ?? null,
|
|
13
|
+
setItem: (name: string, value: unknown) => {
|
|
14
|
+
persistStorage.set(name, value);
|
|
15
|
+
},
|
|
16
|
+
removeItem: (name: string) => {
|
|
17
|
+
persistStorage.delete(name);
|
|
18
|
+
},
|
|
15
19
|
};
|
|
16
20
|
}
|
|
17
21
|
|
|
@@ -28,19 +32,11 @@ vi.mock('@/shared/lib/api', async (importOriginal) => {
|
|
|
28
32
|
});
|
|
29
33
|
|
|
30
34
|
function resetChatSessionListManagerState() {
|
|
31
|
-
|
|
32
|
-
useChatSessionListStore.persist.setOptions({ storage: createLocalStoragePersistStorage() });
|
|
35
|
+
persistStorage.clear();
|
|
36
|
+
useChatSessionListStore.persist.setOptions({ storage: createLocalStoragePersistStorage() as never });
|
|
37
|
+
useChatThreadStore.persist.setOptions({ storage: createLocalStoragePersistStorage() as never });
|
|
33
38
|
mocks.updateNcpSession.mockReset();
|
|
34
39
|
mocks.updateNcpSession.mockResolvedValue({});
|
|
35
|
-
useChatInputStore.setState({
|
|
36
|
-
snapshot: {
|
|
37
|
-
...useChatInputStore.getState().snapshot,
|
|
38
|
-
defaultSessionType: 'native',
|
|
39
|
-
pendingSessionType: 'native',
|
|
40
|
-
pendingProjectRoot: null,
|
|
41
|
-
pendingProjectRootSessionKey: null
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
40
|
useChatSessionListStore.setState({
|
|
45
41
|
optimisticReadAtBySessionKey: {},
|
|
46
42
|
snapshot: {
|
|
@@ -74,21 +70,22 @@ describe('ChatSessionListManager draft and selection flow', () => {
|
|
|
74
70
|
goToSession: vi.fn(),
|
|
75
71
|
isAtChatRoot: vi.fn(() => true),
|
|
76
72
|
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
77
|
-
const chatRunManager = {
|
|
78
|
-
clearRunState: vi.fn()
|
|
79
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
80
73
|
|
|
81
|
-
const manager = new ChatSessionListManager(uiManager
|
|
74
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
82
75
|
manager.createSession('codex');
|
|
83
76
|
|
|
84
|
-
expect(
|
|
85
|
-
|
|
77
|
+
expect(uiManager.navigateTo).toHaveBeenCalledWith('/chat/draft', {
|
|
78
|
+
replace: true,
|
|
79
|
+
state: {
|
|
80
|
+
chatDraft: {
|
|
81
|
+
sessionType: 'codex',
|
|
82
|
+
projectRoot: null,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
86
|
expect(useChatSessionListStore.getState().snapshot.selectedSessionKey).toBeNull();
|
|
87
87
|
expect(useChatThreadStore.getState().snapshot.sessionKey).toBeNull();
|
|
88
88
|
expect(useChatThreadStore.getState().snapshot.hasSubmittedDraftMessage).toBe(false);
|
|
89
|
-
expect(useChatInputStore.getState().snapshot.pendingSessionType).toBe('codex');
|
|
90
|
-
expect(useChatInputStore.getState().snapshot.pendingProjectRoot).toBeNull();
|
|
91
|
-
expect(useChatInputStore.getState().snapshot.pendingProjectRootSessionKey).toBeNull();
|
|
92
89
|
});
|
|
93
90
|
|
|
94
91
|
it('starts an agent draft chat through one owner state transition', () => {
|
|
@@ -98,22 +95,23 @@ describe('ChatSessionListManager draft and selection flow', () => {
|
|
|
98
95
|
goToSession: vi.fn(),
|
|
99
96
|
isAtChatRoot: vi.fn(() => true),
|
|
100
97
|
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
101
|
-
const chatRunManager = {
|
|
102
|
-
clearRunState: vi.fn()
|
|
103
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
104
98
|
|
|
105
|
-
const manager = new ChatSessionListManager(uiManager
|
|
99
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
106
100
|
manager.startAgentDraftChat('researcher', 'codex');
|
|
107
101
|
|
|
108
|
-
expect(
|
|
109
|
-
|
|
102
|
+
expect(uiManager.navigateTo).toHaveBeenCalledWith('/chat/draft', {
|
|
103
|
+
replace: true,
|
|
104
|
+
state: {
|
|
105
|
+
chatDraft: {
|
|
106
|
+
sessionType: 'codex',
|
|
107
|
+
projectRoot: null,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
});
|
|
110
111
|
expect(useChatSessionListStore.getState().snapshot.selectedAgentId).toBe('researcher');
|
|
111
112
|
expect(useChatSessionListStore.getState().snapshot.selectedSessionKey).toBeNull();
|
|
112
113
|
expect(useChatThreadStore.getState().snapshot.sessionKey).toBeNull();
|
|
113
114
|
expect(useChatThreadStore.getState().snapshot.hasSubmittedDraftMessage).toBe(false);
|
|
114
|
-
expect(useChatInputStore.getState().snapshot.pendingSessionType).toBe('codex');
|
|
115
|
-
expect(useChatInputStore.getState().snapshot.pendingProjectRoot).toBeNull();
|
|
116
|
-
expect(useChatInputStore.getState().snapshot.pendingProjectRootSessionKey).toBeNull();
|
|
117
115
|
});
|
|
118
116
|
|
|
119
117
|
it('hydrates the draft project root when creating a session inside a project group', () => {
|
|
@@ -123,43 +121,19 @@ describe('ChatSessionListManager draft and selection flow', () => {
|
|
|
123
121
|
goToSession: vi.fn(),
|
|
124
122
|
isAtChatRoot: vi.fn(() => true),
|
|
125
123
|
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
126
|
-
const chatRunManager = {
|
|
127
|
-
clearRunState: vi.fn()
|
|
128
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
129
124
|
|
|
130
|
-
const manager = new ChatSessionListManager(uiManager
|
|
125
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
131
126
|
manager.createSession('native', '/tmp/project-alpha');
|
|
132
127
|
|
|
133
|
-
expect(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
selectedSessionKey: null
|
|
142
|
-
}
|
|
128
|
+
expect(uiManager.navigateTo).toHaveBeenCalledWith('/chat/draft', {
|
|
129
|
+
replace: true,
|
|
130
|
+
state: {
|
|
131
|
+
chatDraft: {
|
|
132
|
+
sessionType: 'native',
|
|
133
|
+
projectRoot: '/tmp/project-alpha',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
143
136
|
});
|
|
144
|
-
const uiManager = {
|
|
145
|
-
goToChatRoot: vi.fn(),
|
|
146
|
-
navigateTo: vi.fn(),
|
|
147
|
-
goToSession: vi.fn(),
|
|
148
|
-
isAtChatRoot: vi.fn(() => true),
|
|
149
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
150
|
-
const chatRunManager = {
|
|
151
|
-
clearRunState: vi.fn()
|
|
152
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
153
|
-
|
|
154
|
-
const manager = new ChatSessionListManager(uiManager, chatRunManager);
|
|
155
|
-
const sessionKey = manager.ensureDraftSession('native');
|
|
156
|
-
|
|
157
|
-
expect(sessionKey).toBeNull();
|
|
158
|
-
expect(uiManager.goToChatRoot).not.toHaveBeenCalled();
|
|
159
|
-
expect(uiManager.navigateTo).not.toHaveBeenCalled();
|
|
160
|
-
expect(uiManager.goToSession).not.toHaveBeenCalled();
|
|
161
|
-
expect(useChatSessionListStore.getState().snapshot.selectedSessionKey).toBeNull();
|
|
162
|
-
expect(useChatThreadStore.getState().snapshot.hasSubmittedDraftMessage).toBe(true);
|
|
163
137
|
});
|
|
164
138
|
|
|
165
139
|
it('does not eagerly replace the old selected session before the route finishes switching', () => {
|
|
@@ -169,15 +143,12 @@ describe('ChatSessionListManager draft and selection flow', () => {
|
|
|
169
143
|
goToSession: vi.fn(),
|
|
170
144
|
isAtChatRoot: vi.fn(() => true),
|
|
171
145
|
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
172
|
-
const chatRunManager = {
|
|
173
|
-
clearRunState: vi.fn()
|
|
174
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
175
146
|
|
|
176
|
-
const manager = new ChatSessionListManager(uiManager
|
|
147
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
177
148
|
manager.createSession('native', '/tmp/project-alpha');
|
|
178
149
|
|
|
179
150
|
expect(useChatSessionListStore.getState().snapshot.selectedSessionKey).toBeNull();
|
|
180
|
-
expect(
|
|
151
|
+
expect(uiManager.navigateTo).toHaveBeenCalledWith('/chat/draft', expect.any(Object));
|
|
181
152
|
});
|
|
182
153
|
|
|
183
154
|
it('delegates existing-session selection to routing while preserving workspace panel state', () => {
|
|
@@ -187,11 +158,8 @@ describe('ChatSessionListManager draft and selection flow', () => {
|
|
|
187
158
|
goToSession: vi.fn(),
|
|
188
159
|
isAtChatRoot: vi.fn(() => true),
|
|
189
160
|
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
190
|
-
const chatRunManager = {
|
|
191
|
-
clearRunState: vi.fn()
|
|
192
|
-
} as unknown as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
193
161
|
|
|
194
|
-
const manager = new ChatSessionListManager(uiManager
|
|
162
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
195
163
|
manager.selectSession('session-2');
|
|
196
164
|
|
|
197
165
|
expect(uiManager.goToSession).toHaveBeenCalledWith('session-2');
|
|
@@ -208,14 +176,13 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
208
176
|
|
|
209
177
|
it('updates the sidebar list mode without touching other session list state', () => {
|
|
210
178
|
const uiManager = {} as ConstructorParameters<typeof ChatSessionListManager>[0];
|
|
211
|
-
const chatRunManager = {} as ConstructorParameters<typeof ChatSessionListManager>[1];
|
|
212
179
|
|
|
213
|
-
const manager = new ChatSessionListManager(uiManager
|
|
180
|
+
const manager = new ChatSessionListManager(uiManager);
|
|
214
181
|
manager.setListMode('project-first');
|
|
215
182
|
|
|
216
183
|
expect(useChatSessionListStore.getState().snapshot.listMode).toBe('project-first');
|
|
217
184
|
expect(useChatSessionListStore.getState().snapshot.selectedSessionKey).toBe('session-1');
|
|
218
|
-
expect(
|
|
185
|
+
expect(persistStorage.get(chatSessionListModeStorageKey)).toMatchObject({
|
|
219
186
|
state: {
|
|
220
187
|
snapshot: {
|
|
221
188
|
listMode: 'project-first'
|
|
@@ -226,8 +193,7 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
226
193
|
|
|
227
194
|
it('marks a session as read through the session list owner boundary', () => {
|
|
228
195
|
const manager = new ChatSessionListManager(
|
|
229
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
230
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[1]
|
|
196
|
+
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
231
197
|
);
|
|
232
198
|
|
|
233
199
|
manager.markSessionRead('session-2', '2026-04-10T10:00:00.000Z');
|
|
@@ -242,8 +208,7 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
242
208
|
|
|
243
209
|
it('skips persisting read state when the backend already has the same watermark', () => {
|
|
244
210
|
const manager = new ChatSessionListManager(
|
|
245
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
246
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[1]
|
|
211
|
+
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
247
212
|
);
|
|
248
213
|
|
|
249
214
|
manager.markSessionRead(
|
|
@@ -258,8 +223,7 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
258
223
|
|
|
259
224
|
it('marks a visible workspace child session as read through the session list owner', () => {
|
|
260
225
|
const manager = new ChatSessionListManager(
|
|
261
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
262
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[1]
|
|
226
|
+
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
263
227
|
);
|
|
264
228
|
|
|
265
229
|
manager.markVisibleWorkspaceChildRead({
|
|
@@ -279,8 +243,7 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
279
243
|
|
|
280
244
|
it('keeps running workspace child sessions unread until they settle', () => {
|
|
281
245
|
const manager = new ChatSessionListManager(
|
|
282
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
283
|
-
{} as ConstructorParameters<typeof ChatSessionListManager>[1]
|
|
246
|
+
{} as ConstructorParameters<typeof ChatSessionListManager>[0]
|
|
284
247
|
);
|
|
285
248
|
|
|
286
249
|
manager.markVisibleWorkspaceChildRead({
|
|
@@ -298,8 +261,8 @@ describe('ChatSessionListManager list preference and read state', () => {
|
|
|
298
261
|
|
|
299
262
|
describe('ChatSessionListStore persistence', () => {
|
|
300
263
|
beforeEach(() => {
|
|
301
|
-
|
|
302
|
-
useChatSessionListStore.persist.setOptions({ storage: createLocalStoragePersistStorage() });
|
|
264
|
+
persistStorage.clear();
|
|
265
|
+
useChatSessionListStore.persist.setOptions({ storage: createLocalStoragePersistStorage() as never });
|
|
303
266
|
useChatSessionListStore.setState({
|
|
304
267
|
snapshot: {
|
|
305
268
|
...useChatSessionListStore.getState().snapshot,
|
|
@@ -322,15 +285,4 @@ describe('ChatSessionListStore persistence', () => {
|
|
|
322
285
|
expect(useChatSessionListStore.getState().snapshot.listMode).toBe('time-first');
|
|
323
286
|
});
|
|
324
287
|
|
|
325
|
-
it('hydrates the sidebar list mode from persisted preference on store initialization', async () => {
|
|
326
|
-
window.localStorage.setItem(
|
|
327
|
-
chatSessionListModeStorageKey,
|
|
328
|
-
JSON.stringify({ state: { snapshot: { listMode: 'project-first' } }, version: 0 })
|
|
329
|
-
);
|
|
330
|
-
vi.resetModules();
|
|
331
|
-
|
|
332
|
-
const hydratedStoreModule = await import('@/features/chat/stores/chat-session-list.store');
|
|
333
|
-
|
|
334
|
-
expect(hydratedStoreModule.useChatSessionListStore.getState().snapshot.listMode).toBe('project-first');
|
|
335
|
-
});
|
|
336
288
|
});
|
|
@@ -9,6 +9,19 @@ const { deleteNcpSessionMock, deleteSummaryMock } = vi.hoisted(() => ({
|
|
|
9
9
|
deleteNcpSessionMock: vi.fn(async () => ({ deleted: true, sessionId: 'parent-session-1' })),
|
|
10
10
|
deleteSummaryMock: vi.fn(),
|
|
11
11
|
}));
|
|
12
|
+
const persistStorage = new Map<string, unknown>();
|
|
13
|
+
|
|
14
|
+
function createPersistStorage() {
|
|
15
|
+
return {
|
|
16
|
+
getItem: (name: string) => persistStorage.get(name) ?? null,
|
|
17
|
+
setItem: (name: string, value: unknown) => {
|
|
18
|
+
persistStorage.set(name, value);
|
|
19
|
+
},
|
|
20
|
+
removeItem: (name: string) => {
|
|
21
|
+
persistStorage.delete(name);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
12
25
|
|
|
13
26
|
vi.mock('@/shared/lib/api', async (importOriginal) => {
|
|
14
27
|
const actual = await importOriginal<typeof SharedApi>();
|
|
@@ -20,6 +33,9 @@ vi.mock('@/shared/lib/api', async (importOriginal) => {
|
|
|
20
33
|
});
|
|
21
34
|
|
|
22
35
|
beforeEach(() => {
|
|
36
|
+
persistStorage.clear();
|
|
37
|
+
useChatSessionListStore.persist.setOptions({ storage: createPersistStorage() as never });
|
|
38
|
+
useChatThreadStore.persist.setOptions({ storage: createPersistStorage() as never });
|
|
23
39
|
useChatSessionListStore.setState({
|
|
24
40
|
optimisticReadAtBySessionKey: {},
|
|
25
41
|
snapshot: {
|
|
@@ -41,6 +57,7 @@ beforeEach(() => {
|
|
|
41
57
|
},
|
|
42
58
|
],
|
|
43
59
|
activeChildSessionKey: null,
|
|
60
|
+
activeSideChatDraft: null,
|
|
44
61
|
workspaceFileTabs: [],
|
|
45
62
|
activeWorkspaceFileKey: null,
|
|
46
63
|
workspaceNavigationHistory: [],
|
|
@@ -75,7 +92,6 @@ describe('ChatThreadManager', () => {
|
|
|
75
92
|
const manager = new ChatThreadManager(
|
|
76
93
|
uiManager,
|
|
77
94
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
78
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
79
95
|
);
|
|
80
96
|
|
|
81
97
|
manager.openChildSessionPanel({
|
|
@@ -105,7 +121,6 @@ describe('ChatThreadManager', () => {
|
|
|
105
121
|
const manager = new ChatThreadManager(
|
|
106
122
|
uiManager,
|
|
107
123
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
108
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
109
124
|
);
|
|
110
125
|
|
|
111
126
|
manager.openChildSessionPanel({
|
|
@@ -127,7 +142,6 @@ describe('ChatThreadManager', () => {
|
|
|
127
142
|
const manager = new ChatThreadManager(
|
|
128
143
|
uiManager,
|
|
129
144
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
130
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
131
145
|
);
|
|
132
146
|
|
|
133
147
|
manager.openSessionCronPanel('parent-session-1');
|
|
@@ -141,6 +155,79 @@ describe('ChatThreadManager', () => {
|
|
|
141
155
|
expect(uiManager.goToSession).not.toHaveBeenCalled();
|
|
142
156
|
});
|
|
143
157
|
|
|
158
|
+
it('opens a side chat draft beside the selected parent session', () => {
|
|
159
|
+
const uiManager = createUiManager({
|
|
160
|
+
goToSession: vi.fn(),
|
|
161
|
+
});
|
|
162
|
+
const manager = new ChatThreadManager(
|
|
163
|
+
uiManager,
|
|
164
|
+
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
manager.openSideChatDraft('parent-session-1');
|
|
168
|
+
|
|
169
|
+
const { snapshot } = useChatThreadStore.getState();
|
|
170
|
+
expect(snapshot).toMatchObject({
|
|
171
|
+
workspacePanelParentKey: 'parent-session-1',
|
|
172
|
+
activeWorkspacePanelKind: 'side-chat-draft',
|
|
173
|
+
activeChildSessionKey: null,
|
|
174
|
+
activeWorkspaceFileKey: null,
|
|
175
|
+
activeSideChatDraft: {
|
|
176
|
+
parentSessionKey: 'parent-session-1',
|
|
177
|
+
},
|
|
178
|
+
workspaceNavigationHistoryIndex: 0,
|
|
179
|
+
});
|
|
180
|
+
expect(snapshot.activeSideChatDraft?.draftKey).toEqual(expect.any(String));
|
|
181
|
+
expect(snapshot.workspaceNavigationHistory).toEqual([
|
|
182
|
+
{
|
|
183
|
+
kind: 'side-chat-draft',
|
|
184
|
+
key: snapshot.activeSideChatDraft?.draftKey,
|
|
185
|
+
},
|
|
186
|
+
]);
|
|
187
|
+
expect(uiManager.goToSession).not.toHaveBeenCalled();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('materializes an active side chat draft into a real child-session tab', () => {
|
|
191
|
+
const manager = new ChatThreadManager(
|
|
192
|
+
createUiManager(),
|
|
193
|
+
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
manager.openSideChatDraft('parent-session-1');
|
|
197
|
+
const draftKey = useChatThreadStore.getState().snapshot.activeSideChatDraft?.draftKey;
|
|
198
|
+
expect(draftKey).toEqual(expect.any(String));
|
|
199
|
+
|
|
200
|
+
manager.materializeSideChatDraft({
|
|
201
|
+
draftKey: draftKey ?? '',
|
|
202
|
+
sessionKey: 'child-session-side',
|
|
203
|
+
label: 'Side chat',
|
|
204
|
+
agentId: 'main',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
208
|
+
workspacePanelParentKey: 'parent-session-1',
|
|
209
|
+
activeWorkspacePanelKind: 'child-session',
|
|
210
|
+
activeChildSessionKey: 'child-session-side',
|
|
211
|
+
activeSideChatDraft: null,
|
|
212
|
+
activeWorkspaceFileKey: null,
|
|
213
|
+
childSessionTabs: [
|
|
214
|
+
{
|
|
215
|
+
sessionKey: 'child-session-side',
|
|
216
|
+
parentSessionKey: 'parent-session-1',
|
|
217
|
+
label: 'Side chat',
|
|
218
|
+
agentId: 'main',
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
sessionKey: 'child-session-1',
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
workspaceNavigationHistory: [
|
|
225
|
+
{ kind: 'child-session', key: 'child-session-side' },
|
|
226
|
+
],
|
|
227
|
+
workspaceNavigationHistoryIndex: 0,
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
144
231
|
it('routes to the session before opening its cron panel when needed', () => {
|
|
145
232
|
useChatSessionListStore.setState({
|
|
146
233
|
snapshot: {
|
|
@@ -158,7 +245,6 @@ describe('ChatThreadManager', () => {
|
|
|
158
245
|
const manager = new ChatThreadManager(
|
|
159
246
|
uiManager,
|
|
160
247
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
161
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
162
248
|
);
|
|
163
249
|
|
|
164
250
|
manager.openSessionCronPanel('parent-session-1');
|
|
@@ -177,7 +263,6 @@ describe('ChatThreadManager', () => {
|
|
|
177
263
|
const manager = new ChatThreadManager(
|
|
178
264
|
uiManager,
|
|
179
265
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
180
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
181
266
|
);
|
|
182
267
|
|
|
183
268
|
manager.openFilePreview({
|
|
@@ -221,7 +306,6 @@ describe('ChatThreadManager workspace navigation', () => {
|
|
|
221
306
|
const manager = new ChatThreadManager(
|
|
222
307
|
uiManager,
|
|
223
308
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
224
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
225
309
|
);
|
|
226
310
|
|
|
227
311
|
manager.openChildSessionPanel({
|
|
@@ -278,7 +362,6 @@ describe('ChatThreadManager workspace navigation', () => {
|
|
|
278
362
|
const manager = new ChatThreadManager(
|
|
279
363
|
{ goToSession: vi.fn() } as unknown as ConstructorParameters<typeof ChatThreadManager>[0],
|
|
280
364
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
281
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
282
365
|
);
|
|
283
366
|
|
|
284
367
|
manager.openChildSessionPanel({
|
|
@@ -304,7 +387,6 @@ describe('ChatThreadManager workspace navigation', () => {
|
|
|
304
387
|
const manager = new ChatThreadManager(
|
|
305
388
|
{ goToSession: vi.fn() } as unknown as ConstructorParameters<typeof ChatThreadManager>[0],
|
|
306
389
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
307
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
308
390
|
);
|
|
309
391
|
|
|
310
392
|
manager.openChildSessionPanel({
|
|
@@ -330,6 +412,51 @@ describe('ChatThreadManager workspace navigation', () => {
|
|
|
330
412
|
});
|
|
331
413
|
});
|
|
332
414
|
|
|
415
|
+
describe('ChatThreadManager tool actions', () => {
|
|
416
|
+
it('opens child-session tool actions in the workspace panel before child tabs hydrate', async () => {
|
|
417
|
+
useChatThreadStore.getState().setSnapshot({
|
|
418
|
+
childSessionTabs: [],
|
|
419
|
+
activeChildSessionKey: null,
|
|
420
|
+
workspacePanelParentKey: null,
|
|
421
|
+
});
|
|
422
|
+
const uiManager = createUiManager({
|
|
423
|
+
goToSession: vi.fn(),
|
|
424
|
+
});
|
|
425
|
+
const manager = new ChatThreadManager(
|
|
426
|
+
uiManager,
|
|
427
|
+
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
await manager.handleToolAction({
|
|
431
|
+
kind: 'open-session',
|
|
432
|
+
sessionId: ' child-session-9 ',
|
|
433
|
+
sessionKind: 'child',
|
|
434
|
+
agentId: 'verifier-agent',
|
|
435
|
+
label: 'Verifier',
|
|
436
|
+
parentSessionId: ' parent-session-1 ',
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
440
|
+
workspacePanelParentKey: 'parent-session-1',
|
|
441
|
+
activeWorkspacePanelKind: 'child-session',
|
|
442
|
+
activeChildSessionKey: 'child-session-9',
|
|
443
|
+
activeWorkspaceFileKey: null,
|
|
444
|
+
childSessionTabs: [
|
|
445
|
+
{
|
|
446
|
+
sessionKey: 'child-session-9',
|
|
447
|
+
parentSessionKey: 'parent-session-1',
|
|
448
|
+
label: 'Verifier',
|
|
449
|
+
agentId: 'verifier-agent',
|
|
450
|
+
},
|
|
451
|
+
],
|
|
452
|
+
workspaceNavigationHistory: [
|
|
453
|
+
{ kind: 'child-session', key: 'child-session-9' },
|
|
454
|
+
],
|
|
455
|
+
});
|
|
456
|
+
expect(uiManager.goToSession).not.toHaveBeenCalled();
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
|
|
333
460
|
describe('ChatThreadManager showContent', () => {
|
|
334
461
|
it('routes tool actions through the thread manager owner', async () => {
|
|
335
462
|
const uiManager = createUiManager({
|
|
@@ -338,7 +465,6 @@ describe('ChatThreadManager showContent', () => {
|
|
|
338
465
|
const manager = new ChatThreadManager(
|
|
339
466
|
uiManager,
|
|
340
467
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
341
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
342
468
|
);
|
|
343
469
|
|
|
344
470
|
await manager.handleToolAction({
|
|
@@ -376,7 +502,6 @@ describe('ChatThreadManager showContent', () => {
|
|
|
376
502
|
const manager = new ChatThreadManager(
|
|
377
503
|
{ goToSession: vi.fn() } as unknown as ConstructorParameters<typeof ChatThreadManager>[0],
|
|
378
504
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
379
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
380
505
|
);
|
|
381
506
|
|
|
382
507
|
await manager.handleToolAction({
|
|
@@ -414,7 +539,6 @@ describe('ChatThreadManager showContent', () => {
|
|
|
414
539
|
const manager = new ChatThreadManager(
|
|
415
540
|
uiManager,
|
|
416
541
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
417
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
418
542
|
);
|
|
419
543
|
|
|
420
544
|
await manager.handleToolAction({
|
|
@@ -469,7 +593,6 @@ describe('ChatThreadManager showContent', () => {
|
|
|
469
593
|
const manager = new ChatThreadManager(
|
|
470
594
|
uiManager,
|
|
471
595
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
472
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
473
596
|
);
|
|
474
597
|
|
|
475
598
|
await manager.handleUiShowContentEvent({
|
|
@@ -516,7 +639,6 @@ describe('ChatThreadManager showContent', () => {
|
|
|
516
639
|
const manager = new ChatThreadManager(
|
|
517
640
|
uiManager,
|
|
518
641
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
519
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
520
642
|
);
|
|
521
643
|
|
|
522
644
|
await manager.handleToolAction({
|
|
@@ -552,7 +674,6 @@ describe('ChatThreadManager inline showContent', () => {
|
|
|
552
674
|
const manager = new ChatThreadManager(
|
|
553
675
|
uiManager,
|
|
554
676
|
{} as ConstructorParameters<typeof ChatThreadManager>[1],
|
|
555
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
556
677
|
);
|
|
557
678
|
|
|
558
679
|
await manager.handleUiShowContentEvent({
|
|
@@ -581,7 +702,6 @@ describe('ChatThreadManager visible workspace selection', () => {
|
|
|
581
702
|
const manager = new ChatThreadManager(
|
|
582
703
|
{ goToSession: vi.fn() } as unknown as ConstructorParameters<typeof ChatThreadManager>[0],
|
|
583
704
|
sessionListManager,
|
|
584
|
-
{} as ConstructorParameters<typeof ChatThreadManager>[2],
|
|
585
705
|
);
|
|
586
706
|
const tab = {
|
|
587
707
|
sessionKey: 'child-session-1',
|
|
@@ -615,13 +735,9 @@ describe('ChatThreadManager deletion', () => {
|
|
|
615
735
|
});
|
|
616
736
|
}),
|
|
617
737
|
} as unknown as ConstructorParameters<typeof ChatThreadManager>[1];
|
|
618
|
-
const chatRunManager = {
|
|
619
|
-
clearRunState: vi.fn(),
|
|
620
|
-
} as unknown as ConstructorParameters<typeof ChatThreadManager>[2];
|
|
621
738
|
const manager = new ChatThreadManager(
|
|
622
739
|
uiManager,
|
|
623
740
|
sessionListManager,
|
|
624
|
-
chatRunManager,
|
|
625
741
|
);
|
|
626
742
|
|
|
627
743
|
await manager.deleteSession();
|
|
@@ -631,7 +747,6 @@ describe('ChatThreadManager deletion', () => {
|
|
|
631
747
|
expect(useChatThreadStore.getState().snapshot).toMatchObject({
|
|
632
748
|
sessionKey: null,
|
|
633
749
|
canDeleteSession: false,
|
|
634
|
-
messages: [],
|
|
635
750
|
workspacePanelParentKey: null,
|
|
636
751
|
childSessionTabs: [],
|
|
637
752
|
activeChildSessionKey: null,
|
|
@@ -640,7 +755,6 @@ describe('ChatThreadManager deletion', () => {
|
|
|
640
755
|
workspaceNavigationHistory: [],
|
|
641
756
|
workspaceNavigationHistoryIndex: 0,
|
|
642
757
|
});
|
|
643
|
-
expect(chatRunManager.clearRunState).toHaveBeenCalledTimes(1);
|
|
644
758
|
expect(deleteSummaryMock).toHaveBeenCalledWith(appQueryClient, 'parent-session-1');
|
|
645
759
|
expect(removeQueries).toHaveBeenCalledWith({
|
|
646
760
|
queryKey: ['ncp-session-messages', 'parent-session-1'],
|