Skip to content

pywry.chat

Core chat data models, configuration objects, and HTML builder helpers.


Message Models

pywry.chat.ChatMessage

Bases: BaseModel

A single chat message.

Attributes:

Name Type Description
role Literal['user', 'assistant', 'system', 'tool']

Semantic role of the message within the conversation.

content str | list[ChatContentPart]

Message body as plain text or structured content parts.

message_id str

Stable message identifier used across UI and backend events.

timestamp float

Unix timestamp when the message was created.

metadata dict[str, Any]

Arbitrary provider- or application-specific metadata.

tool_calls list[ToolCall] | None

Requested tool invocations attached to assistant messages.

tool_call_id str | None

Tool-call identifier when this message is a tool result.

model str | None

Model name that produced the message, when known.

usage dict[str, Any] | None

Token or billing metadata returned by the provider.

stopped bool

Indicates generation stopped early, typically due to cancellation.

Attributes

role instance-attribute

role: Literal['user', 'assistant', 'system', 'tool']

content class-attribute instance-attribute

content: str | list[ChatContentPart] = ''

message_id class-attribute instance-attribute

message_id: str = Field(default_factory=lambda: f'msg_{hex[:12]}')

timestamp class-attribute instance-attribute

timestamp: float = Field(default_factory=time)

metadata class-attribute instance-attribute

metadata: dict[str, Any] = Field(default_factory=dict)

tool_calls class-attribute instance-attribute

tool_calls: list[ToolCall] | None = None

tool_call_id class-attribute instance-attribute

tool_call_id: str | None = None

model class-attribute instance-attribute

model: str | None = None

usage class-attribute instance-attribute

usage: dict[str, Any] | None = None

stopped class-attribute instance-attribute

stopped: bool = False

Classes

Config

Pydantic model configuration.

Functions

validate_content_length classmethod

validate_content_length(v: str | list[ChatContentPart]) -> str | list[ChatContentPart]

Reject content exceeding MAX_CONTENT_LENGTH.

Parameters:

Name Type Description Default
v str | list[ChatContentPart]

Candidate message content provided to the model.

required

Returns:

Type Description
str | list[ChatContentPart]

The original content when it satisfies size limits.

Raises:

Type Description
ValueError

Raised when plain-text content exceeds MAX_CONTENT_LENGTH.

text_content

text_content() -> str

Return the plain-text content regardless of content type.

Returns:

Type Description
str

The plain-text message body, flattening structured text parts.

pywry.chat.ChatThread

Bases: BaseModel

A conversation thread containing messages.

Attributes:

Name Type Description
thread_id str

Stable identifier for the conversation thread.

title str

Human-readable thread title shown in the UI.

messages list[ChatMessage]

Ordered transcript of messages in the thread.

created_at float

Unix timestamp when the thread was created.

updated_at float

Unix timestamp when the thread was last updated.

metadata dict[str, Any]

Arbitrary application-specific thread metadata.

status Literal['active', 'archived']

Lifecycle state of the thread in the chat UI.

Attributes

thread_id class-attribute instance-attribute

thread_id: str = Field(default_factory=lambda: f'thread_{hex[:8]}')

title class-attribute instance-attribute

title: str = 'New Chat'

messages class-attribute instance-attribute

messages: list[ChatMessage] = Field(default_factory=list)

created_at class-attribute instance-attribute

created_at: float = Field(default_factory=time)

updated_at class-attribute instance-attribute

updated_at: float = Field(default_factory=time)

metadata class-attribute instance-attribute

metadata: dict[str, Any] = Field(default_factory=dict)

status class-attribute instance-attribute

status: Literal['active', 'archived'] = 'active'

Content Parts

pywry.chat.TextPart

Bases: BaseModel

Plain text content part.

Attributes:

Name Type Description
type Literal['text']

Discriminator used when serializing mixed chat content parts.

text str

Plain text payload to render in the transcript.

Attributes

type class-attribute instance-attribute

type: Literal['text'] = 'text'

text instance-attribute

text: str

pywry.chat.ImagePart

Bases: BaseModel

Base64 image content part.

Attributes:

Name Type Description
type Literal['image']

Discriminator used when serializing mixed chat content parts.

data str

Base64-encoded image payload.

mime_type str

MIME type for the encoded image payload.

Attributes

type class-attribute instance-attribute

type: Literal['image'] = 'image'

data instance-attribute

data: str

mime_type class-attribute instance-attribute

mime_type: str = 'image/png'

pywry.chat.ResourceLinkPart

Bases: BaseModel

Resource link content part.

Attributes:

Name Type Description
type Literal['resource_link']

Discriminator used when serializing mixed chat content parts.

uri str

Resource URI exposed to the frontend or MCP consumer.

name str | None

Optional human-readable label for the resource.

mime_type str | None

Optional MIME type associated with the linked resource.

Attributes

type class-attribute instance-attribute

type: Literal['resource_link'] = 'resource_link'

uri instance-attribute

uri: str

name class-attribute instance-attribute

name: str | None = None

mime_type class-attribute instance-attribute

mime_type: str | None = None

Tool Call Models

pywry.chat.ToolCallFunction

Bases: BaseModel

Function call payload embedded in a tool invocation.

Attributes:

Name Type Description
name str

Tool function name requested by the model.

arguments str

JSON string of tool arguments in provider-native format.

Attributes

name instance-attribute

name: str

arguments class-attribute instance-attribute

arguments: str = ''

pywry.chat.ToolCall

Bases: BaseModel

Tool invocation attached to an assistant message.

Attributes:

Name Type Description
id str

Stable tool-call identifier used to correlate tool results.

type Literal['function']

Tool-call type discriminator.

function ToolCallFunction

Function name and serialized arguments requested by the model.

Attributes

id class-attribute instance-attribute

id: str = Field(default_factory=lambda: f'call_{hex[:12]}')

type class-attribute instance-attribute

type: Literal['function'] = 'function'

function instance-attribute

function: ToolCallFunction

Configuration

pywry.chat.SlashCommand

Bases: BaseModel

A slash command registered for the chat input.

Attributes:

Name Type Description
name str

Slash-prefixed command name entered by the user.

description str

Human-readable description displayed in command pickers.

handler_event str

Backend event name fired when the command is invoked.

args_schema dict[str, Any] | None

Optional JSON schema describing accepted command arguments.

builtin bool

Indicates whether the command ships with PyWry by default.

Attributes

name instance-attribute

name: str

description class-attribute instance-attribute

description: str = ''

handler_event class-attribute instance-attribute

handler_event: str = ''

args_schema class-attribute instance-attribute

args_schema: dict[str, Any] | None = None

builtin class-attribute instance-attribute

builtin: bool = False

Functions

validate_name classmethod

validate_name(v: str) -> str

Normalize slash-command names.

Parameters:

Name Type Description Default
v str

Candidate slash-command name.

required

Returns:

Type Description
str

Normalized lowercase name guaranteed to start with /.

pywry.chat.ChatConfig

Bases: BaseModel

Configuration for the chat engine.

Attributes:

Name Type Description
system_prompt str | None

Optional system prompt prepended to model conversations.

model str

Default model identifier used for generations.

temperature float

Sampling temperature passed to provider backends.

max_tokens int

Maximum token budget requested per generation.

streaming bool

Enables streaming responses when supported by the provider.

persist bool

Persists chat history between sessions when enabled.

slash_commands list[SlashCommand]

Commands exposed in the chat input UI.

provider str | None

Explicit provider name when overriding model-based selection.

provider_config dict[str, Any]

Arbitrary provider-specific configuration values.

Attributes

system_prompt class-attribute instance-attribute

system_prompt: str | None = None

model class-attribute instance-attribute

model: str = 'gpt-4'

temperature class-attribute instance-attribute

temperature: float = Field(default=0.7, ge=0.0, le=2.0)

max_tokens class-attribute instance-attribute

max_tokens: int = Field(default=4096, ge=1)

streaming class-attribute instance-attribute

streaming: bool = True

persist class-attribute instance-attribute

persist: bool = False

slash_commands class-attribute instance-attribute

slash_commands: list[SlashCommand] = Field(default_factory=_default_slash_commands)

provider class-attribute instance-attribute

provider: str | None = None

provider_config class-attribute instance-attribute

provider_config: dict[str, Any] = Field(default_factory=dict)

pywry.chat.ChatWidgetConfig

Bases: BaseModel

Full widget configuration including UI and chat settings.

Attributes:

Name Type Description
title str

Window or panel title presented to the user.

width int

Initial widget width in pixels.

height int

Initial widget height in pixels.

theme Literal['dark', 'light', 'system']

Preferred widget theme.

show_sidebar bool

Controls visibility of conversation-management UI.

show_settings bool

Controls visibility of chat settings controls.

toolbar_position Literal['top', 'bottom']

Placement of widget toolbar controls.

chat_config ChatConfig

Nested chat-engine configuration.

Attributes

title class-attribute instance-attribute

title: str = 'Chat'

width class-attribute instance-attribute

width: int = Field(default=600, ge=200)

height class-attribute instance-attribute

height: int = Field(default=700, ge=300)

theme class-attribute instance-attribute

theme: Literal['dark', 'light', 'system'] = 'dark'

show_sidebar class-attribute instance-attribute

show_sidebar: bool = True

show_settings class-attribute instance-attribute

show_settings: bool = True

toolbar_position class-attribute instance-attribute

toolbar_position: Literal['top', 'bottom'] = 'top'

chat_config class-attribute instance-attribute

chat_config: ChatConfig = Field(default_factory=ChatConfig)

pywry.chat.ChatTaskState

Bases: BaseModel

Tracks an MCP task lifecycle for a chat_send_message call.

Attributes:

Name Type Description
task_id str

Stable identifier for the MCP task.

thread_id str

Conversation thread associated with the task.

message_id str

Message that initiated the task.

status Literal['working', 'input_required', 'completed', 'failed', 'cancelled']

Current MCP task status.

status_message str

Human-readable progress or error status.

created_at float

Unix timestamp when the task state was created.

poll_interval float | None

Suggested polling interval for clients watching task progress.

Attributes

task_id class-attribute instance-attribute

task_id: str = Field(default_factory=lambda: f'task_{hex[:12]}')

thread_id class-attribute instance-attribute

thread_id: str = ''

message_id class-attribute instance-attribute

message_id: str = ''

status class-attribute instance-attribute

status: Literal['working', 'input_required', 'completed', 'failed', 'cancelled'] = 'working'

status_message class-attribute instance-attribute

status_message: str = ''

created_at class-attribute instance-attribute

created_at: float = Field(default_factory=time)

poll_interval class-attribute instance-attribute

poll_interval: float | None = None

Generation

pywry.chat.GenerationHandle dataclass

GenerationHandle(task: Task[Any] | None = None, cancel_event: Event = Event(), message_id: str = '', widget_id: str = '', thread_id: str = '', created_at: float = time(), _content_parts: list[str] = list())

Tracks an in-flight LLM generation for stop-button cancellation.

The cooperative cancellation pattern follows OAuthFlow._cancellation_event in auth/flow.py: the cancel_event is checked between chunks, and task.cancel() serves as a backup for non-cooperative generators.

Attributes:

Name Type Description
task Task[Any] | None

Async task performing the active generation, when available.

cancel_event Event

Cooperative cancellation signal checked by streaming providers.

message_id str

Assistant message being populated by the generation.

widget_id str

Widget instance associated with the generation.

thread_id str

Conversation thread associated with the generation.

created_at float

Unix timestamp when the handle was created.

_content_parts list[str]

Internal list of streamed chunks accumulated so far.

Attributes

task class-attribute instance-attribute

task: Task[Any] | None = None

cancel_event class-attribute instance-attribute

cancel_event: Event = field(default_factory=Event)

message_id class-attribute instance-attribute

message_id: str = ''

widget_id class-attribute instance-attribute

widget_id: str = ''

thread_id class-attribute instance-attribute

thread_id: str = ''

created_at class-attribute instance-attribute

created_at: float = field(default_factory=time)

_content_parts class-attribute instance-attribute

_content_parts: list[str] = field(default_factory=list)

is_expired property

is_expired: bool

Check if this handle has exceeded its TTL.

Returns:

Type Description
bool

True when the handle is older than GENERATION_HANDLE_TTL.

partial_content property

partial_content: str

Return content accumulated so far.

Returns:

Type Description
str

Concatenated streamed chunks recorded on the handle.

Functions

append_chunk

append_chunk(chunk: str) -> None

Record a streamed chunk.

Parameters:

Name Type Description Default
chunk str

Incremental content emitted by a streaming provider.

required

cancel

cancel() -> bool

Request cooperative cancellation.

Returns:

Type Description
bool

True if cancellation was newly requested, False if already cancelled.

pywry.chat.GenerationCancelledError

GenerationCancelledError(partial_content: str = '')

Bases: Exception

Raised by providers when cancel_event is detected mid-stream.

Attributes

partial_content instance-attribute

partial_content = partial_content

Functions


HTML Builder

pywry.chat.build_chat_html

build_chat_html(*, show_sidebar: bool = True, show_settings: bool = True, enable_context: bool = False, enable_file_attach: bool = False, file_accept_types: list[str] | None = None, container_id: str = '', header_actions: str = '') -> str

Build the HTML structure for a chat widget.

The layout follows VS Code's Copilot Chat pattern: a compact header bar with conversation management and settings, a full-width scrollable message area, and an input bar at the bottom. All components are inside a single pywry-chat container.

Parameters:

Name Type Description Default
show_sidebar bool

Include the thread/conversation picker in the header bar. When False the conversation dropdown is hidden but new-chat and other header buttons remain.

True
show_settings bool

Include the settings toggle button in the header.

True
enable_context bool

Enable @mention widget references in the chat input.

False
enable_file_attach bool

Show the attach button (📎) and enable drag-and-drop file attachments. Independent of enable_context.

False
file_accept_types list[str] | None

Restrict the file picker to specific extensions (e.g. [".csv", ".json"]). None uses a broad default set.

None
container_id str

Optional id for the outer container div.

''
header_actions str

Extra HTML injected into the header-actions area (right side of the header bar). Developers can add custom buttons here.

''

Returns:

Type Description
str

HTML string for the chat widget.