@juspay/neurolink 9.59.5 → 9.60.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +11 -7
  3. package/dist/adapters/providerImageAdapter.js +52 -2
  4. package/dist/browser/neurolink.min.js +352 -352
  5. package/dist/cli/factories/commandFactory.js +15 -1
  6. package/dist/cli/utils/interactiveSetup.js +64 -0
  7. package/dist/constants/contextWindows.d.ts +5 -1
  8. package/dist/constants/contextWindows.js +67 -3
  9. package/dist/constants/enums.d.ts +52 -0
  10. package/dist/constants/enums.js +63 -0
  11. package/dist/core/baseProvider.d.ts +15 -6
  12. package/dist/core/baseProvider.js +28 -0
  13. package/dist/factories/providerRegistry.js +25 -1
  14. package/dist/lib/adapters/providerImageAdapter.js +52 -2
  15. package/dist/lib/constants/contextWindows.d.ts +5 -1
  16. package/dist/lib/constants/contextWindows.js +67 -3
  17. package/dist/lib/constants/enums.d.ts +52 -0
  18. package/dist/lib/constants/enums.js +63 -0
  19. package/dist/lib/core/baseProvider.d.ts +15 -6
  20. package/dist/lib/core/baseProvider.js +28 -0
  21. package/dist/lib/factories/providerRegistry.js +25 -1
  22. package/dist/lib/neurolink.js +1 -1
  23. package/dist/lib/providers/deepseek.d.ts +29 -0
  24. package/dist/lib/providers/deepseek.js +216 -0
  25. package/dist/lib/providers/index.d.ts +4 -0
  26. package/dist/lib/providers/index.js +4 -0
  27. package/dist/lib/providers/llamaCpp.d.ts +34 -0
  28. package/dist/lib/providers/llamaCpp.js +315 -0
  29. package/dist/lib/providers/lmStudio.d.ts +34 -0
  30. package/dist/lib/providers/lmStudio.js +306 -0
  31. package/dist/lib/providers/nvidiaNim.d.ts +31 -0
  32. package/dist/lib/providers/nvidiaNim.js +354 -0
  33. package/dist/lib/proxy/proxyFetch.d.ts +9 -0
  34. package/dist/lib/proxy/proxyFetch.js +6 -1
  35. package/dist/lib/types/providers.d.ts +37 -2
  36. package/dist/lib/types/providers.js +1 -1
  37. package/dist/lib/utils/modelChoices.js +68 -4
  38. package/dist/lib/utils/pricing.d.ts +5 -0
  39. package/dist/lib/utils/pricing.js +94 -3
  40. package/dist/lib/utils/providerConfig.d.ts +16 -0
  41. package/dist/lib/utils/providerConfig.js +82 -0
  42. package/dist/neurolink.js +1 -1
  43. package/dist/providers/deepseek.d.ts +29 -0
  44. package/dist/providers/deepseek.js +215 -0
  45. package/dist/providers/index.d.ts +4 -0
  46. package/dist/providers/index.js +4 -0
  47. package/dist/providers/llamaCpp.d.ts +34 -0
  48. package/dist/providers/llamaCpp.js +314 -0
  49. package/dist/providers/lmStudio.d.ts +34 -0
  50. package/dist/providers/lmStudio.js +305 -0
  51. package/dist/providers/nvidiaNim.d.ts +31 -0
  52. package/dist/providers/nvidiaNim.js +353 -0
  53. package/dist/proxy/proxyFetch.d.ts +9 -0
  54. package/dist/proxy/proxyFetch.js +6 -1
  55. package/dist/types/providers.d.ts +37 -2
  56. package/dist/utils/modelChoices.js +68 -4
  57. package/dist/utils/pricing.d.ts +5 -0
  58. package/dist/utils/pricing.js +94 -3
  59. package/dist/utils/providerConfig.d.ts +16 -0
  60. package/dist/utils/providerConfig.js +82 -0
  61. package/package.json +19 -12
@@ -224,6 +224,67 @@ const PRICING = {
224
224
  output: 0.15 / 1_000_000,
225
225
  },
226
226
  },
227
+ deepseek: {
228
+ "deepseek-chat": {
229
+ input: 0.27 / 1_000_000,
230
+ output: 1.1 / 1_000_000,
231
+ cacheRead: 0.07 / 1_000_000,
232
+ },
233
+ "deepseek-reasoner": {
234
+ input: 0.55 / 1_000_000,
235
+ output: 2.19 / 1_000_000,
236
+ cacheRead: 0.14 / 1_000_000,
237
+ },
238
+ },
239
+ "nvidia-nim": {
240
+ "meta/llama-3.3-70b-instruct": {
241
+ input: 0.4 / 1_000_000,
242
+ output: 0.4 / 1_000_000,
243
+ },
244
+ "meta/llama-3.1-405b-instruct": {
245
+ input: 1.79 / 1_000_000,
246
+ output: 1.79 / 1_000_000,
247
+ },
248
+ "meta/llama-3.1-70b-instruct": {
249
+ input: 0.4 / 1_000_000,
250
+ output: 0.4 / 1_000_000,
251
+ },
252
+ "meta/llama-3.2-90b-vision-instruct": {
253
+ input: 0.5 / 1_000_000,
254
+ output: 0.5 / 1_000_000,
255
+ },
256
+ "nvidia/llama-3.3-nemotron-super-49b-v1": {
257
+ input: 0.3 / 1_000_000,
258
+ output: 0.3 / 1_000_000,
259
+ },
260
+ "deepseek-ai/deepseek-r1": {
261
+ input: 0.55 / 1_000_000,
262
+ output: 2.19 / 1_000_000,
263
+ },
264
+ "mistralai/mixtral-8x22b-instruct-v0.1": {
265
+ input: 0.6 / 1_000_000,
266
+ output: 0.6 / 1_000_000,
267
+ },
268
+ "mistralai/mixtral-8x7b-instruct-v0.1": {
269
+ input: 0.24 / 1_000_000,
270
+ output: 0.24 / 1_000_000,
271
+ },
272
+ "microsoft/phi-4": { input: 0.07 / 1_000_000, output: 0.07 / 1_000_000 },
273
+ "google/gemma-3-27b-it": {
274
+ input: 0.07 / 1_000_000,
275
+ output: 0.07 / 1_000_000,
276
+ },
277
+ },
278
+ "lm-studio": {
279
+ // Local inference — there is no upstream USD price. Reporting a fabricated
280
+ // symbolic rate here misstated spend in analytics/spans, so the rate is
281
+ // explicitly zero. `calculateCost()` returns 0 for zero rates and the CLI
282
+ // / span renderers already treat 0 as "no billable cost" (no $ shown).
283
+ _default: { input: 0, output: 0 },
284
+ },
285
+ llamacpp: {
286
+ _default: { input: 0, output: 0 },
287
+ },
227
288
  };
228
289
  /**
229
290
  * Map of normalized provider aliases to canonical PRICING keys.
@@ -246,6 +307,12 @@ const PROVIDER_ALIASES = {
246
307
  litellm: "__cross_provider__",
247
308
  openrouter: "__cross_provider__",
248
309
  openaicompatible: "__cross_provider__",
310
+ deepseek: "deepseek",
311
+ nvidianim: "nvidia-nim",
312
+ nim: "nvidia-nim",
313
+ nvidia: "nvidia-nim",
314
+ lmstudio: "lm-studio",
315
+ llamacpp: "llamacpp",
249
316
  };
250
317
  /**
251
318
  * Look up per-token rates for a provider/model combination.
@@ -287,14 +354,19 @@ function findRates(provider, model) {
287
354
  if (providerPricing[model]) {
288
355
  return providerPricing[model];
289
356
  }
290
- // Longest-prefix match
291
- const sortedKeys = Object.keys(providerPricing).sort((a, b) => b.length - a.length);
357
+ // Longest-prefix match (skip the synthetic "_default" sentinel below)
358
+ const sortedKeys = Object.keys(providerPricing)
359
+ .filter((k) => k !== "_default")
360
+ .sort((a, b) => b.length - a.length);
292
361
  const key = sortedKeys.find((k) => model.startsWith(k));
293
362
  if (key) {
294
363
  return providerPricing[key];
295
364
  }
296
365
  // Fallback: Vertex hosts both Claude and Gemini models.
297
366
  // If no match found under "vertex", try "google" pricing for Gemini models.
367
+ // (Run BEFORE the provider-level _default fallback so that Vertex Gemini
368
+ // requests get the more specific Google rates rather than a generic Vertex
369
+ // _default if one is ever added.)
298
370
  if (normalizedProvider === "vertex" && model.startsWith("gemini")) {
299
371
  const googlePricing = PRICING["google"];
300
372
  if (googlePricing) {
@@ -308,6 +380,13 @@ function findRates(provider, model) {
308
380
  }
309
381
  }
310
382
  }
383
+ // Provider-level fallback: when a pricing table only has _default (or has
384
+ // no entry matching the specific model), use _default. This is mainly for
385
+ // local/symbolic providers (lm-studio, llamacpp) that don't enumerate per-
386
+ // model pricing.
387
+ if (providerPricing["_default"]) {
388
+ return providerPricing["_default"];
389
+ }
311
390
  return undefined;
312
391
  }
313
392
  /**
@@ -334,8 +413,20 @@ export function calculateCost(provider, model, usage) {
334
413
  * Check if pricing is available for a provider/model combination.
335
414
  * Checks the rate table directly instead of computing a cost,
336
415
  * so even very cheap models (e.g. gemini-1.5-flash) are detected correctly.
416
+ *
417
+ * Zero-rate entries (the local-provider `_default` for lm-studio / llamacpp)
418
+ * count as "no pricing" — those providers explicitly don't have an upstream
419
+ * USD price, and any caller gated by `hasPricing()` should treat them as
420
+ * non-billable rather than zero-cost-billable.
337
421
  */
338
422
  export function hasPricing(provider, model) {
339
- return findRates(provider, model) !== undefined;
423
+ const rates = findRates(provider, model);
424
+ if (!rates) {
425
+ return false;
426
+ }
427
+ return (rates.input > 0 ||
428
+ rates.output > 0 ||
429
+ (rates.cacheRead ?? 0) > 0 ||
430
+ (rates.cacheCreation ?? 0) > 0);
340
431
  }
341
432
  //# sourceMappingURL=pricing.js.map
@@ -107,6 +107,22 @@ export declare function createAzureEndpointConfig(): ProviderConfigOptions;
107
107
  * Creates OpenAI Compatible provider configuration
108
108
  */
109
109
  export declare function createOpenAICompatibleConfig(): ProviderConfigOptions;
110
+ /**
111
+ * Creates DeepSeek provider configuration
112
+ */
113
+ export declare function createDeepSeekConfig(): ProviderConfigOptions;
114
+ /**
115
+ * Creates NVIDIA NIM provider configuration
116
+ */
117
+ export declare function createNvidiaNimConfig(): ProviderConfigOptions;
118
+ /**
119
+ * Creates LM Studio provider configuration (local server)
120
+ */
121
+ export declare function createLmStudioConfig(): ProviderConfigOptions;
122
+ /**
123
+ * Creates llama.cpp provider configuration (local server)
124
+ */
125
+ export declare function createLlamaCppConfig(): ProviderConfigOptions;
110
126
  /**
111
127
  * Creates Google Vertex Project ID configuration
112
128
  */
@@ -85,6 +85,10 @@ export function validateApiKeyEnhanced(config, enableFormatValidation = false) {
85
85
  }
86
86
  }
87
87
  if (!apiKey) {
88
+ if (config.optional) {
89
+ // Local providers — base URL defaulted; treat as valid with empty value.
90
+ return { isValid: true, apiKey: "" };
91
+ }
88
92
  return {
89
93
  isValid: false,
90
94
  apiKey: "",
@@ -131,6 +135,12 @@ export function validateApiKey(config) {
131
135
  }
132
136
  }
133
137
  if (!apiKey) {
138
+ // Local providers (LM Studio, llama.cpp) treat envVarName as a base-URL
139
+ // override, not a credential. Returning "" lets callers fall back to the
140
+ // documented default URL without raising a configuration error.
141
+ if (config.optional) {
142
+ return "";
143
+ }
134
144
  throw new Error(createConfigErrorMessage(config));
135
145
  }
136
146
  return apiKey;
@@ -366,6 +376,78 @@ export function createOpenAICompatibleConfig() {
366
376
  ],
367
377
  };
368
378
  }
379
+ /**
380
+ * Creates DeepSeek provider configuration
381
+ */
382
+ export function createDeepSeekConfig() {
383
+ return {
384
+ providerName: "DeepSeek",
385
+ envVarName: "DEEPSEEK_API_KEY",
386
+ setupUrl: "https://platform.deepseek.com/api_keys",
387
+ description: "API key",
388
+ instructions: [
389
+ "1. Visit: https://platform.deepseek.com/api_keys",
390
+ "2. Create or sign in to your DeepSeek account",
391
+ "3. Generate a new API key",
392
+ "4. Set DEEPSEEK_API_KEY in your .env file",
393
+ ],
394
+ };
395
+ }
396
+ /**
397
+ * Creates NVIDIA NIM provider configuration
398
+ */
399
+ export function createNvidiaNimConfig() {
400
+ return {
401
+ providerName: "NVIDIA NIM",
402
+ envVarName: "NVIDIA_NIM_API_KEY",
403
+ setupUrl: "https://build.nvidia.com/settings/api-keys",
404
+ description: "API key",
405
+ instructions: [
406
+ "1. Visit: https://build.nvidia.com/",
407
+ "2. Sign in with your NVIDIA developer account",
408
+ "3. Open Settings → API Keys",
409
+ "4. Generate a new API key (Bearer token)",
410
+ "5. Set NVIDIA_NIM_API_KEY in your .env file",
411
+ ],
412
+ };
413
+ }
414
+ /**
415
+ * Creates LM Studio provider configuration (local server)
416
+ */
417
+ export function createLmStudioConfig() {
418
+ return {
419
+ providerName: "LM Studio",
420
+ envVarName: "LM_STUDIO_BASE_URL",
421
+ setupUrl: "https://lmstudio.ai/",
422
+ description: "LM Studio server URL",
423
+ instructions: [
424
+ "1. Install LM Studio: https://lmstudio.ai/",
425
+ "2. Open LM Studio and download a model (e.g. Llama 3.2 3B Instruct)",
426
+ '3. Click "Local Server" → Start Server',
427
+ "4. Default URL is http://localhost:1234/v1 (override via LM_STUDIO_BASE_URL)",
428
+ ],
429
+ // Base URL is optional — defaults to http://localhost:1234/v1 if unset.
430
+ optional: true,
431
+ };
432
+ }
433
+ /**
434
+ * Creates llama.cpp provider configuration (local server)
435
+ */
436
+ export function createLlamaCppConfig() {
437
+ return {
438
+ providerName: "llama.cpp",
439
+ envVarName: "LLAMACPP_BASE_URL",
440
+ setupUrl: "https://github.com/ggerganov/llama.cpp",
441
+ description: "llama.cpp server URL",
442
+ instructions: [
443
+ "1. Build llama.cpp: https://github.com/ggerganov/llama.cpp#build",
444
+ "2. Run: ./llama-server -m model.gguf --port 8080",
445
+ "3. Default URL is http://localhost:8080/v1 (override via LLAMACPP_BASE_URL)",
446
+ ],
447
+ // Base URL is optional — defaults to http://localhost:8080/v1 if unset.
448
+ optional: true,
449
+ };
450
+ }
369
451
  /**
370
452
  * Creates Google Vertex Project ID configuration
371
453
  */
package/dist/neurolink.js CHANGED
@@ -7255,7 +7255,7 @@ Current user's request: ${currentInput}`;
7255
7255
  const finalOptions = {
7256
7256
  timeout: options?.timeout ??
7257
7257
  toolInfo?.tool?.timeoutMs ??
7258
- TOOL_TIMEOUTS.EXECUTION_DEFAULT_MS,
7258
+ TOOL_TIMEOUTS.EXECUTION_BATCH_MS,
7259
7259
  maxRetries: options?.maxRetries ??
7260
7260
  toolInfo?.tool?.maxRetries ??
7261
7261
  RETRY_ATTEMPTS.DEFAULT,
@@ -0,0 +1,29 @@
1
+ import { type LanguageModel } from "ai";
2
+ import type { AIProviderName } from "../constants/enums.js";
3
+ import { BaseProvider } from "../core/baseProvider.js";
4
+ import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
5
+ /**
6
+ * DeepSeek Provider
7
+ * OpenAI-compatible chat completions; supports deepseek-chat (V3) and
8
+ * deepseek-reasoner (R1, exposes reasoning_content).
9
+ */
10
+ export declare class DeepSeekProvider extends BaseProvider {
11
+ private model;
12
+ private apiKey;
13
+ private baseURL;
14
+ constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["deepseek"]);
15
+ protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
16
+ private executeStreamInner;
17
+ protected getProviderName(): AIProviderName;
18
+ protected getDefaultModel(): string;
19
+ protected getAISDKModel(): LanguageModel;
20
+ protected formatProviderError(error: unknown): Error;
21
+ validateConfiguration(): Promise<boolean>;
22
+ getConfiguration(): {
23
+ provider: AIProviderName;
24
+ model: string;
25
+ defaultModel: string;
26
+ baseURL: string;
27
+ };
28
+ }
29
+ export default DeepSeekProvider;
@@ -0,0 +1,215 @@
1
+ import { createOpenAI } from "@ai-sdk/openai";
2
+ import { stepCountIs, streamText } from "ai";
3
+ import { DeepSeekModels } from "../constants/enums.js";
4
+ import { BaseProvider } from "../core/baseProvider.js";
5
+ import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
+ import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
7
+ import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
8
+ import { tracers, ATTR, withClientSpan } from "../telemetry/index.js";
9
+ import { logger } from "../utils/logger.js";
10
+ import { createDeepSeekConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
11
+ import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
12
+ import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
13
+ import { resolveToolChoice } from "../utils/toolChoice.js";
14
+ import { toAnalyticsStreamResult } from "./providerTypeUtils.js";
15
+ const makeLoggingFetch = (provider) => {
16
+ const base = createProxyFetch();
17
+ return (async (input, init) => {
18
+ const url = typeof input === "string"
19
+ ? input
20
+ : input instanceof URL
21
+ ? input.toString()
22
+ : input.url;
23
+ const reqSize = init?.body && typeof init.body === "string" ? init.body.length : 0;
24
+ const response = await base(input, init);
25
+ if (!response.ok) {
26
+ // Don't fall back to the raw URL — that would defeat the redaction.
27
+ const safeUrl = maskProxyUrl(url) ?? "<redacted>";
28
+ if (process.env.NEUROLINK_DEBUG_HTTP === "1") {
29
+ const clone = response.clone();
30
+ const body = await clone.text().catch(() => "<unreadable>");
31
+ logger.warn(`[${provider}] upstream ${response.status}`, {
32
+ url: safeUrl,
33
+ body: body.slice(0, 800),
34
+ reqSize,
35
+ });
36
+ }
37
+ else {
38
+ logger.warn(`[${provider}] upstream ${response.status} url=${safeUrl} reqSize=${reqSize}`);
39
+ }
40
+ }
41
+ return response;
42
+ });
43
+ };
44
+ const DEEPSEEK_DEFAULT_BASE_URL = "https://api.deepseek.com";
45
+ const getDeepSeekApiKey = () => {
46
+ return validateApiKey(createDeepSeekConfig());
47
+ };
48
+ const getDefaultDeepSeekModel = () => {
49
+ return getProviderModel("DEEPSEEK_MODEL", DeepSeekModels.DEEPSEEK_CHAT);
50
+ };
51
+ /**
52
+ * DeepSeek Provider
53
+ * OpenAI-compatible chat completions; supports deepseek-chat (V3) and
54
+ * deepseek-reasoner (R1, exposes reasoning_content).
55
+ */
56
+ export class DeepSeekProvider extends BaseProvider {
57
+ model;
58
+ apiKey;
59
+ baseURL;
60
+ constructor(modelName, sdk, _region, credentials) {
61
+ const validatedNeurolink = sdk && typeof sdk === "object" && "getInMemoryServers" in sdk
62
+ ? sdk
63
+ : undefined;
64
+ super(modelName, "deepseek", validatedNeurolink);
65
+ // Trim the override before applying precedence. A blank/whitespace
66
+ // `credentials.apiKey` should NOT bypass `getDeepSeekApiKey()` — that
67
+ // would build a client with an unusable bearer token and fail at request
68
+ // time with a confusing 401 instead of at construction time.
69
+ const overrideApiKey = credentials?.apiKey?.trim();
70
+ this.apiKey =
71
+ overrideApiKey && overrideApiKey.length > 0
72
+ ? overrideApiKey
73
+ : getDeepSeekApiKey();
74
+ this.baseURL =
75
+ credentials?.baseURL ??
76
+ process.env.DEEPSEEK_BASE_URL ??
77
+ DEEPSEEK_DEFAULT_BASE_URL;
78
+ const deepseek = createOpenAI({
79
+ apiKey: this.apiKey,
80
+ baseURL: this.baseURL,
81
+ fetch: makeLoggingFetch("deepseek"),
82
+ });
83
+ // .chat() returns a Chat Completions model. The default factory call
84
+ // returns a Responses API model which OpenAI-compat providers don't implement.
85
+ this.model = deepseek.chat(this.modelName);
86
+ logger.debug("DeepSeek Provider initialized", {
87
+ modelName: this.modelName,
88
+ providerName: this.providerName,
89
+ baseURL: this.baseURL,
90
+ });
91
+ }
92
+ async executeStream(options, _analysisSchema) {
93
+ return withClientSpan({
94
+ name: "neurolink.provider.stream",
95
+ tracer: tracers.provider,
96
+ attributes: {
97
+ [ATTR.GEN_AI_SYSTEM]: "deepseek",
98
+ [ATTR.GEN_AI_MODEL]: this.modelName,
99
+ [ATTR.GEN_AI_OPERATION]: "stream",
100
+ [ATTR.NL_STREAM_MODE]: true,
101
+ },
102
+ }, async () => this.executeStreamInner(options));
103
+ }
104
+ async executeStreamInner(options) {
105
+ this.validateStreamOptions(options);
106
+ const startTime = Date.now();
107
+ const timeout = this.getTimeout(options);
108
+ const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
109
+ try {
110
+ const shouldUseTools = !options.disableTools && this.supportsTools();
111
+ const tools = shouldUseTools
112
+ ? options.tools || (await this.getAllTools())
113
+ : {};
114
+ const messages = await this.buildMessagesForStream(options);
115
+ const model = await this.getAISDKModelWithMiddleware(options);
116
+ const isReasoner = this.modelName === DeepSeekModels.DEEPSEEK_REASONER;
117
+ const result = await streamText({
118
+ model,
119
+ messages,
120
+ temperature: options.temperature,
121
+ maxOutputTokens: options.maxTokens,
122
+ tools,
123
+ stopWhen: stepCountIs(options.maxSteps || DEFAULT_MAX_STEPS),
124
+ toolChoice: resolveToolChoice(options, tools, shouldUseTools),
125
+ abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
126
+ // DeepSeek's `thinking` mode is opt-in for chat models — only enable
127
+ // when the caller explicitly asks for it via `thinkingConfig.enabled`.
128
+ // Forcing it on every chat call would trigger extended reasoning for
129
+ // simple prompts (and ignore reasoner models which control it natively).
130
+ providerOptions: !isReasoner && options.thinkingConfig?.enabled
131
+ ? {
132
+ openai: {
133
+ thinking: { type: "enabled" },
134
+ },
135
+ }
136
+ : undefined,
137
+ experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
138
+ experimental_repairToolCall: this.getToolCallRepairFn(options),
139
+ onStepFinish: ({ toolCalls, toolResults }) => {
140
+ emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResults);
141
+ this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
142
+ logger.warn("[DeepSeekProvider] Failed to store tool executions", {
143
+ provider: this.providerName,
144
+ error: error instanceof Error ? error.message : String(error),
145
+ });
146
+ });
147
+ },
148
+ });
149
+ timeoutController?.cleanup();
150
+ const transformedStream = this.createTextStream(result);
151
+ const analyticsPromise = streamAnalyticsCollector.createAnalytics(this.providerName, this.modelName, toAnalyticsStreamResult(result), Date.now() - startTime, {
152
+ requestId: `deepseek-stream-${Date.now()}`,
153
+ streamingMode: true,
154
+ });
155
+ return {
156
+ stream: transformedStream,
157
+ provider: this.providerName,
158
+ model: this.modelName,
159
+ analytics: analyticsPromise,
160
+ metadata: { startTime, streamId: `deepseek-${Date.now()}` },
161
+ };
162
+ }
163
+ catch (error) {
164
+ timeoutController?.cleanup();
165
+ throw this.handleProviderError(error);
166
+ }
167
+ }
168
+ getProviderName() {
169
+ return this.providerName;
170
+ }
171
+ getDefaultModel() {
172
+ return getDefaultDeepSeekModel();
173
+ }
174
+ getAISDKModel() {
175
+ return this.model;
176
+ }
177
+ formatProviderError(error) {
178
+ if (error instanceof TimeoutError) {
179
+ return new Error(`DeepSeek request timed out: ${error.message}`);
180
+ }
181
+ const errorRecord = error;
182
+ const message = typeof errorRecord?.message === "string"
183
+ ? errorRecord.message
184
+ : "Unknown error";
185
+ if (message.includes("Invalid API key") ||
186
+ message.includes("Authentication") ||
187
+ message.includes("401")) {
188
+ return new Error("Invalid DeepSeek API key. Please check your DEEPSEEK_API_KEY environment variable.");
189
+ }
190
+ if (message.includes("rate limit") || message.includes("429")) {
191
+ return new Error("DeepSeek rate limit exceeded");
192
+ }
193
+ if (message.includes("Insufficient Balance") ||
194
+ message.includes("insufficient_balance") ||
195
+ message.includes("402")) {
196
+ return new Error("DeepSeek account has insufficient balance. Top up at https://platform.deepseek.com/usage");
197
+ }
198
+ if (message.includes("model_not_found") || message.includes("404")) {
199
+ return new Error(`DeepSeek model '${this.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`);
200
+ }
201
+ return new Error(`DeepSeek error: ${message}`);
202
+ }
203
+ async validateConfiguration() {
204
+ return typeof this.apiKey === "string" && this.apiKey.trim().length > 0;
205
+ }
206
+ getConfiguration() {
207
+ return {
208
+ provider: this.providerName,
209
+ model: this.modelName,
210
+ defaultModel: getDefaultDeepSeekModel(),
211
+ baseURL: this.baseURL,
212
+ };
213
+ }
214
+ }
215
+ export default DeepSeekProvider;
@@ -14,3 +14,7 @@ export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
14
14
  export { OllamaProvider as Ollama } from "./ollama.js";
15
15
  export { MistralProvider as MistralAI } from "./mistral.js";
16
16
  export { LiteLLMProvider as LiteLLM } from "./litellm.js";
17
+ export { DeepSeekProvider as DeepSeek } from "./deepseek.js";
18
+ export { NvidiaNimProvider as NvidiaNim } from "./nvidiaNim.js";
19
+ export { LMStudioProvider as LMStudio } from "./lmStudio.js";
20
+ export { LlamaCppProvider as LlamaCpp } from "./llamaCpp.js";
@@ -14,3 +14,7 @@ export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
14
14
  export { OllamaProvider as Ollama } from "./ollama.js";
15
15
  export { MistralProvider as MistralAI } from "./mistral.js";
16
16
  export { LiteLLMProvider as LiteLLM } from "./litellm.js";
17
+ export { DeepSeekProvider as DeepSeek } from "./deepseek.js";
18
+ export { NvidiaNimProvider as NvidiaNim } from "./nvidiaNim.js";
19
+ export { LMStudioProvider as LMStudio } from "./lmStudio.js";
20
+ export { LlamaCppProvider as LlamaCpp } from "./llamaCpp.js";
@@ -0,0 +1,34 @@
1
+ import { type LanguageModel } from "ai";
2
+ import type { AIProviderName } from "../constants/enums.js";
3
+ import { BaseProvider } from "../core/baseProvider.js";
4
+ import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
5
+ /**
6
+ * llama.cpp Provider
7
+ * Wraps a llama-server process (https://github.com/ggerganov/llama.cpp) that
8
+ * exposes an OpenAI-compatible API at http://localhost:8080/v1 by default.
9
+ * llama-server hosts ONE model loaded at startup; /v1/models returns just that.
10
+ */
11
+ export declare class LlamaCppProvider extends BaseProvider {
12
+ private model?;
13
+ private readonly requestedModelName?;
14
+ private baseURL;
15
+ private apiKey;
16
+ private discoveredModel?;
17
+ private llamaCppClient;
18
+ constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["llamacpp"]);
19
+ private getAvailableModels;
20
+ protected getAISDKModel(signal?: AbortSignal): Promise<LanguageModel>;
21
+ protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
22
+ private executeStreamInner;
23
+ protected getProviderName(): AIProviderName;
24
+ protected getDefaultModel(): string;
25
+ protected formatProviderError(error: unknown): Error;
26
+ validateConfiguration(): Promise<boolean>;
27
+ getConfiguration(): {
28
+ provider: AIProviderName;
29
+ model: string;
30
+ defaultModel: string;
31
+ baseURL: string;
32
+ };
33
+ }
34
+ export default LlamaCppProvider;