dshbase

Plugin directory / Developer / dsh-workspace-upload

dsh-workspace-upload

Unverified LI-Huaa

✓ Actively maintained

View on GitHub ↗ ← Back to plugin directory

1Stars
0Forks
0Open issues
Language
2026-08-14Last push
Cross-platformPlatform

What it does

A simple plugin to address the pain point of inconvenient file management when deploying DeepSeek Harness in the cloud. 一个简单的插件,用于在云端部署deepseek harness时管理文件。

Our take
Unverified — not yet verified

A simple plugin to address the pain point of inconvenient file management when deploying DeepSeek Harness in the cloud. 一个简单的插件,用于在云端部署deepseek harness时管理文件。 Not yet verified — install and test it yourself.

“Unverified” means our automated CI has not yet installed this plugin. Feature descriptions and version compatibility are the author’s claims. This is not a security audit and not an endorsement of third-party code.

Plugin author? Get the “Verified” label — submit your own evidence (screenshots, logs, or a short demo) and we'll review and flip the badge.

Submit verification evidence ↗

README

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:

Half File Role
Host lib/index.js Registers GET/POST /api/workspace-upload on the dsh web server: list / rename / mkdir / delete / download / chunked upload, all with workspace containment.
Client lib/client.js Browser 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).

Install

🧩 Let your agent install it (recommended)

Install the catalog once, then DeepSeek Harness can find and install any plugin from this site automatically:

dsh plugin add dshbase-catalog

Then say "install dsh-workspace-upload for me" — your agent finds it in the directory and installs it. Docs: dshbase-catalog · verified packs.

This plugin is GitHub source (not published to npm) — install it straight from the repo:

Web profile:

dsh plugin --profile web add github:LI-Huaa/dsh-workspace-upload

Headless (CLI) profile:

dsh plugin --profile headless add github:LI-Huaa/dsh-workspace-upload

Test report

Not yet L3-verified — see failure note below if we already ran it.

Status: pending · last test 2026-08-27 · flagged webonly
Note: 验证: web-only;待 L4 web CDP;L4 web CDP runtime-fail on dsh 0.1.0-rc.8. Browse all pending failures →
Security: not yet scanned — our daily static scan will cover it shortly.

Share this badge

More in Developer

Browse all 7795 plugins →