Polyweave

@polyweave/deepseek (1.0.8)

Published 2026-07-11 15:23:17 +00:00 by Dvorak

Installation

@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/
npm install @polyweave/deepseek@1.0.8
"@polyweave/deepseek": "1.0.8"

About this package

@polyweave/deepseek

DeepSeek adapter for the Polyweave platform. OpenAI-compatible chat completions interface supporting streaming and batch modes, tool calling, image inputs, cost estimation with budget gating, and progressive receipt emission.

Published as @polyweave/deepseek.

Synopsis

import { createDeepSeekAdapter } from '@polyweave/deepseek';
import { createFrameSink, FrameType } from '@polyweave/core';

const adapter = createDeepSeekAdapter({
  apiKey: process.env.DEEPSEEK_API_KEY,
  model: 'deepseek-v4-pro',
  maxRetries: 2,
  budget: 0.50
});

adapter.source.pipe(createFrameSink(frame => {
  if (frame.type === 'TEXT') console.log(frame.content.text);
  if (frame.type === 'TOOL_CALL') console.log('Tool:', frame.content.name, frame.content.arguments);
  if (frame.type === 'RECEIPT') console.log('Cost:', frame.content.totalCost);
}));

// Send a chat message
adapter.sink.write({
  type: 'TEXT',
  streamId: 'chat-1',
  content: { text: 'Explain quantum computing in one paragraph.' }
});

// Use cost estimation before sending
adapter.sink.write({ type: 'COST_CHECK', content: { maxBudget: 0.01 } });
adapter.sink.write({ type: 'TEXT', streamId: 'chat-1', content: { text: 'Hello' } });
// Receives COST frame with estimate, or ERROR if over budget

Install

npm install @polyweave/deepseek

Why

DeepSeek provides state-of-the-art reasoning models (V4 Pro, R1) at a fraction of the cost of comparable providers, with an OpenAI-compatible API. This adapter handles the full lifecycle: conversation history management, streaming with progressive cost receipts, tool call accumulation across streaming chunks, configurable retry with exponential backoff, cost estimation with budget gating, and automatic partial receipts on error — so you never lose track of tokens consumed before a failure.

API

createDeepSeekAdapter(config)

Creates a DeepSeek adapter as a Polyweave frame duplex { source, sink }.

Parameters:

Name Type Required Default Description
config.apiKey string No process.env.DEEPSEEK_API_KEY || null DeepSeek API key. Can be set later via adapter.setReady(key) or PARAM { key: 'apiKey', value: '...' }.
config.baseURL string No "https://api.deepseek.com/v1" API base URL. Endpoint appended: /chat/completions.
config.timeout number No 120000 Request timeout in ms.
config.maxRetries number No 2 Maximum retry attempts on connection error or timeout. Backoff: 100ms × 2^n, capped at 10s.
config.budget number No 0 Hard spending limit in USD. Once cumulative spend exceeds this, TEXT/IMAGE/AUDIO frames are rejected with BUDGET_EXCEEDED.
config._debug boolean No false Enables verbose console logging of request/response details.
config.name string No null Human-readable name exposed on adapter.name.

Returns: IFrameDuplex { source, sink, setReady, ready, apiKey, resetConversation, _conversationLength, _outputTokenCount, name }

Additional properties on the returned duplex:

Property Type Description
setReady(key) function Set the API key post-creation. Flushes buffered frames.
ready boolean (getter) Whether the adapter has an API key.
apiKey string (getter) Current API key or null.
resetConversation() function Clears accumulated conversation history.
_conversationLength() function Returns length of conversation array (debug).
_outputTokenCount number Live count of output tokens during streaming (debug).
name string | null Adapter name from config.

Default accumulated parameters (set via PARAM frames):

Key Default Description
model "deepseek-v4-pro" Model identifier.
max_tokens 1024 Maximum output tokens.
temperature undefined Sampling temperature (0–2).
top_p undefined Nucleus sampling parameter.
stop undefined Stop sequence(s).
stream true Whether to use streaming. Set to false for batch.
thinking undefined Thinking mode. Defaults to { type: 'disabled' } when not set.
system undefined System prompt (prepended to every request as a system message).
messages undefined Raw messages (can replace conversation history).
tools undefined Tool definitions array. Enables tool calling.
tool_choice undefined Tool choice constraint. Only sent when tools is defined.
response_format undefined Response format specification.
logprobs undefined Log probabilities setting.
top_logprobs undefined Number of top logprobs to return.

Input frames (sink receives):

Frame type Action
TEXT Pushes user message to conversation history. Triggers chat request. Rejected if budget exceeded (emits ERROR + END).
IMAGE Pushes image message to conversation history. Requires content.url, content.data (base64), or content.b64_json. content.text or content.prompt provides accompanying text. Triggers chat request.
AUDIO Same as TEXT (added to conversation as user message). Triggers chat request.
TOOL_RESULT Pushes tool result to conversation as { role: 'tool', tool_call_id, content }. Does NOT trigger a request — next TEXT frame will include it in history.
TOOL_CALL Pushes tool call to conversation as assistant clause with tool_calls. Used when consumers replay tool call history.
PARAM Accumulates configuration. key: 'apiKey' triggers setReady(). Other keys update params dict.
START / END Ignored.
COST_CHECK Enters cost estimation mode. Subsequent frames are buffered, estimated, and checked against content.maxBudget. Emits a COST frame with estimate or an ERROR if over budget. Exits cost-check mode after emitting. Supports ESTIMATED_OUTPUT frames in the buffer (skipped).
TOPOLOGY_SCAN Responds with TOPOLOGY_REPORT.
TOPOLOGY_REPORT / TOPOLOGY_COMPLETE Passed through to source.
TEST_INJECT Injects frame arrays for testing.
TEST_SNAPSHOT Returns adapter paused state.

Output frames (source emits):

Frame type When Content
TEXT On each streaming chunk or batch response content.text with metadata: model, usage, finishReason.
TOOL_CALL On each tool call (accumulated across streaming chunks, emitted at finish) content.name, content.arguments (parsed JSON object), id (tool call ID).
RECEIPT On response end (batch) or every 50 output tokens (streaming progressive) + final end inputTokens, outputTokens, inputCost, outputCost, totalCost. Progressive receipts: progressive: true, final: false. Final: progressive: false, final: true. Emitted even on error with accumulated partial tokens.
COST Response to COST_CHECK Estimate: totalCost, bounds, accuracy, estimateSource, forwardEstimate, inputBounds, maxOutputTokens.
ERROR On API error, HTTP error, parse failure, budget exceeded, or timeout after all retries content.message, error code "ADAPTER_ERROR" or "BUDGET_EXCEEDED".
END After each response (or error) Metadata: model, usage, finishReason.
TOPOLOGY_REPORT / TEST_SNAPSHOT Protocol responses.

Error conditions:

Condition Error message Code
Budget exceeded (TEXT/IMAGE/AUDIO frame when totalSpent >= budgetTotal) "Budget exceeded" BUDGET_EXCEEDED
COST_CHECK estimate exceeds maxBudget "Estimated cost $X exceeds budget $Y" BUDGET_EXCEEDED
HTTP error status (≥400) API error message from response body, or "HTTP {statusCode}" ADAPTER_ERROR
Stream parse error "Stream error: {message}" (from API error object)
Batch parse error "Failed to parse response: {message}" ADAPTER_ERROR
Connection error after all retries "{message} (after {attempts} attempts)" ADAPTER_ERROR
Request timeout after all retries "Request timeout (after {attempts} attempts)" ADAPTER_ERROR
IMAGE frame without url/data/b64_json "IMAGE frame requires url, data, or b64_json" ADAPTER_ERROR
General catch in sink.write err.message ADAPTER_ERROR

On error during streaming, a partial progressive receipt is emitted for _outputTokenCount accumulated tokens before the ERROR frame, ensuring accurate cost tracking even when requests fail mid-stream.

Ready-state buffering:

If no apiKey is provided at creation, frames are buffered until setReady() is called with a key. Buffered frames are replayed through the sink.

getModelCost(model) (exported from src/costs.js)

Returns the pricing object for a DeepSeek model, or null if unknown.

Supported models and pricing (per million tokens):

Model Input ($/MTok) Output ($/MTok)
deepseek-chat 0.27 1.10
deepseek-v4-pro 0.27 1.10
deepseek-v3 0.27 1.10
deepseek-reasoner 0.55 2.19
deepseek-r1 0.55 2.19
deepseek-r1-0528 0.55 2.19
deepseek-r1-distill-qwen-1.5b 0.14 0.14
deepseek-r1-distill-qwen-7b 0.14 0.14
deepseek-r1-distill-qwen-14b 0.14 0.14
deepseek-r1-distill-qwen-32b 0.14 0.14
deepseek-r1-distill-llama-8b 0.14 0.14
deepseek-r1-distill-llama-70b 0.14 0.14

calculateTokenCost(model, inputTokens, outputTokens) (exported from src/costs.js)

Calculates cost from token counts using the pricing table above.

Parameters:

Name Type Required Default Description
model string Yes Model identifier.
inputTokens number No 0 Prompt tokens.
outputTokens number No 0 Completion tokens.

Returns: { inputCost: number, outputCost: number, totalCost: number } — all in USD. Returns { inputCost: 0, outputCost: 0, totalCost: 0 } if the model is unknown.

Tests

npm test

Runs node --test test/deepseek.test.js test/rigor.test.js. Covering: adapter creation with API key, PARAM accumulation, cost calculation for all models, cost monotonicity (inputTokens/outputTokens), streaming frame handling, budget gating, and progressive receipt emission.

Requirements

  • Node.js >= 22.0.0
  • ESM only
  • Runtime dependencies: @polyweave/costs
  • Peer dependencies: @polyweave/core, @polyweave/errors, @polyweave/costs — must be installed alongside.
  • DeepSeek API key (set via DEEPSEEK_API_KEY env var, config option, or PARAM frame).

Caveats

  • Conversation history accumulates in memory. Use adapter.resetConversation() between logical sessions. There is no automatic history pruning.
  • Tool calls in streaming mode are accumulated across chunks — the function name and arguments arrive piecewise in delta.tool_calls. They are emitted as TOOL_CALL frames only when finish_reason is present in the stream.
  • The thinking parameter defaults to { type: 'disabled' } when not explicitly set. To use DeepSeek's reasoning/thinking mode, set it via PARAM: { key: 'thinking', value: { type: 'enabled' } }.
  • stream_options.include_usage is always enabled when streaming, ensuring token usage is reported in stream chunks.
  • The budget tracker (config.budget) is a simple cumulative counter across the adapter's lifetime. There is no per-request or per-session budget — it tracks total spend since creation.
  • Cost estimation mode (COST_CHECK) uses @polyweave/costs createCostEstimator with provider 'deepseek' and default model 'deepseek-v4-pro'.

Dependencies

Development Dependencies

ID Version
@rigor/core *

Peer Dependencies

ID Version
@polyweave/core *
@polyweave/costs *
@polyweave/errors *

Keywords

polyweave deepseek ai adapter
Details
npm
2026-07-11 15:23:17 +00:00
185
John Dvorak
SEE LICENSE IN LICENSE
latest
9.8 KiB
Assets (1)
Versions (5) View all
1.0.8 2026-07-11
1.0.5 2026-07-10
1.0.4 2026-07-10
1.0.3 2026-07-10
1.0.2 2026-07-10