step method
Executes a single step of the agent's main logic.
This method is called repeatedly by the orchestrator and should:
- Check for work to do
- Perform any necessary actions
- Update status appropriately
Implementations should be idempotent and handle their own errors.
Implementation
@override
Future<void> step() async {
if (_activeTask == null || status != AgentStatus.working) return;
final task = _activeTask!;
logger.info('[Agent $id] Executing Task #${task.id}: ${task.name}');
final fileContext = _getFileContext(task.files);
final prompt = '''
You are an expert developer. Implement the following task.
TASK: ${task.name}
OBJECTIVE: ${task.objective}
CURRENT FILE CONTEXT:
$fileContext
FILES TO MODIFY/CREATE: ${task.files.join(', ')}
Return the full content of each file wrapped in <file_content path="path/to/file"> XML tags.
Example:
<file_content path="lib/main.dart">
void main() {}
</file_content>
''';
try {
final response = await provider.generateResponse(prompt);
final fileContents = _parseFileContents(response);
if (fileContents.isEmpty) {
logger.warn(
'[Agent $id] No file contents generated for Task #${task.id}');
_completeTask(task.id, success: false);
return;
}
for (final entry in fileContents.entries) {
final file = File(entry.key);
if (!file.parent.existsSync()) {
file.parent.createSync(recursive: true);
}
file.writeAsStringSync(entry.value);
logger.detail('[Agent $id] Updated ${entry.key}');
}
logger.success('[Agent $id] Completed Task #${task.id}');
_completeTask(task.id, success: true);
} catch (e) {
logger.err('[Agent $id] Error executing Task #${task.id}: $e');
// Re-throw to let orchestrator handle error recovery
rethrow;
}
}