@posthog/ai 8.6.2 → 8.6.3

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.
@@ -384,7 +384,7 @@ function addDefaults(params) {
384
384
  };
385
385
  }
386
386
 
387
- var version = "8.6.2";
387
+ var version = "8.6.3";
388
388
 
389
389
  const DEFAULT_MAX_DEPTH = 3;
390
390
  const MAX_STACK_LINES = 20;
@@ -495,125 +495,131 @@ const warnIfPostHogAiGateway = baseURL => {
495
495
  * so callers can re-throw the original error reference safely.
496
496
  */
497
497
  const captureAiGeneration = async (client, options) => {
498
- if (!client.capture) {
499
- return;
500
- }
501
- warnIfPostHogAiGateway(options.baseURL);
502
- const traceId = options.traceId ?? uuid.v4();
503
- const eventType = options.eventType ?? AIEvent.Generation;
504
- const privacyMode = options.privacyMode ?? false;
505
- const usage = options.usage ?? {};
498
+ try {
499
+ if (!client.capture) {
500
+ return;
501
+ }
502
+ warnIfPostHogAiGateway(options.baseURL);
503
+ const traceId = options.traceId ?? uuid.v4();
504
+ const eventType = options.eventType ?? AIEvent.Generation;
505
+ const privacyMode = options.privacyMode ?? false;
506
+ const usage = options.usage ?? {};
506
507
 
507
- // Check privacy before reading or traversing input/output. Besides avoiding
508
- // needless work, this ensures hostile getters/proxies cannot observe a value
509
- // that the caller explicitly requested us to redact.
510
- const shouldRedact = withPrivacyMode(client, privacyMode, false) === null;
511
- const safeInput = shouldRedact ? null : core.toJsonSafeValue(options.input);
512
- const safeOutput = shouldRedact ? null : core.toJsonSafeValue(options.output);
513
- let httpStatus = options.httpStatus;
514
- let errorData = {};
515
- if (options.error) {
516
- if (httpStatus === undefined) {
517
- if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
518
- httpStatus = options.error.status;
519
- } else {
520
- httpStatus = 500;
508
+ // Check privacy before reading or traversing input/output. Besides avoiding
509
+ // needless work, this ensures hostile getters/proxies cannot observe a value
510
+ // that the caller explicitly requested us to redact.
511
+ const shouldRedact = withPrivacyMode(client, privacyMode, false) === null;
512
+ const safeInput = shouldRedact ? null : core.toJsonSafeValue(options.input);
513
+ const safeOutput = shouldRedact ? null : core.toJsonSafeValue(options.output);
514
+ let httpStatus = options.httpStatus;
515
+ let errorData = {};
516
+ if (options.error) {
517
+ if (httpStatus === undefined) {
518
+ if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
519
+ httpStatus = options.error.status;
520
+ } else {
521
+ httpStatus = 500;
522
+ }
521
523
  }
522
- }
523
- let exceptionId;
524
- if (client.options?.enableExceptionAutocapture) {
525
- exceptionId = core.uuidv7();
526
- client.captureException(options.error, undefined, {
527
- $ai_trace_id: traceId
528
- }, exceptionId);
529
- if (typeof options.error === 'object') {
530
- options.error.__posthog_previously_captured_error = true;
524
+ let exceptionId;
525
+ if (client.options?.enableExceptionAutocapture) {
526
+ exceptionId = core.uuidv7();
527
+ client.captureException(options.error, undefined, {
528
+ $ai_trace_id: traceId
529
+ }, exceptionId);
530
+ if (typeof options.error === 'object') {
531
+ ;
532
+ options.error.__posthog_previously_captured_error = true;
533
+ }
531
534
  }
535
+ errorData = {
536
+ $ai_is_error: true,
537
+ $ai_error: stringifyError(options.error),
538
+ $exception_event_id: exceptionId
539
+ };
540
+ }
541
+ httpStatus = httpStatus ?? 200;
542
+ let costOverrideData = {};
543
+ if (options.costOverride) {
544
+ const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
545
+ const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
546
+ costOverrideData = {
547
+ $ai_input_cost_usd: inputCostUSD,
548
+ $ai_output_cost_usd: outputCostUSD,
549
+ $ai_total_cost_usd: inputCostUSD + outputCostUSD
550
+ };
532
551
  }
533
- errorData = {
534
- $ai_is_error: true,
535
- $ai_error: stringifyError(options.error),
536
- $exception_event_id: exceptionId
552
+ const additionalTokenValues = {
553
+ ...(usage.reasoningTokens ? {
554
+ $ai_reasoning_tokens: usage.reasoningTokens
555
+ } : {}),
556
+ ...(usage.cacheReadInputTokens ? {
557
+ $ai_cache_read_input_tokens: usage.cacheReadInputTokens
558
+ } : {}),
559
+ ...(usage.cacheCreationInputTokens ? {
560
+ $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
561
+ } : {}),
562
+ ...(usage.webSearchCount ? {
563
+ $ai_web_search_count: usage.webSearchCount
564
+ } : {}),
565
+ ...(usage.rawUsage ? {
566
+ $ai_usage: usage.rawUsage
567
+ } : {})
537
568
  };
538
- }
539
- httpStatus = httpStatus ?? 200;
540
- let costOverrideData = {};
541
- if (options.costOverride) {
542
- const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
543
- const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
544
- costOverrideData = {
545
- $ai_input_cost_usd: inputCostUSD,
546
- $ai_output_cost_usd: outputCostUSD,
547
- $ai_total_cost_usd: inputCostUSD + outputCostUSD
569
+ const properties = {
570
+ $ai_lib: 'posthog-ai',
571
+ $ai_lib_version: version,
572
+ $ai_provider: options.providerOverride ?? options.provider,
573
+ $ai_model: options.modelOverride ?? options.model,
574
+ $ai_model_parameters: options.modelParameters ?? {},
575
+ $ai_input: safeInput,
576
+ $ai_output_choices: safeOutput,
577
+ $ai_http_status: httpStatus,
578
+ $ai_input_tokens: usage.inputTokens ?? 0,
579
+ ...(usage.outputTokens !== undefined ? {
580
+ $ai_output_tokens: usage.outputTokens
581
+ } : {}),
582
+ ...additionalTokenValues,
583
+ $ai_latency: options.latency ?? 0,
584
+ ...(options.timeToFirstToken !== undefined ? {
585
+ $ai_time_to_first_token: options.timeToFirstToken
586
+ } : {}),
587
+ $ai_trace_id: traceId,
588
+ $ai_base_url: options.baseURL ?? '',
589
+ ...options.properties,
590
+ $ai_tokens_source: getTokensSource(options.properties),
591
+ ...(options.distinctId ? {} : {
592
+ $process_person_profile: false
593
+ }),
594
+ ...(options.stopReason ? {
595
+ $ai_stop_reason: options.stopReason
596
+ } : {}),
597
+ ...(options.tools ? {
598
+ $ai_tools: options.tools
599
+ } : {}),
600
+ ...(options.completionId ? {
601
+ $ai_completion_id: options.completionId
602
+ } : {}),
603
+ ...(options.providerMetadata && Object.keys(options.providerMetadata).length > 0 ? {
604
+ $ai_provider_metadata: options.providerMetadata
605
+ } : {}),
606
+ ...errorData,
607
+ ...costOverrideData
548
608
  };
549
- }
550
- const additionalTokenValues = {
551
- ...(usage.reasoningTokens ? {
552
- $ai_reasoning_tokens: usage.reasoningTokens
553
- } : {}),
554
- ...(usage.cacheReadInputTokens ? {
555
- $ai_cache_read_input_tokens: usage.cacheReadInputTokens
556
- } : {}),
557
- ...(usage.cacheCreationInputTokens ? {
558
- $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
559
- } : {}),
560
- ...(usage.webSearchCount ? {
561
- $ai_web_search_count: usage.webSearchCount
562
- } : {}),
563
- ...(usage.rawUsage ? {
564
- $ai_usage: usage.rawUsage
565
- } : {})
566
- };
567
- const properties = {
568
- $ai_lib: 'posthog-ai',
569
- $ai_lib_version: version,
570
- $ai_provider: options.providerOverride ?? options.provider,
571
- $ai_model: options.modelOverride ?? options.model,
572
- $ai_model_parameters: options.modelParameters ?? {},
573
- $ai_input: safeInput,
574
- $ai_output_choices: safeOutput,
575
- $ai_http_status: httpStatus,
576
- $ai_input_tokens: usage.inputTokens ?? 0,
577
- ...(usage.outputTokens !== undefined ? {
578
- $ai_output_tokens: usage.outputTokens
579
- } : {}),
580
- ...additionalTokenValues,
581
- $ai_latency: options.latency ?? 0,
582
- ...(options.timeToFirstToken !== undefined ? {
583
- $ai_time_to_first_token: options.timeToFirstToken
584
- } : {}),
585
- $ai_trace_id: traceId,
586
- $ai_base_url: options.baseURL ?? '',
587
- ...options.properties,
588
- $ai_tokens_source: getTokensSource(options.properties),
589
- ...(options.distinctId ? {} : {
590
- $process_person_profile: false
591
- }),
592
- ...(options.stopReason ? {
593
- $ai_stop_reason: options.stopReason
594
- } : {}),
595
- ...(options.tools ? {
596
- $ai_tools: options.tools
597
- } : {}),
598
- ...(options.completionId ? {
599
- $ai_completion_id: options.completionId
600
- } : {}),
601
- ...(options.providerMetadata && Object.keys(options.providerMetadata).length > 0 ? {
602
- $ai_provider_metadata: options.providerMetadata
603
- } : {}),
604
- ...errorData,
605
- ...costOverrideData
606
- };
607
- const event = {
608
- distinctId: options.distinctId ?? traceId,
609
- event: eventType,
610
- properties,
611
- groups: options.groups
612
- };
613
- if (options.captureImmediate) {
614
- await client.captureImmediate(event);
615
- } else {
616
- client.capture(event);
609
+ const event = {
610
+ distinctId: options.distinctId ?? traceId,
611
+ event: eventType,
612
+ properties,
613
+ groups: options.groups
614
+ };
615
+ if (options.captureImmediate) {
616
+ await client.captureImmediate(event);
617
+ } else {
618
+ client.capture(event);
619
+ }
620
+ } catch (error) {
621
+ // Telemetry failures must never affect the instrumented provider call.
622
+ console.warn('[PostHog AI] Failed to capture generation telemetry:', error);
617
623
  }
618
624
  };
619
625