@namzu/deepseek 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,182 @@
1
1
  # @namzu/deepseek
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - ee4fd1d: Persist provider-native reasoning state with the exact provider, model, and fallback-chain member that produced it. Same-route sessions now replay native reasoning after restart, `/resume`, and `/fork`; a model, provider, or member switch keeps portable assistant/tool history without sending foreign native reasoning metadata.
8
+
9
+ `@namzu/sdk` adds `ProviderRoute`, `AssistantMessageSource`, optional assistant source/replay fields, and the provider request/stream/response plumbing. Fallback and forced-final turns now attribute provenance and cost to the member that actually answered.
10
+
11
+ `@namzu/cli` preserves and validates the additive assistant source shape in stateless and durable history.
12
+
13
+ **What breaks in the drivers:** hand-built assistant reasoning and histories written by earlier versions do not carry a validated route-bound replay envelope, so they are no longer emitted as native `reasoning_content` or signed thinking. Their portable assistant text and tool exchanges remain available, but an upstream that requires native metadata for an old tool continuation may refuse that request; compact or start a fresh conversation before continuing such legacy history. Preserve the complete assistant message returned by new runs, including `source.replayState`. Direct callers of the exported DeepSeek `toDeepSeekMessages` converter must also pass the target `ProviderRoute` as its second argument.
14
+
15
+ ### Minor Changes
16
+
17
+ - 94d3306: Add the chain-aware `reasoningEffortLevelsFor(model, thinking)` provider capability while retaining `effortLevelsFor` as a deprecated compatibility member. The four capability states now distinguish a driver with no menu, an unknown model, an explicitly unsupported model, and an exact selectable set; fallback chains expose only levels every reachable member accepts.
18
+
19
+ The TUI adds session-scoped `/effort [level|default]`, sends the selection to later main-query turns, and resets it atomically when a provider/model replacement succeeds. Failed or cancelled replacements preserve the current selection.
20
+
21
+ OpenAI publishes exact known-model menus and keeps unknown compatible-endpoint models unknown. DeepSeek explicitly publishes no supported levels. Anthropic now refuses unsupported effort levels before transport instead of silently dropping them; callers upgrading Anthropic must choose a level returned by `reasoningEffortLevelsFor()` or omit `effort` to retain the provider default.
22
+
23
+ ### Patch Changes
24
+
25
+ - 15f8ee4: Bound provider stream silence, including query-owned advisory calls and
26
+ RouterAgent routing decisions, compaction verifiers and model-graded eval
27
+ judges, to five minutes by default and abort the stalled provider transport,
28
+ with network-classified retry and fallback recovery where those policies
29
+ apply. This changes the previous default, under which a provider iterator could
30
+ remain silent forever. Set `streamIdleTimeoutMs: 0` on the run, agent, manual
31
+ compaction, verifier, or judge config to keep the old unbounded behavior, or set
32
+ a positive millisecond value to choose a different bound.
33
+
34
+ Queries whose caller signal is already aborted now settle as cancelled before
35
+ starting provider, provider-metadata, or tool work. A later cancellation also
36
+ settles while an optional context-window resolver remains pending, even when
37
+ that resolver ignores its signal. With no caller cancellation, `timeoutMs`
38
+ bounds the optional metadata lookup, aborts its private transport signal, and
39
+ falls back to the static context-window table instead of blocking the run.
40
+
41
+ The OpenRouter context-window lookup now forwards cancellation to its model-list
42
+ transport. Only fulfilled listings are cached, so cancelling one concurrent
43
+ query cannot abort another query's shared metadata request or force that query
44
+ onto the static context-window table.
45
+
46
+ `runExperiment({ timeoutMs })` now applies one validated wall-clock deadline to
47
+ both case execution and scoring. Scorers receive its optional cancellation
48
+ signal; a non-cooperative scorer is detached, and `judgeScorer` forwards the
49
+ signal to its bounded provider transport. Values outside the positive platform
50
+ timer range are refused before a case starts; omit the field for the prior
51
+ unbounded case behavior.
52
+
53
+ Compaction verification inside a query now carries the run cancellation cause
54
+ to its provider transport without placing a second idle timer around retry and
55
+ fallback. Public `buildVerifiedSummary`, `compactNow`, and `compactRegion`
56
+ calls bound raw provider silence themselves and accept optional `signal` and
57
+ `streamIdleTimeoutMs`; malformed values and pre-cancelled manual work are
58
+ refused before provider work or a no-op result.
59
+
60
+ HTTP embedding batches now have a 30-second whole-request default, including
61
+ response-body reads, where the previous default could wait forever. Set
62
+ `requestTimeoutMs: 0` on `HttpEmbeddingProvider` to keep the former unbounded
63
+ behavior. Invalid timeout values and non-positive or fractional `batchSize`
64
+ or `dimensions` values are refused at construction instead of silently
65
+ disabling the bound or entering a non-progressing batch loop. Successful HTTP
66
+ responses must contain exactly one unique, in-range result per input and finite
67
+ vectors of the configured dimension; malformed or incomplete batches are
68
+ refused atomically instead of reaching ingestion with missing embeddings.
69
+
70
+ Public RAG operations accept optional cancellation context. The shipped
71
+ `knowledge_search` tool forwards its run-owned signal through
72
+ `KnowledgeBase`, retrieval or ingestion, and the embedding provider. The HTTP
73
+ provider preserves the caller's exact cancellation reason while aborting only
74
+ its private fetch transport. Custom embedding providers receive the signal as
75
+ a cooperative request; callers still own their wait boundary if a custom
76
+ implementation ignores it. Default retrieval and ingestion recheck authority
77
+ after that custom call settles, so a late result cannot start a vector search
78
+ or persist chunks after cancellation. `VectorStore.search` and `upsert` now
79
+ receive the same optional operation context. The default pipelines also race
80
+ those store promises against cancellation, so a non-cooperative custom store
81
+ cannot leave the public query or ingestion call pending forever.
82
+
83
+ A2A agent-card discovery now has a 30-second whole fetch-and-body default and
84
+ accepts an optional caller signal and `timeoutMs`; set `timeoutMs: 0` to retain
85
+ the former unbounded behavior. `A2ADelegate.timeoutMs` now starts before
86
+ `message/send` and bounds the whole delegation instead of polling only. A
87
+ pre-cancelled dispatch starts no remote work, pending fetch and body promises
88
+ cannot hold `waitForTask`, and caller cancellation preserves its exact cause on
89
+ the private transport. Poll and delegation timers are validated at
90
+ construction. Once a safe task id exists, cancellation or timeout sends one
91
+ independently bounded `tasks/cancel`; during initial task creation the client
92
+ keeps a short cleanup grace and explicitly reports an unknown remote outcome if
93
+ the peer never returns an addressable id. Poll replies are bound to that initial
94
+ id, and transport or protocol failures after it is known make the same bounded
95
+ cleanup attempt before the original failure is returned. An `input-required`
96
+ task is also bounded-cancelled before the delegate reports that it cannot
97
+ supply the requested input.
98
+
99
+ Connector execution now carries optional operation authority through the
100
+ manager, every connector-tool adapter, real query runs, tenant/environment
101
+ facades, health checks, and `MCPConnectorBridge.callTool`. Custom connectors
102
+ receive the signal; if they ignore it, the manager settles with an honest
103
+ unknown remote outcome and rejects a late success that does not identify a
104
+ received response. A tenant call cancelled before admission no longer spends a
105
+ rate-limit slot.
106
+
107
+ `HttpConnector` and `WebhookConnector` now apply one validated 30-second
108
+ fetch-and-body deadline and a streaming 2 MiB response limit by default. Set
109
+ positive `timeoutMs` and `maxResponseBytes` values to choose different bounds.
110
+ Cancellation, deadline, or response-size failure aborts only the private
111
+ transport/body reader and preserves the caller's exact cause. Result metadata
112
+ distinguishes `not_started`, `unknown`, and `response_received`, includes retry
113
+ safety, and keeps a received status visible when its body is unavailable.
114
+
115
+ Dynamic HTTP paths and webhook URL overrides must remain on the configured
116
+ origin. Model-authored routing headers are refused, redirects are not followed,
117
+ and 3xx responses are no longer reported as success. Configure a separate
118
+ connector instance for each authorized origin; callers that previously used a
119
+ cross-origin webhook override must migrate to that instance.
120
+
121
+ `GuardedFetchProvider` now applies one validated 30-second deadline across DNS
122
+ resolution, every manually admitted redirect fetch, and the final response
123
+ body, while preserving a caller's exact cancellation cause on a private
124
+ transport signal. Its 2 MiB default response cap is enforced from streamed
125
+ bytes rather than after `response.text()` allocates the whole body; overflow
126
+ cancels the reader and returns a valid UTF-8 prefix. Redirect bodies are
127
+ cancelled when abandoned, and a spent redirect budget causes no DNS lookup for
128
+ the next target. Set positive `timeoutMs` and `maxBytes` values or a
129
+ non-negative integer `maxRedirects` to choose other bounds. Custom
130
+ `GuardedFetchConfig.resolve` functions may now accept the operation signal as
131
+ a second argument. IPv4-mapped IPv6 literals are canonicalized back to their
132
+ IPv4 address before range checks, closing the hexadecimal mapped loopback and
133
+ link-local bypass; the full IPv6 link-local and multicast ranges are also
134
+ refused.
135
+
136
+ MCP request methods now accept optional cancellation authority, and generated
137
+ MCP tool and prompt adapters forward the run-owned tool signal. A pre-aborted
138
+ request starts no transport work; a pending request preserves the caller's
139
+ exact cause, aborts a private transport, removes its correlated pending id, and
140
+ makes a one-second best-effort `notifications/cancelled` attempt. The
141
+ notification does not prove that an already-started remote side effect stopped.
142
+ Paged list calls recheck the same signal before each page.
143
+
144
+ `MCPClient.requestTimeoutMs` and HTTP MCP transport `timeoutMs` values must now
145
+ be positive platform-range integers. A shorter transport deadline remains a
146
+ request-timeout terminal and emits the same correlated cancellation. HTTP
147
+ fetches and response-body reads share operation authority; disconnect owns
148
+ active requests and cancellation cleanup. Reconnects fence late POST responses
149
+ and SSE batches from prior generations, clear Streamable session state, and
150
+ accept session ids only from successful `initialize` responses. Per-send
151
+ failure no longer marks a Streamable client connection-wide errored or rejects
152
+ unrelated concurrent calls. `MCPTransport.send` now accepts optional
153
+ `MCPTransportSendOptions`; custom transports should refuse pre-aborted work and
154
+ stop their per-send I/O when its signal fires.
155
+
156
+ Provider model listings and credential probes now accept optional cancellation
157
+ signals. Retry, fallback, stream-idle and instrumentation decorators preserve
158
+ that authority, and every bundled CLI driver forwards it to the underlying
159
+ transport where supported or refuses a result that arrived after cancellation.
160
+ Existing zero-argument provider implementations remain valid.
161
+
162
+ The interactive provider picker now cancels model discovery, credential checks
163
+ and subscription sign-in when the operator backs out, supersedes the work, or
164
+ leaves the screen. Late results cannot reopen an old model step, accept a
165
+ credential, re-probe the application, or persist a subscription credential
166
+ after cancellation. Model listing and credential probing both settle after a
167
+ three-second bound even when a custom provider ignores its signal.
168
+
169
+ Between-turn and durable-resume subscription refreshes now settle on caller
170
+ cancellation and apply one 30-second bound across the token request and response
171
+ body. Refreshes in one session are serialized and re-read their source at the
172
+ head of the queue, preventing a later stale caller from downgrading a token
173
+ published by an earlier one. Namzu's credential file uses an exact conditional
174
+ replacement under a cross-process, atomically published lock; an external
175
+ rotation or logout wins, and an uncertain publication refuses instead of using
176
+ an uncommitted refresh. Borrowed macOS Keychain credentials are read-only: a
177
+ changed or removed entry wins, and a successful refresh of an unchanged entry
178
+ remains session-local.
179
+
3
180
  ## 0.1.0
4
181
 
5
182
  ### Minor Changes
package/README.md CHANGED
@@ -6,7 +6,7 @@ description: >-
6
6
  streaming and tool use, and thinking mode mapped onto the kernel's reasoning
7
7
  blocks in both directions.
8
8
  tags: [readme, package, provider, deepseek]
9
- timestamp: 2026-08-17T00:00:00Z
9
+ timestamp: 2026-08-20T00:00:00Z
10
10
  status: active
11
11
  diataxis: reference
12
12
  -->
@@ -70,8 +70,10 @@ Models are `deepseek-v4-flash` and `deepseek-v4-pro`. `deepseek-chat` and
70
70
 
71
71
  **Thinking is on by default** — the vendor's default, not this driver's. The
72
72
  chain of thought arrives as `delta.reasoning` fragments, the same channel
73
- `@namzu/anthropic` uses, and is replayed back to the vendor automatically on
74
- later turns, which its tool-calling flow requires.
73
+ `@namzu/anthropic` uses. The kernel persists it with versioned adapter state and
74
+ the exact provider/model/fallback route, so the same configured route replays it
75
+ after restart or `/resume`. A model, provider, or chain-member switch keeps the
76
+ portable assistant/tool history and omits the foreign native reasoning field.
75
77
 
76
78
  Turn it off per call with `thinking: { type: 'disabled' }`.
77
79
 
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ChatCompletionParams, LLMProvider, ModelInfo, ProviderCapabilities, StreamChunk, ThinkingConfig } from '@namzu/sdk';
1
+ import type { ChatCompletionParams, LLMProvider, ModelInfo, ProviderCapabilities, ProviderRoute, ReasoningEffort, StreamChunk, ThinkingConfig } from '@namzu/sdk';
2
2
  import type { ChatCompletionMessageParam, ChatCompletionTool } from 'openai/resources/chat/completions';
3
3
  import type { DeepSeekConfig } from './types.js';
4
4
  /**
@@ -49,7 +49,7 @@ export declare function assertSamplingUsable(params: ChatCompletionParams, mode:
49
49
  * Completions and says so.
50
50
  */
51
51
  export declare function assertEffortUnsupported(params: ChatCompletionParams): void;
52
- export declare function toDeepSeekMessages(messages: ChatCompletionParams['messages']): ChatCompletionMessageParam[];
52
+ export declare function toDeepSeekMessages(messages: ChatCompletionParams['messages'], targetRoute: ProviderRoute): ChatCompletionMessageParam[];
53
53
  export declare function toDeepSeekTools(params: ChatCompletionParams): ChatCompletionTool[] | undefined;
54
54
  export declare class DeepSeekProvider implements LLMProvider {
55
55
  readonly id = "deepseek";
@@ -60,9 +60,11 @@ export declare class DeepSeekProvider implements LLMProvider {
60
60
  private samplingMode;
61
61
  constructor(config: DeepSeekConfig);
62
62
  private resolveModel;
63
+ /** This Chat Completions endpoint explicitly carries no effort control. */
64
+ reasoningEffortLevelsFor(_model: string): readonly ReasoningEffort[];
63
65
  chatStream(params: ChatCompletionParams): AsyncIterable<StreamChunk>;
64
- probeCredential(): Promise<void>;
65
- listModels(): Promise<ModelInfo[]>;
66
+ probeCredential(signal?: AbortSignal): Promise<void>;
67
+ listModels(signal?: AbortSignal): Promise<ModelInfo[]>;
66
68
  healthCheck(): Promise<boolean>;
67
69
  }
68
70
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EAEpB,WAAW,EACX,SAAS,EACT,oBAAoB,EAEpB,WAAW,EACX,cAAc,EAGd,MAAM,YAAY,CAAA;AAUnB,OAAO,KAAK,EACX,0BAA0B,EAC1B,kBAAkB,EAElB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,oBAMnC,CAAA;AAuFD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GACvB,IAAI,CAQN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAK1E;AA0BD,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,oBAAoB,CAAC,UAAU,CAAC,GACxC,0BAA0B,EAAE,CAoC9B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,oBAAoB,GAAG,kBAAkB,EAAE,GAAG,SAAS,CAe9F;AAED,qBAAa,gBAAiB,YAAW,WAAW;IACnD,QAAQ,CAAC,EAAE,cAAa;IACxB,QAAQ,CAAC,IAAI,cAAa;IAC1B,QAAQ,CAAC,YAAY,uBAAwB;IAE7C,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,YAAY,CAAC,CAAQ;IAC7B,OAAO,CAAC,YAAY,CAAqB;gBAE7B,MAAM,EAAE,cAAc;IAgBlC,OAAO,CAAC,YAAY;IAUb,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,aAAa,CAAC,WAAW,CAAC;IAiJrE,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAYlC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAQrC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EAEpB,WAAW,EACX,SAAS,EACT,oBAAoB,EACpB,aAAa,EAEb,eAAe,EACf,WAAW,EACX,cAAc,EAGd,MAAM,YAAY,CAAA;AAUnB,OAAO,KAAK,EACX,0BAA0B,EAC1B,kBAAkB,EAElB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,EAAE,oBAMnC,CAAA;AAuFD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GACvB,IAAI,CAQN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAK1E;AAuGD,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,oBAAoB,CAAC,UAAU,CAAC,EAC1C,WAAW,EAAE,aAAa,GACxB,0BAA0B,EAAE,CA0C9B;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,oBAAoB,GAAG,kBAAkB,EAAE,GAAG,SAAS,CAe9F;AAED,qBAAa,gBAAiB,YAAW,WAAW;IACnD,QAAQ,CAAC,EAAE,cAAa;IACxB,QAAQ,CAAC,IAAI,cAAa;IAC1B,QAAQ,CAAC,YAAY,uBAAwB;IAE7C,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,YAAY,CAAC,CAAQ;IAC7B,OAAO,CAAC,YAAY,CAAqB;gBAE7B,MAAM,EAAE,cAAc;IAmBlC,OAAO,CAAC,YAAY;IAUpB,2EAA2E;IAC3E,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE;IAI7D,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,aAAa,CAAC,WAAW,CAAC;IA6KrE,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD,UAAU,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IActD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAQrC"}
package/dist/client.js CHANGED
@@ -119,14 +119,58 @@ export function assertEffortUnsupported(params) {
119
119
  return;
120
120
  throw new Error(`DeepSeekProvider: \`effort\` is not carried by this endpoint. The vendor's Chat Completions wire validates \`thinking.type\` and ignores any effort sent beside it, so passing one through would change nothing and report success. Use \`thinking: { type: 'adaptive' | 'enabled' | 'disabled' }\` to steer this driver.`);
121
121
  }
122
+ function sameRoute(left, right) {
123
+ return (left.providerId === right.providerId &&
124
+ left.model === right.model &&
125
+ left.chainIndex === right.chainIndex);
126
+ }
127
+ function resolveDeepSeekRoute(model, candidate) {
128
+ if (candidate === undefined)
129
+ return { providerId: 'deepseek', model, chainIndex: 0 };
130
+ if (candidate.providerId !== 'deepseek' ||
131
+ candidate.model !== model ||
132
+ !Number.isSafeInteger(candidate.chainIndex) ||
133
+ candidate.chainIndex < 0) {
134
+ throw new Error('DeepSeekProvider: providerRoute must name this provider, the requested model, and a non-negative integer chainIndex.');
135
+ }
136
+ return candidate;
137
+ }
138
+ function isDeepSeekReplayState(value) {
139
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
140
+ return false;
141
+ const state = value;
142
+ const route = state.route;
143
+ return (state.kind === 'namzu-deepseek-reasoning' &&
144
+ state.version === 1 &&
145
+ typeof state.reasoningContent === 'string' &&
146
+ state.reasoningContent.length > 0 &&
147
+ typeof route === 'object' &&
148
+ route !== null &&
149
+ !Array.isArray(route) &&
150
+ typeof route.providerId === 'string' &&
151
+ typeof route.model === 'string' &&
152
+ Number.isSafeInteger(route.chainIndex) &&
153
+ route.chainIndex >= 0);
154
+ }
155
+ function durableDeepSeekReasoning(reasoning) {
156
+ if (!reasoning || reasoning.length === 0)
157
+ return undefined;
158
+ if (reasoning.some((block) => block.type !== 'thinking' ||
159
+ typeof block.text !== 'string' ||
160
+ block.signature !== undefined ||
161
+ block.encrypted !== undefined)) {
162
+ return undefined;
163
+ }
164
+ const text = reasoning.map((block) => block.text).join('');
165
+ return text.length > 0 ? text : undefined;
166
+ }
122
167
  /**
123
- * The reasoning blocks an assistant message carries, in wire form.
168
+ * Restore `reasoning_content` only from a validated same-route envelope.
124
169
  *
125
- * The vendor's rule: with tool calls in play, an assistant turn's
126
- * `reasoning_content` **must** be replayed in every later turn of the same
127
- * flow; without tool calls it is ignored if sent. Replayed unconditionally
128
- * here, which satisfies both halves and matches what `AssistantMessage.reasoning`
129
- * already promises — "replayed verbatim and ahead of the text/tool blocks".
170
+ * The vendor's rule: with tool calls in play, an assistant turn's native
171
+ * reasoning must be echoed on later turns. Matching provider/model names are
172
+ * not enough: state can come from another chain member or another adapter
173
+ * format, and legacy messages carry no proof at all.
130
174
  *
131
175
  * Measured note, because it matters to anyone debugging this: as of
132
176
  * 2026-08-17 omitting the replay does NOT produce the documented 400 on either
@@ -134,16 +178,17 @@ export function assertEffortUnsupported(params) {
134
178
  * a contract the vendor states and does not currently enforce is a contract
135
179
  * that can start being enforced in any release.
136
180
  */
137
- function replayReasoning(reasoning) {
138
- if (!reasoning || reasoning.length === 0)
181
+ function replayReasoning(message, targetRoute) {
182
+ const source = message.source;
183
+ if (!source || source.type !== 'model' || !sameRoute(source, targetRoute))
139
184
  return undefined;
140
- const text = reasoning
141
- .filter((b) => b.type === 'thinking' && typeof b.text === 'string')
142
- .map((b) => b.text)
143
- .join('');
144
- return text.length > 0 ? text : undefined;
185
+ const state = source.replayState;
186
+ if (!isDeepSeekReplayState(state) || !sameRoute(state.route, source))
187
+ return undefined;
188
+ const durable = durableDeepSeekReasoning(message.reasoning);
189
+ return durable !== undefined && durable === state.reasoningContent ? durable : undefined;
145
190
  }
146
- export function toDeepSeekMessages(messages) {
191
+ export function toDeepSeekMessages(messages, targetRoute) {
147
192
  return messages.map((msg) => {
148
193
  if (msg.role === 'system')
149
194
  return { role: 'system', content: msg.content };
@@ -164,16 +209,22 @@ export function toDeepSeekMessages(messages) {
164
209
  tool_call_id: msg.toolCallId,
165
210
  };
166
211
  }
167
- const assistant = { role: 'assistant', content: msg.content };
212
+ const assistant = {
213
+ role: 'assistant',
214
+ content: msg.content,
215
+ };
168
216
  if ('toolCalls' in msg && msg.toolCalls && msg.toolCalls.length > 0) {
169
217
  ;
170
218
  assistant.tool_calls = msg.toolCalls.map((tc) => ({
171
219
  id: tc.id,
172
220
  type: 'function',
173
- function: { name: tc.function.name, arguments: tc.function.arguments },
221
+ function: {
222
+ name: tc.function.name,
223
+ arguments: tc.function.arguments,
224
+ },
174
225
  }));
175
226
  }
176
- const replayed = replayReasoning(msg.reasoning);
227
+ const replayed = replayReasoning(msg, targetRoute);
177
228
  if (replayed !== undefined) {
178
229
  ;
179
230
  assistant.reasoning_content = replayed;
@@ -215,7 +266,10 @@ export class DeepSeekProvider {
215
266
  };
216
267
  if (config.timeout !== undefined)
217
268
  clientOptions.timeout = config.timeout;
218
- clientOptions.defaultHeaders = { ...attributionHeaders(), ...(config.defaultHeaders ?? {}) };
269
+ clientOptions.defaultHeaders = {
270
+ ...attributionHeaders(),
271
+ ...(config.defaultHeaders ?? {}),
272
+ };
219
273
  this.client = new OpenAI(clientOptions);
220
274
  this.defaultModel = config.model;
221
275
  this.samplingMode = config.samplingInThinkingMode ?? 'refuse';
@@ -227,8 +281,13 @@ export class DeepSeekProvider {
227
281
  }
228
282
  return model;
229
283
  }
284
+ /** This Chat Completions endpoint explicitly carries no effort control. */
285
+ reasoningEffortLevelsFor(_model) {
286
+ return [];
287
+ }
230
288
  async *chatStream(params) {
231
289
  const model = this.resolveModel(params);
290
+ const providerRoute = resolveDeepSeekRoute(model, params.providerRoute);
232
291
  assertEffortUnsupported(params);
233
292
  assertSamplingUsable(params, this.samplingMode);
234
293
  const sampling = thinkingEnabled(params.thinking)
@@ -246,7 +305,7 @@ export class DeepSeekProvider {
246
305
  // to the non-streaming overload, whose result has no async iterator.
247
306
  const body = {
248
307
  model,
249
- messages: toDeepSeekMessages(params.messages),
308
+ messages: toDeepSeekMessages(params.messages, providerRoute),
250
309
  stream: true,
251
310
  stream_options: { include_usage: true },
252
311
  tools: toDeepSeekTools(params),
@@ -282,6 +341,8 @@ export class DeepSeekProvider {
282
341
  // `reasoning_content` as a flat run of deltas with no index and no
283
342
  // block boundaries, so index 0 is the whole of it rather than a guess.
284
343
  let reasoningOpen = false;
344
+ let reasoningContent = '';
345
+ let replayStateEmitted = false;
285
346
  try {
286
347
  for await (const chunk of stream) {
287
348
  params.signal?.throwIfAborted();
@@ -303,9 +364,12 @@ export class DeepSeekProvider {
303
364
  const usage = chunk.usage ? parseUsage(chunk.usage) : undefined;
304
365
  if (reasoningText) {
305
366
  reasoningOpen = true;
367
+ reasoningContent += reasoningText;
306
368
  yield {
307
369
  id: chunk.id,
308
- delta: { reasoning: { index: 0, type: 'thinking', text: reasoningText } },
370
+ delta: {
371
+ reasoning: { index: 0, type: 'thinking', text: reasoningText },
372
+ },
309
373
  };
310
374
  }
311
375
  // The block closes when content or a tool call starts, which is
@@ -316,14 +380,28 @@ export class DeepSeekProvider {
316
380
  (toolCalls !== undefined && toolCalls.length > 0);
317
381
  if (reasoningOpen && contentStarting) {
318
382
  reasoningOpen = false;
319
- yield { id: chunk.id, delta: { reasoning: { index: 0, done: true } } };
383
+ yield {
384
+ id: chunk.id,
385
+ delta: { reasoning: { index: 0, done: true } },
386
+ };
320
387
  }
321
388
  const hasDelta = (delta?.content !== undefined && delta.content !== null) ||
322
389
  (toolCalls !== undefined && toolCalls.length > 0);
323
390
  if (!hasDelta && !finishReason && !usage)
324
391
  continue;
392
+ const replayState = !replayStateEmitted && finishReason && reasoningContent.length > 0
393
+ ? {
394
+ kind: 'namzu-deepseek-reasoning',
395
+ version: 1,
396
+ route: providerRoute,
397
+ reasoningContent,
398
+ }
399
+ : undefined;
400
+ if (replayState !== undefined)
401
+ replayStateEmitted = true;
325
402
  yield {
326
403
  id: chunk.id,
404
+ ...(replayState !== undefined ? { replayState } : {}),
327
405
  delta: { content: delta?.content ?? undefined, toolCalls },
328
406
  finishReason,
329
407
  usage,
@@ -342,7 +420,10 @@ export class DeepSeekProvider {
342
420
  // A turn that was all reasoning and no content — the model thought
343
421
  // and then stopped — still has to close its block.
344
422
  if (reasoningOpen) {
345
- yield { id: 'deepseek-reasoning-close', delta: { reasoning: { index: 0, done: true } } };
423
+ yield {
424
+ id: 'deepseek-reasoning-close',
425
+ delta: { reasoning: { index: 0, done: true } },
426
+ };
346
427
  }
347
428
  }
348
429
  catch (err) {
@@ -353,11 +434,15 @@ export class DeepSeekProvider {
353
434
  throw providerVendorError({ providerId: 'deepseek', error: err });
354
435
  }
355
436
  }
356
- async probeCredential() {
357
- await this.client.models.list();
437
+ async probeCredential(signal) {
438
+ signal?.throwIfAborted();
439
+ await this.client.models.list(signal ? { signal } : undefined);
440
+ signal?.throwIfAborted();
358
441
  }
359
- async listModels() {
360
- const page = await this.client.models.list();
442
+ async listModels(signal) {
443
+ signal?.throwIfAborted();
444
+ const page = await this.client.models.list(signal ? { signal } : undefined);
445
+ signal?.throwIfAborted();
361
446
  return page.data.map((m) => ({
362
447
  id: m.id,
363
448
  name: m.id,
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/deepseek",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "DeepSeek LLM provider for @namzu/sdk. Chat Completions with streaming, tool use, and thinking mode mapped onto the kernel's reasoning blocks.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "engines": {
@@ -46,16 +46,6 @@
46
46
  "access": "public",
47
47
  "provenance": true
48
48
  },
49
- "scripts": {
50
- "build": "tsc --build",
51
- "dev": "tsc --build --watch",
52
- "lint": "biome check src/",
53
- "lint:fix": "biome check --write src/",
54
- "format": "biome format --write src/",
55
- "test": "vitest run --passWithNoTests",
56
- "typecheck": "tsc --noEmit",
57
- "prepublishOnly": "pnpm lint && pnpm typecheck && pnpm build"
58
- },
59
49
  "dependencies": {
60
50
  "openai": "^6.0.0"
61
51
  },
@@ -64,9 +54,18 @@
64
54
  },
65
55
  "devDependencies": {
66
56
  "@biomejs/biome": "^1.9.4",
67
- "@namzu/sdk": "workspace:^",
68
57
  "@types/node": "^22.19.17",
69
58
  "typescript": "^5.5.0",
70
- "vitest": "^3.2.6"
59
+ "vitest": "^3.2.6",
60
+ "@namzu/sdk": "^31.0.0"
61
+ },
62
+ "scripts": {
63
+ "build": "tsc --build",
64
+ "dev": "tsc --build --watch",
65
+ "lint": "biome check src/",
66
+ "lint:fix": "biome check --write src/",
67
+ "format": "biome format --write src/",
68
+ "test": "vitest run --passWithNoTests",
69
+ "typecheck": "tsc --noEmit"
71
70
  }
72
- }
71
+ }
package/src/client.ts CHANGED
@@ -4,7 +4,9 @@ import type {
4
4
  LLMProvider,
5
5
  ModelInfo,
6
6
  ProviderCapabilities,
7
+ ProviderRoute,
7
8
  ReasoningBlock,
9
+ ReasoningEffort,
8
10
  StreamChunk,
9
11
  ThinkingConfig,
10
12
  TokenUsage,
@@ -188,13 +190,87 @@ export function assertEffortUnsupported(params: ChatCompletionParams): void {
188
190
  }
189
191
 
190
192
  /**
191
- * The reasoning blocks an assistant message carries, in wire form.
193
+ * Adapter-private state for one completed reasoning response.
192
194
  *
193
- * The vendor's rule: with tool calls in play, an assistant turn's
194
- * `reasoning_content` **must** be replayed in every later turn of the same
195
- * flow; without tool calls it is ignored if sent. Replayed unconditionally
196
- * here, which satisfies both halves and matches what `AssistantMessage.reasoning`
197
- * already promises — "replayed verbatim and ahead of the text/tool blocks".
195
+ * The route is repeated inside the opaque envelope rather than trusted from
196
+ * `AssistantMessage.source`: durable content is authoritative, and native
197
+ * metadata is used only after the two independent records agree.
198
+ */
199
+ interface DeepSeekReplayState {
200
+ readonly kind: 'namzu-deepseek-reasoning'
201
+ readonly version: 1
202
+ readonly route: ProviderRoute
203
+ readonly reasoningContent: string
204
+ }
205
+
206
+ function sameRoute(left: ProviderRoute, right: ProviderRoute): boolean {
207
+ return (
208
+ left.providerId === right.providerId &&
209
+ left.model === right.model &&
210
+ left.chainIndex === right.chainIndex
211
+ )
212
+ }
213
+
214
+ function resolveDeepSeekRoute(model: string, candidate: ProviderRoute | undefined): ProviderRoute {
215
+ if (candidate === undefined) return { providerId: 'deepseek', model, chainIndex: 0 }
216
+ if (
217
+ candidate.providerId !== 'deepseek' ||
218
+ candidate.model !== model ||
219
+ !Number.isSafeInteger(candidate.chainIndex) ||
220
+ candidate.chainIndex < 0
221
+ ) {
222
+ throw new Error(
223
+ 'DeepSeekProvider: providerRoute must name this provider, the requested model, and a non-negative integer chainIndex.',
224
+ )
225
+ }
226
+ return candidate
227
+ }
228
+
229
+ function isDeepSeekReplayState(value: unknown): value is DeepSeekReplayState {
230
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) return false
231
+ const state = value as Record<string, unknown>
232
+ const route = state.route
233
+ return (
234
+ state.kind === 'namzu-deepseek-reasoning' &&
235
+ state.version === 1 &&
236
+ typeof state.reasoningContent === 'string' &&
237
+ state.reasoningContent.length > 0 &&
238
+ typeof route === 'object' &&
239
+ route !== null &&
240
+ !Array.isArray(route) &&
241
+ typeof (route as Record<string, unknown>).providerId === 'string' &&
242
+ typeof (route as Record<string, unknown>).model === 'string' &&
243
+ Number.isSafeInteger((route as Record<string, unknown>).chainIndex) &&
244
+ ((route as Record<string, unknown>).chainIndex as number) >= 0
245
+ )
246
+ }
247
+
248
+ function durableDeepSeekReasoning(
249
+ reasoning: readonly ReasoningBlock[] | undefined,
250
+ ): string | undefined {
251
+ if (!reasoning || reasoning.length === 0) return undefined
252
+ if (
253
+ reasoning.some(
254
+ (block) =>
255
+ block.type !== 'thinking' ||
256
+ typeof block.text !== 'string' ||
257
+ block.signature !== undefined ||
258
+ block.encrypted !== undefined,
259
+ )
260
+ ) {
261
+ return undefined
262
+ }
263
+ const text = reasoning.map((block) => block.text as string).join('')
264
+ return text.length > 0 ? text : undefined
265
+ }
266
+
267
+ /**
268
+ * Restore `reasoning_content` only from a validated same-route envelope.
269
+ *
270
+ * The vendor's rule: with tool calls in play, an assistant turn's native
271
+ * reasoning must be echoed on later turns. Matching provider/model names are
272
+ * not enough: state can come from another chain member or another adapter
273
+ * format, and legacy messages carry no proof at all.
198
274
  *
199
275
  * Measured note, because it matters to anyone debugging this: as of
200
276
  * 2026-08-17 omitting the replay does NOT produce the documented 400 on either
@@ -202,17 +278,21 @@ export function assertEffortUnsupported(params: ChatCompletionParams): void {
202
278
  * a contract the vendor states and does not currently enforce is a contract
203
279
  * that can start being enforced in any release.
204
280
  */
205
- function replayReasoning(reasoning: readonly ReasoningBlock[] | undefined): string | undefined {
206
- if (!reasoning || reasoning.length === 0) return undefined
207
- const text = reasoning
208
- .filter((b) => b.type === 'thinking' && typeof b.text === 'string')
209
- .map((b) => b.text as string)
210
- .join('')
211
- return text.length > 0 ? text : undefined
281
+ function replayReasoning(
282
+ message: Extract<ChatCompletionParams['messages'][number], { role: 'assistant' }>,
283
+ targetRoute: ProviderRoute,
284
+ ): string | undefined {
285
+ const source = message.source
286
+ if (!source || source.type !== 'model' || !sameRoute(source, targetRoute)) return undefined
287
+ const state = source.replayState
288
+ if (!isDeepSeekReplayState(state) || !sameRoute(state.route, source)) return undefined
289
+ const durable = durableDeepSeekReasoning(message.reasoning)
290
+ return durable !== undefined && durable === state.reasoningContent ? durable : undefined
212
291
  }
213
292
 
214
293
  export function toDeepSeekMessages(
215
294
  messages: ChatCompletionParams['messages'],
295
+ targetRoute: ProviderRoute,
216
296
  ): ChatCompletionMessageParam[] {
217
297
  return messages.map((msg): ChatCompletionMessageParam => {
218
298
  if (msg.role === 'system') return { role: 'system', content: msg.content }
@@ -235,15 +315,21 @@ export function toDeepSeekMessages(
235
315
  tool_call_id: msg.toolCallId,
236
316
  }
237
317
  }
238
- const assistant: ChatCompletionMessageParam = { role: 'assistant', content: msg.content }
318
+ const assistant: ChatCompletionMessageParam = {
319
+ role: 'assistant',
320
+ content: msg.content,
321
+ }
239
322
  if ('toolCalls' in msg && msg.toolCalls && msg.toolCalls.length > 0) {
240
323
  ;(assistant as { tool_calls?: unknown }).tool_calls = msg.toolCalls.map((tc) => ({
241
324
  id: tc.id,
242
325
  type: 'function' as const,
243
- function: { name: tc.function.name, arguments: tc.function.arguments },
326
+ function: {
327
+ name: tc.function.name,
328
+ arguments: tc.function.arguments,
329
+ },
244
330
  }))
245
331
  }
246
- const replayed = replayReasoning((msg as { reasoning?: readonly ReasoningBlock[] }).reasoning)
332
+ const replayed = replayReasoning(msg, targetRoute)
247
333
  if (replayed !== undefined) {
248
334
  ;(assistant as { reasoning_content?: string }).reasoning_content = replayed
249
335
  }
@@ -286,7 +372,10 @@ export class DeepSeekProvider implements LLMProvider {
286
372
  baseURL: config.baseURL ?? DEFAULT_BASE_URL,
287
373
  }
288
374
  if (config.timeout !== undefined) clientOptions.timeout = config.timeout
289
- clientOptions.defaultHeaders = { ...attributionHeaders(), ...(config.defaultHeaders ?? {}) }
375
+ clientOptions.defaultHeaders = {
376
+ ...attributionHeaders(),
377
+ ...(config.defaultHeaders ?? {}),
378
+ }
290
379
 
291
380
  this.client = new OpenAI(clientOptions)
292
381
  this.defaultModel = config.model
@@ -303,8 +392,14 @@ export class DeepSeekProvider implements LLMProvider {
303
392
  return model
304
393
  }
305
394
 
395
+ /** This Chat Completions endpoint explicitly carries no effort control. */
396
+ reasoningEffortLevelsFor(_model: string): readonly ReasoningEffort[] {
397
+ return []
398
+ }
399
+
306
400
  async *chatStream(params: ChatCompletionParams): AsyncIterable<StreamChunk> {
307
401
  const model = this.resolveModel(params)
402
+ const providerRoute = resolveDeepSeekRoute(model, params.providerRoute)
308
403
  assertEffortUnsupported(params)
309
404
  assertSamplingUsable(params, this.samplingMode)
310
405
 
@@ -324,7 +419,7 @@ export class DeepSeekProvider implements LLMProvider {
324
419
  // to the non-streaming overload, whose result has no async iterator.
325
420
  const body = {
326
421
  model,
327
- messages: toDeepSeekMessages(params.messages),
422
+ messages: toDeepSeekMessages(params.messages, providerRoute),
328
423
  stream: true as const,
329
424
  stream_options: { include_usage: true },
330
425
  tools: toDeepSeekTools(params),
@@ -362,6 +457,8 @@ export class DeepSeekProvider implements LLMProvider {
362
457
  // `reasoning_content` as a flat run of deltas with no index and no
363
458
  // block boundaries, so index 0 is the whole of it rather than a guess.
364
459
  let reasoningOpen = false
460
+ let reasoningContent = ''
461
+ let replayStateEmitted = false
365
462
 
366
463
  try {
367
464
  for await (const chunk of stream) {
@@ -369,7 +466,11 @@ export class DeepSeekProvider implements LLMProvider {
369
466
  try {
370
467
  const choice = chunk.choices[0]
371
468
  const delta = choice?.delta as
372
- | { content?: string | null; reasoning_content?: string | null; tool_calls?: unknown[] }
469
+ | {
470
+ content?: string | null
471
+ reasoning_content?: string | null
472
+ tool_calls?: unknown[]
473
+ }
373
474
  | undefined
374
475
 
375
476
  const toolCalls = (
@@ -398,9 +499,12 @@ export class DeepSeekProvider implements LLMProvider {
398
499
 
399
500
  if (reasoningText) {
400
501
  reasoningOpen = true
502
+ reasoningContent += reasoningText
401
503
  yield {
402
504
  id: chunk.id,
403
- delta: { reasoning: { index: 0, type: 'thinking', text: reasoningText } },
505
+ delta: {
506
+ reasoning: { index: 0, type: 'thinking', text: reasoningText },
507
+ },
404
508
  }
405
509
  }
406
510
 
@@ -413,7 +517,10 @@ export class DeepSeekProvider implements LLMProvider {
413
517
  (toolCalls !== undefined && toolCalls.length > 0)
414
518
  if (reasoningOpen && contentStarting) {
415
519
  reasoningOpen = false
416
- yield { id: chunk.id, delta: { reasoning: { index: 0, done: true } } }
520
+ yield {
521
+ id: chunk.id,
522
+ delta: { reasoning: { index: 0, done: true } },
523
+ }
417
524
  }
418
525
 
419
526
  const hasDelta =
@@ -421,8 +528,20 @@ export class DeepSeekProvider implements LLMProvider {
421
528
  (toolCalls !== undefined && toolCalls.length > 0)
422
529
  if (!hasDelta && !finishReason && !usage) continue
423
530
 
531
+ const replayState =
532
+ !replayStateEmitted && finishReason && reasoningContent.length > 0
533
+ ? ({
534
+ kind: 'namzu-deepseek-reasoning',
535
+ version: 1,
536
+ route: providerRoute,
537
+ reasoningContent,
538
+ } satisfies DeepSeekReplayState)
539
+ : undefined
540
+ if (replayState !== undefined) replayStateEmitted = true
541
+
424
542
  yield {
425
543
  id: chunk.id,
544
+ ...(replayState !== undefined ? { replayState } : {}),
426
545
  delta: { content: delta?.content ?? undefined, toolCalls },
427
546
  finishReason,
428
547
  usage,
@@ -439,7 +558,10 @@ export class DeepSeekProvider implements LLMProvider {
439
558
  // A turn that was all reasoning and no content — the model thought
440
559
  // and then stopped — still has to close its block.
441
560
  if (reasoningOpen) {
442
- yield { id: 'deepseek-reasoning-close', delta: { reasoning: { index: 0, done: true } } }
561
+ yield {
562
+ id: 'deepseek-reasoning-close',
563
+ delta: { reasoning: { index: 0, done: true } },
564
+ }
443
565
  }
444
566
  } catch (err) {
445
567
  if (isCallerAbortError(err, params.signal)) throw params.signal?.reason ?? err
@@ -448,12 +570,16 @@ export class DeepSeekProvider implements LLMProvider {
448
570
  }
449
571
  }
450
572
 
451
- async probeCredential(): Promise<void> {
452
- await this.client.models.list()
573
+ async probeCredential(signal?: AbortSignal): Promise<void> {
574
+ signal?.throwIfAborted()
575
+ await this.client.models.list(signal ? { signal } : undefined)
576
+ signal?.throwIfAborted()
453
577
  }
454
578
 
455
- async listModels(): Promise<ModelInfo[]> {
456
- const page = await this.client.models.list()
579
+ async listModels(signal?: AbortSignal): Promise<ModelInfo[]> {
580
+ signal?.throwIfAborted()
581
+ const page = await this.client.models.list(signal ? { signal } : undefined)
582
+ signal?.throwIfAborted()
457
583
  return page.data.map((m) => ({
458
584
  id: m.id,
459
585
  name: m.id,