@posthog/ai 7.4.1 → 7.4.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.
@@ -2,7 +2,7 @@ import { v4 } from 'uuid';
2
2
  import { Buffer } from 'buffer';
3
3
  import { uuidv7 } from '@posthog/core';
4
4
 
5
- var version = "7.4.1";
5
+ var version = "7.4.3";
6
6
 
7
7
  // Type guards for safer type checking
8
8
 
@@ -714,242 +714,252 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
714
714
  }
715
715
  };
716
716
 
717
- // Create wrapped model that preserves the original type
718
- const wrappedModel = {
719
- ...model,
720
- doGenerate: async params => {
721
- const startTime = Date.now();
722
- const mergedParams = {
723
- ...mergedOptions,
724
- ...mapVercelParams(params)
725
- };
726
- const availableTools = extractAvailableToolCalls('vercel', params);
727
- try {
728
- const result = await model.doGenerate(params);
729
- const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
730
- const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
731
- const baseURL = ''; // cannot currently get baseURL from vercel
732
- const content = mapVercelOutput(result.content);
733
- const latency = (Date.now() - startTime) / 1000;
734
- const providerMetadata = result.providerMetadata;
735
- const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
736
- const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
737
-
738
- // V2 usage has simple numbers, V3 has objects with .total - normalize both
739
- const usageObj = result.usage;
740
- const usage = {
741
- inputTokens: extractTokenCount(result.usage.inputTokens),
742
- outputTokens: extractTokenCount(result.usage.outputTokens),
743
- reasoningTokens: extractReasoningTokens(usageObj),
744
- cacheReadInputTokens: extractCacheReadTokens(usageObj),
745
- webSearchCount,
746
- ...additionalTokenValues
717
+ // Create wrapped model using Object.create to preserve the prototype chain
718
+ // This automatically inherits all properties (including getters) from the model
719
+ const wrappedModel = Object.create(model, {
720
+ doGenerate: {
721
+ value: async params => {
722
+ const startTime = Date.now();
723
+ const mergedParams = {
724
+ ...mergedOptions,
725
+ ...mapVercelParams(params)
747
726
  };
748
- adjustAnthropicV3CacheTokens(model, provider, usage);
749
- await sendEventToPosthog({
750
- client: phClient,
751
- distinctId: mergedOptions.posthogDistinctId,
752
- traceId: mergedOptions.posthogTraceId ?? v4(),
753
- model: modelId,
754
- provider: provider,
755
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
756
- output: content,
757
- latency,
758
- baseURL,
759
- params: mergedParams,
760
- httpStatus: 200,
761
- usage,
762
- tools: availableTools,
763
- captureImmediate: mergedOptions.posthogCaptureImmediate
764
- });
765
- return result;
766
- } catch (error) {
767
- const modelId = model.modelId;
768
- const enrichedError = await sendEventWithErrorToPosthog({
769
- client: phClient,
770
- distinctId: mergedOptions.posthogDistinctId,
771
- traceId: mergedOptions.posthogTraceId ?? v4(),
772
- model: modelId,
773
- provider: model.provider,
774
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
775
- output: [],
776
- latency: 0,
777
- baseURL: '',
778
- params: mergedParams,
779
- usage: {
780
- inputTokens: 0,
781
- outputTokens: 0
782
- },
783
- error: error,
784
- tools: availableTools,
785
- captureImmediate: mergedOptions.posthogCaptureImmediate
786
- });
787
- throw enrichedError;
788
- }
727
+ const availableTools = extractAvailableToolCalls('vercel', params);
728
+ try {
729
+ const result = await model.doGenerate(params);
730
+ const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
731
+ const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
732
+ const baseURL = ''; // cannot currently get baseURL from vercel
733
+ const content = mapVercelOutput(result.content);
734
+ const latency = (Date.now() - startTime) / 1000;
735
+ const providerMetadata = result.providerMetadata;
736
+ const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
737
+ const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
738
+
739
+ // V2 usage has simple numbers, V3 has objects with .total - normalize both
740
+ const usageObj = result.usage;
741
+ const usage = {
742
+ inputTokens: extractTokenCount(result.usage.inputTokens),
743
+ outputTokens: extractTokenCount(result.usage.outputTokens),
744
+ reasoningTokens: extractReasoningTokens(usageObj),
745
+ cacheReadInputTokens: extractCacheReadTokens(usageObj),
746
+ webSearchCount,
747
+ ...additionalTokenValues
748
+ };
749
+ adjustAnthropicV3CacheTokens(model, provider, usage);
750
+ await sendEventToPosthog({
751
+ client: phClient,
752
+ distinctId: mergedOptions.posthogDistinctId,
753
+ traceId: mergedOptions.posthogTraceId ?? v4(),
754
+ model: modelId,
755
+ provider: provider,
756
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
757
+ output: content,
758
+ latency,
759
+ baseURL,
760
+ params: mergedParams,
761
+ httpStatus: 200,
762
+ usage,
763
+ tools: availableTools,
764
+ captureImmediate: mergedOptions.posthogCaptureImmediate
765
+ });
766
+ return result;
767
+ } catch (error) {
768
+ const modelId = model.modelId;
769
+ const enrichedError = await sendEventWithErrorToPosthog({
770
+ client: phClient,
771
+ distinctId: mergedOptions.posthogDistinctId,
772
+ traceId: mergedOptions.posthogTraceId ?? v4(),
773
+ model: modelId,
774
+ provider: model.provider,
775
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
776
+ output: [],
777
+ latency: 0,
778
+ baseURL: '',
779
+ params: mergedParams,
780
+ usage: {
781
+ inputTokens: 0,
782
+ outputTokens: 0
783
+ },
784
+ error: error,
785
+ tools: availableTools,
786
+ captureImmediate: mergedOptions.posthogCaptureImmediate
787
+ });
788
+ throw enrichedError;
789
+ }
790
+ },
791
+ writable: true,
792
+ configurable: true,
793
+ enumerable: false
789
794
  },
790
- doStream: async params => {
791
- const startTime = Date.now();
792
- let generatedText = '';
793
- let reasoningText = '';
794
- let usage = {};
795
- let providerMetadata = undefined;
796
- const mergedParams = {
797
- ...mergedOptions,
798
- ...mapVercelParams(params)
799
- };
800
- const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
801
- const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
802
- const availableTools = extractAvailableToolCalls('vercel', params);
803
- const baseURL = ''; // cannot currently get baseURL from vercel
804
-
805
- // Map to track in-progress tool calls
806
- const toolCallsInProgress = new Map();
807
- try {
808
- const {
809
- stream,
810
- ...rest
811
- } = await model.doStream(params);
812
- const transformStream = new TransformStream({
813
- transform(chunk, controller) {
814
- // Handle streaming patterns - compatible with both V2 and V3
815
- if (chunk.type === 'text-delta') {
816
- generatedText += chunk.delta;
817
- }
818
- if (chunk.type === 'reasoning-delta') {
819
- reasoningText += chunk.delta;
820
- }
795
+ doStream: {
796
+ value: async params => {
797
+ const startTime = Date.now();
798
+ let generatedText = '';
799
+ let reasoningText = '';
800
+ let usage = {};
801
+ let providerMetadata = undefined;
802
+ const mergedParams = {
803
+ ...mergedOptions,
804
+ ...mapVercelParams(params)
805
+ };
806
+ const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
807
+ const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
808
+ const availableTools = extractAvailableToolCalls('vercel', params);
809
+ const baseURL = ''; // cannot currently get baseURL from vercel
821
810
 
822
- // Handle tool call chunks
823
- if (chunk.type === 'tool-input-start') {
824
- // Initialize a new tool call
825
- toolCallsInProgress.set(chunk.id, {
826
- toolCallId: chunk.id,
827
- toolName: chunk.toolName,
828
- input: ''
829
- });
830
- }
831
- if (chunk.type === 'tool-input-delta') {
832
- // Accumulate tool call arguments
833
- const toolCall = toolCallsInProgress.get(chunk.id);
834
- if (toolCall) {
835
- toolCall.input += chunk.delta;
811
+ // Map to track in-progress tool calls
812
+ const toolCallsInProgress = new Map();
813
+ try {
814
+ const {
815
+ stream,
816
+ ...rest
817
+ } = await model.doStream(params);
818
+ const transformStream = new TransformStream({
819
+ transform(chunk, controller) {
820
+ // Handle streaming patterns - compatible with both V2 and V3
821
+ if (chunk.type === 'text-delta') {
822
+ generatedText += chunk.delta;
823
+ }
824
+ if (chunk.type === 'reasoning-delta') {
825
+ reasoningText += chunk.delta;
836
826
  }
837
- }
838
- if (chunk.type === 'tool-input-end') {
839
- // Tool call is complete, keep it in the map for final processing
840
- }
841
- if (chunk.type === 'tool-call') {
842
- // Direct tool call chunk (complete tool call)
843
- toolCallsInProgress.set(chunk.toolCallId, {
844
- toolCallId: chunk.toolCallId,
845
- toolName: chunk.toolName,
846
- input: chunk.input
847
- });
848
- }
849
- if (chunk.type === 'finish') {
850
- providerMetadata = chunk.providerMetadata;
851
- const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
852
- const chunkUsage = chunk.usage || {};
853
- usage = {
854
- inputTokens: extractTokenCount(chunk.usage?.inputTokens),
855
- outputTokens: extractTokenCount(chunk.usage?.outputTokens),
856
- reasoningTokens: extractReasoningTokens(chunkUsage),
857
- cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
858
- ...additionalTokenValues
859
- };
860
- }
861
- controller.enqueue(chunk);
862
- },
863
- flush: async () => {
864
- const latency = (Date.now() - startTime) / 1000;
865
- // Build content array similar to mapVercelOutput structure
866
- const content = [];
867
- if (reasoningText) {
868
- content.push({
869
- type: 'reasoning',
870
- text: truncate(reasoningText)
871
- });
872
- }
873
- if (generatedText) {
874
- content.push({
875
- type: 'text',
876
- text: truncate(generatedText)
877
- });
878
- }
879
827
 
880
- // Add completed tool calls to content
881
- for (const toolCall of toolCallsInProgress.values()) {
882
- if (toolCall.toolName) {
828
+ // Handle tool call chunks
829
+ if (chunk.type === 'tool-input-start') {
830
+ // Initialize a new tool call
831
+ toolCallsInProgress.set(chunk.id, {
832
+ toolCallId: chunk.id,
833
+ toolName: chunk.toolName,
834
+ input: ''
835
+ });
836
+ }
837
+ if (chunk.type === 'tool-input-delta') {
838
+ // Accumulate tool call arguments
839
+ const toolCall = toolCallsInProgress.get(chunk.id);
840
+ if (toolCall) {
841
+ toolCall.input += chunk.delta;
842
+ }
843
+ }
844
+ if (chunk.type === 'tool-input-end') {
845
+ // Tool call is complete, keep it in the map for final processing
846
+ }
847
+ if (chunk.type === 'tool-call') {
848
+ // Direct tool call chunk (complete tool call)
849
+ toolCallsInProgress.set(chunk.toolCallId, {
850
+ toolCallId: chunk.toolCallId,
851
+ toolName: chunk.toolName,
852
+ input: chunk.input
853
+ });
854
+ }
855
+ if (chunk.type === 'finish') {
856
+ providerMetadata = chunk.providerMetadata;
857
+ const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
858
+ const chunkUsage = chunk.usage || {};
859
+ usage = {
860
+ inputTokens: extractTokenCount(chunk.usage?.inputTokens),
861
+ outputTokens: extractTokenCount(chunk.usage?.outputTokens),
862
+ reasoningTokens: extractReasoningTokens(chunkUsage),
863
+ cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
864
+ ...additionalTokenValues
865
+ };
866
+ }
867
+ controller.enqueue(chunk);
868
+ },
869
+ flush: async () => {
870
+ const latency = (Date.now() - startTime) / 1000;
871
+ // Build content array similar to mapVercelOutput structure
872
+ const content = [];
873
+ if (reasoningText) {
883
874
  content.push({
884
- type: 'tool-call',
885
- id: toolCall.toolCallId,
886
- function: {
887
- name: toolCall.toolName,
888
- arguments: toolCall.input
889
- }
875
+ type: 'reasoning',
876
+ text: truncate(reasoningText)
877
+ });
878
+ }
879
+ if (generatedText) {
880
+ content.push({
881
+ type: 'text',
882
+ text: truncate(generatedText)
890
883
  });
891
884
  }
892
- }
893
885
 
894
- // Structure output like mapVercelOutput does
895
- const output = content.length > 0 ? [{
896
- role: 'assistant',
897
- content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
898
- }] : [];
899
- const webSearchCount = extractWebSearchCount(providerMetadata, usage);
900
-
901
- // Update usage with web search count
902
- const finalUsage = {
903
- ...usage,
904
- webSearchCount
905
- };
906
- adjustAnthropicV3CacheTokens(model, provider, finalUsage);
907
- await sendEventToPosthog({
908
- client: phClient,
909
- distinctId: mergedOptions.posthogDistinctId,
910
- traceId: mergedOptions.posthogTraceId ?? v4(),
911
- model: modelId,
912
- provider: provider,
913
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
914
- output: output,
915
- latency,
916
- baseURL,
917
- params: mergedParams,
918
- httpStatus: 200,
919
- usage: finalUsage,
920
- tools: availableTools,
921
- captureImmediate: mergedOptions.posthogCaptureImmediate
922
- });
923
- }
924
- });
925
- return {
926
- stream: stream.pipeThrough(transformStream),
927
- ...rest
928
- };
929
- } catch (error) {
930
- const enrichedError = await sendEventWithErrorToPosthog({
931
- client: phClient,
932
- distinctId: mergedOptions.posthogDistinctId,
933
- traceId: mergedOptions.posthogTraceId ?? v4(),
934
- model: modelId,
935
- provider: provider,
936
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
937
- output: [],
938
- latency: 0,
939
- baseURL: '',
940
- params: mergedParams,
941
- usage: {
942
- inputTokens: 0,
943
- outputTokens: 0
944
- },
945
- error: error,
946
- tools: availableTools,
947
- captureImmediate: mergedOptions.posthogCaptureImmediate
948
- });
949
- throw enrichedError;
950
- }
886
+ // Add completed tool calls to content
887
+ for (const toolCall of toolCallsInProgress.values()) {
888
+ if (toolCall.toolName) {
889
+ content.push({
890
+ type: 'tool-call',
891
+ id: toolCall.toolCallId,
892
+ function: {
893
+ name: toolCall.toolName,
894
+ arguments: toolCall.input
895
+ }
896
+ });
897
+ }
898
+ }
899
+
900
+ // Structure output like mapVercelOutput does
901
+ const output = content.length > 0 ? [{
902
+ role: 'assistant',
903
+ content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
904
+ }] : [];
905
+ const webSearchCount = extractWebSearchCount(providerMetadata, usage);
906
+
907
+ // Update usage with web search count
908
+ const finalUsage = {
909
+ ...usage,
910
+ webSearchCount
911
+ };
912
+ adjustAnthropicV3CacheTokens(model, provider, finalUsage);
913
+ await sendEventToPosthog({
914
+ client: phClient,
915
+ distinctId: mergedOptions.posthogDistinctId,
916
+ traceId: mergedOptions.posthogTraceId ?? v4(),
917
+ model: modelId,
918
+ provider: provider,
919
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
920
+ output: output,
921
+ latency,
922
+ baseURL,
923
+ params: mergedParams,
924
+ httpStatus: 200,
925
+ usage: finalUsage,
926
+ tools: availableTools,
927
+ captureImmediate: mergedOptions.posthogCaptureImmediate
928
+ });
929
+ }
930
+ });
931
+ return {
932
+ stream: stream.pipeThrough(transformStream),
933
+ ...rest
934
+ };
935
+ } catch (error) {
936
+ const enrichedError = await sendEventWithErrorToPosthog({
937
+ client: phClient,
938
+ distinctId: mergedOptions.posthogDistinctId,
939
+ traceId: mergedOptions.posthogTraceId ?? v4(),
940
+ model: modelId,
941
+ provider: provider,
942
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
943
+ output: [],
944
+ latency: 0,
945
+ baseURL: '',
946
+ params: mergedParams,
947
+ usage: {
948
+ inputTokens: 0,
949
+ outputTokens: 0
950
+ },
951
+ error: error,
952
+ tools: availableTools,
953
+ captureImmediate: mergedOptions.posthogCaptureImmediate
954
+ });
955
+ throw enrichedError;
956
+ }
957
+ },
958
+ writable: true,
959
+ configurable: true,
960
+ enumerable: false
951
961
  }
952
- };
962
+ });
953
963
  return wrappedModel;
954
964
  };
955
965