@posthog/ai 8.7.0 → 8.7.1

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.
@@ -172,11 +172,16 @@ function redactBase64DataUrl(str, mediaType) {
172
172
  const sanitizeVercel = data => redactor.redact(data);
173
173
 
174
174
  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']);
175
+
176
+ /**
177
+ * Whether the caller supplied their own token counts, which override the ones the SDK
178
+ * derived from the provider response.
179
+ */
180
+ function hasTokenOverrides(posthogProperties) {
181
+ return !!posthogProperties && Object.keys(posthogProperties).some(key => TOKEN_PROPERTY_KEYS.has(key));
182
+ }
175
183
  function getTokensSource(posthogProperties) {
176
- if (posthogProperties && Object.keys(posthogProperties).some(key => TOKEN_PROPERTY_KEYS.has(key))) {
177
- return 'passthrough';
178
- }
179
- return 'sdk';
184
+ return hasTokenOverrides(posthogProperties) ? 'passthrough' : 'sdk';
180
185
  }
181
186
 
182
187
  // limit large outputs by truncating to 200kb (approx 200k bytes)
@@ -406,7 +411,7 @@ function sanitizeValues(obj) {
406
411
  return jsonSafe;
407
412
  }
408
413
 
409
- var version = "8.7.0";
414
+ var version = "8.7.1";
410
415
 
411
416
  const DEFAULT_MAX_DEPTH = 3;
412
417
  const MAX_STACK_LINES = 20;
@@ -573,6 +578,10 @@ const captureAiGeneration = async (client, options) => {
573
578
  $ai_total_cost_usd: inputCostUSD + outputCostUSD
574
579
  };
575
580
  }
581
+
582
+ // The caller's own token counts override the SDK-derived ones further down, via the
583
+ // `options.properties` spread.
584
+ const tokensOverridden = hasTokenOverrides(options.properties);
576
585
  const additionalTokenValues = {
577
586
  ...(usage.reasoningTokens ? {
578
587
  $ai_reasoning_tokens: usage.reasoningTokens
@@ -583,6 +592,18 @@ const captureAiGeneration = async (client, options) => {
583
592
  ...(usage.cacheCreationInputTokens ? {
584
593
  $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
585
594
  } : {}),
595
+ // Checked against undefined rather than truthiness, because false is the meaningful
596
+ // value here and a truthiness guard would drop it.
597
+ //
598
+ // Dropped entirely when the caller overrides the token counts: the flag describes how
599
+ // the SDK-derived counts relate to each other, so against passthrough counts it can be
600
+ // wrong in the expensive direction. Declaring inclusive over counts that are actually
601
+ // exclusive makes ingestion subtract the cache pool that was never in the input. A
602
+ // caller who knows their own accounting model can still pass
603
+ // `$ai_cache_reporting_exclusive` themselves, and that value wins.
604
+ ...(usage.cacheReportingExclusive !== undefined && !tokensOverridden ? {
605
+ $ai_cache_reporting_exclusive: usage.cacheReportingExclusive
606
+ } : {}),
586
607
  ...(usage.webSearchCount ? {
587
608
  $ai_web_search_count: usage.webSearchCount
588
609
  } : {}),