@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.
@@ -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 the per-model pricing table first (which includes cache token rates),
88
- * then falls back to the provider-level configuration system.
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
- // Fall back to the configuration system for providers/models not in the pricing table
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
- * Calculate actual cost based on token usage and provider configuration.
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
- * Calculate actual cost based on token usage and provider configuration.
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
- // Fall back to provider-level default cost from configuration system
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 0; // Fallback to 0 on any error
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;
@@ -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
- // Gemini 3.1 family (all require -preview suffix)
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.17",
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",