diff --git a/src/artifact_editor/gui.py b/src/artifact_editor/gui.py index 24f61b0..ce6ef3d 100644 --- a/src/artifact_editor/gui.py +++ b/src/artifact_editor/gui.py @@ -252,11 +252,56 @@ class AIThread(QThread): def _validate_output(self, code: str) -> tuple: """Validate the generated code. Returns (is_valid, error_message).""" + # For PlantUML, run syntax check via plantuml command + if self.artifact_type == 'plantuml': + return self._validate_plantuml(code) + + # For other formats, use renderer validation renderer = self._get_renderer() if renderer: return renderer.validate(code) return True, None # No validation available + def _validate_plantuml(self, code: str) -> tuple: + """Validate PlantUML code using plantuml -syntax command.""" + import shutil + + plantuml_cmd = shutil.which('plantuml') + if not plantuml_cmd: + # PlantUML not installed, skip validation + return True, None + + try: + result = subprocess.run( + [plantuml_cmd, '-syntax', '-pipe'], + input=code, + capture_output=True, + text=True, + timeout=30 + ) + + # Exit code 0 = valid, anything else = error + if result.returncode == 0: + return True, None + + # Parse error message from stdout + # Format: "ERROR\n\nSyntax Error?\n" + error_lines = result.stdout.strip().split('\n') + error_msg = "PlantUML syntax error" + + if len(error_lines) >= 2 and error_lines[0] == 'ERROR': + line_num = error_lines[1] + error_msg = f"PlantUML syntax error on line {line_num}" + if len(error_lines) >= 4: + error_msg += f": {error_lines[3]}" + + return False, error_msg + + except subprocess.TimeoutExpired: + return True, None # Skip validation on timeout + except Exception as e: + return True, None # Skip validation on error + def _call_ai(self, instruction: str, current_code: str) -> tuple: """Call artifact-ai SmartTool and return (success, response_or_error).