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
This commit is contained in:
Taylor Mullen 2025-05-27 23:40:25 -07:00 committed by N. Taylor Mullen
parent bfeaac8441
commit f2f2ecf9d8
16 changed files with 260 additions and 61 deletions

View file

@ -174,7 +174,10 @@ Expectation for parameters:
* @returns An object describing the potential edit outcome
* @throws File system errors if reading the file fails unexpectedly (e.g., permissions)
*/
private async calculateEdit(params: EditToolParams): Promise<CalculatedEdit> {
private async calculateEdit(
params: EditToolParams,
abortSignal: AbortSignal,
): Promise<CalculatedEdit> {
const expectedReplacements = 1;
let currentContent: string | null = null;
let fileExists = false;
@ -210,6 +213,7 @@ Expectation for parameters:
currentContent,
params,
this.client,
abortSignal,
);
finalOldString = correctedEdit.params.old_string;
finalNewString = correctedEdit.params.new_string;
@ -262,6 +266,7 @@ Expectation for parameters:
*/
async shouldConfirmExecute(
params: EditToolParams,
abortSignal: AbortSignal,
): Promise<ToolCallConfirmationDetails | false> {
if (this.config.getAlwaysSkipModificationConfirmation()) {
return false;
@ -300,6 +305,7 @@ Expectation for parameters:
currentContent,
params,
this.client,
abortSignal,
);
finalOldString = correctedEdit.params.old_string;
finalNewString = correctedEdit.params.new_string;
@ -376,7 +382,7 @@ Expectation for parameters:
let editData: CalculatedEdit;
try {
editData = await this.calculateEdit(params);
editData = await this.calculateEdit(params, _signal);
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error);
return {