DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

dsh-plugin-thinking-api

Plugin Thinking Api

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

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-plugin-thinking-api@0.2.1-rc.2.2
README兼容性版本

兼容性与来源证明

Plugin Thinking Api 以 dsh-plugin-thinking-api 发布,当前版本为 0.2.1-rc.2.2。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/11/4

版本

0.2.1-rc.2.2prerelease
2026/10/22
0.1.10stable
2026/10/18
0.1.8stable
2026/9/11
0.1.7stable
2026/9/11
查看其余 8 个版本收起版本
0.2.1-rc.2.1prerelease
2026/10/20
0.2.1-rc.2prerelease
2026/10/18
0.1.6stable
2026/9/11
0.1.5stable
2026/9/11
0.1.4stable
2026/9/10
0.1.3stable
2026/9/10
0.1.2stable
2026/8/18
0.1.1stable
2026/8/18

相关插件

正在加载相关插件…

最新版
0.2.1-rc.2.2
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
202 kB
文件数
11
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 2
周下载
390
安全扫描
✓ v0.2.1-rc.2.2 扫描通过
最近提交
2026/10/22
查看源码 ↗项目主页 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 integrations-communication 分类下经过校验的插件。

Acp App@deepseek-ai/dsh-acp-appdsh ACP 配置文件包:基于 dsh-base 的仅限自动化的 JSON-RPC stdio 和进程生命周期管理Remote Bridge@linxin666/dsh-remote-bridgeDSH 远程桥接:主机端通过唯一且精确的 /ios/v1 WebSocket 路由提供协议 v1——会话列表、历史记录基线、提示、包含工具活动的实时回合增量、中断以及进程内代理审批——连接到通过一次性配对的设备Im@xmanrui/dsh-im将微信、飞书、企微、钉钉、QQ、Telegram、WhatsApp、Slack、Discord 和 Matrix 接入 DSH。Ds Botds-botDS Bot:DeepSeek Harness 的一组长期运行的 Bot,支持主 Bot、Bot 间消息和群聊

README

dsh-plugin-thinking-api

简体中文 · English

DeepSeek Harness plugin: configure any OpenAI-compatible API in one block and get thinking mode for free — while dodging the developer-role rejection that breaks such APIs.


What it solves

Three problems in one plugin:

  1. Configure any OpenAI-compatible API in one block — Tencent CodeBuddy, self-hosted vLLM, or any relay — no hand-writing reasoningEfforts, thinkingFormat, or pi-ai provider internals.
  2. Thinking mode out of the box — set thinking: true on a model and it gains reasoning levels automatically.
  3. Fixes the content_filter / developer-role bug — this is the subtle one.

The bug this fixes

When a model declares reasoning, pi-ai rewrites the system prompt into the OpenAI developer role unless it recognizes the endpoint as a non-standard vendor. Third-party APIs that are not on pi-ai's built-in allowlist (Tencent CodeBuddy is a prime example) therefore receive a developer message, which many endpoints hard-reject with content_filter — while the exact same request using system succeeds.

The official dsh-llm-pi-ai adapter drops the compat.supportsDeveloperRole field when it builds models, so you cannot fix this from settings.yaml alone. This plugin builds the pi-ai models itself and injects compat.supportsDeveloperRole: false directly, forcing the system role.

How it stays maintainable

The plugin reuses the official PiAiAdapter class (exported by @deepseek-ai/dsh-llm-pi-ai): its streaming, chunk translation, credential resolution, idle-timeout watchdog, and image handling all keep evolving with DSH. This plugin only owns the small "model/provider assembly" layer where the correct compat is written in.

Install

Add to your profile's package.json dependencies and bundle list:

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

Then reinstall and restart the Harness. The plugin's cordis.patch.yml registers itself (insert: [{ id: thinking-api }]), so no manual cordis.patch.yml edit is needed.

Configure

Add a thinking-api section to ~/.dsh/settings.yaml:

thinking-api:
  providers:
    codebuddy:                                   # route id (any unique name)
      displayName: CodeBuddy                     # optional, shown in pickers
      baseURL: https://copilot.tencent.com/v2
      apiKeyEnv: CODEBUDDY_API_KEY               # env-var reference; store via the Web Models page or export it
      thinkingFormat: deepseek                   # optional, default deepseek
      models:
        deepseek-v4-pro:
          name: DeepSeek V4 Pro
          thinking: true                         # ← enables thinking mode
        deepseek-v4-flash:
          name: DeepSeek V4 Flash
          thinking: false
        deepseek-v4.1-flash:
          name: DeepSeek V4.1 Flash
          thinking: true
          input: [text, image]                   # ← declares vision; makes read_image usable

Store the key (never paste raw keys into the config):

# either export it in the launching environment
export CODEBUDDY_API_KEY=ck_xxxxxxxx

# or write it through the Web UI → Models page (credentials service)

Restart, then pick your API's models from the model picker.

📄 Ready-to-copy configs (CodeBuddy / self-hosted vLLM / any OpenAI-compatible relay): see examples/settings.yaml.

One-click setup in the Web GUI

The plugin also registers a Settings → Thinking API panel with a single setup wizard. Open it to connect an API without touching YAML:

  1. Source — pick a template (CodeBuddy / DeepSeek / OpenRouter / …) or Custom.
  2. API key — paste it once. Templates ship sensible default models, so you can save immediately and start chatting.
  3. Models (optional) — click Fetch models to list the endpoint's models; the wizard pre-flags reasoning models by name (and you can adjust each one with a checkbox). Or add model ids manually.

    Tencent CodeBuddy (copilot.tencent.com) has no OpenAI-compatible /models endpoint; Fetch models falls back to the template's default models instead of failing with 404. On other endpoints a 404 means you should enter model ids manually.

  4. Save — done. The provider appears in the model picker and uses the fixed adapter (supportsDeveloperRole: false).

Existing providers can be edited (the Edit button reloads them into the wizard) or removed.

The client half ships as a browser bundle discovered through exports["./client"]; after changing plugin source, rebuild the Web artifacts so this URL picks up the new bundle.

Configuration reference

Provider (per providers.<id>)

FieldTypeRequiredDefaultMeaning
baseURLstring✅—API endpoint base URL
apiKeyEnvstring——Env-var name holding the API key
displayNamestring—route idName shown in pickers
thinkingFormatenum—deepseekdeepseek | openai | openrouter | together | baseten | zai | qwen | qwen-chat-template | chat-template | string-thinking | ant-ling
modelsdict✅—Model id → model entry

Model (per models.<id>)

FieldTypeRequiredDefaultMeaning
namestring—model idDisplay name
thinkingboolean—falseEnable reasoning levels
thinkingEffortsdict—autoCustom level → wire-value mapping, e.g. { off: null, high: high, max: xhigh }
contextWindownumber—262144Context window size
maxTokensnumber—32768Max output tokens
inputarray—["text"]Input modalities: ["text"] or ["text","image"]. Only a model declaring image is treated as a vision model by DSH (making read_image usable)

When thinking: true and no thinkingEfforts is given, the plugin fills a verified DeepSeek-compatible level map (off / high / max, mapping to disabled / reasoning_effort: high / reasoning_effort: xhigh). Provide thinkingEfforts to add levels (low/medium) or override per API.

About input / image support: DSH's read_image refuses any route that does not declare image (model "..." does not declare image input), and this plugin registers every model as text-only by default. To let a model see images, declare input: [text, image] — e.g. Tencent CodeBuddy's deepseek-v4.1-flash, which is the official natively-multimodal V4.1 Flash. An empty array is synonymous with omitting the field and falls back to ["text"].

This is a declaration only: it does not guarantee the upstream endpoint accepts images. If the endpoint rejects them, you will see an error when an image is actually sent; conversely, if the endpoint supports images but you never declare them, images are blocked locally and never leave your machine.

Why not llm-pi-ai?

The built-in llm-pi-ai adapter already supports custom APIs. It just cannot express supportsDeveloperRole (its compat schema omits the field and its resolver drops it), so thinking-mode models on allowlist-less APIs hit the developer-role rejection. This plugin exists purely to inject that one missing bit, while reusing everything else.

Versioning: the plugin version IS the DSH version

From 0.2.1-rc.2 on, this plugin's version number equals the exact DSH version it is aligned with (previously it incremented independently as 0.1.x). So when you see dsh-plugin-thinking-api@0.2.1-rc.2, you know immediately that it targets DSH 0.2.1-rc.2 — no need to open the changelog to guess. check-docs enforces this: the plugin version must equal the highest DSH version in peerDependencies, or carry one extra patch segment on top of it (e.g. 0.2.1-rc.2.1) for a plugin-only fix, or CI fails.

Versions 0.1.0 – 0.1.10 predate this rule and were numbered independently. 0.1.10 is the last of them; everything it contained is included in 0.2.1-rc.2.

Supported DSH

Built against DSH 0.1.0-rc.6 through 0.2.1-rc.2 (@deepseek-ai/dsh-llm-pi-ai), pi-ai 0.82.1 – 1.x. The plugin defensively reuses PiAiAdapter's constructor shape; if a future DSH changes that internal contract, the plugin fails with a clear error rather than silently misbehaving — check the release notes before upgrading DSH.

DSH 0.2.x. pi-ai 1.3.0 added four thinking dialects (baseten, chat-template, qwen-chat-template, ant-ling) and dsh-llm-pi-ai 0.2.1 accepts all eleven in its SUPPORTED_THINKING_FORMATS. v0.1.10 extends the plugin's thinkingFormat enum and its default effort table to match, and check-compat now diffs the plugin enum against the adapter's source so a future addition fails the check instead of silently rejecting valid config.

DSH 0.1.7 compatibility. 0.1.7 removed SettingsProvider and its installSection() method, replacing them with SettingsForms, which projects the settings page from the plugin's exported Config schema and only exposes fields marked .volatile(). v0.1.9 therefore:

  • exports Config (0.1.7 reads fiber.runtime.Config to build the page), and
  • marks providers volatile, probing volatile() → extra('volatile', true) in that order — probing .volatile() alone is not enough, see the note below, and
  • wires a third settings branch (SettingsForms) beside the existing ≤0.1.1 export-function and 0.1.5/0.1.6 instance-method branches, and
  • unwraps the cosmokit Volatile reference that .volatile() produces, so config.providers still enumerates as a plain dict.

Without the volatile mark, 0.1.7's describe() skips this plugin's row entirely and mutate() throws has no volatile fields — the page silently disappears and CodeBuddy can no longer be saved. Without the Config export, the entry is not configurable at all.

Beware a stale schemastery inside your profile. DSH resolves plugin dependencies from the profile's physical node_modules. If your profile still carries an older copy (e.g. ~/.dsh/profiles/<name>/node_modules/@deepseek-ai/schemastery at 3.18.2 while the 0.1.7 runtime ships 3.18.4), the plugin resolves the old one. That version has no volatile handling at all, so the mark silently fails and 0.1.7's importLegacyDocument() drops the entire thinking-api section of settings.yaml (including the CodeBuddy provider directory) after logging only a warning — exit code stays 0 and no error is printed.

v0.1.9's extra('volatile', true) fallback keeps working in exactly that environment (3.18.4's .volatile() is literally return this.extra("volatile", true), so the two are equivalent), so you do not need to delete that copy, and it survives pnpm install re-creating it. Deleting the directory is still fine if you prefer. Do not copy 3.18.4 into an old profile in reverse: it needs cosmokit ≥1.8.5 (old profiles have 1.8.3) and will make DSH 0.1.6 fail to boot outright.

DSH 0.1.5 compatibility. 0.1.5 moved several internal contracts; versions ≤ 0.1.2 break on it. v0.1.3–v0.1.5 fix them in turn (see the changelog for the full detail):

Symptom on DSH 0.1.5Root causeFixed in
Failed to load plugins at bootdsh.client.inject still declared the removed @deepseek-ai/dsh-client-runtimev0.1.3
Settings panel: Cannot read properties of undefined (reading 'settings')connection no longer exposes .api; reads must go through ctx.remote.*v0.1.4
Model picker: CodeBuddy 加载失败: Cannot read properties of undefined (reading 'get')0.1.5 pi-ai modelOf() reads profile.modelErrors, which the plugin's hand-built profile omittedv0.1.5

After upgrading DSH, CodeBuddy / third-party APIs stop working? Run the compat check

The plugin depends on several internal contracts of pi-ai and DSH (provider auth shape, PiAiAdapter constructor, llm service registration methods). These are not covered by semver. So after every DSH (or pi-ai) upgrade, if models suddenly fail with Provider is not configured, content_filter, or MISSING_CREDENTIAL, run the compat check first:

# from the plugin repo (DSH workspace is auto-detected upward; pass --workspace when needed)
node scripts/check-compat.mjs --workspace ~/.workbuddy/binaries/node/workspace

It verifies, item by item: the plugin imports under the real dependencies, the PiAiAdapter constructor shape, the pi-ai provider auth shape, the llm service registration methods, and the settings/credentials helpers. All ✓ means you can keep using it; any ✗ means the plugin needs an update (each failure names the changed contract and where to fix it).

Incident log (2026-10-21, CodeBuddy gateway 11128 "unapproved channel")

Symptom: every CodeBuddy / CodeBuddy2 request failed with 400 {"code":11128,"msg":"Illegal API invocation from an unapproved channel"}, while curl with the same key and the same body shape returned 200.

The gateway fingerprints the client identity sentence in the system prompt, not the User-Agent and not the message roles. The exact trigger is the whole sentence You are an AI agent powered by DeepSeek Harness. (case-insensitive). Each fragment alone passes: You are an AI agent., You are powered by DeepSeek Harness., You are an AI agent powered by Cursor. — and so does any wording that breaks the "powered by" adjacency. Insert the full sentence and you get 11128 back.

Control experiments run with a real key (all 200 unless noted): tools, 1.3 MB body, 45 tools, image data-URI, assistant+tool transcript, every optional field. Feeding the real system prompt failed even truncated to its first 500 characters, while the same text in a user role passed.

Two lessons worth keeping:

  • "My curl works, the plugin doesn't" does not mean the plugin is broken. Here the only difference that mattered was content, not transport. When bisecting, bisect the body text too, not just headers and roles.
  • A developer-role rejection can be a red herring. It reproduces the identical error string, so it looks like the root cause. It was a real failure mode (now defended), but not the one the user was hitting.

Fix: three defence layers, all in the buildProvider stream/streamSimple wrapper — compat supportsDeveloperRole: false, an onPayload hook rewriting developer → system, and a fetch-level rewrite of the identity sentence (the fetch layer is the last stop, reached by every code path). Observability: each request logs its real wire shape to /tmp/dsh-thinking-api-wire.log, and a 11128 dumps the complete request body to /tmp/dsh-thinking-api-wire-fail-<ts>.json.

Incident log (2026-09-12, images silently failing)

A user reported that CodeBuddy's deepseek-v4.1-flash could not read images. The verdict was the plugin, not the model:

  • Symptom. read_image on any picture failed with model "<id>" does not declare image input; switch to an image-capable model to read images. Note this refusal happened before any network request was made.
  • Root cause. buildModel() hard-coded input: ['text'], and dsh-llm-pi-ai maps that verbatim onto inputModalities; dsh-tool-fs's read_image then refuses any route that does not declare image. So the image was dropped locally — the upstream being natively multimodal made no difference. The model-entry schema had no input field at all, so users could not work around it from settings.yaml.
  • Fix. Added an optional input field (defaulting to ['text'], so existing behavior is unchanged) and made buildModel read it; an empty array is synonymous with omitting it, matching upstream declaredInput semantics.

Lesson: "the model doesn't support it" and "the route never declared it" are different failures. When debugging vision, check the local capability declaration (inputModalities) before suspecting the endpoint — the former blocks images locally, the latter errors server-side, and the two are fixed in completely different places.

One more deployment trap worth remembering: a file: dependency in the profile is a copy, not a symlink. Editing the plugin repo without re-running pnpm install leaves the profile's stale copy untouched and the change silently inert.

Incident log (2026-09-11, DSH 0.1.1-rc.2 → 0.1.5-rc.1)

Three contracts moved at once, each surfacing only at a different layer — which is why a "server boots fine" check misses them:

  • Client bundle preload (Failed to load plugins). 0.1.5 dropped @deepseek-ai/dsh-client-runtime, but the plugin still declared it in dsh.client.inject, so the loader missed the module and the whole plugin graph failed. createSnapshotStore also moved to the built-in seed module @deepseek-ai/dsh-client-store. Fix: drop the runtime from inject; import the store from the seed module.
  • Renderer data layer (reading 'settings'). connection no longer carries .api; the settings/credentials/llm reads had to move to the cordis namespace services ctx.remote.settings / ctx.remote.credentials / ctx.remote.llm. Note the client bundle is served per request with a content-hash rev, so this half takes effect on a page reload — no host restart needed.
  • Host profile shape (reading 'get'). 0.1.5's pi-ai modelOf() unconditionally evaluates profile.modelErrors.get(model). The plugin builds its profiles by hand (it cannot reuse the official resolveProfiles, which has no userAgent/compat.supportsDeveloperRole hook), and that hand-built object predated the field — so modelCatalog enumeration threw for the whole provider group. listModels alone uses getModels() and stays safe, so the group listed fine and only failed once the selector resolved per-model details. Fix: emit modelErrors: new Map() plus the image-budget defaults the official profile also carries. This half is host code and does need a harness restart.

Lesson: after a DSH upgrade, verify at all three layers (boot, settings panel, model picker) — not just that the server starts.

Incident log (2026-08-18, DSH rc.6 → rc.7)

After the upgrade, codebuddy requests failed 100% with PI_AI_ERROR: Provider is not configured: codebuddy. Root cause: pi-ai 0.82.1 changed the provider auth contract:

  • Before 0.82.1: auth: { name, resolve } (top-level resolve).
  • From 0.82.1: resolveProviderAuth only recognizes auth.apiKey.resolve; a top-level resolve is treated as "no auth method" → getAuth returns nothing → the error above.

Fix: buildProvider now assembles auth as { apiKey: { name, resolve } }, matching the official dsh-llm-pi-ai routeAuth/harnessApiKeyAuth shape. The plugin also self-checks this contract at startup, so a version mismatch now fails loudly at boot instead of on your first message.

Second pitfall: editing a provider in the GUI wizard with the key field left blank wiped the existing apiKeyEnv, losing the credential reference after an upgrade/reconfigure (reported as MISSING_CREDENTIAL or auth failures). Fixed: in edit mode, a blank key means "keep unchanged" and the previous apiKeyEnv is preserved.

Contributing

Bugs and reports welcome — please open an issue via the bug report template (it asks for the DSH version, plugin version, and the compat-check output, which covers 90% of failures).

Before opening a PR, run the local checks:

npm run check                 # syntax (lib/index.mjs, lib/client.js, scripts/check-compat.mjs)
node scripts/check-compat.mjs --workspace ~/.workbuddy/binaries/node/workspace   # contract check against your real DSH

CI runs npm run check plus an npm-package sanity job (tarball file list and version-bump) on every push/PR — see .github/workflows/check.yml.

License

MIT