DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Plugin Mesh — DSH Plugin for DeepSeek Harness
← Plugins
P

dsh-plugin-mesh

Plugin Mesh

DSH LAN Mesh: Automatically discovers other DSH instances on the same subnet, provides peer operation pages, and supports bidirectional task dispatch across machines.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:peng456/dsh-plugin-mesh#b3fa9ad3198e2178ad91146d6901ccd3dced8f3f
READMECompatibilityVersions

Compatibility and provenance

Plugin Mesh is published as dsh-plugin-mesh and currently resolves to version 0.2.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/17/2026

Versions

0.2.0stable
9/17/2026

Related plugins

Loading related plugins…

Latest
0.2.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/17/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in agents-orchestration.

Headless@deepseek-ai/dsh-headlessThe dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layerExperimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profileExperimental Web profile layer for Agent Teams Remote and UI pluginsSubagent Codex@deepseek-ai/dsh-subagent-codexOne-shot Codex subagent provider over the official app-server protocolSubagent Claude Code@deepseek-ai/dsh-subagent-claude-codeOne-shot Claude Code subagent provider over the official Agent SDK

README

dsh-plugin-mesh

DSH 的局域网 Mesh 插件:启动后自动发现同一网段的其他 DSH 实例,在侧栏提供一个 操作页面显示各机器的在线状态,并支持把任务派给对端的 agent 执行。

用起来就是你要的那个效果:在 A 机器上开发,把「部署到 B」这件事丢给 agent, 你只下大命令。

零配置:固定端口 + 自动扫描 + ping,装上就能发现彼此,不需要配对码。 首次打开 Mesh 页面会让你给这台机器起个名字(默认填主机名),别的机器就靠这个名字找你。

┌──────── A 机器 (DSH) ────────┐          ┌──────── B 机器 (DSH) ────────┐
│  mesh 插件  :45917            │          │  mesh 插件  :45917            │
│   ├ UDP 组播心跳  ◀───────────┼──────────┼──▶  被动发现                  │
│   ├ 主动扫本网段  ────────────┼──────────┼──▶  兜底发现                  │
│   ├ ping 保活     ────────────┼──────────┼──▶  在线状态                  │
│   └ 侧栏 Mesh 页面            │          │                              │
│                               │───任务──▶│  唤醒本机 agent 执行          │
│                               │◀──回派───┤                              │
└───────────────────────────────┘          └──────────────────────────────┘

发现机制:两条互补的路

只靠组播是不够的 —— 很多路由器/AP 会隔离客户端组播,Windows 防火墙默认也拦入站组播。 所以这里同时用两条路,任一条通就能发现:

路径做法优点缺点
组播心跳每 5s 向 239.255.42.99:45892 广播,同时监听零配置、即时、不产生额外连接可能被路由器/防火墙挡掉
主动扫描并发 GET 本网段每台机器的 :45917/mesh/v1/health只要 TCP 通就能成,最可靠扫一次约 1~2 秒;254 个地址

再加一条ping 保活:每 10s GET 已知对端的 /mesh/v1/health,刷新在线状态。 这条让"发现"一旦建立就不再依赖组播 —— 即使组播完全不通,扫描见过一次之后也能一直维持。

扫描时机:启动时(带退避重试,因为常抢在对方启动之前)+ 每 60s 一次 + UI 上手动触发。

默认端口 45917。固定端口是"扫一下就能连上"的前提。同机跑多个实例时端口会被占用, 此时自动退回随机端口(组播仍能找到,但主动扫描扫不到它)。

组播的作用范围:比"局域网"更窄

239.255.42.99:45892 是我在私有组播段里挑的(239.0.0.0/8 是 RFC 2365 定义的 管理范围,相当于组播里的"私有地址"),TTL 设为 1,所以:

  • ✅ 同一网段(同一个二层广播域)内有效
  • ❌ 路由器不转发 —— 跨子网/VLAN 到不了,那种情况要配 scanRanges
  • ❌ AP isolation 会连它一起挡(那是把客户端之间的所有流量都隔离,不只是组播)
  • ⚠️ 部分交换机的 IGMP snooping 在没有 querier 时会丢掉组播
  • ⚠️ Windows 防火墙默认拦入站组播,要放行 UDP 45892

正因为组播有这么多坑,才加了扫描那条路:只要 TCP 通,扫描就能发现。


身份与命名

每台机器有两个标识,分工不同:

标识是什么稳定性用途
instanceId启动时随机生成的 8 字节 hex每次启动都变内部用:去重、识别"这条是我自己发的"
machineName人可读的名字,如 客厅的Mac持久保存你和 agent 用它指代这台机器

名字解析优先级:插件配置 machineName > 用户首次启动时填的 > 系统主机名。

首次启动时(还没命名过、落在主机名上)Mesh 页面会主动问你一次:输入框预填主机名, 点「就这个」直接用,或改成你想要的名字。名字存在 $DSH_HOME/mesh/state.json (和配对码同一个文件,权限 0600),改完立刻重新广播,对端不用重启就能看到。

重名怎么办

名字是人手填的,可能撞。页面会检测并告警,派发时也不会随便挑一台:

  • 从 A 看:--peer winbox 只要在 A 的上游对端里唯一就能用(自己不算)
  • 从第三台机器看:如果它发现有两台都叫 winbox,mesh_run 会拒绝并列出候选, 让你改用 <ip>:<port> 精确定位

地址也接受实例 id 或 ip:port,所以撞名时总有办法精确指定。


实测验证状态

以下都在真实 DSH host 上跑出来(临时 DSH_HOME,未动你正在用的应用):

项目结果
配置装配进 profile✅ --dump-config 含本项目两行
插件加载、apply 执行✅ 挂载 5 个 UI 接口、注册 4 个工具
两个真实 DSH 互相发现(仅扫描,组播全关)✅ 双向,24 秒内(含启动竞态重试)
两个真实 DSH 互相发现(组播开)✅ 双向,1 秒内
零配对派发任务✅ ok: true,全程没有任何配对操作
对端 agent 被唤醒✅ 建了 mesh-* 会话,17 个事件,含任务提示词 + 线程 + 回派指令,turn/start → assistant/attempt
离线判定✅ 杀掉对端后约 20 秒标记离线(ttl 20s)
固定端口被占用 → 回退✅ 配置 45919、实际 63570
requirePairing: true 时✅ 错误 token → 403;正确 token → 200
首次启动询问名字✅ 未命名时 needsName=true,输入框预填主机名
改名立刻传播✅ 改完 2 秒内对端就看到新名字(立即重新广播)
名字持久化✅ 存 state.json,重启后仍是 客厅的Mac / source=saved
名字校验✅ 空、含 /、超 32 字符均被拒
配置优先✅ 配置里写了 machineName 时改名返回 409,不静默覆盖
重名检测✅ 两端 duplicateNames 均正确列出
客户端 bundle 被提供✅ 出现在 __DSH_BOOT__,路由 200,内容与源码逐字节一致
UI 页面渲染✅ 机器列表 / 任务记录两个 tab
不花你的 token✅ 测试环境无模型密钥,agent 止步于 no API key

没验证的(如实说明):

  • 没在你正在运行的 DSH Desktop 里验证 —— 需要重启应用,会掐断本次会话。 用 dev-boot.mjs 复现了真实主进程的模块解析行为来代替。
  • Windows 侧没跑(手上没那台机器)。代码跨平台,但 Windows 防火墙要放行 TCP 45917 和 UDP 45892。
  • 扫多端口(scanPorts)是我为了在同机测试才加的,真实两机场景用不到。

安装

两台机器都装。装完必须重启 DSH Desktop 才会加载。

方式 A:一键脚本(推荐)

git clone https://github.com/peng456/dsh-plugin-mesh.git
cd dsh-plugin-mesh
./install.sh

脚本做两件事,且可重复执行(已装就跳过):

  1. 把插件复制到 ~/.dsh/profiles/desktop/node_modules/dsh-plugin-mesh/
  2. 把它加进该 profile package.json 的 dsh.profile.bundles (改前自动备份为 package.json.bak)

常用选项:

./install.sh --dry-run              # 只打印会做什么,不落盘
./install.sh --profile web          # 装到别的 profile
./install.sh --home /path/to/.dsh   # 指定 DSH_HOME
./install.sh --uninstall            # 卸载(删目录 + 从 bundles 移除)

方式 B:手动装

# macOS
cp -R dsh-plugin-mesh ~/.dsh/profiles/desktop/node_modules/dsh-plugin-mesh

# Windows (PowerShell)
Copy-Item -Recurse dsh-plugin-mesh "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-plugin-mesh"

然后在 ~/.dsh/profiles/desktop/package.json 的 bundles 里加上 "dsh-plugin-mesh":

{
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-plugin-mesh"],
      "patchReload": "live"
    }
  }
}

⚠️ 必须是真实目录,不能是软链。 DSH 的 profile 包解析器会拒绝 realpath 落在 <profile>/node_modules 之外的包(module-resolution-*.js 里那条判断, 目的是防止陈旧的外部状态覆盖已封装安装)。把插件软链到你的工作目录会在启动时 报 ERR_MODULE_NOT_FOUND。install.sh 已经处理好了这一点。

方式 C:官方命令(用 DSH Desktop 自带的终端)

托盘/菜单 → 终端:

dsh plugin add /path/to/dsh-plugin-mesh

注意 dsh plugin --profile desktop 在普通终端里会被拒绝 (bin.js:29:profile "desktop" is managed exclusively by the Electron application), 必须用应用自带的那个终端。

Windows 防火墙

New-NetFirewallRule -DisplayName "DSH Mesh" -Direction Inbound -Protocol TCP -LocalPort 45917 -Action Allow
New-NetFirewallRule -DisplayName "DSH Mesh (multicast)" -Direction Inbound -Protocol UDP -LocalPort 45892 -Action Allow

只放行 TCP 也行 —— 那时靠主动扫描发现,不依赖组播。

使用

侧栏会出现一个 Mesh 图标(三个节点连成的网状),点开是主页面:

  • 本机信息:机器名、地址、端口、当前发现方式与配对要求
  • 发现的机器:每台一行,在线绿点/离线灰点,显示地址、系统、用户、最后心跳; 每行「探测」和「派发任务」
  • 扫描本网段 / 重新广播 按钮
  • 派发任务:选目标机器 → 填任务 → 派发
  • 任务记录:收到 / 派出的任务
  • 配对码(折叠,默认不需要)

agent 多出四个工具:

工具作用
mesh_peers列出发现的机器
mesh_scan主动扫本网段,找还没发现的机器
mesh_run把任务派给某台机器的 agent(异步)
mesh_tasks查看收到/派出的任务记录

所以你可以直接说:

「看看局域网里有哪些机器,然后让 B 把 web 服务重新部署一下,跑完告诉我。」


工作原理

唤醒:自包含实现,不依赖额外插件

agent 没有事件循环,只在有回合时才思考。所以收到对端任务后,必须建一个会话并让它跑起来。

DSH 提供了官方插件 @deepseek-ai/dsh-webhook 做这件事,但本插件没有用它,理由:

  1. 它不在任何默认 bundle 里,靠补丁替用户插一行,会让"装一个插件"变成配置里两行,困惑
  2. 更实际的问题:万一它已经被启用(比如你以后装了 GitHub webhook 插件), cordis 的 provide 遇到重名会直接抛错(service "webhookRuntime" has been registered at <...>), 而且那是在它的构造函数里,本插件的安全网拦不住

所以这里按官方 createWebhookSession 的做法自己走一遍,用到的都是 DSH 基础服务 (桌面 profile 本来就全都有):

ctx.permissionPresets.resolve / set      校验并设置权限 preset
ctx.agentPresets.resolve / mount         解析并挂载 agent preset
ctx.workspaceRegistry.create             建/取工作区
ctx.agents.create                        建 Agent
ctx.sessionTitle.rename                  给会话起名
ctx.agentDefaultModel.currentSelection   取默认 provider/model
agent.followup(createUserMessage(...))   ← 这一步才是"唤醒"

服务齐备时才启用(用 ctx.inject([...]) 探测);缺任何一个就降级为"只收件不唤醒", 并在日志里说明缺了什么。插件是自包含的,profile 里只多一行。

为什么发现要两条路

我先只做了组播,后来加扫描,是因为组播在真实家庭网络里失败率比想象中高: AP isolation、Windows 防火墙默认策略、跨 VLAN,任何一个都能让它静默失效。 而"TCP 直连固定端口"只要网络通就能成。


配置项

默认已经可用。要改就在 profile 的 cordis.patch.yml 里按 id 覆盖 (注意:patch 是整体替换 config,所以要把想保留的项一起写上):

- id: mesh
  config:
    machineName: ''            # 对端列表里的名字,留空用主机名
    port: 45917                # 固定端口
    useMulticast: true         # 组播被动发现
    scanOnStart: true          # 启动扫描(带退避重试)
    scanIntervalMs: 60000      # 周期扫描;0 = 关闭
    scanRanges: []             # 额外网段,如 ["192.168.1.0/24"];空则扫本机 /24
    scanPorts: []              # 除本机端口外额外要扫的端口
    scanConcurrency: 64
    scanTimeoutMs: 800
    pingIntervalMs: 10000      # ping 保活;0 = 关闭
    announceIntervalMs: 5000
    peerTtlMs: 20000           # 多久没消息算离线
    requirePairing: false      # 见下
    agentPreset: standard
    permissionPreset: workspace-write
    workspaceRoot: ''

安全

默认不需要配对 —— 同一内网里任何发现到本机的 DSH 都能派发任务。 对本机 agent 而言,这些任务会被当成一条用户消息(默认权限 workspace-write: 能读写工作区、能执行命令)。

这在自己家的可信内网里是合理取舍,也正是你要的"零配置"。但如果你在 不完全可信的网络里(合租、公司、宿舍、有访客设备、IoT 设备多),请打开:

- id: mesh
  config:
    requirePairing: true

然后在两台机器的 Mesh 页面里互相对一下配对码(首次启动自动生成,页面上可直接复制)。 打开后所有控制接口都要过配对码,用 timingSafeEqual 比较。

其他:

  • 发现是公开的:同一网段任何人都能看见机器名、地址、系统、用户名。这是有意的取舍。
  • 明文 HTTP:局域网内可接受;跨不可信网络请套 SSH 隧道或 TLS 反代。

已知限制

  1. 每次派发新建一个会话,不续接原对话。
  2. 去重只在进程生命周期内(内存),重启后同 id 会重复入箱。
  3. 没有离线排队:对端离线时 mesh_run 直接失败,不暂存重投。 (要这个能力可以用工作区里的 lanmsg.py。)
  4. 同机多实例:第二个实例端口被占会退回随机端口,主动扫描扫不到它(组播仍能发现)。 真要同机多实例,给它们配不同 port 和对方的 scanPorts。
  5. sidebar.panellist 槽位官方插件没人用过(翻遍 58 个客户端 bundle,只有官方侧栏 自己声明它)。我按源码契约接的,实测注册和渲染都正常,但不如 sidebar.footer.action 那样有第三方先例。

开发与测试

# 搭隔离环境(把插件真实复制进 profile,不碰你的 desktop profile)
MACHINE=macbox PORT=45917 MULTICAST=false SCAN_PORTS="[45918]" \
  ./dev-setup.sh meshtest /tmp/mesh-dsh

# 启动(dev-boot.mjs 复现真实主进程的模块解析行为)
DSH_HOME=/tmp/mesh-dsh ELECTRON_RUN_AS_NODE=1 \
  "/Applications/DSH Desktop 2.app/Contents/MacOS/DSH Desktop" \
  dev-boot.mjs --profile meshtest --port 8877

dev-setup.sh 支持的环境变量:MACHINE PORT MULTICAST SCAN_ON_START SCAN_PORTS PING_INTERVAL_MS REQUIRE_PAIRING。

为什么需要 dev-boot.mjs:desktop-cli.js:78 只在 app.asar 内才安装 profile 包解析器,而这个安装是未打包的 Resources/app。真实 Electron 主进程 (main.js:4478)是无条件安装的,所以真实应用没这个问题,只有 CLI 路径有。

发现模块可以脱离 DSH 单独测:

node lib/_selftest-discovery.mjs alpha 45900 9000   # 两个进程同时跑可验证互相发现

文件结构

dsh-plugin-mesh/
├── package.json           # dsh.bundle.patch + dsh.client 声明
├── cordis.patch.yml       # 只插入本插件(含默认配置)
├── lib/
│   ├── index.js           # 主机侧:发现编排 + 对端 HTTP + agent 工具 + UI 接口 + 入站唤醒
│   ├── discovery.js       # UDP 组播被动发现 + 对端注册表 + 过期清理
│   ├── scan.js            # 主动扫描(固定端口 + CIDR 展开)
│   └── _selftest-discovery.mjs
├── client/
│   └── client.js          # 浏览器侧:手写 bundle,无需打包工具
├── dev-setup.sh           # 隔离测试环境搭建
├── dev-boot.mjs           # 带模块解析器的测试启动器
└── README.md