# Ask presets: design Date: 2026-10-16. Status: approved in brainstorming, not implemented. ## Goal Piece 2 of the file work (piece 1: `2026-10-16-file-drop-design.md`). The file state gains an **Ask** row of canned questions matching the staged files: Summarize a PDF, Describe an image, Review code. A click sends the question with the files and moves to the chat. Canvas only: a preset is an ordinary `ask {text, files}`, so the daemon is unchanged. ## Data `desktop/assistant/Presets.js` holds the defaults, a list of `{label, prompt, kinds}`. `kinds` names the staged kinds a preset applies to (`pdf`, `image`, `text`, `code`), or is `["many"]`: offered whenever two or more files are staged, whatever their kinds. The list in use lives in `Prefs.qml` as `assistant.presets`, read as the defaults while nothing is saved, the same pattern as `perf.pinnedIp`. `Prefs.setPresets(list)` and `Prefs.resetPresets()` are there for a future drawer settings page, which is where presets will be edited; this piece has no editor. A saved list that fails validation (not an array of `{label: string, prompt: string, kinds: array}`) reads as the defaults. Every prompt is sent with " Answer in the language of the document." appended, so an Italian document gets an Italian answer. ## Defaults | label | kinds | prompt | | --- | --- | --- | | Summarize | pdf, text | Summarize this in a few short paragraphs. | | Key points | pdf | List the key points as bullets. | | Explain simply | pdf, text | Explain this simply, as to a non-expert. | | Describe | image | Describe this image. | | Extract text | image, pdf | Transcribe all the text, keeping the layout where it helps. | | What is this? | image | What is this, and what is it for? | | Explain | code | Explain what this code does. | | Review | code | Review this code: bugs, risks, and simplifications. | | Compare | many | Compare these files: what they share and how they differ. | `code` is a new canvas kind in `Files.js`: the text suffixes that are code or configuration (`.py`, `.sh`, `.qml`, `.json`, `.toml`, ...). Prose and data stay `text`: `.txt`, `.md`, `.rst`, `.csv`. Chat takes both, and the daemon still sees one text kind. ## Matching A preset is offered when every staged file's kind is in its `kinds`, or when it is a `many` preset and two or more files are staged. One PDF: Summarize, Key points, Explain simply, Extract text. An image and a PDF: Extract text and Compare. A video: none, and the row is hidden. ## Card - The Ask row sits above Chat about it in the file state. - A click sends the prompt with the staged files. - Shift+click puts the prompt in the input with focus instead, to edit it before sending. `Button.qml`'s `clicked` signal gains the mouse event so a button can read modifiers; existing handlers are unaffected. - While a chip of a kind chat does not take is staged, the row's buttons are disabled, as Chat about it is. ## Testing `node desktop/assistant/test_presets.js`: matching for one PDF, an image plus a PDF, two code files, one code file, a video; the language line on every prompt; validation falling back to the defaults. `test_files.js` gains the `code` kind. A harness load check, then the user's hand check: drop a PDF, see its four presets, click Summarize, get a summary in the document's language; Shift+click puts the prompt in the input.