npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-plugin-thinking-api

v0.1.8

Published

DeepSeek Harness 插件:一键配置任意 OpenAI 兼容 API 并自动带思考模式,同时规避 developer 角色被第三方端点拒绝(content_filter)的问题。

Readme

dsh-plugin-thinking-api

English · 简体中文


解决什么问题

一个插件解决三件事:

  1. 任意 OpenAI 兼容 API 一键配置 —— 腾讯 CodeBuddy、自建 vLLM、各类中转站,一个配置块搞定,无需手写 reasoningEffortsthinkingFormat 或 pi-ai provider 内部结构。
  2. 开箱即用的思考模式 —— 模型上写 thinking: true 就自动获得思考档位。
  3. 修复 content_filter / developer 角色 bug —— 这是最隐蔽的一个。

它修复的 bug

当模型声明了 reasoning(思考)时,pi-ai 会把 system prompt 改写成 OpenAI 的 developer 角色——除非它把该端点识别为「非标厂商」。不在 pi-ai 内置白名单里的第三方 API(腾讯 CodeBuddy 就是典型)因此会收到 developer 消息,而很多端点会硬拒绝它并返回 content_filter;同样的请求换成 system 角色则完全正常。

官方 dsh-llm-pi-ai 适配器在组装模型时丢弃compat.supportsDeveloperRole 字段,所以单靠 settings.yaml 无法修复。本插件自己组装 pi-ai 模型,直接注入 compat.supportsDeveloperRole: false,强制走 system 角色。

为什么它好维护

插件复用官方 PiAiAdapter 类(由 @deepseek-ai/dsh-llm-pi-ai 导出):它的流式输出、chunk 翻译、凭据解析、空闲超时看门狗、图片处理都随 DSH 升级自动演进。本插件只负责「模型 / Provider 组装」这一小层——把正确的 compat 写进去。

安装

在 profile 的 package.json 里加入依赖和 bundle 列表:

// ~/.dsh/profiles/<profile>/package.json
{
  "dependencies": {
    "dsh-plugin-thinking-api": "github:qjf44/dsh-plugin-thinking-api"
  },
  "dsh": {
    "profile": {
      "bundles": [
        // ...你已有的 bundles...
        "dsh-plugin-thinking-api"
      ]
    }
  }
}

重装依赖并重启 Harness。插件的 cordis.patch.yml 会自动注册自身(insert: [{ id: thinking-api }]),无需手动改 cordis.patch.yml

配置

~/.dsh/settings.yaml 里加一个 thinking-api 区块:

thinking-api:
  providers:
    codebuddy:                                   # 路由 id(任意唯一名称)
      displayName: CodeBuddy                     # 可选,选择器里显示的名字
      baseURL: https://copilot.tencent.com/v2
      apiKeyEnv: CODEBUDDY_API_KEY               # 环境变量名;通过 Web 模型页存储或 export
      thinkingFormat: deepseek                   # 可选,默认 deepseek
      models:
        deepseek-v4-pro:
          name: DeepSeek V4 Pro
          thinking: true                         # ← 开启思考模式
        deepseek-v4-flash:
          name: DeepSeek V4 Flash
          thinking: false
        deepseek-v4.1-flash:
          name: DeepSeek V4.1 Flash
          thinking: true
          input: [text, image]                   # ← 声明可看图(多模态),read_image 才可用

存储密钥(不要把明文 key 写进配置):

# 方式一:在启动环境里导出
export CODEBUDDY_API_KEY=ck_xxxxxxxx

# 方式二:通过 Web 界面 → 模型页写入(credentials 服务)

重启后,从模型选择器里选你的 API 模型即可。

📄 可直接复制的配置(CodeBuddy / 自建 vLLM / 任意 OpenAI 兼容中转站):见 examples/settings.yaml

Web 界面一键配置

插件还注册了 设置 → 思考 API 面板,内置一个统一的接入向导,不用手写 YAML 就能接入 API:

  1. 来源 —— 选模板(CodeBuddy / DeepSeek / OpenRouter / …)或「自定义」。
  2. API 密钥 —— 粘贴一次即可。模板自带常用默认模型,填完 key 就能直接保存开始对话。
  3. 模型(可选)—— 点「获取模型列表」拉取端点模型,向导会按名称自动预判思考模型(每条都能用勾选框微调);也可以手动添加模型 id。

    腾讯 CodeBuddy(copilot.tencent.com)不提供 OpenAI 兼容的 /models 端点,点「获取模型列表」时会自动填入模板预置模型(而非报 404 错误);其他端点若 404 则需手动填写模型 id。

  4. 保存 —— 完成。该 provider 会出现在模型选择器里,并走修复版适配器(supportsDeveloperRole: false)。

已接入的 provider 可以点「编辑」回填进向导修改,也可以删除。

client 半通过 exports["./client"] 作为浏览器 bundle 被发现;修改插件源码后需重建 Web 产物,本 URL 才会加载新 bundle。

配置参考

Provider(providers.<id> 下)

| 字段 | 类型 | 必填 | 默认 | 含义 | |---|---|---|---|---| | baseURL | string | ✅ | — | API 端点 base URL | | apiKeyEnv | string | — | — | 存放 API key 的环境变量名 | | displayName | string | — | 路由 id | 选择器里显示的名字 | | thinkingFormat | enum | — | deepseek | deepseek | openai | openrouter | together | zai | qwen | string-thinking | | models | dict | ✅ | — | 模型 id → 模型条目 |

Model(models.<id> 下)

| 字段 | 类型 | 必填 | 默认 | 含义 | |---|---|---|---|---| | name | string | — | 模型 id | 显示名 | | thinking | boolean | — | false | 是否开启思考档位 | | thinkingEfforts | dict | — | 自动 | 自定义档位 → 线上参数映射,如 { off: null, high: high, max: xhigh } | | contextWindow | number | — | 262144 | 上下文窗口大小 | | maxTokens | number | — | 32768 | 最大输出 token | | input | array | — | ["text"] | 输入模态:["text"]["text","image"]。声明 image 后该模型才会被 DSH 认作视觉模型(read_image 才可用) |

thinking: true 且未给 thinkingEfforts 时,插件自动填充已验证可用的 DeepSeek 兼容档位(off / high / max,分别对应关闭 / reasoning_effort: high / reasoning_effort: xhigh)。需要更多档位(low/medium)或按 API 定制时,用 thinkingEfforts 显式覆盖。

关于 input / 图片输入:DSH 的 read_image 会拒绝任何未声明 image 的路由(报 model "..." does not declare image input),而本插件默认把所有模型登记为纯文本。要让某个模型能看图,需显式声明 input: [text, image],例如腾讯 CodeBuddy 的 deepseek-v4.1-flash(即官方原生多模态的 V4.1 Flash)。空数组与缺省同义,均回落为 ["text"]

注意这只是声明,不代表上游端点真的接受图片:声明后若端点拒收,会在真正传图时报错;反之若端点支持而你未声明,图片会在本地就被拦下、根本发不出去。

为什么不用内置 llm-pi-ai

内置 llm-pi-ai 适配器本来就支持自定义 API,只是它无法表达 supportsDeveloperRole(它的 compat schema 没这个字段,解析器也会丢弃它),于是「白名单外 API + 思考模式」就会撞上 developer 角色拒绝。本插件存在的意义,就是补上这缺失的一个字段,其余全部复用。

支持的 DSH 版本

基于 DSH 0.1.0-rc.60.1.5-rc.1@deepseek-ai/dsh-llm-pi-ai)、pi-ai ^0.82.1 构建。插件对 PiAiAdapter 的构造器形状做了防御性依赖;若未来 DSH 改变该内部契约,插件会给出清晰报错而非静默出错——升级 DSH 前请先看本插件的 release notes。

DSH 0.1.5 兼容性。 0.1.5 同时改动了多个内部契约,v0.1.2 及更早版本在其上会直接报错;v0.1.3–v0.1.5 依次修复(细节见 changelog):

| 在 DSH 0.1.5 上的现象 | 根因 | 修复版本 | | --- | --- | --- | | 启动即 Failed to load plugins | dsh.client.inject 仍声明已被移除的 @deepseek-ai/dsh-client-runtime | v0.1.3 | | 设置面板 Cannot read properties of undefined (reading 'settings') | connection 不再暴露 .api,取数须改走 ctx.remote.* | v0.1.4 | | 模型选择器 CodeBuddy 加载失败: Cannot read properties of undefined (reading 'get') | 0.1.5 的 pi-ai modelOf() 会读 profile.modelErrors,而插件手组的 profile 缺该字段 | v0.1.5 |

升级 DSH 后 CodeBuddy / 第三方 API 用不了?先跑自检

插件依赖 pi-ai 与 DSH 的若干内部契约(provider auth 形状、PiAiAdapter 构造器、llm 服务注册方法等)。这些契约不在官方语义版本保证内,所以每次升级 DSH(或 pi-ai)后,如果模型突然报 Provider is not configuredcontent_filterMISSING_CREDENTIAL 之类,先跑一次兼容性自检:

# 在插件仓库目录下(DSH workspace 会自动向上查找;找不到时显式指定)
node scripts/check-compat.mjs --workspace ~/.workbuddy/binaries/node/workspace

它会逐项核对:插件能否在真实依赖下 import、PiAiAdapter 构造器形状、pi-ai provider auth 形状、llm 服务注册方法、settings/credentials 辅助函数。全部 ✓ 才能继续用;有任何 ✗ 就说明需要升级插件(报错信息会点名是哪个契约变了、去哪改)。

历史踩坑记录(2026-09-12,图片输入「静默失效」)

用户反馈「CodeBuddy 的 deepseek-v4.1-flash 读不了图」,排查结论是插件的问题,不是模型的问题

  • 现象:对任意图片调用 read_image 一律报 model "<id>" does not declare image input; switch to an image-capable model to read images。注意这个拒绝发生在发出网络请求之前
  • 根因buildModel()input 硬编码为 ['text'],而 dsh-llm-pi-ai 会把它原样映射为 inputModalitiesdsh-tool-fsread_image 据此拒绝任何未声明 image 的路由。于是图片在本地就被丢掉,上游是原生多模态模型也白搭。模型条目 schema 里当时根本没有 input 字段,用户无法从 settings.yaml 绕过。
  • 修复:新增可选 input 字段(默认 ['text'] 保持行为不变),并把 buildModel 改为读取它;空数组与缺省同义(对齐官方 declaredInput 语义)。

教训:「模型不支持」和「路由没声明」是两回事。 排查视觉问题时,先看本地能力声明(inputModalities),再怀疑上游端点——前者会把图拦在本地,后者的报错来自服务端,两者的报错位置和修复方式完全不同。

另一个值得记住的部署陷阱:profile 里的 file: 依赖是拷贝而非软链。只改插件仓库源码、不重跑 pnpm install,profile 里那份旧代码纹丝不动,改动静默不生效。

历史踩坑记录(2026-09-11,DSH 0.1.1-rc.2 → 0.1.5-rc.1)

0.1.5 一次挪动了三个契约,且各自只在不同层面才暴露——这正是「服务能启动」这类检查抓不到它们的原因:

  • 客户端预加载(Failed to load plugins)。 0.1.5 移除了 @deepseek-ai/dsh-client-runtime,但插件仍在 dsh.client.inject 里声明它,加载器找不到模块,整条插件图一起失败。createSnapshotStore 也迁到了内置 seed 模块 @deepseek-ai/dsh-client-store。修复:从 inject 去掉 runtime,改从 seed 模块导入 store。
  • 渲染层取数(reading 'settings')。 connection 不再携带 .api,settings/credentials/llm 的读取须改走 cordis 命名空间服务 ctx.remote.settings / ctx.remote.credentials / ctx.remote.llm。注意客户端 bundle 是按内容哈希按请求下发的,这一半刷新页面即生效,无需重启宿主
  • 宿主 profile 形状(reading 'get')。 0.1.5 的 pi-ai modelOf() 会无条件执行 profile.modelErrors.get(model)。插件是手工组 profile 的(无法直接复用官方 resolveProfiles——它没有 userAgent / compat.supportsDeveloperRole 这两个钩子),而这个手组对象早于该字段存在,于是 modelCatalog 枚举时整个 provider 组抛错。单看 listModels 走的是 getModels()、本身安全,所以该组能列出、只在选择器解析每个模型详情时才失败。修复:补上 modelErrors: new Map() 以及官方 profile 同样携带的图片预算默认值。这一半是宿主代码,必须重启 harness 才生效。

教训:DSH 升级后要在三个层面分别验证(启动、设置面板、模型选择器),不能只看服务有没有起来。

历史踩坑记录(2026-08-18,DSH rc.6 → rc.7)

升级后 codebuddy 请求 100% 报 PI_AI_ERROR: Provider is not configured: codebuddy,根因是 pi-ai 0.82.1 改了 provider auth 契约

  • 旧(0.82.1 之前):auth: { name, resolve }(顶层 resolve)。
  • 新(0.82.1 起):resolveProviderAuth 只认 auth.apiKey.resolve,顶层 resolve 被当作「无认证方式」→ getAuth 返回空 → 上述报错。

修复:buildProvider 把 auth 组装成 { apiKey: { name, resolve } },与官方 dsh-llm-pi-airouteAuth/harnessApiKeyAuth 形态一致。插件现在启动时会自检该契约,版本不匹配会在启动时直接报错,而不是等你发消息。

另一个坑:GUI 向导编辑 provider 时 key 留空会抹掉已有的 apiKeyEnv,导致升级/重配后密钥引用丢失(报 MISSING_CREDENTIAL 或认证失效)。已修复:编辑模式 key 留空表示「不改」,沿用原有 apiKeyEnv

参与贡献

欢迎提交 bug 和反馈——请用 bug 报告模板 建 issue(模板会要 DSH 版本、插件版本和 check-compat 输出,能覆盖九成故障)。

提 PR 前先跑本地检查:

npm run check                 # 语法(lib/index.mjs、lib/client.js、scripts/check-compat.mjs)
node scripts/check-compat.mjs --workspace ~/.workbuddy/binaries/node/workspace   # 对真实 DSH 做契约自检

每次 push/PR 时 CI 会跑 npm run check 加一个 npm 包体检 job(tarball 文件清单、版本号是否已发布)——见 .github/workflows/check.yml

License

MIT