step method

  1. @override
Future<void> step()
override

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}');

  // Get comprehensive codebase context
  final codebaseContext = _contextService.getCodebaseContext(task.files);
  final fileContext = _getFileContext(task.files);

  final prompt =
      '''
You are an expert developer working on a real codebase. Implement the following task with full awareness of the project context.

$codebaseContext

=== TASK DETAILS ===
TASK: ${task.name}
OBJECTIVE: ${task.objective}
VERIFICATION: ${task.verification}
ACCEPTANCE CRITERIA: ${task.acceptance}

=== TARGET FILES ===
FILES TO MODIFY/CREATE: ${task.files.join(', ')}

=== CURRENT FILE CONTENT ===
$fileContext

=== INSTRUCTIONS ===
1. Analyze the codebase context above to understand project structure, patterns, and conventions
2. Review related files and dependencies to ensure consistency
3. Follow existing code patterns and naming conventions
4. Implement the task objective while maintaining code quality and consistency
5. Ensure your implementation matches the acceptance criteria

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>

IMPORTANT: Only generate code that is relevant to this codebase. Do not invent new patterns or structures that don't match the existing codebase.
''';

  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;
  }
}