@sentry/core 10.46.0 → 10.48.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/build/cjs/api.js +1 -0
- package/build/cjs/api.js.map +1 -1
- package/build/cjs/attributes.js +43 -0
- package/build/cjs/attributes.js.map +1 -1
- package/build/cjs/client.js +13 -6
- package/build/cjs/client.js.map +1 -1
- package/build/cjs/currentScopes.js +33 -0
- package/build/cjs/currentScopes.js.map +1 -1
- package/build/cjs/envelope.js +4 -3
- package/build/cjs/envelope.js.map +1 -1
- package/build/cjs/index.js +50 -13
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/integration.js +6 -0
- package/build/cjs/integration.js.map +1 -1
- package/build/cjs/integrations/express/index.js +206 -0
- package/build/cjs/integrations/express/index.js.map +1 -0
- package/build/cjs/integrations/express/patch-layer.js +251 -0
- package/build/cjs/integrations/express/patch-layer.js.map +1 -0
- package/build/cjs/integrations/express/request-layer-store.js +25 -0
- package/build/cjs/integrations/express/request-layer-store.js.map +1 -0
- package/build/cjs/integrations/express/set-sdk-processing-metadata.js +17 -0
- package/build/cjs/integrations/express/set-sdk-processing-metadata.js.map +1 -0
- package/build/cjs/integrations/express/types.js +17 -0
- package/build/cjs/integrations/express/types.js.map +1 -0
- package/build/cjs/integrations/express/utils.js +238 -0
- package/build/cjs/integrations/express/utils.js.map +1 -0
- package/build/cjs/integrations/mcp-server/correlation.js +5 -1
- package/build/cjs/integrations/mcp-server/correlation.js.map +1 -1
- package/build/cjs/integrations/mcp-server/handlers.js +18 -10
- package/build/cjs/integrations/mcp-server/handlers.js.map +1 -1
- package/build/cjs/integrations/mcp-server/index.js +2 -1
- package/build/cjs/integrations/mcp-server/index.js.map +1 -1
- package/build/cjs/integrations/mcp-server/transport.js +1 -1
- package/build/cjs/integrations/mcp-server/transport.js.map +1 -1
- package/build/cjs/integrations/mcp-server/validation.js +7 -5
- package/build/cjs/integrations/mcp-server/validation.js.map +1 -1
- package/build/cjs/integrations/spanStreaming.js +48 -0
- package/build/cjs/integrations/spanStreaming.js.map +1 -0
- package/build/cjs/integrations/supabase.js +1 -1
- package/build/cjs/integrations/supabase.js.map +1 -1
- package/build/cjs/semanticAttributes.js +35 -3
- package/build/cjs/semanticAttributes.js.map +1 -1
- package/build/cjs/tracing/ai/gen-ai-attributes.js +9 -79
- package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/cjs/tracing/ai/utils.js +50 -35
- package/build/cjs/tracing/ai/utils.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/constants.js +10 -10
- package/build/cjs/tracing/anthropic-ai/constants.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/index.js +18 -20
- package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/streaming.js +2 -100
- package/build/cjs/tracing/anthropic-ai/streaming.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/utils.js +0 -9
- package/build/cjs/tracing/anthropic-ai/utils.js.map +1 -1
- package/build/cjs/tracing/dynamicSamplingContext.js +2 -1
- package/build/cjs/tracing/dynamicSamplingContext.js.map +1 -1
- package/build/cjs/tracing/google-genai/constants.js +9 -12
- package/build/cjs/tracing/google-genai/constants.js.map +1 -1
- package/build/cjs/tracing/google-genai/index.js +49 -27
- package/build/cjs/tracing/google-genai/index.js.map +1 -1
- package/build/cjs/tracing/google-genai/streaming.js +2 -23
- package/build/cjs/tracing/google-genai/streaming.js.map +1 -1
- package/build/cjs/tracing/google-genai/utils.js +0 -25
- package/build/cjs/tracing/google-genai/utils.js.map +1 -1
- package/build/cjs/tracing/langchain/embeddings.js +132 -0
- package/build/cjs/tracing/langchain/embeddings.js.map +1 -0
- package/build/cjs/tracing/langchain/index.js.map +1 -1
- package/build/cjs/tracing/openai/constants.js +7 -7
- package/build/cjs/tracing/openai/constants.js.map +1 -1
- package/build/cjs/tracing/openai/index.js +19 -37
- package/build/cjs/tracing/openai/index.js.map +1 -1
- package/build/cjs/tracing/openai/streaming.js +3 -34
- package/build/cjs/tracing/openai/streaming.js.map +1 -1
- package/build/cjs/tracing/openai/utils.js +78 -243
- package/build/cjs/tracing/openai/utils.js.map +1 -1
- package/build/cjs/tracing/sentryNonRecordingSpan.js +7 -0
- package/build/cjs/tracing/sentryNonRecordingSpan.js.map +1 -1
- package/build/cjs/tracing/sentrySpan.js +39 -0
- package/build/cjs/tracing/sentrySpan.js.map +1 -1
- package/build/cjs/tracing/spans/beforeSendSpan.js +43 -0
- package/build/cjs/tracing/spans/beforeSendSpan.js.map +1 -0
- package/build/cjs/tracing/spans/captureSpan.js +126 -0
- package/build/cjs/tracing/spans/captureSpan.js.map +1 -0
- package/build/cjs/tracing/spans/envelope.js +38 -0
- package/build/cjs/tracing/spans/envelope.js.map +1 -0
- package/build/cjs/tracing/spans/estimateSize.js +41 -0
- package/build/cjs/tracing/spans/estimateSize.js.map +1 -0
- package/build/cjs/tracing/spans/hasSpanStreamingEnabled.js +11 -0
- package/build/cjs/tracing/spans/hasSpanStreamingEnabled.js.map +1 -0
- package/build/cjs/tracing/spans/spanBuffer.js +158 -0
- package/build/cjs/tracing/spans/spanBuffer.js.map +1 -0
- package/build/cjs/tracing/trace.js +88 -13
- package/build/cjs/tracing/trace.js.map +1 -1
- package/build/cjs/tracing/vercel-ai/utils.js +1 -4
- package/build/cjs/tracing/vercel-ai/utils.js.map +1 -1
- package/build/cjs/utils/featureFlags.js +6 -0
- package/build/cjs/utils/featureFlags.js.map +1 -1
- package/build/cjs/utils/object.js +33 -0
- package/build/cjs/utils/object.js.map +1 -1
- package/build/cjs/utils/spanUtils.js +116 -13
- package/build/cjs/utils/spanUtils.js.map +1 -1
- package/build/cjs/utils/stacktrace.js +3 -1
- package/build/cjs/utils/stacktrace.js.map +1 -1
- package/build/cjs/utils/string.js +3 -0
- package/build/cjs/utils/string.js.map +1 -1
- package/build/cjs/utils/traceData.js +11 -0
- package/build/cjs/utils/traceData.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/esm/api.js +1 -1
- package/build/esm/api.js.map +1 -1
- package/build/esm/attributes.js +43 -1
- package/build/esm/attributes.js.map +1 -1
- package/build/esm/client.js +8 -1
- package/build/esm/client.js.map +1 -1
- package/build/esm/currentScopes.js +31 -1
- package/build/esm/currentScopes.js.map +1 -1
- package/build/esm/envelope.js +2 -1
- package/build/esm/envelope.js.map +1 -1
- package/build/esm/index.js +13 -4
- package/build/esm/index.js.map +1 -1
- package/build/esm/integration.js +6 -0
- package/build/esm/integration.js.map +1 -1
- package/build/esm/integrations/express/index.js +202 -0
- package/build/esm/integrations/express/index.js.map +1 -0
- package/build/esm/integrations/express/patch-layer.js +249 -0
- package/build/esm/integrations/express/patch-layer.js.map +1 -0
- package/build/esm/integrations/express/request-layer-store.js +22 -0
- package/build/esm/integrations/express/request-layer-store.js.map +1 -0
- package/build/esm/integrations/express/set-sdk-processing-metadata.js +15 -0
- package/build/esm/integrations/express/set-sdk-processing-metadata.js.map +1 -0
- package/build/esm/integrations/express/types.js +10 -0
- package/build/esm/integrations/express/types.js.map +1 -0
- package/build/esm/integrations/express/utils.js +225 -0
- package/build/esm/integrations/express/utils.js.map +1 -0
- package/build/esm/integrations/mcp-server/correlation.js +5 -1
- package/build/esm/integrations/mcp-server/correlation.js.map +1 -1
- package/build/esm/integrations/mcp-server/handlers.js +18 -10
- package/build/esm/integrations/mcp-server/handlers.js.map +1 -1
- package/build/esm/integrations/mcp-server/index.js +2 -1
- package/build/esm/integrations/mcp-server/index.js.map +1 -1
- package/build/esm/integrations/mcp-server/transport.js +1 -1
- package/build/esm/integrations/mcp-server/transport.js.map +1 -1
- package/build/esm/integrations/mcp-server/validation.js +7 -5
- package/build/esm/integrations/mcp-server/validation.js.map +1 -1
- package/build/esm/integrations/spanStreaming.js +46 -0
- package/build/esm/integrations/spanStreaming.js.map +1 -0
- package/build/esm/integrations/supabase.js +1 -1
- package/build/esm/integrations/supabase.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/semanticAttributes.js +26 -4
- package/build/esm/semanticAttributes.js.map +1 -1
- package/build/esm/tracing/ai/gen-ai-attributes.js +8 -69
- package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
- package/build/esm/tracing/ai/utils.js +51 -35
- package/build/esm/tracing/ai/utils.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/constants.js +10 -10
- package/build/esm/tracing/anthropic-ai/constants.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/index.js +21 -23
- package/build/esm/tracing/anthropic-ai/index.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/streaming.js +3 -101
- package/build/esm/tracing/anthropic-ai/streaming.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/utils.js +1 -9
- package/build/esm/tracing/anthropic-ai/utils.js.map +1 -1
- package/build/esm/tracing/dynamicSamplingContext.js +2 -1
- package/build/esm/tracing/dynamicSamplingContext.js.map +1 -1
- package/build/esm/tracing/google-genai/constants.js +9 -10
- package/build/esm/tracing/google-genai/constants.js.map +1 -1
- package/build/esm/tracing/google-genai/index.js +53 -31
- package/build/esm/tracing/google-genai/index.js.map +1 -1
- package/build/esm/tracing/google-genai/streaming.js +2 -23
- package/build/esm/tracing/google-genai/streaming.js.map +1 -1
- package/build/esm/tracing/google-genai/utils.js +1 -24
- package/build/esm/tracing/google-genai/utils.js.map +1 -1
- package/build/esm/tracing/langchain/embeddings.js +129 -0
- package/build/esm/tracing/langchain/embeddings.js.map +1 -0
- package/build/esm/tracing/langchain/index.js.map +1 -1
- package/build/esm/tracing/openai/constants.js +7 -7
- package/build/esm/tracing/openai/constants.js.map +1 -1
- package/build/esm/tracing/openai/index.js +21 -39
- package/build/esm/tracing/openai/index.js.map +1 -1
- package/build/esm/tracing/openai/streaming.js +4 -35
- package/build/esm/tracing/openai/streaming.js.map +1 -1
- package/build/esm/tracing/openai/utils.js +79 -232
- package/build/esm/tracing/openai/utils.js.map +1 -1
- package/build/esm/tracing/sentryNonRecordingSpan.js +7 -0
- package/build/esm/tracing/sentryNonRecordingSpan.js.map +1 -1
- package/build/esm/tracing/sentrySpan.js +40 -1
- package/build/esm/tracing/sentrySpan.js.map +1 -1
- package/build/esm/tracing/spans/beforeSendSpan.js +40 -0
- package/build/esm/tracing/spans/beforeSendSpan.js.map +1 -0
- package/build/esm/tracing/spans/captureSpan.js +122 -0
- package/build/esm/tracing/spans/captureSpan.js.map +1 -0
- package/build/esm/tracing/spans/envelope.js +36 -0
- package/build/esm/tracing/spans/envelope.js.map +1 -0
- package/build/esm/tracing/spans/estimateSize.js +39 -0
- package/build/esm/tracing/spans/estimateSize.js.map +1 -0
- package/build/esm/tracing/spans/hasSpanStreamingEnabled.js +9 -0
- package/build/esm/tracing/spans/hasSpanStreamingEnabled.js.map +1 -0
- package/build/esm/tracing/spans/spanBuffer.js +156 -0
- package/build/esm/tracing/spans/spanBuffer.js.map +1 -0
- package/build/esm/tracing/trace.js +89 -14
- package/build/esm/tracing/trace.js.map +1 -1
- package/build/esm/tracing/vercel-ai/utils.js +2 -5
- package/build/esm/tracing/vercel-ai/utils.js.map +1 -1
- package/build/esm/utils/featureFlags.js +6 -0
- package/build/esm/utils/featureFlags.js.map +1 -1
- package/build/esm/utils/object.js +33 -1
- package/build/esm/utils/object.js.map +1 -1
- package/build/esm/utils/spanUtils.js +112 -14
- package/build/esm/utils/spanUtils.js.map +1 -1
- package/build/esm/utils/stacktrace.js +3 -1
- package/build/esm/utils/stacktrace.js.map +1 -1
- package/build/esm/utils/string.js +3 -0
- package/build/esm/utils/string.js.map +1 -1
- package/build/esm/utils/traceData.js +12 -1
- package/build/esm/utils/traceData.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/types/api.d.ts +1 -0
- package/build/types/api.d.ts.map +1 -1
- package/build/types/asyncContext/types.d.ts +3 -1
- package/build/types/asyncContext/types.d.ts.map +1 -1
- package/build/types/attributes.d.ts +5 -0
- package/build/types/attributes.d.ts.map +1 -1
- package/build/types/client.d.ts +35 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/currentScopes.d.ts +20 -0
- package/build/types/currentScopes.d.ts.map +1 -1
- package/build/types/envelope.d.ts.map +1 -1
- package/build/types/index.d.ts +15 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/integration.d.ts.map +1 -1
- package/build/types/integrations/express/index.d.ts +75 -0
- package/build/types/integrations/express/index.d.ts.map +1 -0
- package/build/types/integrations/express/patch-layer.d.ts +32 -0
- package/build/types/integrations/express/patch-layer.d.ts.map +1 -0
- package/build/types/integrations/express/request-layer-store.d.ts +32 -0
- package/build/types/integrations/express/request-layer-store.d.ts.map +1 -0
- package/build/types/integrations/express/set-sdk-processing-metadata.d.ts +35 -0
- package/build/types/integrations/express/set-sdk-processing-metadata.d.ts.map +1 -0
- package/build/types/integrations/express/types.d.ts +154 -0
- package/build/types/integrations/express/types.d.ts.map +1 -0
- package/build/types/integrations/express/utils.d.ts +93 -0
- package/build/types/integrations/express/utils.d.ts.map +1 -0
- package/build/types/integrations/mcp-server/correlation.d.ts +2 -1
- package/build/types/integrations/mcp-server/correlation.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/handlers.d.ts +9 -4
- package/build/types/integrations/mcp-server/handlers.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/index.d.ts +2 -1
- package/build/types/integrations/mcp-server/index.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/types.d.ts +40 -7
- package/build/types/integrations/mcp-server/types.d.ts.map +1 -1
- package/build/types/integrations/mcp-server/validation.d.ts +4 -1
- package/build/types/integrations/mcp-server/validation.d.ts.map +1 -1
- package/build/types/integrations/spanStreaming.d.ts +2 -0
- package/build/types/integrations/spanStreaming.d.ts.map +1 -0
- package/build/types/semanticAttributes.d.ts +23 -3
- package/build/types/semanticAttributes.d.ts.map +1 -1
- package/build/types/tracing/ai/gen-ai-attributes.d.ts +6 -46
- package/build/types/tracing/ai/gen-ai-attributes.d.ts.map +1 -1
- package/build/types/tracing/ai/utils.d.ts +34 -9
- package/build/types/tracing/ai/utils.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/constants.d.ts +24 -1
- package/build/types/tracing/anthropic-ai/constants.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/index.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/streaming.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/types.d.ts +5 -2
- package/build/types/tracing/anthropic-ai/types.d.ts.map +1 -1
- package/build/types/tracing/anthropic-ai/utils.d.ts +1 -5
- package/build/types/tracing/anthropic-ai/utils.d.ts.map +1 -1
- package/build/types/tracing/dynamicSamplingContext.d.ts.map +1 -1
- package/build/types/tracing/google-genai/constants.d.ts +22 -3
- package/build/types/tracing/google-genai/constants.d.ts.map +1 -1
- package/build/types/tracing/google-genai/index.d.ts.map +1 -1
- package/build/types/tracing/google-genai/streaming.d.ts.map +1 -1
- package/build/types/tracing/google-genai/types.d.ts +6 -2
- package/build/types/tracing/google-genai/types.d.ts.map +1 -1
- package/build/types/tracing/google-genai/utils.d.ts +0 -9
- package/build/types/tracing/google-genai/utils.d.ts.map +1 -1
- package/build/types/tracing/index.d.ts +1 -0
- package/build/types/tracing/index.d.ts.map +1 -1
- package/build/types/tracing/langchain/embeddings.d.ts +27 -0
- package/build/types/tracing/langchain/embeddings.d.ts.map +1 -0
- package/build/types/tracing/langchain/index.d.ts +1 -0
- package/build/types/tracing/langchain/index.d.ts.map +1 -1
- package/build/types/tracing/openai/constants.d.ts +14 -1
- package/build/types/tracing/openai/constants.d.ts.map +1 -1
- package/build/types/tracing/openai/index.d.ts.map +1 -1
- package/build/types/tracing/openai/streaming.d.ts.map +1 -1
- package/build/types/tracing/openai/types.d.ts +5 -2
- package/build/types/tracing/openai/types.d.ts.map +1 -1
- package/build/types/tracing/openai/utils.d.ts +4 -63
- package/build/types/tracing/openai/utils.d.ts.map +1 -1
- package/build/types/tracing/sentryNonRecordingSpan.d.ts +12 -1
- package/build/types/tracing/sentryNonRecordingSpan.d.ts.map +1 -1
- package/build/types/tracing/sentrySpan.d.ts +10 -1
- package/build/types/tracing/sentrySpan.d.ts.map +1 -1
- package/build/types/tracing/spans/beforeSendSpan.d.ts +35 -0
- package/build/types/tracing/spans/beforeSendSpan.d.ts.map +1 -0
- package/build/types/tracing/spans/captureSpan.d.ts +26 -0
- package/build/types/tracing/spans/captureSpan.d.ts.map +1 -0
- package/build/types/tracing/spans/envelope.d.ts +8 -0
- package/build/types/tracing/spans/envelope.d.ts.map +1 -0
- package/build/types/tracing/spans/estimateSize.d.ts +12 -0
- package/build/types/tracing/spans/estimateSize.d.ts.map +1 -0
- package/build/types/tracing/spans/hasSpanStreamingEnabled.d.ts +6 -0
- package/build/types/tracing/spans/hasSpanStreamingEnabled.d.ts.map +1 -0
- package/build/types/tracing/spans/spanBuffer.d.ts +60 -0
- package/build/types/tracing/spans/spanBuffer.d.ts.map +1 -0
- package/build/types/tracing/trace.d.ts.map +1 -1
- package/build/types/tracing/vercel-ai/utils.d.ts.map +1 -1
- package/build/types/types-hoist/envelope.d.ts +22 -2
- package/build/types/types-hoist/envelope.d.ts.map +1 -1
- package/build/types/types-hoist/integration.d.ts +8 -0
- package/build/types/types-hoist/integration.d.ts.map +1 -1
- package/build/types/types-hoist/link.d.ts +2 -2
- package/build/types/types-hoist/link.d.ts.map +1 -1
- package/build/types/types-hoist/options.d.ts +26 -2
- package/build/types/types-hoist/options.d.ts.map +1 -1
- package/build/types/types-hoist/span.d.ts +35 -0
- package/build/types/types-hoist/span.d.ts.map +1 -1
- package/build/types/utils/featureFlags.d.ts.map +1 -1
- package/build/types/utils/object.d.ts +10 -0
- package/build/types/utils/object.d.ts.map +1 -1
- package/build/types/utils/spanUtils.d.ts +27 -2
- package/build/types/utils/spanUtils.d.ts.map +1 -1
- package/build/types/utils/stacktrace.d.ts.map +1 -1
- package/build/types/utils/string.d.ts +2 -2
- package/build/types/utils/string.d.ts.map +1 -1
- package/build/types/utils/traceData.d.ts +4 -0
- package/build/types/utils/traceData.d.ts.map +1 -1
- package/build/types-ts3.8/api.d.ts +1 -0
- package/build/types-ts3.8/asyncContext/types.d.ts +3 -1
- package/build/types-ts3.8/attributes.d.ts +5 -0
- package/build/types-ts3.8/client.d.ts +35 -1
- package/build/types-ts3.8/currentScopes.d.ts +20 -0
- package/build/types-ts3.8/index.d.ts +15 -6
- package/build/types-ts3.8/integrations/express/index.d.ts +75 -0
- package/build/types-ts3.8/integrations/express/patch-layer.d.ts +32 -0
- package/build/types-ts3.8/integrations/express/request-layer-store.d.ts +32 -0
- package/build/types-ts3.8/integrations/express/set-sdk-processing-metadata.d.ts +35 -0
- package/build/types-ts3.8/integrations/express/types.d.ts +154 -0
- package/build/types-ts3.8/integrations/express/utils.d.ts +96 -0
- package/build/types-ts3.8/integrations/mcp-server/correlation.d.ts +2 -1
- package/build/types-ts3.8/integrations/mcp-server/handlers.d.ts +9 -4
- package/build/types-ts3.8/integrations/mcp-server/index.d.ts +2 -1
- package/build/types-ts3.8/integrations/mcp-server/types.d.ts +40 -7
- package/build/types-ts3.8/integrations/mcp-server/validation.d.ts +4 -1
- package/build/types-ts3.8/integrations/spanStreaming.d.ts +2 -0
- package/build/types-ts3.8/semanticAttributes.d.ts +23 -3
- package/build/types-ts3.8/tracing/ai/gen-ai-attributes.d.ts +6 -46
- package/build/types-ts3.8/tracing/ai/utils.d.ts +34 -9
- package/build/types-ts3.8/tracing/anthropic-ai/constants.d.ts +24 -9
- package/build/types-ts3.8/tracing/anthropic-ai/types.d.ts +5 -2
- package/build/types-ts3.8/tracing/anthropic-ai/utils.d.ts +1 -5
- package/build/types-ts3.8/tracing/google-genai/constants.d.ts +22 -9
- package/build/types-ts3.8/tracing/google-genai/types.d.ts +6 -2
- package/build/types-ts3.8/tracing/google-genai/utils.d.ts +0 -9
- package/build/types-ts3.8/tracing/index.d.ts +1 -0
- package/build/types-ts3.8/tracing/langchain/embeddings.d.ts +27 -0
- package/build/types-ts3.8/tracing/langchain/index.d.ts +1 -0
- package/build/types-ts3.8/tracing/openai/constants.d.ts +14 -6
- package/build/types-ts3.8/tracing/openai/types.d.ts +5 -2
- package/build/types-ts3.8/tracing/openai/utils.d.ts +4 -63
- package/build/types-ts3.8/tracing/sentryNonRecordingSpan.d.ts +12 -1
- package/build/types-ts3.8/tracing/sentrySpan.d.ts +10 -1
- package/build/types-ts3.8/tracing/spans/beforeSendSpan.d.ts +35 -0
- package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +26 -0
- package/build/types-ts3.8/tracing/spans/envelope.d.ts +8 -0
- package/build/types-ts3.8/tracing/spans/estimateSize.d.ts +12 -0
- package/build/types-ts3.8/tracing/spans/hasSpanStreamingEnabled.d.ts +6 -0
- package/build/types-ts3.8/tracing/spans/spanBuffer.d.ts +60 -0
- package/build/types-ts3.8/types-hoist/envelope.d.ts +22 -2
- package/build/types-ts3.8/types-hoist/integration.d.ts +8 -0
- package/build/types-ts3.8/types-hoist/link.d.ts +2 -2
- package/build/types-ts3.8/types-hoist/options.d.ts +26 -2
- package/build/types-ts3.8/types-hoist/span.d.ts +35 -0
- package/build/types-ts3.8/utils/object.d.ts +10 -0
- package/build/types-ts3.8/utils/spanUtils.d.ts +27 -2
- package/build/types-ts3.8/utils/string.d.ts +2 -2
- package/build/types-ts3.8/utils/traceData.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { resolveAIRecordingOptions } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const { recordInputs, recordOutputs } = resolveAIRecordingOptions(options);\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(\n chain: { name?: string },\n inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ) {\n const chainName = runName || chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n // Add inputs if recordInputs is enabled\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(tool: { name?: string }, input: string, runId: string, _parentRunId?: string) {\n const toolName = tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n };\n\n // Add input if recordInputs is enabled\n if (recordInputs) {\n attributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add output if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n [GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(output),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/langchain/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport {\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { resolveAIRecordingOptions } from '../ai/utils';\nimport { LANGCHAIN_ORIGIN } from './constants';\nimport type {\n LangChainCallbackHandler,\n LangChainLLMResult,\n LangChainMessage,\n LangChainOptions,\n LangChainSerialized,\n} from './types';\nimport {\n extractChatModelRequestAttributes,\n extractLLMRequestAttributes,\n extractLlmResponseAttributes,\n getInvocationParams,\n} from './utils';\n\n/**\n * Creates a Sentry callback handler for LangChain\n * Returns a plain object that LangChain will call via duck-typing\n *\n * This is a stateful handler that tracks spans across multiple LangChain executions.\n */\nexport function createLangChainCallbackHandler(options: LangChainOptions = {}): LangChainCallbackHandler {\n const { recordInputs, recordOutputs } = resolveAIRecordingOptions(options);\n\n // Internal state - single instance tracks all spans\n const spanMap = new Map<string, Span>();\n\n /**\n * Exit a span and clean up\n */\n const exitSpan = (runId: string): void => {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.end();\n spanMap.delete(runId);\n }\n };\n\n /**\n * Handler for LLM Start\n * This handler will be called by LangChain's callback handler when an LLM event is detected.\n */\n const handler: LangChainCallbackHandler = {\n // Required LangChain BaseCallbackHandler properties\n lc_serializable: false,\n lc_namespace: ['langchain_core', 'callbacks', 'sentry'],\n lc_secrets: undefined,\n lc_attributes: undefined,\n lc_aliases: undefined,\n lc_serializable_keys: undefined,\n lc_id: ['langchain_core', 'callbacks', 'sentry'],\n lc_kwargs: {},\n name: 'SentryCallbackHandler',\n\n // BaseCallbackHandlerInput boolean flags\n ignoreLLM: false,\n ignoreChain: false,\n ignoreAgent: false,\n ignoreRetriever: false,\n ignoreCustomEvent: false,\n raiseError: false,\n awaitHandlers: true,\n\n handleLLMStart(\n llm: unknown,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractLLMRequestAttributes(\n llm as LangChainSerialized,\n prompts,\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chat Model Start Handler\n handleChatModelStart(\n llm: unknown,\n messages: unknown,\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runName?: string,\n ) {\n const invocationParams = getInvocationParams(tags);\n const attributes = extractChatModelRequestAttributes(\n llm as LangChainSerialized,\n messages as LangChainMessage[][],\n recordInputs,\n invocationParams,\n metadata,\n );\n const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE];\n const operationName = attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE];\n\n startSpanManual(\n {\n name: `${operationName} ${modelName}`,\n op: 'gen_ai.chat',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.chat',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // LLM End Handler - note: handleLLMEnd with capital LLM (used by both LLMs and chat models!)\n handleLLMEnd(\n output: unknown,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>,\n ) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n const attributes = extractLlmResponseAttributes(output as LangChainLLMResult, recordOutputs);\n if (attributes) {\n span.setAttributes(attributes);\n }\n exitSpan(runId);\n }\n },\n\n // LLM Error Handler - note: handleLLMError with capital LLM\n handleLLMError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.llm_error_handler`,\n },\n });\n },\n\n // Chain Start Handler\n handleChainStart(\n chain: { name?: string },\n inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ) {\n const chainName = runName || chain.name || 'unknown_chain';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',\n 'langchain.chain.name': chainName,\n };\n\n // Add inputs if recordInputs is enabled\n if (recordInputs) {\n attributes['langchain.chain.inputs'] = JSON.stringify(inputs);\n }\n\n startSpanManual(\n {\n name: `chain ${chainName}`,\n op: 'gen_ai.invoke_agent',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.invoke_agent',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Chain End Handler\n handleChainEnd(outputs: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add outputs if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n 'langchain.chain.outputs': JSON.stringify(outputs),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Chain Error Handler\n handleChainError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.chain_error_handler`,\n },\n });\n },\n\n // Tool Start Handler\n handleToolStart(tool: { name?: string }, input: string, runId: string, _parentRunId?: string) {\n const toolName = tool.name || 'unknown_tool';\n const attributes: Record<string, SpanAttributeValue> = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n };\n\n // Add input if recordInputs is enabled\n if (recordInputs) {\n attributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = input;\n }\n\n startSpanManual(\n {\n name: `execute_tool ${toolName}`,\n op: 'gen_ai.execute_tool',\n attributes: {\n ...attributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.execute_tool',\n },\n },\n span => {\n spanMap.set(runId, span);\n return span;\n },\n );\n },\n\n // Tool End Handler\n handleToolEnd(output: unknown, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n // Add output if recordOutputs is enabled\n if (recordOutputs) {\n span.setAttributes({\n [GEN_AI_TOOL_OUTPUT_ATTRIBUTE]: JSON.stringify(output),\n });\n }\n exitSpan(runId);\n }\n },\n\n // Tool Error Handler\n handleToolError(error: Error, runId: string) {\n const span = spanMap.get(runId);\n if (span?.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n exitSpan(runId);\n }\n\n captureException(error, {\n mechanism: {\n handled: false,\n type: `${LANGCHAIN_ORIGIN}.tool_error_handler`,\n },\n });\n },\n\n // LangChain BaseCallbackHandler required methods\n copy() {\n return handler;\n },\n\n toJSON() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n\n toJSONNotImplemented() {\n return {\n lc: 1,\n type: 'not_implemented',\n id: handler.lc_id,\n };\n },\n };\n\n return handler;\n}\n\nexport { instrumentLangChainEmbeddings } from './embeddings';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,14 +3,14 @@ const OPENAI_INTEGRATION_NAME = 'OpenAI';
|
|
|
3
3
|
// https://platform.openai.com/docs/quickstart?api-mode=responses
|
|
4
4
|
// https://platform.openai.com/docs/quickstart?api-mode=chat
|
|
5
5
|
// https://platform.openai.com/docs/api-reference/conversations
|
|
6
|
-
const
|
|
7
|
-
'responses.create',
|
|
8
|
-
'chat.completions.create',
|
|
9
|
-
'embeddings.create',
|
|
6
|
+
const OPENAI_METHOD_REGISTRY = {
|
|
7
|
+
'responses.create': { operation: 'chat' },
|
|
8
|
+
'chat.completions.create': { operation: 'chat' },
|
|
9
|
+
'embeddings.create': { operation: 'embeddings' },
|
|
10
10
|
// Conversations API - for conversation state management
|
|
11
11
|
// https://platform.openai.com/docs/guides/conversation-state
|
|
12
|
-
'conversations.create',
|
|
13
|
-
|
|
12
|
+
'conversations.create': { operation: 'chat' },
|
|
13
|
+
} ;
|
|
14
14
|
const RESPONSES_TOOL_CALL_EVENT_TYPES = [
|
|
15
15
|
'response.output_item.added',
|
|
16
16
|
'response.function_call_arguments.delta',
|
|
@@ -28,5 +28,5 @@ const RESPONSE_EVENT_TYPES = [
|
|
|
28
28
|
...RESPONSES_TOOL_CALL_EVENT_TYPES,
|
|
29
29
|
] ;
|
|
30
30
|
|
|
31
|
-
export {
|
|
31
|
+
export { OPENAI_INTEGRATION_NAME, OPENAI_METHOD_REGISTRY, RESPONSES_TOOL_CALL_EVENT_TYPES, RESPONSE_EVENT_TYPES };
|
|
32
32
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":["../../../../src/tracing/openai/constants.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../../src/tracing/openai/constants.ts"],"sourcesContent":["import type { InstrumentedMethodRegistry } from '../ai/utils';\n\nexport const OPENAI_INTEGRATION_NAME = 'OpenAI';\n\n// https://platform.openai.com/docs/quickstart?api-mode=responses\n// https://platform.openai.com/docs/quickstart?api-mode=chat\n// https://platform.openai.com/docs/api-reference/conversations\nexport const OPENAI_METHOD_REGISTRY = {\n 'responses.create': { operation: 'chat' },\n 'chat.completions.create': { operation: 'chat' },\n 'embeddings.create': { operation: 'embeddings' },\n // Conversations API - for conversation state management\n // https://platform.openai.com/docs/guides/conversation-state\n 'conversations.create': { operation: 'chat' },\n} as const satisfies InstrumentedMethodRegistry;\nexport const RESPONSES_TOOL_CALL_EVENT_TYPES = [\n 'response.output_item.added',\n 'response.function_call_arguments.delta',\n 'response.function_call_arguments.done',\n 'response.output_item.done',\n] as const;\nexport const RESPONSE_EVENT_TYPES = [\n 'response.created',\n 'response.in_progress',\n 'response.failed',\n 'response.completed',\n 'response.incomplete',\n 'response.queued',\n 'response.output_text.delta',\n ...RESPONSES_TOOL_CALL_EVENT_TYPES,\n] as const;\n"],"names":[],"mappings":"AAEO,MAAM,uBAAA,GAA0B;;AAEvC;AACA;AACA;AACO,MAAM,yBAAyB;AACtC,EAAE,kBAAkB,EAAE,EAAE,SAAS,EAAE,QAAQ;AAC3C,EAAE,yBAAyB,EAAE,EAAE,SAAS,EAAE,QAAQ;AAClD,EAAE,mBAAmB,EAAE,EAAE,SAAS,EAAE,cAAc;AAClD;AACA;AACA,EAAE,sBAAsB,EAAE,EAAE,SAAS,EAAE,QAAQ;AAC/C,CAAA;AACO,MAAM,kCAAkC;AAC/C,EAAE,4BAA4B;AAC9B,EAAE,wCAAwC;AAC1C,EAAE,uCAAuC;AACzC,EAAE,2BAA2B;AAC7B,CAAA;AACO,MAAM,uBAAuB;AACpC,EAAE,kBAAkB;AACpB,EAAE,sBAAsB;AACxB,EAAE,iBAAiB;AACnB,EAAE,oBAAoB;AACtB,EAAE,qBAAqB;AACvB,EAAE,iBAAiB;AACnB,EAAE,4BAA4B;AAC9B,EAAE,GAAG,+BAA+B;AACpC,CAAA;;;;"}
|
|
@@ -4,10 +4,11 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes.js';
|
|
|
4
4
|
import { debug } from '../../utils/debug-logger.js';
|
|
5
5
|
import { SPAN_STATUS_ERROR } from '../spanstatus.js';
|
|
6
6
|
import { startSpanManual, startSpan } from '../trace.js';
|
|
7
|
-
import {
|
|
8
|
-
import { resolveAIRecordingOptions, wrapPromiseWithMethods, extractSystemInstructions, getTruncatedJsonString
|
|
7
|
+
import { GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE, GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_SYSTEM_ATTRIBUTE } from '../ai/gen-ai-attributes.js';
|
|
8
|
+
import { resolveAIRecordingOptions, wrapPromiseWithMethods, buildMethodPath, extractSystemInstructions, getTruncatedJsonString } from '../ai/utils.js';
|
|
9
|
+
import { OPENAI_METHOD_REGISTRY } from './constants.js';
|
|
9
10
|
import { instrumentStream } from './streaming.js';
|
|
10
|
-
import {
|
|
11
|
+
import { addResponseAttributes, extractRequestParameters } from './utils.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Extract available tools from request parameters
|
|
@@ -35,10 +36,10 @@ function extractAvailableTools(params) {
|
|
|
35
36
|
/**
|
|
36
37
|
* Extract request attributes from method arguments
|
|
37
38
|
*/
|
|
38
|
-
function extractRequestAttributes(args,
|
|
39
|
+
function extractRequestAttributes(args, operationName) {
|
|
39
40
|
const attributes = {
|
|
40
41
|
[GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',
|
|
41
|
-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]:
|
|
42
|
+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: operationName,
|
|
42
43
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.openai',
|
|
43
44
|
};
|
|
44
45
|
|
|
@@ -58,37 +59,10 @@ function extractRequestAttributes(args, methodPath) {
|
|
|
58
59
|
return attributes;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
/**
|
|
62
|
-
* Add response attributes to spans
|
|
63
|
-
* This supports Chat Completion, Responses API, Embeddings, and Conversations API responses
|
|
64
|
-
*/
|
|
65
|
-
function addResponseAttributes(span, result, recordOutputs) {
|
|
66
|
-
if (!result || typeof result !== 'object') return;
|
|
67
|
-
|
|
68
|
-
const response = result ;
|
|
69
|
-
|
|
70
|
-
if (isChatCompletionResponse(response)) {
|
|
71
|
-
addChatCompletionAttributes(span, response, recordOutputs);
|
|
72
|
-
if (recordOutputs && response.choices?.length) {
|
|
73
|
-
const responseTexts = response.choices.map(choice => choice.message?.content || '');
|
|
74
|
-
span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: JSON.stringify(responseTexts) });
|
|
75
|
-
}
|
|
76
|
-
} else if (isResponsesApiResponse(response)) {
|
|
77
|
-
addResponsesApiAttributes(span, response, recordOutputs);
|
|
78
|
-
if (recordOutputs && response.output_text) {
|
|
79
|
-
span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.output_text });
|
|
80
|
-
}
|
|
81
|
-
} else if (isEmbeddingsResponse(response)) {
|
|
82
|
-
addEmbeddingsAttributes(span, response);
|
|
83
|
-
} else if (isConversationResponse(response)) {
|
|
84
|
-
addConversationAttributes(span, response);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
62
|
// Extract and record AI request inputs, if present. This is intentionally separate from response attributes.
|
|
89
63
|
function addRequestAttributes(span, params, operationName) {
|
|
90
64
|
// Store embeddings input on a separate attribute and do not truncate it
|
|
91
|
-
if (operationName ===
|
|
65
|
+
if (operationName === 'embeddings' && 'input' in params) {
|
|
92
66
|
const input = params.input;
|
|
93
67
|
|
|
94
68
|
// No input provided
|
|
@@ -145,20 +119,21 @@ function addRequestAttributes(span, params, operationName) {
|
|
|
145
119
|
function instrumentMethod(
|
|
146
120
|
originalMethod,
|
|
147
121
|
methodPath,
|
|
122
|
+
instrumentedMethod,
|
|
148
123
|
context,
|
|
149
124
|
options,
|
|
150
125
|
) {
|
|
151
|
-
return function
|
|
152
|
-
const
|
|
126
|
+
return function instrumentedCall(...args) {
|
|
127
|
+
const operationName = instrumentedMethod.operation || 'unknown';
|
|
128
|
+
const requestAttributes = extractRequestAttributes(args, operationName);
|
|
153
129
|
const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ) || 'unknown';
|
|
154
|
-
const operationName = getOperationName(methodPath);
|
|
155
130
|
|
|
156
131
|
const params = args[0] ;
|
|
157
132
|
const isStreamRequested = params && typeof params === 'object' && params.stream === true;
|
|
158
133
|
|
|
159
134
|
const spanConfig = {
|
|
160
135
|
name: `${operationName} ${model}`,
|
|
161
|
-
op:
|
|
136
|
+
op: `gen_ai.${operationName}`,
|
|
162
137
|
attributes: requestAttributes ,
|
|
163
138
|
};
|
|
164
139
|
|
|
@@ -241,8 +216,15 @@ function createDeepProxy(target, currentPath = '', options) {
|
|
|
241
216
|
const value = (obj )[prop];
|
|
242
217
|
const methodPath = buildMethodPath(currentPath, String(prop));
|
|
243
218
|
|
|
244
|
-
|
|
245
|
-
|
|
219
|
+
const instrumentedMethod = OPENAI_METHOD_REGISTRY[methodPath ];
|
|
220
|
+
if (typeof value === 'function' && instrumentedMethod) {
|
|
221
|
+
return instrumentMethod(
|
|
222
|
+
value ,
|
|
223
|
+
methodPath,
|
|
224
|
+
instrumentedMethod,
|
|
225
|
+
obj,
|
|
226
|
+
options,
|
|
227
|
+
);
|
|
246
228
|
}
|
|
247
229
|
|
|
248
230
|
if (typeof value === 'function') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/openai/index.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../../debug-build';\nimport { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpan, startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport { debug } from '../../utils/debug-logger';\nimport {\n GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n OPENAI_OPERATIONS,\n} from '../ai/gen-ai-attributes';\nimport {\n extractSystemInstructions,\n getTruncatedJsonString,\n resolveAIRecordingOptions,\n wrapPromiseWithMethods,\n buildMethodPath,\n} from '../ai/utils';\nimport { instrumentStream } from './streaming';\nimport type {\n ChatCompletionChunk,\n InstrumentedMethod,\n OpenAiOptions,\n OpenAiResponse,\n OpenAIStream,\n ResponseStreamingEvent,\n} from './types';\nimport {\n addChatCompletionAttributes,\n addConversationAttributes,\n addEmbeddingsAttributes,\n addResponsesApiAttributes,\n extractRequestParameters,\n getOperationName,\n getSpanOperation,\n isChatCompletionResponse,\n isConversationResponse,\n isEmbeddingsResponse,\n isResponsesApiResponse,\n shouldInstrument,\n} from './utils';\n\n/**\n * Extract available tools from request parameters\n */\nfunction extractAvailableTools(params: Record<string, unknown>): string | undefined {\n const tools = Array.isArray(params.tools) ? params.tools : [];\n const hasWebSearchOptions = params.web_search_options && typeof params.web_search_options === 'object';\n const webSearchOptions = hasWebSearchOptions\n ? [{ type: 'web_search_options', ...(params.web_search_options as Record<string, unknown>) }]\n : [];\n\n const availableTools = [...tools, ...webSearchOptions];\n if (availableTools.length === 0) {\n return undefined;\n }\n\n try {\n return JSON.stringify(availableTools);\n } catch (error) {\n DEBUG_BUILD && debug.error('Failed to serialize OpenAI tools:', error);\n return undefined;\n }\n}\n\n/**\n * Extract request attributes from method arguments\n */\nfunction extractRequestAttributes(args: unknown[], methodPath: string): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.openai',\n };\n\n if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {\n const params = args[0] as Record<string, unknown>;\n\n const availableTools = extractAvailableTools(params);\n if (availableTools) {\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = availableTools;\n }\n\n Object.assign(attributes, extractRequestParameters(params));\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = 'unknown';\n }\n\n return attributes;\n}\n\n/**\n * Add response attributes to spans\n * This supports Chat Completion, Responses API, Embeddings, and Conversations API responses\n */\nfunction addResponseAttributes(span: Span, result: unknown, recordOutputs?: boolean): void {\n if (!result || typeof result !== 'object') return;\n\n const response = result as OpenAiResponse;\n\n if (isChatCompletionResponse(response)) {\n addChatCompletionAttributes(span, response, recordOutputs);\n if (recordOutputs && response.choices?.length) {\n const responseTexts = response.choices.map(choice => choice.message?.content || '');\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: JSON.stringify(responseTexts) });\n }\n } else if (isResponsesApiResponse(response)) {\n addResponsesApiAttributes(span, response, recordOutputs);\n if (recordOutputs && response.output_text) {\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.output_text });\n }\n } else if (isEmbeddingsResponse(response)) {\n addEmbeddingsAttributes(span, response);\n } else if (isConversationResponse(response)) {\n addConversationAttributes(span, response);\n }\n}\n\n// Extract and record AI request inputs, if present. This is intentionally separate from response attributes.\nfunction addRequestAttributes(span: Span, params: Record<string, unknown>, operationName: string): void {\n // Store embeddings input on a separate attribute and do not truncate it\n if (operationName === OPENAI_OPERATIONS.EMBEDDINGS && 'input' in params) {\n const input = params.input;\n\n // No input provided\n if (input == null) {\n return;\n }\n\n // Empty input string\n if (typeof input === 'string' && input.length === 0) {\n return;\n }\n\n // Empty array input\n if (Array.isArray(input) && input.length === 0) {\n return;\n }\n\n // Store strings as-is, arrays/objects as JSON\n span.setAttribute(GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, typeof input === 'string' ? input : JSON.stringify(input));\n return;\n }\n\n const src = 'input' in params ? params.input : 'messages' in params ? params.messages : undefined;\n\n if (!src) {\n return;\n }\n\n if (Array.isArray(src) && src.length === 0) {\n return;\n }\n\n const { systemInstructions, filteredMessages } = extractSystemInstructions(src);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const truncatedInput = getTruncatedJsonString(filteredMessages);\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ATTRIBUTE, truncatedInput);\n\n if (Array.isArray(filteredMessages)) {\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredMessages.length);\n } else {\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, 1);\n }\n}\n\n/**\n * Instrument a method with Sentry spans\n * Following Sentry AI Agents Manual Instrumentation conventions\n * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation\n */\nfunction instrumentMethod<T extends unknown[], R>(\n originalMethod: (...args: T) => Promise<R>,\n methodPath: InstrumentedMethod,\n context: unknown,\n options: OpenAiOptions,\n): (...args: T) => Promise<R> {\n return function instrumentedMethod(...args: T): Promise<R> {\n const requestAttributes = extractRequestAttributes(args, methodPath);\n const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';\n const operationName = getOperationName(methodPath);\n\n const params = args[0] as Record<string, unknown> | undefined;\n const isStreamRequested = params && typeof params === 'object' && params.stream === true;\n\n const spanConfig = {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n };\n\n if (isStreamRequested) {\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpanManual(spanConfig, (span: Span) => {\n originalResult = originalMethod.apply(context, args);\n\n if (options.recordInputs && params) {\n addRequestAttributes(span, params, operationName);\n }\n\n // Return async processing\n return (async () => {\n try {\n const result = await originalResult;\n return instrumentStream(\n result as OpenAIStream<ChatCompletionChunk | ResponseStreamingEvent>,\n span,\n options.recordOutputs ?? false,\n ) as unknown as R;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai.stream',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n })();\n });\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');\n }\n\n // Non-streaming\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpan(spanConfig, (span: Span) => {\n // Call synchronously to capture the promise\n originalResult = originalMethod.apply(context, args);\n\n if (options.recordInputs && params) {\n addRequestAttributes(span, params, operationName);\n }\n\n return originalResult.then(\n result => {\n addResponseAttributes(span, result, options.recordOutputs);\n return result;\n },\n error => {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai',\n data: { function: methodPath },\n },\n });\n throw error;\n },\n );\n });\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');\n };\n}\n\n/**\n * Create a deep proxy for OpenAI client instrumentation\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: OpenAiOptions): T {\n return new Proxy(target, {\n get(obj: object, prop: string): unknown {\n const value = (obj as Record<string, unknown>)[prop];\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n if (typeof value === 'function' && shouldInstrument(methodPath)) {\n return instrumentMethod(value as (...args: unknown[]) => Promise<unknown>, methodPath, obj, options);\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context,\n // which is required for accessing private class fields (e.g. #baseURL) in OpenAI SDK v5.\n return value.bind(obj);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n }) as T;\n}\n\n/**\n * Instrument an OpenAI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n */\nexport function instrumentOpenAiClient<T extends object>(client: T, options?: OpenAiOptions): T {\n return createDeepProxy(client, '', resolveAIRecordingOptions(options));\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/openai/index.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../../debug-build';\nimport { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport { startSpan, startSpanManual } from '../../tracing/trace';\nimport type { Span, SpanAttributeValue } from '../../types-hoist/span';\nimport { debug } from '../../utils/debug-logger';\nimport {\n GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport type { InstrumentedMethodEntry } from '../ai/utils';\nimport {\n buildMethodPath,\n extractSystemInstructions,\n getTruncatedJsonString,\n resolveAIRecordingOptions,\n wrapPromiseWithMethods,\n} from '../ai/utils';\nimport { OPENAI_METHOD_REGISTRY } from './constants';\nimport { instrumentStream } from './streaming';\nimport type { ChatCompletionChunk, OpenAiOptions, OpenAIStream, ResponseStreamingEvent } from './types';\nimport { addResponseAttributes, extractRequestParameters } from './utils';\n\n/**\n * Extract available tools from request parameters\n */\nfunction extractAvailableTools(params: Record<string, unknown>): string | undefined {\n const tools = Array.isArray(params.tools) ? params.tools : [];\n const hasWebSearchOptions = params.web_search_options && typeof params.web_search_options === 'object';\n const webSearchOptions = hasWebSearchOptions\n ? [{ type: 'web_search_options', ...(params.web_search_options as Record<string, unknown>) }]\n : [];\n\n const availableTools = [...tools, ...webSearchOptions];\n if (availableTools.length === 0) {\n return undefined;\n }\n\n try {\n return JSON.stringify(availableTools);\n } catch (error) {\n DEBUG_BUILD && debug.error('Failed to serialize OpenAI tools:', error);\n return undefined;\n }\n}\n\n/**\n * Extract request attributes from method arguments\n */\nfunction extractRequestAttributes(args: unknown[], operationName: string): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: operationName,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.openai',\n };\n\n if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {\n const params = args[0] as Record<string, unknown>;\n\n const availableTools = extractAvailableTools(params);\n if (availableTools) {\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = availableTools;\n }\n\n Object.assign(attributes, extractRequestParameters(params));\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = 'unknown';\n }\n\n return attributes;\n}\n\n// Extract and record AI request inputs, if present. This is intentionally separate from response attributes.\nfunction addRequestAttributes(span: Span, params: Record<string, unknown>, operationName: string): void {\n // Store embeddings input on a separate attribute and do not truncate it\n if (operationName === 'embeddings' && 'input' in params) {\n const input = params.input;\n\n // No input provided\n if (input == null) {\n return;\n }\n\n // Empty input string\n if (typeof input === 'string' && input.length === 0) {\n return;\n }\n\n // Empty array input\n if (Array.isArray(input) && input.length === 0) {\n return;\n }\n\n // Store strings as-is, arrays/objects as JSON\n span.setAttribute(GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, typeof input === 'string' ? input : JSON.stringify(input));\n return;\n }\n\n const src = 'input' in params ? params.input : 'messages' in params ? params.messages : undefined;\n\n if (!src) {\n return;\n }\n\n if (Array.isArray(src) && src.length === 0) {\n return;\n }\n\n const { systemInstructions, filteredMessages } = extractSystemInstructions(src);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const truncatedInput = getTruncatedJsonString(filteredMessages);\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ATTRIBUTE, truncatedInput);\n\n if (Array.isArray(filteredMessages)) {\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredMessages.length);\n } else {\n span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, 1);\n }\n}\n\n/**\n * Instrument a method with Sentry spans\n * Following Sentry AI Agents Manual Instrumentation conventions\n * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation\n */\nfunction instrumentMethod<T extends unknown[], R>(\n originalMethod: (...args: T) => Promise<R>,\n methodPath: string,\n instrumentedMethod: InstrumentedMethodEntry,\n context: unknown,\n options: OpenAiOptions,\n): (...args: T) => Promise<R> {\n return function instrumentedCall(...args: T): Promise<R> {\n const operationName = instrumentedMethod.operation || 'unknown';\n const requestAttributes = extractRequestAttributes(args, operationName);\n const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';\n\n const params = args[0] as Record<string, unknown> | undefined;\n const isStreamRequested = params && typeof params === 'object' && params.stream === true;\n\n const spanConfig = {\n name: `${operationName} ${model}`,\n op: `gen_ai.${operationName}`,\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n };\n\n if (isStreamRequested) {\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpanManual(spanConfig, (span: Span) => {\n originalResult = originalMethod.apply(context, args);\n\n if (options.recordInputs && params) {\n addRequestAttributes(span, params, operationName);\n }\n\n // Return async processing\n return (async () => {\n try {\n const result = await originalResult;\n return instrumentStream(\n result as OpenAIStream<ChatCompletionChunk | ResponseStreamingEvent>,\n span,\n options.recordOutputs ?? false,\n ) as unknown as R;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai.stream',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n })();\n });\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');\n }\n\n // Non-streaming\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpan(spanConfig, (span: Span) => {\n // Call synchronously to capture the promise\n originalResult = originalMethod.apply(context, args);\n\n if (options.recordInputs && params) {\n addRequestAttributes(span, params, operationName);\n }\n\n return originalResult.then(\n result => {\n addResponseAttributes(span, result, options.recordOutputs);\n return result;\n },\n error => {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai',\n data: { function: methodPath },\n },\n });\n throw error;\n },\n );\n });\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');\n };\n}\n\n/**\n * Create a deep proxy for OpenAI client instrumentation\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: OpenAiOptions): T {\n return new Proxy(target, {\n get(obj: object, prop: string): unknown {\n const value = (obj as Record<string, unknown>)[prop];\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n const instrumentedMethod = OPENAI_METHOD_REGISTRY[methodPath as keyof typeof OPENAI_METHOD_REGISTRY];\n if (typeof value === 'function' && instrumentedMethod) {\n return instrumentMethod(\n value as (...args: unknown[]) => Promise<unknown>,\n methodPath,\n instrumentedMethod,\n obj,\n options,\n );\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context,\n // which is required for accessing private class fields (e.g. #baseURL) in OpenAI SDK v5.\n return value.bind(obj);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n }) as T;\n}\n\n/**\n * Instrument an OpenAI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n */\nexport function instrumentOpenAiClient<T extends object>(client: T, options?: OpenAiOptions): T {\n return createDeepProxy(client, '', resolveAIRecordingOptions(options));\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { captureException } from '../../exports.js';
|
|
2
2
|
import { SPAN_STATUS_ERROR } from '../spanstatus.js';
|
|
3
|
-
import {
|
|
3
|
+
import { endStreamSpan } from '../ai/utils.js';
|
|
4
4
|
import { RESPONSE_EVENT_TYPES } from './constants.js';
|
|
5
|
-
import { isChatCompletionChunk, isResponsesApiStreamEvent
|
|
5
|
+
import { isChatCompletionChunk, isResponsesApiStreamEvent } from './utils.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* State object used to accumulate information from a stream of OpenAI events/chunks.
|
|
@@ -51,7 +51,6 @@ function processChatCompletionToolCalls(toolCalls, state) {
|
|
|
51
51
|
function processChatCompletionChunk(chunk, state, recordOutputs) {
|
|
52
52
|
state.responseId = chunk.id ?? state.responseId;
|
|
53
53
|
state.responseModel = chunk.model ?? state.responseModel;
|
|
54
|
-
state.responseTimestamp = chunk.created ?? state.responseTimestamp;
|
|
55
54
|
|
|
56
55
|
if (chunk.usage) {
|
|
57
56
|
// For stream responses, the input tokens remain constant across all events in the stream.
|
|
@@ -135,7 +134,6 @@ function processResponsesApiEvent(
|
|
|
135
134
|
const { response } = event ;
|
|
136
135
|
state.responseId = response.id ?? state.responseId;
|
|
137
136
|
state.responseModel = response.model ?? state.responseModel;
|
|
138
|
-
state.responseTimestamp = response.created_at ?? state.responseTimestamp;
|
|
139
137
|
|
|
140
138
|
if (response.usage) {
|
|
141
139
|
// For stream responses, the input tokens remain constant across all events in the stream.
|
|
@@ -179,7 +177,6 @@ async function* instrumentStream(
|
|
|
179
177
|
finishReasons: [],
|
|
180
178
|
responseId: '',
|
|
181
179
|
responseModel: '',
|
|
182
|
-
responseTimestamp: 0,
|
|
183
180
|
promptTokens: undefined,
|
|
184
181
|
completionTokens: undefined,
|
|
185
182
|
totalTokens: undefined,
|
|
@@ -197,36 +194,8 @@ async function* instrumentStream(
|
|
|
197
194
|
yield event;
|
|
198
195
|
}
|
|
199
196
|
} finally {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
span.setAttributes({
|
|
204
|
-
[GEN_AI_RESPONSE_STREAMING_ATTRIBUTE]: true,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
if (state.finishReasons.length) {
|
|
208
|
-
span.setAttributes({
|
|
209
|
-
[GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify(state.finishReasons),
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (recordOutputs && state.responseTexts.length) {
|
|
214
|
-
span.setAttributes({
|
|
215
|
-
[GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: state.responseTexts.join(''),
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Set tool calls attribute if any were accumulated
|
|
220
|
-
const chatCompletionToolCallsArray = Object.values(state.chatCompletionToolCalls);
|
|
221
|
-
const allToolCalls = [...chatCompletionToolCallsArray, ...state.responsesApiToolCalls];
|
|
222
|
-
|
|
223
|
-
if (allToolCalls.length > 0) {
|
|
224
|
-
span.setAttributes({
|
|
225
|
-
[GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(allToolCalls),
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
span.end();
|
|
197
|
+
const allToolCalls = [...Object.values(state.chatCompletionToolCalls), ...state.responsesApiToolCalls];
|
|
198
|
+
endStreamSpan(span, { ...state, toolCalls: allToolCalls }, recordOutputs);
|
|
230
199
|
}
|
|
231
200
|
}
|
|
232
201
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.js","sources":["../../../../src/tracing/openai/streaming.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span } from '../../types-hoist/span';\nimport {\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_STREAMING_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { RESPONSE_EVENT_TYPES } from './constants';\nimport type {\n ChatCompletionChunk,\n ChatCompletionToolCall,\n OpenAIResponseObject,\n ResponseFunctionCall,\n ResponseStreamingEvent,\n} from './types';\nimport {\n isChatCompletionChunk,\n isResponsesApiStreamEvent,\n setCommonResponseAttributes,\n setTokenUsageAttributes,\n} from './utils';\n\n/**\n * State object used to accumulate information from a stream of OpenAI events/chunks.\n */\ninterface StreamingState {\n /** Types of events encountered in the stream. */\n eventTypes: string[];\n /** Collected response text fragments (for output recording). */\n responseTexts: string[];\n /** Reasons for finishing the response, as reported by the API. */\n finishReasons: string[];\n /** The response ID. */\n responseId: string;\n /** The model name. */\n responseModel: string;\n /** The timestamp of the response. */\n responseTimestamp: number;\n /** Number of prompt/input tokens used. */\n promptTokens: number | undefined;\n /** Number of completion/output tokens used. */\n completionTokens: number | undefined;\n /** Total number of tokens used (prompt + completion). */\n totalTokens: number | undefined;\n /**\n * Accumulated tool calls from Chat Completion streaming, indexed by tool call index.\n * @see https://platform.openai.com/docs/guides/function-calling?api-mode=chat#streaming\n */\n chatCompletionToolCalls: Record<number, ChatCompletionToolCall>;\n /**\n * Accumulated function calls from Responses API streaming.\n * @see https://platform.openai.com/docs/guides/function-calling?api-mode=responses#streaming\n */\n responsesApiToolCalls: Array<ResponseFunctionCall | unknown>;\n}\n\n/**\n * Processes tool calls from a chat completion chunk delta.\n * Follows the pattern: accumulate by index, then convert to array at the end.\n *\n * @param toolCalls - Array of tool calls from the delta.\n * @param state - The current streaming state to update.\n *\n * @see https://platform.openai.com/docs/guides/function-calling#streaming\n */\nfunction processChatCompletionToolCalls(toolCalls: ChatCompletionToolCall[], state: StreamingState): void {\n for (const toolCall of toolCalls) {\n const index = toolCall.index;\n if (index === undefined || !toolCall.function) continue;\n\n // Initialize tool call if this is the first chunk for this index\n if (!(index in state.chatCompletionToolCalls)) {\n state.chatCompletionToolCalls[index] = {\n ...toolCall,\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '',\n },\n };\n } else {\n // Accumulate function arguments from subsequent chunks\n const existingToolCall = state.chatCompletionToolCalls[index];\n if (toolCall.function.arguments && existingToolCall?.function) {\n existingToolCall.function.arguments += toolCall.function.arguments;\n }\n }\n }\n}\n\n/**\n * Processes a single OpenAI ChatCompletionChunk event, updating the streaming state.\n *\n * @param chunk - The ChatCompletionChunk event to process.\n * @param state - The current streaming state to update.\n * @param recordOutputs - Whether to record output text fragments.\n */\nfunction processChatCompletionChunk(chunk: ChatCompletionChunk, state: StreamingState, recordOutputs: boolean): void {\n state.responseId = chunk.id ?? state.responseId;\n state.responseModel = chunk.model ?? state.responseModel;\n state.responseTimestamp = chunk.created ?? state.responseTimestamp;\n\n if (chunk.usage) {\n // For stream responses, the input tokens remain constant across all events in the stream.\n // Output tokens, however, are only finalized in the last event.\n // Since we can't guarantee that the last event will include usage data or even be a typed event,\n // we update the output token values on every event that includes them.\n // This ensures that output token usage is always set, even if the final event lacks it.\n state.promptTokens = chunk.usage.prompt_tokens;\n state.completionTokens = chunk.usage.completion_tokens;\n state.totalTokens = chunk.usage.total_tokens;\n }\n\n for (const choice of chunk.choices ?? []) {\n if (recordOutputs) {\n if (choice.delta?.content) {\n state.responseTexts.push(choice.delta.content);\n }\n\n // Handle tool calls from delta\n if (choice.delta?.tool_calls) {\n processChatCompletionToolCalls(choice.delta.tool_calls, state);\n }\n }\n if (choice.finish_reason) {\n state.finishReasons.push(choice.finish_reason);\n }\n }\n}\n\n/**\n * Processes a single OpenAI Responses API streaming event, updating the streaming state and span.\n *\n * @param streamEvent - The event to process (may be an error or unknown object).\n * @param state - The current streaming state to update.\n * @param recordOutputs - Whether to record output text fragments.\n * @param span - The span to update with error status if needed.\n */\nfunction processResponsesApiEvent(\n streamEvent: ResponseStreamingEvent | unknown | Error,\n state: StreamingState,\n recordOutputs: boolean,\n span: Span,\n): void {\n if (!(streamEvent && typeof streamEvent === 'object')) {\n state.eventTypes.push('unknown:non-object');\n return;\n }\n if (streamEvent instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(streamEvent, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai.stream-response',\n },\n });\n return;\n }\n\n if (!('type' in streamEvent)) return;\n const event = streamEvent as ResponseStreamingEvent;\n\n if (!RESPONSE_EVENT_TYPES.includes(event.type)) {\n state.eventTypes.push(event.type);\n return;\n }\n\n // Handle output text delta\n if (recordOutputs) {\n // Handle tool call events for Responses API\n if (event.type === 'response.output_item.done' && 'item' in event) {\n state.responsesApiToolCalls.push(event.item);\n }\n\n if (event.type === 'response.output_text.delta' && 'delta' in event && event.delta) {\n state.responseTexts.push(event.delta);\n return;\n }\n }\n\n if ('response' in event) {\n const { response } = event as { response: OpenAIResponseObject };\n state.responseId = response.id ?? state.responseId;\n state.responseModel = response.model ?? state.responseModel;\n state.responseTimestamp = response.created_at ?? state.responseTimestamp;\n\n if (response.usage) {\n // For stream responses, the input tokens remain constant across all events in the stream.\n // Output tokens, however, are only finalized in the last event.\n // Since we can't guarantee that the last event will include usage data or even be a typed event,\n // we update the output token values on every event that includes them.\n // This ensures that output token usage is always set, even if the final event lacks it.\n state.promptTokens = response.usage.input_tokens;\n state.completionTokens = response.usage.output_tokens;\n state.totalTokens = response.usage.total_tokens;\n }\n\n if (response.status) {\n state.finishReasons.push(response.status);\n }\n\n if (recordOutputs && response.output_text) {\n state.responseTexts.push(response.output_text);\n }\n }\n}\n\n/**\n * Instruments a stream of OpenAI events, updating the provided span with relevant attributes and\n * optionally recording output text. This function yields each event from the input stream as it is processed.\n *\n * @template T - The type of events in the stream.\n * @param stream - The async iterable stream of events to instrument.\n * @param span - The span to add attributes to and to finish at the end of the stream.\n * @param recordOutputs - Whether to record output text fragments in the span.\n * @returns An async generator yielding each event from the input stream.\n */\nexport async function* instrumentStream<T>(\n stream: AsyncIterable<T>,\n span: Span,\n recordOutputs: boolean,\n): AsyncGenerator<T, void, unknown> {\n const state: StreamingState = {\n eventTypes: [],\n responseTexts: [],\n finishReasons: [],\n responseId: '',\n responseModel: '',\n responseTimestamp: 0,\n promptTokens: undefined,\n completionTokens: undefined,\n totalTokens: undefined,\n chatCompletionToolCalls: {},\n responsesApiToolCalls: [],\n };\n\n try {\n for await (const event of stream) {\n if (isChatCompletionChunk(event)) {\n processChatCompletionChunk(event as ChatCompletionChunk, state, recordOutputs);\n } else if (isResponsesApiStreamEvent(event)) {\n processResponsesApiEvent(event as ResponseStreamingEvent, state, recordOutputs, span);\n }\n yield event;\n }\n } finally {\n setCommonResponseAttributes(span, state.responseId, state.responseModel, state.responseTimestamp);\n setTokenUsageAttributes(span, state.promptTokens, state.completionTokens, state.totalTokens);\n\n span.setAttributes({\n [GEN_AI_RESPONSE_STREAMING_ATTRIBUTE]: true,\n });\n\n if (state.finishReasons.length) {\n span.setAttributes({\n [GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify(state.finishReasons),\n });\n }\n\n if (recordOutputs && state.responseTexts.length) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: state.responseTexts.join(''),\n });\n }\n\n // Set tool calls attribute if any were accumulated\n const chatCompletionToolCallsArray = Object.values(state.chatCompletionToolCalls);\n const allToolCalls = [...chatCompletionToolCallsArray, ...state.responsesApiToolCalls];\n\n if (allToolCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(allToolCalls),\n });\n }\n\n span.end();\n }\n}\n"],"names":[],"mappings":";;;;;;AAwBA;AACA;AACA;;AAgCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,8BAA8B,CAAC,SAAS,EAA4B,KAAK,EAAwB;AAC1G,EAAE,KAAK,MAAM,QAAA,IAAY,SAAS,EAAE;AACpC,IAAI,MAAM,KAAA,GAAQ,QAAQ,CAAC,KAAK;AAChC,IAAI,IAAI,KAAA,KAAU,SAAA,IAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE;;AAEnD;AACA,IAAI,IAAI,EAAE,KAAA,IAAS,KAAK,CAAC,uBAAuB,CAAC,EAAE;AACnD,MAAM,KAAK,CAAC,uBAAuB,CAAC,KAAK,IAAI;AAC7C,QAAQ,GAAG,QAAQ;AACnB,QAAQ,QAAQ,EAAE;AAClB,UAAU,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI;AACtC,UAAU,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,SAAA,IAAa,EAAE;AACtD,SAAS;AACT,OAAO;AACP,IAAI,OAAO;AACX;AACA,MAAM,MAAM,mBAAmB,KAAK,CAAC,uBAAuB,CAAC,KAAK,CAAC;AACnE,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAA,IAAa,gBAAgB,EAAE,QAAQ,EAAE;AACrE,QAAQ,gBAAgB,CAAC,QAAQ,CAAC,SAAA,IAAa,QAAQ,CAAC,QAAQ,CAAC,SAAS;AAC1E,MAAM;AACN,IAAI;AACJ,EAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,0BAA0B,CAAC,KAAK,EAAuB,KAAK,EAAkB,aAAa,EAAiB;AACrH,EAAE,KAAK,CAAC,UAAA,GAAa,KAAK,CAAC,EAAA,IAAM,KAAK,CAAC,UAAU;AACjD,EAAE,KAAK,CAAC,aAAA,GAAgB,KAAK,CAAC,KAAA,IAAS,KAAK,CAAC,aAAa;AAC1D,EAAE,KAAK,CAAC,iBAAA,GAAoB,KAAK,CAAC,OAAA,IAAW,KAAK,CAAC,iBAAiB;;AAEpE,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE;AACnB;AACA;AACA;AACA;AACA;AACA,IAAI,KAAK,CAAC,YAAA,GAAe,KAAK,CAAC,KAAK,CAAC,aAAa;AAClD,IAAI,KAAK,CAAC,gBAAA,GAAmB,KAAK,CAAC,KAAK,CAAC,iBAAiB;AAC1D,IAAI,KAAK,CAAC,WAAA,GAAc,KAAK,CAAC,KAAK,CAAC,YAAY;AAChD,EAAE;;AAEF,EAAE,KAAK,MAAM,MAAA,IAAU,KAAK,CAAC,OAAA,IAAW,EAAE,EAAE;AAC5C,IAAI,IAAI,aAAa,EAAE;AACvB,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE;AACjC,QAAQ,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;AACtD,MAAM;;AAEN;AACA,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE;AACpC,QAAQ,8BAA8B,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC;AACtE,MAAM;AACN,IAAI;AACJ,IAAI,IAAI,MAAM,CAAC,aAAa,EAAE;AAC9B,MAAM,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;AACpD,IAAI;AACJ,EAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,wBAAwB;AACjC,EAAE,WAAW;AACb,EAAE,KAAK;AACP,EAAE,aAAa;AACf,EAAE,IAAI;AACN,EAAQ;AACR,EAAE,IAAI,EAAE,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAQ,CAAC,EAAE;AACzD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAC/C,IAAI;AACJ,EAAE;AACF,EAAE,IAAI,WAAA,YAAuB,KAAK,EAAE;AACpC,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,gBAAA,EAAkB,CAAC;AAC1E,IAAI,gBAAgB,CAAC,WAAW,EAAE;AAClC,MAAM,SAAS,EAAE;AACjB,QAAQ,OAAO,EAAE,KAAK;AACtB,QAAQ,IAAI,EAAE,gCAAgC;AAC9C,OAAO;AACP,KAAK,CAAC;AACN,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,EAAE,UAAU,WAAW,CAAC,EAAE;AAChC,EAAE,MAAM,KAAA,GAAQ,WAAA;;AAEhB,EAAE,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;AAClD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;AACrC,IAAI;AACJ,EAAE;;AAEF;AACA,EAAE,IAAI,aAAa,EAAE;AACrB;AACA,IAAI,IAAI,KAAK,CAAC,IAAA,KAAS,2BAAA,IAA+B,MAAA,IAAU,KAAK,EAAE;AACvE,MAAM,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;AAClD,IAAI;;AAEJ,IAAI,IAAI,KAAK,CAAC,SAAS,4BAAA,IAAgC,OAAA,IAAW,KAAA,IAAS,KAAK,CAAC,KAAK,EAAE;AACxF,MAAM,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;AAC3C,MAAM;AACN,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,UAAA,IAAc,KAAK,EAAE;AAC3B,IAAI,MAAM,EAAE,QAAA,EAAS,GAAI,KAAA;AACzB,IAAI,KAAK,CAAC,UAAA,GAAa,QAAQ,CAAC,EAAA,IAAM,KAAK,CAAC,UAAU;AACtD,IAAI,KAAK,CAAC,aAAA,GAAgB,QAAQ,CAAC,KAAA,IAAS,KAAK,CAAC,aAAa;AAC/D,IAAI,KAAK,CAAC,iBAAA,GAAoB,QAAQ,CAAC,UAAA,IAAc,KAAK,CAAC,iBAAiB;;AAE5E,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE;AACxB;AACA;AACA;AACA;AACA;AACA,MAAM,KAAK,CAAC,YAAA,GAAe,QAAQ,CAAC,KAAK,CAAC,YAAY;AACtD,MAAM,KAAK,CAAC,gBAAA,GAAmB,QAAQ,CAAC,KAAK,CAAC,aAAa;AAC3D,MAAM,KAAK,CAAC,WAAA,GAAc,QAAQ,CAAC,KAAK,CAAC,YAAY;AACrD,IAAI;;AAEJ,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE;AACzB,MAAM,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;AAC/C,IAAI;;AAEJ,IAAI,IAAI,aAAA,IAAiB,QAAQ,CAAC,WAAW,EAAE;AAC/C,MAAM,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;AACpD,IAAI;AACJ,EAAE;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,gBAAgB,gBAAgB;AACvC,EAAE,MAAM;AACR,EAAE,IAAI;AACN,EAAE,aAAa;AACf,EAAoC;AACpC,EAAE,MAAM,KAAK,GAAmB;AAChC,IAAI,UAAU,EAAE,EAAE;AAClB,IAAI,aAAa,EAAE,EAAE;AACrB,IAAI,aAAa,EAAE,EAAE;AACrB,IAAI,UAAU,EAAE,EAAE;AAClB,IAAI,aAAa,EAAE,EAAE;AACrB,IAAI,iBAAiB,EAAE,CAAC;AACxB,IAAI,YAAY,EAAE,SAAS;AAC3B,IAAI,gBAAgB,EAAE,SAAS;AAC/B,IAAI,WAAW,EAAE,SAAS;AAC1B,IAAI,uBAAuB,EAAE,EAAE;AAC/B,IAAI,qBAAqB,EAAE,EAAE;AAC7B,GAAG;;AAEH,EAAE,IAAI;AACN,IAAI,WAAW,MAAM,KAAA,IAAS,MAAM,EAAE;AACtC,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,EAAE;AACxC,QAAQ,0BAA0B,CAAC,KAAA,GAA8B,KAAK,EAAE,aAAa,CAAC;AACtF,MAAM,CAAA,MAAO,IAAI,yBAAyB,CAAC,KAAK,CAAC,EAAE;AACnD,QAAQ,wBAAwB,CAAC,KAAA,GAAiC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC;AAC7F,MAAM;AACN,MAAM,MAAM,KAAK;AACjB,IAAI;AACJ,EAAE,UAAU;AACZ,IAAI,2BAA2B,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,iBAAiB,CAAC;AACrG,IAAI,uBAAuB,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,WAAW,CAAC;;AAEhG,IAAI,IAAI,CAAC,aAAa,CAAC;AACvB,MAAM,CAAC,mCAAmC,GAAG,IAAI;AACjD,KAAK,CAAC;;AAEN,IAAI,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE;AACpC,MAAM,IAAI,CAAC,aAAa,CAAC;AACzB,QAAQ,CAAC,wCAAwC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC;AACvF,OAAO,CAAC;AACR,IAAI;;AAEJ,IAAI,IAAI,aAAA,IAAiB,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE;AACrD,MAAM,IAAI,CAAC,aAAa,CAAC;AACzB,QAAQ,CAAC,8BAA8B,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACtE,OAAO,CAAC;AACR,IAAI;;AAEJ;AACA,IAAI,MAAM,4BAAA,GAA+B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC;AACrF,IAAI,MAAM,YAAA,GAAe,CAAC,GAAG,4BAA4B,EAAE,GAAG,KAAK,CAAC,qBAAqB,CAAC;;AAE1F,IAAI,IAAI,YAAY,CAAC,MAAA,GAAS,CAAC,EAAE;AACjC,MAAM,IAAI,CAAC,aAAa,CAAC;AACzB,QAAQ,CAAC,oCAAoC,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;AAC5E,OAAO,CAAC;AACR,IAAI;;AAEJ,IAAI,IAAI,CAAC,GAAG,EAAE;AACd,EAAE;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"streaming.js","sources":["../../../../src/tracing/openai/streaming.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span } from '../../types-hoist/span';\nimport { endStreamSpan } from '../ai/utils';\nimport { RESPONSE_EVENT_TYPES } from './constants';\nimport type {\n ChatCompletionChunk,\n ChatCompletionToolCall,\n OpenAIResponseObject,\n ResponseFunctionCall,\n ResponseStreamingEvent,\n} from './types';\nimport { isChatCompletionChunk, isResponsesApiStreamEvent } from './utils';\n\n/**\n * State object used to accumulate information from a stream of OpenAI events/chunks.\n */\ninterface StreamingState {\n /** Types of events encountered in the stream. */\n eventTypes: string[];\n /** Collected response text fragments (for output recording). */\n responseTexts: string[];\n /** Reasons for finishing the response, as reported by the API. */\n finishReasons: string[];\n /** The response ID. */\n responseId: string;\n /** The model name. */\n responseModel: string;\n /** Number of prompt/input tokens used. */\n promptTokens: number | undefined;\n /** Number of completion/output tokens used. */\n completionTokens: number | undefined;\n /** Total number of tokens used (prompt + completion). */\n totalTokens: number | undefined;\n /**\n * Accumulated tool calls from Chat Completion streaming, indexed by tool call index.\n * @see https://platform.openai.com/docs/guides/function-calling?api-mode=chat#streaming\n */\n chatCompletionToolCalls: Record<number, ChatCompletionToolCall>;\n /**\n * Accumulated function calls from Responses API streaming.\n * @see https://platform.openai.com/docs/guides/function-calling?api-mode=responses#streaming\n */\n responsesApiToolCalls: Array<ResponseFunctionCall | unknown>;\n}\n\n/**\n * Processes tool calls from a chat completion chunk delta.\n * Follows the pattern: accumulate by index, then convert to array at the end.\n *\n * @param toolCalls - Array of tool calls from the delta.\n * @param state - The current streaming state to update.\n *\n * @see https://platform.openai.com/docs/guides/function-calling#streaming\n */\nfunction processChatCompletionToolCalls(toolCalls: ChatCompletionToolCall[], state: StreamingState): void {\n for (const toolCall of toolCalls) {\n const index = toolCall.index;\n if (index === undefined || !toolCall.function) continue;\n\n // Initialize tool call if this is the first chunk for this index\n if (!(index in state.chatCompletionToolCalls)) {\n state.chatCompletionToolCalls[index] = {\n ...toolCall,\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '',\n },\n };\n } else {\n // Accumulate function arguments from subsequent chunks\n const existingToolCall = state.chatCompletionToolCalls[index];\n if (toolCall.function.arguments && existingToolCall?.function) {\n existingToolCall.function.arguments += toolCall.function.arguments;\n }\n }\n }\n}\n\n/**\n * Processes a single OpenAI ChatCompletionChunk event, updating the streaming state.\n *\n * @param chunk - The ChatCompletionChunk event to process.\n * @param state - The current streaming state to update.\n * @param recordOutputs - Whether to record output text fragments.\n */\nfunction processChatCompletionChunk(chunk: ChatCompletionChunk, state: StreamingState, recordOutputs: boolean): void {\n state.responseId = chunk.id ?? state.responseId;\n state.responseModel = chunk.model ?? state.responseModel;\n\n if (chunk.usage) {\n // For stream responses, the input tokens remain constant across all events in the stream.\n // Output tokens, however, are only finalized in the last event.\n // Since we can't guarantee that the last event will include usage data or even be a typed event,\n // we update the output token values on every event that includes them.\n // This ensures that output token usage is always set, even if the final event lacks it.\n state.promptTokens = chunk.usage.prompt_tokens;\n state.completionTokens = chunk.usage.completion_tokens;\n state.totalTokens = chunk.usage.total_tokens;\n }\n\n for (const choice of chunk.choices ?? []) {\n if (recordOutputs) {\n if (choice.delta?.content) {\n state.responseTexts.push(choice.delta.content);\n }\n\n // Handle tool calls from delta\n if (choice.delta?.tool_calls) {\n processChatCompletionToolCalls(choice.delta.tool_calls, state);\n }\n }\n if (choice.finish_reason) {\n state.finishReasons.push(choice.finish_reason);\n }\n }\n}\n\n/**\n * Processes a single OpenAI Responses API streaming event, updating the streaming state and span.\n *\n * @param streamEvent - The event to process (may be an error or unknown object).\n * @param state - The current streaming state to update.\n * @param recordOutputs - Whether to record output text fragments.\n * @param span - The span to update with error status if needed.\n */\nfunction processResponsesApiEvent(\n streamEvent: ResponseStreamingEvent | unknown | Error,\n state: StreamingState,\n recordOutputs: boolean,\n span: Span,\n): void {\n if (!(streamEvent && typeof streamEvent === 'object')) {\n state.eventTypes.push('unknown:non-object');\n return;\n }\n if (streamEvent instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(streamEvent, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai.stream-response',\n },\n });\n return;\n }\n\n if (!('type' in streamEvent)) return;\n const event = streamEvent as ResponseStreamingEvent;\n\n if (!RESPONSE_EVENT_TYPES.includes(event.type)) {\n state.eventTypes.push(event.type);\n return;\n }\n\n // Handle output text delta\n if (recordOutputs) {\n // Handle tool call events for Responses API\n if (event.type === 'response.output_item.done' && 'item' in event) {\n state.responsesApiToolCalls.push(event.item);\n }\n\n if (event.type === 'response.output_text.delta' && 'delta' in event && event.delta) {\n state.responseTexts.push(event.delta);\n return;\n }\n }\n\n if ('response' in event) {\n const { response } = event as { response: OpenAIResponseObject };\n state.responseId = response.id ?? state.responseId;\n state.responseModel = response.model ?? state.responseModel;\n\n if (response.usage) {\n // For stream responses, the input tokens remain constant across all events in the stream.\n // Output tokens, however, are only finalized in the last event.\n // Since we can't guarantee that the last event will include usage data or even be a typed event,\n // we update the output token values on every event that includes them.\n // This ensures that output token usage is always set, even if the final event lacks it.\n state.promptTokens = response.usage.input_tokens;\n state.completionTokens = response.usage.output_tokens;\n state.totalTokens = response.usage.total_tokens;\n }\n\n if (response.status) {\n state.finishReasons.push(response.status);\n }\n\n if (recordOutputs && response.output_text) {\n state.responseTexts.push(response.output_text);\n }\n }\n}\n\n/**\n * Instruments a stream of OpenAI events, updating the provided span with relevant attributes and\n * optionally recording output text. This function yields each event from the input stream as it is processed.\n *\n * @template T - The type of events in the stream.\n * @param stream - The async iterable stream of events to instrument.\n * @param span - The span to add attributes to and to finish at the end of the stream.\n * @param recordOutputs - Whether to record output text fragments in the span.\n * @returns An async generator yielding each event from the input stream.\n */\nexport async function* instrumentStream<T>(\n stream: AsyncIterable<T>,\n span: Span,\n recordOutputs: boolean,\n): AsyncGenerator<T, void, unknown> {\n const state: StreamingState = {\n eventTypes: [],\n responseTexts: [],\n finishReasons: [],\n responseId: '',\n responseModel: '',\n promptTokens: undefined,\n completionTokens: undefined,\n totalTokens: undefined,\n chatCompletionToolCalls: {},\n responsesApiToolCalls: [],\n };\n\n try {\n for await (const event of stream) {\n if (isChatCompletionChunk(event)) {\n processChatCompletionChunk(event as ChatCompletionChunk, state, recordOutputs);\n } else if (isResponsesApiStreamEvent(event)) {\n processResponsesApiEvent(event as ResponseStreamingEvent, state, recordOutputs, span);\n }\n yield event;\n }\n } finally {\n const allToolCalls = [...Object.values(state.chatCompletionToolCalls), ...state.responsesApiToolCalls];\n endStreamSpan(span, { ...state, toolCalls: allToolCalls }, recordOutputs);\n }\n}\n"],"names":[],"mappings":"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"}
|