from __future__ import annotations from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field from .decision_schema import ModeCard class SemanticContextTurn(BaseModel): model_config = ConfigDict(extra="ignore") role: str text: str class SemanticContextThread(BaseModel): model_config = ConfigDict(extra="ignore") thread_key: Optional[str] = None conversation_scope_key: Optional[str] = None thread_summary: Optional[str] = None recent_turns: list[SemanticContextTurn] = Field(default_factory=list) open_questions: list[str] = Field(default_factory=list) class SemanticContextTopic(BaseModel): model_config = ConfigDict(extra="ignore") topic_workspace_id: int topic_key: str source_system: str channel_ref: Optional[str] = None conversation_scope_key: Optional[str] = None thread_key: Optional[str] = None mode: str status: str plan_status: Optional[str] = None facts: Optional[Any] = None goals: Optional[Any] = None constraints: Optional[Any] = None metadata: Optional[Any] = None class SemanticContextDraftSnapshot(BaseModel): model_config = ConfigDict(extra="ignore") draft_workspace_id: int state: str draft_version: int requirement_card: Optional[Any] = None draft_payload: Optional[Any] = None required_confirmations: list[str] = Field(default_factory=list) class SemanticContextIngress(BaseModel): model_config = ConfigDict(extra="ignore") candidate_kind: Optional[str] = None source_system: Optional[str] = None reply_anchor_present: bool = False active_context_kind: Optional[str] = None allowed_followup_actions: list[str] = Field(default_factory=list) allowed_context_scopes: list[str] = Field(default_factory=list) thread_context: Optional[Any] = None class SemanticContextPacket(BaseModel): model_config = ConfigDict(extra="ignore") packet_version: str = "v1" tenant_id: int operator_user_id: int topic_workspace_id: int latest_user_message: str topic: SemanticContextTopic draft: SemanticContextDraftSnapshot | None = None thread: SemanticContextThread mode_card: ModeCard ingress: SemanticContextIngress | None = None