# ----------------------------------------------------------------------------
#
#  Welcome to Baml! To use this generated code, please run the following:
#
#  $ pip install baml
#
# ----------------------------------------------------------------------------

# This file was generated by BAML: please do not edit it. Instead, edit the
# BAML files and re-generate this code using: baml-cli generate
# baml-cli is available with the baml package.

import typing
import typing_extensions
from enum import Enum


from pydantic import BaseModel, ConfigDict, Field


import baml_py

CheckT = typing_extensions.TypeVar('CheckT')
CheckName = typing_extensions.TypeVar('CheckName', bound=str)

class Check(BaseModel):
    name: str
    expression: str
    status: str
class Checked(BaseModel, typing.Generic[CheckT, CheckName]):
    value: CheckT
    checks: typing.Dict[CheckName, Check]

def get_checks(checks: typing.Dict[CheckName, Check]) -> typing.List[Check]:
    return list(checks.values())

def all_succeeded(checks: typing.Dict[CheckName, Check]) -> bool:
    return all(check.status == "succeeded" for check in get_checks(checks))
# #########################################################################
# Generated enums (46)
# #########################################################################

class AICommandType(str, Enum):
    TONE_ADJUSTMENT = "TONE_ADJUSTMENT"
    CONTENT_ADDITION = "CONTENT_ADDITION"
    CONTENT_REMOVAL = "CONTENT_REMOVAL"
    SECTION_MODIFICATION = "SECTION_MODIFICATION"
    VOICE_CORRECTION = "VOICE_CORRECTION"
    SPECIFIC_EDIT = "SPECIFIC_EDIT"

class ActionSpecificity(str, Enum):
    # Level of specificity for action items
    
    WHEN = "WHEN"
    WHAT = "WHAT"
    HOW = "HOW"
    WHO = "WHO"

class ActionVariant(str, Enum):
    # Action button variants
    
    PRIMARY = "PRIMARY"
    SECONDARY = "SECONDARY"
    GHOST = "GHOST"
    LINK = "LINK"
    DANGER = "DANGER"

class BadgeVariant(str, Enum):
    # Badge style variants
    
    DEFAULT = "DEFAULT"
    PRIMARY = "PRIMARY"
    SECONDARY = "SECONDARY"
    SUCCESS = "SUCCESS"
    WARNING = "WARNING"
    DANGER = "DANGER"
    INFO = "INFO"

class BetweenSessionEventType(str, Enum):
    # Type of between-session event
    
    CHECK_IN = "CHECK_IN"
    JOURNAL = "JOURNAL"
    COMPLETION = "COMPLETION"
    CONVERSATION = "CONVERSATION"

class CoachFeedback(str, Enum):
    OFF_VOICE = "OFF_VOICE"
    PERFECT = "PERFECT"

class CommandItemType(str, Enum):
    CLIENT_ACTION = "CLIENT_ACTION"
    SESSION_PREP = "SESSION_PREP"
    FOLLOW_UP = "FOLLOW_UP"
    PATTERN_ALERT = "PATTERN_ALERT"

class CommitmentSource(str, Enum):
    # Source of a commitment
    
    SESSION = "SESSION"
    BETWEEN_SESSION = "BETWEEN_SESSION"

class CommitmentStatus(str, Enum):
    # Status of a commitment
    
    COMPLETED = "COMPLETED"
    PENDING = "PENDING"
    PARTIAL = "PARTIAL"
    UNKNOWN = "UNKNOWN"

class DashboardView(str, Enum):
    # Dashboard view options
    
    OVERVIEW = "OVERVIEW"
    SESSIONS = "SESSIONS"
    CLIENTS = "CLIENTS"
    ACTIONS = "ACTIONS"

class DisclosureLevel(str, Enum):
    # Level of detail to disclose in UI
    
    SUMMARY = "SUMMARY"
    HEADINGS = "HEADINGS"
    KEY_POINTS = "KEY_POINTS"
    FULL_DETAIL = "FULL_DETAIL"
    EXACT_QUOTE = "EXACT_QUOTE"
    TIMESTAMP = "TIMESTAMP"

class EditType(str, Enum):
    MINOR_TWEAK = "MINOR_TWEAK"
    SIGNIFICANT_CHANGE = "SIGNIFICANT_CHANGE"
    COMPLETE_REWRITE = "COMPLETE_REWRITE"

class EventType(str, Enum):
    # All WebSocket event types (stable enum, not free-form strings)
    
    CONTEXT_CHANGED = "CONTEXT_CHANGED"
    STATE_UPDATED = "STATE_UPDATED"
    MESSAGE_RECEIVED = "MESSAGE_RECEIVED"
    MESSAGE_SENT = "MESSAGE_SENT"
    CONVERSATION_STARTED = "CONVERSATION_STARTED"
    CONVERSATION_ENDED = "CONVERSATION_ENDED"
    ACTION_PENDING = "ACTION_PENDING"
    ACTION_EXECUTING = "ACTION_EXECUTING"
    ACTION_COMPLETED = "ACTION_COMPLETED"
    ACTION_FAILED = "ACTION_FAILED"
    ACTION_CANCELLED = "ACTION_CANCELLED"
    FRONTEND_COMMAND = "FRONTEND_COMMAND"
    FRONTEND_COMMAND_RESULT = "FRONTEND_COMMAND_RESULT"
    SCHEDULED_MESSAGE_CREATED = "SCHEDULED_MESSAGE_CREATED"
    SCHEDULED_MESSAGE_UPDATED = "SCHEDULED_MESSAGE_UPDATED"
    SCHEDULED_MESSAGE_APPROVED = "SCHEDULED_MESSAGE_APPROVED"
    SCHEDULED_MESSAGE_SENT = "SCHEDULED_MESSAGE_SENT"
    SCHEDULED_MESSAGE_CANCELLED = "SCHEDULED_MESSAGE_CANCELLED"
    SCHEDULED_MESSAGE_FAILED = "SCHEDULED_MESSAGE_FAILED"
    SCHEDULED_MESSAGE_REVIEW_DUE = "SCHEDULED_MESSAGE_REVIEW_DUE"
    COMMAND_CENTER_UPDATED = "COMMAND_CENTER_UPDATED"
    PRIORITY_ITEM_ADDED = "PRIORITY_ITEM_ADDED"
    PRIORITY_ITEM_COMPLETED = "PRIORITY_ITEM_COMPLETED"
    VOICE_CORRECTION_SUBMITTED = "VOICE_CORRECTION_SUBMITTED"
    VOICE_PROFILE_UPDATED = "VOICE_PROFILE_UPDATED"
    OBSERVATION_DETECTED = "OBSERVATION_DETECTED"
    CURRENT_READ_UPDATED = "CURRENT_READ_UPDATED"
    RESOURCE_CREATED = "RESOURCE_CREATED"
    RESOURCE_UPDATED = "RESOURCE_UPDATED"
    RESOURCE_DELETED = "RESOURCE_DELETED"
    SESSION_STARTED = "SESSION_STARTED"
    SESSION_UPDATED = "SESSION_UPDATED"
    SESSION_ENDED = "SESSION_ENDED"
    CONNECTION_ESTABLISHED = "CONNECTION_ESTABLISHED"
    CONNECTION_ERROR = "CONNECTION_ERROR"
    HEARTBEAT = "HEARTBEAT"
    ERROR = "ERROR"
    ONBOARDING_STEP_COMPLETED = "ONBOARDING_STEP_COMPLETED"
    ONBOARDING_PHASE_STARTED = "ONBOARDING_PHASE_STARTED"
    VOICE_SAMPLES_SUBMITTED = "VOICE_SAMPLES_SUBMITTED"
    T15_PREP_GENERATED = "T15_PREP_GENERATED"
    T15_PREP_UPDATED = "T15_PREP_UPDATED"
    T15_PREP_VIEWED = "T15_PREP_VIEWED"
    PREP_NOTIFICATION = "PREP_NOTIFICATION"
    PREP_READY = "PREP_READY"
    PREP_VIEWED = "PREP_VIEWED"
    SESSION_NOTES_GENERATED = "SESSION_NOTES_GENERATED"
    SESSION_NOTES_UPDATED = "SESSION_NOTES_UPDATED"
    SESSION_NOTES_FINALIZED = "SESSION_NOTES_FINALIZED"
    SESSION_NOTES_SHARED = "SESSION_NOTES_SHARED"

class FrontendActionStatus(str, Enum):
    # Frontend action status lifecycle
    
    PENDING = "PENDING"
    EXECUTING = "EXECUTING"
    COMPLETED = "COMPLETED"
    FAILED = "FAILED"
    EXPIRED = "EXPIRED"

class FrontendToolName(str, Enum):
    # Frontend tool names - execute on frontend, not backend
    
    NAVIGATE_TO = "NAVIGATE_TO"
    CLICK_ELEMENT = "CLICK_ELEMENT"
    EXPAND_SECTION = "EXPAND_SECTION"
    SET_FORM_FIELD = "SET_FORM_FIELD"
    SUBMIT_FORM = "SUBMIT_FORM"
    OPEN_MODAL = "OPEN_MODAL"
    CLOSE_MODAL = "CLOSE_MODAL"

class GoalCategory(str, Enum):
    # Category of goal
    
    CAREER = "CAREER"
    LEADERSHIP = "LEADERSHIP"
    RELATIONSHIPS = "RELATIONSHIPS"
    PERSONAL = "PERSONAL"
    HEALTH = "HEALTH"
    OTHER = "OTHER"

class GoalStatus(str, Enum):
    # Status of goal
    
    ACTIVE = "ACTIVE"
    COMPLETED = "COMPLETED"
    PAUSED = "PAUSED"
    ARCHIVED = "ARCHIVED"

class InquiryCategory(str, Enum):
    # Category of inquiry question
    
    GROWTH = "GROWTH"
    REFLECTION = "REFLECTION"
    CHALLENGE = "CHALLENGE"
    EXPLORATION = "EXPLORATION"

class IntegrationStatus(str, Enum):
    # Status of an integration
    
    NOT_CONNECTED = "NOT_CONNECTED"
    PENDING = "PENDING"
    CONNECTED = "CONNECTED"
    EXPIRED = "EXPIRED"
    ERROR = "ERROR"

class IntegrationType(str, Enum):
    # Types of integrations supported
    
    GOOGLE_CALENDAR = "GOOGLE_CALENDAR"
    OUTLOOK_CALENDAR = "OUTLOOK_CALENDAR"
    ZOOM = "ZOOM"
    GOOGLE_MEET = "GOOGLE_MEET"
    TEAMS = "TEAMS"
    SALESFORCE = "SALESFORCE"
    HUBSPOT = "HUBSPOT"
    PRACTICE = "PRACTICE"

class LifeContextArea(str, Enum):
    # Area of life context
    
    WORK = "WORK"
    RELATIONSHIPS = "RELATIONSHIPS"
    HEALTH = "HEALTH"
    PERSONAL = "PERSONAL"
    OTHER = "OTHER"

class MessageChannel(str, Enum):
    # Channel choices for message delivery
    
    EMAIL = "EMAIL"
    SMS = "SMS"
    WHATSAPP = "WHATSAPP"

class MessageRole(str, Enum):
    USER = "USER"
    ASSISTANT = "ASSISTANT"
    SYSTEM = "SYSTEM"

class MessageStatus(str, Enum):
    # Status choices for scheduled messages
    
    DRAFT = "DRAFT"
    APPROVED = "APPROVED"
    PENDING_REVIEW = "PENDING_REVIEW"
    SENT = "SENT"
    CANCELLED = "CANCELLED"
    FAILED = "FAILED"

class ObservationType(str, Enum):
    PATTERN = "PATTERN"
    CHANGE = "CHANGE"
    BREAKTHROUGH = "BREAKTHROUGH"

class OnboardingAction(str, Enum):
    # Onboarding action type
    
    START = "START"
    COMPLETE = "COMPLETE"
    SKIP = "SKIP"
    SAVE_PROGRESS = "SAVE_PROGRESS"

class OnboardingPhase(str, Enum):
    # The 8 phases of coach onboarding
    
    ACCOUNT_CREATED = "ACCOUNT_CREATED"
    PROFILE_SETUP = "PROFILE_SETUP"
    VOICE_SAMPLES = "VOICE_SAMPLES"
    COACHING_STYLE = "COACHING_STYLE"
    INTEGRATIONS = "INTEGRATIONS"
    CLIENT_IMPORT = "CLIENT_IMPORT"
    TUTORIAL = "TUTORIAL"
    COMPLETED = "COMPLETED"

class OpenerCategory(str, Enum):
    # Category of opener question
    
    COMMITMENT = "COMMITMENT"
    PATTERN = "PATTERN"
    CONTEXT = "CONTEXT"
    EXPLORATION = "EXPLORATION"

class PatternTrend(str, Enum):
    # Trend direction for patterns
    
    INCREASING = "INCREASING"
    STABLE = "STABLE"
    DECREASING = "DECREASING"

class PhaseStatus(str, Enum):
    # Status of an onboarding phase
    
    NOT_STARTED = "NOT_STARTED"
    IN_PROGRESS = "IN_PROGRESS"
    COMPLETED = "COMPLETED"
    SKIPPED = "SKIPPED"

class PrepSectionId(str, Enum):
    # Identifiers for prep sections
    
    NORTH_STAR = "NORTH_STAR"
    LAST_SESSION = "LAST_SESSION"
    COMMITMENTS = "COMMITMENTS"
    LIFE_CONTEXT = "LIFE_CONTEXT"
    PATTERNS = "PATTERNS"
    OPENERS = "OPENERS"
    PRIVATE_NOTES = "PRIVATE_NOTES"
    BETWEEN_SESSION = "BETWEEN_SESSION"
    COACHEE_INPUT = "COACHEE_INPUT"

class PrepStatus(str, Enum):
    # Status of prep document
    
    DRAFT = "DRAFT"
    READY = "READY"
    VIEWED = "VIEWED"

class PrepStatusValue(str, Enum):
    # Prep status values
    
    NOT_STARTED = "NOT_STARTED"
    GENERATING = "GENERATING"
    READY = "READY"
    VIEWED = "VIEWED"

class Priority(str, Enum):
    FOCUS_NOW = "FOCUS_NOW"
    SOON = "SOON"
    LATER = "LATER"

class ResourceLinkType(str, Enum):
    # Type of resource link
    
    DOCUMENT = "DOCUMENT"
    LINK = "LINK"
    FRAMEWORK = "FRAMEWORK"

class ResourceType(str, Enum):
    DOCUMENT = "DOCUMENT"
    LINK = "LINK"
    FRAMEWORK = "FRAMEWORK"
    TEMPLATE = "TEMPLATE"

class Sentiment(str, Enum):
    # Sentiment indicator
    
    POSITIVE = "POSITIVE"
    NEUTRAL = "NEUTRAL"
    NEGATIVE = "NEGATIVE"

class SessionNoteSectionId(str, Enum):
    # The 6 sections of session notes
    
    RECAP = "RECAP"
    OBSERVATIONS = "OBSERVATIONS"
    INQUIRIES = "INQUIRIES"
    INVITATIONS = "INVITATIONS"
    RESOURCES = "RESOURCES"
    NEXT = "NEXT"

class SessionNotesStatus(str, Enum):
    # Status of session notes
    
    DRAFT = "DRAFT"
    SENT = "SENT"
    ARCHIVED = "ARCHIVED"

class StateSource(str, Enum):
    # Source of state update
    
    FRONTEND = "FRONTEND"
    EXTENSION = "EXTENSION"

class ToolName(str, Enum):
    # Backend tool names for action execution
    
    DRAFT_T15 = "DRAFT_T15"
    DRAFT_SESSION_NOTES = "DRAFT_SESSION_NOTES"
    SEND_FOLLOW_UP_EMAIL = "SEND_FOLLOW_UP_EMAIL"
    UPDATE_SESSION_STATUS = "UPDATE_SESSION_STATUS"
    SUMMARIZE_TRANSCRIPT = "SUMMARIZE_TRANSCRIPT"
    ADD_CLIENT_NOTE = "ADD_CLIENT_NOTE"
    SCHEDULE_SESSION = "SCHEDULE_SESSION"
    LOOKUP_CLIENT = "LOOKUP_CLIENT"

class TransparencyIndicator(str, Enum):
    COACH_DIRECT = "COACH_DIRECT"
    AI_DRAFTED_APPROVED = "AI_DRAFTED_APPROVED"
    AI_AUTONOMOUS = "AI_AUTONOMOUS"

class VoiceContentType(str, Enum):
    SESSION_NOTES = "SESSION_NOTES"
    EMAIL = "EMAIL"
    MESSAGE = "MESSAGE"

class VoiceSampleStatus(str, Enum):
    # Processing status for voice sample
    
    PENDING = "PENDING"
    PROCESSING = "PROCESSING"
    PROCESSED = "PROCESSED"
    FAILED = "FAILED"

class VoiceSampleType(str, Enum):
    # Type of voice sample for AI learning
    
    EMAIL = "EMAIL"
    SESSION_NOTES = "SESSION_NOTES"
    FOLLOW_UP = "FOLLOW_UP"
    FEEDBACK = "FEEDBACK"
    GENERAL = "GENERAL"

class VoiceTrainingStatus(str, Enum):
    # Status of voice profile training
    
    NEEDS_SAMPLES = "NEEDS_SAMPLES"
    READY = "READY"
    TRAINING = "TRAINING"
    TRAINED = "TRAINED"
    RETRAINING = "RETRAINING"

# #########################################################################
# Generated classes (168)
# #########################################################################

class AICommandHistoryItem(BaseModel):
    # A single AI command history entry
    id: str
    command: str
    commandType: typing.Optional[AICommandType] = None
    originalContent: str
    editedContent: str
    section: typing.Optional[str] = None
    applied: bool
    explanation: typing.Optional[str] = None
    createdAt: str

class AICommandRequest(BaseModel):
    # Request to execute an AI command
    contentId: str
    section: typing.Optional[str] = None
    command: str
    currentContent: str
    commandType: typing.Optional[AICommandType] = None

class AICommandResult(BaseModel):
    # Response from executing an AI command
    editedContent: str
    explanation: typing.Optional[str] = None
    appliedChange: typing.Optional[str] = None
    commandId: typing.Optional[str] = None

class AccordionGroup(BaseModel):
    # Accordion group configuration
    id: str
    sections: typing.List["AccordionSection"]
    allowMultipleExpanded: bool
    defaultExpandedIds: typing.List[str]

class AccordionSection(BaseModel):
    # Accordion section for expandable UI components
    id: str
    title: str
    summary: typing.Optional[str] = None
    level: int
    expanded: bool
    children: typing.Optional[typing.List["AccordionSection"]] = None

class ActionError(BaseModel):
    code: str
    message: str
    retryable: bool
    details: typing.Dict[str, str]

class ActionEventPayload(BaseModel):
    # Payload for ACTION_* events
    actionId: str
    tool: str
    status: str
    parameters: typing.Dict[str, str]
    result: typing.Optional[typing.Dict[str, str]] = None
    error: typing.Optional[typing.Dict[str, str]] = None

class ActionItem(BaseModel):
    # An action item or invitation given to client
    id: str
    action: str
    specificity: ActionSpecificity
    details: str
    dueDate: typing.Optional[str] = None
    completed: typing.Optional[bool] = None

class ActionOutput(BaseModel):
    type: str
    text: typing.Optional[str] = None
    structured: typing.Dict[str, str]
    preview: typing.Optional[str] = None

class ActionRequest(BaseModel):
    conversationId: str
    tool: ToolName
    parameters: typing.Dict[str, str]
    context: "PageContext"
    confirmed: bool

class ActionResponse(BaseModel):
    success: bool
    actionId: typing.Optional[str] = None
    tool: ToolName
    output: typing.Optional["ActionOutput"] = None
    error: typing.Optional["ActionError"] = None
    appliedChanges: typing.List[str]
    followUpMessage: typing.Optional[str] = None
    suggestedNextActions: typing.List["SuggestedAction"]

class AiTimingSuggestion(BaseModel):
    # Response from AI timing suggestion
    suggestedTime: str
    reason: str
    confidence: float
    alternativeTimes: typing.List[str]

class AiTimingSuggestionRequest(BaseModel):
    # Request for AI timing suggestion
    clientId: int
    messageType: str
    preferredTimeRange: typing.Optional[str] = None

class AuthVerifyResponse(BaseModel):
    authenticated: bool
    userId: typing.Optional[int] = None
    username: typing.Optional[str] = None
    email: typing.Optional[str] = None
    firstName: typing.Optional[str] = None
    lastName: typing.Optional[str] = None
    organizationId: typing.Optional[int] = None
    permissions: typing.List[str]

class BetweenSessionEvent(BaseModel):
    # Event from between sessions
    id: str
    type: BetweenSessionEventType
    summary: str
    sentiment: typing.Optional[Sentiment] = None
    timestamp: str

class CardAction(BaseModel):
    # Card action button
    id: str
    label: str
    icon: typing.Optional[str] = None
    variant: ActionVariant
    disabled: typing.Optional[bool] = None

class CardData(BaseModel):
    # Card component data
    id: str
    title: str
    subtitle: typing.Optional[str] = None
    description: typing.Optional[str] = None
    icon: typing.Optional[str] = None
    badge: typing.Optional[str] = None
    badgeVariant: typing.Optional[BadgeVariant] = None
    actions: typing.Optional[typing.List["CardAction"]] = None

class ChatMessage(BaseModel):
    # Single chat message
    role: MessageRole
    content: str
    timestamp: str

class ChatRequest(BaseModel):
    # Chat request from extension to backend
    message: str
    context: typing.Optional["PageContext"] = None
    conversationHistory: typing.Optional[typing.List["ChatMessage"]] = None
    conversationId: typing.Optional[str] = None

class ChatResponse(BaseModel):
    # Chat response from backend to extension
    message: str
    conversationId: str
    suggestedActions: typing.List["SuggestedAction"]
    context: typing.Optional["ResolvedContext"] = None
    frontendCommands: typing.Optional[typing.List["FrontendCommand"]] = None

class ClientContext(BaseModel):
    id: int
    name: str
    email: typing.Optional[str] = None
    phone: typing.Optional[str] = None
    goals: typing.List[str]
    recentNotes: typing.Optional[str] = None
    lastSessionDate: typing.Optional[str] = None
    nextSessionDate: typing.Optional[str] = None
    totalSessions: int

class ClientGoal(BaseModel):
    # A client goal
    id: str
    clientId: int
    title: str
    description: typing.Optional[str] = None
    category: GoalCategory
    status: GoalStatus
    progress: int
    targetDate: typing.Optional[str] = None
    completedAt: typing.Optional[str] = None
    createdAt: str
    updatedAt: str

class ClientList(BaseModel):
    # List of clients with pagination
    items: typing.List["ClientSummary"]
    total: int
    page: int
    pageSize: int

class ClientNote(BaseModel):
    # Private coach notes about a client
    id: str
    clientId: int
    content: str
    createdAt: str
    updatedAt: str

class ClientNoteList(BaseModel):
    # List of client notes
    items: typing.List["ClientNote"]
    total: int

class ClientProfile(BaseModel):
    # Full client profile
    id: int
    name: str
    email: str
    phone: typing.Optional[str] = None
    company: typing.Optional[str] = None
    title: typing.Optional[str] = None
    bio: typing.Optional[str] = None
    values: typing.List[str]
    vision: typing.Optional[str] = None
    overarchingGoals: typing.List[str]
    totalSessions: int
    completedGoals: int
    activeGoals: int
    pendingActions: int
    lastSessionDate: typing.Optional[str] = None
    nextSessionDate: typing.Optional[str] = None
    coachingStartDate: str

class ClientStats(BaseModel):
    # Client engagement statistics
    clientId: int
    totalSessions: int
    averageSessionDuration: int
    completedGoals: int
    activeGoals: int
    completedActions: int
    pendingActions: int
    averageMoodRating: typing.Optional[float] = None
    sessionFrequency: float
    coachingDurationMonths: int

class ClientSummary(BaseModel):
    # Lightweight client summary for list views
    id: int
    name: str
    email: str
    company: typing.Optional[str] = None
    totalSessions: int
    lastSessionDate: typing.Optional[str] = None
    nextSessionDate: typing.Optional[str] = None

class CoacheePreSessionInput(BaseModel):
    # Coachee's pre-session input
    submitted: bool
    submittedAt: typing.Optional[str] = None
    topics: typing.Optional[typing.List[str]] = None
    updates: typing.Optional[str] = None
    questions: typing.Optional[typing.List[str]] = None
    moodRating: typing.Optional[int] = None

class CommandCenterData(BaseModel):
    # Grouped command center response
    focusNow: typing.List["CommandCenterItem"]
    soon: typing.List["CommandCenterItem"]
    later: typing.List["CommandCenterItem"]
    lastUpdated: str

class CommandCenterEventPayload(BaseModel):
    # Payload for COMMAND_CENTER_UPDATED event
    focusNowCount: int
    soonCount: int
    laterCount: int
    lastUpdated: str

class CommandCenterItem(BaseModel):
    # A single command center item
    id: str
    type: CommandItemType
    clientId: int
    clientName: typing.Optional[str] = None
    priority: Priority
    priorityReason: str
    action: str
    dueDate: typing.Optional[str] = None
    crossDomainContext: typing.Optional[str] = None
    sessionId: typing.Optional[str] = None
    createdAt: str

class Commitment(BaseModel):
    # A commitment from a previous session
    id: str
    description: str
    status: CommitmentStatus
    source: CommitmentSource
    sessionId: typing.Optional[str] = None
    createdAt: str

class ConnectionPayload(BaseModel):
    # Payload for CONNECTION_ESTABLISHED event
    connectionId: str
    userId: int
    capabilities: typing.List[str]

class ContextChangedPayload(BaseModel):
    # Payload for CONTEXT_CHANGED and STATE_UPDATED events
    page: str
    clientId: typing.Optional[int] = None
    clientName: typing.Optional[str] = None
    sessionId: typing.Optional[str] = None
    sessionDate: typing.Optional[str] = None
    availableActions: typing.List[str]
    source: typing.Optional[str] = None

class CorrectionPair(BaseModel):
    # Correction pair for batch analysis
    originalContent: str
    editedContent: str
    editType: EditType
    coachFeedback: typing.Optional[CoachFeedback] = None
    contentType: typing.Optional[VoiceContentType] = None
    timestamp: str

class CreateGoalRequest(BaseModel):
    # Request to create a new goal
    title: str
    description: typing.Optional[str] = None
    category: GoalCategory
    targetDate: typing.Optional[str] = None

class CreateResourceRequest(BaseModel):
    # Request to create a new resource
    type: ResourceType
    title: str
    description: typing.Optional[str] = None
    externalUrl: typing.Optional[str] = None
    tags: typing.List[str]

class CreateScheduledMessageRequest(BaseModel):
    # Request to create a scheduled message
    clientId: int
    sessionId: typing.Optional[str] = None
    templateId: typing.Optional[str] = None
    channel: MessageChannel
    subject: typing.Optional[str] = None
    body: str
    scheduledFor: str
    useAiSuggestion: bool
    autoApprove: bool
    transparencyIndicator: typing.Optional[str] = None
    transparencyDisplayName: typing.Optional[str] = None

class CurrentRead(BaseModel):
    # AI's current read/assessment of client
    assessment: str
    confidence: float
    lastUpdated: str

class DashboardData(BaseModel):
    # Full dashboard data response
    upcomingSessions: typing.List["SessionPrepStatus"]
    recentClients: typing.List["RecentClient"]
    pendingActionsCount: int
    todaySessionsCount: int
    weekSessionsCount: int
    lastUpdated: str

class DashboardPreferences(BaseModel):
    # Dashboard layout preferences
    coachId: int
    sections: typing.List["DashboardSection"]
    defaultView: DashboardView
    refreshInterval: int

class DashboardSection(BaseModel):
    # Dashboard section configuration
    id: str
    title: str
    priority: int
    visible: bool
    collapsed: bool

class DisclosureConfig(BaseModel):
    # Disclosure configuration
    defaultLevel: DisclosureLevel
    allowToggle: bool
    expandByDefault: bool

class EmptyState(BaseModel):
    # Empty state configuration
    icon: typing.Optional[str] = None
    title: str
    description: typing.Optional[str] = None
    actionLabel: typing.Optional[str] = None
    actionHref: typing.Optional[str] = None

class ErrorPayload(BaseModel):
    # Payload for ERROR event
    code: str
    message: str
    details: typing.Dict[str, str]
    retryable: bool

class EventEnvelope(BaseModel):
    # Event envelope - all WebSocket messages MUST be wrapped in this
    type: EventType
    meta: "EventMeta"
    payload: typing.Dict[str, str]

class EventMeta(BaseModel):
    # Metadata for every event (required for debugging/replay)
    timestamp: str
    correlationId: typing.Optional[str] = None
    contractsVersion: str
    actorId: typing.Optional[int] = None
    requestId: typing.Optional[str] = None

class FinalizeNotesRequest(BaseModel):
    # Request to finalize/send session notes
    notesId: str
    sendToClient: bool
    personalizedMessage: typing.Optional[str] = None

class FinalizeNotesResponse(BaseModel):
    # Response from finalizing notes
    success: bool
    status: SessionNotesStatus
    sentAt: typing.Optional[str] = None
    error: typing.Optional[str] = None

class FrontendActionResult(BaseModel):
    # Result reported back by frontend
    actionId: str
    status: FrontendActionStatus
    success: bool
    message: typing.Optional[str] = None
    error: typing.Optional["ActionError"] = None
    executedAt: str

class FrontendCommand(BaseModel):
    # Command sent to frontend via WebSocket
    actionId: str
    tool: FrontendToolName
    parameters: typing.Dict[str, str]
    timeout: int
    requiresConfirmation: bool

class FrontendCommandPayload(BaseModel):
    # Payload for FRONTEND_COMMAND event
    actionId: str
    tool: str
    parameters: typing.Dict[str, str]
    timeout: int
    requiresConfirmation: bool

class FrontendToolConfig(BaseModel):
    # Tool configuration for admin panel
    tool: FrontendToolName
    requiresConfirmation: bool
    defaultTimeout: int

class GenerateNotesRequest(BaseModel):
    # Request to generate session notes
    sessionId: str
    regenerate: bool

class GeneratePrepRequest(BaseModel):
    # Request to generate a prep document
    sessionId: str
    regenerate: bool

class GoalFilter(BaseModel):
    # Filter options for goals list
    clientId: typing.Optional[int] = None
    category: typing.Optional[GoalCategory] = None
    status: typing.Optional[GoalStatus] = None
    searchQuery: typing.Optional[str] = None

class GoalList(BaseModel):
    # List of goals with pagination
    items: typing.List["ClientGoal"]
    total: int
    page: int
    pageSize: int

class GoalMilestone(BaseModel):
    # Goal milestone
    id: str
    goalId: str
    title: str
    description: typing.Optional[str] = None
    targetDate: typing.Optional[str] = None
    completed: bool
    completedAt: typing.Optional[str] = None

class GoalProgressUpdate(BaseModel):
    # Goal progress update
    goalId: str
    progress: int
    note: typing.Optional[str] = None
    updatedAt: str

class GoalResponse(BaseModel):
    # Response containing goal data
    success: bool
    goal: typing.Optional["ClientGoal"] = None
    error: typing.Optional[str] = None

class GroupedList(BaseModel):
    # Grouped list data
    id: str
    groups: typing.List["ListGroup"]

class HeartbeatPayload(BaseModel):
    # Payload for HEARTBEAT event
    serverTime: str
    connectionAge: int

class InquiriesSection(BaseModel):
    # Inquiries section with questions
    id: str
    summary: str
    keyPoints: typing.List["KeyPoint"]
    expanded: typing.Optional[bool] = None
    questions: typing.List["InquiryQuestion"]

class InquiryQuestion(BaseModel):
    # A powerful question explored in the session
    id: str
    question: str
    category: InquiryCategory
    answered: typing.Optional[bool] = None

class IntegrationConfig(BaseModel):
    # Configuration for a single integration
    id: str
    coachId: int
    type: IntegrationType
    status: IntegrationStatus
    displayName: str
    accountEmail: typing.Optional[str] = None
    connectedAt: typing.Optional[str] = None
    lastSyncAt: typing.Optional[str] = None
    settings: typing.Dict[str, str]
    error: typing.Optional[str] = None

class IntegrationConnectRequest(BaseModel):
    # Request to initiate an integration connection
    type: IntegrationType
    redirectUrl: str

class IntegrationConnectResponse(BaseModel):
    # Response with OAuth URL
    success: bool
    authUrl: typing.Optional[str] = None
    error: typing.Optional[str] = None

class IntegrationDisconnectRequest(BaseModel):
    # Request to disconnect an integration
    integrationId: str

class IntegrationList(BaseModel):
    # List of coach's integrations
    integrations: typing.List["IntegrationConfig"]
    availableTypes: typing.List[IntegrationType]

class InvitationsSection(BaseModel):
    # Invitations section with action items
    id: str
    summary: str
    keyPoints: typing.List["KeyPoint"]
    expanded: typing.Optional[bool] = None
    actionItems: typing.List["ActionItem"]

class KeyPoint(BaseModel):
    # A key point within a section
    id: str
    text: str
    detail: typing.Optional[str] = None
    quote: typing.Optional["Quote"] = None

class LastSessionRecap(BaseModel):
    # Recap of previous session
    themes: typing.List[str]
    breakthroughs: typing.List[str]
    emotionalMoments: typing.List[str]
    summary: str
    sessionDate: str

class LifeContextItem(BaseModel):
    # Recent life context item
    area: LifeContextArea
    summary: str
    source: str
    updatedAt: str

class ListGroup(BaseModel):
    # A group within a list
    id: str
    title: str
    items: typing.List["ListItem"]
    collapsible: typing.Optional[bool] = None
    collapsed: typing.Optional[bool] = None

class ListItem(BaseModel):
    # List item data
    id: str
    primary: str
    secondary: typing.Optional[str] = None
    meta: typing.Optional[str] = None
    avatar: typing.Optional[str] = None
    selected: typing.Optional[bool] = None
    disabled: typing.Optional[bool] = None

class LoadingState(BaseModel):
    # Loading state configuration
    message: typing.Optional[str] = None
    showProgress: typing.Optional[bool] = None
    progress: typing.Optional[int] = None

class MessagePayload(BaseModel):
    # Payload for MESSAGE_RECEIVED and MESSAGE_SENT events
    conversationId: str
    role: str
    content: str
    timestamp: str

class NavigationOption(BaseModel):
    # Navigation option for available routes/actions
    label: str
    route: str
    icon: typing.Optional[str] = None

class NextSection(BaseModel):
    # Next section with focus areas
    id: str
    summary: str
    keyPoints: typing.List["KeyPoint"]
    expanded: typing.Optional[bool] = None
    focusAreas: typing.List[str]
    nextSessionDate: typing.Optional[str] = None

class NorthStarReminder(BaseModel):
    # Client's articulated purpose and direction
    values: typing.List[str]
    vision: str
    overarchingGoals: typing.List[str]

class ObservationEntry(BaseModel):
    # A single observation entry
    id: str
    type: ObservationType
    description: str
    evidence: typing.List[str]
    confidence: float
    detectedAt: str
    dismissed: bool
    dismissedBy: typing.Optional[str] = None
    dismissedAt: typing.Optional[str] = None

class ObservationPayload(BaseModel):
    # Payload for OBSERVATION_DETECTED event
    observationId: str
    clientId: int
    type: str
    description: str
    confidence: float

class OnboardingEventPayload(BaseModel):
    # Payload for ONBOARDING_* events
    coachId: int
    phase: str
    previousPhase: typing.Optional[str] = None
    overallProgress: float
    action: str
    timestamp: str

class OnboardingPhaseProgress(BaseModel):
    # Progress for a single onboarding phase
    phase: OnboardingPhase
    status: PhaseStatus
    startedAt: typing.Optional[str] = None
    completedAt: typing.Optional[str] = None
    skipped: bool
    skipReason: typing.Optional[str] = None
    data: typing.Dict[str, str]

class OnboardingProgress(BaseModel):
    # Overall onboarding progress
    coachId: int
    currentPhase: OnboardingPhase
    phases: typing.List["OnboardingPhaseProgress"]
    overallProgress: float
    startedAt: str
    completedAt: typing.Optional[str] = None
    estimatedTimeRemaining: typing.Optional[int] = None
    canSkipCurrent: bool

class OnboardingUpdateRequest(BaseModel):
    # Request to update onboarding progress
    phase: OnboardingPhase
    action: OnboardingAction
    data: typing.Dict[str, str]

class OnboardingUpdateResponse(BaseModel):
    # Response from onboarding update
    success: bool
    progress: "OnboardingProgress"
    nextPhase: typing.Optional[OnboardingPhase] = None
    error: typing.Optional[str] = None

class PageContext(BaseModel):
    # Page context from extension content script
    url: str
    route: typing.Optional[str] = None
    clientId: typing.Optional[int] = None
    sessionId: typing.Optional[str] = None
    pageTitle: typing.Optional[str] = None
    pageData: typing.Dict[str, str]

class PatternEvidence(BaseModel):
    # Evidence supporting a pattern
    sessionId: str
    sessionDate: str
    quote: str
    timestamp: typing.Optional[str] = None

class PatternIntelligence(BaseModel):
    # Detected pattern or theme
    id: str
    pattern: str
    frequency: int
    trend: PatternTrend
    evidence: typing.List["PatternEvidence"]
    lastOccurrence: str

class PrepDocument(BaseModel):
    # Full T-15 prep document with typed sections
    id: str
    sessionId: str
    clientId: int
    clientName: str
    sessionTitle: str
    sessionDateTime: str
    northStarReminder: "NorthStarReminder"
    lastSessionRecap: "LastSessionRecap"
    commitments: typing.List["Commitment"]
    lifeContext: typing.List["LifeContextItem"]
    patternIntelligence: typing.List["PatternIntelligence"]
    suggestedOpeners: typing.List["SuggestedOpener"]
    privateCoachNotes: str
    betweenSessionIntelligence: typing.List["BetweenSessionEvent"]
    coacheePreSessionInput: "CoacheePreSessionInput"
    generatedAt: str
    status: PrepStatus

class PrepList(BaseModel):
    # List of preps with pagination
    items: typing.List["PrepSummary"]
    total: int
    page: int
    pageSize: int

class PrepNotificationPayload(BaseModel):
    # Payload for PREP_NOTIFICATION, PREP_READY, PREP_VIEWED events
    sessionId: str
    clientName: str
    sessionDateTime: str
    prepStatus: str
    minutesUntilSession: int

class PrepResponse(BaseModel):
    # Response containing generated prep
    success: bool
    document: typing.Optional["PrepDocument"] = None
    error: typing.Optional[str] = None
    warnings: typing.List[str]
    generationTimeMs: int

class PrepSummary(BaseModel):
    # Lightweight summary for list views
    id: str
    sessionId: str
    clientId: int
    clientName: str
    sessionDateTime: str
    status: PrepStatus
    generatedAt: str

class PrepTemplate(BaseModel):
    # Template for coach's prep preferences
    id: str
    coachId: int
    name: str
    sectionsEnabled: typing.List[PrepSectionId]
    defaultExpanded: typing.List[PrepSectionId]

class PriorityItemPayload(BaseModel):
    # Payload for PRIORITY_ITEM_* events
    itemId: str
    type: str
    clientId: int
    clientName: typing.Optional[str] = None
    priority: str
    action: str

class PrivateIntelligence(BaseModel):
    # Complete private intelligence for a client
    clientId: int
    currentRead: typing.Optional["CurrentRead"] = None
    observations: typing.List["ObservationEntry"]
    coachPrivateNotes: typing.Optional[str] = None
    lastUpdated: str

class ProfileScrapeRequest(BaseModel):
    # Request to scrape coach profile
    urls: typing.List[str]
    linkedInUrl: typing.Optional[str] = None
    websiteUrl: typing.Optional[str] = None

class ProfileScrapeResponse(BaseModel):
    # Response from profile scraping
    success: bool
    profiles: typing.List["ScrapedCoachProfile"]
    mergedProfile: typing.Optional["ScrapedCoachProfile"] = None
    error: typing.Optional[str] = None

class Quote(BaseModel):
    # A quote from the session
    text: str
    timestamp: typing.Optional[str] = None
    videoLink: typing.Optional[str] = None

class RecentClient(BaseModel):
    # Recent client for dashboard display
    id: int
    name: str
    firstName: typing.Optional[str] = None
    lastName: typing.Optional[str] = None
    avatarUrl: typing.Optional[str] = None
    lastSessionDate: typing.Optional[str] = None
    nextSessionDate: typing.Optional[str] = None
    recentActivity: typing.Optional[str] = None
    hasPendingPrep: bool
    pendingActionsCount: int
    pendingMessages: typing.Optional[int] = None

class ResolvedContext(BaseModel):
    # Resolved context (what the system understood from PageContext)
    clientId: typing.Optional[int] = None
    clientName: typing.Optional[str] = None
    sessionId: typing.Optional[str] = None
    sessionDate: typing.Optional[str] = None
    confidence: float

class ResourceEventPayload(BaseModel):
    # Payload for RESOURCE_* events
    resourceId: str
    clientId: int
    type: str
    title: str
    action: str

class ResourceItem(BaseModel):
    # A single resource item
    id: str
    clientId: int
    coachId: int
    type: ResourceType
    title: str
    description: typing.Optional[str] = None
    fileUrl: typing.Optional[str] = None
    externalUrl: typing.Optional[str] = None
    thumbnailUrl: typing.Optional[str] = None
    tags: typing.List[str]
    metadata: "ResourceMetadata"
    createdAt: str
    updatedAt: str

class ResourceLink(BaseModel):
    # A resource link shared in the session
    id: str
    title: str
    url: str
    type: ResourceLinkType
    description: typing.Optional[str] = None

class ResourceListData(BaseModel):
    # Paginated resource list
    items: typing.List["ResourceItem"]
    total: int
    page: int
    pageSize: int
    nextPage: typing.Optional[int] = None

class ResourceMetadata(BaseModel):
    # Metadata for a resource item
    fileSize: typing.Optional[int] = None
    mimeType: typing.Optional[str] = None
    originalName: typing.Optional[str] = None
    linkTitle: typing.Optional[str] = None
    linkDescription: typing.Optional[str] = None
    linkImage: typing.Optional[str] = None

class ResourcesSection(BaseModel):
    # Resources section with links
    id: str
    summary: str
    keyPoints: typing.List["KeyPoint"]
    expanded: typing.Optional[bool] = None
    links: typing.List["ResourceLink"]

class ScheduledMessage(BaseModel):
    # Full representation of a scheduled message (API response)
    id: str
    coachId: int
    coachName: str
    clientId: int
    clientName: str
    clientEmail: str
    sessionId: typing.Optional[str] = None
    sessionDate: typing.Optional[str] = None
    templateUsed: typing.Optional[str] = None
    channel: MessageChannel
    subject: typing.Optional[str] = None
    body: str
    scheduledFor: str
    aiSuggestedTime: typing.Optional[str] = None
    aiSuggestionReason: typing.Optional[str] = None
    status: MessageStatus
    approvedAt: typing.Optional[str] = None
    reviewedAt: typing.Optional[str] = None
    sentAt: typing.Optional[str] = None
    cancelledAt: typing.Optional[str] = None
    cancellationReason: typing.Optional[str] = None
    deliveryAttempts: int
    lastDeliveryError: typing.Optional[str] = None
    externalMessageId: typing.Optional[str] = None
    transparencyIndicator: str
    transparencyDisplayName: typing.Optional[str] = None
    canEdit: bool
    canCancel: bool
    canSend: bool
    createdAt: str
    updatedAt: str

class ScheduledMessageAuditEntry(BaseModel):
    # Audit log entry for message state changes
    id: str
    messageId: str
    action: str
    actorId: typing.Optional[int] = None
    actorName: typing.Optional[str] = None
    details: typing.Dict[str, str]
    createdAt: str

class ScheduledMessageEventPayload(BaseModel):
    # Payload for SCHEDULED_MESSAGE_* events
    messageId: str
    clientId: int
    clientName: typing.Optional[str] = None
    channel: str
    subject: typing.Optional[str] = None
    scheduledFor: str
    status: str
    previousStatus: typing.Optional[str] = None

class ScheduledMessageFilter(BaseModel):
    # Filter parameters for listing messages
    status: typing.Optional[MessageStatus] = None
    channel: typing.Optional[MessageChannel] = None
    clientId: typing.Optional[int] = None
    sessionId: typing.Optional[str] = None
    fromDate: typing.Optional[str] = None
    toDate: typing.Optional[str] = None

class ScheduledMessageList(BaseModel):
    # Paginated list of scheduled messages
    items: typing.List["ScheduledMessage"]
    total: int
    page: int
    pageSize: int
    hasNext: bool

class ScheduledMessagePreferences(BaseModel):
    # User preferences for scheduled message handling
    preSendReviewEnabled: bool
    preSendReviewMinutes: int
    autoCancelIfClientResponds: bool
    defaultChannel: MessageChannel
    createdAt: str
    updatedAt: str

class ScrapedCoachProfile(BaseModel):
    # Scraped coach profile from external sources
    source: str
    sourceUrl: str
    name: typing.Optional[str] = None
    title: typing.Optional[str] = None
    bio: typing.Optional[str] = None
    certifications: typing.List[str]
    specialties: typing.List[str]
    yearsExperience: typing.Optional[int] = None
    photoUrl: typing.Optional[str] = None
    contactEmail: typing.Optional[str] = None
    scrapedAt: str
    confidence: float

class SessionContext(BaseModel):
    id: str
    clientId: int
    clientName: str
    scheduledAt: str
    status: str
    t15Summary: typing.Optional[str] = None
    notes: typing.Optional[str] = None
    transcript: typing.Optional[str] = None
    runningNotes: typing.Optional[str] = None

class SessionEventPayload(BaseModel):
    # Payload for SESSION_* events
    sessionId: str
    clientId: int
    clientName: typing.Optional[str] = None
    status: str
    scheduledAt: typing.Optional[str] = None

class SessionNoteSection(BaseModel):
    # Base structure for simple sections (recap, observations)
    id: str
    summary: str
    keyPoints: typing.List["KeyPoint"]
    expanded: typing.Optional[bool] = None

class SessionNotes(BaseModel):
    # Full session notes document with typed sections
    sessionId: str
    recap: "SessionNoteSection"
    observations: "SessionNoteSection"
    inquiries: "InquiriesSection"
    invitations: "InvitationsSection"
    resources: "ResourcesSection"
    next: "NextSection"
    voiceConfidence: float
    generatedAt: str
    lastEditedAt: typing.Optional[str] = None
    status: SessionNotesStatus

class SessionNotesEventPayload(BaseModel):
    # Payload for SESSION_NOTES_* events
    notesId: str
    sessionId: str
    clientId: int
    clientName: typing.Optional[str] = None
    sessionDate: str
    action: str
    status: str
    previousStatus: typing.Optional[str] = None
    sectionsCompleted: int
    totalSections: int

class SessionNotesFilter(BaseModel):
    # Filter options for session notes list
    clientId: typing.Optional[int] = None
    status: typing.Optional[SessionNotesStatus] = None
    fromDate: typing.Optional[str] = None
    toDate: typing.Optional[str] = None
    searchQuery: typing.Optional[str] = None

class SessionNotesList(BaseModel):
    # List of session notes with pagination
    items: typing.List["SessionNotesSummary"]
    total: int
    page: int
    pageSize: int

class SessionNotesResponse(BaseModel):
    # Response containing generated notes
    success: bool
    notes: typing.Optional["SessionNotes"] = None
    error: typing.Optional[str] = None
    warnings: typing.List[str]
    generationTimeMs: int

class SessionNotesSummary(BaseModel):
    # Lightweight summary for list views
    id: str
    sessionId: str
    clientId: int
    clientName: str
    sessionDate: str
    status: SessionNotesStatus
    summary: str
    generatedAt: str

class SessionPrepStatus(BaseModel):
    # Status of session preparation for dashboard display
    sessionId: str
    clientId: int
    clientName: str
    sessionDateTime: str
    sessionTitle: typing.Optional[str] = None
    prepStatus: PrepStatusValue
    timeUntilSession: int
    needsAttention: bool
    clientAvatarUrl: typing.Optional[str] = None
    meetLink: typing.Optional[str] = None

class StateHistoryEntry(BaseModel):
    # Historical state entry
    id: str
    userId: int
    page: str
    clientId: typing.Optional[int] = None
    sessionId: typing.Optional[str] = None
    source: StateSource
    createdAt: str

class StateHistoryQuery(BaseModel):
    # Request to query state history
    userId: typing.Optional[int] = None
    fromDate: typing.Optional[str] = None
    toDate: typing.Optional[str] = None
    limit: typing.Optional[int] = None

class StateUpdateRequest(BaseModel):
    # Request to update user's active state
    page: str
    clientId: typing.Optional[int] = None
    sessionId: typing.Optional[str] = None
    availableActions: typing.List[str]
    navigationOptions: typing.List["NavigationOption"]
    source: StateSource

class StateUpdateResponse(BaseModel):
    # Response from state update
    success: bool
    stateId: str

class StyleAnalysis(BaseModel):
    # LLM-computed style profile aggregated from correction analysis
    toneProfile: "ToneVector"
    sentencePatterns: typing.List[str]
    transitionPhrases: typing.List[str]
    emotionalRegister: str
    rhetoricalPatterns: typing.List[str]
    confidence: float
    sampleCount: int
    lastUpdated: str

class StyleAnalysisRequest(BaseModel):
    # Request for batch style analysis
    coachId: int
    correctionPairs: typing.List["CorrectionPair"]
    existingProfile: typing.Optional["StyleAnalysis"] = None
    includeInsights: bool

class StyleAnalysisResponse(BaseModel):
    # Response from style analysis
    styleProfile: "StyleAnalysis"
    insights: typing.Optional[typing.List["StyleInsight"]] = None
    voiceMatchConfidence: float
    improvementSuggestions: typing.List[str]

class StyleDashboardData(BaseModel):
    # Data for the style analysis dashboard
    profile: "VoiceProfileV1"
    trendData: typing.List["StyleTrendPoint"]
    topInsights: typing.List["StyleInsight"]
    recentCorrections: typing.List["VoiceCorrection"]
    improvementAreas: typing.List[str]

class StyleInsight(BaseModel):
    # Human-readable insight derived from style analysis for dashboard display
    category: str
    insight: str
    evidence: typing.List[str]
    confidence: float

class StyleTrendPoint(BaseModel):
    # Single data point for style trend chart
    date: str
    voiceConfidence: float
    correctionsCount: int
    avgMatchScore: typing.Optional[float] = None

class StyleTuning(BaseModel):
    # Coach's manual style tuning adjustments
    toneAdjustments: typing.Optional["ToneVector"] = None
    addPhrases: typing.List[str]
    removePhrases: typing.List[str]
    notes: typing.Optional[str] = None

class SuggestedAction(BaseModel):
    # Suggested action (Phase 2+)
    tool: ToolName
    label: str
    description: str
    parameters: typing.Dict[str, str]
    requiresConfirmation: bool

class SuggestedOpener(BaseModel):
    # AI-generated conversation starter
    question: str
    rationale: str
    category: OpenerCategory

class T15PrepEventPayload(BaseModel):
    # Payload for T15_PREP_* events
    prepId: str
    sessionId: str
    clientId: int
    clientName: typing.Optional[str] = None
    scheduledAt: str
    action: str
    sectionsCompleted: int
    totalSections: int
    overallReadiness: typing.Optional[str] = None

class TonePreference(BaseModel):
    # Tone preference configuration
    tone: str
    weight: float

class ToneVector(BaseModel):
    # 5-dimensional tone profile for measuring communication style
# Each dimension is computed from analyzing correction patterns
    warmth: float
    formality: float
    directness: float
    empathy: float
    energy: float

class ToolDefinition(BaseModel):
    name: ToolName
    description: str
    parameters: typing.List["ToolParameter"]
    requiresConfirmation: bool
    outputType: str

class ToolParameter(BaseModel):
    name: str
    type: str
    description: str
    required: bool
    default: typing.Optional[str] = None

class TransparentMessage(BaseModel):
    # Message with transparency metadata
    content: str
    indicator: TransparencyIndicator
    coachName: typing.Optional[str] = None
    approvedAt: typing.Optional[str] = None

class UpdateClientProfileRequest(BaseModel):
    # Request to update client profile
    name: typing.Optional[str] = None
    email: typing.Optional[str] = None
    phone: typing.Optional[str] = None
    company: typing.Optional[str] = None
    title: typing.Optional[str] = None
    bio: typing.Optional[str] = None
    values: typing.Optional[typing.List[str]] = None
    vision: typing.Optional[str] = None
    overarchingGoals: typing.Optional[typing.List[str]] = None

class UpdateClientProfileResponse(BaseModel):
    # Response from profile update
    success: bool
    profile: typing.Optional["ClientProfile"] = None
    error: typing.Optional[str] = None

class UpdateGoalRequest(BaseModel):
    # Request to update an existing goal
    title: typing.Optional[str] = None
    description: typing.Optional[str] = None
    category: typing.Optional[GoalCategory] = None
    status: typing.Optional[GoalStatus] = None
    progress: typing.Optional[int] = None
    targetDate: typing.Optional[str] = None

class UpdatePreferencesRequest(BaseModel):
    # Request to update preferences
    preSendReviewEnabled: typing.Optional[bool] = None
    preSendReviewMinutes: typing.Optional[int] = None
    autoCancelIfClientResponds: typing.Optional[bool] = None
    defaultChannel: typing.Optional[MessageChannel] = None

class UpdatePrepNotesRequest(BaseModel):
    # Request to update private notes
    privateCoachNotes: str

class UpdateResourceRequest(BaseModel):
    # Request to update an existing resource
    title: typing.Optional[str] = None
    description: typing.Optional[str] = None
    tags: typing.List[str]
    externalUrl: typing.Optional[str] = None

class UpdateScheduledMessageRequest(BaseModel):
    # Request to update a scheduled message
    subject: typing.Optional[str] = None
    body: typing.Optional[str] = None
    scheduledFor: typing.Optional[str] = None
    channel: typing.Optional[MessageChannel] = None

class UpdateSectionRequest(BaseModel):
    # Request to update a specific section
    sectionId: SessionNoteSectionId
    summary: typing.Optional[str] = None
    keyPoints: typing.Optional[typing.List["KeyPoint"]] = None

class UserActiveState(BaseModel):
    # Current user state (broadcast via WebSocket)
    page: str
    clientId: typing.Optional[int] = None
    clientName: typing.Optional[str] = None
    sessionId: typing.Optional[str] = None
    sessionDate: typing.Optional[str] = None
    availableActions: typing.List[str]
    navigationOptions: typing.List["NavigationOption"]
    source: typing.Optional[StateSource] = None
    lastUpdated: typing.Optional[str] = None

class VoiceCorrection(BaseModel):
    # A single voice correction record
    id: str
    originalContent: str
    editedContent: str
    editType: EditType
    coachFeedback: typing.Optional[CoachFeedback] = None
    contentType: VoiceContentType
    sessionId: typing.Optional[str] = None
    timestamp: str

class VoiceCorrectionRequest(BaseModel):
    # Request to submit a voice correction
    sessionId: typing.Optional[str] = None
    originalContent: str
    editedContent: str
    editType: EditType
    coachFeedback: typing.Optional[CoachFeedback] = None
    contentType: typing.Optional[VoiceContentType] = None

class VoiceCorrectionResponse(BaseModel):
    # Response from submitting a voice correction
    success: bool
    voiceConfidenceAfter: float
    improvementNote: typing.Optional[str] = None
    correctionId: typing.Optional[str] = None

class VoiceEventPayload(BaseModel):
    # Payload for VOICE_* events
    correctionId: typing.Optional[str] = None
    voiceConfidence: typing.Optional[float] = None
    contentType: typing.Optional[str] = None

class VoiceMatchResult(BaseModel):
    # Result of scoring content against voice profile
    overallScore: float
    toneScore: float
    structureScore: float
    vocabularyScore: float
    breakdown: typing.Dict[str, float]
    suggestions: typing.List[str]

class VoiceProfile(BaseModel):
    # Coach's voice profile
    coachId: int
    voiceConfidence: float
    totalCorrections: int
    vocabularyPatterns: typing.List[str]
    avoidPatterns: typing.List[str]
    tonePreferences: typing.List["TonePreference"]
    recentEdits: typing.List["VoiceCorrection"]
    lastTrainedAt: typing.Optional[str] = None

class VoiceProfileConfig(BaseModel):
    # Voice profile configuration (for onboarding setup)
    coachId: int
    minSamplesRequired: int
    currentSampleCount: int
    sampleTypes: typing.List[VoiceContentType]
    trainingStatus: VoiceTrainingStatus
    estimatedConfidence: typing.Optional[float] = None
    canStartTraining: bool
    lastUpdated: str

class VoiceProfileV1(BaseModel):
    # Extended voice profile with v1 style analysis
# Extends the base VoiceProfile with LLM-computed style data
    coachId: int
    voiceConfidence: float
    totalCorrections: int
    vocabularyPatterns: typing.List[str]
    avoidPatterns: typing.List[str]
    tonePreferences: typing.List["TonePreference"]
    recentEdits: typing.List["VoiceCorrection"]
    lastTrainedAt: typing.Optional[str] = None
    styleAnalysis: typing.Optional["StyleAnalysis"] = None
    styleInsights: typing.Optional[typing.List["StyleInsight"]] = None
    analysisVersion: str
    lastAnalyzedAt: typing.Optional[str] = None

class VoiceSample(BaseModel):
    # A single voice sample for training
    id: str
    coachId: int
    type: VoiceSampleType
    content: str
    context: typing.Optional[str] = None
    isPreferred: bool
    submittedAt: str
    processedAt: typing.Optional[str] = None
    processingStatus: VoiceSampleStatus

class VoiceSampleInput(BaseModel):
    # Input for a single voice sample
    type: VoiceSampleType
    content: str
    context: typing.Optional[str] = None
    isPreferred: bool

class VoiceSampleSubmitRequest(BaseModel):
    # Request to submit voice samples
    samples: typing.List["VoiceSampleInput"]

class VoiceSampleSubmitResponse(BaseModel):
    # Response from voice sample submission
    success: bool
    submittedCount: int
    sampleIds: typing.List[str]
    voiceProfileStatus: str
    minimumSamplesRequired: int
    currentSampleCount: int
    error: typing.Optional[str] = None

class VoiceSamplesPayload(BaseModel):
    # Payload for VOICE_SAMPLES_SUBMITTED event
    coachId: int
    sampleCount: int
    totalSamples: int
    sampleTypes: typing.List[str]
    voiceProfileStatus: str

# #########################################################################
# Generated type aliases (0)
# #########################################################################
