DeepSeek provider
Standalone — usable in any Node project, no
@warlock.js/corerequired.
@warlock.js/ai-deepseek is the DeepSeek provider adapter for
@warlock.js/ai. DeepSeek’s API is OpenAI-compatible
on the wire, so this package is a thin wrapper over the
OpenAI adapter: it constructs one internal
OpenAISDK pinned to https://api.deepseek.com with provider: "deepseek"
and delegates everything to it — while injecting DeepSeek’s own capability
inference and pricing so the right flags are set even though the model names
aren’t OpenAI names.
You get a vendor-neutral ModelContract — the same shape every agent,
workflow, and supervisor already speaks.
Install
Section titled “Install”npm install @warlock.js/ai @warlock.js/ai-deepseekyarn add @warlock.js/ai @warlock.js/ai-deepseekpnpm add @warlock.js/ai @warlock.js/ai-deepseekConstruct
Section titled “Construct”DeepSeekSDK is a class holding one long-lived wrapped client. Build it
once at boot and reuse it everywhere — every model it produces shares the
same connection pool, auth, and rate-limit state.
import { DeepSeekSDK } from "@warlock.js/ai-deepseek";
const deepseek = new DeepSeekSDK({ apiKey: process.env.DEEPSEEK_API_KEY! });apiKey is the only required field. baseURL defaults to
https://api.deepseek.com and provider defaults to "deepseek" (it flows
through to ModelContract.provider, AgentReport.model.provider, and logs).
Override baseURL only for a proxy/gateway, or provider to relabel the
upstream:
const deepseek = new DeepSeekSDK({ apiKey: process.env.DEEPSEEK_API_KEY!, baseURL: "https://my-gateway.internal/deepseek", provider: "deepseek-proxy",});First call
Section titled “First call”Build a model, hand it to an agent, run it. execute() never throws —
failures land in error as a typed AIError.
import { ai } from "@warlock.js/ai";import { DeepSeekSDK } from "@warlock.js/ai-deepseek";
const deepseek = new DeepSeekSDK({ apiKey: process.env.DEEPSEEK_API_KEY! });
const assistant = ai.agent({ model: deepseek.model({ name: "deepseek-chat" }), systemPrompt: "You are a concise senior TypeScript engineer.",});
const { text, usage, error } = await assistant.execute("Why use generics?");
if (error) { console.warn(error.code, error.category);} else { console.log(text, usage.total);}Use as a model
Section titled “Use as a model”deepseek.model({ name: "deepseek-chat" }); // V3 lineage, non-thinkingdeepseek.model({ name: "deepseek-reasoner" }); // R1 lineage, reasoning-capabledeepseek.model({ name: "deepseek-chat", temperature: 0.2 });Returns a ModelContract you pass straight into any agent, workflow, or
supervisor.
Models
Section titled “Models”| Model | Notes |
|---|---|
deepseek-chat | Non-thinking surface (V3 lineage). Fast, cheap, broad coverage. Reasoning off. |
deepseek-reasoner | Thinking surface (R1 lineage). Emits a reasoning channel. Reasoning on. |
deepseek-v4-flash | Newer flash tier. Reasoning off by default. |
deepseek-v4-pro | Newer quality tier. Reasoning on by default. |
DeepSeek announced the legacy deepseek-chat / deepseek-reasoner names
retire 2026/07/24 in favor of the deepseek-v4-* family; both name sets are
understood by the capability inference. deepseek.model({ name }) accepts any
id the upstream serves.
Capabilities
Section titled “Capabilities”The wrapper injects DeepSeek’s own inference so the right flags are set even though the model names aren’t OpenAI names:
| Flag | Default |
|---|---|
reasoning | Inferred from the model name — true for deepseek-reasoner and the *-pro tier; false for deepseek-chat / *-flash. Drives whether the reasoning-effort knob is forwarded. |
vision | false for every DeepSeek model — no DeepSeek chat model documents image input (mid-2026). |
structuredOutput | true (inherited from the wrapped OpenAI model), unless responseFormat is set to a loose mode. |
promptCaching | true (inherited). DeepSeek reports cache hits via usage.cachedTokens, the same shape as OpenAI. |
An explicit value always wins over the injected inference:
deepseek.model({ name: "deepseek-chat", reasoning: true }); // force the thinking flagdeepseek.model({ name: "deepseek-reasoner", reasoning: false }); // suppress itReasoning effort
Section titled “Reasoning effort”deepseek-reasoner (and the *-pro tier) emit a reasoning channel. When the
model is reasoning-capable, reasoning.effort ("low" | "medium" | "high")
maps verbatim to the OpenAI-compatible reasoning_effort param. When
capabilities.reasoning is false (e.g. deepseek-chat), the option is
dropped — the adapter never forwards it.
const model = deepseek.model({ name: "deepseek-reasoner" }); // reasoning auto-trueawait model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"Inherited from the OpenAI adapter
Section titled “Inherited from the OpenAI adapter”Everything on the wire — the Chat Completions request/response shape, the
streaming loop, tool-call accumulation, structured-output response_format,
multipart message mapping, and error wrapping — is inherited unchanged
from the OpenAI adapter against https://api.deepseek.com. Structured output
and streaming therefore behave exactly as documented for OpenAI; see
the OpenAI provider for the wire-level
detail, including the responseFormat override modes.
Pricing and usage
Section titled “Pricing and usage”Every response reports token usage (input, output, total); DeepSeek
prompt-cache hits surface as cachedTokens. The adapter ships built-in
DeepSeek pricing defaults (USD per million tokens, from DeepSeek’s published
table), so usage.cost is computed out of the box:
const deepseek = new DeepSeekSDK({ apiKey: process.env.DEEPSEEK_API_KEY! });// deepseek-chat → { input: 0.14, output: 0.28, cachedInput: 0.0028 }Override per SDK or per model exactly like the OpenAI adapter. Resolution at
model() time: per-model pricing > SDK pricing registry > built-in
DeepSeek default > undefined.
const deepseek = new DeepSeekSDK({ apiKey: process.env.DEEPSEEK_API_KEY!, pricing: { "deepseek-reasoner": { input: 0.55, output: 2.19 } },});Need an offline token estimate before a call? deepseek.count(text) returns
a fast character-heuristic approximation — good for budgeting and quota
guards, not for billing.
Embeddings and images
Section titled “Embeddings and images”deepseek.embedder({...}) and deepseek.image({...}) delegate to the wrapped
OpenAI adapter.
See also
Section titled “See also”- OpenAI provider — the wrapped adapter; all wire-level behavior applies here.
@warlock.js/ai— the agent, tool, and system-prompt surface these models plug into.- For provider-specific notes and the latest model ids, see the
setup-deepseekskill.