aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/assistant/Assistant.qml
AgeCommit message (Collapse)AuthorFilesLines
8 hoursassistant: pick the chat's model, local or cloud, from the headerDanilo M.1-4/+42
The canvas keeps the chat's model from the daemon (hello.chat_model, conversation.model), falls back to the preferred one (set from shell.qml later), and sends it as model with every ask, typed or spoken. The To .md write stays without one: the daemon always writes with the local model. Models.qml lists the daemon's models event, router models then cloud ones, in a panel like History. It opens from the header label in chat, from a Model button next to History outside chat, and with Ctrl+M. The models are asked for on hello too, so the cloud marker is right before the panel was ever opened. Moving a chat with turns to a cloud model says once that its history goes to that provider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 hoursassistant: replied() when a reply finishesDanilo M.1-1/+7
The desktop companion waves when an answer is ready. The moment already existed as the done branch that calls notifyDone; it is now a signal too, so the companion connects to it instead of reading the turn list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 hoursassistant: notify when a reply ends while the card is closedDanilo M.1-0/+23
A reply streams into the canvas state while the card is closed, but nothing said when it was done, so working elsewhere meant checking back. Now a finished or failed turn sends a notification whose Open action brings the card back on that conversation. A stopped reply does not notify: stopping it was the user's own act. notify-send -A blocks until the notification is acted on or dismissed and prints the picked key, so one Process carries it. A newer reply restarts that Process and its stack tag replaces the balloon, which drops the older wait: only the latest reply's Open works. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysassistant: grey out the mic when the model cannot hearDanilo M.1-1/+4
AssistantModule keeps each router model's input_modalities and exposes hears: the model loading, else the first not unloaded (the daemon's rule), reports audio. Unknown inputs or a router that is down count as yes; the daemon's error covers the rest. The model list is now read on every canvas open, not only when a preferred model is set, so hears is current when the card shows. Checked: the rule against the router's live /models (Gemma resident: on; Qwen resident or loading: off; router down: on). Not yet seen by eye after a desktop shell reload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysassistant: a mic button asks by voiceDanilo M.1-3/+63
Each recording is a pw-record Process of its own, made from a Component like the Do row's runs, so a stopped recording's late exit cannot be read as the next one's. Stopping sets running to false (SIGTERM), which lets pw-record write the WAV header; the audio ask goes out from the process's exit, not from the click. Recording stops itself at 59 s: the daemon refuses over 60 s by file size, and the stop lands a little after the tick. Escape cancels a recording before it does anything else, and closing the card or losing the daemon cancels it too. A pw-record that ends on its own says "recording failed". Checked: a scratch harness saw transcribing, thinking, idle for a 2 s recording; by hand, every case in the spec passed with no pw-record left behind, a desktop shell reload mid-recording included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysName the project Keystone, and move its paths and namespacesDanilo M.1-1/+1
The repository had no name of its own, only the framework's. It is now Keystone, in the README, AGENTS.md, the settings window, notes commit messages, calctl's PRODID and the user page's User-Agent. Its files move off quickshell's name too: ~/.config/quickshell/greetings -> ~/.config/keystone/ ~/.config/quickshell/obs-scene-icons.json -> ~/.config/keystone/ $XDG_STATE_HOME/quickshell/desktop.json -> $XDG_STATE_HOME/keystone/ ~/.config/quickshell is Quickshell's own default config directory (a bare qs loads its shell.qml), so sharing it was a collision rather than a home. There is no fallback to the old paths: the files are moved once. The layer namespaces become keystone-*, and the Hyprland blur rules in hypr-theme are renamed to match in the same change. A running shell keeps its old namespaces until restarted. Left alone: the retired standalone mail and vm shells' namespaces, which their READMEs keep as history; Quickshell's own app id, binary and process name; and the repository directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysassistant: Load no longer changes the preferred modelDanilo M.1-1/+3
Load set the preference as well as swapping the model in, so loading a model from the settings page for any reason made it the assistant's model too: after loading Qwen there, the canvas kept Qwen instead of bringing the preferred Gemma back. Load and Prefer are now separate buttons: Load swaps a model in now and leaves the preference alone, and Prefer only records which model the canvas loads when it opens. The canvas header also showed a stale model name after a swap; it now takes the model from the daemon's ctx event, which carries it from desktop-assistant f9d4644 on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysassistant: opening the canvas loads the preferred modelDanilo M.1-0/+3
A preferred model that only took effect from the settings page did nothing the next time another client had swapped it out. On this desktop one model and one client run at a time, so opening the canvas is when the assistant's model should come back: if the preferred one is neither loaded nor loading, it is loaded, and the canvas header says so until the router reports it in. The daemon still never asks for a model; with no preference set nothing changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(assistant): review of the Do row and fileopsDanilo M.1-19/+42
The canvas: a To .md ended any other way than its own Stop (the footer Stop, a question, a drop, a daemon restart, an older daemon refusing the command) left the card at Working forever. The footer Stop goes through stopOp(), asking and dropping end the operation first, a disconnect ends it, and an error while nothing else runs is taken as its outcome. Each fileops run gets its own Process, so a stopped run's late answer is never read as the next one's. To .md takes one PDF, as one file is written. Compress... no longer flips back when file(1) refines a kind, long errors are elided, and a desktop with no documents folder gets Documents/Assistant rather than ~/Assistant. fileops: an animated GIF to PNG or JPEG left one file per frame under names the rename never found; the first frame is taken. JPEG flattens transparency onto white. Zipping a folder holding the output folder read its own growing archive without end; only regular files outside it are added, which also skips FIFOs and dangling links. qpdf warnings no longer fail a merge. A folder's free name keeps its dots, a lone .gz or .xz is decompressed rather than refused, and a dotfile's archive is not hidden. Tools die with fileops even when it is killed outright, a killed run's leftovers are swept on the next run, a stop between fork and bookkeeping cannot miss the child, and a late stop cannot add a second answer. Error lines lose bsdtar's doubled prefix and its delayed-exit noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): the Do row of file operationsDanilo M.1-0/+84
Conversions, extraction, merge and compression on the staged files from the file state, one at a time, with Stop; Compress… opens its formats. To .md goes through the daemon's write, the rest through fileops. The card keeps the result line, Saved name with Open and Folder, or the error, so another operation can follow on the same files. Results land in Documents/Assistant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): tell a nameless file's kind from its contentDanilo M.1-1/+31
A script with no suffix staged as 'other' and was refused. A staged file the name says nothing about is now handed to file(1) once, and its mime type gives the kind, so a shell script is code and gets Explain and Review. The daemon makes its own call on the content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(assistant): keep state across reloads, refusals and long repliesDanilo M.1-3/+16
From review. A shell reload reconnected with lastActive at 0, so the next SUPER+Home started a new conversation thirty seconds into one; hello with turns now counts as activity. show() could send new under a reply still running, which stops it unsaved; it waits while busy. ask() cleared the chips before the daemon accepted them, so a refused file (unreadable, too big, a model without vision) dropped them and collapsed the card to the entry line; the user event clears them now, and chatting holds the layout while a PDF is read. In the picker, folders ignore name filters and sorted first, so filter then Enter opened a folder; folders hide while filtering. Folder URLs are encoded, so a '#' in a name no longer cuts the path, and glob characters typed in the filter are taken literally. The card says the assistant is not running in every state, panels sit under the chat header instead of over it, and History and the picker no longer open together. Dropped file://localhost/ URLs are accepted, other hosts refused, and the island receptor keeps the sliver's width at rest so it takes no clicks beside it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): entry line, file state, staged files and a pickerDanilo M.1-9/+71
The card has three states: an entry line, a file state for staged files with Chat about it, and the chat. SUPER+Home resumes a conversation active in the last 10 minutes and otherwise starts a new one. The paperclip opens a picker drawn in the card, since a system dialog would open beneath the overlay that holds the keyboard. Button gains a font alias for the paperclip glyph, and the canvas a socketPath property so a check can point it at a scratch daemon. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysfix(assistant): keep focus in the card, scope errors, guard linksDanilo M.1-7/+13
From review of the canvas. Escape stopped working in three ways, each leaving the keyboard grabbed with nothing to receive it: the history field hiding took focus with it, a disabled input could not hold focus while the daemon was down, and a click in a streaming reply focused text the next flush destroyed. The card now gives focus back to the input whenever it falls out, and the input is read-only rather than disabled. Only an error the daemon marks as ending the reply (turn) closes the live row; a command error, possibly another client's, used to freeze the reply mid-stream. The running tool comes from state events, hello included. Scrolling up during a stream no longer snaps back, since following stops when a movement starts. History snippets go through Notify.sanitize like any model output, links open only for http, https and mailto, and a line opening with inline triple-backtick code is no longer taken as a fence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): the canvas, a view over the assistant daemonDanilo M.1-0/+208
The socket, the turn model and the window live in Assistant.qml, outside the window's loader, so closing the card loses nothing and a reply keeps streaming while it is closed. Tokens reach the model on a 50 ms tick rather than per token. Prose goes through Notify.sanitize, because model output can quote a search result and a remote image in it would be fetched on render. Code blocks get a copy button once their fence closes. The history panel lists conversations and searches them through the daemon's full-text index. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>