2008robocode-crypto/code-generation-system
0
1"""2Repair engine for fixing detected issues in generated configurations.3Implements intelligent repairs rather than blind retries.4"""5 6import json7from typing import Any, Dict, List, Optional, Tuple8from schemas import FieldType9 10 11class RepairEngine:12 """Repairs detected issues in generated configurations."""13 14 def __init__(self):15 self.repairs_made = []16 17 def repair_json(self, json_str: str) -> Tuple[bool, Optional[Dict[str, Any]]]:18 """Attempt to repair malformed JSON."""19 # Try obvious fixes first20 attempts = [21 json_str,22 json_str.rstrip(",") + "}", # Remove trailing comma before }23 json_str.rstrip(",") + "]", # Remove trailing comma before ]24 self._fix_unquoted_keys(json_str),25 self._fix_missing_quotes(json_str),26 ]27 28 for attempt in attempts:29 try:30 data = json.loads(attempt)31 self.repairs_made.append(f"Fixed malformed JSON")32 return True, data33 except json.JSONDecodeError:34 continue35 36 return False, None37 38 def _fix_unquoted_keys(self, json_str: str) -> str:39 """Fix unquoted keys in JSON."""40 import re41 # Pattern to match unquoted keys42 return re.sub(r'(\w+):', r'"\1":', json_str)43 44 def _fix_missing_quotes(self, json_str: str) -> str:45 """Attempt to fix missing quotes around values."""46 # This is risky, so be conservative47 return json_str48 49 def repair_missing_fields(self, config: Dict[str, Any], required_fields: List[str]) -> Dict[str, Any]:50 """Add missing required fields with sensible defaults."""51 for field in required_fields:52 if field not in config or config[field] is None:53 default = self._get_default_for_field(field)54 config[field] = default55 self.repairs_made.append(f"Added missing field '{field}' with default: {default}")56 57 return config58 59 def _get_default_for_field(self, field_name: str) -> Any:60 """Provide sensible default for a field."""61 defaults = {62 "app_name": "GeneratedApp",63 "app_description": "Auto-generated application",64 "database_schema": [],65 "api_schema": [],66 "ui_schema": [],67 "auth_config": {"type": "basic"},68 "roles": [{"name": "user", "permissions": []}],69 "business_logic": {},70 "validation_metadata": {},71 }72 return defaults.get(field_name, "")73 74 def repair_database_schema(self, db_schema: List[Dict[str, Any]]) -> List[Dict[str, Any]]:75 """Repair issues in database schema."""76 repaired = []77 78 for table in db_schema:79 if not isinstance(table, dict):80 continue81 82 # Ensure required fields83 if "name" not in table:84 table["name"] = f"table_{len(repaired)}"85 self.repairs_made.append(f"Added missing table name")86 87 if "fields" not in table:88 table["fields"] = []89 self.repairs_made.append(f"Table '{table['name']}': added empty fields list")90 91 if "primary_key" not in table:92 table["primary_key"] = "id"93 self.repairs_made.append(f"Table '{table['name']}': added default primary_key")94 95 # Repair fields96 if isinstance(table["fields"], list):97 table["fields"] = self._repair_fields(table["fields"], table["name"])98 99 repaired.append(table)100 101 return repaired102 103 def _repair_fields(self, fields: List[Dict[str, Any]], table_name: str) -> List[Dict[str, Any]]:104 """Repair field definitions."""105 repaired = []106 107 for field in fields:108 if not isinstance(field, dict):109 continue110 111 # Ensure name112 if "name" not in field:113 field["name"] = f"field_{len(repaired)}"114 self.repairs_made.append(f"Table '{table_name}': added field name")115 116 # Ensure valid type117 if "type" not in field:118 field["type"] = FieldType.STRING.value119 self.repairs_made.append(f"Table '{table_name}', field '{field['name']}': set default type to string")120 else:121 valid_types = [t.value for t in FieldType]122 if field["type"] not in valid_types:123 field["type"] = FieldType.STRING.value124 self.repairs_made.append(125 f"Table '{table_name}', field '{field['name']}': fixed invalid type"126 )127 128 # Ensure required field129 if "required" not in field:130 field["required"] = True131 132 repaired.append(field)133 134 return repaired135 136 def repair_api_schema(self, api_schema: List[Dict[str, Any]]) -> List[Dict[str, Any]]:137 """Repair issues in API schema."""138 repaired = []139 valid_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"]140 141 for endpoint in api_schema:142 if not isinstance(endpoint, dict):143 continue144 145 # Ensure path146 if "path" not in endpoint:147 endpoint["path"] = f"/endpoint_{len(repaired)}"148 self.repairs_made.append(f"API: added missing endpoint path")149 150 # Ensure valid method151 if "method" not in endpoint:152 endpoint["method"] = "GET"153 self.repairs_made.append(f"API {endpoint['path']}: added default method GET")154 elif endpoint["method"] not in valid_methods:155 endpoint["method"] = "POST"156 self.repairs_made.append(f"API {endpoint['path']}: fixed invalid HTTP method")157 158 # Ensure description159 if "description" not in endpoint:160 endpoint["description"] = f"Endpoint for {endpoint['path']}"161 self.repairs_made.append(f"API {endpoint['path']}: added auto-description")162 163 repaired.append(endpoint)164 165 return repaired166 167 def repair_ui_schema(self, ui_schema: List[Dict[str, Any]]) -> List[Dict[str, Any]]:168 """Repair issues in UI schema."""169 repaired = []170 171 for page in ui_schema:172 if not isinstance(page, dict):173 continue174 175 # Ensure path176 if "path" not in page:177 page["path"] = f"/page_{len(repaired)}"178 self.repairs_made.append(f"UI: added missing page path")179 180 # Ensure title181 if "title" not in page:182 page["title"] = page["path"].replace("/", " ").title()183 self.repairs_made.append(f"UI page {page['path']}: added auto-generated title")184 185 # Ensure components186 if "components" not in page:187 page["components"] = []188 self.repairs_made.append(f"UI page {page['path']}: added empty components list")189 190 repaired.append(page)191 192 return repaired193 194 def repair_roles_config(self, roles: List[Dict[str, Any]]) -> List[Dict[str, Any]]:195 """Repair roles configuration."""196 repaired = []197 198 for role in roles:199 if not isinstance(role, dict):200 continue201 202 if "name" not in role:203 role["name"] = f"role_{len(repaired)}"204 self.repairs_made.append(f"Added missing role name")205 206 if "permissions" not in role:207 role["permissions"] = []208 self.repairs_made.append(f"Role '{role['name']}': added empty permissions list")209 210 if "description" not in role:211 role["description"] = f"Role: {role['name']}"212 self.repairs_made.append(f"Role '{role['name']}': added auto-description")213 214 repaired.append(role)215 216 return repaired217 218 def repair_config(self, config: Dict[str, Any]) -> Tuple[Dict[str, Any], List[str]]:219 """Run complete repair on configuration."""220 self.repairs_made = []221 222 # Repair missing top-level fields223 required_fields = [224 "app_name", "app_description", "database_schema", 225 "api_schema", "ui_schema", "auth_config", "roles", "business_logic"226 ]227 config = self.repair_missing_fields(config, required_fields)228 229 # Repair each layer230 if isinstance(config["database_schema"], list):231 config["database_schema"] = self.repair_database_schema(config["database_schema"])232 233 if isinstance(config["api_schema"], list):234 config["api_schema"] = self.repair_api_schema(config["api_schema"])235 236 if isinstance(config["ui_schema"], list):237 config["ui_schema"] = self.repair_ui_schema(config["ui_schema"])238 239 if isinstance(config["roles"], list):240 config["roles"] = self.repair_roles_config(config["roles"])241 242 return config, self.repairs_made243 