@posthog/ai 8.6.2 → 8.6.4

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.
@@ -143,7 +143,7 @@ const truncate = input => {
143
143
  return `${truncatedStr}... [truncated]`;
144
144
  };
145
145
 
146
- var version = "8.6.2";
146
+ var version = "8.6.4";
147
147
 
148
148
  // Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway
149
149
  // emits its own $ai_generation, so each call would be captured (and, for billable
@@ -141,7 +141,7 @@ const truncate = input => {
141
141
  return `${truncatedStr}... [truncated]`;
142
142
  };
143
143
 
144
- var version = "8.6.2";
144
+ var version = "8.6.4";
145
145
 
146
146
  // Warn when a wrapper's base_url points at the PostHog AI Gateway: the gateway
147
147
  // emits its own $ai_generation, so each call would be captured (and, for billable
@@ -397,7 +397,7 @@ function sanitizeValues(obj) {
397
397
  return jsonSafe;
398
398
  }
399
399
 
400
- var version = "8.6.2";
400
+ var version = "8.6.4";
401
401
 
402
402
  const DEFAULT_MAX_DEPTH = 3;
403
403
  const MAX_STACK_LINES = 20;
@@ -508,125 +508,133 @@ const warnIfPostHogAiGateway = baseURL => {
508
508
  * so callers can re-throw the original error reference safely.
509
509
  */
510
510
  const captureAiGeneration = async (client, options) => {
511
- if (!client.capture) {
512
- return;
513
- }
514
- warnIfPostHogAiGateway(options.baseURL);
515
- const traceId = options.traceId ?? uuid.v4();
516
- const eventType = options.eventType ?? AIEvent.Generation;
517
- const privacyMode = options.privacyMode ?? false;
518
- const usage = options.usage ?? {};
511
+ try {
512
+ if (!client.capture) {
513
+ return;
514
+ }
515
+ warnIfPostHogAiGateway(options.baseURL);
516
+ const traceId = options.traceId ?? uuid.v4();
517
+ const eventType = options.eventType ?? AIEvent.Generation;
518
+ const privacyMode = options.privacyMode ?? false;
519
+ const usage = options.usage ?? {};
519
520
 
520
- // Check privacy before reading or traversing input/output. Besides avoiding
521
- // needless work, this ensures hostile getters/proxies cannot observe a value
522
- // that the caller explicitly requested us to redact.
523
- const shouldRedact = withPrivacyMode(client, privacyMode, false) === null;
524
- const safeInput = shouldRedact ? null : core.toJsonSafeValue(options.input);
525
- const safeOutput = shouldRedact ? null : core.toJsonSafeValue(options.output);
526
- let httpStatus = options.httpStatus;
527
- let errorData = {};
528
- if (options.error) {
529
- if (httpStatus === undefined) {
530
- if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
531
- httpStatus = options.error.status;
532
- } else {
533
- httpStatus = 500;
521
+ // Check privacy before reading or traversing input/output. Besides avoiding
522
+ // needless work, this ensures hostile getters/proxies cannot observe a value
523
+ // that the caller explicitly requested us to redact.
524
+ const shouldRedact = withPrivacyMode(client, privacyMode, false) === null;
525
+ const safeInput = shouldRedact ? null : core.toJsonSafeValue(options.input);
526
+ const safeOutput = shouldRedact ? null : core.toJsonSafeValue(options.output);
527
+ let httpStatus = options.httpStatus;
528
+ let errorData = {};
529
+ if (options.error) {
530
+ if (httpStatus === undefined) {
531
+ if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
532
+ httpStatus = options.error.status;
533
+ } else if (typeof options.error === 'object' && 'statusCode' in options.error && typeof options.error.statusCode === 'number') {
534
+ httpStatus = options.error.statusCode;
535
+ } else {
536
+ httpStatus = 500;
537
+ }
534
538
  }
535
- }
536
- let exceptionId;
537
- if (client.options?.enableExceptionAutocapture) {
538
- exceptionId = core.uuidv7();
539
- client.captureException(options.error, undefined, {
540
- $ai_trace_id: traceId
541
- }, exceptionId);
542
- if (typeof options.error === 'object') {
543
- options.error.__posthog_previously_captured_error = true;
539
+ let exceptionId;
540
+ if (client.options?.enableExceptionAutocapture) {
541
+ exceptionId = core.uuidv7();
542
+ client.captureException(options.error, undefined, {
543
+ $ai_trace_id: traceId
544
+ }, exceptionId);
545
+ if (typeof options.error === 'object') {
546
+ ;
547
+ options.error.__posthog_previously_captured_error = true;
548
+ }
544
549
  }
550
+ errorData = {
551
+ $ai_is_error: true,
552
+ $ai_error: stringifyError(options.error),
553
+ $exception_event_id: exceptionId
554
+ };
555
+ }
556
+ httpStatus = httpStatus ?? 200;
557
+ let costOverrideData = {};
558
+ if (options.costOverride) {
559
+ const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
560
+ const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
561
+ costOverrideData = {
562
+ $ai_input_cost_usd: inputCostUSD,
563
+ $ai_output_cost_usd: outputCostUSD,
564
+ $ai_total_cost_usd: inputCostUSD + outputCostUSD
565
+ };
545
566
  }
546
- errorData = {
547
- $ai_is_error: true,
548
- $ai_error: stringifyError(options.error),
549
- $exception_event_id: exceptionId
567
+ const additionalTokenValues = {
568
+ ...(usage.reasoningTokens ? {
569
+ $ai_reasoning_tokens: usage.reasoningTokens
570
+ } : {}),
571
+ ...(usage.cacheReadInputTokens ? {
572
+ $ai_cache_read_input_tokens: usage.cacheReadInputTokens
573
+ } : {}),
574
+ ...(usage.cacheCreationInputTokens ? {
575
+ $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
576
+ } : {}),
577
+ ...(usage.webSearchCount ? {
578
+ $ai_web_search_count: usage.webSearchCount
579
+ } : {}),
580
+ ...(usage.rawUsage ? {
581
+ $ai_usage: usage.rawUsage
582
+ } : {})
550
583
  };
551
- }
552
- httpStatus = httpStatus ?? 200;
553
- let costOverrideData = {};
554
- if (options.costOverride) {
555
- const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
556
- const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
557
- costOverrideData = {
558
- $ai_input_cost_usd: inputCostUSD,
559
- $ai_output_cost_usd: outputCostUSD,
560
- $ai_total_cost_usd: inputCostUSD + outputCostUSD
584
+ const properties = {
585
+ $ai_lib: 'posthog-ai',
586
+ $ai_lib_version: version,
587
+ $ai_provider: options.providerOverride ?? options.provider,
588
+ $ai_model: options.modelOverride ?? options.model,
589
+ $ai_model_parameters: options.modelParameters ?? {},
590
+ $ai_input: safeInput,
591
+ $ai_output_choices: safeOutput,
592
+ $ai_http_status: httpStatus,
593
+ $ai_input_tokens: usage.inputTokens ?? 0,
594
+ ...(usage.outputTokens !== undefined ? {
595
+ $ai_output_tokens: usage.outputTokens
596
+ } : {}),
597
+ ...additionalTokenValues,
598
+ $ai_latency: options.latency ?? 0,
599
+ ...(options.timeToFirstToken !== undefined ? {
600
+ $ai_time_to_first_token: options.timeToFirstToken
601
+ } : {}),
602
+ $ai_trace_id: traceId,
603
+ $ai_base_url: options.baseURL ?? '',
604
+ ...options.properties,
605
+ $ai_tokens_source: getTokensSource(options.properties),
606
+ ...(options.distinctId ? {} : {
607
+ $process_person_profile: false
608
+ }),
609
+ ...(options.stopReason ? {
610
+ $ai_stop_reason: options.stopReason
611
+ } : {}),
612
+ ...(options.tools ? {
613
+ $ai_tools: options.tools
614
+ } : {}),
615
+ ...(options.completionId ? {
616
+ $ai_completion_id: options.completionId
617
+ } : {}),
618
+ ...(options.providerMetadata && Object.keys(options.providerMetadata).length > 0 ? {
619
+ $ai_provider_metadata: options.providerMetadata
620
+ } : {}),
621
+ ...errorData,
622
+ ...costOverrideData
561
623
  };
562
- }
563
- const additionalTokenValues = {
564
- ...(usage.reasoningTokens ? {
565
- $ai_reasoning_tokens: usage.reasoningTokens
566
- } : {}),
567
- ...(usage.cacheReadInputTokens ? {
568
- $ai_cache_read_input_tokens: usage.cacheReadInputTokens
569
- } : {}),
570
- ...(usage.cacheCreationInputTokens ? {
571
- $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
572
- } : {}),
573
- ...(usage.webSearchCount ? {
574
- $ai_web_search_count: usage.webSearchCount
575
- } : {}),
576
- ...(usage.rawUsage ? {
577
- $ai_usage: usage.rawUsage
578
- } : {})
579
- };
580
- const properties = {
581
- $ai_lib: 'posthog-ai',
582
- $ai_lib_version: version,
583
- $ai_provider: options.providerOverride ?? options.provider,
584
- $ai_model: options.modelOverride ?? options.model,
585
- $ai_model_parameters: options.modelParameters ?? {},
586
- $ai_input: safeInput,
587
- $ai_output_choices: safeOutput,
588
- $ai_http_status: httpStatus,
589
- $ai_input_tokens: usage.inputTokens ?? 0,
590
- ...(usage.outputTokens !== undefined ? {
591
- $ai_output_tokens: usage.outputTokens
592
- } : {}),
593
- ...additionalTokenValues,
594
- $ai_latency: options.latency ?? 0,
595
- ...(options.timeToFirstToken !== undefined ? {
596
- $ai_time_to_first_token: options.timeToFirstToken
597
- } : {}),
598
- $ai_trace_id: traceId,
599
- $ai_base_url: options.baseURL ?? '',
600
- ...options.properties,
601
- $ai_tokens_source: getTokensSource(options.properties),
602
- ...(options.distinctId ? {} : {
603
- $process_person_profile: false
604
- }),
605
- ...(options.stopReason ? {
606
- $ai_stop_reason: options.stopReason
607
- } : {}),
608
- ...(options.tools ? {
609
- $ai_tools: options.tools
610
- } : {}),
611
- ...(options.completionId ? {
612
- $ai_completion_id: options.completionId
613
- } : {}),
614
- ...(options.providerMetadata && Object.keys(options.providerMetadata).length > 0 ? {
615
- $ai_provider_metadata: options.providerMetadata
616
- } : {}),
617
- ...errorData,
618
- ...costOverrideData
619
- };
620
- const event = {
621
- distinctId: options.distinctId ?? traceId,
622
- event: eventType,
623
- properties,
624
- groups: options.groups
625
- };
626
- if (options.captureImmediate) {
627
- await client.captureImmediate(event);
628
- } else {
629
- client.capture(event);
624
+ const event = {
625
+ distinctId: options.distinctId ?? traceId,
626
+ event: eventType,
627
+ properties,
628
+ groups: options.groups
629
+ };
630
+ if (options.captureImmediate) {
631
+ await client.captureImmediate(event);
632
+ } else {
633
+ client.capture(event);
634
+ }
635
+ } catch (error) {
636
+ // Telemetry failures must never affect the instrumented provider call.
637
+ console.warn('[PostHog AI] Failed to capture generation telemetry:', error);
630
638
  }
631
639
  };
632
640