@posthog/ai 7.16.14 → 7.17.0

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.
package/dist/index.mjs CHANGED
@@ -5,8 +5,6 @@ import { uuidv7 } from '@posthog/core';
5
5
  import AnthropicOriginal from '@anthropic-ai/sdk';
6
6
  import { GoogleGenAI } from '@google/genai';
7
7
 
8
- var version = "7.16.14";
9
-
10
8
  // Type guards for safer type checking
11
9
  const isString = value => {
12
10
  return typeof value === 'string';
@@ -710,73 +708,107 @@ function addDefaults(params) {
710
708
  traceId: params.traceId ?? v4()
711
709
  };
712
710
  }
713
- const sendEventWithErrorToPosthog = async ({
714
- client,
715
- traceId,
716
- error,
717
- ...args
718
- }) => {
719
- const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
720
- const properties = {
721
- client,
722
- traceId,
723
- httpStatus,
724
- error: JSON.stringify(error),
725
- ...args
726
- };
727
- const enrichedError = error;
728
- if (client.options?.enableExceptionAutocapture) {
729
- // assign a uuid that can be used to link the trace and exception events
730
- const exceptionId = uuidv7();
731
- client.captureException(error, undefined, {
732
- $ai_trace_id: traceId
733
- }, exceptionId);
734
- enrichedError.__posthog_previously_captured_error = true;
735
- properties.exceptionId = exceptionId;
736
- }
737
- await sendEventToPosthog(properties);
738
- return enrichedError;
739
- };
740
- const sendEventToPosthog = async ({
741
- client,
742
- eventType = AIEvent.Generation,
743
- distinctId,
744
- traceId,
745
- model,
746
- provider,
747
- input,
748
- output,
749
- latency,
750
- timeToFirstToken,
751
- baseURL,
752
- params,
753
- httpStatus = 200,
754
- usage = {},
755
- error,
756
- exceptionId,
757
- stopReason,
758
- tools,
759
- captureImmediate = false
760
- }) => {
761
- if (!client.capture) {
762
- return Promise.resolve();
711
+ function formatOpenAIResponsesInput(input, instructions) {
712
+ const messages = [];
713
+ if (instructions) {
714
+ messages.push({
715
+ role: 'system',
716
+ content: instructions
717
+ });
763
718
  }
764
- // sanitize input and output for UTF-8 validity
765
- const safeInput = sanitizeValues(input);
766
- const safeOutput = sanitizeValues(output);
767
- const safeError = sanitizeValues(error);
719
+ if (Array.isArray(input)) {
720
+ for (const item of input) {
721
+ if (typeof item === 'string') {
722
+ messages.push({
723
+ role: 'user',
724
+ content: item
725
+ });
726
+ } else if (item && typeof item === 'object') {
727
+ const obj = item;
728
+ const role = isString(obj.role) ? obj.role : 'user';
729
+ // Handle content properly - preserve structure for objects/arrays
730
+ const content = obj.content ?? obj.text ?? item;
731
+ messages.push({
732
+ role,
733
+ content: toContentString(content)
734
+ });
735
+ } else {
736
+ messages.push({
737
+ role: 'user',
738
+ content: toContentString(item)
739
+ });
740
+ }
741
+ }
742
+ } else if (typeof input === 'string') {
743
+ messages.push({
744
+ role: 'user',
745
+ content: input
746
+ });
747
+ } else if (input) {
748
+ messages.push({
749
+ role: 'user',
750
+ content: toContentString(input)
751
+ });
752
+ }
753
+ return messages;
754
+ }
755
+
756
+ var version = "7.17.0";
757
+
758
+ /**
759
+ * Capture an `$ai_generation` (or `$ai_embedding`) event to PostHog.
760
+ *
761
+ * This is the canonical primitive that every `@posthog/ai` wrapper
762
+ * (`withTracing`, `OpenAI`, `Anthropic`, `GoogleGenAI`, …) funnels through, so
763
+ * external code can use it directly to instrument LLM calls made through
764
+ * arbitrary clients (Cloudflare Workers AI, custom HTTP, etc.) and get the
765
+ * same events the SDK wrappers produce.
766
+ *
767
+ * When `error` is set, the event is captured as an error. If the error is an
768
+ * object, it is mutated in place to set `__posthog_previously_captured_error`
769
+ * so callers can re-throw the original error reference safely.
770
+ */
771
+ const captureAiGeneration = async (client, options) => {
772
+ if (!client.capture) {
773
+ return;
774
+ }
775
+ const traceId = options.traceId ?? v4();
776
+ const eventType = options.eventType ?? AIEvent.Generation;
777
+ const privacyMode = options.privacyMode ?? false;
778
+ const usage = options.usage ?? {};
779
+ const safeInput = sanitizeValues(options.input);
780
+ const safeOutput = sanitizeValues(options.output);
781
+ let httpStatus = options.httpStatus;
768
782
  let errorData = {};
769
- if (error) {
783
+ if (options.error) {
784
+ if (httpStatus === undefined) {
785
+ if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
786
+ httpStatus = options.error.status;
787
+ } else {
788
+ httpStatus = 500;
789
+ }
790
+ }
791
+ let exceptionId;
792
+ if (client.options?.enableExceptionAutocapture) {
793
+ exceptionId = uuidv7();
794
+ client.captureException(options.error, undefined, {
795
+ $ai_trace_id: traceId
796
+ }, exceptionId);
797
+ if (typeof options.error === 'object') {
798
+ options.error.__posthog_previously_captured_error = true;
799
+ }
800
+ }
770
801
  errorData = {
771
802
  $ai_is_error: true,
772
- $ai_error: safeError,
803
+ $ai_error: sanitizeValues(JSON.stringify(options.error)),
773
804
  $exception_event_id: exceptionId
774
805
  };
775
806
  }
807
+ httpStatus = httpStatus ?? 200;
776
808
  let costOverrideData = {};
777
- if (params.posthogCostOverride) {
778
- const inputCostUSD = (params.posthogCostOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
779
- const outputCostUSD = (params.posthogCostOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
809
+ if (options.costOverride) {
810
+ const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
811
+ const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
780
812
  costOverrideData = {
781
813
  $ai_input_cost_usd: inputCostUSD,
782
814
  $ai_output_cost_usd: outputCostUSD,
@@ -803,95 +835,49 @@ const sendEventToPosthog = async ({
803
835
  const properties = {
804
836
  $ai_lib: 'posthog-ai',
805
837
  $ai_lib_version: version,
806
- $ai_provider: params.posthogProviderOverride ?? provider,
807
- $ai_model: params.posthogModelOverride ?? model,
808
- $ai_model_parameters: getModelParams(params),
809
- $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeInput),
810
- $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeOutput),
838
+ $ai_provider: options.providerOverride ?? options.provider,
839
+ $ai_model: options.modelOverride ?? options.model,
840
+ $ai_model_parameters: options.modelParameters ?? {},
841
+ $ai_input: withPrivacyMode(client, privacyMode, safeInput),
842
+ $ai_output_choices: withPrivacyMode(client, privacyMode, safeOutput),
811
843
  $ai_http_status: httpStatus,
812
844
  $ai_input_tokens: usage.inputTokens ?? 0,
813
845
  ...(usage.outputTokens !== undefined ? {
814
846
  $ai_output_tokens: usage.outputTokens
815
847
  } : {}),
816
848
  ...additionalTokenValues,
817
- $ai_latency: latency,
818
- ...(timeToFirstToken !== undefined ? {
819
- $ai_time_to_first_token: timeToFirstToken
849
+ $ai_latency: options.latency ?? 0,
850
+ ...(options.timeToFirstToken !== undefined ? {
851
+ $ai_time_to_first_token: options.timeToFirstToken
820
852
  } : {}),
821
853
  $ai_trace_id: traceId,
822
- $ai_base_url: baseURL,
823
- ...params.posthogProperties,
824
- $ai_tokens_source: getTokensSource(params.posthogProperties),
825
- ...(distinctId ? {} : {
854
+ $ai_base_url: options.baseURL ?? '',
855
+ ...options.properties,
856
+ $ai_tokens_source: getTokensSource(options.properties),
857
+ ...(options.distinctId ? {} : {
826
858
  $process_person_profile: false
827
859
  }),
828
- ...(stopReason ? {
829
- $ai_stop_reason: stopReason
860
+ ...(options.stopReason ? {
861
+ $ai_stop_reason: options.stopReason
830
862
  } : {}),
831
- ...(tools ? {
832
- $ai_tools: tools
863
+ ...(options.tools ? {
864
+ $ai_tools: options.tools
833
865
  } : {}),
834
866
  ...errorData,
835
867
  ...costOverrideData
836
868
  };
837
869
  const event = {
838
- distinctId: distinctId ?? traceId,
870
+ distinctId: options.distinctId ?? traceId,
839
871
  event: eventType,
840
872
  properties,
841
- groups: params.posthogGroups
873
+ groups: options.groups
842
874
  };
843
- if (captureImmediate) {
844
- // await capture promise to send single event in serverless environments
875
+ if (options.captureImmediate) {
845
876
  await client.captureImmediate(event);
846
877
  } else {
847
878
  client.capture(event);
848
879
  }
849
- return Promise.resolve();
850
880
  };
851
- function formatOpenAIResponsesInput(input, instructions) {
852
- const messages = [];
853
- if (instructions) {
854
- messages.push({
855
- role: 'system',
856
- content: instructions
857
- });
858
- }
859
- if (Array.isArray(input)) {
860
- for (const item of input) {
861
- if (typeof item === 'string') {
862
- messages.push({
863
- role: 'user',
864
- content: item
865
- });
866
- } else if (item && typeof item === 'object') {
867
- const obj = item;
868
- const role = isString(obj.role) ? obj.role : 'user';
869
- // Handle content properly - preserve structure for objects/arrays
870
- const content = obj.content ?? obj.text ?? item;
871
- messages.push({
872
- role,
873
- content: toContentString(content)
874
- });
875
- } else {
876
- messages.push({
877
- role: 'user',
878
- content: toContentString(item)
879
- });
880
- }
881
- }
882
- } else if (typeof input === 'string') {
883
- messages.push({
884
- role: 'user',
885
- content: input
886
- });
887
- } else if (input) {
888
- messages.push({
889
- role: 'user',
890
- content: toContentString(input)
891
- });
892
- }
893
- return messages;
894
- }
895
881
 
896
882
  /**
897
883
  * Checks if a ResponseStreamEvent chunk represents the first token/content from the model.
@@ -1060,8 +1046,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1060
1046
  const latency = (Date.now() - startTime) / 1000;
1061
1047
  const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
1062
1048
  const availableTools = extractAvailableToolCalls('openai', openAIParams);
1063
- await sendEventToPosthog({
1064
- client: this.phClient,
1049
+ await captureAiGeneration(this.phClient, {
1065
1050
  ...posthogParams,
1066
1051
  model: openAIParams.model ?? modelFromResponse,
1067
1052
  provider: 'openai',
@@ -1070,7 +1055,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1070
1055
  latency,
1071
1056
  timeToFirstToken,
1072
1057
  baseURL: this.baseURL,
1073
- params: body,
1058
+ modelParameters: getModelParams(body),
1074
1059
  httpStatus: 200,
1075
1060
  usage: {
1076
1061
  inputTokens: usage.inputTokens,
@@ -1084,8 +1069,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1084
1069
  tools: availableTools
1085
1070
  });
1086
1071
  } catch (error) {
1087
- const enrichedError = await sendEventWithErrorToPosthog({
1088
- client: this.phClient,
1072
+ await captureAiGeneration(this.phClient, {
1089
1073
  ...posthogParams,
1090
1074
  model: openAIParams.model,
1091
1075
  provider: 'openai',
@@ -1093,14 +1077,14 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1093
1077
  output: [],
1094
1078
  latency: 0,
1095
1079
  baseURL: this.baseURL,
1096
- params: body,
1080
+ modelParameters: getModelParams(body),
1097
1081
  usage: {
1098
1082
  inputTokens: 0,
1099
1083
  outputTokens: 0
1100
1084
  },
1101
1085
  error
1102
1086
  });
1103
- throw enrichedError;
1087
+ throw error;
1104
1088
  }
1105
1089
  })();
1106
1090
  // Return the other stream to the user
@@ -1114,8 +1098,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1114
1098
  const latency = (Date.now() - startTime) / 1000;
1115
1099
  const availableTools = extractAvailableToolCalls('openai', openAIParams);
1116
1100
  const formattedOutput = formatResponseOpenAI(result);
1117
- await sendEventToPosthog({
1118
- client: this.phClient,
1101
+ await captureAiGeneration(this.phClient, {
1119
1102
  ...posthogParams,
1120
1103
  model: openAIParams.model ?? result.model,
1121
1104
  provider: 'openai',
@@ -1123,7 +1106,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1123
1106
  output: formattedOutput,
1124
1107
  latency,
1125
1108
  baseURL: this.baseURL,
1126
- params: body,
1109
+ modelParameters: getModelParams(body),
1127
1110
  httpStatus: 200,
1128
1111
  usage: {
1129
1112
  inputTokens: result.usage?.prompt_tokens ?? 0,
@@ -1140,8 +1123,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1140
1123
  return result;
1141
1124
  }, async error => {
1142
1125
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
1143
- await sendEventToPosthog({
1144
- client: this.phClient,
1126
+ await captureAiGeneration(this.phClient, {
1145
1127
  ...posthogParams,
1146
1128
  model: openAIParams.model,
1147
1129
  provider: 'openai',
@@ -1149,13 +1131,13 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
1149
1131
  output: [],
1150
1132
  latency: 0,
1151
1133
  baseURL: this.baseURL,
1152
- params: body,
1134
+ modelParameters: getModelParams(body),
1153
1135
  httpStatus,
1154
1136
  usage: {
1155
1137
  inputTokens: 0,
1156
1138
  outputTokens: 0
1157
1139
  },
1158
- error: JSON.stringify(error)
1140
+ error
1159
1141
  });
1160
1142
  throw error;
1161
1143
  });
@@ -1228,8 +1210,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1228
1210
  const latency = (Date.now() - startTime) / 1000;
1229
1211
  const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
1230
1212
  const availableTools = extractAvailableToolCalls('openai', openAIParams);
1231
- await sendEventToPosthog({
1232
- client: this.phClient,
1213
+ await captureAiGeneration(this.phClient, {
1233
1214
  ...posthogParams,
1234
1215
  model: openAIParams.model ?? modelFromResponse,
1235
1216
  provider: 'openai',
@@ -1238,7 +1219,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1238
1219
  latency,
1239
1220
  timeToFirstToken,
1240
1221
  baseURL: this.baseURL,
1241
- params: body,
1222
+ modelParameters: getModelParams(body),
1242
1223
  httpStatus: 200,
1243
1224
  usage: {
1244
1225
  inputTokens: usage.inputTokens,
@@ -1252,8 +1233,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1252
1233
  tools: availableTools
1253
1234
  });
1254
1235
  } catch (error) {
1255
- const enrichedError = await sendEventWithErrorToPosthog({
1256
- client: this.phClient,
1236
+ await captureAiGeneration(this.phClient, {
1257
1237
  ...posthogParams,
1258
1238
  model: openAIParams.model,
1259
1239
  provider: 'openai',
@@ -1261,14 +1241,14 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1261
1241
  output: [],
1262
1242
  latency: 0,
1263
1243
  baseURL: this.baseURL,
1264
- params: body,
1244
+ modelParameters: getModelParams(body),
1265
1245
  usage: {
1266
1246
  inputTokens: 0,
1267
1247
  outputTokens: 0
1268
1248
  },
1269
- error: error
1249
+ error
1270
1250
  });
1271
- throw enrichedError;
1251
+ throw error;
1272
1252
  }
1273
1253
  })();
1274
1254
  return stream2;
@@ -1283,8 +1263,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1283
1263
  const formattedOutput = formatResponseOpenAI({
1284
1264
  output: result.output
1285
1265
  });
1286
- await sendEventToPosthog({
1287
- client: this.phClient,
1266
+ await captureAiGeneration(this.phClient, {
1288
1267
  ...posthogParams,
1289
1268
  model: openAIParams.model ?? result.model,
1290
1269
  provider: 'openai',
@@ -1292,7 +1271,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1292
1271
  output: formattedOutput,
1293
1272
  latency,
1294
1273
  baseURL: this.baseURL,
1295
- params: body,
1274
+ modelParameters: getModelParams(body),
1296
1275
  httpStatus: 200,
1297
1276
  usage: {
1298
1277
  inputTokens: result.usage?.input_tokens ?? 0,
@@ -1309,8 +1288,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1309
1288
  return result;
1310
1289
  }, async error => {
1311
1290
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
1312
- await sendEventToPosthog({
1313
- client: this.phClient,
1291
+ await captureAiGeneration(this.phClient, {
1314
1292
  ...posthogParams,
1315
1293
  model: openAIParams.model,
1316
1294
  provider: 'openai',
@@ -1318,13 +1296,13 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1318
1296
  output: [],
1319
1297
  latency: 0,
1320
1298
  baseURL: this.baseURL,
1321
- params: body,
1299
+ modelParameters: getModelParams(body),
1322
1300
  httpStatus,
1323
1301
  usage: {
1324
1302
  inputTokens: 0,
1325
1303
  outputTokens: 0
1326
1304
  },
1327
- error: JSON.stringify(error)
1305
+ error
1328
1306
  });
1329
1307
  throw error;
1330
1308
  });
@@ -1345,8 +1323,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1345
1323
  const parentPromise = super.parse(openAIParams, options);
1346
1324
  const wrappedPromise = parentPromise.then(async result => {
1347
1325
  const latency = (Date.now() - startTime) / 1000;
1348
- await sendEventToPosthog({
1349
- client: this.phClient,
1326
+ await captureAiGeneration(this.phClient, {
1350
1327
  ...posthogParams,
1351
1328
  model: openAIParams.model ?? result.model,
1352
1329
  provider: 'openai',
@@ -1354,7 +1331,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1354
1331
  output: result.output,
1355
1332
  latency,
1356
1333
  baseURL: this.baseURL,
1357
- params: body,
1334
+ modelParameters: getModelParams(body),
1358
1335
  httpStatus: 200,
1359
1336
  usage: {
1360
1337
  inputTokens: result.usage?.input_tokens ?? 0,
@@ -1367,8 +1344,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1367
1344
  });
1368
1345
  return result;
1369
1346
  }, async error => {
1370
- const enrichedError = await sendEventWithErrorToPosthog({
1371
- client: this.phClient,
1347
+ await captureAiGeneration(this.phClient, {
1372
1348
  ...posthogParams,
1373
1349
  model: openAIParams.model,
1374
1350
  provider: 'openai',
@@ -1376,14 +1352,14 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1376
1352
  output: [],
1377
1353
  latency: 0,
1378
1354
  baseURL: this.baseURL,
1379
- params: body,
1355
+ modelParameters: getModelParams(body),
1380
1356
  usage: {
1381
1357
  inputTokens: 0,
1382
1358
  outputTokens: 0
1383
1359
  },
1384
- error: JSON.stringify(error)
1360
+ error
1385
1361
  });
1386
- throw enrichedError;
1362
+ throw error;
1387
1363
  });
1388
1364
  return wrappedPromise;
1389
1365
  } finally {
@@ -1407,8 +1383,7 @@ let WrappedEmbeddings$1 = class WrappedEmbeddings extends Embeddings {
1407
1383
  const parentPromise = super.create(openAIParams, options);
1408
1384
  const wrappedPromise = parentPromise.then(async result => {
1409
1385
  const latency = (Date.now() - startTime) / 1000;
1410
- await sendEventToPosthog({
1411
- client: this.phClient,
1386
+ await captureAiGeneration(this.phClient, {
1412
1387
  ...posthogParams,
1413
1388
  eventType: AIEvent.Embedding,
1414
1389
  model: openAIParams.model,
@@ -1418,7 +1393,7 @@ let WrappedEmbeddings$1 = class WrappedEmbeddings extends Embeddings {
1418
1393
  // Embeddings don't have output content
1419
1394
  latency,
1420
1395
  baseURL: this.baseURL,
1421
- params: body,
1396
+ modelParameters: getModelParams(body),
1422
1397
  httpStatus: 200,
1423
1398
  usage: {
1424
1399
  inputTokens: result.usage?.prompt_tokens ?? 0,
@@ -1428,8 +1403,7 @@ let WrappedEmbeddings$1 = class WrappedEmbeddings extends Embeddings {
1428
1403
  return result;
1429
1404
  }, async error => {
1430
1405
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
1431
- await sendEventToPosthog({
1432
- client: this.phClient,
1406
+ await captureAiGeneration(this.phClient, {
1433
1407
  eventType: AIEvent.Embedding,
1434
1408
  ...posthogParams,
1435
1409
  model: openAIParams.model,
@@ -1439,12 +1413,12 @@ let WrappedEmbeddings$1 = class WrappedEmbeddings extends Embeddings {
1439
1413
  // Embeddings don't have output content
1440
1414
  latency: 0,
1441
1415
  baseURL: this.baseURL,
1442
- params: body,
1416
+ modelParameters: getModelParams(body),
1443
1417
  httpStatus,
1444
1418
  usage: {
1445
1419
  inputTokens: 0
1446
1420
  },
1447
- error: JSON.stringify(error)
1421
+ error
1448
1422
  });
1449
1423
  throw error;
1450
1424
  });
@@ -1503,8 +1477,7 @@ class WrappedTranscriptions extends Transcriptions {
1503
1477
  const latency = (Date.now() - startTime) / 1000;
1504
1478
  const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
1505
1479
  const availableTools = extractAvailableToolCalls('openai', openAIParams);
1506
- await sendEventToPosthog({
1507
- client: this.phClient,
1480
+ await captureAiGeneration(this.phClient, {
1508
1481
  ...posthogParams,
1509
1482
  model: openAIParams.model,
1510
1483
  provider: 'openai',
@@ -1513,14 +1486,13 @@ class WrappedTranscriptions extends Transcriptions {
1513
1486
  latency,
1514
1487
  timeToFirstToken,
1515
1488
  baseURL: this.baseURL,
1516
- params: body,
1489
+ modelParameters: getModelParams(body),
1517
1490
  httpStatus: 200,
1518
1491
  usage,
1519
1492
  tools: availableTools
1520
1493
  });
1521
1494
  } catch (error) {
1522
- const enrichedError = await sendEventWithErrorToPosthog({
1523
- client: this.phClient,
1495
+ await captureAiGeneration(this.phClient, {
1524
1496
  ...posthogParams,
1525
1497
  model: openAIParams.model,
1526
1498
  provider: 'openai',
@@ -1528,14 +1500,14 @@ class WrappedTranscriptions extends Transcriptions {
1528
1500
  output: [],
1529
1501
  latency: 0,
1530
1502
  baseURL: this.baseURL,
1531
- params: body,
1503
+ modelParameters: getModelParams(body),
1532
1504
  usage: {
1533
1505
  inputTokens: 0,
1534
1506
  outputTokens: 0
1535
1507
  },
1536
- error: error
1508
+ error
1537
1509
  });
1538
- throw enrichedError;
1510
+ throw error;
1539
1511
  }
1540
1512
  })();
1541
1513
  return stream2;
@@ -1546,8 +1518,7 @@ class WrappedTranscriptions extends Transcriptions {
1546
1518
  const wrappedPromise = parentPromise.then(async result => {
1547
1519
  if ('text' in result) {
1548
1520
  const latency = (Date.now() - startTime) / 1000;
1549
- await sendEventToPosthog({
1550
- client: this.phClient,
1521
+ await captureAiGeneration(this.phClient, {
1551
1522
  ...posthogParams,
1552
1523
  model: openAIParams.model,
1553
1524
  provider: 'openai',
@@ -1555,7 +1526,7 @@ class WrappedTranscriptions extends Transcriptions {
1555
1526
  output: result.text,
1556
1527
  latency,
1557
1528
  baseURL: this.baseURL,
1558
- params: body,
1529
+ modelParameters: getModelParams(body),
1559
1530
  httpStatus: 200,
1560
1531
  usage: {
1561
1532
  inputTokens: result.usage?.type === 'tokens' ? result.usage.input_tokens ?? 0 : 0,
@@ -1566,8 +1537,7 @@ class WrappedTranscriptions extends Transcriptions {
1566
1537
  return result;
1567
1538
  }
1568
1539
  }, async error => {
1569
- const enrichedError = await sendEventWithErrorToPosthog({
1570
- client: this.phClient,
1540
+ await captureAiGeneration(this.phClient, {
1571
1541
  ...posthogParams,
1572
1542
  model: openAIParams.model,
1573
1543
  provider: 'openai',
@@ -1575,14 +1545,14 @@ class WrappedTranscriptions extends Transcriptions {
1575
1545
  output: [],
1576
1546
  latency: 0,
1577
1547
  baseURL: this.baseURL,
1578
- params: body,
1548
+ modelParameters: getModelParams(body),
1579
1549
  usage: {
1580
1550
  inputTokens: 0,
1581
1551
  outputTokens: 0
1582
1552
  },
1583
- error: error
1553
+ error
1584
1554
  });
1585
- throw enrichedError;
1555
+ throw error;
1586
1556
  });
1587
1557
  return wrappedPromise;
1588
1558
  }
@@ -1727,8 +1697,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1727
1697
  }];
1728
1698
  const latency = (Date.now() - startTime) / 1000;
1729
1699
  const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
1730
- await sendEventToPosthog({
1731
- client: this.phClient,
1700
+ await captureAiGeneration(this.phClient, {
1732
1701
  ...posthogParams,
1733
1702
  model: openAIParams.model ?? modelFromResponse,
1734
1703
  provider: 'azure',
@@ -1737,13 +1706,12 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1737
1706
  latency,
1738
1707
  timeToFirstToken,
1739
1708
  baseURL: this.baseURL,
1740
- params: body,
1709
+ modelParameters: getModelParams(body),
1741
1710
  httpStatus: 200,
1742
1711
  usage
1743
1712
  });
1744
1713
  } catch (error) {
1745
- const enrichedError = await sendEventWithErrorToPosthog({
1746
- client: this.phClient,
1714
+ await captureAiGeneration(this.phClient, {
1747
1715
  ...posthogParams,
1748
1716
  model: openAIParams.model,
1749
1717
  provider: 'azure',
@@ -1751,14 +1719,14 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1751
1719
  output: [],
1752
1720
  latency: 0,
1753
1721
  baseURL: this.baseURL,
1754
- params: body,
1722
+ modelParameters: getModelParams(body),
1755
1723
  usage: {
1756
1724
  inputTokens: 0,
1757
1725
  outputTokens: 0
1758
1726
  },
1759
1727
  error: error
1760
1728
  });
1761
- throw enrichedError;
1729
+ throw error;
1762
1730
  }
1763
1731
  })();
1764
1732
  // Return the other stream to the user
@@ -1770,8 +1738,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1770
1738
  const wrappedPromise = parentPromise.then(async result => {
1771
1739
  if ('choices' in result) {
1772
1740
  const latency = (Date.now() - startTime) / 1000;
1773
- await sendEventToPosthog({
1774
- client: this.phClient,
1741
+ await captureAiGeneration(this.phClient, {
1775
1742
  ...posthogParams,
1776
1743
  model: openAIParams.model ?? result.model,
1777
1744
  provider: 'azure',
@@ -1779,7 +1746,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1779
1746
  output: formatResponseOpenAI(result),
1780
1747
  latency,
1781
1748
  baseURL: this.baseURL,
1782
- params: body,
1749
+ modelParameters: getModelParams(body),
1783
1750
  httpStatus: 200,
1784
1751
  usage: {
1785
1752
  inputTokens: result.usage?.prompt_tokens ?? 0,
@@ -1792,8 +1759,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1792
1759
  return result;
1793
1760
  }, async error => {
1794
1761
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
1795
- await sendEventToPosthog({
1796
- client: this.phClient,
1762
+ await captureAiGeneration(this.phClient, {
1797
1763
  ...posthogParams,
1798
1764
  model: openAIParams.model,
1799
1765
  provider: 'azure',
@@ -1801,13 +1767,13 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1801
1767
  output: [],
1802
1768
  latency: 0,
1803
1769
  baseURL: this.baseURL,
1804
- params: body,
1770
+ modelParameters: getModelParams(body),
1805
1771
  httpStatus,
1806
1772
  usage: {
1807
1773
  inputTokens: 0,
1808
1774
  outputTokens: 0
1809
1775
  },
1810
- error: JSON.stringify(error)
1776
+ error
1811
1777
  });
1812
1778
  throw error;
1813
1779
  });
@@ -1867,8 +1833,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1867
1833
  }
1868
1834
  const latency = (Date.now() - startTime) / 1000;
1869
1835
  const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
1870
- await sendEventToPosthog({
1871
- client: this.phClient,
1836
+ await captureAiGeneration(this.phClient, {
1872
1837
  ...posthogParams,
1873
1838
  model: openAIParams.model ?? modelFromResponse,
1874
1839
  provider: 'azure',
@@ -1877,13 +1842,12 @@ class WrappedResponses extends AzureOpenAI.Responses {
1877
1842
  latency,
1878
1843
  timeToFirstToken,
1879
1844
  baseURL: this.baseURL,
1880
- params: body,
1845
+ modelParameters: getModelParams(body),
1881
1846
  httpStatus: 200,
1882
1847
  usage
1883
1848
  });
1884
1849
  } catch (error) {
1885
- const enrichedError = await sendEventWithErrorToPosthog({
1886
- client: this.phClient,
1850
+ await captureAiGeneration(this.phClient, {
1887
1851
  ...posthogParams,
1888
1852
  model: openAIParams.model,
1889
1853
  provider: 'azure',
@@ -1891,14 +1855,14 @@ class WrappedResponses extends AzureOpenAI.Responses {
1891
1855
  output: [],
1892
1856
  latency: 0,
1893
1857
  baseURL: this.baseURL,
1894
- params: body,
1858
+ modelParameters: getModelParams(body),
1895
1859
  usage: {
1896
1860
  inputTokens: 0,
1897
1861
  outputTokens: 0
1898
1862
  },
1899
1863
  error: error
1900
1864
  });
1901
- throw enrichedError;
1865
+ throw error;
1902
1866
  }
1903
1867
  })();
1904
1868
  return stream2;
@@ -1909,8 +1873,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1909
1873
  const wrappedPromise = parentPromise.then(async result => {
1910
1874
  if ('output' in result) {
1911
1875
  const latency = (Date.now() - startTime) / 1000;
1912
- await sendEventToPosthog({
1913
- client: this.phClient,
1876
+ await captureAiGeneration(this.phClient, {
1914
1877
  ...posthogParams,
1915
1878
  model: openAIParams.model ?? result.model,
1916
1879
  provider: 'azure',
@@ -1918,7 +1881,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1918
1881
  output: result.output,
1919
1882
  latency,
1920
1883
  baseURL: this.baseURL,
1921
- params: body,
1884
+ modelParameters: getModelParams(body),
1922
1885
  httpStatus: 200,
1923
1886
  usage: {
1924
1887
  inputTokens: result.usage?.input_tokens ?? 0,
@@ -1931,8 +1894,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1931
1894
  return result;
1932
1895
  }, async error => {
1933
1896
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
1934
- await sendEventToPosthog({
1935
- client: this.phClient,
1897
+ await captureAiGeneration(this.phClient, {
1936
1898
  ...posthogParams,
1937
1899
  model: openAIParams.model,
1938
1900
  provider: 'azure',
@@ -1940,13 +1902,13 @@ class WrappedResponses extends AzureOpenAI.Responses {
1940
1902
  output: [],
1941
1903
  latency: 0,
1942
1904
  baseURL: this.baseURL,
1943
- params: body,
1905
+ modelParameters: getModelParams(body),
1944
1906
  httpStatus,
1945
1907
  usage: {
1946
1908
  inputTokens: 0,
1947
1909
  outputTokens: 0
1948
1910
  },
1949
- error: JSON.stringify(error)
1911
+ error
1950
1912
  });
1951
1913
  throw error;
1952
1914
  });
@@ -1962,8 +1924,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1962
1924
  const parentPromise = super.parse(openAIParams, options);
1963
1925
  const wrappedPromise = parentPromise.then(async result => {
1964
1926
  const latency = (Date.now() - startTime) / 1000;
1965
- await sendEventToPosthog({
1966
- client: this.phClient,
1927
+ await captureAiGeneration(this.phClient, {
1967
1928
  ...posthogParams,
1968
1929
  model: openAIParams.model ?? result.model,
1969
1930
  provider: 'azure',
@@ -1971,7 +1932,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1971
1932
  output: result.output,
1972
1933
  latency,
1973
1934
  baseURL: this.baseURL,
1974
- params: body,
1935
+ modelParameters: getModelParams(body),
1975
1936
  httpStatus: 200,
1976
1937
  usage: {
1977
1938
  inputTokens: result.usage?.input_tokens ?? 0,
@@ -1982,8 +1943,7 @@ class WrappedResponses extends AzureOpenAI.Responses {
1982
1943
  });
1983
1944
  return result;
1984
1945
  }, async error => {
1985
- await sendEventToPosthog({
1986
- client: this.phClient,
1946
+ await captureAiGeneration(this.phClient, {
1987
1947
  ...posthogParams,
1988
1948
  model: openAIParams.model,
1989
1949
  provider: 'azure',
@@ -1991,13 +1951,13 @@ class WrappedResponses extends AzureOpenAI.Responses {
1991
1951
  output: [],
1992
1952
  latency: 0,
1993
1953
  baseURL: this.baseURL,
1994
- params: body,
1954
+ modelParameters: getModelParams(body),
1995
1955
  httpStatus: error?.status ? error.status : 500,
1996
1956
  usage: {
1997
1957
  inputTokens: 0,
1998
1958
  outputTokens: 0
1999
1959
  },
2000
- error: JSON.stringify(error)
1960
+ error
2001
1961
  });
2002
1962
  throw error;
2003
1963
  });
@@ -2019,8 +1979,7 @@ class WrappedEmbeddings extends AzureOpenAI.Embeddings {
2019
1979
  const parentPromise = super.create(openAIParams, options);
2020
1980
  const wrappedPromise = parentPromise.then(async result => {
2021
1981
  const latency = (Date.now() - startTime) / 1000;
2022
- await sendEventToPosthog({
2023
- client: this.phClient,
1982
+ await captureAiGeneration(this.phClient, {
2024
1983
  eventType: AIEvent.Embedding,
2025
1984
  ...posthogParams,
2026
1985
  model: openAIParams.model,
@@ -2030,7 +1989,7 @@ class WrappedEmbeddings extends AzureOpenAI.Embeddings {
2030
1989
  // Embeddings don't have output content
2031
1990
  latency,
2032
1991
  baseURL: this.baseURL,
2033
- params: body,
1992
+ modelParameters: getModelParams(body),
2034
1993
  httpStatus: 200,
2035
1994
  usage: {
2036
1995
  inputTokens: result.usage?.prompt_tokens ?? 0
@@ -2039,8 +1998,7 @@ class WrappedEmbeddings extends AzureOpenAI.Embeddings {
2039
1998
  return result;
2040
1999
  }, async error => {
2041
2000
  const httpStatus = error && typeof error === 'object' && 'status' in error ? error.status ?? 500 : 500;
2042
- await sendEventToPosthog({
2043
- client: this.phClient,
2001
+ await captureAiGeneration(this.phClient, {
2044
2002
  eventType: AIEvent.Embedding,
2045
2003
  ...posthogParams,
2046
2004
  model: openAIParams.model,
@@ -2049,12 +2007,12 @@ class WrappedEmbeddings extends AzureOpenAI.Embeddings {
2049
2007
  output: null,
2050
2008
  latency: 0,
2051
2009
  baseURL: this.baseURL,
2052
- params: body,
2010
+ modelParameters: getModelParams(body),
2053
2011
  httpStatus,
2054
2012
  usage: {
2055
2013
  inputTokens: 0
2056
2014
  },
2057
- error: JSON.stringify(error)
2015
+ error
2058
2016
  });
2059
2017
  throw error;
2060
2018
  });
@@ -2383,6 +2341,18 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2383
2341
  $ai_framework_version: model.specificationVersion === 'v3' ? '6' : '5'
2384
2342
  }
2385
2343
  };
2344
+ // Shared `captureAiGeneration` options for every call site in this wrapper.
2345
+ const baseOptions = {
2346
+ distinctId: mergedOptions.posthogDistinctId,
2347
+ traceId,
2348
+ properties: mergedOptions.posthogProperties,
2349
+ groups: mergedOptions.posthogGroups,
2350
+ privacyMode: mergedOptions.posthogPrivacyMode,
2351
+ modelOverride: mergedOptions.posthogModelOverride,
2352
+ providerOverride: mergedOptions.posthogProviderOverride,
2353
+ costOverride: mergedOptions.posthogCostOverride,
2354
+ captureImmediate: mergedOptions.posthogCaptureImmediate
2355
+ };
2386
2356
  // Create wrapped model using Object.create to preserve the prototype chain
2387
2357
  // This automatically inherits all properties (including getters) from the model
2388
2358
  const wrappedModel = Object.create(model, {
@@ -2435,46 +2405,40 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2435
2405
  // Extract finish reason - V2 returns a string, V3 returns an object with .unified
2436
2406
  const rawFinishReason = result.finishReason;
2437
2407
  const finishReasonStr = typeof rawFinishReason === 'string' ? rawFinishReason : rawFinishReason && typeof rawFinishReason === 'object' && 'unified' in rawFinishReason ? String(rawFinishReason.unified) : undefined;
2438
- await sendEventToPosthog({
2439
- client: phClient,
2440
- distinctId: mergedOptions.posthogDistinctId,
2441
- traceId: mergedOptions.posthogTraceId ?? v4(),
2408
+ await captureAiGeneration(phClient, {
2409
+ ...baseOptions,
2442
2410
  model: modelId,
2443
2411
  provider: provider,
2444
2412
  input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2445
2413
  output: content,
2446
2414
  latency,
2447
2415
  baseURL,
2448
- params: mergedParams,
2416
+ modelParameters: getModelParams(mergedParams),
2449
2417
  httpStatus: 200,
2450
2418
  usage,
2451
2419
  stopReason: finishReasonStr,
2452
- tools: availableTools,
2453
- captureImmediate: mergedOptions.posthogCaptureImmediate
2420
+ tools: availableTools
2454
2421
  });
2455
2422
  return result;
2456
2423
  } catch (error) {
2457
2424
  const modelId = model.modelId;
2458
- const enrichedError = await sendEventWithErrorToPosthog({
2459
- client: phClient,
2460
- distinctId: mergedOptions.posthogDistinctId,
2461
- traceId: mergedOptions.posthogTraceId ?? v4(),
2425
+ await captureAiGeneration(phClient, {
2426
+ ...baseOptions,
2462
2427
  model: modelId,
2463
2428
  provider: model.provider,
2464
2429
  input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2465
2430
  output: [],
2466
2431
  latency: 0,
2467
2432
  baseURL: '',
2468
- params: mergedParams,
2433
+ modelParameters: getModelParams(mergedParams),
2469
2434
  usage: {
2470
2435
  inputTokens: 0,
2471
2436
  outputTokens: 0
2472
2437
  },
2473
2438
  error: error,
2474
- tools: availableTools,
2475
- captureImmediate: mergedOptions.posthogCaptureImmediate
2439
+ tools: availableTools
2476
2440
  });
2477
- throw enrichedError;
2441
+ throw error;
2478
2442
  }
2479
2443
  },
2480
2444
  writable: true,
@@ -2620,10 +2584,8 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2620
2584
  }
2621
2585
  };
2622
2586
  adjustAnthropicV3CacheTokens(model, modelId, provider, finalUsage);
2623
- await sendEventToPosthog({
2624
- client: phClient,
2625
- distinctId: mergedOptions.posthogDistinctId,
2626
- traceId: mergedOptions.posthogTraceId ?? v4(),
2587
+ await captureAiGeneration(phClient, {
2588
+ ...baseOptions,
2627
2589
  model: modelId,
2628
2590
  provider: provider,
2629
2591
  input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
@@ -2631,12 +2593,11 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2631
2593
  latency,
2632
2594
  timeToFirstToken,
2633
2595
  baseURL,
2634
- params: mergedParams,
2596
+ modelParameters: getModelParams(mergedParams),
2635
2597
  httpStatus: 200,
2636
2598
  usage: finalUsage,
2637
2599
  stopReason,
2638
- tools: availableTools,
2639
- captureImmediate: mergedOptions.posthogCaptureImmediate
2600
+ tools: availableTools
2640
2601
  });
2641
2602
  }
2642
2603
  });
@@ -2645,26 +2606,23 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2645
2606
  ...rest
2646
2607
  };
2647
2608
  } catch (error) {
2648
- const enrichedError = await sendEventWithErrorToPosthog({
2649
- client: phClient,
2650
- distinctId: mergedOptions.posthogDistinctId,
2651
- traceId: mergedOptions.posthogTraceId ?? v4(),
2609
+ await captureAiGeneration(phClient, {
2610
+ ...baseOptions,
2652
2611
  model: modelId,
2653
2612
  provider: provider,
2654
2613
  input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2655
2614
  output: [],
2656
2615
  latency: 0,
2657
2616
  baseURL: '',
2658
- params: mergedParams,
2617
+ modelParameters: getModelParams(mergedParams),
2659
2618
  usage: {
2660
2619
  inputTokens: 0,
2661
2620
  outputTokens: 0
2662
2621
  },
2663
2622
  error: error,
2664
- tools: availableTools,
2665
- captureImmediate: mergedOptions.posthogCaptureImmediate
2623
+ tools: availableTools
2666
2624
  });
2667
- throw enrichedError;
2625
+ throw error;
2668
2626
  }
2669
2627
  },
2670
2628
  writable: true,
@@ -2829,8 +2787,7 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2829
2787
  text: accumulatedContent
2830
2788
  }]
2831
2789
  }];
2832
- await sendEventToPosthog({
2833
- client: this.phClient,
2790
+ await captureAiGeneration(this.phClient, {
2834
2791
  ...posthogParams,
2835
2792
  model: anthropicParams.model,
2836
2793
  provider: 'anthropic',
@@ -2839,15 +2796,14 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2839
2796
  latency,
2840
2797
  timeToFirstToken,
2841
2798
  baseURL: this.baseURL,
2842
- params: body,
2799
+ modelParameters: getModelParams(body),
2843
2800
  httpStatus: 200,
2844
2801
  usage,
2845
2802
  stopReason,
2846
2803
  tools: availableTools
2847
2804
  });
2848
2805
  } catch (error) {
2849
- const enrichedError = await sendEventWithErrorToPosthog({
2850
- client: this.phClient,
2806
+ await captureAiGeneration(this.phClient, {
2851
2807
  ...posthogParams,
2852
2808
  model: anthropicParams.model,
2853
2809
  provider: 'anthropic',
@@ -2855,14 +2811,14 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2855
2811
  output: [],
2856
2812
  latency: 0,
2857
2813
  baseURL: this.baseURL,
2858
- params: body,
2814
+ modelParameters: getModelParams(body),
2859
2815
  usage: {
2860
2816
  inputTokens: 0,
2861
2817
  outputTokens: 0
2862
2818
  },
2863
2819
  error: error
2864
2820
  });
2865
- throw enrichedError;
2821
+ throw error;
2866
2822
  }
2867
2823
  })();
2868
2824
  // Return the other stream to the user
@@ -2875,8 +2831,7 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2875
2831
  if ('content' in result) {
2876
2832
  const latency = (Date.now() - startTime) / 1000;
2877
2833
  const availableTools = extractAvailableToolCalls('anthropic', anthropicParams);
2878
- await sendEventToPosthog({
2879
- client: this.phClient,
2834
+ await captureAiGeneration(this.phClient, {
2880
2835
  ...posthogParams,
2881
2836
  model: anthropicParams.model,
2882
2837
  provider: 'anthropic',
@@ -2884,7 +2839,7 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2884
2839
  output: formatResponseAnthropic(result),
2885
2840
  latency,
2886
2841
  baseURL: this.baseURL,
2887
- params: body,
2842
+ modelParameters: getModelParams(body),
2888
2843
  httpStatus: 200,
2889
2844
  usage: {
2890
2845
  inputTokens: result.usage.input_tokens ?? 0,
@@ -2900,8 +2855,7 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2900
2855
  }
2901
2856
  return result;
2902
2857
  }, async error => {
2903
- await sendEventToPosthog({
2904
- client: this.phClient,
2858
+ await captureAiGeneration(this.phClient, {
2905
2859
  ...posthogParams,
2906
2860
  model: anthropicParams.model,
2907
2861
  provider: 'anthropic',
@@ -2909,13 +2863,13 @@ class WrappedMessages extends AnthropicOriginal.Messages {
2909
2863
  output: [],
2910
2864
  latency: 0,
2911
2865
  baseURL: this.baseURL,
2912
- params: body,
2866
+ modelParameters: getModelParams(body),
2913
2867
  httpStatus: error?.status ? error.status : 500,
2914
2868
  usage: {
2915
2869
  inputTokens: 0,
2916
2870
  outputTokens: 0
2917
2871
  },
2918
- error: JSON.stringify(error)
2872
+ error: error
2919
2873
  });
2920
2874
  throw error;
2921
2875
  });
@@ -2952,8 +2906,7 @@ class WrappedModels {
2952
2906
  const availableTools = extractAvailableToolCalls('gemini', geminiParams);
2953
2907
  const metadata = response.usageMetadata;
2954
2908
  const finishReason = response.candidates?.[0]?.finishReason;
2955
- await sendEventToPosthog({
2956
- client: this.phClient,
2909
+ await captureAiGeneration(this.phClient, {
2957
2910
  ...posthogParams,
2958
2911
  model: geminiParams.model,
2959
2912
  provider: 'gemini',
@@ -2961,7 +2914,7 @@ class WrappedModels {
2961
2914
  output: formatResponseGemini(response),
2962
2915
  latency,
2963
2916
  baseURL: 'https://generativelanguage.googleapis.com',
2964
- params: params,
2917
+ modelParameters: getModelParams(params),
2965
2918
  httpStatus: 200,
2966
2919
  usage: {
2967
2920
  inputTokens: metadata?.promptTokenCount ?? 0,
@@ -2977,8 +2930,7 @@ class WrappedModels {
2977
2930
  return response;
2978
2931
  } catch (error) {
2979
2932
  const latency = (Date.now() - startTime) / 1000;
2980
- const enrichedError = await sendEventWithErrorToPosthog({
2981
- client: this.phClient,
2933
+ await captureAiGeneration(this.phClient, {
2982
2934
  ...posthogParams,
2983
2935
  model: geminiParams.model,
2984
2936
  provider: 'gemini',
@@ -2986,14 +2938,14 @@ class WrappedModels {
2986
2938
  output: [],
2987
2939
  latency,
2988
2940
  baseURL: 'https://generativelanguage.googleapis.com',
2989
- params: params,
2941
+ modelParameters: getModelParams(params),
2990
2942
  usage: {
2991
2943
  inputTokens: 0,
2992
2944
  outputTokens: 0
2993
2945
  },
2994
- error: error
2946
+ error
2995
2947
  });
2996
- throw enrichedError;
2948
+ throw error;
2997
2949
  }
2998
2950
  }
2999
2951
  async *generateContentStream(params) {
@@ -3092,8 +3044,7 @@ class WrappedModels {
3092
3044
  role: 'assistant',
3093
3045
  content: accumulatedContent
3094
3046
  }] : [];
3095
- await sendEventToPosthog({
3096
- client: this.phClient,
3047
+ await captureAiGeneration(this.phClient, {
3097
3048
  ...posthogParams,
3098
3049
  model: geminiParams.model,
3099
3050
  provider: 'gemini',
@@ -3102,7 +3053,7 @@ class WrappedModels {
3102
3053
  latency,
3103
3054
  timeToFirstToken,
3104
3055
  baseURL: 'https://generativelanguage.googleapis.com',
3105
- params: params,
3056
+ modelParameters: getModelParams(params),
3106
3057
  httpStatus: 200,
3107
3058
  usage: {
3108
3059
  ...usage,
@@ -3114,8 +3065,7 @@ class WrappedModels {
3114
3065
  });
3115
3066
  } catch (error) {
3116
3067
  const latency = (Date.now() - startTime) / 1000;
3117
- const enrichedError = await sendEventWithErrorToPosthog({
3118
- client: this.phClient,
3068
+ await captureAiGeneration(this.phClient, {
3119
3069
  ...posthogParams,
3120
3070
  model: geminiParams.model,
3121
3071
  provider: 'gemini',
@@ -3123,14 +3073,14 @@ class WrappedModels {
3123
3073
  output: [],
3124
3074
  latency,
3125
3075
  baseURL: 'https://generativelanguage.googleapis.com',
3126
- params: params,
3076
+ modelParameters: getModelParams(params),
3127
3077
  usage: {
3128
3078
  inputTokens: 0,
3129
3079
  outputTokens: 0
3130
3080
  },
3131
- error: error
3081
+ error
3132
3082
  });
3133
- throw enrichedError;
3083
+ throw error;
3134
3084
  }
3135
3085
  }
3136
3086
  async embedContent(params) {
@@ -3143,8 +3093,7 @@ class WrappedModels {
3143
3093
  const response = await this.client.models.embedContent(geminiParams);
3144
3094
  const latency = (Date.now() - startTime) / 1000;
3145
3095
  const inputTokens = extractEmbeddingTokenCount(response);
3146
- await sendEventToPosthog({
3147
- client: this.phClient,
3096
+ await captureAiGeneration(this.phClient, {
3148
3097
  ...posthogParams,
3149
3098
  eventType: AIEvent.Embedding,
3150
3099
  model: geminiParams.model,
@@ -3153,7 +3102,7 @@ class WrappedModels {
3153
3102
  output: null,
3154
3103
  latency,
3155
3104
  baseURL: 'https://generativelanguage.googleapis.com',
3156
- params: params,
3105
+ modelParameters: getModelParams(params),
3157
3106
  httpStatus: 200,
3158
3107
  usage: {
3159
3108
  inputTokens
@@ -3162,8 +3111,7 @@ class WrappedModels {
3162
3111
  return response;
3163
3112
  } catch (error) {
3164
3113
  const latency = (Date.now() - startTime) / 1000;
3165
- const enrichedError = await sendEventWithErrorToPosthog({
3166
- client: this.phClient,
3114
+ await captureAiGeneration(this.phClient, {
3167
3115
  ...posthogParams,
3168
3116
  eventType: AIEvent.Embedding,
3169
3117
  model: geminiParams.model,
@@ -3172,13 +3120,13 @@ class WrappedModels {
3172
3120
  output: null,
3173
3121
  latency,
3174
3122
  baseURL: 'https://generativelanguage.googleapis.com',
3175
- params: params,
3123
+ modelParameters: getModelParams(params),
3176
3124
  usage: {
3177
3125
  inputTokens: 0
3178
3126
  },
3179
- error: error
3127
+ error
3180
3128
  });
3181
- throw enrichedError;
3129
+ throw error;
3182
3130
  }
3183
3131
  }
3184
3132
  formatPartsAsContentBlocks(parts) {
@@ -4714,5 +4662,5 @@ class Prompts {
4714
4662
  }
4715
4663
  }
4716
4664
 
4717
- export { PostHogAnthropic as Anthropic, PostHogAzureOpenAI as AzureOpenAI, PostHogGoogleGenAI as GoogleGenAI, LangChainCallbackHandler, PostHogOpenAI as OpenAI, Prompts, wrapVercelLanguageModel as withTracing };
4665
+ export { AIEvent, PostHogAnthropic as Anthropic, PostHogAzureOpenAI as AzureOpenAI, PostHogGoogleGenAI as GoogleGenAI, LangChainCallbackHandler, PostHogOpenAI as OpenAI, Prompts, captureAiGeneration, wrapVercelLanguageModel as withTracing };
4718
4666
  //# sourceMappingURL=index.mjs.map