@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
|
@@ -115,41 +115,6 @@ describe('ChatPluginAction', () => {
|
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
describe('internal_togglePluginApiCalling', () => {
|
|
119
|
-
it('should toggle plugin API calling state', () => {
|
|
120
|
-
const internal_toggleLoadingArraysMock = vi.fn();
|
|
121
|
-
|
|
122
|
-
act(() => {
|
|
123
|
-
useChatStore.setState({
|
|
124
|
-
internal_toggleLoadingArrays: internal_toggleLoadingArraysMock,
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
const { result } = renderHook(() => useChatStore());
|
|
129
|
-
|
|
130
|
-
const messageId = 'message-id';
|
|
131
|
-
const action = 'test-action';
|
|
132
|
-
|
|
133
|
-
result.current.internal_togglePluginApiCalling(true, messageId, action);
|
|
134
|
-
|
|
135
|
-
expect(internal_toggleLoadingArraysMock).toHaveBeenCalledWith(
|
|
136
|
-
'pluginApiLoadingIds',
|
|
137
|
-
true,
|
|
138
|
-
messageId,
|
|
139
|
-
action,
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
result.current.internal_togglePluginApiCalling(false, messageId, action);
|
|
143
|
-
|
|
144
|
-
expect(internal_toggleLoadingArraysMock).toHaveBeenCalledWith(
|
|
145
|
-
'pluginApiLoadingIds',
|
|
146
|
-
false,
|
|
147
|
-
messageId,
|
|
148
|
-
action,
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
118
|
describe('fillPluginMessageContent', () => {
|
|
154
119
|
it('should update message content and trigger the ai message', async () => {
|
|
155
120
|
// 设置模拟函数的返回值
|
|
@@ -234,7 +199,6 @@ describe('ChatPluginAction', () => {
|
|
|
234
199
|
|
|
235
200
|
vi.spyOn(storeState, 'refreshMessages');
|
|
236
201
|
vi.spyOn(storeState, 'triggerAIMessage').mockResolvedValue(undefined);
|
|
237
|
-
vi.spyOn(storeState, 'internal_togglePluginApiCalling').mockReturnValue(undefined);
|
|
238
202
|
vi.spyOn(storeState, 'optimisticUpdateMessageContent').mockResolvedValue();
|
|
239
203
|
|
|
240
204
|
const runSpy = vi.spyOn(chatService, 'runPluginApi').mockResolvedValue({
|
|
@@ -248,25 +212,12 @@ describe('ChatPluginAction', () => {
|
|
|
248
212
|
await result.current.invokeDefaultTypePlugin(messageId, pluginPayload);
|
|
249
213
|
});
|
|
250
214
|
|
|
251
|
-
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
252
|
-
true,
|
|
253
|
-
messageId,
|
|
254
|
-
expect.any(String),
|
|
255
|
-
);
|
|
256
215
|
expect(runSpy).toHaveBeenCalledWith(pluginPayload, { signal: undefined, trace: {} });
|
|
257
216
|
expect(storeState.optimisticUpdateMessageContent).toHaveBeenCalledWith(
|
|
258
217
|
messageId,
|
|
259
218
|
pluginApiResponse,
|
|
260
219
|
undefined,
|
|
261
|
-
|
|
262
|
-
sessionId: undefined,
|
|
263
|
-
topicId: undefined,
|
|
264
|
-
},
|
|
265
|
-
);
|
|
266
|
-
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
267
|
-
false,
|
|
268
|
-
'message-id',
|
|
269
|
-
'plugin/fetchPlugin/end',
|
|
220
|
+
undefined,
|
|
270
221
|
);
|
|
271
222
|
});
|
|
272
223
|
|
|
@@ -285,7 +236,6 @@ describe('ChatPluginAction', () => {
|
|
|
285
236
|
const storeState = useChatStore.getState();
|
|
286
237
|
const replaceMessagesSpy = vi.spyOn(storeState, 'replaceMessages');
|
|
287
238
|
vi.spyOn(storeState, 'triggerAIMessage').mockResolvedValue(undefined);
|
|
288
|
-
vi.spyOn(storeState, 'internal_togglePluginApiCalling').mockReturnValue(undefined);
|
|
289
239
|
|
|
290
240
|
vi.spyOn(chatService, 'runPluginApi').mockRejectedValue(error);
|
|
291
241
|
|
|
@@ -294,11 +244,6 @@ describe('ChatPluginAction', () => {
|
|
|
294
244
|
await result.current.invokeDefaultTypePlugin(messageId, pluginPayload);
|
|
295
245
|
});
|
|
296
246
|
|
|
297
|
-
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
298
|
-
true,
|
|
299
|
-
messageId,
|
|
300
|
-
expect.any(String),
|
|
301
|
-
);
|
|
302
247
|
expect(chatService.runPluginApi).toHaveBeenCalledWith(pluginPayload, { trace: {} });
|
|
303
248
|
expect(messageService.updateMessageError).toHaveBeenCalledWith(messageId, error, {
|
|
304
249
|
sessionId: undefined,
|
|
@@ -308,260 +253,10 @@ describe('ChatPluginAction', () => {
|
|
|
308
253
|
sessionId: undefined,
|
|
309
254
|
topicId: undefined,
|
|
310
255
|
});
|
|
311
|
-
expect(storeState.internal_togglePluginApiCalling).toHaveBeenCalledWith(
|
|
312
|
-
false,
|
|
313
|
-
'message-id',
|
|
314
|
-
'plugin/fetchPlugin/end',
|
|
315
|
-
);
|
|
316
256
|
expect(storeState.triggerAIMessage).not.toHaveBeenCalled(); // 确保在错误情况下不调用此方法
|
|
317
257
|
});
|
|
318
258
|
});
|
|
319
259
|
|
|
320
|
-
describe('triggerToolCalls', () => {
|
|
321
|
-
it('should trigger tool calls for the assistant message', async () => {
|
|
322
|
-
const assistantId = 'assistant-id';
|
|
323
|
-
const message = {
|
|
324
|
-
id: assistantId,
|
|
325
|
-
role: 'assistant',
|
|
326
|
-
content: 'Assistant message',
|
|
327
|
-
tools: [
|
|
328
|
-
{
|
|
329
|
-
id: 'tool1',
|
|
330
|
-
type: 'standalone',
|
|
331
|
-
identifier: 'plugin1',
|
|
332
|
-
apiName: 'api1',
|
|
333
|
-
arguments: '{}',
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
id: 'tool2',
|
|
337
|
-
type: 'markdown',
|
|
338
|
-
identifier: 'plugin2',
|
|
339
|
-
apiName: 'api2',
|
|
340
|
-
arguments: '{}',
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
id: 'tool3',
|
|
344
|
-
type: 'builtin',
|
|
345
|
-
identifier: 'builtin1',
|
|
346
|
-
apiName: 'api3',
|
|
347
|
-
arguments: '{}',
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
id: 'tool4',
|
|
351
|
-
type: 'default',
|
|
352
|
-
identifier: 'plugin3',
|
|
353
|
-
apiName: 'api4',
|
|
354
|
-
arguments: '{}',
|
|
355
|
-
},
|
|
356
|
-
],
|
|
357
|
-
} as UIChatMessage;
|
|
358
|
-
|
|
359
|
-
const invokeStandaloneTypePluginMock = vi.fn();
|
|
360
|
-
const invokeMarkdownTypePluginMock = vi.fn();
|
|
361
|
-
const invokeBuiltinToolMock = vi.fn();
|
|
362
|
-
const invokeDefaultTypePluginMock = vi.fn().mockResolvedValue('Default tool response');
|
|
363
|
-
const triggerAIMessageMock = vi.fn();
|
|
364
|
-
const optimisticCreateMessageMock = vi
|
|
365
|
-
.fn()
|
|
366
|
-
.mockResolvedValue({ id: 'tool-message-id', messages: [] });
|
|
367
|
-
const getTraceIdByMessageIdMock = vi.fn().mockReturnValue('trace-id');
|
|
368
|
-
|
|
369
|
-
act(() => {
|
|
370
|
-
useChatStore.setState({
|
|
371
|
-
messagesMap: {
|
|
372
|
-
[messageMapKey('session-id', 'topic-id')]: [message],
|
|
373
|
-
},
|
|
374
|
-
invokeStandaloneTypePlugin: invokeStandaloneTypePluginMock,
|
|
375
|
-
invokeMarkdownTypePlugin: invokeMarkdownTypePluginMock,
|
|
376
|
-
invokeBuiltinTool: invokeBuiltinToolMock,
|
|
377
|
-
invokeDefaultTypePlugin: invokeDefaultTypePluginMock,
|
|
378
|
-
triggerAIMessage: triggerAIMessageMock,
|
|
379
|
-
optimisticCreateMessage: optimisticCreateMessageMock,
|
|
380
|
-
activeId: 'session-id',
|
|
381
|
-
activeTopicId: 'topic-id',
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const { result } = renderHook(() => useChatStore());
|
|
386
|
-
|
|
387
|
-
await act(async () => {
|
|
388
|
-
await result.current.triggerToolCalls(assistantId);
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
// Verify that tool messages were created for each tool call
|
|
392
|
-
expect(optimisticCreateMessageMock).toHaveBeenCalledTimes(4);
|
|
393
|
-
expect(optimisticCreateMessageMock).toHaveBeenNthCalledWith(
|
|
394
|
-
1,
|
|
395
|
-
{
|
|
396
|
-
content: '',
|
|
397
|
-
parentId: assistantId,
|
|
398
|
-
plugin: message.tools![0],
|
|
399
|
-
role: 'tool',
|
|
400
|
-
sessionId: 'session-id',
|
|
401
|
-
tool_call_id: 'tool1',
|
|
402
|
-
topicId: 'topic-id',
|
|
403
|
-
threadId: undefined,
|
|
404
|
-
groupId: undefined,
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
sessionId: 'session-id',
|
|
408
|
-
topicId: 'topic-id',
|
|
409
|
-
},
|
|
410
|
-
);
|
|
411
|
-
expect(optimisticCreateMessageMock).toHaveBeenNthCalledWith(
|
|
412
|
-
2,
|
|
413
|
-
{
|
|
414
|
-
content: '',
|
|
415
|
-
parentId: assistantId,
|
|
416
|
-
plugin: message.tools![1],
|
|
417
|
-
role: 'tool',
|
|
418
|
-
sessionId: 'session-id',
|
|
419
|
-
tool_call_id: 'tool2',
|
|
420
|
-
topicId: 'topic-id',
|
|
421
|
-
threadId: undefined,
|
|
422
|
-
groupId: undefined,
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
sessionId: 'session-id',
|
|
426
|
-
topicId: 'topic-id',
|
|
427
|
-
},
|
|
428
|
-
);
|
|
429
|
-
expect(optimisticCreateMessageMock).toHaveBeenNthCalledWith(
|
|
430
|
-
3,
|
|
431
|
-
{
|
|
432
|
-
content: '',
|
|
433
|
-
parentId: assistantId,
|
|
434
|
-
plugin: message.tools![2],
|
|
435
|
-
role: 'tool',
|
|
436
|
-
sessionId: 'session-id',
|
|
437
|
-
tool_call_id: 'tool3',
|
|
438
|
-
topicId: 'topic-id',
|
|
439
|
-
threadId: undefined,
|
|
440
|
-
groupId: undefined,
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
sessionId: 'session-id',
|
|
444
|
-
topicId: 'topic-id',
|
|
445
|
-
},
|
|
446
|
-
);
|
|
447
|
-
expect(optimisticCreateMessageMock).toHaveBeenNthCalledWith(
|
|
448
|
-
4,
|
|
449
|
-
{
|
|
450
|
-
content: '',
|
|
451
|
-
parentId: assistantId,
|
|
452
|
-
plugin: message.tools![3],
|
|
453
|
-
role: 'tool',
|
|
454
|
-
sessionId: 'session-id',
|
|
455
|
-
tool_call_id: 'tool4',
|
|
456
|
-
topicId: 'topic-id',
|
|
457
|
-
threadId: undefined,
|
|
458
|
-
groupId: undefined,
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
sessionId: 'session-id',
|
|
462
|
-
topicId: 'topic-id',
|
|
463
|
-
},
|
|
464
|
-
);
|
|
465
|
-
|
|
466
|
-
// Verify that the appropriate plugin types were invoked
|
|
467
|
-
expect(invokeStandaloneTypePluginMock).toHaveBeenCalledWith(
|
|
468
|
-
'tool-message-id',
|
|
469
|
-
message.tools![0],
|
|
470
|
-
);
|
|
471
|
-
expect(invokeMarkdownTypePluginMock).toHaveBeenCalledWith(
|
|
472
|
-
'tool-message-id',
|
|
473
|
-
message.tools![1],
|
|
474
|
-
);
|
|
475
|
-
expect(invokeBuiltinToolMock).toHaveBeenCalledWith('tool-message-id', message.tools![2]);
|
|
476
|
-
expect(invokeDefaultTypePluginMock).toHaveBeenCalledWith(
|
|
477
|
-
'tool-message-id',
|
|
478
|
-
message.tools![3],
|
|
479
|
-
);
|
|
480
|
-
|
|
481
|
-
// Verify that AI message was triggered for default type tool call
|
|
482
|
-
// expect(getTraceIdByMessageIdMock).toHaveBeenCalledWith('tool-message-id');
|
|
483
|
-
// expect(triggerAIMessageMock).toHaveBeenCalledWith({ traceId: 'trace-id' });
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
it('should not trigger AI message if no default type tool calls', async () => {
|
|
487
|
-
const assistantId = 'assistant-id';
|
|
488
|
-
const message = {
|
|
489
|
-
id: assistantId,
|
|
490
|
-
role: 'assistant',
|
|
491
|
-
content: 'Assistant message',
|
|
492
|
-
tools: [
|
|
493
|
-
{
|
|
494
|
-
id: 'tool1',
|
|
495
|
-
type: 'standalone',
|
|
496
|
-
identifier: 'plugin1',
|
|
497
|
-
apiName: 'api1',
|
|
498
|
-
arguments: '{}',
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
id: 'tool2',
|
|
502
|
-
type: 'markdown',
|
|
503
|
-
identifier: 'plugin2',
|
|
504
|
-
apiName: 'api2',
|
|
505
|
-
arguments: '{}',
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
id: 'tool3',
|
|
509
|
-
type: 'builtin',
|
|
510
|
-
identifier: 'builtin1',
|
|
511
|
-
apiName: 'api3',
|
|
512
|
-
arguments: '{}',
|
|
513
|
-
},
|
|
514
|
-
],
|
|
515
|
-
} as UIChatMessage;
|
|
516
|
-
|
|
517
|
-
const invokeStandaloneTypePluginMock = vi.fn();
|
|
518
|
-
const invokeMarkdownTypePluginMock = vi.fn();
|
|
519
|
-
const invokeBuiltinToolMock = vi.fn();
|
|
520
|
-
const triggerAIMessageMock = vi.fn();
|
|
521
|
-
const optimisticCreateMessageMock = vi
|
|
522
|
-
.fn()
|
|
523
|
-
.mockResolvedValue({ id: 'tool-message-id', messages: [] });
|
|
524
|
-
|
|
525
|
-
act(() => {
|
|
526
|
-
useChatStore.setState({
|
|
527
|
-
invokeStandaloneTypePlugin: invokeStandaloneTypePluginMock,
|
|
528
|
-
invokeMarkdownTypePlugin: invokeMarkdownTypePluginMock,
|
|
529
|
-
invokeBuiltinTool: invokeBuiltinToolMock,
|
|
530
|
-
triggerAIMessage: triggerAIMessageMock,
|
|
531
|
-
optimisticCreateMessage: optimisticCreateMessageMock,
|
|
532
|
-
activeId: 'session-id',
|
|
533
|
-
messagesMap: {
|
|
534
|
-
[messageMapKey('session-id', 'topic-id')]: [message],
|
|
535
|
-
},
|
|
536
|
-
activeTopicId: 'topic-id',
|
|
537
|
-
});
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
const { result } = renderHook(() => useChatStore());
|
|
541
|
-
|
|
542
|
-
await act(async () => {
|
|
543
|
-
await result.current.triggerToolCalls(assistantId);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// Verify that tool messages were created for each tool call
|
|
547
|
-
expect(optimisticCreateMessageMock).toHaveBeenCalledTimes(3);
|
|
548
|
-
|
|
549
|
-
// Verify that the appropriate plugin types were invoked
|
|
550
|
-
expect(invokeStandaloneTypePluginMock).toHaveBeenCalledWith(
|
|
551
|
-
'tool-message-id',
|
|
552
|
-
message.tools![0],
|
|
553
|
-
);
|
|
554
|
-
expect(invokeMarkdownTypePluginMock).toHaveBeenCalledWith(
|
|
555
|
-
'tool-message-id',
|
|
556
|
-
message.tools![1],
|
|
557
|
-
);
|
|
558
|
-
expect(invokeBuiltinToolMock).toHaveBeenCalledWith('tool-message-id', message.tools![2]);
|
|
559
|
-
|
|
560
|
-
// Verify that AI message was not triggered
|
|
561
|
-
expect(triggerAIMessageMock).not.toHaveBeenCalled();
|
|
562
|
-
});
|
|
563
|
-
});
|
|
564
|
-
|
|
565
260
|
describe('updatePluginState', () => {
|
|
566
261
|
it('should update the plugin state for a message', async () => {
|
|
567
262
|
const messageId = 'message-id';
|
|
@@ -896,10 +591,7 @@ describe('ChatPluginAction', () => {
|
|
|
896
591
|
await result.current.reInvokeToolMessage(messageId);
|
|
897
592
|
});
|
|
898
593
|
|
|
899
|
-
expect(internal_updateMessageErrorMock).toHaveBeenCalledWith(messageId, null,
|
|
900
|
-
sessionId: undefined,
|
|
901
|
-
topicId: undefined,
|
|
902
|
-
});
|
|
594
|
+
expect(internal_updateMessageErrorMock).toHaveBeenCalledWith(messageId, null, undefined);
|
|
903
595
|
});
|
|
904
596
|
});
|
|
905
597
|
|
|
@@ -973,7 +665,6 @@ describe('ChatPluginAction', () => {
|
|
|
973
665
|
|
|
974
666
|
act(() => {
|
|
975
667
|
useChatStore.setState({
|
|
976
|
-
internal_togglePluginApiCalling: vi.fn(),
|
|
977
668
|
optimisticUpdateMessageContent: vi.fn(),
|
|
978
669
|
refreshMessages: vi.fn(),
|
|
979
670
|
});
|
|
@@ -990,10 +681,7 @@ describe('ChatPluginAction', () => {
|
|
|
990
681
|
messageId,
|
|
991
682
|
apiResponse,
|
|
992
683
|
undefined,
|
|
993
|
-
|
|
994
|
-
sessionId: undefined,
|
|
995
|
-
topicId: undefined,
|
|
996
|
-
},
|
|
684
|
+
undefined,
|
|
997
685
|
);
|
|
998
686
|
expect(messageService.updateMessage).toHaveBeenCalledWith(messageId, { traceId: 'trace-id' });
|
|
999
687
|
});
|
|
@@ -1022,7 +710,6 @@ describe('ChatPluginAction', () => {
|
|
|
1022
710
|
|
|
1023
711
|
act(() => {
|
|
1024
712
|
useChatStore.setState({
|
|
1025
|
-
internal_togglePluginApiCalling: vi.fn(),
|
|
1026
713
|
replaceMessages: replaceMessagesSpy,
|
|
1027
714
|
});
|
|
1028
715
|
});
|
|
@@ -1238,10 +925,17 @@ describe('ChatPluginAction', () => {
|
|
|
1238
925
|
|
|
1239
926
|
const replaceMessagesSpy = vi.spyOn(result.current, 'replaceMessages');
|
|
1240
927
|
|
|
928
|
+
let operationId: string;
|
|
1241
929
|
await act(async () => {
|
|
930
|
+
// Create operation with desired context
|
|
931
|
+
const op = result.current.startOperation({
|
|
932
|
+
type: 'sendMessage',
|
|
933
|
+
context: { sessionId: contextSessionId, topicId: contextTopicId },
|
|
934
|
+
});
|
|
935
|
+
operationId = op.operationId;
|
|
936
|
+
|
|
1242
937
|
await result.current.optimisticUpdatePluginState(messageId, pluginState, {
|
|
1243
|
-
|
|
1244
|
-
topicId: contextTopicId,
|
|
938
|
+
operationId,
|
|
1245
939
|
});
|
|
1246
940
|
});
|
|
1247
941
|
|
|
@@ -1298,10 +992,17 @@ describe('ChatPluginAction', () => {
|
|
|
1298
992
|
messages: [],
|
|
1299
993
|
});
|
|
1300
994
|
|
|
995
|
+
let operationId: string;
|
|
1301
996
|
await act(async () => {
|
|
997
|
+
// Create operation with desired context
|
|
998
|
+
const op = result.current.startOperation({
|
|
999
|
+
type: 'sendMessage',
|
|
1000
|
+
context: { sessionId: contextSessionId, topicId: contextTopicId },
|
|
1001
|
+
});
|
|
1002
|
+
operationId = op.operationId;
|
|
1003
|
+
|
|
1302
1004
|
await result.current.optimisticUpdatePluginError(messageId, error, {
|
|
1303
|
-
|
|
1304
|
-
topicId: contextTopicId,
|
|
1005
|
+
operationId,
|
|
1305
1006
|
});
|
|
1306
1007
|
});
|
|
1307
1008
|
|
|
@@ -1331,7 +1032,15 @@ describe('ChatPluginAction', () => {
|
|
|
1331
1032
|
|
|
1332
1033
|
// Set up both dbMessagesMap and messagesMap
|
|
1333
1034
|
const key = messageMapKey(contextSessionId, contextTopicId);
|
|
1035
|
+
let operationId: string;
|
|
1334
1036
|
act(() => {
|
|
1037
|
+
// Create operation with desired context
|
|
1038
|
+
const op = result.current.startOperation({
|
|
1039
|
+
type: 'sendMessage',
|
|
1040
|
+
context: { sessionId: contextSessionId, topicId: contextTopicId },
|
|
1041
|
+
});
|
|
1042
|
+
operationId = op.operationId;
|
|
1043
|
+
|
|
1335
1044
|
useChatStore.setState({
|
|
1336
1045
|
dbMessagesMap: {
|
|
1337
1046
|
[key]: [message],
|
|
@@ -1346,8 +1055,7 @@ describe('ChatPluginAction', () => {
|
|
|
1346
1055
|
|
|
1347
1056
|
await act(async () => {
|
|
1348
1057
|
await result.current.internal_refreshToUpdateMessageTools(messageId, {
|
|
1349
|
-
|
|
1350
|
-
topicId: contextTopicId,
|
|
1058
|
+
operationId,
|
|
1351
1059
|
});
|
|
1352
1060
|
});
|
|
1353
1061
|
|
|
@@ -8,7 +8,6 @@ import { ChatStore } from '@/store/chat/store';
|
|
|
8
8
|
import { useToolStore } from '@/store/tool';
|
|
9
9
|
import { pluginSelectors } from '@/store/tool/selectors';
|
|
10
10
|
import { builtinTools } from '@/tools';
|
|
11
|
-
import { Action } from '@/utils/storeDebug';
|
|
12
11
|
|
|
13
12
|
import { displayMessageSelectors } from '../../message/selectors';
|
|
14
13
|
|
|
@@ -17,15 +16,6 @@ import { displayMessageSelectors } from '../../message/selectors';
|
|
|
17
16
|
* These are building blocks used by other actions
|
|
18
17
|
*/
|
|
19
18
|
export interface PluginInternalsAction {
|
|
20
|
-
/**
|
|
21
|
-
* Toggle plugin API calling state
|
|
22
|
-
*/
|
|
23
|
-
internal_togglePluginApiCalling: (
|
|
24
|
-
loading: boolean,
|
|
25
|
-
id?: string,
|
|
26
|
-
action?: Action,
|
|
27
|
-
) => AbortController | undefined;
|
|
28
|
-
|
|
29
19
|
/**
|
|
30
20
|
* Transform tool calls from runtime format to storage format
|
|
31
21
|
*/
|
|
@@ -43,10 +33,6 @@ export const pluginInternals: StateCreator<
|
|
|
43
33
|
[],
|
|
44
34
|
PluginInternalsAction
|
|
45
35
|
> = (set, get) => ({
|
|
46
|
-
internal_togglePluginApiCalling: (loading, id, action) => {
|
|
47
|
-
return get().internal_toggleLoadingArrays('pluginApiLoadingIds', loading, id, action);
|
|
48
|
-
},
|
|
49
|
-
|
|
50
36
|
internal_transformToolCalls: (toolCalls) => {
|
|
51
37
|
const toolNameResolver = new ToolNameResolver();
|
|
52
38
|
|
|
@@ -86,13 +86,15 @@ export const pluginOptimisticUpdate: StateCreator<
|
|
|
86
86
|
PluginOptimisticUpdateAction
|
|
87
87
|
> = (set, get) => ({
|
|
88
88
|
optimisticUpdatePluginState: async (id, value, context) => {
|
|
89
|
-
const { replaceMessages } = get();
|
|
89
|
+
const { replaceMessages, internal_getSessionContext } = get();
|
|
90
90
|
|
|
91
91
|
// optimistic update
|
|
92
|
-
get().internal_dispatchMessage(
|
|
92
|
+
get().internal_dispatchMessage(
|
|
93
|
+
{ id, type: 'updateMessage', value: { pluginState: value } },
|
|
94
|
+
context,
|
|
95
|
+
);
|
|
93
96
|
|
|
94
|
-
const sessionId
|
|
95
|
-
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
97
|
+
const { sessionId, topicId } = internal_getSessionContext(context);
|
|
96
98
|
|
|
97
99
|
const result = await messageService.updateMessagePluginState(id, value, {
|
|
98
100
|
sessionId,
|
|
@@ -152,17 +154,19 @@ export const pluginOptimisticUpdate: StateCreator<
|
|
|
152
154
|
},
|
|
153
155
|
|
|
154
156
|
optimisticUpdatePlugin: async (id, value, context) => {
|
|
155
|
-
const { replaceMessages } = get();
|
|
157
|
+
const { replaceMessages, internal_getSessionContext } = get();
|
|
156
158
|
|
|
157
159
|
// optimistic update
|
|
158
|
-
get().internal_dispatchMessage(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
get().internal_dispatchMessage(
|
|
161
|
+
{
|
|
162
|
+
id,
|
|
163
|
+
type: 'updateMessagePlugin',
|
|
164
|
+
value,
|
|
165
|
+
},
|
|
166
|
+
context,
|
|
167
|
+
);
|
|
163
168
|
|
|
164
|
-
const sessionId
|
|
165
|
-
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
169
|
+
const { sessionId, topicId } = internal_getSessionContext(context);
|
|
166
170
|
|
|
167
171
|
const result = await messageService.updateMessagePlugin(id, value, {
|
|
168
172
|
sessionId,
|
|
@@ -202,12 +206,11 @@ export const pluginOptimisticUpdate: StateCreator<
|
|
|
202
206
|
},
|
|
203
207
|
|
|
204
208
|
optimisticUpdatePluginError: async (id, error, context) => {
|
|
205
|
-
const { replaceMessages } = get();
|
|
209
|
+
const { replaceMessages, internal_getSessionContext } = get();
|
|
206
210
|
|
|
207
|
-
get().internal_dispatchMessage({ id, type: 'updateMessage', value: { error } });
|
|
211
|
+
get().internal_dispatchMessage({ id, type: 'updateMessage', value: { error } }, context);
|
|
208
212
|
|
|
209
|
-
const sessionId
|
|
210
|
-
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
213
|
+
const { sessionId, topicId } = internal_getSessionContext(context);
|
|
211
214
|
|
|
212
215
|
const result = await messageService.updateMessage(
|
|
213
216
|
id,
|
|
@@ -227,10 +230,9 @@ export const pluginOptimisticUpdate: StateCreator<
|
|
|
227
230
|
const message = dbMessageSelectors.getDbMessageById(id)(get());
|
|
228
231
|
if (!message || !message.tools) return;
|
|
229
232
|
|
|
230
|
-
const { internal_toggleMessageLoading, replaceMessages } = get();
|
|
233
|
+
const { internal_toggleMessageLoading, replaceMessages, internal_getSessionContext } = get();
|
|
231
234
|
|
|
232
|
-
const sessionId
|
|
233
|
-
const topicId = context?.topicId !== undefined ? context.topicId : get().activeTopicId;
|
|
235
|
+
const { sessionId, topicId } = internal_getSessionContext(context);
|
|
234
236
|
|
|
235
237
|
internal_toggleMessageLoading(true, id);
|
|
236
238
|
const result = await messageService.updateMessage(
|