mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-02 15:23:19 +08:00
- Implemented final verification tests for contentPattern to validate behavior with empty strings, dangerous patterns, and normal patterns. - Created glob pattern matching tests to verify regex conversion and matching functionality. - Developed infinite loop risk tests using Worker threads to isolate potential blocking operations. - Introduced optimized contentPattern tests to validate improvements in the findMatches function. - Added verification tests to assess the effectiveness of contentPattern optimizations. - Conducted safety tests for contentPattern to identify edge cases and potential vulnerabilities. - Implemented unrestricted loop tests to analyze infinite loop risks without match limits. - Developed tests for zero-width pattern detection logic to ensure proper handling of dangerous regex patterns.
110 lines
2.9 KiB
TypeScript
110 lines
2.9 KiB
TypeScript
/**
|
|
* Read File Tool - Single file precise reading with optional line pagination
|
|
*
|
|
* Features:
|
|
* - Read a single file with full content
|
|
* - Line-based pagination with offset/limit
|
|
* - Binary file detection
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
import type { ToolSchema, ToolResult } from '../types/tool.js';
|
|
import { existsSync, statSync } from 'fs';
|
|
import { relative } from 'path';
|
|
import { validatePath, getProjectRoot } from '../utils/path-validator.js';
|
|
import {
|
|
MAX_CONTENT_LENGTH,
|
|
readFileContent,
|
|
type FileEntry,
|
|
type ReadResult,
|
|
} from '../utils/file-reader.js';
|
|
|
|
const ParamsSchema = z.object({
|
|
path: z.string().describe('Single file path to read'),
|
|
offset: z.number().min(0).optional().describe('Line offset to start reading from (0-based)'),
|
|
limit: z.number().min(1).optional().describe('Number of lines to read'),
|
|
});
|
|
|
|
type Params = z.infer<typeof ParamsSchema>;
|
|
|
|
export const schema: ToolSchema = {
|
|
name: 'read_file',
|
|
description: `Read a single file with optional line-based pagination.
|
|
|
|
Usage:
|
|
read_file(path="file.ts") # Full content
|
|
read_file(path="file.ts", offset=100, limit=50) # Lines 100-149 (0-based)
|
|
|
|
Supports both absolute and relative paths. Relative paths are resolved from project root.
|
|
Use offset/limit for large file pagination.`,
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
path: {
|
|
type: 'string',
|
|
description: 'Single file path to read',
|
|
},
|
|
offset: {
|
|
type: 'number',
|
|
description: 'Line offset to start reading from (0-based)',
|
|
minimum: 0,
|
|
},
|
|
limit: {
|
|
type: 'number',
|
|
description: 'Number of lines to read',
|
|
minimum: 1,
|
|
},
|
|
},
|
|
required: ['path'],
|
|
},
|
|
};
|
|
|
|
export async function handler(params: Record<string, unknown>): Promise<ToolResult<ReadResult>> {
|
|
const parsed = ParamsSchema.safeParse(params);
|
|
if (!parsed.success) {
|
|
return { success: false, error: `Invalid params: ${parsed.error.message}` };
|
|
}
|
|
|
|
const { path: filePath, offset, limit } = parsed.data;
|
|
const cwd = getProjectRoot();
|
|
const resolvedPath = await validatePath(filePath);
|
|
|
|
if (!existsSync(resolvedPath)) {
|
|
return { success: false, error: `File not found: ${filePath}` };
|
|
}
|
|
|
|
const stat = statSync(resolvedPath);
|
|
if (!stat.isFile()) {
|
|
return { success: false, error: `Not a file: ${filePath}. Use read_many_files for directories.` };
|
|
}
|
|
|
|
const { content, truncated, totalLines, lineRange } = readFileContent(resolvedPath, {
|
|
maxLength: MAX_CONTENT_LENGTH,
|
|
offset,
|
|
limit,
|
|
});
|
|
|
|
const entry: FileEntry = {
|
|
path: relative(cwd, resolvedPath) || filePath,
|
|
size: stat.size,
|
|
content,
|
|
truncated,
|
|
totalLines,
|
|
lineRange,
|
|
};
|
|
|
|
let message = `Read 1 file`;
|
|
if (lineRange) {
|
|
message += ` [lines ${lineRange.start}-${lineRange.end} of ${totalLines}]`;
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
result: {
|
|
files: [entry],
|
|
totalFiles: 1,
|
|
message,
|
|
},
|
|
};
|
|
}
|