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 str

Semantic role — "user", "assistant", "system", or "tool".

content str | list[ContentBlock]

Message body as plain text or ACP content blocks.

message_id str

Stable 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[ACPToolCall] | None

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.

usage dict[str, Any] | None

Token or billing metadata.

stopped bool

Whether generation stopped early (e.g. cancellation).

Attributes

role instance-attribute

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

content class-attribute instance-attribute

content: str | list[ContentBlock] = ''

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[ACPToolCall] | 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

model_config class-attribute instance-attribute

model_config = ConfigDict(populate_by_name=True)

Functions

validate_content_length classmethod

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

Reject content exceeding MAX_CONTENT_LENGTH.

Parameters:

Name Type Description Default
v str | list[ContentBlock]

Candidate message content.

required

Returns:

Type Description
str | list[ContentBlock]

The original content when it satisfies size limits.

Raises:

Type Description
ValueError

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 str

Lifecycle state — "active" or "archived".

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 block.

Attributes:

Name Type Description
type str

Discriminator — always "text".

text str

Plain text payload.

annotations dict[str, Any] | None

Optional ACP annotations.

Attributes

type class-attribute instance-attribute

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

text instance-attribute

text: str

annotations class-attribute instance-attribute

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

pywry.chat.ImagePart

Bases: BaseModel

Base64-encoded image content block.

Attributes:

Name Type Description
type str

Discriminator — always "image".

data str

Base64-encoded image bytes.

mime_type str

MIME type (e.g. "image/png"). Serializes as mimeType.

uri str | None

Optional source URI.

annotations dict[str, Any] | None

Optional ACP annotations.

Attributes

model_config class-attribute instance-attribute

model_config = ConfigDict(populate_by_name=True)

type class-attribute instance-attribute

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

data instance-attribute

data: str

mime_type class-attribute instance-attribute

mime_type: str = Field(default='image/png', alias='mimeType')

uri class-attribute instance-attribute

uri: str | None = None

annotations class-attribute instance-attribute

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

pywry.chat.ResourceLinkPart

Bases: BaseModel

Reference to an agent-accessible resource without embedding content.

Attributes:

Name Type Description
type str

Discriminator — always "resource_link".

uri str

Resource URI.

name str

Human-readable label.

mimeType str | None

MIME type of the linked resource.

title str | None

Display title.

description str | None

Longer description of the resource.

size int | None

Resource size in bytes.

annotations dict[str, Any] | None

Optional ACP annotations.

Attributes

model_config class-attribute instance-attribute

model_config = ConfigDict(populate_by_name=True)

type class-attribute instance-attribute

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

uri instance-attribute

uri: str

name class-attribute instance-attribute

name: str = ''

mime_type class-attribute instance-attribute

mime_type: str | None = Field(default=None, alias='mimeType')

title class-attribute instance-attribute

title: str | None = None

description class-attribute instance-attribute

description: str | None = None

size class-attribute instance-attribute

size: int | None = None

annotations class-attribute instance-attribute

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

Tool Call Models

pywry.chat.ACPToolCall

Bases: BaseModel

ACP tool invocation attached to an assistant message.

Attributes:

Name Type Description
toolCallId str

Unique identifier within the session.

title str

Human-readable description shown in the UI.

name str

Tool name.

kind str

Category from the ACP taxonomy.

status str

Lifecycle state.

arguments dict[str, Any]

Tool arguments.

content list[ContentBlock] | None

Result content blocks (populated on completion).

locations list[ToolCallLocation] | None

Affected file paths with optional line numbers.

Attributes

model_config class-attribute instance-attribute

model_config = ConfigDict(populate_by_name=True)

tool_call_id class-attribute instance-attribute

tool_call_id: str = Field(default_factory=lambda: f'call_{hex[:12]}', alias='toolCallId')

title class-attribute instance-attribute

title: str = ''

name class-attribute instance-attribute

name: str = ''

kind class-attribute instance-attribute

kind: ToolCallKind = 'other'

status class-attribute instance-attribute

status: ToolCallStatus = 'pending'

arguments class-attribute instance-attribute

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

content class-attribute instance-attribute

content: list[ContentBlock] | None = None

locations class-attribute instance-attribute

locations: list[ToolCallLocation] | None = None

pywry.chat.ToolCallLocation

Bases: BaseModel

File location affected by a tool call.

Attributes:

Name Type Description
path str

Absolute file path.

line int | None

Optional 1-based line number.

Attributes

path instance-attribute

path: str

line class-attribute instance-attribute

line: int | None = None

Configuration

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.

temperature float

Sampling temperature.

max_tokens int

Maximum token budget per generation.

streaming bool

Enable streaming responses.

persist bool

Persist chat history between sessions.

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

pywry.chat.ChatWidgetConfig

Bases: BaseModel

Full widget configuration including UI and chat settings.

Attributes:

Name Type Description
title str

Window or panel title.

width int

Initial widget width in pixels.

height int

Initial widget height in pixels.

theme str

Preferred widget theme.

show_sidebar bool

Show conversation-management UI.

show_settings bool

Show chat settings controls.

toolbar_position str

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 str

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.

Uses cooperative cancellation: 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.

cancel_event Event

Cooperative cancellation signal.

message_id str

Assistant message being populated.

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.

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.

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:

Name Type Description
partial_content str

Content accumulated before cancellation.

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.

Parameters:

Name Type Description Default
show_sidebar bool

Include the thread/conversation picker in the header bar.

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.

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.

''

Returns:

Type Description
str

HTML string for the chat widget.