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

Zen 免费模型适配器 1624318455/dsh-plugin-adapter

DeepSeek Harness
16243184555 天前有提交已提供中文文档扫描:含敏感能力

在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。

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

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

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 1624318455/dsh-plugin-adapter
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

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

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

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

✗npm 包dsh-plugin-adapter(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/28 02:51:42

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 25 处,展示前 25 条)
  • 执行外部命令来自配置/变量
    packages/plugin/src/agent-process.ts:89
    const child = spawn(this.agentPath, this.args, { stdio: ['ignore', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    packages/plugin/src/agent-process.ts:262
    const killer = spawn('taskkill', args, { stdio: 'ignore' })
  • 读取本地文件
    packages/plugin/src/config.ts:205
    await stat(path)
  • 读取本地文件
    packages/plugin/src/config.ts:218
    const existing = (await readFile(paths.tokenPath, 'utf8')).trim()
  • 写入本地文件
    packages/plugin/src/config.ts:222
    await mkdir(dirname(paths.tokenPath), { recursive: true })
  • 写入本地文件
    packages/plugin/src/config.ts:223
    await writeFile(paths.tokenPath, token + '\n', { encoding: 'utf8' })
  • 写入本地文件
    packages/plugin/src/config.ts:225
    await chmod(paths.tokenPath, 0o600).catch(() => {})
  • 写入本地文件
    packages/plugin/src/config.ts:253
    await mkdir(paths.dataDir, { recursive: true })
  • 写入本地文件
    packages/plugin/src/config.ts:255
    await writeFile(tmpPath, JSON.stringify(config, null, 2), 'utf8')
  • 删除本地文件
    packages/plugin/src/config.ts:256
    await rm(paths.configPath, { force: true })
  • 写入本地文件
    packages/plugin/src/config.ts:257
    await rename(tmpPath, paths.configPath)
  • 读取本地文件
    packages/plugin/src/data-dir.ts:74
    return statSync(path).size
  • 写入本地文件
    packages/plugin/src/data-dir.ts:86
    mkdirSync(to, { recursive: true })
  • 读取本地文件
    packages/plugin/src/data-dir.ts:87
    for (const entry of readdirSync(from, { withFileTypes: true })) {
  • 读取本地文件
    packages/plugin/src/data-dir.ts:92
    if (!existsSync(target)) throw new Error(`copy verification failed: ${target}`)
  • 读取本地文件
    packages/plugin/src/data-dir.ts:123
    if (existsSync(newDir)) {
  • 读取本地文件
    packages/plugin/src/data-dir.ts:128
    if (!existsSync(legacyDir)) {
  • 写入本地文件
    packages/plugin/src/data-dir.ts:129
    mkdirSync(newDir, { recursive: true })
  • 写入本地文件
    packages/plugin/src/data-dir.ts:136
    renameSync(legacyDir, backup)
  • 读取本地文件
    packages/plugin/src/data-dir.ts:142
    if (existsSync(legacyDir)) {
  • 删除本地文件递归
    packages/plugin/src/data-dir.ts:161
    rmSync(backup, { recursive: true, force: true })
  • 写入本地文件
    packages/plugin/src/index.ts:90
    void writeFile(
  • 读取本地文件
    packages/plugin/src/index.ts:346
    if (existsSync(sibling)) return sibling
  • 发起网络请求
    packages/plugin/src/provider.ts:97
    const response = await fetch(providerBaseURL(port) + '/models', {
  • 发起网络请求
    packages/plugin/src/provider.ts:113
    const response = await fetch(`http://127.0.0.1:${port}/healthz`, { signal: controller.signal })
扫描于 2026/10/31(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

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

功能亮点

  • 接入免费模型开聊
  • 网关兼容补丁

OpenCode Zen 免费模型的 DSH 适配器(维护分支,含网关兼容补丁)

README

由 DeepSeek 最新模型翻译生成
dsh-plugin-adapter 在 DSH(DeepSeek Harness)里原生使用 OpenCode Zen 的免费匿名模型。 无需 API Key。无需注册。无需额外进程。 dsh-plugin-adapter 会向 DSH 注册一个原生的 LlmAdapter,直接流式对接 OpenCode Zen 的匿名免费通道——也就是 OpenCode 官方 CLI 无需登录即可使用的那批免费模型,它们会以 zen-free 这个常规 provider 出现在你的 DSH 模型选择器里(opencode2dsh 保留为旧会话的兼容别名)。 插件发出的请求与 OpenCode CLI 的流量完全同形(相同的 User-Agent、相同的关联请求头),模型目录通过三级回退链保持新鲜。不用登录任何账号,也不用自己部署任何东西。
展开完整文档(README 剩余 1 节)
dsh-plugin-adapter

在 DSH(DeepSeek Harness)里原生使用 OpenCode Zen 的免费匿名模型。

无需 API Key。无需注册。无需额外进程。

dsh-plugin-adapter 会向 DSH 注册一个原生的 LlmAdapter,直接流式对接 OpenCode Zen 的匿名免费通道——也就是 OpenCode 官方 CLI 无需登录即可使用的那批免费模型,它们会以 zen-free 这个常规 provider 出现在你的 DSH 模型选择器里(opencode2dsh 保留为旧会话的兼容别名)。

插件发出的请求与 OpenCode CLI 的流量完全同形(相同的 User-Agent、相同的关联请求头),模型目录通过三级回退链保持新鲜。不用登录任何账号,也不用自己部署任何东西。

特性

- 零凭据、零配置——匿名通道不需要任何 Key;装好、重启、开聊
- 原生 adapter,无 sidecar——一个 npm 包,没有子进程、没有二进制、没有本地端口(旧版 Go sidecar 不随包发行,见 legacy/)
- CLI 同形伪装——请求携带 OpenCode CLI 的 User-Agent 和整套会话/请求/项目关联头,按会话派生
- 思考等级可选——带推理的免费模型在 DSH 模型选择器里出现思考等级选项(模型声明档位的按声明展示,其余提供 Off/Minimal/Low/Medium/High);Off 向上游发送 reasoning_effort: "none" 真正停思考,不选则保持上游默认
- 实时目录 + 三级回退——上游实时列表 ∩ 免费判定(models.dev 价格为 0,或名字带 -free 由通道本身免费供应),断网时依次回退到磁盘缓存与已验证的静态名单
- 自愈能力——启动期快速重试、周期刷新,并落盘健康快照便于排查
- 规范的错误呈现——上游故障(限流、鉴权、超时、传输)以分类的 finish 原因送达 DSH,重试策略始终由 DSH 掌控

安装

从插件市场安装(推荐,收录后可用):在 DSH 里打开 设置 → 插件市场,搜索 dsh-plugin-adapter,一键安装。

从 GitHub 安装:

dsh plugin --profile web add github:1624318455/dsh-plugin-adapter

从 npm 安装:

dsh plugin --profile web add @memef1f1y/dsh-plugin-adapter

从源码安装(自行打包):

git clone https://github.com/1624318455/dsh-plugin-adapter.git
cd dsh-plugin-adapter/packages/plugin
pnpm install && pnpm pack
dsh plugin --profile web add ./memef1f1y-dsh-plugin-adapter-<version>.tgz

验证:重启 dsh web,打开模型选择器,在 zen-free 分组里选模型即可。

需要带 web profile 的 DSH(DeepSeek Harness);Node.js ≥ 20(DSH 能跑就满足);出站 HTTPS 需可达 opencode.ai 与 models.dev。

配置

默认配置开箱即用。需要覆盖时,编辑 profile 的 cordis.patch.yml:

- id: dsh-plugin-adapter
name: '@memef1f1y/dsh-plugin-adapter'
config:
mode: adapter # adapter(默认)| sidecar providerId: zen-free refreshSeconds: 300 # 目录刷新周期(秒)

从 ≤ 0.3.x 升级:0.4.0 起插件 id 从 opencode2dsh 改为 dsh-plugin-adapter。
DSH 靠这个 id 把 config 挂到插件上,所以升级时要同步把线上 cordis.patch.yml 的 - id: 行改掉,否则配置(例如钉住的 gatewaySession)会被静默丢弃。数据目录也跟着搬了家(~/.opencode2dsh → ~/.dsh-plugin-adapter):插件首次启动会把旧目录复制过去,并把原目录改名为 ~/.opencode2dsh.bak-<日期> 保留,确认新配置可用后可以删掉。

| 配置项 | 默认值 | 说明 |
| mode | adapter | adapter:原生 LlmAdapter 直连 Zen。sidecar:旧版本地 agent 模式,不随包发行——请从 legacy/agent 自行构建并通过 agentPath 指定。 |
| providerId | zen-free | 在 DSH 中显示的 provider 名称(opencode2dsh 保留为兼容别名)。 |
| refreshSeconds | 300 | 实时目录刷新间隔;定价元数据每 24 小时刷新。 |
| gatewaySession | — | 每轮固定发送的 session id。默认不要设:不设时适配器按每个会话的首条用户消息派生 canonical id(同会话多轮不变、不同会话互不相同)。免费通道的每日额度是按出口 IP 计的(额度耗尽后换 IP 即恢复),而实例亲和按 session 计(同一 session 会一直落在同一台后端实例上)。所以:额度问题换出口(见 transport.proxyUrls),「Endpoint is unavailable」这类单实例故障才需要换 session——那档适配器自己会重掷一次;逃生口也可以填本机 CLI 的 live session id。 |
| watchdog.firstEventMs | 60000 | 首 token 预算。Zen 会把响应头压到上游吐出第一个 token 才放行,所以这个窗口衡量的是「首个回答有多慢」,不是「出口是否哑火」。 |
| watchdog.reasoningFirstEventMs | 90000 | reasoning 模型的同一预算(它们思考更久)。 |
| watchdog.bodyIdleMs | 120000 | 内容开始流出后的静默预算(Responses 模型 300 秒)。 |
| contextWindow | — | 上报给 DSH 的上下文窗口上限(token 数)。DSH 按 provider 报的窗口做压缩,而免费模型声明的是 1,000,000——于是长会话永远不压缩,每轮都把整个(还在增长的)上下文重发一遍(实测:surface 404K token,每步从提示缓存读回 205K)。设一个上限(如 262144,即免费通道的真实窗口)让 DSH 早点压缩:prompt 更小、首 token 更快、烧的配额更少。不设 = 用模型自己的窗口。上报的输出上限会跟着这个窗口走:取 min(模型上限, 窗口 / 4)——因为 DSH 的压缩器把请求的 maxTokens 记在窗口里预留(messageBudget = contextWindow - maxTokens),这个预算一旦为负,压缩会被静默跳过。 |
| transport.proxyUrls | — | 出口候选列表(按顺序),例如 ["http://127.0.0.1:10808"],指向 v2rayN 的入站。Zen 的每日免费额度按出口 IP 计,额度耗尽时上游对每个请求都回 429;中继遇到 429 或连接失败就换下一个出口,这一轮照常完成。v2rayN 切节点时同一个入站换的是背后的出口 IP,所以中继把失败出口只冷却 transport.proxyCooldownMs(默认 20s)后自动重试——切完节点不用重启 DSH,最多等一个冷却周期。 |
| transport.proxyUrl | — | 单出口写法,等价于 proxyUrls: [proxyUrl]。保留兼容旧配置。 |
| transport.proxyCooldownMs | 20000 | 出口失败/429 后的冷却时长。冷却期内该出口不被使用(不白付 CONNECT),到点自动重试。 |
| transport.noReuse | true | 设为 false 可让 Zen 通道继续复用连接。 |
| agentPath | 自动解析 | 仅 sidecar:agent 二进制路径。 |
| agentArgs | — | 仅 sidecar:传给 agent 的额外 CLI 参数。 |
| restartDelayMs / restartMaxDelayMs / maxConsecutiveCrashes | 1000 / 60000 / 5 | 仅 sidecar:重启退避与熔断阈值。 |

工作原理

DSH 会话 │ harness chunk(block-start / text-delta / usage / finish …)
▼
ZenAdapter(注册的 LlmAdapter) │ pi-ai openai-completions 流式 ▼ https://opencode.ai/zen/v1 ← Authorization: Bearer public 携带与 CLI 同形的请求头: user-agent: opencode/…
x-opencode-client, x-opencode-session, x-session-affinity,
X-Session-Id, x-opencode-request, x-opencode-project

- 会话关联——session/project id 由会话首条用户消息经 SHA-256 派生(同一会话稳定、不可逆推),每个请求再附带一个全新的随机 id,与 CLI 行为一致。
- 目录回退链——S1:实时 GET /v1/models;S2:models.dev 定价元数据判定 "免费"(模型名带 -free 且通道本身免费供应时,元数据缺失也不会被误杀;但明确标注"付费"或"已下架"的判定仍然优先);S3:编译期验证的静态名单。
上游故障时由磁盘缓存(约 7 天有效期)兜底。
- 韧性——adapter 在启动时立即注册;若首次目录拉取撞上网络尚未就绪(VPN/TUN 重连、DNS 等),会以短周期重试(约 1 分钟内),随后转入常规刷新。
- sidecar 模式(mode: sidecar,旧版)——拉起本地 Go agent( opencode2api 的单租户移植版),监听 127.0.0.1:<随机端口>、token 鉴权,并注册标准 llm-pi-ai 路由。
不随包发行;请从 legacy/agent 构建(go build ./cmd/agent)并把 agentPath 指向产物。

网关兼容(Zen 门跟踪)

Zen 免费通道会锁第三方客户端,且不打招呼就迁移模型接口。2026-10-25 起上游把判定升级成一整套客户端指纹,五道门缺一即拒,而拒绝用的是 429 配额文案,看起来像「额度用完」。
本 fork 0.5.0 起完整复刻(详见 packages/plugin/src/adapter/fingerprint.ts):

| 门 | 要求 | 失败表现 |
| User-Agent | opencode/latest/<ver>/cli(v2 形状) | 403 / 429 |
| 会话头 | ses_ + 12 hex(时间戳)+ 14 base62 | 429 |
| 工具声明 | OpenCode 自己的 read、shell,描述与 schema 逐字一致 | 403 |
| 流式 | stream: true | 403 |
| 系统提示 | 恰好一对 <env>…</env>,内含 Working directory: | 429 |

外加一道运行时门:同一请求体、同一出口 IP,Node/undici 必被 429,Bun 的 fetch 才被放行(2026-10-26 实测 6/6 vs 5/5)。DSH 跑在 Node 上,所以插件用 adapter/zen-relay.ts 拉起一个 bun 子进程做 loopback 中继,由它重新发起上游请求并流式回传。

- 需要安装 bun(bun --version)。插件自动在 PATH、~/.bun/bin、 %LOCALAPPDATA%\Programs\bun 里找;找不到会打一条 warning,免费模型仍会 429。
可用 transport.bunPath 指定路径,transport.relay: 'off' 关闭中继。
- 宿主自己的工具名(如 DSH 的 read)会自动改名为 read_client 走线,响应侧再还原,不会污染会话里已有的工具调用。

出口轮换(免费额度按 IP 每天一份):额度用尽后上游对每个请求都回 429,换 session 没用,换出口 IP 才有用。中继按 transport.proxyUrls 的顺序走候选出口,遇到 429 或连接失败就换下一个;失败出口只进冷却(默认 20s)后自动重试——v2rayN 切节点时 同一个入站背后换了 IP,冷却到点就恢复,不必重启 DSH。

- id: dsh-plugin-adapter
config:
transport:
proxyUrls: # 按顺序尝试;429 自动换下一个
- http://127.0.0.1:10808 # v2rayN 入站:切节点=换出口 IP proxyCooldownMs: 20000 # 失败出口冷却多久后重试 bunPath: C:\Users\you\.bun\bin\bun.exe # 可选

历史门(仍生效):

- Responses-only 模型——muse-spark- 走 /chat/completions 必裸 500,走 /responses 200。adapter 把它们路由到 pi-ai openai-responses (reasoning 阵发,body 静默窗口放宽到 300 秒),其余仍走 openai-completions。
- 严格 UA——网关要求 opencode/... 形状;带后缀或旧版本一律被拒。
opencodeUserAgent() 跟随 CLI 发版。
- 真 session 检查——未知 id 会被拒。插件按对话自动生成时间戳会话 id;仍可用 gatewaySession 钉死一个 live session。

健康状态与排查

插件在每轮刷新后写入健康快照:

~/.dsh-plugin-adapter/adapter-status.json

{
"status": "ready",
"total": 64,
"exposed": 9,
"lastError": "",
"writtenAt": "2026-08-29T07:01:54.915Z"
}

| 现象 | 可能原因与处理 |
| 启动页报 Failed to load plugins … list slot "settings.plugin.item" requires options.id | DSH 版本过旧(≤ 0.1.0-rc.6):设置槽位契约与插件 0.3.0 的浏览器半边不匹配。升级 DSH 到 ≥ 0.1.0-rc.7(推荐最新)即可;插件 ≥ 0.3.1 已自带双形态兼容,旧版 DSH 上最多没有设置卡片,模型路由不受影响。 |
| 只有 3 个模型 | 启动时网络未就绪,重试会在约 1 分钟内补齐;看 adapter-status.json 里的 lastError。 |
| lastError: "fetch failed" 持续出现 | 出站 HTTPS 到 opencode.ai 被拦截;检查代理/VPN 规则。 |
| 对话中报限流错误 | 匿名通道按 IP 限额;切换网络节点或稍后再试。 |
| muse-spark- 经 chat 报 500 | Responses-only 模型;本 fork 已自动路由到 /responses。 |
| 403 FreeTierError:free tier can only be used from within OpenCode | Zen 收紧指纹:升级插件(裸当前 UA)并用 gatewaySessionFile 同步本机 CLI 的真 session。 |
| reasoning 模型报 stream body idle timeout | 阵发式 chain-of-thought 触发 120 秒看门狗;本 fork 对 Responses 模型用 300 秒。 |
| 报 first stream event timeout | 这是首 token 超时,不是出口哑火:Zen 把响应头压到上游吐出第一个 token 才放行,首个回答慢以前会被误报成「出口静默」。窗口为 60 秒(reasoning 模型 90 秒),可用 watchdog. 调整;有 IP 池时会换出口重试。 |
| 连接 127.0.0.1: 报错 | 残留的 sidecar 路由遮蔽了 adapter;插件 ≥ 0.2.1 启动时会自动清理。 |
| 429 … "Upstream request failed: Endpoint is unavailable." | 网关背后的模型实例挂了——不是配额问题,也跟出口无关。适配器会重掷一次 session id(通道按 session 绑定实例),把请求挪到另一个实例。 |
| Request timed out. | OpenAI SDK 的请求上界先于任何响应头触发。适配器现在会显式传上界(看门狗窗口 + 30 秒),上游卡死不会拖成 SDK 默认的 10 分钟,且由看门狗给出可读诊断而不是这句裸错误。 |
| 400 … requires adaptive thinking; reasoning effort none is not allowed | 该模型不允许关思考(minimax-m3.1)。选 off 会被映射成它接受的最便宜档位(low),而不是整轮 400。 |
| 安装时报 ERR_PNPM_IGNORED_BUILDS | pi-ai 的传递依赖(@google/genai、protobufjs)带构建脚本,运行时并不需要。在插件市场里按提示选择允许/拒绝,或在 profile 的 pnpm-workspace.yaml 的 allowBuilds: 下把这两项设为 false。 |

安全性

- 不涉及任何机密:匿名通道的 Key 就是字面量 public;插件不存储任何东西,也没有任何遥测。
- 安装产物仅限 lib/;不执行任何依赖的构建脚本。
- 所有请求均从你的机器直连 opencode.ai / models.dev。

开发

git clone https://github.com/1624318455/dsh-plugin-adapter.git
cd dsh-plugin-adapter/packages/plugin
pnpm install
pnpm typecheck && pnpm test
pnpm build # 打包到 lib/

旧版 Go sidecar 在 legacy/agent(go test ./...)。架构说明与移植记录见 docs/。

发布:打 v tag(tag 必须等于 packages/plugin/package.json 里的 version), publish 工作流会在 Node 22/24 上跑测试,然后通过 npm Trusted Publisher (GitHub Actions 的 OIDC 身份,无需长期 token)带 provenance 发布 packages/plugin。本地仍可在 packages/plugin 执行 pnpm pack (prepack 会构建并同步文档)。

致谢

- opencode2dsh(FishBottle7)——本项目是它的维护分支,adapter、目录与 IP 池设计源自该项目。
- opencode2api,作者 @jasonxu114514——legacy/agent 里的旧版 Go sidecar 是其匿名通道实现的移植版,目录回退链与请求伪装细节同样源自它。
本项目能成立,全靠它踩过的路。
- OpenCode——运营免费匿名 Zen 通道。
- @earendil-works/pi-ai——adapter 模式使用的线上协议层。
- DeepSeek Harness 与 dsh-market 社区。

友链

LinuxDo —— 新的理想型社区

许可证

MIT © FishBottle7
预览分享卡片长什么样 ↓1624318455/dsh-plugin-adapter
分享 · DeepSeek Harness Hub
1624318455/dsh-plugin-adapter

在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。

回到顶部