@sentry/core 10.45.0 → 10.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/build/cjs/asyncContext/stackStrategy.js +6 -11
  2. package/build/cjs/asyncContext/stackStrategy.js.map +1 -1
  3. package/build/cjs/tracing/ai/messageTruncation.js +57 -39
  4. package/build/cjs/tracing/ai/messageTruncation.js.map +1 -1
  5. package/build/cjs/tracing/ai/utils.js +81 -0
  6. package/build/cjs/tracing/ai/utils.js.map +1 -1
  7. package/build/cjs/tracing/anthropic-ai/index.js +35 -19
  8. package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
  9. package/build/cjs/tracing/openai/index.js +3 -73
  10. package/build/cjs/tracing/openai/index.js.map +1 -1
  11. package/build/cjs/tracing/openai/utils.js +0 -8
  12. package/build/cjs/tracing/openai/utils.js.map +1 -1
  13. package/build/cjs/tracing/vercel-ai/index.js +9 -1
  14. package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
  15. package/build/cjs/utils/chain-and-copy-promiselike.js +57 -0
  16. package/build/cjs/utils/chain-and-copy-promiselike.js.map +1 -0
  17. package/build/cjs/utils/handleCallbackErrors.js +15 -11
  18. package/build/cjs/utils/handleCallbackErrors.js.map +1 -1
  19. package/build/cjs/utils/version.js +1 -1
  20. package/build/esm/asyncContext/stackStrategy.js +6 -11
  21. package/build/esm/asyncContext/stackStrategy.js.map +1 -1
  22. package/build/esm/package.json +1 -1
  23. package/build/esm/tracing/ai/messageTruncation.js +57 -39
  24. package/build/esm/tracing/ai/messageTruncation.js.map +1 -1
  25. package/build/esm/tracing/ai/utils.js +81 -1
  26. package/build/esm/tracing/ai/utils.js.map +1 -1
  27. package/build/esm/tracing/anthropic-ai/index.js +36 -20
  28. package/build/esm/tracing/anthropic-ai/index.js.map +1 -1
  29. package/build/esm/tracing/openai/index.js +4 -74
  30. package/build/esm/tracing/openai/index.js.map +1 -1
  31. package/build/esm/tracing/openai/utils.js +1 -8
  32. package/build/esm/tracing/openai/utils.js.map +1 -1
  33. package/build/esm/tracing/vercel-ai/index.js +9 -1
  34. package/build/esm/tracing/vercel-ai/index.js.map +1 -1
  35. package/build/esm/utils/chain-and-copy-promiselike.js +55 -0
  36. package/build/esm/utils/chain-and-copy-promiselike.js.map +1 -0
  37. package/build/esm/utils/handleCallbackErrors.js +15 -11
  38. package/build/esm/utils/handleCallbackErrors.js.map +1 -1
  39. package/build/esm/utils/version.js +1 -1
  40. package/build/types/asyncContext/stackStrategy.d.ts.map +1 -1
  41. package/build/types/tracing/ai/messageTruncation.d.ts.map +1 -1
  42. package/build/types/tracing/ai/utils.d.ts +9 -0
  43. package/build/types/tracing/ai/utils.d.ts.map +1 -1
  44. package/build/types/tracing/anthropic-ai/index.d.ts.map +1 -1
  45. package/build/types/tracing/openai/index.d.ts.map +1 -1
  46. package/build/types/tracing/openai/utils.d.ts +0 -4
  47. package/build/types/tracing/openai/utils.d.ts.map +1 -1
  48. package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
  49. package/build/types/utils/chain-and-copy-promiselike.d.ts +6 -0
  50. package/build/types/utils/chain-and-copy-promiselike.d.ts.map +1 -0
  51. package/build/types/utils/handleCallbackErrors.d.ts.map +1 -1
  52. package/build/types-ts3.8/tracing/ai/utils.d.ts +9 -0
  53. package/build/types-ts3.8/tracing/openai/utils.d.ts +0 -4
  54. package/build/types-ts3.8/utils/chain-and-copy-promiselike.d.ts +6 -0
  55. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/tracing/anthropic-ai/index.ts"],"sourcesContent":["import { 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 { handleCallbackErrors } from '../../utils/handleCallbackErrors';\nimport {\n ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_PROMPT_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_K_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport {\n buildMethodPath,\n getFinalOperationName,\n getSpanOperation,\n resolveAIRecordingOptions,\n setTokenUsageAttributes,\n} from '../ai/utils';\nimport { instrumentAsyncIterableStream, instrumentMessageStream } from './streaming';\nimport type {\n AnthropicAiInstrumentedMethod,\n AnthropicAiOptions,\n AnthropicAiResponse,\n AnthropicAiStreamingEvent,\n ContentBlock,\n} from './types';\nimport { handleResponseError, messagesFromParams, setMessagesAttribute, shouldInstrument } from './utils';\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]: 'anthropic',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.anthropic',\n };\n\n if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {\n const params = args[0] as Record<string, unknown>;\n if (params.tools && Array.isArray(params.tools)) {\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(params.tools);\n }\n\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = params.model ?? 'unknown';\n if ('temperature' in params) attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = params.temperature;\n if ('top_p' in params) attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = params.top_p;\n if ('stream' in params) attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE] = params.stream;\n if ('top_k' in params) attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = params.top_k;\n if ('frequency_penalty' in params)\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = params.frequency_penalty;\n if ('max_tokens' in params) attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = params.max_tokens;\n } else {\n if (methodPath === 'models.retrieve' || methodPath === 'models.get') {\n // models.retrieve(model-id) and models.get(model-id)\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = args[0];\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = 'unknown';\n }\n }\n\n return attributes;\n}\n\n/**\n * Add private request attributes to spans.\n * This is only recorded if recordInputs is true.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages = messagesFromParams(params);\n setMessagesAttribute(span, messages);\n\n if ('prompt' in params) {\n span.setAttributes({ [GEN_AI_PROMPT_ATTRIBUTE]: JSON.stringify(params.prompt) });\n }\n}\n\n/**\n * Add content attributes when recordOutputs is enabled\n */\nfunction addContentAttributes(span: Span, response: AnthropicAiResponse): void {\n // Messages.create\n if ('content' in response) {\n if (Array.isArray(response.content)) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.content\n .map((item: ContentBlock) => item.text)\n .filter(text => !!text)\n .join(''),\n });\n\n const toolCalls: Array<ContentBlock> = [];\n\n for (const item of response.content) {\n if (item.type === 'tool_use' || item.type === 'server_tool_use') {\n toolCalls.push(item);\n }\n }\n if (toolCalls.length > 0) {\n span.setAttributes({ [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(toolCalls) });\n }\n }\n }\n // Completions.create\n if ('completion' in response) {\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.completion });\n }\n // Models.countTokens\n if ('input_tokens' in response) {\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: JSON.stringify(response.input_tokens) });\n }\n}\n\n/**\n * Add basic metadata attributes from the response\n */\nfunction addMetadataAttributes(span: Span, response: AnthropicAiResponse): void {\n if ('id' in response && 'model' in response) {\n span.setAttributes({\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: response.id,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n });\n\n if ('created' in response && typeof response.created === 'number') {\n span.setAttributes({\n [ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(response.created * 1000).toISOString(),\n });\n }\n if ('created_at' in response && typeof response.created_at === 'number') {\n span.setAttributes({\n [ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(response.created_at * 1000).toISOString(),\n });\n }\n\n if ('usage' in response && response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.input_tokens,\n response.usage.output_tokens,\n response.usage.cache_creation_input_tokens,\n response.usage.cache_read_input_tokens,\n );\n }\n }\n}\n\n/**\n * Add response attributes to spans\n */\nfunction addResponseAttributes(span: Span, response: AnthropicAiResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n // capture error, do not add attributes if error (they shouldn't exist)\n if ('type' in response && response.type === 'error') {\n handleResponseError(span, response);\n return;\n }\n\n // Private response attributes that are only recorded if recordOutputs is true.\n if (recordOutputs) {\n addContentAttributes(span, response);\n }\n\n // Add basic metadata attributes\n addMetadataAttributes(span, response);\n}\n\n/**\n * Handle common error catching and reporting for streaming requests\n */\nfunction handleStreamingError(error: unknown, span: Span, methodPath: string): never {\n captureException(error, {\n mechanism: { handled: false, type: 'auto.ai.anthropic', data: { function: methodPath } },\n });\n\n if (span.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n span.end();\n }\n throw error;\n}\n\n/**\n * Handle streaming cases with common logic\n */\nfunction handleStreamingRequest<T extends unknown[], R>(\n originalMethod: (...args: T) => R | Promise<R>,\n target: (...args: T) => R | Promise<R>,\n context: unknown,\n args: T,\n requestAttributes: Record<string, unknown>,\n operationName: string,\n methodPath: string,\n params: Record<string, unknown> | undefined,\n options: AnthropicAiOptions,\n isStreamRequested: boolean,\n isStreamingMethod: boolean,\n): R | Promise<R> {\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const spanConfig = {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n };\n\n // messages.stream() always returns a sync MessageStream, even with stream: true param\n if (isStreamRequested && !isStreamingMethod) {\n return startSpanManual(spanConfig, async span => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const result = await originalMethod.apply(context, args);\n return instrumentAsyncIterableStream(\n result as AsyncIterable<AnthropicAiStreamingEvent>,\n span,\n options.recordOutputs ?? false,\n ) as unknown as R;\n } catch (error) {\n return handleStreamingError(error, span, methodPath);\n }\n });\n } else {\n return startSpanManual(spanConfig, span => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const messageStream = target.apply(context, args);\n return instrumentMessageStream(messageStream, span, options.recordOutputs ?? false);\n } catch (error) {\n return handleStreamingError(error, span, methodPath);\n }\n });\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) => R | Promise<R>,\n methodPath: AnthropicAiInstrumentedMethod,\n context: unknown,\n options: AnthropicAiOptions,\n): (...args: T) => R | Promise<R> {\n return new Proxy(originalMethod, {\n apply(target, thisArg, args: T): R | Promise<R> {\n const requestAttributes = extractRequestAttributes(args, methodPath);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n const params = typeof args[0] === 'object' ? (args[0] as Record<string, unknown>) : undefined;\n const isStreamRequested = Boolean(params?.stream);\n const isStreamingMethod = methodPath === 'messages.stream';\n\n if (isStreamRequested || isStreamingMethod) {\n return handleStreamingRequest(\n originalMethod,\n target,\n context,\n args,\n requestAttributes,\n operationName,\n methodPath,\n params,\n options,\n isStreamRequested,\n isStreamingMethod,\n );\n }\n\n return startSpan(\n {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n },\n span => {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n\n return handleCallbackErrors(\n () => target.apply(context, args),\n error => {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.anthropic',\n data: {\n function: methodPath,\n },\n },\n });\n },\n () => {},\n result => addResponseAttributes(span, result as AnthropicAiResponse, options.recordOutputs),\n );\n },\n );\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Anthropic AI client instrumentation\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: AnthropicAiOptions): 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[]) => 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 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 Anthropic AI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n *\n * @template T - The type of the client that extends object\n * @param client - The Anthropic AI client to instrument\n * @param options - Optional configuration for recording inputs and outputs\n * @returns The instrumented client with the same type as the input\n */\nexport function instrumentAnthropicAiClient<T extends object>(anthropicAiClient: T, options?: AnthropicAiOptions): T {\n return createDeepProxy(anthropicAiClient, '', resolveAIRecordingOptions(options));\n}\n"],"names":["GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","messagesFromParams","setMessagesAttribute","GEN_AI_PROMPT_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE","setTokenUsageAttributes","handleResponseError","captureException","SPAN_STATUS_ERROR","getSpanOperation","startSpanManual","instrumentAsyncIterableStream","instrumentMessageStream","startSpan","handleCallbackErrors","buildMethodPath","shouldInstrument","resolveAIRecordingOptions"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/tracing/anthropic-ai/index.ts"],"sourcesContent":["import { 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 {\n ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_PROMPT_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_K_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport {\n buildMethodPath,\n getFinalOperationName,\n getSpanOperation,\n resolveAIRecordingOptions,\n setTokenUsageAttributes,\n wrapPromiseWithMethods,\n} from '../ai/utils';\nimport { instrumentAsyncIterableStream, instrumentMessageStream } from './streaming';\nimport type {\n AnthropicAiInstrumentedMethod,\n AnthropicAiOptions,\n AnthropicAiResponse,\n AnthropicAiStreamingEvent,\n ContentBlock,\n} from './types';\nimport { handleResponseError, messagesFromParams, setMessagesAttribute, shouldInstrument } from './utils';\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]: 'anthropic',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.anthropic',\n };\n\n if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {\n const params = args[0] as Record<string, unknown>;\n if (params.tools && Array.isArray(params.tools)) {\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(params.tools);\n }\n\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = params.model ?? 'unknown';\n if ('temperature' in params) attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = params.temperature;\n if ('top_p' in params) attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = params.top_p;\n if ('stream' in params) attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE] = params.stream;\n if ('top_k' in params) attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = params.top_k;\n if ('frequency_penalty' in params)\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = params.frequency_penalty;\n if ('max_tokens' in params) attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = params.max_tokens;\n } else {\n if (methodPath === 'models.retrieve' || methodPath === 'models.get') {\n // models.retrieve(model-id) and models.get(model-id)\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = args[0];\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = 'unknown';\n }\n }\n\n return attributes;\n}\n\n/**\n * Add private request attributes to spans.\n * This is only recorded if recordInputs is true.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages = messagesFromParams(params);\n setMessagesAttribute(span, messages);\n\n if ('prompt' in params) {\n span.setAttributes({ [GEN_AI_PROMPT_ATTRIBUTE]: JSON.stringify(params.prompt) });\n }\n}\n\n/**\n * Add content attributes when recordOutputs is enabled\n */\nfunction addContentAttributes(span: Span, response: AnthropicAiResponse): void {\n // Messages.create\n if ('content' in response) {\n if (Array.isArray(response.content)) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.content\n .map((item: ContentBlock) => item.text)\n .filter(text => !!text)\n .join(''),\n });\n\n const toolCalls: Array<ContentBlock> = [];\n\n for (const item of response.content) {\n if (item.type === 'tool_use' || item.type === 'server_tool_use') {\n toolCalls.push(item);\n }\n }\n if (toolCalls.length > 0) {\n span.setAttributes({ [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(toolCalls) });\n }\n }\n }\n // Completions.create\n if ('completion' in response) {\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: response.completion });\n }\n // Models.countTokens\n if ('input_tokens' in response) {\n span.setAttributes({ [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: JSON.stringify(response.input_tokens) });\n }\n}\n\n/**\n * Add basic metadata attributes from the response\n */\nfunction addMetadataAttributes(span: Span, response: AnthropicAiResponse): void {\n if ('id' in response && 'model' in response) {\n span.setAttributes({\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: response.id,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n });\n\n if ('created' in response && typeof response.created === 'number') {\n span.setAttributes({\n [ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(response.created * 1000).toISOString(),\n });\n }\n if ('created_at' in response && typeof response.created_at === 'number') {\n span.setAttributes({\n [ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(response.created_at * 1000).toISOString(),\n });\n }\n\n if ('usage' in response && response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.input_tokens,\n response.usage.output_tokens,\n response.usage.cache_creation_input_tokens,\n response.usage.cache_read_input_tokens,\n );\n }\n }\n}\n\n/**\n * Add response attributes to spans\n */\nfunction addResponseAttributes(span: Span, response: AnthropicAiResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n // capture error, do not add attributes if error (they shouldn't exist)\n if ('type' in response && response.type === 'error') {\n handleResponseError(span, response);\n return;\n }\n\n // Private response attributes that are only recorded if recordOutputs is true.\n if (recordOutputs) {\n addContentAttributes(span, response);\n }\n\n // Add basic metadata attributes\n addMetadataAttributes(span, response);\n}\n\n/**\n * Handle common error catching and reporting for streaming requests\n */\nfunction handleStreamingError(error: unknown, span: Span, methodPath: string): never {\n captureException(error, {\n mechanism: { handled: false, type: 'auto.ai.anthropic', data: { function: methodPath } },\n });\n\n if (span.isRecording()) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n span.end();\n }\n throw error;\n}\n\n/**\n * Handle streaming cases with common logic\n */\nfunction handleStreamingRequest<T extends unknown[], R>(\n originalMethod: (...args: T) => R | Promise<R>,\n target: (...args: T) => R | Promise<R>,\n context: unknown,\n args: T,\n requestAttributes: Record<string, unknown>,\n operationName: string,\n methodPath: string,\n params: Record<string, unknown> | undefined,\n options: AnthropicAiOptions,\n isStreamRequested: boolean,\n isStreamingMethod: boolean,\n): R | Promise<R> {\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const spanConfig = {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n };\n\n // messages.stream() always returns a sync MessageStream, even with stream: true param\n if (isStreamRequested && !isStreamingMethod) {\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpanManual(spanConfig, (span: Span) => {\n originalResult = originalMethod.apply(context, args) as Promise<R>;\n\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n\n return (async () => {\n try {\n const result = await originalResult;\n return instrumentAsyncIterableStream(\n result as AsyncIterable<AnthropicAiStreamingEvent>,\n span,\n options.recordOutputs ?? false,\n ) as unknown as R;\n } catch (error) {\n return handleStreamingError(error, span, methodPath);\n }\n })();\n });\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.anthropic');\n } else {\n return startSpanManual(spanConfig, span => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const messageStream = target.apply(context, args);\n return instrumentMessageStream(messageStream, span, options.recordOutputs ?? false);\n } catch (error) {\n return handleStreamingError(error, span, methodPath);\n }\n });\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) => R | Promise<R>,\n methodPath: AnthropicAiInstrumentedMethod,\n context: unknown,\n options: AnthropicAiOptions,\n): (...args: T) => R | Promise<R> {\n return new Proxy(originalMethod, {\n apply(target, thisArg, args: T): R | Promise<R> {\n const requestAttributes = extractRequestAttributes(args, methodPath);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n const params = typeof args[0] === 'object' ? (args[0] as Record<string, unknown>) : undefined;\n const isStreamRequested = Boolean(params?.stream);\n const isStreamingMethod = methodPath === 'messages.stream';\n\n if (isStreamRequested || isStreamingMethod) {\n return handleStreamingRequest(\n originalMethod,\n target,\n context,\n args,\n requestAttributes,\n operationName,\n methodPath,\n params,\n options,\n isStreamRequested,\n isStreamingMethod,\n );\n }\n\n let originalResult!: Promise<R>;\n\n const instrumentedPromise = startSpan(\n {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes as Record<string, SpanAttributeValue>,\n },\n span => {\n originalResult = target.apply(context, args) as Promise<R>;\n\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n\n return originalResult.then(\n result => {\n addResponseAttributes(span, result as AnthropicAiResponse, options.recordOutputs);\n return result;\n },\n error => {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.anthropic',\n data: {\n function: methodPath,\n },\n },\n });\n throw error;\n },\n );\n },\n );\n\n return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.anthropic');\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Anthropic AI client instrumentation\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: AnthropicAiOptions): 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[]) => 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 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 Anthropic AI client with Sentry tracing\n * Can be used across Node.js, Cloudflare Workers, and Vercel Edge\n *\n * @template T - The type of the client that extends object\n * @param client - The Anthropic AI client to instrument\n * @param options - Optional configuration for recording inputs and outputs\n * @returns The instrumented client with the same type as the input\n */\nexport function instrumentAnthropicAiClient<T extends object>(anthropicAiClient: T, options?: AnthropicAiOptions): T {\n return createDeepProxy(anthropicAiClient, '', resolveAIRecordingOptions(options));\n}\n"],"names":["GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","messagesFromParams","setMessagesAttribute","GEN_AI_PROMPT_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","ANTHROPIC_AI_RESPONSE_TIMESTAMP_ATTRIBUTE","setTokenUsageAttributes","handleResponseError","captureException","SPAN_STATUS_ERROR","getSpanOperation","startSpanManual","instrumentAsyncIterableStream","wrapPromiseWithMethods","instrumentMessageStream","startSpan","buildMethodPath","shouldInstrument","resolveAIRecordingOptions"],"mappings":"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"}
@@ -4,7 +4,6 @@ const debugBuild = require('../../debug-build.js');
4
4
  const _exports = require('../../exports.js');
5
5
  const semanticAttributes = require('../../semanticAttributes.js');
6
6
  const debugLogger = require('../../utils/debug-logger.js');
7
- const is = require('../../utils/is.js');
8
7
  const spanstatus = require('../spanstatus.js');
9
8
  const trace = require('../trace.js');
10
9
  const genAiAttributes = require('../ai/gen-ai-attributes.js');
@@ -140,75 +139,6 @@ function addRequestAttributes(span, params, operationName) {
140
139
  }
141
140
  }
142
141
 
143
- /**
144
- * Creates a wrapped version of .withResponse() that replaces the data field
145
- * with the instrumented result while preserving metadata (response, request_id).
146
- */
147
- async function createWithResponseWrapper(
148
- originalWithResponse,
149
- instrumentedPromise,
150
- ) {
151
- // Attach catch handler to originalWithResponse immediately to prevent unhandled rejection
152
- // If instrumentedPromise rejects first, we still need this handled
153
- const safeOriginalWithResponse = originalWithResponse.catch(error => {
154
- _exports.captureException(error, {
155
- mechanism: {
156
- handled: false,
157
- type: 'auto.ai.openai',
158
- },
159
- });
160
- throw error;
161
- });
162
-
163
- const instrumentedResult = await instrumentedPromise;
164
- const originalWrapper = await safeOriginalWithResponse;
165
-
166
- // Combine instrumented result with original metadata
167
- if (originalWrapper && typeof originalWrapper === 'object' && 'data' in originalWrapper) {
168
- return {
169
- ...originalWrapper,
170
- data: instrumentedResult,
171
- };
172
- }
173
- return instrumentedResult;
174
- }
175
-
176
- /**
177
- * Wraps a promise-like object to preserve additional methods (like .withResponse())
178
- */
179
- function wrapPromiseWithMethods(originalPromiseLike, instrumentedPromise) {
180
- // If the original result is not thenable, return the instrumented promise
181
- // Should not happen with current OpenAI SDK instrumented methods, but just in case.
182
- if (!is.isThenable(originalPromiseLike)) {
183
- return instrumentedPromise;
184
- }
185
-
186
- // Create a proxy that forwards Promise methods to instrumentedPromise
187
- // and preserves additional methods from the original result
188
- return new Proxy(originalPromiseLike, {
189
- get(target, prop) {
190
- // For standard Promise methods (.then, .catch, .finally, Symbol.toStringTag),
191
- // use instrumentedPromise to preserve Sentry instrumentation.
192
- // For custom methods (like .withResponse()), use the original target.
193
- const useInstrumentedPromise = prop in Promise.prototype || prop === Symbol.toStringTag;
194
- const source = useInstrumentedPromise ? instrumentedPromise : target;
195
-
196
- const value = Reflect.get(source, prop) ;
197
-
198
- // Special handling for .withResponse() to preserve instrumentation
199
- // .withResponse() returns { data: T, response: Response, request_id: string }
200
- if (prop === 'withResponse' && typeof value === 'function') {
201
- return function wrappedWithResponse() {
202
- const originalWithResponse = (value ).call(target);
203
- return createWithResponseWrapper(originalWithResponse, instrumentedPromise);
204
- };
205
- }
206
-
207
- return typeof value === 'function' ? value.bind(source) : value;
208
- },
209
- }) ;
210
- }
211
-
212
142
  /**
213
143
  * Instrument a method with Sentry spans
214
144
  * Following Sentry AI Agents Manual Instrumentation conventions
@@ -268,7 +198,7 @@ function instrumentMethod(
268
198
  })();
269
199
  });
270
200
 
271
- return wrapPromiseWithMethods(originalResult, instrumentedPromise);
201
+ return utils.wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');
272
202
  }
273
203
 
274
204
  // Non-streaming
@@ -300,7 +230,7 @@ function instrumentMethod(
300
230
  );
301
231
  });
302
232
 
303
- return wrapPromiseWithMethods(originalResult, instrumentedPromise);
233
+ return utils.wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');
304
234
  };
305
235
  }
306
236
 
@@ -311,7 +241,7 @@ function createDeepProxy(target, currentPath = '', options) {
311
241
  return new Proxy(target, {
312
242
  get(obj, prop) {
313
243
  const value = (obj )[prop];
314
- const methodPath = utils$1.buildMethodPath(currentPath, String(prop));
244
+ const methodPath = utils.buildMethodPath(currentPath, String(prop));
315
245
 
316
246
  if (typeof value === 'function' && utils$1.shouldInstrument(methodPath)) {
317
247
  return instrumentMethod(value , methodPath, obj, options);
@@ -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 { isThenable } from '../../utils/is';\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 { extractSystemInstructions, getTruncatedJsonString, resolveAIRecordingOptions } 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 buildMethodPath,\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 * Creates a wrapped version of .withResponse() that replaces the data field\n * with the instrumented result while preserving metadata (response, request_id).\n */\nasync function createWithResponseWrapper<T>(\n originalWithResponse: Promise<unknown>,\n instrumentedPromise: Promise<T>,\n): Promise<unknown> {\n // Attach catch handler to originalWithResponse immediately to prevent unhandled rejection\n // If instrumentedPromise rejects first, we still need this handled\n const safeOriginalWithResponse = originalWithResponse.catch(error => {\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.openai',\n },\n });\n throw error;\n });\n\n const instrumentedResult = await instrumentedPromise;\n const originalWrapper = await safeOriginalWithResponse;\n\n // Combine instrumented result with original metadata\n if (originalWrapper && typeof originalWrapper === 'object' && 'data' in originalWrapper) {\n return {\n ...originalWrapper,\n data: instrumentedResult,\n };\n }\n return instrumentedResult;\n}\n\n/**\n * Wraps a promise-like object to preserve additional methods (like .withResponse())\n */\nfunction wrapPromiseWithMethods<R>(originalPromiseLike: Promise<R>, instrumentedPromise: Promise<R>): Promise<R> {\n // If the original result is not thenable, return the instrumented promise\n // Should not happen with current OpenAI SDK instrumented methods, but just in case.\n if (!isThenable(originalPromiseLike)) {\n return instrumentedPromise;\n }\n\n // Create a proxy that forwards Promise methods to instrumentedPromise\n // and preserves additional methods from the original result\n return new Proxy(originalPromiseLike, {\n get(target: object, prop: string | symbol): unknown {\n // For standard Promise methods (.then, .catch, .finally, Symbol.toStringTag),\n // use instrumentedPromise to preserve Sentry instrumentation.\n // For custom methods (like .withResponse()), use the original target.\n const useInstrumentedPromise = prop in Promise.prototype || prop === Symbol.toStringTag;\n const source = useInstrumentedPromise ? instrumentedPromise : target;\n\n const value = Reflect.get(source, prop) as unknown;\n\n // Special handling for .withResponse() to preserve instrumentation\n // .withResponse() returns { data: T, response: Response, request_id: string }\n if (prop === 'withResponse' && typeof value === 'function') {\n return function wrappedWithResponse(this: unknown): unknown {\n const originalWithResponse = (value as (...args: unknown[]) => unknown).call(target);\n return createWithResponseWrapper(originalWithResponse, instrumentedPromise);\n };\n }\n\n return typeof value === 'function' ? value.bind(source) : value;\n },\n }) as Promise<R>;\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);\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);\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":["DEBUG_BUILD","debug","GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","getOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","extractRequestParameters","GEN_AI_REQUEST_MODEL_ATTRIBUTE","isChatCompletionResponse","addChatCompletionAttributes","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","isResponsesApiResponse","addResponsesApiAttributes","isEmbeddingsResponse","addEmbeddingsAttributes","isConversationResponse","addConversationAttributes","OPENAI_OPERATIONS","GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","getTruncatedJsonString","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","captureException","isThenable","getSpanOperation","startSpanManual","instrumentStream","SPAN_STATUS_ERROR","startSpan","buildMethodPath","shouldInstrument","resolveAIRecordingOptions"],"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_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":["DEBUG_BUILD","debug","GEN_AI_SYSTEM_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","getOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","extractRequestParameters","GEN_AI_REQUEST_MODEL_ATTRIBUTE","isChatCompletionResponse","addChatCompletionAttributes","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","isResponsesApiResponse","addResponsesApiAttributes","isEmbeddingsResponse","addEmbeddingsAttributes","isConversationResponse","addConversationAttributes","OPENAI_OPERATIONS","GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","getTruncatedJsonString","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","getSpanOperation","startSpanManual","instrumentStream","SPAN_STATUS_ERROR","captureException","wrapPromiseWithMethods","startSpan","buildMethodPath","shouldInstrument","resolveAIRecordingOptions"],"mappings":"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"}
@@ -38,13 +38,6 @@ function shouldInstrument(methodPath) {
38
38
  return constants.INSTRUMENTED_METHODS.includes(methodPath );
39
39
  }
40
40
 
41
- /**
42
- * Build method path from current traversal
43
- */
44
- function buildMethodPath(currentPath, prop) {
45
- return currentPath ? `${currentPath}.${prop}` : prop;
46
- }
47
-
48
41
  /**
49
42
  * Check if response is a Chat Completion object
50
43
  */
@@ -338,7 +331,6 @@ exports.addChatCompletionAttributes = addChatCompletionAttributes;
338
331
  exports.addConversationAttributes = addConversationAttributes;
339
332
  exports.addEmbeddingsAttributes = addEmbeddingsAttributes;
340
333
  exports.addResponsesApiAttributes = addResponsesApiAttributes;
341
- exports.buildMethodPath = buildMethodPath;
342
334
  exports.extractRequestParameters = extractRequestParameters;
343
335
  exports.getOperationName = getOperationName;
344
336
  exports.getSpanOperation = getSpanOperation;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../src/tracing/openai/utils.ts"],"sourcesContent":["import type { Span } from '../../types-hoist/span';\nimport {\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE,\n GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n OPENAI_OPERATIONS,\n OPENAI_RESPONSE_ID_ATTRIBUTE,\n OPENAI_RESPONSE_MODEL_ATTRIBUTE,\n OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE,\n OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,\n OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { INSTRUMENTED_METHODS } from './constants';\nimport type {\n ChatCompletionChunk,\n InstrumentedMethod,\n OpenAiChatCompletionObject,\n OpenAIConversationObject,\n OpenAICreateEmbeddingsObject,\n OpenAIResponseObject,\n ResponseStreamingEvent,\n} from './types';\n\n/**\n * Maps OpenAI method paths to OpenTelemetry semantic convention operation names\n * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#llm-request-spans\n */\nexport function getOperationName(methodPath: string): string {\n if (methodPath.includes('chat.completions')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n if (methodPath.includes('responses')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n if (methodPath.includes('embeddings')) {\n return OPENAI_OPERATIONS.EMBEDDINGS;\n }\n if (methodPath.includes('conversations')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n return methodPath.split('.').pop() || 'unknown';\n}\n\n/**\n * Get the span operation for OpenAI methods\n * Following Sentry's convention: \"gen_ai.{operation_name}\"\n */\nexport function getSpanOperation(methodPath: string): string {\n return `gen_ai.${getOperationName(methodPath)}`;\n}\n\n/**\n * Check if a method path should be instrumented\n */\nexport function shouldInstrument(methodPath: string): methodPath is InstrumentedMethod {\n return INSTRUMENTED_METHODS.includes(methodPath as InstrumentedMethod);\n}\n\n/**\n * Build method path from current traversal\n */\nexport function buildMethodPath(currentPath: string, prop: string): string {\n return currentPath ? `${currentPath}.${prop}` : prop;\n}\n\n/**\n * Check if response is a Chat Completion object\n */\nexport function isChatCompletionResponse(response: unknown): response is OpenAiChatCompletionObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'chat.completion'\n );\n}\n\n/**\n * Check if response is a Responses API object\n */\nexport function isResponsesApiResponse(response: unknown): response is OpenAIResponseObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'response'\n );\n}\n\n/**\n * Check if response is an Embeddings API object\n */\nexport function isEmbeddingsResponse(response: unknown): response is OpenAICreateEmbeddingsObject {\n if (response === null || typeof response !== 'object' || !('object' in response)) {\n return false;\n }\n const responseObject = response as Record<string, unknown>;\n return (\n responseObject.object === 'list' &&\n typeof responseObject.model === 'string' &&\n responseObject.model.toLowerCase().includes('embedding')\n );\n}\n\n/**\n * Check if response is a Conversations API object\n * @see https://platform.openai.com/docs/api-reference/conversations\n */\nexport function isConversationResponse(response: unknown): response is OpenAIConversationObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'conversation'\n );\n}\n\n/**\n * Check if streaming event is from the Responses API\n */\nexport function isResponsesApiStreamEvent(event: unknown): event is ResponseStreamingEvent {\n return (\n event !== null &&\n typeof event === 'object' &&\n 'type' in event &&\n typeof (event as Record<string, unknown>).type === 'string' &&\n ((event as Record<string, unknown>).type as string).startsWith('response.')\n );\n}\n\n/**\n * Check if streaming event is a chat completion chunk\n */\nexport function isChatCompletionChunk(event: unknown): event is ChatCompletionChunk {\n return (\n event !== null &&\n typeof event === 'object' &&\n 'object' in event &&\n (event as Record<string, unknown>).object === 'chat.completion.chunk'\n );\n}\n\n/**\n * Add attributes for Chat Completion responses\n */\nexport function addChatCompletionAttributes(\n span: Span,\n response: OpenAiChatCompletionObject,\n recordOutputs?: boolean,\n): void {\n setCommonResponseAttributes(span, response.id, response.model, response.created);\n if (response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.prompt_tokens,\n response.usage.completion_tokens,\n response.usage.total_tokens,\n );\n }\n if (Array.isArray(response.choices)) {\n const finishReasons = response.choices\n .map(choice => choice.finish_reason)\n .filter((reason): reason is string => reason !== null);\n if (finishReasons.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify(finishReasons),\n });\n }\n\n // Extract tool calls from all choices (only if recordOutputs is true)\n if (recordOutputs) {\n const toolCalls = response.choices\n .map(choice => choice.message?.tool_calls)\n .filter(calls => Array.isArray(calls) && calls.length > 0)\n .flat();\n\n if (toolCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(toolCalls),\n });\n }\n }\n }\n}\n\n/**\n * Add attributes for Responses API responses\n */\nexport function addResponsesApiAttributes(span: Span, response: OpenAIResponseObject, recordOutputs?: boolean): void {\n setCommonResponseAttributes(span, response.id, response.model, response.created_at);\n if (response.status) {\n span.setAttributes({\n [GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify([response.status]),\n });\n }\n if (response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.input_tokens,\n response.usage.output_tokens,\n response.usage.total_tokens,\n );\n }\n\n // Extract function calls from output (only if recordOutputs is true)\n if (recordOutputs) {\n const responseWithOutput = response as OpenAIResponseObject & { output?: unknown[] };\n if (Array.isArray(responseWithOutput.output) && responseWithOutput.output.length > 0) {\n // Filter for function_call type objects in the output array\n const functionCalls = responseWithOutput.output.filter(\n (item): unknown =>\n // oxlint-disable-next-line typescript/prefer-optional-chain\n typeof item === 'object' && item !== null && (item as Record<string, unknown>).type === 'function_call',\n );\n\n if (functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n }\n}\n\n/**\n * Add attributes for Embeddings API responses\n */\nexport function addEmbeddingsAttributes(span: Span, response: OpenAICreateEmbeddingsObject): void {\n span.setAttributes({\n [OPENAI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n });\n\n if (response.usage) {\n setTokenUsageAttributes(span, response.usage.prompt_tokens, undefined, response.usage.total_tokens);\n }\n}\n\n/**\n * Add attributes for Conversations API responses\n * @see https://platform.openai.com/docs/api-reference/conversations\n */\nexport function addConversationAttributes(span: Span, response: OpenAIConversationObject): void {\n const { id, created_at } = response;\n\n span.setAttributes({\n [OPENAI_RESPONSE_ID_ATTRIBUTE]: id,\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: id,\n // The conversation id is used to link messages across API calls\n [GEN_AI_CONVERSATION_ID_ATTRIBUTE]: id,\n });\n\n if (created_at) {\n span.setAttributes({\n [OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(created_at * 1000).toISOString(),\n });\n }\n}\n\n/**\n * Set token usage attributes\n * @param span - The span to add attributes to\n * @param promptTokens - The number of prompt tokens\n * @param completionTokens - The number of completion tokens\n * @param totalTokens - The number of total tokens\n */\nexport function setTokenUsageAttributes(\n span: Span,\n promptTokens?: number,\n completionTokens?: number,\n totalTokens?: number,\n): void {\n if (promptTokens !== undefined) {\n span.setAttributes({\n [OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE]: promptTokens,\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: promptTokens,\n });\n }\n if (completionTokens !== undefined) {\n span.setAttributes({\n [OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE]: completionTokens,\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: completionTokens,\n });\n }\n if (totalTokens !== undefined) {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: totalTokens,\n });\n }\n}\n\n/**\n * Set common response attributes\n * @param span - The span to add attributes to\n * @param id - The response id\n * @param model - The response model\n * @param timestamp - The response timestamp\n */\nexport function setCommonResponseAttributes(span: Span, id: string, model: string, timestamp: number): void {\n span.setAttributes({\n [OPENAI_RESPONSE_ID_ATTRIBUTE]: id,\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: id,\n });\n span.setAttributes({\n [OPENAI_RESPONSE_MODEL_ATTRIBUTE]: model,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: model,\n });\n span.setAttributes({\n [OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(timestamp * 1000).toISOString(),\n });\n}\n\n/**\n * Extract conversation ID from request parameters\n * Supports both Conversations API and previous_response_id chaining\n * @see https://platform.openai.com/docs/guides/conversation-state\n */\nfunction extractConversationId(params: Record<string, unknown>): string | undefined {\n // Conversations API: conversation parameter (e.g., \"conv_...\")\n if ('conversation' in params && typeof params.conversation === 'string') {\n return params.conversation;\n }\n // Responses chaining: previous_response_id links to parent response\n if ('previous_response_id' in params && typeof params.previous_response_id === 'string') {\n return params.previous_response_id;\n }\n return undefined;\n}\n\n/**\n * Extract request parameters including model settings and conversation context\n */\nexport function extractRequestParameters(params: Record<string, unknown>): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n [GEN_AI_REQUEST_MODEL_ATTRIBUTE]: params.model ?? 'unknown',\n };\n\n if ('temperature' in params) attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = params.temperature;\n if ('top_p' in params) attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = params.top_p;\n if ('frequency_penalty' in params) attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = params.frequency_penalty;\n if ('presence_penalty' in params) attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = params.presence_penalty;\n if ('stream' in params) attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE] = params.stream;\n if ('encoding_format' in params) attributes[GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE] = params.encoding_format;\n if ('dimensions' in params) attributes[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE] = params.dimensions;\n\n // Capture conversation ID for linking messages across API calls\n const conversationId = extractConversationId(params);\n if (conversationId) {\n attributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE] = conversationId;\n }\n\n return attributes;\n}\n"],"names":["OPENAI_OPERATIONS","INSTRUMENTED_METHODS","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","OPENAI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","OPENAI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_CONVERSATION_ID_ATTRIBUTE","OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE","OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE","GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/tracing/openai/utils.ts"],"sourcesContent":["import type { Span } from '../../types-hoist/span';\nimport {\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE,\n GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE,\n GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_STREAM_ATTRIBUTE,\n GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE,\n GEN_AI_REQUEST_TOP_P_ATTRIBUTE,\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_ID_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n OPENAI_OPERATIONS,\n OPENAI_RESPONSE_ID_ATTRIBUTE,\n OPENAI_RESPONSE_MODEL_ATTRIBUTE,\n OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE,\n OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE,\n OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { INSTRUMENTED_METHODS } from './constants';\nimport type {\n ChatCompletionChunk,\n InstrumentedMethod,\n OpenAiChatCompletionObject,\n OpenAIConversationObject,\n OpenAICreateEmbeddingsObject,\n OpenAIResponseObject,\n ResponseStreamingEvent,\n} from './types';\n\n/**\n * Maps OpenAI method paths to OpenTelemetry semantic convention operation names\n * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#llm-request-spans\n */\nexport function getOperationName(methodPath: string): string {\n if (methodPath.includes('chat.completions')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n if (methodPath.includes('responses')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n if (methodPath.includes('embeddings')) {\n return OPENAI_OPERATIONS.EMBEDDINGS;\n }\n if (methodPath.includes('conversations')) {\n return OPENAI_OPERATIONS.CHAT;\n }\n return methodPath.split('.').pop() || 'unknown';\n}\n\n/**\n * Get the span operation for OpenAI methods\n * Following Sentry's convention: \"gen_ai.{operation_name}\"\n */\nexport function getSpanOperation(methodPath: string): string {\n return `gen_ai.${getOperationName(methodPath)}`;\n}\n\n/**\n * Check if a method path should be instrumented\n */\nexport function shouldInstrument(methodPath: string): methodPath is InstrumentedMethod {\n return INSTRUMENTED_METHODS.includes(methodPath as InstrumentedMethod);\n}\n\n/**\n * Check if response is a Chat Completion object\n */\nexport function isChatCompletionResponse(response: unknown): response is OpenAiChatCompletionObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'chat.completion'\n );\n}\n\n/**\n * Check if response is a Responses API object\n */\nexport function isResponsesApiResponse(response: unknown): response is OpenAIResponseObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'response'\n );\n}\n\n/**\n * Check if response is an Embeddings API object\n */\nexport function isEmbeddingsResponse(response: unknown): response is OpenAICreateEmbeddingsObject {\n if (response === null || typeof response !== 'object' || !('object' in response)) {\n return false;\n }\n const responseObject = response as Record<string, unknown>;\n return (\n responseObject.object === 'list' &&\n typeof responseObject.model === 'string' &&\n responseObject.model.toLowerCase().includes('embedding')\n );\n}\n\n/**\n * Check if response is a Conversations API object\n * @see https://platform.openai.com/docs/api-reference/conversations\n */\nexport function isConversationResponse(response: unknown): response is OpenAIConversationObject {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'object' in response &&\n (response as Record<string, unknown>).object === 'conversation'\n );\n}\n\n/**\n * Check if streaming event is from the Responses API\n */\nexport function isResponsesApiStreamEvent(event: unknown): event is ResponseStreamingEvent {\n return (\n event !== null &&\n typeof event === 'object' &&\n 'type' in event &&\n typeof (event as Record<string, unknown>).type === 'string' &&\n ((event as Record<string, unknown>).type as string).startsWith('response.')\n );\n}\n\n/**\n * Check if streaming event is a chat completion chunk\n */\nexport function isChatCompletionChunk(event: unknown): event is ChatCompletionChunk {\n return (\n event !== null &&\n typeof event === 'object' &&\n 'object' in event &&\n (event as Record<string, unknown>).object === 'chat.completion.chunk'\n );\n}\n\n/**\n * Add attributes for Chat Completion responses\n */\nexport function addChatCompletionAttributes(\n span: Span,\n response: OpenAiChatCompletionObject,\n recordOutputs?: boolean,\n): void {\n setCommonResponseAttributes(span, response.id, response.model, response.created);\n if (response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.prompt_tokens,\n response.usage.completion_tokens,\n response.usage.total_tokens,\n );\n }\n if (Array.isArray(response.choices)) {\n const finishReasons = response.choices\n .map(choice => choice.finish_reason)\n .filter((reason): reason is string => reason !== null);\n if (finishReasons.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify(finishReasons),\n });\n }\n\n // Extract tool calls from all choices (only if recordOutputs is true)\n if (recordOutputs) {\n const toolCalls = response.choices\n .map(choice => choice.message?.tool_calls)\n .filter(calls => Array.isArray(calls) && calls.length > 0)\n .flat();\n\n if (toolCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(toolCalls),\n });\n }\n }\n }\n}\n\n/**\n * Add attributes for Responses API responses\n */\nexport function addResponsesApiAttributes(span: Span, response: OpenAIResponseObject, recordOutputs?: boolean): void {\n setCommonResponseAttributes(span, response.id, response.model, response.created_at);\n if (response.status) {\n span.setAttributes({\n [GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE]: JSON.stringify([response.status]),\n });\n }\n if (response.usage) {\n setTokenUsageAttributes(\n span,\n response.usage.input_tokens,\n response.usage.output_tokens,\n response.usage.total_tokens,\n );\n }\n\n // Extract function calls from output (only if recordOutputs is true)\n if (recordOutputs) {\n const responseWithOutput = response as OpenAIResponseObject & { output?: unknown[] };\n if (Array.isArray(responseWithOutput.output) && responseWithOutput.output.length > 0) {\n // Filter for function_call type objects in the output array\n const functionCalls = responseWithOutput.output.filter(\n (item): unknown =>\n // oxlint-disable-next-line typescript/prefer-optional-chain\n typeof item === 'object' && item !== null && (item as Record<string, unknown>).type === 'function_call',\n );\n\n if (functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n }\n}\n\n/**\n * Add attributes for Embeddings API responses\n */\nexport function addEmbeddingsAttributes(span: Span, response: OpenAICreateEmbeddingsObject): void {\n span.setAttributes({\n [OPENAI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: response.model,\n });\n\n if (response.usage) {\n setTokenUsageAttributes(span, response.usage.prompt_tokens, undefined, response.usage.total_tokens);\n }\n}\n\n/**\n * Add attributes for Conversations API responses\n * @see https://platform.openai.com/docs/api-reference/conversations\n */\nexport function addConversationAttributes(span: Span, response: OpenAIConversationObject): void {\n const { id, created_at } = response;\n\n span.setAttributes({\n [OPENAI_RESPONSE_ID_ATTRIBUTE]: id,\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: id,\n // The conversation id is used to link messages across API calls\n [GEN_AI_CONVERSATION_ID_ATTRIBUTE]: id,\n });\n\n if (created_at) {\n span.setAttributes({\n [OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(created_at * 1000).toISOString(),\n });\n }\n}\n\n/**\n * Set token usage attributes\n * @param span - The span to add attributes to\n * @param promptTokens - The number of prompt tokens\n * @param completionTokens - The number of completion tokens\n * @param totalTokens - The number of total tokens\n */\nexport function setTokenUsageAttributes(\n span: Span,\n promptTokens?: number,\n completionTokens?: number,\n totalTokens?: number,\n): void {\n if (promptTokens !== undefined) {\n span.setAttributes({\n [OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE]: promptTokens,\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: promptTokens,\n });\n }\n if (completionTokens !== undefined) {\n span.setAttributes({\n [OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE]: completionTokens,\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: completionTokens,\n });\n }\n if (totalTokens !== undefined) {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: totalTokens,\n });\n }\n}\n\n/**\n * Set common response attributes\n * @param span - The span to add attributes to\n * @param id - The response id\n * @param model - The response model\n * @param timestamp - The response timestamp\n */\nexport function setCommonResponseAttributes(span: Span, id: string, model: string, timestamp: number): void {\n span.setAttributes({\n [OPENAI_RESPONSE_ID_ATTRIBUTE]: id,\n [GEN_AI_RESPONSE_ID_ATTRIBUTE]: id,\n });\n span.setAttributes({\n [OPENAI_RESPONSE_MODEL_ATTRIBUTE]: model,\n [GEN_AI_RESPONSE_MODEL_ATTRIBUTE]: model,\n });\n span.setAttributes({\n [OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE]: new Date(timestamp * 1000).toISOString(),\n });\n}\n\n/**\n * Extract conversation ID from request parameters\n * Supports both Conversations API and previous_response_id chaining\n * @see https://platform.openai.com/docs/guides/conversation-state\n */\nfunction extractConversationId(params: Record<string, unknown>): string | undefined {\n // Conversations API: conversation parameter (e.g., \"conv_...\")\n if ('conversation' in params && typeof params.conversation === 'string') {\n return params.conversation;\n }\n // Responses chaining: previous_response_id links to parent response\n if ('previous_response_id' in params && typeof params.previous_response_id === 'string') {\n return params.previous_response_id;\n }\n return undefined;\n}\n\n/**\n * Extract request parameters including model settings and conversation context\n */\nexport function extractRequestParameters(params: Record<string, unknown>): Record<string, unknown> {\n const attributes: Record<string, unknown> = {\n [GEN_AI_REQUEST_MODEL_ATTRIBUTE]: params.model ?? 'unknown',\n };\n\n if ('temperature' in params) attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = params.temperature;\n if ('top_p' in params) attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = params.top_p;\n if ('frequency_penalty' in params) attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = params.frequency_penalty;\n if ('presence_penalty' in params) attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = params.presence_penalty;\n if ('stream' in params) attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE] = params.stream;\n if ('encoding_format' in params) attributes[GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE] = params.encoding_format;\n if ('dimensions' in params) attributes[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE] = params.dimensions;\n\n // Capture conversation ID for linking messages across API calls\n const conversationId = extractConversationId(params);\n if (conversationId) {\n attributes[GEN_AI_CONVERSATION_ID_ATTRIBUTE] = conversationId;\n }\n\n return attributes;\n}\n"],"names":["OPENAI_OPERATIONS","INSTRUMENTED_METHODS","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","OPENAI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","OPENAI_RESPONSE_ID_ATTRIBUTE","GEN_AI_RESPONSE_ID_ATTRIBUTE","GEN_AI_CONVERSATION_ID_ATTRIBUTE","OPENAI_RESPONSE_TIMESTAMP_ATTRIBUTE","OPENAI_USAGE_PROMPT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","OPENAI_USAGE_COMPLETION_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_STREAM_ATTRIBUTE","GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE","GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE"],"mappings":"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"}
@@ -203,6 +203,12 @@ function processEndedVercelAiSpan(span) {
203
203
  return;
204
204
  }
205
205
 
206
+ // The Vercel AI SDK sets span status to raw error message strings.
207
+ // Any such value should be normalized to a SpanStatusType value. We pick internal_error as it is the most generic.
208
+ if (span.status && span.status !== 'ok') {
209
+ span.status = 'internal_error';
210
+ }
211
+
206
212
  renameAttributeKey(attributes, vercelAiAttributes.AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE, genAiAttributes.GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE);
207
213
  renameAttributeKey(attributes, vercelAiAttributes.AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE);
208
214
  renameAttributeKey(attributes, vercelAiAttributes.AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE, genAiAttributes.GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE);
@@ -407,7 +413,9 @@ function addProviderMetadataToAttributes(attributes) {
407
413
  'gen_ai.usage.output_tokens.prediction_rejected',
408
414
  openaiMetadata.rejectedPredictionTokens,
409
415
  );
410
- setAttributeIfDefined(attributes, 'gen_ai.conversation.id', openaiMetadata.responseId);
416
+ if (!attributes['gen_ai.conversation.id']) {
417
+ setAttributeIfDefined(attributes, 'gen_ai.conversation.id', openaiMetadata.responseId);
418
+ }
411
419
  }
412
420
 
413
421
  if (providerMetadataObject.anthropic) {