Skip to main content
J

dsh-download-server

jestions-dev/dsh-download-server

A persistent download server for DSH — jobs outlive the session, survive a restart, and resume from the last byte.

Install

dsh plugin --profile web add github:jestions-dev/dsh-download-server

README

dsh-dl-server

English | 中文

DLS — DSH Download Server A persistent download queue for DeepSeek Harness.

Downloads should not live inside a session.


Install

Settings → Plugins → Install a third-party plugin → Add plugin

Type dsh-dl-server@0.1.1, confirm, then restart DSH once.

From the command line

dsh plugin add dsh-dl-server@0.1.1

Pin the version. 0.1.0 declared @deepseek-ai/dsh-storage-domain as a regular dependency, so pnpm installed a second copy inside the plugin; the injected service then no longer matched the host and the plugin never mounted (every service stayed pending). 0.1.1 moves it to peerDependencies.

pnpm also caches registry metadata — without an explicit version you may still resolve 0.1.0.

dsh must be on your PATH. The desktop build ships one at …\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd; if you have never added it, use the UI path.

Requires DSH 0.2.1-rc.5 or newer. aria2 is optional — install it for 16-way segmented downloading, or skip it and the plugin falls back to a single-stream transfer. Same features, less speed.


Why

Most DSH downloaders are one tool function that blocks until the file lands. They make downloads fast; they don't solve three things:

  • the download dies when the session or the turn ends
  • there is no queue, no pause, no resume
  • nothing survives a restart

DLS is the queue layer, not the transport layer.

Jobs live in DSH, not in a session.

A download started in one session is visible to every other session — progress, destination, everything. But only the session that started it can pause, resume, or cancel it.


The seven tools

ToolWhat it does
download_enqueueQueue a job, return immediately with a job id
download_statusInspect the queue or a single job (J#1042)
download_waitBlock until a job reaches a terminal state, with a timeout
download_pausePause, keeping the bytes already on disk
download_resumeContinue from the last checkpoint
download_cancelCancel, optionally dropping the partial file
download_cleanupDrop records (the default scope leaves downloaded files alone)

New in 0.2.0

Mirror expansionGitHub Releases / HuggingFace / raw.githubusercontent / PyPI URLs gain a fallback mirror automatically. The original always stays first.
Mirror cooldownTwo consecutive failures on one host parks it for 10 minutes instead of retrying it on every job.
Size-aware concurrencyUnder 1 MB skips aria2 entirely; 1–8 MB runs 4 connections; only 8 MB and up gets 16.
Session fairnessWhen two sessions queue at once they share the slots instead of one of them taking the whole queue.
Cumulative disk budgetEnqueue counts what already-queued jobs still need, so a batch cannot quietly fill the disk.
Failures are no longer silentCheckpoint write errors are counted and surfaced in download_status under storage; an unwritable destination is refused before the transfer starts.

New in 0.3.0

Queue de-duplicationOne destination is never downloaded twice. A finished job is reused while its file is still on disk; a different source claiming the same path fails with dest-in-use.
Mirror self-verificationBefore a mirror is used, it is HEADed once: the length must equal the origin's, and when the origin advertises an ETag the mirror's must match too.

A mirror is a third party and serves whatever it likes. Length plus ETag catches a cached older build or an HTML error page; it does not catch a poisoned copy. Only sha256 proves content, which is why mirrors are a fallback and not a guarantee.

Example

You:   download these two PDFs into D:\Papers and tell me when they're done

The agent calls download_enqueue twice and gets J#10 / J#11 back, then download_wait.

Because enqueue returns immediately, it can fire off ten downloads without waiting for any of them.


Measured

Same machine, same file:

SetupThroughput
TUNA mirror · single connection43.98 MB/s
TUNA mirror · 16 threads (another plugin)54.20 MB/s
TUNA mirror · DLS61.08 MB/s (saturates a 500 Mbps link)
HuggingFace · single-stream fallback1.00 MB/s
HuggingFace · DLS6.96 MB/s (7×)

The last row is the point: on a per-connection-throttled host, segmentation beats bandwidth.


Behaviour worth knowing

  • Ownership is per session. Any session on the machine can see every job; only the owner can mutate one.
  • cleanup(scope="all") deletes files. The default allWithoutFiles only drops records.
  • Checkpoints live in DSH storage, not as lock files dropped into your home directory — the plugin does not depend on TMPDIR or the working directory.
  • When aria2 is unavailable the transport degrades to a single Node stream. No features lost, some speed lost.

Docs

  • SPEC.md — the 565-line design doc: comparison with four sibling plugins, what was borrowed from PCL2, and the v1 trade-offs
  • CONTRIBUTING.md — layout, how to run the tests, what not to touch
  • SECURITY.md — how to report a vulnerability, and what counts as one

Roadmap

The roadmap names product stages (v1, v1.1, v1.2, v2); npm versions follow semver. They do not map one-to-one — use this table:

npmRoadmapContentStatus
0.1.xv1queue + persistence + seven tools + aria2 transportreleased
0.2.xv1.1mirrors / mirror cooldown / size-aware concurrency / session fairness / disk budget / loud failuresreleased
0.3.xv1.2queue de-duplication / mirror self-verificationplanned
1.0.0v2shell interception / torrents / own segmented engine / content addressingplanned
1.1.xv3user panel + callbacks into the agentplanned

Why 0.x lasts until v2: 1.0.0 means "the tool names and config keys will not change incompatibly". Only v2 touches the transport and the tool set, so that is where 1.0 belongs.

You never have to do the conversion yourself — install the latest and you get the newest milestone.

License

MIT

Related plugins