@sentry/core 10.40.0 → 10.41.0-beta.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/integrations/consola.js.map +1 -1
- package/build/cjs/tracing/ai/mediaStripping.js +135 -0
- package/build/cjs/tracing/ai/mediaStripping.js.map +1 -0
- package/build/cjs/tracing/ai/messageTruncation.js +18 -60
- package/build/cjs/tracing/ai/messageTruncation.js.map +1 -1
- package/build/cjs/tracing/anthropic-ai/index.js +1 -1
- package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
- package/build/cjs/tracing/google-genai/index.js +1 -1
- package/build/cjs/tracing/google-genai/index.js.map +1 -1
- package/build/cjs/tracing/openai/index.js +1 -1
- package/build/cjs/tracing/openai/index.js.map +1 -1
- package/build/cjs/utils/version.js +1 -1
- package/build/cjs/utils/version.js.map +1 -1
- package/build/esm/integrations/consola.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/tracing/ai/mediaStripping.js +132 -0
- package/build/esm/tracing/ai/mediaStripping.js.map +1 -0
- package/build/esm/tracing/ai/messageTruncation.js +12 -54
- package/build/esm/tracing/ai/messageTruncation.js.map +1 -1
- package/build/esm/tracing/anthropic-ai/index.js +1 -1
- package/build/esm/tracing/anthropic-ai/index.js.map +1 -1
- package/build/esm/tracing/google-genai/index.js +1 -1
- package/build/esm/tracing/google-genai/index.js.map +1 -1
- package/build/esm/tracing/openai/index.js +1 -1
- package/build/esm/tracing/openai/index.js.map +1 -1
- package/build/esm/utils/version.js +1 -1
- package/build/esm/utils/version.js.map +1 -1
- package/build/types/integrations/consola.d.ts +8 -1
- package/build/types/integrations/consola.d.ts.map +1 -1
- package/build/types/tracing/ai/mediaStripping.d.ts +40 -0
- package/build/types/tracing/ai/mediaStripping.d.ts.map +1 -0
- package/build/types/tracing/ai/messageTruncation.d.ts.map +1 -1
- package/build/types/types-hoist/replay.d.ts +1 -0
- package/build/types/types-hoist/replay.d.ts.map +1 -1
- package/build/types-ts3.8/integrations/consola.d.ts +8 -1
- package/build/types-ts3.8/tracing/ai/mediaStripping.d.ts +40 -0
- package/build/types-ts3.8/types-hoist/replay.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/google-genai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\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 { handleCallbackErrors } from '../../utils/handleCallbackErrors';\nimport {\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_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_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_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { truncateGenAiMessages } from '../ai/messageTruncation';\nimport { buildMethodPath, extractSystemInstructions, getFinalOperationName, getSpanOperation } from '../ai/utils';\nimport { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants';\nimport { instrumentStream } from './streaming';\nimport type {\n Candidate,\n ContentPart,\n GoogleGenAIIstrumentedMethod,\n GoogleGenAIOptions,\n GoogleGenAIResponse,\n} from './types';\nimport type { ContentListUnion, ContentUnion, Message, PartListUnion } from './utils';\nimport { contentUnionToMessages, isStreamingMethod, shouldInstrument } from './utils';\n\n/**\n * Extract model from parameters or chat context object\n * For chat instances, the model is available on the chat object as 'model' (older versions) or 'modelVersion' (newer versions)\n */\nexport function extractModel(params: Record<string, unknown>, context?: unknown): string {\n if ('model' in params && typeof params.model === 'string') {\n return params.model;\n }\n\n // Try to get model from chat context object (chat instance has model property)\n if (context && typeof context === 'object') {\n const contextObj = context as Record<string, unknown>;\n\n // Check for 'model' property (older versions, and streaming)\n if ('model' in contextObj && typeof contextObj.model === 'string') {\n return contextObj.model;\n }\n\n // Check for 'modelVersion' property (newer versions)\n if ('modelVersion' in contextObj && typeof contextObj.modelVersion === 'string') {\n return contextObj.modelVersion;\n }\n }\n\n return 'unknown';\n}\n\n/**\n * Extract generation config parameters\n */\nfunction extractConfigAttributes(config: Record<string, unknown>): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {};\n\n if ('temperature' in config && typeof config.temperature === 'number') {\n attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = config.temperature;\n }\n if ('topP' in config && typeof config.topP === 'number') {\n attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = config.topP;\n }\n if ('topK' in config && typeof config.topK === 'number') {\n attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = config.topK;\n }\n if ('maxOutputTokens' in config && typeof config.maxOutputTokens === 'number') {\n attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = config.maxOutputTokens;\n }\n if ('frequencyPenalty' in config && typeof config.frequencyPenalty === 'number') {\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = config.frequencyPenalty;\n }\n if ('presencePenalty' in config && typeof config.presencePenalty === 'number') {\n attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = config.presencePenalty;\n }\n\n return attributes;\n}\n\n/**\n * Extract request attributes from method arguments\n * Builds the base attributes for span creation including system info, model, and config\n */\nfunction extractRequestAttributes(\n methodPath: string,\n params?: Record<string, unknown>,\n context?: unknown,\n): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: GOOGLE_GENAI_SYSTEM_NAME,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.google_genai',\n };\n\n if (params) {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel(params, context);\n\n // Extract generation config parameters\n if ('config' in params && typeof params.config === 'object' && params.config) {\n const config = params.config as Record<string, unknown>;\n Object.assign(attributes, extractConfigAttributes(config));\n\n // Extract available tools from config\n if ('tools' in config && Array.isArray(config.tools)) {\n const functionDeclarations = config.tools.flatMap(\n (tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,\n );\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(functionDeclarations);\n }\n }\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel({}, context);\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 * Handles different parameter formats for different Google GenAI methods.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages: Message[] = [];\n\n // config.systemInstruction: ContentUnion\n if (\n 'config' in params &&\n params.config &&\n typeof params.config === 'object' &&\n 'systemInstruction' in params.config &&\n params.config.systemInstruction\n ) {\n messages.push(...contentUnionToMessages(params.config.systemInstruction as ContentUnion, 'system'));\n }\n\n // For chats.create: history contains the conversation history\n if ('history' in params) {\n messages.push(...contentUnionToMessages(params.history as PartListUnion, 'user'));\n }\n\n // For models.generateContent: ContentListUnion\n if ('contents' in params) {\n messages.push(...contentUnionToMessages(params.contents as ContentListUnion, 'user'));\n }\n\n // For chat.sendMessage: message can be PartListUnion\n if ('message' in params) {\n messages.push(...contentUnionToMessages(params.message as PartListUnion, 'user'));\n }\n\n if (Array.isArray(messages) && messages.length) {\n const { systemInstructions, filteredMessages } = extractSystemInstructions(messages);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify(truncateGenAiMessages(filteredMessages as unknown[])),\n });\n }\n}\n\n/**\n * Add response attributes from the Google GenAI response\n * @see https://github.com/googleapis/js-genai/blob/v1.19.0/src/types.ts#L2313\n */\nfunction addResponseAttributes(span: Span, response: GoogleGenAIResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n if (response.modelVersion) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, response.modelVersion);\n }\n\n // Add usage metadata if present\n if (response.usageMetadata && typeof response.usageMetadata === 'object') {\n const usage = response.usageMetadata;\n if (typeof usage.promptTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: usage.promptTokenCount,\n });\n }\n if (typeof usage.candidatesTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: usage.candidatesTokenCount,\n });\n }\n if (typeof usage.totalTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: usage.totalTokenCount,\n });\n }\n }\n\n // Add response text if recordOutputs is enabled\n if (recordOutputs && Array.isArray(response.candidates) && response.candidates.length > 0) {\n const responseTexts = response.candidates\n .map((candidate: Candidate) => {\n if (candidate.content?.parts && Array.isArray(candidate.content.parts)) {\n return candidate.content.parts\n .map((part: ContentPart) => (typeof part.text === 'string' ? part.text : ''))\n .filter((text: string) => text.length > 0)\n .join('');\n }\n return '';\n })\n .filter((text: string) => text.length > 0);\n\n if (responseTexts.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: responseTexts.join(''),\n });\n }\n }\n\n // Add tool calls if recordOutputs is enabled\n if (recordOutputs && response.functionCalls) {\n const functionCalls = response.functionCalls;\n if (Array.isArray(functionCalls) && functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n}\n\n/**\n * Instrument any async or synchronous genai method with Sentry spans\n * Handles operations like models.generateContent and chat.sendMessage and chats.create\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: GoogleGenAIIstrumentedMethod,\n context: unknown,\n options: GoogleGenAIOptions,\n): (...args: T) => R | Promise<R> {\n const isSyncCreate = methodPath === CHATS_CREATE_METHOD;\n\n return new Proxy(originalMethod, {\n apply(target, _, args: T): R | Promise<R> {\n const params = args[0] as Record<string, unknown> | undefined;\n const requestAttributes = extractRequestAttributes(methodPath, params, context);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n // Check if this is a streaming method\n if (isStreamingMethod(methodPath)) {\n // Use startSpanManual for streaming methods to control span lifecycle\n return startSpanManual(\n {\n name: `${operationName} ${model} stream-response`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n async (span: Span) => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const stream = await target.apply(context, args);\n return instrumentStream(stream, span, Boolean(options.recordOutputs)) 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.google_genai',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n },\n );\n }\n // Single span for both sync and async operations\n return startSpan(\n {\n name: isSyncCreate ? `${operationName} ${model} create` : `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n (span: 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: { handled: false, type: 'auto.ai.google_genai', data: { function: methodPath } },\n });\n },\n () => {},\n result => {\n // Only add response attributes for content-producing methods, not for chats.create\n if (!isSyncCreate) {\n addResponseAttributes(span, result, options.recordOutputs);\n }\n },\n );\n },\n );\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Google GenAI client instrumentation\n * Recursively instruments methods and handles special cases like chats.create\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: GoogleGenAIOptions): T {\n return new Proxy(target, {\n get: (t, prop, receiver) => {\n const value = Reflect.get(t, prop, receiver);\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n if (typeof value === 'function' && shouldInstrument(methodPath)) {\n // Special case: chats.create is synchronous but needs both instrumentation AND result proxying\n if (methodPath === CHATS_CREATE_METHOD) {\n const instrumentedMethod = instrumentMethod(value as (...args: unknown[]) => unknown, methodPath, t, options);\n return function instrumentedAndProxiedCreate(...args: unknown[]): unknown {\n const result = instrumentedMethod(...args);\n // If the result is an object (like a chat instance), proxy it too\n if (result && typeof result === 'object') {\n return createDeepProxy(result, CHAT_PATH, options);\n }\n return result;\n };\n }\n\n return instrumentMethod(value as (...args: unknown[]) => Promise<unknown>, methodPath, t, options);\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context\n return value.bind(t);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n });\n}\n\n/**\n * Instrument a Google GenAI 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 client object\n * @param client - The Google GenAI 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 *\n * @example\n * ```typescript\n * import { GoogleGenAI } from '@google/genai';\n * import { instrumentGoogleGenAIClient } from '@sentry/core';\n *\n * const genAI = new GoogleGenAI({ apiKey: process.env.GOOGLE_GENAI_API_KEY });\n * const instrumentedClient = instrumentGoogleGenAIClient(genAI);\n *\n * // Now both chats.create and sendMessage will be instrumented\n * const chat = instrumentedClient.chats.create({ model: 'gemini-1.5-pro' });\n * const response = await chat.sendMessage({ message: 'Hello' });\n * ```\n */\nexport function instrumentGoogleGenAIClient<T extends object>(client: T, options?: GoogleGenAIOptions): T {\n const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n return createDeepProxy(client, '', _options);\n}\n"],"names":["GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GOOGLE_GENAI_SYSTEM_NAME","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","contentUnionToMessages","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","truncateGenAiMessages","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","CHATS_CREATE_METHOD","isStreamingMethod","startSpanManual","getSpanOperation","instrumentStream","SPAN_STATUS_ERROR","captureException","startSpan","handleCallbackErrors","buildMethodPath","shouldInstrument","CHAT_PATH","getClient"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/google-genai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\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 { handleCallbackErrors } from '../../utils/handleCallbackErrors';\nimport {\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_FREQUENCY_PENALTY_ATTRIBUTE,\n GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_REQUEST_PRESENCE_PENALTY_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_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_SYSTEM_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport { truncateGenAiMessages } from '../ai/messageTruncation';\nimport { buildMethodPath, extractSystemInstructions, getFinalOperationName, getSpanOperation } from '../ai/utils';\nimport { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants';\nimport { instrumentStream } from './streaming';\nimport type {\n Candidate,\n ContentPart,\n GoogleGenAIIstrumentedMethod,\n GoogleGenAIOptions,\n GoogleGenAIResponse,\n} from './types';\nimport type { ContentListUnion, ContentUnion, Message, PartListUnion } from './utils';\nimport { contentUnionToMessages, isStreamingMethod, shouldInstrument } from './utils';\n\n/**\n * Extract model from parameters or chat context object\n * For chat instances, the model is available on the chat object as 'model' (older versions) or 'modelVersion' (newer versions)\n */\nexport function extractModel(params: Record<string, unknown>, context?: unknown): string {\n if ('model' in params && typeof params.model === 'string') {\n return params.model;\n }\n\n // Try to get model from chat context object (chat instance has model property)\n if (context && typeof context === 'object') {\n const contextObj = context as Record<string, unknown>;\n\n // Check for 'model' property (older versions, and streaming)\n if ('model' in contextObj && typeof contextObj.model === 'string') {\n return contextObj.model;\n }\n\n // Check for 'modelVersion' property (newer versions)\n if ('modelVersion' in contextObj && typeof contextObj.modelVersion === 'string') {\n return contextObj.modelVersion;\n }\n }\n\n return 'unknown';\n}\n\n/**\n * Extract generation config parameters\n */\nfunction extractConfigAttributes(config: Record<string, unknown>): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {};\n\n if ('temperature' in config && typeof config.temperature === 'number') {\n attributes[GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE] = config.temperature;\n }\n if ('topP' in config && typeof config.topP === 'number') {\n attributes[GEN_AI_REQUEST_TOP_P_ATTRIBUTE] = config.topP;\n }\n if ('topK' in config && typeof config.topK === 'number') {\n attributes[GEN_AI_REQUEST_TOP_K_ATTRIBUTE] = config.topK;\n }\n if ('maxOutputTokens' in config && typeof config.maxOutputTokens === 'number') {\n attributes[GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE] = config.maxOutputTokens;\n }\n if ('frequencyPenalty' in config && typeof config.frequencyPenalty === 'number') {\n attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE] = config.frequencyPenalty;\n }\n if ('presencePenalty' in config && typeof config.presencePenalty === 'number') {\n attributes[GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE] = config.presencePenalty;\n }\n\n return attributes;\n}\n\n/**\n * Extract request attributes from method arguments\n * Builds the base attributes for span creation including system info, model, and config\n */\nfunction extractRequestAttributes(\n methodPath: string,\n params?: Record<string, unknown>,\n context?: unknown,\n): Record<string, SpanAttributeValue> {\n const attributes: Record<string, SpanAttributeValue> = {\n [GEN_AI_SYSTEM_ATTRIBUTE]: GOOGLE_GENAI_SYSTEM_NAME,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getFinalOperationName(methodPath),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.google_genai',\n };\n\n if (params) {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel(params, context);\n\n // Extract generation config parameters\n if ('config' in params && typeof params.config === 'object' && params.config) {\n const config = params.config as Record<string, unknown>;\n Object.assign(attributes, extractConfigAttributes(config));\n\n // Extract available tools from config\n if ('tools' in config && Array.isArray(config.tools)) {\n const functionDeclarations = config.tools.flatMap(\n (tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,\n );\n attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE] = JSON.stringify(functionDeclarations);\n }\n }\n } else {\n attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = extractModel({}, context);\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 * Handles different parameter formats for different Google GenAI methods.\n */\nfunction addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {\n const messages: Message[] = [];\n\n // config.systemInstruction: ContentUnion\n if (\n 'config' in params &&\n params.config &&\n typeof params.config === 'object' &&\n 'systemInstruction' in params.config &&\n params.config.systemInstruction\n ) {\n messages.push(...contentUnionToMessages(params.config.systemInstruction as ContentUnion, 'system'));\n }\n\n // For chats.create: history contains the conversation history\n if ('history' in params) {\n messages.push(...contentUnionToMessages(params.history as PartListUnion, 'user'));\n }\n\n // For models.generateContent: ContentListUnion\n if ('contents' in params) {\n messages.push(...contentUnionToMessages(params.contents as ContentListUnion, 'user'));\n }\n\n // For chat.sendMessage: message can be PartListUnion\n if ('message' in params) {\n messages.push(...contentUnionToMessages(params.message as PartListUnion, 'user'));\n }\n\n if (Array.isArray(messages) && messages.length) {\n const { systemInstructions, filteredMessages } = extractSystemInstructions(messages);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: JSON.stringify(truncateGenAiMessages(filteredMessages as unknown[])),\n });\n }\n}\n\n/**\n * Add response attributes from the Google GenAI response\n * @see https://github.com/googleapis/js-genai/blob/v1.19.0/src/types.ts#L2313\n */\nfunction addResponseAttributes(span: Span, response: GoogleGenAIResponse, recordOutputs?: boolean): void {\n if (!response || typeof response !== 'object') return;\n\n if (response.modelVersion) {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, response.modelVersion);\n }\n\n // Add usage metadata if present\n if (response.usageMetadata && typeof response.usageMetadata === 'object') {\n const usage = response.usageMetadata;\n if (typeof usage.promptTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE]: usage.promptTokenCount,\n });\n }\n if (typeof usage.candidatesTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: usage.candidatesTokenCount,\n });\n }\n if (typeof usage.totalTokenCount === 'number') {\n span.setAttributes({\n [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: usage.totalTokenCount,\n });\n }\n }\n\n // Add response text if recordOutputs is enabled\n if (recordOutputs && Array.isArray(response.candidates) && response.candidates.length > 0) {\n const responseTexts = response.candidates\n .map((candidate: Candidate) => {\n if (candidate.content?.parts && Array.isArray(candidate.content.parts)) {\n return candidate.content.parts\n .map((part: ContentPart) => (typeof part.text === 'string' ? part.text : ''))\n .filter((text: string) => text.length > 0)\n .join('');\n }\n return '';\n })\n .filter((text: string) => text.length > 0);\n\n if (responseTexts.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TEXT_ATTRIBUTE]: responseTexts.join(''),\n });\n }\n }\n\n // Add tool calls if recordOutputs is enabled\n if (recordOutputs && response.functionCalls) {\n const functionCalls = response.functionCalls;\n if (Array.isArray(functionCalls) && functionCalls.length > 0) {\n span.setAttributes({\n [GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE]: JSON.stringify(functionCalls),\n });\n }\n }\n}\n\n/**\n * Instrument any async or synchronous genai method with Sentry spans\n * Handles operations like models.generateContent and chat.sendMessage and chats.create\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: GoogleGenAIIstrumentedMethod,\n context: unknown,\n options: GoogleGenAIOptions,\n): (...args: T) => R | Promise<R> {\n const isSyncCreate = methodPath === CHATS_CREATE_METHOD;\n\n return new Proxy(originalMethod, {\n apply(target, _, args: T): R | Promise<R> {\n const params = args[0] as Record<string, unknown> | undefined;\n const requestAttributes = extractRequestAttributes(methodPath, params, context);\n const model = requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] ?? 'unknown';\n const operationName = getFinalOperationName(methodPath);\n\n // Check if this is a streaming method\n if (isStreamingMethod(methodPath)) {\n // Use startSpanManual for streaming methods to control span lifecycle\n return startSpanManual(\n {\n name: `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n async (span: Span) => {\n try {\n if (options.recordInputs && params) {\n addPrivateRequestAttributes(span, params);\n }\n const stream = await target.apply(context, args);\n return instrumentStream(stream, span, Boolean(options.recordOutputs)) 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.google_genai',\n data: { function: methodPath },\n },\n });\n span.end();\n throw error;\n }\n },\n );\n }\n // Single span for both sync and async operations\n return startSpan(\n {\n name: isSyncCreate ? `${operationName} ${model} create` : `${operationName} ${model}`,\n op: getSpanOperation(methodPath),\n attributes: requestAttributes,\n },\n (span: 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: { handled: false, type: 'auto.ai.google_genai', data: { function: methodPath } },\n });\n },\n () => {},\n result => {\n // Only add response attributes for content-producing methods, not for chats.create\n if (!isSyncCreate) {\n addResponseAttributes(span, result, options.recordOutputs);\n }\n },\n );\n },\n );\n },\n }) as (...args: T) => R | Promise<R>;\n}\n\n/**\n * Create a deep proxy for Google GenAI client instrumentation\n * Recursively instruments methods and handles special cases like chats.create\n */\nfunction createDeepProxy<T extends object>(target: T, currentPath = '', options: GoogleGenAIOptions): T {\n return new Proxy(target, {\n get: (t, prop, receiver) => {\n const value = Reflect.get(t, prop, receiver);\n const methodPath = buildMethodPath(currentPath, String(prop));\n\n if (typeof value === 'function' && shouldInstrument(methodPath)) {\n // Special case: chats.create is synchronous but needs both instrumentation AND result proxying\n if (methodPath === CHATS_CREATE_METHOD) {\n const instrumentedMethod = instrumentMethod(value as (...args: unknown[]) => unknown, methodPath, t, options);\n return function instrumentedAndProxiedCreate(...args: unknown[]): unknown {\n const result = instrumentedMethod(...args);\n // If the result is an object (like a chat instance), proxy it too\n if (result && typeof result === 'object') {\n return createDeepProxy(result, CHAT_PATH, options);\n }\n return result;\n };\n }\n\n return instrumentMethod(value as (...args: unknown[]) => Promise<unknown>, methodPath, t, options);\n }\n\n if (typeof value === 'function') {\n // Bind non-instrumented functions to preserve the original `this` context\n return value.bind(t);\n }\n\n if (value && typeof value === 'object') {\n return createDeepProxy(value, methodPath, options);\n }\n\n return value;\n },\n });\n}\n\n/**\n * Instrument a Google GenAI 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 client object\n * @param client - The Google GenAI 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 *\n * @example\n * ```typescript\n * import { GoogleGenAI } from '@google/genai';\n * import { instrumentGoogleGenAIClient } from '@sentry/core';\n *\n * const genAI = new GoogleGenAI({ apiKey: process.env.GOOGLE_GENAI_API_KEY });\n * const instrumentedClient = instrumentGoogleGenAIClient(genAI);\n *\n * // Now both chats.create and sendMessage will be instrumented\n * const chat = instrumentedClient.chats.create({ model: 'gemini-1.5-pro' });\n * const response = await chat.sendMessage({ message: 'Hello' });\n * ```\n */\nexport function instrumentGoogleGenAIClient<T extends object>(client: T, options?: GoogleGenAIOptions): T {\n const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n return createDeepProxy(client, '', _options);\n}\n"],"names":["GEN_AI_REQUEST_TEMPERATURE_ATTRIBUTE","GEN_AI_REQUEST_TOP_P_ATTRIBUTE","GEN_AI_REQUEST_TOP_K_ATTRIBUTE","GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE","GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE","GEN_AI_REQUEST_PRESENCE_PENALTY_ATTRIBUTE","GEN_AI_SYSTEM_ATTRIBUTE","GOOGLE_GENAI_SYSTEM_NAME","GEN_AI_OPERATION_NAME_ATTRIBUTE","getFinalOperationName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","contentUnionToMessages","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","truncateGenAiMessages","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","CHATS_CREATE_METHOD","isStreamingMethod","startSpanManual","getSpanOperation","instrumentStream","SPAN_STATUS_ERROR","captureException","startSpan","handleCallbackErrors","buildMethodPath","shouldInstrument","CHAT_PATH","getClient"],"mappings":"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"}
|
|
@@ -230,7 +230,7 @@ function instrumentMethod(
|
|
|
230
230
|
const isStreamRequested = params && typeof params === 'object' && params.stream === true;
|
|
231
231
|
|
|
232
232
|
const spanConfig = {
|
|
233
|
-
name: `${operationName} ${model}
|
|
233
|
+
name: `${operationName} ${model}`,
|
|
234
234
|
op: utils.getSpanOperation(methodPath),
|
|
235
235
|
attributes: requestAttributes ,
|
|
236
236
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/tracing/openai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\nimport { 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 } 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}${isStreamRequested ? ' stream-response' : ''}`,\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 const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n\n return createDeepProxy(client, '', _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","getClient"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/tracing/openai/index.ts"],"sourcesContent":["import { getClient } from '../../currentScopes';\nimport { 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 } 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 const sendDefaultPii = Boolean(getClient()?.getOptions().sendDefaultPii);\n\n const _options = {\n recordInputs: sendDefaultPii,\n recordOutputs: sendDefaultPii,\n ...options,\n };\n\n return createDeepProxy(client, '', _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","getClient"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
// This is a magic string replaced by rollup
|
|
4
4
|
|
|
5
|
-
const SDK_VERSION = "10.
|
|
5
|
+
const SDK_VERSION = "10.41.0-beta.0" ;
|
|
6
6
|
|
|
7
7
|
exports.SDK_VERSION = SDK_VERSION;
|
|
8
8
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sources":["../../../src/utils/version.ts"],"sourcesContent":["// This is a magic string replaced by rollup\ndeclare const __SENTRY_SDK_VERSION__: string;\n\nexport const SDK_VERSION = typeof __SENTRY_SDK_VERSION__ === 'string' ? __SENTRY_SDK_VERSION__ : '0.0.0-unknown.0';\n"],"names":[],"mappings":";;AAAA;;AAGO,MAAM,WAAA,GAA2D,
|
|
1
|
+
{"version":3,"file":"version.js","sources":["../../../src/utils/version.ts"],"sourcesContent":["// This is a magic string replaced by rollup\ndeclare const __SENTRY_SDK_VERSION__: string;\n\nexport const SDK_VERSION = typeof __SENTRY_SDK_VERSION__ === 'string' ? __SENTRY_SDK_VERSION__ : '0.0.0-unknown.0';\n"],"names":[],"mappings":";;AAAA;;AAGO,MAAM,WAAA,GAA2D,gBAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consola.js","sources":["../../../src/integrations/consola.ts"],"sourcesContent":["import type { Client } from '../client';\nimport { getClient } from '../currentScopes';\nimport { _INTERNAL_captureLog } from '../logs/internal';\nimport { formatConsoleArgs } from '../logs/utils';\nimport type { LogSeverityLevel } from '../types-hoist/log';\n\n/**\n * Options for the Sentry Consola reporter.\n */\ninterface ConsolaReporterOptions {\n /**\n * Use this option to filter which levels should be captured. By default, all levels are captured.\n *\n * @example\n * ```ts\n * const sentryReporter = Sentry.createConsolaReporter({\n * // Only capture error and warn logs\n * levels: ['error', 'warn'],\n * });\n * consola.addReporter(sentryReporter);\n * ```\n */\n levels?: Array<LogSeverityLevel>;\n\n /**\n * Optionally provide a specific Sentry client instance to use for capturing logs.\n * If not provided, the current client will be retrieved using `getClient()`.\n *\n * This is useful when you want to use specific client options for log normalization\n * or when working with multiple client instances.\n *\n * @example\n * ```ts\n * const sentryReporter = Sentry.createConsolaReporter({\n * client: myCustomClient,\n * });\n * ```\n */\n client?: Client;\n}\n\nexport interface ConsolaReporter {\n log: (logObj: ConsolaLogObject) => void;\n}\n\n/**\n * Represents a log object that Consola reporters receive.\n *\n * This interface matches the structure of log objects passed to Consola reporters.\n * See: https://github.com/unjs/consola#custom-reporters\n *\n * @example\n * ```ts\n * const reporter = {\n * log(logObj: ConsolaLogObject) {\n * console.log(`[${logObj.type}] ${logObj.message || logObj.args?.join(' ')}`);\n * }\n * };\n * consola.addReporter(reporter);\n * ```\n */\nexport interface ConsolaLogObject {\n /**\n * Allows additional custom properties to be set on the log object.\n * These properties will be captured as log attributes with a 'consola.' prefix.\n *\n * @example\n * ```ts\n * const reporter = Sentry.createConsolaReporter();\n * reporter.log({\n * type: 'info',\n * message: 'User action',\n * userId: 123,\n * sessionId: 'abc-123'\n * });\n * // Will create attributes: consola.userId and consola.sessionId\n * ```\n */\n [key: string]: unknown;\n\n /**\n * The numeric log level (0-5) or null.\n *\n * Consola log levels:\n * - 0: Fatal and Error\n * - 1: Warnings\n * - 2: Normal logs\n * - 3: Informational logs, success, fail, ready, start, box, ...\n * - 4: Debug logs\n * - 5: Trace logs\n * - null: Some special types like 'verbose'\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#log-level\n */\n level?: number | null;\n\n /**\n * The log type/method name (e.g., 'error', 'warn', 'info', 'debug', 'trace', 'success', 'fail', etc.).\n *\n * Consola built-in types include:\n * - Standard: silent, fatal, error, warn, log, info, success, fail, ready, start, box, debug, trace, verbose\n * - Custom types can also be defined\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#log-types\n */\n type?: string;\n\n /**\n * An optional tag/scope for the log entry.\n *\n * Tags are created using `consola.withTag('scope')` and help categorize logs.\n *\n * @example\n * ```ts\n * const scopedLogger = consola.withTag('auth');\n * scopedLogger.info('User logged in'); // tag will be 'auth'\n * ```\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#withtagtag\n */\n tag?: string;\n\n /**\n * The raw arguments passed to the log method.\n *\n * When `message` is not provided, these args are typically formatted into the final message.\n *\n * @example\n * ```ts\n * consola.info('Hello', 'world', { user: 'john' });\n * // args = ['Hello', 'world', { user: 'john' }]\n * ```\n */\n args?: unknown[];\n\n /**\n * The timestamp when the log was created.\n *\n * This is automatically set by Consola when the log is created.\n */\n date?: Date;\n\n /**\n * The formatted log message.\n *\n * When provided, this is the final formatted message. When not provided,\n * the message should be constructed from the `args` array.\n */\n message?: string;\n}\n\nconst DEFAULT_CAPTURED_LEVELS: Array<LogSeverityLevel> = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\n/**\n * Creates a new Sentry reporter for Consola that forwards logs to Sentry. Requires the `enableLogs` option to be enabled.\n *\n * **Note: This integration supports Consola v3.x only.** The reporter interface and log object structure\n * may differ in other versions of Consola.\n *\n * @param options - Configuration options for the reporter.\n * @returns A Consola reporter that can be added to consola instances.\n *\n * @example\n * ```ts\n * import * as Sentry from '@sentry/node';\n * import { consola } from 'consola';\n *\n * Sentry.init({\n * enableLogs: true,\n * });\n *\n * const sentryReporter = Sentry.createConsolaReporter({\n * // Optional: filter levels to capture\n * levels: ['error', 'warn', 'info'],\n * });\n *\n * consola.addReporter(sentryReporter);\n *\n * // Now consola logs will be captured by Sentry\n * consola.info('This will be sent to Sentry');\n * consola.error('This error will also be sent to Sentry');\n * ```\n */\nexport function createConsolaReporter(options: ConsolaReporterOptions = {}): ConsolaReporter {\n const levels = new Set(options.levels ?? DEFAULT_CAPTURED_LEVELS);\n const providedClient = options.client;\n\n return {\n log(logObj: ConsolaLogObject) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type, level, message: consolaMessage, args, tag, date: _date, ...attributes } = logObj;\n\n // Get client - use provided client or current client\n const client = providedClient || getClient();\n if (!client) {\n return;\n }\n\n // Determine the log severity level\n const logSeverityLevel = getLogSeverityLevel(type, level);\n\n // Early exit if this level should not be captured\n if (!levels.has(logSeverityLevel)) {\n return;\n }\n\n const { normalizeDepth = 3, normalizeMaxBreadth = 1_000 } = client.getOptions();\n\n // Format the log message using the same approach as consola's basic reporter\n const messageParts = [];\n if (consolaMessage) {\n messageParts.push(consolaMessage);\n }\n if (args && args.length > 0) {\n messageParts.push(formatConsoleArgs(args, normalizeDepth, normalizeMaxBreadth));\n }\n const message = messageParts.join(' ');\n\n // Build attributes\n attributes['sentry.origin'] = 'auto.log.consola';\n\n if (tag) {\n attributes['consola.tag'] = tag;\n }\n\n if (type) {\n attributes['consola.type'] = type;\n }\n\n // Only add level if it's a valid number (not null/undefined)\n if (level != null && typeof level === 'number') {\n attributes['consola.level'] = level;\n }\n\n _INTERNAL_captureLog({\n level: logSeverityLevel,\n message,\n attributes,\n });\n },\n };\n}\n\n// Mapping from consola log types to Sentry log severity levels\nconst CONSOLA_TYPE_TO_LOG_SEVERITY_LEVEL_MAP: Record<string, LogSeverityLevel> = {\n // Consola built-in types\n silent: 'trace',\n fatal: 'fatal',\n error: 'error',\n warn: 'warn',\n log: 'info',\n info: 'info',\n success: 'info',\n fail: 'error',\n ready: 'info',\n start: 'info',\n box: 'info',\n debug: 'debug',\n trace: 'trace',\n verbose: 'debug',\n // Custom types that might exist\n critical: 'fatal',\n notice: 'info',\n};\n\n// Mapping from consola log levels (numbers) to Sentry log severity levels\nconst CONSOLA_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP: Record<number, LogSeverityLevel> = {\n 0: 'fatal', // Fatal and Error\n 1: 'warn', // Warnings\n 2: 'info', // Normal logs\n 3: 'info', // Informational logs, success, fail, ready, start, ...\n 4: 'debug', // Debug logs\n 5: 'trace', // Trace logs\n};\n\n/**\n * Determines the log severity level from Consola type and level.\n *\n * @param type - The Consola log type (e.g., 'error', 'warn', 'info')\n * @param level - The Consola numeric log level (0-5) or null for some types like 'verbose'\n * @returns The corresponding Sentry log severity level\n */\nfunction getLogSeverityLevel(type?: string, level?: number | null): LogSeverityLevel {\n // Handle special case for verbose logs (level can be null with infinite level in Consola)\n if (type === 'verbose') {\n return 'debug';\n }\n\n // Handle silent logs - these should be at trace level\n if (type === 'silent') {\n return 'trace';\n }\n\n // First try to map by type (more specific)\n if (type) {\n const mappedLevel = CONSOLA_TYPE_TO_LOG_SEVERITY_LEVEL_MAP[type];\n if (mappedLevel) {\n return mappedLevel;\n }\n }\n\n // Fallback to level mapping (handle null level)\n if (typeof level === 'number') {\n const mappedLevel = CONSOLA_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP[level];\n if (mappedLevel) {\n return mappedLevel;\n }\n }\n\n // Default fallback\n return 'info';\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"consola.js","sources":["../../../src/integrations/consola.ts"],"sourcesContent":["import type { Client } from '../client';\nimport { getClient } from '../currentScopes';\nimport { _INTERNAL_captureLog } from '../logs/internal';\nimport { formatConsoleArgs } from '../logs/utils';\nimport type { LogSeverityLevel } from '../types-hoist/log';\n\n/**\n * Options for the Sentry Consola reporter.\n */\ninterface ConsolaReporterOptions {\n /**\n * Use this option to filter which levels should be captured. By default, all levels are captured.\n *\n * @example\n * ```ts\n * const sentryReporter = Sentry.createConsolaReporter({\n * // Only capture error and warn logs\n * levels: ['error', 'warn'],\n * });\n * consola.addReporter(sentryReporter);\n * ```\n */\n levels?: Array<LogSeverityLevel>;\n\n /**\n * Optionally provide a specific Sentry client instance to use for capturing logs.\n * If not provided, the current client will be retrieved using `getClient()`.\n *\n * This is useful when you want to use specific client options for log normalization\n * or when working with multiple client instances.\n *\n * @example\n * ```ts\n * const sentryReporter = Sentry.createConsolaReporter({\n * client: myCustomClient,\n * });\n * ```\n */\n client?: Client;\n}\n\nexport interface ConsolaReporter {\n log: (logObj: ConsolaLogObject) => void;\n}\n\n/**\n * Represents a log object that Consola reporters receive.\n *\n * This interface matches the structure of log objects passed to Consola reporters.\n * See: https://github.com/unjs/consola#custom-reporters\n *\n * @example\n * ```ts\n * const reporter = {\n * log(logObj: ConsolaLogObject) {\n * console.log(`[${logObj.type}] ${logObj.message || logObj.args?.join(' ')}`);\n * }\n * };\n * consola.addReporter(reporter);\n * ```\n */\nexport interface ConsolaLogObject {\n /**\n * Allows additional custom properties to be set on the log object.\n * These properties will be captured as log attributes with a 'consola.' prefix.\n *\n * @example\n * ```ts\n * const reporter = Sentry.createConsolaReporter();\n * reporter.log({\n * type: 'info',\n * message: 'User action',\n * userId: 123,\n * sessionId: 'abc-123'\n * });\n * // Will create attributes: consola.userId and consola.sessionId\n * ```\n */\n [key: string]: unknown;\n\n /**\n * The numeric log level (0-5) or null.\n *\n * Consola log levels:\n * - 0: Fatal and Error\n * - 1: Warnings\n * - 2: Normal logs\n * - 3: Informational logs, success, fail, ready, start, box, ...\n * - 4: Debug logs\n * - 5: Trace logs\n * - null: Some special types like 'verbose'\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#log-level\n */\n level?: number | null;\n\n /**\n * The log type/method name (e.g., 'error', 'warn', 'info', 'debug', 'trace', 'success', 'fail', etc.).\n *\n * Consola built-in types include:\n * - Standard: silent, fatal, error, warn, log, info, success, fail, ready, start, box, debug, trace, verbose\n * - Custom types can also be defined\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#log-types\n */\n type?: string;\n\n /**\n * An optional tag/scope for the log entry.\n *\n * Tags are created using `consola.withTag('scope')` and help categorize logs.\n *\n * @example\n * ```ts\n * const scopedLogger = consola.withTag('auth');\n * scopedLogger.info('User logged in'); // tag will be 'auth'\n * ```\n *\n * See: https://github.com/unjs/consola/blob/main/README.md#withtagtag\n */\n tag?: string;\n\n /**\n * The raw arguments passed to the log method.\n *\n * These args are typically formatted into the final `message`. In Consola reporters, `message` is not provided.\n *\n * @example\n * ```ts\n * consola.info('Hello', 'world', { user: 'john' });\n * // args = ['Hello', 'world', { user: 'john' }]\n * ```\n *\n * @example\n * ```ts\n * // `message` is a reserved property in Consola\n * consola.log({ message: 'Hello' });\n * // args = ['Hello']\n * ```\n */\n args?: unknown[];\n\n /**\n * The timestamp when the log was created.\n *\n * This is automatically set by Consola when the log is created.\n */\n date?: Date;\n\n /**\n * The formatted log message.\n *\n * When provided, this is the final formatted message. When not provided,\n * the message should be constructed from the `args` array.\n */\n message?: string;\n}\n\nconst DEFAULT_CAPTURED_LEVELS: Array<LogSeverityLevel> = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\n/**\n * Creates a new Sentry reporter for Consola that forwards logs to Sentry. Requires the `enableLogs` option to be enabled.\n *\n * **Note: This integration supports Consola v3.x only.** The reporter interface and log object structure\n * may differ in other versions of Consola.\n *\n * @param options - Configuration options for the reporter.\n * @returns A Consola reporter that can be added to consola instances.\n *\n * @example\n * ```ts\n * import * as Sentry from '@sentry/node';\n * import { consola } from 'consola';\n *\n * Sentry.init({\n * enableLogs: true,\n * });\n *\n * const sentryReporter = Sentry.createConsolaReporter({\n * // Optional: filter levels to capture\n * levels: ['error', 'warn', 'info'],\n * });\n *\n * consola.addReporter(sentryReporter);\n *\n * // Now consola logs will be captured by Sentry\n * consola.info('This will be sent to Sentry');\n * consola.error('This error will also be sent to Sentry');\n * ```\n */\nexport function createConsolaReporter(options: ConsolaReporterOptions = {}): ConsolaReporter {\n const levels = new Set(options.levels ?? DEFAULT_CAPTURED_LEVELS);\n const providedClient = options.client;\n\n return {\n log(logObj: ConsolaLogObject) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type, level, message: consolaMessage, args, tag, date: _date, ...attributes } = logObj;\n\n // Get client - use provided client or current client\n const client = providedClient || getClient();\n if (!client) {\n return;\n }\n\n // Determine the log severity level\n const logSeverityLevel = getLogSeverityLevel(type, level);\n\n // Early exit if this level should not be captured\n if (!levels.has(logSeverityLevel)) {\n return;\n }\n\n const { normalizeDepth = 3, normalizeMaxBreadth = 1_000 } = client.getOptions();\n\n // Format the log message using the same approach as consola's basic reporter\n const messageParts = [];\n if (consolaMessage) {\n messageParts.push(consolaMessage);\n }\n if (args && args.length > 0) {\n messageParts.push(formatConsoleArgs(args, normalizeDepth, normalizeMaxBreadth));\n }\n const message = messageParts.join(' ');\n\n // Build attributes\n attributes['sentry.origin'] = 'auto.log.consola';\n\n if (tag) {\n attributes['consola.tag'] = tag;\n }\n\n if (type) {\n attributes['consola.type'] = type;\n }\n\n // Only add level if it's a valid number (not null/undefined)\n if (level != null && typeof level === 'number') {\n attributes['consola.level'] = level;\n }\n\n _INTERNAL_captureLog({\n level: logSeverityLevel,\n message,\n attributes,\n });\n },\n };\n}\n\n// Mapping from consola log types to Sentry log severity levels\nconst CONSOLA_TYPE_TO_LOG_SEVERITY_LEVEL_MAP: Record<string, LogSeverityLevel> = {\n // Consola built-in types\n silent: 'trace',\n fatal: 'fatal',\n error: 'error',\n warn: 'warn',\n log: 'info',\n info: 'info',\n success: 'info',\n fail: 'error',\n ready: 'info',\n start: 'info',\n box: 'info',\n debug: 'debug',\n trace: 'trace',\n verbose: 'debug',\n // Custom types that might exist\n critical: 'fatal',\n notice: 'info',\n};\n\n// Mapping from consola log levels (numbers) to Sentry log severity levels\nconst CONSOLA_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP: Record<number, LogSeverityLevel> = {\n 0: 'fatal', // Fatal and Error\n 1: 'warn', // Warnings\n 2: 'info', // Normal logs\n 3: 'info', // Informational logs, success, fail, ready, start, ...\n 4: 'debug', // Debug logs\n 5: 'trace', // Trace logs\n};\n\n/**\n * Determines the log severity level from Consola type and level.\n *\n * @param type - The Consola log type (e.g., 'error', 'warn', 'info')\n * @param level - The Consola numeric log level (0-5) or null for some types like 'verbose'\n * @returns The corresponding Sentry log severity level\n */\nfunction getLogSeverityLevel(type?: string, level?: number | null): LogSeverityLevel {\n // Handle special case for verbose logs (level can be null with infinite level in Consola)\n if (type === 'verbose') {\n return 'debug';\n }\n\n // Handle silent logs - these should be at trace level\n if (type === 'silent') {\n return 'trace';\n }\n\n // First try to map by type (more specific)\n if (type) {\n const mappedLevel = CONSOLA_TYPE_TO_LOG_SEVERITY_LEVEL_MAP[type];\n if (mappedLevel) {\n return mappedLevel;\n }\n }\n\n // Fallback to level mapping (handle null level)\n if (typeof level === 'number') {\n const mappedLevel = CONSOLA_LEVEL_TO_LOG_SEVERITY_LEVEL_MAP[level];\n if (mappedLevel) {\n return mappedLevel;\n }\n }\n\n // Default fallback\n return 'info';\n}\n"],"names":[],"mappings":"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"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.41.0-beta.0","sideEffects":false}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline media content source, with a potentially very large base64
|
|
3
|
+
* blob or data: uri.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if a content part is an OpenAI/Anthropic media source
|
|
8
|
+
*/
|
|
9
|
+
function isContentMedia(part) {
|
|
10
|
+
if (!part || typeof part !== 'object') return false;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
isContentMediaSource(part) ||
|
|
14
|
+
hasInlineData(part) ||
|
|
15
|
+
hasImageUrl(part) ||
|
|
16
|
+
hasInputAudio(part) ||
|
|
17
|
+
hasFileData(part) ||
|
|
18
|
+
hasMediaTypeData(part) ||
|
|
19
|
+
hasBlobOrBase64Type(part) ||
|
|
20
|
+
hasB64Json(part) ||
|
|
21
|
+
hasImageGenerationResult(part) ||
|
|
22
|
+
hasDataUri(part)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hasImageUrl(part) {
|
|
27
|
+
if (!('image_url' in part)) return false;
|
|
28
|
+
if (typeof part.image_url === 'string') return part.image_url.startsWith('data:');
|
|
29
|
+
return hasNestedImageUrl(part);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function hasNestedImageUrl(part) {
|
|
33
|
+
return (
|
|
34
|
+
'image_url' in part &&
|
|
35
|
+
!!part.image_url &&
|
|
36
|
+
typeof part.image_url === 'object' &&
|
|
37
|
+
'url' in part.image_url &&
|
|
38
|
+
typeof part.image_url.url === 'string' &&
|
|
39
|
+
part.image_url.url.startsWith('data:')
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isContentMediaSource(part) {
|
|
44
|
+
return 'type' in part && typeof part.type === 'string' && 'source' in part && isContentMedia(part.source);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function hasInlineData(part) {
|
|
48
|
+
return (
|
|
49
|
+
'inlineData' in part &&
|
|
50
|
+
!!part.inlineData &&
|
|
51
|
+
typeof part.inlineData === 'object' &&
|
|
52
|
+
'data' in part.inlineData &&
|
|
53
|
+
typeof part.inlineData.data === 'string'
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function hasInputAudio(part) {
|
|
58
|
+
return (
|
|
59
|
+
'type' in part &&
|
|
60
|
+
part.type === 'input_audio' &&
|
|
61
|
+
'input_audio' in part &&
|
|
62
|
+
!!part.input_audio &&
|
|
63
|
+
typeof part.input_audio === 'object' &&
|
|
64
|
+
'data' in part.input_audio &&
|
|
65
|
+
typeof part.input_audio.data === 'string'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function hasFileData(part) {
|
|
70
|
+
return (
|
|
71
|
+
'type' in part &&
|
|
72
|
+
part.type === 'file' &&
|
|
73
|
+
'file' in part &&
|
|
74
|
+
!!part.file &&
|
|
75
|
+
typeof part.file === 'object' &&
|
|
76
|
+
'file_data' in part.file &&
|
|
77
|
+
typeof part.file.file_data === 'string'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function hasMediaTypeData(part) {
|
|
82
|
+
return 'media_type' in part && typeof part.media_type === 'string' && 'data' in part;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function hasBlobOrBase64Type(part) {
|
|
86
|
+
return 'type' in part && (part.type === 'blob' || part.type === 'base64');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function hasB64Json(part) {
|
|
90
|
+
return 'b64_json' in part;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function hasImageGenerationResult(part) {
|
|
94
|
+
return 'type' in part && 'result' in part && part.type === 'image_generation';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function hasDataUri(part) {
|
|
98
|
+
return 'uri' in part && typeof part.uri === 'string' && part.uri.startsWith('data:');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const REMOVED_STRING = '[Blob substitute]';
|
|
102
|
+
|
|
103
|
+
const MEDIA_FIELDS = ['image_url', 'data', 'content', 'b64_json', 'result', 'uri'] ;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Replace inline binary data in a single media content part with a placeholder.
|
|
107
|
+
*/
|
|
108
|
+
function stripInlineMediaFromSingleMessage(part) {
|
|
109
|
+
const strip = { ...part };
|
|
110
|
+
if (isContentMedia(strip.source)) {
|
|
111
|
+
strip.source = stripInlineMediaFromSingleMessage(strip.source);
|
|
112
|
+
}
|
|
113
|
+
if (hasInlineData(part)) {
|
|
114
|
+
strip.inlineData = { ...part.inlineData, data: REMOVED_STRING };
|
|
115
|
+
}
|
|
116
|
+
if (hasNestedImageUrl(part)) {
|
|
117
|
+
strip.image_url = { ...part.image_url, url: REMOVED_STRING };
|
|
118
|
+
}
|
|
119
|
+
if (hasInputAudio(part)) {
|
|
120
|
+
strip.input_audio = { ...part.input_audio, data: REMOVED_STRING };
|
|
121
|
+
}
|
|
122
|
+
if (hasFileData(part)) {
|
|
123
|
+
strip.file = { ...part.file, file_data: REMOVED_STRING };
|
|
124
|
+
}
|
|
125
|
+
for (const field of MEDIA_FIELDS) {
|
|
126
|
+
if (typeof strip[field] === 'string') strip[field] = REMOVED_STRING;
|
|
127
|
+
}
|
|
128
|
+
return strip;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { isContentMedia, stripInlineMediaFromSingleMessage };
|
|
132
|
+
//# sourceMappingURL=mediaStripping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaStripping.js","sources":["../../../../src/tracing/ai/mediaStripping.ts"],"sourcesContent":["/**\n * Inline media content source, with a potentially very large base64\n * blob or data: uri.\n */\nexport type ContentMedia = Record<string, unknown> &\n (\n | {\n media_type: string;\n data: string;\n }\n | {\n image_url: `data:${string}`;\n }\n | {\n image_url: { url: `data:${string}` };\n }\n | {\n type: 'blob' | 'base64';\n content: string;\n }\n | {\n b64_json: string;\n }\n | {\n uri: `data:${string}`;\n }\n | {\n type: 'input_audio';\n input_audio: { data: string };\n }\n | {\n type: 'file';\n file: { file_data?: string };\n }\n );\n\n/**\n * Check if a content part is an OpenAI/Anthropic media source\n */\nexport function isContentMedia(part: unknown): part is ContentMedia {\n if (!part || typeof part !== 'object') return false;\n\n return (\n isContentMediaSource(part) ||\n hasInlineData(part) ||\n hasImageUrl(part) ||\n hasInputAudio(part) ||\n hasFileData(part) ||\n hasMediaTypeData(part) ||\n hasBlobOrBase64Type(part) ||\n hasB64Json(part) ||\n hasImageGenerationResult(part) ||\n hasDataUri(part)\n );\n}\n\nfunction hasImageUrl(part: NonNullable<unknown>): boolean {\n if (!('image_url' in part)) return false;\n if (typeof part.image_url === 'string') return part.image_url.startsWith('data:');\n return hasNestedImageUrl(part);\n}\n\nfunction hasNestedImageUrl(part: NonNullable<unknown>): part is { image_url: { url: string } } {\n return (\n 'image_url' in part &&\n !!part.image_url &&\n typeof part.image_url === 'object' &&\n 'url' in part.image_url &&\n typeof part.image_url.url === 'string' &&\n part.image_url.url.startsWith('data:')\n );\n}\n\nfunction isContentMediaSource(part: NonNullable<unknown>): boolean {\n return 'type' in part && typeof part.type === 'string' && 'source' in part && isContentMedia(part.source);\n}\n\nfunction hasInlineData(part: NonNullable<unknown>): part is { inlineData: { data?: string } } {\n return (\n 'inlineData' in part &&\n !!part.inlineData &&\n typeof part.inlineData === 'object' &&\n 'data' in part.inlineData &&\n typeof part.inlineData.data === 'string'\n );\n}\n\nfunction hasInputAudio(part: NonNullable<unknown>): part is { type: 'input_audio'; input_audio: { data: string } } {\n return (\n 'type' in part &&\n part.type === 'input_audio' &&\n 'input_audio' in part &&\n !!part.input_audio &&\n typeof part.input_audio === 'object' &&\n 'data' in part.input_audio &&\n typeof part.input_audio.data === 'string'\n );\n}\n\nfunction hasFileData(part: NonNullable<unknown>): part is { type: 'file'; file: { file_data: string } } {\n return (\n 'type' in part &&\n part.type === 'file' &&\n 'file' in part &&\n !!part.file &&\n typeof part.file === 'object' &&\n 'file_data' in part.file &&\n typeof part.file.file_data === 'string'\n );\n}\n\nfunction hasMediaTypeData(part: NonNullable<unknown>): part is { media_type: string; data: string } {\n return 'media_type' in part && typeof part.media_type === 'string' && 'data' in part;\n}\n\nfunction hasBlobOrBase64Type(part: NonNullable<unknown>): part is { type: 'blob' | 'base64'; content: string } {\n return 'type' in part && (part.type === 'blob' || part.type === 'base64');\n}\n\nfunction hasB64Json(part: NonNullable<unknown>): part is { b64_json: string } {\n return 'b64_json' in part;\n}\n\nfunction hasImageGenerationResult(part: NonNullable<unknown>): part is { type: 'image_generation'; result: string } {\n return 'type' in part && 'result' in part && part.type === 'image_generation';\n}\n\nfunction hasDataUri(part: NonNullable<unknown>): part is { uri: string } {\n return 'uri' in part && typeof part.uri === 'string' && part.uri.startsWith('data:');\n}\n\nconst REMOVED_STRING = '[Blob substitute]';\n\nconst MEDIA_FIELDS = ['image_url', 'data', 'content', 'b64_json', 'result', 'uri'] as const;\n\n/**\n * Replace inline binary data in a single media content part with a placeholder.\n */\nexport function stripInlineMediaFromSingleMessage(part: ContentMedia): ContentMedia {\n const strip = { ...part };\n if (isContentMedia(strip.source)) {\n strip.source = stripInlineMediaFromSingleMessage(strip.source);\n }\n if (hasInlineData(part)) {\n strip.inlineData = { ...part.inlineData, data: REMOVED_STRING };\n }\n if (hasNestedImageUrl(part)) {\n strip.image_url = { ...part.image_url, url: REMOVED_STRING };\n }\n if (hasInputAudio(part)) {\n strip.input_audio = { ...part.input_audio, data: REMOVED_STRING };\n }\n if (hasFileData(part)) {\n strip.file = { ...part.file, file_data: REMOVED_STRING };\n }\n for (const field of MEDIA_FIELDS) {\n if (typeof strip[field] === 'string') strip[field] = REMOVED_STRING;\n }\n return strip;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isContentMedia, stripInlineMediaFromSingleMessage } from './mediaStripping.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Default maximum size in bytes for GenAI messages.
|
|
3
5
|
* Messages exceeding this limit will be truncated.
|
|
@@ -23,12 +25,12 @@ const jsonBytes = (value) => {
|
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
|
-
* Truncate a string to fit within maxBytes when encoded as UTF-8.
|
|
28
|
+
* Truncate a string to fit within maxBytes (inclusive) when encoded as UTF-8.
|
|
27
29
|
* Uses binary search for efficiency with multi-byte characters.
|
|
28
30
|
*
|
|
29
31
|
* @param text - The string to truncate
|
|
30
|
-
* @param maxBytes - Maximum byte length (UTF-8 encoded)
|
|
31
|
-
* @returns Truncated string
|
|
32
|
+
* @param maxBytes - Maximum byte length (inclusive, UTF-8 encoded)
|
|
33
|
+
* @returns Truncated string whose UTF-8 byte length is at most maxBytes
|
|
32
34
|
*/
|
|
33
35
|
function truncateTextByBytes(text, maxBytes) {
|
|
34
36
|
if (utf8Bytes(text) <= maxBytes) {
|
|
@@ -102,36 +104,6 @@ function isContentArrayMessage(message) {
|
|
|
102
104
|
return message !== null && typeof message === 'object' && 'content' in message && Array.isArray(message.content);
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
/**
|
|
106
|
-
* Check if a content part is an OpenAI/Anthropic media source
|
|
107
|
-
*/
|
|
108
|
-
function isContentMedia(part) {
|
|
109
|
-
if (!part || typeof part !== 'object') return false;
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
isContentMediaSource(part) ||
|
|
113
|
-
hasInlineData(part) ||
|
|
114
|
-
('media_type' in part && typeof part.media_type === 'string' && 'data' in part) ||
|
|
115
|
-
('image_url' in part && typeof part.image_url === 'string' && part.image_url.startsWith('data:')) ||
|
|
116
|
-
('type' in part && (part.type === 'blob' || part.type === 'base64')) ||
|
|
117
|
-
'b64_json' in part ||
|
|
118
|
-
('type' in part && 'result' in part && part.type === 'image_generation') ||
|
|
119
|
-
('uri' in part && typeof part.uri === 'string' && part.uri.startsWith('data:'))
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
function isContentMediaSource(part) {
|
|
123
|
-
return 'type' in part && typeof part.type === 'string' && 'source' in part && isContentMedia(part.source);
|
|
124
|
-
}
|
|
125
|
-
function hasInlineData(part) {
|
|
126
|
-
return (
|
|
127
|
-
'inlineData' in part &&
|
|
128
|
-
!!part.inlineData &&
|
|
129
|
-
typeof part.inlineData === 'object' &&
|
|
130
|
-
'data' in part.inlineData &&
|
|
131
|
-
typeof part.inlineData.data === 'string'
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
107
|
/**
|
|
136
108
|
* Check if a message has the Google GenAI parts format.
|
|
137
109
|
*/
|
|
@@ -256,25 +228,6 @@ function truncateSingleMessage(message, maxBytes) {
|
|
|
256
228
|
return [];
|
|
257
229
|
}
|
|
258
230
|
|
|
259
|
-
const REMOVED_STRING = '[Filtered]';
|
|
260
|
-
|
|
261
|
-
const MEDIA_FIELDS = ['image_url', 'data', 'content', 'b64_json', 'result', 'uri'] ;
|
|
262
|
-
|
|
263
|
-
function stripInlineMediaFromSingleMessage(part) {
|
|
264
|
-
const strip = { ...part };
|
|
265
|
-
if (isContentMedia(strip.source)) {
|
|
266
|
-
strip.source = stripInlineMediaFromSingleMessage(strip.source);
|
|
267
|
-
}
|
|
268
|
-
// google genai inline data blob objects
|
|
269
|
-
if (hasInlineData(part)) {
|
|
270
|
-
strip.inlineData = { ...part.inlineData, data: REMOVED_STRING };
|
|
271
|
-
}
|
|
272
|
-
for (const field of MEDIA_FIELDS) {
|
|
273
|
-
if (typeof strip[field] === 'string') strip[field] = REMOVED_STRING;
|
|
274
|
-
}
|
|
275
|
-
return strip;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
231
|
/**
|
|
279
232
|
* Strip the inline media from message arrays.
|
|
280
233
|
*
|
|
@@ -339,6 +292,11 @@ function truncateMessagesByBytes(messages, maxBytes) {
|
|
|
339
292
|
return messages;
|
|
340
293
|
}
|
|
341
294
|
|
|
295
|
+
// The result is always a single-element array that callers wrap with
|
|
296
|
+
// JSON.stringify([message]), so subtract the 2-byte array wrapper ("[" and "]")
|
|
297
|
+
// to ensure the final serialized value stays under the limit.
|
|
298
|
+
const effectiveMaxBytes = maxBytes - 2;
|
|
299
|
+
|
|
342
300
|
// Always keep only the last message
|
|
343
301
|
const lastMessage = messages[messages.length - 1];
|
|
344
302
|
|
|
@@ -348,12 +306,12 @@ function truncateMessagesByBytes(messages, maxBytes) {
|
|
|
348
306
|
|
|
349
307
|
// Check if it fits
|
|
350
308
|
const messageBytes = jsonBytes(strippedMessage);
|
|
351
|
-
if (messageBytes <=
|
|
309
|
+
if (messageBytes <= effectiveMaxBytes) {
|
|
352
310
|
return stripped;
|
|
353
311
|
}
|
|
354
312
|
|
|
355
313
|
// Truncate the single message if needed
|
|
356
|
-
return truncateSingleMessage(strippedMessage,
|
|
314
|
+
return truncateSingleMessage(strippedMessage, effectiveMaxBytes);
|
|
357
315
|
}
|
|
358
316
|
|
|
359
317
|
/**
|