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