92 lines
2.8 KiB
Python
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())
|