"""Runtime orchestrator joining Search Gateway, registry, audit and events.""" from __future__ import annotations from typing import Any import os from .search_audit_store import SearchAuditStore from .search_event_bridge import SearchEventBridge from .search_gateway import SearchGateway, SearchRequest from .search_provider_registry import SearchProviderRegistry from .trace_tool_credential_governance import ( GovernanceActor, GovernanceScope, GovernanceStore, ToolDescriptor, TraceContext, ) class SearchGatewayOrchestrator: def __init__(self, *, governance_store: GovernanceStore | None = None): self.registry = SearchProviderRegistry() self.audit = SearchAuditStore() self.events = SearchEventBridge() self.governance = governance_store or GovernanceStore( os.environ.get("AIOS_SEARCH_GOVERNANCE_DB", "runtime/search-governance.sqlite3") ) registrar = GovernanceActor( "search-runtime-bootstrap", GovernanceScope("system"), ("system.admin",) ) for provider in self.registry.ordered(): self.governance.register_tool( ToolDescriptor( f"search.{provider.name}", "tool", GovernanceScope("global"), ("tool.search",) ), registrar, ) self.gateway = SearchGateway(self.registry.ordered(), governance_store=self.governance) def execute(self, payload: dict[str, Any], *, actor: GovernanceActor | dict[str, Any] | None = None, trace: TraceContext | None = None) -> dict[str, Any]: if actor is None or trace is None: from .trace_tool_credential_governance import GovernanceError raise GovernanceError("TOOL_MCP_AUTHZ_DENY") self.governance.record_trace(trace, actor) request = SearchRequest(**payload) self.events.search_started(request.to_dict()) response = self.gateway.search(request, actor=actor, trace=trace) result = response.to_dict() for attempt in result.get("attempts", []): self.events.provider_attempted(result["request_id"], attempt) if len(result.get("attempts", [])) > 1: self.events.fallback_triggered(result["request_id"], "multiple providers attempted") self.audit.append(result) self.events.search_completed(result) return result def status(self) -> dict[str, Any]: return { "registry": self.registry.status(), "audit": "enabled", "events": "enabled", "governance": "required", } __all__ = ["SearchGatewayOrchestrator"]