""" Defines the core Pydantic data models (contracts) for the Emma Master Hub. These models ensure data consistency and validation across services. """ import uuid from datetime import datetime, timezone from typing import List, Dict, Any, Optional, Literal from pydantic import BaseModel, Field # --- Core Data Types --- SchemaVersion = Literal["1.0.0"] CallerType = Literal["human", "agent", "system"] Classification = Literal["public", "internal", "confidential", "secret"] MemoryType = Literal["fact", "pattern", "procedure", "preference", "chat_summary", "ticket_ref"] ToolRiskLevel = Literal["read_only", "propose_only", "requires_approval", "requires_high_approval", "forbidden"] ApprovalStatus = Literal["PENDING", "APPROVED", 'REJECTED', "EXPIRED"] ExecutionStatus = Literal["PENDING", "EXECUTING", "SUCCESS", "FAILED"] # --- Context and Identity Contracts --- class CallerContext(BaseModel): """Server-derived context about the authenticated caller.""" caller_id: str # e.g., "agent:perplexity" or "user:chris.c" caller_type: CallerType profile: str # e.g., "operator", "viewer", "admin" owner_id: str # The user or service account owning the session workspace_id: str allowed_tool_policy: Dict[str, ToolRiskLevel] = Field(default_factory=dict) schema_version: SchemaVersion = "1.0.0" # --- Core Object Contracts --- class EmmaConversation(BaseModel): """Metadata for a single conversation session.""" conversation_id: str = Field(default_factory=lambda: f"convo-{uuid.uuid4().hex}") owner_id: str workspace_id: str task_id: Optional[str] = None created_by: str created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) last_updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) classification: Classification = "internal" # Raw messages are stored separately, this holds a reference or summary message_references: List[str] = Field(default_factory=list) schema_version: SchemaVersion = "1.0.0" class MemoryRecord(BaseModel): """A single, recallable piece of information for Emma.""" memory_id: str = Field(default_factory=lambda: f"mem-{uuid.uuid4().hex}") memory_type: MemoryType owner_id: str workspace_id: str source_conversation_id: str content_text: str embedding_vector_ref: Optional[str] = None created_by: str created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) last_accessed_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) access_count: int = 1 reward_score: float = 0.0 classification: Classification = "internal" schema_version: SchemaVersion = "1.0.0" class ProposedToolAction(BaseModel): """A tool action proposed by Emma, awaiting approval.""" action_id: str = Field(default_factory=lambda: f"act-{uuid.uuid4().hex}") correlation_id: str tool_name: str parameters: Dict[str, Any] human_readable_summary: str risk_class: ToolRiskLevel target_resource: Optional[str] = None source_revision_sha: Optional[str] = None requires_approval: bool schema_version: SchemaVersion = "1.0.0" class ApprovalRecord(BaseModel): """A record of an approval process for a ProposedToolAction.""" approval_id: str = Field(default_factory=lambda: f"appr-{uuid.uuid4().hex}") action: ProposedToolAction status: ApprovalStatus = "PENDING" execution_status: ExecutionStatus = "PENDING" created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) expires_at: datetime requested_by_caller_id: str approved_by_user_id: Optional[str] = None actioned_at: Optional[datetime] = None execution_log: List[str] = Field(default_factory=list) idempotency_key: str = Field(default_factory=lambda: uuid.uuid4().hex) workspace_id: str schema_version: SchemaVersion = "1.0.0" class AuditEvent(BaseModel): """A discrete, immutable event for audit purposes.""" event_id: str = Field(default_factory=lambda: f"aud-{uuid.uuid4().hex}") timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) event_type: str # e.g., "TOOL_PROPOSED", "APPROVAL_GRANTED", "TOOL_EXECUTED" caller_id: str user_id: Optional[str] = None details: Dict[str, Any] workspace_id: str schema_version: SchemaVersion = "1.0.0" # --- API Contracts for call_emma --- class CallEmmaRequest(BaseModel): prompt: str conversation_id: Optional[str] = None task_id: Optional[str] = None requested_memory_scope: List[MemoryType] = Field(default_factory=list) client_context: Dict[str, Any] = Field(default_factory=dict) class CallEmmaResponse(BaseModel): reply_text: str model: str conversation_id: str correlation_id: str memory_references: List[str] = Field(default_factory=list) proposed_actions: List[ProposedToolAction] = Field(default_factory=list) approval_state: Optional[Dict[str, Any]] = None schema_version: SchemaVersion = "1.0.0"