dsh-inline-download
English | 中文
Put a download button directly on file cards inside the DSH conversation. One click and the original file goes to the current device through the browser's download manager.
No sidebar, no context menu, no SFTP. It is meant for DSH running on a remote host, container, or NAS, where the files live on the Host and the browser is in front of you.
Where the button appears
| Surface | Button |
|---|---|
present delivery cards (files a model declared as deliverables) |
Download icon beside the native Open button |
| File bubbles in user messages (uploaded PDFs, archives, spreadsheets, …) | Download icon on the right side of the file card |
Image bubbles are out of scope; DSH's native image menu still saves them.
Usage
- Ask the model to deliver a file with
present, or send a message with a file attachment. - A download icon appears on the file card.
- Click it. The browser downloads the original bytes under the original filename.
The button reports preparing, started, and failed states. On failure, a short toast shows the HTTP status instead of the browser's opaque "download failed" message.
Install
dsh plugin --profile web add github:BearingSteel/dsh-inline-download
Refresh the browser page after installation. If the button does not appear, restart dsh web and refresh again. There is no build step and no runtime npm dependency.
Routes
The Host half serves two same-origin, authenticated routes. The browser never sends a file path:
GET|HEAD /api/inline-download.presented?sessionId=…&seq=…&index=…
GET|HEAD /api/inline-download.attachment?sessionId=…&seq=…&index=…
An unauthenticated request gets 401; coordinates outside that Session get 404.
Security boundaries
- Both download routes are registered behind DSH's Connection authentication fence; unauthenticated requests get
401. - The browser sends Session id, event sequence, and file index — never a file path. The Host resolves the target from the Session log, so editing the URL cannot read an arbitrary path.
- A delivered file must be a real
deliverables/presenteddeclaration in that Session. An uploaded attachment must be a realFileAttachmentRefinside auser/messageevent; the attachment is digest- and length-verified while it streams. - Bytes are streamed in bounded chunks with
Content-Disposition: attachment; the page never buffers the whole file. - DSH Session / filesystem authorization is not bypassed, and no core package is modified.
Known limitations
- Files only — no directory ZIP downloads.
- The user-file-bubble button relies on the official Chat renderer — the plugin locates file blocks through the rendered
conversation.chat.user.contentresult. A plugin that replaces that Factory may remove the per-card button from user messages;presentdelivery cards keep working through the officialdeliverables.file.actionsslot. - Delivered files must still exist — moving, deleting, or replacing a file with a directory makes the download fail.
- The browser chooses the save location — the plugin keeps no download history and does not claim to know the local path.
- Draft attachment cards are not covered — a file still in the browser draft is not a durable Host attachment yet, so it has no downloadable reference.
Compatibility
Developed and verified against DSH 0.2.2-rc.1. It requires:
- the Web GUI (
platform: web); - the
deliverables.file.actionsslot (@deepseek-ai/dsh-client-ui-deliverables); - the official Chat user-message renderer with
data-message-attachments(@deepseek-ai/dsh-client-ui-chat).
engines.dsh is >=0.2.2-rc.1 <0.3.0-0.
Development
npm test # Host route and browser-helper tests
npm run check # syntax checks + tests
npm pack --dry-run
No build is involved. client.js is a hand-written browser bundle loaded directly by DSH's window.__ModuleLoader__.
Layout
| File | Role |
|---|---|
index.js |
Host half: registers the two authenticated download routes |
lib/download.js |
Resolves coordinates from the Session log, streams bytes, names files, maps failures |
client.js |
Browser half: delivery-card slot action + user file-bubble buttons |
cordis.patch.yml |
Bundle patch that inserts the plugin row |
test/ |
Host route and browser-helper tests |
License
MIT, see LICENSE.
No comments yet. Be the first to write one.