@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.
@@ -169,11 +169,16 @@ const sanitizeOpenAI = data => redactor.redact(data);
169
169
  const sanitizeOpenAIResponse = data => redactor.redact(data);
170
170
 
171
171
  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']);
172
+
173
+ /**
174
+ * Whether the caller supplied their own token counts, which override the ones the SDK
175
+ * derived from the provider response.
176
+ */
177
+ function hasTokenOverrides(posthogProperties) {
178
+ return !!posthogProperties && Object.keys(posthogProperties).some(key => TOKEN_PROPERTY_KEYS.has(key));
179
+ }
172
180
  function getTokensSource(posthogProperties) {
173
- if (posthogProperties && Object.keys(posthogProperties).some(key => TOKEN_PROPERTY_KEYS.has(key))) {
174
- return 'passthrough';
175
- }
176
- return 'sdk';
181
+ return hasTokenOverrides(posthogProperties) ? 'passthrough' : 'sdk';
177
182
  }
178
183
  const STRING_FORMAT = 'utf8';
179
184
 
@@ -544,7 +549,7 @@ function formatOpenAIResponsesInput(input, instructions) {
544
549
  return messages;
545
550
  }
546
551
 
547
- var version = "8.7.0";
552
+ var version = "8.7.1";
548
553
 
549
554
  const DEFAULT_MAX_DEPTH = 3;
550
555
  const MAX_STACK_LINES = 20;
@@ -711,6 +716,10 @@ const captureAiGeneration$1 = async (client, options) => {
711
716
  $ai_total_cost_usd: inputCostUSD + outputCostUSD
712
717
  };
713
718
  }
719
+
720
+ // The caller's own token counts override the SDK-derived ones further down, via the
721
+ // `options.properties` spread.
722
+ const tokensOverridden = hasTokenOverrides(options.properties);
714
723
  const additionalTokenValues = {
715
724
  ...(usage.reasoningTokens ? {
716
725
  $ai_reasoning_tokens: usage.reasoningTokens
@@ -721,6 +730,18 @@ const captureAiGeneration$1 = async (client, options) => {
721
730
  ...(usage.cacheCreationInputTokens ? {
722
731
  $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
723
732
  } : {}),
733
+ // Checked against undefined rather than truthiness, because false is the meaningful
734
+ // value here and a truthiness guard would drop it.
735
+ //
736
+ // Dropped entirely when the caller overrides the token counts: the flag describes how
737
+ // the SDK-derived counts relate to each other, so against passthrough counts it can be
738
+ // wrong in the expensive direction. Declaring inclusive over counts that are actually
739
+ // exclusive makes ingestion subtract the cache pool that was never in the input. A
740
+ // caller who knows their own accounting model can still pass
741
+ // `$ai_cache_reporting_exclusive` themselves, and that value wins.
742
+ ...(usage.cacheReportingExclusive !== undefined && !tokensOverridden ? {
743
+ $ai_cache_reporting_exclusive: usage.cacheReportingExclusive
744
+ } : {}),
724
745
  ...(usage.webSearchCount ? {
725
746
  $ai_web_search_count: usage.webSearchCount
726
747
  } : {}),