# assistant The assistant canvas: a centred card on DP-1, on SUPER+Home, for typed conversations with the local text assistant. It is only a view. desktop-assistant (the repo next to this one) is the daemon that owns the model, the tools and the history; this connects to its socket, `$XDG_RUNTIME_DIR/desktop-assistant.sock`, draws what it is told and sends what is typed. The protocol is specified in that repo, `docs/superpowers/specs/2026-10-16-text-daemon-design.md`. qs -p ./desktop ipc call assistant toggle | File | Does | | --- | --- | | `Assistant.qml` | the socket, the turn model, the window | | `Card.qml` | header, transcript, input, the history panel's place | | `Message.qml` | one turn: question, thinking line, tool chips, reply | | `Segments.qml` | markdown with a copy button per code block | | `History.qml` | conversation list and full-text search | | `Md.js` | splits a message into prose and fenced code | Keys: Enter sends, Shift+Enter is a newline, Escape closes the history panel and then the card. Stop replaces Send while a reply streams. Notes: - **The state outlives the card.** The socket and the turn model live in `Assistant.qml`, outside the window's loader, so closing the card loses nothing, and a reply keeps streaming into it while it is closed. - **Tokens are batched.** They collect in a buffer and reach the model on a 50 ms tick, so markdown is re-rendered twenty times a second at most rather than per token. - **Prose goes through `Notify.sanitize`**, which blocks remote images. Model output can quote a search result, and an image URL in it would be fetched the moment it rendered. - **A code block's copy button appears once the fence closes.** A half-streamed block is not the command the model meant. - **The daemon may be down.** The card says so and disables the input; the socket retries every 2 s with a fresh `Socket` (see AGENTS.md), logging a `ServerNotFoundError` warning each time. - **`tools` is a comma-joined string role.** A ListModel role holding an array becomes a nested model, which `setProperty` cannot append to. - **A stopped reply is shown, not kept.** The daemon does not save a partial turn, so it is gone after the next reopen or restart. - **Only an error marked `turn` ends a reply.** Every client sees every event, so a command error (another canvas opening a deleted conversation) shows above the input instead. - **Search snippets** mark matches with `**`, rendered as bold; backticks are stripped first, since a match inside a code span would show the markers literally. Test the splitter: `node desktop/assistant/test_md.js`.