@posthog/ai 7.13.2 → 7.14.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 +14 -1
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +14 -1
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +79 -1
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +2 -1
- package/dist/gemini/index.mjs +79 -1
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +145 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +145 -2
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +38 -1
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.d.ts +1 -0
- package/dist/langchain/index.mjs +38 -1
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +19 -2
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +19 -2
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +20 -1
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +20 -1
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -29,7 +29,7 @@ function _interopNamespace(e) {
|
|
|
29
29
|
var uuid__namespace = /*#__PURE__*/_interopNamespace(uuid);
|
|
30
30
|
var AnthropicOriginal__default = /*#__PURE__*/_interopDefault(AnthropicOriginal);
|
|
31
31
|
|
|
32
|
-
var version = "7.
|
|
32
|
+
var version = "7.14.0";
|
|
33
33
|
|
|
34
34
|
// Type guards for safer type checking
|
|
35
35
|
const isString = value => {
|
|
@@ -778,6 +778,7 @@ const sendEventToPosthog = async ({
|
|
|
778
778
|
usage = {},
|
|
779
779
|
error,
|
|
780
780
|
exceptionId,
|
|
781
|
+
stopReason,
|
|
781
782
|
tools,
|
|
782
783
|
captureImmediate = false
|
|
783
784
|
}) => {
|
|
@@ -848,6 +849,9 @@ const sendEventToPosthog = async ({
|
|
|
848
849
|
...(distinctId ? {} : {
|
|
849
850
|
$process_person_profile: false
|
|
850
851
|
}),
|
|
852
|
+
...(stopReason ? {
|
|
853
|
+
$ai_stop_reason: stopReason
|
|
854
|
+
} : {}),
|
|
851
855
|
...(tools ? {
|
|
852
856
|
$ai_tools: tools
|
|
853
857
|
} : {}),
|
|
@@ -971,6 +975,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
971
975
|
let accumulatedContent = '';
|
|
972
976
|
let modelFromResponse;
|
|
973
977
|
let firstTokenTime;
|
|
978
|
+
let stopReason;
|
|
974
979
|
let usage = {
|
|
975
980
|
inputTokens: 0,
|
|
976
981
|
outputTokens: 0,
|
|
@@ -985,6 +990,9 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
985
990
|
modelFromResponse = chunk.model;
|
|
986
991
|
}
|
|
987
992
|
const choice = chunk?.choices?.[0];
|
|
993
|
+
if (choice?.finish_reason) {
|
|
994
|
+
stopReason = choice.finish_reason;
|
|
995
|
+
}
|
|
988
996
|
const chunkWebSearchCount = calculateWebSearchCount(chunk);
|
|
989
997
|
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
990
998
|
usage.webSearchCount = chunkWebSearchCount;
|
|
@@ -1096,6 +1104,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
1096
1104
|
webSearchCount: usage.webSearchCount,
|
|
1097
1105
|
rawUsage: rawUsageData
|
|
1098
1106
|
},
|
|
1107
|
+
stopReason,
|
|
1099
1108
|
tools: availableTools
|
|
1100
1109
|
});
|
|
1101
1110
|
} catch (error) {
|
|
@@ -1148,6 +1157,7 @@ let WrappedCompletions$1 = class WrappedCompletions extends Completions {
|
|
|
1148
1157
|
webSearchCount: calculateWebSearchCount(result),
|
|
1149
1158
|
rawUsage: result.usage
|
|
1150
1159
|
},
|
|
1160
|
+
stopReason: result.choices[0]?.finish_reason ?? undefined,
|
|
1151
1161
|
tools: availableTools
|
|
1152
1162
|
});
|
|
1153
1163
|
}
|
|
@@ -1200,6 +1210,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1200
1210
|
let finalContent = [];
|
|
1201
1211
|
let modelFromResponse;
|
|
1202
1212
|
let firstTokenTime;
|
|
1213
|
+
let stopReason;
|
|
1203
1214
|
let usage = {
|
|
1204
1215
|
inputTokens: 0,
|
|
1205
1216
|
outputTokens: 0,
|
|
@@ -1223,6 +1234,9 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1223
1234
|
}
|
|
1224
1235
|
if (chunk.type === 'response.completed' && 'response' in chunk && chunk.response?.output && chunk.response.output.length > 0) {
|
|
1225
1236
|
finalContent = chunk.response.output;
|
|
1237
|
+
if (chunk.response.status) {
|
|
1238
|
+
stopReason = chunk.response.status;
|
|
1239
|
+
}
|
|
1226
1240
|
}
|
|
1227
1241
|
if ('response' in chunk && chunk.response?.usage) {
|
|
1228
1242
|
rawUsageData = chunk.response.usage;
|
|
@@ -1258,6 +1272,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1258
1272
|
webSearchCount: usage.webSearchCount,
|
|
1259
1273
|
rawUsage: rawUsageData
|
|
1260
1274
|
},
|
|
1275
|
+
stopReason,
|
|
1261
1276
|
tools: availableTools
|
|
1262
1277
|
});
|
|
1263
1278
|
} catch (error) {
|
|
@@ -1311,6 +1326,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1311
1326
|
webSearchCount: calculateWebSearchCount(result),
|
|
1312
1327
|
rawUsage: result.usage
|
|
1313
1328
|
},
|
|
1329
|
+
stopReason: result.status ?? undefined,
|
|
1314
1330
|
tools: availableTools
|
|
1315
1331
|
});
|
|
1316
1332
|
}
|
|
@@ -1370,7 +1386,8 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
|
|
|
1370
1386
|
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
1371
1387
|
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
1372
1388
|
rawUsage: result.usage
|
|
1373
|
-
}
|
|
1389
|
+
},
|
|
1390
|
+
stopReason: result.status ?? undefined
|
|
1374
1391
|
});
|
|
1375
1392
|
return result;
|
|
1376
1393
|
}, async error => {
|
|
@@ -2406,6 +2423,9 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2406
2423
|
rawUsage: rawUsageData
|
|
2407
2424
|
};
|
|
2408
2425
|
adjustAnthropicV3CacheTokens(model, provider, usage);
|
|
2426
|
+
// Extract finish reason - V2 returns a string, V3 returns an object with .unified
|
|
2427
|
+
const rawFinishReason = result.finishReason;
|
|
2428
|
+
const finishReasonStr = typeof rawFinishReason === 'string' ? rawFinishReason : rawFinishReason && typeof rawFinishReason === 'object' && 'unified' in rawFinishReason ? String(rawFinishReason.unified) : undefined;
|
|
2409
2429
|
await sendEventToPosthog({
|
|
2410
2430
|
client: phClient,
|
|
2411
2431
|
distinctId: mergedOptions.posthogDistinctId,
|
|
@@ -2419,6 +2439,7 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2419
2439
|
params: mergedParams,
|
|
2420
2440
|
httpStatus: 200,
|
|
2421
2441
|
usage,
|
|
2442
|
+
stopReason: finishReasonStr,
|
|
2422
2443
|
tools: availableTools,
|
|
2423
2444
|
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2424
2445
|
});
|
|
@@ -2457,6 +2478,7 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2457
2478
|
let firstTokenTime;
|
|
2458
2479
|
let generatedText = '';
|
|
2459
2480
|
let reasoningText = '';
|
|
2481
|
+
let stopReason;
|
|
2460
2482
|
let usage = {};
|
|
2461
2483
|
let providerMetadata = undefined;
|
|
2462
2484
|
const mergedParams = {
|
|
@@ -2533,6 +2555,13 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2533
2555
|
cacheReadInputTokens: extractCacheReadTokens(chunkUsage),
|
|
2534
2556
|
...additionalTokenValues
|
|
2535
2557
|
};
|
|
2558
|
+
// Extract finish reason - V2 returns a string, V3 returns an object with .unified
|
|
2559
|
+
const rawFinishReason = chunk.finishReason;
|
|
2560
|
+
if (typeof rawFinishReason === 'string') {
|
|
2561
|
+
stopReason = rawFinishReason;
|
|
2562
|
+
} else if (rawFinishReason && typeof rawFinishReason === 'object' && 'unified' in rawFinishReason) {
|
|
2563
|
+
stopReason = String(rawFinishReason.unified);
|
|
2564
|
+
}
|
|
2536
2565
|
}
|
|
2537
2566
|
controller.enqueue(chunk);
|
|
2538
2567
|
},
|
|
@@ -2596,6 +2625,7 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2596
2625
|
params: mergedParams,
|
|
2597
2626
|
httpStatus: 200,
|
|
2598
2627
|
usage: finalUsage,
|
|
2628
|
+
stopReason,
|
|
2599
2629
|
tools: availableTools,
|
|
2600
2630
|
captureImmediate: mergedOptions.posthogCaptureImmediate
|
|
2601
2631
|
});
|
|
@@ -2667,6 +2697,7 @@ class WrappedMessages extends AnthropicOriginal__default.default.Messages {
|
|
|
2667
2697
|
const toolsInProgress = new Map();
|
|
2668
2698
|
let currentTextBlock = null;
|
|
2669
2699
|
let firstTokenTime;
|
|
2700
|
+
let stopReason;
|
|
2670
2701
|
const usage = {
|
|
2671
2702
|
inputTokens: 0,
|
|
2672
2703
|
outputTokens: 0,
|
|
@@ -2767,6 +2798,12 @@ class WrappedMessages extends AnthropicOriginal__default.default.Messages {
|
|
|
2767
2798
|
usage.webSearchCount = chunk.usage.server_tool_use.web_search_requests;
|
|
2768
2799
|
}
|
|
2769
2800
|
}
|
|
2801
|
+
if (chunk.type === 'message_delta' && 'delta' in chunk) {
|
|
2802
|
+
const delta = chunk.delta;
|
|
2803
|
+
if ('stop_reason' in delta && typeof delta.stop_reason === 'string' && delta.stop_reason) {
|
|
2804
|
+
stopReason = delta.stop_reason;
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2770
2807
|
}
|
|
2771
2808
|
usage.rawUsage = lastRawUsage;
|
|
2772
2809
|
const latency = (Date.now() - startTime) / 1000;
|
|
@@ -2796,6 +2833,7 @@ class WrappedMessages extends AnthropicOriginal__default.default.Messages {
|
|
|
2796
2833
|
params: body,
|
|
2797
2834
|
httpStatus: 200,
|
|
2798
2835
|
usage,
|
|
2836
|
+
stopReason,
|
|
2799
2837
|
tools: availableTools
|
|
2800
2838
|
});
|
|
2801
2839
|
} catch (error) {
|
|
@@ -2847,6 +2885,7 @@ class WrappedMessages extends AnthropicOriginal__default.default.Messages {
|
|
|
2847
2885
|
webSearchCount: result.usage.server_tool_use?.web_search_requests ?? 0,
|
|
2848
2886
|
rawUsage: result.usage
|
|
2849
2887
|
},
|
|
2888
|
+
stopReason: result.stop_reason ?? undefined,
|
|
2850
2889
|
tools: availableTools
|
|
2851
2890
|
});
|
|
2852
2891
|
}
|
|
@@ -2903,6 +2942,7 @@ class WrappedModels {
|
|
|
2903
2942
|
const latency = (Date.now() - startTime) / 1000;
|
|
2904
2943
|
const availableTools = extractAvailableToolCalls('gemini', geminiParams);
|
|
2905
2944
|
const metadata = response.usageMetadata;
|
|
2945
|
+
const finishReason = response.candidates?.[0]?.finishReason;
|
|
2906
2946
|
await sendEventToPosthog({
|
|
2907
2947
|
client: this.phClient,
|
|
2908
2948
|
...posthogParams,
|
|
@@ -2922,6 +2962,7 @@ class WrappedModels {
|
|
|
2922
2962
|
webSearchCount: calculateGoogleWebSearchCount(response),
|
|
2923
2963
|
rawUsage: metadata
|
|
2924
2964
|
},
|
|
2965
|
+
stopReason: finishReason ?? undefined,
|
|
2925
2966
|
tools: availableTools
|
|
2926
2967
|
});
|
|
2927
2968
|
return response;
|
|
@@ -2954,6 +2995,7 @@ class WrappedModels {
|
|
|
2954
2995
|
const startTime = Date.now();
|
|
2955
2996
|
const accumulatedContent = [];
|
|
2956
2997
|
let firstTokenTime;
|
|
2998
|
+
let stopReason;
|
|
2957
2999
|
let usage = {
|
|
2958
3000
|
inputTokens: 0,
|
|
2959
3001
|
outputTokens: 0,
|
|
@@ -2990,6 +3032,10 @@ class WrappedModels {
|
|
|
2990
3032
|
});
|
|
2991
3033
|
}
|
|
2992
3034
|
}
|
|
3035
|
+
// Track finish reason from candidates
|
|
3036
|
+
if (chunk.candidates?.[0]?.finishReason) {
|
|
3037
|
+
stopReason = chunk.candidates[0].finishReason;
|
|
3038
|
+
}
|
|
2993
3039
|
// Handle function calls from candidates
|
|
2994
3040
|
if (chunk.candidates && Array.isArray(chunk.candidates)) {
|
|
2995
3041
|
for (const candidate of chunk.candidates) {
|
|
@@ -3054,6 +3100,7 @@ class WrappedModels {
|
|
|
3054
3100
|
webSearchCount: usage.webSearchCount,
|
|
3055
3101
|
rawUsage: usage.rawUsage
|
|
3056
3102
|
},
|
|
3103
|
+
stopReason,
|
|
3057
3104
|
tools: availableTools
|
|
3058
3105
|
});
|
|
3059
3106
|
} catch (error) {
|
|
@@ -3077,6 +3124,54 @@ class WrappedModels {
|
|
|
3077
3124
|
throw enrichedError;
|
|
3078
3125
|
}
|
|
3079
3126
|
}
|
|
3127
|
+
async embedContent(params) {
|
|
3128
|
+
const {
|
|
3129
|
+
providerParams: geminiParams,
|
|
3130
|
+
posthogParams
|
|
3131
|
+
} = extractPosthogParams(params);
|
|
3132
|
+
const startTime = Date.now();
|
|
3133
|
+
try {
|
|
3134
|
+
const response = await this.client.models.embedContent(geminiParams);
|
|
3135
|
+
const latency = (Date.now() - startTime) / 1000;
|
|
3136
|
+
const inputTokens = extractEmbeddingTokenCount(response);
|
|
3137
|
+
await sendEventToPosthog({
|
|
3138
|
+
client: this.phClient,
|
|
3139
|
+
...posthogParams,
|
|
3140
|
+
eventType: AIEvent.Embedding,
|
|
3141
|
+
model: geminiParams.model,
|
|
3142
|
+
provider: 'gemini',
|
|
3143
|
+
input: withPrivacyMode(this.phClient, posthogParams.privacyMode ?? false, geminiParams.contents),
|
|
3144
|
+
output: null,
|
|
3145
|
+
latency,
|
|
3146
|
+
baseURL: 'https://generativelanguage.googleapis.com',
|
|
3147
|
+
params: params,
|
|
3148
|
+
httpStatus: 200,
|
|
3149
|
+
usage: {
|
|
3150
|
+
inputTokens
|
|
3151
|
+
}
|
|
3152
|
+
});
|
|
3153
|
+
return response;
|
|
3154
|
+
} catch (error) {
|
|
3155
|
+
const latency = (Date.now() - startTime) / 1000;
|
|
3156
|
+
const enrichedError = await sendEventWithErrorToPosthog({
|
|
3157
|
+
client: this.phClient,
|
|
3158
|
+
...posthogParams,
|
|
3159
|
+
eventType: AIEvent.Embedding,
|
|
3160
|
+
model: geminiParams.model,
|
|
3161
|
+
provider: 'gemini',
|
|
3162
|
+
input: withPrivacyMode(this.phClient, posthogParams.privacyMode ?? false, geminiParams.contents),
|
|
3163
|
+
output: null,
|
|
3164
|
+
latency,
|
|
3165
|
+
baseURL: 'https://generativelanguage.googleapis.com',
|
|
3166
|
+
params: params,
|
|
3167
|
+
usage: {
|
|
3168
|
+
inputTokens: 0
|
|
3169
|
+
},
|
|
3170
|
+
error: error
|
|
3171
|
+
});
|
|
3172
|
+
throw enrichedError;
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3080
3175
|
formatPartsAsContentBlocks(parts) {
|
|
3081
3176
|
const blocks = [];
|
|
3082
3177
|
for (const part of parts) {
|
|
@@ -3231,6 +3326,22 @@ class WrappedModels {
|
|
|
3231
3326
|
return messages;
|
|
3232
3327
|
}
|
|
3233
3328
|
}
|
|
3329
|
+
/**
|
|
3330
|
+
* Extract total token count from a Gemini embed_content response.
|
|
3331
|
+
* Token counts are only available per-embedding via Vertex AI's statistics.tokenCount.
|
|
3332
|
+
* Returns 0 if no token counts are available.
|
|
3333
|
+
*/
|
|
3334
|
+
function extractEmbeddingTokenCount(response) {
|
|
3335
|
+
let total = 0;
|
|
3336
|
+
if (response.embeddings) {
|
|
3337
|
+
for (const embedding of response.embeddings) {
|
|
3338
|
+
if (embedding.statistics?.tokenCount != null) {
|
|
3339
|
+
total += embedding.statistics.tokenCount;
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
return total;
|
|
3344
|
+
}
|
|
3234
3345
|
/**
|
|
3235
3346
|
* Detect if Google Search grounding was used in the response.
|
|
3236
3347
|
* Gemini bills per request that uses grounding, not per individual query.
|
|
@@ -4054,6 +4165,11 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
4054
4165
|
if (additionalTokenData.webSearchCount !== undefined) {
|
|
4055
4166
|
eventProperties['$ai_web_search_count'] = additionalTokenData.webSearchCount;
|
|
4056
4167
|
}
|
|
4168
|
+
// Extract stop reason from generation info
|
|
4169
|
+
const stopReason = this._extractStopReason(output);
|
|
4170
|
+
if (stopReason) {
|
|
4171
|
+
eventProperties['$ai_stop_reason'] = stopReason;
|
|
4172
|
+
}
|
|
4057
4173
|
// Handle generations/completions
|
|
4058
4174
|
let completions;
|
|
4059
4175
|
if (output.generations && Array.isArray(output.generations)) {
|
|
@@ -4188,6 +4304,33 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
4188
4304
|
// Sanitize the message content to redact base64 images
|
|
4189
4305
|
return sanitizeLangChain(messageDict);
|
|
4190
4306
|
}
|
|
4307
|
+
_extractStopReason(output) {
|
|
4308
|
+
if (!output.generations || !Array.isArray(output.generations)) {
|
|
4309
|
+
return undefined;
|
|
4310
|
+
}
|
|
4311
|
+
const lastGeneration = output.generations[output.generations.length - 1];
|
|
4312
|
+
if (!Array.isArray(lastGeneration) || lastGeneration.length === 0) {
|
|
4313
|
+
return undefined;
|
|
4314
|
+
}
|
|
4315
|
+
const gen = lastGeneration[0];
|
|
4316
|
+
// Check generationInfo for finish_reason (OpenAI format)
|
|
4317
|
+
if (gen.generationInfo?.finish_reason) {
|
|
4318
|
+
return String(gen.generationInfo.finish_reason);
|
|
4319
|
+
}
|
|
4320
|
+
// Check generationInfo for response_metadata.stop_reason (Anthropic format)
|
|
4321
|
+
if (gen.generationInfo?.response_metadata?.stop_reason) {
|
|
4322
|
+
return String(gen.generationInfo.response_metadata.stop_reason);
|
|
4323
|
+
}
|
|
4324
|
+
// Check message response_metadata for finish_reason (common LangChain format)
|
|
4325
|
+
if (gen.generationInfo?.response_metadata?.finish_reason) {
|
|
4326
|
+
return String(gen.generationInfo.response_metadata.finish_reason);
|
|
4327
|
+
}
|
|
4328
|
+
// Check for stop_reason directly in generationInfo
|
|
4329
|
+
if (gen.generationInfo?.stop_reason) {
|
|
4330
|
+
return String(gen.generationInfo.stop_reason);
|
|
4331
|
+
}
|
|
4332
|
+
return undefined;
|
|
4333
|
+
}
|
|
4191
4334
|
_parseUsageModel(usage, provider, model) {
|
|
4192
4335
|
const conversionList = [['promptTokens', 'input'], ['completionTokens', 'output'], ['input_tokens', 'input'], ['output_tokens', 'output'], ['prompt_token_count', 'input'], ['candidates_token_count', 'output'], ['inputTokenCount', 'input'], ['outputTokenCount', 'output'], ['input_token_count', 'input'], ['generated_token_count', 'output']];
|
|
4193
4336
|
const parsedUsage = conversionList.reduce((acc, [modelKey, typeKey]) => {
|