CHENGXIAO
mypanda-hash/chengxiao
Verbindet zwei DeepSeek-Harness-Rechner mit einem Einmalcode – direkt im LAN oder über Netzwerke hinweg durch einen Ende-zu-Ende-verschlüsselten Relay mit konfigurationsfreiem offiziellen Standard –, sodass ein Agent Aufgaben auf dem anderen ausführen und Dateien austauschen kann, während jede Maschine ihre eigenen Dateien an Ort und Stelle behält.
Installation
dsh plugin --profile web add github:mypanda-hash/chengxiaoREADME
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
Ähnliche Plugins
dsh-web (dsh-ssh)
zhu1090093659/dsh-web
dsh-web (dsh-remote-web-ui)
zhu1090093659/dsh-web
dsh-web-ui (dsh-ssh)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-remote-web-ui)
zhu1090093659/dsh-web-ui