@posthog/ai 8.6.3 → 8.6.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/sanitization/base64_recognizer.ts","../../src/sanitization/media_type_context.ts","../../src/sanitization/binary_content_redactor.ts","../../src/otel/redact.ts","../../src/otel/spans.ts","../../src/gatewayWarning.ts","../../src/otel/exporter.ts","../../src/otel/processor.ts"],"sourcesContent":["const DATA_URL_PREFIX_RE = /^data:([^;,\\s]+)(?:;[^;,\\s]+)*;base64,/i\nconst BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/\n\nexport type Base64Recognition = { kind: 'data-url'; mediaType: string } | { kind: 'raw' } | { kind: 'none' }\n\nexport class Base64Recognizer {\n recognize(value: string, minLength: number): Base64Recognition {\n const dataUrl = DATA_URL_PREFIX_RE.exec(value)\n if (dataUrl) return { kind: 'data-url', mediaType: dataUrl[1] }\n\n if (value.length < minLength) return { kind: 'none' }\n\n const confidencePrefix = value.slice(0, minLength)\n if (BASE64_ALPHABET_RE.test(confidencePrefix)) {\n return { kind: 'raw' }\n } else {\n return { kind: 'none' }\n }\n }\n}\n","const MIME_HINT_KEYS = ['mediaType', 'media_type', 'mimeType', 'mime_type'] as const\n\nconst STRONG_CONTEXT_KEYS = new Set([\n 'data',\n 'file_data',\n 'fileData',\n 'image_url',\n 'imageUrl',\n 'video_url',\n 'videoUrl',\n 'audio',\n 'audio_data',\n 'audioData',\n 'inline_data',\n 'inlineData',\n 'source',\n 'result',\n])\n\nconst STRONG_CONTEXT_TYPES = new Set([\n 'image',\n 'image_url',\n 'input_image',\n 'audio',\n 'input_audio',\n 'video',\n 'video_url',\n 'file',\n 'input_file',\n 'document',\n 'media',\n 'file-data',\n])\n\nconst FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'file-data'])\n\nconst KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm'])\n\nexport class MediaTypeContext {\n static readonly EMPTY = new MediaTypeContext(undefined, undefined)\n\n constructor(\n private readonly parent: Record<string, unknown> | undefined,\n private readonly key: string | undefined\n ) {}\n\n inferMediaType(): string | undefined {\n return (\n this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey()\n )\n }\n\n inferFromSiblingMime(): string | undefined {\n if (!this.parent) return undefined\n for (const hint of MIME_HINT_KEYS) {\n const v = this.parent[hint]\n if (typeof v === 'string') return v\n }\n return undefined\n }\n\n inferFromSiblingFormat(): string | undefined {\n if (!this.parent) return undefined\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) {\n return `audio/${fmt.toLowerCase()}`\n }\n return undefined\n }\n\n inferFromParentType(): string | undefined {\n if (!this.parent) return undefined\n const t = this.parent.type\n if (typeof t !== 'string') return undefined\n if (t === 'image' || t === 'image_url' || t === 'input_image') return 'image'\n if (t === 'audio' || t === 'input_audio') return 'audio'\n if (t === 'video' || t === 'video_url') return 'video'\n if (FILE_FAMILY_TYPES.has(t)) return 'application/octet-stream'\n return undefined\n }\n\n inferFromKey(): string | undefined {\n if (!this.key) return undefined\n const key = this.key.toLowerCase()\n if (key.includes('audio')) return 'audio'\n if (key.includes('video')) return 'video'\n if (key.includes('image')) return 'image'\n if (key.includes('file') || key.includes('document')) return 'application/octet-stream'\n return undefined\n }\n\n signalsBinary(): boolean {\n if (this.parent) {\n for (const hint of MIME_HINT_KEYS) {\n if (typeof this.parent[hint] === 'string') return true\n }\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) return true\n const t = this.parent.type\n if (typeof t === 'string' && STRONG_CONTEXT_TYPES.has(t)) return true\n }\n if (this.key && STRONG_CONTEXT_KEYS.has(this.key)) return true\n return false\n }\n}\n","import { Base64Recognizer } from './base64_recognizer'\nimport { MediaTypeContext } from './media_type_context'\n\nconst STRONG_CONTEXT_MIN_LENGTH = 64\nconst WEAK_CONTEXT_MIN_LENGTH = 1024\n\nexport class BinaryContentRedactor {\n private visited: WeakSet<object> = new WeakSet()\n\n constructor(private readonly recognizer: Base64Recognizer = new Base64Recognizer()) {}\n\n redact<T>(value: T): T\n redact(value: unknown): unknown {\n if (this.isMultimodalEnabled()) return value\n this.visited = new WeakSet()\n return this.walk(value, MediaTypeContext.EMPTY)\n }\n\n private walk(value: unknown, ctx: MediaTypeContext): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return this.redactString(value, ctx)\n if (typeof value !== 'object') return value\n\n // Buffer extends Uint8Array, so this branch catches both.\n if (typeof Uint8Array !== 'undefined' && value instanceof Uint8Array) {\n return this.placeholderFor(ctx.inferMediaType())\n }\n\n if (this.visited.has(value)) return null\n this.visited.add(value)\n\n if (Array.isArray(value)) {\n return value.map((item) => this.walk(item, ctx))\n }\n\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const k of Object.keys(obj)) {\n out[k] = this.walk(obj[k], new MediaTypeContext(obj, k))\n }\n return out\n }\n\n private redactString(value: string, ctx: MediaTypeContext): string {\n const minLength = ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH\n const recognition = this.recognizer.recognize(value, minLength)\n switch (recognition.kind) {\n case 'data-url':\n return this.placeholderFor(recognition.mediaType)\n case 'raw':\n return this.placeholderFor(ctx.inferMediaType())\n case 'none':\n return value\n }\n }\n\n private placeholderFor(mediaType?: string): string {\n if (!mediaType) return '[base64 redacted]'\n if (mediaType === 'application/octet-stream') return '[base64 file redacted]'\n return `[base64 ${mediaType} redacted]`\n }\n\n private isMultimodalEnabled(): boolean {\n const val = process.env._INTERNAL_LLMA_MULTIMODAL || ''\n return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes'\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api'\nimport type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'\n\nimport { BinaryContentRedactor } from '../sanitization/binary_content_redactor'\n\nconst redactor = new BinaryContentRedactor()\n\nexport function redactSpan(span: ReadableSpan): ReadableSpan {\n const attributes = span.attributes ? redactAttributes(span.attributes) : span.attributes\n const events = span.events ? redactEvents(span.events) : span.events\n if (attributes === span.attributes && events === span.events) {\n return span\n }\n // Copy rather than mutate: the span is shared across every registered processor/exporter.\n return Object.create(span, {\n attributes: { value: attributes, enumerable: true, configurable: true },\n events: { value: events, enumerable: true, configurable: true },\n })\n}\n\nfunction redactAttributes(attributes: Attributes): Attributes {\n let changed = false\n const out: Attributes = {}\n for (const key of Object.keys(attributes)) {\n const value = attributes[key]\n const redacted = value === undefined ? value : redactAttributeValue(value)\n if (redacted !== value) {\n changed = true\n }\n out[key] = redacted\n }\n return changed ? out : attributes\n}\n\nfunction redactEvents(events: TimedEvent[]): TimedEvent[] {\n let changed = false\n const out = events.map((event) => {\n if (!event.attributes) {\n return event\n }\n const attributes = redactAttributes(event.attributes)\n if (attributes === event.attributes) {\n return event\n }\n changed = true\n return { ...event, attributes }\n })\n return changed ? out : events\n}\n\nfunction redactAttributeValue(value: AttributeValue): AttributeValue {\n if (typeof value === 'string') {\n return redactString(value)\n }\n if (isStringArray(value)) {\n let changed = false\n const out = value.map((item) => {\n if (typeof item !== 'string') {\n return item\n }\n const redacted = redactString(item)\n if (redacted !== item) {\n changed = true\n }\n return redacted\n })\n return changed ? out : value\n }\n return value\n}\n\nfunction isStringArray(value: AttributeValue): value is Array<string | null | undefined> {\n return Array.isArray(value) && value.every((item) => typeof item !== 'number' && typeof item !== 'boolean')\n}\n\nfunction redactString(value: string): string {\n const trimmed = value.trimStart()\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n const redacted = redactJson(value)\n if (redacted !== undefined) {\n return redacted\n }\n }\n return redactor.redact(value)\n}\n\nfunction redactJson(value: string): string | undefined {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n } catch {\n return undefined\n }\n if (parsed === null || typeof parsed !== 'object') {\n return undefined\n }\n const redactedStr = JSON.stringify(redactor.redact(parsed))\n // Preserve the original string (and its formatting) when nothing was redacted.\n return redactedStr === JSON.stringify(parsed) ? value : redactedStr\n}\n","import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nconst AI_SPAN_PREFIXES = ['gen_ai.', 'llm.', 'ai.', 'traceloop.'] as const\n\n/**\n * Returns `true` when the span is AI-related — its name or any attribute\n * key starts with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`.\n */\nexport function isAISpan(span: ReadableSpan): boolean {\n if (AI_SPAN_PREFIXES.some((prefix) => span.name.startsWith(prefix))) {\n return true\n }\n const attributes = span.attributes\n if (attributes) {\n return Object.keys(attributes).some((key) => AI_SPAN_PREFIXES.some((prefix) => key.startsWith(prefix)))\n }\n return false\n}\n","// Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway\n// emits its own $ai_generation, so each call would be captured (and, for billable\n// products, billed) twice. We only warn — the wrapper's event carries data the\n// gateway never sees (groups, custom properties, trace hierarchy).\n\n// Keep in sync with the gateway's deployed hosts (see services/llm-gateway in the\n// main repo). gateway.us.posthog.com is live today; the rest are listed ahead of\n// any traffic moving to them.\nexport const POSTHOG_AI_GATEWAY_HOSTS: readonly string[] = [\n 'gateway.posthog.com',\n 'gateway.us.posthog.com',\n 'gateway.eu.posthog.com',\n 'ai-gateway.us.posthog.com',\n 'ai-gateway.eu.posthog.com',\n]\n\n// Swap for the dedicated AI Gateway page once it ships.\nconst GATEWAY_DOCS_URL = 'https://posthog.com/docs/ai-observability'\n\nconst extractHost = (baseURL: string): string | undefined => {\n try {\n // Tolerate bare hosts that omit a scheme, e.g. \"gateway.us.posthog.com/v1\".\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(baseURL)\n return new URL(hasScheme ? baseURL : `https://${baseURL}`).hostname.toLowerCase()\n } catch {\n return undefined\n }\n}\n\nexport const isPostHogAiGatewayUrl = (baseURL: string | undefined | null): boolean => {\n if (!baseURL) {\n return false\n }\n const host = extractHost(baseURL)\n return host !== undefined && POSTHOG_AI_GATEWAY_HOSTS.includes(host)\n}\n\n// Warns on every gateway call by design: the misconfiguration is impossible to\n// miss that way, and a doubled bill is worse than noisy logs.\nexport const warnIfPostHogAiGateway = (baseURL: string | undefined | null): void => {\n if (!isPostHogAiGatewayUrl(baseURL)) {\n return\n }\n console.warn(\n '[PostHog] The PostHog AI wrapper is pointed at the PostHog AI Gateway. ' +\n 'Both capture $ai_generation, so every call is double-counted and double-billed. ' +\n `Use one or the other — see ${GATEWAY_DOCS_URL}.`\n )\n}\n\n// OTel spans don't pass through captureAiGeneration, so detect the gateway from\n// the span's host/URL attributes instead. These follow the GenAI / HTTP semantic\n// conventions: `server.address` is a bare host, `url.full` a full URL, both of\n// which isPostHogAiGatewayUrl accepts.\nconst OTEL_GATEWAY_URL_ATTRIBUTES = ['server.address', 'url.full'] as const\n\nexport const warnIfPostHogAiGatewayOtelAttributes = (attributes: Record<string, unknown> | undefined): void => {\n if (!attributes) {\n return\n }\n for (const key of OTEL_GATEWAY_URL_ATTRIBUTES) {\n const value = attributes[key]\n if (typeof value === 'string' && isPostHogAiGatewayUrl(value)) {\n warnIfPostHogAiGateway(value)\n return\n }\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n// OpenTelemetry's ExportResultCode.SUCCESS is 0. Keep this local so loading the\n// published subpath does not require the exporter package's transitive dependencies.\nconst EXPORT_SUCCESS = 0\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\n/**\n * Options for the PostHogTraceExporter. `projectToken` is required; a blank token disables the\n * exporter as a defensive no-op. You can also optionally override the `host` URL. `host` defaults to `https://us.i.posthog.com`.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...' })\n * ```\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...', host: 'https://eu.i.posthog.com' })\n * ```\n */\nexport type PostHogTraceExporterOptions = { projectToken: string; host?: string }\n\n/**\n * An OpenTelemetry `TraceExporter` that sends AI traces to PostHog's OTLP\n * ingestion endpoint. PostHog converts `gen_ai.*` spans into\n * `$ai_generation` events server-side.\n *\n * Only AI-related spans (those whose name or attribute keys start with\n * `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported; all other\n * spans are silently dropped.\n *\n * Use this when the API you're integrating with only accepts a\n * `TraceExporter` (e.g. Vercel's `registerOTel`) or when you need to\n * plug PostHog into an existing processor chain. Otherwise prefer\n * {@link PostHogSpanProcessor}, which is self-contained.\n *\n * `projectToken` is required; a blank token disables the exporter as a defensive no-op.\n * You can also optionally override the `host` URL.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n * import { registerOTel } from '@vercel/otel'\n *\n * registerOTel({\n * serviceName: 'my-app',\n * traceExporter: new PostHogTraceExporter({ projectToken: 'phc_...' }),\n * })\n * ```\n */\nexport class PostHogTraceExporter extends OTLPTraceExporter {\n private readonly disabled: boolean\n\n constructor(options: PostHogTraceExporterOptions) {\n const token = normalizeToken(options.projectToken)\n const disabled = !token\n const host = token ? new URL(normalizeHost(options.host)).origin : DEFAULT_OTEL_HOST\n super({\n url: `${host}/i/v0/ai/otel`,\n headers: token\n ? {\n Authorization: `Bearer ${token}`,\n }\n : {},\n })\n\n this.disabled = disabled\n if (this.disabled) {\n console.warn('[PostHogTraceExporter] projectToken is missing or blank; the exporter will be disabled.')\n }\n }\n\n override export(spans: ReadableSpan[], resultCallback: (result: { code: number; error?: Error }) => void): void {\n if (this.disabled) {\n // Intentionally report success: missing or blank tokens disable exporting as a compatibility no-op.\n // Reporting failure would make OpenTelemetry treat every span as an export error.\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n\n const aiSpans = spans.filter(isAISpan)\n if (aiSpans.length === 0) {\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n for (const span of aiSpans) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n }\n super.export(aiSpans.map(redactSpan), resultCallback)\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Context } from '@opentelemetry/api'\nimport { BatchSpanProcessor, type SpanProcessor, type ReadableSpan, type Span } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\nexport interface PostHogSpanProcessorOptions {\n /**\n * Your PostHog project token (the `phc_...` key). Required; a blank token disables the\n * processor as a defensive no-op.\n */\n projectToken: string\n\n /**\n * PostHog host URL. Defaults to `https://us.i.posthog.com`.\n */\n host?: string\n\n /**\n * @internal Injected processor for testing — bypasses exporter creation.\n */\n _spanProcessor?: SpanProcessor\n}\n\nclass NoopSpanProcessor implements SpanProcessor {\n onStart(_span: Span, _parentContext: Context): void {\n return\n }\n onEnd(_span: ReadableSpan): void {\n return\n }\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * An OpenTelemetry `SpanProcessor` that sends AI traces to PostHog.\n *\n * `projectToken` is required; a blank token disables the processor as a defensive no-op.\n *\n * Internally batches spans and exports them to PostHog's OTLP ingestion\n * endpoint. Only AI-related spans (those whose name or attribute keys\n * start with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported;\n * all other spans are silently dropped.\n *\n * This is the recommended integration point when your setup accepts a\n * `SpanProcessor`. If you need a `TraceExporter` instead (e.g. for\n * Vercel's `registerOTel`), use {@link PostHogTraceExporter}.\n *\n * @example\n * ```ts\n * import { PostHogSpanProcessor } from '@posthog/ai/otel'\n * import { NodeSDK } from '@opentelemetry/sdk-node'\n *\n * const sdk = new NodeSDK({\n * spanProcessors: [new PostHogSpanProcessor({ projectToken: 'phc_...' })],\n * })\n * sdk.start()\n * ```\n */\nexport class PostHogSpanProcessor implements SpanProcessor {\n private readonly inner: SpanProcessor\n\n constructor(options: PostHogSpanProcessorOptions) {\n const token = normalizeToken(options.projectToken)\n if (!token) {\n console.warn('[PostHogSpanProcessor] projectToken is missing or blank; the processor will be disabled.')\n this.inner = new NoopSpanProcessor()\n return\n }\n\n if (options._spanProcessor) {\n this.inner = options._spanProcessor\n } else {\n const host = new URL(normalizeHost(options.host)).origin\n const exporter = new OTLPTraceExporter({\n url: `${host}/i/v0/ai/otel`,\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n this.inner = new BatchSpanProcessor(exporter)\n }\n }\n\n onStart(span: Span, parentContext: Context): void {\n // Forwarded unconditionally — filtering happens in onEnd. We can't filter\n // here because the span hasn't finished yet and may not have AI attributes\n // set. BatchSpanProcessor.onStart is a no-op so this is safe.\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isAISpan(span)) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n this.inner.onEnd(redactSpan(span))\n }\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n}\n"],"names":["DATA_URL_PREFIX_RE","BASE64_ALPHABET_RE","Base64Recognizer","recognize","value","minLength","dataUrl","exec","kind","mediaType","length","confidencePrefix","slice","test","MIME_HINT_KEYS","STRONG_CONTEXT_KEYS","Set","STRONG_CONTEXT_TYPES","FILE_FAMILY_TYPES","KNOWN_AUDIO_FORMATS","MediaTypeContext","EMPTY","undefined","constructor","parent","key","inferMediaType","inferFromSiblingMime","inferFromSiblingFormat","inferFromParentType","inferFromKey","hint","v","fmt","format","has","toLowerCase","t","type","includes","signalsBinary","STRONG_CONTEXT_MIN_LENGTH","WEAK_CONTEXT_MIN_LENGTH","BinaryContentRedactor","visited","WeakSet","recognizer","redact","isMultimodalEnabled","walk","ctx","redactString","Uint8Array","placeholderFor","add","Array","isArray","map","item","obj","out","k","Object","keys","recognition","val","process","env","_INTERNAL_LLMA_MULTIMODAL","redactor","redactSpan","span","attributes","redactAttributes","events","redactEvents","create","enumerable","configurable","changed","redacted","redactAttributeValue","event","isStringArray","every","trimmed","trimStart","startsWith","redactJson","parsed","JSON","parse","redactedStr","stringify","AI_SPAN_PREFIXES","isAISpan","some","prefix","name","POSTHOG_AI_GATEWAY_HOSTS","GATEWAY_DOCS_URL","extractHost","baseURL","hasScheme","URL","hostname","isPostHogAiGatewayUrl","host","warnIfPostHogAiGateway","console","warn","OTEL_GATEWAY_URL_ATTRIBUTES","warnIfPostHogAiGatewayOtelAttributes","DEFAULT_OTEL_HOST","EXPORT_SUCCESS","normalizeToken","trim","normalizeHost","normalizedValue","PostHogTraceExporter","OTLPTraceExporter","options","token","projectToken","disabled","origin","url","headers","Authorization","export","spans","resultCallback","code","aiSpans","filter","NoopSpanProcessor","onStart","_span","_parentContext","onEnd","shutdown","Promise","resolve","forceFlush","PostHogSpanProcessor","inner","_spanProcessor","exporter","BatchSpanProcessor","parentContext"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/sanitization/base64_recognizer.ts","../../src/sanitization/media_type_context.ts","../../src/sanitization/binary_content_redactor.ts","../../src/otel/redact.ts","../../src/otel/spans.ts","../../src/gatewayWarning.ts","../../src/otel/exporter.ts","../../src/otel/processor.ts"],"sourcesContent":["const DATA_URL_PREFIX_RE = /^data:([^;,\\s]+)(?:;[^;,\\s]+)*;base64,/i\nconst BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/\n\nexport type Base64Recognition = { kind: 'data-url'; mediaType: string } | { kind: 'raw' } | { kind: 'none' }\n\nexport class Base64Recognizer {\n recognize(value: string, minLength: number): Base64Recognition {\n const dataUrl = DATA_URL_PREFIX_RE.exec(value)\n if (dataUrl) return { kind: 'data-url', mediaType: dataUrl[1] }\n\n if (value.length < minLength) return { kind: 'none' }\n\n const confidencePrefix = value.slice(0, minLength)\n if (BASE64_ALPHABET_RE.test(confidencePrefix)) {\n return { kind: 'raw' }\n } else {\n return { kind: 'none' }\n }\n }\n}\n","const MIME_HINT_KEYS = ['mediaType', 'media_type', 'mimeType', 'mime_type'] as const\n\nconst STRONG_CONTEXT_KEYS = new Set([\n 'data',\n 'file_data',\n 'fileData',\n 'image_url',\n 'imageUrl',\n 'video_url',\n 'videoUrl',\n 'audio',\n 'audio_data',\n 'audioData',\n 'inline_data',\n 'inlineData',\n 'source',\n 'result',\n])\n\nconst STRONG_CONTEXT_TYPES = new Set([\n 'image',\n 'image_url',\n 'input_image',\n 'audio',\n 'input_audio',\n 'video',\n 'video_url',\n 'file',\n 'input_file',\n 'document',\n 'media',\n 'file-data',\n])\n\nconst FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'file-data'])\n\nconst KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm'])\n\nexport class MediaTypeContext {\n static readonly EMPTY = new MediaTypeContext(undefined, undefined)\n\n constructor(\n private readonly parent: Record<string, unknown> | undefined,\n private readonly key: string | undefined,\n private readonly explicitMediaType?: string\n ) {}\n\n inferMediaType(): string | undefined {\n return (\n this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey()\n )\n }\n\n inferFromSiblingMime(): string | undefined {\n if (this.explicitMediaType) return this.explicitMediaType\n if (!this.parent) return undefined\n for (const hint of MIME_HINT_KEYS) {\n const v = this.parent[hint]\n if (typeof v === 'string') return v\n }\n return undefined\n }\n\n inferFromSiblingFormat(): string | undefined {\n if (!this.parent) return undefined\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) {\n return `audio/${fmt.toLowerCase()}`\n }\n return undefined\n }\n\n inferFromParentType(): string | undefined {\n if (!this.parent) return undefined\n const t = this.parent.type\n if (typeof t !== 'string') return undefined\n if (t === 'image' || t === 'image_url' || t === 'input_image') return 'image'\n if (t === 'audio' || t === 'input_audio') return 'audio'\n if (t === 'video' || t === 'video_url') return 'video'\n if (FILE_FAMILY_TYPES.has(t)) return 'application/octet-stream'\n return undefined\n }\n\n inferFromKey(): string | undefined {\n if (!this.key) return undefined\n const key = this.key.toLowerCase()\n if (key.includes('audio')) return 'audio'\n if (key.includes('video')) return 'video'\n if (key.includes('image')) return 'image'\n if (key.includes('file') || key.includes('document')) return 'application/octet-stream'\n return undefined\n }\n\n hasExplicitBinaryMediaType(): boolean {\n if (!this.explicitMediaType && (!this.parent || !this.key || !STRONG_CONTEXT_KEYS.has(this.key))) return false\n const mediaType = this.inferFromSiblingMime()\n return mediaType !== undefined && !mediaType.toLowerCase().startsWith('text/')\n }\n\n signalsBinary(): boolean {\n if (this.explicitMediaType) return true\n if (this.parent) {\n for (const hint of MIME_HINT_KEYS) {\n if (typeof this.parent[hint] === 'string') return true\n }\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) return true\n const t = this.parent.type\n if (typeof t === 'string' && STRONG_CONTEXT_TYPES.has(t)) return true\n }\n if (this.key && STRONG_CONTEXT_KEYS.has(this.key)) return true\n return false\n }\n}\n","import { Base64Recognizer } from './base64_recognizer'\nimport { MediaTypeContext } from './media_type_context'\n\nconst STRONG_CONTEXT_MIN_LENGTH = 64\nconst WEAK_CONTEXT_MIN_LENGTH = 1024\n\nexport class BinaryContentRedactor {\n private visited: WeakSet<object> = new WeakSet()\n\n constructor(private readonly recognizer: Base64Recognizer = new Base64Recognizer()) {}\n\n redact<T>(value: T, mediaType?: string): T\n redact(value: unknown, mediaType?: string): unknown {\n if (this.isMultimodalEnabled()) return value\n this.visited = new WeakSet()\n return this.walk(value, mediaType ? new MediaTypeContext(undefined, undefined, mediaType) : MediaTypeContext.EMPTY)\n }\n\n private walk(value: unknown, ctx: MediaTypeContext): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return this.redactString(value, ctx)\n if (typeof value !== 'object') return value\n\n // Buffer extends Uint8Array, so this branch catches both.\n if (typeof Uint8Array !== 'undefined' && value instanceof Uint8Array) {\n return this.placeholderFor(ctx.inferMediaType())\n }\n\n if (this.visited.has(value)) return null\n this.visited.add(value)\n\n if (Array.isArray(value)) {\n return value.map((item) => this.walk(item, ctx))\n }\n\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const k of Object.keys(obj)) {\n out[k] = this.walk(obj[k], new MediaTypeContext(obj, k))\n }\n return out\n }\n\n private redactString(value: string, ctx: MediaTypeContext): string {\n const hasExplicitBinaryMediaType = ctx.hasExplicitBinaryMediaType()\n const recognitionValue = hasExplicitBinaryMediaType ? value.replace(/[\\r\\n]/g, '') : value\n const minLength = hasExplicitBinaryMediaType\n ? Math.min(recognitionValue.length, STRONG_CONTEXT_MIN_LENGTH)\n : ctx.signalsBinary()\n ? STRONG_CONTEXT_MIN_LENGTH\n : WEAK_CONTEXT_MIN_LENGTH\n const recognition = this.recognizer.recognize(recognitionValue, minLength)\n switch (recognition.kind) {\n case 'data-url':\n return this.placeholderFor(recognition.mediaType)\n case 'raw':\n return this.placeholderFor(ctx.inferMediaType())\n case 'none':\n return value\n }\n }\n\n private placeholderFor(mediaType?: string): string {\n if (!mediaType) return '[base64 redacted]'\n if (mediaType === 'application/octet-stream') return '[base64 file redacted]'\n return `[base64 ${mediaType} redacted]`\n }\n\n private isMultimodalEnabled(): boolean {\n const val = process.env._INTERNAL_LLMA_MULTIMODAL || ''\n return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes'\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api'\nimport type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'\n\nimport { BinaryContentRedactor } from '../sanitization/binary_content_redactor'\n\nconst redactor = new BinaryContentRedactor()\n\nexport function redactSpan(span: ReadableSpan): ReadableSpan {\n const attributes = span.attributes ? redactAttributes(span.attributes) : span.attributes\n const events = span.events ? redactEvents(span.events) : span.events\n if (attributes === span.attributes && events === span.events) {\n return span\n }\n // Copy rather than mutate: the span is shared across every registered processor/exporter.\n return Object.create(span, {\n attributes: { value: attributes, enumerable: true, configurable: true },\n events: { value: events, enumerable: true, configurable: true },\n })\n}\n\nfunction redactAttributes(attributes: Attributes): Attributes {\n let changed = false\n const out: Attributes = {}\n for (const key of Object.keys(attributes)) {\n const value = attributes[key]\n const redacted = value === undefined ? value : redactAttributeValue(value)\n if (redacted !== value) {\n changed = true\n }\n out[key] = redacted\n }\n return changed ? out : attributes\n}\n\nfunction redactEvents(events: TimedEvent[]): TimedEvent[] {\n let changed = false\n const out = events.map((event) => {\n if (!event.attributes) {\n return event\n }\n const attributes = redactAttributes(event.attributes)\n if (attributes === event.attributes) {\n return event\n }\n changed = true\n return { ...event, attributes }\n })\n return changed ? out : events\n}\n\nfunction redactAttributeValue(value: AttributeValue): AttributeValue {\n if (typeof value === 'string') {\n return redactString(value)\n }\n if (isStringArray(value)) {\n let changed = false\n const out = value.map((item) => {\n if (typeof item !== 'string') {\n return item\n }\n const redacted = redactString(item)\n if (redacted !== item) {\n changed = true\n }\n return redacted\n })\n return changed ? out : value\n }\n return value\n}\n\nfunction isStringArray(value: AttributeValue): value is Array<string | null | undefined> {\n return Array.isArray(value) && value.every((item) => typeof item !== 'number' && typeof item !== 'boolean')\n}\n\nfunction redactString(value: string): string {\n const trimmed = value.trimStart()\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n const redacted = redactJson(value)\n if (redacted !== undefined) {\n return redacted\n }\n }\n return redactor.redact(value)\n}\n\nfunction redactJson(value: string): string | undefined {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n } catch {\n return undefined\n }\n if (parsed === null || typeof parsed !== 'object') {\n return undefined\n }\n const redactedStr = JSON.stringify(redactor.redact(parsed))\n // Preserve the original string (and its formatting) when nothing was redacted.\n return redactedStr === JSON.stringify(parsed) ? value : redactedStr\n}\n","import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nconst AI_SPAN_PREFIXES = ['gen_ai.', 'llm.', 'ai.', 'traceloop.'] as const\n\n/**\n * Returns `true` when the span is AI-related — its name or any attribute\n * key starts with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`.\n */\nexport function isAISpan(span: ReadableSpan): boolean {\n if (AI_SPAN_PREFIXES.some((prefix) => span.name.startsWith(prefix))) {\n return true\n }\n const attributes = span.attributes\n if (attributes) {\n return Object.keys(attributes).some((key) => AI_SPAN_PREFIXES.some((prefix) => key.startsWith(prefix)))\n }\n return false\n}\n","// Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway\n// emits its own $ai_generation, so each call would be captured (and, for billable\n// products, billed) twice. We only warn — the wrapper's event carries data the\n// gateway never sees (groups, custom properties, trace hierarchy).\n\n// Keep in sync with the gateway's deployed hosts (see services/llm-gateway in the\n// main repo). gateway.us.posthog.com is live today; the rest are listed ahead of\n// any traffic moving to them.\nexport const POSTHOG_AI_GATEWAY_HOSTS: readonly string[] = [\n 'gateway.posthog.com',\n 'gateway.us.posthog.com',\n 'gateway.eu.posthog.com',\n 'ai-gateway.us.posthog.com',\n 'ai-gateway.eu.posthog.com',\n]\n\n// Swap for the dedicated AI Gateway page once it ships.\nconst GATEWAY_DOCS_URL = 'https://posthog.com/docs/ai-observability'\n\nconst extractHost = (baseURL: string): string | undefined => {\n try {\n // Tolerate bare hosts that omit a scheme, e.g. \"gateway.us.posthog.com/v1\".\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(baseURL)\n return new URL(hasScheme ? baseURL : `https://${baseURL}`).hostname.toLowerCase()\n } catch {\n return undefined\n }\n}\n\nexport const isPostHogAiGatewayUrl = (baseURL: string | undefined | null): boolean => {\n if (!baseURL) {\n return false\n }\n const host = extractHost(baseURL)\n return host !== undefined && POSTHOG_AI_GATEWAY_HOSTS.includes(host)\n}\n\n// Warns on every gateway call by design: the misconfiguration is impossible to\n// miss that way, and a doubled bill is worse than noisy logs.\nexport const warnIfPostHogAiGateway = (baseURL: string | undefined | null): void => {\n if (!isPostHogAiGatewayUrl(baseURL)) {\n return\n }\n console.warn(\n '[PostHog] The PostHog AI wrapper is pointed at the PostHog AI Gateway. ' +\n 'Both capture $ai_generation, so every call is double-counted and double-billed. ' +\n `Use one or the other — see ${GATEWAY_DOCS_URL}.`\n )\n}\n\n// OTel spans don't pass through captureAiGeneration, so detect the gateway from\n// the span's host/URL attributes instead. These follow the GenAI / HTTP semantic\n// conventions: `server.address` is a bare host, `url.full` a full URL, both of\n// which isPostHogAiGatewayUrl accepts.\nconst OTEL_GATEWAY_URL_ATTRIBUTES = ['server.address', 'url.full'] as const\n\nexport const warnIfPostHogAiGatewayOtelAttributes = (attributes: Record<string, unknown> | undefined): void => {\n if (!attributes) {\n return\n }\n for (const key of OTEL_GATEWAY_URL_ATTRIBUTES) {\n const value = attributes[key]\n if (typeof value === 'string' && isPostHogAiGatewayUrl(value)) {\n warnIfPostHogAiGateway(value)\n return\n }\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n// OpenTelemetry's ExportResultCode.SUCCESS is 0. Keep this local so loading the\n// published subpath does not require the exporter package's transitive dependencies.\nconst EXPORT_SUCCESS = 0\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\n/**\n * Options for the PostHogTraceExporter. `projectToken` is required; a blank token disables the\n * exporter as a defensive no-op. You can also optionally override the `host` URL. `host` defaults to `https://us.i.posthog.com`.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...' })\n * ```\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...', host: 'https://eu.i.posthog.com' })\n * ```\n */\nexport type PostHogTraceExporterOptions = { projectToken: string; host?: string }\n\n/**\n * An OpenTelemetry `TraceExporter` that sends AI traces to PostHog's OTLP\n * ingestion endpoint. PostHog converts `gen_ai.*` spans into\n * `$ai_generation` events server-side.\n *\n * Only AI-related spans (those whose name or attribute keys start with\n * `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported; all other\n * spans are silently dropped.\n *\n * Use this when the API you're integrating with only accepts a\n * `TraceExporter` (e.g. Vercel's `registerOTel`) or when you need to\n * plug PostHog into an existing processor chain. Otherwise prefer\n * {@link PostHogSpanProcessor}, which is self-contained.\n *\n * `projectToken` is required; a blank token disables the exporter as a defensive no-op.\n * You can also optionally override the `host` URL.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n * import { registerOTel } from '@vercel/otel'\n *\n * registerOTel({\n * serviceName: 'my-app',\n * traceExporter: new PostHogTraceExporter({ projectToken: 'phc_...' }),\n * })\n * ```\n */\nexport class PostHogTraceExporter extends OTLPTraceExporter {\n private readonly disabled: boolean\n\n constructor(options: PostHogTraceExporterOptions) {\n const token = normalizeToken(options.projectToken)\n const disabled = !token\n const host = token ? new URL(normalizeHost(options.host)).origin : DEFAULT_OTEL_HOST\n super({\n url: `${host}/i/v0/ai/otel`,\n headers: token\n ? {\n Authorization: `Bearer ${token}`,\n }\n : {},\n })\n\n this.disabled = disabled\n if (this.disabled) {\n console.warn('[PostHogTraceExporter] projectToken is missing or blank; the exporter will be disabled.')\n }\n }\n\n override export(spans: ReadableSpan[], resultCallback: (result: { code: number; error?: Error }) => void): void {\n if (this.disabled) {\n // Intentionally report success: missing or blank tokens disable exporting as a compatibility no-op.\n // Reporting failure would make OpenTelemetry treat every span as an export error.\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n\n const aiSpans = spans.filter(isAISpan)\n if (aiSpans.length === 0) {\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n for (const span of aiSpans) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n }\n super.export(aiSpans.map(redactSpan), resultCallback)\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Context } from '@opentelemetry/api'\nimport { BatchSpanProcessor, type SpanProcessor, type ReadableSpan, type Span } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\nexport interface PostHogSpanProcessorOptions {\n /**\n * Your PostHog project token (the `phc_...` key). Required; a blank token disables the\n * processor as a defensive no-op.\n */\n projectToken: string\n\n /**\n * PostHog host URL. Defaults to `https://us.i.posthog.com`.\n */\n host?: string\n\n /**\n * @internal Injected processor for testing — bypasses exporter creation.\n */\n _spanProcessor?: SpanProcessor\n}\n\nclass NoopSpanProcessor implements SpanProcessor {\n onStart(_span: Span, _parentContext: Context): void {\n return\n }\n onEnd(_span: ReadableSpan): void {\n return\n }\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * An OpenTelemetry `SpanProcessor` that sends AI traces to PostHog.\n *\n * `projectToken` is required; a blank token disables the processor as a defensive no-op.\n *\n * Internally batches spans and exports them to PostHog's OTLP ingestion\n * endpoint. Only AI-related spans (those whose name or attribute keys\n * start with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported;\n * all other spans are silently dropped.\n *\n * This is the recommended integration point when your setup accepts a\n * `SpanProcessor`. If you need a `TraceExporter` instead (e.g. for\n * Vercel's `registerOTel`), use {@link PostHogTraceExporter}.\n *\n * @example\n * ```ts\n * import { PostHogSpanProcessor } from '@posthog/ai/otel'\n * import { NodeSDK } from '@opentelemetry/sdk-node'\n *\n * const sdk = new NodeSDK({\n * spanProcessors: [new PostHogSpanProcessor({ projectToken: 'phc_...' })],\n * })\n * sdk.start()\n * ```\n */\nexport class PostHogSpanProcessor implements SpanProcessor {\n private readonly inner: SpanProcessor\n\n constructor(options: PostHogSpanProcessorOptions) {\n const token = normalizeToken(options.projectToken)\n if (!token) {\n console.warn('[PostHogSpanProcessor] projectToken is missing or blank; the processor will be disabled.')\n this.inner = new NoopSpanProcessor()\n return\n }\n\n if (options._spanProcessor) {\n this.inner = options._spanProcessor\n } else {\n const host = new URL(normalizeHost(options.host)).origin\n const exporter = new OTLPTraceExporter({\n url: `${host}/i/v0/ai/otel`,\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n this.inner = new BatchSpanProcessor(exporter)\n }\n }\n\n onStart(span: Span, parentContext: Context): void {\n // Forwarded unconditionally — filtering happens in onEnd. We can't filter\n // here because the span hasn't finished yet and may not have AI attributes\n // set. BatchSpanProcessor.onStart is a no-op so this is safe.\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isAISpan(span)) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n this.inner.onEnd(redactSpan(span))\n }\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n}\n"],"names":["DATA_URL_PREFIX_RE","BASE64_ALPHABET_RE","Base64Recognizer","recognize","value","minLength","dataUrl","exec","kind","mediaType","length","confidencePrefix","slice","test","MIME_HINT_KEYS","STRONG_CONTEXT_KEYS","Set","STRONG_CONTEXT_TYPES","FILE_FAMILY_TYPES","KNOWN_AUDIO_FORMATS","MediaTypeContext","EMPTY","undefined","constructor","parent","key","explicitMediaType","inferMediaType","inferFromSiblingMime","inferFromSiblingFormat","inferFromParentType","inferFromKey","hint","v","fmt","format","has","toLowerCase","t","type","includes","hasExplicitBinaryMediaType","startsWith","signalsBinary","STRONG_CONTEXT_MIN_LENGTH","WEAK_CONTEXT_MIN_LENGTH","BinaryContentRedactor","visited","WeakSet","recognizer","redact","isMultimodalEnabled","walk","ctx","redactString","Uint8Array","placeholderFor","add","Array","isArray","map","item","obj","out","k","Object","keys","recognitionValue","replace","Math","min","recognition","val","process","env","_INTERNAL_LLMA_MULTIMODAL","redactor","redactSpan","span","attributes","redactAttributes","events","redactEvents","create","enumerable","configurable","changed","redacted","redactAttributeValue","event","isStringArray","every","trimmed","trimStart","redactJson","parsed","JSON","parse","redactedStr","stringify","AI_SPAN_PREFIXES","isAISpan","some","prefix","name","POSTHOG_AI_GATEWAY_HOSTS","GATEWAY_DOCS_URL","extractHost","baseURL","hasScheme","URL","hostname","isPostHogAiGatewayUrl","host","warnIfPostHogAiGateway","console","warn","OTEL_GATEWAY_URL_ATTRIBUTES","warnIfPostHogAiGatewayOtelAttributes","DEFAULT_OTEL_HOST","EXPORT_SUCCESS","normalizeToken","trim","normalizeHost","normalizedValue","PostHogTraceExporter","OTLPTraceExporter","options","token","projectToken","disabled","origin","url","headers","Authorization","export","spans","resultCallback","code","aiSpans","filter","NoopSpanProcessor","onStart","_span","_parentContext","onEnd","shutdown","Promise","resolve","forceFlush","PostHogSpanProcessor","inner","_spanProcessor","exporter","BatchSpanProcessor","parentContext"],"mappings":"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"}
@@ -33,14 +33,16 @@ const FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'f
33
33
  const KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm']);
34
34
  class MediaTypeContext {
35
35
  static EMPTY = new MediaTypeContext(undefined, undefined);
36
- constructor(parent, key) {
36
+ constructor(parent, key, explicitMediaType) {
37
37
  this.parent = parent;
38
38
  this.key = key;
39
+ this.explicitMediaType = explicitMediaType;
39
40
  }
40
41
  inferMediaType() {
41
42
  return this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey();
42
43
  }
43
44
  inferFromSiblingMime() {
45
+ if (this.explicitMediaType) return this.explicitMediaType;
44
46
  if (!this.parent) return undefined;
45
47
  for (const hint of MIME_HINT_KEYS) {
46
48
  const v = this.parent[hint];
@@ -75,7 +77,13 @@ class MediaTypeContext {
75
77
  if (key.includes('file') || key.includes('document')) return 'application/octet-stream';
76
78
  return undefined;
77
79
  }
80
+ hasExplicitBinaryMediaType() {
81
+ if (!this.explicitMediaType && (!this.parent || !this.key || !STRONG_CONTEXT_KEYS.has(this.key))) return false;
82
+ const mediaType = this.inferFromSiblingMime();
83
+ return mediaType !== undefined && !mediaType.toLowerCase().startsWith('text/');
84
+ }
78
85
  signalsBinary() {
86
+ if (this.explicitMediaType) return true;
79
87
  if (this.parent) {
80
88
  for (const hint of MIME_HINT_KEYS) {
81
89
  if (typeof this.parent[hint] === 'string') return true;
@@ -97,10 +105,10 @@ class BinaryContentRedactor {
97
105
  constructor(recognizer = new Base64Recognizer()) {
98
106
  this.recognizer = recognizer;
99
107
  }
100
- redact(value) {
108
+ redact(value, mediaType) {
101
109
  if (this.isMultimodalEnabled()) return value;
102
110
  this.visited = new WeakSet();
103
- return this.walk(value, MediaTypeContext.EMPTY);
111
+ return this.walk(value, mediaType ? new MediaTypeContext(undefined, undefined, mediaType) : MediaTypeContext.EMPTY);
104
112
  }
105
113
  walk(value, ctx) {
106
114
  if (value === null || value === undefined) return value;
@@ -124,8 +132,10 @@ class BinaryContentRedactor {
124
132
  return out;
125
133
  }
126
134
  redactString(value, ctx) {
127
- const minLength = ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH;
128
- const recognition = this.recognizer.recognize(value, minLength);
135
+ const hasExplicitBinaryMediaType = ctx.hasExplicitBinaryMediaType();
136
+ const recognitionValue = hasExplicitBinaryMediaType ? value.replace(/[\r\n]/g, '') : value;
137
+ const minLength = hasExplicitBinaryMediaType ? Math.min(recognitionValue.length, STRONG_CONTEXT_MIN_LENGTH) : ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH;
138
+ const recognition = this.recognizer.recognize(recognitionValue, minLength);
129
139
  switch (recognition.kind) {
130
140
  case 'data-url':
131
141
  return this.placeholderFor(recognition.mediaType);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/sanitization/base64_recognizer.ts","../../src/sanitization/media_type_context.ts","../../src/sanitization/binary_content_redactor.ts","../../src/otel/redact.ts","../../src/otel/spans.ts","../../src/gatewayWarning.ts","../../src/otel/exporter.ts","../../src/otel/processor.ts"],"sourcesContent":["const DATA_URL_PREFIX_RE = /^data:([^;,\\s]+)(?:;[^;,\\s]+)*;base64,/i\nconst BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/\n\nexport type Base64Recognition = { kind: 'data-url'; mediaType: string } | { kind: 'raw' } | { kind: 'none' }\n\nexport class Base64Recognizer {\n recognize(value: string, minLength: number): Base64Recognition {\n const dataUrl = DATA_URL_PREFIX_RE.exec(value)\n if (dataUrl) return { kind: 'data-url', mediaType: dataUrl[1] }\n\n if (value.length < minLength) return { kind: 'none' }\n\n const confidencePrefix = value.slice(0, minLength)\n if (BASE64_ALPHABET_RE.test(confidencePrefix)) {\n return { kind: 'raw' }\n } else {\n return { kind: 'none' }\n }\n }\n}\n","const MIME_HINT_KEYS = ['mediaType', 'media_type', 'mimeType', 'mime_type'] as const\n\nconst STRONG_CONTEXT_KEYS = new Set([\n 'data',\n 'file_data',\n 'fileData',\n 'image_url',\n 'imageUrl',\n 'video_url',\n 'videoUrl',\n 'audio',\n 'audio_data',\n 'audioData',\n 'inline_data',\n 'inlineData',\n 'source',\n 'result',\n])\n\nconst STRONG_CONTEXT_TYPES = new Set([\n 'image',\n 'image_url',\n 'input_image',\n 'audio',\n 'input_audio',\n 'video',\n 'video_url',\n 'file',\n 'input_file',\n 'document',\n 'media',\n 'file-data',\n])\n\nconst FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'file-data'])\n\nconst KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm'])\n\nexport class MediaTypeContext {\n static readonly EMPTY = new MediaTypeContext(undefined, undefined)\n\n constructor(\n private readonly parent: Record<string, unknown> | undefined,\n private readonly key: string | undefined\n ) {}\n\n inferMediaType(): string | undefined {\n return (\n this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey()\n )\n }\n\n inferFromSiblingMime(): string | undefined {\n if (!this.parent) return undefined\n for (const hint of MIME_HINT_KEYS) {\n const v = this.parent[hint]\n if (typeof v === 'string') return v\n }\n return undefined\n }\n\n inferFromSiblingFormat(): string | undefined {\n if (!this.parent) return undefined\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) {\n return `audio/${fmt.toLowerCase()}`\n }\n return undefined\n }\n\n inferFromParentType(): string | undefined {\n if (!this.parent) return undefined\n const t = this.parent.type\n if (typeof t !== 'string') return undefined\n if (t === 'image' || t === 'image_url' || t === 'input_image') return 'image'\n if (t === 'audio' || t === 'input_audio') return 'audio'\n if (t === 'video' || t === 'video_url') return 'video'\n if (FILE_FAMILY_TYPES.has(t)) return 'application/octet-stream'\n return undefined\n }\n\n inferFromKey(): string | undefined {\n if (!this.key) return undefined\n const key = this.key.toLowerCase()\n if (key.includes('audio')) return 'audio'\n if (key.includes('video')) return 'video'\n if (key.includes('image')) return 'image'\n if (key.includes('file') || key.includes('document')) return 'application/octet-stream'\n return undefined\n }\n\n signalsBinary(): boolean {\n if (this.parent) {\n for (const hint of MIME_HINT_KEYS) {\n if (typeof this.parent[hint] === 'string') return true\n }\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) return true\n const t = this.parent.type\n if (typeof t === 'string' && STRONG_CONTEXT_TYPES.has(t)) return true\n }\n if (this.key && STRONG_CONTEXT_KEYS.has(this.key)) return true\n return false\n }\n}\n","import { Base64Recognizer } from './base64_recognizer'\nimport { MediaTypeContext } from './media_type_context'\n\nconst STRONG_CONTEXT_MIN_LENGTH = 64\nconst WEAK_CONTEXT_MIN_LENGTH = 1024\n\nexport class BinaryContentRedactor {\n private visited: WeakSet<object> = new WeakSet()\n\n constructor(private readonly recognizer: Base64Recognizer = new Base64Recognizer()) {}\n\n redact<T>(value: T): T\n redact(value: unknown): unknown {\n if (this.isMultimodalEnabled()) return value\n this.visited = new WeakSet()\n return this.walk(value, MediaTypeContext.EMPTY)\n }\n\n private walk(value: unknown, ctx: MediaTypeContext): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return this.redactString(value, ctx)\n if (typeof value !== 'object') return value\n\n // Buffer extends Uint8Array, so this branch catches both.\n if (typeof Uint8Array !== 'undefined' && value instanceof Uint8Array) {\n return this.placeholderFor(ctx.inferMediaType())\n }\n\n if (this.visited.has(value)) return null\n this.visited.add(value)\n\n if (Array.isArray(value)) {\n return value.map((item) => this.walk(item, ctx))\n }\n\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const k of Object.keys(obj)) {\n out[k] = this.walk(obj[k], new MediaTypeContext(obj, k))\n }\n return out\n }\n\n private redactString(value: string, ctx: MediaTypeContext): string {\n const minLength = ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH\n const recognition = this.recognizer.recognize(value, minLength)\n switch (recognition.kind) {\n case 'data-url':\n return this.placeholderFor(recognition.mediaType)\n case 'raw':\n return this.placeholderFor(ctx.inferMediaType())\n case 'none':\n return value\n }\n }\n\n private placeholderFor(mediaType?: string): string {\n if (!mediaType) return '[base64 redacted]'\n if (mediaType === 'application/octet-stream') return '[base64 file redacted]'\n return `[base64 ${mediaType} redacted]`\n }\n\n private isMultimodalEnabled(): boolean {\n const val = process.env._INTERNAL_LLMA_MULTIMODAL || ''\n return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes'\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api'\nimport type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'\n\nimport { BinaryContentRedactor } from '../sanitization/binary_content_redactor'\n\nconst redactor = new BinaryContentRedactor()\n\nexport function redactSpan(span: ReadableSpan): ReadableSpan {\n const attributes = span.attributes ? redactAttributes(span.attributes) : span.attributes\n const events = span.events ? redactEvents(span.events) : span.events\n if (attributes === span.attributes && events === span.events) {\n return span\n }\n // Copy rather than mutate: the span is shared across every registered processor/exporter.\n return Object.create(span, {\n attributes: { value: attributes, enumerable: true, configurable: true },\n events: { value: events, enumerable: true, configurable: true },\n })\n}\n\nfunction redactAttributes(attributes: Attributes): Attributes {\n let changed = false\n const out: Attributes = {}\n for (const key of Object.keys(attributes)) {\n const value = attributes[key]\n const redacted = value === undefined ? value : redactAttributeValue(value)\n if (redacted !== value) {\n changed = true\n }\n out[key] = redacted\n }\n return changed ? out : attributes\n}\n\nfunction redactEvents(events: TimedEvent[]): TimedEvent[] {\n let changed = false\n const out = events.map((event) => {\n if (!event.attributes) {\n return event\n }\n const attributes = redactAttributes(event.attributes)\n if (attributes === event.attributes) {\n return event\n }\n changed = true\n return { ...event, attributes }\n })\n return changed ? out : events\n}\n\nfunction redactAttributeValue(value: AttributeValue): AttributeValue {\n if (typeof value === 'string') {\n return redactString(value)\n }\n if (isStringArray(value)) {\n let changed = false\n const out = value.map((item) => {\n if (typeof item !== 'string') {\n return item\n }\n const redacted = redactString(item)\n if (redacted !== item) {\n changed = true\n }\n return redacted\n })\n return changed ? out : value\n }\n return value\n}\n\nfunction isStringArray(value: AttributeValue): value is Array<string | null | undefined> {\n return Array.isArray(value) && value.every((item) => typeof item !== 'number' && typeof item !== 'boolean')\n}\n\nfunction redactString(value: string): string {\n const trimmed = value.trimStart()\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n const redacted = redactJson(value)\n if (redacted !== undefined) {\n return redacted\n }\n }\n return redactor.redact(value)\n}\n\nfunction redactJson(value: string): string | undefined {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n } catch {\n return undefined\n }\n if (parsed === null || typeof parsed !== 'object') {\n return undefined\n }\n const redactedStr = JSON.stringify(redactor.redact(parsed))\n // Preserve the original string (and its formatting) when nothing was redacted.\n return redactedStr === JSON.stringify(parsed) ? value : redactedStr\n}\n","import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nconst AI_SPAN_PREFIXES = ['gen_ai.', 'llm.', 'ai.', 'traceloop.'] as const\n\n/**\n * Returns `true` when the span is AI-related — its name or any attribute\n * key starts with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`.\n */\nexport function isAISpan(span: ReadableSpan): boolean {\n if (AI_SPAN_PREFIXES.some((prefix) => span.name.startsWith(prefix))) {\n return true\n }\n const attributes = span.attributes\n if (attributes) {\n return Object.keys(attributes).some((key) => AI_SPAN_PREFIXES.some((prefix) => key.startsWith(prefix)))\n }\n return false\n}\n","// Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway\n// emits its own $ai_generation, so each call would be captured (and, for billable\n// products, billed) twice. We only warn — the wrapper's event carries data the\n// gateway never sees (groups, custom properties, trace hierarchy).\n\n// Keep in sync with the gateway's deployed hosts (see services/llm-gateway in the\n// main repo). gateway.us.posthog.com is live today; the rest are listed ahead of\n// any traffic moving to them.\nexport const POSTHOG_AI_GATEWAY_HOSTS: readonly string[] = [\n 'gateway.posthog.com',\n 'gateway.us.posthog.com',\n 'gateway.eu.posthog.com',\n 'ai-gateway.us.posthog.com',\n 'ai-gateway.eu.posthog.com',\n]\n\n// Swap for the dedicated AI Gateway page once it ships.\nconst GATEWAY_DOCS_URL = 'https://posthog.com/docs/ai-observability'\n\nconst extractHost = (baseURL: string): string | undefined => {\n try {\n // Tolerate bare hosts that omit a scheme, e.g. \"gateway.us.posthog.com/v1\".\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(baseURL)\n return new URL(hasScheme ? baseURL : `https://${baseURL}`).hostname.toLowerCase()\n } catch {\n return undefined\n }\n}\n\nexport const isPostHogAiGatewayUrl = (baseURL: string | undefined | null): boolean => {\n if (!baseURL) {\n return false\n }\n const host = extractHost(baseURL)\n return host !== undefined && POSTHOG_AI_GATEWAY_HOSTS.includes(host)\n}\n\n// Warns on every gateway call by design: the misconfiguration is impossible to\n// miss that way, and a doubled bill is worse than noisy logs.\nexport const warnIfPostHogAiGateway = (baseURL: string | undefined | null): void => {\n if (!isPostHogAiGatewayUrl(baseURL)) {\n return\n }\n console.warn(\n '[PostHog] The PostHog AI wrapper is pointed at the PostHog AI Gateway. ' +\n 'Both capture $ai_generation, so every call is double-counted and double-billed. ' +\n `Use one or the other — see ${GATEWAY_DOCS_URL}.`\n )\n}\n\n// OTel spans don't pass through captureAiGeneration, so detect the gateway from\n// the span's host/URL attributes instead. These follow the GenAI / HTTP semantic\n// conventions: `server.address` is a bare host, `url.full` a full URL, both of\n// which isPostHogAiGatewayUrl accepts.\nconst OTEL_GATEWAY_URL_ATTRIBUTES = ['server.address', 'url.full'] as const\n\nexport const warnIfPostHogAiGatewayOtelAttributes = (attributes: Record<string, unknown> | undefined): void => {\n if (!attributes) {\n return\n }\n for (const key of OTEL_GATEWAY_URL_ATTRIBUTES) {\n const value = attributes[key]\n if (typeof value === 'string' && isPostHogAiGatewayUrl(value)) {\n warnIfPostHogAiGateway(value)\n return\n }\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n// OpenTelemetry's ExportResultCode.SUCCESS is 0. Keep this local so loading the\n// published subpath does not require the exporter package's transitive dependencies.\nconst EXPORT_SUCCESS = 0\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\n/**\n * Options for the PostHogTraceExporter. `projectToken` is required; a blank token disables the\n * exporter as a defensive no-op. You can also optionally override the `host` URL. `host` defaults to `https://us.i.posthog.com`.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...' })\n * ```\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...', host: 'https://eu.i.posthog.com' })\n * ```\n */\nexport type PostHogTraceExporterOptions = { projectToken: string; host?: string }\n\n/**\n * An OpenTelemetry `TraceExporter` that sends AI traces to PostHog's OTLP\n * ingestion endpoint. PostHog converts `gen_ai.*` spans into\n * `$ai_generation` events server-side.\n *\n * Only AI-related spans (those whose name or attribute keys start with\n * `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported; all other\n * spans are silently dropped.\n *\n * Use this when the API you're integrating with only accepts a\n * `TraceExporter` (e.g. Vercel's `registerOTel`) or when you need to\n * plug PostHog into an existing processor chain. Otherwise prefer\n * {@link PostHogSpanProcessor}, which is self-contained.\n *\n * `projectToken` is required; a blank token disables the exporter as a defensive no-op.\n * You can also optionally override the `host` URL.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n * import { registerOTel } from '@vercel/otel'\n *\n * registerOTel({\n * serviceName: 'my-app',\n * traceExporter: new PostHogTraceExporter({ projectToken: 'phc_...' }),\n * })\n * ```\n */\nexport class PostHogTraceExporter extends OTLPTraceExporter {\n private readonly disabled: boolean\n\n constructor(options: PostHogTraceExporterOptions) {\n const token = normalizeToken(options.projectToken)\n const disabled = !token\n const host = token ? new URL(normalizeHost(options.host)).origin : DEFAULT_OTEL_HOST\n super({\n url: `${host}/i/v0/ai/otel`,\n headers: token\n ? {\n Authorization: `Bearer ${token}`,\n }\n : {},\n })\n\n this.disabled = disabled\n if (this.disabled) {\n console.warn('[PostHogTraceExporter] projectToken is missing or blank; the exporter will be disabled.')\n }\n }\n\n override export(spans: ReadableSpan[], resultCallback: (result: { code: number; error?: Error }) => void): void {\n if (this.disabled) {\n // Intentionally report success: missing or blank tokens disable exporting as a compatibility no-op.\n // Reporting failure would make OpenTelemetry treat every span as an export error.\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n\n const aiSpans = spans.filter(isAISpan)\n if (aiSpans.length === 0) {\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n for (const span of aiSpans) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n }\n super.export(aiSpans.map(redactSpan), resultCallback)\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Context } from '@opentelemetry/api'\nimport { BatchSpanProcessor, type SpanProcessor, type ReadableSpan, type Span } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\nexport interface PostHogSpanProcessorOptions {\n /**\n * Your PostHog project token (the `phc_...` key). Required; a blank token disables the\n * processor as a defensive no-op.\n */\n projectToken: string\n\n /**\n * PostHog host URL. Defaults to `https://us.i.posthog.com`.\n */\n host?: string\n\n /**\n * @internal Injected processor for testing — bypasses exporter creation.\n */\n _spanProcessor?: SpanProcessor\n}\n\nclass NoopSpanProcessor implements SpanProcessor {\n onStart(_span: Span, _parentContext: Context): void {\n return\n }\n onEnd(_span: ReadableSpan): void {\n return\n }\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * An OpenTelemetry `SpanProcessor` that sends AI traces to PostHog.\n *\n * `projectToken` is required; a blank token disables the processor as a defensive no-op.\n *\n * Internally batches spans and exports them to PostHog's OTLP ingestion\n * endpoint. Only AI-related spans (those whose name or attribute keys\n * start with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported;\n * all other spans are silently dropped.\n *\n * This is the recommended integration point when your setup accepts a\n * `SpanProcessor`. If you need a `TraceExporter` instead (e.g. for\n * Vercel's `registerOTel`), use {@link PostHogTraceExporter}.\n *\n * @example\n * ```ts\n * import { PostHogSpanProcessor } from '@posthog/ai/otel'\n * import { NodeSDK } from '@opentelemetry/sdk-node'\n *\n * const sdk = new NodeSDK({\n * spanProcessors: [new PostHogSpanProcessor({ projectToken: 'phc_...' })],\n * })\n * sdk.start()\n * ```\n */\nexport class PostHogSpanProcessor implements SpanProcessor {\n private readonly inner: SpanProcessor\n\n constructor(options: PostHogSpanProcessorOptions) {\n const token = normalizeToken(options.projectToken)\n if (!token) {\n console.warn('[PostHogSpanProcessor] projectToken is missing or blank; the processor will be disabled.')\n this.inner = new NoopSpanProcessor()\n return\n }\n\n if (options._spanProcessor) {\n this.inner = options._spanProcessor\n } else {\n const host = new URL(normalizeHost(options.host)).origin\n const exporter = new OTLPTraceExporter({\n url: `${host}/i/v0/ai/otel`,\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n this.inner = new BatchSpanProcessor(exporter)\n }\n }\n\n onStart(span: Span, parentContext: Context): void {\n // Forwarded unconditionally — filtering happens in onEnd. We can't filter\n // here because the span hasn't finished yet and may not have AI attributes\n // set. BatchSpanProcessor.onStart is a no-op so this is safe.\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isAISpan(span)) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n this.inner.onEnd(redactSpan(span))\n }\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n}\n"],"names":["DATA_URL_PREFIX_RE","BASE64_ALPHABET_RE","Base64Recognizer","recognize","value","minLength","dataUrl","exec","kind","mediaType","length","confidencePrefix","slice","test","MIME_HINT_KEYS","STRONG_CONTEXT_KEYS","Set","STRONG_CONTEXT_TYPES","FILE_FAMILY_TYPES","KNOWN_AUDIO_FORMATS","MediaTypeContext","EMPTY","undefined","constructor","parent","key","inferMediaType","inferFromSiblingMime","inferFromSiblingFormat","inferFromParentType","inferFromKey","hint","v","fmt","format","has","toLowerCase","t","type","includes","signalsBinary","STRONG_CONTEXT_MIN_LENGTH","WEAK_CONTEXT_MIN_LENGTH","BinaryContentRedactor","visited","WeakSet","recognizer","redact","isMultimodalEnabled","walk","ctx","redactString","Uint8Array","placeholderFor","add","Array","isArray","map","item","obj","out","k","Object","keys","recognition","val","process","env","_INTERNAL_LLMA_MULTIMODAL","redactor","redactSpan","span","attributes","redactAttributes","events","redactEvents","create","enumerable","configurable","changed","redacted","redactAttributeValue","event","isStringArray","every","trimmed","trimStart","startsWith","redactJson","parsed","JSON","parse","redactedStr","stringify","AI_SPAN_PREFIXES","isAISpan","some","prefix","name","POSTHOG_AI_GATEWAY_HOSTS","GATEWAY_DOCS_URL","extractHost","baseURL","hasScheme","URL","hostname","isPostHogAiGatewayUrl","host","warnIfPostHogAiGateway","console","warn","OTEL_GATEWAY_URL_ATTRIBUTES","warnIfPostHogAiGatewayOtelAttributes","DEFAULT_OTEL_HOST","EXPORT_SUCCESS","normalizeToken","trim","normalizeHost","normalizedValue","PostHogTraceExporter","OTLPTraceExporter","options","token","projectToken","disabled","origin","url","headers","Authorization","export","spans","resultCallback","code","aiSpans","filter","NoopSpanProcessor","onStart","_span","_parentContext","onEnd","shutdown","Promise","resolve","forceFlush","PostHogSpanProcessor","inner","_spanProcessor","exporter","BatchSpanProcessor","parentContext"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/sanitization/base64_recognizer.ts","../../src/sanitization/media_type_context.ts","../../src/sanitization/binary_content_redactor.ts","../../src/otel/redact.ts","../../src/otel/spans.ts","../../src/gatewayWarning.ts","../../src/otel/exporter.ts","../../src/otel/processor.ts"],"sourcesContent":["const DATA_URL_PREFIX_RE = /^data:([^;,\\s]+)(?:;[^;,\\s]+)*;base64,/i\nconst BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/\n\nexport type Base64Recognition = { kind: 'data-url'; mediaType: string } | { kind: 'raw' } | { kind: 'none' }\n\nexport class Base64Recognizer {\n recognize(value: string, minLength: number): Base64Recognition {\n const dataUrl = DATA_URL_PREFIX_RE.exec(value)\n if (dataUrl) return { kind: 'data-url', mediaType: dataUrl[1] }\n\n if (value.length < minLength) return { kind: 'none' }\n\n const confidencePrefix = value.slice(0, minLength)\n if (BASE64_ALPHABET_RE.test(confidencePrefix)) {\n return { kind: 'raw' }\n } else {\n return { kind: 'none' }\n }\n }\n}\n","const MIME_HINT_KEYS = ['mediaType', 'media_type', 'mimeType', 'mime_type'] as const\n\nconst STRONG_CONTEXT_KEYS = new Set([\n 'data',\n 'file_data',\n 'fileData',\n 'image_url',\n 'imageUrl',\n 'video_url',\n 'videoUrl',\n 'audio',\n 'audio_data',\n 'audioData',\n 'inline_data',\n 'inlineData',\n 'source',\n 'result',\n])\n\nconst STRONG_CONTEXT_TYPES = new Set([\n 'image',\n 'image_url',\n 'input_image',\n 'audio',\n 'input_audio',\n 'video',\n 'video_url',\n 'file',\n 'input_file',\n 'document',\n 'media',\n 'file-data',\n])\n\nconst FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'file-data'])\n\nconst KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm'])\n\nexport class MediaTypeContext {\n static readonly EMPTY = new MediaTypeContext(undefined, undefined)\n\n constructor(\n private readonly parent: Record<string, unknown> | undefined,\n private readonly key: string | undefined,\n private readonly explicitMediaType?: string\n ) {}\n\n inferMediaType(): string | undefined {\n return (\n this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey()\n )\n }\n\n inferFromSiblingMime(): string | undefined {\n if (this.explicitMediaType) return this.explicitMediaType\n if (!this.parent) return undefined\n for (const hint of MIME_HINT_KEYS) {\n const v = this.parent[hint]\n if (typeof v === 'string') return v\n }\n return undefined\n }\n\n inferFromSiblingFormat(): string | undefined {\n if (!this.parent) return undefined\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) {\n return `audio/${fmt.toLowerCase()}`\n }\n return undefined\n }\n\n inferFromParentType(): string | undefined {\n if (!this.parent) return undefined\n const t = this.parent.type\n if (typeof t !== 'string') return undefined\n if (t === 'image' || t === 'image_url' || t === 'input_image') return 'image'\n if (t === 'audio' || t === 'input_audio') return 'audio'\n if (t === 'video' || t === 'video_url') return 'video'\n if (FILE_FAMILY_TYPES.has(t)) return 'application/octet-stream'\n return undefined\n }\n\n inferFromKey(): string | undefined {\n if (!this.key) return undefined\n const key = this.key.toLowerCase()\n if (key.includes('audio')) return 'audio'\n if (key.includes('video')) return 'video'\n if (key.includes('image')) return 'image'\n if (key.includes('file') || key.includes('document')) return 'application/octet-stream'\n return undefined\n }\n\n hasExplicitBinaryMediaType(): boolean {\n if (!this.explicitMediaType && (!this.parent || !this.key || !STRONG_CONTEXT_KEYS.has(this.key))) return false\n const mediaType = this.inferFromSiblingMime()\n return mediaType !== undefined && !mediaType.toLowerCase().startsWith('text/')\n }\n\n signalsBinary(): boolean {\n if (this.explicitMediaType) return true\n if (this.parent) {\n for (const hint of MIME_HINT_KEYS) {\n if (typeof this.parent[hint] === 'string') return true\n }\n const fmt = this.parent.format\n if (typeof fmt === 'string' && KNOWN_AUDIO_FORMATS.has(fmt.toLowerCase())) return true\n const t = this.parent.type\n if (typeof t === 'string' && STRONG_CONTEXT_TYPES.has(t)) return true\n }\n if (this.key && STRONG_CONTEXT_KEYS.has(this.key)) return true\n return false\n }\n}\n","import { Base64Recognizer } from './base64_recognizer'\nimport { MediaTypeContext } from './media_type_context'\n\nconst STRONG_CONTEXT_MIN_LENGTH = 64\nconst WEAK_CONTEXT_MIN_LENGTH = 1024\n\nexport class BinaryContentRedactor {\n private visited: WeakSet<object> = new WeakSet()\n\n constructor(private readonly recognizer: Base64Recognizer = new Base64Recognizer()) {}\n\n redact<T>(value: T, mediaType?: string): T\n redact(value: unknown, mediaType?: string): unknown {\n if (this.isMultimodalEnabled()) return value\n this.visited = new WeakSet()\n return this.walk(value, mediaType ? new MediaTypeContext(undefined, undefined, mediaType) : MediaTypeContext.EMPTY)\n }\n\n private walk(value: unknown, ctx: MediaTypeContext): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return this.redactString(value, ctx)\n if (typeof value !== 'object') return value\n\n // Buffer extends Uint8Array, so this branch catches both.\n if (typeof Uint8Array !== 'undefined' && value instanceof Uint8Array) {\n return this.placeholderFor(ctx.inferMediaType())\n }\n\n if (this.visited.has(value)) return null\n this.visited.add(value)\n\n if (Array.isArray(value)) {\n return value.map((item) => this.walk(item, ctx))\n }\n\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const k of Object.keys(obj)) {\n out[k] = this.walk(obj[k], new MediaTypeContext(obj, k))\n }\n return out\n }\n\n private redactString(value: string, ctx: MediaTypeContext): string {\n const hasExplicitBinaryMediaType = ctx.hasExplicitBinaryMediaType()\n const recognitionValue = hasExplicitBinaryMediaType ? value.replace(/[\\r\\n]/g, '') : value\n const minLength = hasExplicitBinaryMediaType\n ? Math.min(recognitionValue.length, STRONG_CONTEXT_MIN_LENGTH)\n : ctx.signalsBinary()\n ? STRONG_CONTEXT_MIN_LENGTH\n : WEAK_CONTEXT_MIN_LENGTH\n const recognition = this.recognizer.recognize(recognitionValue, minLength)\n switch (recognition.kind) {\n case 'data-url':\n return this.placeholderFor(recognition.mediaType)\n case 'raw':\n return this.placeholderFor(ctx.inferMediaType())\n case 'none':\n return value\n }\n }\n\n private placeholderFor(mediaType?: string): string {\n if (!mediaType) return '[base64 redacted]'\n if (mediaType === 'application/octet-stream') return '[base64 file redacted]'\n return `[base64 ${mediaType} redacted]`\n }\n\n private isMultimodalEnabled(): boolean {\n const val = process.env._INTERNAL_LLMA_MULTIMODAL || ''\n return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes'\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api'\nimport type { ReadableSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'\n\nimport { BinaryContentRedactor } from '../sanitization/binary_content_redactor'\n\nconst redactor = new BinaryContentRedactor()\n\nexport function redactSpan(span: ReadableSpan): ReadableSpan {\n const attributes = span.attributes ? redactAttributes(span.attributes) : span.attributes\n const events = span.events ? redactEvents(span.events) : span.events\n if (attributes === span.attributes && events === span.events) {\n return span\n }\n // Copy rather than mutate: the span is shared across every registered processor/exporter.\n return Object.create(span, {\n attributes: { value: attributes, enumerable: true, configurable: true },\n events: { value: events, enumerable: true, configurable: true },\n })\n}\n\nfunction redactAttributes(attributes: Attributes): Attributes {\n let changed = false\n const out: Attributes = {}\n for (const key of Object.keys(attributes)) {\n const value = attributes[key]\n const redacted = value === undefined ? value : redactAttributeValue(value)\n if (redacted !== value) {\n changed = true\n }\n out[key] = redacted\n }\n return changed ? out : attributes\n}\n\nfunction redactEvents(events: TimedEvent[]): TimedEvent[] {\n let changed = false\n const out = events.map((event) => {\n if (!event.attributes) {\n return event\n }\n const attributes = redactAttributes(event.attributes)\n if (attributes === event.attributes) {\n return event\n }\n changed = true\n return { ...event, attributes }\n })\n return changed ? out : events\n}\n\nfunction redactAttributeValue(value: AttributeValue): AttributeValue {\n if (typeof value === 'string') {\n return redactString(value)\n }\n if (isStringArray(value)) {\n let changed = false\n const out = value.map((item) => {\n if (typeof item !== 'string') {\n return item\n }\n const redacted = redactString(item)\n if (redacted !== item) {\n changed = true\n }\n return redacted\n })\n return changed ? out : value\n }\n return value\n}\n\nfunction isStringArray(value: AttributeValue): value is Array<string | null | undefined> {\n return Array.isArray(value) && value.every((item) => typeof item !== 'number' && typeof item !== 'boolean')\n}\n\nfunction redactString(value: string): string {\n const trimmed = value.trimStart()\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n const redacted = redactJson(value)\n if (redacted !== undefined) {\n return redacted\n }\n }\n return redactor.redact(value)\n}\n\nfunction redactJson(value: string): string | undefined {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n } catch {\n return undefined\n }\n if (parsed === null || typeof parsed !== 'object') {\n return undefined\n }\n const redactedStr = JSON.stringify(redactor.redact(parsed))\n // Preserve the original string (and its formatting) when nothing was redacted.\n return redactedStr === JSON.stringify(parsed) ? value : redactedStr\n}\n","import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nconst AI_SPAN_PREFIXES = ['gen_ai.', 'llm.', 'ai.', 'traceloop.'] as const\n\n/**\n * Returns `true` when the span is AI-related — its name or any attribute\n * key starts with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`.\n */\nexport function isAISpan(span: ReadableSpan): boolean {\n if (AI_SPAN_PREFIXES.some((prefix) => span.name.startsWith(prefix))) {\n return true\n }\n const attributes = span.attributes\n if (attributes) {\n return Object.keys(attributes).some((key) => AI_SPAN_PREFIXES.some((prefix) => key.startsWith(prefix)))\n }\n return false\n}\n","// Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway\n// emits its own $ai_generation, so each call would be captured (and, for billable\n// products, billed) twice. We only warn — the wrapper's event carries data the\n// gateway never sees (groups, custom properties, trace hierarchy).\n\n// Keep in sync with the gateway's deployed hosts (see services/llm-gateway in the\n// main repo). gateway.us.posthog.com is live today; the rest are listed ahead of\n// any traffic moving to them.\nexport const POSTHOG_AI_GATEWAY_HOSTS: readonly string[] = [\n 'gateway.posthog.com',\n 'gateway.us.posthog.com',\n 'gateway.eu.posthog.com',\n 'ai-gateway.us.posthog.com',\n 'ai-gateway.eu.posthog.com',\n]\n\n// Swap for the dedicated AI Gateway page once it ships.\nconst GATEWAY_DOCS_URL = 'https://posthog.com/docs/ai-observability'\n\nconst extractHost = (baseURL: string): string | undefined => {\n try {\n // Tolerate bare hosts that omit a scheme, e.g. \"gateway.us.posthog.com/v1\".\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(baseURL)\n return new URL(hasScheme ? baseURL : `https://${baseURL}`).hostname.toLowerCase()\n } catch {\n return undefined\n }\n}\n\nexport const isPostHogAiGatewayUrl = (baseURL: string | undefined | null): boolean => {\n if (!baseURL) {\n return false\n }\n const host = extractHost(baseURL)\n return host !== undefined && POSTHOG_AI_GATEWAY_HOSTS.includes(host)\n}\n\n// Warns on every gateway call by design: the misconfiguration is impossible to\n// miss that way, and a doubled bill is worse than noisy logs.\nexport const warnIfPostHogAiGateway = (baseURL: string | undefined | null): void => {\n if (!isPostHogAiGatewayUrl(baseURL)) {\n return\n }\n console.warn(\n '[PostHog] The PostHog AI wrapper is pointed at the PostHog AI Gateway. ' +\n 'Both capture $ai_generation, so every call is double-counted and double-billed. ' +\n `Use one or the other — see ${GATEWAY_DOCS_URL}.`\n )\n}\n\n// OTel spans don't pass through captureAiGeneration, so detect the gateway from\n// the span's host/URL attributes instead. These follow the GenAI / HTTP semantic\n// conventions: `server.address` is a bare host, `url.full` a full URL, both of\n// which isPostHogAiGatewayUrl accepts.\nconst OTEL_GATEWAY_URL_ATTRIBUTES = ['server.address', 'url.full'] as const\n\nexport const warnIfPostHogAiGatewayOtelAttributes = (attributes: Record<string, unknown> | undefined): void => {\n if (!attributes) {\n return\n }\n for (const key of OTEL_GATEWAY_URL_ATTRIBUTES) {\n const value = attributes[key]\n if (typeof value === 'string' && isPostHogAiGatewayUrl(value)) {\n warnIfPostHogAiGateway(value)\n return\n }\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n// OpenTelemetry's ExportResultCode.SUCCESS is 0. Keep this local so loading the\n// published subpath does not require the exporter package's transitive dependencies.\nconst EXPORT_SUCCESS = 0\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\n/**\n * Options for the PostHogTraceExporter. `projectToken` is required; a blank token disables the\n * exporter as a defensive no-op. You can also optionally override the `host` URL. `host` defaults to `https://us.i.posthog.com`.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...' })\n * ```\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n *\n * new PostHogTraceExporter({ projectToken: 'phc_...', host: 'https://eu.i.posthog.com' })\n * ```\n */\nexport type PostHogTraceExporterOptions = { projectToken: string; host?: string }\n\n/**\n * An OpenTelemetry `TraceExporter` that sends AI traces to PostHog's OTLP\n * ingestion endpoint. PostHog converts `gen_ai.*` spans into\n * `$ai_generation` events server-side.\n *\n * Only AI-related spans (those whose name or attribute keys start with\n * `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported; all other\n * spans are silently dropped.\n *\n * Use this when the API you're integrating with only accepts a\n * `TraceExporter` (e.g. Vercel's `registerOTel`) or when you need to\n * plug PostHog into an existing processor chain. Otherwise prefer\n * {@link PostHogSpanProcessor}, which is self-contained.\n *\n * `projectToken` is required; a blank token disables the exporter as a defensive no-op.\n * You can also optionally override the `host` URL.\n *\n * @example\n * ```ts\n * import { PostHogTraceExporter } from '@posthog/ai/otel'\n * import { registerOTel } from '@vercel/otel'\n *\n * registerOTel({\n * serviceName: 'my-app',\n * traceExporter: new PostHogTraceExporter({ projectToken: 'phc_...' }),\n * })\n * ```\n */\nexport class PostHogTraceExporter extends OTLPTraceExporter {\n private readonly disabled: boolean\n\n constructor(options: PostHogTraceExporterOptions) {\n const token = normalizeToken(options.projectToken)\n const disabled = !token\n const host = token ? new URL(normalizeHost(options.host)).origin : DEFAULT_OTEL_HOST\n super({\n url: `${host}/i/v0/ai/otel`,\n headers: token\n ? {\n Authorization: `Bearer ${token}`,\n }\n : {},\n })\n\n this.disabled = disabled\n if (this.disabled) {\n console.warn('[PostHogTraceExporter] projectToken is missing or blank; the exporter will be disabled.')\n }\n }\n\n override export(spans: ReadableSpan[], resultCallback: (result: { code: number; error?: Error }) => void): void {\n if (this.disabled) {\n // Intentionally report success: missing or blank tokens disable exporting as a compatibility no-op.\n // Reporting failure would make OpenTelemetry treat every span as an export error.\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n\n const aiSpans = spans.filter(isAISpan)\n if (aiSpans.length === 0) {\n resultCallback({ code: EXPORT_SUCCESS })\n return\n }\n for (const span of aiSpans) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n }\n super.export(aiSpans.map(redactSpan), resultCallback)\n }\n}\n","import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Context } from '@opentelemetry/api'\nimport { BatchSpanProcessor, type SpanProcessor, type ReadableSpan, type Span } from '@opentelemetry/sdk-trace-base'\n\nimport { redactSpan } from './redact'\nimport { isAISpan } from './spans'\nimport { warnIfPostHogAiGatewayOtelAttributes } from '../gatewayWarning'\n\nconst DEFAULT_OTEL_HOST = 'https://us.i.posthog.com'\n\nfunction normalizeToken(value?: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\nfunction normalizeHost(value?: unknown): string {\n const normalizedValue = typeof value === 'string' ? value.trim() : ''\n return normalizedValue || DEFAULT_OTEL_HOST\n}\n\nexport interface PostHogSpanProcessorOptions {\n /**\n * Your PostHog project token (the `phc_...` key). Required; a blank token disables the\n * processor as a defensive no-op.\n */\n projectToken: string\n\n /**\n * PostHog host URL. Defaults to `https://us.i.posthog.com`.\n */\n host?: string\n\n /**\n * @internal Injected processor for testing — bypasses exporter creation.\n */\n _spanProcessor?: SpanProcessor\n}\n\nclass NoopSpanProcessor implements SpanProcessor {\n onStart(_span: Span, _parentContext: Context): void {\n return\n }\n onEnd(_span: ReadableSpan): void {\n return\n }\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * An OpenTelemetry `SpanProcessor` that sends AI traces to PostHog.\n *\n * `projectToken` is required; a blank token disables the processor as a defensive no-op.\n *\n * Internally batches spans and exports them to PostHog's OTLP ingestion\n * endpoint. Only AI-related spans (those whose name or attribute keys\n * start with `gen_ai.`, `llm.`, `ai.`, or `traceloop.`) are exported;\n * all other spans are silently dropped.\n *\n * This is the recommended integration point when your setup accepts a\n * `SpanProcessor`. If you need a `TraceExporter` instead (e.g. for\n * Vercel's `registerOTel`), use {@link PostHogTraceExporter}.\n *\n * @example\n * ```ts\n * import { PostHogSpanProcessor } from '@posthog/ai/otel'\n * import { NodeSDK } from '@opentelemetry/sdk-node'\n *\n * const sdk = new NodeSDK({\n * spanProcessors: [new PostHogSpanProcessor({ projectToken: 'phc_...' })],\n * })\n * sdk.start()\n * ```\n */\nexport class PostHogSpanProcessor implements SpanProcessor {\n private readonly inner: SpanProcessor\n\n constructor(options: PostHogSpanProcessorOptions) {\n const token = normalizeToken(options.projectToken)\n if (!token) {\n console.warn('[PostHogSpanProcessor] projectToken is missing or blank; the processor will be disabled.')\n this.inner = new NoopSpanProcessor()\n return\n }\n\n if (options._spanProcessor) {\n this.inner = options._spanProcessor\n } else {\n const host = new URL(normalizeHost(options.host)).origin\n const exporter = new OTLPTraceExporter({\n url: `${host}/i/v0/ai/otel`,\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n this.inner = new BatchSpanProcessor(exporter)\n }\n }\n\n onStart(span: Span, parentContext: Context): void {\n // Forwarded unconditionally — filtering happens in onEnd. We can't filter\n // here because the span hasn't finished yet and may not have AI attributes\n // set. BatchSpanProcessor.onStart is a no-op so this is safe.\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (isAISpan(span)) {\n warnIfPostHogAiGatewayOtelAttributes(span.attributes)\n this.inner.onEnd(redactSpan(span))\n }\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n}\n"],"names":["DATA_URL_PREFIX_RE","BASE64_ALPHABET_RE","Base64Recognizer","recognize","value","minLength","dataUrl","exec","kind","mediaType","length","confidencePrefix","slice","test","MIME_HINT_KEYS","STRONG_CONTEXT_KEYS","Set","STRONG_CONTEXT_TYPES","FILE_FAMILY_TYPES","KNOWN_AUDIO_FORMATS","MediaTypeContext","EMPTY","undefined","constructor","parent","key","explicitMediaType","inferMediaType","inferFromSiblingMime","inferFromSiblingFormat","inferFromParentType","inferFromKey","hint","v","fmt","format","has","toLowerCase","t","type","includes","hasExplicitBinaryMediaType","startsWith","signalsBinary","STRONG_CONTEXT_MIN_LENGTH","WEAK_CONTEXT_MIN_LENGTH","BinaryContentRedactor","visited","WeakSet","recognizer","redact","isMultimodalEnabled","walk","ctx","redactString","Uint8Array","placeholderFor","add","Array","isArray","map","item","obj","out","k","Object","keys","recognitionValue","replace","Math","min","recognition","val","process","env","_INTERNAL_LLMA_MULTIMODAL","redactor","redactSpan","span","attributes","redactAttributes","events","redactEvents","create","enumerable","configurable","changed","redacted","redactAttributeValue","event","isStringArray","every","trimmed","trimStart","redactJson","parsed","JSON","parse","redactedStr","stringify","AI_SPAN_PREFIXES","isAISpan","some","prefix","name","POSTHOG_AI_GATEWAY_HOSTS","GATEWAY_DOCS_URL","extractHost","baseURL","hasScheme","URL","hostname","isPostHogAiGatewayUrl","host","warnIfPostHogAiGateway","console","warn","OTEL_GATEWAY_URL_ATTRIBUTES","warnIfPostHogAiGatewayOtelAttributes","DEFAULT_OTEL_HOST","EXPORT_SUCCESS","normalizeToken","trim","normalizeHost","normalizedValue","PostHogTraceExporter","OTLPTraceExporter","options","token","projectToken","disabled","origin","url","headers","Authorization","export","spans","resultCallback","code","aiSpans","filter","NoopSpanProcessor","onStart","_span","_parentContext","onEnd","shutdown","Promise","resolve","forceFlush","PostHogSpanProcessor","inner","_spanProcessor","exporter","BatchSpanProcessor","parentContext"],"mappings":"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"}
@@ -44,14 +44,16 @@ const FILE_FAMILY_TYPES = new Set(['file', 'input_file', 'document', 'media', 'f
44
44
  const KNOWN_AUDIO_FORMATS = new Set(['wav', 'mp3', 'ogg', 'flac', 'm4a', 'aac', 'webm']);
45
45
  class MediaTypeContext {
46
46
  static EMPTY = new MediaTypeContext(undefined, undefined);
47
- constructor(parent, key) {
47
+ constructor(parent, key, explicitMediaType) {
48
48
  this.parent = parent;
49
49
  this.key = key;
50
+ this.explicitMediaType = explicitMediaType;
50
51
  }
51
52
  inferMediaType() {
52
53
  return this.inferFromSiblingMime() ?? this.inferFromSiblingFormat() ?? this.inferFromParentType() ?? this.inferFromKey();
53
54
  }
54
55
  inferFromSiblingMime() {
56
+ if (this.explicitMediaType) return this.explicitMediaType;
55
57
  if (!this.parent) return undefined;
56
58
  for (const hint of MIME_HINT_KEYS) {
57
59
  const v = this.parent[hint];
@@ -86,7 +88,13 @@ class MediaTypeContext {
86
88
  if (key.includes('file') || key.includes('document')) return 'application/octet-stream';
87
89
  return undefined;
88
90
  }
91
+ hasExplicitBinaryMediaType() {
92
+ if (!this.explicitMediaType && (!this.parent || !this.key || !STRONG_CONTEXT_KEYS.has(this.key))) return false;
93
+ const mediaType = this.inferFromSiblingMime();
94
+ return mediaType !== undefined && !mediaType.toLowerCase().startsWith('text/');
95
+ }
89
96
  signalsBinary() {
97
+ if (this.explicitMediaType) return true;
90
98
  if (this.parent) {
91
99
  for (const hint of MIME_HINT_KEYS) {
92
100
  if (typeof this.parent[hint] === 'string') return true;
@@ -108,10 +116,10 @@ class BinaryContentRedactor {
108
116
  constructor(recognizer = new Base64Recognizer()) {
109
117
  this.recognizer = recognizer;
110
118
  }
111
- redact(value) {
119
+ redact(value, mediaType) {
112
120
  if (this.isMultimodalEnabled()) return value;
113
121
  this.visited = new WeakSet();
114
- return this.walk(value, MediaTypeContext.EMPTY);
122
+ return this.walk(value, mediaType ? new MediaTypeContext(undefined, undefined, mediaType) : MediaTypeContext.EMPTY);
115
123
  }
116
124
  walk(value, ctx) {
117
125
  if (value === null || value === undefined) return value;
@@ -135,8 +143,10 @@ class BinaryContentRedactor {
135
143
  return out;
136
144
  }
137
145
  redactString(value, ctx) {
138
- const minLength = ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH;
139
- const recognition = this.recognizer.recognize(value, minLength);
146
+ const hasExplicitBinaryMediaType = ctx.hasExplicitBinaryMediaType();
147
+ const recognitionValue = hasExplicitBinaryMediaType ? value.replace(/[\r\n]/g, '') : value;
148
+ const minLength = hasExplicitBinaryMediaType ? Math.min(recognitionValue.length, STRONG_CONTEXT_MIN_LENGTH) : ctx.signalsBinary() ? STRONG_CONTEXT_MIN_LENGTH : WEAK_CONTEXT_MIN_LENGTH;
149
+ const recognition = this.recognizer.recognize(recognitionValue, minLength);
140
150
  switch (recognition.kind) {
141
151
  case 'data-url':
142
152
  return this.placeholderFor(recognition.mediaType);
@@ -158,9 +168,10 @@ class BinaryContentRedactor {
158
168
  }
159
169
 
160
170
  const redactor = new BinaryContentRedactor();
161
- function redactBase64DataUrl(str) {
162
- return redactor.redact(str);
171
+ function redactBase64DataUrl(str, mediaType) {
172
+ return redactor.redact(str, mediaType);
163
173
  }
174
+ const sanitizeVercel = data => redactor.redact(data);
164
175
 
165
176
  const TOKEN_PROPERTY_KEYS = new Set(['$ai_input_tokens', '$ai_output_tokens', '$ai_cache_read_input_tokens', '$ai_cache_creation_input_tokens', '$ai_total_tokens', '$ai_reasoning_tokens']);
166
177
  function getTokensSource(posthogProperties) {
@@ -397,7 +408,7 @@ function sanitizeValues(obj) {
397
408
  return jsonSafe;
398
409
  }
399
410
 
400
- var version = "8.6.3";
411
+ var version = "8.6.5";
401
412
 
402
413
  const DEFAULT_MAX_DEPTH = 3;
403
414
  const MAX_STACK_LINES = 20;
@@ -530,6 +541,8 @@ const captureAiGeneration = async (client, options) => {
530
541
  if (httpStatus === undefined) {
531
542
  if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
532
543
  httpStatus = options.error.status;
544
+ } else if (typeof options.error === 'object' && 'statusCode' in options.error && typeof options.error.statusCode === 'number') {
545
+ httpStatus = options.error.statusCode;
533
546
  } else {
534
547
  httpStatus = 500;
535
548
  }
@@ -645,6 +658,15 @@ function isV3Model(model) {
645
658
 
646
659
  // Content types for the output array
647
660
 
661
+ const redactFileData = (data, mediaType) => {
662
+ if (data instanceof URL) {
663
+ return redactBase64DataUrl(data.toString(), data.protocol === 'data:' ? mediaType : undefined);
664
+ }
665
+ if (isString(data)) {
666
+ return redactBase64DataUrl(data, mediaType);
667
+ }
668
+ return undefined;
669
+ };
648
670
  const mapVercelParams = params => {
649
671
  return {
650
672
  temperature: params.temperature,
@@ -677,17 +699,8 @@ const mapVercelPrompt = messages => {
677
699
  text: truncate(c.text)
678
700
  };
679
701
  } else if (c.type === 'file') {
680
- // For file type, check if it's a data URL and redact if needed
681
- let fileData;
682
- const contentData = c.data;
683
- if (contentData instanceof URL) {
684
- fileData = contentData.toString();
685
- } else if (isString(contentData)) {
686
- // Redact base64 data URLs and raw base64 to prevent oversized events
687
- fileData = redactBase64DataUrl(contentData);
688
- } else {
689
- fileData = 'raw files not supported';
690
- }
702
+ // Redact base64 data URLs and raw base64 to prevent oversized events
703
+ const fileData = redactFileData(c.data, c.mediaType) ?? 'raw files not supported';
691
704
  return {
692
705
  type: 'file',
693
706
  file: fileData,
@@ -710,7 +723,7 @@ const mapVercelPrompt = messages => {
710
723
  type: 'tool-result',
711
724
  toolCallId: c.toolCallId,
712
725
  toolName: c.toolName,
713
- output: c.output,
726
+ output: sanitizeVercel(c.output),
714
727
  isError: c.isError
715
728
  };
716
729
  }
@@ -796,18 +809,11 @@ const mapVercelOutput = result => {
796
809
  }
797
810
  if (item.type === 'file') {
798
811
  // Handle files similar to input mapping - avoid large base64 data
799
- let fileData;
800
- if (item.data instanceof URL) {
801
- fileData = item.data.toString();
802
- } else if (typeof item.data === 'string') {
803
- fileData = redactBase64DataUrl(item.data);
812
+ let fileData = redactFileData(item.data, item.mediaType) ?? `[binary ${item.mediaType} file]`;
804
813
 
805
- // If not redacted and still large, replace with size indicator
806
- if (fileData === item.data && item.data.length > 1000) {
807
- fileData = `[${item.mediaType} file - ${item.data.length} bytes]`;
808
- }
809
- } else {
810
- fileData = `[binary ${item.mediaType} file]`;
814
+ // If not redacted and still large, replace with size indicator
815
+ if (typeof item.data === 'string' && fileData === item.data && item.data.length > 1000) {
816
+ fileData = `[${item.mediaType} file - ${item.data.length} bytes]`;
811
817
  }
812
818
  return {
813
819
  type: 'file',