44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
"""Pipeline orchestrator — builds the graph + middleware chain and executes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from app.graph.builder import ReportGraph
|
|
from app.graph.state import ReportState
|
|
from app.middleware.chain import MiddlewareChain
|
|
from app.middleware.client_context import ClientContextMiddleware
|
|
from app.middleware.token_budget import TokenBudgetMiddleware
|
|
from app.middleware.compliance import ComplianceMiddleware
|
|
from app.middleware.memory import MemoryMiddleware
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def build_middleware() -> MiddlewareChain:
|
|
"""Assemble the middleware chain in execution order."""
|
|
chain = MiddlewareChain()
|
|
chain.add(ClientContextMiddleware()) # 1. load client profile
|
|
chain.add(MemoryMiddleware()) # 2. inject memory facts
|
|
chain.add(TokenBudgetMiddleware()) # 3. set token budget
|
|
chain.add(ComplianceMiddleware()) # 4. scan output for PII (after only)
|
|
return chain
|
|
|
|
|
|
class PipelineOrchestrator:
|
|
"""Top-level entry: creates graph + middleware, runs end-to-end."""
|
|
|
|
def __init__(self):
|
|
self.middleware = build_middleware()
|
|
self.graph = ReportGraph(middleware=self.middleware)
|
|
|
|
async def run(self, state: ReportState) -> ReportState:
|
|
logger.info(f"[orchestrator] starting report {state.id}")
|
|
state = await self.graph.run(state)
|
|
logger.info(
|
|
f"[orchestrator] finished report {state.id} — "
|
|
f"status={'OK' if not state.error else 'FAILED'}, "
|
|
f"files={len(state.generated_files)}"
|
|
)
|
|
return state
|