from uuid import uuid4 from sqlalchemy.orm import Session from app.ai.tool_registry import ToolRegistry from app.domain.schemas import EventType, PendingActionCreate, TranscriptChunk from app.infrastructure.database import PendingAction from app.infrastructure.events import EventPublisher from app.memory.context_builder import ContextBuilder from app.memory.memory_manager import MemoryManager from app.planner.llm_planner import HybridPlanner from app.validation.action_validator import ActionValidator from app.validation.policy_engine import PolicyEngine class Orchestrator: """Turns transcript events into pending, validated review actions.""" def __init__( self, context: ContextBuilder, memory: MemoryManager, planner: HybridPlanner, registry: ToolRegistry, publisher: EventPublisher, ) -> None: self.context = context self.memory = memory self.planner = planner self.registry = registry self.publisher = publisher async def ingest(self, session: Session, chunk: TranscriptChunk) -> PendingAction | None: request_id = str(uuid4()) self.context.add_chunk(chunk) self.publisher.publish(EventType.CONVERSATION_EVENT, request_id, chunk.model_dump(mode="json")) memories = self.memory.retrieve(chunk.text) decision = await self.planner.plan(chunk, self.context.snapshot(), memories, self.registry.list()) self.context.add_decision(decision.model_dump()) validation = ActionValidator(self.registry).validate(decision) existing = [row.payload for row in session.query(PendingAction).filter(PendingAction.status == "pending_review").all()] policy = PolicyEngine(existing).evaluate(decision) if not validation.valid or not policy.allowed: self.publisher.publish( EventType.ACTION_REJECTED, request_id, {"decision": decision.model_dump(), "validation": validation.model_dump(), "policy": policy.model_dump()}, ) return None action_in = PendingActionCreate( meeting_id="demo-meeting", tool=decision.tool or "", intent=decision.intent, reasoning=decision.reasoning, confidence=decision.confidence, payload=decision.arguments, extracted_entities=decision.extracted_entities, validation=validation, policy=policy, ) row = action_in.model_dump(mode="json") row["validation"] = validation.model_dump() row["policy"] = policy.model_dump() action = PendingAction(**row, status="pending_review") session.add(action) session.commit() session.refresh(action) self.memory.upsert("pending_action", f"{action.intent}: {action.payload}", {"action_id": action.id}) self.publisher.publish(EventType.ACTION_CREATED, request_id, {"action_id": action.id, "decision": decision.model_dump()}) self.publisher.publish(EventType.MEMORY_UPDATED, request_id, {"action_id": action.id, "type": "pending_action"}) return action