Files
wehub-resource-sync 2c632336aa
CI / Viewer CI (push) Successful in 13m37s
CI / Core CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:38 +08:00

134 lines
4.2 KiB
Python

from __future__ import annotations
import argparse
import time
from pathlib import Path
from typing import Any
from agent.feedback import render_compile_signals
from agent.models import CompileSignalBundle
from cli.common import add_data_dir_argument, resolve_data_dir
from storage.repo import StorageRepo
from storage.revisions import active_model_path
from viewer.api.store import ViewerStore
def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="articraft compile")
parser.add_argument(
"record_dir",
type=Path,
help="Path to the saved record directory containing model.py.",
)
parser.add_argument(
"--repo-root",
type=Path,
default=Path("."),
help="Articraft code repository root.",
)
add_data_dir_argument(parser)
parser.add_argument(
"--target",
choices=("full", "visual"),
default="full",
help="Compile target to build.",
)
parser.add_argument(
"--validate",
action="store_true",
help="Run validation-heavy checks during full materialization.",
)
parser.add_argument(
"--strict-geom-qc",
action="store_true",
help="Do not downgrade geometry QC findings when validation is enabled.",
)
return parser
def _render_compile_report_signals(payload: dict[str, Any] | None) -> str | None:
if not isinstance(payload, dict):
return None
signal_payload = payload.get("signal_bundle")
if not isinstance(signal_payload, dict):
return None
try:
bundle = CompileSignalBundle.from_dict(signal_payload)
except Exception:
return None
return render_compile_signals(bundle)
def main(argv: list[str] | None = None) -> int:
parser = _build_parser()
args = parser.parse_args(argv)
repo_root = args.repo_root.resolve()
data_root = resolve_data_dir(repo_root, args.data_dir)
repo = StorageRepo(repo_root, data_root=data_root)
record_arg = args.record_dir.expanduser()
if record_arg.exists():
record_dir = record_arg.resolve()
else:
record_dir = repo.layout.record_dir(str(record_arg)).resolve()
record = repo.read_json(repo.layout.record_metadata_path(record_dir.name))
model_path = (
active_model_path(repo, record_dir.name, record=record)
if isinstance(record, dict)
else record_dir / "model.py"
)
if not model_path.is_file():
parser.error(f"Record model not found: {model_path}")
viewer_store = ViewerStore(repo_root, data_root=data_root)
started_at = time.perf_counter()
try:
result = viewer_store.materialization.materialize_record_assets(
record_dir.name,
force=True,
validate=bool(args.validate),
ignore_geom_qc=not bool(args.strict_geom_qc),
target=str(args.target),
)
except RuntimeError as exc:
elapsed_seconds = time.perf_counter() - started_at
compile_report = repo.read_json(
repo.layout.record_materialization_compile_report_path(record_dir.name)
)
rendered = _render_compile_report_signals(
compile_report if isinstance(compile_report, dict) else None
)
if rendered:
print(rendered)
else:
print(str(exc))
print(f"Elapsed: {elapsed_seconds:.2f}s")
return 1
elapsed_seconds = time.perf_counter() - started_at
compile_report = repo.read_json(
repo.layout.record_materialization_compile_report_path(record_dir.name)
)
rendered = _render_compile_report_signals(
compile_report if isinstance(compile_report, dict) else None
)
if rendered:
print(rendered)
urdf_path = repo.layout.record_materialization_urdf_path(record_dir.name)
action = "Compiled visuals for" if args.target == "visual" else "Recompiled"
print(f"{action} {model_path}")
print(f"Wrote URDF to {urdf_path}")
if result.warnings:
print(f"Warnings: {len(result.warnings)}")
for warning in result.warnings:
print(f"- {warning.splitlines()[0]}")
else:
print("Warnings: 0")
print(f"Elapsed: {elapsed_seconds:.2f}s")
return 0
if __name__ == "__main__":
raise SystemExit(main())