agentic-os/integrations/pipeline.py

87 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""
Abstraction Forge — local-first integration hub for Agentic OS.
Pipelines are stored as JSON state files so they survive restarts and do
not depend on any external service being reachable at load time.
"""
from __future__ import annotations
import copy
import json
import threading
import time
from pathlib import Path
from typing import Any, Dict, List, Optional
INTEGRATIONS_DIR = Path(__file__).parent
PIPELINES_FILE = INTEGRATIONS_DIR / "pipelines.json"
_local = threading.local()
def _timestamp() -> str:
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
def _load_pipelines() -> Dict[str, Any]:
if not PIPELINES_FILE.exists():
return {"pipelines": {}}
try:
return json.loads(PIPELINES_FILE.read_text(encoding="utf-8"))
except Exception:
return {"pipelines": {}}
def _save_pipelines(state: Dict[str, Any]) -> None:
PIPELINES_FILE.write_text(json.dumps(state, indent=2, default=str), encoding="utf-8")
class Pipeline:
def __init__(self, name: str, payload: Dict[str, Any]):
self.name = name
self.payload = copy.deepcopy(payload)
self.created_at = _timestamp()
self.updated_at = self.created_at
self.status = "pending"
self.results: Dict[str, Any] = {}
self.error: Optional[str] = None
class PipelineManager:
def __init__(self) -> None:
PIPELINES_FILE.parent.mkdir(parents=True, exist_ok=True)
_local.state = _load_pipelines()
def save(self) -> None:
_save_pipelines(_local.state)
def create_pipeline(self, name: str, payload: Dict[str, Any]) -> Pipeline:
p = Pipeline(name, payload)
_local.state.setdefault("pipelines", {})[name] = {
"name": name,
"payload": p.payload,
"created_at": p.created_at,
"updated_at": p.updated_at,
"status": p.status,
"results": p.results,
"error": p.error,
}
self.save()
return p
def list_pipelines(self) -> List[Dict[str, Any]]:
return list(_local.state.get("pipelines", {}).values())
def get_pipeline(self, name: str) -> Optional[Dict[str, Any]]:
return _local.state.get("pipelines", {}).get(name)
def record_result(self, name: str, adapter_name: str, result: Any) -> None:
p = _local.state.setdefault("pipelines", {}).get(name)
if not p:
return
p["results"][adapter_name] = result.to_dict()
p["updated_at"] = _timestamp()
self.save()