@posthog/ai 8.6.7 → 8.6.8

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.
@@ -394,7 +394,7 @@ function addDefaults(params) {
394
394
  };
395
395
  }
396
396
 
397
- var version = "8.6.7";
397
+ var version = "8.6.8";
398
398
 
399
399
  const DEFAULT_MAX_DEPTH = 3;
400
400
  const MAX_STACK_LINES = 20;
@@ -390,7 +390,7 @@ function addDefaults(params) {
390
390
  };
391
391
  }
392
392
 
393
- var version = "8.6.7";
393
+ var version = "8.6.8";
394
394
 
395
395
  const DEFAULT_MAX_DEPTH = 3;
396
396
  const MAX_STACK_LINES = 20;
package/dist/index.cjs CHANGED
@@ -391,7 +391,7 @@ function sanitizeValues(obj) {
391
391
  return jsonSafe;
392
392
  }
393
393
 
394
- var version = "8.6.7";
394
+ var version = "8.6.8";
395
395
 
396
396
  const DEFAULT_MAX_DEPTH = 3;
397
397
  const MAX_STACK_LINES = 20;
package/dist/index.mjs CHANGED
@@ -389,7 +389,7 @@ function sanitizeValues(obj) {
389
389
  return jsonSafe;
390
390
  }
391
391
 
392
- var version = "8.6.7";
392
+ var version = "8.6.8";
393
393
 
394
394
  const DEFAULT_MAX_DEPTH = 3;
395
395
  const MAX_STACK_LINES = 20;
@@ -3,6 +3,12 @@
3
3
  require('uuid');
4
4
  var base = require('@langchain/core/callbacks/base');
5
5
 
6
+ // Type guards for safer type checking
7
+
8
+ const isObject = value => {
9
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
10
+ };
11
+
6
12
  const DATA_URL_PREFIX_RE = /^data:([^;,\s]+)(?:;[^;,\s]+)*;base64,/i;
7
13
  const BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/;
8
14
  class Base64Recognizer {
@@ -227,7 +233,7 @@ function sanitizeValues(obj) {
227
233
  return jsonSafe;
228
234
  }
229
235
 
230
- var version = "8.6.7";
236
+ var version = "8.6.8";
231
237
 
232
238
  const DEFAULT_MAX_DEPTH = 3;
233
239
  const MAX_STACK_LINES = 20;
@@ -657,6 +663,10 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
657
663
  if (additionalTokenData.cacheWriteInputTokens) {
658
664
  eventProperties['$ai_cache_creation_input_tokens'] = additionalTokenData.cacheWriteInputTokens;
659
665
  }
666
+ if (additionalTokenData.cacheWrite5mInputTokens !== undefined && additionalTokenData.cacheWrite1hInputTokens !== undefined) {
667
+ eventProperties['$ai_cache_creation_5m_input_tokens'] = additionalTokenData.cacheWrite5mInputTokens;
668
+ eventProperties['$ai_cache_creation_1h_input_tokens'] = additionalTokenData.cacheWrite1hInputTokens;
669
+ }
660
670
  if (additionalTokenData.reasoningTokens) {
661
671
  eventProperties['$ai_reasoning_tokens'] = additionalTokenData.reasoningTokens;
662
672
  }
@@ -826,7 +836,52 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
826
836
  const stopReason = messageResponseMetadata?.finish_reason || messageResponseMetadata?.stop_reason || gen.generationInfo?.finish_reason || generationResponseMetadata?.stop_reason || generationResponseMetadata?.finish_reason || gen.generationInfo?.stop_reason;
827
837
  return stopReason != null ? String(stopReason) : undefined;
828
838
  }
829
- _parseUsageModel(usage, provider, model) {
839
+ _extractCacheCreationTtlBreakdown(cacheCreation, aggregateValues) {
840
+ if (!isObject(cacheCreation)) {
841
+ return undefined;
842
+ }
843
+ const {
844
+ ephemeral_5m_input_tokens: cache5m,
845
+ ephemeral_1h_input_tokens: cache1h
846
+ } = cacheCreation;
847
+ const providedValues = [cache5m, cache1h].filter(value => value != null);
848
+ if (providedValues.length === 0 || !providedValues.every(value => typeof value === 'number' && Number.isFinite(value) && value >= 0)) {
849
+ return undefined;
850
+ }
851
+ const breakdown = [typeof cache5m === 'number' ? cache5m : 0, typeof cache1h === 'number' ? cache1h : 0];
852
+ const total = breakdown[0] + breakdown[1];
853
+ const validAggregates = aggregateValues.filter(value => typeof value === 'number' && Number.isFinite(value) && value >= 0);
854
+ return total > 0 && !validAggregates.some(aggregate => aggregate !== total) ? breakdown : undefined;
855
+ }
856
+ _extractBedrockCacheCreationTtlBreakdown(cacheDetails, aggregateValues) {
857
+ if (!Array.isArray(cacheDetails)) {
858
+ return undefined;
859
+ }
860
+ let cache5m = 0;
861
+ let cache1h = 0;
862
+ for (const detail of cacheDetails) {
863
+ if (!isObject(detail)) {
864
+ continue;
865
+ }
866
+ const ttl = typeof detail.ttl === 'string' ? detail.ttl.toLowerCase() : undefined;
867
+ const inputTokens = detail.inputTokens;
868
+ if (ttl !== '5m' && ttl !== 't5m' && ttl !== '1h' && ttl !== 't1h' || typeof inputTokens !== 'number' || !Number.isFinite(inputTokens) || inputTokens < 0) {
869
+ continue;
870
+ }
871
+ if (ttl === '5m' || ttl === 't5m') {
872
+ cache5m += inputTokens;
873
+ } else {
874
+ cache1h += inputTokens;
875
+ }
876
+ }
877
+ const total = cache5m + cache1h;
878
+ const validAggregates = aggregateValues.filter(value => typeof value === 'number' && Number.isFinite(value) && value >= 0);
879
+ if (total === 0 || validAggregates.some(aggregate => aggregate !== total)) {
880
+ return undefined;
881
+ }
882
+ return [cache5m, cache1h];
883
+ }
884
+ _parseUsageModel(usage, provider, model, inputIncludesCacheTokens = true, rawUsage) {
830
885
  const conversionList = [['promptTokens', 'input'], ['completionTokens', 'output'], ['input_tokens', 'input'], ['output_tokens', 'output'], ['prompt_token_count', 'input'], ['candidates_token_count', 'output'], ['inputTokenCount', 'input'], ['outputTokenCount', 'output'], ['input_token_count', 'input'], ['generated_token_count', 'output']];
831
886
  const parsedUsage = conversionList.reduce((acc, [modelKey, typeKey]) => {
832
887
  const value = usage[modelKey];
@@ -860,6 +915,14 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
860
915
  } else if (usage.input_token_details?.cache_creation != null) {
861
916
  additionalTokenData.cacheWriteInputTokens = usage.input_token_details.cache_creation;
862
917
  }
918
+ const directCacheCreationAggregates = [usage.cache_creation_input_tokens, usage.input_token_details?.cache_creation, usage.cacheWriteInputTokens, rawUsage?.cache_creation_input_tokens, rawUsage?.input_token_details?.cache_creation, rawUsage?.cacheWriteInputTokens, additionalTokenData.cacheWriteInputTokens];
919
+ const cacheCreationTtl = this._extractCacheCreationTtlBreakdown(usage.cache_creation, directCacheCreationAggregates) ?? this._extractCacheCreationTtlBreakdown(rawUsage?.cache_creation, directCacheCreationAggregates) ?? this._extractBedrockCacheCreationTtlBreakdown(usage.cacheDetails, [usage.cacheWriteInputTokens, additionalTokenData.cacheWriteInputTokens]) ?? this._extractBedrockCacheCreationTtlBreakdown(rawUsage?.cacheDetails, [rawUsage?.cacheWriteInputTokens, additionalTokenData.cacheWriteInputTokens]);
920
+ if (cacheCreationTtl) {
921
+ const [cacheWrite5mInputTokens, cacheWrite1hInputTokens] = cacheCreationTtl;
922
+ additionalTokenData.cacheWrite5mInputTokens = cacheWrite5mInputTokens;
923
+ additionalTokenData.cacheWrite1hInputTokens = cacheWrite1hInputTokens;
924
+ additionalTokenData.cacheWriteInputTokens = cacheWrite5mInputTokens + cacheWrite1hInputTokens;
925
+ }
863
926
 
864
927
  // Check for reasoning tokens in various formats
865
928
  if (usage.completion_tokens_details?.reasoning_tokens != null) {
@@ -920,7 +983,7 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
920
983
  } else if (model && model.toLowerCase().includes('anthropic')) {
921
984
  isAnthropic = true;
922
985
  }
923
- if (isAnthropic && parsedUsage.input) {
986
+ if (isAnthropic && inputIncludesCacheTokens && parsedUsage.input) {
924
987
  const cacheTokens = (additionalTokenData.cacheReadInputTokens || 0) + (additionalTokenData.cacheWriteInputTokens || 0);
925
988
  if (cacheTokens > 0) {
926
989
  parsedUsage.input = Math.max(parsedUsage.input - cacheTokens, 0);
@@ -929,32 +992,49 @@ class LangChainCallbackHandler extends base.BaseCallbackHandler {
929
992
  return [parsedUsage.input, parsedUsage.output, additionalTokenData];
930
993
  }
931
994
  parseUsage(response, provider, model) {
932
- let llmUsage = [0, 0, {}];
933
- const llmUsageKeys = ['token_usage', 'usage', 'tokenUsage'];
934
- if (response.llmOutput != null) {
935
- const key = llmUsageKeys.find(k => response.llmOutput?.[k] != null);
936
- if (key) {
937
- llmUsage = this._parseUsageModel(response.llmOutput[key], provider, model);
995
+ const isNonEmptyUsage = usage => isObject(usage) && Object.keys(usage).length > 0;
996
+ const firstNonEmptyUsage = (...candidates) => candidates.find(isNonEmptyUsage);
997
+ let normalizedGenerationUsage;
998
+ let rawGenerationUsage;
999
+ let fallbackGenerationUsage;
1000
+ for (const generation of response.generations ?? []) {
1001
+ for (const genChunk of generation) {
1002
+ const generationInfo = genChunk.generationInfo ?? {};
1003
+ const message = 'message' in genChunk ? genChunk.message : undefined;
1004
+ const messageUsage = message && typeof message === 'object' && 'usage_metadata' in message ? message.usage_metadata : undefined;
1005
+ normalizedGenerationUsage = firstNonEmptyUsage(normalizedGenerationUsage, messageUsage, generationInfo.usage_metadata);
1006
+ const messageResponseMetadata = message && typeof message === 'object' && 'response_metadata' in message && isObject(message.response_metadata) ? message.response_metadata : undefined;
1007
+ const generationResponseMetadata = isObject(generationInfo.response_metadata) ? generationInfo.response_metadata : undefined;
1008
+ const messageStreamMetadata = isObject(messageResponseMetadata?.metadata) ? messageResponseMetadata.metadata : undefined;
1009
+ const generationStreamMetadata = isObject(generationResponseMetadata?.metadata) ? generationResponseMetadata.metadata : undefined;
1010
+ rawGenerationUsage = firstNonEmptyUsage(rawGenerationUsage, messageResponseMetadata?.usage, messageStreamMetadata?.usage, generationResponseMetadata?.usage, generationStreamMetadata?.usage);
1011
+ fallbackGenerationUsage = firstNonEmptyUsage(fallbackGenerationUsage, messageResponseMetadata?.['amazon-bedrock-invocationMetrics'], generationResponseMetadata?.['amazon-bedrock-invocationMetrics'], generationInfo.usage_metadata);
938
1012
  }
939
1013
  }
940
-
941
- // If top-level usage info was not found, try checking the generations.
942
- if (llmUsage[0] === 0 && llmUsage[1] === 0 && response.generations) {
943
- for (const generation of response.generations) {
944
- for (const genChunk of generation) {
945
- const message = genChunk.message ?? {};
946
- const messageResponseMetadata = message.response_metadata ?? {};
947
- const generationInfo = genChunk.generationInfo ?? {};
948
- const generationResponseMetadata = generationInfo.response_metadata ?? {};
949
- const chunkUsage = message.usage_metadata ?? messageResponseMetadata['usage'] ?? messageResponseMetadata['amazon-bedrock-invocationMetrics'] ?? generationInfo.usage_metadata ?? generationResponseMetadata['usage'] ?? generationResponseMetadata['amazon-bedrock-invocationMetrics'];
950
- if (chunkUsage) {
951
- llmUsage = this._parseUsageModel(chunkUsage, provider, model);
952
- return llmUsage;
953
- }
1014
+ const isAnthropic = provider?.toLowerCase() === 'anthropic' || model?.toLowerCase().includes('anthropic') === true;
1015
+ if (isAnthropic && isNonEmptyUsage(normalizedGenerationUsage)) {
1016
+ return this._parseUsageModel(normalizedGenerationUsage, provider, model, true, rawGenerationUsage);
1017
+ }
1018
+ const llmUsageKeys = ['token_usage', 'usage', 'tokenUsage'];
1019
+ if (response.llmOutput != null) {
1020
+ for (const key of llmUsageKeys) {
1021
+ const llmUsage = response.llmOutput[key];
1022
+ if (!isNonEmptyUsage(llmUsage)) {
1023
+ continue;
954
1024
  }
1025
+ return this._parseUsageModel(llmUsage, provider, model, key !== 'usage', llmUsage);
955
1026
  }
956
1027
  }
957
- return llmUsage;
1028
+ if (isNonEmptyUsage(normalizedGenerationUsage)) {
1029
+ return this._parseUsageModel(normalizedGenerationUsage, provider, model, true, rawGenerationUsage);
1030
+ }
1031
+ if (isNonEmptyUsage(rawGenerationUsage)) {
1032
+ return this._parseUsageModel(rawGenerationUsage, provider, model, false, rawGenerationUsage);
1033
+ }
1034
+ if (isNonEmptyUsage(fallbackGenerationUsage)) {
1035
+ return this._parseUsageModel(fallbackGenerationUsage, provider, model);
1036
+ }
1037
+ return [0, 0, {}];
958
1038
  }
959
1039
  }
960
1040