🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

跨实例互通 Chinesezjc/dsh-interconnect

DeepSeek Harnessv0.13.0
Chinesezjc12 天前有提交已提供中文文档扫描:含敏感能力

跨实例消息互通与事件通知插件,用于 DeepSeek Harness DSH。

48.1/100
综合分
36
GitHub 星标
694
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-interconnect
npm 源 · dsh-interconnect 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · security
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 12 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-interconnect @ 0.13.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/29 22:40:55

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件
查看扫描证据(共 1 处,展示前 1 条)
  • 读取本地文件
    lib/skill-interconnect/index.js:29
    content: await readFile(SKILL_BODY_URL, "utf8")
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-loader@deepseek-ai/schemastery@deepseek-ai/dsh-agent@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-credentials@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-subagent@deepseek-ai/dsh-typert-protocol@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 跨实例消息传递
  • 事件通知
  • 互联服务与工具

DSH 跨实例消息与事件传递插件(互联服务 + 工具)

README

由 DeepSeek 最新模型翻译生成
dsh-interconnect 跨实例消息互通与事件通知插件,用于 DeepSeek Harness (DSH)。 让一个 DSH 实例能向同一个实例、另一台机器、或另一台机器上的别的 DSH 实例发送消息、探测活性,并在实例之间双向推送事件。 项目状态(2026-09-16):本仓库是该插件的树外(out-of-tree)主源。并入 DSH monorepo 的计划(PR #3243)已按「保持树外」的评审意见关闭;插件继续经 npm 分发(dsh-interconnect),并由团队内部的插件集合仓以 git submodule 引用本仓库。 包含三个插件 interconnect —— host 服务(ctx.interconnect): - 全走持久 WebSocket 链接:跨实例、跨机器投递消息、枚举 live session、探测活性(send/reply/ping/list 经 /interconnect/link 的 msg/query 帧) - /interconnect/link WebSocket 端点:双向实时事件推流,含心跳与指数退避重连;也承载 send/reply 消息(msg/msg-result 帧)。
展开完整文档(README 剩余 1 节)
dsh-interconnect

跨实例消息互通与事件通知插件,用于 DeepSeek Harness (DSH)。
让一个 DSH 实例能向同一个实例、另一台机器、或另一台机器上的别的 DSH 实例发送消息、探测活性,并在实例之间双向推送事件。

项目状态(2026-09-16):本仓库是该插件的树外(out-of-tree)主源。并入 DSH monorepo 的计划(PR #3243)已按「保持树外」的评审意见关闭;插件继续经 npm 分发(dsh-interconnect),并由团队内部的插件集合仓以 git submodule 引用本仓库。

包含三个插件

interconnect —— host 服务(ctx.interconnect):

- 全走持久 WebSocket 链接:跨实例、跨机器投递消息、枚举 live session、探测活性(send/reply/ping/list 经 /interconnect/link 的 msg/query 帧)
- /interconnect/link WebSocket 端点:双向实时事件推流,含心跳与指数退避重连;也承载 send/reply 消息(msg/msg-result 帧)。0.9 起没有 HTTP 端点,也没有 HTTP 回退
- 事件 fan-out 只在 WebSocket 链路上;入站事件以 interconnect/event 发出
- 共享密钥鉴权(DSH_INTERCONNECT_TOKEN,bearer,fail-closed,timing-safe 比较)

tool-interconnect —— 模型可见工具:

- interconnect_peers:列出本实例已配置的对端及其拨号链路状态(up/down),用于在不知道 peer id 时先看有哪些可用目标,也是区分「没配这个 peer」与「配了但链路不通」的唯一入口
- interconnect_send:向对端实例的指定 session 投递消息;默认唤醒没有 live agent 的持久 session(resume: false 关闭),可选 delivery 选投递模式
- interconnect_list:列出对端实例的 live session(id + 标题 + 状态),用于在不预先知道 session id 时寻址
- interconnect_ping:探测对端实例活性与身份
- interconnect_reply:向记录过的发送方回传消息,只需文本;回信 session 是本 agent 自己的,无需再次寻址

skill-interconnect —— 配套 skill:

- 向模型注册 dsh-interconnect skill,说明 peers/list/ping/send/reply 的完整用法、投递模式、resume 唤醒语义与失败处理。
- 明确告知模型:interconnect_send 会自动注入发送方的 instanceId 和 sessionId,接收方凭记录的 sender 即可用 interconnect_reply 回信,不需要手工传地址。
- 依赖 interconnect 服务,只有传输层存在时才注册进 ctx.skills。

用法

寻址(0.9 起用 instanceId,全走持久链接)

从 0.9 起,传输只走 WebSocket 持久链接,不再有 HTTP 端点,寻址参数从 baseUrl 改为 instanceId:

- interconnect_send(instanceId="peer", sessionId=..., text=...)
- interconnect_ping(instanceId="peer")
- interconnect_list(instanceId="peer")
- interconnect_peers()(不接受参数;返回本实例配置的全部对端及其链路状态)
- interconnect_reply(text=...)(只需文本;回信 session 是本 agent 自己的,目标从记录的 sender 解析)

instanceId 是 interconnect 行 peers 映射里的键;真正用来拨号的 origin 由该映射的值给出(例如隧道端点 http://127.0.0.1:13080),instanceId 本身从不出现在线上,也不参与路由——origin 才是唯一的拨号依据。

对端没配在这里时,send/reply 返回 peer-not-configured,ping/list 则在返回 reachable: false 的同时带上 configured: false——这一支重试永远不会成功,只能去补 peers 映射。配了但链路不通是另一支:链路断或两端 token 不一致时返回 unreachable (configured: true),重连成功后就可能通(无 HTTP 回退)。

interconnect_peers 就是这两支的判据来源,输出每行一个对端:

peer-a http://127.0.0.1:13080 [up]
peer-b http://127.0.0.1:13081 [down]

up/down 是拨号链路当前是否可用;down 不代表对端没开——重连按指数退避自己跑,改完网络或对端重启后无需重启本实例,链路会自己回来。

增删或改点 peers 同样不需要重启:profile patch 层的改动会重建本插件的 fiber,构造器按新映射重新建链。这条已实测(双向对照):patch 层加入 peers 后出现拨号、删掉后拨号消失;改 instanceId 后新链接自报的就是新名字。生效的前提是这一层被真正应用——由 dsh 启动、组合里带 hmr 行的实例会自己应用(见「安装」一节),其它启动方式只能重启。构造器只在激活时读一次该映射,所以改了文件但没被应用时,行为仍是旧的。

interconnect_list 返回对端当前 live 的 session,每一行的 sessionId 在调用时刻都是合法的投递目标:

session-264d37b0-… 重构 interconnect 插件 [idle]
session-b07326da-… [running]
title 与 status 是尽力而为的:标题来自可选的 title projection 服务。对端没装该服务、或该 session 还没有标题时,整个键不出现(而不是空字符串),所以「无标题」与「该对端不提供标题」可以区分。projection 抛错只会让那一行降级成只有 id,不会让整个列表失败。

只列 live session 是有意的:send 能到达的正好是这些。对端存在但没有运行 agent 的 session 不会出现在列表里,也收不到消息。

答案有双重上限:行数(MAX_LISTED_SESSIONS,100 行)与字节预算(MAX_LIST_ROWS_BYTES,等于链路帧上限减去 4 KiB 的 query-result 信封)。整帧必须待在链路的帧上限内,ws 对超限帧会直接关闭链路,所以 live session 极多、或标题很长时,对端只回答能装下的前若干行,而不是把传输打断。对端不上报截断标志,所以 interconnect_list 只在收到的行数正好等于该上限时追加一行提示(100 of possibly more live sessions)——满页可能被截断,缺失的目标仍可能 live。ping 与 list 的答复还会按调用方问的 kind 校验形状,形状不符按「无答复」处理(对应 unreachable)。

回复(reply)

send 的线负载带一个 sender 身份(无地址:instanceId + sessionId),收到消息的 instance 会按「本地 session id → 该 sender」记下这份身份。之后那个 session 回信只需要文本:回信 session 就是执行 interconnect_reply 的 agent 自己的 session,工具据此查出记录的 sender,不用再次给出本地 session id、对端 instanceId 或远程 session id——回信走的是本机到那个 instance 的持久链接。
text

源实例 A 指定目标 B 的 session,并带上自己的身份(无 baseUrl)

interconnect_send(instanceId="b", sessionId=B-sess, text="…", sender={instanceId:A, sessionId:A-sess})

B 回传:只给文本,回信 session 即执行该工具的 agent 自己的 session

interconnect_reply(text="reply")

- sender 是自报的,只用于 reply 归因与寻址,不是路由或鉴权依据——连接本身仍由共享密钥在每个 origin 上独立鉴权。
- 回复的消息也带 sender(本机恒带,不再需要配置 origin),所以对话可双向多轮延续。
- 只有当入站 send 带了 sender 时 reply 才有目标;对端版本没带、或本 session 从未收过互联消息时,reply 返回 delivered: false, reason: "no-sender-known"。
- sender 不进模型上下文(和 source 一样只落到持久化日志与 UI 归因)——这条消息的内容字面就是 wire 上传来的 text,模型看到的仍是普通 user 文本,只是不带任何结构化的发送方标记。

消息信道:全走 WS(msg / query 帧)

从 0.9 起不再有任何 HTTP 端点——send/reply/ping/list 全部在持久 WebSocket 链路(/interconnect/link)上完成。peers 映射在激活时自动 link() 每个对端(心跳 + 指数退避重连沿用既有实现),寻址按 instanceId 查对应链接。

| 帧 | 方向 | 作用 |
| hello | 双方 | 拨号方自报 instance id |
| event | 双方 | 生命周期事件推流 |
| msg | 请求方 → 接收方 | 携带 kind(send/reply)、sessionId、text、sender/delivery/resume、reqId |
| msg-result | 接收方 → 请求方 | 与 reqId 对应的 SendResult |
| query | 请求方 → 接收方 | ping / list / event 发现与事件查询 |
| query-result | 接收方 → 请求方 | 与 reqId 对应的查询结果 |

- 出站:interconnect_send/interconnect_reply/ping/list 都发对应帧并等待匹配 reqId 的结果(受 requestTimeoutMs 约束)。到未配置或未联通的对端直接返回 unreachable——没有 HTTP 回退,这是 0.9 的破坏性变化。
- 入站:msg 帧携带 send,走 deliver 逻辑(sender 记录、subagent 封栏等),结果经同一 socket 回 msg-result;query 帧回 query-result。
- 心跳与指数退避重连沿用既有实现。

投递失败的原因

delivered: false 单独一个布尔值无法据以行动,因为不同失败需要不同应对,所以 SendResult.reason 会指明是哪一种:

| reason | 含义 | 应对 |
| session-not-live | 对端答复了,但那个 session 没有 live agent,且唤醒被关闭(resume: false)或对端无法唤醒 | 不要改投其它 session;报告失败,或移除 resume: false 后重试 |
| unreachable | 配了该对端,但没拿到可用答复(链路断,或鉴权被拒) | 目标 session 可能完好,链路重连后重试可能成功 |
| peer-not-configured | 本实例的 peers 里没有这个 instanceId,链路根本不存在 | 重试永远不会成功;补 peers 映射(patch 层改完即生效,见「寻址」一节),或改用 interconnect_peers 列出的 id |
| resume-refused | 请求了唤醒,但对端不允许(allowResume: false) | 再请求也没用;不要改投其它 session,报告失败 |
| resume-failed | 允许唤醒且尝试了,但没得到 live agent(无此持久化 session,或被别的 owner 持有) | 不要改投其它 session;报告失败 |
| session-owned-by-subagent | 该 session 属于 subagent 路由,投递权在它的父 agent | 通过父 agent 触达,别直接投 |
| message-too-large | 编好的帧超过链路帧上限(1 MiB),什么都没写、链路也没断 | 缩短文本,重发原文没用 |
| no-sender-known | reply 指向的本地 session 从未记录过发送方(它没收到过带 sender 的消息,或对端版本过旧没带 sender) | 先用 interconnect_send 主动建立联系 |

reason 恰好在 delivered 为 false 时出现。

后两种加上 peer-not-configured 是本机产生的原因,不会从线缆上来:msgResultSchema 只接受接收方能回答的原因,所以这三条只可能出自本实例自己的服务(对端无法借它们伪造一个本地判定)。

只有真的「尝试唤醒但失败」才是 resume-failed。没装 api-proxy 的部署里,agent lookup 退化成一次 registry 查询、根本没有唤醒能力,这时报 session-not-live——否则会让调用方去重试一个永远不可能成功的操作。

subagent 会话不可直投

interconnect_send 不会往 subagent 拥有的 session 里投递,interconnect_list 也不会把它们列出来。那类 session 的投递权属于它的父 agent,从这里 splice 进 inbox 会和父 agent 抢。判定逻辑镜像 Host 的 hasApiSessionSubagentOwner(@deepseek-ai/dsh-api-session-controller): Host 在 0.6 之后把这个谓词从 @deepseek-ai/dsh-api-remotes 移走,且没有公开导出——桌面端和
npx @deepseek-ai/dsh web 运行时里没有任何可 import 的 Host 绑定,所以这里逐字复制一份
(isSessionOwnedBySubagent,见 src/interconnect/index.ts)。这是安全规则,Host 改动该规则时必须同步此副本;tests 覆盖 origin=subagent 与 parent-owned 两条封栏分支。

已实测:起一个真实 subagent 后,interconnect_list 不包含它;直接 send 到它的 id 返回 session-owned-by-subagent,消息没有进入 inbox。

唤醒离线 session(resume,默认开)

投递目标是一个「已持久化但没有运行 agent」的 session 时默认会唤醒它:不带 resume 时 interconnect_send 与 interconnect_reply 都按 resume: true 处理;传 resume: false 才保持原样并返回 session-not-live。

默认开启是 2026-10-23 的决定。 实测确认:消息投递到 session 后会触发一次完整的 agent
回合——wakeDriver() → kick() → turn() → llm.stream(),即一次计费的模型调用,且
assembly 里带着该 session 的完整工具集。默认关闭时,最常见的结果不是省下这一次调用,而是投递失败后发送方改投另一个正在运行的 session:原会话永远收不到,别的会话收到一段不属于它的内容。目标通常是用户关心的那个会话,只是它此刻没在跑;所以默认唤醒它,把「不唤醒」留给明确这样要求的调用方。

两侧的控制权不变:

- 发送方可逐条用 resume: false 关闭唤醒
- 接收方用 Config.allowResume(默认 true)一票否决——因为花钱和跑工具的是它那台机器;拒绝时在跑 lookup 之前就短路,回 resume-refused

唤醒不是调本插件的 ctx.agents.resume(),而是走 Host 已配置的 agent lookup
(typert.lookups.get('agent'))。这一点是关键:resume() 返回的 handle 由调用方
context 拥有,实测确认插件 fiber 被 dispose 时会把 resume 出来的 agent 和 session 一起拆掉(同一调用改用根 ctx 则两者都存活)。交给 Host 的 resolver 之后 owner 是 api-proxy,而且它会按 session 日志里记录的 preset 重建工具集——不是空壳。

没有 Host lookup 的部署(headless、无 api-proxy 的 profile)会降级为 session-not-live,不会报错。

唤醒只把消息放进 inbox,是否真的开始处理取决于 delivery: text

默认:唤醒并让对方实际处理(会起一个计费回合)

interconnect_send(instanceId="peer", sessionId, text, delivery="followup")

唤醒但不起回合:只写入上下文,等对方下次被唤醒时一起读

interconnect_send(instanceId="peer", sessionId, text, delivery="inject")

不唤醒:目标保持原样,返回 session-not-live

interconnect_send(instanceId="peer", sessionId, text, resume=false)

已实测:唤醒(默认开启)+ delivery="inject" 之后目标从非 live 变 live (interconnect_list 计数 +1),且该 session 日志里只多一条 agent/inbox/spliced、后面没有 turn/start。
已知限制:磁盘格式过旧的 session 无法唤醒,返回 resume-failed。这不是本插件的限制——Host 自己的 resume 路径对同一个 session 报 SessionFormatUnsupportedError,同样失败。

投递模式

delivery 的三个取值各自对应一个 Agent 方法,即 (inbox target, wakeup) 组合:

| 模式 | inbox target | 唤醒 | 行为 |
| followup | next-turn | 是 | 排队成独立一轮,等接收方当前那轮结束 |
| steer | next-step | 是 | 插进运行中那轮的最近 step 边界,不等整轮结束;接收方 idle 时起新一轮 |
| inject | next-step | 否 | 只写入上下文,不唤醒 idle 的 agent,可能一直不被读到 |

紧急程度属于单条消息而非整条链路,所以发送方可以按消息覆盖接收方的默认模式;不带该字段时沿用接收方 Config.delivery 的配置。SendResult.delivery 回报实际生效的模式,发送方据此判断覆盖是否被采纳。

配置

interconnect 行的 config(全部可选,下表为默认值):

| 字段 | 默认 | 说明 |
| instanceId | 'dsh' | 本实例自报的 id,出现在 ping/send/list 的回包里。也作为「对端如何寻址到我」的身份 |
| requestTimeoutMs | 10000 | 出站请求超时,上限 60000 |
| peers | {} | 对端路由映射:{ [对端 instanceId]: 我拨向它的 origin },例如隧道端点 http://127.0.0.1:13080。激活时对每个对端自动建持久 WS 链;send/reply/ping/list 都按 instanceId 走对应链接。改这一行不需要重启:profile patch 层的改动会重建 fiber 并按新映射建链 |
| delivery | 'followup' | 入站消息未带 delivery 时的默认投递模式 |
| allowResume | true | 是否允许发送方用 resume 唤醒本机的离线 session |
yaml
- id: interconnect
config:
instanceId: my-box
peers:
peer-a: http://127.0.0.1:13080 # 我拨向对端 peer-a 的 origin peer-b: http://127.0.0.1:13081 delivery: followup allowResume: false # 拒绝一切唤醒请求

鉴权用的共享密钥不在这里,而是取自 credentials 的 DSH_INTERCONNECT_TOKEN(fail-closed:没有 token 时端点返回 403)。

安装

本包已发布到 npm:dsh-interconnect。本仓库是一个 DSH profile bundle(根 package.json 声明 dsh.bundle.patch 指向根 cordis.patch.yml,后者 insert 三个插件行)。
bash

从 npm

dsh plugin --profile <name> add dsh-interconnect

或从本地路径(已实测)

dsh plugin --profile <name> add file:/path/to/dsh-interconnect

registry 上的 tarball 自带 lib/.js 与 lib/types//.d.ts,安装时不跑构建。

dsh plugin add 会把仓库识别为 bundle 并追加进 profile 的 dsh.profile.bundles。这次改动落在组合层:@deepseek-ai/dsh-base 插入的 hmr 行监听 profile 的 package.json,manifest 一变就重读 dsh.profile.bundles 并重算 patch 层,所以新增的行会在几秒内插进运行中的树并激活,不需要重启。已实测:安装前 GET /interconnect/link 返回 404,安装后 6 秒内同一请求返回 403(插件 fail-closed 的应答)。

插件代码的更新属于另一层,必须重启该实例:hmr 的模块监听根在 base 里是空的(root: [])且跳过 node_modules,已经导入的模块不会重载。升级已装插件、或在 file: 安装下重建 lib/,都落在这一类。没有 profileContext 的启动方式(hmr 行被禁用)也只能靠重启。

file: 安装还有一个文件粒度的差异,来自 pnpm 用硬链接装本地目录依赖(实测所装副本的 link 数:lib/ 为 2,其余为 1):lib/ 是硬链接,仓库里重建后 profile 里那份跟着变,重启即可生效;assets/、dsh.plugin.json、package.json、cordis.patch.yml 是安装时刻的副本,改仓库不会传播。skill 正文来自 assets/,所以「只重建 + 重启」会得到新代码配旧 skill 正文,profile 的 package.json 里还可能写着很久以前的版本号。要整体刷新就用重装: bash
dsh plugin --profile <name> remove dsh-interconnect
dsh plugin --profile <name> add file:/path/to/dsh-interconnect

两端实例用相同的 DSH_INTERCONNECT_TOKEN 作为共享密钥,任选一种来源:继承的进程环境变量、$DSH_HOME/.env、或 $DSH_HOME/.credentials.yaml 的 refs 段(该 provider 由 @deepseek-ai/dsh-base 挂载;优先级为 继承的环境 > credentials 文档 > 调用目录的 .env > $DSH_HOME/.env): yaml version: 1 refs: DSH_INTERCONNECT_TOKEN: <两端相同的共享密钥>

两台机器最小可用

下面用 A、B 两台机器说明最短路径:A 要主动发消息给 B,B 也要能回信。五步里前四步两端都要做,漏掉哪一步就会停在对应的失败原因上。

1. 两端各装一次 bash
dsh plugin --profile <name> add dsh-interconnect

由 dsh 启动的实例几秒内自己热加载(见上一节),不用重启。

2. 两端设同一个共享密钥

按上一节任选一种来源,两侧的值必须逐字节相同。任一端没配 token 时端点 fail-closed,直接 403,另一侧只会看到链路 down。

3. 打通网络:把 B 的端口映射到 A 的本机端口

链接路由 /interconnect/link 挂在 B 的宿主 webserver 上,也就是 B 那个 DSH 实例监听的端口(dsh web 就是 GUI 的端口)。同一台机器上就是回环地址;跨机器时先建立隧道: bash

在 A 上执行:B 的 3080 变成 A 本机的 13080;-N 不执行远程命令

ssh -N -L 13080:127.0.0.1:3080

只用 A→B 单向发消息时,这一条就够了。要让 B 也能主动发给 A,在 B 上反向再建一条(把 A 的端口映射成 B 本机的 13081)。

4. 两端各配一遍 peer

改 profile 的 patch 层(不是插件包内的文件;interconnect 行由 bundle 插入,这里按键名覆盖它的 config): yaml

A: $DSH_HOME/profiles/<name>/cordis.patch.yml

- id: interconnect
config:
instanceId: a
peers:
b: http://127.0.0.1:13080 # key = B 自报的 instanceId;value = A 拨向 B 的 origin yaml

B: $DSH_HOME/profiles/<name>/cordis.patch.yml

- id: interconnect
config:
instanceId: b
peers:
a: http://127.0.0.1:13081 # 没有这一条,B 能收消息但回信会得到 peer-not-configured

改完不用重启:patch 层的改动会重建 fiber 并按新映射建链。key 建议与对端自报的 instanceId 一致,否则 B 拨入的那条链路在 A 侧认不出是同一个 peer,事件会重复一份(服务会 warn 一次)。

5. 按顺序验证

1. interconnect_peers —— 应看到 b 且链路 up。
2. interconnect_ping(instanceId="b") —— 应答里是 B 的实例 id。
3. interconnect_list(instanceId="b") —— 列出 B 上 live 的 session。
4. interconnect_send(instanceId="b", sessionId=..., text=...) —— 投递成功。
5. B 侧 interconnect_reply(text=...) 回信,A 侧收到续文。

停在哪一步就回查哪一步:unreachable(configured: true)回查第 2、3 步(token、隧道); configured: false / peer-not-configured 回查第 4 步(映射里没有这个 key);链路一直 down 时,对端日志里对应的是 401/403,回查第 2 步(两侧 token 是否都有值且逐字节相同)。

开发

依赖 公开的 DeepSeek Harness monorepo 作为 sibling checkout:package.json 的 devDependencies 用 link:../dsh/... 指向它, peer 依赖由该 checkout 提供,构建与测试都跑在这份源码上。
bash
ln -s /path/to/deepseek-harness ../dsh
pnpm install --config.auto-install-peers=false # peer @deepseek-ai/dsh-* 由 sibling checkout 提供
pnpm run check # typecheck + test + build
pnpm run build # esbuild → lib/

架构说明

- 三个插件都挂在 host composition:interconnect 是跨 session、跨机器的进程级服务(有 HTTP/WS 端点),必须 host 级;tool-interconnect 和 skill-interconnect 也放 host,因为 interconnect 未做 TypeRT @Remote/Gateway 绑定,放进 agent preset 的 isolate realm 会导致工具/技能行无法 inject 到该服务。
- 服务只 inject agents 与 credentials;宿主 webserver 是可选的。有 webserver 时入站升级路由注册在它上面(webServer 经等待式 inject fiber 接入,与组合顺序无关);没有 webserver 的 profile(例如 headless)里服务仍会拨号已配置对端并经这些出站链接投递,即仅出站模式。dsh.plugin.json 的 inject 与之一致,只有 agents、credentials。
- ws 是运行依赖,由宿主的 node_modules 提供(构建时 external)。

验证

- 179/179 单测通过(服务 + 工具 + skill,含 wire 校验、畸形帧、心跳/池清理、结果帧按 kind 绑定与投影、list 的行数与字节双上限及满页提示、peer 状态与「未配置」分支、本机原因不得从线缆上来的负例等回归用例);类型检查、构建均干净。
- 已在两台机器之间实测双向互通:消息投递、WebSocket 事件推流,以及智能体经 interconnect_send 工具反向回发,均验证通过。
- CI(GitHub Actions):clone 公开 DSH 仓库作为 sibling,跑 pnpm run check。
- 已发布版本:从 registry 下载的 tarball 与本地构建 shasum 一致;干净消费端解析 .、./tool-interconnect、./skill-interconnect 入口的类型均通过,负例(把 string 赋给 number)如期报 TS2322。
- 投递消息以 source: { kind: 'plugin', plugin: 'dsh-interconnect' } 落库,而不是 { kind: 'user' }。负例:把该 source 改回 kind: 'user',对应断言转红。
注意 source 不进模型上下文——只有 role 和 content 会,而 role 是 user。
所以这个字段的价值在持久化日志与 UI 归因,接收方的模型本身分辨不出消息来自插件。
同理,reply 的记录与寻址依赖 sender,它同样不进模型上下文。
- reply 双向多轮延续在同一测试进程内用真实 WS 双向回环验证(A→B→A→B),不是 mockout。
- 每个行为改动都配负例对照(删掉实现使对应断言转红),而不只是「测试通过」。
例如:去掉 peers 激活时的自动 link(),3 条「自动建链投递 / ping/list / reply 回环」测试转红;去掉 requestTimeoutMs 的定时会违反「超时即 unreachable」的契约。
- WS + instanceId 传输在真实 WS 链路上验证:接收方只暴露 upgrade 路由、不暴露任何 HTTP,一条 send 仍投递成功——排除了「其实走了 HTTP 回退」的误判(0.9 起根本没有 HTTP)。

许可

MIT,Copyright (c) 2026 Chinesezjc。
预览分享卡片长什么样 ↓Chinesezjc/dsh-interconnect
分享 · DeepSeek Harness Hub
Chinesezjc/dsh-interconnect

跨实例消息互通与事件通知插件,用于 DeepSeek Harness DSH。

这是你的仓库?认领条目

回到顶部