@posthog/ai 7.16.14 → 7.17.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/README.md +31 -0
- package/dist/anthropic/index.cjs +83 -95
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +83 -95
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +92 -106
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.mjs +92 -106
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +267 -318
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +83 -2
- package/dist/index.mjs +245 -297
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +2 -3
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +2 -3
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +161 -185
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +161 -185
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openai-agents/index.cjs +2 -3
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.mjs +2 -3
- package/dist/openai-agents/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +104 -111
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +104 -111
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/gemini/index.mjs
CHANGED
|
@@ -2,8 +2,6 @@ import { GoogleGenAI } from '@google/genai';
|
|
|
2
2
|
import { v4 } from 'uuid';
|
|
3
3
|
import { uuidv7 } from '@posthog/core';
|
|
4
4
|
|
|
5
|
-
var version = "7.16.14";
|
|
6
|
-
|
|
7
5
|
// Type guards for safer type checking
|
|
8
6
|
|
|
9
7
|
const isString = value => {
|
|
@@ -295,73 +293,69 @@ function addDefaults(params) {
|
|
|
295
293
|
traceId: params.traceId ?? v4()
|
|
296
294
|
};
|
|
297
295
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
await sendEventToPosthog(properties);
|
|
323
|
-
return enrichedError;
|
|
324
|
-
};
|
|
325
|
-
const sendEventToPosthog = async ({
|
|
326
|
-
client,
|
|
327
|
-
eventType = AIEvent.Generation,
|
|
328
|
-
distinctId,
|
|
329
|
-
traceId,
|
|
330
|
-
model,
|
|
331
|
-
provider,
|
|
332
|
-
input,
|
|
333
|
-
output,
|
|
334
|
-
latency,
|
|
335
|
-
timeToFirstToken,
|
|
336
|
-
baseURL,
|
|
337
|
-
params,
|
|
338
|
-
httpStatus = 200,
|
|
339
|
-
usage = {},
|
|
340
|
-
error,
|
|
341
|
-
exceptionId,
|
|
342
|
-
stopReason,
|
|
343
|
-
tools,
|
|
344
|
-
captureImmediate = false
|
|
345
|
-
}) => {
|
|
296
|
+
|
|
297
|
+
var version = "7.17.0";
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Options for `captureAiGeneration`. Mirrors the `$ai_generation` event shape
|
|
301
|
+
* directly so that any caller — first-party SDK wrappers and external code
|
|
302
|
+
* alike — produces an identical event.
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Capture an `$ai_generation` (or `$ai_embedding`) event to PostHog.
|
|
307
|
+
*
|
|
308
|
+
* This is the canonical primitive that every `@posthog/ai` wrapper
|
|
309
|
+
* (`withTracing`, `OpenAI`, `Anthropic`, `GoogleGenAI`, …) funnels through, so
|
|
310
|
+
* external code can use it directly to instrument LLM calls made through
|
|
311
|
+
* arbitrary clients (Cloudflare Workers AI, custom HTTP, etc.) and get the
|
|
312
|
+
* same events the SDK wrappers produce.
|
|
313
|
+
*
|
|
314
|
+
* When `error` is set, the event is captured as an error. If the error is an
|
|
315
|
+
* object, it is mutated in place to set `__posthog_previously_captured_error`
|
|
316
|
+
* so callers can re-throw the original error reference safely.
|
|
317
|
+
*/
|
|
318
|
+
const captureAiGeneration = async (client, options) => {
|
|
346
319
|
if (!client.capture) {
|
|
347
|
-
return
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
const
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const traceId = options.traceId ?? v4();
|
|
323
|
+
const eventType = options.eventType ?? AIEvent.Generation;
|
|
324
|
+
const privacyMode = options.privacyMode ?? false;
|
|
325
|
+
const usage = options.usage ?? {};
|
|
326
|
+
const safeInput = sanitizeValues(options.input);
|
|
327
|
+
const safeOutput = sanitizeValues(options.output);
|
|
328
|
+
let httpStatus = options.httpStatus;
|
|
353
329
|
let errorData = {};
|
|
354
|
-
if (error) {
|
|
330
|
+
if (options.error) {
|
|
331
|
+
if (httpStatus === undefined) {
|
|
332
|
+
if (typeof options.error === 'object' && 'status' in options.error && typeof options.error.status === 'number') {
|
|
333
|
+
httpStatus = options.error.status;
|
|
334
|
+
} else {
|
|
335
|
+
httpStatus = 500;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
let exceptionId;
|
|
339
|
+
if (client.options?.enableExceptionAutocapture) {
|
|
340
|
+
exceptionId = uuidv7();
|
|
341
|
+
client.captureException(options.error, undefined, {
|
|
342
|
+
$ai_trace_id: traceId
|
|
343
|
+
}, exceptionId);
|
|
344
|
+
if (typeof options.error === 'object') {
|
|
345
|
+
options.error.__posthog_previously_captured_error = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
355
348
|
errorData = {
|
|
356
349
|
$ai_is_error: true,
|
|
357
|
-
$ai_error:
|
|
350
|
+
$ai_error: sanitizeValues(JSON.stringify(options.error)),
|
|
358
351
|
$exception_event_id: exceptionId
|
|
359
352
|
};
|
|
360
353
|
}
|
|
354
|
+
httpStatus = httpStatus ?? 200;
|
|
361
355
|
let costOverrideData = {};
|
|
362
|
-
if (
|
|
363
|
-
const inputCostUSD = (
|
|
364
|
-
const outputCostUSD = (
|
|
356
|
+
if (options.costOverride) {
|
|
357
|
+
const inputCostUSD = (options.costOverride.inputCost ?? 0) * (usage.inputTokens ?? 0);
|
|
358
|
+
const outputCostUSD = (options.costOverride.outputCost ?? 0) * (usage.outputTokens ?? 0);
|
|
365
359
|
costOverrideData = {
|
|
366
360
|
$ai_input_cost_usd: inputCostUSD,
|
|
367
361
|
$ai_output_cost_usd: outputCostUSD,
|
|
@@ -388,50 +382,48 @@ const sendEventToPosthog = async ({
|
|
|
388
382
|
const properties = {
|
|
389
383
|
$ai_lib: 'posthog-ai',
|
|
390
384
|
$ai_lib_version: version,
|
|
391
|
-
$ai_provider:
|
|
392
|
-
$ai_model:
|
|
393
|
-
$ai_model_parameters:
|
|
394
|
-
$ai_input: withPrivacyMode(client,
|
|
395
|
-
$ai_output_choices: withPrivacyMode(client,
|
|
385
|
+
$ai_provider: options.providerOverride ?? options.provider,
|
|
386
|
+
$ai_model: options.modelOverride ?? options.model,
|
|
387
|
+
$ai_model_parameters: options.modelParameters ?? {},
|
|
388
|
+
$ai_input: withPrivacyMode(client, privacyMode, safeInput),
|
|
389
|
+
$ai_output_choices: withPrivacyMode(client, privacyMode, safeOutput),
|
|
396
390
|
$ai_http_status: httpStatus,
|
|
397
391
|
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
398
392
|
...(usage.outputTokens !== undefined ? {
|
|
399
393
|
$ai_output_tokens: usage.outputTokens
|
|
400
394
|
} : {}),
|
|
401
395
|
...additionalTokenValues,
|
|
402
|
-
$ai_latency: latency,
|
|
403
|
-
...(timeToFirstToken !== undefined ? {
|
|
404
|
-
$ai_time_to_first_token: timeToFirstToken
|
|
396
|
+
$ai_latency: options.latency ?? 0,
|
|
397
|
+
...(options.timeToFirstToken !== undefined ? {
|
|
398
|
+
$ai_time_to_first_token: options.timeToFirstToken
|
|
405
399
|
} : {}),
|
|
406
400
|
$ai_trace_id: traceId,
|
|
407
|
-
$ai_base_url: baseURL,
|
|
408
|
-
...
|
|
409
|
-
$ai_tokens_source: getTokensSource(
|
|
410
|
-
...(distinctId ? {} : {
|
|
401
|
+
$ai_base_url: options.baseURL ?? '',
|
|
402
|
+
...options.properties,
|
|
403
|
+
$ai_tokens_source: getTokensSource(options.properties),
|
|
404
|
+
...(options.distinctId ? {} : {
|
|
411
405
|
$process_person_profile: false
|
|
412
406
|
}),
|
|
413
|
-
...(stopReason ? {
|
|
414
|
-
$ai_stop_reason: stopReason
|
|
407
|
+
...(options.stopReason ? {
|
|
408
|
+
$ai_stop_reason: options.stopReason
|
|
415
409
|
} : {}),
|
|
416
|
-
...(tools ? {
|
|
417
|
-
$ai_tools: tools
|
|
410
|
+
...(options.tools ? {
|
|
411
|
+
$ai_tools: options.tools
|
|
418
412
|
} : {}),
|
|
419
413
|
...errorData,
|
|
420
414
|
...costOverrideData
|
|
421
415
|
};
|
|
422
416
|
const event = {
|
|
423
|
-
distinctId: distinctId ?? traceId,
|
|
417
|
+
distinctId: options.distinctId ?? traceId,
|
|
424
418
|
event: eventType,
|
|
425
419
|
properties,
|
|
426
|
-
groups:
|
|
420
|
+
groups: options.groups
|
|
427
421
|
};
|
|
428
|
-
if (captureImmediate) {
|
|
429
|
-
// await capture promise to send single event in serverless environments
|
|
422
|
+
if (options.captureImmediate) {
|
|
430
423
|
await client.captureImmediate(event);
|
|
431
424
|
} else {
|
|
432
425
|
client.capture(event);
|
|
433
426
|
}
|
|
434
|
-
return Promise.resolve();
|
|
435
427
|
};
|
|
436
428
|
|
|
437
429
|
class PostHogGoogleGenAI {
|
|
@@ -462,8 +454,7 @@ class WrappedModels {
|
|
|
462
454
|
const availableTools = extractAvailableToolCalls('gemini', geminiParams);
|
|
463
455
|
const metadata = response.usageMetadata;
|
|
464
456
|
const finishReason = response.candidates?.[0]?.finishReason;
|
|
465
|
-
await
|
|
466
|
-
client: this.phClient,
|
|
457
|
+
await captureAiGeneration(this.phClient, {
|
|
467
458
|
...posthogParams,
|
|
468
459
|
model: geminiParams.model,
|
|
469
460
|
provider: 'gemini',
|
|
@@ -471,7 +462,7 @@ class WrappedModels {
|
|
|
471
462
|
output: formatResponseGemini(response),
|
|
472
463
|
latency,
|
|
473
464
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
474
|
-
|
|
465
|
+
modelParameters: getModelParams(params),
|
|
475
466
|
httpStatus: 200,
|
|
476
467
|
usage: {
|
|
477
468
|
inputTokens: metadata?.promptTokenCount ?? 0,
|
|
@@ -487,8 +478,7 @@ class WrappedModels {
|
|
|
487
478
|
return response;
|
|
488
479
|
} catch (error) {
|
|
489
480
|
const latency = (Date.now() - startTime) / 1000;
|
|
490
|
-
|
|
491
|
-
client: this.phClient,
|
|
481
|
+
await captureAiGeneration(this.phClient, {
|
|
492
482
|
...posthogParams,
|
|
493
483
|
model: geminiParams.model,
|
|
494
484
|
provider: 'gemini',
|
|
@@ -496,14 +486,14 @@ class WrappedModels {
|
|
|
496
486
|
output: [],
|
|
497
487
|
latency,
|
|
498
488
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
499
|
-
|
|
489
|
+
modelParameters: getModelParams(params),
|
|
500
490
|
usage: {
|
|
501
491
|
inputTokens: 0,
|
|
502
492
|
outputTokens: 0
|
|
503
493
|
},
|
|
504
|
-
error
|
|
494
|
+
error
|
|
505
495
|
});
|
|
506
|
-
throw
|
|
496
|
+
throw error;
|
|
507
497
|
}
|
|
508
498
|
}
|
|
509
499
|
async *generateContentStream(params) {
|
|
@@ -607,8 +597,7 @@ class WrappedModels {
|
|
|
607
597
|
role: 'assistant',
|
|
608
598
|
content: accumulatedContent
|
|
609
599
|
}] : [];
|
|
610
|
-
await
|
|
611
|
-
client: this.phClient,
|
|
600
|
+
await captureAiGeneration(this.phClient, {
|
|
612
601
|
...posthogParams,
|
|
613
602
|
model: geminiParams.model,
|
|
614
603
|
provider: 'gemini',
|
|
@@ -617,7 +606,7 @@ class WrappedModels {
|
|
|
617
606
|
latency,
|
|
618
607
|
timeToFirstToken,
|
|
619
608
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
620
|
-
|
|
609
|
+
modelParameters: getModelParams(params),
|
|
621
610
|
httpStatus: 200,
|
|
622
611
|
usage: {
|
|
623
612
|
...usage,
|
|
@@ -629,8 +618,7 @@ class WrappedModels {
|
|
|
629
618
|
});
|
|
630
619
|
} catch (error) {
|
|
631
620
|
const latency = (Date.now() - startTime) / 1000;
|
|
632
|
-
|
|
633
|
-
client: this.phClient,
|
|
621
|
+
await captureAiGeneration(this.phClient, {
|
|
634
622
|
...posthogParams,
|
|
635
623
|
model: geminiParams.model,
|
|
636
624
|
provider: 'gemini',
|
|
@@ -638,14 +626,14 @@ class WrappedModels {
|
|
|
638
626
|
output: [],
|
|
639
627
|
latency,
|
|
640
628
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
641
|
-
|
|
629
|
+
modelParameters: getModelParams(params),
|
|
642
630
|
usage: {
|
|
643
631
|
inputTokens: 0,
|
|
644
632
|
outputTokens: 0
|
|
645
633
|
},
|
|
646
|
-
error
|
|
634
|
+
error
|
|
647
635
|
});
|
|
648
|
-
throw
|
|
636
|
+
throw error;
|
|
649
637
|
}
|
|
650
638
|
}
|
|
651
639
|
async embedContent(params) {
|
|
@@ -658,8 +646,7 @@ class WrappedModels {
|
|
|
658
646
|
const response = await this.client.models.embedContent(geminiParams);
|
|
659
647
|
const latency = (Date.now() - startTime) / 1000;
|
|
660
648
|
const inputTokens = extractEmbeddingTokenCount(response);
|
|
661
|
-
await
|
|
662
|
-
client: this.phClient,
|
|
649
|
+
await captureAiGeneration(this.phClient, {
|
|
663
650
|
...posthogParams,
|
|
664
651
|
eventType: AIEvent.Embedding,
|
|
665
652
|
model: geminiParams.model,
|
|
@@ -668,7 +655,7 @@ class WrappedModels {
|
|
|
668
655
|
output: null,
|
|
669
656
|
latency,
|
|
670
657
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
671
|
-
|
|
658
|
+
modelParameters: getModelParams(params),
|
|
672
659
|
httpStatus: 200,
|
|
673
660
|
usage: {
|
|
674
661
|
inputTokens
|
|
@@ -677,8 +664,7 @@ class WrappedModels {
|
|
|
677
664
|
return response;
|
|
678
665
|
} catch (error) {
|
|
679
666
|
const latency = (Date.now() - startTime) / 1000;
|
|
680
|
-
|
|
681
|
-
client: this.phClient,
|
|
667
|
+
await captureAiGeneration(this.phClient, {
|
|
682
668
|
...posthogParams,
|
|
683
669
|
eventType: AIEvent.Embedding,
|
|
684
670
|
model: geminiParams.model,
|
|
@@ -687,13 +673,13 @@ class WrappedModels {
|
|
|
687
673
|
output: null,
|
|
688
674
|
latency,
|
|
689
675
|
baseURL: 'https://generativelanguage.googleapis.com',
|
|
690
|
-
|
|
676
|
+
modelParameters: getModelParams(params),
|
|
691
677
|
usage: {
|
|
692
678
|
inputTokens: 0
|
|
693
679
|
},
|
|
694
|
-
error
|
|
680
|
+
error
|
|
695
681
|
});
|
|
696
|
-
throw
|
|
682
|
+
throw error;
|
|
697
683
|
}
|
|
698
684
|
}
|
|
699
685
|
formatPartsAsContentBlocks(parts) {
|