CHENGXIAO
Manifest valid★ 3Pairs two DeepSeek Harness machines over a local network with a one-time code, so one agent can run tasks and exchange files on the other while each machine keeps its own files in place.
dsh-peer-mcp
用得顺手就点个 Star —— 市场搜索按星排序,一颗星直接决定别人能不能搜到它。
让两台电脑上的 DSH 互相干活、互相传文件 —— 而各自的文件始终留在本机。
不再用截图 + 模拟键盘去驱动另一台机器。装好这个插件后,A 机的 agent 可以把 B 机当成 工具来调:B 机用自己本地的文件、工具和模型执行任务,只把结论和文件回传。
┌─ A 机 ─────────────────────┐ ┌─ B 机 ──────────────────────┐
│ DSH │ │ 文件/仓库都在本地,不搬家 │
│ └ MCP 客户端 ─────────────┼── HTTPS ─┼─▶ dsh-peer-mcp │
│ mcp__<对端名>__ask │ 凭据 │ ├ ask → 本地 DSH │
│ mcp__<对端名>__fetch_file│ │ ├ fetch_file → 读本地 │
│ mcp__<对端名>__send_file │ │ └ send_file → 收文件 │
└────────────────────────────┘ └─────────────────────────────┘
安装
dsh plugin --profile <你的 profile> add github:MyPanda-Hash/CHENGXIAO
这一条命令就够了:它会把插件装进 profile 的 node_modules/,并自动注册到
dsh.profile.bundles(你可以打开 profile 的 package.json 确认)。
装完后安装本身不会对外暴露任何东西 —— 插件自带的 cordis.patch.yml 里 listen 默认是
false,必须由操作者显式开启。
快速开始(推荐:官方中继,装完即用)
两台电脑任何网络(同一局域网、不同网络均可)走官方中继,不需要 Tailscale、 不需要入站端口、不需要碰防火墙和路由器:
-
两台机器都在 profile 覆盖层(
~/.dsh/profiles/<你的 profile>/cordis.patch.yml) 写入并重启 DSH:- id: dsh-peer-mcp config: relayEnabled: true就这三行——不填
relayUrl时自动使用官方公共中继。 -
干活端
设置 → 设备互联,确认「共享工作区」(默认%USERPROFILE%\DSH Workspace) 与能力权限摘要。 -
点「生成配对码」,链接形如
dshr://<中继>/<设备ID>/XXXXX-XXXXX,交给发起端粘贴。 -
配对完成,发起端立即多出
mcp__<干活端名>__ask/__submit_task/__fetch_file等工具——同一局域网时可改走直连(见下节),其余场景全部经中继。
官方中继(http://8.134.255.221:7332):一台阿里云 Ubuntu 上的常驻 systemd 服务,
只转发端到端加密信封——不持有密钥、不落盘、GET /health 可随时探活。不信任它或需要
内网封闭时,换成自托管中继(改一行 relayUrl),协议与体验完全一致。
局域网直连(可选,延迟更低)
两台机器在同一个局域网时可以把 listen 配成 true 走直连(同时保留中继做兜底),
其余流程不变;细节见下文「配置」。
中继(自托管与运维)
中继模式:双方都主动出站连接同一台中继服务器,不需要任何入站端口、端口映射或 防火墙配置。中继只转发端到端加密的信封,看不到配对码、凭据、任务内容或文件明文, 也不落盘。
- 默认 = 官方中继(上一节),零配置。
- 自托管:任一台公网可达的机器上
docker compose -f docker-compose.relay.yml up -d(或DSH_RELAY_HOST=0.0.0.0 node src/relay-server-bin.js),生产建议前置 TLS 反代; 两台机器的配置里加relayUrl: 'https://relay.example.com'指向它即可。
加密方式:配对时双方做一次性 X25519 密钥交换,配对应答(含长期凭据)与后续所有消息 都用派生的会话密钥做 AES-256-GCM 加密;中继转发的永远是密文,配对码本身不经过中继。 直连和中继可以共存:同一台机器开监听时局域网内仍走直连。
运维:中继提供 GET /health(返回 ok、运行秒数、注册设备数,无任何身份信息);
DSH_RELAY_OFFLINE_TTL_MS 可选开启内存离线驻留(设备未注册时信封暂存至其上线,
上限 24 小时,官方中继设为 5 分钟)。无数据库模式是唯一模式——协议里所有流程都是双方
在线的请求/响应,持久化存储(PostgreSQL 之类)待出现多实例需求再议。
配置
配置写在 profile 的 patch 层(~/.dsh/profiles/<profile>/cordis.patch.yml),
不要改插件包里的文件 —— 那个文件属于插件,升级时会被覆盖。加一条 id 定向覆盖即可:
- id: dsh-peer-mcp
config:
listen: true # 本机对外监听,对端才能配对
host: 0.0.0.0
port: 7331
allowedDirs: # 对端被允许进入的绝对目录
- 'C:\Users\你的用户名\DSH Workspace'
taskTimeoutMs: 600000
listen: true 时 allowedDirs 必须至少给一个绝对目录 —— schema 会拒绝一个
"没边界的监听口"。改完重启 DSH 生效。
不配 allowedDirs 时使用默认共享工作区 %USERPROFILE%\DSH Workspace
(POSIX 为 $HOME/DSH Workspace),不会把整个用户目录放进白名单。设置页里保存的
共享工作区立即生效并自动迁移旧配置,不需要重启。
独立 worker(两端都不开 DSH)
配合上面的 CLI,被驱动的一端也可以不开 DSH:仓库根目录的 worker.mjs 是一个
纯 node 的独立 worker——与插件共享 ~/.dsh(同一份信任库,已配对的凭据直接可用),
任务经 dsh --profile headless 命令行执行(不需要 Desktop 界面)。
node worker.mjs --port 7331 --dirs "D:\repos" # 监听模式(占 7331 前先停 DSH 或换端口)
node worker.mjs --relay # 中继模式,零入站端口
node worker.mjs --with-ticket ... # 启动即打印配对链接
node worker.mjs --ticket / --status # 单独发码 / 看状态
常驻部署(实测有效的关键点):
- 用计划任务拉起(
schtasks /sc onlogon或 NSSM 服务)——从 DSH 会话里Start-Process的进程会随 agent 回合结束被杀(实测两次);计划任务环境注意 PATH 里可能没有dsh, 启动脚本需自行定位dsh.cmd。 - 防火墙规则按程序放行:DSH Desktop 有规则不代表 node.exe 有——独立 worker 换端口时
要单独
New-NetFirewallRule放行该端口。 - 独立 worker 必须用真实
~/.dsh运行(DSH_HOME重定向会破坏派生 agent 的凭据继承, 实测报MISSING_CREDENTIAL)。 - 服务器广播的配对地址可能是内网 IP(如云主机 VPC 网段),跨网配对时把链接里的地址换成 可达地址即可——配对码本身不受影响。
实测(2026-09-24):Windows Server 2022 云主机,DSH Desktop 完全关闭,仅
schtasks 拉起的 node worker 监听 7333——配对、ask 真实回合、凭据解析全部正常。
命令行直控(本机不开 DSH)
配对过一次之后,凭据持久化在 ~/.dsh——本机不需要打开 DSH 就能操作对端
(对端机器的 DSH 需在运行)。仓库根目录的 peer.cmd(或直接
node scripts/peer.mjs):
peer status # 对端、地址、远端工具面
peer ls # 列对端目录(首次带目录参数,之后记住)
peer ask "重启 nginx 并报告状态" # 在对端跑任务
peer read D:\logs\app.log # 直读对端文件(≤5MiB)
peer pull D:\logs\big.zip C:\local\ # 分片拉取大文件(sha256 校验)
peer push C:\local\report.pdf # 分片推送到对端 staging
首次 ask/ls 用 --cwd 指定对端白名单内目录后会记住(存
~/.dsh/peer-cli.json),之后零参数使用。
配对(一次性码)
两种方式,任选其一。
用设置页(推荐)
设置 → 设备互联,一个页面做完三件事:
| 区域 | 能做什么 |
|---|---|
| 本机监听 | 看是否在监听、监听地址、待用配对码的到期时间(只读 —— 开关属配置,改 profile 后重启生效) |
| 共享工作区 | 查看/修改对端可访问的目录(默认 DSH Workspace),并核对能力型权限摘要 |
| 发配对码 | 选权限档位 → 生成 → 大号等宽字体显示短码,可选中可复制,附完整 dshp:// 链接 |
| 连接另一台机器 | 粘贴对方给的链接 → 配对;配对成功后列出「本机可调用的对端」 |
| 被允许驱动本机的机器 | 列出每台对端及其权限档位,一键撤销 |
配对码既可以整段 dshp://… 链接转交,也可以只把短码(XXXXX-XXXXX 部分)读给操作者,
由操作者在发起端粘贴完整链接时补上(或直接转交整段链接)。短码是同一配对码的
可读形式,不产生第二个秘密;发起端真正需要的是包含地址的完整链接。
这个页面存在的原因是:把一次性码通过模型转述给人既绕又慢。它调的是插件自己的 routes
(/plugins/dsh-peer-mcp/*),只服务 loopback,且状态读取永不返回码或凭据。
用 agent 工具
- 在 B 机让 agent 调
peer_ticket,或直接跑一次工具,拿到形如dshp://10.60.31.127:7331/C7K2M-9QWMP的链接。 - 在 A 机让 agent 调
peer_pair,把链接贴进去。 - 成功后 A 机多出
mcp__<B机名>__ask等工具,立即可用(无需重启)。
配对码一次性、默认 15 分钟有效、消费即废。它只是一次握手的通行证;握手后换发 长期凭据,磁盘上只存它的 sha256。
agent 能做什么,不能做什么
| 工具 | 作用 |
|---|---|
peer_status | 报告监听状态、对端地址、待配对码到期时间、双向机器列表、共享工作区和能力权限(不含任何秘密) |
peer_ticket | 申请一次性配对码转交给人;监听未开时拒绝并说明要人去开启 |
peer_pair | 贴入 dshp:// 链接完成配对 |
peer_revoke | 撤销某个对端的访问权(立即生效,记录留存可审计) |
四个工具里没有任何一个能打开监听口或放宽权限。 是否对外暴露只能改配置 ——
这一条有测试盯着(加个叫 peer_listen 的工具就会红)。
对端侧(被驱动的机器)提供十五个工具:同步兼容入口 ask、异步任务 submit_task /
task_status / task_events / task_result / cancel_task、整文件 fetch_file / send_file,
以及分片传输 open_read / read_chunk / close_read / send_begin / send_chunk /
send_finish / send_cancel。
异步任务
长任务推荐走异步流程:提交立即返回 taskId,不占住调用方当前回合:
submit_task(prompt, cwd?, timeoutMs?, idempotencyKey?) → { taskId, status }
├─ task_status(taskId) → queued | running | completed | failed | cancelled | expired
├─ task_events(taskId, cursor?) → 生命周期事件 + nextCursor(增量读取)
├─ task_result(taskId) → 终态结果(与 ask 同形状);运行中返回 task-not-terminal
└─ cancel_task(taskId) → 取消排队中(跳过不执行)或运行中(击杀进程)的任务
要点:
- 状态在执行任务的设备上:调用方断线重连后凭
taskId继续查询;中继转发请求但不持有任务状态。 - 幂等:同一
idempotencyKey重复提交返回同一任务,网络重试不会重复执行。 - 保留期:终态结果默认保留 24 小时,之后标记
expired并释放结果内容。 - 并发:每台 worker 默认同时运行 1 个任务(一个完整 agent 回合),后续排队。
- 兼容:
ask保留原形状与超时语义——内部提交异步任务、等待终态、返回原有结果;旧调用方零迁移。
事件是生命周期事件(submitted / started / completed / failed / cancelled / expired),
不伪造百分比进度。
分片文件传输
fetch_file / send_file(整文件、≤5 MiB)保留不变;更大的文件走分片通道:
- worker 侧工具:
open_read打开一个读会话(返回大小、整文件 SHA-256、块几何),read_chunk任意顺序、可重复读(这就是断点续传),close_read释放;send_begin/send_chunk/send_finish/send_cancel组装对端文件—— 每块带摘要校验、按块序号幂等(重发不重写)、整文件校验通过后原子落进 staging, 绝不覆盖同名文件。会话按对端隔离,空闲 10 分钟自动回收;单文件上限 100 MiB;默认块 1 MiB。 - 程序化驱动(推荐,模型不适合逐块搬运):发起端 service 提供
fetchPeerFile(name, remotePath, localPath)与sendPeerFile(name, localPath), 内部经对端 MCP 端点(直连地址或中继回环代理,配对时选了哪条路就走哪条)驱动分片循环, 逐块校验、链路抖动自动重试(每块 3 次)、本地同样临时文件 + 原子落盘不覆盖。 - 直连优先:连接选择沿用既有行为——有直连用直连,中继兜底;两条路径的传输语义完全一致。
// 发起端示例(service 上):
const landed = await service.fetchPeerFile('desk', 'D:\\shared\\dataset.bin', 'C:\\local\\copy.bin', {
onProgress: ({ received, totalChunks }) => console.log(`${received}/${totalChunks}`),
});
安全模型
| 概念 | 含义 |
|---|---|
| 配对码 | 一次性、短时,只用于一次握手。泄露也只值一次配对 |
| 对端凭据 | 长期密钥,磁盘只存 sha256,明文仅在配对那一刻返回一次 |
| 信任表 | $DSH_HOME/dsh-peer/trust.json:对端身份、公钥、权限档位、撤销时间 |
| 目录白名单 | 对端的 ask / fetch_file 只能进入配置的绝对目录,按路径分量比较;未配置时默认是用户目录下的 DSH Workspace |
| 权限档位 | 每个对端一个 workspace-write(默认)或 danger-full-access,由发码方授予,对端不能自选 |
| 能力权限 | 设置页展示的能力摘要:读取/写入工作区、执行任务、传输文件默认允许;系统命令、工作区外访问、修改 DSH 配置默认禁止 |
关于"提权":插件不能改变权限级别 —— 它运行在 DSH 进程内。可配置的是 每个对端的权限档位,语义是"允许对端在你机器的什么范围内干活"。
send_file 收到的文件落在 $DSH_HOME/dsh-peer/incoming/,名称压成 basename,
调用方无法指定落点、不会覆盖同名文件,且写入前校验 sha256。
实测数据
直连基线(2026-09-23)
在一台 Windows 机器上用两个 DSH 实例实跑(局域网直连路径):
| 项 | 实测 |
|---|---|
| 发码 → 配对 → 挂载 | mounted: true;配对前工具不存在,配对后立即可用 |
| 一次完整跨实例任务 | 10,328 ms(含完整 agent 回合:枚举目录 + 算字节 + 推理 + 自校验) |
| 结果精确性 | 文件数 3、字节 22/75/11 全部匹配 |
fetch_file → send_file | SHA256 双向一致,落盘逐字节相同 |
| 白名单负向测试 | 白名单外路径被拒(path-not-allowed),不是静默返回 |
全链路(中继 + 异步任务 + 分片传输,2026-09-24)
同一台 Windows 机器上的两个完全隔离 service 实例(独立身份与信任库)经 Docker 容器中继(仓库镜像,独立网络命名空间)跑通全部新链路。执行器为真实 子进程、固定 8 秒应答(与真实 agent 回合同量级),以剥离模型推理的随机性、 单独度量协议栈开销;全部数值为真实墙钟时间,字节一致性校验通过:
| 环节 | 耗时 | 备注 |
|---|---|---|
| service 启动 + 中继注册 | 71 / 11 ms | 双端各一次出站注册 |
生成 dshr 配对码 | 3 ms | |
| 经中继配对(X25519 握手 + 密封应答) | 108 ms | 中继全程只见密文 |
ask(同步兼容入口) | 8,192 ms | 8s 任务本体 + 约 190 ms 全链路往返开销 |
submit_task(异步提交) | 59 ms | 立即返回,调用方回合不被占用 |
submit_task → 轮询至结果就绪 | 8,343 ms | 任务本体占绝对大头 |
cancel_task(击杀运行中子进程) | 60 ms | |
fetchPeerFile(12 MiB 分片拉取) | 1,844 ms | 6.5 MiB/s,12 块 |
sendPeerFile(12 MiB 分片推送) | 1,919 ms | 6.3 MiB/s |
fetch_file(4 MiB 整文件,对照) | 400 ms | 旧通道走同一中继路径 |
环境与复现:win32 10.0.26340、node v20.19.5、中继 =
dsh-peer-relay容器。 本表为同机双实例 + 容器化中继的协议开销度量(网络跳为本机容器 NAT,不含真实 广域网往返);跨真机/VPS 复现用同一脚本:docker compose -f docker-compose.relay.yml up -d # 在 VPS 上 node scripts/measure-full-chain.mjs --relay http://<VPS>:7332 --mib 12
真实跨网实测(Windows 本机 ↔ 阿里云 VPS,2026-09-24)
发起端 = Windows 家庭宽带(win11/node 20.19),worker 与中继 = 同一台阿里云 Ubuntu 22.04 ECS(按流量计费,node 20.20),公网往返真实走互联网。执行器同为真实子进程(8s 应答), 拉取方向本地逐字节校验、推送方向经 worker 侧摘要门禁落盘,均通过:
| 环节 | 耗时 | 备注 |
|---|---|---|
| 经公网中继配对(X25519 握手 + 密封应答) | 119 ms | 含全部真实 WAN 往返 |
ask(同步) | 8,197 ms | 8s 任务 + ~197 ms 跨网往返开销 |
submit_task(异步提交) | 85 ms | |
cancel_task | 105 ms | |
fetchPeerFile 12 MiB 分片拉取 | 2,389 ms | 5.0 MiB/s(~42 Mbps,受本机下行) |
sendPeerFile 12 MiB 分片推送 | 4,453 ms | 2.7 MiB/s(~22 Mbps,家庭宽带上行典型不对称) |
fetch_file 4 MiB 整文件对照 | 548 ms |
复现(真双机):VPS 上 node scripts/measure-worker.mjs --relay http://127.0.0.1:7332 --link-out worker-info.json
- 中继同机;发起机把链接中的中继地址换成公网 IP 后
node scripts/measure-full-chain.mjs --pair-info worker-info.json --relay http://<VPS>:7332。
关于延迟:ask 付的是一次完整 agent 回合的代价(独立适配器直测简单问答约 4.3 s,
第二次 3.8 s —— 固定开销,不随次数变快)。适合"让另一台机器干活并拿结论",
不适合高频细粒度往返;长任务用 submit_task 异步提交(约 60 ms 返回),大文件走
分片通道(实测 6 MiB/s 量级,经中继端到端加密)。
限制
- 每次
ask都是冷启动,且无跨调用记忆(每次dsh --profile headless都是新会话)。 要常驻会话需改走--profile sdk,尚未实现。 - 同步入口
ask仍会等到任务完成:长任务要避免占住回合请用submit_task异步流程 (提交立即返回taskId,凭它查状态/事件/结果、随时取消);两个入口跑的是同一套任务机制。 - 文件走 base64 + JSON:整文件工具默认上限 5 MiB;更大的文件用分片通道 (见「分片文件传输」,单文件上限 100 MiB,逐块校验、断点续传)。
- 局域网直连或自托管中继:直连跨 NAT 不通,需部署中继(见「跨网络:中继模式」)或组网。
- Windows 上
dsh是.cmd外壳,Node 拒绝直接 spawn。插件会自动解析成真实可执行文件; 若解析失败,启动日志会明确说明,ask也会给出可行动的报错而不是ENOENT。
验证
node --test test/ # 259 个测试,不联网、不调用模型
node scripts/verify-host-load.mjs # 用真实 Cordis 上下文跑一遍 apply()
node scripts/verify-host-load.mjs --profile desktop # 验证已安装副本
node scripts/prepare-release.mjs # 产出干净发布树(并断言没有 node_modules)
test/mount-contract.test.js用真实 Cordis 验证挂载契约,不是替身test/plugin.test.js比对已安装副本与源码,防止"测试全绿、宿主加载旧代码"
独立适配器(可选)
不起 DSH 也能把一台机器变成"干活端":
.\start-peer.ps1 -AllowedDirs "D:\repos" -Host 0.0.0.0
或用环境变量直接跑 node src/bin.js(见 src/config.js 的配置项表)。
License
MIT
Comments
Loading…
Similar plugins
by tonytanglab
Delegate long-running work to DeepSeek Harness from any MCP agent—and monitor it to completion.
★ 2
↓ 245/wk
MIT
TypeScript
Sep 27, 2026
dsh plugin --profile web add harness-relay-mcpby FYL1025
DeepSeek Harness (DSH) 远程工作区插件:通过 SSH 连接一台或多台服务器,直接在 DSH 的 Web 界面里浏览文件、编辑代码、执行命令——体验类似 VS Code Remote-SSH,无需离开对话。
★ 3
MIT
JavaScript
Aug 16, 2026
dsh plugin --profile web add dsh-remote-workspaceby lifecoder1988
DevSpace nodes and remote-directory mirror Workspaces for the DeepSeek Harness: manage N MCP endpoints, adopt a remote directory as a local Workspace, and move files both ways
★ 0
MIT
JavaScript
Sep 18, 2026
dsh plugin --profile web add @local/dsh-devspaceby songofhawk
Multi-machine, multi-agent orchestration and control plane for DSH: discovers Agents and workspaces across devices, routes tasks by machine, repository, capability, and load to local or remote Agent r
★ 3
↓ 99/wk
JavaScript
Sep 29, 2026
dsh plugin --profile web add dsh-alphaby donoteatme
Browser-first, LAN-only access to the current DeepSeek Harness Web UI with one-time QR pairing, revocable devices, event-driven diagnostics, and a slot-preserving mobile layout; no companion app, clou
★ 1
↓ 182/wk
MIT
TypeScript
Sep 12, 2026
dsh plugin --profile web add dsh-local-linkby limuyang2
Multi-agent team collaboration for DeepSeek Harness, with independent models, skills, MCP tools, contexts, and a shared workspace.
★ 39
MIT
TypeScript
Aug 26, 2026
dsh plugin --profile web add @limuyang2/dsh-agent-team