pi2dsh

by weijiafu14

13 工具与能力github 检测到 manifest package.json#dsh收录于 08-16

Bridge the Pi and DeepSeek Harness ecosystems: one Pi Host ABI runs unmodified Pi extensions as native DSH plugins. 打通 Pi 与 DSH 生态。

安装

dsh plugin --profile web add github:weijiafu14/pi2dsh

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗

安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。

README

目录

English | 中文

让 Pi 生态的插件原样跑在 DeepSeek Harness 上。

dsh plugin add pi2dsh          # 装一次
dsh plugin add <任意 Pi 插件>   # 之后想装谁装谁,直接用 npm 原包

为什么有这个项目

DeepSeek Harness(DSH)的 理念值得押注——可重建的持久会话日志、干净的服务组合、一条真能讲清楚的 agent 循环。它现在缺的是插件生态:还处在早期,而大家开箱就想要的那些能力——联网搜索、 记忆、代码导航、子代理、看图——大多还没人为它写。

Pi 的生态已经成熟:几百个已发布的包,很多都有真实用户。

pi2dsh 是一层兼容层,把 Pi 的公开扩展 ABI 实现在 DSH 的原生服务之上,让 Pi 包 以发布的原样跑在 DSH 上——不 fork、不打补丁、不为每个包写适配器。你像装任何 DSH 插件一样装一个 Pi 插件,它就能用。

同时,pi2dsh 也是对 DSH 架构的一次覆盖完整能力面的持续实战检验。我们不是为单个插件 打补丁,而是在检验:Pi 插件依赖的模型、工具、会话、交互、资源和客户端能力,能否 只通过 DSH 对外开放的服务与扩展点,保持原有逻辑和生命周期。如果这些能力都能在 DSH 上成立,就说明 DSH 为构建 Agent 及其插件生态所设定的架构目标,至少在这个方向上 经受住了真实生态的验证;任何必须旁路、降级或无法表达的地方,也会准确暴露它仍缺少的 架构能力。

安装

一次引擎,之后想装谁装谁:

dsh plugin --profile web add pi2dsh
dsh plugin --profile web add @kassing/pi-vision

然后重启 dsh——插件在启动时挂载。

profile 必须带一个界面 bundle。 DSH 内置模板是 web 与 headless;产品 自己装了界面的自定义 profile 也完全有效,例如 dsh-tui profile 里的 @deepseek-harness-tui/dsh-tui。只有随手新建、没装任何界面层的空 profile 才会 启动后没人驱动;这种情况先把目标界面加进 dsh.profile.bundles。

就这一种方式。没有转换步骤,没有生成产物,不用构建。引擎会读出你 profile 里的 Pi 包(每一个都是你显式装的),用同一个桥实例挂载它们:一个模型目录、一个登录、 一个凭证存储、一个升级单元。

日常操作:

要做的事 命令
装插件 dsh plugin add <包名>(然后重启 dsh)
卸插件 dsh plugin remove <包名>——先卸插件,再卸引擎
升级插件 dsh plugin add <包名>@latest,引擎不动
升级引擎 dsh plugin add pi2dsh@latest,插件不动
升级前先体检 npx pi2dsh inspect <包名>@<版本>

两条安装期提示值得提前知道:

  • ERR_PNPM_IGNORED_BUILDS:pnpm 默认拦截依赖的构建脚本。在 $DSH_HOME/profiles/web 里跑 pnpm approve-builds,或者把提示 里的包在该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下设成 true, 然后重跑 add。(这是你的决定权,桥不会绕过它。)
  • 刚发版后 add 装到了旧版本:pnpm 的 minimumReleaseAge 会跳过刚发布不久 的版本。显式钉版本即可:dsh plugin add pi2dsh@<版本>。

需要 Node.js 22.19+ 和 DeepSeek Harness。

走一遍:让纯文本模型能看图

这个例子最能说明这座桥值什么。DeepSeek 系列是纯文本模型,DSH 没法把图片发给它。 Pi 生态里正好有插件干这件事:把图片交给你指定的视觉模型,再把分析结果注入回对话。

1. 装插件

dsh plugin --profile web add @kassing/pi-vision

2. 给它配一个多模态模型

这一步是关键——插件需要它自己的视觉模型,这个模型和你聊天用的那个不是同一个。 任何 OpenAI 兼容的视觉端点都行(OpenRouter、DashScope/Qwen-VL、自建 vLLM……)。

插件从环境变量读自己的配置——这是 Pi 插件生态的主流做法,对你来说就是一个纯粹的 DSH 侧动作:

export VISION_BRIDGE_BASE_URL=https://openrouter.ai/api/v1
export VISION_BRIDGE_MODEL=qwen/qwen2.5-vl-72b-instruct
export VISION_BRIDGE_API_KEY=$OPENROUTER_API_KEY

配到这里就能用了。如果你还想让这个视觉模型出现在 DSH 自己的模型选择器里(这样 你也能直接和它聊),就再把它按普通 DSH 路由配一份——$DSH_HOME/settings.yaml 的 llm-pi-ai: 段:

llm-pi-ai:
  providers:
    openrouter:
      baseUrl: https://openrouter.ai/api/v1
      apiKeyEnv: OPENROUTER_API_KEY
      models:
        - id: qwen/qwen2.5-vl-72b-instruct

这两处都是普通的 DSH 配置。桥自己不持有任何模型配置,也没有任何需要你手写的 Pi 格式文件。

视觉后端别选 GPT-5/o 系列:那一代模型会拒绝非默认的 temperature,而有些视觉 插件会带这个参数。

3. 问一张图

CLI 里直接提路径:

dsh --profile web "$PWD/photo.png 这张图是什么颜色?只答一个词。"

Web 里直接粘图——哪怕你的主模型是纯文本的。DSH 正常情况下会拒绝给纯文本模型 上传图片,所以引擎会给模型目录里每一个纯文本路由自动注册一个贴图伴生路由, 名字是 <路由>-vision。在模型选择器里选它(显示为 “+ Vision Bridge” 分组), 粘图,提问。

你会看到:你消息里的图片块变成引导文本,一行 pi2dsh:@kassing/pi-vision 的 上下文注入带着分析结果,然后你的纯文本模型照常回答图片内容。像素从没进过纯文本 那条线。

伴生路由是全自动的。想关掉、或者只给某些路由开,在引擎的插件配置里设 visionCompanions($DSH_HOME/profiles/web/cordis.patch.yml):

- id: pi2dsh
  config:
    visionCompanions: false

完整可跑版本(含纯色探针图):examples/vision-bridge。

现在到底哪些真能用

分两级,这两件事不是一回事。

第一级——端到端实测过,配可跑示例

有人真坐下来,在真实 DSH loop 上用了这个插件的真功能,亲眼看到它工作。 要信就信这张表。

插件 验证了什么 在哪验的 示例
@kassing/pi-vision 图片委托给视觉模型;贴图伴生路由;分析结果注入纯文本模型的这一轮 CLI + Web vision-bridge
@crazygit/pi-codex-image-gen ChatGPT/Codex OAuth 调 gpt-image-2 生图;本地参考图走 DSH 审批后上传;编辑图片;原生附件存储并在 Web 内直接显示 CLI + Web codex-image-gen
pi-btw /btw <问题> 跑成 DSH 子代理界面里的真子会话;/btw-inject;/btw --save;主会话保持干净 CLI + Web side-conversation
pi-powerline-footer 终端状态条(模型、思考档位、项目、上下文用量)画进 DSH 的 widget dock,带颜色 Web presentation-surfaces
pi-mcp-adapter 完整管理界面画进 dsh-TUI;stdio/Streamable HTTP/SSE;发现、直连/代理/脚本调用、resources、prompts、图片、结构化内容、MCP Apps、审批、elicitation、sampling、取消与重启全部穿过 DSH 运行时;原生 /mcp 与 /pi-mcp 共存 dsh-TUI tui-mcp · 证据矩阵
pi-provider-alibaba 阿里云 Token Plan(中国区)专属 key:实时目录、冷启动动态模型、完整工具闭环与重启均已实测;包也声明 Coding/API 路由,但必须分别使用不可混用的专属凭证 CLI + Web alibaba-token-plan
pi-vision-tool 工具注册,且带一个 DSH 需要转换的 JSON Schema 形状(anyOf → oneOf) CLI + Web —
pi-approval-guardian 每次工具调用先由第二个模型审批;放行与拒绝两条路都看到了 CLI(裸环境) —
pi-hermes-memory 跨会话记忆:一个进程写入,另一个全新进程读回 CLI —

后三个的示例还没写。按本项目自己的规矩,补示例前必须重新端到端验证一遍,所以 这张表如实标出今天谁有示例。

第二级——能挂载,且注册面能被探针调起来

Pi 目录里月下载量前 50 的包,每个都在真实 DSH 运行时里挂载,然后用黑盒探针 调用。状态截至 2026-08-14;逐包的机器可读证据在 community/。

50 个里 47 个探针调用成功 · 1 个没有可探测面 · 2 个待复跑。

这一级不能说明的事:不能说明这个插件的真功能按你的用法能跑通。探针是拿合成 参数去调一个注册面,用户跑的是一整条工作流。pi-btw 就是最好的反例——它在这张 表里挂着"working"挂了好几周,而真实会话里 /btw <问题> 是直接失败的:这个功能 需要补两个 ABI 缺口(Pi 公开可写的 AgentState.messages,以及给桥接命令声明输入 描述符),而任何探针都不会碰到它们。两个缺口都在 0.11.0 修好了,而且都是通用修 复——同样用法的插件一起解锁。

所以下面这张表请读成**"桥覆盖了这个插件用到的面"**,而不是"这个插件已知可用"。 你要是试了哪个,不管成没成,反馈回来都有用。

能力 插件
MCP pi-mcp-adapter · pi-mcp-extension
联网搜索与抓取 pi-web-access · pi-deepseek-search · pi-web-search · @ollama/pi-web-search · @juicesharp/rpiv-web-tools
代码导航与编辑 pi-lens(ast-grep)· @narumitw/pi-lsp · pi-readseek · @ff-labs/pi-fff · pi-landstrip · pi-hashline-edit-pro¹
子代理与后台任务 @tintinweb/pi-subagents · @gotgenes/pi-subagents · pi-background-tasks² · @mjasnikovs/pi-task
记忆 pi-hermes-memory · pi-goosedump
计划与目标 @narumitw/pi-goal · pi-goal-list-loop-audit · @narumitw/pi-plan-mode · @juicesharp/rpiv-todo
问你 / 审批 @juicesharp/rpiv-ask-user-question · pi-ask-user · @gotgenes/pi-permission-system · @juicesharp/rpiv-advisor
侧边对话 pi-btw · @narumitw/pi-btw
模型与 provider pi-provider-litellm · pi-llama-cpp · pi-prompt-template-model · @vigolium/piolium
图像 @kassing/pi-vision(见上文)· @amaster.ai/pi-image-gen
外部集成 @llblab/pi-telegram · pi-cursor-sdk² · @howaboua/pi-codex-conversion · pi-agent-browser-native² · pi-harness-runtime
提示词与工作流 pi-simplify · pi-fabric² · mitsupi · pi-cc-extensions · pi-rtk-optimizer · pi-interview¹
终端装饰 pi-powerline-footer · @narumitw/pi-statusline · pi-zentui
语音 @juicesharp/rpiv-voice
用量统计 @alexanderfortin/pi-deepseek-usage³

¹ 能挂载,调用验证待复跑(装置侧的失败,不是包或桥的问题)。 ² 业务逻辑真跑到底了,然后拒绝了合成的探针参数——属于正常工作、参数校验正确。 ³ 纯事件钩子包:四个订阅全都挂上了,但每个处理器都要求有活的 DeepSeek 计费会话 (它拉账单用量并渲染 footer),黑盒探针没有可安全断言的调用面。

前 50 之外的包不是另一类情况——桥里没有任何逐包代码。哪个包撞上 ABI 缺口,补上 那个缺口,撞同一处的包一起解锁。

第一级是靠一个一个啃第二级长出来的。完整的验证阶梯、以及每一级分别能证明什么、 不能证明什么:support matrix。

技术架构

三层,谁也不跨谁:

┌─ Pi 插件 ───────────────────────────────────────────────────┐
│ 原样的 npm 包。它看到的是一个完整的 Pi 宿主:三个 Pi 运行时  │
│ 导入、registerX、ctx.*、33 个生命周期事件。它永远不知道      │
│ DSH 的存在。                                                │
└──────────────────────────┬──────────────────────────────────┘
                           │  Pi 的公开 ABI
┌──────────────────────────▼──────────────────────────────────┐
│ pi2dsh——翻译官,也是唯一同时懂两边词汇的地方。目录投影、    │
│ 事件桥、会话与子代理桥、凭证、vendored 的 Pi 逻辑。          │
└──────────────────────────┬──────────────────────────────────┘
                           │  一个普通 DSH 插件 + llm adapter
┌──────────────────────────▼──────────────────────────────────┐
│ DeepSeek Harness。它只看到一个普通插件,永远不知道 Pi 的存在。│
└─────────────────────────────────────────────────────────────┘

DSH 有两半,桥也有两半。上面那根柱子是服务端;浏览器壳有自己的插件面, 当一个 Pi 能力是"形态"而不是"行为"时,它落在那边:

┌──────────── DSH 服务端(cordis) ───────────┐  ┌──────── DSH 浏览器壳 ────────────┐
│ 服务 · waterfall · durable 事件             │  │ dsh.client + exports "./client"   │
│                                             │  │ slot 注册表(ui-slots)           │
│ pi2dsh 引擎                                 │  │   shell.overlay  ← 浮层与 pill    │
│   工具 · 命令 · 模型 · 会话                  │  │   header.utilities ← 头部文本     │
│   子代理桥 ───────────────────┐             │  │   input.dock ← widget             │
│   browser-state 注册表        │             │  │   composer.dock ← working/底部    │
│     GET /pi2dsh/browser-state┼── 自有通路 ─┼──┼─▶ 四个座位,共用一个轮询           │
└───────────────────────────────┴─────────────┘  └───────────────────────────────────┘

浏览器半边用的数据走本包自己的路由,不走 DSH 的 typed Remote 体系——那是 一等公民的代码生成契约,仓外插件跟自己的 UI 说话就该自带通道。一个会话一个 payload,喂给所有座位:侧边对话浮层,以及 Pi 的呈现面(status、widget、header、 footer、title、working/thinking 类),都画在宿主自己的 slot 座位里,而不是再造 一套。另外两条宿主规则决定浏览器半边能不能被装载:包必须导出 ./package.json (宿主按子路径解析清单),./client 产物必须是闭包工厂格式而不是普通 ESM。

保证它靠谱的几条标准:

  • DSH 已经有的东西,桥绝不再造一遍。 工具进 DSH 的工具注册表,模型进 DSH 的 llm 配置,只有 server 配置的 MCP 交给 dsh-mcp-client,skills 交给 dsh-skill-filesystem,提问交给 DSH 的 user questions。用户显式安装的 Pi 能力包可以保留它自己拥有的行为;桥只映射公开宿主面,不抄它的 transport。
  • 不造桥私有的用户世界。 常规配置仍然全是 DSH 形状:DSH 设置、命令、凭证。 如果一个被安装的能力包明确自带管理面,就保留并在冲突时标出来源——dsh-TUI 的 /mcp 不动,Pi 管理面叫 /pi-mcp。
  • 零逐包特判。 核心里没有任何 if (packageName === …)。修一个 ABI 缺口, 撞上它的包一起解锁。
  • 绝不伪装成功。 映射不了的能力会如实告诉你——同一个插件同一项能力只提示 一次,讲人话。如果某个插件在启动期就需要这样一项能力,它会被整包标成不可用并 给出卸载建议,而不是半死不活地跑着。
  • 验证过才算数。 每项能力都有公开 API 契约测试,并且必须在它声称支持的每个 DSH 界面上端到端跑通才会发布。

这件事正在检验 DSH 什么

pi2dsh 同时也是一套会执行的 DSH 插件架构压力测试。Pi 提供的不是为了迎合 DSH 现编的几个 demo,而是一套已经被大量真实插件用过的公开 ABI,所以它很适合回答: DSH 所说的“能力由插件自由组合”,到底走到了哪一步。

目前的结论不是简单的“好”或“不好”,而是边界已经很清楚:

  • DSH 对替换一整项能力的公开 seam 是成立的:工具、命令、模型 adapter、用户 提问、原生子会话和浏览器 slot 都已经承接住真实 Pi 能力。
  • 压力集中在从内部扩展已有能力:仓外插件新增一种持久会话事件、拦截真正发出的 provider 请求/响应、在压缩发生前改变决定、在项目资源加载前参与 trust。
  • pi2dsh 用 sidecar 或另一条 adapter 把功能绕通,对用户有价值,但不能算 DSH 原生架构已经承接成功。我们会把“功能可用”和“宿主 seam 完整”分开记。

一个容易说错的例子:pi-btw 的回答已经是真正的 DSH child session,宿主能打开、 续聊和恢复;sidecar 存的是 Pi 自定义 entry 等 DSH 仓外插件目前无法写进原生日志的 事实,不是把整个子会话伪造了一遍。模型侧也一样:自带 transport 的 Pi provider 可以注册成原生 DSH route;从 DSH rc.8 开始,只声明目录的 provider 也有了完整的官方 路径——pi2dsh 把端点、输入模态、推理档位和 DSH 已开放的协议 compat 翻译成 llm-pi-ai profile,真正请求仍由 DSH 发出。

项目采用一套统一的 Pi → DSH 架构映射标准: 具体 Pi 接口 → Pi 能力契约 → DSH 承载机制 → 公开 seam → 真实插件验证 → 五级结论。 这是一条统一推理路线,不是额外的运行时层。可扩展的分支维护在手写的 架构模型知识树,真实场景维护在 逐插件验证记录,三类总体判断维护在 架构结论。架构分类不再由 JSON 总账或生成器 产生;曾经观察到的 111 条 Pi 规则和 45 个 DSH 子系统只是带版本的调查快照,不是固定 总量或完整性证明。这样既能从总体看到已经适配的能力,也能从任一插件下钻到它用了哪些 Pi 能力、落到哪些 DSH 机制、实际达到哪一级。 当前仍有 4 个 DSH 缺口;第 5 个历史缺口 DSH-ARCH-002 已由 rc.8 上游修复。 这些是已经坐实的发现,不是已经完成全覆盖。 当前已向上游提交的实证包括 #2708:让仓外插件安全写持久事件 和 #3076:llm-pi-ai 丢 provider compat 字段; 后者已在 rc.8 的 profile schema 中解决。

Pi 的开放能力在 DSH 上怎么落

Pi 包能碰到的每一个面,以及它落到 DSH 的什么位置。下面这些表是从桥在运行时真正 查的那份规则生成的,所以不会和代码脱节。

针对固定的 Pi 0.84.1,当前生成目录有 111 条上游形状的规则行。桥另外保留了一个 兼容扩展 unregisterTool;它会出现在工具细表中,但明确不计入这个总数。 sessionManager 等嵌套对象仍可能用一行代表多个方法,架构审计会明确写出这层边界。

能力域 Pi 面数 状态
工具 11 2 语义一致 · 9 已映射并写明差异
命令、flag、编辑器输入 13 13 已映射并写明差异
消息、上下文、agent 循环 20 9 语义一致 · 11 已映射并写明差异
会话与侧边对话 24 7 语义一致 · 17 已映射并写明差异
模型、provider、凭证 15 1 语义一致 · 12 已映射并写明差异 · 2 不提供
向用户提问与渲染 24 5 语义一致 · 19 已映射并写明差异
项目环境与资源 4 1 语义一致 · 1 已映射并写明差异 · 2 不提供
合计 111 25 语义一致 · 82 已映射并写明差异 · 4 不提供

另外还有 Pi 三个运行时包(pi-coding-agent、pi-tui、pi-ai)的 203 个 导入符号,由 vendored 或 headless shim 提供——所以插件自己钉的 Pi 版本永远不会 被加载,清单见导入的 Pi 运行时符号。

每个能力域页面对每一个面都写清它属于哪个 Pi 能力契约、理论上应落到哪个 DSH 承载 机制与公开 seam、当前代码实际上如何实现。新增接口如果没有能力归属或理论映射,文档 检查会直接失败。

从能力索引开始看。机器可读版:pi2dsh matrix --json。

用订阅登录也能用:DSH 本身只提供静态 HTTP header,桥补上了 Pi 生态的交互式 OAuth 层。任何声明了 oauth 块的 Pi provider 包都会得到一条可用的 /login <provider>,跑的是这个包自己的协议代码——Pi 官方的四条流程(OpenAI Codex、Anthropic、GitHub Copilot、Kimi Code)内置;只装好引擎、还没装第一个社区 Pi 包时也能直接使用。凭证按 Pi 的 auth.json 语义持久化,并通过标准的 dsh-credentials provider 按请求解析,所以你的订阅能 驱动 DSH 原生 llm 路径上的真实调用。细节见模型。

哪些是刻意不提供的,以及为什么:运行时装包和独立模型运行时属于宿主及其安全 门;provider 的 payload/header/response 拦截应该写成 DSH llm adapter;项目信任 是宿主的决定。见模型与 项目环境。

我们自己欠的那一块:插件自绘卡片。Pi 插件可以自带渲染器,目前这类注册我们接 下来但不调用,所以这种笔记会显示成原生的上下文注入行——内容你和模型都拿得到, 只是没有插件自己的样式。客户端半边已经在并占着四个座位(侧边对话浮层、头部、 widget 区、working 区)——卡片渲染器正是它还没画的那部分。

示例

每一项验证过的能力都配一个完整可跑的 example。example 里的每条命令都在真实 DSH loop 上实际跑过才会进来。

示例 你能得到什么
vision-bridge 纯文本模型回答图片问题——CLI 与 Web 双端,附探针图
codex-image-gen 用 ChatGPT/Codex 订阅生图和改图,包含 DSH 上传审批与 Web 内直接显示结果
side-conversation /btw <问题> 在 DSH 原生子代理界面里开一条侧边线程,主会话保持干净
presentation-surfaces 真插件(pi-powerline-footer)的终端界面画进 DSH Web 座位,附 top50 里哪些 Pi 插件会画界面
subscription-login 用 ChatGPT / Claude / Copilot / Kimi 订阅账号当 DSH 的模型:/login、登录后自动建路由与凭证
gateway-compat 私有 / 国内 / 代理网关拒收 developer 角色:rc.8 官方 profile 如何把 Pi compat 声明送到真实请求(附透传录制代理)
alibaba-token-plan 通过原版 Pi provider 使用阿里云百炼 Plan;包含动态 DeepSeek 模型、工具闭环与重启验证
custom-gateways 按 DSH 官方方式接任何 OpenAI 兼容网关,每个 Pi 插件都能看到它
tui-mcp 保留 dsh-TUI 原生 /mcp,把 Pi 生态管理面作为 /pi-mcp 加进来,并让完整的宿主相关 MCP 功能面穿过 DSH 运行时

其它工具

除了引擎,CLI 还有几个辅助命令:

npx pi2dsh inspect <包名>@<版本>   # 升级前的兼容性报告
npx pi2dsh matrix --json           # 完整能力矩阵
npx pi2dsh mcp-config              # Pi 的 mcpServers 配置 → DSH 官方 MCP 条目

开发与验证

pnpm verify                 # 类型检查 + 契约测试 + 打包检查
pnpm audit:community        # 前 50 静态筛查
pnpm test:community         # 深度运行时 + 官方插件管理器 + e2e
DEEPSEEK_API_KEY=… pnpm test:live    # 真实模型验收(key 只从环境读)
CODEX_AUTH_FILE=… pnpm test:codex-image # 真 OAuth 生图 + 参考图编辑 + Web 像素显示

逐项能力的验收证据:docs/acceptance.md。 工作标准:CLAUDE.md 与 docs/STANDARDS.md。

许可

MIT。vendored 的 Pi 源码保留其上游 MIT 许可 (src/compat/vendor/PI-LICENSE);生成的 bundle 保留拷贝过来的上游许可与声明 文件。

原始 README: https://github.com/weijiafu14/pi2dsh/blob/main/README.zh.md ↗