# puml-validator - Validates and fixes PlantUML syntax # Usage: cat diagram.puml | puml-validator # Returns: valid PlantUML (original if valid, fixed if correctable, error if unfixable) name: puml-validator description: Validates PlantUML syntax and fixes errors if possible category: Utility steps: # Step 1: Write input to temp file and validate - type: code code: | import subprocess import tempfile import os # Write to temp file with tempfile.NamedTemporaryFile(mode='w', suffix='.puml', delete=False) as f: f.write(input) temp_path = f.name # Try to validate with plantuml try: result = subprocess.run( ['plantuml', '-syntax', temp_path], capture_output=True, text=True, timeout=30 ) output = result.stdout + result.stderr is_valid = ('SYNTAX ERROR' not in output.upper() and 'ERROR' not in output.upper() and 'NO DIAGRAM FOUND' not in output.upper()) error_msg = output.strip() if not is_valid else "" except FileNotFoundError: # plantuml not installed, skip validation is_valid = True error_msg = "" except Exception as e: is_valid = False error_msg = str(e) finally: os.unlink(temp_path) needs_fix = "true" if not is_valid else "false" output_var: needs_fix, error_msg # Step 2: If valid, just return original - type: code code: | if needs_fix == "false": final_output = input done = "true" else: done = "false" final_output = "" output_var: done, final_output # Step 3: If invalid, try to fix with AI - type: prompt prompt: | Fix this PlantUML diagram. It has syntax errors. Error message: {error_msg} Original diagram: ``` {input} ``` Common issues: - Mermaid syntax mixed with PlantUML (use PlantUML only) - Missing @startuml/@enduml - Invalid arrow syntax (use --> not ->) - Unclosed notes or rectangles Return ONLY the fixed PlantUML code, nothing else. Start with @startuml and end with @enduml. If the diagram is unfixable, respond with: ERROR: [reason] provider: claude-haiku output_var: fixed_output skip_if: done == "true" # Step 4: Check if fix succeeded or returned error - type: code code: | if done == "true": result = final_output success = "true" elif fixed_output.strip().startswith("ERROR:"): result = fixed_output success = "false" else: result = fixed_output.strip() # Remove any markdown code blocks if present if result.startswith("```"): import re match = re.search(r'```(?:puml|plantuml)?\s*(.*?)```', result, re.DOTALL) if match: result = match.group(1).strip() success = "true" output_var: result, success output: "{result}"