@posthog/ai 7.2.1 → 7.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/dist/anthropic/index.cjs +13 -3
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +13 -3
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +69 -8
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +1 -0
- package/dist/gemini/index.mjs +69 -8
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +253 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +253 -151
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +13 -2
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +13 -2
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +48 -14
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +48 -14
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +141 -113
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.d.ts +7 -2
- package/dist/vercel/index.mjs +141 -113
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +17 -12
package/dist/index.mjs
CHANGED
|
@@ -2,11 +2,10 @@ import { OpenAI, AzureOpenAI } from 'openai';
|
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
3
|
import * as uuid from 'uuid';
|
|
4
4
|
import { v4 } from 'uuid';
|
|
5
|
-
import { wrapLanguageModel } from 'ai';
|
|
6
5
|
import AnthropicOriginal from '@anthropic-ai/sdk';
|
|
7
6
|
import { GoogleGenAI } from '@google/genai';
|
|
8
7
|
|
|
9
|
-
var version = "7.
|
|
8
|
+
var version = "7.3.0";
|
|
10
9
|
|
|
11
10
|
// Type guards for safer type checking
|
|
12
11
|
const isString = value => {
|
|
@@ -113,6 +112,13 @@ const formatResponseOpenAI = response => {
|
|
|
113
112
|
});
|
|
114
113
|
}
|
|
115
114
|
}
|
|
115
|
+
// Handle audio output (gpt-4o-audio-preview)
|
|
116
|
+
if (choice.message.audio) {
|
|
117
|
+
content.push({
|
|
118
|
+
type: 'audio',
|
|
119
|
+
...choice.message.audio
|
|
120
|
+
});
|
|
121
|
+
}
|
|
116
122
|
}
|
|
117
123
|
if (content.length > 0) {
|
|
118
124
|
output.push({
|
|
@@ -194,6 +200,19 @@ const formatResponseGemini = response => {
|
|
|
194
200
|
arguments: part.functionCall.args
|
|
195
201
|
}
|
|
196
202
|
});
|
|
203
|
+
} else if (part.inlineData) {
|
|
204
|
+
// Handle audio/media inline data
|
|
205
|
+
const mimeType = part.inlineData.mimeType || 'audio/pcm';
|
|
206
|
+
let data = part.inlineData.data;
|
|
207
|
+
// Handle binary data (Buffer/Uint8Array -> base64)
|
|
208
|
+
if (data instanceof Uint8Array || Buffer.isBuffer(data)) {
|
|
209
|
+
data = Buffer.from(data).toString('base64');
|
|
210
|
+
}
|
|
211
|
+
content.push({
|
|
212
|
+
type: 'audio',
|
|
213
|
+
mime_type: mimeType,
|
|
214
|
+
data: data
|
|
215
|
+
});
|
|
197
216
|
}
|
|
198
217
|
}
|
|
199
218
|
if (content.length > 0) {
|
|
@@ -598,6 +617,13 @@ function formatOpenAIResponsesInput(input, instructions) {
|
|
|
598
617
|
|
|
599
618
|
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
600
619
|
// ============================================
|
|
620
|
+
// Multimodal Feature Toggle
|
|
621
|
+
// ============================================
|
|
622
|
+
const isMultimodalEnabled = () => {
|
|
623
|
+
const val = process.env._INTERNAL_LLMA_MULTIMODAL || '';
|
|
624
|
+
return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes';
|
|
625
|
+
};
|
|
626
|
+
// ============================================
|
|
601
627
|
// Base64 Detection Helpers
|
|
602
628
|
// ============================================
|
|
603
629
|
const isBase64DataUrl = str => {
|
|
@@ -622,6 +648,7 @@ const isRawBase64 = str => {
|
|
|
622
648
|
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
623
649
|
};
|
|
624
650
|
function redactBase64DataUrl(str) {
|
|
651
|
+
if (isMultimodalEnabled()) return str;
|
|
625
652
|
if (!isString(str)) return str;
|
|
626
653
|
// Check for data URL format
|
|
627
654
|
if (isBase64DataUrl(str)) {
|
|
@@ -672,12 +699,21 @@ const sanitizeOpenAIImage = item => {
|
|
|
672
699
|
}
|
|
673
700
|
};
|
|
674
701
|
}
|
|
702
|
+
// Handle audio format
|
|
703
|
+
if (item.type === 'audio' && 'data' in item) {
|
|
704
|
+
if (isMultimodalEnabled()) return item;
|
|
705
|
+
return {
|
|
706
|
+
...item,
|
|
707
|
+
data: REDACTED_IMAGE_PLACEHOLDER
|
|
708
|
+
};
|
|
709
|
+
}
|
|
675
710
|
return item;
|
|
676
711
|
};
|
|
677
712
|
const sanitizeAnthropicImage = item => {
|
|
713
|
+
if (isMultimodalEnabled()) return item;
|
|
678
714
|
if (!isObject(item)) return item;
|
|
679
|
-
// Handle Anthropic's image
|
|
680
|
-
if (item.type === 'image' && 'source' in item && isObject(item.source) && item.source.type === 'base64' && 'data' in item.source) {
|
|
715
|
+
// Handle Anthropic's image and document formats (same structure, different type field)
|
|
716
|
+
if ((item.type === 'image' || item.type === 'document') && 'source' in item && isObject(item.source) && item.source.type === 'base64' && 'data' in item.source) {
|
|
681
717
|
return {
|
|
682
718
|
...item,
|
|
683
719
|
source: {
|
|
@@ -689,8 +725,9 @@ const sanitizeAnthropicImage = item => {
|
|
|
689
725
|
return item;
|
|
690
726
|
};
|
|
691
727
|
const sanitizeGeminiPart = part => {
|
|
728
|
+
if (isMultimodalEnabled()) return part;
|
|
692
729
|
if (!isObject(part)) return part;
|
|
693
|
-
// Handle Gemini's inline data format
|
|
730
|
+
// Handle Gemini's inline data format (images, audio, PDFs all use inlineData)
|
|
694
731
|
if ('inlineData' in part && isObject(part.inlineData) && 'data' in part.inlineData) {
|
|
695
732
|
return {
|
|
696
733
|
...part,
|
|
@@ -735,6 +772,7 @@ const sanitizeLangChainImage = item => {
|
|
|
735
772
|
}
|
|
736
773
|
// Anthropic style
|
|
737
774
|
if (item.type === 'image' && 'source' in item && isObject(item.source) && 'data' in item.source) {
|
|
775
|
+
if (isMultimodalEnabled()) return item;
|
|
738
776
|
return {
|
|
739
777
|
...item,
|
|
740
778
|
source: {
|
|
@@ -820,6 +858,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
820
858
|
try {
|
|
821
859
|
const contentBlocks = [];
|
|
822
860
|
let accumulatedContent = '';
|
|
861
|
+
let modelFromResponse;
|
|
823
862
|
let usage = {
|
|
824
863
|
inputTokens: 0,
|
|
825
864
|
outputTokens: 0,
|
|
@@ -828,6 +867,10 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
828
867
|
// Map to track in-progress tool calls
|
|
829
868
|
const toolCallsInProgress = new Map();
|
|
830
869
|
for await (const chunk of stream1) {
|
|
870
|
+
// Extract model from chunk (Chat Completions chunks have model field)
|
|
871
|
+
if (!modelFromResponse && chunk.model) {
|
|
872
|
+
modelFromResponse = chunk.model;
|
|
873
|
+
}
|
|
831
874
|
const choice = chunk?.choices?.[0];
|
|
832
875
|
const chunkWebSearchCount = calculateWebSearchCount(chunk);
|
|
833
876
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
@@ -915,7 +958,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
915
958
|
await sendEventToPosthog({
|
|
916
959
|
client: this.phClient,
|
|
917
960
|
...posthogParams,
|
|
918
|
-
model: openAIParams.model,
|
|
961
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
919
962
|
provider: 'openai',
|
|
920
963
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
921
964
|
output: formattedOutput,
|
|
@@ -968,7 +1011,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
968
1011
|
await sendEventToPosthog({
|
|
969
1012
|
client: this.phClient,
|
|
970
1013
|
...posthogParams,
|
|
971
|
-
model: openAIParams.model,
|
|
1014
|
+
model: openAIParams.model ?? result.model,
|
|
972
1015
|
provider: 'openai',
|
|
973
1016
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
974
1017
|
output: formattedOutput,
|
|
@@ -992,7 +1035,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
992
1035
|
await sendEventToPosthog({
|
|
993
1036
|
client: this.phClient,
|
|
994
1037
|
...posthogParams,
|
|
995
|
-
model:
|
|
1038
|
+
model: openAIParams.model,
|
|
996
1039
|
provider: 'openai',
|
|
997
1040
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
998
1041
|
output: [],
|
|
@@ -1034,6 +1077,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1034
1077
|
(async () => {
|
|
1035
1078
|
try {
|
|
1036
1079
|
let finalContent = [];
|
|
1080
|
+
let modelFromResponse;
|
|
1037
1081
|
let usage = {
|
|
1038
1082
|
inputTokens: 0,
|
|
1039
1083
|
outputTokens: 0,
|
|
@@ -1041,6 +1085,10 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1041
1085
|
};
|
|
1042
1086
|
for await (const chunk of stream1) {
|
|
1043
1087
|
if ('response' in chunk && chunk.response) {
|
|
1088
|
+
// Extract model from response object in chunk (for stored prompts)
|
|
1089
|
+
if (!modelFromResponse && chunk.response.model) {
|
|
1090
|
+
modelFromResponse = chunk.response.model;
|
|
1091
|
+
}
|
|
1044
1092
|
const chunkWebSearchCount = calculateWebSearchCount(chunk.response);
|
|
1045
1093
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
1046
1094
|
usage.webSearchCount = chunkWebSearchCount;
|
|
@@ -1064,8 +1112,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1064
1112
|
await sendEventToPosthog({
|
|
1065
1113
|
client: this.phClient,
|
|
1066
1114
|
...posthogParams,
|
|
1067
|
-
|
|
1068
|
-
model: openAIParams.model,
|
|
1115
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1069
1116
|
provider: 'openai',
|
|
1070
1117
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1071
1118
|
output: finalContent,
|
|
@@ -1087,7 +1134,6 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1087
1134
|
await sendEventToPosthog({
|
|
1088
1135
|
client: this.phClient,
|
|
1089
1136
|
...posthogParams,
|
|
1090
|
-
//@ts-expect-error
|
|
1091
1137
|
model: openAIParams.model,
|
|
1092
1138
|
provider: 'openai',
|
|
1093
1139
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
@@ -1120,8 +1166,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1120
1166
|
await sendEventToPosthog({
|
|
1121
1167
|
client: this.phClient,
|
|
1122
1168
|
...posthogParams,
|
|
1123
|
-
|
|
1124
|
-
model: openAIParams.model,
|
|
1169
|
+
model: openAIParams.model ?? result.model,
|
|
1125
1170
|
provider: 'openai',
|
|
1126
1171
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1127
1172
|
output: formattedOutput,
|
|
@@ -1145,7 +1190,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1145
1190
|
await sendEventToPosthog({
|
|
1146
1191
|
client: this.phClient,
|
|
1147
1192
|
...posthogParams,
|
|
1148
|
-
model:
|
|
1193
|
+
model: openAIParams.model,
|
|
1149
1194
|
provider: 'openai',
|
|
1150
1195
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1151
1196
|
output: [],
|
|
@@ -1182,7 +1227,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1182
1227
|
await sendEventToPosthog({
|
|
1183
1228
|
client: this.phClient,
|
|
1184
1229
|
...posthogParams,
|
|
1185
|
-
model:
|
|
1230
|
+
model: openAIParams.model ?? result.model,
|
|
1186
1231
|
provider: 'openai',
|
|
1187
1232
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1188
1233
|
output: result.output,
|
|
@@ -1203,7 +1248,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1203
1248
|
await sendEventToPosthog({
|
|
1204
1249
|
client: this.phClient,
|
|
1205
1250
|
...posthogParams,
|
|
1206
|
-
model:
|
|
1251
|
+
model: openAIParams.model,
|
|
1207
1252
|
provider: 'openai',
|
|
1208
1253
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1209
1254
|
output: [],
|
|
@@ -1378,7 +1423,7 @@ class WrappedTranscriptions extends Transcriptions {
|
|
|
1378
1423
|
await sendEventToPosthog({
|
|
1379
1424
|
client: this.phClient,
|
|
1380
1425
|
...posthogParams,
|
|
1381
|
-
model:
|
|
1426
|
+
model: openAIParams.model,
|
|
1382
1427
|
provider: 'openai',
|
|
1383
1428
|
input: openAIParams.prompt,
|
|
1384
1429
|
output: result.text,
|
|
@@ -1398,7 +1443,7 @@ class WrappedTranscriptions extends Transcriptions {
|
|
|
1398
1443
|
await sendEventToPosthog({
|
|
1399
1444
|
client: this.phClient,
|
|
1400
1445
|
...posthogParams,
|
|
1401
|
-
model:
|
|
1446
|
+
model: openAIParams.model,
|
|
1402
1447
|
provider: 'openai',
|
|
1403
1448
|
input: openAIParams.prompt,
|
|
1404
1449
|
output: [],
|
|
@@ -1460,6 +1505,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1460
1505
|
try {
|
|
1461
1506
|
const contentBlocks = [];
|
|
1462
1507
|
let accumulatedContent = '';
|
|
1508
|
+
let modelFromResponse;
|
|
1463
1509
|
let usage = {
|
|
1464
1510
|
inputTokens: 0,
|
|
1465
1511
|
outputTokens: 0
|
|
@@ -1467,6 +1513,10 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1467
1513
|
// Map to track in-progress tool calls
|
|
1468
1514
|
const toolCallsInProgress = new Map();
|
|
1469
1515
|
for await (const chunk of stream1) {
|
|
1516
|
+
// Extract model from response if not in params
|
|
1517
|
+
if (!modelFromResponse && chunk.model) {
|
|
1518
|
+
modelFromResponse = chunk.model;
|
|
1519
|
+
}
|
|
1470
1520
|
const choice = chunk?.choices?.[0];
|
|
1471
1521
|
// Handle text content
|
|
1472
1522
|
const deltaContent = choice?.delta?.content;
|
|
@@ -1548,7 +1598,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1548
1598
|
await sendEventToPosthog({
|
|
1549
1599
|
client: this.phClient,
|
|
1550
1600
|
...posthogParams,
|
|
1551
|
-
model: openAIParams.model,
|
|
1601
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1552
1602
|
provider: 'azure',
|
|
1553
1603
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
1554
1604
|
output: formattedOutput,
|
|
@@ -1592,7 +1642,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1592
1642
|
await sendEventToPosthog({
|
|
1593
1643
|
client: this.phClient,
|
|
1594
1644
|
...posthogParams,
|
|
1595
|
-
model: openAIParams.model,
|
|
1645
|
+
model: openAIParams.model ?? result.model,
|
|
1596
1646
|
provider: 'azure',
|
|
1597
1647
|
input: openAIParams.messages,
|
|
1598
1648
|
output: formatResponseOpenAI(result),
|
|
@@ -1656,11 +1706,18 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1656
1706
|
(async () => {
|
|
1657
1707
|
try {
|
|
1658
1708
|
let finalContent = [];
|
|
1709
|
+
let modelFromResponse;
|
|
1659
1710
|
let usage = {
|
|
1660
1711
|
inputTokens: 0,
|
|
1661
1712
|
outputTokens: 0
|
|
1662
1713
|
};
|
|
1663
1714
|
for await (const chunk of stream1) {
|
|
1715
|
+
if ('response' in chunk && chunk.response) {
|
|
1716
|
+
// Extract model from response if not in params (for stored prompts)
|
|
1717
|
+
if (!modelFromResponse && chunk.response.model) {
|
|
1718
|
+
modelFromResponse = chunk.response.model;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1664
1721
|
if (chunk.type === 'response.completed' && 'response' in chunk && chunk.response?.output && chunk.response.output.length > 0) {
|
|
1665
1722
|
finalContent = chunk.response.output;
|
|
1666
1723
|
}
|
|
@@ -1677,10 +1734,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1677
1734
|
await sendEventToPosthog({
|
|
1678
1735
|
client: this.phClient,
|
|
1679
1736
|
...posthogParams,
|
|
1680
|
-
|
|
1681
|
-
model: openAIParams.model,
|
|
1737
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1682
1738
|
provider: 'azure',
|
|
1683
|
-
input: openAIParams.input,
|
|
1739
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1684
1740
|
output: finalContent,
|
|
1685
1741
|
latency,
|
|
1686
1742
|
baseURL: this.baseURL,
|
|
@@ -1693,10 +1749,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1693
1749
|
await sendEventToPosthog({
|
|
1694
1750
|
client: this.phClient,
|
|
1695
1751
|
...posthogParams,
|
|
1696
|
-
//@ts-expect-error
|
|
1697
1752
|
model: openAIParams.model,
|
|
1698
1753
|
provider: 'azure',
|
|
1699
|
-
input: openAIParams.input,
|
|
1754
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1700
1755
|
output: [],
|
|
1701
1756
|
latency: 0,
|
|
1702
1757
|
baseURL: this.baseURL,
|
|
@@ -1722,10 +1777,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1722
1777
|
await sendEventToPosthog({
|
|
1723
1778
|
client: this.phClient,
|
|
1724
1779
|
...posthogParams,
|
|
1725
|
-
|
|
1726
|
-
model: openAIParams.model,
|
|
1780
|
+
model: openAIParams.model ?? result.model,
|
|
1727
1781
|
provider: 'azure',
|
|
1728
|
-
input: openAIParams.input,
|
|
1782
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1729
1783
|
output: result.output,
|
|
1730
1784
|
latency,
|
|
1731
1785
|
baseURL: this.baseURL,
|
|
@@ -1745,10 +1799,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1745
1799
|
await sendEventToPosthog({
|
|
1746
1800
|
client: this.phClient,
|
|
1747
1801
|
...posthogParams,
|
|
1748
|
-
//@ts-expect-error
|
|
1749
1802
|
model: openAIParams.model,
|
|
1750
1803
|
provider: 'azure',
|
|
1751
|
-
input: openAIParams.input,
|
|
1804
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1752
1805
|
output: [],
|
|
1753
1806
|
latency: 0,
|
|
1754
1807
|
baseURL: this.baseURL,
|
|
@@ -1778,9 +1831,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1778
1831
|
await sendEventToPosthog({
|
|
1779
1832
|
client: this.phClient,
|
|
1780
1833
|
...posthogParams,
|
|
1781
|
-
model:
|
|
1834
|
+
model: openAIParams.model ?? result.model,
|
|
1782
1835
|
provider: 'azure',
|
|
1783
|
-
input: openAIParams.input,
|
|
1836
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1784
1837
|
output: result.output,
|
|
1785
1838
|
latency,
|
|
1786
1839
|
baseURL: this.baseURL,
|
|
@@ -1798,9 +1851,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1798
1851
|
await sendEventToPosthog({
|
|
1799
1852
|
client: this.phClient,
|
|
1800
1853
|
...posthogParams,
|
|
1801
|
-
model:
|
|
1854
|
+
model: openAIParams.model,
|
|
1802
1855
|
provider: 'azure',
|
|
1803
|
-
input: openAIParams.input,
|
|
1856
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1804
1857
|
output: [],
|
|
1805
1858
|
latency: 0,
|
|
1806
1859
|
baseURL: this.baseURL,
|
|
@@ -2073,67 +2126,117 @@ const extractProvider = model => {
|
|
|
2073
2126
|
const providerName = provider.split('.')[0];
|
|
2074
2127
|
return providerName;
|
|
2075
2128
|
};
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2129
|
+
// Extract web search count from provider metadata (works for both V2 and V3)
|
|
2130
|
+
const extractWebSearchCount = (providerMetadata, usage) => {
|
|
2131
|
+
// Try Anthropic-specific extraction
|
|
2132
|
+
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
2133
|
+
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
2134
|
+
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
2135
|
+
return serverToolUse.web_search_requests;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
// Fall back to generic calculation
|
|
2139
|
+
return calculateWebSearchCount({
|
|
2140
|
+
usage,
|
|
2141
|
+
providerMetadata
|
|
2142
|
+
});
|
|
2143
|
+
};
|
|
2144
|
+
// Extract additional token values from provider metadata
|
|
2145
|
+
const extractAdditionalTokenValues = providerMetadata => {
|
|
2146
|
+
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'cacheCreationInputTokens' in providerMetadata.anthropic) {
|
|
2147
|
+
return {
|
|
2148
|
+
cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
return {};
|
|
2152
|
+
};
|
|
2153
|
+
// Helper to extract numeric token value from V2 (number) or V3 (object with .total) usage formats
|
|
2154
|
+
const extractTokenCount = value => {
|
|
2155
|
+
if (typeof value === 'number') {
|
|
2156
|
+
return value;
|
|
2157
|
+
}
|
|
2158
|
+
if (value && typeof value === 'object' && 'total' in value && typeof value.total === 'number') {
|
|
2159
|
+
return value.total;
|
|
2160
|
+
}
|
|
2161
|
+
return undefined;
|
|
2162
|
+
};
|
|
2163
|
+
// Helper to extract reasoning tokens from V2 (usage.reasoningTokens) or V3 (usage.outputTokens.reasoning)
|
|
2164
|
+
const extractReasoningTokens = usage => {
|
|
2165
|
+
// V2 style: top-level reasoningTokens
|
|
2166
|
+
if ('reasoningTokens' in usage) {
|
|
2167
|
+
return usage.reasoningTokens;
|
|
2168
|
+
}
|
|
2169
|
+
// V3 style: nested in outputTokens.reasoning
|
|
2170
|
+
if ('outputTokens' in usage && usage.outputTokens && typeof usage.outputTokens === 'object' && 'reasoning' in usage.outputTokens) {
|
|
2171
|
+
return usage.outputTokens.reasoning;
|
|
2172
|
+
}
|
|
2173
|
+
return undefined;
|
|
2174
|
+
};
|
|
2175
|
+
// Helper to extract cached input tokens from V2 (usage.cachedInputTokens) or V3 (usage.inputTokens.cacheRead)
|
|
2176
|
+
const extractCacheReadTokens = usage => {
|
|
2177
|
+
// V2 style: top-level cachedInputTokens
|
|
2178
|
+
if ('cachedInputTokens' in usage) {
|
|
2179
|
+
return usage.cachedInputTokens;
|
|
2180
|
+
}
|
|
2181
|
+
// V3 style: nested in inputTokens.cacheRead
|
|
2182
|
+
if ('inputTokens' in usage && usage.inputTokens && typeof usage.inputTokens === 'object' && 'cacheRead' in usage.inputTokens) {
|
|
2183
|
+
return usage.inputTokens.cacheRead;
|
|
2184
|
+
}
|
|
2185
|
+
return undefined;
|
|
2186
|
+
};
|
|
2187
|
+
/**
|
|
2188
|
+
* Wraps a Vercel AI SDK language model (V2 or V3) with PostHog tracing.
|
|
2189
|
+
* Automatically detects the model version and applies appropriate instrumentation.
|
|
2190
|
+
*/
|
|
2191
|
+
const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
2192
|
+
const traceId = options.posthogTraceId ?? v4();
|
|
2193
|
+
const mergedOptions = {
|
|
2194
|
+
...options,
|
|
2195
|
+
posthogTraceId: traceId,
|
|
2196
|
+
posthogDistinctId: options.posthogDistinctId,
|
|
2197
|
+
posthogProperties: {
|
|
2198
|
+
...options.posthogProperties,
|
|
2199
|
+
$ai_framework: 'vercel',
|
|
2200
|
+
$ai_framework_version: model.specificationVersion === 'v3' ? '6' : '5'
|
|
2201
|
+
}
|
|
2202
|
+
};
|
|
2203
|
+
// Create wrapped model that preserves the original type
|
|
2204
|
+
const wrappedModel = {
|
|
2205
|
+
...model,
|
|
2206
|
+
doGenerate: async params => {
|
|
2082
2207
|
const startTime = Date.now();
|
|
2083
2208
|
const mergedParams = {
|
|
2084
|
-
...
|
|
2085
|
-
...mapVercelParams(params)
|
|
2086
|
-
posthogProperties: {
|
|
2087
|
-
...options.posthogProperties,
|
|
2088
|
-
$ai_framework: 'vercel'
|
|
2089
|
-
}
|
|
2209
|
+
...mergedOptions,
|
|
2210
|
+
...mapVercelParams(params)
|
|
2090
2211
|
};
|
|
2091
2212
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
2092
2213
|
try {
|
|
2093
|
-
const result = await doGenerate();
|
|
2094
|
-
const modelId =
|
|
2095
|
-
const provider =
|
|
2214
|
+
const result = await model.doGenerate(params);
|
|
2215
|
+
const modelId = mergedOptions.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
|
|
2216
|
+
const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
|
|
2096
2217
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
2097
2218
|
const content = mapVercelOutput(result.content);
|
|
2098
2219
|
const latency = (Date.now() - startTime) / 1000;
|
|
2099
2220
|
const providerMetadata = result.providerMetadata;
|
|
2100
|
-
const additionalTokenValues =
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
};
|
|
2105
|
-
// Calculate web search count based on provider
|
|
2106
|
-
let webSearchCount = 0;
|
|
2107
|
-
if (providerMetadata?.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
2108
|
-
// Anthropic-specific extraction
|
|
2109
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
2110
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
2111
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
2112
|
-
}
|
|
2113
|
-
} else {
|
|
2114
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
2115
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
2116
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
2117
|
-
webSearchCount = calculateWebSearchCount({
|
|
2118
|
-
usage: result.usage,
|
|
2119
|
-
providerMetadata: providerMetadata
|
|
2120
|
-
});
|
|
2121
|
-
}
|
|
2221
|
+
const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
|
|
2222
|
+
const webSearchCount = extractWebSearchCount(providerMetadata, result.usage);
|
|
2223
|
+
// V2 usage has simple numbers, V3 has objects with .total - normalize both
|
|
2224
|
+
const usageObj = result.usage;
|
|
2122
2225
|
const usage = {
|
|
2123
|
-
inputTokens: result.usage.inputTokens,
|
|
2124
|
-
outputTokens: result.usage.outputTokens,
|
|
2125
|
-
reasoningTokens:
|
|
2126
|
-
cacheReadInputTokens:
|
|
2226
|
+
inputTokens: extractTokenCount(result.usage.inputTokens),
|
|
2227
|
+
outputTokens: extractTokenCount(result.usage.outputTokens),
|
|
2228
|
+
reasoningTokens: extractReasoningTokens(usageObj),
|
|
2229
|
+
cacheReadInputTokens: extractCacheReadTokens(usageObj),
|
|
2127
2230
|
webSearchCount,
|
|
2128
2231
|
...additionalTokenValues
|
|
2129
2232
|
};
|
|
2130
2233
|
await sendEventToPosthog({
|
|
2131
2234
|
client: phClient,
|
|
2132
|
-
distinctId:
|
|
2133
|
-
traceId:
|
|
2235
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2236
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2134
2237
|
model: modelId,
|
|
2135
2238
|
provider: provider,
|
|
2136
|
-
input:
|
|
2239
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2137
2240
|
output: content,
|
|
2138
2241
|
latency,
|
|
2139
2242
|
baseURL,
|
|
@@ -2141,18 +2244,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2141
2244
|
httpStatus: 200,
|
|
2142
2245
|
usage,
|
|
2143
2246
|
tools: availableTools,
|
|
2144
|
-
captureImmediate:
|
|
2247
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2145
2248
|
});
|
|
2146
2249
|
return result;
|
|
2147
2250
|
} catch (error) {
|
|
2148
2251
|
const modelId = model.modelId;
|
|
2149
2252
|
await sendEventToPosthog({
|
|
2150
2253
|
client: phClient,
|
|
2151
|
-
distinctId:
|
|
2152
|
-
traceId:
|
|
2254
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2255
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2153
2256
|
model: modelId,
|
|
2154
2257
|
provider: model.provider,
|
|
2155
|
-
input:
|
|
2258
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2156
2259
|
output: [],
|
|
2157
2260
|
latency: 0,
|
|
2158
2261
|
baseURL: '',
|
|
@@ -2165,30 +2268,23 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2165
2268
|
isError: true,
|
|
2166
2269
|
error: truncate(JSON.stringify(error)),
|
|
2167
2270
|
tools: availableTools,
|
|
2168
|
-
captureImmediate:
|
|
2271
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2169
2272
|
});
|
|
2170
2273
|
throw error;
|
|
2171
2274
|
}
|
|
2172
2275
|
},
|
|
2173
|
-
|
|
2174
|
-
doStream,
|
|
2175
|
-
params
|
|
2176
|
-
}) => {
|
|
2276
|
+
doStream: async params => {
|
|
2177
2277
|
const startTime = Date.now();
|
|
2178
2278
|
let generatedText = '';
|
|
2179
2279
|
let reasoningText = '';
|
|
2180
2280
|
let usage = {};
|
|
2181
2281
|
let providerMetadata = undefined;
|
|
2182
2282
|
const mergedParams = {
|
|
2183
|
-
...
|
|
2184
|
-
...mapVercelParams(params)
|
|
2185
|
-
posthogProperties: {
|
|
2186
|
-
...options.posthogProperties,
|
|
2187
|
-
$ai_framework: 'vercel'
|
|
2188
|
-
}
|
|
2283
|
+
...mergedOptions,
|
|
2284
|
+
...mapVercelParams(params)
|
|
2189
2285
|
};
|
|
2190
|
-
const modelId =
|
|
2191
|
-
const provider =
|
|
2286
|
+
const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
|
|
2287
|
+
const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
|
|
2192
2288
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
2193
2289
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
2194
2290
|
// Map to track in-progress tool calls
|
|
@@ -2197,15 +2293,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2197
2293
|
const {
|
|
2198
2294
|
stream,
|
|
2199
2295
|
...rest
|
|
2200
|
-
} = await doStream();
|
|
2296
|
+
} = await model.doStream(params);
|
|
2201
2297
|
const transformStream = new TransformStream({
|
|
2202
2298
|
transform(chunk, controller) {
|
|
2203
|
-
// Handle
|
|
2299
|
+
// Handle streaming patterns - compatible with both V2 and V3
|
|
2204
2300
|
if (chunk.type === 'text-delta') {
|
|
2205
2301
|
generatedText += chunk.delta;
|
|
2206
2302
|
}
|
|
2207
2303
|
if (chunk.type === 'reasoning-delta') {
|
|
2208
|
-
reasoningText += chunk.delta;
|
|
2304
|
+
reasoningText += chunk.delta;
|
|
2209
2305
|
}
|
|
2210
2306
|
// Handle tool call chunks
|
|
2211
2307
|
if (chunk.type === 'tool-input-start') {
|
|
@@ -2225,7 +2321,6 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2225
2321
|
}
|
|
2226
2322
|
if (chunk.type === 'tool-input-end') {
|
|
2227
2323
|
// Tool call is complete, keep it in the map for final processing
|
|
2228
|
-
// Nothing specific to do here, the tool call is already complete
|
|
2229
2324
|
}
|
|
2230
2325
|
if (chunk.type === 'tool-call') {
|
|
2231
2326
|
// Direct tool call chunk (complete tool call)
|
|
@@ -2237,14 +2332,13 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2237
2332
|
}
|
|
2238
2333
|
if (chunk.type === 'finish') {
|
|
2239
2334
|
providerMetadata = chunk.providerMetadata;
|
|
2240
|
-
const additionalTokenValues = providerMetadata
|
|
2241
|
-
|
|
2242
|
-
} : {};
|
|
2335
|
+
const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
|
|
2336
|
+
const chunkUsage = chunk.usage || {};
|
|
2243
2337
|
usage = {
|
|
2244
|
-
inputTokens: chunk.usage?.inputTokens,
|
|
2245
|
-
outputTokens: chunk.usage?.outputTokens,
|
|
2246
|
-
reasoningTokens:
|
|
2247
|
-
cacheReadInputTokens:
|
|
2338
|
+
inputTokens: extractTokenCount(chunk.usage?.inputTokens),
|
|
2339
|
+
outputTokens: extractTokenCount(chunk.usage?.outputTokens),
|
|
2340
|
+
reasoningTokens: extractReasoningTokens(chunkUsage),
|
|
2341
|
+
cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
|
|
2248
2342
|
...additionalTokenValues
|
|
2249
2343
|
};
|
|
2250
2344
|
}
|
|
@@ -2284,23 +2378,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2284
2378
|
role: 'assistant',
|
|
2285
2379
|
content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
|
|
2286
2380
|
}] : [];
|
|
2287
|
-
|
|
2288
|
-
let webSearchCount = 0;
|
|
2289
|
-
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
2290
|
-
// Anthropic-specific extraction
|
|
2291
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
2292
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
2293
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
2294
|
-
}
|
|
2295
|
-
} else {
|
|
2296
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
2297
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
2298
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
2299
|
-
webSearchCount = calculateWebSearchCount({
|
|
2300
|
-
usage: usage,
|
|
2301
|
-
providerMetadata: providerMetadata
|
|
2302
|
-
});
|
|
2303
|
-
}
|
|
2381
|
+
const webSearchCount = extractWebSearchCount(providerMetadata, usage);
|
|
2304
2382
|
// Update usage with web search count
|
|
2305
2383
|
const finalUsage = {
|
|
2306
2384
|
...usage,
|
|
@@ -2308,11 +2386,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2308
2386
|
};
|
|
2309
2387
|
await sendEventToPosthog({
|
|
2310
2388
|
client: phClient,
|
|
2311
|
-
distinctId:
|
|
2312
|
-
traceId:
|
|
2389
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2390
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2313
2391
|
model: modelId,
|
|
2314
2392
|
provider: provider,
|
|
2315
|
-
input:
|
|
2393
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2316
2394
|
output: output,
|
|
2317
2395
|
latency,
|
|
2318
2396
|
baseURL,
|
|
@@ -2320,7 +2398,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2320
2398
|
httpStatus: 200,
|
|
2321
2399
|
usage: finalUsage,
|
|
2322
2400
|
tools: availableTools,
|
|
2323
|
-
captureImmediate:
|
|
2401
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2324
2402
|
});
|
|
2325
2403
|
}
|
|
2326
2404
|
});
|
|
@@ -2331,11 +2409,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2331
2409
|
} catch (error) {
|
|
2332
2410
|
await sendEventToPosthog({
|
|
2333
2411
|
client: phClient,
|
|
2334
|
-
distinctId:
|
|
2335
|
-
traceId:
|
|
2412
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2413
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2336
2414
|
model: modelId,
|
|
2337
2415
|
provider: provider,
|
|
2338
|
-
input:
|
|
2416
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2339
2417
|
output: [],
|
|
2340
2418
|
latency: 0,
|
|
2341
2419
|
baseURL: '',
|
|
@@ -2348,25 +2426,12 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2348
2426
|
isError: true,
|
|
2349
2427
|
error: truncate(JSON.stringify(error)),
|
|
2350
2428
|
tools: availableTools,
|
|
2351
|
-
captureImmediate:
|
|
2429
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2352
2430
|
});
|
|
2353
2431
|
throw error;
|
|
2354
2432
|
}
|
|
2355
2433
|
}
|
|
2356
2434
|
};
|
|
2357
|
-
return middleware;
|
|
2358
|
-
};
|
|
2359
|
-
const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
2360
|
-
const traceId = options.posthogTraceId ?? v4();
|
|
2361
|
-
const middleware = createInstrumentationMiddleware(phClient, model, {
|
|
2362
|
-
...options,
|
|
2363
|
-
posthogTraceId: traceId,
|
|
2364
|
-
posthogDistinctId: options.posthogDistinctId
|
|
2365
|
-
});
|
|
2366
|
-
const wrappedModel = wrapLanguageModel({
|
|
2367
|
-
model,
|
|
2368
|
-
middleware
|
|
2369
|
-
});
|
|
2370
2435
|
return wrappedModel;
|
|
2371
2436
|
};
|
|
2372
2437
|
|
|
@@ -2790,6 +2855,39 @@ class WrappedModels {
|
|
|
2790
2855
|
throw error;
|
|
2791
2856
|
}
|
|
2792
2857
|
}
|
|
2858
|
+
formatPartsAsContentBlocks(parts) {
|
|
2859
|
+
const blocks = [];
|
|
2860
|
+
for (const part of parts) {
|
|
2861
|
+
// Handle dict/object with text field
|
|
2862
|
+
if (part && typeof part === 'object' && 'text' in part && part.text) {
|
|
2863
|
+
blocks.push({
|
|
2864
|
+
type: 'text',
|
|
2865
|
+
text: String(part.text)
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
// Handle string parts
|
|
2869
|
+
else if (typeof part === 'string') {
|
|
2870
|
+
blocks.push({
|
|
2871
|
+
type: 'text',
|
|
2872
|
+
text: part
|
|
2873
|
+
});
|
|
2874
|
+
}
|
|
2875
|
+
// Handle inlineData (images, audio, PDFs)
|
|
2876
|
+
else if (part && typeof part === 'object' && 'inlineData' in part) {
|
|
2877
|
+
const inlineData = part.inlineData;
|
|
2878
|
+
const mimeType = inlineData.mimeType || inlineData.mime_type || '';
|
|
2879
|
+
const contentType = mimeType.startsWith('image/') ? 'image' : 'document';
|
|
2880
|
+
blocks.push({
|
|
2881
|
+
type: contentType,
|
|
2882
|
+
inline_data: {
|
|
2883
|
+
data: inlineData.data,
|
|
2884
|
+
mime_type: mimeType
|
|
2885
|
+
}
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
return blocks;
|
|
2890
|
+
}
|
|
2793
2891
|
formatInput(contents) {
|
|
2794
2892
|
if (typeof contents === 'string') {
|
|
2795
2893
|
return [{
|
|
@@ -2814,20 +2912,24 @@ class WrappedModels {
|
|
|
2814
2912
|
};
|
|
2815
2913
|
}
|
|
2816
2914
|
if ('content' in obj && obj.content) {
|
|
2915
|
+
// If content is a list, format it as content blocks
|
|
2916
|
+
if (Array.isArray(obj.content)) {
|
|
2917
|
+
const contentBlocks = this.formatPartsAsContentBlocks(obj.content);
|
|
2918
|
+
return {
|
|
2919
|
+
role: isString(obj.role) ? obj.role : 'user',
|
|
2920
|
+
content: contentBlocks
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2817
2923
|
return {
|
|
2818
2924
|
role: isString(obj.role) ? obj.role : 'user',
|
|
2819
2925
|
content: obj.content
|
|
2820
2926
|
};
|
|
2821
2927
|
}
|
|
2822
2928
|
if ('parts' in obj && Array.isArray(obj.parts)) {
|
|
2929
|
+
const contentBlocks = this.formatPartsAsContentBlocks(obj.parts);
|
|
2823
2930
|
return {
|
|
2824
2931
|
role: isString(obj.role) ? obj.role : 'user',
|
|
2825
|
-
content:
|
|
2826
|
-
if (part && typeof part === 'object' && 'text' in part) {
|
|
2827
|
-
return part.text;
|
|
2828
|
-
}
|
|
2829
|
-
return part;
|
|
2830
|
-
})
|
|
2932
|
+
content: contentBlocks
|
|
2831
2933
|
};
|
|
2832
2934
|
}
|
|
2833
2935
|
}
|
|
@@ -3405,7 +3507,7 @@ var BaseCallbackHandler = class extends BaseCallbackHandlerMethodsClass {
|
|
|
3405
3507
|
}
|
|
3406
3508
|
static fromMethods(methods) {
|
|
3407
3509
|
class Handler extends BaseCallbackHandler {
|
|
3408
|
-
name = uuid.
|
|
3510
|
+
name = uuid.v7();
|
|
3409
3511
|
constructor() {
|
|
3410
3512
|
super();
|
|
3411
3513
|
Object.assign(this, methods);
|