@juspay/neurolink 9.68.12 → 9.68.14
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 +4 -0
- package/dist/browser/neurolink.min.js +411 -425
- package/dist/lib/providers/deepseek.d.ts +39 -21
- package/dist/lib/providers/deepseek.js +68 -217
- package/dist/lib/providers/openAI.d.ts +29 -57
- package/dist/lib/providers/openAI.js +184 -579
- package/dist/lib/utils/providerSetupMessages.js +1 -1
- package/dist/providers/deepseek.d.ts +39 -21
- package/dist/providers/deepseek.js +68 -217
- package/dist/providers/openAI.d.ts +29 -57
- package/dist/providers/openAI.js +184 -579
- package/dist/utils/providerSetupMessages.js +1 -1
- 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,78 +1,51 @@
|
|
|
1
|
-
import { AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import type { EnhancedGenerateResult, TextGenerationOptions, ValidationSchema, StreamOptions, StreamResult } from "../types/index.js";
|
|
5
|
-
import type { LanguageModel } from "../types/index.js";
|
|
1
|
+
import type { AIProviderName } from "../constants/enums.js";
|
|
2
|
+
import type { EnhancedGenerateResult, NeurolinkCredentials, OpenAICompatStreamLifecycleListeners, TextGenerationOptions } from "../types/index.js";
|
|
3
|
+
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
6
4
|
/**
|
|
7
|
-
* OpenAI Provider
|
|
8
|
-
*
|
|
5
|
+
* OpenAI Provider — direct HTTP, no AI SDK.
|
|
6
|
+
*
|
|
7
|
+
* OpenAI chat completions at api.openai.com/v1. All request / stream /
|
|
8
|
+
* tool-loop orchestration lives in `OpenAIChatCompletionsProvider`; this
|
|
9
|
+
* class adds:
|
|
10
|
+
* - OTel span wrap with cost (`onStreamStart`)
|
|
11
|
+
* - Native `/v1/embeddings` (`embed` / `embedMany`)
|
|
12
|
+
* - Image generation via `/v1/images/generations` (`executeImageGeneration`)
|
|
13
|
+
* - OpenAI-specific error mapping (`formatProviderError`)
|
|
14
|
+
*
|
|
15
|
+
* @see https://platform.openai.com/docs/api-reference
|
|
9
16
|
*/
|
|
10
|
-
export declare class OpenAIProvider extends
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
baseURL?: string;
|
|
16
|
-
});
|
|
17
|
+
export declare class OpenAIProvider extends OpenAIChatCompletionsProvider {
|
|
18
|
+
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["openai"]);
|
|
19
|
+
protected getProviderName(): AIProviderName;
|
|
20
|
+
protected getDefaultModel(): string;
|
|
21
|
+
formatProviderError(error: unknown): Error;
|
|
17
22
|
/**
|
|
18
|
-
*
|
|
23
|
+
* Wrap the stream in an OTel span to capture provider-level latency,
|
|
24
|
+
* token usage, finish reason, and cost. Mirrors the pre-migration
|
|
25
|
+
* `streamText`-span behaviour.
|
|
19
26
|
*/
|
|
20
|
-
|
|
21
|
-
getProviderName(): AIProviderName;
|
|
22
|
-
getDefaultModel(): string;
|
|
27
|
+
protected onStreamStart(modelId: string): OpenAICompatStreamLifecycleListeners | undefined;
|
|
23
28
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @returns The default OpenAI embedding model name
|
|
29
|
+
* Default embedding model, overridable via OPENAI_EMBEDDING_MODEL env var.
|
|
26
30
|
*/
|
|
27
31
|
protected getDefaultEmbeddingModel(): string;
|
|
28
32
|
/**
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
getAISDKModel(): LanguageModel;
|
|
32
|
-
/**
|
|
33
|
-
* OpenAI-specific tool validation and filtering
|
|
34
|
-
* Filters out tools that might cause streaming issues
|
|
35
|
-
*/
|
|
36
|
-
private validateAndFilterToolsForOpenAI;
|
|
37
|
-
/**
|
|
38
|
-
* Validate Zod schema structure
|
|
39
|
-
*/
|
|
40
|
-
private validateZodSchema;
|
|
41
|
-
/**
|
|
42
|
-
* Validate tool structure for OpenAI compatibility
|
|
43
|
-
* More lenient validation to avoid filtering out valid tools
|
|
44
|
-
*/
|
|
45
|
-
/** Shared helper: mark a stream span as ERROR, record the exception, and end it. */
|
|
46
|
-
private endStreamSpanWithError;
|
|
47
|
-
private isValidToolStructure;
|
|
48
|
-
/**
|
|
49
|
-
* Validate tool parameters for OpenAI compatibility
|
|
50
|
-
* Ensures the tool has either valid Zod schema or valid JSON schema
|
|
51
|
-
*/
|
|
52
|
-
private isValidToolParameters;
|
|
53
|
-
formatProviderError(error: unknown): Error;
|
|
54
|
-
/**
|
|
55
|
-
* executeGenerate method removed - generation is now handled by BaseProvider.
|
|
56
|
-
* For details on the changes and migration steps, refer to the BaseProvider documentation
|
|
57
|
-
* and the migration guide in the project repository.
|
|
58
|
-
*/
|
|
59
|
-
protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
60
|
-
private createOpenAITransformedStream;
|
|
61
|
-
private extractOpenAIChunkContent;
|
|
62
|
-
/**
|
|
63
|
-
* Generate embeddings for text using OpenAI text-embedding models
|
|
33
|
+
* Generate an embedding for a single text input via native /v1/embeddings.
|
|
34
|
+
*
|
|
64
35
|
* @param text - The text to embed
|
|
65
36
|
* @param modelName - The embedding model to use (default: text-embedding-3-small)
|
|
66
37
|
* @returns Promise resolving to the embedding vector
|
|
67
38
|
*/
|
|
68
39
|
embed(text: string, modelName?: string): Promise<number[]>;
|
|
69
40
|
/**
|
|
70
|
-
* Generate embeddings for multiple texts in a single batch
|
|
41
|
+
* Generate embeddings for multiple texts in a single batch via native /v1/embeddings.
|
|
42
|
+
*
|
|
71
43
|
* @param texts - The texts to embed
|
|
72
44
|
* @param modelName - The embedding model to use (default: text-embedding-3-small)
|
|
73
45
|
* @returns Promise resolving to an array of embedding vectors
|
|
74
46
|
*/
|
|
75
47
|
embedMany(texts: string[], modelName?: string): Promise<number[][]>;
|
|
48
|
+
private callEmbeddings;
|
|
76
49
|
/**
|
|
77
50
|
* Image generation via the OpenAI Images API (`/v1/images/generations`).
|
|
78
51
|
*
|
|
@@ -95,4 +68,3 @@ export declare class OpenAIProvider extends BaseProvider {
|
|
|
95
68
|
*/
|
|
96
69
|
private aspectRatioToOpenAISize;
|
|
97
70
|
}
|
|
98
|
-
export default OpenAIProvider;
|