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