diff options
| author | Taylor Mullen <[email protected]> | 2025-05-27 23:40:25 -0700 |
|---|---|---|
| committer | N. Taylor Mullen <[email protected]> | 2025-05-27 23:46:37 -0700 |
| commit | f2f2ecf9d83224778e5fc38cfcc4a1edddf9f7d4 (patch) | |
| tree | 6ad7ce8c34f16016c67c208a5182a016739b2c07 /packages/server/src/utils/nextSpeakerChecker.test.ts | |
| parent | bfeaac844186153698d3a7079b41214bbf1e4371 (diff) | |
feat: Allow cancellation of in-progress Gemini requests and pre-execution checks
- Implements cancellation for Gemini requests while they are actively being processed by the model.
- Extends cancellation support to the logic within tools. This allows users to cancel operations during the phase where the system is determining if a tool execution requires user confirmation, which can include potentially long-running pre-flight checks or LLM-based corrections.
- Underlying LLM calls for edit corrections (within and ) and next speaker checks can now also be cancelled.
- Previously, cancellation of the main request was not possible until text started streaming, and pre-execution checks were not cancellable.
- This change leverages the updated SDK's ability to accept an abort token and threads s throughout the request, tool execution, and pre-execution check lifecycle.
Fixes https://github.com/google-gemini/gemini-cli/issues/531
Diffstat (limited to 'packages/server/src/utils/nextSpeakerChecker.test.ts')
| -rw-r--r-- | packages/server/src/utils/nextSpeakerChecker.test.ts | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/packages/server/src/utils/nextSpeakerChecker.test.ts b/packages/server/src/utils/nextSpeakerChecker.test.ts index 1d87bffb..872e00f6 100644 --- a/packages/server/src/utils/nextSpeakerChecker.test.ts +++ b/packages/server/src/utils/nextSpeakerChecker.test.ts @@ -44,6 +44,7 @@ describe('checkNextSpeaker', () => { let chatInstance: GeminiChat; let mockGeminiClient: GeminiClient; let MockConfig: Mock; + const abortSignal = new AbortController().signal; beforeEach(() => { MockConfig = vi.mocked(Config); @@ -71,7 +72,7 @@ describe('checkNextSpeaker', () => { mockGoogleGenAIInstance, // This will be the instance returned by the mocked GoogleGenAI constructor mockModelsInstance, // This is the instance returned by mockGoogleGenAIInstance.getGenerativeModel 'gemini-pro', // model name - {}, // config + {}, [], // initial history ); @@ -85,7 +86,11 @@ describe('checkNextSpeaker', () => { it('should return null if history is empty', async () => { (chatInstance.getHistory as Mock).mockReturnValue([]); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); expect(mockGeminiClient.generateJson).not.toHaveBeenCalled(); }); @@ -94,7 +99,11 @@ describe('checkNextSpeaker', () => { (chatInstance.getHistory as Mock).mockReturnValue([ { role: 'user', parts: [{ text: 'Hello' }] }, ] as Content[]); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); expect(mockGeminiClient.generateJson).not.toHaveBeenCalled(); }); @@ -109,7 +118,11 @@ describe('checkNextSpeaker', () => { }; (mockGeminiClient.generateJson as Mock).mockResolvedValue(mockApiResponse); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toEqual(mockApiResponse); expect(mockGeminiClient.generateJson).toHaveBeenCalledTimes(1); }); @@ -124,7 +137,11 @@ describe('checkNextSpeaker', () => { }; (mockGeminiClient.generateJson as Mock).mockResolvedValue(mockApiResponse); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toEqual(mockApiResponse); }); @@ -138,7 +155,11 @@ describe('checkNextSpeaker', () => { }; (mockGeminiClient.generateJson as Mock).mockResolvedValue(mockApiResponse); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toEqual(mockApiResponse); }); @@ -153,7 +174,11 @@ describe('checkNextSpeaker', () => { new Error('API Error'), ); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); consoleWarnSpy.mockRestore(); }); @@ -166,7 +191,11 @@ describe('checkNextSpeaker', () => { reasoning: 'This is incomplete.', } as unknown as NextSpeakerResponse); // Type assertion to simulate invalid response - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); }); @@ -179,7 +208,11 @@ describe('checkNextSpeaker', () => { next_speaker: 123, // Invalid type } as unknown as NextSpeakerResponse); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); }); @@ -192,7 +225,11 @@ describe('checkNextSpeaker', () => { next_speaker: 'neither', // Invalid enum value } as unknown as NextSpeakerResponse); - const result = await checkNextSpeaker(chatInstance, mockGeminiClient); + const result = await checkNextSpeaker( + chatInstance, + mockGeminiClient, + abortSignal, + ); expect(result).toBeNull(); }); }); |
