@juspay/neurolink 10.6.4 → 10.7.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 (76) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/analytics/pricing.d.ts +4 -1
  3. package/dist/analytics/pricing.js +6 -2
  4. package/dist/browser/neurolink.min.js +406 -406
  5. package/dist/cli/commands/proxyAnalyze.js +12 -0
  6. package/dist/core/analytics.js +8 -2
  7. package/dist/core/baseProvider.js +9 -7
  8. package/dist/core/modules/GenerationHandler.d.ts +8 -0
  9. package/dist/core/modules/GenerationHandler.js +28 -38
  10. package/dist/core/modules/TelemetryHandler.d.ts +3 -9
  11. package/dist/core/modules/TelemetryHandler.js +17 -12
  12. package/dist/lib/analytics/pricing.d.ts +4 -1
  13. package/dist/lib/analytics/pricing.js +6 -2
  14. package/dist/lib/core/analytics.js +8 -2
  15. package/dist/lib/core/baseProvider.js +9 -7
  16. package/dist/lib/core/modules/GenerationHandler.d.ts +8 -0
  17. package/dist/lib/core/modules/GenerationHandler.js +28 -38
  18. package/dist/lib/core/modules/TelemetryHandler.d.ts +3 -9
  19. package/dist/lib/core/modules/TelemetryHandler.js +17 -12
  20. package/dist/lib/neurolink.js +18 -1
  21. package/dist/lib/providers/amazonBedrock.js +68 -6
  22. package/dist/lib/providers/anthropic.js +50 -16
  23. package/dist/lib/providers/googleAiStudio.js +29 -4
  24. package/dist/lib/providers/googleNativeGemini3.js +10 -0
  25. package/dist/lib/providers/googleVertex.js +150 -25
  26. package/dist/lib/providers/litellm.js +13 -2
  27. package/dist/lib/providers/openAI.js +13 -2
  28. package/dist/lib/providers/openaiChatCompletionsBase.js +45 -10
  29. package/dist/lib/providers/openaiChatCompletionsClient.d.ts +2 -14
  30. package/dist/lib/providers/openaiChatCompletionsClient.js +20 -1
  31. package/dist/lib/providers/sagemaker/language-model.js +5 -3
  32. package/dist/lib/providers/sagemaker/parsers.js +18 -9
  33. package/dist/lib/providers/sagemaker/streaming.d.ts +9 -0
  34. package/dist/lib/providers/sagemaker/streaming.js +64 -6
  35. package/dist/lib/proxy/accountCooldown.js +2 -7
  36. package/dist/lib/proxy/proxyAnalysis.js +197 -0
  37. package/dist/lib/proxy/requestLogger.js +11 -0
  38. package/dist/lib/proxy/routingEvidence.d.ts +6 -0
  39. package/dist/lib/proxy/routingEvidence.js +33 -0
  40. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +2 -1
  41. package/dist/lib/server/routes/claudeProxyRoutes.js +257 -87
  42. package/dist/lib/types/common.d.ts +3 -0
  43. package/dist/lib/types/openaiCompatible.d.ts +8 -7
  44. package/dist/lib/types/providers.d.ts +6 -0
  45. package/dist/lib/types/proxy.d.ts +97 -2
  46. package/dist/lib/utils/pricing.js +15 -3
  47. package/dist/lib/utils/tokenUtils.js +38 -3
  48. package/dist/neurolink.js +18 -1
  49. package/dist/providers/amazonBedrock.js +68 -6
  50. package/dist/providers/anthropic.js +50 -16
  51. package/dist/providers/googleAiStudio.js +29 -4
  52. package/dist/providers/googleNativeGemini3.js +10 -0
  53. package/dist/providers/googleVertex.js +150 -25
  54. package/dist/providers/litellm.js +13 -2
  55. package/dist/providers/openAI.js +13 -2
  56. package/dist/providers/openaiChatCompletionsBase.js +45 -10
  57. package/dist/providers/openaiChatCompletionsClient.d.ts +2 -14
  58. package/dist/providers/openaiChatCompletionsClient.js +20 -1
  59. package/dist/providers/sagemaker/language-model.js +5 -3
  60. package/dist/providers/sagemaker/parsers.js +18 -9
  61. package/dist/providers/sagemaker/streaming.d.ts +9 -0
  62. package/dist/providers/sagemaker/streaming.js +64 -6
  63. package/dist/proxy/accountCooldown.js +2 -7
  64. package/dist/proxy/proxyAnalysis.js +197 -0
  65. package/dist/proxy/requestLogger.js +11 -0
  66. package/dist/proxy/routingEvidence.d.ts +6 -0
  67. package/dist/proxy/routingEvidence.js +32 -0
  68. package/dist/server/routes/claudeProxyRoutes.d.ts +2 -1
  69. package/dist/server/routes/claudeProxyRoutes.js +257 -87
  70. package/dist/types/common.d.ts +3 -0
  71. package/dist/types/openaiCompatible.d.ts +8 -7
  72. package/dist/types/providers.d.ts +6 -0
  73. package/dist/types/proxy.d.ts +97 -2
  74. package/dist/utils/pricing.js +15 -3
  75. package/dist/utils/tokenUtils.js +38 -3
  76. package/package.json +2 -1
@@ -653,15 +653,27 @@ function findRates(provider, model) {
653
653
  if (!providerPricing) {
654
654
  return undefined;
655
655
  }
656
+ // Bedrock model IDs carry region/vendor prefixes ("us.anthropic.claude-…",
657
+ // "global.anthropic.claude-…", "anthropic.claude-…") or arrive as full
658
+ // inference-profile ARNs ("arn:aws:bedrock:…:inference-profile/us.anthropic.
659
+ // claude-…" — the form this repo's own setup guides recommend). None of
660
+ // those match the bare pricing keys ("claude-…"), so every Bedrock call
661
+ // priced to $0. Strip everything up to and including the vendor prefix; the
662
+ // trailing "-v1:0" version suffix is absorbed by the longest-prefix match
663
+ // below. Non-Anthropic Bedrock models (meta./amazon./mistral.) don't match
664
+ // and fall through unchanged, exactly as before.
665
+ const modelKey = stripped === "bedrock" || stripped === "amazonbedrock"
666
+ ? model.replace(/^.*\banthropic\./, "")
667
+ : model;
656
668
  // Exact match
657
- if (providerPricing[model]) {
658
- return providerPricing[model];
669
+ if (providerPricing[modelKey]) {
670
+ return providerPricing[modelKey];
659
671
  }
660
672
  // Longest-prefix match (skip the synthetic "_default" sentinel below)
661
673
  const sortedKeys = Object.keys(providerPricing)
662
674
  .filter((k) => k !== "_default")
663
675
  .sort((a, b) => b.length - a.length);
664
- const key = sortedKeys.find((k) => model.startsWith(k));
676
+ const key = sortedKeys.find((k) => modelKey.startsWith(k));
665
677
  if (key) {
666
678
  return providerPricing[key];
667
679
  }
@@ -44,10 +44,13 @@ export function extractOutputTokens(usage) {
44
44
  * Falls back to input + output if total is not provided
45
45
  */
46
46
  export function extractTotalTokens(usage, input, output) {
47
- if (typeof usage.total === "number") {
47
+ // A literal 0 alongside non-zero components means the provider omitted the
48
+ // figure (several gateways/parsers emit total: 0) — fall through to the
49
+ // computed sum instead of letting the zero win.
50
+ if (typeof usage.total === "number" && usage.total > 0) {
48
51
  return usage.total;
49
52
  }
50
- if (typeof usage.totalTokens === "number") {
53
+ if (typeof usage.totalTokens === "number" && usage.totalTokens > 0) {
51
54
  return usage.totalTokens;
52
55
  }
53
56
  return input + output;
@@ -185,7 +188,6 @@ export function extractTokenUsage(result, options = {}) {
185
188
  // Extract base token counts
186
189
  let input = extractInputTokens(usage);
187
190
  const output = extractOutputTokens(usage);
188
- const total = extractTotalTokens(usage, input, output);
189
191
  // Extract optional token fields
190
192
  const reasoning = extractReasoningTokens(usage);
191
193
  const cacheCreationTokens = extractCacheCreationTokens(usage);
@@ -204,6 +206,39 @@ export function extractTokenUsage(result, options = {}) {
204
206
  input = Math.max(0, input - overlappingCached);
205
207
  }
206
208
  }
209
+ // ai@6-shape rebase: when the cache values came ONLY from the ai@6
210
+ // normalized shape (cachedInputTokens / inputTokenDetails.*), the flat
211
+ // input is cache-INCLUSIVE — asLanguageModelUsage reports
212
+ // inputTokens.total = noCache + cacheRead + cacheWrite — so `input` must
213
+ // be rebased onto the uncached portion or calculateCost bills the cached
214
+ // tokens twice (full input rate + cacheRead/cacheCreation rate). The
215
+ // native fields excluded below (cacheReadInputTokens / cacheReadTokens /
216
+ // cacheCreationInputTokens / cacheCreationTokens) follow the
217
+ // non-overlapping convention where input is already the uncached
218
+ // remainder, and the overlapping snake_case shape was already rebased
219
+ // above — neither must be rebased again.
220
+ if ((cacheReadTokens !== undefined || cacheCreationTokens !== undefined) &&
221
+ usage.cacheReadInputTokens === undefined &&
222
+ usage.cacheReadTokens === undefined &&
223
+ usage.cacheCreationInputTokens === undefined &&
224
+ usage.cacheCreationTokens === undefined &&
225
+ usage.prompt_tokens_details?.cached_tokens === undefined &&
226
+ (usage.cachedInputTokens !== undefined ||
227
+ usage.inputTokenDetails !== undefined)) {
228
+ const noCacheTokens = usage.inputTokenDetails?.noCacheTokens;
229
+ if (typeof noCacheTokens === "number") {
230
+ input = noCacheTokens;
231
+ }
232
+ else {
233
+ input = Math.max(0, input -
234
+ (cacheReadTokens ?? 0) -
235
+ (usage.inputTokenDetails?.cacheWriteTokens ?? 0));
236
+ }
237
+ }
238
+ // Total: prefer the provider-reported figure; the fallback conserves every
239
+ // billed component — cache tokens are additive on top of the (post-rebase)
240
+ // uncached input. Reasoning is already inside `output`, so it is NOT added.
241
+ const total = extractTotalTokens(usage, input + (cacheReadTokens ?? 0) + (cacheCreationTokens ?? 0), output);
207
242
  // Calculate cache savings if enabled
208
243
  const cacheSavingsPercent = calculateCacheSavings
209
244
  ? calculateCacheSavingsPercent(cacheReadTokens, input)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "10.6.4",
3
+ "version": "10.7.0",
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": {
@@ -104,6 +104,7 @@
104
104
  "test:google-native": "npx tsx test/continuous-test-suite-google-native.ts",
105
105
  "test:gemini-abort": "npx tsx test/continuous-test-suite-gemini-abort.ts",
106
106
  "test:anthropic-cap": "npx tsx test/continuous-test-suite-anthropic-cap.ts",
107
+ "test:token-usage": "npx tsx test/continuous-test-suite-token-usage.ts",
107
108
  "test:tts": "npx tsx test/continuous-test-suite-tts.ts",
108
109
  "test:voice": "npx tsx test/continuous-test-suite-voice.ts",
109
110
  "test:voice-server": "npx tsx test/continuous-test-suite-voice-server.ts",