Repository navigation
Chat
A streaming AI chat surface: multiple conversations with local persistence, a model picker, an artifact preview panel, and push-to-talk or hands-free voice capture. wAwesomeChat is built on it.
from wapyt import ChatConfig, ChatMessageConfig
chat = self.add_chat("main", ChatConfig(storage_key="myapp", default_model="gpt-4o"))
def on_send(payload):
prompt = payload["text"] # also: payload["id"], payload["message"]
reply_id = chat.start_stream(ChatMessageConfig(role="assistant", content=""))
spawn(stream_reply(reply_id, prompt), "chat")
async def stream_reply(reply_id, prompt):
stream = ... # an (async) iterator of provider chunks, e.g. from a @bff_stream export
chat.consume_stream(reply_id, stream)
chat.on_send(on_send)-
on_sendreceives{id, text, message}. The prompt istext;messageis the user message the widget appended (withauto_append_user_messages). -
start_stream(message)→ id; thenappend_stream(id, chunk)andfinish_stream(id). -
consume_stream(id, stream)drives a sync or async iterator of provider chunks for you. Streaming backends report failures in-band as{"error": {...}}chunks;consume_streamraises those asChatStreamErrorinstead of rendering an empty message. Any other consumer needs the same check (Chat.extract_stream_error). -
build_history(system_prompt=..., exclude_ids=...)returns[{"role", "content"}]for the active chat.
- Conversations persist to
localStorageunderChatConfig(storage_key=...). Without a key nothing survives a reload. - The selected model resolves as: the active chat's model, then the last model
the user picked, then
default_model, then the first available. - Load the catalogue from a BFF after construction with
set_extra({"providerConfig": {"providers": {...}}})orset_models([...]).
-
voice_input=True: a hold-to-talk mic.on_voice→{audio (base64), mimeType, bytes, durationMs}; transcribe server-side and hand the text back withset_composer_text(text, submit=...)orapply_transcript(...). -
voice_continuous=True: a latching mic that segments speech on silence (vad_threshold,vad_silence_ms) and auto-submits. -
voice_max_seconds(default 120) caps a take. - Needs a secure context (
http://127.0.0.1counts, a LAN IP does not). pyTincture sendsPermissions-Policy: microphone=()by default; setPYTINCTURE_ALLOW_MICROPHONE=1(pyTincture ≥ 1.0.0rc8) to allow the mic.on_voice_errorreports refusals.
Events: on_artifact_save, on_artifact_load, on_copy, on_voice_error.
Methods: set_messages, add_message, update_message, remove_message,
clear_messages, set_agent, set_theme, focus_composer,
set_chat_badge, get_chats, get_messages, destroy.
Messages render through an escaping markdown renderer (marked is used only
when DOMPurify is present too). Artifact previews run in
<iframe sandbox="allow-scripts"> without allow-same-origin. See
Security and Escaping.
wapyt is MIT-licensed · Repository · pyTincture · Issues
Getting started
Widgets
- Layout and MainWindow
- Tree
- DataTable
- Form
- ModalWindow
- Window
- TabWidget
- Toolbar
- Sidebar
- Chat
- Terminal
- CardPanel
- ResourceBoard
- File Transfer
- Message
- ContextMenu
- MenuBar
- Listbox
- Kanban
- ProgressBar
- Pagination
- Popup and tooltips
- Chart
- Scheduler
- MediaPlayer
Guides
Planning
Contributing