"""Pipeline Loader - YAML 加载器""" import logging from pathlib import Path import yaml from agentkit.orchestrator.pipeline_schema import Pipeline, PipelineStage logger = logging.getLogger(__name__) class PipelineLoader: """Pipeline YAML 加载器""" def __init__(self, pipelines_dir: str | Path | None = None): self._pipelines_dir = Path(pipelines_dir) if pipelines_dir else Path("pipelines") def load(self, pipeline_name: str) -> Pipeline: """从 YAML 文件加载 Pipeline""" yaml_path = self._pipelines_dir / f"{pipeline_name}.yaml" if not yaml_path.exists(): yaml_path = self._pipelines_dir / f"{pipeline_name}.yml" if not yaml_path.exists(): raise FileNotFoundError( f"Pipeline '{pipeline_name}' not found in {self._pipelines_dir}" ) content = yaml_path.read_text(encoding="utf-8") return self.load_from_yaml(content, pipeline_name) def load_from_yaml(self, yaml_content: str, pipeline_name: str | None = None) -> Pipeline: """从 YAML 字符串加载 Pipeline""" data = yaml.safe_load(yaml_content) stages = [] for stage_data in data.get("stages", []): stages.append(PipelineStage(**stage_data)) return Pipeline( name=data.get("name", pipeline_name or "unnamed"), version=data.get("version", "1.0.0"), description=data.get("description", ""), stages=stages, variables=data.get("variables", {}), ) @staticmethod def validate_dag(stages: list[PipelineStage]) -> bool: """验证 DAG 无环""" stage_names = {s.name for s in stages} visited = set() path = set() def dfs(name: str) -> bool: if name in path: return False if name in visited: return True path.add(name) stage = next((s for s in stages if s.name == name), None) if stage: for dep in stage.depends_on: if dep not in stage_names: return False if not dfs(dep): return False path.remove(name) visited.add(name) return True return all(dfs(name) for name in stage_names)