mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-22 15:15:18 +00:00
fix(cli): drop tool calls after cancellation (#5020)
This commit is contained in:
parent
533fafa2d2
commit
b6b15e45e8
2 changed files with 73 additions and 1 deletions
|
|
@ -4915,6 +4915,77 @@ describe('useGeminiStream', () => {
|
|||
expect(result.current.streamingState).toBe(StreamingState.Idle);
|
||||
});
|
||||
|
||||
it('should drop queued tool calls when user cancels the turn', async () => {
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield {
|
||||
type: ServerGeminiEventType.ToolCallRequest,
|
||||
value: {
|
||||
callId: 'call_cancelled',
|
||||
name: 'write_file',
|
||||
args: { path: 'cancelled.txt' },
|
||||
},
|
||||
};
|
||||
yield { type: ServerGeminiEventType.UserCancelled };
|
||||
})(),
|
||||
);
|
||||
|
||||
const { result } = renderTestHook();
|
||||
|
||||
await act(async () => {
|
||||
await result.current.submitQuery('cancel before tool dispatch');
|
||||
});
|
||||
|
||||
expect(mockScheduleToolCalls).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not dispatch queued tool calls after the request is aborted', async () => {
|
||||
let resolveStream!: () => void;
|
||||
let toolCallQueued!: () => void;
|
||||
|
||||
const streamCanFinish = new Promise<void>((resolve) => {
|
||||
resolveStream = resolve;
|
||||
});
|
||||
const toolCallWasQueued = new Promise<void>((resolve) => {
|
||||
toolCallQueued = resolve;
|
||||
});
|
||||
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
(async function* () {
|
||||
yield {
|
||||
type: ServerGeminiEventType.ToolCallRequest,
|
||||
value: {
|
||||
callId: 'call_aborted',
|
||||
name: 'write_file',
|
||||
args: { path: 'aborted.txt' },
|
||||
},
|
||||
};
|
||||
toolCallQueued();
|
||||
await streamCanFinish;
|
||||
})(),
|
||||
);
|
||||
|
||||
const { result } = renderTestHook();
|
||||
|
||||
let submitPromise!: Promise<void>;
|
||||
await act(async () => {
|
||||
submitPromise = result.current.submitQuery(
|
||||
'abort before tool dispatch',
|
||||
);
|
||||
});
|
||||
|
||||
await toolCallWasQueued;
|
||||
|
||||
act(() => {
|
||||
result.current.cancelOngoingRequest();
|
||||
});
|
||||
|
||||
resolveStream();
|
||||
await submitPromise;
|
||||
|
||||
expect(mockScheduleToolCalls).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset thought to null when there is an error', async () => {
|
||||
// Mock a stream that yields a thought then encounters an error
|
||||
mockSendMessageStream.mockReturnValue(
|
||||
|
|
|
|||
|
|
@ -1535,6 +1535,7 @@ export const useGeminiStream = (
|
|||
break;
|
||||
case ServerGeminiEventType.UserCancelled:
|
||||
flushBufferedStreamEvents();
|
||||
toolCallRequests.length = 0;
|
||||
handleUserCancelledEvent(userMessageTimestamp);
|
||||
break;
|
||||
case ServerGeminiEventType.Error:
|
||||
|
|
@ -1663,7 +1664,7 @@ export const useGeminiStream = (
|
|||
flushBufferedStreamEventsRef.current.delete(flushBufferedStreamEvents);
|
||||
}
|
||||
dualOutput?.finalizeAssistantMessage();
|
||||
if (toolCallRequests.length > 0) {
|
||||
if (toolCallRequests.length > 0 && !signal.aborted) {
|
||||
scheduleToolCalls(toolCallRequests, signal);
|
||||
}
|
||||
return StreamProcessingStatus.Completed;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue