@posthog/ai 8.9.0 → 8.9.2

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.
@@ -577,7 +577,7 @@ function formatOpenAIResponsesInput(input, instructions) {
577
577
  return messages;
578
578
  }
579
579
 
580
- var version = "8.9.0";
580
+ var version = "8.9.2";
581
581
 
582
582
  const DEFAULT_MAX_DEPTH = 3;
583
583
  const MAX_STACK_LINES = 20;
@@ -734,15 +734,22 @@ const captureAiGeneration$1 = async (client, options) => {
734
734
  };
735
735
  }
736
736
  httpStatus = httpStatus ?? 200;
737
- let costOverrideData = {};
737
+
738
+ // A configured price applies only to a count the provider reported, so a call with no
739
+ // reported usage sends no cost instead of asserting $0. $ai_total_cost_usd sums the sides
740
+ // that were priced, which makes it the cost of the known side alone when the other side
741
+ // went unreported: a lower bound on the true total, not an assertion of it.
742
+ const costOverrideData = {};
738
743
  if (options.costOverride) {
739
- const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
740
- const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
741
- costOverrideData = {
742
- $ai_input_cost_usd: inputCostUSD,
743
- $ai_output_cost_usd: outputCostUSD,
744
- $ai_total_cost_usd: inputCostUSD + outputCostUSD
745
- };
744
+ if (usage.inputTokens !== undefined) {
745
+ costOverrideData.$ai_input_cost_usd = (options.costOverride.inputCost ?? 0) * usage.inputTokens;
746
+ }
747
+ if (usage.outputTokens !== undefined) {
748
+ costOverrideData.$ai_output_cost_usd = (options.costOverride.outputCost ?? 0) * usage.outputTokens;
749
+ }
750
+ if (Object.keys(costOverrideData).length > 0) {
751
+ costOverrideData.$ai_total_cost_usd = (costOverrideData.$ai_input_cost_usd ?? 0) + (costOverrideData.$ai_output_cost_usd ?? 0);
752
+ }
746
753
  }
747
754
 
748
755
  // The caller's own token counts override the SDK-derived ones further down, via the
@@ -786,7 +793,9 @@ const captureAiGeneration$1 = async (client, options) => {
786
793
  $ai_input: safeInput,
787
794
  $ai_output_choices: safeOutput,
788
795
  $ai_http_status: httpStatus,
789
- $ai_input_tokens: usage.inputTokens ?? 0,
796
+ ...(usage.inputTokens !== undefined ? {
797
+ $ai_input_tokens: usage.inputTokens
798
+ } : {}),
790
799
  ...(usage.outputTokens !== undefined ? {
791
800
  $ai_output_tokens: usage.outputTokens
792
801
  } : {}),
@@ -1017,14 +1026,23 @@ function wrapBackgroundResponseStream(stream, responseID, tracker, captureTermin
1017
1026
  return new Stream(() => inspectStream(), stream.controller);
1018
1027
  }
1019
1028
 
1020
- function addRequestId(result, response, requestIdHeader) {
1029
+ function addResponseIds(result, response, requestIdHeader, workspaceIdHeader) {
1021
1030
  if (!result || typeof result !== 'object' || Array.isArray(result)) {
1022
1031
  return result;
1023
1032
  }
1024
- return Object.defineProperty(result, '_request_id', {
1025
- value: response.headers.get(requestIdHeader),
1026
- enumerable: false
1027
- });
1033
+ const properties = {
1034
+ _request_id: {
1035
+ value: response.headers.get(requestIdHeader),
1036
+ enumerable: false
1037
+ }
1038
+ };
1039
+ if (workspaceIdHeader) {
1040
+ properties._workspace_id = {
1041
+ value: response.headers.get(workspaceIdHeader),
1042
+ enumerable: false
1043
+ };
1044
+ }
1045
+ return Object.defineProperties(result, properties);
1028
1046
  }
1029
1047
  function getResponsePropsPromise(parentPromise) {
1030
1048
  const responsePromise = parentPromise.responsePromise;
@@ -1033,7 +1051,7 @@ function getResponsePropsPromise(parentPromise) {
1033
1051
  }
1034
1052
  return responsePromise;
1035
1053
  }
1036
- function decorateProviderPromise(wrappedPromise, responsePropsPromise, requestIdHeader, preserveThenUnwrap) {
1054
+ function decorateProviderPromise(wrappedPromise, responsePropsPromise, requestIdHeader, workspaceIdHeader, preserveThenUnwrap) {
1037
1055
  const providerPromise = wrappedPromise;
1038
1056
  if (responsePropsPromise) {
1039
1057
  providerPromise.asResponse = async () => (await responsePropsPromise).response;
@@ -1042,7 +1060,10 @@ function decorateProviderPromise(wrappedPromise, responsePropsPromise, requestId
1042
1060
  return {
1043
1061
  response: props.response,
1044
1062
  data,
1045
- request_id: props.response.headers.get(requestIdHeader)
1063
+ request_id: props.response.headers.get(requestIdHeader),
1064
+ ...(workspaceIdHeader ? {
1065
+ workspace_id: props.response.headers.get(workspaceIdHeader)
1066
+ } : {})
1046
1067
  };
1047
1068
  };
1048
1069
  }
@@ -1051,8 +1072,8 @@ function decorateProviderPromise(wrappedPromise, responsePropsPromise, requestId
1051
1072
  if (!responsePropsPromise) {
1052
1073
  throw new Error('The provider promise response metadata is unavailable');
1053
1074
  }
1054
- const transformedPromise = Promise.all([wrappedPromise, responsePropsPromise]).then(([data, props]) => addRequestId(transform(data, props), props.response, requestIdHeader));
1055
- return decorateProviderPromise(transformedPromise, responsePropsPromise, requestIdHeader, true);
1075
+ const transformedPromise = Promise.all([wrappedPromise, responsePropsPromise]).then(([data, props]) => addResponseIds(transform(data, props), props.response, requestIdHeader, workspaceIdHeader));
1076
+ return decorateProviderPromise(transformedPromise, responsePropsPromise, requestIdHeader, workspaceIdHeader, true);
1056
1077
  };
1057
1078
  }
1058
1079
  return providerPromise;
@@ -1068,7 +1089,7 @@ function decorateProviderPromise(wrappedPromise, responsePropsPromise, requestId
1068
1089
  function preserveProviderPromise(parentPromise, wrappedPromise, options = {}) {
1069
1090
  const responsePropsPromise = getResponsePropsPromise(parentPromise);
1070
1091
  const preserveThenUnwrap = typeof parentPromise._thenUnwrap === 'function';
1071
- const providerPromise = decorateProviderPromise(wrappedPromise, responsePropsPromise, options.requestIdHeader ?? 'x-request-id', preserveThenUnwrap);
1092
+ const providerPromise = decorateProviderPromise(wrappedPromise, responsePropsPromise, options.requestIdHeader ?? 'x-request-id', options.workspaceIdHeader, preserveThenUnwrap);
1072
1093
  if (!responsePropsPromise) {
1073
1094
  const asResponse = parentPromise.asResponse?.bind(parentPromise);
1074
1095
  if (asResponse) {
@@ -1327,8 +1348,6 @@ function monitoredStreamTee(source, createStream) {
1327
1348
  class OpenAIChatStreamAccumulator {
1328
1349
  accumulatedContent = '';
1329
1350
  usage = {
1330
- inputTokens: 0,
1331
- outputTokens: 0,
1332
1351
  webSearchCount: 0
1333
1352
  };
1334
1353
  toolCalls = new Map();
@@ -1430,8 +1449,6 @@ class OpenAIChatStreamAccumulator {
1430
1449
  class OpenAIResponsesStreamAccumulator {
1431
1450
  output = [];
1432
1451
  usage = {
1433
- inputTokens: 0,
1434
- outputTokens: 0,
1435
1452
  webSearchCount: 0
1436
1453
  };
1437
1454
  consume(event, receivedAt = Date.now()) {
@@ -1540,20 +1557,17 @@ function buildChatSuccessOptions(context, result) {
1540
1557
  })
1541
1558
  };
1542
1559
  }
1543
- function buildChatErrorOptions(context, error, metadata = {}) {
1560
+ function buildChatErrorOptions(context, error, metadata) {
1544
1561
  return {
1545
1562
  ...context.monitoring,
1546
1563
  model: context.params.model,
1547
1564
  provider: context.provider,
1548
1565
  input: sanitizeOpenAI(context.params.messages, context.client),
1549
1566
  output: [],
1550
- latency: 0,
1567
+ latency: metadata.latency,
1551
1568
  baseURL: context.baseURL,
1552
1569
  modelParameters: getModelParams(context.modelParametersSource),
1553
- usage: {
1554
- inputTokens: 0,
1555
- outputTokens: 0
1556
- },
1570
+ usage: metadata.usage ?? {},
1557
1571
  completionId: metadata.completionId,
1558
1572
  providerMetadata: buildProviderMetadata({
1559
1573
  systemFingerprint: metadata.systemFingerprint
@@ -1603,21 +1617,18 @@ function buildBackgroundResponseOptions(context, response) {
1603
1617
  includeRequestId: true
1604
1618
  });
1605
1619
  }
1606
- function buildResponsesErrorOptions(context, error, completionId) {
1620
+ function buildResponsesErrorOptions(context, error, metadata) {
1607
1621
  return {
1608
1622
  ...context.monitoring,
1609
1623
  model: context.params.model,
1610
1624
  provider: context.provider,
1611
1625
  input: buildSanitizedResponsesInput(context),
1612
1626
  output: [],
1613
- latency: 0,
1627
+ latency: metadata.latency,
1614
1628
  baseURL: context.baseURL,
1615
1629
  modelParameters: getModelParams(context.modelParametersSource),
1616
- usage: {
1617
- inputTokens: 0,
1618
- outputTokens: 0
1619
- },
1620
- completionId,
1630
+ usage: metadata.usage ?? {},
1631
+ completionId: metadata.completionId,
1621
1632
  error
1622
1633
  };
1623
1634
  }
@@ -1639,7 +1650,7 @@ function buildEmbeddingSuccessOptions(context, usage, latency) {
1639
1650
  }
1640
1651
  };
1641
1652
  }
1642
- function buildEmbeddingErrorOptions(context, error) {
1653
+ function buildEmbeddingErrorOptions(context, error, latency) {
1643
1654
  return {
1644
1655
  eventType: AIEvent.Embedding,
1645
1656
  ...context.monitoring,
@@ -1647,12 +1658,10 @@ function buildEmbeddingErrorOptions(context, error) {
1647
1658
  provider: context.provider,
1648
1659
  input: withPrivacyMode(context.client, context.monitoring.privacyMode, context.params.input),
1649
1660
  output: null,
1650
- latency: 0,
1661
+ latency,
1651
1662
  baseURL: context.baseURL,
1652
1663
  modelParameters: getModelParams(context.modelParametersSource),
1653
- usage: {
1654
- inputTokens: 0
1655
- },
1664
+ usage: {},
1656
1665
  error
1657
1666
  };
1658
1667
  }
@@ -1731,7 +1740,9 @@ let WrappedCompletions$1 = class WrappedCompletions extends AzureOpenAI.Chat.Com
1731
1740
  modelParametersSource: body
1732
1741
  }, error, {
1733
1742
  completionId: accumulated.completionId,
1734
- systemFingerprint: accumulated.systemFingerprint
1743
+ systemFingerprint: accumulated.systemFingerprint,
1744
+ usage: accumulated.usage,
1745
+ latency: (Date.now() - startTime) / 1000
1735
1746
  }));
1736
1747
  throw error;
1737
1748
  }
@@ -1777,7 +1788,9 @@ let WrappedCompletions$1 = class WrappedCompletions extends AzureOpenAI.Chat.Com
1777
1788
  params: openAIParams,
1778
1789
  monitoring: posthogParams,
1779
1790
  modelParametersSource: body
1780
- }, error));
1791
+ }, error, {
1792
+ latency: (Date.now() - startTime) / 1000
1793
+ }));
1781
1794
  throw error;
1782
1795
  });
1783
1796
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -1879,7 +1892,11 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
1879
1892
  params: openAIParams,
1880
1893
  monitoring: posthogParams,
1881
1894
  modelParametersSource: body
1882
- }, error, accumulated.completionId));
1895
+ }, error, {
1896
+ completionId: accumulated.completionId,
1897
+ usage: accumulated.usage,
1898
+ latency: (Date.now() - startTime) / 1000
1899
+ }));
1883
1900
  throw error;
1884
1901
  }
1885
1902
  })().catch(() => {
@@ -1927,7 +1944,9 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
1927
1944
  params: openAIParams,
1928
1945
  monitoring: posthogParams,
1929
1946
  modelParametersSource: body
1930
- }, error));
1947
+ }, error, {
1948
+ latency: (Date.now() - startTime) / 1000
1949
+ }));
1931
1950
  throw error;
1932
1951
  });
1933
1952
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2019,7 +2038,9 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
2019
2038
  params: openAIParams,
2020
2039
  monitoring: posthogParams,
2021
2040
  modelParametersSource: body
2022
- }, error));
2041
+ }, error, {
2042
+ latency: (Date.now() - startTime) / 1000
2043
+ }));
2023
2044
  throw error;
2024
2045
  });
2025
2046
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2056,7 +2077,7 @@ let WrappedEmbeddings$1 = class WrappedEmbeddings extends AzureOpenAI.Embeddings
2056
2077
  params: openAIParams,
2057
2078
  monitoring: posthogParams,
2058
2079
  modelParametersSource: body
2059
- }, error));
2080
+ }, error, (Date.now() - startTime) / 1000));
2060
2081
  throw error;
2061
2082
  });
2062
2083
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2144,7 +2165,9 @@ class WrappedCompletions extends Completions {
2144
2165
  modelParametersSource: body
2145
2166
  }, error, {
2146
2167
  completionId: accumulated.completionId,
2147
- systemFingerprint: accumulated.systemFingerprint
2168
+ systemFingerprint: accumulated.systemFingerprint,
2169
+ usage: accumulated.usage,
2170
+ latency: (Date.now() - startTime) / 1000
2148
2171
  }));
2149
2172
  throw error;
2150
2173
  }
@@ -2190,7 +2213,9 @@ class WrappedCompletions extends Completions {
2190
2213
  params: openAIParams,
2191
2214
  monitoring: posthogParams,
2192
2215
  modelParametersSource: body
2193
- }, error));
2216
+ }, error, {
2217
+ latency: (Date.now() - startTime) / 1000
2218
+ }));
2194
2219
  throw error;
2195
2220
  });
2196
2221
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2292,7 +2317,11 @@ class WrappedResponses extends Responses {
2292
2317
  params: openAIParams,
2293
2318
  monitoring: posthogParams,
2294
2319
  modelParametersSource: body
2295
- }, error, accumulated.completionId));
2320
+ }, error, {
2321
+ completionId: accumulated.completionId,
2322
+ usage: accumulated.usage,
2323
+ latency: (Date.now() - startTime) / 1000
2324
+ }));
2296
2325
  throw error;
2297
2326
  }
2298
2327
  })().catch(() => {
@@ -2340,7 +2369,9 @@ class WrappedResponses extends Responses {
2340
2369
  params: openAIParams,
2341
2370
  monitoring: posthogParams,
2342
2371
  modelParametersSource: body
2343
- }, error));
2372
+ }, error, {
2373
+ latency: (Date.now() - startTime) / 1000
2374
+ }));
2344
2375
  throw error;
2345
2376
  });
2346
2377
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2432,7 +2463,9 @@ class WrappedResponses extends Responses {
2432
2463
  params: openAIParams,
2433
2464
  monitoring: posthogParams,
2434
2465
  modelParametersSource: body
2435
- }, error));
2466
+ }, error, {
2467
+ latency: (Date.now() - startTime) / 1000
2468
+ }));
2436
2469
  throw error;
2437
2470
  });
2438
2471
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2469,7 +2502,7 @@ class WrappedEmbeddings extends Embeddings {
2469
2502
  params: openAIParams,
2470
2503
  monitoring: posthogParams,
2471
2504
  modelParametersSource: body
2472
- }, error));
2505
+ }, error, (Date.now() - startTime) / 1000));
2473
2506
  throw error;
2474
2507
  });
2475
2508
  return preserveProviderPromise(parentPromise, wrappedPromise);
@@ -2515,13 +2548,10 @@ class WrappedTranscriptions extends Transcriptions {
2515
2548
  if (Symbol.asyncIterator in value) {
2516
2549
  const [stream1, stream2] = monitoredStreamTee(value, (iterator, controller) => new Stream(iterator, controller));
2517
2550
  (async () => {
2551
+ let usage = {};
2518
2552
  try {
2519
2553
  let finalContent = '';
2520
2554
  let firstTokenTime;
2521
- let usage = {
2522
- inputTokens: 0,
2523
- outputTokens: 0
2524
- };
2525
2555
  const doneEvent = 'transcript.text.done';
2526
2556
  for await (const chunk of stream1) {
2527
2557
  // Track first token on text delta events
@@ -2563,13 +2593,10 @@ class WrappedTranscriptions extends Transcriptions {
2563
2593
  provider: 'openai',
2564
2594
  input: openAIParams.prompt,
2565
2595
  output: [],
2566
- latency: 0,
2596
+ latency: (Date.now() - startTime) / 1000,
2567
2597
  baseURL: this.baseURL,
2568
2598
  modelParameters: getModelParams(body),
2569
- usage: {
2570
- inputTokens: 0,
2571
- outputTokens: 0
2572
- },
2599
+ usage,
2573
2600
  error
2574
2601
  });
2575
2602
  throw error;
@@ -2612,13 +2639,10 @@ class WrappedTranscriptions extends Transcriptions {
2612
2639
  provider: 'openai',
2613
2640
  input: openAIParams.prompt,
2614
2641
  output: [],
2615
- latency: 0,
2642
+ latency: (Date.now() - startTime) / 1000,
2616
2643
  baseURL: this.baseURL,
2617
2644
  modelParameters: getModelParams(body),
2618
- usage: {
2619
- inputTokens: 0,
2620
- outputTokens: 0
2621
- },
2645
+ usage: {},
2622
2646
  error
2623
2647
  });
2624
2648
  throw error;