dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把极空间(ZSpace)NAS 变成 agent 的原生工具:列目录、查属性、按名检索、读取、下载、上传、写入、建目录、重命名、移动、复制、删除 NAS 文件。跨网络走桌面客户端中转——不需要同一局域网、不用 WebDAV、不用 SSH;同一网络时自动改走更快的 WebDAV 直连。删除需显式传 confirm: true;写入、上传、建目录、重命名、移动、复制默认直接执行,zspace_write 会覆盖同名文件(除非传 overwrite: false)。
极空间(ZSpace)NAS 的 DeepSeek Harness 插件:把 NAS 变成 agent 的原生工具 —— 跨网络可用,不需要同一局域网、不需要 WebDAV、不需要 SSH、不需要 Python。
DSH 插件 → http://127.0.0.1:13579 → 极空间桌面客户端(已登录) → 极空间云中转 / P2P → NAS
认证直接复用桌面客户端自己的登录态(vuex.json),所以换任何网络都能用:只要跑 DSH 的这台机器上极空间桌面客户端在线即可。这正好补上 dsh-webdav 那类"必须同网段"方案的短板。
# 从 npm 安装(推荐)
dsh plugin --profile desktop add dsh-zspace@latest
# 或用仓库里的本地包
dsh plugin --profile desktop add /绝对路径/dsh-zspace-0.1.0.tgz
装完重启 DSH(或在插件市场点「一键重启」)即可在会话里看到 zspace_* 工具。
前置条件:
插件对同一套工具自动选路,判断依据是可达性而不是 IP 网段(本机在 192.168.31.x 也能直连 <nas-ip> 的 NAS):
| 情况 | 通道 | 条件 |
|---|---|---|
| 能直连 NAS(同网络) | WebDAV 直连 | 配了 webdavUrl + 环境变量 ZS_WEBDAV_PASSWORD;1.5s PROPFIND 探测通过即启用 |
| 跨网络 / WebDAV 不可达 | 桌面客户端云中转(默认) | 桌面客户端已登录并在运行 |
PROPFIND 拿全(没有中转的 50 行分页)。transportMode:auto(默认)/ webdav(强制,失败直接报错)/ relay(保持旧行为)。/sata1/my/data/... ↔ WebDAV 的 <webdavHomePath>/...(默认根 /);公共空间由 webdavPublicPath 指定(默认空=不在 WebDAV 暴露,相关路径自动回到中转)。5005,本机实测可用;5006 是自签 HTTPS,证书校验会失败)。ZS_WEBDAV_URL(如 http://<nas-ip>:5005/)、ZS_WEBDAV_USER(NAS 账号)、ZS_WEBDAV_PASSWORD。
插件跑在 DSH Desktop 进程里,所以要让桌面端能看到这些变量(macOS):
launchctl setenv ZS_WEBDAV_URL 'http://<nas-ip>:5005/'
launchctl setenv ZS_WEBDAV_USER '<NAS账号>'
launchctl setenv ZS_WEBDAV_PASSWORD '<密码>'
# 然后 Cmd+Q 完全退出 DSH Desktop 再重新打开(launchctl setenv 只影响之后启动的进程)
想改回只走中转:launchctl unsetenv ZS_WEBDAV_URL(或设 transportMode: relay)。zspace_remove 在 WebDAV 通道下是 NAS 侧的删除语义(是否进回收站由 NAS 决定);要确保进回收站请用 transportMode: relay。| 工具 | 作用 |
|---|---|
zspace_status | 探活:当前通道(WebDAV 直连 / 云中转)、代理、账号、NAS、存储池余量、个人/公共空间根路径与条目数。其它工具报错时先跑它 |
zspace_ls | 列目录,支持 depth 递归与 limit 预算;自动分页(NAS 单页 50 条) |
zspace_stat | 单个文件/目录的元信息(大小、修改/创建时间) |
zspace_find | 按名称在目录树里查找(大小写不敏感子串),会报告扫描了多少条目、是否提前停止 |
zspace_read | 把小文本文件读进上下文(默认上限 256 KB,二进制自动识别) |
zspace_download | 从 NAS 下载到本机(默认落到 ~/Downloads/zspace) |
zspace_upload | 上传本地文件,大文件自动走分片协议,中文文件名可用 |
zspace_write | 把文本直接写到 NAS(省掉本地临时文件),默认覆盖、可传 overwrite: false 拒绝覆盖 |
zspace_mkdir | 建目录 |
zspace_rename | 就地重命名 |
zspace_move | 移动到另一个目录(服务端操作,不下载) |
zspace_copy | 服务端复制 |
zspace_remove | 删除(NAS 侧进回收站);必须显式传 confirm: true |
zspace_docker_list | 容器列表(name/state/status/id)与 running/count |
zspace_docker_inspect | 单个容器的完整配置:镜像、命令、env、挂载、端口、网络模式、重启策略。重建前先留底 |
zspace_docker_logs | 容器尾部日志(tail 默认 200);多路复用帧头已剥掉,可直接读 |
zspace_docker_op | 容器生命周期:start / stop / restart / remove / pause;remove 必须 confirm: true |
zspace_docker_health | 引擎真健康判据;verdict 见下 |
zspace_system_reboot | 整机重启(POST /system/reboot);必须 confirm: true |
这台 NAS 的 containerd 会周期性卡死(wedge),此时容器状态还显示 running,但所有启动/停止/删除都静默失效。这几个工具就是为诊断与恢复准备的:
zspace_docker_health 再动手。verdict:healthy(container_top 返回了真实进程列表,containerd 在工作)、containerd-wedged(dial unix:///run/containerd/containerd.sock: timeout,此时任何容器操作都无效)、container-not-running(探针容器没跑,container_top 根本不碰 containerd,结论不可信)、service-off、error。zspace_system_reboot(POST /system/reboot,约 7~8 分钟)。Docker 引擎重启只重启 dockerd,不动 containerd,救不了。container_op(start/stop/restart/remove/pause)是 GET,而 system_restart 与 /system/reboot 是 POST;传错一律 404 page not found。插件在客户端层固定方法,工具参数里没有 method。code 字段里。插件会把它当失败抛出,并附带下一步提示。| 写法 | 含义 |
|---|---|
省略 / "" | 个人空间根(形如 /<pool>/my/data,实际值由插件探测) |
home:相册 | 个人空间下的 相册 |
public:公共分组/skills | 公共空间下的路径(形如 /<pool>/public/...) |
docs/2026 | 相对个人空间根 |
/<pool>/my/data/x.txt | NAS 绝对路径,原样使用 |
两个根路径由插件按存储池自动探测(/<pool>/my/data、/<pool>/public),也可在配置里写死。
zspace_upload 的 localPath、zspace_download 的 dir 建议传绝对路径或 ~/…:插件跑在 DSH 宿主进程里,普通相对路径是按宿主进程的工作目录解析的(不是会话工作区)。找不到文件时的报错会把解析后的绝对路径打出来。
写在 profile 的补丁层(~/.dsh/profiles/<profile>/cordis.patch.yml)里 id: zspace 那一条的 config 下,改完热加载:
| 配置项 | 默认 | 说明 |
|---|---|---|
baseUrl | http://127.0.0.1:13579 | 桌面客户端本地代理(可用 ZS_BASE_URL 覆盖) |
configDir | 自动探测 | vuex.json 所在目录(可用 ZS_CONFIG_DIR 覆盖) |
apiVersion | 2.3.2026042401 | NAS Web API 版本号参数 |
homePath / publicPath | 空=自动探测 | 写死个人/公共空间根 |
downloadDir | 空=~/Downloads/zspace | 默认下载目录 |
transportMode | auto | 通道:auto / webdav / relay |
webdavUrl | 空=关闭 | WebDAV 地址,如 http://<nas-ip>:5005/ |
webdavUser | 空 | WebDAV 账号(NAS 账号);密码走 ZS_WEBDAV_PASSWORD |
webdavPassword | 空 | 密码兜底项,建议留空改用环境变量 |
webdavHomePath / webdavPublicPath | / / 空 | 个人/公共空间在 WebDAV 里的路径(空=公共空间不暴露) |
webdavProbeTimeoutMs | 1500 | 直连探测超时 |
readMaxBytes | 262144 | zspace_read 上限 |
writeMaxBytes | 5242880 | zspace_write 单次写入上限(更大的内容用 zspace_upload) |
listMaxEntries | 2000 | 单次列目录/树的上限 |
timeoutMs / maxRetries | 60000 / 2 | 请求超时与瞬时失败重试 |
smallUploadMaxBytes | 8388608 | 超过就用分片上传 |
sliceSize | 2097152 | 分片大小(远端模式上限 2 MB) |
promptEnabled / promptOrder | true / 60 | 是否向系统提示注入使用说明 |
vuex.json 现读 token(按 mtime 缓存),客户端退出登录即失效。zspace_remove 必须 confirm: true,且 NAS 侧进回收站,不是硬删。/file_search/file_search 在当前固件上忽略关键字(换任何关键词都返回同一批 100 项),所以 zspace_find 用的是受限目录遍历而不是该接口,结果会明确报告扫描范围;按「一个文件 = 一个能独立解释的能力」组织,完整职责表与扩展步骤见 lib/README.md:
lib/index.js 插件接线(name/inject 转发 Config + apply) lib/client/ 协议按能力拆分
lib/config.js 配置 schema、默认值、边界校验 transport URL/编码/重试/校验
lib/prompt.js 系统提示里的用法说明 spaces 探活、存储池、空间根
lib/tools.js 工具注册表(只做注册) browse/mutate 列表 / 增删改
lib/tools/*.js 19 个工具,各一个文件 upload/download 分片上传 / 流式下载
依赖是严格单向无环:index → tools → client → {errors,transport} → format/auth。加一个工具 = 新建 lib/tools/<名字>.js + 在 lib/tools.js 注册一行。
node --test test/client.test.js test/tools.test.js test/adaptor.test.js # 36 项单测/集成(mock 代理)
node scripts/live-selftest.js # 真机端到端自检(会创建并清理临时目录)
node scripts/docker-selftest.js # 真机 Docker 只读冒烟(列表/详情/日志/健康判据)
live-selftest.js 覆盖:探活 → 存储池 → 定位个人/公共空间 → 建目录 → 中文名单请求上传 → 强制多分片上传 → 详情 → 读取 → 下载并校验 sha256 → 服务端复制 → 重命名 → 遍历查找 → 移动 → 删除 → 确认消失。
本机的 zspace-nas / zspace-public-access 等 skill 依赖 zspace-cli(Python)或独立 Node 脚本;本插件把同一套协议内置进 DSH,不依赖 Python、不依赖额外命令,并且带输出 schema、错误提示与安全护栏。两者可以共存。
MIT