Preface

Developing agents within DeepSeek Harness (DSH) often requires passing local files to models: logs, screenshots, configurations, data samples. The native web input box is primarily designed for text, and relying solely on copy-pasting or manually typing paths into prompts makes handling multiple files, binaries, or large images cumbersome. The model might not even be able to access files on the host machine as intended.

This introduces the community plugin dsh-web-file-uploader (maintained by Mooling0602). It adds a DeepSeek web-style paperclip button to the DSH Web conversation input toolbar, uploads selected files to the DSH host machine, and determines the injection method based on the current model’s capabilities: multimodal models receive native image blocks, while text-only models receive readable paths. The current plugin version is 0.3.0, licensed under MIT, has approximately 11 stars on GitHub, and is classified as a client-side plugin.

What It Is

dsh-web-file-uploader is a file upload plugin for DeepSeek Harness Web UI. In one sentence: it adds an attachment entry to the composer input area, persists files to the DSH host machine, and passes them to the running model during message transmission based on the model’s capabilities.

Unlike “temporarily storing attachments only in browser memory,” this plugin writes files to the host disk (dynamic mode uses the session workspace uploads/, static bundles use $DSH_HOME/uploads, defaulting to ~/.dsh/uploads) and maintains a deduplication index to prevent repeated uploads from consuming storage.

Core Features

Input Area Attachment UI

The plugin adds a paperclip button to the left of the input toolbar, supporting multi-selection. Each file is displayed as an attachment card above the input box (showing thumbnails for images), with statuses: reading, uploading, saved. It offers copy path and remove operations. UI text is localized via the application’s locale service, supporting Chinese and English, following the DSH Web language setting or system default.

Model-Aware Injection

Uploaded files are injected based on the attachment card: when the card is present, the file’s absolute path is injected into every subsequent user message sent. Closing the card (×) calls the Host remove RPC, stopping injection but retaining the disk file. Deleting the card (🗑) calls the delete RPC, permanently deleting the file from the host and cleaning the deduplication index.

Injection behavior is differentiated by the model’s inputModalities (detected via llm.resolveModelInfo().inputModalities, cached for 10 minutes):

Model Type Images (png/jpeg/webp/gif) Other Files
Multimodal (including image) Injected as native ImageBlock via the attachments service, no additional text prompt Path text block
Text-only (e.g., DeepSeek V4 series) Path text block; the model can call read or vision tools itself Path text block

The injection block format for text-only models is as follows (English, for model reading):

-----
[Attached files] Some files have uploaded with this message:
- /path/to/file1.txt
- /path/to/image1.png
Read the files or use tools to analyse (like vision tools), then answer the user.

The plugin only injects absolute paths and is decoupled from auxiliary plugins like vision-tools; injection applies only to real user messages (source.kind === 'user'), not modifying steering or system messages. Ctrl+V pasting images goes through the product’s native draft pipeline, and the plugin does not interfere.

Content-Addressable Deduplication

During upload, the file bytes’ SHA-256 is computed, and the index is persisted in uploads/.dfu-index.json (hash → { path, at }). Uploading identical content reuses existing copies, with the response including dedup: true. For same-named but different content, filename conflicts are handled using the -1, -2 rule. Uploads are serialized via a Promise queue to avoid concurrency races.

Cleanup and Retention

The default TTL is 7 days. Files exceeding the TTL and not referenced in any active session’s pending list are lazily deleted during garbage collection. Retention can be configured in Settings → File Upload (the { ttl } field in the dsh-web-file-uploader namespace under settings); the environment variable DSH_UPLOAD_TTL (e.g., DSH_UPLOAD_TTL=30m) serves as a fallback. Setting it to 0 or empty disables automatic GC, requiring manual deletion via 🗑.

Size and Security Limits

Single file limit is approximately 48 MiB (dynamic mode RPC payload 64 MiB base64 limit, decoded to about 48 MiB). Filenames are sanitized by removing path separators, .., and control characters.

Installation and Enabling

The DSH ecosystem follows “everything is a plugin.” The community directory SkillHub provides a plugin index, with no official affiliation to DeepSeek or High-Flyer.

The package declares dsh.bundle.patch and is installed to the web profile via dsh plugin --profile web add:

dsh plugin --profile web add github:Mooling0602/dsh-web-file-uploader

After installation, restart the DSH web process and refresh the page. To update:

dsh plugin --profile web update dsh-web-file-uploader

Dynamic Plugin (Current Session, No Installation Needed)

Suitable for quick trials; definition is required again after restart:

cordis_define + cordis_run   # host = src/host.js, client = src/client.js

After approving the Run card, the paperclip button appears.

Typical Usage

  1. Install and restart DSH Web, then open the conversation page.

  2. Click the paperclip on the left of the input toolbar, select one or more local files. Cards show upload progress; after completion, you can click “Copy Path.”

  3. Enter a question and send. For multimodal models, images enter the request as native attachments; text-only models receive absolute file paths in the message, which can be analyzed using read, vision, and other tools.

  4. If you no longer need to inject paths into subsequent messages, click the card × to close (the file remains in the uploads directory). Click 🗑 for permanent deletion confirmation.

  5. To adjust the automatic cleanup cycle, open Settings → File Upload, modify TTL, e.g., 30m, 7d; or set the environment variable before starting:

DSH_UPLOAD_TTL=30m

Use Cases and Considerations

For Whom: Developers who frequently have models read logs, view screenshots, analyze configurations or data files in DSH Web; users who have installed file-reading plugins like vision-tools and want path injection decoupled from the toolchain.

Runtime Permissions: The plugin runs with the current DSH process permissions, writing files to the host disk. Before installation, read the GitHub source code and MIT license to ensure the upload directory and retention policy meet your security requirements.

Other Notes: Dynamic mode files are saved in the session workspace uploads/; static bundles write to $DSH_HOME/uploads. Single file limit is about 48 MiB; errors for oversized files are shown on the card. Node engine requirement is >=20.

Links

Following these steps, the DSH Web input box can attach files like the DeepSeek web version, with files persisted on the host, injected based on model capabilities, and featuring deduplication and TTL cleanup, suitable for daily conversational file analysis workflows.