execute method
Execute the tool with the given input.
Implementation
@override
Future<ToolResult> execute(Map<String, dynamic> input) async {
final parsed = FileReadInput.fromMap(input);
final errors = parsed.validate();
if (errors.isNotEmpty) {
return ToolResult.error(errors.first);
}
// Resolve symlinks
final resolvedPath = await _resolveSymlinks(parsed.filePath);
// Check existence
final fileType = await FileSystemEntity.type(resolvedPath);
if (fileType == FileSystemEntityType.notFound) {
return ToolResult.error('File not found: ${parsed.filePath}');
}
if (fileType == FileSystemEntityType.directory) {
return ToolResult.error(
'${parsed.filePath} is a directory, not a file. '
'Use the Bash tool with ls to list directory contents.',
);
}
final file = File(resolvedPath);
// Permission check
try {
final stat = await file.stat();
if (stat.type == FileSystemEntityType.notFound) {
return ToolResult.error('File not found: ${parsed.filePath}');
}
} on FileSystemException catch (e) {
return ToolResult.error('Permission denied: ${e.message}');
}
final stat = await file.stat();
final fileSize = stat.size;
final modified = stat.modified;
// Check for binary file
final binaryInfo = await _detectBinaryFile(file);
if (binaryInfo != null) {
return _handleBinaryFile(file, parsed, binaryInfo, fileSize, modified);
}
// Handle special file types by extension
final ext = p.extension(parsed.filePath).toLowerCase();
if (ext == '.ipynb') {
return _handleNotebook(file, fileSize, modified);
}
if (ext == '.pdf') {
return _handlePdf(file, parsed, fileSize, modified);
}
// Read as text
return _readTextFile(file, parsed, fileSize, modified);
}