mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 12:04:56 -07:00
feat(core, cli): Implement sequential approval. (#11593)
This commit is contained in:
@@ -62,12 +62,20 @@ export type TrackedToolCall =
|
||||
| TrackedCompletedToolCall
|
||||
| TrackedCancelledToolCall;
|
||||
|
||||
export type CancelAllFn = (signal: AbortSignal) => void;
|
||||
|
||||
export function useReactToolScheduler(
|
||||
onComplete: (tools: CompletedToolCall[]) => Promise<void>,
|
||||
config: Config,
|
||||
getPreferredEditor: () => EditorType | undefined,
|
||||
onEditorClose: () => void,
|
||||
): [TrackedToolCall[], ScheduleFn, MarkToolsAsSubmittedFn] {
|
||||
): [
|
||||
TrackedToolCall[],
|
||||
ScheduleFn,
|
||||
MarkToolsAsSubmittedFn,
|
||||
React.Dispatch<React.SetStateAction<TrackedToolCall[]>>,
|
||||
CancelAllFn,
|
||||
] {
|
||||
const [toolCallsForDisplay, setToolCallsForDisplay] = useState<
|
||||
TrackedToolCall[]
|
||||
>([]);
|
||||
@@ -112,37 +120,36 @@ export function useReactToolScheduler(
|
||||
);
|
||||
|
||||
const toolCallsUpdateHandler: ToolCallsUpdateHandler = useCallback(
|
||||
(updatedCoreToolCalls: ToolCall[]) => {
|
||||
setToolCallsForDisplay((prevTrackedCalls) =>
|
||||
updatedCoreToolCalls.map((coreTc) => {
|
||||
const existingTrackedCall = prevTrackedCalls.find(
|
||||
(ptc) => ptc.request.callId === coreTc.request.callId,
|
||||
);
|
||||
// Start with the new core state, then layer on the existing UI state
|
||||
// to ensure UI-only properties like pid are preserved.
|
||||
(allCoreToolCalls: ToolCall[]) => {
|
||||
setToolCallsForDisplay((prevTrackedCalls) => {
|
||||
const prevCallsMap = new Map(
|
||||
prevTrackedCalls.map((c) => [c.request.callId, c]),
|
||||
);
|
||||
|
||||
return allCoreToolCalls.map((coreTc): TrackedToolCall => {
|
||||
const existingTrackedCall = prevCallsMap.get(coreTc.request.callId);
|
||||
|
||||
const responseSubmittedToGemini =
|
||||
existingTrackedCall?.responseSubmittedToGemini ?? false;
|
||||
|
||||
if (coreTc.status === 'executing') {
|
||||
// Preserve live output if it exists from a previous render.
|
||||
const liveOutput = (existingTrackedCall as TrackedExecutingToolCall)
|
||||
?.liveOutput;
|
||||
return {
|
||||
...coreTc,
|
||||
responseSubmittedToGemini,
|
||||
liveOutput: (existingTrackedCall as TrackedExecutingToolCall)
|
||||
?.liveOutput,
|
||||
liveOutput,
|
||||
pid: (coreTc as ExecutingToolCall).pid,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...coreTc,
|
||||
responseSubmittedToGemini,
|
||||
};
|
||||
}
|
||||
|
||||
// For other statuses, explicitly set liveOutput and pid to undefined
|
||||
// to ensure they are not carried over from a previous executing state.
|
||||
return {
|
||||
...coreTc,
|
||||
responseSubmittedToGemini,
|
||||
liveOutput: undefined,
|
||||
pid: undefined,
|
||||
};
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
[setToolCallsForDisplay],
|
||||
);
|
||||
@@ -178,9 +185,10 @@ export function useReactToolScheduler(
|
||||
request: ToolCallRequestInfo | ToolCallRequestInfo[],
|
||||
signal: AbortSignal,
|
||||
) => {
|
||||
setToolCallsForDisplay([]);
|
||||
void scheduler.schedule(request, signal);
|
||||
},
|
||||
[scheduler],
|
||||
[scheduler, setToolCallsForDisplay],
|
||||
);
|
||||
|
||||
const markToolsAsSubmitted: MarkToolsAsSubmittedFn = useCallback(
|
||||
@@ -196,7 +204,20 @@ export function useReactToolScheduler(
|
||||
[],
|
||||
);
|
||||
|
||||
return [toolCallsForDisplay, schedule, markToolsAsSubmitted];
|
||||
const cancelAllToolCalls = useCallback(
|
||||
(signal: AbortSignal) => {
|
||||
scheduler.cancelAll(signal);
|
||||
},
|
||||
[scheduler],
|
||||
);
|
||||
|
||||
return [
|
||||
toolCallsForDisplay,
|
||||
schedule,
|
||||
markToolsAsSubmitted,
|
||||
setToolCallsForDisplay,
|
||||
cancelAllToolCalls,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user