from src.graph.state import SandboxState from src.agents.coder import generate_code from src.agents.critic import analyze_error from src.sandbox.executor import execute_code def coder_node(state: SandboxState) -> dict: last_error = None if state.get("error_analysis"): last_error = state["error_analysis"] code = generate_code(state["user_prompt"], previous_error=last_error) trace_entry = { "node": "coder", "retry": state["retry_count"], "explanation": code.explanation[:200], "requirements": code.requirements, } return { "script": code.script, "requirements": code.requirements, "explanation": code.explanation, "trace": state.get("trace", []) + [trace_entry], } def executor_node(state: SandboxState) -> dict: result = execute_code(state["script"], state.get("requirements")) trace_entry = { "node": "executor", "retry": state["retry_count"], "exit_code": result.exit_code, "success": result.success, "stdout_preview": result.stdout[:300] if result.stdout else "", "stderr_preview": result.stderr[:300] if result.stderr else "", } updates: dict = { "sandbox_result": result, "files": result.files, "trace": state.get("trace", []) + [trace_entry], } if result.success: updates["final_output"] = result.stdout else: updates["final_error"] = result.stderr return updates def critic_node(state: SandboxState) -> dict: critique = analyze_error( script=state["script"], stderr=state["sandbox_result"].stderr, user_prompt=state["user_prompt"], ) trace_entry = { "node": "critic", "retry": state["retry_count"], "error_analysis": critique.error_analysis[:300], "correction_strategy": critique.correction_strategy[:300], "confidence": critique.confidence, } prev = state.get("error_analysis") or "" return { "error_analysis": prev + f"\n--- Attempt {state['retry_count'] + 1} ---\n" + critique.error_analysis, "correction_strategy": critique.correction_strategy, "retry_count": state["retry_count"] + 1, "trace": state.get("trace", []) + [trace_entry], } def success_node(state: SandboxState) -> dict: return { "final_output": state.get("final_output") or state.get("script", ""), "final_error": None, } def fail_node(state: SandboxState) -> dict: return { "final_output": None, "final_error": state.get("final_error", "Unknown error after all retries exhausted."), }