@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.
- package/CHANGELOG.md +12 -0
- package/README.md +22 -20
- package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/adapters/video/videoAnalyzer.js +10 -8
- package/dist/cli/commands/setup-anthropic.js +1 -14
- package/dist/cli/commands/setup-azure.js +1 -12
- package/dist/cli/commands/setup-bedrock.js +1 -9
- package/dist/cli/commands/setup-google-ai.js +1 -12
- package/dist/cli/commands/setup-openai.js +1 -14
- package/dist/cli/commands/workflow.d.ts +27 -0
- package/dist/cli/commands/workflow.js +216 -0
- package/dist/cli/factories/commandFactory.js +79 -20
- package/dist/cli/index.js +0 -1
- package/dist/cli/parser.js +4 -1
- package/dist/cli/utils/maskCredential.d.ts +11 -0
- package/dist/cli/utils/maskCredential.js +23 -0
- package/dist/constants/contextWindows.js +107 -16
- package/dist/constants/enums.d.ts +99 -15
- package/dist/constants/enums.js +152 -22
- package/dist/context/budgetChecker.js +1 -1
- package/dist/context/contextCompactor.js +31 -4
- package/dist/context/emergencyTruncation.d.ts +21 -0
- package/dist/context/emergencyTruncation.js +88 -0
- package/dist/context/errorDetection.d.ts +16 -0
- package/dist/context/errorDetection.js +48 -1
- package/dist/context/errors.d.ts +19 -0
- package/dist/context/errors.js +21 -0
- package/dist/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/context/stages/structuredSummarizer.js +2 -2
- package/dist/core/baseProvider.js +306 -200
- package/dist/core/conversationMemoryManager.js +104 -61
- package/dist/core/evaluationProviders.js +16 -33
- package/dist/core/factory.js +237 -164
- package/dist/core/modules/GenerationHandler.js +175 -116
- package/dist/core/modules/MessageBuilder.js +222 -170
- package/dist/core/modules/StreamHandler.d.ts +1 -0
- package/dist/core/modules/StreamHandler.js +95 -27
- package/dist/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/core/modules/TelemetryHandler.js +25 -7
- package/dist/core/modules/ToolsManager.js +115 -191
- package/dist/core/redisConversationMemoryManager.js +418 -282
- package/dist/factories/providerRegistry.d.ts +5 -0
- package/dist/factories/providerRegistry.js +20 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -2
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/lib/adapters/video/videoAnalyzer.js +10 -8
- package/dist/lib/constants/contextWindows.js +107 -16
- package/dist/lib/constants/enums.d.ts +99 -15
- package/dist/lib/constants/enums.js +152 -22
- package/dist/lib/context/budgetChecker.js +1 -1
- package/dist/lib/context/contextCompactor.js +31 -4
- package/dist/lib/context/emergencyTruncation.d.ts +21 -0
- package/dist/lib/context/emergencyTruncation.js +89 -0
- package/dist/lib/context/errorDetection.d.ts +16 -0
- package/dist/lib/context/errorDetection.js +48 -1
- package/dist/lib/context/errors.d.ts +19 -0
- package/dist/lib/context/errors.js +22 -0
- package/dist/lib/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/lib/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/lib/context/stages/structuredSummarizer.js +2 -2
- package/dist/lib/core/baseProvider.js +306 -200
- package/dist/lib/core/conversationMemoryManager.js +104 -61
- package/dist/lib/core/evaluationProviders.js +16 -33
- package/dist/lib/core/factory.js +237 -164
- package/dist/lib/core/modules/GenerationHandler.js +175 -116
- package/dist/lib/core/modules/MessageBuilder.js +222 -170
- package/dist/lib/core/modules/StreamHandler.d.ts +1 -0
- package/dist/lib/core/modules/StreamHandler.js +95 -27
- package/dist/lib/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/lib/core/modules/TelemetryHandler.js +25 -7
- package/dist/lib/core/modules/ToolsManager.js +115 -191
- package/dist/lib/core/redisConversationMemoryManager.js +418 -282
- package/dist/lib/factories/providerRegistry.d.ts +5 -0
- package/dist/lib/factories/providerRegistry.js +20 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +4 -2
- package/dist/lib/mcp/externalServerManager.js +66 -0
- package/dist/lib/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/lib/mcp/mcpClientFactory.js +16 -0
- package/dist/lib/mcp/toolDiscoveryService.js +32 -6
- package/dist/lib/mcp/toolRegistry.js +193 -123
- package/dist/lib/neurolink.d.ts +6 -0
- package/dist/lib/neurolink.js +1162 -646
- package/dist/lib/providers/amazonBedrock.d.ts +1 -1
- package/dist/lib/providers/amazonBedrock.js +521 -319
- package/dist/lib/providers/anthropic.js +73 -17
- package/dist/lib/providers/anthropicBaseProvider.js +77 -17
- package/dist/lib/providers/googleAiStudio.d.ts +1 -1
- package/dist/lib/providers/googleAiStudio.js +292 -227
- package/dist/lib/providers/googleVertex.d.ts +36 -1
- package/dist/lib/providers/googleVertex.js +553 -260
- package/dist/lib/providers/ollama.js +329 -278
- package/dist/lib/providers/openAI.js +77 -19
- package/dist/lib/providers/sagemaker/parsers.js +3 -3
- package/dist/lib/providers/sagemaker/streaming.js +3 -3
- package/dist/lib/proxy/proxyFetch.js +81 -48
- package/dist/lib/rag/ChunkerFactory.js +1 -1
- package/dist/lib/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/lib/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/lib/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/lib/rag/chunking/markdownChunker.js +174 -2
- package/dist/lib/rag/pipeline/contextAssembly.js +2 -1
- package/dist/lib/rag/ragIntegration.d.ts +18 -1
- package/dist/lib/rag/ragIntegration.js +94 -14
- package/dist/lib/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/lib/server/abstract/baseServerAdapter.js +4 -1
- package/dist/lib/server/adapters/fastifyAdapter.js +35 -30
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/lib/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/lib/telemetry/attributes.d.ts +52 -0
- package/dist/lib/telemetry/attributes.js +61 -0
- package/dist/lib/telemetry/index.d.ts +3 -0
- package/dist/lib/telemetry/index.js +3 -0
- package/dist/lib/telemetry/telemetryService.d.ts +6 -0
- package/dist/lib/telemetry/telemetryService.js +6 -0
- package/dist/lib/telemetry/tracers.d.ts +15 -0
- package/dist/lib/telemetry/tracers.js +17 -0
- package/dist/lib/telemetry/withSpan.d.ts +9 -0
- package/dist/lib/telemetry/withSpan.js +35 -0
- package/dist/lib/types/contextTypes.d.ts +10 -0
- package/dist/lib/types/streamTypes.d.ts +14 -0
- package/dist/lib/utils/conversationMemory.js +123 -84
- package/dist/lib/utils/logger.d.ts +5 -0
- package/dist/lib/utils/logger.js +50 -2
- package/dist/lib/utils/messageBuilder.js +22 -42
- package/dist/lib/utils/modelDetection.js +3 -3
- package/dist/lib/utils/providerRetry.d.ts +41 -0
- package/dist/lib/utils/providerRetry.js +114 -0
- package/dist/lib/utils/retryability.d.ts +14 -0
- package/dist/lib/utils/retryability.js +23 -0
- package/dist/lib/utils/sanitizers/svg.js +4 -5
- package/dist/lib/utils/tokenEstimation.d.ts +11 -1
- package/dist/lib/utils/tokenEstimation.js +19 -4
- package/dist/lib/utils/videoAnalysisProcessor.js +7 -3
- package/dist/mcp/externalServerManager.js +66 -0
- package/dist/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/mcp/mcpClientFactory.js +16 -0
- package/dist/mcp/toolDiscoveryService.js +32 -6
- package/dist/mcp/toolRegistry.js +193 -123
- package/dist/neurolink.d.ts +6 -0
- package/dist/neurolink.js +1162 -646
- package/dist/providers/amazonBedrock.d.ts +1 -1
- package/dist/providers/amazonBedrock.js +521 -319
- package/dist/providers/anthropic.js +73 -17
- package/dist/providers/anthropicBaseProvider.js +77 -17
- package/dist/providers/googleAiStudio.d.ts +1 -1
- package/dist/providers/googleAiStudio.js +292 -227
- package/dist/providers/googleVertex.d.ts +36 -1
- package/dist/providers/googleVertex.js +553 -260
- package/dist/providers/ollama.js +329 -278
- package/dist/providers/openAI.js +77 -19
- package/dist/providers/sagemaker/parsers.js +3 -3
- package/dist/providers/sagemaker/streaming.js +3 -3
- package/dist/proxy/proxyFetch.js +81 -48
- package/dist/rag/ChunkerFactory.js +1 -1
- package/dist/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/rag/chunking/markdownChunker.js +174 -2
- package/dist/rag/pipeline/contextAssembly.js +2 -1
- package/dist/rag/ragIntegration.d.ts +18 -1
- package/dist/rag/ragIntegration.js +94 -14
- package/dist/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/server/abstract/baseServerAdapter.js +4 -1
- package/dist/server/adapters/fastifyAdapter.js +35 -30
- package/dist/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/telemetry/attributes.d.ts +52 -0
- package/dist/telemetry/attributes.js +60 -0
- package/dist/telemetry/index.d.ts +3 -0
- package/dist/telemetry/index.js +3 -0
- package/dist/telemetry/telemetryService.d.ts +6 -0
- package/dist/telemetry/telemetryService.js +6 -0
- package/dist/telemetry/tracers.d.ts +15 -0
- package/dist/telemetry/tracers.js +16 -0
- package/dist/telemetry/withSpan.d.ts +9 -0
- package/dist/telemetry/withSpan.js +34 -0
- package/dist/types/contextTypes.d.ts +10 -0
- package/dist/types/streamTypes.d.ts +14 -0
- package/dist/utils/conversationMemory.js +123 -84
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +50 -2
- package/dist/utils/messageBuilder.js +22 -42
- package/dist/utils/modelDetection.js +3 -3
- package/dist/utils/providerRetry.d.ts +41 -0
- package/dist/utils/providerRetry.js +113 -0
- package/dist/utils/retryability.d.ts +14 -0
- package/dist/utils/retryability.js +22 -0
- package/dist/utils/sanitizers/svg.js +4 -5
- package/dist/utils/tokenEstimation.d.ts +11 -1
- package/dist/utils/tokenEstimation.js +19 -4
- package/dist/utils/videoAnalysisProcessor.js +7 -3
- package/dist/workflow/config.d.ts +26 -26
- 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
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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>;
|