DeepSeek Harness plugin

dsh-workspace-upload

Workspace file manager for the dsh Web GUI: browse, upload, download, rename, create, and delete session files.

Jump to install

Source facts

Repository
LI-Huaa/dsh-workspace-upload
Latest update
Aug 14, 2026
Category
Tools & Capabilities
GitHub stars
1
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/LI-Huaa/dsh-workspace-upload
Plugin: dsh-workspace-upload
Author: LI-Huaa

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer4 files
README.mdSource · read only
README language

dsh-workspace-upload

English | 中文

A workspace file-manager plugin for the dsh Web profile — browse, upload, download, rename, create and delete files in the session's workspace, right from the chat UI.

Features

  • A 文件 (Files) button in the composer's left controls opens a file-manager

dialog over the app: browse the workspace and its subdirectories (breadcrumb navigation, up / refresh); upload — multi-file, chunked, any size (640 KiB chunks, adaptive shrink under proxy body limits); download files; rename files and folders; create folders; delete files and folders (two-step confirm).

  • Every operation is scoped to the workspace root: host-side path containment

rejects any .. or absolute-path escape.

  • The workspace resolves to the session's workspace (session → cwd → first

registered workspace).

Directory structure

dsh-workspace-upload/
├── cordis.patch.yml      # profile patch layer: inserts the plugin row
├── package.json          # dsh.bundle / dsh.client declarations, exports
├── lib/
│   ├── index.js          # host half: /api/workspace-upload file-manager route
│   └── client.js         # client half: browser bundle (button + dialog)
├── test/
│   ├── protocol.mjs      # host protocol tests (real handler, no dsh needed)
│   └── simulate.mjs      # client kernel simulation (slot registration fake)
├── LICENSE               # MIT
├── .gitignore
├── README.md             # English
└── README-zh.md          # 中文

Architecture

One package, one profile row, two halves:

HalfFileRole
Hostlib/index.jsRegisters GET/POST /api/workspace-upload on the dsh web server: list / rename / mkdir / delete / download / chunked upload, all with workspace containment.
Clientlib/client.jsBrowser bundle (window.__ModuleLoader__.load): the trigger button in conversation.input.left; the dialog renders from the button itself (plain local state, position: fixed overlay).

Wiring:

  • package.jsondsh.bundle.patch points at cordis.patch.yml (the profile

layer that inserts the row) and dsh.client.platform: "web" marks the package as a browser-roster entry whose bundle ships via exports["./client"].

  • cordis.patch.yml inserts one row, workspace-upload, into the web

composition.

API

GET  /api/workspace-upload
       → { "workspace": "<resolved workspace dir>" }        (no params)
       → file download with attachment headers              (?sessionId&path&name)

File-manager modes (JSON POST; path is a workspace-relative directory "" / "sub" / "sub/deep", name is always one path segment):

{ "mode": "list",   "sessionId"?, "path"? }                    → { workspace, path, entries:[{name,type,size,mtime}] }
{ "mode": "rename", "sessionId"?, "path"?, "name", "newName" } → { ok, from, to }
{ "mode": "mkdir",  "sessionId"?, "path"?, "name" }            → { ok, path }
{ "mode": "delete", "sessionId"?, "path"?, "name" }            → { ok, deleted }

Chunked upload (any file size; the GUI sends 640 KiB chunks — base64 bodies ~853 KiB, under the nginx default client_max_body_size of 1 MiB; on a bare 413 the client halves the chunk size down to 64 KiB and retries):

{ "mode": "chunk",  "sessionId"?, "path"?, "transferId", "name", "offset", "data", "total" } → { received }
{ "mode": "finish", "sessionId"?, "path"?, "transferId", "name", "total", "overwrite"? }     → { status, path, bytes }
{ "mode": "abort",  "transferId" }                                                            → { aborted }

Chunks are appended to a hidden .dsh-upload-<transferId> temp file inside the target directory and renamed on finish. Chunks must arrive in order from offset 0; a repeated chunk at an already-received offset is answered idempotently (safe client retry). Orphaned transfers are swept after 30 minutes.

A legacy single-shot batch mode is kept for API/curl compatibility:

{ "sessionId"?, "files": [{ "name", "data": "<base64>", "overwrite"? }] }
  → { "workspace": string, "results": [{ name, path?, status, bytes?, error? }] }

Limits: 32 MiB per request (one chunk + overhead), 8 MiB decoded per chunk. overwrite: true replaces an existing file; otherwise the file is skipped with status: "skipped".

Install

The package installs as a dsh profile bundle. From the checkout that owns the package directory:

dsh plugin --profile web add ./dsh-workspace-upload
# or from a clone:  dsh plugin --profile web add /path/to/dsh-workspace-upload

Then restart the web profile (dsh web ...) so the loader picks up the new row, and refresh the browser. Removing the plugin:

dsh plugin --profile web remove dsh-workspace-upload

Development

Both tests run without a dsh instance (they exercise the real host handler and client bundle factory directly):

node test/protocol.mjs   # host protocol: list/rename/mkdir/delete/download/chunked upload
node test/simulate.mjs   # client kernel: slot registration against a faithful slots fake

Security notes

  • All path / name values are sanitized and containment-checked on the host;

uploads use hidden temp files that never escape the target directory.

  • The route inherits the dsh web server's bind (localhost by default); when

exposing the GUI remotely, put it behind the same TLS/Basic-Auth reverse proxy as the rest of the app (and raise client_max_body_size if you want fewer, larger chunks).