mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 09:17:53 +00:00
fix: tool use permission hint
This commit is contained in:
@@ -291,90 +291,74 @@ describe('errors', () => {
|
||||
).mockReturnValue(OutputFormat.JSON);
|
||||
});
|
||||
|
||||
it('should format error as JSON and exit with default code', () => {
|
||||
expect(() => {
|
||||
handleToolError(toolName, toolError, mockConfig);
|
||||
}).toThrow('process.exit called with code: 54');
|
||||
it('should log error message to stderr and not exit', () => {
|
||||
handleToolError(toolName, toolError, mockConfig);
|
||||
|
||||
// In JSON mode, should not exit (just log to stderr)
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
JSON.stringify(
|
||||
{
|
||||
error: {
|
||||
type: 'FatalToolExecutionError',
|
||||
message: 'Error executing tool test-tool: Tool failed',
|
||||
code: 54,
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
'Error executing tool test-tool: Tool failed',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use custom error code', () => {
|
||||
expect(() => {
|
||||
handleToolError(toolName, toolError, mockConfig, 'CUSTOM_TOOL_ERROR');
|
||||
}).toThrow('process.exit called with code: 54');
|
||||
it('should log error with custom error code and not exit', () => {
|
||||
handleToolError(toolName, toolError, mockConfig, 'CUSTOM_TOOL_ERROR');
|
||||
|
||||
// In JSON mode, should not exit (just log to stderr)
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
JSON.stringify(
|
||||
{
|
||||
error: {
|
||||
type: 'FatalToolExecutionError',
|
||||
message: 'Error executing tool test-tool: Tool failed',
|
||||
code: 'CUSTOM_TOOL_ERROR',
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
'Error executing tool test-tool: Tool failed',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use numeric error code and exit with that code', () => {
|
||||
expect(() => {
|
||||
handleToolError(toolName, toolError, mockConfig, 500);
|
||||
}).toThrow('process.exit called with code: 500');
|
||||
it('should log error with numeric error code and not exit', () => {
|
||||
handleToolError(toolName, toolError, mockConfig, 500);
|
||||
|
||||
// In JSON mode, should not exit (just log to stderr)
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
JSON.stringify(
|
||||
{
|
||||
error: {
|
||||
type: 'FatalToolExecutionError',
|
||||
message: 'Error executing tool test-tool: Tool failed',
|
||||
code: 500,
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
'Error executing tool test-tool: Tool failed',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should prefer resultDisplay over error message', () => {
|
||||
expect(() => {
|
||||
handleToolError(
|
||||
toolName,
|
||||
toolError,
|
||||
mockConfig,
|
||||
'DISPLAY_ERROR',
|
||||
'Display message',
|
||||
);
|
||||
}).toThrow('process.exit called with code: 54');
|
||||
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
JSON.stringify(
|
||||
{
|
||||
error: {
|
||||
type: 'FatalToolExecutionError',
|
||||
message: 'Error executing tool test-tool: Display message',
|
||||
code: 'DISPLAY_ERROR',
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
handleToolError(
|
||||
toolName,
|
||||
toolError,
|
||||
mockConfig,
|
||||
'DISPLAY_ERROR',
|
||||
'Display message',
|
||||
);
|
||||
|
||||
// In JSON mode, should not exit (just log to stderr)
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'Error executing tool test-tool: Display message',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not exit in JSON mode', () => {
|
||||
handleToolError(toolName, toolError, mockConfig);
|
||||
|
||||
// Should not throw (no exit)
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'Error executing tool test-tool: Tool failed',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not exit in STREAM_JSON mode', () => {
|
||||
(
|
||||
mockConfig.getOutputFormat as ReturnType<typeof vi.fn>
|
||||
).mockReturnValue(OutputFormat.STREAM_JSON);
|
||||
|
||||
handleToolError(toolName, toolError, mockConfig);
|
||||
|
||||
// Should not exit in STREAM_JSON mode
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'Error executing tool test-tool: Tool failed',
|
||||
);
|
||||
expect(processExitSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
JsonFormatter,
|
||||
parseAndFormatApiError,
|
||||
FatalTurnLimitedError,
|
||||
FatalToolExecutionError,
|
||||
FatalCancellationError,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
|
||||
@@ -88,32 +87,29 @@ export function handleError(
|
||||
|
||||
/**
|
||||
* Handles tool execution errors specifically.
|
||||
* In JSON mode, outputs formatted JSON error and exits.
|
||||
* In JSON/STREAM_JSON mode, outputs error message to stderr only and does not exit.
|
||||
* The error will be properly formatted in the tool_result block by the adapter,
|
||||
* allowing the session to continue so the LLM can decide what to do next.
|
||||
* In text mode, outputs error message to stderr only.
|
||||
*
|
||||
* @param toolName - Name of the tool that failed
|
||||
* @param toolError - The error that occurred during tool execution
|
||||
* @param config - Configuration object
|
||||
* @param errorCode - Optional error code
|
||||
* @param resultDisplay - Optional display message for the error
|
||||
*/
|
||||
export function handleToolError(
|
||||
toolName: string,
|
||||
toolError: Error,
|
||||
config: Config,
|
||||
errorCode?: string | number,
|
||||
_errorCode?: string | number,
|
||||
resultDisplay?: string,
|
||||
): void {
|
||||
const errorMessage = `Error executing tool ${toolName}: ${resultDisplay || toolError.message}`;
|
||||
const toolExecutionError = new FatalToolExecutionError(errorMessage);
|
||||
|
||||
if (config.getOutputFormat() === OutputFormat.JSON) {
|
||||
const formatter = new JsonFormatter();
|
||||
const formattedError = formatter.formatError(
|
||||
toolExecutionError,
|
||||
errorCode ?? toolExecutionError.exitCode,
|
||||
// Always just log to stderr; JSON/streaming formatting happens in the tool_result block elsewhere
|
||||
if (config.getDebugMode()) {
|
||||
console.error(
|
||||
`Error executing tool ${toolName}: ${resultDisplay || toolError.message}`,
|
||||
);
|
||||
|
||||
console.error(formattedError);
|
||||
process.exit(
|
||||
typeof errorCode === 'number' ? errorCode : toolExecutionError.exitCode,
|
||||
);
|
||||
} else {
|
||||
console.error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user