@juspay/neurolink 9.68.12 → 9.68.13
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 +2 -0
- package/dist/browser/neurolink.min.js +408 -422
- package/dist/lib/providers/deepseek.d.ts +39 -21
- package/dist/lib/providers/deepseek.js +68 -217
- package/dist/providers/deepseek.d.ts +39 -21
- package/dist/providers/deepseek.js +68 -217
- package/package.json +1 -1
|
@@ -1,29 +1,47 @@
|
|
|
1
1
|
import type { AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import type { LanguageModel } from "../types/index.js";
|
|
2
|
+
import type { NeurolinkCredentials, OpenAICompatResponseFormat } from "../types/index.js";
|
|
3
|
+
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
5
4
|
/**
|
|
6
|
-
* DeepSeek Provider
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* DeepSeek Provider — direct HTTP, no AI SDK.
|
|
6
|
+
*
|
|
7
|
+
* OpenAI-compatible chat completions at api.deepseek.com (deepseek-chat /
|
|
8
|
+
* deepseek-reasoner). All request/stream/tool-loop orchestration lives in
|
|
9
|
+
* `OpenAIChatCompletionsProvider`; this class declares configuration and
|
|
10
|
+
* provider-specific quirks:
|
|
11
|
+
*
|
|
12
|
+
* 1. Structured-output downgrade — DeepSeek rejects `response_format:
|
|
13
|
+
* { type: "json_schema" }` ("This response_format type is unavailable
|
|
14
|
+
* now"), so `adjustResponseFormat` downgrades it to `json_object` —
|
|
15
|
+
* matching the `supportsStructuredOutputs: false` behaviour of the
|
|
16
|
+
* `@ai-sdk/openai-compatible` path this migration replaced. The base
|
|
17
|
+
* client injects the literal "json" word the API requires for that mode.
|
|
18
|
+
*
|
|
19
|
+
* 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
|
|
20
|
+
* chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
|
|
21
|
+
* both require plumbing the thinking signal and the reasoning delta
|
|
22
|
+
* through the native base client. That plumbing isn't in place yet, so
|
|
23
|
+
* neither is wired here; it is tracked as a base-client follow-up. All
|
|
24
|
+
* other behavior is preserved.
|
|
25
|
+
*
|
|
26
|
+
* @see https://api-docs.deepseek.com
|
|
9
27
|
*/
|
|
10
|
-
export declare class DeepSeekProvider extends
|
|
11
|
-
private model;
|
|
12
|
-
private apiKey;
|
|
13
|
-
private baseURL;
|
|
28
|
+
export declare class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
14
29
|
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["deepseek"]);
|
|
15
|
-
protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
16
|
-
private executeStreamInner;
|
|
17
30
|
protected getProviderName(): AIProviderName;
|
|
18
31
|
protected getDefaultModel(): string;
|
|
19
|
-
protected getAISDKModel(): LanguageModel;
|
|
20
32
|
protected formatProviderError(error: unknown): Error;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
33
|
+
protected getFallbackModelName(): string;
|
|
34
|
+
protected getFallbackModels(): string[];
|
|
35
|
+
/**
|
|
36
|
+
* DeepSeek's /chat/completions rejects `response_format: { type:
|
|
37
|
+
* "json_schema" }` outright ("This response_format type is unavailable
|
|
38
|
+
* now"). The `@ai-sdk/openai-compatible` provider this migration replaced
|
|
39
|
+
* ran with `supportsStructuredOutputs: false`, which downgraded structured-
|
|
40
|
+
* output requests to `{ type: "json_object" }`. Replicate that downgrade so
|
|
41
|
+
* `generate({ schema })` keeps working. (DeepSeek's json_object mode also
|
|
42
|
+
* requires the word "json" somewhere in the messages; the base client's
|
|
43
|
+
* `ensureJsonWordInBody` injects a minimal instruction when the prompt
|
|
44
|
+
* lacks it.)
|
|
45
|
+
*/
|
|
46
|
+
protected adjustResponseFormat(rf: OpenAICompatResponseFormat | undefined, _modelId: string): OpenAICompatResponseFormat | undefined;
|
|
28
47
|
}
|
|
29
|
-
export default DeepSeekProvider;
|
|
@@ -1,50 +1,10 @@
|
|
|
1
|
-
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
2
1
|
import { DeepSeekModels } from "../constants/enums.js";
|
|
3
|
-
import { BaseProvider } from "../core/baseProvider.js";
|
|
4
|
-
import { DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
5
|
-
import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
|
|
6
|
-
import { isNeuroLink } from "../neurolink.js";
|
|
7
|
-
import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
|
|
8
|
-
import { tracers, ATTR, withClientStreamSpan } from "../telemetry/index.js";
|
|
9
2
|
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../types/index.js";
|
|
10
3
|
import { logger } from "../utils/logger.js";
|
|
11
4
|
import { createDeepSeekConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
|
|
16
|
-
import { stepCountIs } from "../utils/tool.js";
|
|
17
|
-
import { streamText } from "../utils/generation.js";
|
|
18
|
-
const makeLoggingFetch = (provider) => {
|
|
19
|
-
const base = createProxyFetch();
|
|
20
|
-
return (async (input, init) => {
|
|
21
|
-
const url = typeof input === "string"
|
|
22
|
-
? input
|
|
23
|
-
: input instanceof URL
|
|
24
|
-
? input.toString()
|
|
25
|
-
: input.url;
|
|
26
|
-
const reqSize = init?.body && typeof init.body === "string" ? init.body.length : 0;
|
|
27
|
-
const response = await base(input, init);
|
|
28
|
-
if (!response.ok) {
|
|
29
|
-
// Don't fall back to the raw URL — that would defeat the redaction.
|
|
30
|
-
const safeUrl = maskProxyUrl(url) ?? "<redacted>";
|
|
31
|
-
if (process.env.NEUROLINK_DEBUG_HTTP === "1") {
|
|
32
|
-
const clone = response.clone();
|
|
33
|
-
const body = await clone.text().catch(() => "<unreadable>");
|
|
34
|
-
logger.warn(`[${provider}] upstream ${response.status}`, {
|
|
35
|
-
url: safeUrl,
|
|
36
|
-
body: body.slice(0, 800),
|
|
37
|
-
reqSize,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
logger.warn(`[${provider}] upstream ${response.status} url=${safeUrl} reqSize=${reqSize}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return response;
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
const DEEPSEEK_DEFAULT_BASE_URL = "https://api.deepseek.com";
|
|
5
|
+
import { TimeoutError } from "../utils/timeout.js";
|
|
6
|
+
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
7
|
+
const DEEPSEEK_BASE_URL = "https://api.deepseek.com";
|
|
48
8
|
const getDeepSeekApiKey = () => {
|
|
49
9
|
return validateApiKey(createDeepSeekConfig());
|
|
50
10
|
};
|
|
@@ -52,184 +12,61 @@ const getDefaultDeepSeekModel = () => {
|
|
|
52
12
|
return getProviderModel("DEEPSEEK_MODEL", DeepSeekModels.DEEPSEEK_CHAT);
|
|
53
13
|
};
|
|
54
14
|
/**
|
|
55
|
-
* DeepSeek Provider
|
|
56
|
-
*
|
|
57
|
-
*
|
|
15
|
+
* DeepSeek Provider — direct HTTP, no AI SDK.
|
|
16
|
+
*
|
|
17
|
+
* OpenAI-compatible chat completions at api.deepseek.com (deepseek-chat /
|
|
18
|
+
* deepseek-reasoner). All request/stream/tool-loop orchestration lives in
|
|
19
|
+
* `OpenAIChatCompletionsProvider`; this class declares configuration and
|
|
20
|
+
* provider-specific quirks:
|
|
21
|
+
*
|
|
22
|
+
* 1. Structured-output downgrade — DeepSeek rejects `response_format:
|
|
23
|
+
* { type: "json_schema" }` ("This response_format type is unavailable
|
|
24
|
+
* now"), so `adjustResponseFormat` downgrades it to `json_object` —
|
|
25
|
+
* matching the `supportsStructuredOutputs: false` behaviour of the
|
|
26
|
+
* `@ai-sdk/openai-compatible` path this migration replaced. The base
|
|
27
|
+
* client injects the literal "json" word the API requires for that mode.
|
|
28
|
+
*
|
|
29
|
+
* 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
|
|
30
|
+
* chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
|
|
31
|
+
* both require plumbing the thinking signal and the reasoning delta
|
|
32
|
+
* through the native base client. That plumbing isn't in place yet, so
|
|
33
|
+
* neither is wired here; it is tracked as a base-client follow-up. All
|
|
34
|
+
* other behavior is preserved.
|
|
35
|
+
*
|
|
36
|
+
* @see https://api-docs.deepseek.com
|
|
58
37
|
*/
|
|
59
|
-
export class DeepSeekProvider extends
|
|
60
|
-
model;
|
|
61
|
-
apiKey;
|
|
62
|
-
baseURL;
|
|
38
|
+
export class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
63
39
|
constructor(modelName, sdk, _region, credentials) {
|
|
64
|
-
const validatedNeurolink = isNeuroLink(sdk) ? sdk : undefined;
|
|
65
|
-
super(modelName, "deepseek", validatedNeurolink);
|
|
66
40
|
// Trim the override before applying precedence. A blank/whitespace
|
|
67
|
-
// `credentials.apiKey`
|
|
68
|
-
// would build a client with an unusable bearer token and fail at
|
|
69
|
-
// time with a confusing 401 instead of at construction time.
|
|
41
|
+
// `credentials.apiKey` must NOT bypass `getDeepSeekApiKey()` — that
|
|
42
|
+
// would build a client with an unusable bearer token and fail at
|
|
43
|
+
// request time with a confusing 401 instead of at construction time.
|
|
70
44
|
const overrideApiKey = credentials?.apiKey?.trim();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// 1. It always sends `response_format: { type: "json_schema" }` when a
|
|
82
|
-
// schema is provided. DeepSeek's API rejects that with the literal
|
|
83
|
-
// message "This response_format type is unavailable now".
|
|
84
|
-
// 2. It does not parse the `reasoning_content` field that
|
|
85
|
-
// `deepseek-reasoner` emits, so chain-of-thought is silently dropped.
|
|
86
|
-
// `@ai-sdk/openai-compatible` honors `supportsStructuredOutputs: false`
|
|
87
|
-
// (falls back to `{ type: "json_object" }` and injects the schema into
|
|
88
|
-
// the prompt) and parses both `choice.message.reasoning_content` and
|
|
89
|
-
// `delta.reasoning_content` into the SDK-standard `reasoning` part.
|
|
90
|
-
const deepseek = createOpenAICompatible({
|
|
91
|
-
name: "deepseek",
|
|
92
|
-
apiKey: this.apiKey,
|
|
93
|
-
baseURL: this.baseURL,
|
|
94
|
-
fetch: makeLoggingFetch("deepseek"),
|
|
95
|
-
supportsStructuredOutputs: false,
|
|
96
|
-
includeUsage: true,
|
|
97
|
-
// DeepSeek's `response_format: { type: "json_object" }` requires the
|
|
98
|
-
// prompt to literally contain the word "json" — otherwise the API
|
|
99
|
-
// rejects with: "Prompt must contain the word 'json' in some form to
|
|
100
|
-
// use 'response_format' of type 'json_object'." The OpenAI-compatible
|
|
101
|
-
// SDK fallback path (used because supportsStructuredOutputs is false)
|
|
102
|
-
// does not inject this guidance itself, so we prepend a system
|
|
103
|
-
// message when it's missing. No-op for non-JSON requests.
|
|
104
|
-
transformRequestBody: (body) => {
|
|
105
|
-
const rf = body
|
|
106
|
-
.response_format;
|
|
107
|
-
if (rf?.type !== "json_object") {
|
|
108
|
-
return body;
|
|
109
|
-
}
|
|
110
|
-
const messages = body
|
|
111
|
-
.messages;
|
|
112
|
-
if (!Array.isArray(messages)) {
|
|
113
|
-
return body;
|
|
114
|
-
}
|
|
115
|
-
const containsJsonWord = messages.some((m) => {
|
|
116
|
-
const c = m?.content;
|
|
117
|
-
if (typeof c === "string") {
|
|
118
|
-
return /\bjson\b/i.test(c);
|
|
119
|
-
}
|
|
120
|
-
if (Array.isArray(c)) {
|
|
121
|
-
return c.some((part) => typeof part?.text === "string" &&
|
|
122
|
-
/\bjson\b/i.test(part.text));
|
|
123
|
-
}
|
|
124
|
-
return false;
|
|
125
|
-
});
|
|
126
|
-
if (containsJsonWord) {
|
|
127
|
-
return body;
|
|
128
|
-
}
|
|
129
|
-
return {
|
|
130
|
-
...body,
|
|
131
|
-
messages: [
|
|
132
|
-
{
|
|
133
|
-
role: "system",
|
|
134
|
-
content: "Respond with valid JSON that satisfies the requested schema. Output JSON only — no prose, no markdown fencing.",
|
|
135
|
-
},
|
|
136
|
-
...messages,
|
|
137
|
-
],
|
|
138
|
-
};
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
this.model = deepseek.chatModel(this.modelName);
|
|
45
|
+
const apiKey = overrideApiKey && overrideApiKey.length > 0
|
|
46
|
+
? overrideApiKey
|
|
47
|
+
: getDeepSeekApiKey();
|
|
48
|
+
// Treat blank/whitespace overrides as unset so an empty
|
|
49
|
+
// `credentials.baseURL` or `DEEPSEEK_BASE_URL=` cannot silently override
|
|
50
|
+
// the default with "" (mirrors the apiKey precedence above).
|
|
51
|
+
const baseURL = credentials?.baseURL?.trim() ||
|
|
52
|
+
process.env.DEEPSEEK_BASE_URL?.trim() ||
|
|
53
|
+
DEEPSEEK_BASE_URL;
|
|
54
|
+
super("deepseek", modelName, sdk, { baseURL, apiKey });
|
|
142
55
|
logger.debug("DeepSeek Provider initialized", {
|
|
143
56
|
modelName: this.modelName,
|
|
144
57
|
providerName: this.providerName,
|
|
145
|
-
baseURL: this.baseURL,
|
|
58
|
+
baseURL: this.config.baseURL,
|
|
146
59
|
});
|
|
147
60
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
tracer: tracers.provider,
|
|
152
|
-
attributes: {
|
|
153
|
-
[ATTR.GEN_AI_SYSTEM]: "deepseek",
|
|
154
|
-
[ATTR.GEN_AI_MODEL]: this.modelName,
|
|
155
|
-
[ATTR.GEN_AI_OPERATION]: "stream",
|
|
156
|
-
[ATTR.NL_STREAM_MODE]: true,
|
|
157
|
-
},
|
|
158
|
-
}, async () => this.executeStreamInner(options), (r) => r.stream, (r, wrapped) => ({ ...r, stream: wrapped }));
|
|
159
|
-
}
|
|
160
|
-
async executeStreamInner(options) {
|
|
161
|
-
this.validateStreamOptions(options);
|
|
162
|
-
const startTime = Date.now();
|
|
163
|
-
const timeout = this.getTimeout(options);
|
|
164
|
-
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
165
|
-
try {
|
|
166
|
-
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
167
|
-
const tools = shouldUseTools
|
|
168
|
-
? options.tools || (await this.getAllTools())
|
|
169
|
-
: {};
|
|
170
|
-
const messages = await this.buildMessagesForStream(options);
|
|
171
|
-
const model = await this.getAISDKModelWithMiddleware(options);
|
|
172
|
-
const isReasoner = this.modelName === DeepSeekModels.DEEPSEEK_REASONER;
|
|
173
|
-
const result = await streamText({
|
|
174
|
-
model,
|
|
175
|
-
messages,
|
|
176
|
-
temperature: options.temperature,
|
|
177
|
-
maxOutputTokens: options.maxTokens,
|
|
178
|
-
tools,
|
|
179
|
-
stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
|
|
180
|
-
toolChoice: resolveToolChoice(options, tools, shouldUseTools),
|
|
181
|
-
abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
|
|
182
|
-
// DeepSeek's `thinking` mode is opt-in for chat models — only enable
|
|
183
|
-
// when the caller explicitly asks for it via `thinkingConfig.enabled`.
|
|
184
|
-
// Forcing it on every chat call would trigger extended reasoning for
|
|
185
|
-
// simple prompts (and ignore reasoner models which control it natively).
|
|
186
|
-
providerOptions: !isReasoner && options.thinkingConfig?.enabled
|
|
187
|
-
? {
|
|
188
|
-
openai: {
|
|
189
|
-
thinking: { type: "enabled" },
|
|
190
|
-
},
|
|
191
|
-
}
|
|
192
|
-
: undefined,
|
|
193
|
-
experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
|
|
194
|
-
experimental_repairToolCall: this.getToolCallRepairFn(options),
|
|
195
|
-
onStepFinish: ({ toolCalls, toolResults }) => {
|
|
196
|
-
emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
|
|
197
|
-
this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
|
|
198
|
-
logger.warn("[DeepSeekProvider] Failed to store tool executions", {
|
|
199
|
-
provider: this.providerName,
|
|
200
|
-
error: error instanceof Error ? error.message : String(error),
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
timeoutController?.cleanup();
|
|
206
|
-
const transformedStream = this.createTextStream(result);
|
|
207
|
-
const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
|
|
208
|
-
requestId: `deepseek-stream-${Date.now()}`,
|
|
209
|
-
streamingMode: true,
|
|
210
|
-
});
|
|
211
|
-
return {
|
|
212
|
-
stream: transformedStream,
|
|
213
|
-
provider: this.providerName,
|
|
214
|
-
model: this.modelName,
|
|
215
|
-
analytics: analyticsPromise,
|
|
216
|
-
metadata: { startTime, streamId: `deepseek-${Date.now()}` },
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
catch (error) {
|
|
220
|
-
timeoutController?.cleanup();
|
|
221
|
-
throw this.handleProviderError(error);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
61
|
+
// ===========================================================================
|
|
62
|
+
// Abstract hooks (required)
|
|
63
|
+
// ===========================================================================
|
|
224
64
|
getProviderName() {
|
|
225
|
-
return
|
|
65
|
+
return "deepseek";
|
|
226
66
|
}
|
|
227
67
|
getDefaultModel() {
|
|
228
68
|
return getDefaultDeepSeekModel();
|
|
229
69
|
}
|
|
230
|
-
getAISDKModel() {
|
|
231
|
-
return this.model;
|
|
232
|
-
}
|
|
233
70
|
formatProviderError(error) {
|
|
234
71
|
if (error instanceof TimeoutError) {
|
|
235
72
|
return new NetworkError(`Request timed out: ${error.message}`, "deepseek");
|
|
@@ -256,17 +93,31 @@ export class DeepSeekProvider extends BaseProvider {
|
|
|
256
93
|
}
|
|
257
94
|
return new ProviderError(`DeepSeek error: ${message}`, "deepseek");
|
|
258
95
|
}
|
|
259
|
-
|
|
260
|
-
|
|
96
|
+
// ===========================================================================
|
|
97
|
+
// Optional hooks — provider-specific quirks
|
|
98
|
+
// ===========================================================================
|
|
99
|
+
getFallbackModelName() {
|
|
100
|
+
return DeepSeekModels.DEEPSEEK_CHAT;
|
|
261
101
|
}
|
|
262
|
-
|
|
263
|
-
return
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
102
|
+
getFallbackModels() {
|
|
103
|
+
return [DeepSeekModels.DEEPSEEK_CHAT, DeepSeekModels.DEEPSEEK_REASONER];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* DeepSeek's /chat/completions rejects `response_format: { type:
|
|
107
|
+
* "json_schema" }` outright ("This response_format type is unavailable
|
|
108
|
+
* now"). The `@ai-sdk/openai-compatible` provider this migration replaced
|
|
109
|
+
* ran with `supportsStructuredOutputs: false`, which downgraded structured-
|
|
110
|
+
* output requests to `{ type: "json_object" }`. Replicate that downgrade so
|
|
111
|
+
* `generate({ schema })` keeps working. (DeepSeek's json_object mode also
|
|
112
|
+
* requires the word "json" somewhere in the messages; the base client's
|
|
113
|
+
* `ensureJsonWordInBody` injects a minimal instruction when the prompt
|
|
114
|
+
* lacks it.)
|
|
115
|
+
*/
|
|
116
|
+
adjustResponseFormat(rf, _modelId) {
|
|
117
|
+
if (rf?.type === "json_schema") {
|
|
118
|
+
return { type: "json_object" };
|
|
119
|
+
}
|
|
120
|
+
return rf;
|
|
269
121
|
}
|
|
270
122
|
}
|
|
271
|
-
export default DeepSeekProvider;
|
|
272
123
|
//# sourceMappingURL=deepseek.js.map
|
|
@@ -1,29 +1,47 @@
|
|
|
1
1
|
import type { AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import type { LanguageModel } from "../types/index.js";
|
|
2
|
+
import type { NeurolinkCredentials, OpenAICompatResponseFormat } from "../types/index.js";
|
|
3
|
+
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
5
4
|
/**
|
|
6
|
-
* DeepSeek Provider
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* DeepSeek Provider — direct HTTP, no AI SDK.
|
|
6
|
+
*
|
|
7
|
+
* OpenAI-compatible chat completions at api.deepseek.com (deepseek-chat /
|
|
8
|
+
* deepseek-reasoner). All request/stream/tool-loop orchestration lives in
|
|
9
|
+
* `OpenAIChatCompletionsProvider`; this class declares configuration and
|
|
10
|
+
* provider-specific quirks:
|
|
11
|
+
*
|
|
12
|
+
* 1. Structured-output downgrade — DeepSeek rejects `response_format:
|
|
13
|
+
* { type: "json_schema" }` ("This response_format type is unavailable
|
|
14
|
+
* now"), so `adjustResponseFormat` downgrades it to `json_object` —
|
|
15
|
+
* matching the `supportsStructuredOutputs: false` behaviour of the
|
|
16
|
+
* `@ai-sdk/openai-compatible` path this migration replaced. The base
|
|
17
|
+
* client injects the literal "json" word the API requires for that mode.
|
|
18
|
+
*
|
|
19
|
+
* 2. Reasoning support — the opt-in `thinking` request param (non-reasoner
|
|
20
|
+
* chat models) and `reasoning_content` surfacing (deepseek-reasoner / R1)
|
|
21
|
+
* both require plumbing the thinking signal and the reasoning delta
|
|
22
|
+
* through the native base client. That plumbing isn't in place yet, so
|
|
23
|
+
* neither is wired here; it is tracked as a base-client follow-up. All
|
|
24
|
+
* other behavior is preserved.
|
|
25
|
+
*
|
|
26
|
+
* @see https://api-docs.deepseek.com
|
|
9
27
|
*/
|
|
10
|
-
export declare class DeepSeekProvider extends
|
|
11
|
-
private model;
|
|
12
|
-
private apiKey;
|
|
13
|
-
private baseURL;
|
|
28
|
+
export declare class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
14
29
|
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["deepseek"]);
|
|
15
|
-
protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
16
|
-
private executeStreamInner;
|
|
17
30
|
protected getProviderName(): AIProviderName;
|
|
18
31
|
protected getDefaultModel(): string;
|
|
19
|
-
protected getAISDKModel(): LanguageModel;
|
|
20
32
|
protected formatProviderError(error: unknown): Error;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
33
|
+
protected getFallbackModelName(): string;
|
|
34
|
+
protected getFallbackModels(): string[];
|
|
35
|
+
/**
|
|
36
|
+
* DeepSeek's /chat/completions rejects `response_format: { type:
|
|
37
|
+
* "json_schema" }` outright ("This response_format type is unavailable
|
|
38
|
+
* now"). The `@ai-sdk/openai-compatible` provider this migration replaced
|
|
39
|
+
* ran with `supportsStructuredOutputs: false`, which downgraded structured-
|
|
40
|
+
* output requests to `{ type: "json_object" }`. Replicate that downgrade so
|
|
41
|
+
* `generate({ schema })` keeps working. (DeepSeek's json_object mode also
|
|
42
|
+
* requires the word "json" somewhere in the messages; the base client's
|
|
43
|
+
* `ensureJsonWordInBody` injects a minimal instruction when the prompt
|
|
44
|
+
* lacks it.)
|
|
45
|
+
*/
|
|
46
|
+
protected adjustResponseFormat(rf: OpenAICompatResponseFormat | undefined, _modelId: string): OpenAICompatResponseFormat | undefined;
|
|
28
47
|
}
|
|
29
|
-
export default DeepSeekProvider;
|