summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
authorjoshualitt <[email protected]>2025-08-18 13:28:15 -0700
committerGitHub <[email protected]>2025-08-18 20:28:15 +0000
commitd66ddcd82e09d7b6fbc0226e31d73d38db5cff2a (patch)
treed78d3437feffc7eb3620f5e02f5489453b3766aa /packages/cli/src
parent91cd0db2b3e99f5829dbb6d09696333e9198cc9d (diff)
bug(core): Do not throw validation errors when building tools in `nonInteractiveToolExecutor`. (#6363)
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/nonInteractiveCli.test.ts48
-rw-r--r--packages/cli/src/nonInteractiveCli.ts3
2 files changed, 40 insertions, 11 deletions
diff --git a/packages/cli/src/nonInteractiveCli.test.ts b/packages/cli/src/nonInteractiveCli.test.ts
index 3e4ce037..79ee2d0d 100644
--- a/packages/cli/src/nonInteractiveCli.test.ts
+++ b/packages/cli/src/nonInteractiveCli.test.ts
@@ -150,7 +150,7 @@ describe('runNonInteractive', () => {
expect(processStdoutSpy).toHaveBeenCalledWith('\n');
});
- it('should handle error during tool execution', async () => {
+ it('should handle error during tool execution and should send error back to the model', async () => {
const toolCallEvent: ServerGeminiStreamEvent = {
type: GeminiEventType.ToolCallRequest,
value: {
@@ -162,20 +162,52 @@ describe('runNonInteractive', () => {
},
};
mockCoreExecuteToolCall.mockResolvedValue({
- error: new Error('Tool execution failed badly'),
- errorType: ToolErrorType.UNHANDLED_EXCEPTION,
+ error: new Error('Execution failed'),
+ errorType: ToolErrorType.EXECUTION_FAILED,
+ responseParts: {
+ functionResponse: {
+ name: 'errorTool',
+ response: {
+ output: 'Error: Execution failed',
+ },
+ },
+ },
+ resultDisplay: 'Execution failed',
});
- mockGeminiClient.sendMessageStream.mockReturnValue(
- createStreamFromEvents([toolCallEvent]),
- );
+ const finalResponse: ServerGeminiStreamEvent[] = [
+ {
+ type: GeminiEventType.Content,
+ value: 'Sorry, let me try again.',
+ },
+ ];
+ mockGeminiClient.sendMessageStream
+ .mockReturnValueOnce(createStreamFromEvents([toolCallEvent]))
+ .mockReturnValueOnce(createStreamFromEvents(finalResponse));
await runNonInteractive(mockConfig, 'Trigger tool error', 'prompt-id-3');
expect(mockCoreExecuteToolCall).toHaveBeenCalled();
expect(consoleErrorSpy).toHaveBeenCalledWith(
- 'Error executing tool errorTool: Tool execution failed badly',
+ 'Error executing tool errorTool: Execution failed',
);
- expect(processExitSpy).toHaveBeenCalledWith(1);
+ expect(processExitSpy).not.toHaveBeenCalled();
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenNthCalledWith(
+ 2,
+ [
+ {
+ functionResponse: {
+ name: 'errorTool',
+ response: {
+ output: 'Error: Execution failed',
+ },
+ },
+ },
+ ],
+ expect.any(AbortSignal),
+ 'prompt-id-3',
+ );
+ expect(processStdoutSpy).toHaveBeenCalledWith('Sorry, let me try again.');
});
it('should exit with error if sendMessageStream throws initially', async () => {
diff --git a/packages/cli/src/nonInteractiveCli.ts b/packages/cli/src/nonInteractiveCli.ts
index f2efe8fc..b65bf15d 100644
--- a/packages/cli/src/nonInteractiveCli.ts
+++ b/packages/cli/src/nonInteractiveCli.ts
@@ -12,7 +12,6 @@ import {
shutdownTelemetry,
isTelemetrySdkInitialized,
GeminiEventType,
- ToolErrorType,
parseAndFormatApiError,
} from '@google/gemini-cli-core';
import { Content, Part, FunctionCall } from '@google/genai';
@@ -109,8 +108,6 @@ export async function runNonInteractive(
console.error(
`Error executing tool ${fc.name}: ${toolResponse.resultDisplay || toolResponse.error.message}`,
);
- if (toolResponse.errorType === ToolErrorType.UNHANDLED_EXCEPTION)
- process.exit(1);
}
if (toolResponse.responseParts) {