[Fix Telemetry for tool calls, PR 1/n] Propagate tool reported errors via ToolCallResponseInfo and ToolResult (#5222)

This commit is contained in:
Silvio Junior
2025-08-01 11:20:08 -04:00
committed by GitHub
parent e126d2fcd9
commit 7748e56153
14 changed files with 224 additions and 25 deletions

View File

@@ -27,6 +27,7 @@ vi.mock('../utils/editor.js', () => ({
import { describe, it, expect, beforeEach, afterEach, vi, Mock } from 'vitest';
import { EditTool, EditToolParams } from './edit.js';
import { FileDiff } from './tools.js';
import { ToolErrorType } from './tool-error.js';
import path from 'path';
import fs from 'fs';
import os from 'os';
@@ -627,6 +628,98 @@ describe('EditTool', () => {
});
});
describe('Error Scenarios', () => {
const testFile = 'error_test.txt';
let filePath: string;
beforeEach(() => {
filePath = path.join(rootDir, testFile);
});
it('should return FILE_NOT_FOUND error', async () => {
const params: EditToolParams = {
file_path: filePath,
old_string: 'any',
new_string: 'new',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(ToolErrorType.FILE_NOT_FOUND);
});
it('should return ATTEMPT_TO_CREATE_EXISTING_FILE error', async () => {
fs.writeFileSync(filePath, 'existing content', 'utf8');
const params: EditToolParams = {
file_path: filePath,
old_string: '',
new_string: 'new content',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(
ToolErrorType.ATTEMPT_TO_CREATE_EXISTING_FILE,
);
});
it('should return NO_OCCURRENCE_FOUND error', async () => {
fs.writeFileSync(filePath, 'content', 'utf8');
const params: EditToolParams = {
file_path: filePath,
old_string: 'not-found',
new_string: 'new',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(ToolErrorType.EDIT_NO_OCCURRENCE_FOUND);
});
it('should return EXPECTED_OCCURRENCE_MISMATCH error', async () => {
fs.writeFileSync(filePath, 'one one two', 'utf8');
const params: EditToolParams = {
file_path: filePath,
old_string: 'one',
new_string: 'new',
expected_replacements: 3,
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(
ToolErrorType.EDIT_EXPECTED_OCCURRENCE_MISMATCH,
);
});
it('should return NO_CHANGE error', async () => {
fs.writeFileSync(filePath, 'content', 'utf8');
const params: EditToolParams = {
file_path: filePath,
old_string: 'content',
new_string: 'content',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(ToolErrorType.EDIT_NO_CHANGE);
});
it('should return INVALID_PARAMETERS error for relative path', async () => {
const params: EditToolParams = {
file_path: 'relative/path.txt',
old_string: 'a',
new_string: 'b',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(ToolErrorType.INVALID_TOOL_PARAMS);
});
it('should return FILE_WRITE_FAILURE on write error', async () => {
fs.writeFileSync(filePath, 'content', 'utf8');
// Make file readonly to trigger a write error
fs.chmodSync(filePath, '444');
const params: EditToolParams = {
file_path: filePath,
old_string: 'content',
new_string: 'new content',
};
const result = await tool.execute(params, new AbortController().signal);
expect(result.error?.type).toBe(ToolErrorType.FILE_WRITE_FAILURE);
});
});
describe('getDescription', () => {
it('should return "No file changes to..." if old_string and new_string are the same', () => {
const testFileName = 'test.txt';