@juspay/neurolink 12.12.10 → 12.12.12
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 -2
- package/dist/browser/neurolink.min.js +395 -396
- package/dist/constants/contextWindows.js +1 -0
- package/dist/constants/enums.d.ts +1 -0
- package/dist/constants/enums.js +7 -0
- package/dist/core/baseProvider.d.ts +0 -22
- package/dist/core/baseProvider.js +18 -81
- package/dist/factories/providerDescriptors.js +1 -1
- package/dist/factories/providerRegistry.js +4 -1
- package/dist/providers/anthropic/client.js +4 -1
- package/dist/providers/nvidiaNim/client.js +11 -1
- package/dist/providers/openaiChatCompletionsBase.js +4 -1
- package/dist/utils/modelChoices.js +1 -1
- package/dist/utils/pricing.js +8 -0
- package/package.json +1 -1
- package/dist/core/modules/GenerationHandler.d.ts +0 -145
- package/dist/core/modules/GenerationHandler.js +0 -754
|
@@ -644,6 +644,7 @@ export declare enum DeepSeekModels {
|
|
|
644
644
|
* Note: NIM hosts hundreds of models; pass arbitrary IDs via --model.
|
|
645
645
|
*/
|
|
646
646
|
export declare enum NvidiaNimModels {
|
|
647
|
+
GPT_OSS_20B = "openai/gpt-oss-20b",
|
|
647
648
|
LLAMA_3_3_70B_INSTRUCT = "meta/llama-3.3-70b-instruct",
|
|
648
649
|
LLAMA_3_1_405B_INSTRUCT = "meta/llama-3.1-405b-instruct",
|
|
649
650
|
LLAMA_3_1_70B_INSTRUCT = "meta/llama-3.1-70b-instruct",
|
package/dist/constants/enums.js
CHANGED
|
@@ -872,6 +872,13 @@ export var DeepSeekModels;
|
|
|
872
872
|
*/
|
|
873
873
|
export var NvidiaNimModels;
|
|
874
874
|
(function (NvidiaNimModels) {
|
|
875
|
+
// NVIDIA retired a large part of this list upstream on 2026-08-26 —
|
|
876
|
+
// llama-3.3-70b, llama-3.1-70b, llama-3.2-90b-vision, the deepseek-r1
|
|
877
|
+
// distill and gemma-3-27b all answer "no longer available" now. The members
|
|
878
|
+
// are kept so existing callers still compile, but the provider default
|
|
879
|
+
// below must point at something live: gpt-oss-20b is on the current roster
|
|
880
|
+
// and was probed for text, streaming, tool calling and structured output.
|
|
881
|
+
NvidiaNimModels["GPT_OSS_20B"] = "openai/gpt-oss-20b";
|
|
875
882
|
// Meta Llama
|
|
876
883
|
NvidiaNimModels["LLAMA_3_3_70B_INSTRUCT"] = "meta/llama-3.3-70b-instruct";
|
|
877
884
|
NvidiaNimModels["LLAMA_3_1_405B_INSTRUCT"] = "meta/llama-3.1-405b-instruct";
|
|
@@ -22,7 +22,6 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
22
22
|
} | null): void;
|
|
23
23
|
private messageBuilder;
|
|
24
24
|
private streamHandler;
|
|
25
|
-
private generationHandler;
|
|
26
25
|
protected telemetryHandler: TelemetryHandler;
|
|
27
26
|
private utilities;
|
|
28
27
|
private readonly toolsManager;
|
|
@@ -185,30 +184,10 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
185
184
|
* @returns Promise resolving to ModelMessage array ready for AI SDK
|
|
186
185
|
*/
|
|
187
186
|
protected buildMessagesForStream(options: StreamOptions | TextGenerationOptions): Promise<ModelMessage[]>;
|
|
188
|
-
/**
|
|
189
|
-
* Execute the generation with AI SDK - delegated to GenerationHandler
|
|
190
|
-
*/
|
|
191
|
-
private executeGeneration;
|
|
192
|
-
/**
|
|
193
|
-
* Log generation completion information - delegated to GenerationHandler
|
|
194
|
-
*/
|
|
195
|
-
private logGenerationComplete;
|
|
196
187
|
/**
|
|
197
188
|
* Record performance metrics - delegated to TelemetryHandler
|
|
198
189
|
*/
|
|
199
190
|
protected recordPerformanceMetrics(usage: RawUsageObject | undefined, responseTime: number): Promise<void>;
|
|
200
|
-
/**
|
|
201
|
-
* Extract tool information from generation result - delegated to GenerationHandler
|
|
202
|
-
*/
|
|
203
|
-
private extractToolInformation;
|
|
204
|
-
/**
|
|
205
|
-
* Format the enhanced result - delegated to GenerationHandler
|
|
206
|
-
*/
|
|
207
|
-
private formatEnhancedResult;
|
|
208
|
-
/**
|
|
209
|
-
* Analyze AI response structure and log detailed debugging information - delegated to GenerationHandler
|
|
210
|
-
*/
|
|
211
|
-
private analyzeAIResponse;
|
|
212
191
|
/**
|
|
213
192
|
* Text generation method - implements AIProvider interface
|
|
214
193
|
* Tools are always available unless explicitly disabled
|
|
@@ -281,7 +260,6 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
281
260
|
private runGenerateInActiveContext;
|
|
282
261
|
protected handleDirectTTSSynthesis(options: TextGenerationOptions, startTime: number): Promise<EnhancedGenerateResult>;
|
|
283
262
|
private handleVideoFrameGeneration;
|
|
284
|
-
private executeStandardGenerateFlow;
|
|
285
263
|
/**
|
|
286
264
|
* Close out a turn produced by a provider's own native generate loop.
|
|
287
265
|
*
|
|
@@ -32,14 +32,13 @@ import { TimeoutError as AsyncTimeoutError, withTimeoutFn, } from "../utils/asyn
|
|
|
32
32
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
33
33
|
import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
|
|
34
34
|
import { getKeyCount, getKeysAsString } from "../utils/transformationUtils.js";
|
|
35
|
-
import { ToolExecutionRecorder
|
|
35
|
+
import { ToolExecutionRecorder } from "./toolExecutionRecorder.js";
|
|
36
36
|
import { TTS_ERROR_CODES, TTSProcessor } from "../utils/ttsProcessor.js";
|
|
37
37
|
import { executeVideoAnalysis, hasVideoFrames, } from "../utils/videoAnalysisProcessor.js";
|
|
38
38
|
import { dedupeTools } from "./toolDedup.js";
|
|
39
39
|
import { resolveToolPolicy, toolNameMatcher } from "../tools/toolPolicy.js";
|
|
40
40
|
import { applyToolGate } from "../tools/toolGate.js";
|
|
41
41
|
import { partitionToolsForDiscovery, isDiscoveryMetaTool, LARGE_CATALOG_WARN_THRESHOLD, } from "../tools/toolDiscovery.js";
|
|
42
|
-
import { GenerationHandler } from "./modules/GenerationHandler.js";
|
|
43
42
|
// Import modules for composition
|
|
44
43
|
import { MessageBuilder } from "./modules/MessageBuilder.js";
|
|
45
44
|
import { StreamHandler } from "./modules/StreamHandler.js";
|
|
@@ -137,7 +136,6 @@ export class BaseProvider {
|
|
|
137
136
|
// alone.
|
|
138
137
|
messageBuilder;
|
|
139
138
|
streamHandler;
|
|
140
|
-
generationHandler;
|
|
141
139
|
telemetryHandler;
|
|
142
140
|
utilities;
|
|
143
141
|
toolsManager;
|
|
@@ -150,7 +148,6 @@ export class BaseProvider {
|
|
|
150
148
|
this.messageBuilder = new MessageBuilder(this.providerName, this.modelName);
|
|
151
149
|
this.streamHandler = new StreamHandler(this.providerName, this.modelName);
|
|
152
150
|
this.telemetryHandler = new TelemetryHandler(this.providerName, this.modelName, this.neurolink);
|
|
153
|
-
this.generationHandler = new GenerationHandler(this.providerName, this.modelName, () => this.supportsTools(), (options, type) => this.telemetryHandler.getTelemetryConfig(options, type), (toolCalls, toolResults, options, timestamp) => this.handleToolExecutionStorage(toolCalls, toolResults, options, timestamp), { getEmitterFn: () => this.neurolink?.getEventEmitter() });
|
|
154
151
|
this.utilities = new Utilities(this.providerName, this.modelName, this.defaultTimeout, this.middlewareOptions);
|
|
155
152
|
this.toolsManager = new ToolsManager(this.providerName, this.directTools, this.neurolink, {
|
|
156
153
|
isZodSchema: (schema) => this.isZodSchema(schema),
|
|
@@ -175,7 +172,6 @@ export class BaseProvider {
|
|
|
175
172
|
this.messageBuilder = new MessageBuilder(this.providerName, this.modelName);
|
|
176
173
|
this.streamHandler = new StreamHandler(this.providerName, this.modelName);
|
|
177
174
|
this.telemetryHandler = new TelemetryHandler(this.providerName, this.modelName, this.neurolink);
|
|
178
|
-
this.generationHandler = new GenerationHandler(this.providerName, this.modelName, () => this.supportsTools(), (options, type) => this.telemetryHandler.getTelemetryConfig(options, type), (toolCalls, toolResults, options, timestamp) => this.handleToolExecutionStorage(toolCalls, toolResults, options, timestamp), { getEmitterFn: () => this.neurolink?.getEventEmitter() });
|
|
179
175
|
this.utilities = new Utilities(this.providerName, this.modelName, this.defaultTimeout, this.middlewareOptions);
|
|
180
176
|
}
|
|
181
177
|
/**
|
|
@@ -1202,42 +1198,12 @@ export class BaseProvider {
|
|
|
1202
1198
|
async buildMessagesForStream(options) {
|
|
1203
1199
|
return this.messageBuilder.buildMessagesForStream(options);
|
|
1204
1200
|
}
|
|
1205
|
-
/**
|
|
1206
|
-
* Execute the generation with AI SDK - delegated to GenerationHandler
|
|
1207
|
-
*/
|
|
1208
|
-
async executeGeneration(model, messages, tools, options) {
|
|
1209
|
-
return this.generationHandler.executeGeneration(model, messages, tools, options);
|
|
1210
|
-
}
|
|
1211
|
-
/**
|
|
1212
|
-
* Log generation completion information - delegated to GenerationHandler
|
|
1213
|
-
*/
|
|
1214
|
-
logGenerationComplete(generateResult) {
|
|
1215
|
-
this.generationHandler.logGenerationComplete(generateResult);
|
|
1216
|
-
}
|
|
1217
1201
|
/**
|
|
1218
1202
|
* Record performance metrics - delegated to TelemetryHandler
|
|
1219
1203
|
*/
|
|
1220
1204
|
async recordPerformanceMetrics(usage, responseTime) {
|
|
1221
1205
|
await this.telemetryHandler.recordPerformanceMetrics(usage, responseTime);
|
|
1222
1206
|
}
|
|
1223
|
-
/**
|
|
1224
|
-
* Extract tool information from generation result - delegated to GenerationHandler
|
|
1225
|
-
*/
|
|
1226
|
-
extractToolInformation(generateResult) {
|
|
1227
|
-
return this.generationHandler.extractToolInformation(generateResult);
|
|
1228
|
-
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Format the enhanced result - delegated to GenerationHandler
|
|
1231
|
-
*/
|
|
1232
|
-
formatEnhancedResult(generateResult, tools, toolsUsed, toolExecutions, options) {
|
|
1233
|
-
return this.generationHandler.formatEnhancedResult(generateResult, tools, toolsUsed, toolExecutions, options);
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Analyze AI response structure and log detailed debugging information - delegated to GenerationHandler
|
|
1237
|
-
*/
|
|
1238
|
-
analyzeAIResponse(result) {
|
|
1239
|
-
this.generationHandler.analyzeAIResponse(result);
|
|
1240
|
-
}
|
|
1241
1207
|
/**
|
|
1242
1208
|
* Text generation method - implements AIProvider interface
|
|
1243
1209
|
* Tools are always available unless explicitly disabled
|
|
@@ -1398,13 +1364,28 @@ export class BaseProvider {
|
|
|
1398
1364
|
if (requestKind === "tts-direct") {
|
|
1399
1365
|
return this.handleDirectTTSSynthesis(options, startTime);
|
|
1400
1366
|
}
|
|
1401
|
-
|
|
1367
|
+
// Only `model` is used now — the video-frame path needs it. `tools`
|
|
1368
|
+
// fed the standard generate flow, which no longer exists.
|
|
1369
|
+
const { model } = await this.prepareGenerationContext(options);
|
|
1402
1370
|
const messages = await this.buildMessages(options);
|
|
1403
1371
|
const videoFrameResult = await this.handleVideoFrameGeneration(options, messages, model, startTime);
|
|
1404
1372
|
if (videoFrameResult) {
|
|
1405
1373
|
return videoFrameResult;
|
|
1406
1374
|
}
|
|
1407
|
-
|
|
1375
|
+
// Every provider that generates text overrides `generate()` and runs a
|
|
1376
|
+
// native loop. There is no shared fallback any more: the standard flow
|
|
1377
|
+
// called the ai package's `generateText`, and once that was gone the
|
|
1378
|
+
// flow could only throw. Reaching here means a provider was asked for
|
|
1379
|
+
// text without implementing it — an image or embedding provider handed
|
|
1380
|
+
// a text model, or a new subclass with no `generate()` yet.
|
|
1381
|
+
throw new NeuroLinkError({
|
|
1382
|
+
code: ERROR_CODES.INVALID_CONFIGURATION,
|
|
1383
|
+
message: `${this.providerName} cannot generate text: it does not override generate(). Every text provider implements a native generate() — see docs/plans/2026-09-03-completing-the-ai-sdk-removal.md`,
|
|
1384
|
+
category: ErrorCategory.CONFIGURATION,
|
|
1385
|
+
severity: ErrorSeverity.CRITICAL,
|
|
1386
|
+
retriable: false,
|
|
1387
|
+
context: { provider: this.providerName, model: this.modelName },
|
|
1388
|
+
});
|
|
1408
1389
|
}
|
|
1409
1390
|
catch (error) {
|
|
1410
1391
|
otelSpan.setStatus({
|
|
@@ -1537,50 +1518,6 @@ export class BaseProvider {
|
|
|
1537
1518
|
usage,
|
|
1538
1519
|
}, options, startTime);
|
|
1539
1520
|
}
|
|
1540
|
-
async executeStandardGenerateFlow(options, startTime, model, messages, tools) {
|
|
1541
|
-
// Apply a defensive default timeout when the caller didn't pass one.
|
|
1542
|
-
// Without this guard, AI SDK's generateText() will wait forever on
|
|
1543
|
-
// an upstream that accepts the connection but never produces a response
|
|
1544
|
-
// (observed against the litellm gateway when a request triggers the
|
|
1545
|
-
// team-access denial path — connection stays open, no response is sent,
|
|
1546
|
-
// and the matrix test hangs the entire suite). Callers can still pass
|
|
1547
|
-
// a larger value (e.g. video generation passes 10 min).
|
|
1548
|
-
//
|
|
1549
|
-
// A provider descriptor may declare a LARGER generate budget than the
|
|
1550
|
-
// 3-min floor (litellm: 300s — slow proxied models routinely need more
|
|
1551
|
-
// than 180s end-to-end even while streaming). The declared value only
|
|
1552
|
-
// ever raises the default, never lowers it: several descriptors carry
|
|
1553
|
-
// aspirational sub-180s numbers (openai 30s, bedrock 45s) that were
|
|
1554
|
-
// never enforced on this path, and enforcing them now would break
|
|
1555
|
-
// long-running generations that have always been allowed.
|
|
1556
|
-
const descriptorGenerateMs = PROVIDER_DESCRIPTORS_BY_NAME.get(this.providerName)?.timeouts?.generateMs;
|
|
1557
|
-
// An explicit, valid turnTimeoutMs is the caller's whole-turn contract
|
|
1558
|
-
// and owns this hard abort; `timeout` then keeps its per-model-call
|
|
1559
|
-
// meaning (it reaches the model layer via providerOptions.neurolink).
|
|
1560
|
-
// Before this, `timeout` alone bounded the ENTIRE multi-step loop, so a
|
|
1561
|
-
// caller asking for a 40-minute turn of 5-minute calls was killed at 5
|
|
1562
|
-
// minutes flat — mid-loop, dressed as "Request was aborted.".
|
|
1563
|
-
const generateResult = await this.withTurnTimeout(options, descriptorGenerateMs, (timedOptions) => this.executeGeneration(model, messages, tools, timedOptions));
|
|
1564
|
-
this.analyzeAIResponse(generateResult);
|
|
1565
|
-
this.logGenerationComplete(generateResult);
|
|
1566
|
-
const responseTime = Date.now() - startTime;
|
|
1567
|
-
const { toolsUsed, toolExecutions } = this.extractToolInformation(generateResult);
|
|
1568
|
-
// Prefer the per-call recorder's real records (params/result/timing per
|
|
1569
|
-
// execution); fall back to a conversion of the step-extraction entries
|
|
1570
|
-
// for tools the recorder could not wrap (provider-executed tools).
|
|
1571
|
-
const toolExecutionRecords = resolveToolExecutionRecords(options, toolExecutions);
|
|
1572
|
-
let enhancedResult = this.formatEnhancedResult(generateResult, tools, toolsUsed, toolExecutionRecords, options);
|
|
1573
|
-
// Recorded AFTER formatEnhancedResult so telemetry sees the same usage
|
|
1574
|
-
// the caller gets: the cross-step aggregate (totalUsage, not last-step
|
|
1575
|
-
// usage) WITH the providerMetadata cache merge applied — otherwise
|
|
1576
|
-
// providers whose cache data lives only in providerMetadata would have
|
|
1577
|
-
// their cache tokens billed at the full input rate in OTEL metrics,
|
|
1578
|
-
// diverging from analytics.cost.
|
|
1579
|
-
await this.recordPerformanceMetrics(enhancedResult.usage, responseTime);
|
|
1580
|
-
enhancedResult = await this.synthesizeAIResponseIfNeeded(enhancedResult, options);
|
|
1581
|
-
const finalResult = await this.enhanceResult(enhancedResult, options, startTime);
|
|
1582
|
-
return finalResult;
|
|
1583
|
-
}
|
|
1584
1521
|
/**
|
|
1585
1522
|
* Close out a turn produced by a provider's own native generate loop.
|
|
1586
1523
|
*
|
|
@@ -321,7 +321,7 @@ const HAND_DESCRIPTORS = [
|
|
|
321
321
|
baseURL: "NVIDIA_NIM_BASE_URL",
|
|
322
322
|
model: "NVIDIA_NIM_MODEL",
|
|
323
323
|
},
|
|
324
|
-
defaultModel: NvidiaNimModels.
|
|
324
|
+
defaultModel: NvidiaNimModels.GPT_OSS_20B,
|
|
325
325
|
toolSupport: "native",
|
|
326
326
|
localRuntime: false,
|
|
327
327
|
healthCheck: "env-only",
|
|
@@ -174,7 +174,10 @@ export class ProviderRegistry {
|
|
|
174
174
|
const nimCreds = credentials;
|
|
175
175
|
const { NvidiaNimProvider } = await import("../providers/nvidiaNim/index.js");
|
|
176
176
|
return new NvidiaNimProvider(modelName, sdk, undefined, nimCreds);
|
|
177
|
-
}, process.env.NVIDIA_NIM_MODEL ||
|
|
177
|
+
}, process.env.NVIDIA_NIM_MODEL ||
|
|
178
|
+
PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.NVIDIA_NIM)
|
|
179
|
+
?.defaultModel ||
|
|
180
|
+
NvidiaNimModels.GPT_OSS_20B, ["nvidia", "nim", "nvidia-nim"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.NVIDIA_NIM));
|
|
178
181
|
// Register LM Studio provider (local)
|
|
179
182
|
ProviderFactory.registerProvider(AIProviderName.LM_STUDIO, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
180
183
|
const lmStudioCreds = credentials;
|
|
@@ -1280,7 +1280,10 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1280
1280
|
};
|
|
1281
1281
|
},
|
|
1282
1282
|
doStream: () => {
|
|
1283
|
-
throw new Error(`${providerName}: doStream is not implemented on the delegating model
|
|
1283
|
+
throw new Error(`${providerName}: doStream is not implemented on the delegating model. ` +
|
|
1284
|
+
`NeuroLink streams through executeStream, reached via NeuroLink.stream() — ` +
|
|
1285
|
+
`use that (the browser bundle exports the NeuroLink class) rather than ` +
|
|
1286
|
+
`calling doStream on a model handle.`);
|
|
1284
1287
|
},
|
|
1285
1288
|
};
|
|
1286
1289
|
return delegatingModel;
|
|
@@ -5,6 +5,7 @@ import { logger } from "../../utils/logger.js";
|
|
|
5
5
|
import { redactUrlCredentials } from "../../utils/logSanitize.js";
|
|
6
6
|
import { createNvidiaNimConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
7
7
|
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
8
|
+
import { PROVIDER_DESCRIPTORS_BY_NAME } from "../../factories/providerDescriptors.js";
|
|
8
9
|
/**
|
|
9
10
|
* Decide whether a NIM 400 response body is a rejection of the named
|
|
10
11
|
* field (as opposed to an unrelated 400 that happens to mention the
|
|
@@ -136,7 +137,16 @@ const getNimApiKey = () => {
|
|
|
136
137
|
return validateApiKey(createNvidiaNimConfig());
|
|
137
138
|
};
|
|
138
139
|
const getDefaultNimModel = () => {
|
|
139
|
-
|
|
140
|
+
// NVIDIA retired meta/llama-3.3-70b-instruct upstream on 2026-08-26, so this
|
|
141
|
+
// fallback answered "no longer available" for anyone who selected nvidia-nim
|
|
142
|
+
// without naming a model. gpt-oss-20b is on the current roster and was
|
|
143
|
+
// probed for text, streaming, tool calling and structured output.
|
|
144
|
+
// Read the descriptor rather than repeating the literal. Review on this PR
|
|
145
|
+
// pointed out the default lived in four places and that changing only some
|
|
146
|
+
// of them is a no-op — which happened twice while tracking this down. The
|
|
147
|
+
// descriptor is the Factory+Registry convention's source of truth.
|
|
148
|
+
return getProviderModel("NVIDIA_NIM_MODEL", PROVIDER_DESCRIPTORS_BY_NAME.get("nvidia-nim")
|
|
149
|
+
?.defaultModel ?? NvidiaNimModels.GPT_OSS_20B);
|
|
140
150
|
};
|
|
141
151
|
/**
|
|
142
152
|
* NVIDIA NIM Provider — native HTTP+SSE, no AI SDK.
|
|
@@ -784,7 +784,10 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
784
784
|
};
|
|
785
785
|
},
|
|
786
786
|
doStream: () => {
|
|
787
|
-
throw new Error(`${providerName}: doStream is not implemented on the delegating model
|
|
787
|
+
throw new Error(`${providerName}: doStream is not implemented on the delegating model. ` +
|
|
788
|
+
`NeuroLink streams through executeStream, reached via NeuroLink.stream() — ` +
|
|
789
|
+
`use that (the browser bundle exports the NeuroLink class) rather than ` +
|
|
790
|
+
`calling doStream on a model handle.`);
|
|
788
791
|
},
|
|
789
792
|
};
|
|
790
793
|
}
|
|
@@ -420,7 +420,7 @@ export const DEFAULT_MODELS = {
|
|
|
420
420
|
[AIProviderName.OPENROUTER]: OpenRouterModels.CLAUDE_SONNET_4_5,
|
|
421
421
|
[AIProviderName.OPENAI_COMPATIBLE]: "gpt-4o",
|
|
422
422
|
[AIProviderName.DEEPSEEK]: DeepSeekModels.DEEPSEEK_CHAT,
|
|
423
|
-
[AIProviderName.NVIDIA_NIM]: NvidiaNimModels.
|
|
423
|
+
[AIProviderName.NVIDIA_NIM]: NvidiaNimModels.GPT_OSS_20B,
|
|
424
424
|
// LM Studio + llama.cpp auto-discover their loaded model from /v1/models;
|
|
425
425
|
// an empty default is the documented signal to use that path.
|
|
426
426
|
[AIProviderName.LM_STUDIO]: "",
|
package/dist/utils/pricing.js
CHANGED
|
@@ -500,6 +500,14 @@ const PRICING = {
|
|
|
500
500
|
},
|
|
501
501
|
},
|
|
502
502
|
"nvidia-nim": {
|
|
503
|
+
// Source: NVIDIA build.nvidia.com listed rates for openai/gpt-oss-20b,
|
|
504
|
+
// read 2026-09-06. NIM prices and models both rot — this PR exists
|
|
505
|
+
// because the default model was decommissioned — so re-check against
|
|
506
|
+
// https://build.nvidia.com/openai/gpt-oss-20b rather than trusting this.
|
|
507
|
+
"openai/gpt-oss-20b": {
|
|
508
|
+
input: 0.05 / 1_000_000,
|
|
509
|
+
output: 0.2 / 1_000_000,
|
|
510
|
+
},
|
|
503
511
|
"meta/llama-3.3-70b-instruct": {
|
|
504
512
|
input: 0.4 / 1_000_000,
|
|
505
513
|
output: 0.4 / 1_000_000,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.12.
|
|
3
|
+
"version": "12.12.12",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generation Handler Module
|
|
3
|
-
*
|
|
4
|
-
* Handles text generation execution, result formatting, and tool information extraction.
|
|
5
|
-
* Extracted from BaseProvider to follow Single Responsibility Principle.
|
|
6
|
-
*
|
|
7
|
-
* Responsibilities:
|
|
8
|
-
* - Generation execution with AI SDK
|
|
9
|
-
* - Tool information extraction
|
|
10
|
-
* - Result formatting and enhancement
|
|
11
|
-
* - Response analysis and logging
|
|
12
|
-
*
|
|
13
|
-
* @module core/modules/GenerationHandler
|
|
14
|
-
*/
|
|
15
|
-
import type { GenerateTextResult, AIProviderName, EnhancedGenerateResult, NeuroLinkEvents, StandardRecord, TextGenerationOptions, ToolExecutionRecord, TypedEventEmitter } from "../../types/index.js";
|
|
16
|
-
import type { LanguageModel, ModelMessage, Tool } from "../../types/index.js";
|
|
17
|
-
/**
|
|
18
|
-
* Turn budget + wrap-up deadline (parity with the googleVertex native loops).
|
|
19
|
-
* A deadline is engaged only when the caller expressed one: turnTimeoutMs
|
|
20
|
-
* wins, else an explicit generate timeout. Callers that set neither keep the
|
|
21
|
-
* pre-existing behaviour (no wrap-up; the outer defensive timeout in
|
|
22
|
-
* executeStandardGenerateFlow still applies). With `wrapupTimeLeadMs` left of
|
|
23
|
-
* the deadline, the loop stops offering tools (toolChoice: "none") so the
|
|
24
|
-
* model spends the remaining budget producing a final answer instead of being
|
|
25
|
-
* guillotined mid-tool-loop with all work discarded. The lead is clamped to a
|
|
26
|
-
* quarter of the budget so short explicit timeouts (e.g. 30s) don't trigger
|
|
27
|
-
* wrap-up on the very first step.
|
|
28
|
-
*
|
|
29
|
-
* `turnStartMs` anchors the deadline to the ORIGINAL generation start:
|
|
30
|
-
* callGenerateText re-runs on executeGeneration's fallback retries
|
|
31
|
-
* (structured-output conflict, temperature-deprecated) and provider retries,
|
|
32
|
-
* and a deadline computed from Date.now() per attempt would hand each retry
|
|
33
|
-
* a fresh budget — multiplying the caller's wall-clock cap.
|
|
34
|
-
*/
|
|
35
|
-
export declare function resolveTurnBudget(options: TextGenerationOptions, turnStartMs: number): {
|
|
36
|
-
callerTimeoutMs: number | undefined;
|
|
37
|
-
turnBudgetMs: number | undefined;
|
|
38
|
-
wrapupLeadMs: number;
|
|
39
|
-
turnDeadline: number | undefined;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* GenerationHandler class - Handles text generation operations for AI providers
|
|
43
|
-
*/
|
|
44
|
-
export declare class GenerationHandler {
|
|
45
|
-
private readonly providerName;
|
|
46
|
-
private readonly modelName;
|
|
47
|
-
private readonly supportsToolsFn;
|
|
48
|
-
private readonly getTelemetryConfigFn;
|
|
49
|
-
private readonly handleToolStorageFn;
|
|
50
|
-
/**
|
|
51
|
-
* The remaining, optional dependencies.
|
|
52
|
-
*
|
|
53
|
-
* Grouped rather than added as further positional parameters: the
|
|
54
|
-
* constructor is already at the six-parameter cap, and both of these are
|
|
55
|
-
* optional injection seams rather than required collaborators.
|
|
56
|
-
*
|
|
57
|
-
* `generateTextFn` exists because every other dependency of this class
|
|
58
|
-
* arrives through the constructor while `generateText` was reached by
|
|
59
|
-
* static import. `utils/generation.ts` is a bare re-export of `ai`, and an
|
|
60
|
-
* ESM re-export cannot be substituted from a test, so asserting on the
|
|
61
|
-
* arguments this class builds — the entire contract of the system-message
|
|
62
|
-
* hoisting below — had no seam to work through. Production passes neither.
|
|
63
|
-
*/
|
|
64
|
-
private readonly deps;
|
|
65
|
-
constructor(providerName: AIProviderName, modelName: string, supportsToolsFn: () => boolean, getTelemetryConfigFn: (options: TextGenerationOptions, type: string) => {
|
|
66
|
-
isEnabled: boolean;
|
|
67
|
-
functionId?: string;
|
|
68
|
-
metadata?: Record<string, string | number | boolean>;
|
|
69
|
-
} | undefined, handleToolStorageFn: (toolCalls: unknown[], toolResults: unknown[], options: TextGenerationOptions, timestamp: Date) => Promise<void>,
|
|
70
|
-
/**
|
|
71
|
-
* The remaining, optional dependencies.
|
|
72
|
-
*
|
|
73
|
-
* Grouped rather than added as further positional parameters: the
|
|
74
|
-
* constructor is already at the six-parameter cap, and both of these are
|
|
75
|
-
* optional injection seams rather than required collaborators.
|
|
76
|
-
*
|
|
77
|
-
* `generateTextFn` exists because every other dependency of this class
|
|
78
|
-
* arrives through the constructor while `generateText` was reached by
|
|
79
|
-
* static import. `utils/generation.ts` is a bare re-export of `ai`, and an
|
|
80
|
-
* ESM re-export cannot be substituted from a test, so asserting on the
|
|
81
|
-
* arguments this class builds — the entire contract of the system-message
|
|
82
|
-
* hoisting below — had no seam to work through. Production passes neither.
|
|
83
|
-
*/
|
|
84
|
-
deps?: {
|
|
85
|
-
getEmitterFn?: () => TypedEventEmitter<NeuroLinkEvents> | undefined;
|
|
86
|
-
generateTextFn?: (options: Record<string, unknown>) => Promise<GenerateTextResult<Record<string, Tool>, unknown>>;
|
|
87
|
-
});
|
|
88
|
-
/**
|
|
89
|
-
* Helper method to call generateText with optional structured output
|
|
90
|
-
* @private
|
|
91
|
-
*/
|
|
92
|
-
/**
|
|
93
|
-
* The ai-package generate loop.
|
|
94
|
-
*
|
|
95
|
-
* Unreachable: every text provider now implements a native generate() and
|
|
96
|
-
* none of them return here. That was established by trapping the seam —
|
|
97
|
-
* replacing the ai package's generateText with a throwing stub left the full
|
|
98
|
-
* provider matrix passing and zero cells reaching it — and non-text request
|
|
99
|
-
* kinds return from runGenerateInActiveContext before this handler is
|
|
100
|
-
* consulted.
|
|
101
|
-
*
|
|
102
|
-
* Kept as an explicit failure rather than deleted outright so a provider
|
|
103
|
-
* added without a native generate() fails loudly here instead of silently
|
|
104
|
-
* reintroducing a dependency on the removed package.
|
|
105
|
-
*/
|
|
106
|
-
private callGenerateText;
|
|
107
|
-
executeGeneration(model: LanguageModel, messages: ModelMessage[], tools: Record<string, Tool>, options: TextGenerationOptions): Promise<GenerateTextResult<Record<string, Tool>, unknown>>;
|
|
108
|
-
/**
|
|
109
|
-
* Extract cache metrics from provider metadata (e.g. Anthropic's providerMetadata.anthropic)
|
|
110
|
-
* The AI SDK's LanguageModelUsage only has inputTokens/outputTokens.
|
|
111
|
-
* Cache metrics are surfaced via providerMetadata by provider-specific SDK adapters.
|
|
112
|
-
*/
|
|
113
|
-
/**
|
|
114
|
-
* Set gen_ai usage attributes + cache-aware cost on the span from the
|
|
115
|
-
* CROSS-STEP aggregate (result.totalUsage). result.usage is the LAST step
|
|
116
|
-
* only — using it undercounted every multi-step tool loop, and pricing the
|
|
117
|
-
* raw cache-inclusive inputTokens without the cache fields billed cache
|
|
118
|
-
* reads at the full input rate.
|
|
119
|
-
*/
|
|
120
|
-
private setUsageSpanAttributes;
|
|
121
|
-
private extractCacheMetricsFromProviderMetadata;
|
|
122
|
-
/**
|
|
123
|
-
* Log generation completion information
|
|
124
|
-
*/
|
|
125
|
-
logGenerationComplete(generateResult: GenerateTextResult<Record<string, Tool>, unknown>): void;
|
|
126
|
-
/**
|
|
127
|
-
* Extract tool information from generation result
|
|
128
|
-
*/
|
|
129
|
-
extractToolInformation(generateResult: GenerateTextResult<Record<string, Tool>, unknown>): {
|
|
130
|
-
toolsUsed: string[];
|
|
131
|
-
toolExecutions: Array<{
|
|
132
|
-
name: string;
|
|
133
|
-
input: StandardRecord;
|
|
134
|
-
output: unknown;
|
|
135
|
-
}>;
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* Format the enhanced result
|
|
139
|
-
*/
|
|
140
|
-
formatEnhancedResult(generateResult: GenerateTextResult<Record<string, Tool>, unknown>, tools: Record<string, Tool>, toolsUsed: string[], toolExecutions: ToolExecutionRecord[], options: TextGenerationOptions): EnhancedGenerateResult;
|
|
141
|
-
/**
|
|
142
|
-
* Analyze AI response structure and log detailed debugging information
|
|
143
|
-
*/
|
|
144
|
-
analyzeAIResponse(rawResult: unknown): void;
|
|
145
|
-
}
|