166 lines
5.8 KiB
YAML
166 lines
5.8 KiB
YAML
# artifact-ai - Generate or modify artifacts using AI
|
|
# Usage: cat diagram.puml | artifact-ai --format plantuml --instruction "Add a cache layer"
|
|
# Usage: echo "" | artifact-ai --format mermaid --instruction "Create a flowchart for login"
|
|
|
|
name: artifact-ai
|
|
description: Generate or modify artifacts (diagrams, 3D models, code) using AI
|
|
category: Artifact
|
|
|
|
arguments:
|
|
- flag: --format
|
|
variable: format
|
|
required: true
|
|
description: "Artifact format: plantuml, mermaid, openscad, svg, excalidraw, code"
|
|
- flag: --instruction
|
|
variable: instruction
|
|
required: true
|
|
description: Natural language instruction for generating or modifying the artifact
|
|
|
|
steps:
|
|
# Step 1: Build format-specific prompt and call AI
|
|
- type: code
|
|
output_var: prompt
|
|
code: |
|
|
import json
|
|
|
|
format_prompts = {
|
|
'plantuml': """You are a PlantUML expert. Create or modify PlantUML diagrams.
|
|
|
|
Supported diagram types:
|
|
- Sequence diagrams: actor, participant, ->, -->
|
|
- Class diagrams: class, interface, extends, implements
|
|
- Activity diagrams: start, stop, :action;, if/then/else
|
|
- Component diagrams: component, package, [interface]
|
|
- State diagrams: state, [*], -->
|
|
|
|
Always wrap with @startuml/@enduml.""",
|
|
|
|
'mermaid': """You are a Mermaid diagram expert. Create or modify Mermaid diagrams.
|
|
|
|
Supported diagram types:
|
|
- Flowcharts: graph TD/LR, A-->B
|
|
- Sequence: sequenceDiagram, Alice->>Bob
|
|
- Class: classDiagram, class ClassName
|
|
- State: stateDiagram-v2
|
|
- Entity Relationship: erDiagram
|
|
- Gantt: gantt, section, task
|
|
|
|
Start with the diagram type declaration (graph TD, sequenceDiagram, etc.).""",
|
|
|
|
'openscad': """You are an OpenSCAD 3D modeling expert. Create or modify parametric 3D models.
|
|
|
|
Core operations:
|
|
- Primitives: cube(), sphere(), cylinder(), polyhedron()
|
|
- Transformations: translate(), rotate(), scale(), mirror()
|
|
- Boolean: union(), difference(), intersection()
|
|
- 2D: circle(), square(), polygon(), linear_extrude(), rotate_extrude()
|
|
|
|
Use modules for reusable components. Use $fn for smoothness.""",
|
|
|
|
'svg': """You are an SVG expert. Create or modify vector graphics.
|
|
|
|
Core elements:
|
|
- Shapes: <rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon>, <path>
|
|
- Text: <text>, <tspan>
|
|
- Groups: <g>, <defs>, <use>, <symbol>
|
|
- Styling: fill, stroke, stroke-width, opacity, transform
|
|
|
|
Include xmlns and viewBox. Use descriptive IDs.""",
|
|
|
|
'excalidraw': """You are an Excalidraw expert. Create hand-drawn style diagrams as JSON.
|
|
|
|
Structure:
|
|
- type: element type (rectangle, diamond, ellipse, arrow, line, text)
|
|
- x, y: position
|
|
- width, height: dimensions
|
|
- strokeColor, backgroundColor, fillStyle
|
|
- roughness: 0-2 (0=smooth, 2=sketchy)
|
|
|
|
Output valid JSON with "type": "excalidraw" and "elements" array.""",
|
|
|
|
'code': """You are a programming expert. Create or modify code in any language.
|
|
|
|
Focus on:
|
|
- Clean, readable code
|
|
- Proper language conventions
|
|
- Comments for complex logic only
|
|
- Error handling where appropriate
|
|
|
|
Detect the language from context or instruction."""
|
|
}
|
|
|
|
format_outputs = {
|
|
'plantuml': "Output ONLY valid PlantUML code starting with @startuml and ending with @enduml.",
|
|
'mermaid': "Output ONLY valid Mermaid code starting with the diagram type.",
|
|
'openscad': "Output ONLY valid OpenSCAD code with proper syntax.",
|
|
'svg': "Output ONLY valid SVG code starting with <?xml or <svg and ending with </svg>.",
|
|
'excalidraw': 'Output ONLY valid Excalidraw JSON starting with { and ending with }.',
|
|
'code': "Output ONLY the code, no markdown fences or explanations."
|
|
}
|
|
|
|
current_code = input.strip() if input.strip() else "(empty - create from scratch)"
|
|
format_guide = format_prompts.get(format, f"You are a {format} expert.")
|
|
output_instruction = format_outputs.get(format, "Output ONLY the code, no explanations.")
|
|
|
|
prompt = f"""{format_guide}
|
|
|
|
CRITICAL: {output_instruction}
|
|
|
|
Current code:
|
|
---
|
|
{current_code}
|
|
---
|
|
|
|
User request: {instruction}
|
|
|
|
{output_instruction}"""
|
|
|
|
# Don't print - just set the variable
|
|
result = prompt
|
|
|
|
- type: prompt
|
|
prompt: "{prompt}"
|
|
provider: claude
|
|
output_var: ai_output
|
|
|
|
# Step 2: Clean up output based on format
|
|
- type: code
|
|
output_var: result
|
|
code: |
|
|
import re
|
|
|
|
code = ai_output.strip()
|
|
|
|
# Remove markdown code blocks if present (three backticks)
|
|
fence_pattern = r'`{3}(?:\w+)?\n(.*?)`{3}'
|
|
match = re.search(fence_pattern, code, re.DOTALL)
|
|
if match:
|
|
code = match.group(1).strip()
|
|
|
|
# Format-specific cleanup
|
|
if format == 'svg':
|
|
# Remove any wrapper formats
|
|
code = re.sub(r'^@startuml\s*\n?', '', code)
|
|
code = re.sub(r'\n?@enduml\s*$', '', code)
|
|
# Find SVG content
|
|
svg_match = re.search(r'(<\?xml[^?]*\?>)?\s*(<svg[\s\S]*?</svg>)', code)
|
|
if svg_match:
|
|
xml_decl = svg_match.group(1) or ''
|
|
svg_content = svg_match.group(2)
|
|
code = (xml_decl + '\n' + svg_content).strip() if xml_decl else svg_content
|
|
|
|
elif format == 'excalidraw':
|
|
# Find JSON object
|
|
json_match = re.search(r'\{[\s\S]*\}', code)
|
|
if json_match:
|
|
code = json_match.group(0)
|
|
|
|
elif format == 'plantuml':
|
|
# Ensure proper tags
|
|
if not code.strip().startswith('@start'):
|
|
code = '@startuml\n' + code
|
|
if not code.strip().endswith('@enduml') and '@enduml' not in code:
|
|
code = code + '\n@enduml'
|
|
|
|
print(code.strip())
|