""" Pydantic models for mental models. """ from datetime import datetime, timezone from enum import Enum from pydantic import BaseModel, Field class MentalModelSubtype(str, Enum): """Subtype of mental model - how it was created.""" STRUCTURAL = "structural" # Derived from mission, created upfront EMERGENT = "emergent" # Discovered from data patterns LEARNED = "learned" # Formed through reflection PINNED = "pinned" # User-defined topic, observations LLM-generated DIRECTIVE = "directive" # User-defined hard rules, observations user-provided class MentalModel(BaseModel): """ A mental model representing synthesized understanding. Mental models are the agent's consolidated knowledge. Unlike raw facts, mental models provide: - A one-liner description for quick scanning/retrieval - A full summary for deep understanding - Links to related mental models """ id: str = Field(description="Unique identifier within the bank") bank_id: str = Field(description="Bank this mental model belongs to") subtype: MentalModelSubtype = Field(description="How this model was created") name: str = Field(description="Human-readable name") description: str = Field(description="One-liner for quick scanning and retrieval matching") summary: str | None = Field(default=None, description="Full synthesized understanding") # References entity_id: str | None = Field(default=None, description="Reference to entities table when type=entity") source_facts: list[str] = Field(default_factory=list, description="Fact IDs used to generate summary") links: list[str] = Field(default_factory=list, description="Related mental model IDs") # Tags for scoped visibility (similar to document tags) tags: list[str] = Field(default_factory=list, description="Tags for scoped visibility filtering") # Timestamps last_updated: datetime | None = Field(default=None, description="When summary was last regenerated") created_at: datetime = Field( default_factory=lambda: datetime.now(timezone.utc), description="When this model was created" ) class StructuralModelTemplate(BaseModel): """ A template for a structural mental model. Generated by LLM based on the bank's mission. Represents what any agent with this role would need to track. """ id: str = Field(default="", description="Existing model ID to keep, or empty for new models") name: str = Field(description="Human-readable name") description: str = Field(description="What this model should track") initial_probes: list[str] = Field(default_factory=list, description="Initial search queries to populate this model") class StructuralModelDerivationResponse(BaseModel): """Response from LLM for structural model derivation.""" templates: list[StructuralModelTemplate] = Field(description="Structural model templates derived from the mission") class EmergentCandidate(BaseModel): """ A candidate for promotion to emergent mental model. Detected through pattern analysis of facts. """ name: str = Field(description="Name of the detected pattern/entity") detection_method: str = Field(description="How this candidate was detected") mention_count: int = Field(default=0, description="How many times referenced") entity_id: str | None = Field(default=None, description="Entity ID if detected as entity") relevance_score: float = Field(default=0.0, description="Score from mission filter (0-1)") class ResearchResult(BaseModel): """ Result from the research endpoint. Contains the answer along with the mental models and facts used. """ answer: str = Field(description="The synthesized answer") mental_models_used: list[str] = Field(default_factory=list, description="IDs of mental models that contributed") facts_used: list[str] = Field(default_factory=list, description="Fact IDs that contributed") question_type: str | None = Field(default=None, description="Detected question type (WHO, WHAT, HOW, etc.)")