diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-16 14:56:56 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-16 14:56:56 +0200 |
| commit | ab05d5bbb89745f1e7cb1615a6da305577aff864 (patch) | |
| tree | 74a2d34ee3962c0154fd0c1f2296a3ea6b982ea5 /docs/superpowers/specs/2026-10-16-file-drop-design.md | |
| parent | 94f12dc0e14b5e671965bee8fd664fed95c69d0b (diff) | |
| download | quickshell-ab05d5bbb89745f1e7cb1615a6da305577aff864.tar.gz quickshell-ab05d5bbb89745f1e7cb1615a6da305577aff864.zip | |
docs: spec the entry line and file drop on the island
Three card states: an entry line, a file state offering what to do with
dropped files, and the chat. A drop always starts a new task, and asking
about a file is one of the choices rather than the only one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/specs/2026-10-16-file-drop-design.md')
| -rw-r--r-- | docs/superpowers/specs/2026-10-16-file-drop-design.md | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-16-file-drop-design.md b/docs/superpowers/specs/2026-10-16-file-drop-design.md new file mode 100644 index 0000000..d3c8a9d --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-file-drop-design.md @@ -0,0 +1,92 @@ +# File drop and the entry line: design + +Date: 2026-10-16. Status: approved in brainstorming, not implemented. + +## Goal + +SUPER+Home opens a single line, "How can I help you?", which grows into the +chat once a question is asked. A file dragged onto the island opens a middle +state offering what can be done with it, and asking about it is one of +those choices, not the only one. This follows Modesty's island drop (read +for ideas only; Modesty is GPLv3). + +The daemon side (files in `ask`, extraction, history) is desktop-assistant's +`docs/superpowers/specs/2026-10-16-attachments-design.md`. + +This is piece 1 of three. Piece 2 fills the file state's **Ask** row with +per-type model prompts, piece 3 its **Do** row with local file operations +(PDF to markdown, merge, video to audio, format or GIF, trackcrop). Each +gets its own spec. + +## Three states + +| state | when | the card shows | +| --- | --- | --- | +| entry | no turns, nothing staged | one line: "How can I help you?" | +| file | files staged, no turns | the file chips, the action rows, the input ("Ask about report.pdf…"), **Chat about it** | +| chat | the conversation has turns | the chat as today | + +The card stays centred, with the dim backdrop in every state. Its height +animates (about 180 ms) between states, growing from the centre. + +- **Opening.** SUPER+Home shows the chat if the current conversation was + active (a `user` or `done` event) in the last 10 minutes. Otherwise the + canvas sends `new`, and the empty conversation is the entry state. The + old conversation stays in History. The 10 minutes are a constant, not a + preference. +- **Entry to chat.** Enter on a typed question sends `ask`; its `user` + event adds a turn, which is the chat state. +- **A drop** always starts a new task: the canvas sends `new`, stages the + files and shows the file state, even over a recent conversation. +- **File state.** Each chip has a ×; removing the last returns to entry. + Enter on a typed question sends `ask {text, files}` and clears the chips. + **Chat about it** moves to the chat layout with the files still staged + and focus in the input, sending nothing. In piece 1 the action rows hold + only Chat about it. A file of a kind chat does not take (video, archive) + shows "chat supports text, images and PDF" on its chip; while any such + chip is staged, Chat about it and the input are disabled (removing it + enables them). +- **Results of a local operation** (piece 3) report in the file state and + never turn it into a chat. +- Escape closes the card in every state, after the history panel. + +Sent files show as chips under the question in the transcript, with the +`truncated` mark from the daemon's `files` list. + +## File kinds + +`desktop/assistant/Files.js` maps a path to `text`, `image`, `pdf`, +`video`, `archive` or `other` by extension, with the same text, code and +image lists as the daemon. It also turns a dropped URL into a path: +`file://` URLs are decoded, anything else is ignored. + +## The island receptacle + +In `desktop/island/Island.qml`: + +- one `DropArea` spans the sliver and the space for a bubble below it; +- a drag entering with URLs and a copy action sets `dropHold`, which shows + a bubble, "Drop for the assistant", and adds the bubble to the input + mask so the drop can land on it; +- leaving clears `dropHold`; +- a drop converts the URLs, calls `asst.attach(paths)` and accepts the + copy. With no file URLs it is refused. + +`shell.qml` passes the canvas as `asst: assistant`, never under the +canvas's own id name (AGENTS.md: a property named like the enclosing id +binds to itself). + +Wayland reports a drag only once it enters one of the island's input +regions, which is why the drop begins on the sliver. + +## Testing + +- `node desktop/assistant/test_files.js`: kinds per extension, case + folding, files with no extension, URL decoding with spaces and non-ASCII + names, non-file URLs dropped. +- The scratch harness load check, as for the canvas. +- By hand: drag a file over the sliver and see the bubble; drop it and get + the file state; remove the chip and get entry; drop again and use Chat + about it; ask about a PDF and an image; see chips in the transcript; + drop a video and see the refusal; SUPER+Home after more than 10 minutes + gives entry, within 10 minutes the chat. |
