"""code_agent.py — Coding Agent: scan→analyze→plan→edit→validate→reflect""" import asyncio, json, re from models.ollama_client import OllamaClient SYSTEM = """Sei un coding agent esperto. Analisi codice, bugfix, refactor. Rispondi con JSON strutturato quando richiesto.""" class CodeAgent: def __init__(self, ollama: OllamaClient): self.ollama = ollama async def _llm_json(self, prompt:str, system:str=SYSTEM, max_tokens:int=1024)->dict: msgs=[{"role":"system","content":system},{"role":"user","content":prompt}] try: raw=await self.ollama.chat(msgs,temperature=0.2,max_tokens=max_tokens) m=re.search(r'\{[\s\S]+\}',raw) return json.loads(m.group()) if m else {} except: return {} async def analyze_file(self, filepath:str, content:str, goal:str)->dict: p=f"Analizza per: {goal}\nFile: {filepath}\nContenuto (prime 3000 char):\n{content[:3000]}\n\nRispondi JSON: {{issues:[], suggestions:[], complexity:'low|medium|high', priority:1-10, safe_to_edit:bool}}" r=await self._llm_json(p) return r or {"issues":[],"suggestions":[],"complexity":"unknown","priority":5,"safe_to_edit":True} async def plan_edit(self, filepath:str, content:str, goal:str)->dict: p=f"Pianifica modifiche per: {goal}\nFile: {filepath}\n{content[:2500]}\n\nJSON: {{steps:[{{description,type:'insert|replace|delete',old_code,new_code,risk:'low|medium|high'}}], requires_tests:bool, breaking_change:bool}}" r=await self._llm_json(p,max_tokens=2048) return r or {"steps":[],"requires_tests":False,"breaking_change":False,"_fallback":True} async def generate_fix(self, filepath:str, content:str, issue:str)->str: msgs=[{"role":"system","content":SYSTEM}, {"role":"user","content":f"Correggi: {issue}\nFile: {filepath}\n{content[:4000]}\n\nRestituisci SOLO il codice corretto."}] return await self.ollama.chat(msgs,temperature=0.15,max_tokens=4096) async def validate_edit(self, original:str, edited:str, goal:str)->dict: p=f"Valida modifica per: {goal}\nPRIMA:{original[:1500]}\nDOPO:{edited[:1500]}\nJSON:{{valid:bool,achieves_goal:bool,regressions:[],confidence:0-1}}" r=await self._llm_json(p,max_tokens=512) return r or {"valid":True,"achieves_goal":True,"regressions":[],"confidence":0.7,"_fallback":True} async def full_session(self, goal:str, files:list[dict])->dict: session={"goal":goal,"analyzed":[],"edits":[]} for f in files[:4]: analysis=await self.analyze_file(f["path"],f["content"],goal) if (analysis.get("priority") or 0)>3: plan=await self.plan_edit(f["path"],f["content"],goal) session["analyzed"].append({"path":f["path"],"analysis":analysis,"plan":plan}) if plan.get("steps"): edited=await self.generate_fix(f["path"],f["content"],goal) val=await self.validate_edit(f["content"],edited,goal) session["edits"].append({"path":f["path"],"edited":edited,"validation":val}) session["summary"]=f"Analizzati {len(session['analyzed'])} file, {len(session['edits'])} modifiche." return session