@lobehub/lobehub 2.0.0-next.85 → 2.0.0-next.87
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 +50 -0
- package/apps/desktop/src/main/modules/networkProxy/dispatcher.ts +16 -16
- package/apps/desktop/src/main/modules/networkProxy/tester.ts +11 -11
- package/apps/desktop/src/main/modules/networkProxy/urlBuilder.ts +3 -3
- package/apps/desktop/src/main/modules/networkProxy/validator.ts +10 -10
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/core/runtime.ts +36 -1
- package/packages/agent-runtime/src/types/event.ts +1 -0
- package/packages/agent-runtime/src/types/generalAgent.ts +16 -0
- package/packages/agent-runtime/src/types/instruction.ts +30 -0
- package/packages/agent-runtime/src/types/runtime.ts +7 -0
- package/packages/types/src/message/common/metadata.ts +3 -0
- package/packages/types/src/message/common/tools.ts +2 -2
- package/packages/types/src/tool/search/index.ts +8 -2
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/V1Mobile/index.tsx +2 -2
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/V1Mobile/useSend.ts +7 -2
- package/src/app/[variants]/(main)/chat/components/conversation/features/ChatInput/useSend.ts +15 -14
- package/src/app/[variants]/(main)/chat/session/features/SessionListContent/List/Item/index.tsx +2 -2
- package/src/components/Analytics/MainInterfaceTracker.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/browser.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +2 -2
- package/src/features/Conversation/MarkdownElements/LobeThinking/Render.tsx +3 -3
- package/src/features/Conversation/MarkdownElements/Thinking/Render.tsx +3 -3
- package/src/features/Conversation/Messages/Group/Tool/Inspector/index.tsx +1 -1
- package/src/features/Conversation/Messages/User/index.tsx +3 -3
- package/src/features/Conversation/Messages/index.tsx +3 -3
- package/src/features/Conversation/components/AutoScroll.tsx +2 -2
- package/src/features/PluginsUI/Render/StandaloneType/Iframe.tsx +3 -3
- package/src/features/Portal/Home/Body/Plugins/ArtifactList/index.tsx +3 -3
- package/src/features/ShareModal/ShareText/index.tsx +3 -3
- package/src/services/search.ts +2 -2
- package/src/store/chat/agents/GeneralChatAgent.ts +98 -0
- package/src/store/chat/agents/__tests__/GeneralChatAgent.test.ts +366 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/call-llm.test.ts +1217 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/call-tool.test.ts +1976 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/finish.test.ts +453 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/index.ts +4 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockInstructions.ts +126 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockMessages.ts +94 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockOperations.ts +96 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/fixtures/mockStore.ts +138 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/assertions.ts +185 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/index.ts +3 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/operationTestUtils.ts +94 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/testExecutor.ts +139 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/request-human-approve.test.ts +545 -0
- package/src/store/chat/agents/__tests__/createAgentExecutors/resolve-aborted-tools.test.ts +686 -0
- package/src/store/chat/agents/createAgentExecutors.ts +313 -80
- package/src/store/chat/selectors.ts +1 -0
- package/src/store/chat/slices/aiChat/__tests__/ai-chat.integration.test.ts +667 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/cancel-functionality.test.ts +137 -27
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationControl.test.ts +163 -125
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +12 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/fixtures.ts +0 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +0 -2
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +286 -19
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingStates.test.ts +0 -112
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +42 -99
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +90 -57
- package/src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts +5 -25
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +220 -98
- package/src/store/chat/slices/aiChat/actions/streamingStates.ts +0 -34
- package/src/store/chat/slices/aiChat/initialState.ts +0 -28
- package/src/store/chat/slices/aiChat/selectors.test.ts +280 -0
- package/src/store/chat/slices/aiChat/selectors.ts +31 -7
- package/src/store/chat/slices/builtinTool/actions/__tests__/localSystem.test.ts +21 -30
- package/src/store/chat/slices/builtinTool/actions/__tests__/search.test.ts +29 -49
- package/src/store/chat/slices/builtinTool/actions/interpreter.ts +83 -48
- package/src/store/chat/slices/builtinTool/actions/localSystem.ts +78 -28
- package/src/store/chat/slices/builtinTool/actions/search.ts +146 -59
- package/src/store/chat/slices/builtinTool/selectors.test.ts +258 -0
- package/src/store/chat/slices/builtinTool/selectors.ts +25 -4
- package/src/store/chat/slices/message/action.test.ts +134 -16
- package/src/store/chat/slices/message/actions/internals.ts +33 -7
- package/src/store/chat/slices/message/actions/optimisticUpdate.ts +85 -52
- package/src/store/chat/slices/message/initialState.ts +0 -10
- package/src/store/chat/slices/message/selectors/messageState.ts +34 -12
- package/src/store/chat/slices/operation/__tests__/actions.test.ts +712 -16
- package/src/store/chat/slices/operation/__tests__/integration.test.ts +342 -0
- package/src/store/chat/slices/operation/__tests__/selectors.test.ts +257 -17
- package/src/store/chat/slices/operation/actions.ts +218 -11
- package/src/store/chat/slices/operation/selectors.ts +135 -6
- package/src/store/chat/slices/operation/types.ts +29 -3
- package/src/store/chat/slices/plugin/action.test.ts +30 -322
- package/src/store/chat/slices/plugin/actions/internals.ts +0 -14
- package/src/store/chat/slices/plugin/actions/optimisticUpdate.ts +21 -19
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +45 -27
- package/src/store/chat/slices/plugin/actions/publicApi.ts +3 -4
- package/src/store/chat/slices/plugin/actions/workflow.ts +0 -55
- package/src/store/chat/slices/thread/selectors/index.ts +4 -2
- package/src/store/chat/slices/topic/action.ts +3 -3
- package/src/store/chat/slices/translate/action.ts +54 -41
- package/src/tools/web-browsing/ExecutionRuntime/index.ts +5 -2
- package/src/tools/web-browsing/Portal/Search/Footer.tsx +11 -9
|
@@ -16,12 +16,12 @@ describe('Operation Selectors', () => {
|
|
|
16
16
|
|
|
17
17
|
act(() => {
|
|
18
18
|
result.current.startOperation({
|
|
19
|
-
type: '
|
|
19
|
+
type: 'execAgentRuntime',
|
|
20
20
|
context: { sessionId: 'session1' },
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
result.current.startOperation({
|
|
24
|
-
type: '
|
|
24
|
+
type: 'execAgentRuntime',
|
|
25
25
|
context: { sessionId: 'session1' },
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -31,7 +31,9 @@ describe('Operation Selectors', () => {
|
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
const generateOps = operationSelectors.getOperationsByType('
|
|
34
|
+
const generateOps = operationSelectors.getOperationsByType('execAgentRuntime')(
|
|
35
|
+
result.current,
|
|
36
|
+
);
|
|
35
37
|
const reasoningOps = operationSelectors.getOperationsByType('reasoning')(result.current);
|
|
36
38
|
|
|
37
39
|
expect(generateOps).toHaveLength(2);
|
|
@@ -48,7 +50,7 @@ describe('Operation Selectors', () => {
|
|
|
48
50
|
useChatStore.setState({ activeId: 'session1', activeTopicId: 'topic1' });
|
|
49
51
|
|
|
50
52
|
result.current.startOperation({
|
|
51
|
-
type: '
|
|
53
|
+
type: 'execAgentRuntime',
|
|
52
54
|
context: { sessionId: 'session1', topicId: 'topic1' },
|
|
53
55
|
});
|
|
54
56
|
|
|
@@ -59,7 +61,7 @@ describe('Operation Selectors', () => {
|
|
|
59
61
|
|
|
60
62
|
// Operation in different context
|
|
61
63
|
result.current.startOperation({
|
|
62
|
-
type: '
|
|
64
|
+
type: 'execAgentRuntime',
|
|
63
65
|
context: { sessionId: 'session2', topicId: 'topic2' },
|
|
64
66
|
});
|
|
65
67
|
});
|
|
@@ -82,7 +84,7 @@ describe('Operation Selectors', () => {
|
|
|
82
84
|
|
|
83
85
|
act(() => {
|
|
84
86
|
opId = result.current.startOperation({
|
|
85
|
-
type: '
|
|
87
|
+
type: 'execAgentRuntime',
|
|
86
88
|
context: { sessionId: 'session1' },
|
|
87
89
|
}).operationId;
|
|
88
90
|
});
|
|
@@ -103,12 +105,14 @@ describe('Operation Selectors', () => {
|
|
|
103
105
|
|
|
104
106
|
act(() => {
|
|
105
107
|
result.current.startOperation({
|
|
106
|
-
type: '
|
|
108
|
+
type: 'execAgentRuntime',
|
|
107
109
|
context: { sessionId: 'session1' },
|
|
108
110
|
});
|
|
109
111
|
});
|
|
110
112
|
|
|
111
|
-
expect(operationSelectors.hasRunningOperationType('
|
|
113
|
+
expect(operationSelectors.hasRunningOperationType('execAgentRuntime')(result.current)).toBe(
|
|
114
|
+
true,
|
|
115
|
+
);
|
|
112
116
|
expect(operationSelectors.hasRunningOperationType('reasoning')(result.current)).toBe(false);
|
|
113
117
|
});
|
|
114
118
|
});
|
|
@@ -125,7 +129,7 @@ describe('Operation Selectors', () => {
|
|
|
125
129
|
|
|
126
130
|
act(() => {
|
|
127
131
|
result.current.startOperation({
|
|
128
|
-
type: '
|
|
132
|
+
type: 'execAgentRuntime',
|
|
129
133
|
context: { sessionId: 'session1', topicId: 'topic1' },
|
|
130
134
|
});
|
|
131
135
|
});
|
|
@@ -146,7 +150,7 @@ describe('Operation Selectors', () => {
|
|
|
146
150
|
|
|
147
151
|
act(() => {
|
|
148
152
|
result.current.startOperation({
|
|
149
|
-
type: '
|
|
153
|
+
type: 'execAgentRuntime',
|
|
150
154
|
context: { sessionId: 'session1', topicId: 'topic1' },
|
|
151
155
|
});
|
|
152
156
|
});
|
|
@@ -163,7 +167,7 @@ describe('Operation Selectors', () => {
|
|
|
163
167
|
useChatStore.setState({ activeId: 'session1', activeTopicId: 'topic1' });
|
|
164
168
|
|
|
165
169
|
result.current.startOperation({
|
|
166
|
-
type: '
|
|
170
|
+
type: 'execAgentRuntime',
|
|
167
171
|
context: { sessionId: 'session1', topicId: 'topic1' },
|
|
168
172
|
label: 'Generating response...',
|
|
169
173
|
});
|
|
@@ -190,7 +194,7 @@ describe('Operation Selectors', () => {
|
|
|
190
194
|
|
|
191
195
|
act(() => {
|
|
192
196
|
result.current.startOperation({
|
|
193
|
-
type: '
|
|
197
|
+
type: 'execAgentRuntime',
|
|
194
198
|
context: { sessionId: 'session1', messageId: 'msg1' },
|
|
195
199
|
});
|
|
196
200
|
});
|
|
@@ -200,6 +204,122 @@ describe('Operation Selectors', () => {
|
|
|
200
204
|
});
|
|
201
205
|
});
|
|
202
206
|
|
|
207
|
+
describe('isMessageCreating', () => {
|
|
208
|
+
it('should return true for user message during sendMessage operation', () => {
|
|
209
|
+
const { result } = renderHook(() => useChatStore());
|
|
210
|
+
|
|
211
|
+
let opId: string;
|
|
212
|
+
|
|
213
|
+
act(() => {
|
|
214
|
+
opId = result.current.startOperation({
|
|
215
|
+
type: 'sendMessage',
|
|
216
|
+
context: { sessionId: 'session1', messageId: 'user_msg_1' },
|
|
217
|
+
}).operationId;
|
|
218
|
+
|
|
219
|
+
// Associate message with operation
|
|
220
|
+
result.current.associateMessageWithOperation('user_msg_1', opId!);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
expect(operationSelectors.isMessageCreating('user_msg_1')(result.current)).toBe(true);
|
|
224
|
+
expect(operationSelectors.isMessageCreating('other_msg')(result.current)).toBe(false);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should return true for assistant message during createAssistantMessage operation', () => {
|
|
228
|
+
const { result } = renderHook(() => useChatStore());
|
|
229
|
+
|
|
230
|
+
let opId: string;
|
|
231
|
+
|
|
232
|
+
act(() => {
|
|
233
|
+
opId = result.current.startOperation({
|
|
234
|
+
type: 'createAssistantMessage',
|
|
235
|
+
context: { sessionId: 'session1', messageId: 'assistant_msg_1' },
|
|
236
|
+
}).operationId;
|
|
237
|
+
|
|
238
|
+
// Associate message with operation
|
|
239
|
+
result.current.associateMessageWithOperation('assistant_msg_1', opId!);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect(operationSelectors.isMessageCreating('assistant_msg_1')(result.current)).toBe(true);
|
|
243
|
+
expect(operationSelectors.isMessageCreating('other_msg')(result.current)).toBe(false);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should return false when operation completes', () => {
|
|
247
|
+
const { result } = renderHook(() => useChatStore());
|
|
248
|
+
|
|
249
|
+
let opId: string;
|
|
250
|
+
|
|
251
|
+
act(() => {
|
|
252
|
+
opId = result.current.startOperation({
|
|
253
|
+
type: 'sendMessage',
|
|
254
|
+
context: { sessionId: 'session1', messageId: 'msg1' },
|
|
255
|
+
}).operationId;
|
|
256
|
+
|
|
257
|
+
result.current.associateMessageWithOperation('msg1', opId!);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
expect(operationSelectors.isMessageCreating('msg1')(result.current)).toBe(true);
|
|
261
|
+
|
|
262
|
+
act(() => {
|
|
263
|
+
result.current.completeOperation(opId!);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
expect(operationSelectors.isMessageCreating('msg1')(result.current)).toBe(false);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('should return false for other operation types', () => {
|
|
270
|
+
const { result } = renderHook(() => useChatStore());
|
|
271
|
+
|
|
272
|
+
let opId: string;
|
|
273
|
+
|
|
274
|
+
act(() => {
|
|
275
|
+
// execAgentRuntime should not be considered as "creating"
|
|
276
|
+
opId = result.current.startOperation({
|
|
277
|
+
type: 'execAgentRuntime',
|
|
278
|
+
context: { sessionId: 'session1', messageId: 'msg1' },
|
|
279
|
+
}).operationId;
|
|
280
|
+
|
|
281
|
+
result.current.associateMessageWithOperation('msg1', opId!);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
expect(operationSelectors.isMessageCreating('msg1')(result.current)).toBe(false);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should only check sendMessage and createAssistantMessage operations', () => {
|
|
288
|
+
const { result } = renderHook(() => useChatStore());
|
|
289
|
+
|
|
290
|
+
let sendMsgOpId: string;
|
|
291
|
+
let createAssistantOpId: string;
|
|
292
|
+
let toolCallOpId: string;
|
|
293
|
+
|
|
294
|
+
act(() => {
|
|
295
|
+
// sendMessage - should be creating
|
|
296
|
+
sendMsgOpId = result.current.startOperation({
|
|
297
|
+
type: 'sendMessage',
|
|
298
|
+
context: { sessionId: 'session1', messageId: 'user_msg' },
|
|
299
|
+
}).operationId;
|
|
300
|
+
result.current.associateMessageWithOperation('user_msg', sendMsgOpId!);
|
|
301
|
+
|
|
302
|
+
// createAssistantMessage - should be creating
|
|
303
|
+
createAssistantOpId = result.current.startOperation({
|
|
304
|
+
type: 'createAssistantMessage',
|
|
305
|
+
context: { sessionId: 'session1', messageId: 'assistant_msg' },
|
|
306
|
+
}).operationId;
|
|
307
|
+
result.current.associateMessageWithOperation('assistant_msg', createAssistantOpId!);
|
|
308
|
+
|
|
309
|
+
// toolCalling - should NOT be creating
|
|
310
|
+
toolCallOpId = result.current.startOperation({
|
|
311
|
+
type: 'toolCalling',
|
|
312
|
+
context: { sessionId: 'session1', messageId: 'tool_msg' },
|
|
313
|
+
}).operationId;
|
|
314
|
+
result.current.associateMessageWithOperation('tool_msg', toolCallOpId!);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
expect(operationSelectors.isMessageCreating('user_msg')(result.current)).toBe(true);
|
|
318
|
+
expect(operationSelectors.isMessageCreating('assistant_msg')(result.current)).toBe(true);
|
|
319
|
+
expect(operationSelectors.isMessageCreating('tool_msg')(result.current)).toBe(false);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
203
323
|
describe('getOperationContextFromMessage', () => {
|
|
204
324
|
it('should return operation context from message ID', () => {
|
|
205
325
|
const { result } = renderHook(() => useChatStore());
|
|
@@ -208,7 +328,7 @@ describe('Operation Selectors', () => {
|
|
|
208
328
|
|
|
209
329
|
act(() => {
|
|
210
330
|
opId = result.current.startOperation({
|
|
211
|
-
type: '
|
|
331
|
+
type: 'execAgentRuntime',
|
|
212
332
|
context: { sessionId: 'session1', topicId: 'topic1', messageId: 'msg1' },
|
|
213
333
|
}).operationId;
|
|
214
334
|
|
|
@@ -225,19 +345,19 @@ describe('Operation Selectors', () => {
|
|
|
225
345
|
});
|
|
226
346
|
|
|
227
347
|
describe('backward compatibility selectors', () => {
|
|
228
|
-
it('
|
|
348
|
+
it('isAgentRuntimeRunning should work', () => {
|
|
229
349
|
const { result } = renderHook(() => useChatStore());
|
|
230
350
|
|
|
231
|
-
expect(operationSelectors.
|
|
351
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(false);
|
|
232
352
|
|
|
233
353
|
act(() => {
|
|
234
354
|
result.current.startOperation({
|
|
235
|
-
type: '
|
|
355
|
+
type: 'execAgentRuntime',
|
|
236
356
|
context: { sessionId: 'session1' },
|
|
237
357
|
});
|
|
238
358
|
});
|
|
239
359
|
|
|
240
|
-
expect(operationSelectors.
|
|
360
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(true);
|
|
241
361
|
});
|
|
242
362
|
|
|
243
363
|
it('isSendingMessage should work', () => {
|
|
@@ -269,5 +389,125 @@ describe('Operation Selectors', () => {
|
|
|
269
389
|
|
|
270
390
|
expect(operationSelectors.isInRAGFlow(result.current)).toBe(true);
|
|
271
391
|
});
|
|
392
|
+
|
|
393
|
+
it('isMainWindowAgentRuntimeRunning should only detect main window operations', () => {
|
|
394
|
+
const { result } = renderHook(() => useChatStore());
|
|
395
|
+
|
|
396
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
397
|
+
|
|
398
|
+
// Start a main window operation (inThread: false)
|
|
399
|
+
let mainOpId: string;
|
|
400
|
+
act(() => {
|
|
401
|
+
mainOpId = result.current.startOperation({
|
|
402
|
+
type: 'execAgentRuntime',
|
|
403
|
+
context: { sessionId: 'session1' },
|
|
404
|
+
metadata: { inThread: false },
|
|
405
|
+
}).operationId;
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(true);
|
|
409
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(true);
|
|
410
|
+
|
|
411
|
+
// Complete main window operation
|
|
412
|
+
act(() => {
|
|
413
|
+
result.current.completeOperation(mainOpId!);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
417
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(false);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('isMainWindowAgentRuntimeRunning should exclude thread operations', () => {
|
|
421
|
+
const { result } = renderHook(() => useChatStore());
|
|
422
|
+
|
|
423
|
+
// Start a thread operation (inThread: true)
|
|
424
|
+
let threadOpId: string;
|
|
425
|
+
act(() => {
|
|
426
|
+
threadOpId = result.current.startOperation({
|
|
427
|
+
type: 'execAgentRuntime',
|
|
428
|
+
context: { sessionId: 'session1', threadId: 'thread1' },
|
|
429
|
+
metadata: { inThread: true },
|
|
430
|
+
}).operationId;
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// Thread operation should not affect main window state
|
|
434
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
435
|
+
// But should be detected by general isAgentRuntimeRunning
|
|
436
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(true);
|
|
437
|
+
|
|
438
|
+
// Complete thread operation
|
|
439
|
+
act(() => {
|
|
440
|
+
result.current.completeOperation(threadOpId!);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
444
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(false);
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it('isMainWindowAgentRuntimeRunning should distinguish between main and thread operations', () => {
|
|
448
|
+
const { result } = renderHook(() => useChatStore());
|
|
449
|
+
|
|
450
|
+
let mainOpId: string;
|
|
451
|
+
let threadOpId: string;
|
|
452
|
+
|
|
453
|
+
// Start both main window and thread operations
|
|
454
|
+
act(() => {
|
|
455
|
+
mainOpId = result.current.startOperation({
|
|
456
|
+
type: 'execAgentRuntime',
|
|
457
|
+
context: { sessionId: 'session1' },
|
|
458
|
+
metadata: { inThread: false },
|
|
459
|
+
}).operationId;
|
|
460
|
+
|
|
461
|
+
threadOpId = result.current.startOperation({
|
|
462
|
+
type: 'execAgentRuntime',
|
|
463
|
+
context: { sessionId: 'session1', threadId: 'thread1' },
|
|
464
|
+
metadata: { inThread: true },
|
|
465
|
+
}).operationId;
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// Both selectors should detect their respective operations
|
|
469
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(true);
|
|
470
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(true);
|
|
471
|
+
|
|
472
|
+
// Complete main window operation, thread operation still running
|
|
473
|
+
act(() => {
|
|
474
|
+
result.current.completeOperation(mainOpId!);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
478
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(true);
|
|
479
|
+
|
|
480
|
+
// Complete thread operation
|
|
481
|
+
act(() => {
|
|
482
|
+
result.current.completeOperation(threadOpId!);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
486
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(false);
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('isMainWindowAgentRuntimeRunning should exclude aborting operations', () => {
|
|
490
|
+
const { result } = renderHook(() => useChatStore());
|
|
491
|
+
|
|
492
|
+
let opId: string;
|
|
493
|
+
act(() => {
|
|
494
|
+
opId = result.current.startOperation({
|
|
495
|
+
type: 'execAgentRuntime',
|
|
496
|
+
context: { sessionId: 'session1' },
|
|
497
|
+
metadata: { inThread: false },
|
|
498
|
+
}).operationId;
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(true);
|
|
502
|
+
|
|
503
|
+
// Mark as aborting
|
|
504
|
+
act(() => {
|
|
505
|
+
result.current.updateOperationMetadata(opId!, { isAborting: true });
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Should exclude aborting operations
|
|
509
|
+
expect(operationSelectors.isMainWindowAgentRuntimeRunning(result.current)).toBe(false);
|
|
510
|
+
expect(operationSelectors.isAgentRuntimeRunning(result.current)).toBe(false);
|
|
511
|
+
});
|
|
272
512
|
});
|
|
273
513
|
});
|