from __future__ import annotations import json import subprocess from pathlib import Path from .config import AGENT4_ROOT, settings from .models import SkillStep from .skillflow import normalize_steps class SolidWorksExtractor: def audit_part(self, part_path: str) -> list[SkillStep]: path = Path(part_path) if not path.exists(): raise FileNotFoundError(part_path) output_dir = settings.runtime_dir / "audits" / path.stem output_dir.mkdir(parents=True, exist_ok=True) command = [ "dotnet", "run", "--project", str(settings.part_feature_audit_project), "--", str(path), "--output-dir", str(output_dir), ] subprocess.run(command, check=True, cwd=str(AGENT4_ROOT)) return self._read_latest_steps(output_dir) def audit_active_part(self) -> list[SkillStep]: output_dir = settings.runtime_dir / "audits" / "active-part" output_dir.mkdir(parents=True, exist_ok=True) command = [ "dotnet", "run", "--project", str(settings.part_feature_audit_project), "--", "--active", "--output-dir", str(output_dir), ] subprocess.run(command, check=True, cwd=str(AGENT4_ROOT)) return self._read_latest_steps(output_dir) def _read_latest_steps(self, output_dir: Path) -> list[SkillStep]: candidates = sorted( list(output_dir.glob("*_modeling_plan.json")) + list(output_dir.glob("*_skill_flow.json")), key=lambda item: item.stat().st_mtime, reverse=True, ) if not candidates: raise FileNotFoundError(f"No audit JSON generated under {output_dir}") payload = json.loads(candidates[0].read_text(encoding="utf-8-sig")) return normalize_steps(payload)