@juspay/neurolink 9.15.0 → 9.17.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 (196) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +22 -20
  3. package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
  4. package/dist/adapters/video/videoAnalyzer.js +10 -8
  5. package/dist/cli/commands/setup-anthropic.js +1 -14
  6. package/dist/cli/commands/setup-azure.js +1 -12
  7. package/dist/cli/commands/setup-bedrock.js +1 -9
  8. package/dist/cli/commands/setup-google-ai.js +1 -12
  9. package/dist/cli/commands/setup-openai.js +1 -14
  10. package/dist/cli/commands/workflow.d.ts +27 -0
  11. package/dist/cli/commands/workflow.js +216 -0
  12. package/dist/cli/factories/commandFactory.js +79 -20
  13. package/dist/cli/index.js +0 -1
  14. package/dist/cli/parser.js +4 -1
  15. package/dist/cli/utils/maskCredential.d.ts +11 -0
  16. package/dist/cli/utils/maskCredential.js +23 -0
  17. package/dist/constants/contextWindows.js +107 -16
  18. package/dist/constants/enums.d.ts +99 -15
  19. package/dist/constants/enums.js +152 -22
  20. package/dist/context/budgetChecker.js +1 -1
  21. package/dist/context/contextCompactor.js +31 -4
  22. package/dist/context/emergencyTruncation.d.ts +21 -0
  23. package/dist/context/emergencyTruncation.js +88 -0
  24. package/dist/context/errorDetection.d.ts +16 -0
  25. package/dist/context/errorDetection.js +48 -1
  26. package/dist/context/errors.d.ts +19 -0
  27. package/dist/context/errors.js +21 -0
  28. package/dist/context/stages/slidingWindowTruncator.d.ts +6 -0
  29. package/dist/context/stages/slidingWindowTruncator.js +159 -24
  30. package/dist/context/stages/structuredSummarizer.js +2 -2
  31. package/dist/core/baseProvider.js +306 -200
  32. package/dist/core/conversationMemoryManager.js +104 -61
  33. package/dist/core/evaluationProviders.js +16 -33
  34. package/dist/core/factory.js +237 -164
  35. package/dist/core/modules/GenerationHandler.js +175 -116
  36. package/dist/core/modules/MessageBuilder.js +222 -170
  37. package/dist/core/modules/StreamHandler.d.ts +1 -0
  38. package/dist/core/modules/StreamHandler.js +95 -27
  39. package/dist/core/modules/TelemetryHandler.d.ts +10 -1
  40. package/dist/core/modules/TelemetryHandler.js +25 -7
  41. package/dist/core/modules/ToolsManager.js +115 -191
  42. package/dist/core/redisConversationMemoryManager.js +418 -282
  43. package/dist/factories/providerRegistry.d.ts +5 -0
  44. package/dist/factories/providerRegistry.js +20 -2
  45. package/dist/index.d.ts +2 -2
  46. package/dist/index.js +4 -2
  47. package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
  48. package/dist/lib/adapters/video/videoAnalyzer.js +10 -8
  49. package/dist/lib/constants/contextWindows.js +107 -16
  50. package/dist/lib/constants/enums.d.ts +99 -15
  51. package/dist/lib/constants/enums.js +152 -22
  52. package/dist/lib/context/budgetChecker.js +1 -1
  53. package/dist/lib/context/contextCompactor.js +31 -4
  54. package/dist/lib/context/emergencyTruncation.d.ts +21 -0
  55. package/dist/lib/context/emergencyTruncation.js +89 -0
  56. package/dist/lib/context/errorDetection.d.ts +16 -0
  57. package/dist/lib/context/errorDetection.js +48 -1
  58. package/dist/lib/context/errors.d.ts +19 -0
  59. package/dist/lib/context/errors.js +22 -0
  60. package/dist/lib/context/stages/slidingWindowTruncator.d.ts +6 -0
  61. package/dist/lib/context/stages/slidingWindowTruncator.js +159 -24
  62. package/dist/lib/context/stages/structuredSummarizer.js +2 -2
  63. package/dist/lib/core/baseProvider.js +306 -200
  64. package/dist/lib/core/conversationMemoryManager.js +104 -61
  65. package/dist/lib/core/evaluationProviders.js +16 -33
  66. package/dist/lib/core/factory.js +237 -164
  67. package/dist/lib/core/modules/GenerationHandler.js +175 -116
  68. package/dist/lib/core/modules/MessageBuilder.js +222 -170
  69. package/dist/lib/core/modules/StreamHandler.d.ts +1 -0
  70. package/dist/lib/core/modules/StreamHandler.js +95 -27
  71. package/dist/lib/core/modules/TelemetryHandler.d.ts +10 -1
  72. package/dist/lib/core/modules/TelemetryHandler.js +25 -7
  73. package/dist/lib/core/modules/ToolsManager.js +115 -191
  74. package/dist/lib/core/redisConversationMemoryManager.js +418 -282
  75. package/dist/lib/factories/providerRegistry.d.ts +5 -0
  76. package/dist/lib/factories/providerRegistry.js +20 -2
  77. package/dist/lib/index.d.ts +2 -2
  78. package/dist/lib/index.js +4 -2
  79. package/dist/lib/mcp/externalServerManager.js +66 -0
  80. package/dist/lib/mcp/mcpCircuitBreaker.js +24 -0
  81. package/dist/lib/mcp/mcpClientFactory.js +16 -0
  82. package/dist/lib/mcp/toolDiscoveryService.js +32 -6
  83. package/dist/lib/mcp/toolRegistry.js +193 -123
  84. package/dist/lib/neurolink.d.ts +6 -0
  85. package/dist/lib/neurolink.js +1162 -646
  86. package/dist/lib/providers/amazonBedrock.d.ts +1 -1
  87. package/dist/lib/providers/amazonBedrock.js +521 -319
  88. package/dist/lib/providers/anthropic.js +73 -17
  89. package/dist/lib/providers/anthropicBaseProvider.js +77 -17
  90. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  91. package/dist/lib/providers/googleAiStudio.js +292 -227
  92. package/dist/lib/providers/googleVertex.d.ts +36 -1
  93. package/dist/lib/providers/googleVertex.js +553 -260
  94. package/dist/lib/providers/ollama.js +329 -278
  95. package/dist/lib/providers/openAI.js +77 -19
  96. package/dist/lib/providers/sagemaker/parsers.js +3 -3
  97. package/dist/lib/providers/sagemaker/streaming.js +3 -3
  98. package/dist/lib/proxy/proxyFetch.js +81 -48
  99. package/dist/lib/rag/ChunkerFactory.js +1 -1
  100. package/dist/lib/rag/chunkers/MarkdownChunker.d.ts +22 -0
  101. package/dist/lib/rag/chunkers/MarkdownChunker.js +213 -9
  102. package/dist/lib/rag/chunking/markdownChunker.d.ts +16 -0
  103. package/dist/lib/rag/chunking/markdownChunker.js +174 -2
  104. package/dist/lib/rag/pipeline/contextAssembly.js +2 -1
  105. package/dist/lib/rag/ragIntegration.d.ts +18 -1
  106. package/dist/lib/rag/ragIntegration.js +94 -14
  107. package/dist/lib/rag/retrieval/vectorQueryTool.js +21 -4
  108. package/dist/lib/server/abstract/baseServerAdapter.js +4 -1
  109. package/dist/lib/server/adapters/fastifyAdapter.js +35 -30
  110. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +32 -0
  111. package/dist/lib/services/server/ai/observability/instrumentation.js +39 -0
  112. package/dist/lib/telemetry/attributes.d.ts +52 -0
  113. package/dist/lib/telemetry/attributes.js +61 -0
  114. package/dist/lib/telemetry/index.d.ts +3 -0
  115. package/dist/lib/telemetry/index.js +3 -0
  116. package/dist/lib/telemetry/telemetryService.d.ts +6 -0
  117. package/dist/lib/telemetry/telemetryService.js +6 -0
  118. package/dist/lib/telemetry/tracers.d.ts +15 -0
  119. package/dist/lib/telemetry/tracers.js +17 -0
  120. package/dist/lib/telemetry/withSpan.d.ts +9 -0
  121. package/dist/lib/telemetry/withSpan.js +35 -0
  122. package/dist/lib/types/contextTypes.d.ts +10 -0
  123. package/dist/lib/types/streamTypes.d.ts +14 -0
  124. package/dist/lib/utils/conversationMemory.js +123 -84
  125. package/dist/lib/utils/logger.d.ts +5 -0
  126. package/dist/lib/utils/logger.js +50 -2
  127. package/dist/lib/utils/messageBuilder.js +22 -42
  128. package/dist/lib/utils/modelDetection.js +3 -3
  129. package/dist/lib/utils/providerRetry.d.ts +41 -0
  130. package/dist/lib/utils/providerRetry.js +114 -0
  131. package/dist/lib/utils/retryability.d.ts +14 -0
  132. package/dist/lib/utils/retryability.js +23 -0
  133. package/dist/lib/utils/sanitizers/svg.js +4 -5
  134. package/dist/lib/utils/tokenEstimation.d.ts +11 -1
  135. package/dist/lib/utils/tokenEstimation.js +19 -4
  136. package/dist/lib/utils/videoAnalysisProcessor.js +7 -3
  137. package/dist/mcp/externalServerManager.js +66 -0
  138. package/dist/mcp/mcpCircuitBreaker.js +24 -0
  139. package/dist/mcp/mcpClientFactory.js +16 -0
  140. package/dist/mcp/toolDiscoveryService.js +32 -6
  141. package/dist/mcp/toolRegistry.js +193 -123
  142. package/dist/neurolink.d.ts +6 -0
  143. package/dist/neurolink.js +1162 -646
  144. package/dist/providers/amazonBedrock.d.ts +1 -1
  145. package/dist/providers/amazonBedrock.js +521 -319
  146. package/dist/providers/anthropic.js +73 -17
  147. package/dist/providers/anthropicBaseProvider.js +77 -17
  148. package/dist/providers/googleAiStudio.d.ts +1 -1
  149. package/dist/providers/googleAiStudio.js +292 -227
  150. package/dist/providers/googleVertex.d.ts +36 -1
  151. package/dist/providers/googleVertex.js +553 -260
  152. package/dist/providers/ollama.js +329 -278
  153. package/dist/providers/openAI.js +77 -19
  154. package/dist/providers/sagemaker/parsers.js +3 -3
  155. package/dist/providers/sagemaker/streaming.js +3 -3
  156. package/dist/proxy/proxyFetch.js +81 -48
  157. package/dist/rag/ChunkerFactory.js +1 -1
  158. package/dist/rag/chunkers/MarkdownChunker.d.ts +22 -0
  159. package/dist/rag/chunkers/MarkdownChunker.js +213 -9
  160. package/dist/rag/chunking/markdownChunker.d.ts +16 -0
  161. package/dist/rag/chunking/markdownChunker.js +174 -2
  162. package/dist/rag/pipeline/contextAssembly.js +2 -1
  163. package/dist/rag/ragIntegration.d.ts +18 -1
  164. package/dist/rag/ragIntegration.js +94 -14
  165. package/dist/rag/retrieval/vectorQueryTool.js +21 -4
  166. package/dist/server/abstract/baseServerAdapter.js +4 -1
  167. package/dist/server/adapters/fastifyAdapter.js +35 -30
  168. package/dist/services/server/ai/observability/instrumentation.d.ts +32 -0
  169. package/dist/services/server/ai/observability/instrumentation.js +39 -0
  170. package/dist/telemetry/attributes.d.ts +52 -0
  171. package/dist/telemetry/attributes.js +60 -0
  172. package/dist/telemetry/index.d.ts +3 -0
  173. package/dist/telemetry/index.js +3 -0
  174. package/dist/telemetry/telemetryService.d.ts +6 -0
  175. package/dist/telemetry/telemetryService.js +6 -0
  176. package/dist/telemetry/tracers.d.ts +15 -0
  177. package/dist/telemetry/tracers.js +16 -0
  178. package/dist/telemetry/withSpan.d.ts +9 -0
  179. package/dist/telemetry/withSpan.js +34 -0
  180. package/dist/types/contextTypes.d.ts +10 -0
  181. package/dist/types/streamTypes.d.ts +14 -0
  182. package/dist/utils/conversationMemory.js +123 -84
  183. package/dist/utils/logger.d.ts +5 -0
  184. package/dist/utils/logger.js +50 -2
  185. package/dist/utils/messageBuilder.js +22 -42
  186. package/dist/utils/modelDetection.js +3 -3
  187. package/dist/utils/providerRetry.d.ts +41 -0
  188. package/dist/utils/providerRetry.js +113 -0
  189. package/dist/utils/retryability.d.ts +14 -0
  190. package/dist/utils/retryability.js +22 -0
  191. package/dist/utils/sanitizers/svg.js +4 -5
  192. package/dist/utils/tokenEstimation.d.ts +11 -1
  193. package/dist/utils/tokenEstimation.js +19 -4
  194. package/dist/utils/videoAnalysisProcessor.js +7 -3
  195. package/dist/workflow/config.d.ts +26 -26
  196. package/package.json +1 -1
@@ -1,11 +1,13 @@
1
1
  import { createAnthropic } from "@ai-sdk/anthropic";
2
2
  import { streamText } from "ai";
3
+ import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
3
4
  import { AnthropicModels } from "../constants/enums.js";
4
5
  import { BaseProvider } from "../core/baseProvider.js";
5
6
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
6
7
  import { createProxyFetch } from "../proxy/proxyFetch.js";
7
8
  import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
8
9
  import { logger } from "../utils/logger.js";
10
+ import { calculateCost } from "../utils/pricing.js";
9
11
  import { createAnthropicConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
10
12
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
11
13
  import { isModelAvailableForTier, getRecommendedModelForTier, getModelCapabilities, } from "../models/anthropicModels.js";
@@ -213,6 +215,7 @@ const getAnthropicApiKey = () => {
213
215
  const getDefaultAnthropicModel = () => {
214
216
  return getProviderModel("ANTHROPIC_MODEL", AnthropicModels.CLAUDE_3_5_SONNET);
215
217
  };
218
+ const streamTracer = trace.getTracer("neurolink.provider.anthropic");
216
219
  /**
217
220
  * Get OAuth token from stored credentials file or environment.
218
221
  * Priority:
@@ -878,25 +881,78 @@ export class AnthropicProvider extends BaseProvider {
878
881
  // Using protected helper from BaseProvider to eliminate code duplication
879
882
  const messages = await this.buildMessagesForStream(options);
880
883
  const model = await this.getAISDKModelWithMiddleware(options);
881
- const result = await streamText({
882
- model: model,
883
- messages: messages,
884
- temperature: options.temperature,
885
- maxTokens: options.maxTokens, // No default limit - unlimited unless specified
886
- tools,
887
- maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
888
- toolChoice: shouldUseTools ? "auto" : "none",
889
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
890
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
891
- onStepFinish: ({ toolCalls, toolResults }) => {
892
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
893
- logger.warn("[AnthropicProvider] Failed to store tool executions", {
894
- provider: this.providerName,
895
- error: error instanceof Error ? error.message : String(error),
896
- });
897
- });
884
+ // Wrap streamText in an OTel span to capture provider-level latency and token usage
885
+ const streamSpan = streamTracer.startSpan("neurolink.provider.streamText", {
886
+ kind: SpanKind.CLIENT,
887
+ attributes: {
888
+ "gen_ai.system": "anthropic",
889
+ "gen_ai.request.model": model.modelId || this.modelName || "unknown",
898
890
  },
899
891
  });
892
+ let result;
893
+ try {
894
+ result = streamText({
895
+ model: model,
896
+ messages: messages,
897
+ temperature: options.temperature,
898
+ maxTokens: options.maxTokens, // No default limit - unlimited unless specified
899
+ maxRetries: 0, // NL11: Disable AI SDK's invisible internal retries; we handle retries with OTel instrumentation
900
+ tools,
901
+ maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
902
+ toolChoice: shouldUseTools ? "auto" : "none",
903
+ abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
904
+ experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
905
+ onStepFinish: ({ toolCalls, toolResults }) => {
906
+ this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
907
+ logger.warn("[AnthropicProvider] Failed to store tool executions", {
908
+ provider: this.providerName,
909
+ error: error instanceof Error ? error.message : String(error),
910
+ });
911
+ });
912
+ },
913
+ });
914
+ }
915
+ catch (streamError) {
916
+ streamSpan.end();
917
+ throw streamError;
918
+ }
919
+ // Collect token usage and finish reason asynchronously when the stream completes,
920
+ // then end the span. This avoids blocking the stream consumer.
921
+ result.usage
922
+ .then((usage) => {
923
+ streamSpan.setAttribute("gen_ai.usage.input_tokens", usage.promptTokens || 0);
924
+ streamSpan.setAttribute("gen_ai.usage.output_tokens", usage.completionTokens || 0);
925
+ const cost = calculateCost(this.providerName, this.modelName, {
926
+ input: usage.promptTokens || 0,
927
+ output: usage.completionTokens || 0,
928
+ total: (usage.promptTokens || 0) + (usage.completionTokens || 0),
929
+ });
930
+ if (cost && cost > 0) {
931
+ streamSpan.setAttribute("neurolink.cost", cost);
932
+ }
933
+ })
934
+ .catch(() => {
935
+ // Usage may not be available if the stream is aborted
936
+ });
937
+ result.finishReason
938
+ .then((reason) => {
939
+ streamSpan.setAttribute("gen_ai.response.finish_reason", reason || "unknown");
940
+ })
941
+ .catch(() => {
942
+ // Finish reason may not be available if the stream is aborted
943
+ });
944
+ // End the span when the stream text resolves (stream fully consumed)
945
+ result.text
946
+ .then(() => {
947
+ streamSpan.end();
948
+ })
949
+ .catch((err) => {
950
+ streamSpan.setStatus({
951
+ code: SpanStatusCode.ERROR,
952
+ message: err instanceof Error ? err.message : String(err),
953
+ });
954
+ streamSpan.end();
955
+ });
900
956
  timeoutController?.cleanup();
901
957
  const transformedStream = this.createTextStream(result);
902
958
  // ✅ Note: Vercel AI SDK's streamText() method limitations with tools
@@ -1,11 +1,14 @@
1
1
  import { createAnthropic } from "@ai-sdk/anthropic";
2
2
  import { streamText } from "ai";
3
+ import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
3
4
  import { AIProviderName, AnthropicModels } from "../constants/enums.js";
4
5
  import { BaseProvider } from "../core/baseProvider.js";
5
6
  import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
6
7
  import { logger } from "../utils/logger.js";
8
+ import { calculateCost } from "../utils/pricing.js";
7
9
  import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
8
10
  import { validateApiKey, createAnthropicBaseConfig, } from "../utils/providerConfig.js";
11
+ const streamTracer = trace.getTracer("neurolink.provider.anthropic");
9
12
  /**
10
13
  * Anthropic provider implementation using BaseProvider pattern
11
14
  * Migrated from direct API calls to Vercel AI SDK (@ai-sdk/anthropic)
@@ -68,25 +71,82 @@ export class AnthropicProviderV2 extends BaseProvider {
68
71
  const tools = shouldUseTools
69
72
  ? options.tools || (await this.getAllTools())
70
73
  : {};
71
- const result = await streamText({
72
- model,
73
- prompt: options.input.text,
74
- system: options.systemPrompt,
75
- temperature: options.temperature,
76
- maxTokens: options.maxTokens, // No default limit - unlimited unless specified
77
- tools,
78
- toolChoice: shouldUseTools ? "auto" : "none",
79
- abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
80
- experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
81
- onStepFinish: ({ toolCalls, toolResults }) => {
82
- this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
83
- logger.warn("[AnthropicBaseProvider] Failed to store tool executions", {
84
- provider: this.providerName,
85
- error: error instanceof Error ? error.message : String(error),
86
- });
87
- });
74
+ // Wrap streamText in an OTel span to capture provider-level latency and token usage
75
+ const streamSpan = streamTracer.startSpan("neurolink.provider.streamText", {
76
+ kind: SpanKind.CLIENT,
77
+ attributes: {
78
+ "gen_ai.system": "anthropic",
79
+ "gen_ai.request.model": model.modelId || this.modelName || "unknown",
88
80
  },
89
81
  });
82
+ let result;
83
+ try {
84
+ result = streamText({
85
+ model,
86
+ prompt: options.input.text,
87
+ system: options.systemPrompt,
88
+ temperature: options.temperature,
89
+ maxTokens: options.maxTokens, // No default limit - unlimited unless specified
90
+ maxRetries: 0, // NL11: Disable AI SDK's invisible internal retries; we handle retries with OTel instrumentation
91
+ tools,
92
+ toolChoice: shouldUseTools ? "auto" : "none",
93
+ abortSignal: composeAbortSignals(options.abortSignal, timeoutController?.controller.signal),
94
+ experimental_telemetry: this.telemetryHandler.getTelemetryConfig(options),
95
+ onStepFinish: ({ toolCalls, toolResults }) => {
96
+ this.handleToolExecutionStorage(toolCalls, toolResults, options, new Date()).catch((error) => {
97
+ logger.warn("[AnthropicBaseProvider] Failed to store tool executions", {
98
+ provider: this.providerName,
99
+ error: error instanceof Error ? error.message : String(error),
100
+ });
101
+ });
102
+ },
103
+ });
104
+ }
105
+ catch (err) {
106
+ streamSpan.recordException(err instanceof Error ? err : new Error(String(err)));
107
+ streamSpan.setStatus({
108
+ code: SpanStatusCode.ERROR,
109
+ message: err instanceof Error ? err.message : String(err),
110
+ });
111
+ streamSpan.end();
112
+ throw err;
113
+ }
114
+ // Collect token usage and finish reason asynchronously when the stream completes,
115
+ // then end the span. This avoids blocking the stream consumer.
116
+ result.usage
117
+ .then((usage) => {
118
+ streamSpan.setAttribute("gen_ai.usage.input_tokens", usage.promptTokens || 0);
119
+ streamSpan.setAttribute("gen_ai.usage.output_tokens", usage.completionTokens || 0);
120
+ const cost = calculateCost(this.providerName, this.modelName, {
121
+ input: usage.promptTokens || 0,
122
+ output: usage.completionTokens || 0,
123
+ total: (usage.promptTokens || 0) + (usage.completionTokens || 0),
124
+ });
125
+ if (cost && cost > 0) {
126
+ streamSpan.setAttribute("neurolink.cost", cost);
127
+ }
128
+ })
129
+ .catch(() => {
130
+ // Usage may not be available if the stream is aborted
131
+ });
132
+ result.finishReason
133
+ .then((reason) => {
134
+ streamSpan.setAttribute("gen_ai.response.finish_reason", reason || "unknown");
135
+ })
136
+ .catch(() => {
137
+ // Finish reason may not be available if the stream is aborted
138
+ });
139
+ result.text
140
+ .then(() => {
141
+ streamSpan.end();
142
+ })
143
+ .catch((err) => {
144
+ streamSpan.setStatus({
145
+ code: SpanStatusCode.ERROR,
146
+ message: err instanceof Error ? err.message : String(err),
147
+ });
148
+ streamSpan.end();
149
+ });
90
150
  timeoutController?.cleanup();
91
151
  // Transform string stream to content object stream (match Google AI pattern)
92
152
  const transformedStream = async function* () {
@@ -56,7 +56,7 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
56
56
  */
57
57
  private detectImageType;
58
58
  /**
59
- * Estimate token count from text (simple character-based estimation)
59
+ * Estimate token count from text using centralized estimation with provider multipliers
60
60
  */
61
61
  private estimateTokenCount;
62
62
  protected executeStream(options: StreamOptions, _analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;