execute method
Execute the tool with the given input.
Implementation
@override
Future<ToolResult> execute(Map<String, dynamic> input) async {
final validation = validateInput(input);
if (!validation.isValid) return ToolResult.error(validation.error!);
final parsed = NotebookEditInput.fromMap(input);
final file = File(parsed.notebookPath);
// Check existence.
if (!await file.exists()) {
return ToolResult.error('Notebook not found: ${parsed.notebookPath}');
}
// Check size.
final stat = await file.stat();
if (stat.size > maxNotebookSize) {
return ToolResult.error(
'Notebook too large: '
'${(stat.size / (1024 * 1024)).toStringAsFixed(1)} MB '
'(max ${maxNotebookSize ~/ (1024 * 1024)} MB)',
);
}
// Parse notebook JSON.
final Map<String, dynamic> notebook;
try {
final raw = await file.readAsString();
notebook = jsonDecode(raw) as Map<String, dynamic>;
} catch (e) {
return ToolResult.error('Failed to parse notebook JSON: $e');
}
// Validate notebook structure.
if (!notebook.containsKey('cells') || notebook['cells'] is! List) {
return ToolResult.error(
'Invalid notebook: missing or malformed "cells" array',
);
}
final cells = (notebook['cells'] as List).cast<Map<String, dynamic>>();
// Create backup before modifying.
await _createBackup(file);
try {
final result = switch (parsed.command) {
'add' => _addCell(cells, parsed),
'edit' => _editCell(cells, parsed),
'delete' => _deleteCell(cells, parsed),
'move' => _moveCell(cells, parsed),
_ => NotebookEditOutput(
success: false,
message: 'Unknown command: ${parsed.command}',
cellCount: cells.length,
),
};
if (!result.success) {
return ToolResult.error(result.message);
}
// Write updated notebook, preserving metadata and kernel info.
notebook['cells'] = cells;
final encoder = const JsonEncoder.withIndent(' ');
await file.writeAsString(encoder.convert(notebook));
return ToolResult.success(
result.toString(),
metadata: result.toMetadata(),
);
} catch (e) {
return ToolResult.error('Error editing notebook: $e');
}
}