@lobehub/lobehub 2.0.0-next.85 → 2.0.0-next.86
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 +25 -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 +9 -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/features/ChatInput/ActionBar/STT/browser.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +2 -2
- 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/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/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
|
@@ -220,6 +220,50 @@ describe('GeneralChatAgent', () => {
|
|
|
220
220
|
]);
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
+
it('should handle invalid JSON in tool arguments gracefully', async () => {
|
|
224
|
+
const agent = new GeneralChatAgent({
|
|
225
|
+
agentConfig: { maxSteps: 100 },
|
|
226
|
+
sessionId: 'test-session',
|
|
227
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const toolCall: ChatToolPayload = {
|
|
231
|
+
id: 'call-1',
|
|
232
|
+
identifier: 'test-plugin',
|
|
233
|
+
apiName: 'test-api',
|
|
234
|
+
arguments: '{invalid json}', // Invalid JSON
|
|
235
|
+
type: 'default',
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const state = createMockState({
|
|
239
|
+
toolManifestMap: {
|
|
240
|
+
'test-plugin': {
|
|
241
|
+
identifier: 'test-plugin',
|
|
242
|
+
// No humanIntervention config
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const context = createMockContext('llm_result', {
|
|
248
|
+
hasToolsCalling: true,
|
|
249
|
+
toolsCalling: [toolCall],
|
|
250
|
+
parentMessageId: 'msg-1',
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Should not throw, should proceed with call_tool (treats invalid JSON as empty args)
|
|
254
|
+
const result = await agent.runner(context, state);
|
|
255
|
+
|
|
256
|
+
expect(result).toEqual([
|
|
257
|
+
{
|
|
258
|
+
type: 'call_tool',
|
|
259
|
+
payload: {
|
|
260
|
+
parentMessageId: 'msg-1',
|
|
261
|
+
toolCalling: toolCall,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
]);
|
|
265
|
+
});
|
|
266
|
+
|
|
223
267
|
it('should return request_human_approve for tools requiring intervention', async () => {
|
|
224
268
|
const agent = new GeneralChatAgent({
|
|
225
269
|
agentConfig: { maxSteps: 100 },
|
|
@@ -526,6 +570,328 @@ describe('GeneralChatAgent', () => {
|
|
|
526
570
|
});
|
|
527
571
|
});
|
|
528
572
|
|
|
573
|
+
describe('unified abort check', () => {
|
|
574
|
+
it('should handle abort at llm_result phase when state is interrupted', async () => {
|
|
575
|
+
const agent = new GeneralChatAgent({
|
|
576
|
+
agentConfig: { maxSteps: 100 },
|
|
577
|
+
sessionId: 'test-session',
|
|
578
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
const toolCalls: ChatToolPayload[] = [
|
|
582
|
+
{
|
|
583
|
+
apiName: 'search',
|
|
584
|
+
arguments: '{"query":"test"}',
|
|
585
|
+
id: 'call-1',
|
|
586
|
+
identifier: 'lobe-web-browsing',
|
|
587
|
+
type: 'default',
|
|
588
|
+
},
|
|
589
|
+
];
|
|
590
|
+
|
|
591
|
+
const state = createMockState({
|
|
592
|
+
status: 'interrupted', // State is interrupted
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
const context = createMockContext('llm_result', {
|
|
596
|
+
hasToolsCalling: true,
|
|
597
|
+
toolsCalling: toolCalls,
|
|
598
|
+
parentMessageId: 'msg-123',
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
const result = await agent.runner(context, state);
|
|
602
|
+
|
|
603
|
+
// Should handle abort and return resolve_aborted_tools
|
|
604
|
+
expect(result).toEqual({
|
|
605
|
+
type: 'resolve_aborted_tools',
|
|
606
|
+
payload: {
|
|
607
|
+
parentMessageId: 'msg-123',
|
|
608
|
+
toolsCalling: toolCalls,
|
|
609
|
+
},
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('should handle abort at tool_result phase when state is interrupted', async () => {
|
|
614
|
+
const agent = new GeneralChatAgent({
|
|
615
|
+
agentConfig: { maxSteps: 100 },
|
|
616
|
+
sessionId: 'test-session',
|
|
617
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
const state = createMockState({
|
|
621
|
+
status: 'interrupted',
|
|
622
|
+
messages: [
|
|
623
|
+
{
|
|
624
|
+
id: 'tool-msg-1',
|
|
625
|
+
role: 'tool',
|
|
626
|
+
content: '',
|
|
627
|
+
plugin: {
|
|
628
|
+
id: 'call-1',
|
|
629
|
+
identifier: 'bash',
|
|
630
|
+
apiName: 'bash',
|
|
631
|
+
arguments: '{"command":"ls"}',
|
|
632
|
+
type: 'builtin',
|
|
633
|
+
},
|
|
634
|
+
pluginIntervention: { status: 'pending' },
|
|
635
|
+
} as any,
|
|
636
|
+
],
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
const context = createMockContext('tool_result', {
|
|
640
|
+
parentMessageId: 'msg-456',
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
const result = await agent.runner(context, state);
|
|
644
|
+
|
|
645
|
+
// Should handle abort and resolve pending tools
|
|
646
|
+
expect(result).toEqual({
|
|
647
|
+
type: 'resolve_aborted_tools',
|
|
648
|
+
payload: {
|
|
649
|
+
parentMessageId: 'msg-456',
|
|
650
|
+
toolsCalling: [
|
|
651
|
+
{
|
|
652
|
+
id: 'call-1',
|
|
653
|
+
identifier: 'bash',
|
|
654
|
+
apiName: 'bash',
|
|
655
|
+
arguments: '{"command":"ls"}',
|
|
656
|
+
type: 'builtin',
|
|
657
|
+
},
|
|
658
|
+
],
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('should return finish when state is interrupted with no tools', async () => {
|
|
664
|
+
const agent = new GeneralChatAgent({
|
|
665
|
+
agentConfig: { maxSteps: 100 },
|
|
666
|
+
sessionId: 'test-session',
|
|
667
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
const state = createMockState({
|
|
671
|
+
status: 'interrupted',
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const context = createMockContext('llm_result', {
|
|
675
|
+
hasToolsCalling: false,
|
|
676
|
+
toolsCalling: [],
|
|
677
|
+
parentMessageId: 'msg-789',
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
const result = await agent.runner(context, state);
|
|
681
|
+
|
|
682
|
+
// Should handle abort and return finish
|
|
683
|
+
expect(result).toEqual({
|
|
684
|
+
type: 'finish',
|
|
685
|
+
reason: 'user_requested',
|
|
686
|
+
reasonDetail: 'Operation cancelled by user',
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
it('should continue normal flow when state is not interrupted', async () => {
|
|
691
|
+
const agent = new GeneralChatAgent({
|
|
692
|
+
agentConfig: { maxSteps: 100 },
|
|
693
|
+
sessionId: 'test-session',
|
|
694
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
const toolCalls: ChatToolPayload[] = [
|
|
698
|
+
{
|
|
699
|
+
apiName: 'search',
|
|
700
|
+
arguments: '{"query":"test"}',
|
|
701
|
+
id: 'call-1',
|
|
702
|
+
identifier: 'lobe-web-browsing',
|
|
703
|
+
type: 'default',
|
|
704
|
+
},
|
|
705
|
+
];
|
|
706
|
+
|
|
707
|
+
const state = createMockState({
|
|
708
|
+
status: 'running', // Normal running state
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
const context = createMockContext('llm_result', {
|
|
712
|
+
hasToolsCalling: true,
|
|
713
|
+
toolsCalling: toolCalls,
|
|
714
|
+
parentMessageId: 'msg-999',
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
const result = await agent.runner(context, state);
|
|
718
|
+
|
|
719
|
+
// Should continue normal flow and execute tools
|
|
720
|
+
expect(result).toEqual([
|
|
721
|
+
{
|
|
722
|
+
type: 'call_tool',
|
|
723
|
+
payload: {
|
|
724
|
+
parentMessageId: 'msg-999',
|
|
725
|
+
toolCalling: toolCalls[0],
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
]);
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
describe('unified abort check', () => {
|
|
733
|
+
it('should handle abort at human_abort phase when state is interrupted', async () => {
|
|
734
|
+
const agent = new GeneralChatAgent({
|
|
735
|
+
agentConfig: { maxSteps: 100 },
|
|
736
|
+
sessionId: 'test-session',
|
|
737
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
const toolCalls: ChatToolPayload[] = [
|
|
741
|
+
{
|
|
742
|
+
apiName: 'search',
|
|
743
|
+
arguments: '{"query":"test"}',
|
|
744
|
+
id: 'call-1',
|
|
745
|
+
identifier: 'lobe-web-browsing',
|
|
746
|
+
type: 'default',
|
|
747
|
+
},
|
|
748
|
+
];
|
|
749
|
+
|
|
750
|
+
const state = createMockState({
|
|
751
|
+
status: 'interrupted', // Trigger unified abort check
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
const context = createMockContext('human_abort', {
|
|
755
|
+
reason: 'user_cancelled',
|
|
756
|
+
parentMessageId: 'msg-123',
|
|
757
|
+
hasToolsCalling: true,
|
|
758
|
+
toolsCalling: toolCalls,
|
|
759
|
+
result: { content: '', tool_calls: [] },
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
const result = await agent.runner(context, state);
|
|
763
|
+
|
|
764
|
+
// Should handle abort via extractAbortInfo and return resolve_aborted_tools
|
|
765
|
+
expect(result).toEqual({
|
|
766
|
+
type: 'resolve_aborted_tools',
|
|
767
|
+
payload: {
|
|
768
|
+
parentMessageId: 'msg-123',
|
|
769
|
+
toolsCalling: toolCalls,
|
|
770
|
+
},
|
|
771
|
+
});
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
describe('human_abort phase', () => {
|
|
776
|
+
it('should return resolve_aborted_tools when there are pending tool calls', async () => {
|
|
777
|
+
const agent = new GeneralChatAgent({
|
|
778
|
+
agentConfig: { maxSteps: 100 },
|
|
779
|
+
sessionId: 'test-session',
|
|
780
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
const toolCalls: ChatToolPayload[] = [
|
|
784
|
+
{
|
|
785
|
+
apiName: 'search',
|
|
786
|
+
arguments: '{"query":"test"}',
|
|
787
|
+
id: 'call-1',
|
|
788
|
+
identifier: 'lobe-web-browsing',
|
|
789
|
+
type: 'default',
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
apiName: 'getWeather',
|
|
793
|
+
arguments: '{"location":"NYC"}',
|
|
794
|
+
id: 'call-2',
|
|
795
|
+
identifier: 'weather-plugin',
|
|
796
|
+
type: 'default',
|
|
797
|
+
},
|
|
798
|
+
];
|
|
799
|
+
|
|
800
|
+
const state = createMockState();
|
|
801
|
+
const context = createMockContext('human_abort', {
|
|
802
|
+
reason: 'user_cancelled',
|
|
803
|
+
parentMessageId: 'msg-123',
|
|
804
|
+
hasToolsCalling: true,
|
|
805
|
+
toolsCalling: toolCalls,
|
|
806
|
+
result: { content: '', tool_calls: [] },
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
const result = await agent.runner(context, state);
|
|
810
|
+
|
|
811
|
+
expect(result).toEqual({
|
|
812
|
+
type: 'resolve_aborted_tools',
|
|
813
|
+
payload: {
|
|
814
|
+
parentMessageId: 'msg-123',
|
|
815
|
+
toolsCalling: toolCalls,
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
it('should return finish when there are no tool calls', async () => {
|
|
821
|
+
const agent = new GeneralChatAgent({
|
|
822
|
+
agentConfig: { maxSteps: 100 },
|
|
823
|
+
sessionId: 'test-session',
|
|
824
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
const state = createMockState();
|
|
828
|
+
const context = createMockContext('human_abort', {
|
|
829
|
+
reason: 'user_cancelled',
|
|
830
|
+
parentMessageId: 'msg-123',
|
|
831
|
+
hasToolsCalling: false,
|
|
832
|
+
toolsCalling: [],
|
|
833
|
+
result: { content: 'Hello', tool_calls: [] },
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
const result = await agent.runner(context, state);
|
|
837
|
+
|
|
838
|
+
expect(result).toEqual({
|
|
839
|
+
type: 'finish',
|
|
840
|
+
reason: 'user_requested',
|
|
841
|
+
reasonDetail: 'user_cancelled',
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
it('should return finish when toolsCalling is undefined', async () => {
|
|
846
|
+
const agent = new GeneralChatAgent({
|
|
847
|
+
agentConfig: { maxSteps: 100 },
|
|
848
|
+
sessionId: 'test-session',
|
|
849
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
850
|
+
});
|
|
851
|
+
|
|
852
|
+
const state = createMockState();
|
|
853
|
+
const context = createMockContext('human_abort', {
|
|
854
|
+
reason: 'operation_cancelled',
|
|
855
|
+
parentMessageId: 'msg-456',
|
|
856
|
+
hasToolsCalling: false,
|
|
857
|
+
result: { content: 'Partial response', tool_calls: [] },
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
const result = await agent.runner(context, state);
|
|
861
|
+
|
|
862
|
+
expect(result).toEqual({
|
|
863
|
+
type: 'finish',
|
|
864
|
+
reason: 'user_requested',
|
|
865
|
+
reasonDetail: 'operation_cancelled',
|
|
866
|
+
});
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
it('should return finish when toolsCalling is empty array', async () => {
|
|
870
|
+
const agent = new GeneralChatAgent({
|
|
871
|
+
agentConfig: { maxSteps: 100 },
|
|
872
|
+
sessionId: 'test-session',
|
|
873
|
+
modelRuntimeConfig: mockModelRuntimeConfig,
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
const state = createMockState();
|
|
877
|
+
const context = createMockContext('human_abort', {
|
|
878
|
+
reason: 'user_cancelled',
|
|
879
|
+
parentMessageId: 'msg-789',
|
|
880
|
+
hasToolsCalling: true,
|
|
881
|
+
toolsCalling: [],
|
|
882
|
+
result: { content: '', tool_calls: [] },
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
const result = await agent.runner(context, state);
|
|
886
|
+
|
|
887
|
+
expect(result).toEqual({
|
|
888
|
+
type: 'finish',
|
|
889
|
+
reason: 'user_requested',
|
|
890
|
+
reasonDetail: 'user_cancelled',
|
|
891
|
+
});
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
|
|
529
895
|
describe('unknown phase', () => {
|
|
530
896
|
it('should return finish instruction for unknown phase', async () => {
|
|
531
897
|
const agent = new GeneralChatAgent({
|