@juspay/neurolink 12.49.17 → 12.49.18
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/agent/agent.js +21 -0
- package/dist/browser/neurolink.min.js +277 -277
- package/dist/core/analytics.js +3 -18
- package/dist/core/evaluationProviders.d.ts +2 -7
- package/dist/core/evaluationProviders.js +1 -1
- package/dist/core/modules/TelemetryHandler.d.ts +3 -11
- package/dist/core/modules/TelemetryHandler.js +6 -29
- package/dist/types/agentNetwork.d.ts +8 -0
- package/dist/types/evaluationProviders.d.ts +6 -0
- package/dist/utils/pricing.js +16 -1
- package/package.json +2 -1
package/dist/core/analytics.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* including tokens, costs, performance metrics, and custom context.
|
|
6
6
|
*/
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
|
-
import { modelConfig } from "./modelConfiguration.js";
|
|
9
8
|
import { extractTokenUsage as extractTokenUsageUtil } from "../utils/tokenUtils.js";
|
|
10
9
|
import { calculateCost, hasPricing } from "../utils/pricing.js";
|
|
11
10
|
/**
|
|
@@ -84,8 +83,8 @@ function extractTokenUsage(result) {
|
|
|
84
83
|
}
|
|
85
84
|
/**
|
|
86
85
|
* Estimate cost based on provider, model, and token usage.
|
|
87
|
-
* Uses
|
|
88
|
-
*
|
|
86
|
+
* Uses known per-model rates, including cache tiers. An unpriced model has
|
|
87
|
+
* unknown cost; another model's provider default cannot estimate its bill.
|
|
89
88
|
*/
|
|
90
89
|
function estimateCost(provider, model, tokens) {
|
|
91
90
|
try {
|
|
@@ -93,21 +92,7 @@ function estimateCost(provider, model, tokens) {
|
|
|
93
92
|
if (hasPricing(provider, model)) {
|
|
94
93
|
return calculateCost(provider, model, tokens);
|
|
95
94
|
}
|
|
96
|
-
|
|
97
|
-
const costInfo = modelConfig.getCostInfo(provider.toLowerCase(), model);
|
|
98
|
-
if (!costInfo) {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
// Calculate cost using the configuration system (per-1K-token rates).
|
|
102
|
-
// costInfo has no cache tiers, so cache tokens are billed at the input
|
|
103
|
-
// rate — the pre-split total a cache-blind provider would report, never $0.
|
|
104
|
-
const inputCost = ((tokens.input +
|
|
105
|
-
(tokens.cacheReadTokens ?? 0) +
|
|
106
|
-
(tokens.cacheCreationTokens ?? 0)) /
|
|
107
|
-
1000) *
|
|
108
|
-
costInfo.input;
|
|
109
|
-
const outputCost = (tokens.output / 1000) * costInfo.output;
|
|
110
|
-
return Math.round((inputCost + outputCost) * 1_000_000) / 1_000_000; // Round to 6 decimal places
|
|
95
|
+
return undefined;
|
|
111
96
|
}
|
|
112
97
|
catch (error) {
|
|
113
98
|
logger.debug("Cost estimation failed", { provider, model, error });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ProviderModelConfig } from "../types/index.js";
|
|
1
|
+
import type { ProviderModelConfig, ProviderPerformanceSample } from "../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Dynamic provider configurations for evaluation
|
|
4
4
|
* Now uses configurable system instead of hardcoded values
|
|
@@ -35,12 +35,7 @@ export declare function getBestAvailableProvider(preferCheap?: boolean): Provide
|
|
|
35
35
|
/**
|
|
36
36
|
* Record actual provider performance for optimization
|
|
37
37
|
*/
|
|
38
|
-
export declare function recordProviderPerformanceFromMetrics(providerName: string, metrics:
|
|
39
|
-
responseTime: number;
|
|
40
|
-
tokensGenerated: number;
|
|
41
|
-
cost: number;
|
|
42
|
-
success: boolean;
|
|
43
|
-
}): void;
|
|
38
|
+
export declare function recordProviderPerformanceFromMetrics(providerName: string, metrics: ProviderPerformanceSample): void;
|
|
44
39
|
/**
|
|
45
40
|
* Get performance-optimized provider based on real metrics
|
|
46
41
|
*/
|
|
@@ -142,7 +142,7 @@ export function recordProviderPerformanceFromMetrics(providerName, metrics) {
|
|
|
142
142
|
// If responseTime is 0, skip updating tokenThroughput for this sample
|
|
143
143
|
// but still update other metrics
|
|
144
144
|
// Update cost efficiency (tokens per dollar)
|
|
145
|
-
if (metrics.cost > 0) {
|
|
145
|
+
if (metrics.cost !== undefined && metrics.cost > 0) {
|
|
146
146
|
const tokensPerDollar = metrics.tokensGenerated / metrics.cost;
|
|
147
147
|
existing.costEfficiency =
|
|
148
148
|
(existing.costEfficiency * existing.sampleCount + tokensPerDollar) /
|
|
@@ -40,18 +40,10 @@ export declare class TelemetryHandler {
|
|
|
40
40
|
*/
|
|
41
41
|
recordTTSFailure(ttsProvider: string, error: NonNullable<TTSMetadata["error"]>, latency: number): void;
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* Uses the per-model pricing table first (which has accurate rates for
|
|
46
|
-
* specific models like Claude on Vertex AI), then falls back to the
|
|
47
|
-
* provider-level default cost from modelConfiguration.
|
|
48
|
-
*
|
|
49
|
-
* Previously this only used modelConfig.getCostInfo() which returns
|
|
50
|
-
* provider-level defaults (e.g. Gemini rates for the "vertex" provider),
|
|
51
|
-
* causing a ~1,780x under-estimate when the actual model was Claude Sonnet
|
|
52
|
-
* on Vertex AI ($0.000060 vs $0.106895 for the same request).
|
|
43
|
+
* Estimate cost only from known per-model rates. Unknown pricing remains
|
|
44
|
+
* absent from cost metrics instead of using another model's default rate.
|
|
53
45
|
*/
|
|
54
|
-
calculateActualCost(usage: TokenUsage): Promise<number>;
|
|
46
|
+
calculateActualCost(usage: TokenUsage): Promise<number | undefined>;
|
|
55
47
|
/**
|
|
56
48
|
* Create telemetry configuration for Vercel AI SDK experimental_telemetry
|
|
57
49
|
* This enables automatic OpenTelemetry tracing when telemetry is enabled
|
|
@@ -17,7 +17,6 @@ import { nanoid } from "nanoid";
|
|
|
17
17
|
import { extractTokenUsage } from "../../utils/tokenUtils.js";
|
|
18
18
|
import { logger } from "../../utils/logger.js";
|
|
19
19
|
import { recordProviderPerformanceFromMetrics } from "../evaluationProviders.js";
|
|
20
|
-
import { modelConfig } from "../modelConfiguration.js";
|
|
21
20
|
import { TelemetryService } from "../../telemetry/telemetryService.js";
|
|
22
21
|
import { calculateCost, hasPricing } from "../../utils/pricing.js";
|
|
23
22
|
import { getLangfuseContext } from "../../services/server/ai/observability/instrumentation.js";
|
|
@@ -89,11 +88,11 @@ export class TelemetryHandler {
|
|
|
89
88
|
success: true,
|
|
90
89
|
});
|
|
91
90
|
// Wire TelemetryService metrics so OTEL counters/histograms are populated
|
|
92
|
-
TelemetryService.getInstance().recordAIRequest(this.providerName, this.modelName, totalTokens, responseTime, actualCost > 0 ? actualCost : undefined);
|
|
91
|
+
TelemetryService.getInstance().recordAIRequest(this.providerName, this.modelName, totalTokens, responseTime, actualCost !== undefined && actualCost > 0 ? actualCost : undefined);
|
|
93
92
|
logger.debug(`Performance recorded for ${this.providerName}`, {
|
|
94
93
|
responseTime: `${responseTime}ms`,
|
|
95
94
|
tokens: totalTokens,
|
|
96
|
-
estimatedCost: `$${actualCost.toFixed(6)}`,
|
|
95
|
+
estimatedCost: actualCost === undefined ? "unknown" : `$${actualCost.toFixed(6)}`,
|
|
97
96
|
});
|
|
98
97
|
}
|
|
99
98
|
catch (perfError) {
|
|
@@ -121,16 +120,8 @@ export class TelemetryHandler {
|
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
122
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* Uses the per-model pricing table first (which has accurate rates for
|
|
127
|
-
* specific models like Claude on Vertex AI), then falls back to the
|
|
128
|
-
* provider-level default cost from modelConfiguration.
|
|
129
|
-
*
|
|
130
|
-
* Previously this only used modelConfig.getCostInfo() which returns
|
|
131
|
-
* provider-level defaults (e.g. Gemini rates for the "vertex" provider),
|
|
132
|
-
* causing a ~1,780x under-estimate when the actual model was Claude Sonnet
|
|
133
|
-
* on Vertex AI ($0.000060 vs $0.106895 for the same request).
|
|
123
|
+
* Estimate cost only from known per-model rates. Unknown pricing remains
|
|
124
|
+
* absent from cost metrics instead of using another model's default rate.
|
|
134
125
|
*/
|
|
135
126
|
async calculateActualCost(usage) {
|
|
136
127
|
try {
|
|
@@ -139,25 +130,11 @@ export class TelemetryHandler {
|
|
|
139
130
|
if (hasPricing(this.providerName, this.modelName)) {
|
|
140
131
|
return calculateCost(this.providerName, this.modelName, usage);
|
|
141
132
|
}
|
|
142
|
-
|
|
143
|
-
const costInfo = modelConfig.getCostInfo(this.providerName, this.modelName);
|
|
144
|
-
if (!costInfo) {
|
|
145
|
-
return 0; // No cost info available
|
|
146
|
-
}
|
|
147
|
-
// Calculate cost per 1K tokens. costInfo has no cache tiers, so cache
|
|
148
|
-
// tokens are billed at the input rate — the same total a provider
|
|
149
|
-
// without cache-aware splitting would have reported, never $0.
|
|
150
|
-
const inputCost = ((usage.input +
|
|
151
|
-
(usage.cacheReadTokens ?? 0) +
|
|
152
|
-
(usage.cacheCreationTokens ?? 0)) /
|
|
153
|
-
1000) *
|
|
154
|
-
costInfo.input;
|
|
155
|
-
const outputCost = (usage.output / 1000) * costInfo.output;
|
|
156
|
-
return inputCost + outputCost;
|
|
133
|
+
return undefined;
|
|
157
134
|
}
|
|
158
135
|
catch (error) {
|
|
159
136
|
logger.debug(`Cost calculation failed for ${this.providerName}:`, error);
|
|
160
|
-
return
|
|
137
|
+
return undefined;
|
|
161
138
|
}
|
|
162
139
|
}
|
|
163
140
|
/**
|
|
@@ -49,6 +49,8 @@ export type AgentInput = string | Record<string, unknown>;
|
|
|
49
49
|
* Result of agent execution
|
|
50
50
|
*/
|
|
51
51
|
export type AgentResult = {
|
|
52
|
+
/** SDK estimate in USD; undefined when the model has no known pricing. */
|
|
53
|
+
cost?: number;
|
|
52
54
|
/** Generated content */
|
|
53
55
|
content: string;
|
|
54
56
|
/** Structured output if schema was provided */
|
|
@@ -80,6 +82,10 @@ export type AgentResult = {
|
|
|
80
82
|
* Options for agent execution
|
|
81
83
|
*/
|
|
82
84
|
export type AgentExecutionOptions = {
|
|
85
|
+
/** Enable SDK usage and cost analytics for this execution. */
|
|
86
|
+
enableAnalytics?: boolean;
|
|
87
|
+
/** Cumulative budget for the NeuroLink instance, not a per-run cap. */
|
|
88
|
+
maxBudgetUsd?: number;
|
|
83
89
|
/** Additional context for the agent */
|
|
84
90
|
context?: Record<string, unknown>;
|
|
85
91
|
/** Override max steps for this execution */
|
|
@@ -469,6 +475,8 @@ export type AgentStreamChunkType = "agent-start" | "agent-thinking" | "agent-tex
|
|
|
469
475
|
* Agent stream chunk
|
|
470
476
|
*/
|
|
471
477
|
export type AgentStreamChunk = {
|
|
478
|
+
/** SDK cost estimate in USD (for complete chunks), when priced. */
|
|
479
|
+
cost?: number;
|
|
472
480
|
/** Chunk type */
|
|
473
481
|
type: AgentStreamChunkType;
|
|
474
482
|
/** Agent ID */
|
|
@@ -28,6 +28,12 @@ export type ProviderModelConfig = {
|
|
|
28
28
|
/**
|
|
29
29
|
* Real-time provider performance tracking metrics
|
|
30
30
|
*/
|
|
31
|
+
export type ProviderPerformanceSample = {
|
|
32
|
+
responseTime: number;
|
|
33
|
+
tokensGenerated: number;
|
|
34
|
+
cost?: number;
|
|
35
|
+
success: boolean;
|
|
36
|
+
};
|
|
31
37
|
export type ProviderPerformanceMetrics = {
|
|
32
38
|
responseTime: number[];
|
|
33
39
|
successRate: number;
|
package/dist/utils/pricing.js
CHANGED
|
@@ -283,6 +283,15 @@ const PRICING = {
|
|
|
283
283
|
},
|
|
284
284
|
// Google Vertex AI — Claude models on Vertex (same pricing, @ date suffix)
|
|
285
285
|
vertex: {
|
|
286
|
+
// Standard Sonnet 4 rates; the lookup also recognizes its @ date suffix.
|
|
287
|
+
// https://platform.claude.com/docs/en/about-claude/pricing
|
|
288
|
+
"claude-sonnet-4": {
|
|
289
|
+
input: 3.0 / 1_000_000,
|
|
290
|
+
output: 15.0 / 1_000_000,
|
|
291
|
+
cacheRead: 0.3 / 1_000_000,
|
|
292
|
+
cacheCreation: 3.75 / 1_000_000,
|
|
293
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
294
|
+
},
|
|
286
295
|
// A 1-hour cache write is 2x base input, as on the direct API.
|
|
287
296
|
// Claude 5 family. Absent here until now, so a Vertex leg serving any of
|
|
288
297
|
// them resolved to no rate at all and booked the turn at $0 — on the one
|
|
@@ -527,7 +536,13 @@ const PRICING = {
|
|
|
527
536
|
},
|
|
528
537
|
// Google (Gemini) — updated March 2026
|
|
529
538
|
google: {
|
|
530
|
-
//
|
|
539
|
+
// GA text/image/video rates: https://ai.google.dev/gemini-api/docs/pricing
|
|
540
|
+
"gemini-3.1-flash-lite": {
|
|
541
|
+
input: 0.25 / 1_000_000,
|
|
542
|
+
output: 1.5 / 1_000_000,
|
|
543
|
+
cacheRead: 0.025 / 1_000_000,
|
|
544
|
+
},
|
|
545
|
+
// Gemini 3.1 preview family
|
|
531
546
|
// cacheRead = 0.25x input (cached content tokens; explicit-cache storage is
|
|
532
547
|
// billed separately by TTL/time, so no per-token cacheCreation rate here).
|
|
533
548
|
"gemini-3.1-pro-preview": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.49.
|
|
3
|
+
"version": "12.49.18",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"test:anthropic-silent-truncation": "pnpm exec tsx test/continuous-test-suite-anthropic-silent-truncation.ts",
|
|
108
108
|
"test:anthropic-thinking-disabled": "pnpm exec tsx test/continuous-test-suite-anthropic-thinking-disabled.ts",
|
|
109
109
|
"test:cache-cost-accounting": "pnpm exec tsx test/continuous-test-suite-cache-cost-accounting.ts",
|
|
110
|
+
"test:agent:cost": "pnpm exec tsx test/continuous-test-suite-agent-cost.ts",
|
|
110
111
|
"test:adjust-body-after-400": "pnpm exec tsx test/continuous-test-suite-adjust-body-after-400.ts",
|
|
111
112
|
"test:zod3-schema-native-path": "pnpm exec tsx test/continuous-test-suite-zod3-schema-native-path.ts",
|
|
112
113
|
"test:error-classification-e2e": "pnpm exec tsx test/continuous-test-suite-error-classification-e2e.ts",
|