contaigents
Version:
Modular AI Content Ecosystem with Audio Generation
151 lines (146 loc) • 5.67 kB
JavaScript
import { BaseTool } from './BaseTool.js';
import { FileService } from '../fileService.js';
export class FileReadLinesTool extends BaseTool {
constructor(baseDir) {
super();
this.fileService = new FileService(baseDir);
}
getName() {
return 'file_read_lines';
}
getDescription() {
return 'Read specific lines or line ranges from a file. More efficient than reading entire files when you only need specific sections. Supports single lines, ranges, and multiple line selections.';
}
getAgentGuidance() {
return `
## 📖 FILE READ LINES BEST PRACTICES
### 🎯 WHEN TO USE:
- **Precise reading**: Read specific functions, classes, or code blocks
- **Context-aware editing**: Read around areas you plan to modify
- **Large file handling**: Avoid loading entire large files into memory
- **Follow-up to search**: Read specific lines found by file_search tool
### 📝 LINE SPECIFICATION:
- **Single line**: line_start=10, line_end=10 (or just line_start=10)
- **Range**: line_start=10, line_end=20
- **From line to end**: line_start=10, line_end=-1
- **First N lines**: line_start=1, line_end=N
### 💡 OPTIMIZATION TIPS:
- Use after file_search to read specific areas
- Combine with file_write_lines for precise editing
- Use line ranges for reading entire functions or classes
- Check total_lines to understand file size
### 🚀 COMMON PATTERNS:
- Read function: Use search to find, then read_lines for full function
- Read imports: line_start=1, line_end=20 (typically at top)
- Read specific error: Use search result line numbers
`;
}
getParameters() {
return [
{
name: 'file_path',
type: 'string',
description: 'Path to the file to read (relative to project root)',
required: true
},
{
name: 'line_start',
type: 'number',
description: 'Starting line number (1-based, inclusive)',
required: true
},
{
name: 'line_end',
type: 'number',
description: 'Ending line number (1-based, inclusive). Use -1 for end of file. If omitted, reads only line_start.',
required: false
},
{
name: 'include_line_numbers',
type: 'boolean',
description: 'Whether to include line numbers in the output (default: true)',
required: false,
default: true
}
];
}
async execute(parameters) {
// Validate parameters
const validationError = this.validateParameters(parameters);
if (validationError) {
return validationError;
}
const { file_path, line_start, line_end, include_line_numbers = true } = parameters;
try {
// Validate line numbers
if (line_start < 1) {
return {
success: false,
error: 'line_start must be >= 1'
};
}
if (line_end !== undefined && line_end !== -1 && line_end < line_start) {
return {
success: false,
error: 'line_end must be >= line_start or -1 for end of file'
};
}
// Read file content
const fileContent = await this.fileService.readFile(file_path);
// Split content into lines
const lines = fileContent.split('\n');
const totalLines = lines.length;
// Validate line ranges against file size
if (line_start > totalLines) {
return {
success: false,
error: `line_start (${line_start}) exceeds file length (${totalLines} lines)`
};
}
// Determine actual end line
let actualLineEnd = line_end;
if (actualLineEnd === undefined) {
actualLineEnd = line_start; // Read single line
}
else if (actualLineEnd === -1) {
actualLineEnd = totalLines; // Read to end of file
}
else if (actualLineEnd > totalLines) {
actualLineEnd = totalLines; // Cap at file length
}
// Extract requested lines (convert to 0-based indexing)
const startIndex = line_start - 1;
const endIndex = actualLineEnd - 1;
const selectedLines = lines.slice(startIndex, endIndex + 1);
// Format output
let content;
if (include_line_numbers) {
content = selectedLines
.map((line, index) => `${line_start + index}: ${line}`)
.join('\n');
}
else {
content = selectedLines.join('\n');
}
return {
success: true,
data: {
file_path,
line_start,
line_end: actualLineEnd,
lines_read: selectedLines.length,
total_lines: totalLines,
content,
raw_lines: selectedLines
},
message: `Read lines ${line_start}-${actualLineEnd} from ${file_path} (${selectedLines.length} lines)`
};
}
catch (error) {
return {
success: false,
error: `Failed to read lines: ${error.message}`
};
}
}
}