@posthog/ai 7.2.2 → 7.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/dist/anthropic/index.cjs +1 -1
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +1 -1
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +1 -1
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +2 -7
- package/dist/gemini/index.mjs +1 -1
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +167 -141
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.mjs +167 -141
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +1 -1
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +1 -1
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +21 -14
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +21 -14
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +131 -113
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.d.ts +7 -2
- package/dist/vercel/index.mjs +131 -113
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +11 -6
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.1";
|
|
10
9
|
|
|
11
10
|
// Type guards for safer type checking
|
|
12
11
|
const isString = value => {
|
|
@@ -859,6 +858,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
859
858
|
try {
|
|
860
859
|
const contentBlocks = [];
|
|
861
860
|
let accumulatedContent = '';
|
|
861
|
+
let modelFromResponse;
|
|
862
862
|
let usage = {
|
|
863
863
|
inputTokens: 0,
|
|
864
864
|
outputTokens: 0,
|
|
@@ -867,6 +867,10 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
867
867
|
// Map to track in-progress tool calls
|
|
868
868
|
const toolCallsInProgress = new Map();
|
|
869
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
|
+
}
|
|
870
874
|
const choice = chunk?.choices?.[0];
|
|
871
875
|
const chunkWebSearchCount = calculateWebSearchCount(chunk);
|
|
872
876
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
@@ -954,7 +958,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
954
958
|
await sendEventToPosthog({
|
|
955
959
|
client: this.phClient,
|
|
956
960
|
...posthogParams,
|
|
957
|
-
model: openAIParams.model,
|
|
961
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
958
962
|
provider: 'openai',
|
|
959
963
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
960
964
|
output: formattedOutput,
|
|
@@ -1007,7 +1011,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
1007
1011
|
await sendEventToPosthog({
|
|
1008
1012
|
client: this.phClient,
|
|
1009
1013
|
...posthogParams,
|
|
1010
|
-
model: openAIParams.model,
|
|
1014
|
+
model: openAIParams.model ?? result.model,
|
|
1011
1015
|
provider: 'openai',
|
|
1012
1016
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
1013
1017
|
output: formattedOutput,
|
|
@@ -1031,7 +1035,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
1031
1035
|
await sendEventToPosthog({
|
|
1032
1036
|
client: this.phClient,
|
|
1033
1037
|
...posthogParams,
|
|
1034
|
-
model:
|
|
1038
|
+
model: openAIParams.model,
|
|
1035
1039
|
provider: 'openai',
|
|
1036
1040
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
1037
1041
|
output: [],
|
|
@@ -1073,6 +1077,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1073
1077
|
(async () => {
|
|
1074
1078
|
try {
|
|
1075
1079
|
let finalContent = [];
|
|
1080
|
+
let modelFromResponse;
|
|
1076
1081
|
let usage = {
|
|
1077
1082
|
inputTokens: 0,
|
|
1078
1083
|
outputTokens: 0,
|
|
@@ -1080,6 +1085,10 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1080
1085
|
};
|
|
1081
1086
|
for await (const chunk of stream1) {
|
|
1082
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
|
+
}
|
|
1083
1092
|
const chunkWebSearchCount = calculateWebSearchCount(chunk.response);
|
|
1084
1093
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
1085
1094
|
usage.webSearchCount = chunkWebSearchCount;
|
|
@@ -1103,8 +1112,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1103
1112
|
await sendEventToPosthog({
|
|
1104
1113
|
client: this.phClient,
|
|
1105
1114
|
...posthogParams,
|
|
1106
|
-
|
|
1107
|
-
model: openAIParams.model,
|
|
1115
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1108
1116
|
provider: 'openai',
|
|
1109
1117
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1110
1118
|
output: finalContent,
|
|
@@ -1126,7 +1134,6 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1126
1134
|
await sendEventToPosthog({
|
|
1127
1135
|
client: this.phClient,
|
|
1128
1136
|
...posthogParams,
|
|
1129
|
-
//@ts-expect-error
|
|
1130
1137
|
model: openAIParams.model,
|
|
1131
1138
|
provider: 'openai',
|
|
1132
1139
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
@@ -1159,8 +1166,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1159
1166
|
await sendEventToPosthog({
|
|
1160
1167
|
client: this.phClient,
|
|
1161
1168
|
...posthogParams,
|
|
1162
|
-
|
|
1163
|
-
model: openAIParams.model,
|
|
1169
|
+
model: openAIParams.model ?? result.model,
|
|
1164
1170
|
provider: 'openai',
|
|
1165
1171
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1166
1172
|
output: formattedOutput,
|
|
@@ -1184,7 +1190,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1184
1190
|
await sendEventToPosthog({
|
|
1185
1191
|
client: this.phClient,
|
|
1186
1192
|
...posthogParams,
|
|
1187
|
-
model:
|
|
1193
|
+
model: openAIParams.model,
|
|
1188
1194
|
provider: 'openai',
|
|
1189
1195
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1190
1196
|
output: [],
|
|
@@ -1221,7 +1227,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1221
1227
|
await sendEventToPosthog({
|
|
1222
1228
|
client: this.phClient,
|
|
1223
1229
|
...posthogParams,
|
|
1224
|
-
model:
|
|
1230
|
+
model: openAIParams.model ?? result.model,
|
|
1225
1231
|
provider: 'openai',
|
|
1226
1232
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1227
1233
|
output: result.output,
|
|
@@ -1242,7 +1248,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1242
1248
|
await sendEventToPosthog({
|
|
1243
1249
|
client: this.phClient,
|
|
1244
1250
|
...posthogParams,
|
|
1245
|
-
model:
|
|
1251
|
+
model: openAIParams.model,
|
|
1246
1252
|
provider: 'openai',
|
|
1247
1253
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1248
1254
|
output: [],
|
|
@@ -1417,7 +1423,7 @@ class WrappedTranscriptions extends Transcriptions {
|
|
|
1417
1423
|
await sendEventToPosthog({
|
|
1418
1424
|
client: this.phClient,
|
|
1419
1425
|
...posthogParams,
|
|
1420
|
-
model:
|
|
1426
|
+
model: openAIParams.model,
|
|
1421
1427
|
provider: 'openai',
|
|
1422
1428
|
input: openAIParams.prompt,
|
|
1423
1429
|
output: result.text,
|
|
@@ -1437,7 +1443,7 @@ class WrappedTranscriptions extends Transcriptions {
|
|
|
1437
1443
|
await sendEventToPosthog({
|
|
1438
1444
|
client: this.phClient,
|
|
1439
1445
|
...posthogParams,
|
|
1440
|
-
model:
|
|
1446
|
+
model: openAIParams.model,
|
|
1441
1447
|
provider: 'openai',
|
|
1442
1448
|
input: openAIParams.prompt,
|
|
1443
1449
|
output: [],
|
|
@@ -1499,6 +1505,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1499
1505
|
try {
|
|
1500
1506
|
const contentBlocks = [];
|
|
1501
1507
|
let accumulatedContent = '';
|
|
1508
|
+
let modelFromResponse;
|
|
1502
1509
|
let usage = {
|
|
1503
1510
|
inputTokens: 0,
|
|
1504
1511
|
outputTokens: 0
|
|
@@ -1506,6 +1513,10 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1506
1513
|
// Map to track in-progress tool calls
|
|
1507
1514
|
const toolCallsInProgress = new Map();
|
|
1508
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
|
+
}
|
|
1509
1520
|
const choice = chunk?.choices?.[0];
|
|
1510
1521
|
// Handle text content
|
|
1511
1522
|
const deltaContent = choice?.delta?.content;
|
|
@@ -1587,7 +1598,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1587
1598
|
await sendEventToPosthog({
|
|
1588
1599
|
client: this.phClient,
|
|
1589
1600
|
...posthogParams,
|
|
1590
|
-
model: openAIParams.model,
|
|
1601
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1591
1602
|
provider: 'azure',
|
|
1592
1603
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
1593
1604
|
output: formattedOutput,
|
|
@@ -1631,7 +1642,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
1631
1642
|
await sendEventToPosthog({
|
|
1632
1643
|
client: this.phClient,
|
|
1633
1644
|
...posthogParams,
|
|
1634
|
-
model: openAIParams.model,
|
|
1645
|
+
model: openAIParams.model ?? result.model,
|
|
1635
1646
|
provider: 'azure',
|
|
1636
1647
|
input: openAIParams.messages,
|
|
1637
1648
|
output: formatResponseOpenAI(result),
|
|
@@ -1695,11 +1706,18 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1695
1706
|
(async () => {
|
|
1696
1707
|
try {
|
|
1697
1708
|
let finalContent = [];
|
|
1709
|
+
let modelFromResponse;
|
|
1698
1710
|
let usage = {
|
|
1699
1711
|
inputTokens: 0,
|
|
1700
1712
|
outputTokens: 0
|
|
1701
1713
|
};
|
|
1702
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
|
+
}
|
|
1703
1721
|
if (chunk.type === 'response.completed' && 'response' in chunk && chunk.response?.output && chunk.response.output.length > 0) {
|
|
1704
1722
|
finalContent = chunk.response.output;
|
|
1705
1723
|
}
|
|
@@ -1716,10 +1734,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1716
1734
|
await sendEventToPosthog({
|
|
1717
1735
|
client: this.phClient,
|
|
1718
1736
|
...posthogParams,
|
|
1719
|
-
|
|
1720
|
-
model: openAIParams.model,
|
|
1737
|
+
model: openAIParams.model ?? modelFromResponse,
|
|
1721
1738
|
provider: 'azure',
|
|
1722
|
-
input: openAIParams.input,
|
|
1739
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1723
1740
|
output: finalContent,
|
|
1724
1741
|
latency,
|
|
1725
1742
|
baseURL: this.baseURL,
|
|
@@ -1732,10 +1749,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1732
1749
|
await sendEventToPosthog({
|
|
1733
1750
|
client: this.phClient,
|
|
1734
1751
|
...posthogParams,
|
|
1735
|
-
//@ts-expect-error
|
|
1736
1752
|
model: openAIParams.model,
|
|
1737
1753
|
provider: 'azure',
|
|
1738
|
-
input: openAIParams.input,
|
|
1754
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1739
1755
|
output: [],
|
|
1740
1756
|
latency: 0,
|
|
1741
1757
|
baseURL: this.baseURL,
|
|
@@ -1761,10 +1777,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1761
1777
|
await sendEventToPosthog({
|
|
1762
1778
|
client: this.phClient,
|
|
1763
1779
|
...posthogParams,
|
|
1764
|
-
|
|
1765
|
-
model: openAIParams.model,
|
|
1780
|
+
model: openAIParams.model ?? result.model,
|
|
1766
1781
|
provider: 'azure',
|
|
1767
|
-
input: openAIParams.input,
|
|
1782
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1768
1783
|
output: result.output,
|
|
1769
1784
|
latency,
|
|
1770
1785
|
baseURL: this.baseURL,
|
|
@@ -1784,10 +1799,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1784
1799
|
await sendEventToPosthog({
|
|
1785
1800
|
client: this.phClient,
|
|
1786
1801
|
...posthogParams,
|
|
1787
|
-
//@ts-expect-error
|
|
1788
1802
|
model: openAIParams.model,
|
|
1789
1803
|
provider: 'azure',
|
|
1790
|
-
input: openAIParams.input,
|
|
1804
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1791
1805
|
output: [],
|
|
1792
1806
|
latency: 0,
|
|
1793
1807
|
baseURL: this.baseURL,
|
|
@@ -1817,9 +1831,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1817
1831
|
await sendEventToPosthog({
|
|
1818
1832
|
client: this.phClient,
|
|
1819
1833
|
...posthogParams,
|
|
1820
|
-
model:
|
|
1834
|
+
model: openAIParams.model ?? result.model,
|
|
1821
1835
|
provider: 'azure',
|
|
1822
|
-
input: openAIParams.input,
|
|
1836
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1823
1837
|
output: result.output,
|
|
1824
1838
|
latency,
|
|
1825
1839
|
baseURL: this.baseURL,
|
|
@@ -1837,9 +1851,9 @@ class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1837
1851
|
await sendEventToPosthog({
|
|
1838
1852
|
client: this.phClient,
|
|
1839
1853
|
...posthogParams,
|
|
1840
|
-
model:
|
|
1854
|
+
model: openAIParams.model,
|
|
1841
1855
|
provider: 'azure',
|
|
1842
|
-
input: openAIParams.input,
|
|
1856
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1843
1857
|
output: [],
|
|
1844
1858
|
latency: 0,
|
|
1845
1859
|
baseURL: this.baseURL,
|
|
@@ -2112,67 +2126,117 @@ const extractProvider = model => {
|
|
|
2112
2126
|
const providerName = provider.split('.')[0];
|
|
2113
2127
|
return providerName;
|
|
2114
2128
|
};
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
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 => {
|
|
2121
2207
|
const startTime = Date.now();
|
|
2122
2208
|
const mergedParams = {
|
|
2123
|
-
...
|
|
2124
|
-
...mapVercelParams(params)
|
|
2125
|
-
posthogProperties: {
|
|
2126
|
-
...options.posthogProperties,
|
|
2127
|
-
$ai_framework: 'vercel'
|
|
2128
|
-
}
|
|
2209
|
+
...mergedOptions,
|
|
2210
|
+
...mapVercelParams(params)
|
|
2129
2211
|
};
|
|
2130
2212
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
2131
2213
|
try {
|
|
2132
|
-
const result = await doGenerate();
|
|
2133
|
-
const modelId =
|
|
2134
|
-
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);
|
|
2135
2217
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
2136
2218
|
const content = mapVercelOutput(result.content);
|
|
2137
2219
|
const latency = (Date.now() - startTime) / 1000;
|
|
2138
2220
|
const providerMetadata = result.providerMetadata;
|
|
2139
|
-
const additionalTokenValues =
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
};
|
|
2144
|
-
// Calculate web search count based on provider
|
|
2145
|
-
let webSearchCount = 0;
|
|
2146
|
-
if (providerMetadata?.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
2147
|
-
// Anthropic-specific extraction
|
|
2148
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
2149
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
2150
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
2151
|
-
}
|
|
2152
|
-
} else {
|
|
2153
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
2154
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
2155
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
2156
|
-
webSearchCount = calculateWebSearchCount({
|
|
2157
|
-
usage: result.usage,
|
|
2158
|
-
providerMetadata: providerMetadata
|
|
2159
|
-
});
|
|
2160
|
-
}
|
|
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;
|
|
2161
2225
|
const usage = {
|
|
2162
|
-
inputTokens: result.usage.inputTokens,
|
|
2163
|
-
outputTokens: result.usage.outputTokens,
|
|
2164
|
-
reasoningTokens:
|
|
2165
|
-
cacheReadInputTokens:
|
|
2226
|
+
inputTokens: extractTokenCount(result.usage.inputTokens),
|
|
2227
|
+
outputTokens: extractTokenCount(result.usage.outputTokens),
|
|
2228
|
+
reasoningTokens: extractReasoningTokens(usageObj),
|
|
2229
|
+
cacheReadInputTokens: extractCacheReadTokens(usageObj),
|
|
2166
2230
|
webSearchCount,
|
|
2167
2231
|
...additionalTokenValues
|
|
2168
2232
|
};
|
|
2169
2233
|
await sendEventToPosthog({
|
|
2170
2234
|
client: phClient,
|
|
2171
|
-
distinctId:
|
|
2172
|
-
traceId:
|
|
2235
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2236
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2173
2237
|
model: modelId,
|
|
2174
2238
|
provider: provider,
|
|
2175
|
-
input:
|
|
2239
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2176
2240
|
output: content,
|
|
2177
2241
|
latency,
|
|
2178
2242
|
baseURL,
|
|
@@ -2180,18 +2244,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2180
2244
|
httpStatus: 200,
|
|
2181
2245
|
usage,
|
|
2182
2246
|
tools: availableTools,
|
|
2183
|
-
captureImmediate:
|
|
2247
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2184
2248
|
});
|
|
2185
2249
|
return result;
|
|
2186
2250
|
} catch (error) {
|
|
2187
2251
|
const modelId = model.modelId;
|
|
2188
2252
|
await sendEventToPosthog({
|
|
2189
2253
|
client: phClient,
|
|
2190
|
-
distinctId:
|
|
2191
|
-
traceId:
|
|
2254
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2255
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2192
2256
|
model: modelId,
|
|
2193
2257
|
provider: model.provider,
|
|
2194
|
-
input:
|
|
2258
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2195
2259
|
output: [],
|
|
2196
2260
|
latency: 0,
|
|
2197
2261
|
baseURL: '',
|
|
@@ -2204,30 +2268,23 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2204
2268
|
isError: true,
|
|
2205
2269
|
error: truncate(JSON.stringify(error)),
|
|
2206
2270
|
tools: availableTools,
|
|
2207
|
-
captureImmediate:
|
|
2271
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2208
2272
|
});
|
|
2209
2273
|
throw error;
|
|
2210
2274
|
}
|
|
2211
2275
|
},
|
|
2212
|
-
|
|
2213
|
-
doStream,
|
|
2214
|
-
params
|
|
2215
|
-
}) => {
|
|
2276
|
+
doStream: async params => {
|
|
2216
2277
|
const startTime = Date.now();
|
|
2217
2278
|
let generatedText = '';
|
|
2218
2279
|
let reasoningText = '';
|
|
2219
2280
|
let usage = {};
|
|
2220
2281
|
let providerMetadata = undefined;
|
|
2221
2282
|
const mergedParams = {
|
|
2222
|
-
...
|
|
2223
|
-
...mapVercelParams(params)
|
|
2224
|
-
posthogProperties: {
|
|
2225
|
-
...options.posthogProperties,
|
|
2226
|
-
$ai_framework: 'vercel'
|
|
2227
|
-
}
|
|
2283
|
+
...mergedOptions,
|
|
2284
|
+
...mapVercelParams(params)
|
|
2228
2285
|
};
|
|
2229
|
-
const modelId =
|
|
2230
|
-
const provider =
|
|
2286
|
+
const modelId = mergedOptions.posthogModelOverride ?? model.modelId;
|
|
2287
|
+
const provider = mergedOptions.posthogProviderOverride ?? extractProvider(model);
|
|
2231
2288
|
const availableTools = extractAvailableToolCalls('vercel', params);
|
|
2232
2289
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
2233
2290
|
// Map to track in-progress tool calls
|
|
@@ -2236,15 +2293,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2236
2293
|
const {
|
|
2237
2294
|
stream,
|
|
2238
2295
|
...rest
|
|
2239
|
-
} = await doStream();
|
|
2296
|
+
} = await model.doStream(params);
|
|
2240
2297
|
const transformStream = new TransformStream({
|
|
2241
2298
|
transform(chunk, controller) {
|
|
2242
|
-
// Handle
|
|
2299
|
+
// Handle streaming patterns - compatible with both V2 and V3
|
|
2243
2300
|
if (chunk.type === 'text-delta') {
|
|
2244
2301
|
generatedText += chunk.delta;
|
|
2245
2302
|
}
|
|
2246
2303
|
if (chunk.type === 'reasoning-delta') {
|
|
2247
|
-
reasoningText += chunk.delta;
|
|
2304
|
+
reasoningText += chunk.delta;
|
|
2248
2305
|
}
|
|
2249
2306
|
// Handle tool call chunks
|
|
2250
2307
|
if (chunk.type === 'tool-input-start') {
|
|
@@ -2264,7 +2321,6 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2264
2321
|
}
|
|
2265
2322
|
if (chunk.type === 'tool-input-end') {
|
|
2266
2323
|
// Tool call is complete, keep it in the map for final processing
|
|
2267
|
-
// Nothing specific to do here, the tool call is already complete
|
|
2268
2324
|
}
|
|
2269
2325
|
if (chunk.type === 'tool-call') {
|
|
2270
2326
|
// Direct tool call chunk (complete tool call)
|
|
@@ -2276,14 +2332,13 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2276
2332
|
}
|
|
2277
2333
|
if (chunk.type === 'finish') {
|
|
2278
2334
|
providerMetadata = chunk.providerMetadata;
|
|
2279
|
-
const additionalTokenValues = providerMetadata
|
|
2280
|
-
|
|
2281
|
-
} : {};
|
|
2335
|
+
const additionalTokenValues = extractAdditionalTokenValues(providerMetadata);
|
|
2336
|
+
const chunkUsage = chunk.usage || {};
|
|
2282
2337
|
usage = {
|
|
2283
|
-
inputTokens: chunk.usage?.inputTokens,
|
|
2284
|
-
outputTokens: chunk.usage?.outputTokens,
|
|
2285
|
-
reasoningTokens:
|
|
2286
|
-
cacheReadInputTokens:
|
|
2338
|
+
inputTokens: extractTokenCount(chunk.usage?.inputTokens),
|
|
2339
|
+
outputTokens: extractTokenCount(chunk.usage?.outputTokens),
|
|
2340
|
+
reasoningTokens: extractReasoningTokens(chunkUsage),
|
|
2341
|
+
cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
|
|
2287
2342
|
...additionalTokenValues
|
|
2288
2343
|
};
|
|
2289
2344
|
}
|
|
@@ -2323,23 +2378,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2323
2378
|
role: 'assistant',
|
|
2324
2379
|
content: content.length === 1 && content[0].type === 'text' ? content[0].text : content
|
|
2325
2380
|
}] : [];
|
|
2326
|
-
|
|
2327
|
-
let webSearchCount = 0;
|
|
2328
|
-
if (providerMetadata && typeof providerMetadata === 'object' && 'anthropic' in providerMetadata && providerMetadata.anthropic && typeof providerMetadata.anthropic === 'object' && 'server_tool_use' in providerMetadata.anthropic) {
|
|
2329
|
-
// Anthropic-specific extraction
|
|
2330
|
-
const serverToolUse = providerMetadata.anthropic.server_tool_use;
|
|
2331
|
-
if (serverToolUse && typeof serverToolUse === 'object' && 'web_search_requests' in serverToolUse && typeof serverToolUse.web_search_requests === 'number') {
|
|
2332
|
-
webSearchCount = serverToolUse.web_search_requests;
|
|
2333
|
-
}
|
|
2334
|
-
} else {
|
|
2335
|
-
// For other providers through Vercel, pass available metadata to helper
|
|
2336
|
-
// Note: Vercel abstracts provider responses, so we may not have access to
|
|
2337
|
-
// raw citations/annotations unless Vercel exposes them in usage/metadata
|
|
2338
|
-
webSearchCount = calculateWebSearchCount({
|
|
2339
|
-
usage: usage,
|
|
2340
|
-
providerMetadata: providerMetadata
|
|
2341
|
-
});
|
|
2342
|
-
}
|
|
2381
|
+
const webSearchCount = extractWebSearchCount(providerMetadata, usage);
|
|
2343
2382
|
// Update usage with web search count
|
|
2344
2383
|
const finalUsage = {
|
|
2345
2384
|
...usage,
|
|
@@ -2347,11 +2386,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2347
2386
|
};
|
|
2348
2387
|
await sendEventToPosthog({
|
|
2349
2388
|
client: phClient,
|
|
2350
|
-
distinctId:
|
|
2351
|
-
traceId:
|
|
2389
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2390
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2352
2391
|
model: modelId,
|
|
2353
2392
|
provider: provider,
|
|
2354
|
-
input:
|
|
2393
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2355
2394
|
output: output,
|
|
2356
2395
|
latency,
|
|
2357
2396
|
baseURL,
|
|
@@ -2359,7 +2398,7 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2359
2398
|
httpStatus: 200,
|
|
2360
2399
|
usage: finalUsage,
|
|
2361
2400
|
tools: availableTools,
|
|
2362
|
-
captureImmediate:
|
|
2401
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2363
2402
|
});
|
|
2364
2403
|
}
|
|
2365
2404
|
});
|
|
@@ -2370,11 +2409,11 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2370
2409
|
} catch (error) {
|
|
2371
2410
|
await sendEventToPosthog({
|
|
2372
2411
|
client: phClient,
|
|
2373
|
-
distinctId:
|
|
2374
|
-
traceId:
|
|
2412
|
+
distinctId: mergedOptions.posthogDistinctId,
|
|
2413
|
+
traceId: mergedOptions.posthogTraceId ?? v4(),
|
|
2375
2414
|
model: modelId,
|
|
2376
2415
|
provider: provider,
|
|
2377
|
-
input:
|
|
2416
|
+
input: mergedOptions.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
2378
2417
|
output: [],
|
|
2379
2418
|
latency: 0,
|
|
2380
2419
|
baseURL: '',
|
|
@@ -2387,25 +2426,12 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
2387
2426
|
isError: true,
|
|
2388
2427
|
error: truncate(JSON.stringify(error)),
|
|
2389
2428
|
tools: availableTools,
|
|
2390
|
-
captureImmediate:
|
|
2429
|
+
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2391
2430
|
});
|
|
2392
2431
|
throw error;
|
|
2393
2432
|
}
|
|
2394
2433
|
}
|
|
2395
2434
|
};
|
|
2396
|
-
return middleware;
|
|
2397
|
-
};
|
|
2398
|
-
const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
2399
|
-
const traceId = options.posthogTraceId ?? v4();
|
|
2400
|
-
const middleware = createInstrumentationMiddleware(phClient, model, {
|
|
2401
|
-
...options,
|
|
2402
|
-
posthogTraceId: traceId,
|
|
2403
|
-
posthogDistinctId: options.posthogDistinctId
|
|
2404
|
-
});
|
|
2405
|
-
const wrappedModel = wrapLanguageModel({
|
|
2406
|
-
model,
|
|
2407
|
-
middleware
|
|
2408
|
-
});
|
|
2409
2435
|
return wrappedModel;
|
|
2410
2436
|
};
|
|
2411
2437
|
|