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

本地智能体中继 Noelune/dsh-agent-relay

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

DeepSeek Harness 本地多智能体协作中继——为 dsh、Codex、Claude Code 和 Hermes 提供 HMAC 认证的环回消息代理。

32.9/100
综合分
4
GitHub 星标
246
npm 周下载
—/5
用户评分

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · tool
装得上吗
静态安装检查通过
未做真实安装
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 22 天前
档位由哪些信号合成

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

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

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

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/20 16:15:17

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 68 处,展示前 68 条)
  • 读取本地文件
    lib/index.js:68
    if (existsSync(CONFIG_FILE)) fileCfg = JSON.parse(readFileSync(CONFIG_FILE, 'utf8'))
  • 读取本地文件
    lib/index.js:68
    if (existsSync(CONFIG_FILE)) fileCfg = JSON.parse(readFileSync(CONFIG_FILE, 'utf8'))
  • 读取本地文件
    lib/index.js:180
    if (!vaultPath || !subprocess || !existsSync(vaultPath)) return ''
  • 读取本地文件
    lib/index.js:437
    if (!existsSync(brokerIndexPath())) {
  • 读取本地文件
    lib/index.js:441
    if (!existsSync(cfg.brokerConfigPath)) {
  • 执行外部命令来自配置/变量
    lib/index.js:445
    const child = spawn(process.execPath, [brokerIndexPath(), '--config', cfg.brokerConfigPath], {
  • 发起网络请求
    lib/client-ui.js:87
    window.fetch(STATUS_API, { cache: 'no-store' })
  • 发起网络请求
    lib/client-v2.js:47
    const res = await fetch(this.endpoint + path, {
  • 读取本地文件
    lib/relay-plugin-core.js:94
    try { raw = JSON.parse(readFileSync(file, 'utf8')) } catch { return }
  • 写入本地文件
    lib/relay-plugin-core.js:115
    writeFileSync(tmp, JSON.stringify({ [keyField]: list }, null, 2), 'utf8')
  • 写入本地文件
    lib/relay-plugin-core.js:116
    renameSync(tmp, file)
  • 执行外部命令来自配置/变量
    lib/memory-bridge.js:26
    const child = execFile(
  • 执行外部命令来自配置/变量
    adapters/backends/claude-backend.mjs:44
    const child = spawn(RESOLVED.file, [...RESOLVED.args, ...buildArgs(cwd)], { cwd, stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    adapters/backends/codex-backend.mjs:48
    const child = spawn(RESOLVED.file, [...RESOLVED.args, ...buildArgs(cwd)], { env, stdio: ['pipe', 'pipe', 'pipe'] })
  • 读取本地文件
    adapters/backends/resolve-cli.mjs:22
    if (!existsSync(full)) continue
  • 读取本地文件
    adapters/backends/resolve-cli.mjs:27
    try { content = readFileSync(full, 'utf8') } catch { }
  • 读取本地文件
    adapters/cli/relay.mjs:28
    try { return JSON.parse(readFileSync(STATE_FILE, 'utf8')) } catch { return {} }
  • 写入本地文件
    adapters/cli/relay.mjs:31
    try { writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), 'utf8') } catch { }
  • 读取本地文件
    adapters/cli/relay.mjs:78
    if (existsSync(file)) fileCfg = JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    adapters/cli/relay.mjs:78
    if (existsSync(file)) fileCfg = JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    adapters/relay-agent.mjs:45
    try { if (existsSync(CONFIG_FILE)) file = JSON.parse(readFileSync(CONFIG_FILE, 'utf8')) } catch { }
  • 读取本地文件
    adapters/relay-agent.mjs:45
    try { if (existsSync(CONFIG_FILE)) file = JSON.parse(readFileSync(CONFIG_FILE, 'utf8')) } catch { }
  • 执行外部命令来自配置/变量
    adapters/relay-agent.mjs:64
    const child = execFile(prog, args, { cwd, env, maxBuffer: 2 * 1024 * 1024 }, (err, stdout, stderr) => {
  • 读取本地文件
    broker/src/config.js:18
    if (!existsSync(path)) throw new Error(`config file not found: ${path}`)
  • 读取本地文件
    broker/src/config.js:19
    const lines = readFileSync(path, 'utf8').split(/ ? /)
  • 写入本地文件
    broker/src/store-v2.js:47
    mkdirSync(dataDir, { recursive: true })
  • 写入本地文件
    broker/src/store-v2.js:117
    mkdirSync(dataDir, { recursive: true })
  • 写入本地文件
    broker/src/store-v2.js:137
    writeFileSync(jsonlPath, lines.join('\n') + (lines.length ? '\n' : ''), 'utf8')
  • 写入本地文件
    broker/src/store-v2.js:142
    mkdirSync(dataDir, { recursive: true })
  • 写入本地文件
    broker/src/store-v2.js:152
    appendFileSync(jsonlPath, JSON.stringify({ message: m }) + '\n', 'utf8')
  • 读取本地文件
    broker/src/store-v2.js:195
    if (!existsSync(jsonlPath)) return
  • 读取本地文件
    broker/src/store-v2.js:196
    for (const line of readFileSync(jsonlPath, 'utf8').split(/ ? /).filter(Boolean)) {
  • 写入本地文件
    broker/src/store.js:59
    mkdirSync(opts.dataDir, { recursive: true })
  • 读取本地文件
    broker/src/store.js:88
    if (!opts.persist || !existsSync(persistPath)) return
  • 读取本地文件
    broker/src/store.js:89
    const raw = readFileSync(persistPath, 'utf8').split(/ ? /).filter(Boolean)
  • 写入本地文件
    broker/src/store.js:114
    mkdirSync(opts.dataDir, { recursive: true })
  • 写入本地文件
    broker/src/store.js:130
    writeFileSync(persistPath, lines.join('\n') + (lines.length ? '\n' : ''), 'utf8')
  • 写入本地文件
    broker/src/store.js:135
    mkdirSync(opts.dataDir, { recursive: true })
  • 写入本地文件
    broker/src/store.js:137
    appendFileSync(persistPath, JSON.stringify({ seq, message }) + '\n', 'utf8')
  • 读取本地文件
    broker/src/store.js:347
    if (!messages.size && existsSync(persistPath)) {
  • 发起网络请求
    lib/client.js:46
    const res = await fetch(this.brokerUrl + path, {
  • 写入本地文件
    lib/lease.js:58
    mkdirSync(root, { recursive: true })
  • 读取本地文件
    lib/lease.js:78
    try { age = Date.now() / 1000 - statSync(path).mtimeMs / 1000 } catch { }
  • 删除本地文件
    lib/lease.js:80
    try { unlinkSync(path) } catch { return { lease: null, owner: existing } }
  • 删除本地文件
    lib/lease.js:84
    try { unlinkSync(path) } catch { return { lease: null, owner: existing } }
  • 写入本地文件
    lib/lease.js:97
    utimesSync(this.path, now, now)
  • 删除本地文件
    lib/lease.js:106
    unlinkSync(this.path)
  • 读取本地文件
    lib/lease.js:113
    const payload = JSON.parse(readFileSync(path, 'utf8'))
  • 执行外部命令固定命令
    lib/workspace.js:16
    return execFileSync('git', ['-C', root, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
  • 读取本地文件
    lib/workspace.js:53
    const isWorktree = existsSync(root) && git(root, 'rev-parse', '--is-inside-work-tree') === 'true'
  • 读取本地文件
    lib/workspace.js:55
    if (existsSync(root)) throw new Error('relay worktree path already exists but is invalid')
  • 读取本地文件
    lib/workspace.js:61
    if (!created && !existsSync(root)) throw new Error('could not create isolated relay worktree')
  • 读取本地文件
    lib/workspace.js:75
    if (!existsSync(workspace)) throw new Error('isolated relay workspace is unavailable')
  • 读取本地文件
    setup/migrate-v2.mjs:42
    if (!existsSync(args.source)) {
  • 写入本地文件
    setup/migrate-v2.mjs:47
    mkdirSync(args.dataDir, { recursive: true })
  • 读取本地文件
    setup/selfcheck.js:22
    const raw = readFileSync(CONFIG_PATH, 'utf8')
  • 读取本地文件
    setup/selfcheck.js:37
    if (!existsSync(CONFIG_PATH)) {
  • 发起网络请求
    setup/selfcheck.js:49
    const res = await fetch(brokerUrl + '/', { signal: AbortSignal.timeout(3000) })
  • 读取本地文件
    setup/setup.js:45
    if (existsSync(CONFIG_PATH)) {
  • 写入本地文件
    setup/setup.js:48
    mkdirSync(BROKER_DIR, { recursive: true })
  • 写入本地文件
    setup/setup.js:49
    writeFileSync(CONFIG_PATH, CONFIG_TEMPLATE(randomBytes(32).toString('hex')), 'utf8')
  • 读取本地文件
    setup/setup.js:64
    if (!existsSync(CONFIG_PATH)) {
  • 写入本地文件
    setup/setup.js:68
    mkdirSync(dirname(PID_PATH), { recursive: true })
  • 执行外部命令来自配置/变量
    setup/setup.js:69
    const child = spawn(process.execPath, [join(BROKER_DIR, 'src', 'index.js'), '--config', CONFIG_PATH], {
  • 写入本地文件
    setup/setup.js:73
    writeFileSync(PID_PATH, String(child.pid), 'utf8')
  • 读取本地文件
    setup/setup.js:76
    try { readFileSync(PID_PATH) } catch { }
  • 读取本地文件
    setup/setup.js:88
    if (!existsSync(CONFIG_PATH)) {
  • 发起网络请求
    setup/setup.js:101
    const res = await fetch(brokerUrl, { signal: AbortSignal.timeout(3000) })
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 本机代理间消息转发
  • HMAC认证
  • 环回消息代理

README

由 DeepSeek 最新模型翻译生成
⚡ dsh-agent-relay Local Multi-Agent Collaboration Relay for DeepSeek Harness & Local Fleets DeepSeek Harness 本地多智能体轻量级通信中继总线 — 基于 HMAC-SHA256 鉴权与 Loopback 优先架构的安全消息路由组件 产品定位与设计动机 • 核心技术特性 • 系统架构与流程 • Agent 全流程自动部署 • Wire Protocol 规范 📌 产品定位与设计动机 现有的智能体框架多数专注于单体智能体内部的推理链条与工具调用(Task Execution),但缺乏标准化的智能体间对等通信机制(Peer-to-Peer Inter-Agent Communication)。当在同一宿主机上并行运行 dsh、Codex、Claude Code 与 Hermes 等多个独立智能体时,代理之间无法直接发起代码评审(Code Review)、事实交叉验证或协作任务分发。 dsh-agent-relay 旨在填补这一架构空白:它是一个完全解耦、轻量且自建的智能体通信总线(Communication Bus),包含 HTTP Broker、dsh Cordis 插件、JS/Python 客户端与命令行辅助工具,助力开发者构建智能体舰队协同链路。
展开完整文档(README 剩余 1 节)
⚡ dsh-agent-relay

Local Multi-Agent Collaboration Relay for DeepSeek Harness & Local Fleets

DeepSeek Harness 本地多智能体轻量级通信中继总线 — 基于 HMAC-SHA256 鉴权与 Loopback 优先架构的安全消息路由组件

产品定位与设计动机 • 核心技术特性 • 系统架构与流程 • Agent 全流程自动部署 • Wire Protocol 规范

📌 产品定位与设计动机

现有的智能体框架多数专注于单体智能体内部的推理链条与工具调用(Task Execution),但缺乏标准化的智能体间对等通信机制(Peer-to-Peer Inter-Agent Communication)。当在同一宿主机上并行运行 dsh、Codex、Claude Code 与 Hermes 等多个独立智能体时,代理之间无法直接发起代码评审(Code Review)、事实交叉验证或协作任务分发。

dsh-agent-relay 旨在填补这一架构空白:它是一个完全解耦、轻量且自建的智能体通信总线(Communication Bus),包含 HTTP Broker、dsh Cordis 插件、JS/Python 客户端与命令行辅助工具,助力开发者构建智能体舰队协同链路。

🚀 核心技术特性

- 通信与编排解耦 (Decoupled Transport) 区别于强侵入性的工作流编排引擎(Orchestration Frameworks),Relay 仅专注于消息路由与可靠投递,保持智能体内部推理与决策逻辑的完整解耦。
- Loopback 优先的安全架构 (Loopback-First Architecture) Broker 默认仅绑定本地回环地址 127.0.0.1:19121,免去云端部署成本与外部网络攻击面风险。
- HMAC-SHA256 鉴权体系 (Cryptographic Verification) 所有接口调用均经由 HMAC-SHA256 签名校验,内置 300 秒时间戳重放防护与常量时间比较;投递层再以「每次认领一枚租约令牌」约束确认与续租。速率限制与鉴权失败锁定属于已删除的 v1 世代,现在没有这两道闸,所以边界由「只绑回环」承担。
- 高可靠投递与容错机制 (Reliable Delivery & Idempotency) 请求默认留存 7 天、SQLite 单一路径持久化、租约投递 + 令牌化确认、服务端长轮询唤醒(落库即达)、失败/过期由服务端定时扫描自动回发未送达通知,并以幂等键去重。
- 隐私保护设计 (Privacy-by-Design) 消息体只为可靠投递保存在本机 TTL 队列中,Broker 与参考客户端不会把消息体写入应用日志或遥测;默认回环部署时数据不离开本机。
- dsh 一级工具无缝集成 (First-Class Cordis Plugin) 针对 DeepSeek Harness 提供原生 Cordis 插件,注册 agent_relay_send / agent_relay_status / agent_relay_history / agent_relay_peers / agent_relay_retry 模型工具,自适应退避轮询 + per-root relay 会话 + read/write 权限预设,并提供图形化侧边栏状态面板。
- v2/v3 线协议(与自用版 Python 客户端字节兼容) canonical-JSON 签名、snake_case 信封、execution mode、per-mode ACL、租约令牌、undelivered 通知;v1 世代已于 2026-09-19 移除。

⚖️ 系统设计对比 (Architecture Comparison)

| 维度对比 | ⚡ dsh-agent-relay | ❌ 工作流编排引擎 (AutoGPT/LangGraph) | ❌ 传统消息服务 (Slack/Discord API) |
| 架构定位 | 纯粹消息路由总线,保持智能体推理独立 | 强依赖 DAG 图逻辑,侵入式驱动控制流 | 人类社交 UI 框架,包含复杂的 Presence 状态 |
| 部署与网络依赖 | 零第三方依赖,Loopback 本地极速运行 | 需复杂的中间件环境与 Redis/数据库支持 | 需公网访问、OAuth 鉴权与 WebSocket 长连接 |
| 状态持久化与容错 | 本地 SQLite + 7 天留存 + 租约投递 + 长轮询唤醒 | 依赖外部集中式数据库管理状态 | 依赖第三方云端服务器消息留存 |
| 数据隐私保护 | 默认纯本地,消息体不进入日志或遥测 | 常见云端日志留存与 Embedding 上传 | 消息明文通过第三方服务器中转 |

🏗️ 系统架构与工作流

全部路由都在 /v1/ 之下,说同一套 v2/v3 线协议(规范见 docs/PROTOCOL-V2.md):签名有两种形态——不带 keyId 头走 v2 串,带 X-Agent-Relay-Key-Id 走 v3 串——但共用同一个密钥环与同一套租约/ack 投递。v1 世代(X-Relay- 头、/register、/peers、游标轮询)已整代删除,不带 v2/v3 头的请求会收到 400 并附协议指引。

sequenceDiagram
autonumber
participant D as dsh (Agent A)
participant B as Relay Broker (127.0.0.1:19121)
participant C as Claude Code (Agent B)

Note over D,C: Loopback 架构下基于 HMAC-SHA256 的通信流程 D->>B: POST /v1/messages (v2/v3 HMAC Signed) Note over B: 校验时间戳/签名/ACL写入 SQLite 队列
B-->>D: 200 {message_id, root_id, protocol_version}
C->>B: POST /v1/pull (lease)
B-->>C: 200 {messages, lease_token}
Note over C: Agent 接收消息并执行相关任务 C->>B: POST /v1/lease/renew (长任务可选) C->>B: POST /v1/ack (completed 或 retry)
B-->>D: 状态可由 /v1/status 查询,回复通过 parent_id 关联

🤖 Agent 全流程自动部署流程 (Agent-Driven Automated Deployment)

本项目原生支持由 AI Agent 主导的全流程自主部署与链路装配。开发者无需手动执行繁琐的环境配置,只需将部署任务交由 DSH (DeepSeek Harness) 或通用 AI Agent,系统即可自动完成终态构建。

flowchart LR
A[开发者执行插件挂载] --> B[DSH 读取 docs/AGENT-DEPLOY.md]
B --> C[自主生成 HMAC 密钥与 Broker 配置]
C --> D[启动 Broker 进程与健康检查 selfcheck]
D --> E[装配 CLI / Python / Agent 通信凭据]
E --> F[自动校验自检并输出部署报告]

🚪 推荐接入方式:MCP(Codex / Claude Code / Qoder / 任意 MCP 宿主)

mcp/relay-mcp.mjs 是协作圈的 MCP 入口。宿主在会话启动时自己拉起它、结束时回收,所以接入一个 Agent 是 3 行配置,而不是一个常驻轮询进程。工具面只有 5 个:

| 工具 | 作用 |
| relay_ask | 交给对方并直接等到回答(对方不在线时立刻返回 peer_offline,请求仍留存数天等自动投递) |
| relay_send | 异步投递,不等 |
| relay_inbox | 取别人发给我的请求(默认读完即确认) |
| relay_reply | 把答案回到某条收到的请求上(同一条会话线) |
| relay_status | 我发的请求到哪一步了 |
| relay_agents | 谁在圈里、谁此刻在线、队列积压 |

Codex(~/.codex/config.toml)与 Claude Code(~/.claude.json)示例:

[mcp_servers.relay_codex]
command = "node"
args = ["<repo>/mcp/relay-mcp.mjs"] # 本仓库的绝对路径
[mcp_servers.relay_codex.env]
AGENT_RELAY_AGENT = "codex"
AGENT_RELAY_BROKER_URL = "http://127.0.0.1:19121"
指向部署里已有的 dotenv,别让宿主配置变成密钥的第二个明文副本:
AGENT_RELAY_SECRET_ENV_FILE = "D:/path/to/bot/.env" # 读取 AGENT_RELAY_CODEX_SECRET
或者用 DPAPI 保管库:AGENT_RELAY_SECRET_REF + AGENT_RELAY_VAULT_MODULE

Claude Code 同理,写进 ~/.claude.json 顶层 mcpServers。凭据优先级:secret → secret_env → secret_env_file → secret_ref+vault_module。

接入后一句"让 claude 审一下这个函数"就是一次 relay_ask 工具调用。

让"没在跑的成员"也能被投递:wake_command

轮询模型要求接收方一直有进程活着,这在个人机器上经常不成立。给成员声明 wake_command 后,消息落库时若它 90 秒内没取过件,broker 会按需启动一次工作进程(凭据走子进程环境变量,不进命令行);它真的会跑一次该成员的 CLI 并产生 API 费用,所以开关单独成一条命令,默认只预演:

node setup/enable-wake.mjs --agent codex # 预演:打印将写入的行
node setup/enable-wake.mjs --all-clients --apply # 确认后写入(自动备份),再重启 broker

唤醒是兜底而非竞争:成员只要 90 秒内取过件(比如它的常驻代理正在跑),broker 就不会另起工作进程,避免同一消息被处理两次。

一条命令自检

node setup/doctor.mjs # 或 node adapters/cli/relay.mjs doctor

输出:broker 是否可达、谁真的能收消息、队列积压、两处凭据是否漂移、明文密钥、WAL 是否膨胀、线上 adapter 与仓库基线是否一致。退出码 0/2/1。

1. DSH 自主部署指令 (推荐)

在终端中安装插件后,直接让 DSH 读取任务指南 docs/AGENT-DEPLOY.md 即可完成端到端自主部署:

安装中继插件
dsh plugin --profile web add dsh-agent-relay

在接下来的 DSH 会话中,DSH 将自动执行如下全流程步骤:
1. 自动配置生成:生成随机 HMAC 密钥并写入 broker 的 config.yaml;成员的运行时配置是 ~/.dsh/agent-relay.json(只记 vault 条目名,不记明文密钥)。
2. 后台服务拉起:启动 Broker 进程并绑定 127.0.0.1:19121 端口。
3. 多 Agent 凭据装配:为 dsh、Codex、Claude Code 与 Python 客户端各自落地身份与凭据来源(环境变量 AGENT_RELAY_/DSH_RELAY_、指向已有 dotenv、或 DPAPI 保管库条目),不新造明文密钥副本。成员身份由取件行为体现,没有注册这一步。
4. 链路自检与验证:自动运行 selfcheck 验证收发链路,并向用户汇报部署结果。

2. 命令行手动部署流程 (单机快速验证)

git clone https://github.com/Noelune/dsh-agent-relay.git && cd dsh-agent-relay
node setup/setup.js init
node setup/setup.js start

收发验证(无需注册:身份就是签名里的 agent 名)
export DSH_RELAY_SECRET=<secret_printed_in_config>
node adapters/cli/relay.mjs v2 send beta "hello from alpha" --agent alpha --secret $DSH_RELAY_SECRET
node adapters/cli/relay.mjs v2 pull --wait 10 --agent beta --secret $DSH_RELAY_SECRET
node adapters/cli/relay.mjs doctor

完整指南详见:docs/DEPLOY.md · Wire Protocol 规范:docs/PROTOCOL-V2.md · 系统架构:docs/ARCHITECTURE.md · 安全规范:docs/SECURITY.md

📜 Wire Protocol 规范

唯一在用的协议是 v2/v3,规范见 docs/PROTOCOL-V2.md; v1 世代(X-Relay- 头、/register、/messages 游标轮询)已于 2026-09-19 移除——审计显示 v1 队列表自 2026-08-15 起再无任何消息,且没有任何现役客户端注册过。

鉴权头:X-Agent-Relay-Agent、X-Agent-Relay-Timestamp、X-Agent-Relay-Signature; v3 另带 X-Agent-Relay-Key-Id(现役飞书 bot 与 Hermes 适配器都走 v3 的 legacy 键)。

签名串(canonical JSON + HMAC-SHA256,v3 在第二段插入 keyId)的字节级定义只在 docs/PROTOCOL-V2.md 维护,此处不再复制一份等着漂移。
跨语言字节级一致性由 test/protocol_v2_golden.py 与 test/protocol-v2-python.test.mjs 锁定;不要自行改写签名规则,改协议请同步更新这两个测试。

📂 仓库目录结构 (Repository Layout)

| 路径 | 功能说明 |
| broker/ | Relay 中继核心服务(零 npm 运行依赖:配置、v2/v3 签名鉴权、SQLite 持久化、长轮询唤醒与按需拉起)+ Dockerfile |
| lib/ | 可发布的客户端层:v2/v3 客户端 (client-v2.js)、协议单一来源 (protocol.js)、配置分层 (relay-config.mjs)、凭据解析 (credentials.mjs)、DSH 的五个 agent_relay_ 工具、workspace 租约/隔离 |
| mcp/ | MCP stdio 入口 relay-mcp.mjs:6 个工具,宿主按会话拉起,不需要常驻轮询进程 |
| adapters/cli/ | 零第三方依赖 Node.js CLI 客户端适配器 |
| adapters/hermes/ | 纯 Python 标准库客户端适配器 + Hermes 风格 Agent 集成示例 |
| adapters/openclaw/ | OpenClaw 框架集成适配说明文档 |
| adapters/relay-agent.mjs | 短生命周期工作进程:认领→交给 --backend-cmd→ack→队列空即退出(wake_command 的默认目标) |
| setup/ | setup.js (init/start/selfcheck)、add-member.mjs、sync-secrets.mjs、doctor.mjs(一条命令体检)、enable-wake.mjs(按需唤醒开关,默认预演)、migrate-v2.mjs、capture-adapter.mjs、Docker Compose 演示 |
| docs/ | PROTOCOL-V2(线协议规范,唯一权威)、ARCHITECTURE(系统结构与取舍)、DEPLOY(部署)、SECURITY(威胁模型)、AGENT-DEPLOY(给 Agent 的部署任务书) |

🔧 环境要求 (Requirements)

- Node.js ≥ 22.13(Broker 服务、CLI 客户端、dsh 插件)。持久化只有 SQLite 一条路径(零外部依赖,用 Node 内置 node:sqlite,需 Node ≥ 22.13);JSONL 回退已随 v1 世代一起移除。
- Python ≥ 3.10 (仅 Python 客户端适配器需要,可选)
- dsh 0.1.0-rc.6(推荐测试版本)

📌 维护状态 (Maintenance Status)

- 维护者:Noelune
- 社区维护 —— 欢迎提交 Issue 与 Pull Request。缺陷修复通常在 1–2 周内处理,安全相关问题将优先响应。
- 兼容性:基于 dsh 0.1.0-rc.6 进行测试与兼容性验证。上游 API 变更说明同步记录于 CHANGELOG.md。
- 许可证:MIT License —— 允许商业化使用。

🛡️ 安全规范 (Security)

详细说明请参阅 docs/SECURITY.md。

* 鉴权与传输:通过 HMAC 实施身份验证,网络级加密依赖 TLS。默认强制推荐使用 Loopback 本地回环模式,切勿将未加密的明文 Broker 暴露在公网环境。
* 威胁模型防护:对于从 Relay 接收到的任何消息体,接收端 Agent 必须将其视为未校验的数据输入(Untrusted Data),严禁直接作为高权限指令执行。

🤝 贡献指南 (Contributing)

欢迎提交 Pull Request。提交前请确保运行单元测试(node --test)。项目的 CI 流程会在每次 Push 时自动执行单元测试、代码密钥扫描(gitleaks)与开源许可证合规检查。
预览分享卡片长什么样 ↓Noelune/dsh-agent-relay
分享 · DeepSeek Harness Hub
Noelune/dsh-agent-relay

DeepSeek Harness 本地多智能体协作中继——为 dsh、Codex、Claude Code 和 Hermes 提供 HMAC 认证的环回消息代理。

这是你的仓库?认领条目

回到顶部