# ----------------------------------------------------------------------------
#
#  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 (28)
# #########################################################################

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 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 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"
    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 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 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 PhaseStatus(str, Enum):
    # Status of an onboarding phase
    
    NOT_STARTED = "NOT_STARTED"
    IN_PROGRESS = "IN_PROGRESS"
    COMPLETED = "COMPLETED"
    SKIPPED = "SKIPPED"

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

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

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

class SessionNotesStatus(str, Enum):
    # Status of session notes document
    
    DRAFT = "DRAFT"
    IN_REVIEW = "IN_REVIEW"
    FINALIZED = "FINALIZED"
    SHARED = "SHARED"

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

class T15PrepSection(str, Enum):
    # The 9 sections of a T-15 prep document (matches backend spec)
    
    NORTH_STAR_REMINDER = "NORTH_STAR_REMINDER"
    LAST_SESSION_RECAP = "LAST_SESSION_RECAP"
    COMMITMENTS_TO_CHECK = "COMMITMENTS_TO_CHECK"
    LIFE_CONTEXT = "LIFE_CONTEXT"
    PATTERN_INTELLIGENCE = "PATTERN_INTELLIGENCE"
    SUGGESTED_OPENERS = "SUGGESTED_OPENERS"
    PRIVATE_COACH_NOTES = "PRIVATE_COACH_NOTES"
    BETWEEN_SESSION_INTELLIGENCE = "BETWEEN_SESSION_INTELLIGENCE"
    COACHEE_PRE_SESSION_INPUT = "COACHEE_PRE_SESSION_INPUT"

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 (109)
# #########################################################################

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 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 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
    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 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.List["ChatMessage"]
    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

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 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 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 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 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 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 HeartbeatPayload(BaseModel):
    # Payload for HEARTBEAT event
    serverTime: str
    connectionAge: int

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 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 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[int] = None
    pageTitle: typing.Optional[str] = None
    pageData: typing.Dict[str, str]

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 ResolvedContext(BaseModel):
    # Resolved context (what the system understood from PageContext)
    clientId: typing.Optional[int] = None
    clientName: typing.Optional[str] = None
    sessionId: typing.Optional[int] = 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 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 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: int
    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 SessionNotesDocument(BaseModel):
    # Full session notes document
    id: str
    sessionId: int
    clientId: int
    clientName: str
    sessionDate: str
    sessionDuration: int
    sections: typing.List["SessionSectionContent"]
    summary: str
    keyInsights: typing.List[str]
    followUpDate: typing.Optional[str] = None
    generatedAt: str
    lastUpdatedAt: str
    status: SessionNotesStatus
    version: int

class SessionNotesEventPayload(BaseModel):
    # Payload for SESSION_NOTES_* events
    notesId: str
    sessionId: int
    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 SessionNotesFinalizeRequest(BaseModel):
    # Request to finalize/approve session notes
    notesId: str
    shareWithCoachee: bool
    personalizedMessage: typing.Optional[str] = None

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

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

class SessionNotesRequest(BaseModel):
    # Request to generate session notes
    sessionId: int
    clientId: int
    transcript: typing.Optional[str] = None
    coachRunningNotes: typing.Optional[str] = None
    includeSections: typing.List[SessionNoteSection]
    regenerate: bool

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

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

class SessionSectionContent(BaseModel):
    # Content for a single session note section
    section: SessionNoteSection
    title: str
    content: str
    bulletPoints: typing.List[str]
    aiGenerated: bool
    coachEdited: bool
    lastEditedAt: typing.Optional[str] = None

class SessionSectionUpdateRequest(BaseModel):
    # Request to update a specific section
    notesId: str
    section: SessionNoteSection
    content: typing.Optional[str] = None
    bulletPoints: typing.List[str]
    markAsEdited: bool

class SessionSectionUpdateResponse(BaseModel):
    # Response from section update
    success: bool
    updatedSection: typing.Optional["SessionSectionContent"] = None
    error: 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 SuggestedAction(BaseModel):
    # Suggested action (Phase 2+)
    tool: ToolName
    label: str
    description: str
    parameters: typing.Dict[str, str]
    requiresConfirmation: bool

class T15PrepDocument(BaseModel):
    # Full T-15 prep document
    id: str
    sessionId: int
    clientId: int
    clientName: str
    scheduledAt: str
    sections: typing.List["T15SectionContent"]
    overallReadiness: str
    generatedAt: str
    lastUpdatedAt: str
    version: int

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

class T15PrepList(BaseModel):
    # List of T-15 preps with pagination
    items: typing.List["T15PrepSummary"]
    total: int
    page: int
    pageSize: int

class T15PrepRequest(BaseModel):
    # Request to generate a T-15 prep document
    sessionId: int
    clientId: int
    includeSections: typing.List[T15PrepSection]
    regenerate: bool
    focusAreas: typing.List[str]

class T15PrepResponse(BaseModel):
    # Response containing generated T-15 prep
    success: bool
    document: typing.Optional["T15PrepDocument"] = None
    error: typing.Optional[str] = None
    warnings: typing.List[str]
    generationTimeMs: int

class T15PrepSummary(BaseModel):
    # Lightweight summary for list views
    id: str
    sessionId: int
    clientId: int
    clientName: str
    scheduledAt: str
    generatedAt: str
    completedSections: int
    totalSections: int
    overallReadiness: str

class T15SectionContent(BaseModel):
    # Content for a single T-15 section
    section: T15PrepSection
    title: str
    content: str
    bulletPoints: typing.List[str]
    priority: int
    aiConfidence: float

class T15SectionUpdateRequest(BaseModel):
    # Request to update a specific section
    prepId: str
    section: T15PrepSection
    content: typing.Optional[str] = None
    bulletPoints: typing.List[str]
    coachNotes: typing.Optional[str] = None

class T15SectionUpdateResponse(BaseModel):
    # Response from section update
    success: bool
    updatedSection: typing.Optional["T15SectionContent"] = None
    error: typing.Optional[str] = None

class TonePreference(BaseModel):
    # Tone preference configuration
    tone: str
    weight: 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 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 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 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 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 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)
# #########################################################################
