CascadingDev/agents/visualizer.py

92 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""
AI_Visualizer agent.
Generates placeholder PlantUML diagrams on demand when @AI_Visualizer (or @AI_visual)
is mentioned in a discussion. Provides scaffolding for future AI-powered
diagram generation.
"""
from __future__ import annotations
import argparse
import re
from pathlib import Path
# Support multiple mention patterns (case-insensitive)
MENTION_REGEX = re.compile(r"@ai[-_]visual(?:izer)?\s*:?\s*(.+)", re.IGNORECASE)
BLOCK_START = "<!-- AUTO:VISUALIZER START -->"
BLOCK_END = "<!-- AUTO:VISUALIZER END -->"
def find_next_diagram(diagram_dir: Path) -> Path:
diagram_dir.mkdir(parents=True, exist_ok=True)
existing = sorted(diagram_dir.glob("diagram_*.puml"))
next_index = len(existing) + 1
return diagram_dir / f"diagram_{next_index:03d}.puml"
def write_placeholder_plantuml(path: Path, prompt: str) -> None:
content = "\n".join(
[
"@startuml",
"' Auto-generated scaffold",
"' Requested via @AI_Visualizer",
f"note as N1",
prompt.strip() or "Diagram requested with no additional context.",
"end note",
"@enduml",
"",
]
)
path.write_text(content, encoding="utf-8")
def append_comment(discussion_path: Path, diagram_rel: Path) -> None:
comment = (
f"{BLOCK_START}\n"
"Name: AI_Visualizer\n"
f"Generated diagram: `{diagram_rel.as_posix()}`\n"
"\n"
"Let me know if you need an updated view.\n"
f"{BLOCK_END}\n"
)
text = discussion_path.read_text(encoding="utf-8")
if text and not text.endswith("\n"):
text += "\n"
discussion_path.write_text(text + comment, encoding="utf-8")
def main() -> int:
parser = argparse.ArgumentParser(description="AI Visualizer agent")
parser.add_argument("--repo-root", required=True, help="Repository root path")
parser.add_argument("--path", required=True, help="Relative path to discussion file")
args = parser.parse_args()
repo_root = Path(args.repo_root).resolve()
discussion_rel = Path(args.path)
discussion_path = (repo_root / discussion_rel).resolve()
if not discussion_path.exists():
return 0
text = discussion_path.read_text(encoding="utf-8")
match = MENTION_REGEX.search(text)
if not match:
return 0
# Simple check to avoid re-processing if our comment is already there
if f"Name: AI_Visualizer" in text and BLOCK_START in text:
return 0
diagram_dir = discussion_path.parent.parent / "diagrams"
diagram_path = find_next_diagram(diagram_dir)
prompt = match.group(1) # Extract text after the mention
write_placeholder_plantuml(diagram_path, prompt)
append_comment(discussion_path, diagram_path.relative_to(repo_root))
return 0
if __name__ == "__main__":
raise SystemExit(main())