Initial release — OpenMontage: the first open-source agentic video production system
11 production pipelines, 47 tools, 124 agent skills. Supports cloud APIs (fal.ai, OpenAI, ElevenLabs, Suno, HeyGen, Runway) and free local providers (diffusers, Piper TTS, WAN 2.1, Hunyuan, CogVideo). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"""Pipeline manifest loader.
|
||||
|
||||
Loads and validates pipeline YAML manifests from pipeline_defs/.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
import yaml
|
||||
import jsonschema
|
||||
|
||||
PIPELINE_DEFS_DIR = Path(__file__).resolve().parent.parent / "pipeline_defs"
|
||||
SCHEMA_PATH = (
|
||||
Path(__file__).resolve().parent.parent
|
||||
/ "schemas"
|
||||
/ "pipelines"
|
||||
/ "pipeline_manifest.schema.json"
|
||||
)
|
||||
|
||||
|
||||
def _load_manifest_schema() -> dict:
|
||||
with open(SCHEMA_PATH) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def load_pipeline(name: str, defs_dir: Optional[Path] = None) -> dict[str, Any]:
|
||||
"""Load and validate a pipeline manifest by name.
|
||||
|
||||
Args:
|
||||
name: Pipeline name (without .yaml extension).
|
||||
defs_dir: Override directory for pipeline definitions.
|
||||
|
||||
Returns:
|
||||
Validated pipeline manifest dict.
|
||||
"""
|
||||
defs_dir = defs_dir or PIPELINE_DEFS_DIR
|
||||
path = defs_dir / f"{name}.yaml"
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Pipeline manifest not found: {path}")
|
||||
|
||||
with open(path) as f:
|
||||
manifest = yaml.safe_load(f)
|
||||
|
||||
schema = _load_manifest_schema()
|
||||
jsonschema.validate(instance=manifest, schema=schema)
|
||||
|
||||
return manifest
|
||||
|
||||
|
||||
def list_pipelines(defs_dir: Optional[Path] = None) -> list[str]:
|
||||
"""List all available pipeline manifest names."""
|
||||
defs_dir = defs_dir or PIPELINE_DEFS_DIR
|
||||
return [p.stem for p in defs_dir.glob("*.yaml")]
|
||||
|
||||
|
||||
def get_stage_order(manifest: dict) -> list[str]:
|
||||
"""Extract the ordered list of stage names from a manifest."""
|
||||
return [stage["name"] for stage in manifest["stages"]]
|
||||
|
||||
|
||||
def get_required_tools(manifest: dict) -> set[str]:
|
||||
"""Collect all preferred + fallback + available tools across all stages."""
|
||||
tools: set[str] = set()
|
||||
for stage in manifest["stages"]:
|
||||
tools.update(stage.get("preferred_tools", []))
|
||||
tools.update(stage.get("fallback_tools", []))
|
||||
tools.update(stage.get("tools_available", []))
|
||||
return tools
|
||||
|
||||
|
||||
def get_stage_skill(manifest: dict, stage_name: str) -> Optional[str]:
|
||||
"""Get the skill path for an instruction-driven stage."""
|
||||
for stage in manifest["stages"]:
|
||||
if stage["name"] == stage_name:
|
||||
return stage.get("skill")
|
||||
return None
|
||||
|
||||
|
||||
def get_stage_review_focus(manifest: dict, stage_name: str) -> list[str]:
|
||||
"""Get the review focus items for a stage."""
|
||||
for stage in manifest["stages"]:
|
||||
if stage["name"] == stage_name:
|
||||
return stage.get("review_focus", [])
|
||||
return []
|
||||
Reference in New Issue
Block a user