← 返回列表
⚠ 装前注意
为 DeepSeek Harness 提供按 agent 区分的 plumb 会话身份。
基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/17 · 已提供中文文档
DeepSeek Harness 的按代理 plumb 会话身份:每个对话、工作区和子代理都在共享的 plumb MCP 连接上拥有自己稳定的 plumb 会话 ID
综合分
29.6
GitHub 分
29.6
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add plumbkit/dsh-plumb-identity未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 1 天前真实安装成功
- 是什么
- dsh 原生插件 · chat
- 装得上吗
- 本站已真实安装成功(非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 8 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/21(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-plumb-identity(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
未发布到 npm registry,仅可从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/22 03:52:34
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-plumb-identity
为 DeepSeek Harness 提供按 agent 区分的 plumb 会话身份。
这是一个 cordis 插件,为每个 DSH 对话、工作区和进程内子 agent 赋予其自身稳定的 plumb 会话身份——在传输层强制执行,而非通过指令。针对 @deepseek-ai/dsh@0.1.1-rc.2 和 plumb 0.17.x 开发并测试;其字段位置已于 2026-09-16 通过检查对照 @deepseek-ai/dsh@0.1.5-rc.1(MCP SDK 1.30.0)重新验证——关于这具体声称了什么、没有声称什么,请参阅文末的兼容性说明。
为什么
DSH 将每个对话多路复用到每进程一个 plumb serve 连接上,而 DSH 的 MCP 客户端(@deepseek-ai/dsh-mcp-client)不发送任何身份信息:没有按对话区分的 session id,也没有按调用区分的 _meta。plumb 的隔离层——按 agent 的工作区分片、读取跟踪、邮件寻址——在声明身份时才会启用,因此未标识的对话可能会强制重新固定彼此的工作区。通常的缓解措施是在 ~/.dsh/AGENTS.md 中写一条指令,要求每个对话声明一个 session_id;这覆盖了主对话,但 DSH 子 agent 在进程内运行,拥有自己的系统提示且没有父上下文,因此它们在结构上就是匿名的。
plumb 在两个通道上接受 agent 身份,此处两者都会使用:
- session_start { session_id, workspace, purpose }——声明该 agent,固定其自身的工作区分片,并记录关联关系(稳定 id 在恢复会话时继承 plumb 会话名称)。
- 每次调用的 tools/call params _meta["dev.plumbkit/logical-agent"]——plumb 始终会采纳;这是兜底方案,即使尚未发生任何声明,也能让每次调用都被归属。
工作原理
1. 关联。 DSH 的 tools/execute waterfall 上的监听器会看到每次工具调用及其 exec.agent——即调用方,无论是对话还是子 agent,各自拥有自己的会话 UUID 和工作区。对于 mcp____ 调用,它会生成一个稳定 id dsh--,并在 AsyncLocalStorage 作用域内运行管线的其余部分。
2. 标记。 对 MCP SDK Client.prototype.request 的一处窄范围补丁(正是 dsh-mcp-client 使用的那个类实例,在模块加载时从 DSH 的共享 profile 树中按绝对路径导入)会向在此类作用域内发出的 tools/call 请求添加 _meta["dev.plumbkit/logical-agent"]。该作用域仅在 plumb 工具执行期间被激活,因此被标记的请求在构造上就是发往 plumb 服务器的请求。同一个补丁会在 plumb Client 实例的连接自我命名的那一刻——stdio 传输的服务器参数显示为 plumb serve——捕获该实例,这发生在 SDK 初始工具同步期间,远在任何 agent 存在之前。
3. 声明。 使用捕获到的实例,插件会为每个 agent 的首次 plumb 调用主动发出 session_start { session_id, workspace, purpose } —— 位于身份作用域之外,因此该 id 会随参数传递,plumb 的 linkage 会在那里记录它,而 shard 会固定自己的 workspace。按每个 Client 记账,因为 dsh-mcp-client 会在每个重连代际构建一个全新的 client,而新连接必须重新声明。
一切都以失败开放:SDK 缺失、补丁被拒绝、声明被拒绝 —— 调用照常进行,AGENTS.md 指令面仍然是回退方案。工具调用绝不能因为其观察者无法描述自身而中断。
安装
需要一个正在运行的 plumb 守护进程(plumb serve 可作为名为 plumb 的 MCP 服务器访问 —— 参见 plumb setup dsh)。
作为 profile bundle(推荐)
dsh plugin --profile web add dsh-plumb-identity
dsh plugin --profile headless add dsh-plumb-identity
该包附带一个 dsh.bundle 补丁,因此安装该 bundle 也会以默认配置挂载插件。重启 dsh(正在运行的进程不会重新读取补丁层)。
选择一种挂载机制。 同时安装 bundle 并保留具有相同 id 的手动 insert 行会导致 DSH 在启动时崩溃 —— duplicate loader entry id: dsh-plumb-identity。补丁层会按行 id 合并配置覆盖,但两个 insert 永远不会合并。如果你在两者之间切换,请先移除另一个(dsh plugin --profile remove dsh-plumb-identity,或删除该行)。
手动补丁行(bundle 的替代方案)
仅当 bundle 未安装时 —— 追加到 ~/.dsh/cordis.patch.yml:
- insert:
- id: dsh-plumb-identity
name: dsh-plumb-identity
config:
serverName: plumb
移除该行,或在挂载它的补丁层之后加载的任意补丁层的顶层用覆盖行将其禁用(绝不要放在 insert 列表内 —— 那会插入一个无名行):
- id: dsh-plumb-identity
disabled: true
本地开发
将该行指向一个 checkout,而不是包名 —— 并且根据上面的警告,先移除或禁用 bundle 挂载:
- insert:
- id: dsh-plumb-identity
name: 'file:///absolute/path/to/dsh-plumb-identity/dsh-plumb-identity.mjs'
config: { serverName: plumb, logEvents: true }
配置(全部可选)
| 字段 | 默认值 | 含义 |
| ----------------- | -------------------- | ------------------------------------------------------------------------------ |
| serverName | plumb | 要守护哪个 MCP 服务器的工具(mcp____) |
| idPrefix | dsh | 生成的 id 的第一段 |
| purpose | dsh | 对话的 session_start purpose 标签 |
| subagentPurpose | dsh-subagent | 当会话头部显示 parentSession/delegationDepth 时的用途标签 |
| detail | brief | 主动式 session_start 的定向信息包大小 |
| excludeEnv | ["PAUTA_RUN_ID"] | 当设置了其中任一环境变量时完全跳过 |
| connectMarker | plumb | 与 stdio 命令匹配以识别 plumb 连接的子字符串 |
| logEvents | false | 每次调用的时间戳/捕获调试行 |
| sdkPath | DSH profile tree | MCP SDK 的 client/index.js 的绝对路径(非标准安装) |
excludeEnv 很重要:pauta 的 dsh 驱动会附加它自己的 plumb 关联语句(pauta-dsh--),而同一运行的第二个身份会造成干扰。
要清楚排除的代价。 被排除的运行不会挂载任何东西,因此它的 plumb 调用完全不携带身份。在共享连接上,这些匿名调用会依据该 CONNECTION 的 pin 进行解析,而这样的运行所设置的 pin 正是为其他所有 agent 的分片播种的来源——因此一次 pauta 运行可能会让一个 DSH 对话在另一个工作区上被播种。有两件事限制了损害:一旦连接上出现过两个身份,plumb 就会拒绝匿名的状态变更调用;并且(自 2026-09-16 起在 plumb main 中)声明被拒绝的 agent 会被门控——其携带路径的调用会按名称被拒绝,并给出 force: true 的补救措施,而不是悄悄解析到已播种的根。如果你更希望这次 pauta 运行由本插件归属,请移除这里的 PAUTA_RUN_ID,并让驱动通过相同的通道传递其运行 id——但请先核实驱动的契约;全面排除是有意为之,而非疏忽。
验证
identities and their workspaces, per agent
sqlite3 "file:$HOME/Library/Application Support/plumb/session_state.db?mode=ro" \
"SELECT logical_agent_id, workspace, source FROM pinned_workspace WHERE logical_agent_id != '';"
declared sessions (external_id = minted id, purpose = dsh / dsh-subagent)
ls -t "$HOME/Library/Application Support/plumb/sessions/" | head
当两个工作区中有两个对话外加一个子代理时,你应该看到 ≥3 个不同的 logical_agent_id,每个都固定到自己的工作区,并且守护进程日志中没有 pin 争用通知。plumb sessions 和 workspace_sessions 工具会实时显示相同的画面。
测试
npm test
封闭式——无 DSH、无 plumb、无网络(MCP SDK 是一个桩 fixture)。spike/probe.mjs 和 spike/observe.mjs 是现场诊断工具:通过 --patch 覆盖层将其中任一挂载到 dsh --profile headless 运行中,以便在升级后重新映射 DSH 内部结构。
针对假模型的端到端测试
npm run test:e2e
验证完整链路——真实的 DSH agent 循环、从工作树挂载的此插件、真实的 plumb——仅对 MODEL 进行脚本化(test/fake-model.mjs,一个本地 OpenAI 兼容服务器),因此它花费零 LLM 额度,且除 localhost 外不接触任何网络。每个场景都在一个一次性的 DSH_HOME 中运行,其中唯一配置的 provider 是本地 fake(错误路由的模型请求会因“unknown provider”而失败,而不是向真实密钥计费),并针对一个隔离的 plumb serve,其 HOME/XDG 根目录位于该场景的临时目录下——你的 DSH 配置文件和你的 plumb 状态都不会被触及。
三个场景,每个都对 plumb 自身的会话记录进行断言:
- tool-call——一次 plumb 工具调用;必须声明一个 purpose: dsh 且 external_id: dsh-* 的会话。
- text-only——没有 plumb 工具调用;不得声明任何内容(对照组)。
- subagent——agent 委托一个 subagent 进行 plumb 调用;必须声明一个 purpose: dsh-subagent 身份。
要求:一个 dsh 安装(从 $DSH_BIN 解析,否则从 $DSH_HOME / ~/.dsh 配置文件树解析,与 dsh 自身解析的完全一致)以及一个 plumb 二进制文件($PLUMB_BIN,否则为此检出目录旁的 ../plumb/plumb,否则为 PATH 上的 plumb)。使用 node test/e2e-mock-provider.mjs --mode subagent 运行单个场景;使用 --keep 或 E2E_KEEP=1 保留临时目录以便调试。
交互说明
- 一个遵循 ~/.dsh/AGENTS.md 并使用自身 id 调用 session_start 的模型不会改变任何东西:每次调用的 _meta 标记在 plumb 的身份解析中胜出,因此对话保持在其铸造的 id 之下。保留 AGENTS.md 规则——它们是插件缺失时的回退,也是模型接收 plumb 定向数据包的路径。
- 一个 plumb 连接只保留一条会话记录;plumb sessions 中的 external_id/purpose 显示该连接上最近的声明者。每个 agent 的隔离是 plumb 的分片状态(以 logical_agent_id 为键的 pinned_workspace/read_tracking),而不是会话记录。
- 单身份连接按设计在连接级别固定(“一个已声明的 id 不会武装任何东西”);分片和每个 agent 的固定从第二个不同身份开始生效,这正是多工作区 Web 场景。
- 被拒绝的声明是失败,而不是成功。 plumb 对被拒绝的 session_start 的回应是一个普通的工具 RESULT,携带 isError: true——而不是传输错误——因此 try/catch 会看到成功。此插件检查结果,并让 plumb 自身的 scope 决定恢复方式:details.scope = "agent" 意味着 force: true 只移动此 agent 的分片,因此它会以 force 重试一次;details.scope = "connection" 意味着 force 会移动连接上每个 agent 所解析依据的固定,因此它会被报告,且绝不会自动强制。来自同一 agent 的并发首次调用共享单个进行中的声明。
- 兼容性固定于 @deepseek-ai/dsh@0.1.1-rc.2 的字段位置(agent.id、agent.session.header.{cwd,parentSession,delegationDepth}、tools/execute 瀑布流、SDK client/index.js)。在 2026-09-16,这些字段已通过对照 @deepseek-ai/dsh@0.1.5-rc.1(搭配 MCP SDK 1.30.0)的检查重新验证:实时 DSH 对话仍会以本插件生成的 id 出现在 plumb 的 pinned_workspace 行中,且 SDK 的 ResultSchema 是一个声明了 _meta 的 z.looseObject,因此本插件读取的失败信封(_meta["dev.plumbkit/error"])能够通过解析。针对 0.1.5-rc.1 的 spike 探针未重新运行,且已测试的目标版本尚未提升——请将 0.1.1-rc.2 视为已测试,将 0.1.5-rc.1 视为已观察可正常工作。如果 DSH 升级改动了其中任何一项,插件会在 DSH 日志中大声地失败开放(fail open);请重新运行 spike 探针以重新映射,并请提交一个 issue。
许可证
MIT