dsh-plugin
DayuanJiang/next-ai-draw-iodsh 的 draw.io 绘图插件:通过 next-ai-drawio MCP 服务器作图,点回复里的链接在右侧栏打开实时预览,可以手动修改图,AI 的每次修改都是可以恢复的版本。需 Node.js 18+,首次使用由 npx 下载 MCP 服务器。
在 DeepSeek Harness 里直接跑本地 NVIDIA CUDA GPU 的 Python 任务:设备状态、前台/后台作业、持久日志、每次运行实测的峰值显存。
Run Python on your local NVIDIA GPU from DeepSeek Harness.
Three tools plus one skill, so an agent can do numerical work on the GPU instead of occupying the CPU: device status, foreground and detached runs, durable logs, and a measured peak-VRAM figure for every run.
中文说明见 README.zh.md.
| Name | Purpose |
|---|---|
cuda_status | device memory, utilization, GPU processes, every CUDA-capable Python on the machine, recent jobs |
cuda_run | submit Python source (code=) or a .py file (script=, plus args=); foreground or background=true |
cuda_job | follow one job: logs / wait / kill / info, by exact id, unique prefix, or latest |
skill cuda-compute | the local terrain, how to write the code, the traps — loaded on demand by the model |
Every run gets its own directory under ~/.dsh/gpu-runs/<job-id>/:
script.py a copy of what actually ran
_runner.py the wrapper that records resource facts
stdout.log full stdout (the tool returns only a tail)
stderr.log full stderr
job.json the durable record: pid, cwd, argv, timestamps, status
result.json written by the wrapper: ok, exit_code, elapsed_s, peak VRAM
peak_alloc_MB comes from torch.cuda.max_memory_allocated() inside the child, so the
number is measured, not estimated. A program can read DSH_CUDA_JOB_DIR to write its own
artifacts there — they are listed back to the model automatically.
status: running and a note; follow it with cuda_job. Only an explicit
cancellation actually terminates.cuda_status is for.result.json. No parent is left to record
the exit code, so once the pid disappears the wrapper's own fact sheet decides
done/failed; only its absence means lost.ctx.skills still gets the tools.lib/engine.js imports nothing from DSH, so the engine is driven directly by plain
Node in the test suite — see below.The package lives in a workspace directory. Install it through the harness rather than by
hand-editing the profile (the bundled cordis-plugin-development skill explains why):
plugin_manager action: install_bundle target: <absolute path to this directory>
Bundle code is only loaded at harness startup — restart DSH after installing or editing.
(The installer's applied result means the config was written and the entry imports
cleanly; it does not mean the tools are already visible to a running agent.)
Precedence for every setting: explicit plugin config → environment variable →
~/.dsh/cuda.json → built-in discovery.
| Environment variable | Meaning | Default |
|---|---|---|
DSH_CUDA_PYTHON | interpreter to use | discovered |
DSH_CUDA_RUNS_DIR | where job directories live | ~/.dsh/gpu-runs |
DSH_CUDA_TIMEOUT_MS | foreground budget | 300000 |
DSH_CUDA_MAX_TIMEOUT_MS | ceiling for a caller-supplied budget | 1800000 |
DSH_CUDA_MAX_OUTPUT_CHARS | output returned to the model per stream | 12000 |
~/.dsh/cuda.json is the convenient place for a machine-specific interpreter (an embedded
Python, a conda env):
{
"pythonPath": "C:\\path\\to\\python.exe",
"pythonCandidates": ["C:\\path\\to\\python.exe"],
"runsDir": "D:\\gpu-runs"
}
A malformed file is ignored rather than fatal.
With nothing configured, the plugin probes every python/python3 on PATH and a few
usual install locations, then picks the first candidate that exists. cuda_status reports
what each one can actually do (torch version, CUDA availability, device name, bf16), and
the probe result is cached for an hour.
An interpreter only counts if it has torch with CUDA. A system Python without torch
is reported but never chosen. Embedded interpreters shipped with image-generation tools
(ComfyUI, Stable Diffusion WebUI) work well — point DSH_CUDA_PYTHON at them.
cuda_status reports the model, memory, compute capability and bf16 support at runtime, so
the documents deliberately do not hard-code them.torch.cuda.is_available() is False, that
mismatch (or a CPU-only torch wheel) is the usual cause. cuda_status shows the driver and each
interpreter's CUDA availability side by side, so the problem is visible before writing any code.torch + CUDA. The rest (numpy, triton, scipy…) is optional.For writing custom kernels the plugin's skill documents what actually works: use
triton if it is installed. numba.cuda needs
libNVVM (shipped with the CUDA Toolkit) and fails with
NvvmSupportError: libNVVM cannot be found when the Toolkit is absent — a common trap.
110 checks across three suites. All of them run with plain Node — no harness restart, no test framework:
node test/selftest.mjs # 36 engine, against the real GPU
node test/harness.mjs # 46 plugin: mock context drives apply(), then the tools run
node test/lossless.mjs # 28 every tool value crosses the wire (see below)
selftest.mjs covers both run modes, promotion, cancellation, log tails, artifact
collection and argument validation on real hardware.harness.mjs builds a fake cordis context with exactly the surface the plugin uses, so
apply() and every tool branch are exercised without the harness.lossless.mjs deserves its own line: DSH refuses a tool value that is not lossless JSON
(visitJsonValue in @deepseek-ai/dsh-api-gateway rejects undefined, NaN, -0,
class instances, array holes and cycles). A single undefined field is enough to make a
perfectly working tool answer value is not lossless JSON, and no mock-based test
catches it. The suite reimplements that rule verbatim and adds six deliberately broken
values to prove the check itself has teeth.nvidia-smi reports no per-process VRAM and mixes graphics processes
into the GPU process list. cuda_status says so rather than pretending otherwise.cuda_run is registered as not concurrency-safe, so the harness will not
overlap two runs; large concurrent jobs would compete for VRAM anyway.nvcc is never invoked. Everything runs through the
interpreter, which keeps the plugin zero-install.MIT — see LICENSE.