Files
SkillCompiler/scripts/compile_pipeline/paths.py
T
2026-09-04 14:58:42 +08:00

61 lines
2.1 KiB
Python

"""项目路径解析与输入范围校验。"""
from __future__ import annotations
from datetime import datetime
from pathlib import Path
import uuid
PROJECT_ROOT = Path(__file__).resolve().parents[2]
TASKS_ROOT = PROJECT_ROOT / "data" / "skills-bench" / "tasks"
RESULTS_ROOT = PROJECT_ROOT / "results" / "compile-pipeline"
def task_directory(value: str) -> Path:
requested = Path(value).expanduser()
if requested.is_absolute():
candidate = requested.resolve()
elif len(requested.parts) == 1:
candidate = (TASKS_ROOT / requested).resolve()
else:
candidate = (PROJECT_ROOT / requested).resolve()
try:
candidate.relative_to(TASKS_ROOT.resolve())
except ValueError as exc:
raise ValueError(f"--task must resolve below {TASKS_ROOT}") from exc
if not (candidate / "task.md").is_file():
raise ValueError(f"not a SkillsBench task directory: {candidate}")
skills = candidate / "environment" / "skills"
if not skills.is_dir():
raise ValueError(f"SkillsBench task has no environment/skills directory: {candidate}")
return candidate
def single_skill_source(task_dir: Path) -> Path:
skills_root = task_dir / "environment" / "skills"
skill_files = sorted(skills_root.rglob("SKILL.md"))
if len(skill_files) != 1:
raise ValueError(
"the complete pipeline currently requires exactly one task Skill because "
f"Fast and Deep accept one Skill package; found {len(skill_files)} under {skills_root}"
)
return skills_root
def requested_run_root(value: str | Path | None) -> Path:
if value is None:
run_id = datetime.now().strftime("%Y%m%d-%H%M%S") + "-" + uuid.uuid4().hex[:6]
return (RESULTS_ROOT / run_id).resolve()
requested = Path(value).expanduser()
candidate = (
requested.resolve()
if requested.is_absolute()
else (PROJECT_ROOT / requested).resolve()
)
try:
candidate.relative_to(RESULTS_ROOT.resolve())
except ValueError as exc:
raise ValueError(f"--run-dir must resolve below {RESULTS_ROOT}") from exc
return candidate