@juspay/neurolink 12.59.0 → 13.0.1
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 +3 -3
- package/dist/auth/anthropicOAuth.js +3 -3
- package/dist/auth/middleware/AuthMiddleware.d.ts +1 -1
- package/dist/auth/sessionManager.js +4 -4
- package/dist/auth/tokenStore.js +4 -4
- package/dist/browser/neurolink.min.js +474 -473
- package/dist/cli/commands/observability.d.ts +1 -6
- package/dist/cli/commands/observability.js +0 -106
- package/dist/cli/commands/proxy.js +9 -18
- package/dist/cli/commands/telemetry.d.ts +3 -13
- package/dist/cli/commands/telemetry.js +7 -354
- package/dist/cli/loop/session.js +1 -1
- package/dist/client/httpClient.js +1 -1
- package/dist/client/sseClient.js +1 -1
- package/dist/client/streamingClient.js +2 -2
- package/dist/client/wsClient.js +1 -1
- package/dist/constants/langfuse.d.ts +25 -0
- package/dist/constants/langfuse.js +38 -0
- package/dist/constants/telemetry.d.ts +20 -0
- package/dist/constants/telemetry.js +34 -0
- package/dist/core/baseProvider.d.ts +2 -1
- package/dist/core/baseProvider.js +4 -11
- package/dist/core/conversationMemoryManager.js +5 -8
- package/dist/core/factory.js +1 -1
- package/dist/core/geminiLoopAdapter.d.ts +8 -1
- package/dist/core/geminiLoopAdapter.js +25 -1
- package/dist/core/loopEngine.js +69 -40
- package/dist/core/modules/MessageBuilder.js +2 -2
- package/dist/core/modules/StreamHandler.js +2 -2
- package/dist/core/modules/TelemetryHandler.d.ts +2 -18
- package/dist/core/modules/TelemetryHandler.js +1 -66
- package/dist/core/modules/ToolsManager.js +40 -31
- package/dist/core/nativeGenerateLoop.js +78 -8
- package/dist/core/redisConversationMemoryManager.js +8 -15
- package/dist/core/toolExecutionGuards.js +1 -13
- package/dist/index.d.ts +5 -12
- package/dist/index.js +5 -37
- package/dist/mcp/batching/requestBatcher.js +1 -1
- package/dist/mcp/externalServerManager.js +3 -21
- package/dist/mcp/toolDiscoveryService.js +4 -16
- package/dist/mcp/toolRegistry.js +2 -5
- package/dist/memory/memoryRetrievalTools.js +1 -1
- package/dist/neurolink.d.ts +16 -27
- package/dist/neurolink.js +788 -792
- package/dist/observability/exporterSpanProcessor.d.ts +50 -0
- package/dist/observability/exporterSpanProcessor.js +181 -0
- package/dist/observability/exporters/langfuseExporter.d.ts +13 -34
- package/dist/observability/exporters/langfuseExporter.js +101 -154
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/langfuseMasking.d.ts +8 -0
- package/dist/observability/langfuseMasking.js +47 -0
- package/dist/observability/otlpEncoding.d.ts +20 -0
- package/dist/observability/otlpEncoding.js +85 -0
- package/dist/providers/amazonBedrock/client.js +142 -176
- package/dist/providers/amazonBedrock/loopAdapter.js +14 -1
- package/dist/providers/amazonSagemaker.js +118 -80
- package/dist/providers/anthropic/client.js +3 -52
- package/dist/providers/anthropic/loopAdapter.js +24 -1
- package/dist/providers/anthropic/rateLimitCapture.js +9 -12
- package/dist/providers/googleAiStudio/client.d.ts +4 -5
- package/dist/providers/googleAiStudio/client.js +38 -40
- package/dist/providers/googleVertex/client.d.ts +2 -7
- package/dist/providers/googleVertex/client.js +282 -378
- package/dist/providers/googleVertex/constants.js +2 -2
- package/dist/providers/litellm/client.d.ts +2 -9
- package/dist/providers/litellm/client.js +1 -63
- package/dist/providers/openAI/client.d.ts +1 -8
- package/dist/providers/openAI/client.js +0 -65
- package/dist/providers/openaiChatCompletionsBase.d.ts +1 -0
- package/dist/providers/openaiChatCompletionsBase.js +61 -4
- package/dist/providers/replicate.js +22 -4
- package/dist/proxy/codexUsage.js +7 -0
- package/dist/proxy/proxyFetch.js +19 -25
- package/dist/proxy/proxyTracer.d.ts +14 -7
- package/dist/proxy/proxyTracer.js +129 -83
- package/dist/proxy/proxyTranslationEngine.js +0 -1
- package/dist/proxy/requestLogger.d.ts +1 -1
- package/dist/proxy/requestLogger.js +39 -45
- package/dist/server/middleware/auth.d.ts +5 -1
- package/dist/server/middleware/auth.js +10 -3
- package/dist/server/middleware/common.js +1 -1
- package/dist/server/routes/agentRoutes.js +4 -4
- package/dist/server/routes/claudeProxyRoutes.js +99 -196
- package/dist/server/routes/codexProxyRoutes.js +621 -591
- package/dist/server/routes/healthRoutes.js +6 -6
- package/dist/server/routes/mcpRoutes.js +7 -7
- package/dist/server/routes/memoryRoutes.js +7 -7
- package/dist/server/routes/openApiRoutes.js +3 -3
- package/dist/server/routes/toolRoutes.js +5 -5
- package/dist/server/routes/transcribeRoutes.js +1 -1
- package/dist/server/utils/validation.d.ts +3 -3
- package/dist/services/server/ai/observability/instrumentation.d.ts +34 -201
- package/dist/services/server/ai/observability/instrumentation.js +220 -1267
- package/dist/services/server/ai/observability/langfuseSetup.d.ts +14 -0
- package/dist/services/server/ai/observability/langfuseSetup.js +55 -0
- package/dist/services/server/ai/observability/otlpSetup.d.ts +16 -0
- package/dist/services/server/ai/observability/otlpSetup.js +58 -0
- package/dist/session/globalSessionState.js +0 -11
- package/dist/telemetry/attributes.d.ts +23 -46
- package/dist/telemetry/attributes.js +76 -162
- package/dist/telemetry/chatMessages.d.ts +13 -0
- package/dist/telemetry/chatMessages.js +59 -0
- package/dist/telemetry/index.d.ts +5 -19
- package/dist/telemetry/index.js +5 -26
- package/dist/telemetry/observation.d.ts +37 -0
- package/dist/telemetry/observation.js +112 -0
- package/dist/telemetry/observationNames.d.ts +18 -0
- package/dist/telemetry/observationNames.js +24 -0
- package/dist/telemetry/spanSanitizer.d.ts +39 -0
- package/dist/telemetry/spanSanitizer.js +92 -0
- package/dist/telemetry/spanSerialization.d.ts +13 -0
- package/dist/telemetry/spanSerialization.js +46 -0
- package/dist/telemetry/tracers.d.ts +37 -18
- package/dist/telemetry/tracers.js +97 -19
- package/dist/telemetry/withSpan.d.ts +47 -25
- package/dist/telemetry/withSpan.js +158 -71
- package/dist/types/cli.d.ts +0 -11
- package/dist/types/decision.d.ts +3 -0
- package/dist/types/exporter.d.ts +54 -0
- package/dist/types/exporter.js +0 -4
- package/dist/types/generate.d.ts +4 -1
- package/dist/types/isolatedAgent.d.ts +5 -4
- package/dist/types/loopEngine.d.ts +18 -28
- package/dist/types/observability.d.ts +127 -160
- package/dist/types/providers.d.ts +15 -0
- package/dist/types/proxy.d.ts +41 -2
- package/dist/types/server.d.ts +9 -5
- package/dist/utils/anthropicTraceSanitizer.d.ts +2 -2
- package/dist/utils/anthropicTraceSanitizer.js +3 -1
- package/dist/utils/conversationMemory.js +4 -4
- package/dist/utils/fileDetector.js +1 -1
- package/dist/utils/messageBuilder.js +1 -1
- package/dist/utils/noOutputSentinel.d.ts +4 -16
- package/dist/utils/noOutputSentinel.js +12 -28
- package/dist/utils/providerRetry.js +4 -4
- package/dist/voice/livekit/brain.js +1 -1
- package/dist/voice/livekit/realtimeMemory.d.ts +1 -1
- package/dist/voice/livekit/realtimeMemory.js +66 -1
- package/dist/voice/livekit/realtimeVoiceAgent.js +1 -1
- package/docs-site/static/search-index.json +42 -64
- package/package.json +5 -4
- package/dist/telemetry/telemetryService.d.ts +0 -79
- package/dist/telemetry/telemetryService.js +0 -572
- package/dist/utils/observabilityHelpers.d.ts +0 -27
- package/dist/utils/observabilityHelpers.js +0 -47
|
@@ -74,7 +74,7 @@ export function createAgentRoutes(basePath = "/api") {
|
|
|
74
74
|
}
|
|
75
75
|
const request = validation.data;
|
|
76
76
|
return withSpan({
|
|
77
|
-
name: "
|
|
77
|
+
name: "http.execute",
|
|
78
78
|
tracer: tracers.http,
|
|
79
79
|
attributes: {
|
|
80
80
|
"http.route": "/api/agent/execute",
|
|
@@ -165,7 +165,7 @@ export function createAgentRoutes(basePath = "/api") {
|
|
|
165
165
|
// Wrap stream with a span that stays open for the full consumption
|
|
166
166
|
// lifetime, not just the generator creation.
|
|
167
167
|
async function* redactedStream() {
|
|
168
|
-
const streamSpan = tracers.http.startSpan("
|
|
168
|
+
const streamSpan = tracers.http.startSpan("http.stream", {
|
|
169
169
|
attributes: {
|
|
170
170
|
"http.route": "/api/agent/stream",
|
|
171
171
|
"ai.provider": request.provider || "default",
|
|
@@ -221,7 +221,7 @@ export function createAgentRoutes(basePath = "/api") {
|
|
|
221
221
|
try {
|
|
222
222
|
const providerName = request.provider || "openai";
|
|
223
223
|
return await withSpan({
|
|
224
|
-
name: "
|
|
224
|
+
name: "http.embed",
|
|
225
225
|
tracer: tracers.http,
|
|
226
226
|
attributes: {
|
|
227
227
|
"http.route": "/api/agent/embed",
|
|
@@ -260,7 +260,7 @@ export function createAgentRoutes(basePath = "/api") {
|
|
|
260
260
|
try {
|
|
261
261
|
const providerName = request.provider || "openai";
|
|
262
262
|
return await withSpan({
|
|
263
|
-
name: "
|
|
263
|
+
name: "http.embedMany",
|
|
264
264
|
tracer: tracers.http,
|
|
265
265
|
attributes: {
|
|
266
266
|
"http.route": "/api/agent/embed-many",
|
|
@@ -2306,7 +2306,10 @@ function extractResponseInfo(responseJson) {
|
|
|
2306
2306
|
* streaming path records the same gen_ai.response.* attributes as non-streaming.
|
|
2307
2307
|
*/
|
|
2308
2308
|
function responseInfoFromStream(data) {
|
|
2309
|
-
const info = {
|
|
2309
|
+
const info = {
|
|
2310
|
+
output: data.contentBlocks,
|
|
2311
|
+
firstOutputAt: data.firstUsefulOutputAt,
|
|
2312
|
+
};
|
|
2310
2313
|
if (data.model) {
|
|
2311
2314
|
info.responseModel = data.model;
|
|
2312
2315
|
}
|
|
@@ -2736,6 +2739,64 @@ function trackUpstreamReadableStream(source) {
|
|
|
2736
2739
|
});
|
|
2737
2740
|
return { stream, outcome: tracker.outcome };
|
|
2738
2741
|
}
|
|
2742
|
+
function settleStreamSpend(account, model, usage) {
|
|
2743
|
+
settleBorrowedRequest(account.key, model, usage);
|
|
2744
|
+
recordLeasedAccountSpend(account.label, model, usage);
|
|
2745
|
+
}
|
|
2746
|
+
function logStreamFinal(logFinalRequest, failure, accountLabel, accountType, usage) {
|
|
2747
|
+
logFinalRequest(failure?.status ?? 200, accountLabel, accountType, failure?.errorType, failure?.message, usage);
|
|
2748
|
+
}
|
|
2749
|
+
function streamUsageFields(usage) {
|
|
2750
|
+
return {
|
|
2751
|
+
inputTokens: usage.inputTokens,
|
|
2752
|
+
outputTokens: usage.outputTokens,
|
|
2753
|
+
cacheCreationTokens: usage.cacheCreationInputTokens,
|
|
2754
|
+
...oneHourCacheWriteFields(usage.cacheCreation1hInputTokens),
|
|
2755
|
+
cacheReadTokens: usage.cacheReadInputTokens,
|
|
2756
|
+
};
|
|
2757
|
+
}
|
|
2758
|
+
function setRateLimitUsage(tracer, response, usage) {
|
|
2759
|
+
const rateLimit5h = parseFloat(response.headers.get("anthropic-ratelimit-unified-5h-utilization") ?? "");
|
|
2760
|
+
const rateLimit7d = parseFloat(response.headers.get("anthropic-ratelimit-unified-7d-utilization") ?? "");
|
|
2761
|
+
if (isNaN(rateLimit5h) && isNaN(rateLimit7d)) {
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2764
|
+
const usageUpdate = streamUsageFields(usage);
|
|
2765
|
+
if (!isNaN(rateLimit5h)) {
|
|
2766
|
+
usageUpdate.rateLimitAfter5h = rateLimit5h;
|
|
2767
|
+
}
|
|
2768
|
+
if (!isNaN(rateLimit7d)) {
|
|
2769
|
+
usageUpdate.rateLimitAfter7d = rateLimit7d;
|
|
2770
|
+
}
|
|
2771
|
+
tracer.setUsage(usageUpdate);
|
|
2772
|
+
}
|
|
2773
|
+
function logStreamBodies(args) {
|
|
2774
|
+
const { logProxyBody, headers, data, clientBody, requestStartTime } = args;
|
|
2775
|
+
const common = {
|
|
2776
|
+
headers,
|
|
2777
|
+
contentType: headers["content-type"] ?? "text/event-stream",
|
|
2778
|
+
account: args.account,
|
|
2779
|
+
accountType: args.accountType,
|
|
2780
|
+
attempt: args.attempt,
|
|
2781
|
+
responseStatus: args.responseStatus,
|
|
2782
|
+
};
|
|
2783
|
+
logProxyBody({
|
|
2784
|
+
...common,
|
|
2785
|
+
phase: "upstream_response",
|
|
2786
|
+
body: data.rawText ?? "",
|
|
2787
|
+
sourceTruncated: data.rawTextTruncated,
|
|
2788
|
+
bodySize: data.totalBytesReceived,
|
|
2789
|
+
durationMs: Date.now() - requestStartTime,
|
|
2790
|
+
});
|
|
2791
|
+
logProxyBody({
|
|
2792
|
+
...common,
|
|
2793
|
+
phase: "client_response",
|
|
2794
|
+
body: clientBody.text,
|
|
2795
|
+
sourceTruncated: clientBody.truncated,
|
|
2796
|
+
bodySize: clientBody.totalBytes,
|
|
2797
|
+
durationMs: Date.now() - requestStartTime,
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2739
2800
|
async function handleClaudePassthroughStreamResponse(args) {
|
|
2740
2801
|
const { ctx, bodyStr, response, tracer, requestStartTime, upstreamSpan, upstreamResponseHeaders, logProxyBody, logFinalRequest, } = args;
|
|
2741
2802
|
const responseHeaders = { ...upstreamResponseHeaders };
|
|
@@ -2779,73 +2840,28 @@ async function handleClaudePassthroughStreamResponse(args) {
|
|
|
2779
2840
|
const terminalOutcome = mergeStreamTerminalOutcome(rawOutcome, data.streamErrorMessage, data.messageStopReceived);
|
|
2780
2841
|
observeClaudeStreamOutput(ctx.metadata, data);
|
|
2781
2842
|
const failure = getStreamFailureDetails(terminalOutcome);
|
|
2782
|
-
capturedTracer.setUsage(
|
|
2783
|
-
inputTokens: data.usage.inputTokens,
|
|
2784
|
-
outputTokens: data.usage.outputTokens,
|
|
2785
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
2786
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
2787
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
2788
|
-
});
|
|
2843
|
+
capturedTracer.setUsage(streamUsageFields(data.usage));
|
|
2789
2844
|
capturedTracer.logStreamEvents(data.events);
|
|
2790
2845
|
capturedTracer.setResponseInfo(responseInfoFromStream(data));
|
|
2791
|
-
|
|
2792
|
-
const rateLimit7d = parseFloat(capturedResponse.headers.get("anthropic-ratelimit-unified-7d-utilization") ?? "");
|
|
2793
|
-
const usageUpdate = {
|
|
2794
|
-
inputTokens: data.usage.inputTokens,
|
|
2795
|
-
outputTokens: data.usage.outputTokens,
|
|
2796
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
2797
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
2798
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
2799
|
-
};
|
|
2800
|
-
if (!isNaN(rateLimit5h)) {
|
|
2801
|
-
usageUpdate.rateLimitAfter5h = rateLimit5h;
|
|
2802
|
-
}
|
|
2803
|
-
if (!isNaN(rateLimit7d)) {
|
|
2804
|
-
usageUpdate.rateLimitAfter7d = rateLimit7d;
|
|
2805
|
-
}
|
|
2806
|
-
if (!isNaN(rateLimit5h) || !isNaN(rateLimit7d)) {
|
|
2807
|
-
capturedTracer.setUsage(usageUpdate);
|
|
2808
|
-
}
|
|
2846
|
+
setRateLimitUsage(capturedTracer, capturedResponse, data.usage);
|
|
2809
2847
|
capturedTracer.logUpstreamResponseBody(data.rawText ?? "");
|
|
2810
|
-
capturedTracer.recordMetrics();
|
|
2811
2848
|
capturedTracer.recordBodySizes(capturedRequestBytes, data.totalBytesReceived);
|
|
2812
2849
|
capturedUpstreamSpan?.end();
|
|
2813
2850
|
if (failure) {
|
|
2814
2851
|
capturedTracer.setError(failure.errorType, failure.message);
|
|
2815
2852
|
}
|
|
2816
2853
|
capturedTracer.end(failure?.status ?? response.status, Date.now() - requestStartTime);
|
|
2817
|
-
finalizeStream(failure?.status ?? response.status, failure?.errorType, failure?.message,
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
2821
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
2822
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
2823
|
-
});
|
|
2824
|
-
logProxyBody({
|
|
2825
|
-
phase: "upstream_response",
|
|
2826
|
-
headers: responseHeaders,
|
|
2827
|
-
body: data.rawText ?? "",
|
|
2828
|
-
sourceTruncated: data.rawTextTruncated,
|
|
2829
|
-
bodySize: data.totalBytesReceived,
|
|
2830
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
2831
|
-
account: "passthrough",
|
|
2832
|
-
accountType: "passthrough",
|
|
2833
|
-
attempt: 1,
|
|
2834
|
-
responseStatus: 200,
|
|
2835
|
-
durationMs: Date.now() - requestStartTime,
|
|
2836
|
-
});
|
|
2837
|
-
logProxyBody({
|
|
2838
|
-
phase: "client_response",
|
|
2854
|
+
finalizeStream(failure?.status ?? response.status, failure?.errorType, failure?.message, streamUsageFields(data.usage));
|
|
2855
|
+
logStreamBodies({
|
|
2856
|
+
logProxyBody,
|
|
2839
2857
|
headers: responseHeaders,
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
bodySize: clientBody.totalBytes,
|
|
2843
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
2858
|
+
data,
|
|
2859
|
+
clientBody,
|
|
2844
2860
|
account: "passthrough",
|
|
2845
2861
|
accountType: "passthrough",
|
|
2846
2862
|
attempt: 1,
|
|
2847
2863
|
responseStatus: 200,
|
|
2848
|
-
|
|
2864
|
+
requestStartTime,
|
|
2849
2865
|
});
|
|
2850
2866
|
})
|
|
2851
2867
|
.catch((error) => {
|
|
@@ -2886,38 +2902,17 @@ async function handleClaudePassthroughStreamResponse(args) {
|
|
|
2886
2902
|
const terminalOutcome = mergeStreamTerminalOutcome(rawOutcome, data.streamErrorMessage, data.messageStopReceived);
|
|
2887
2903
|
observeClaudeStreamOutput(ctx.metadata, data);
|
|
2888
2904
|
const failure = getStreamFailureDetails(terminalOutcome);
|
|
2889
|
-
finalizeStream(failure?.status ?? response.status, failure?.errorType, failure?.message,
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
2893
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
2894
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
2895
|
-
});
|
|
2896
|
-
logProxyBody({
|
|
2897
|
-
phase: "upstream_response",
|
|
2898
|
-
headers: responseHeaders,
|
|
2899
|
-
body: data.rawText ?? "",
|
|
2900
|
-
sourceTruncated: data.rawTextTruncated,
|
|
2901
|
-
bodySize: data.totalBytesReceived,
|
|
2902
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
2903
|
-
account: "passthrough",
|
|
2904
|
-
accountType: "passthrough",
|
|
2905
|
-
attempt: 1,
|
|
2906
|
-
responseStatus: response.status,
|
|
2907
|
-
durationMs: Date.now() - requestStartTime,
|
|
2908
|
-
});
|
|
2909
|
-
logProxyBody({
|
|
2910
|
-
phase: "client_response",
|
|
2905
|
+
finalizeStream(failure?.status ?? response.status, failure?.errorType, failure?.message, streamUsageFields(data.usage));
|
|
2906
|
+
logStreamBodies({
|
|
2907
|
+
logProxyBody,
|
|
2911
2908
|
headers: responseHeaders,
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
bodySize: clientBody.totalBytes,
|
|
2915
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
2909
|
+
data,
|
|
2910
|
+
clientBody,
|
|
2916
2911
|
account: "passthrough",
|
|
2917
2912
|
accountType: "passthrough",
|
|
2918
2913
|
attempt: 1,
|
|
2919
2914
|
responseStatus: response.status,
|
|
2920
|
-
|
|
2915
|
+
requestStartTime,
|
|
2921
2916
|
});
|
|
2922
2917
|
})
|
|
2923
2918
|
.catch((error) => {
|
|
@@ -3012,7 +3007,6 @@ async function handleClaudePassthroughJsonResponse(args) {
|
|
|
3012
3007
|
}
|
|
3013
3008
|
}
|
|
3014
3009
|
tracer.setResponseInfo(extractResponseInfo(responseJson));
|
|
3015
|
-
tracer.recordMetrics();
|
|
3016
3010
|
const responseJsonStr = JSON.stringify(responseJson);
|
|
3017
3011
|
tracer.recordBodySizes(bodyStr.length, responseJsonStr.length);
|
|
3018
3012
|
upstreamSpan?.end();
|
|
@@ -5251,99 +5245,38 @@ function attachAnthropicSuccessStreamTelemetry(args) {
|
|
|
5251
5245
|
const capturedResponse = response;
|
|
5252
5246
|
const capturedRequestBytes = finalBodyStr.length;
|
|
5253
5247
|
const capturedAccountLabel = account.label;
|
|
5254
|
-
const capturedAccountKey = account.key;
|
|
5255
5248
|
telemetryDone = Promise.all([telemetry, clientCapture, streamOutcome])
|
|
5256
5249
|
.then(([data, clientBody, rawOutcome]) => {
|
|
5257
5250
|
const terminalOutcome = mergeStreamTerminalOutcome(rawOutcome, data.streamErrorMessage, data.messageStopReceived);
|
|
5258
5251
|
observeClaudeStreamOutput(ctx.metadata, data);
|
|
5259
5252
|
recordCommittedAnthropicStreamAttemptFailure(terminalOutcome, account, logAttempt);
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
outputTokens: data.usage.outputTokens,
|
|
5263
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5264
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
5265
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5266
|
-
});
|
|
5253
|
+
const usage = streamUsageFields(data.usage);
|
|
5254
|
+
capturedTracer.setUsage(usage);
|
|
5267
5255
|
// Bill the borrowing grant from the same totals. A stream's usage is
|
|
5268
5256
|
// only final at message_delta, which is exactly here.
|
|
5269
|
-
|
|
5270
|
-
inputTokens: data.usage.inputTokens,
|
|
5271
|
-
outputTokens: data.usage.outputTokens,
|
|
5272
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5273
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5274
|
-
});
|
|
5275
|
-
recordLeasedAccountSpend(capturedAccountLabel, data.model, {
|
|
5276
|
-
inputTokens: data.usage.inputTokens,
|
|
5277
|
-
outputTokens: data.usage.outputTokens,
|
|
5278
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5279
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5280
|
-
});
|
|
5257
|
+
settleStreamSpend(account, data.model, usage);
|
|
5281
5258
|
capturedTracer.logStreamEvents(data.events);
|
|
5282
5259
|
capturedTracer.setResponseInfo(responseInfoFromStream(data));
|
|
5283
|
-
|
|
5284
|
-
const rateLimit7d = parseFloat(capturedResponse.headers.get("anthropic-ratelimit-unified-7d-utilization") ?? "");
|
|
5285
|
-
const usageUpdate = {
|
|
5286
|
-
inputTokens: data.usage.inputTokens,
|
|
5287
|
-
outputTokens: data.usage.outputTokens,
|
|
5288
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5289
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
5290
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5291
|
-
};
|
|
5292
|
-
if (!isNaN(rateLimit5h)) {
|
|
5293
|
-
usageUpdate.rateLimitAfter5h = rateLimit5h;
|
|
5294
|
-
}
|
|
5295
|
-
if (!isNaN(rateLimit7d)) {
|
|
5296
|
-
usageUpdate.rateLimitAfter7d = rateLimit7d;
|
|
5297
|
-
}
|
|
5298
|
-
if (!isNaN(rateLimit5h) || !isNaN(rateLimit7d)) {
|
|
5299
|
-
capturedTracer.setUsage(usageUpdate);
|
|
5300
|
-
}
|
|
5260
|
+
setRateLimitUsage(capturedTracer, capturedResponse, data.usage);
|
|
5301
5261
|
capturedTracer.logUpstreamResponseBody(data.rawText ?? "");
|
|
5302
|
-
capturedTracer.recordMetrics();
|
|
5303
5262
|
capturedTracer.recordBodySizes(capturedRequestBytes, data.totalBytesReceived);
|
|
5304
5263
|
capturedUpstreamSpan?.end();
|
|
5305
5264
|
const failure = getStreamFailureDetails(terminalOutcome);
|
|
5306
|
-
const usage = {
|
|
5307
|
-
inputTokens: data.usage.inputTokens,
|
|
5308
|
-
outputTokens: data.usage.outputTokens,
|
|
5309
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5310
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
5311
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5312
|
-
};
|
|
5313
5265
|
if (failure) {
|
|
5314
5266
|
capturedTracer.setError(failure.errorType, failure.message);
|
|
5315
|
-
capturedTracer.end(failure.status, Date.now() - requestStartTime);
|
|
5316
|
-
logFinalRequest(failure.status, capturedAccountLabel, account.type, failure.errorType, failure.message, usage);
|
|
5317
|
-
}
|
|
5318
|
-
else {
|
|
5319
|
-
capturedTracer.end(200, Date.now() - requestStartTime);
|
|
5320
|
-
logFinalRequest(200, capturedAccountLabel, account.type, undefined, undefined, usage);
|
|
5321
5267
|
}
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
sourceTruncated: data.rawTextTruncated,
|
|
5327
|
-
bodySize: data.totalBytesReceived,
|
|
5328
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
5329
|
-
account: capturedAccountLabel,
|
|
5330
|
-
accountType: account.type,
|
|
5331
|
-
attempt: attemptNumber,
|
|
5332
|
-
responseStatus: 200,
|
|
5333
|
-
durationMs: Date.now() - requestStartTime,
|
|
5334
|
-
});
|
|
5335
|
-
logProxyBody({
|
|
5336
|
-
phase: "client_response",
|
|
5268
|
+
capturedTracer.end(failure?.status ?? 200, Date.now() - requestStartTime);
|
|
5269
|
+
logStreamFinal(logFinalRequest, failure, capturedAccountLabel, account.type, usage);
|
|
5270
|
+
logStreamBodies({
|
|
5271
|
+
logProxyBody,
|
|
5337
5272
|
headers: responseHeaders,
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
bodySize: clientBody.totalBytes,
|
|
5341
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
5273
|
+
data,
|
|
5274
|
+
clientBody,
|
|
5342
5275
|
account: capturedAccountLabel,
|
|
5343
5276
|
accountType: account.type,
|
|
5344
5277
|
attempt: attemptNumber,
|
|
5345
5278
|
responseStatus: 200,
|
|
5346
|
-
|
|
5279
|
+
requestStartTime,
|
|
5347
5280
|
});
|
|
5348
5281
|
})
|
|
5349
5282
|
.catch((error) => {
|
|
@@ -5382,7 +5315,6 @@ function attachAnthropicSuccessStreamTelemetry(args) {
|
|
|
5382
5315
|
});
|
|
5383
5316
|
streamSource = streamSource.pipeThrough(noTracerInterceptor);
|
|
5384
5317
|
const capturedAccountLabel = account.label;
|
|
5385
|
-
const capturedAccountKey = account.key;
|
|
5386
5318
|
telemetryDone = Promise.all([
|
|
5387
5319
|
noTracerTelemetry,
|
|
5388
5320
|
clientCapture,
|
|
@@ -5393,48 +5325,21 @@ function attachAnthropicSuccessStreamTelemetry(args) {
|
|
|
5393
5325
|
observeClaudeStreamOutput(ctx.metadata, data);
|
|
5394
5326
|
recordCommittedAnthropicStreamAttemptFailure(terminalOutcome, account, logAttempt);
|
|
5395
5327
|
const failure = getStreamFailureDetails(terminalOutcome);
|
|
5396
|
-
const usage =
|
|
5397
|
-
inputTokens: data.usage.inputTokens,
|
|
5398
|
-
outputTokens: data.usage.outputTokens,
|
|
5399
|
-
cacheCreationTokens: data.usage.cacheCreationInputTokens,
|
|
5400
|
-
...oneHourCacheWriteFields(data.usage.cacheCreation1hInputTokens),
|
|
5401
|
-
cacheReadTokens: data.usage.cacheReadInputTokens,
|
|
5402
|
-
};
|
|
5328
|
+
const usage = streamUsageFields(data.usage);
|
|
5403
5329
|
// Settled on the untraced path too: whether telemetry is exported has
|
|
5404
5330
|
// nothing to do with whether a borrower should be charged.
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
}
|
|
5410
|
-
else {
|
|
5411
|
-
logFinalRequest(200, capturedAccountLabel, account.type, undefined, undefined, usage);
|
|
5412
|
-
}
|
|
5413
|
-
logProxyBody({
|
|
5414
|
-
phase: "upstream_response",
|
|
5415
|
-
headers: responseHeaders,
|
|
5416
|
-
body: data.rawText ?? "",
|
|
5417
|
-
sourceTruncated: data.rawTextTruncated,
|
|
5418
|
-
bodySize: data.totalBytesReceived,
|
|
5419
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
5420
|
-
account: capturedAccountLabel,
|
|
5421
|
-
accountType: account.type,
|
|
5422
|
-
attempt: attemptNumber,
|
|
5423
|
-
responseStatus: 200,
|
|
5424
|
-
durationMs: Date.now() - requestStartTime,
|
|
5425
|
-
});
|
|
5426
|
-
logProxyBody({
|
|
5427
|
-
phase: "client_response",
|
|
5331
|
+
settleStreamSpend(account, data.model, usage);
|
|
5332
|
+
logStreamFinal(logFinalRequest, failure, capturedAccountLabel, account.type, usage);
|
|
5333
|
+
logStreamBodies({
|
|
5334
|
+
logProxyBody,
|
|
5428
5335
|
headers: responseHeaders,
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
bodySize: clientBody.totalBytes,
|
|
5432
|
-
contentType: responseHeaders["content-type"] ?? "text/event-stream",
|
|
5336
|
+
data,
|
|
5337
|
+
clientBody,
|
|
5433
5338
|
account: capturedAccountLabel,
|
|
5434
5339
|
accountType: account.type,
|
|
5435
5340
|
attempt: attemptNumber,
|
|
5436
5341
|
responseStatus: 200,
|
|
5437
|
-
|
|
5342
|
+
requestStartTime,
|
|
5438
5343
|
});
|
|
5439
5344
|
})
|
|
5440
5345
|
.catch((error) => {
|
|
@@ -5569,7 +5474,6 @@ async function handleAnthropicJsonSuccessResponse(args) {
|
|
|
5569
5474
|
}
|
|
5570
5475
|
}
|
|
5571
5476
|
tracer.setResponseInfo(extractResponseInfo(responseJson));
|
|
5572
|
-
tracer.recordMetrics();
|
|
5573
5477
|
const responseJsonStr = JSON.stringify(responseJson);
|
|
5574
5478
|
tracer.recordBodySizes(finalBodyStr.length, responseJsonStr.length);
|
|
5575
5479
|
upstreamSpan?.end();
|
|
@@ -5672,7 +5576,6 @@ async function handleAnthropicSuccessfulNonStreamRetryResponse(args) {
|
|
|
5672
5576
|
});
|
|
5673
5577
|
}
|
|
5674
5578
|
tracer.setResponseInfo(extractResponseInfo(retryJson));
|
|
5675
|
-
tracer.recordMetrics();
|
|
5676
5579
|
const retryJsonStr = JSON.stringify(retryJson);
|
|
5677
5580
|
tracer.recordBodySizes(finalBodyStr.length, retryJsonStr.length);
|
|
5678
5581
|
upstreamSpan?.end();
|
|
@@ -8518,7 +8421,7 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
|
|
|
8518
8421
|
? runtimeConfigProvider().modelRouter
|
|
8519
8422
|
: modelRouter;
|
|
8520
8423
|
return withSpan({
|
|
8521
|
-
name: "
|
|
8424
|
+
name: "http.claudeProxy.listModels",
|
|
8522
8425
|
tracer: tracers.http,
|
|
8523
8426
|
attributes: { "http.route": `${basePath}/v1/models` },
|
|
8524
8427
|
}, async () => buildAnthropicModelsListResponse(requestModelRouter));
|
|
@@ -8533,7 +8436,7 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
|
|
|
8533
8436
|
method: "POST",
|
|
8534
8437
|
path: `${basePath}/v1/messages/count_tokens`,
|
|
8535
8438
|
handler: async (ctx) => withSpan({
|
|
8536
|
-
name: "
|
|
8439
|
+
name: "http.claudeProxy.countTokens",
|
|
8537
8440
|
tracer: tracers.http,
|
|
8538
8441
|
attributes: {
|
|
8539
8442
|
"http.route": `${basePath}/v1/messages/count_tokens`,
|
|
@@ -8552,7 +8455,7 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
|
|
|
8552
8455
|
.join(" ");
|
|
8553
8456
|
const inputTokens = Math.ceil(text.length / 4);
|
|
8554
8457
|
span.setAttribute("ai.model", body.model);
|
|
8555
|
-
span.setAttribute("
|
|
8458
|
+
span.setAttribute("ai.tokens.input", inputTokens);
|
|
8556
8459
|
return { input_tokens: inputTokens };
|
|
8557
8460
|
}),
|
|
8558
8461
|
description: "Count tokens for a messages request",
|
|
@@ -8587,7 +8490,7 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
|
|
|
8587
8490
|
const snapshotOnly = ctx.query?.snapshot === "true" || ctx.query?.snapshot === "1";
|
|
8588
8491
|
const accountFilter = ctx.query?.account;
|
|
8589
8492
|
return withSpan({
|
|
8590
|
-
name: "
|
|
8493
|
+
name: "http.claudeProxy.limits",
|
|
8591
8494
|
tracer: tracers.http,
|
|
8592
8495
|
attributes: { "http.route": `${basePath}/limits` },
|
|
8593
8496
|
}, async () => {
|