Smart_Code_Generator / agent /loop_controller.py
SaiSankarSwarna's picture
Initial commit
3962d8b
Raw
History Blame Contribute Delete
6.66 kB
import time
from datetime import datetime
from typing import Iterator
from .code_generator import CodeGenerator
from .code_executor import CodeExecutor
from .error_parser import parse_error
from .reflection import ReflectionModule
from .task_classifier import TaskClassifier
from .multi_language_agent import MultiLanguageAgent
class AgentLoopController:
def __init__(self, api_key: str, model: str = "llama-3.3-70b-versatile"):
self.generator = CodeGenerator(api_key, model)
self.executor = CodeExecutor()
self.reflector = ReflectionModule(api_key, model)
self.classifier = TaskClassifier()
self.multi_agent = MultiLanguageAgent(api_key, model)
def run(
self,
task: str,
test_cases: str,
max_iterations: int = 5,
timeout: int = 10,
) -> Iterator[dict]:
start_time = time.time()
yield self._evt("start", f"Agent started - max {max_iterations} iterations, {timeout}s timeout")
yield self._evt("classifying", "Detecting task type and target languages...")
classification = self.classifier.classify(task)
mode = classification["mode"]
languages = classification.get("languages", ["Python"])
yield self._evt(
"classified",
f"Mode: {mode.upper()} | Languages: {', '.join(languages)}",
mode=mode,
languages=languages,
)
if mode == "analyze":
yield from self._run_analyze(task)
else:
yield from self._run_execute(task, test_cases, max_iterations, timeout, start_time)
def _run_analyze(self, task: str) -> Iterator[dict]:
yield self._evt("analyzing", "Generating multi-language analysis with LLM")
try:
result = self.multi_agent.generate(task)
langs = [impl["language"] for impl in result.get("implementations", [])]
label = ", ".join(langs) if langs else "response ready"
yield self._evt("analysis_ready", f"Analysis complete: {label}", analysis=result)
yield self._evt(
"complete",
"Analysis finished.",
success=True,
mode="analyze",
final_code="",
total_time=0,
iterations_count=0,
iterations=[],
analysis=result,
)
except Exception as exc:
yield self._evt("failed", f"Analysis failed: {exc}", error=str(exc))
def _run_execute(
self, task: str, test_cases: str, max_iterations: int, timeout: int, start_time: float
) -> Iterator[dict]:
all_iterations: list[dict] = []
yield self._evt("generating", "Generating initial code with LLM")
try:
code, _ = self.generator.generate(task, test_cases)
except Exception as exc:
yield self._evt("failed", f"LLM call failed: {exc}", error=str(exc))
return
yield self._evt("code_ready", f"Initial code ready ({self._line_count(code)} lines)", code=code, iteration=0)
for iteration in range(1, max_iterations + 1):
yield self._evt(
"executing",
f"Executing code - iteration {iteration}/{max_iterations}",
code=code,
iteration=iteration,
)
exec_result = self.executor.execute(code, test_cases, timeout)
iter_data: dict = {
"iteration": iteration,
"code": code,
"execution": exec_result,
"timestamp": self._ts(),
}
if exec_result["success"]:
iter_data["status"] = "success"
all_iterations.append(iter_data)
yield self._evt(
"success",
f"Code passed on iteration {iteration}",
code=code,
iteration=iteration,
execution=exec_result,
iteration_data=iter_data,
)
yield self._evt(
"complete",
f"Task completed successfully in {iteration} iteration(s).",
iterations=all_iterations,
final_code=code,
success=True,
mode="execute",
total_time=round(time.time() - start_time, 2),
iterations_count=iteration,
)
return
error_info = parse_error(exec_result)
iter_data["status"] = "failed"
iter_data["error"] = error_info
all_iterations.append(iter_data)
yield self._evt(
"error",
f"Error on iteration {iteration}: {error_info['type']}: {error_info['message'][:120]}",
code=code,
iteration=iteration,
execution=exec_result,
error=error_info,
iteration_data=iter_data,
)
if iteration < max_iterations:
yield self._evt("reflecting", "Sending error to LLM for reflection and fix", iteration=iteration)
try:
new_code, reflection = self.reflector.reflect_and_refine(
task, code, exec_result, error_info
)
iter_data["reflection"] = reflection
code = new_code
yield self._evt(
"refined",
"Code refined based on error feedback",
new_code=new_code,
reflection=reflection,
iteration=iteration,
)
except Exception as exc:
yield self._evt("error", f"Reflection failed: {exc}", iteration=iteration)
yield self._evt(
"complete",
f"Reached max iterations ({max_iterations}) without full success.",
iterations=all_iterations,
final_code=code,
success=False,
mode="execute",
total_time=round(time.time() - start_time, 2),
iterations_count=max_iterations,
)
def _evt(self, event_type: str, message: str, **kwargs) -> dict:
return {"type": event_type, "message": message, "timestamp": self._ts(), **kwargs}
@staticmethod
def _ts() -> str:
return datetime.now().strftime("%H:%M:%S")
@staticmethod
def _line_count(code: str) -> int:
return len(code.strip().splitlines())