@posthog/ai 7.4.0 → 7.4.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.
@@ -11,7 +11,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
12
  var AnthropicOriginal__default = /*#__PURE__*/_interopDefault(AnthropicOriginal);
13
13
 
14
- var version = "7.4.0";
14
+ var version = "7.4.2";
15
15
 
16
16
  // Type guards for safer type checking
17
17
 
@@ -3,7 +3,7 @@ import { Buffer } from 'buffer';
3
3
  import { v4 } from 'uuid';
4
4
  import { uuidv7 } from '@posthog/core';
5
5
 
6
- var version = "7.4.0";
6
+ var version = "7.4.2";
7
7
 
8
8
  // Type guards for safer type checking
9
9
 
@@ -7,7 +7,7 @@ var buffer = require('buffer');
7
7
  var uuid = require('uuid');
8
8
  var core = require('@posthog/core');
9
9
 
10
- var version = "7.4.0";
10
+ var version = "7.4.2";
11
11
 
12
12
  // Type guards for safer type checking
13
13
 
@@ -3,7 +3,7 @@ import { Buffer } from 'buffer';
3
3
  import { v4 } from 'uuid';
4
4
  import { uuidv7 } from '@posthog/core';
5
5
 
6
- var version = "7.4.0";
6
+ var version = "7.4.2";
7
7
 
8
8
  // Type guards for safer type checking
9
9
 
package/dist/index.cjs CHANGED
@@ -30,7 +30,7 @@ function _interopNamespace(e) {
30
30
  var uuid__namespace = /*#__PURE__*/_interopNamespace(uuid);
31
31
  var AnthropicOriginal__default = /*#__PURE__*/_interopDefault(AnthropicOriginal);
32
32
 
33
- var version = "7.4.0";
33
+ var version = "7.4.2";
34
34
 
35
35
  // Type guards for safer type checking
36
36
  const isString = value => {
@@ -1961,6 +1961,10 @@ class WrappedEmbeddings extends openai.AzureOpenAI.Embeddings {
1961
1961
  }
1962
1962
  }
1963
1963
 
1964
+ // Type guards
1965
+ function isV3Model(model) {
1966
+ return model.specificationVersion === 'v3';
1967
+ }
1964
1968
  const mapVercelParams = params => {
1965
1969
  return {
1966
1970
  temperature: params.temperature,
@@ -2181,6 +2185,19 @@ const extractAdditionalTokenValues = providerMetadata => {
2181
2185
  }
2182
2186
  return {};
2183
2187
  };
2188
+ // For Anthropic providers in V3, inputTokens.total is the sum of all tokens (uncached + cache read + cache write).
2189
+ // Our cost calculation expects inputTokens to be only the uncached portion for Anthropic.
2190
+ // This helper subtracts cache tokens from inputTokens for Anthropic V3 models.
2191
+ const adjustAnthropicV3CacheTokens = (model, provider, usage) => {
2192
+ if (isV3Model(model) && provider.toLowerCase().includes('anthropic')) {
2193
+ const cacheReadTokens = usage.cacheReadInputTokens || 0;
2194
+ const cacheWriteTokens = usage.cacheCreationInputTokens || 0;
2195
+ const cacheTokens = cacheReadTokens + cacheWriteTokens;
2196
+ if (usage.inputTokens && cacheTokens > 0) {
2197
+ usage.inputTokens = Math.max(usage.inputTokens - cacheTokens, 0);
2198
+ }
2199
+ }
2200
+ };
2184
2201
  // Helper to extract numeric token value from V2 (number) or V3 (object with .total) usage formats
2185
2202
  const extractTokenCount = value => {
2186
2203
  if (typeof value === 'number') {
@@ -2231,234 +2248,246 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
2231
2248
  $ai_framework_version: model.specificationVersion === 'v3' ? '6' : '5'
2232
2249
  }
2233
2250
  };
2234
- // Create wrapped model that preserves the original type
2235
- const wrappedModel = {
2236
- ...model,
2237
- doGenerate: async params => {
2238
- const startTime = Date.now();
2239
- const mergedParams = {
2240
- ...mergedOptions,
2241
- ...mapVercelParams(params)
2242
- };
2243
- const availableTools = extractAvailableToolCalls('vercel', params);
2244
- try {
2245
- const result = await model.doGenerate(params);
2246
- const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
2247
- const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
2248
- const baseURL = ''; // cannot currently get baseURL from vercel
2249
- const content = mapVercelOutput(result.content);
2250
- const latency = (Date.now() - startTime) / 1000;
2251
- const providerMetadata = result.providerMetadata;
2252
- const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
2253
- const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
2254
- // V2 usage has simple numbers, V3 has objects with .total - normalize both
2255
- const usageObj = result.usage;
2256
- const usage = {
2257
- inputTokens: extractTokenCount(result.usage.inputTokens),
2258
- outputTokens: extractTokenCount(result.usage.outputTokens),
2259
- reasoningTokens: extractReasoningTokens(usageObj),
2260
- cacheReadInputTokens: extractCacheReadTokens(usageObj),
2261
- webSearchCount,
2262
- ...additionalTokenValues
2251
+ // Create wrapped model using Object.create to preserve the prototype chain
2252
+ // This automatically inherits all properties (including getters) from the model
2253
+ const wrappedModel = Object.create(model, {
2254
+ doGenerate: {
2255
+ value: async params => {
2256
+ const startTime = Date.now();
2257
+ const mergedParams = {
2258
+ ...mergedOptions,
2259
+ ...mapVercelParams(params)
2263
2260
  };
2264
- await sendEventToPosthog({
2265
- client: phClient,
2266
- distinctId: mergedOptions.posthogDistinctId,
2267
- traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2268
- model: modelId,
2269
- provider: provider,
2270
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2271
- output: content,
2272
- latency,
2273
- baseURL,
2274
- params: mergedParams,
2275
- httpStatus: 200,
2276
- usage,
2277
- tools: availableTools,
2278
- captureImmediate: mergedOptions.posthogCaptureImmediate
2279
- });
2280
- return result;
2281
- } catch (error) {
2282
- const modelId = model.modelId;
2283
- const enrichedError = await sendEventWithErrorToPosthog({
2284
- client: phClient,
2285
- distinctId: mergedOptions.posthogDistinctId,
2286
- traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2287
- model: modelId,
2288
- provider: model.provider,
2289
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2290
- output: [],
2291
- latency: 0,
2292
- baseURL: '',
2293
- params: mergedParams,
2294
- usage: {
2295
- inputTokens: 0,
2296
- outputTokens: 0
2297
- },
2298
- error: error,
2299
- tools: availableTools,
2300
- captureImmediate: mergedOptions.posthogCaptureImmediate
2301
- });
2302
- throw enrichedError;
2303
- }
2261
+ const availableTools = extractAvailableToolCalls('vercel', params);
2262
+ try {
2263
+ const result = await model.doGenerate(params);
2264
+ const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
2265
+ const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
2266
+ const baseURL = ''; // cannot currently get baseURL from vercel
2267
+ const content = mapVercelOutput(result.content);
2268
+ const latency = (Date.now() - startTime) / 1000;
2269
+ const providerMetadata = result.providerMetadata;
2270
+ const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
2271
+ const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
2272
+ // V2 usage has simple numbers, V3 has objects with .total - normalize both
2273
+ const usageObj = result.usage;
2274
+ const usage = {
2275
+ inputTokens: extractTokenCount(result.usage.inputTokens),
2276
+ outputTokens: extractTokenCount(result.usage.outputTokens),
2277
+ reasoningTokens: extractReasoningTokens(usageObj),
2278
+ cacheReadInputTokens: extractCacheReadTokens(usageObj),
2279
+ webSearchCount,
2280
+ ...additionalTokenValues
2281
+ };
2282
+ adjustAnthropicV3CacheTokens(model, provider, usage);
2283
+ await sendEventToPosthog({
2284
+ client: phClient,
2285
+ distinctId: mergedOptions.posthogDistinctId,
2286
+ traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2287
+ model: modelId,
2288
+ provider: provider,
2289
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2290
+ output: content,
2291
+ latency,
2292
+ baseURL,
2293
+ params: mergedParams,
2294
+ httpStatus: 200,
2295
+ usage,
2296
+ tools: availableTools,
2297
+ captureImmediate: mergedOptions.posthogCaptureImmediate
2298
+ });
2299
+ return result;
2300
+ } catch (error) {
2301
+ const modelId = model.modelId;
2302
+ const enrichedError = await sendEventWithErrorToPosthog({
2303
+ client: phClient,
2304
+ distinctId: mergedOptions.posthogDistinctId,
2305
+ traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2306
+ model: modelId,
2307
+ provider: model.provider,
2308
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2309
+ output: [],
2310
+ latency: 0,
2311
+ baseURL: '',
2312
+ params: mergedParams,
2313
+ usage: {
2314
+ inputTokens: 0,
2315
+ outputTokens: 0
2316
+ },
2317
+ error: error,
2318
+ tools: availableTools,
2319
+ captureImmediate: mergedOptions.posthogCaptureImmediate
2320
+ });
2321
+ throw enrichedError;
2322
+ }
2323
+ },
2324
+ writable: true,
2325
+ configurable: true,
2326
+ enumerable: false
2304
2327
  },
2305
- doStream: async params => {
2306
- const startTime = Date.now();
2307
- let generatedText = '';
2308
- let reasoningText = '';
2309
- let usage = {};
2310
- let providerMetadata = undefined;
2311
- const mergedParams = {
2312
- ...mergedOptions,
2313
- ...mapVercelParams(params)
2314
- };
2315
- const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
2316
- const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
2317
- const availableTools = extractAvailableToolCalls('vercel', params);
2318
- const baseURL = ''; // cannot currently get baseURL from vercel
2319
- // Map to track in-progress tool calls
2320
- const toolCallsInProgress = new Map();
2321
- try {
2322
- const {
2323
- stream,
2324
- ...rest
2325
- } = await model.doStream(params);
2326
- const transformStream = new TransformStream({
2327
- transform(chunk, controller) {
2328
- // Handle streaming patterns - compatible with both V2 and V3
2329
- if (chunk.type === 'text-delta') {
2330
- generatedText += chunk.delta;
2331
- }
2332
- if (chunk.type === 'reasoning-delta') {
2333
- reasoningText += chunk.delta;
2334
- }
2335
- // Handle tool call chunks
2336
- if (chunk.type === 'tool-input-start') {
2337
- // Initialize a new tool call
2338
- toolCallsInProgress.set(chunk.id, {
2339
- toolCallId: chunk.id,
2340
- toolName: chunk.toolName,
2341
- input: ''
2342
- });
2343
- }
2344
- if (chunk.type === 'tool-input-delta') {
2345
- // Accumulate tool call arguments
2346
- const toolCall = toolCallsInProgress.get(chunk.id);
2347
- if (toolCall) {
2348
- toolCall.input += chunk.delta;
2328
+ doStream: {
2329
+ value: async params => {
2330
+ const startTime = Date.now();
2331
+ let generatedText = '';
2332
+ let reasoningText = '';
2333
+ let usage = {};
2334
+ let providerMetadata = undefined;
2335
+ const mergedParams = {
2336
+ ...mergedOptions,
2337
+ ...mapVercelParams(params)
2338
+ };
2339
+ const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
2340
+ const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
2341
+ const availableTools = extractAvailableToolCalls('vercel', params);
2342
+ const baseURL = ''; // cannot currently get baseURL from vercel
2343
+ // Map to track in-progress tool calls
2344
+ const toolCallsInProgress = new Map();
2345
+ try {
2346
+ const {
2347
+ stream,
2348
+ ...rest
2349
+ } = await model.doStream(params);
2350
+ const transformStream = new TransformStream({
2351
+ transform(chunk, controller) {
2352
+ // Handle streaming patterns - compatible with both V2 and V3
2353
+ if (chunk.type === 'text-delta') {
2354
+ generatedText += chunk.delta;
2349
2355
  }
2350
- }
2351
- if (chunk.type === 'tool-input-end') {
2352
- // Tool call is complete, keep it in the map for final processing
2353
- }
2354
- if (chunk.type === 'tool-call') {
2355
- // Direct tool call chunk (complete tool call)
2356
- toolCallsInProgress.set(chunk.toolCallId, {
2357
- toolCallId: chunk.toolCallId,
2358
- toolName: chunk.toolName,
2359
- input: chunk.input
2360
- });
2361
- }
2362
- if (chunk.type === 'finish') {
2363
- providerMetadata = chunk.providerMetadata;
2364
- const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
2365
- const chunkUsage = chunk.usage || {};
2366
- usage = {
2367
- inputTokens: extractTokenCount(chunk.usage?.inputTokens),
2368
- outputTokens: extractTokenCount(chunk.usage?.outputTokens),
2369
- reasoningTokens: extractReasoningTokens(chunkUsage),
2370
- cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
2371
- ...additionalTokenValues
2372
- };
2373
- }
2374
- controller.enqueue(chunk);
2375
- },
2376
- flush: async () => {
2377
- const latency = (Date.now() - startTime) / 1000;
2378
- // Build content array similar to mapVercelOutput structure
2379
- const content = [];
2380
- if (reasoningText) {
2381
- content.push({
2382
- type: 'reasoning',
2383
- text: truncate(reasoningText)
2384
- });
2385
- }
2386
- if (generatedText) {
2387
- content.push({
2388
- type: 'text',
2389
- text: truncate(generatedText)
2390
- });
2391
- }
2392
- // Add completed tool calls to content
2393
- for (const toolCall of toolCallsInProgress.values()) {
2394
- if (toolCall.toolName) {
2356
+ if (chunk.type === 'reasoning-delta') {
2357
+ reasoningText += chunk.delta;
2358
+ }
2359
+ // Handle tool call chunks
2360
+ if (chunk.type === 'tool-input-start') {
2361
+ // Initialize a new tool call
2362
+ toolCallsInProgress.set(chunk.id, {
2363
+ toolCallId: chunk.id,
2364
+ toolName: chunk.toolName,
2365
+ input: ''
2366
+ });
2367
+ }
2368
+ if (chunk.type === 'tool-input-delta') {
2369
+ // Accumulate tool call arguments
2370
+ const toolCall = toolCallsInProgress.get(chunk.id);
2371
+ if (toolCall) {
2372
+ toolCall.input += chunk.delta;
2373
+ }
2374
+ }
2375
+ if (chunk.type === 'tool-input-end') {
2376
+ // Tool call is complete, keep it in the map for final processing
2377
+ }
2378
+ if (chunk.type === 'tool-call') {
2379
+ // Direct tool call chunk (complete tool call)
2380
+ toolCallsInProgress.set(chunk.toolCallId, {
2381
+ toolCallId: chunk.toolCallId,
2382
+ toolName: chunk.toolName,
2383
+ input: chunk.input
2384
+ });
2385
+ }
2386
+ if (chunk.type === 'finish') {
2387
+ providerMetadata = chunk.providerMetadata;
2388
+ const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
2389
+ const chunkUsage = chunk.usage || {};
2390
+ usage = {
2391
+ inputTokens: extractTokenCount(chunk.usage?.inputTokens),
2392
+ outputTokens: extractTokenCount(chunk.usage?.outputTokens),
2393
+ reasoningTokens: extractReasoningTokens(chunkUsage),
2394
+ cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
2395
+ ...additionalTokenValues
2396
+ };
2397
+ }
2398
+ controller.enqueue(chunk);
2399
+ },
2400
+ flush: async () => {
2401
+ const latency = (Date.now() - startTime) / 1000;
2402
+ // Build content array similar to mapVercelOutput structure
2403
+ const content = [];
2404
+ if (reasoningText) {
2395
2405
  content.push({
2396
- type: 'tool-call',
2397
- id: toolCall.toolCallId,
2398
- function: {
2399
- name: toolCall.toolName,
2400
- arguments: toolCall.input
2401
- }
2406
+ type: 'reasoning',
2407
+ text: truncate(reasoningText)
2402
2408
  });
2403
2409
  }
2410
+ if (generatedText) {
2411
+ content.push({
2412
+ type: 'text',
2413
+ text: truncate(generatedText)
2414
+ });
2415
+ }
2416
+ // Add completed tool calls to content
2417
+ for (const toolCall of toolCallsInProgress.values()) {
2418
+ if (toolCall.toolName) {
2419
+ content.push({
2420
+ type: 'tool-call',
2421
+ id: toolCall.toolCallId,
2422
+ function: {
2423
+ name: toolCall.toolName,
2424
+ arguments: toolCall.input
2425
+ }
2426
+ });
2427
+ }
2428
+ }
2429
+ // Structure output like mapVercelOutput does
2430
+ const output = content.length > 0 ? [{
2431
+ role: 'assistant',
2432
+ content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
2433
+ }] : [];
2434
+ const webSearchCount = extractWebSearchCount(providerMetadata, usage);
2435
+ // Update usage with web search count
2436
+ const finalUsage = {
2437
+ ...usage,
2438
+ webSearchCount
2439
+ };
2440
+ adjustAnthropicV3CacheTokens(model, provider, finalUsage);
2441
+ await sendEventToPosthog({
2442
+ client: phClient,
2443
+ distinctId: mergedOptions.posthogDistinctId,
2444
+ traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2445
+ model: modelId,
2446
+ provider: provider,
2447
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2448
+ output: output,
2449
+ latency,
2450
+ baseURL,
2451
+ params: mergedParams,
2452
+ httpStatus: 200,
2453
+ usage: finalUsage,
2454
+ tools: availableTools,
2455
+ captureImmediate: mergedOptions.posthogCaptureImmediate
2456
+ });
2404
2457
  }
2405
- // Structure output like mapVercelOutput does
2406
- const output = content.length > 0 ? [{
2407
- role: 'assistant',
2408
- content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
2409
- }] : [];
2410
- const webSearchCount = extractWebSearchCount(providerMetadata, usage);
2411
- // Update usage with web search count
2412
- const finalUsage = {
2413
- ...usage,
2414
- webSearchCount
2415
- };
2416
- await sendEventToPosthog({
2417
- client: phClient,
2418
- distinctId: mergedOptions.posthogDistinctId,
2419
- traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2420
- model: modelId,
2421
- provider: provider,
2422
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2423
- output: output,
2424
- latency,
2425
- baseURL,
2426
- params: mergedParams,
2427
- httpStatus: 200,
2428
- usage: finalUsage,
2429
- tools: availableTools,
2430
- captureImmediate: mergedOptions.posthogCaptureImmediate
2431
- });
2432
- }
2433
- });
2434
- return {
2435
- stream: stream.pipeThrough(transformStream),
2436
- ...rest
2437
- };
2438
- } catch (error) {
2439
- const enrichedError = await sendEventWithErrorToPosthog({
2440
- client: phClient,
2441
- distinctId: mergedOptions.posthogDistinctId,
2442
- traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2443
- model: modelId,
2444
- provider: provider,
2445
- input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2446
- output: [],
2447
- latency: 0,
2448
- baseURL: '',
2449
- params: mergedParams,
2450
- usage: {
2451
- inputTokens: 0,
2452
- outputTokens: 0
2453
- },
2454
- error: error,
2455
- tools: availableTools,
2456
- captureImmediate: mergedOptions.posthogCaptureImmediate
2457
- });
2458
- throw enrichedError;
2459
- }
2458
+ });
2459
+ return {
2460
+ stream: stream.pipeThrough(transformStream),
2461
+ ...rest
2462
+ };
2463
+ } catch (error) {
2464
+ const enrichedError = await sendEventWithErrorToPosthog({
2465
+ client: phClient,
2466
+ distinctId: mergedOptions.posthogDistinctId,
2467
+ traceId: mergedOptions.posthogTraceId ?? uuid.v4(),
2468
+ model: modelId,
2469
+ provider: provider,
2470
+ input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
2471
+ output: [],
2472
+ latency: 0,
2473
+ baseURL: '',
2474
+ params: mergedParams,
2475
+ usage: {
2476
+ inputTokens: 0,
2477
+ outputTokens: 0
2478
+ },
2479
+ error: error,
2480
+ tools: availableTools,
2481
+ captureImmediate: mergedOptions.posthogCaptureImmediate
2482
+ });
2483
+ throw enrichedError;
2484
+ }
2485
+ },
2486
+ writable: true,
2487
+ configurable: true,
2488
+ enumerable: false
2460
2489
  }
2461
- };
2490
+ });
2462
2491
  return wrappedModel;
2463
2492
  };
2464
2493