Skip to content

feat(providers): add a dedicated DeepSeek provider module - #3035

Merged
esokullu merged 2 commits into
webbrain-one:mainfrom
xianhongtao:feat/deepseek-provider
Sep 14, 2026
Merged

esokullu merged 2 commits into
webbrain-one:mainfrom
xianhongtao:feat/deepseek-provider

Conversation

@xianhongtao

Copy link
Copy Markdown
Contributor

Summary

Adds a dedicated DeepSeek provider and refreshes WebBrain against the current
DeepSeek API (V4.1 line). The vendor-specific logic is moved out of the shared
OpenAI-compatible modules into two new files, so openai.js and
provider-compatibility.js stay protocol-generic.

Docs of record: https://api-docs.deepseek.com/zh-cn/ (模型 & 价格 / 思考模式 /
图像理解 / 上下文硬盘缓存 / 使用 Responses API / 限速与隔离).

Why

  • The shipped default model id was the retired deepseek-v4-flash; the current
    id is deepseek-flash (DeepSeek-V4.1-Flash).
  • deepseek-flash was not recognised by the capacity tables: it fell through to
    the 8K output ceiling and the generic 128K context window instead of 384K / 1M.
  • Vision detection only knew deepseek-v4-flash-vision-exp, although the whole
    V4.1-Flash family is multimodal and deepseek-v4-pro is text-only.
  • The card still carried pre-V4.1 prices and had no cache-hit rate, and
    DeepSeek's top-level prompt_cache_hit_tokens counter was ignored, so cached
    input was billed at the full input rate.

Architecture

Two new modules per build (src/chrome + src/firefox):

  • providers/deepseek-config.js — the API contract: endpoints, shipped and
    retired model ids, model capacities, the reasoning-effort mapping, and the
    thinking / planner / vision request extras for both wire formats. It has no
    internal imports, so provider-compatibility.js can delegate to it without
    creating an import cycle.
  • providers/deepseek.jsDeepSeekProvider extends OpenAICompatibleProvider,
    owning vision capability, stream_options.include_usage, and cross-turn
    reasoning_content replay (DeepSeek returns 400 when a tool-carrying
    follow-up omits it).

ProviderManager#_createProvider() dispatches the deepseek card — or any card
pointed at api.deepseek.com, or one that explicitly selects the deepseek
compatibility preset — to the dedicated class. Router-hosted DeepSeek models
(for example deepseek/deepseek-v4 on OpenRouter) stay on the generic provider.

Cleanup in the shared modules: openai.js loses its DeepSeek import, the
deepseek entry in _shouldRequestStreamUsage(), the DeepSeek branch of
_supportsReasoningContentReplay(), and the DeepSeek id in the vision regex; it
gains a _modelNameSniffedVision(model) hook that vendor subclasses override.
provider-compatibility.js loses mappedDeepSeekReasoningEffort() and the
hard-coded DeepSeek host/endpoint knowledge and now delegates. A source-guard
test fails the build if DeepSeek literals reappear in either shared module.

Behaviour changes

Model id Context Max output Vision
deepseek-flash 1M 384K yes
deepseek-v4-flash, deepseek-v4-flash-vision-exp (retired aliases, same model) 1M 384K yes
deepseek-v4-pro (retired), deepseek-chat, deepseek-reasoner 64K 8K no

Unknown DeepSeek ids deliberately fall into the conservative profile rather than
inheriting capacities we cannot verify.

  • Thinking: top-level thinking object plus reasoning_effort; disabling
    thinking omits reasoning_effort entirely. The shared UI ladder maps
    minimallow and medium/xhighhigh, matching DeepSeek's table.
  • Wire format: Chat Completions stays the default. A new apiFormat
    selector in the Advanced panel opts into DeepSeek's Responses API, which then
    uses reasoning.effort (including none to disable thinking) and full
    text.format JSON Schema for the planner.
  • Cost: off-peak list price (1 input / 0.02 cached input / 4 output CNY per
    1M, peak 2 / 0.04 / 8) converted at 1 USD = 7.1 CNY, with a new
    cacheReadCostPerMillionUsd. usage.prompt_cache_hit_tokens is now counted
    as cached input and priced at the cache-read rate, and the field is preserved
    in usage traces.
  • Migration: cards that still hold the untouched shipped default (old model
    id, old base path and old prices, no API key, never saved) migrate to
    deepseek-flash and the new prices; saved or customised cards are never
    rewritten.
  • Images: deepseek-flash is advertised as multimodal, so screenshots flow
    through the existing image_url path.

Also updated

  • ui/settings.js: model suggestions drop the retired ids; the new apiFormat
    select is rendered only for the DeepSeek card, behind the Advanced panel.
  • i18n: one new key (st.provider.field.api_format) added to all 23 locale
    files in both builds.
  • Docs: docs/providers-and-models.md, docs/zh-CN/…, docs/fr/… — default
    model row, vision-detection table, a new DeepSeek section, and the contributor
    guidance now points at _modelNameSniffedVision() / vendor subclasses.

Verification

  • node test/run.js2308 passed, 0 failed (includes new assertions for
    model capacities, the Responses wire shape, prompt-cache pricing, dispatch,
    migration, and the module-boundary guard).
  • npm run test:provider-limits → passed.
  • Manual wire checks: default requests go to /chat/completions with
    thinking + reasoning_effort; reasoningEffort: off clears
    reasoning_effort; apiFormat: responses sends only reasoning.effort;
    deepseek-v4-pro no longer advertises vision.

Notes / follow-ups

  • user_id (DeepSeek's KVCache and scheduling isolation parameter) is not
    implemented; low concurrency limits (2500 for Flash) are expected to be fine
    for browser-agent traffic.
  • The Anthropic-format endpoint (https://api.deepseek.com/anthropic) works by
    overriding the built-in anthropic card's base URL; documented, not a new
    provider card.
  • Cost rates use off-peak prices, so peak-hour estimates are optimistic by 2×.

DeepSeek's V4.1 line (deepseek-flash) replaced the retired deepseek-v4-flash
default and changed the wire contract, so all DeepSeek knowledge moves out of
the shared OpenAI-compatible modules into two new files:

- providers/deepseek-config.js owns the API contract: endpoints, the shipped
  and retired model ids, model capacities, the reasoning-effort mapping, and
  the thinking/planner/vision request extras for both wire formats. It is
  dependency-free so provider-compatibility.js can import it without a cycle.
- providers/deepseek.js adds DeepSeekProvider extends OpenAICompatibleProvider,
  which owns vision capability, stream usage, and reasoning_content replay.

openai.js and provider-compatibility.js no longer contain any DeepSeek
literals: the shared provider gains a _modelNameSniffedVision() hook and the
compatibility presets delegate to the contract module. A source-guard test
keeps that boundary in place.

Behaviour changes:
- the default model is deepseek-flash; deepseek-v4-pro and the V3-era ids stay
  on a conservative 64K context / 8K output / text-only profile
- the V4.1-Flash family, including the retired deepseek-v4-flash aliases, is
  multimodal with a 1M context window and a 384K output ceiling
- Chat Completions stays the default wire format; the Responses API is an
  opt-in apiFormat setting that maps thinking to reasoning.effort
- pricing moves to the off-peak list price plus a cache-hit rate, and
  usage.prompt_cache_hit_tokens is priced at the cache-read rate
- untouched default configs migrate to the new model id and prices, while
  saved cards are never rewritten

Tests: test/run.js (2308 passed) and test/provider-model-limits.mjs.
Copilot AI balanced review requested due to automatic review settings September 14, 2026 04:12
@vercel

vercel Bot commented Sep 14, 2026

Copy link
Copy Markdown

@xianhongtao is attempting to deploy a commit to the esokullu's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@esokullu
esokullu merged commit 7ca0c6e into webbrain-one:main Sep 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants