Spaces:
Running
Running
| import json | |
| import os | |
| from datetime import datetime | |
| from pathlib import Path | |
| from uuid import uuid4 | |
| from agent_core.config import ARTIFACT_ROOT, DEFAULT_LUX3D_OUTPUT_PATH, STEP_SUFFIXES, WORKDIR | |
| def safe_path(p: str) -> Path: | |
| raw_path = Path(p) | |
| path = (raw_path if raw_path.is_absolute() else WORKDIR / raw_path).resolve() | |
| if not path.is_relative_to(WORKDIR) and not path.is_relative_to(ARTIFACT_ROOT): | |
| raise ValueError(f"Path escapes workspace: {p}") | |
| return path | |
| def workspace_relative(path: Path) -> str: | |
| absolute = path if path.is_absolute() else WORKDIR / path | |
| normalized = Path(os.path.normpath(str(absolute))) | |
| if normalized.is_relative_to(WORKDIR): | |
| return str(normalized.relative_to(WORKDIR)) | |
| return str(normalized) | |
| def new_run_id() -> str: | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| return f"{timestamp}_{uuid4().hex[:6]}" | |
| def allocate_run_dir(output_root: Path) -> tuple[Path, str]: | |
| for _ in range(20): | |
| run_id = new_run_id() | |
| run_dir = output_root / "runs" / run_id | |
| if not run_dir.exists(): | |
| return run_dir, run_id | |
| raise RuntimeError("Failed to allocate a unique output run directory.") | |
| def resolve_run_output(requested_output_path: str) -> tuple[Path, Path, str]: | |
| requested_path = safe_path(requested_output_path) | |
| suffix = requested_path.suffix.lower() | |
| if suffix in STEP_SUFFIXES: | |
| output_root = requested_path.parent | |
| output_name = requested_path.name | |
| elif suffix: | |
| raise ValueError("Only STEP output is supported in this version. Use a .step/.stp file path or a directory path.") | |
| else: | |
| output_root = requested_path | |
| output_name = "model.step" | |
| run_dir, run_id = allocate_run_dir(output_root) | |
| return run_dir, run_dir / output_name, run_id | |
| def resolve_lux3d_run(output_path: str | None) -> tuple[Path, Path, str, str | None, str]: | |
| requested_output_path = output_path or DEFAULT_LUX3D_OUTPUT_PATH | |
| requested_path = safe_path(requested_output_path) | |
| if requested_path.suffix: | |
| output_root = requested_path.parent | |
| output_name = requested_path.name | |
| else: | |
| output_root = requested_path | |
| output_name = None | |
| run_dir, run_id = allocate_run_dir(output_root) | |
| return output_root, run_dir, run_id, output_name, requested_output_path | |
| def update_latest_link(output_root: Path, run_dir: Path) -> str | None: | |
| latest = output_root / "latest" | |
| try: | |
| if latest.is_symlink() or latest.is_file(): | |
| latest.unlink() | |
| elif latest.exists(): | |
| return f"Skipped latest link because {workspace_relative(latest)} already exists and is not a symlink." | |
| latest.symlink_to(Path("runs") / run_dir.name, target_is_directory=True) | |
| except OSError as exc: | |
| return f"Failed to update latest link: {exc}" | |
| return None | |
| def write_manifest( | |
| run_dir: Path, | |
| run_id: str, | |
| requested_output_path: str, | |
| output_path: Path, | |
| code: str, | |
| prompt: str | None, | |
| payload: dict, | |
| ) -> Path: | |
| manifest_path = run_dir / "manifest.json" | |
| manifest_path.parent.mkdir(parents=True, exist_ok=True) | |
| manifest = { | |
| "run_id": run_id, | |
| "created_at": datetime.now().astimezone().isoformat(timespec="seconds"), | |
| "generator": "cadquery", | |
| "prompt": prompt, | |
| "requested_output_path": requested_output_path, | |
| "output_path": workspace_relative(output_path), | |
| "preview_path": payload.get("preview_path"), | |
| "format": output_path.suffix.lstrip(".").lower(), | |
| "code": code, | |
| "stdout": payload.get("stdout", ""), | |
| "stderr": payload.get("stderr", ""), | |
| "warning": payload.get("warning"), | |
| } | |
| manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8") | |
| return manifest_path | |
| def write_lux3d_manifest( | |
| run_dir: Path, | |
| run_id: str, | |
| prompt: str | None, | |
| image_path: Path, | |
| requested_output_path: str, | |
| output_path: Path | None, | |
| preview_path: Path | None, | |
| busid: str | int | None, | |
| status: int | None, | |
| result_url: str | None, | |
| poll_count: int, | |
| error: str | None = None, | |
| ) -> Path: | |
| manifest_path = run_dir / "manifest.json" | |
| manifest_path.parent.mkdir(parents=True, exist_ok=True) | |
| manifest = { | |
| "run_id": run_id, | |
| "created_at": datetime.now().astimezone().isoformat(timespec="seconds"), | |
| "generator": "lux3d", | |
| "prompt": prompt, | |
| "image_path": workspace_relative(image_path), | |
| "requested_output_path": requested_output_path, | |
| "output_path": workspace_relative(output_path) if output_path else None, | |
| "preview_path": workspace_relative(preview_path) if preview_path else None, | |
| "busid": busid, | |
| "status": status, | |
| "result_url": result_url, | |
| "poll_count": poll_count, | |
| "error": error, | |
| } | |
| manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8") | |
| return manifest_path | |