From 566b1a73ad1caf7ed399f96f5ec45153f7bd980f Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 23 Oct 2026 17:10:56 +0200 Subject: assistant: load the chat's model on open, docs for cloud models The canvas asks for its chat's model, else the preferred one, when it opens and when the pick changes; a cloud id loads nothing. The paperclip also closes the model panel, so it and the picker never stack. The plan's Models.qml import is corrected to the one that resolves. Co-Authored-By: Claude Opus 5.5 --- desktop/assistant/Card.qml | 2 +- desktop/assistant/README.md | 10 +++++++++- desktop/modules/assistant/README.md | 20 ++++++++++++++------ desktop/shell.qml | 11 +++++++---- .../plans/2026-10-23-assistant-cloud-models.md | 2 +- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/desktop/assistant/Card.qml b/desktop/assistant/Card.qml index b9fe4e5..810920f 100644 --- a/desktop/assistant/Card.qml +++ b/desktop/assistant/Card.qml @@ -465,7 +465,7 @@ Rectangle { text: "" font.family: Theme.iconFamily onClicked: { - card.canvas.historyOpen = false; + card.canvas.historyOpen = card.canvas.modelsOpen = false; card.canvas.pickerOpen = !card.canvas.pickerOpen; } } diff --git a/desktop/assistant/README.md b/desktop/assistant/README.md index 58fbb14..4c76a66 100644 --- a/desktop/assistant/README.md +++ b/desktop/assistant/README.md @@ -18,6 +18,7 @@ what is typed. The protocol is specified in that repo, | `Segments.qml` | markdown with a copy button per code block | | `History.qml` | conversation list and full-text search | | `Picker.qml` | the in-card file picker behind the paperclip | +| `Models.qml` | the model panel: local and cloud models, the chat's pick | | `Md.js` | splits a message into prose and fenced code | | `Files.js` | a path's kind, and a dropped URL to a path | | `Presets.js` | the Ask row's canned questions and which kinds they fit | @@ -38,9 +39,16 @@ model transcribe it and answers the words. The mic is greyed out while the model in use reports no `audio` input (`AssistantModule.hears`, from the router's `/models`, read on every open). +The header's model name (the Model button outside chat, or Ctrl+M) opens +the model panel: the router's models, then each cloud provider's. A pick +applies to this chat from its next question and is stored with it by the +daemon; a new chat starts on the preferred model. Moving a chat with turns +to a cloud model says once that its history goes to that provider. Voice is +transcribed by the local model in a cloud chat too. + Keys: Enter sends, Shift+Enter is a newline, Escape cancels a recording, then closes the picker, the history panel, then the card. Ctrl+N starts a -new chat, Ctrl+H toggles the history panel. Stop replaces +new chat, Ctrl+H toggles the history panel, Ctrl+M the model panel. Stop replaces Send while a reply streams. Notes: diff --git a/desktop/modules/assistant/README.md b/desktop/modules/assistant/README.md index 3c35dc6..9ee9736 100644 --- a/desktop/modules/assistant/README.md +++ b/desktop/modules/assistant/README.md @@ -15,6 +15,14 @@ The system prompt also has "Use the default". The tool environment saved, renames `tools/.toml` to `.toml.off`, which the daemon's `*.toml` glob skips. +**Cloud** edits the daemon's `[[cloud]]` tables: name, URL and key +command per provider. Fetch saves the page, then runs `assistant.py +--cloud-models `, which runs the key command and lists the +provider's ids; the switches choose which the canvas offers. The key +never reaches this page. A table holding more than the page writes (a +multi-line array, another key) is left alone, with a note to edit it by +hand. The saved cloud models also get Prefer in the Model list. + The page also lists llama-server's models with their state. The daemon always answers with whichever model is loaded and never asks for one, so it never swaps a model out from under another client. Load is the @@ -24,12 +32,12 @@ Prefer is the other, separate choice: the model the assistant should use, saved in `Prefs`. A first version made Load also set the preference, so a model loaded for another client became the assistant's too. -Opening the assistant canvas (SUPER+Home) loads the preferred model when -another one is resident, and the canvas header reads "loading …" -until it is in. This desktop runs one model and one client at a time, so -opening the assistant is when its model should come back; the daemon still -never asks for a model itself. With no preferred model set, nothing is -swapped. +Each chat uses the model picked in the canvas's model menu, else the +preferred one, else whatever is loaded. Opening the canvas, or picking a +local model for its chat, loads that model when another one is resident, +and the canvas header reads "loading …" until it is in. This +desktop runs one model and one client at a time, so that is when the +model should come back. A cloud model loads nothing. The daemon reads all of this only at startup, so after a change the page says so and offers Restart, which runs `assistant.sh restart`; a daemon that diff --git a/desktop/shell.qml b/desktop/shell.qml index 4b4f47f..8aaead3 100644 --- a/desktop/shell.qml +++ b/desktop/shell.qml @@ -126,17 +126,20 @@ ShellRoot { // The assistant canvas on SUPER+Home, a view over desktop-assistant's // socket. See assistant/README.md. - Assistant { id: assistant; swapping: asstSettings.loading; hears: asstSettings.hears } + Assistant { id: assistant; swapping: asstSettings.loading; hears: asstSettings.hears + preferred: Prefs.assistantModel } // The desktop companion, bottom-right of the focused monitor, on SUPER+\. // She reads the assistant's state. See companion/README.md. Companion { asst: assistant } - // Opening the assistant loads its preferred model if another one is in - // VRAM. See modules/assistant/README.md. + // Opening the assistant, or picking another model for its chat, loads + // that model if it is a local one and another is in VRAM. See + // modules/assistant/README.md. Connections { target: assistant - function onOpenChanged() { if (assistant.open) asstSettings.ensurePreferred(); } + function onOpenChanged() { if (assistant.open) asstSettings.ensureModel(assistant.wanted); } + function onWantedChanged() { if (assistant.open) asstSettings.ensureModel(assistant.wanted); } } // The waybar launcher and the deep-link keybinds all reach this: diff --git a/docs/superpowers/plans/2026-10-23-assistant-cloud-models.md b/docs/superpowers/plans/2026-10-23-assistant-cloud-models.md index bec65eb..6d9628a 100644 --- a/docs/superpowers/plans/2026-10-23-assistant-cloud-models.md +++ b/docs/superpowers/plans/2026-10-23-assistant-cloud-models.md @@ -639,7 +639,7 @@ Create `desktop/assistant/Models.qml` (GPLv2 header first, copied from `History. ```qml import QtQuick -import "../.." +import ".." // The model panel, over the transcript: the router's models, then the // cloud ones, in the daemon's order. A pick applies to this chat from its -- cgit v1.2.3