- Главная
- Плагины
- Улучшения UI
- dsh-file-upload
dsh-file-upload
a903067276-rgb/dsh-file-upload
One upload button plus drag-and-drop files into the conversation as local paths: save to the project's uploads/, path text into the input box, works with any vision tool.
Установка
dsh plugin --profile web add github:a903067276-rgb/dsh-file-uploadREADME
dsh-file-upload ⬆️
One upload button + drag-and-drop files straight into the conversation — a plugin for DeepSeek Harness (dsh) web.
Unofficial project: independently developed and maintained by a community member, not an official DeepSeek product.
Screenshot

The upload icon button in the composer tool row (official DSH design tokens, follows dark/light theme); the picked file's path (blurred in the screenshot) is inserted into the input box automatically, ready to send.
Features
| Action | Effect |
|---|---|
| Click upload icon | System file picker (multi-select) → save → path into the input box |
| Drag a file into the window | Images & any file type are taken over (no "unsupported" toast) → save → path into the input box |
| Send the message | The model / vision tool reads the file by absolute path |
| Switch sessions | Button follows the current session; files land in that session's project uploads/ |
- Single-file limit: 25 MB (frontend) / 30 MB (backend)
- Filenames keep Chinese/space characters; a timestamp prefix avoids collisions
- Button shows busy state while uploading; failures surface as Chinese notices
Install
Official bundle install (one line):
dsh plugin --profile web add "github:a903067276-rgb/dsh-file-upload#main"
Restart dsh web (bundle layers are composed at startup). Requires pnpm on PATH (dsh plugin forwards to pnpm).
Manual mount (fallback): see docs/install.md — symlink into ~/.dsh/profiles/web/node_modules/ plus a single entry in ~/.dsh/cordis.patch.yml (a double entry makes the plugin apply twice and crash on duplicate route registration), then restart.
Usage
- Click the upload icon and pick files (multi-select), or drag files anywhere into the window.
- The file is saved to the current project's
uploads/directory; the input box gets[上传文件] <absolute path>lines — e.g.[上传文件] /path/to/uploads/xxx.png— and your existing draft text is kept. - Press send; the model — or any attached vision tool — reads the file by path.
Platform support
| Platform | Status |
|---|---|
| macOS | ✅ fully tested (development environment) |
| Linux | ✅ expected to work (pure Node implementation), untested |
| Windows | ⚠️ expected to work (pure Node implementation, Windows-safe filename sanitization, platform separator paths), untested |
Requirements
- DSH web (run with
dsh web) - No extra shell needed: the host half is pure Node (
node:fs), no system commands required on any platform.
How it works
- Host (
lib/index.js): one routePOST /api/file-upload/save— validates the session and size, then writes the base64 payload to<session cwd>/uploads/with pure Node (node:fs, no system command dependency, cross-platform); the returned path is built vianode:pathand follows the platform separator. - Client (
lib/client.js): registers the upload icon button in theconversation.input.leftseat (visually distinct from the default "+" command button); a capture-phase document listener takes over file drags before the official InputBar's bubble-phase listener (which would reject images);FileReaderreads base64, uploads it, then the path text is appended to the input draft (inputActions.setDraft). - Error boundary: a render crash degrades to a small "⚠ upload component error" chip instead of unmounting the whole composer.
Notes
- The
uploads/directory only grows; it is never cleaned automatically (we don't delete your files) — remove files manually when needed. - After modifying the plugin, restart
dsh webfor changes to take effect (client-side edits apply on a page refresh; host edits need a restart).
Why this plugin exists
DSH natively rejects dragged-in images when the current model doesn't support them (official toast: "the current model does not support images"). This plugin saves the file to disk first and puts a path text into the conversation instead — a plain-text message that passes the model's image check and works with any model or vision plugin.
Vision-plugin agnostic: the message only carries a local absolute path (plain text), so it works with dsh-vision's view_image, any other model/tool that can read local paths, or no vision at all. It bypasses DSH's native image rejection because no image block is ever submitted.