Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions coda/agents/debug_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,23 @@ def debug_code_if_needed(self, code_result, execution_result: ExecutionResult,

# Use debug_and_fix method
try:
fixed_code = self.debug_and_fix(code_text, error_msg, max_attempts=3)
if fixed_code != code_text:
# Re-execute the fixed code
# debug_and_fix may return either a string (fixed code) or a dict
debug_fix_result = self.debug_and_fix(code_text, error_msg, max_attempts=3)
fixed_code = None
exec_result_from_fix = None

if isinstance(debug_fix_result, dict):
fixed_code = debug_fix_result.get('fixed_code')
exec_result_from_fix = debug_fix_result.get('execution_result')
else:
fixed_code = debug_fix_result

# If the debug function already produced an ExecutionResult, return it directly
if isinstance(exec_result_from_fix, ExecutionResult):
return exec_result_from_fix

# If we obtained fixed code string, re-run it
if isinstance(fixed_code, str) and fixed_code and fixed_code != code_text:
py_filepath = "generated_code.py" # Always use generated_code.py to match code_generator
return self.run_python_code(
code_text=fixed_code,
Expand Down Expand Up @@ -270,6 +284,25 @@ def run_python_code(
# For benchmark data, intelligently detect and replace incorrect file paths
code_text = self._intelligent_file_path_replacement(code_text, data_file_path)

# Ensure code_text is a string. If a dict (from debug helper), try to extract common keys.
if not isinstance(code_text, str):
if isinstance(code_text, dict):
for key in ('fixed_code', 'generated_code', 'code', 'code_text'):
candidate = code_text.get(key)
if isinstance(candidate, str):
code_text = candidate
break

if not isinstance(code_text, str):
self.logger.error("run_python_code received non-string code_text; cannot write to file.")
return ExecutionResult(
returncode=-1,
stdout="",
stderr="Failed to write code to file: code_text is not a string",
execution_time=0,
success=False
)

# Write the Python code to the file
try:
with open(py_filepath, 'w', encoding='utf-8') as f:
Expand Down
19 changes: 17 additions & 2 deletions coda/workflow/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,9 +1140,24 @@ def _save_iteration_result(self, workflow_id: str, iteration: WorkflowIteration)
with open(iteration_dir / "generated_code.py", 'w') as f:
f.write(iteration.code_generation_result.generated_code)

if hasattr(iteration.debug_result, 'fixed_code') and iteration.debug_result.fixed_code and iteration.debug_result.fixed_code != iteration.code_generation_result.generated_code:
# Safely handle fixed_code: it may be None, a string, or (unexpectedly) a dict
fixed_code_val = None
if hasattr(iteration.debug_result, 'fixed_code'):
fixed_code_val = iteration.debug_result.fixed_code

# If a dict was stored for some reason, try to extract common string keys
if isinstance(fixed_code_val, dict):
for key in ('fixed_code', 'code', 'generated_code'):
if isinstance(fixed_code_val.get(key), str):
fixed_code_val = fixed_code_val.get(key)
break

if isinstance(fixed_code_val, str) and fixed_code_val and (
not iteration.code_generation_result or
fixed_code_val != iteration.code_generation_result.generated_code
):
with open(iteration_dir / "fixed_code.py", 'w') as f:
f.write(iteration.debug_result.fixed_code)
f.write(fixed_code_val)

# Copy output image if available
if iteration.debug_result.output_file and os.path.exists(iteration.debug_result.output_file):
Expand Down