@deepstrike/sdk 0.2.31 → 0.2.33

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.
@@ -16,4 +16,16 @@ export declare class GeminiProvider implements LLMProvider {
16
16
  complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
17
17
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
18
18
  private modelExtensions;
19
+ /**
20
+ * Gemini vendor features from extensions, mapped to the Node SDK shape (mirrors the Python provider's
21
+ * extension keys for a consistent cross-SDK API):
22
+ * - `google_search` (truthy → default, object → config): Google Search grounding server tool
23
+ * (gemini-2.0+), appended to tools[].
24
+ * - `response_mime_type` / `response_schema`: structured output → `generationConfig` (the API rejects
25
+ * pairing this with google_search).
26
+ */
27
+ vendorConfig(extensions?: Record<string, unknown>): {
28
+ tools?: unknown[];
29
+ generationConfig?: Record<string, unknown>;
30
+ };
19
31
  }
@@ -116,11 +116,14 @@ export class GeminiProvider {
116
116
  let lastErr;
117
117
  for (let i = 0; i < this.maxRetries; i++) {
118
118
  try {
119
+ const vc = this.vendorConfig(extensions);
120
+ const allTools = [...geminiTools, ...(vc.tools ?? [])];
119
121
  const m = this.genAI.getGenerativeModel({
120
122
  ...this.modelExtensions(extensions),
121
123
  model: this.model,
122
124
  ...(system ? { systemInstruction: system } : {}),
123
- ...(geminiTools.length ? { tools: geminiTools } : {}),
125
+ ...(allTools.length ? { tools: allTools } : {}),
126
+ ...(vc.generationConfig ? { generationConfig: vc.generationConfig } : {}),
124
127
  }, this.requestOptions);
125
128
  const resp = await m.generateContent({ contents });
126
129
  this.circuit.recordSuccess();
@@ -157,11 +160,14 @@ export class GeminiProvider {
157
160
  const system = context.systemText || undefined;
158
161
  const contents = buildContents(turnsWithStateAppended(context));
159
162
  const geminiTools = buildTools(tools);
163
+ const vc = this.vendorConfig(extensions);
164
+ const allTools = [...geminiTools, ...(vc.tools ?? [])];
160
165
  const m = this.genAI.getGenerativeModel({
161
166
  ...this.modelExtensions(extensions),
162
167
  model: this.model,
163
168
  ...(system ? { systemInstruction: system } : {}),
164
- ...(geminiTools.length ? { tools: geminiTools } : {}),
169
+ ...(allTools.length ? { tools: allTools } : {}),
170
+ ...(vc.generationConfig ? { generationConfig: vc.generationConfig } : {}),
165
171
  }, this.requestOptions);
166
172
  const result = await m.generateContentStream({ contents });
167
173
  const toolCalls = [];
@@ -195,7 +201,36 @@ export class GeminiProvider {
195
201
  modelExtensions(extensions) {
196
202
  if (!extensions)
197
203
  return {};
198
- const { model: _model, systemInstruction: _systemInstruction, tools: _tools, ...rest } = extensions;
204
+ // Strip keys handled explicitly elsewhere (incl. the vendor server-tool / structured-output keys
205
+ // consumed by `vendorConfig`) so they never leak raw into getGenerativeModel.
206
+ // Strip keys handled explicitly: the SDK fields set below + the named vendor keys consumed by
207
+ // `vendorConfig`. A caller-provided raw `generationConfig` still passes through (and is merged with
208
+ // any structured-output config at the call site).
209
+ const { model: _model, systemInstruction: _systemInstruction, tools: _tools, google_search: _gs, response_mime_type: _rmt, response_schema: _rs, ...rest } = extensions;
199
210
  return rest;
200
211
  }
212
+ /**
213
+ * Gemini vendor features from extensions, mapped to the Node SDK shape (mirrors the Python provider's
214
+ * extension keys for a consistent cross-SDK API):
215
+ * - `google_search` (truthy → default, object → config): Google Search grounding server tool
216
+ * (gemini-2.0+), appended to tools[].
217
+ * - `response_mime_type` / `response_schema`: structured output → `generationConfig` (the API rejects
218
+ * pairing this with google_search).
219
+ */
220
+ vendorConfig(extensions) {
221
+ const ext = extensions ?? {};
222
+ const tools = [];
223
+ if (ext.google_search)
224
+ tools.push({ googleSearch: typeof ext.google_search === "object" ? ext.google_search : {} });
225
+ // Seed from any caller-provided raw generationConfig, then layer the named structured-output keys.
226
+ const gc = { ...ext.generationConfig };
227
+ if (ext.response_mime_type != null)
228
+ gc.responseMimeType = ext.response_mime_type;
229
+ if (ext.response_schema != null)
230
+ gc.responseSchema = ext.response_schema;
231
+ return {
232
+ ...(tools.length ? { tools } : {}),
233
+ ...(Object.keys(gc).length ? { generationConfig: gc } : {}),
234
+ };
235
+ }
201
236
  }
@@ -20,4 +20,6 @@ export declare class GLMProvider extends OpenAIChatProvider {
20
20
  }, baseURL?: string);
21
21
  runtimePolicy(): RuntimePolicy;
22
22
  descriptor(): ProviderDescriptor;
23
+ protected serverTools(extensions?: Record<string, unknown>): unknown[];
24
+ protected prepareExtensions(extensions?: Record<string, unknown>): Record<string, unknown> | undefined;
23
25
  }
@@ -14,7 +14,7 @@ export class GLMAnthropicProvider extends AnthropicCompatibleProvider {
14
14
  }
15
15
  }
16
16
  export class GLMProvider extends OpenAIChatProvider {
17
- constructor(apiKey, model = "glm-5.1", retry, baseURL = endpointProfiles["glm.openai"].baseURL) {
17
+ constructor(apiKey, model = "glm-5.2", retry, baseURL = endpointProfiles["glm.openai"].baseURL) {
18
18
  super(apiKey, model, retry, baseURL);
19
19
  }
20
20
  runtimePolicy() {
@@ -27,4 +27,22 @@ export class GLMProvider extends OpenAIChatProvider {
27
27
  model: this.model,
28
28
  };
29
29
  }
30
+ // ── GLM web_search (Zhipu vendor server tool; OpenAI-wire only) ──────────────
31
+ // Enable with `extensions={ web_search: true }` (default config) or `{ web_search: {...} }`
32
+ // (passthrough: search_engine, search_recency_filter, search_domain_filter, count, …). Injected as a
33
+ // `{ type: "web_search", web_search: {...} }` entry in tools[]; the model searches server-side and
34
+ // the results come back inline (no client tool-loop). Mirrors the Python GLM provider.
35
+ serverTools(extensions) {
36
+ const ws = extensions?.web_search;
37
+ if (!ws)
38
+ return [];
39
+ return [{ type: "web_search", web_search: typeof ws === "object" ? ws : {} }];
40
+ }
41
+ // Strip `web_search` from the passthrough so it shapes tools[] only, never leaks as a body field.
42
+ prepareExtensions(extensions) {
43
+ if (!extensions || !("web_search" in extensions))
44
+ return extensions;
45
+ const { web_search: _omit, ...rest } = extensions;
46
+ return rest;
47
+ }
30
48
  }
@@ -25,7 +25,7 @@ export class MiniMaxAnthropicProvider extends AnthropicCompatibleProvider {
25
25
  * tool-call machinery is inherited from the base class.
26
26
  */
27
27
  export class MiniMaxOpenAIProvider extends OpenAIChatProvider {
28
- constructor(apiKey, model = "MiniMax-M2.7", retry, baseURL = endpointProfiles["minimax.openai"].baseURL) {
28
+ constructor(apiKey, model = "MiniMax-M3", retry, baseURL = endpointProfiles["minimax.openai"].baseURL) {
29
29
  super(apiKey, model, retry, baseURL);
30
30
  }
31
31
  runtimePolicy() {
@@ -40,5 +40,11 @@ export declare class OpenAIResponsesProvider implements LLMProvider {
40
40
  complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
41
41
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): AsyncIterable<StreamEvent>;
42
42
  private requestExtensions;
43
+ /** Responses API built-in server tools from extensions (live in the same tools[] as function tools):
44
+ * `web_search: true` (or a config object), plus a `builtin_tools` list passed through verbatim for
45
+ * file_search / code_interpreter. They run server-side; results return inline. Mirrors py. */
46
+ private builtinTools;
47
+ /** Function tools + built-in server tools merged into the wire tools[] (undefined when empty). */
48
+ private allTools;
43
49
  private asRunState;
44
50
  }
@@ -176,7 +176,7 @@ export class OpenAIResponsesProvider {
176
176
  model: this.model,
177
177
  input: this.responses.buildInput(context),
178
178
  ...(instructions ? { instructions } : {}),
179
- ...(tools.length ? { tools: this.responses.buildTools(tools) } : {}),
179
+ ...((t => t ? { tools: t } : {})(this.allTools(tools, extensions))),
180
180
  });
181
181
  this.circuit.recordSuccess();
182
182
  const decoded = this.responses.decodeOutput(resp.output);
@@ -206,7 +206,7 @@ export class OpenAIResponsesProvider {
206
206
  input: this.responses.buildInput(context, runState),
207
207
  ...(instructions ? { instructions } : {}),
208
208
  ...(runState.previousResponseId ? { previous_response_id: runState.previousResponseId } : {}),
209
- ...(tools.length ? { tools: this.responses.buildTools(tools) } : {}),
209
+ ...((t => t ? { tools: t } : {})(this.allTools(tools, extensions))),
210
210
  stream: true,
211
211
  });
212
212
  for await (const evt of stream) {
@@ -266,8 +266,28 @@ export class OpenAIResponsesProvider {
266
266
  requestExtensions(extensions) {
267
267
  return omitExtensionKeys(extensions, [
268
268
  "model", "input", "instructions", "tools", "stream", "previous_response_id",
269
+ "web_search", "builtin_tools",
269
270
  ]);
270
271
  }
272
+ /** Responses API built-in server tools from extensions (live in the same tools[] as function tools):
273
+ * `web_search: true` (or a config object), plus a `builtin_tools` list passed through verbatim for
274
+ * file_search / code_interpreter. They run server-side; results return inline. Mirrors py. */
275
+ builtinTools(extensions) {
276
+ const ext = extensions ?? {};
277
+ const out = [];
278
+ const ws = ext.web_search;
279
+ if (ws)
280
+ out.push(typeof ws === "object" ? { type: "web_search", ...ws } : { type: "web_search" });
281
+ if (Array.isArray(ext.builtin_tools))
282
+ out.push(...ext.builtin_tools);
283
+ return out;
284
+ }
285
+ /** Function tools + built-in server tools merged into the wire tools[] (undefined when empty). */
286
+ allTools(tools, extensions) {
287
+ const fnTools = tools.length ? this.responses.buildTools(tools) : [];
288
+ const all = [...fnTools, ...this.builtinTools(extensions)];
289
+ return all.length ? all : undefined;
290
+ }
271
291
  asRunState(state) {
272
292
  if (!state)
273
293
  return this.createRunState();
@@ -51,6 +51,15 @@ export declare class OpenAIChatProvider implements LLMProvider {
51
51
  /** Extra top-level request-body fields merged into the chat.completions call (vendor thinking
52
52
  * knobs like `reasoning_effort`, `extra_body`, `reasoning_split`). Default: none. */
53
53
  protected requestBodyExtras(_extensions?: Record<string, unknown>): Record<string, unknown>;
54
+ /** Vendor server tools (e.g. web search) injected into the `tools[]` array alongside the function
55
+ * tools, driven by caller `extensions`. These run server-side — the model invokes them and the
56
+ * results come back inline, with no client tool-loop round-trip. Default: none. Vendors that ship
57
+ * built-in tools (GLM web_search, …) override this and strip the consumed key in `prepareExtensions`
58
+ * so it does not also leak into the request body. */
59
+ protected serverTools(_extensions?: Record<string, unknown>): unknown[];
60
+ /** Merge function tools + vendor server tools into the wire `tools[]` (undefined when empty). Server
61
+ * tools (e.g. web_search) are non-standard wire entries, so the array is cast to the SDK tool type. */
62
+ protected assembleTools(tools: ToolSchema[], extensions?: Record<string, unknown>): OpenAI.Chat.Completions.ChatCompletionTool[] | undefined;
54
63
  /** Request-body params controlling prompt caching. Default sends OpenAI's `prompt_cache_key`;
55
64
  * vendors whose endpoints reject unknown params (e.g. DeepSeek 400s) override to `{}`. */
56
65
  protected cacheKeyParams(context: RenderedContext, tools: ToolSchema[]): Record<string, unknown>;
@@ -97,6 +97,21 @@ export class OpenAIChatProvider {
97
97
  requestBodyExtras(_extensions) {
98
98
  return {};
99
99
  }
100
+ /** Vendor server tools (e.g. web search) injected into the `tools[]` array alongside the function
101
+ * tools, driven by caller `extensions`. These run server-side — the model invokes them and the
102
+ * results come back inline, with no client tool-loop round-trip. Default: none. Vendors that ship
103
+ * built-in tools (GLM web_search, …) override this and strip the consumed key in `prepareExtensions`
104
+ * so it does not also leak into the request body. */
105
+ serverTools(_extensions) {
106
+ return [];
107
+ }
108
+ /** Merge function tools + vendor server tools into the wire `tools[]` (undefined when empty). Server
109
+ * tools (e.g. web_search) are non-standard wire entries, so the array is cast to the SDK tool type. */
110
+ assembleTools(tools, extensions) {
111
+ const fnTools = tools.length ? this.chat.buildTools(tools) : [];
112
+ const all = [...fnTools, ...this.serverTools(extensions)];
113
+ return all.length ? all : undefined;
114
+ }
100
115
  /** Request-body params controlling prompt caching. Default sends OpenAI's `prompt_cache_key`;
101
116
  * vendors whose endpoints reject unknown params (e.g. DeepSeek 400s) override to `{}`. */
102
117
  cacheKeyParams(context, tools) {
@@ -162,7 +177,7 @@ export class OpenAIChatProvider {
162
177
  ...this.requestBodyExtras(extensions),
163
178
  model: this.model,
164
179
  messages: msgs,
165
- ...(tools.length ? { tools: this.chat.buildTools(tools) } : {}),
180
+ ...((t => t ? { tools: t } : {})(this.assembleTools(tools, extensions))),
166
181
  });
167
182
  this.circuit.recordSuccess();
168
183
  const choice = resp.choices[0].message;
@@ -202,7 +217,7 @@ export class OpenAIChatProvider {
202
217
  ...this.requestBodyExtras(extensions),
203
218
  model: this.model,
204
219
  messages: msgs,
205
- ...(tools.length ? { tools: this.chat.buildTools(tools) } : {}),
220
+ ...((t => t ? { tools: t } : {})(this.assembleTools(tools, extensions))),
206
221
  stream: true,
207
222
  stream_options: { include_usage: true },
208
223
  // #2-B-ii: forward the abort signal so a preempt cancels the in-flight HTTP request.
@@ -81,7 +81,7 @@ export declare const endpointProfiles: {
81
81
  readonly id: "kimi.anthropic";
82
82
  readonly providerId: "kimi";
83
83
  readonly protocol: "anthropic-messages";
84
- readonly baseURL: "https://api.moonshot.ai/anthropic";
84
+ readonly baseURL: "https://api.moonshot.cn/anthropic";
85
85
  };
86
86
  readonly "kimi.openai": {
87
87
  readonly id: "kimi.openai";
@@ -129,7 +129,7 @@ export declare const endpointProfiles: {
129
129
  readonly id: "glm.anthropic";
130
130
  readonly providerId: "glm";
131
131
  readonly protocol: "anthropic-messages";
132
- readonly baseURL: "https://api.z.ai/api/anthropic";
132
+ readonly baseURL: "https://open.bigmodel.cn/api/anthropic";
133
133
  };
134
134
  readonly "glm.openai": {
135
135
  readonly id: "glm.openai";
@@ -729,6 +729,46 @@ export declare const modelProfiles: {
729
729
  readonly preserveAcrossToolTurns: false;
730
730
  };
731
731
  };
732
+ readonly "minimax/MiniMax-M3": {
733
+ readonly id: "minimax/MiniMax-M3";
734
+ readonly providerId: "minimax";
735
+ readonly defaultEndpointId: "minimax.anthropic";
736
+ readonly contextWindow: 204800;
737
+ readonly modalities: {
738
+ readonly input: ["text", "image"];
739
+ readonly output: ["text"];
740
+ };
741
+ readonly tools: {
742
+ readonly supported: true;
743
+ };
744
+ readonly reasoning: {
745
+ readonly supported: true;
746
+ readonly preserveAcrossToolTurns: true;
747
+ };
748
+ readonly policy: {
749
+ readonly maxTurns: 35;
750
+ };
751
+ };
752
+ readonly "minimax/MiniMax-M3-highspeed": {
753
+ readonly id: "minimax/MiniMax-M3-highspeed";
754
+ readonly providerId: "minimax";
755
+ readonly defaultEndpointId: "minimax.anthropic";
756
+ readonly contextWindow: 204800;
757
+ readonly modalities: {
758
+ readonly input: ["text", "image"];
759
+ readonly output: ["text"];
760
+ };
761
+ readonly tools: {
762
+ readonly supported: true;
763
+ };
764
+ readonly reasoning: {
765
+ readonly supported: true;
766
+ readonly preserveAcrossToolTurns: true;
767
+ };
768
+ readonly policy: {
769
+ readonly maxTurns: 35;
770
+ };
771
+ };
732
772
  readonly "minimax/MiniMax-M2.7": {
733
773
  readonly id: "minimax/MiniMax-M2.7";
734
774
  readonly providerId: "minimax";
@@ -1650,6 +1690,26 @@ export declare const modelProfiles: {
1650
1690
  readonly preserveAcrossToolTurns: false;
1651
1691
  };
1652
1692
  };
1693
+ readonly "glm/glm-5.2": {
1694
+ readonly id: "glm/glm-5.2";
1695
+ readonly providerId: "glm";
1696
+ readonly defaultEndpointId: "glm.anthropic";
1697
+ readonly contextWindow: 200000;
1698
+ readonly modalities: {
1699
+ readonly input: ["text"];
1700
+ readonly output: ["text"];
1701
+ };
1702
+ readonly tools: {
1703
+ readonly supported: true;
1704
+ };
1705
+ readonly reasoning: {
1706
+ readonly supported: true;
1707
+ readonly preserveAcrossToolTurns: true;
1708
+ };
1709
+ readonly policy: {
1710
+ readonly maxTurns: 50;
1711
+ };
1712
+ };
1653
1713
  readonly "glm/glm-5.1": {
1654
1714
  readonly id: "glm/glm-5.1";
1655
1715
  readonly providerId: "glm";
@@ -47,11 +47,17 @@ export const endpointProfiles = {
47
47
  protocol: "openai-chat",
48
48
  baseURL: "https://api.deepseek.com",
49
49
  },
50
+ // CN vendors (Kimi/GLM) are region-split: mainland (.cn hosts) and international (.ai/z.ai) are
51
+ // SEPARATE accounts with SEPARATE keys — a mainland key 401s on the international host & vice-versa.
52
+ // There is no `region` concept in this SDK: baseURL IS the host axis. These ids carry the DEFAULT =
53
+ // mainland (cn); international users pass their own `baseURL` (with their international key). Keeping
54
+ // both wires on the same region (cn) also fixes the prior split where openai=cn but anthropic=intl,
55
+ // which 401'd a mainland key on the default anthropic wire.
50
56
  "kimi.anthropic": {
51
57
  id: "kimi.anthropic",
52
58
  providerId: "kimi",
53
59
  protocol: "anthropic-messages",
54
- baseURL: "https://api.moonshot.ai/anthropic",
60
+ baseURL: "https://api.moonshot.cn/anthropic",
55
61
  },
56
62
  "kimi.openai": {
57
63
  id: "kimi.openai",
@@ -99,7 +105,9 @@ export const endpointProfiles = {
99
105
  id: "glm.anthropic",
100
106
  providerId: "glm",
101
107
  protocol: "anthropic-messages",
102
- baseURL: "https://api.z.ai/api/anthropic",
108
+ // Default = mainland (consistent with the already-mainland glm.openai). International: pass baseURL
109
+ // "https://api.z.ai/api/anthropic" with an international (z.ai) key.
110
+ baseURL: "https://open.bigmodel.cn/api/anthropic",
103
111
  },
104
112
  "glm.openai": {
105
113
  id: "glm.openai",
@@ -341,6 +349,21 @@ export const modelProfiles = {
341
349
  tools: { supported: false }, reasoning: { supported: false, preserveAcrossToolTurns: false },
342
350
  },
343
351
  // ── MiniMax ────────────────────────────────────────────────────────────────
352
+ "minimax/MiniMax-M3": {
353
+ id: "minimax/MiniMax-M3", providerId: "minimax", defaultEndpointId: "minimax.anthropic",
354
+ contextWindow: 204_800,
355
+ // Natively multimodal — image input verified live via the Anthropic image-block path.
356
+ modalities: { input: ["text", "image"], output: ["text"] },
357
+ tools: { supported: true }, reasoning: { supported: true, preserveAcrossToolTurns: true },
358
+ policy: { maxTurns: 35 },
359
+ },
360
+ "minimax/MiniMax-M3-highspeed": {
361
+ id: "minimax/MiniMax-M3-highspeed", providerId: "minimax", defaultEndpointId: "minimax.anthropic",
362
+ contextWindow: 204_800,
363
+ modalities: { input: ["text", "image"], output: ["text"] },
364
+ tools: { supported: true }, reasoning: { supported: true, preserveAcrossToolTurns: true },
365
+ policy: { maxTurns: 35 },
366
+ },
344
367
  "minimax/MiniMax-M2.7": {
345
368
  id: "minimax/MiniMax-M2.7", providerId: "minimax", defaultEndpointId: "minimax.anthropic",
346
369
  contextWindow: 204_800,
@@ -668,6 +691,13 @@ export const modelProfiles = {
668
691
  tools: { supported: false }, reasoning: { supported: false, preserveAcrossToolTurns: false },
669
692
  },
670
693
  // ── GLM ────────────────────────────────────────────────────────────────────
694
+ "glm/glm-5.2": {
695
+ id: "glm/glm-5.2", providerId: "glm", defaultEndpointId: "glm.anthropic",
696
+ contextWindow: 200_000,
697
+ modalities: { input: ["text"], output: ["text"] },
698
+ tools: { supported: true }, reasoning: { supported: true, preserveAcrossToolTurns: true },
699
+ policy: { maxTurns: 50 },
700
+ },
671
701
  "glm/glm-5.1": {
672
702
  id: "glm/glm-5.1", providerId: "glm", defaultEndpointId: "glm.anthropic",
673
703
  contextWindow: 200_000,
@@ -31,6 +31,7 @@ export declare class QwenProvider extends OpenAIChatProvider {
31
31
  protected usesInlineThinkingTags(): boolean;
32
32
  protected requestBodyExtras(extensions?: Record<string, unknown>): Record<string, unknown>;
33
33
  protected requestExtensions(extensions?: Record<string, unknown>): Record<string, unknown>;
34
+ private searchExtraBody;
34
35
  peekProviderReplay(message: Pick<Message, "content" | "toolCalls">): ProviderReplay | undefined;
35
36
  seedProviderReplay(message: Pick<Message, "content" | "toolCalls">, replay: ProviderReplay): void;
36
37
  private thinkingExtraBody;
@@ -52,15 +52,27 @@ export class QwenProvider extends OpenAIChatProvider {
52
52
  return false;
53
53
  }
54
54
  requestBodyExtras(extensions) {
55
- const extraBody = this.thinkingExtraBody(extensions);
56
- return extraBody ? { extra_body: extraBody } : {};
55
+ // DashScope vendor knobs travel under `extra_body` in OpenAI-compat mode: thinking + web search.
56
+ const extraBody = { ...this.thinkingExtraBody(extensions), ...this.searchExtraBody(extensions) };
57
+ return Object.keys(extraBody).length ? { extra_body: extraBody } : {};
57
58
  }
58
59
  requestExtensions(extensions) {
59
60
  return omitExtensionKeys(extensions, [
60
61
  "model", "messages", "tools", "stream", "stream_options", "extra_body",
61
62
  "enableThinking", "enable_thinking", "thinkingBudget", "thinking_budget",
63
+ "enable_search", "search_options",
62
64
  ]);
63
65
  }
66
+ // DashScope web search (Qwen vendor feature): `extensions={ enable_search: true }` + optional
67
+ // `search_options` (forced_search / search_strategy / enable_citation …). Mirrors the Python provider.
68
+ searchExtraBody(extensions) {
69
+ if (!extensions?.enable_search)
70
+ return {};
71
+ return {
72
+ enable_search: true,
73
+ ...(extensions.search_options != null ? { search_options: extensions.search_options } : {}),
74
+ };
75
+ }
64
76
  peekProviderReplay(message) {
65
77
  const fields = this.chat.peekReplayFields(message);
66
78
  if (!fields || !("reasoning_content" in fields))
@@ -30,6 +30,8 @@ export const QWEN_POLICIES = {
30
30
  "qwen3.5-27b": { maxTurns: 20 },
31
31
  };
32
32
  export const GLM_POLICIES = {
33
+ "glm-5.2": { maxTurns: 50 },
34
+ "glm/glm-5.2": { maxTurns: 50 },
33
35
  "glm-5.1": { maxTurns: 50 },
34
36
  "glm/glm-5.1": { maxTurns: 50 },
35
37
  "glm-4-plus": { maxTurns: 35 },
@@ -40,6 +42,8 @@ export const GLM_POLICIES = {
40
42
  "glm/glm-4-air": { maxTurns: 20 },
41
43
  };
42
44
  export const MINIMAX_POLICIES = {
45
+ "MiniMax-M3": { maxTurns: 35 },
46
+ "MiniMax-M3-highspeed": { maxTurns: 35 },
43
47
  "MiniMax-M2.7": { maxTurns: 35 },
44
48
  "MiniMax-M2.7-highspeed": { maxTurns: 35 },
45
49
  "MiniMax-M2.5": { maxTurns: 25 },
@@ -53,8 +57,8 @@ export const anthropicVendorProfiles = {
53
57
  deepseek: { providerId: "deepseek", defaultModel: "deepseek-v4-flash", baseURLProfileKey: "deepseek.anthropic", policies: DEEPSEEK_POLICIES },
54
58
  kimi: { providerId: "kimi", defaultModel: "kimi-k2.6", baseURLProfileKey: "kimi.anthropic", policies: KIMI_POLICIES },
55
59
  qwen: { providerId: "qwen", defaultModel: "qwen3.6-plus", baseURLProfileKey: "qwen.anthropic", policies: QWEN_POLICIES },
56
- glm: { providerId: "glm", defaultModel: "glm-5.1", baseURLProfileKey: "glm.anthropic", policies: GLM_POLICIES },
57
- minimax: { providerId: "minimax", defaultModel: "MiniMax-M2.7", baseURLProfileKey: "minimax.anthropic", policies: MINIMAX_POLICIES },
60
+ glm: { providerId: "glm", defaultModel: "glm-5.2", baseURLProfileKey: "glm.anthropic", policies: GLM_POLICIES },
61
+ minimax: { providerId: "minimax", defaultModel: "MiniMax-M3", baseURLProfileKey: "minimax.anthropic", policies: MINIMAX_POLICIES },
58
62
  };
59
63
  /** Resolve the Anthropic-compatible base URL for a vendor profile. */
60
64
  export function anthropicVendorBaseURL(profile) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.31",
3
+ "version": "0.2.33",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@anthropic-ai/sdk": "^0.99.0",
75
- "@deepstrike/core": "0.2.31",
75
+ "@deepstrike/core": "0.2.33",
76
76
  "@google/generative-ai": "^0.24.1",
77
77
  "openai": "^5.23.2"
78
78
  },