dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把 OpenCode Zen 的免费模型作为一组 provider 接入 DeepSeek Harness,底层是受管、隔离的 OpenCode 运行时,并在设置页列出每个模型并可逐个检测。
在 DeepSeek Harness 里使用 OpenCode Zen 的免费模型。
把 OpenCode 的免费模型(big-pickle、LongCat、MiMo、Nemotron、Space Bunny 等)接进 DSH 的模型选择器,作为 opencode-xdbridge 分组使用,并在设置 → OpenCode-XD 里提供一个可视化的交互入口。
OpenCode Zen 的免费模型有一个服务端门禁:
FreeTierError: OpenCode's free tier can only be used from within OpenCode
实测(2026-09-29)确认:
https://opencode.ai/zen/v1/chat/completions 直接请求返回 403。opencode、opencode/1.18.33、Bun/1.2.0 等 9 种写法,全部 403。判据不是 UA。opencode serve 后,同一批免费模型立刻可用。permission 必须是 {'*':'ask'};改成 {'*':'deny'} 或 tools: {'*':false} 会立刻变回 403。所以本插件不自造协议技巧,而是:下载官方 OpenCode 二进制 → 在隔离环境里跑起来 → 在本地转成 OpenAI 兼容端点 → 注册给 DSH。
权限必须是
ask意味着"每个本地操作都要审批"。插件在本地把所有审批请求全部拒绝,所以运行时看起来像正常 OpenCode 会话(门禁放行),但本地一个动作都不会执行。真正执行的是 DSH。
从 npm(推荐,最省事):
dsh plugin --profile <profile> add dsh-opencode-xdbridge
从 GitHub 源码:
dsh plugin --profile <profile> add github:XDTrees/dsh-opencode-xdbridge
或者手动链接(开发用):
# 1. 链接插件到 profile
New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-opencode-xdbridge" `
-Target "D:\DSH\dsh-opencode-xdbridge"
# 2. 在 profile package.json 的 dsh.profile.bundles 里追加 "dsh-opencode-xdbridge"
# 3. 重启 DSH Desktop
首次启动会下载约 57 MB 的官方 OpenCode 运行时(只下载一次,缓存在数据目录)。
下载的是 OpenCode 官方二进制(opencode-windows-x64 这个 npm 包,57.4 MB)。它必须存在,因为免费模型的门禁只认真实 OpenCode 进程发出的请求——插件自身只有 71 KB,不含模型代码。
下载被设计成不会失败,只会慢:
如果确实很慢,可以自己下载一次并指给它,插件会直接复制而不联网:
# 方式一:把已装好的 opencode 指给它
set OPENCODE_BINARY_PATH=C:\path\to\opencode.exe
# 方式二:指定一个下载源
set OPENCODE_XDBRIDGE_RUNTIME_URL=https://your-mirror/opencode-windows-x64-1.18.33.tgz
重启后:
opencode-xdbridge),直接选即可。可用的模型随上游变化,插件每次启动都会重新读取。
设置页里这张卡片就是插件的控制台:
| 区域 | 作用 |
|---|---|
| 服务状态 | 状态点 + 一行当前状态(启动中 / 运行中 / 错误 / 重启中),错误时直接给「重试」 |
| 指标条 | 已发现 / 可用 / 待检测 / 不可用 四个计数 |
| 运行时信息 | OpenCode 版本、本地端点、数据目录 |
| 模型目录 | 每个模型一行:名称、推荐用途、能力徽章(推理 / 图片)、状态徽章、最近响应耗时 |
| 详情 | 点任意一行展开:推荐用途、上下文与输出上限、图片与工具能力、推理档位、最近一次调用的动作数 / 被拦截的本地尝试 / 转交的外部工具 |
| 操作 | 读取模型(重新向上游取清单)、检测全部(逐个发真实请求验证)、重启运行时 |
排序规则与 OW Bridge 一致:可用模型在前、待检测居中、不可用置底。
上游 OpenCode 的模型目录只提供 family、release_date、上下文与输出上限、图片与推理能力、推理档位——没有「推荐用途」字段。所以这一行是本插件按实测能力整理的,不是抄来的宣传语:
要改文案,编辑 src/client/index.js 里的 USE_NOTES,然后 npm run build。
导航行与页面标题使用同一个内联 SVG 标记(菱形 + 桥拱,呼应 OpenCode 与本插件的「桥」定位)。DSH 的 settings.section 契约不带图标字段,外壳对不认识的 id 一律画齿轮,所以导航图标是用 CSS mask 覆盖上去的(社区页面的通行做法)。
几个设计取舍:
一次检测失败并不等于「模型不能用」,所以失败被分成两类:
| 类别 | 含义 | 是否从选择器移除 |
|---|---|---|
| 超时 / 限流 / 服务端错误 | 这一刻够不到(不稳定) | 否,保留并标为「不稳定」 |
| 地区限制 / 鉴权失败 / 额度不足 | 确定性的拒绝 | 是,标为「不可用」 |
这个区分很重要:超时说不了模型本身的任何事,因为一次慢就把它从选择器里拿掉,等于把能用的模型也一起收走了。
每个模型每次检测最多尝试 2 次,每次独立计时(90 秒)——早期版本让两次尝试共用一个 60 秒预算,慢模型的重试还没跑就被掐断,于是把「只回文本」这种有效结论误报成超时。实测把预算分开之后,可用模型从 4 个恢复到 6 个。
检测失败不会让模型变成不可再检测:失败记录只影响它是否出现在选择器里,模型始终留在目录中,下一次「检测全部」会重新试。
插件不会把模型的原始窗口直接报给 DSH,而是报一个可用预算:
可用 = (声明窗口 − 输出预留) × (1 − 15% 安全余量)
这么做的原因是一个实测过的故障:某个会话长到 约 144 万 token,而免费模型的窗口在 20 万~105 万之间。DSH 看到"窗口还够"就没有压缩,把请求发了出去,上游回了一句完全不含原因的 invalid_request_error: invalid request。用户看到的现象是"换哪个模型、选哪个档位都报错",真实原因只是上下文超出了每一个模型的容量。
所以现在:
设置页的模型详情里会同时显示:可用上下文 / 声明的原始窗口。
中文的 token 估算按每字符 ≈ 1 token 计算,而不是"字节数 ÷ 4"。中文在 UTF-8 里占 3 字节/字,用字节估算会严重低估——这正是早期误判的原因之一。
配置写在 profile 的 settings.yaml 里,命名空间 opencode-xdbridge:
opencode-xdbridge:
dataDir: D:\DSH-data\opencode-xdbridge # 运行时/日志存放位置
binaryPath: C:\path\to\opencode.exe # 用已有的 OpenCode,不下载
runtimeVersion: 1.18.33 # 固定版本
autoRefresh: true # 启动后重新读一次模型清单
| 字段 | 说明 | 默认 |
|---|---|---|
dataDir | 受管运行时、日志、状态目录 | <DSH home>/opencode-xdbridge |
binaryPath | 使用已有的 OpenCode 二进制 | 自动下载官方版本 |
runtimeVersion | 固定 OpenCode 版本 | 最新版 |
autoRefresh | 启动 15 秒后重读一次免费模型清单 | true |
也可用环境变量 OPENCODE_XDBRIDGE_DATA_DIR 指定数据目录。
DSH Harness
│ (pi-ai provider "opencode-xdbridge")
▼
lib/adapter.js ──── pi-ai createProvider + openAICompletionsApi
│
▼
lib/shim.js ─────── 127.0.0.1 随机端口,进程内随机密钥
│ (OpenAI /v1/chat/completions ↔ JSON 信封)
▼
lib/backend.js ──── 会话管理、权限拦截、信封校验
│
▼
lib/runtime.js ──── 隔离的 opencode serve(独立 XDG 根 + 随机密码)
│
▼
OpenCode Zen 免费模型
| 文件 | 职责 |
|---|---|
lib/index.js | 插件入口:编排启动顺序,注册 provider,挂载设置页路由 |
lib/platform.js | 数据目录与平台包名 |
lib/runtime.js | 下载、启动、监督隔离的 OpenCode 运行时 |
lib/shim.js | 回环 OpenAI 兼容端点(安全边界所在) |
lib/backend.js | 一次推理回合:会话、权限拦截、信封校验 |
lib/protocol.js | OpenAI ↔ JSON 信封的双向转换与校验 |
lib/handoff.js | 被拦截的本地动作 → 外部工具调用的映射 |
lib/probe.js | 模型检测(真实请求 + 动作判定 + 一次重试) |
lib/adapter.js | pi-ai provider 组装 |
lib/catalog.js | 免费模型目录 + 每个模型的最近观测结果 |
lib/web-status.js | 设置页的同源路由(状态 / 读取 / 检测 / 重启 / 详情) |
lib/status-paths.js | 主机与浏览器两侧共享的路由常量与文档结构 |
src/client/index.js | 设置页卡片(浏览器侧,手写 CJS) |
scripts/build-client.mjs | 把卡片包成宿主要求的模块加载器格式 |
对外发布涉及三条各自独立、各自会失败的通道:
| 通道 | 由什么触发 | 详细说明 |
|---|---|---|
| npm 包 | 推 v* tag → GitHub Actions(OIDC) | release/npm.md |
| GitHub Release | 手动,维护者本人身份(运行时二进制的兜底源) | release/github-release.md |
| 插件商店 | 往 awesome-dsh-plugin 提 PR,等维护者合并 | list/ |
发新版本的逐步操作见 release/checklist.md。
商店收录只是发现渠道。提了 PR 不等于会显示,但不影响安装——
dsh plugin add dsh-opencode-xdbridge与dsh plugin add github:XDTrees/dsh-opencode-xdbridge都是现在就能用的。
127.0.0.1 随机端口;校验 Host/Origin 必须是回环(防 DNS rebinding 与浏览器页面访问);Bearer 常量时间比较;请求体上限 8 MB。npm run build # 把 src/client/index.js 包成 lib/client.js
npm test # 单元测试 + 四个独立校验(bundle / 渲染 / 声明 / 代理默认值),无需网络
npm run test:smoke # apply() 注册 + 真实 PiAiAdapter + 检测流程
npm run test:e2e # 端到端(需 OPENCODE_XDBRIDGE_E2E=1)
单独跑:
node test/client-bundle.test.mjs # 模拟宿主加载器,验证卡片注册与渲染
node test/client-declaration.test.mjs # 用宿主自己的代码校验 dsh.client 声明
node test/proxy-default-check.mjs # 静态断言:代理变量没被写回 FORWARDED_ENV
node test/proxy-live.mjs # 真实跑一次请求,验证运行时能到上游
node test/apply-smoke.mjs # 用桩 ctx 验证 apply() 注册与全部路由
node test/harness-smoke.mjs # 通过真实 PiAiAdapter 走一次 stream()
node test/probe-smoke.mjs # 真实跑一次模型检测
node test/profile-load-check.mjs # 用 DSH 自己的 loader 校验 profile
改了
src/client/index.js必须重新npm run build,否则 DSH 拿到的是旧的lib/client.js。
集成测试会真实下载/使用官方 OpenCode 二进制并产生真实上游请求,因此默认关闭,需要 OPENCODE_XDBRIDGE_E2E=1 显式开启。
dsh plugin add dsh-opencode-xdbridge 现在就能用。详见 list/。dsh-opencode-xdbridge,npm 规范),设置页显示为 OpenCode-XD / OpenCode-XDbridge。MIT