@posthog/ai 3.2.1 → 3.3.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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 3.3.0 - 2025-03-08
2
+
3
+ - feat: add reasoning and cache tokens to openai and anthropic
4
+ - feat: add tool support for vercel
5
+ - feat: add support for other media types vercel
6
+
1
7
  # 3.2.1 - 2025-02-11
2
8
 
3
9
  - fix: add experimental_wrapLanguageModel to vercel middleware supporting older versions of ai
package/lib/index.cjs.js CHANGED
@@ -100,7 +100,8 @@ const sendEventToPosthog = ({
100
100
  httpStatus = 200,
101
101
  usage = {},
102
102
  isError = false,
103
- error
103
+ error,
104
+ tools
104
105
  }) => {
105
106
  if (client.capture) {
106
107
  let errorData = {};
@@ -120,6 +121,17 @@ const sendEventToPosthog = ({
120
121
  $ai_total_cost_usd: inputCostUSD + outputCostUSD
121
122
  };
122
123
  }
124
+ let additionalTokenValues = {
125
+ ...(usage.reasoningTokens ? {
126
+ $ai_reasoning_tokens: usage.reasoningTokens
127
+ } : {}),
128
+ ...(usage.cacheReadInputTokens ? {
129
+ $ai_cache_read_input_tokens: usage.cacheReadInputTokens
130
+ } : {}),
131
+ ...(usage.cacheCreationInputTokens ? {
132
+ $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
133
+ } : {})
134
+ };
123
135
  client.capture({
124
136
  distinctId: distinctId ?? traceId,
125
137
  event: '$ai_generation',
@@ -132,6 +144,7 @@ const sendEventToPosthog = ({
132
144
  $ai_http_status: httpStatus,
133
145
  $ai_input_tokens: usage.inputTokens ?? 0,
134
146
  $ai_output_tokens: usage.outputTokens ?? 0,
147
+ ...additionalTokenValues,
135
148
  $ai_latency: latency,
136
149
  $ai_trace_id: traceId,
137
150
  $ai_base_url: baseURL,
@@ -139,6 +152,9 @@ const sendEventToPosthog = ({
139
152
  ...(distinctId ? {} : {
140
153
  $process_person_profile: false
141
154
  }),
155
+ ...(tools ? {
156
+ $ai_tools: tools
157
+ } : {}),
142
158
  ...errorData,
143
159
  ...costOverrideData
144
160
  },
@@ -200,7 +216,9 @@ class WrappedCompletions$1 extends OpenAIOrignal__default["default"].Chat.Comple
200
216
  if (chunk.usage) {
201
217
  usage = {
202
218
  inputTokens: chunk.usage.prompt_tokens ?? 0,
203
- outputTokens: chunk.usage.completion_tokens ?? 0
219
+ outputTokens: chunk.usage.completion_tokens ?? 0,
220
+ reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
221
+ cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
204
222
  };
205
223
  }
206
224
  }
@@ -267,7 +285,9 @@ class WrappedCompletions$1 extends OpenAIOrignal__default["default"].Chat.Comple
267
285
  httpStatus: 200,
268
286
  usage: {
269
287
  inputTokens: result.usage?.prompt_tokens ?? 0,
270
- outputTokens: result.usage?.completion_tokens ?? 0
288
+ outputTokens: result.usage?.completion_tokens ?? 0,
289
+ reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
290
+ cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
271
291
  }
272
292
  });
273
293
  }
@@ -356,7 +376,9 @@ class WrappedCompletions extends OpenAIOrignal.AzureOpenAI.Chat.Completions {
356
376
  }
357
377
  usage = {
358
378
  inputTokens: chunk.usage.prompt_tokens ?? 0,
359
- outputTokens: chunk.usage.completion_tokens ?? 0
379
+ outputTokens: chunk.usage.completion_tokens ?? 0,
380
+ reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
381
+ cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
360
382
  };
361
383
  }
362
384
  }
@@ -428,7 +450,9 @@ class WrappedCompletions extends OpenAIOrignal.AzureOpenAI.Chat.Completions {
428
450
  httpStatus: 200,
429
451
  usage: {
430
452
  inputTokens: result.usage?.prompt_tokens ?? 0,
431
- outputTokens: result.usage?.completion_tokens ?? 0
453
+ outputTokens: result.usage?.completion_tokens ?? 0,
454
+ reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
455
+ cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
432
456
  }
433
457
  });
434
458
  }
@@ -473,16 +497,60 @@ const mapVercelParams = params => {
473
497
  };
474
498
  const mapVercelPrompt = prompt => {
475
499
  return prompt.map(p => {
476
- let content = '';
500
+ let content = {};
477
501
  if (Array.isArray(p.content)) {
478
502
  content = p.content.map(c => {
479
503
  if (c.type === 'text') {
480
- return c.text;
504
+ return {
505
+ type: 'text',
506
+ content: c.text
507
+ };
508
+ } else if (c.type === 'image') {
509
+ return {
510
+ type: 'image',
511
+ content: {
512
+ // if image is a url use it, or use "none supported"
513
+ image: c.image instanceof URL ? c.image.toString() : 'raw images not supported',
514
+ mimeType: c.mimeType
515
+ }
516
+ };
517
+ } else if (c.type === 'file') {
518
+ return {
519
+ type: 'file',
520
+ content: {
521
+ file: c.data instanceof URL ? c.data.toString() : 'raw files not supported',
522
+ mimeType: c.mimeType
523
+ }
524
+ };
525
+ } else if (c.type === 'tool-call') {
526
+ return {
527
+ type: 'tool-call',
528
+ content: {
529
+ toolCallId: c.toolCallId,
530
+ toolName: c.toolName,
531
+ args: c.args
532
+ }
533
+ };
534
+ } else if (c.type === 'tool-result') {
535
+ return {
536
+ type: 'tool-result',
537
+ content: {
538
+ toolCallId: c.toolCallId,
539
+ toolName: c.toolName,
540
+ result: c.result,
541
+ isError: c.isError
542
+ }
543
+ };
481
544
  }
482
- return '';
483
- }).join('');
545
+ return {
546
+ content: ''
547
+ };
548
+ });
484
549
  } else {
485
- content = p.content;
550
+ content = {
551
+ type: 'text',
552
+ text: p.content
553
+ };
486
554
  }
487
555
  return {
488
556
  role: p.role,
@@ -513,11 +581,21 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
513
581
  const modelId = options.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
514
582
  const provider = options.posthogProviderOverride ?? extractProvider(model);
515
583
  const baseURL = ''; // cannot currently get baseURL from vercel
516
- let content = result.text;
517
- if (!content) {
518
- // support generate Object
519
- content = result.toolCalls?.[0].args || JSON.stringify(result);
520
- }
584
+ let content = result.text || JSON.stringify(result);
585
+ // let tools = result.toolCalls
586
+ let providerMetadata = result.providerMetadata;
587
+ let additionalTokenValues = {
588
+ ...(providerMetadata?.openai?.reasoningTokens ? {
589
+ reasoningTokens: providerMetadata.openai.reasoningTokens
590
+ } : {}),
591
+ ...(providerMetadata?.openai?.cachedPromptToken ? {
592
+ cacheReadInputTokens: providerMetadata.openai.cachedPromptTokens
593
+ } : {}),
594
+ ...(providerMetadata?.anthropic ? {
595
+ cacheReadInputTokens: providerMetadata.anthropic.cacheReadInputTokens,
596
+ cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
597
+ } : {})
598
+ };
521
599
  sendEventToPosthog({
522
600
  client: phClient,
523
601
  distinctId: options.posthogDistinctId,
@@ -535,7 +613,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
535
613
  httpStatus: 200,
536
614
  usage: {
537
615
  inputTokens: result.usage.promptTokens,
538
- outputTokens: result.usage.completionTokens
616
+ outputTokens: result.usage.completionTokens,
617
+ ...additionalTokenValues
539
618
  }
540
619
  });
541
620
  return result;
@@ -592,6 +671,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
592
671
  inputTokens: chunk.usage?.promptTokens,
593
672
  outputTokens: chunk.usage?.completionTokens
594
673
  };
674
+ if (chunk.providerMetadata?.openai?.reasoningTokens) {
675
+ usage.reasoningTokens = chunk.providerMetadata.openai.reasoningTokens;
676
+ }
677
+ if (chunk.providerMetadata?.openai?.cachedPromptToken) {
678
+ usage.cacheReadInputTokens = chunk.providerMetadata.openai.cachedPromptToken;
679
+ }
680
+ if (chunk.providerMetadata?.anthropic?.cacheReadInputTokens) {
681
+ usage.cacheReadInputTokens = chunk.providerMetadata.anthropic.cacheReadInputTokens;
682
+ }
683
+ if (chunk.providerMetadata?.anthropic?.cacheCreationInputTokens) {
684
+ usage.cacheCreationInputTokens = chunk.providerMetadata.anthropic.cacheCreationInputTokens;
685
+ }
595
686
  }
596
687
  controller.enqueue(chunk);
597
688
  },
@@ -694,7 +785,9 @@ class WrappedMessages extends AnthropicOriginal__default["default"].Messages {
694
785
  let accumulatedContent = '';
695
786
  const usage = {
696
787
  inputTokens: 0,
697
- outputTokens: 0
788
+ outputTokens: 0,
789
+ cacheCreationInputTokens: 0,
790
+ cacheReadInputTokens: 0
698
791
  };
699
792
  if ('tee' in value) {
700
793
  const [stream1, stream2] = value.tee();
@@ -709,6 +802,8 @@ class WrappedMessages extends AnthropicOriginal__default["default"].Messages {
709
802
  }
710
803
  if (chunk.type == 'message_start') {
711
804
  usage.inputTokens = chunk.message.usage.input_tokens ?? 0;
805
+ usage.cacheCreationInputTokens = chunk.message.usage.cache_creation_input_tokens ?? 0;
806
+ usage.cacheReadInputTokens = chunk.message.usage.cache_read_input_tokens ?? 0;
712
807
  }
713
808
  if ('usage' in chunk) {
714
809
  usage.outputTokens = chunk.usage.output_tokens ?? 0;
@@ -778,7 +873,9 @@ class WrappedMessages extends AnthropicOriginal__default["default"].Messages {
778
873
  httpStatus: 200,
779
874
  usage: {
780
875
  inputTokens: result.usage.input_tokens ?? 0,
781
- outputTokens: result.usage.output_tokens ?? 0
876
+ outputTokens: result.usage.output_tokens ?? 0,
877
+ cacheCreationInputTokens: result.usage.cache_creation_input_tokens ?? 0,
878
+ cacheReadInputTokens: result.usage.cache_read_input_tokens ?? 0
782
879
  }
783
880
  });
784
881
  }
@@ -1549,6 +1646,9 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
1549
1646
  $ai_latency: latency,
1550
1647
  $ai_base_url: run.baseUrl
1551
1648
  };
1649
+ if (run.tools) {
1650
+ eventProperties['$ai_tools'] = withPrivacyMode(this.client, this.privacyMode, run.tools);
1651
+ }
1552
1652
  if (output instanceof Error) {
1553
1653
  eventProperties['$ai_http_status'] = output.status || 500;
1554
1654
  eventProperties['$ai_error'] = output.toString();