""" CodingAgent — Autonomous code generation, editing, refactoring (Devin/Genspark style) """ import json import os import re from typing import Dict, List import structlog from .base_agent import BaseAgent log = structlog.get_logger() CODING_SYSTEM = """You are an elite autonomous software engineer — like Devin combined with Genspark. You write production-quality code that is: - Clean, readable, well-structured - Properly typed (TypeScript/Python type hints) - Error-handled and resilient - Documented with clear comments - Following best practices for the language/framework When generating code: 1. Think about the full architecture first 2. Write complete, runnable code (not snippets) 3. Include proper imports 4. Add error handling 5. Include brief usage examples in comments Support: Python, TypeScript, JavaScript, Go, Rust, SQL, Shell, YAML, JSON """ class CodingAgent(BaseAgent): def __init__(self, ws_manager=None, ai_router=None): super().__init__("CodingAgent", ws_manager, ai_router) async def run(self, task: str, context: Dict = {}, **kwargs) -> str: session_id = kwargs.get("session_id", "") task_id = kwargs.get("task_id", "") await self.emit(task_id, "agent_start", { "agent": "CodingAgent", "task": task[:80], }, session_id) # Build context-aware messages prev_results = context.get("previous_results", []) project_ctx = context.get("project_context", "") plan = context.get("plan", "") system_content = CODING_SYSTEM if project_ctx: system_content += f"\n\nProject Context:\n{project_ctx[:1000]}" user_content = f"Task: {task}" if plan: user_content += f"\n\nExecution Plan:\n{plan[:500]}" if prev_results: user_content += f"\n\nPrevious results:\n" + "\n".join(str(r)[:200] for r in prev_results[-3:]) messages = [ {"role": "system", "content": system_content}, {"role": "user", "content": user_content}, ] await self.emit(task_id, "tool_called", { "agent": "CodingAgent", "tool": "code_generation", "step": task[:60], }, session_id) result = await self.llm( messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=8192, ) # Extract code blocks for display code_blocks = self._extract_code_blocks(result) await self.emit(task_id, "code_generated", { "agent": "CodingAgent", "code_blocks": len(code_blocks), "total_lines": sum(len(b.split("\n")) for b in code_blocks), "languages": list(set(self._detect_language(b) for b in code_blocks)), }, session_id) return result async def generate_file( self, filename: str, description: str, task_id: str = "", session_id: str = "", context: Dict = {}, ) -> str: """Generate a complete file with proper structure.""" messages = [ {"role": "system", "content": CODING_SYSTEM}, {"role": "user", "content": ( f"Generate a complete, production-ready file.\n" f"Filename: {filename}\n" f"Description: {description}\n" f"Context: {json.dumps(context)[:500]}\n\n" f"Return ONLY the file content, no explanation." )}, ] content = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192) # Strip markdown code fences if present content = self._strip_code_fences(content) # Write to workspace workspace = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace") filepath = os.path.join(workspace, filename) os.makedirs(os.path.dirname(filepath), exist_ok=True) with open(filepath, "w") as f: f.write(content) await self.emit(task_id, "file_written", { "filename": filename, "size": len(content), "lines": len(content.split("\n")), }, session_id) return content async def refactor( self, code: str, instructions: str, task_id: str = "", session_id: str = "", ) -> str: """Refactor existing code based on instructions.""" messages = [ {"role": "system", "content": CODING_SYSTEM}, {"role": "user", "content": ( f"Refactor this code based on these instructions:\n" f"Instructions: {instructions}\n\n" f"Original code:\n```\n{code}\n```\n\n" f"Return ONLY the refactored code." )}, ] return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192) async def scan_repository(self, repo_path: str) -> Dict: """Scan repository and build project intelligence graph.""" import subprocess try: result = subprocess.run( ["find", repo_path, "-type", "f", "-name", "*.py", "-o", "-name", "*.ts", "-o", "-name", "*.js", "-o", "-name", "*.go"], capture_output=True, text=True, timeout=10 ) files = result.stdout.strip().split("\n")[:50] # Read key files key_files = {} for f in ["package.json", "requirements.txt", "tsconfig.json", "pyproject.toml", "go.mod"]: path = os.path.join(repo_path, f) if os.path.exists(path): with open(path) as fp: key_files[f] = fp.read()[:1000] return { "files": files, "key_configs": key_files, "total_files": len(files), } except Exception as e: return {"error": str(e), "files": [], "key_configs": {}} def _extract_code_blocks(self, text: str) -> List[str]: pattern = r"```[\w]*\n(.*?)```" return re.findall(pattern, text, re.DOTALL) def _strip_code_fences(self, text: str) -> str: text = re.sub(r"^```[\w]*\n", "", text.strip()) text = re.sub(r"\n```$", "", text) return text def _detect_language(self, code: str) -> str: if "def " in code and "import " in code: return "python" if "function " in code or "const " in code or "interface " in code: return "typescript" if "package main" in code: return "go" return "unknown"