mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-11 06:31:01 -07:00
refactor: generalize CLI background execution handling
This commit is contained in:
@@ -599,6 +599,35 @@ describe('useGeminiStream', () => {
|
||||
expect(mockSendMessageStream).not.toHaveBeenCalled(); // submitQuery uses this
|
||||
});
|
||||
|
||||
it('should expose activePtyId for non-shell executing tools that report an execution ID', () => {
|
||||
const remoteExecutingTool: TrackedExecutingToolCall = {
|
||||
request: {
|
||||
callId: 'remote-call-1',
|
||||
name: 'remote_agent_call',
|
||||
args: {},
|
||||
isClientInitiated: false,
|
||||
prompt_id: 'prompt-id-remote',
|
||||
},
|
||||
status: CoreToolCallStatus.Executing,
|
||||
responseSubmittedToGemini: false,
|
||||
tool: {
|
||||
name: 'remote_agent_call',
|
||||
displayName: 'Remote Agent',
|
||||
description: 'Remote agent execution',
|
||||
build: vi.fn(),
|
||||
} as any,
|
||||
invocation: {
|
||||
getDescription: () => 'Calling remote agent',
|
||||
} as unknown as AnyToolInvocation,
|
||||
startTime: Date.now(),
|
||||
liveOutput: 'working...',
|
||||
pid: 4242,
|
||||
};
|
||||
|
||||
const { result } = renderTestHook([remoteExecutingTool]);
|
||||
expect(result.current.activePtyId).toBe(4242);
|
||||
});
|
||||
|
||||
it('should submit tool responses when all tool calls are completed and ready', async () => {
|
||||
const toolCall1ResponseParts: Part[] = [{ text: 'tool 1 final response' }];
|
||||
const toolCall2ResponseParts: Part[] = [{ text: 'tool 2 final response' }];
|
||||
|
||||
@@ -94,8 +94,8 @@ type ToolResponseWithParts = ToolCallResponseInfo & {
|
||||
llmContent?: PartListUnion;
|
||||
};
|
||||
|
||||
interface BackgroundedShellInfo {
|
||||
pid: number;
|
||||
interface BackgroundedToolInfo {
|
||||
executionId: number;
|
||||
command: string;
|
||||
initialOutput: string;
|
||||
}
|
||||
@@ -151,29 +151,34 @@ function getBackgroundExecutionId(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getBackgroundedShellInfo(
|
||||
function getBackgroundedToolInfo(
|
||||
toolCall: TrackedCompletedToolCall | TrackedCancelledToolCall,
|
||||
): BackgroundedShellInfo | undefined {
|
||||
if (toolCall.request.name !== SHELL_COMMAND_NAME) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
): BackgroundedToolInfo | undefined {
|
||||
const response = toolCall.response as ToolResponseWithParts;
|
||||
const rawData = response?.data;
|
||||
const data = isBackgroundExecutionData(rawData) ? rawData : undefined;
|
||||
const executionId = data ? getBackgroundExecutionId(data) : undefined;
|
||||
|
||||
if (!executionId) {
|
||||
if (executionId === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
pid: executionId,
|
||||
command: data.command ?? 'shell',
|
||||
executionId,
|
||||
command: data.command ?? toolCall.request.name,
|
||||
initialOutput: data.initialOutput ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
function isBackgroundableExecutingToolCall(
|
||||
toolCall: TrackedToolCall,
|
||||
): toolCall is TrackedExecutingToolCall {
|
||||
return (
|
||||
toolCall.status === CoreToolCallStatus.Executing &&
|
||||
typeof toolCall.pid === 'number'
|
||||
);
|
||||
}
|
||||
|
||||
function showCitations(settings: LoadedSettings): boolean {
|
||||
const enabled = settings.merged.ui.showCitations;
|
||||
if (enabled !== undefined) {
|
||||
@@ -362,13 +367,11 @@ export const useGeminiStream = (
|
||||
getPreferredEditor,
|
||||
);
|
||||
|
||||
const activeToolExecutionId = useMemo(() => {
|
||||
const executingShellTool = toolCalls.find(
|
||||
(tc): tc is TrackedExecutingToolCall =>
|
||||
tc.status === CoreToolCallStatus.Executing &&
|
||||
tc.request.name === SHELL_COMMAND_NAME,
|
||||
const activeBackgroundExecutionId = useMemo(() => {
|
||||
const executingBackgroundableTool = toolCalls.find(
|
||||
isBackgroundableExecutingToolCall,
|
||||
);
|
||||
return executingShellTool?.pid;
|
||||
return executingBackgroundableTool?.pid;
|
||||
}, [toolCalls]);
|
||||
|
||||
const onExec = useCallback(async (done: Promise<void>) => {
|
||||
@@ -398,7 +401,7 @@ export const useGeminiStream = (
|
||||
setShellInputFocused,
|
||||
terminalWidth,
|
||||
terminalHeight,
|
||||
activeToolExecutionId,
|
||||
activeBackgroundExecutionId,
|
||||
);
|
||||
|
||||
const streamingState = useMemo(
|
||||
@@ -576,7 +579,8 @@ export const useGeminiStream = (
|
||||
onComplete: (result: { userSelection: 'disable' | 'keep' }) => void;
|
||||
} | null>(null);
|
||||
|
||||
const activePtyId = activeShellPtyId || activeToolExecutionId;
|
||||
const activePtyId =
|
||||
activeShellPtyId ?? activeBackgroundExecutionId ?? undefined;
|
||||
|
||||
const prevActiveShellPtyIdRef = useRef<number | null>(null);
|
||||
useEffect(() => {
|
||||
@@ -1703,12 +1707,12 @@ export const useGeminiStream = (
|
||||
);
|
||||
|
||||
for (const toolCall of completedAndReadyToSubmitTools) {
|
||||
const backgroundedShell = getBackgroundedShellInfo(toolCall);
|
||||
if (backgroundedShell) {
|
||||
const backgroundedTool = getBackgroundedToolInfo(toolCall);
|
||||
if (backgroundedTool) {
|
||||
registerBackgroundShell(
|
||||
backgroundedShell.pid,
|
||||
backgroundedShell.command,
|
||||
backgroundedShell.initialOutput,
|
||||
backgroundedTool.executionId,
|
||||
backgroundedTool.command,
|
||||
backgroundedTool.initialOutput,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user