@posthog/ai 3.2.1 → 3.3.1

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/lib/index.esm.js CHANGED
@@ -73,7 +73,8 @@ const sendEventToPosthog = ({
73
73
  httpStatus = 200,
74
74
  usage = {},
75
75
  isError = false,
76
- error
76
+ error,
77
+ tools
77
78
  }) => {
78
79
  if (client.capture) {
79
80
  let errorData = {};
@@ -93,6 +94,17 @@ const sendEventToPosthog = ({
93
94
  $ai_total_cost_usd: inputCostUSD + outputCostUSD
94
95
  };
95
96
  }
97
+ let additionalTokenValues = {
98
+ ...(usage.reasoningTokens ? {
99
+ $ai_reasoning_tokens: usage.reasoningTokens
100
+ } : {}),
101
+ ...(usage.cacheReadInputTokens ? {
102
+ $ai_cache_read_input_tokens: usage.cacheReadInputTokens
103
+ } : {}),
104
+ ...(usage.cacheCreationInputTokens ? {
105
+ $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
106
+ } : {})
107
+ };
96
108
  client.capture({
97
109
  distinctId: distinctId ?? traceId,
98
110
  event: '$ai_generation',
@@ -105,6 +117,7 @@ const sendEventToPosthog = ({
105
117
  $ai_http_status: httpStatus,
106
118
  $ai_input_tokens: usage.inputTokens ?? 0,
107
119
  $ai_output_tokens: usage.outputTokens ?? 0,
120
+ ...additionalTokenValues,
108
121
  $ai_latency: latency,
109
122
  $ai_trace_id: traceId,
110
123
  $ai_base_url: baseURL,
@@ -112,6 +125,9 @@ const sendEventToPosthog = ({
112
125
  ...(distinctId ? {} : {
113
126
  $process_person_profile: false
114
127
  }),
128
+ ...(tools ? {
129
+ $ai_tools: tools
130
+ } : {}),
115
131
  ...errorData,
116
132
  ...costOverrideData
117
133
  },
@@ -173,7 +189,9 @@ class WrappedCompletions$1 extends OpenAIOrignal.Chat.Completions {
173
189
  if (chunk.usage) {
174
190
  usage = {
175
191
  inputTokens: chunk.usage.prompt_tokens ?? 0,
176
- outputTokens: chunk.usage.completion_tokens ?? 0
192
+ outputTokens: chunk.usage.completion_tokens ?? 0,
193
+ reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
194
+ cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
177
195
  };
178
196
  }
179
197
  }
@@ -240,7 +258,9 @@ class WrappedCompletions$1 extends OpenAIOrignal.Chat.Completions {
240
258
  httpStatus: 200,
241
259
  usage: {
242
260
  inputTokens: result.usage?.prompt_tokens ?? 0,
243
- outputTokens: result.usage?.completion_tokens ?? 0
261
+ outputTokens: result.usage?.completion_tokens ?? 0,
262
+ reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
263
+ cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
244
264
  }
245
265
  });
246
266
  }
@@ -329,7 +349,9 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
329
349
  }
330
350
  usage = {
331
351
  inputTokens: chunk.usage.prompt_tokens ?? 0,
332
- outputTokens: chunk.usage.completion_tokens ?? 0
352
+ outputTokens: chunk.usage.completion_tokens ?? 0,
353
+ reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
354
+ cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
333
355
  };
334
356
  }
335
357
  }
@@ -401,7 +423,9 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
401
423
  httpStatus: 200,
402
424
  usage: {
403
425
  inputTokens: result.usage?.prompt_tokens ?? 0,
404
- outputTokens: result.usage?.completion_tokens ?? 0
426
+ outputTokens: result.usage?.completion_tokens ?? 0,
427
+ reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
428
+ cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
405
429
  }
406
430
  });
407
431
  }
@@ -446,16 +470,60 @@ const mapVercelParams = params => {
446
470
  };
447
471
  const mapVercelPrompt = prompt => {
448
472
  return prompt.map(p => {
449
- let content = '';
473
+ let content = {};
450
474
  if (Array.isArray(p.content)) {
451
475
  content = p.content.map(c => {
452
476
  if (c.type === 'text') {
453
- return c.text;
477
+ return {
478
+ type: 'text',
479
+ content: c.text
480
+ };
481
+ } else if (c.type === 'image') {
482
+ return {
483
+ type: 'image',
484
+ content: {
485
+ // if image is a url use it, or use "none supported"
486
+ image: c.image instanceof URL ? c.image.toString() : 'raw images not supported',
487
+ mimeType: c.mimeType
488
+ }
489
+ };
490
+ } else if (c.type === 'file') {
491
+ return {
492
+ type: 'file',
493
+ content: {
494
+ file: c.data instanceof URL ? c.data.toString() : 'raw files not supported',
495
+ mimeType: c.mimeType
496
+ }
497
+ };
498
+ } else if (c.type === 'tool-call') {
499
+ return {
500
+ type: 'tool-call',
501
+ content: {
502
+ toolCallId: c.toolCallId,
503
+ toolName: c.toolName,
504
+ args: c.args
505
+ }
506
+ };
507
+ } else if (c.type === 'tool-result') {
508
+ return {
509
+ type: 'tool-result',
510
+ content: {
511
+ toolCallId: c.toolCallId,
512
+ toolName: c.toolName,
513
+ result: c.result,
514
+ isError: c.isError
515
+ }
516
+ };
454
517
  }
455
- return '';
456
- }).join('');
518
+ return {
519
+ content: ''
520
+ };
521
+ });
457
522
  } else {
458
- content = p.content;
523
+ content = {
524
+ type: 'text',
525
+ text: p.content
526
+ };
459
527
  }
460
528
  return {
461
529
  role: p.role,
@@ -463,6 +531,45 @@ const mapVercelPrompt = prompt => {
463
531
  };
464
532
  });
465
533
  };
534
+ const mapVercelOutput = result => {
535
+ let output = {
536
+ ...(result.text ? {
537
+ text: result.text
538
+ } : {}),
539
+ ...(result.object ? {
540
+ object: result.object
541
+ } : {}),
542
+ ...(result.reasoning ? {
543
+ reasoning: result.reasoning
544
+ } : {}),
545
+ ...(result.response ? {
546
+ response: result.response
547
+ } : {}),
548
+ ...(result.finishReason ? {
549
+ finishReason: result.finishReason
550
+ } : {}),
551
+ ...(result.usage ? {
552
+ usage: result.usage
553
+ } : {}),
554
+ ...(result.warnings ? {
555
+ warnings: result.warnings
556
+ } : {}),
557
+ ...(result.providerMetadata ? {
558
+ toolCalls: result.providerMetadata
559
+ } : {})
560
+ };
561
+ // if text and no object or reasoning, return text
562
+ if (output.text && !output.object && !output.reasoning) {
563
+ return [{
564
+ content: output.text,
565
+ role: 'assistant'
566
+ }];
567
+ }
568
+ return [{
569
+ content: JSON.stringify(output),
570
+ role: 'assistant'
571
+ }];
572
+ };
466
573
  const extractProvider = model => {
467
574
  // vercel provider is in the format of provider.endpoint
468
575
  const provider = model.provider.toLowerCase();
@@ -486,11 +593,21 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
486
593
  const modelId = options.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
487
594
  const provider = options.posthogProviderOverride ?? extractProvider(model);
488
595
  const baseURL = ''; // cannot currently get baseURL from vercel
489
- let content = result.text;
490
- if (!content) {
491
- // support generate Object
492
- content = result.toolCalls?.[0].args || JSON.stringify(result);
493
- }
596
+ let content = mapVercelOutput(result);
597
+ // let tools = result.toolCalls
598
+ let providerMetadata = result.providerMetadata;
599
+ let additionalTokenValues = {
600
+ ...(providerMetadata?.openai?.reasoningTokens ? {
601
+ reasoningTokens: providerMetadata.openai.reasoningTokens
602
+ } : {}),
603
+ ...(providerMetadata?.openai?.cachedPromptTokens ? {
604
+ cacheReadInputTokens: providerMetadata.openai.cachedPromptTokens
605
+ } : {}),
606
+ ...(providerMetadata?.anthropic ? {
607
+ cacheReadInputTokens: providerMetadata.anthropic.cacheReadInputTokens,
608
+ cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
609
+ } : {})
610
+ };
494
611
  sendEventToPosthog({
495
612
  client: phClient,
496
613
  distinctId: options.posthogDistinctId,
@@ -508,7 +625,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
508
625
  httpStatus: 200,
509
626
  usage: {
510
627
  inputTokens: result.usage.promptTokens,
511
- outputTokens: result.usage.completionTokens
628
+ outputTokens: result.usage.completionTokens,
629
+ ...additionalTokenValues
512
630
  }
513
631
  });
514
632
  return result;
@@ -565,6 +683,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
565
683
  inputTokens: chunk.usage?.promptTokens,
566
684
  outputTokens: chunk.usage?.completionTokens
567
685
  };
686
+ if (chunk.providerMetadata?.openai?.reasoningTokens) {
687
+ usage.reasoningTokens = chunk.providerMetadata.openai.reasoningTokens;
688
+ }
689
+ if (chunk.providerMetadata?.openai?.cachedPromptTokens) {
690
+ usage.cacheReadInputTokens = chunk.providerMetadata.openai.cachedPromptTokens;
691
+ }
692
+ if (chunk.providerMetadata?.anthropic?.cacheReadInputTokens) {
693
+ usage.cacheReadInputTokens = chunk.providerMetadata.anthropic.cacheReadInputTokens;
694
+ }
695
+ if (chunk.providerMetadata?.anthropic?.cacheCreationInputTokens) {
696
+ usage.cacheCreationInputTokens = chunk.providerMetadata.anthropic.cacheCreationInputTokens;
697
+ }
568
698
  }
569
699
  controller.enqueue(chunk);
570
700
  },
@@ -667,7 +797,9 @@ class WrappedMessages extends AnthropicOriginal.Messages {
667
797
  let accumulatedContent = '';
668
798
  const usage = {
669
799
  inputTokens: 0,
670
- outputTokens: 0
800
+ outputTokens: 0,
801
+ cacheCreationInputTokens: 0,
802
+ cacheReadInputTokens: 0
671
803
  };
672
804
  if ('tee' in value) {
673
805
  const [stream1, stream2] = value.tee();
@@ -682,6 +814,8 @@ class WrappedMessages extends AnthropicOriginal.Messages {
682
814
  }
683
815
  if (chunk.type == 'message_start') {
684
816
  usage.inputTokens = chunk.message.usage.input_tokens ?? 0;
817
+ usage.cacheCreationInputTokens = chunk.message.usage.cache_creation_input_tokens ?? 0;
818
+ usage.cacheReadInputTokens = chunk.message.usage.cache_read_input_tokens ?? 0;
685
819
  }
686
820
  if ('usage' in chunk) {
687
821
  usage.outputTokens = chunk.usage.output_tokens ?? 0;
@@ -751,7 +885,9 @@ class WrappedMessages extends AnthropicOriginal.Messages {
751
885
  httpStatus: 200,
752
886
  usage: {
753
887
  inputTokens: result.usage.input_tokens ?? 0,
754
- outputTokens: result.usage.output_tokens ?? 0
888
+ outputTokens: result.usage.output_tokens ?? 0,
889
+ cacheCreationInputTokens: result.usage.cache_creation_input_tokens ?? 0,
890
+ cacheReadInputTokens: result.usage.cache_read_input_tokens ?? 0
755
891
  }
756
892
  });
757
893
  }
@@ -1522,6 +1658,9 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
1522
1658
  $ai_latency: latency,
1523
1659
  $ai_base_url: run.baseUrl
1524
1660
  };
1661
+ if (run.tools) {
1662
+ eventProperties['$ai_tools'] = withPrivacyMode(this.client, this.privacyMode, run.tools);
1663
+ }
1525
1664
  if (output instanceof Error) {
1526
1665
  eventProperties['$ai_http_status'] = output.status || 500;
1527
1666
  eventProperties['$ai_error'] = output.toString();