"""Private, durable messages between an ordinary chat and one investigation run.""" from typing import Annotated, Literal from uuid import UUID from pydantic import Field from app.domain.schemas.shared import NonEmptyStr, StrictModel from app.domain.schemas.workbench_runtime import WorkbenchDateTime MessageText = Annotated[str, Field(min_length=1, max_length=12000, pattern=r"\S")] MessageStatus = Literal["pending", "enqueued", "delivered", "failed"] class AgentMessageCreate(StrictModel): request_id: UUID task_id: UUID run_id: UUID source_session_id: NonEmptyStr text: MessageText class AgentMessageReply(StrictModel): request_id: UUID source_session_id: NonEmptyStr text: MessageText class AgentMessageDelivery(StrictModel): status: Literal["enqueued", "delivered", "failed"] target_session_id: NonEmptyStr | None = None native_message_id: NonEmptyStr | None = None failure_detail: Annotated[str, Field(max_length=500)] | None = None class AgentMessage(StrictModel): project_id: UUID message_id: UUID request_id: UUID task_id: UUID run_id: UUID source_session_id: NonEmptyStr source_owner_id: UUID conversation_owner_id: UUID target_session_id: NonEmptyStr | None = None direction: Literal["to_task", "to_chat"] in_reply_to: UUID | None = None text: MessageText status: MessageStatus native_message_id: NonEmptyStr failure_detail: str | None = None created_at: WorkbenchDateTime updated_at: WorkbenchDateTime delivered_at: WorkbenchDateTime | None = None class AgentMessagePage(StrictModel): items: list[AgentMessage] next_cursor: str | None = None