1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# 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.
|