@posthog/ai 7.11.2 → 7.12.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/README.md +16 -33
- package/dist/anthropic/index.cjs +1 -1
- package/dist/anthropic/index.mjs +1 -1
- package/dist/gemini/index.cjs +1 -1
- package/dist/gemini/index.mjs +1 -1
- package/dist/index.cjs +29 -841
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +29 -62
- package/dist/index.mjs +29 -839
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +1 -1
- package/dist/langchain/index.mjs +1 -1
- package/dist/openai/index.cjs +1 -1
- package/dist/openai/index.mjs +1 -1
- package/dist/otel/index.cjs +30 -1128
- package/dist/otel/index.cjs.map +1 -1
- package/dist/otel/index.d.ts +29 -72
- package/dist/otel/index.mjs +30 -1125
- package/dist/otel/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +1 -1
- package/dist/vercel/index.mjs +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var openai = require('openai');
|
|
4
4
|
var uuid = require('uuid');
|
|
5
5
|
var core = require('@posthog/core');
|
|
6
|
+
var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
|
|
6
7
|
var AnthropicOriginal = require('@anthropic-ai/sdk');
|
|
7
8
|
var genai = require('@google/genai');
|
|
8
9
|
|
|
@@ -29,7 +30,7 @@ function _interopNamespace(e) {
|
|
|
29
30
|
var uuid__namespace = /*#__PURE__*/_interopNamespace(uuid);
|
|
30
31
|
var AnthropicOriginal__default = /*#__PURE__*/_interopDefault(AnthropicOriginal);
|
|
31
32
|
|
|
32
|
-
var version = "7.
|
|
33
|
+
var version = "7.12.1";
|
|
33
34
|
|
|
34
35
|
// Type guards for safer type checking
|
|
35
36
|
const isString = value => {
|
|
@@ -2635,847 +2636,36 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
2635
2636
|
return wrappedModel;
|
|
2636
2637
|
};
|
|
2637
2638
|
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
const parsed = Number(value);
|
|
2659
|
-
if (Number.isFinite(parsed)) {
|
|
2660
|
-
return parsed;
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
|
-
return undefined;
|
|
2664
|
-
}
|
|
2665
|
-
function toStringValue(value) {
|
|
2666
|
-
return typeof value === 'string' ? value : undefined;
|
|
2667
|
-
}
|
|
2668
|
-
function toStringArray(value) {
|
|
2669
|
-
if (!Array.isArray(value)) {
|
|
2670
|
-
return [];
|
|
2671
|
-
}
|
|
2672
|
-
return value.filter(item => typeof item === 'string');
|
|
2673
|
-
}
|
|
2674
|
-
function toSafeBinaryData(value) {
|
|
2675
|
-
const asString = typeof value === 'string' ? value : JSON.stringify(value ?? '');
|
|
2676
|
-
return truncate(redactBase64DataUrl(asString));
|
|
2677
|
-
}
|
|
2678
|
-
function toMimeType(value) {
|
|
2679
|
-
return typeof value === 'string' && value.length > 0 ? value : 'application/octet-stream';
|
|
2680
|
-
}
|
|
2681
|
-
function getSpanLatencySeconds(span) {
|
|
2682
|
-
const duration = span.duration;
|
|
2683
|
-
if (!duration || !Array.isArray(duration) || duration.length !== 2) {
|
|
2684
|
-
return 0;
|
|
2685
|
-
}
|
|
2686
|
-
const seconds = Number(duration[0]) || 0;
|
|
2687
|
-
const nanos = Number(duration[1]) || 0;
|
|
2688
|
-
return seconds + nanos / 1000000000;
|
|
2689
|
-
}
|
|
2690
|
-
function getOperationId(span) {
|
|
2691
|
-
const attributes = span.attributes || {};
|
|
2692
|
-
const operationId = toStringValue(attributes['ai.operationId']);
|
|
2693
|
-
if (operationId) {
|
|
2694
|
-
return operationId;
|
|
2695
|
-
}
|
|
2696
|
-
return span.name || '';
|
|
2697
|
-
}
|
|
2698
|
-
function isDoGenerateSpan(operationId) {
|
|
2699
|
-
return operationId.endsWith('.doGenerate');
|
|
2700
|
-
}
|
|
2701
|
-
function isDoStreamSpan(operationId) {
|
|
2702
|
-
return operationId.endsWith('.doStream');
|
|
2703
|
-
}
|
|
2704
|
-
function isDoEmbedSpan(operationId) {
|
|
2705
|
-
return operationId.endsWith('.doEmbed');
|
|
2706
|
-
}
|
|
2707
|
-
function shouldMapAiSdkSpan(span) {
|
|
2708
|
-
const operationId = getOperationId(span);
|
|
2709
|
-
return isDoGenerateSpan(operationId) || isDoStreamSpan(operationId) || isDoEmbedSpan(operationId);
|
|
2710
|
-
}
|
|
2711
|
-
function extractAiSdkTelemetryMetadata(attributes) {
|
|
2712
|
-
const metadata = {};
|
|
2713
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
2714
|
-
if (key.startsWith(AI_TELEMETRY_METADATA_PREFIX)) {
|
|
2715
|
-
metadata[key.slice(AI_TELEMETRY_METADATA_PREFIX.length)] = value;
|
|
2716
|
-
}
|
|
2717
|
-
}
|
|
2718
|
-
if (metadata.traceId && typeof metadata.traceId === 'string') {
|
|
2719
|
-
metadata.trace_id = metadata.traceId;
|
|
2720
|
-
}
|
|
2721
|
-
return metadata;
|
|
2722
|
-
}
|
|
2723
|
-
function mapPromptMessagesInput(attributes) {
|
|
2724
|
-
const promptMessages = parseJsonValue(attributes['ai.prompt.messages']) || [];
|
|
2725
|
-
if (!Array.isArray(promptMessages)) {
|
|
2726
|
-
return [];
|
|
2727
|
-
}
|
|
2728
|
-
return promptMessages.map(message => {
|
|
2729
|
-
const role = typeof message?.role === 'string' ? message.role : 'user';
|
|
2730
|
-
const content = message?.content;
|
|
2731
|
-
if (typeof content === 'string') {
|
|
2732
|
-
return {
|
|
2733
|
-
role,
|
|
2734
|
-
content: [{
|
|
2735
|
-
type: 'text',
|
|
2736
|
-
text: truncate(content)
|
|
2737
|
-
}]
|
|
2738
|
-
};
|
|
2739
|
-
}
|
|
2740
|
-
if (Array.isArray(content)) {
|
|
2741
|
-
return {
|
|
2742
|
-
role,
|
|
2743
|
-
content: content.map(part => {
|
|
2744
|
-
if (part && typeof part === 'object' && 'type' in part) {
|
|
2745
|
-
const typedPart = part;
|
|
2746
|
-
if (typedPart.type === 'text' && typeof typedPart.text === 'string') {
|
|
2747
|
-
return {
|
|
2748
|
-
type: 'text',
|
|
2749
|
-
text: truncate(typedPart.text)
|
|
2750
|
-
};
|
|
2751
|
-
}
|
|
2752
|
-
return typedPart;
|
|
2753
|
-
}
|
|
2754
|
-
return {
|
|
2755
|
-
type: 'text',
|
|
2756
|
-
text: truncate(String(part))
|
|
2757
|
-
};
|
|
2758
|
-
})
|
|
2759
|
-
};
|
|
2760
|
-
}
|
|
2761
|
-
return {
|
|
2762
|
-
role,
|
|
2763
|
-
content: [{
|
|
2764
|
-
type: 'text',
|
|
2765
|
-
text: truncate(content)
|
|
2766
|
-
}]
|
|
2767
|
-
};
|
|
2768
|
-
});
|
|
2769
|
-
}
|
|
2770
|
-
function mapPromptInput(attributes, operationId) {
|
|
2771
|
-
if (isDoEmbedSpan(operationId)) {
|
|
2772
|
-
if (attributes['ai.values'] !== undefined) {
|
|
2773
|
-
return attributes['ai.values'];
|
|
2774
|
-
}
|
|
2775
|
-
return attributes['ai.value'] ?? null;
|
|
2776
|
-
}
|
|
2777
|
-
const promptMessages = mapPromptMessagesInput(attributes);
|
|
2778
|
-
if (promptMessages.length > 0) {
|
|
2779
|
-
return promptMessages;
|
|
2780
|
-
}
|
|
2781
|
-
if (attributes['ai.prompt'] !== undefined) {
|
|
2782
|
-
return [{
|
|
2783
|
-
role: 'user',
|
|
2784
|
-
content: [{
|
|
2785
|
-
type: 'text',
|
|
2786
|
-
text: truncate(attributes['ai.prompt'])
|
|
2787
|
-
}]
|
|
2788
|
-
}];
|
|
2789
|
-
}
|
|
2790
|
-
return [];
|
|
2791
|
-
}
|
|
2792
|
-
function mapOutputPart(part) {
|
|
2793
|
-
const partType = toStringValue(part.type);
|
|
2794
|
-
if (partType === 'text' && typeof part.text === 'string') {
|
|
2795
|
-
return {
|
|
2796
|
-
type: 'text',
|
|
2797
|
-
text: truncate(part.text)
|
|
2798
|
-
};
|
|
2799
|
-
}
|
|
2800
|
-
if (partType === 'tool-call') {
|
|
2801
|
-
const toolName = toStringValue(part.toolName) || toStringValue(part.function?.name) || '';
|
|
2802
|
-
const toolCallId = toStringValue(part.toolCallId) || toStringValue(part.id) || '';
|
|
2803
|
-
const input = 'input' in part ? part.input : part.function?.arguments;
|
|
2804
|
-
if (toolName) {
|
|
2805
|
-
return {
|
|
2806
|
-
type: 'tool-call',
|
|
2807
|
-
id: toolCallId,
|
|
2808
|
-
function: {
|
|
2809
|
-
name: toolName,
|
|
2810
|
-
arguments: typeof input === 'string' ? input : JSON.stringify(input ?? {})
|
|
2811
|
-
}
|
|
2812
|
-
};
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
if (partType === 'file') {
|
|
2816
|
-
const mediaType = toMimeType(part.mediaType ?? part.mimeType ?? part.contentType);
|
|
2817
|
-
const data = part.data ?? part.base64 ?? part.bytes ?? part.url ?? part.uri;
|
|
2818
|
-
if (data !== undefined) {
|
|
2819
|
-
return {
|
|
2820
|
-
type: 'file',
|
|
2821
|
-
name: 'generated_file',
|
|
2822
|
-
mediaType,
|
|
2823
|
-
data: toSafeBinaryData(data)
|
|
2824
|
-
};
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
if (partType === 'image') {
|
|
2828
|
-
const mediaType = toMimeType(part.mediaType ?? part.mimeType ?? part.contentType ?? 'image/unknown');
|
|
2829
|
-
const data = part.data ?? part.base64 ?? part.bytes ?? part.url ?? part.uri ?? part.image ?? part.image_url;
|
|
2830
|
-
if (data !== undefined) {
|
|
2831
|
-
return {
|
|
2832
|
-
type: 'file',
|
|
2833
|
-
name: 'generated_file',
|
|
2834
|
-
mediaType,
|
|
2835
|
-
data: toSafeBinaryData(data)
|
|
2836
|
-
};
|
|
2837
|
-
}
|
|
2838
|
-
}
|
|
2839
|
-
const inlineData = part.inlineData ?? part.inline_data;
|
|
2840
|
-
if (inlineData && typeof inlineData === 'object' && inlineData.data !== undefined) {
|
|
2841
|
-
const mediaType = toMimeType(inlineData.mimeType ?? inlineData.mime_type);
|
|
2842
|
-
return {
|
|
2843
|
-
type: 'file',
|
|
2844
|
-
name: 'generated_file',
|
|
2845
|
-
mediaType,
|
|
2846
|
-
data: toSafeBinaryData(inlineData.data)
|
|
2847
|
-
};
|
|
2848
|
-
}
|
|
2849
|
-
if (partType === 'object' && part.object !== undefined) {
|
|
2850
|
-
return {
|
|
2851
|
-
type: 'object',
|
|
2852
|
-
object: part.object
|
|
2853
|
-
};
|
|
2854
|
-
}
|
|
2855
|
-
return null;
|
|
2856
|
-
}
|
|
2857
|
-
function mapResponseMessagesOutput(attributes) {
|
|
2858
|
-
const messagesRaw = parseJsonValue(attributes['ai.response.messages']) ?? parseJsonValue(attributes['ai.response.message']);
|
|
2859
|
-
if (!messagesRaw) {
|
|
2860
|
-
return [];
|
|
2861
|
-
}
|
|
2862
|
-
const messages = Array.isArray(messagesRaw) ? messagesRaw : [messagesRaw];
|
|
2863
|
-
const mappedMessages = [];
|
|
2864
|
-
for (const message of messages) {
|
|
2865
|
-
if (!message || typeof message !== 'object') {
|
|
2866
|
-
continue;
|
|
2867
|
-
}
|
|
2868
|
-
const role = toStringValue(message.role) || 'assistant';
|
|
2869
|
-
const content = message.content;
|
|
2870
|
-
if (typeof content === 'string') {
|
|
2871
|
-
mappedMessages.push({
|
|
2872
|
-
role,
|
|
2873
|
-
content: [{
|
|
2874
|
-
type: 'text',
|
|
2875
|
-
text: truncate(content)
|
|
2876
|
-
}]
|
|
2877
|
-
});
|
|
2878
|
-
continue;
|
|
2879
|
-
}
|
|
2880
|
-
if (Array.isArray(content)) {
|
|
2881
|
-
const parts = content.map(part => part && typeof part === 'object' ? mapOutputPart(part) : null).filter(part => part !== null);
|
|
2882
|
-
if (parts.length > 0) {
|
|
2883
|
-
mappedMessages.push({
|
|
2884
|
-
role,
|
|
2885
|
-
content: parts
|
|
2886
|
-
});
|
|
2887
|
-
}
|
|
2888
|
-
continue;
|
|
2889
|
-
}
|
|
2890
|
-
}
|
|
2891
|
-
return mappedMessages;
|
|
2892
|
-
}
|
|
2893
|
-
function mapTextToolObjectOutputParts(attributes) {
|
|
2894
|
-
const responseText = toStringValue(attributes['ai.response.text']) || '';
|
|
2895
|
-
const toolCalls = parseJsonValue(attributes['ai.response.toolCalls']) || [];
|
|
2896
|
-
const responseObjectRaw = attributes['ai.response.object'];
|
|
2897
|
-
const responseObject = parseJsonValue(responseObjectRaw);
|
|
2898
|
-
const contentParts = [];
|
|
2899
|
-
if (responseText) {
|
|
2900
|
-
contentParts.push({
|
|
2901
|
-
type: 'text',
|
|
2902
|
-
text: truncate(responseText)
|
|
2903
|
-
});
|
|
2904
|
-
}
|
|
2905
|
-
if (responseObjectRaw !== undefined) {
|
|
2906
|
-
contentParts.push({
|
|
2907
|
-
type: 'object',
|
|
2908
|
-
object: responseObject ?? responseObjectRaw
|
|
2909
|
-
});
|
|
2910
|
-
}
|
|
2911
|
-
if (Array.isArray(toolCalls)) {
|
|
2912
|
-
for (const toolCall of toolCalls) {
|
|
2913
|
-
if (!toolCall || typeof toolCall !== 'object') {
|
|
2914
|
-
continue;
|
|
2915
|
-
}
|
|
2916
|
-
const toolName = typeof toolCall.toolName === 'string' ? toolCall.toolName : '';
|
|
2917
|
-
const toolCallId = typeof toolCall.toolCallId === 'string' ? toolCall.toolCallId : '';
|
|
2918
|
-
if (!toolName) {
|
|
2919
|
-
continue;
|
|
2920
|
-
}
|
|
2921
|
-
const input = 'input' in toolCall ? toolCall.input : {};
|
|
2922
|
-
contentParts.push({
|
|
2923
|
-
type: 'tool-call',
|
|
2924
|
-
id: toolCallId,
|
|
2925
|
-
function: {
|
|
2926
|
-
name: toolName,
|
|
2927
|
-
arguments: typeof input === 'string' ? input : JSON.stringify(input)
|
|
2928
|
-
}
|
|
2929
|
-
});
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
return contentParts;
|
|
2933
|
-
}
|
|
2934
|
-
function mapResponseFilesOutput(attributes) {
|
|
2935
|
-
const responseFiles = parseJsonValue(attributes['ai.response.files']) || [];
|
|
2936
|
-
if (!Array.isArray(responseFiles)) {
|
|
2937
|
-
return [];
|
|
2938
|
-
}
|
|
2939
|
-
const mapped = [];
|
|
2940
|
-
for (const file of responseFiles) {
|
|
2941
|
-
if (!file || typeof file !== 'object') {
|
|
2942
|
-
continue;
|
|
2943
|
-
}
|
|
2944
|
-
const mimeType = toMimeType(file.mimeType ?? file.mediaType ?? file.contentType);
|
|
2945
|
-
const data = file.data ?? file.base64 ?? file.bytes;
|
|
2946
|
-
const url = typeof file.url === 'string' ? file.url : typeof file.uri === 'string' ? file.uri : undefined;
|
|
2947
|
-
if (data !== undefined) {
|
|
2948
|
-
mapped.push({
|
|
2949
|
-
type: 'file',
|
|
2950
|
-
name: 'generated_file',
|
|
2951
|
-
mediaType: mimeType,
|
|
2952
|
-
data: toSafeBinaryData(data)
|
|
2953
|
-
});
|
|
2954
|
-
continue;
|
|
2955
|
-
}
|
|
2956
|
-
if (url) {
|
|
2957
|
-
mapped.push({
|
|
2958
|
-
type: 'file',
|
|
2959
|
-
name: 'generated_file',
|
|
2960
|
-
mediaType: mimeType,
|
|
2961
|
-
data: truncate(url)
|
|
2962
|
-
});
|
|
2963
|
-
}
|
|
2964
|
-
}
|
|
2965
|
-
return mapped;
|
|
2966
|
-
}
|
|
2967
|
-
function extractGeminiParts(providerMetadata) {
|
|
2968
|
-
const parts = [];
|
|
2969
|
-
const visit = node => {
|
|
2970
|
-
if (!node || typeof node !== 'object') {
|
|
2971
|
-
return;
|
|
2972
|
-
}
|
|
2973
|
-
if (Array.isArray(node)) {
|
|
2974
|
-
for (const item of node) {
|
|
2975
|
-
visit(item);
|
|
2976
|
-
}
|
|
2977
|
-
return;
|
|
2978
|
-
}
|
|
2979
|
-
const objectNode = node;
|
|
2980
|
-
const maybeParts = objectNode.parts;
|
|
2981
|
-
if (Array.isArray(maybeParts)) {
|
|
2982
|
-
for (const part of maybeParts) {
|
|
2983
|
-
if (part && typeof part === 'object') {
|
|
2984
|
-
parts.push(part);
|
|
2985
|
-
}
|
|
2986
|
-
}
|
|
2987
|
-
}
|
|
2988
|
-
for (const value of Object.values(objectNode)) {
|
|
2989
|
-
visit(value);
|
|
2990
|
-
}
|
|
2991
|
-
};
|
|
2992
|
-
visit(providerMetadata);
|
|
2993
|
-
return parts;
|
|
2994
|
-
}
|
|
2995
|
-
function mapProviderMetadataInlineDataOutput(providerMetadata) {
|
|
2996
|
-
const parts = extractGeminiParts(providerMetadata);
|
|
2997
|
-
const mapped = [];
|
|
2998
|
-
for (const part of parts) {
|
|
2999
|
-
const inlineData = part.inlineData ?? part.inline_data;
|
|
3000
|
-
if (!inlineData || typeof inlineData !== 'object') {
|
|
3001
|
-
continue;
|
|
3002
|
-
}
|
|
3003
|
-
const mimeType = toMimeType(inlineData.mimeType ?? inlineData.mime_type);
|
|
3004
|
-
if (inlineData.data === undefined) {
|
|
3005
|
-
continue;
|
|
3006
|
-
}
|
|
3007
|
-
mapped.push({
|
|
3008
|
-
type: 'file',
|
|
3009
|
-
name: 'generated_file',
|
|
3010
|
-
mediaType: mimeType,
|
|
3011
|
-
data: toSafeBinaryData(inlineData.data)
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
|
-
return mapped;
|
|
3015
|
-
}
|
|
3016
|
-
function mapProviderMetadataTextOutput(providerMetadata) {
|
|
3017
|
-
const parts = extractGeminiParts(providerMetadata);
|
|
3018
|
-
const mapped = [];
|
|
3019
|
-
for (const part of parts) {
|
|
3020
|
-
if (typeof part.text === 'string' && part.text.length > 0) {
|
|
3021
|
-
mapped.push({
|
|
3022
|
-
type: 'text',
|
|
3023
|
-
text: truncate(part.text)
|
|
3024
|
-
});
|
|
3025
|
-
}
|
|
3026
|
-
}
|
|
3027
|
-
return mapped;
|
|
3028
|
-
}
|
|
3029
|
-
function extractMediaBlocksFromUnknownNode(node) {
|
|
3030
|
-
const mapped = [];
|
|
3031
|
-
const visit = value => {
|
|
3032
|
-
if (!value || typeof value !== 'object') {
|
|
3033
|
-
return;
|
|
3034
|
-
}
|
|
3035
|
-
if (Array.isArray(value)) {
|
|
3036
|
-
for (const item of value) {
|
|
3037
|
-
visit(item);
|
|
3038
|
-
}
|
|
3039
|
-
return;
|
|
3040
|
-
}
|
|
3041
|
-
const objectValue = value;
|
|
3042
|
-
const inlineData = objectValue.inlineData ?? objectValue.inline_data;
|
|
3043
|
-
if (inlineData && typeof inlineData === 'object' && inlineData.data !== undefined) {
|
|
3044
|
-
const mediaType = toMimeType(inlineData.mimeType ?? inlineData.mime_type);
|
|
3045
|
-
mapped.push({
|
|
3046
|
-
type: 'file',
|
|
3047
|
-
name: 'generated_file',
|
|
3048
|
-
mediaType,
|
|
3049
|
-
data: toSafeBinaryData(inlineData.data)
|
|
3050
|
-
});
|
|
3051
|
-
}
|
|
3052
|
-
if ((objectValue.type === 'file' || 'mediaType' in objectValue || 'mimeType' in objectValue) && objectValue.data) {
|
|
3053
|
-
const mediaType = toMimeType(objectValue.mediaType ?? objectValue.mimeType);
|
|
3054
|
-
mapped.push({
|
|
3055
|
-
type: 'file',
|
|
3056
|
-
name: 'generated_file',
|
|
3057
|
-
mediaType,
|
|
3058
|
-
data: toSafeBinaryData(objectValue.data)
|
|
3059
|
-
});
|
|
3060
|
-
}
|
|
3061
|
-
for (const child of Object.values(objectValue)) {
|
|
3062
|
-
visit(child);
|
|
3063
|
-
}
|
|
3064
|
-
};
|
|
3065
|
-
visit(node);
|
|
3066
|
-
return mapped;
|
|
3067
|
-
}
|
|
3068
|
-
function mapUnknownResponseAttributeMediaOutput(attributes) {
|
|
3069
|
-
const mapped = [];
|
|
3070
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
3071
|
-
if (!key.startsWith('ai.response.')) {
|
|
3072
|
-
continue;
|
|
3073
|
-
}
|
|
3074
|
-
if (key === 'ai.response.text' || key === 'ai.response.toolCalls' || key === 'ai.response.object' || key === 'ai.response.files' || key === 'ai.response.message' || key === 'ai.response.messages' || key === 'ai.response.providerMetadata') {
|
|
3075
|
-
continue;
|
|
3076
|
-
}
|
|
3077
|
-
const parsed = typeof value === 'string' ? parseJsonValue(value) ?? value : value;
|
|
3078
|
-
mapped.push(...extractMediaBlocksFromUnknownNode(parsed));
|
|
3079
|
-
}
|
|
3080
|
-
return mapped;
|
|
3081
|
-
}
|
|
3082
|
-
function mapGenericResponseAttributeMediaOutput(attributes) {
|
|
3083
|
-
const mapped = [];
|
|
3084
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
3085
|
-
if (!key.includes('response') || key.startsWith('ai.response.') || key === 'ai.response.providerMetadata' || key.startsWith('ai.prompt.') || key.startsWith('gen_ai.request.')) {
|
|
3086
|
-
continue;
|
|
3087
|
-
}
|
|
3088
|
-
const parsed = typeof value === 'string' ? parseJsonValue(value) : value;
|
|
3089
|
-
if (parsed === null || parsed === undefined) {
|
|
3090
|
-
continue;
|
|
3091
|
-
}
|
|
3092
|
-
mapped.push(...extractMediaBlocksFromUnknownNode(parsed));
|
|
3093
|
-
}
|
|
3094
|
-
return mapped;
|
|
3095
|
-
}
|
|
3096
|
-
function dedupeContentParts(parts) {
|
|
3097
|
-
const seen = new Set();
|
|
3098
|
-
const deduped = [];
|
|
3099
|
-
for (const part of parts) {
|
|
3100
|
-
const key = JSON.stringify(part);
|
|
3101
|
-
if (seen.has(key)) {
|
|
3102
|
-
continue;
|
|
3103
|
-
}
|
|
3104
|
-
seen.add(key);
|
|
3105
|
-
deduped.push(part);
|
|
3106
|
-
}
|
|
3107
|
-
return deduped;
|
|
3108
|
-
}
|
|
3109
|
-
function mapOutput(attributes, operationId, providerMetadata) {
|
|
3110
|
-
if (isDoEmbedSpan(operationId)) {
|
|
3111
|
-
// Keep embedding behavior aligned with existing provider wrappers.
|
|
3112
|
-
return null;
|
|
3113
|
-
}
|
|
3114
|
-
const responseMessages = mapResponseMessagesOutput(attributes);
|
|
3115
|
-
if (responseMessages.length > 0) {
|
|
3116
|
-
return responseMessages;
|
|
3117
|
-
}
|
|
3118
|
-
const textToolObjectParts = mapTextToolObjectOutputParts(attributes);
|
|
3119
|
-
const responseFileParts = mapResponseFilesOutput(attributes);
|
|
3120
|
-
const unknownMediaParts = mapUnknownResponseAttributeMediaOutput(attributes);
|
|
3121
|
-
const genericResponseMediaParts = mapGenericResponseAttributeMediaOutput(attributes);
|
|
3122
|
-
const providerMetadataTextParts = mapProviderMetadataTextOutput(providerMetadata);
|
|
3123
|
-
const providerMetadataInlineParts = mapProviderMetadataInlineDataOutput(providerMetadata);
|
|
3124
|
-
const mergedContentParts = dedupeContentParts([...textToolObjectParts, ...responseFileParts, ...unknownMediaParts, ...genericResponseMediaParts, ...providerMetadataTextParts, ...providerMetadataInlineParts]);
|
|
3125
|
-
const contentParts = mergedContentParts;
|
|
3126
|
-
if (contentParts.length === 0) {
|
|
3127
|
-
return [];
|
|
3128
|
-
}
|
|
3129
|
-
return [{
|
|
3130
|
-
role: 'assistant',
|
|
3131
|
-
content: contentParts
|
|
3132
|
-
}];
|
|
3133
|
-
}
|
|
3134
|
-
function mapModelSettings(attributes, operationId) {
|
|
3135
|
-
const temperature = toNumber(attributes['ai.settings.temperature']) ?? toNumber(attributes['gen_ai.request.temperature']);
|
|
3136
|
-
const maxTokens = toNumber(attributes['ai.settings.maxTokens']) ?? toNumber(attributes['gen_ai.request.max_tokens']);
|
|
3137
|
-
const maxOutputTokens = toNumber(attributes['ai.settings.maxOutputTokens']);
|
|
3138
|
-
const topP = toNumber(attributes['ai.settings.topP']) ?? toNumber(attributes['gen_ai.request.top_p']);
|
|
3139
|
-
const frequencyPenalty = toNumber(attributes['ai.settings.frequencyPenalty']) ?? toNumber(attributes['gen_ai.request.frequency_penalty']);
|
|
3140
|
-
const presencePenalty = toNumber(attributes['ai.settings.presencePenalty']) ?? toNumber(attributes['gen_ai.request.presence_penalty']);
|
|
3141
|
-
const stopSequences = parseJsonValue(attributes['ai.settings.stopSequences']) ?? parseJsonValue(attributes['gen_ai.request.stop_sequences']);
|
|
3142
|
-
const stream = isDoStreamSpan(operationId);
|
|
3143
|
-
return {
|
|
3144
|
-
...(temperature !== undefined ? {
|
|
3145
|
-
temperature
|
|
3146
|
-
} : {}),
|
|
3147
|
-
...(maxTokens !== undefined ? {
|
|
3148
|
-
max_tokens: maxTokens
|
|
3149
|
-
} : {}),
|
|
3150
|
-
...(maxOutputTokens !== undefined ? {
|
|
3151
|
-
max_completion_tokens: maxOutputTokens
|
|
3152
|
-
} : {}),
|
|
3153
|
-
...(topP !== undefined ? {
|
|
3154
|
-
top_p: topP
|
|
3155
|
-
} : {}),
|
|
3156
|
-
...(frequencyPenalty !== undefined ? {
|
|
3157
|
-
frequency_penalty: frequencyPenalty
|
|
3158
|
-
} : {}),
|
|
3159
|
-
...(presencePenalty !== undefined ? {
|
|
3160
|
-
presence_penalty: presencePenalty
|
|
3161
|
-
} : {}),
|
|
3162
|
-
...(stopSequences !== null ? {
|
|
3163
|
-
stop: stopSequences
|
|
3164
|
-
} : {}),
|
|
3165
|
-
...(stream ? {
|
|
3166
|
-
stream: true
|
|
3167
|
-
} : {})
|
|
3168
|
-
};
|
|
3169
|
-
}
|
|
3170
|
-
function mapUsage(attributes, providerMetadata, operationId) {
|
|
3171
|
-
if (isDoEmbedSpan(operationId)) {
|
|
3172
|
-
const tokens = toNumber(attributes['ai.usage.tokens']) ?? toNumber(attributes['gen_ai.usage.input_tokens']) ?? 0;
|
|
3173
|
-
return {
|
|
3174
|
-
inputTokens: tokens,
|
|
3175
|
-
rawUsage: {
|
|
3176
|
-
usage: {
|
|
3177
|
-
tokens
|
|
3178
|
-
},
|
|
3179
|
-
providerMetadata
|
|
3180
|
-
}
|
|
3181
|
-
};
|
|
3182
|
-
}
|
|
3183
|
-
const inputTokens = toNumber(attributes['ai.usage.promptTokens']) ?? toNumber(attributes['gen_ai.usage.input_tokens']) ?? 0;
|
|
3184
|
-
const outputTokens = toNumber(attributes['ai.usage.completionTokens']) ?? toNumber(attributes['gen_ai.usage.output_tokens']) ?? 0;
|
|
3185
|
-
const totalTokens = toNumber(attributes['ai.usage.totalTokens']);
|
|
3186
|
-
const reasoningTokens = toNumber(attributes['ai.usage.reasoningTokens']);
|
|
3187
|
-
const cachedInputTokens = toNumber(attributes['ai.usage.cachedInputTokens']);
|
|
3188
|
-
return {
|
|
3189
|
-
inputTokens,
|
|
3190
|
-
outputTokens,
|
|
3191
|
-
...(reasoningTokens !== undefined ? {
|
|
3192
|
-
reasoningTokens
|
|
3193
|
-
} : {}),
|
|
3194
|
-
...(cachedInputTokens !== undefined ? {
|
|
3195
|
-
cacheReadInputTokens: cachedInputTokens
|
|
3196
|
-
} : {}),
|
|
3197
|
-
rawUsage: {
|
|
3198
|
-
usage: {
|
|
3199
|
-
promptTokens: inputTokens,
|
|
3200
|
-
completionTokens: outputTokens,
|
|
3201
|
-
...(totalTokens !== undefined ? {
|
|
3202
|
-
totalTokens
|
|
3203
|
-
} : {})
|
|
3204
|
-
},
|
|
3205
|
-
providerMetadata
|
|
2639
|
+
/**
|
|
2640
|
+
* An OpenTelemetry SpanExporter that sends traces to PostHog's OTLP
|
|
2641
|
+
* ingestion endpoint. PostHog converts `gen_ai.*` spans into
|
|
2642
|
+
* `$ai_generation` events server-side.
|
|
2643
|
+
*
|
|
2644
|
+
* @example
|
|
2645
|
+
* ```ts
|
|
2646
|
+
* import { PostHogTraceExporter } from '@posthog/ai/otel'
|
|
2647
|
+
* import { NodeSDK } from '@opentelemetry/sdk-node'
|
|
2648
|
+
*
|
|
2649
|
+
* const sdk = new NodeSDK({
|
|
2650
|
+
* traceExporter: new PostHogTraceExporter({ apiKey: 'phc_...' }),
|
|
2651
|
+
* })
|
|
2652
|
+
* sdk.start()
|
|
2653
|
+
* ```
|
|
2654
|
+
*/
|
|
2655
|
+
class PostHogTraceExporter extends exporterTraceOtlpHttp.OTLPTraceExporter {
|
|
2656
|
+
constructor(options) {
|
|
2657
|
+
if (!options.apiKey) {
|
|
2658
|
+
throw new Error('PostHogTraceExporter requires an apiKey');
|
|
3206
2659
|
}
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
}
|
|
3214
|
-
const parsedTools = [];
|
|
3215
|
-
for (const rawTool of rawTools) {
|
|
3216
|
-
if (typeof rawTool === 'string') {
|
|
3217
|
-
const parsed = parseJsonValue(rawTool);
|
|
3218
|
-
if (parsed !== null) {
|
|
3219
|
-
parsedTools.push(parsed);
|
|
2660
|
+
const host = new URL(options.host || 'https://us.i.posthog.com').origin;
|
|
2661
|
+
super({
|
|
2662
|
+
url: `${host}/i/v0/ai/otel`,
|
|
2663
|
+
headers: {
|
|
2664
|
+
// The OTLP ingestion endpoint authenticates using the project API key as a Bearer token
|
|
2665
|
+
Authorization: `Bearer ${options.apiKey}`
|
|
3220
2666
|
}
|
|
3221
|
-
continue;
|
|
3222
|
-
}
|
|
3223
|
-
if (rawTool && typeof rawTool === 'object') {
|
|
3224
|
-
parsedTools.push(rawTool);
|
|
3225
|
-
}
|
|
3226
|
-
}
|
|
3227
|
-
return parsedTools.length > 0 ? parsedTools : null;
|
|
3228
|
-
}
|
|
3229
|
-
function extractProviderMetadata(attributes) {
|
|
3230
|
-
const rawProviderMetadata = attributes['ai.response.providerMetadata'];
|
|
3231
|
-
return parseJsonValue(rawProviderMetadata) || {};
|
|
3232
|
-
}
|
|
3233
|
-
function getAiSdkFrameworkVersion(span) {
|
|
3234
|
-
const instrumentedSpan = span;
|
|
3235
|
-
const attributes = span.attributes || {};
|
|
3236
|
-
const instrumentationScopeVersion = toStringValue(instrumentedSpan.instrumentationScope?.version) || toStringValue(instrumentedSpan.instrumentationLibrary?.version);
|
|
3237
|
-
const aiUserAgent = toStringValue(attributes['ai.request.headers.user-agent']);
|
|
3238
|
-
const userAgentVersionMatch = aiUserAgent?.match(/\bai\/(\d+(?:\.\d+)*)\b/i);
|
|
3239
|
-
const userAgentVersion = userAgentVersionMatch?.[1];
|
|
3240
|
-
const rawVersion = instrumentationScopeVersion || userAgentVersion;
|
|
3241
|
-
if (!rawVersion) {
|
|
3242
|
-
return undefined;
|
|
3243
|
-
}
|
|
3244
|
-
const majorVersionMatch = rawVersion.match(/^v?(\d+)/i);
|
|
3245
|
-
return majorVersionMatch ? majorVersionMatch[1] : rawVersion;
|
|
3246
|
-
}
|
|
3247
|
-
function buildPosthogProperties(attributes, operationId) {
|
|
3248
|
-
const telemetryMetadata = extractAiSdkTelemetryMetadata(attributes);
|
|
3249
|
-
const finishReasons = toStringArray(parseJsonValue(attributes['gen_ai.response.finish_reasons']));
|
|
3250
|
-
const finishReason = toStringValue(attributes['ai.response.finishReason']) || finishReasons[0];
|
|
3251
|
-
const toolChoice = parseJsonValue(attributes['ai.prompt.toolChoice']) ?? attributes['ai.prompt.toolChoice'];
|
|
3252
|
-
return {
|
|
3253
|
-
...telemetryMetadata,
|
|
3254
|
-
$ai_framework: 'vercel',
|
|
3255
|
-
ai_operation_id: operationId,
|
|
3256
|
-
...(finishReason ? {
|
|
3257
|
-
ai_finish_reason: finishReason
|
|
3258
|
-
} : {}),
|
|
3259
|
-
...(toStringValue(attributes['ai.response.model']) ? {
|
|
3260
|
-
ai_response_model: attributes['ai.response.model']
|
|
3261
|
-
} : {}),
|
|
3262
|
-
...(toStringValue(attributes['gen_ai.response.model']) ? {
|
|
3263
|
-
ai_response_model: attributes['gen_ai.response.model']
|
|
3264
|
-
} : {}),
|
|
3265
|
-
...(toStringValue(attributes['ai.response.id']) ? {
|
|
3266
|
-
ai_response_id: attributes['ai.response.id']
|
|
3267
|
-
} : {}),
|
|
3268
|
-
...(toStringValue(attributes['gen_ai.response.id']) ? {
|
|
3269
|
-
ai_response_id: attributes['gen_ai.response.id']
|
|
3270
|
-
} : {}),
|
|
3271
|
-
...(toStringValue(attributes['ai.response.timestamp']) ? {
|
|
3272
|
-
ai_response_timestamp: attributes['ai.response.timestamp']
|
|
3273
|
-
} : {}),
|
|
3274
|
-
...(toNumber(attributes['ai.response.msToFinish']) !== undefined ? {
|
|
3275
|
-
ai_response_ms_to_finish: toNumber(attributes['ai.response.msToFinish'])
|
|
3276
|
-
} : {}),
|
|
3277
|
-
...(toNumber(attributes['ai.response.avgCompletionTokensPerSecond']) !== undefined ? {
|
|
3278
|
-
ai_response_avg_completion_tokens_per_second: toNumber(attributes['ai.response.avgCompletionTokensPerSecond'])
|
|
3279
|
-
} : {}),
|
|
3280
|
-
...(toStringValue(attributes['ai.telemetry.functionId']) ? {
|
|
3281
|
-
ai_telemetry_function_id: attributes['ai.telemetry.functionId']
|
|
3282
|
-
} : {}),
|
|
3283
|
-
...(toNumber(attributes['ai.settings.maxRetries']) !== undefined ? {
|
|
3284
|
-
ai_settings_max_retries: toNumber(attributes['ai.settings.maxRetries'])
|
|
3285
|
-
} : {}),
|
|
3286
|
-
...(toNumber(attributes['gen_ai.request.top_k']) !== undefined ? {
|
|
3287
|
-
ai_request_top_k: toNumber(attributes['gen_ai.request.top_k'])
|
|
3288
|
-
} : {}),
|
|
3289
|
-
...(attributes['ai.schema.name'] !== undefined ? {
|
|
3290
|
-
ai_schema_name: attributes['ai.schema.name']
|
|
3291
|
-
} : {}),
|
|
3292
|
-
...(attributes['ai.schema.description'] !== undefined ? {
|
|
3293
|
-
ai_schema_description: attributes['ai.schema.description']
|
|
3294
|
-
} : {}),
|
|
3295
|
-
...(attributes['ai.settings.output'] !== undefined ? {
|
|
3296
|
-
ai_settings_output: attributes['ai.settings.output']
|
|
3297
|
-
} : {}),
|
|
3298
|
-
...(toolChoice ? {
|
|
3299
|
-
ai_prompt_tool_choice: toolChoice
|
|
3300
|
-
} : {})
|
|
3301
|
-
};
|
|
3302
|
-
}
|
|
3303
|
-
function buildAiSdkMapperResult(span) {
|
|
3304
|
-
const attributes = span.attributes || {};
|
|
3305
|
-
const operationId = getOperationId(span);
|
|
3306
|
-
const providerMetadata = extractProviderMetadata(attributes);
|
|
3307
|
-
const model = toStringValue(attributes['ai.model.id']) || toStringValue(attributes['gen_ai.request.model']) || 'unknown';
|
|
3308
|
-
const provider = (toStringValue(attributes['ai.model.provider']) || toStringValue(attributes['gen_ai.system']) || 'unknown').toLowerCase();
|
|
3309
|
-
const latency = getSpanLatencySeconds(span);
|
|
3310
|
-
const timeToFirstTokenMs = toNumber(attributes['ai.response.msToFirstChunk']);
|
|
3311
|
-
const timeToFirstToken = timeToFirstTokenMs !== undefined ? timeToFirstTokenMs / 1000 : undefined;
|
|
3312
|
-
const input = mapPromptInput(attributes, operationId);
|
|
3313
|
-
const output = mapOutput(attributes, operationId, providerMetadata);
|
|
3314
|
-
const usage = mapUsage(attributes, providerMetadata, operationId);
|
|
3315
|
-
const modelParams = mapModelSettings(attributes, operationId);
|
|
3316
|
-
const tools = parsePromptTools(attributes);
|
|
3317
|
-
const httpStatus = toNumber(attributes['http.response.status_code']) || 200;
|
|
3318
|
-
const eventType = isDoEmbedSpan(operationId) ? AIEvent.Embedding : AIEvent.Generation;
|
|
3319
|
-
const frameworkVersion = getAiSdkFrameworkVersion(span);
|
|
3320
|
-
const error = span.status?.code === OTEL_STATUS_ERROR ? span.status.message || 'AI SDK span recorded error status' : undefined;
|
|
3321
|
-
return {
|
|
3322
|
-
model,
|
|
3323
|
-
provider,
|
|
3324
|
-
input,
|
|
3325
|
-
output,
|
|
3326
|
-
latency,
|
|
3327
|
-
timeToFirstToken,
|
|
3328
|
-
httpStatus,
|
|
3329
|
-
eventType,
|
|
3330
|
-
usage,
|
|
3331
|
-
tools,
|
|
3332
|
-
modelParams,
|
|
3333
|
-
posthogProperties: {
|
|
3334
|
-
...buildPosthogProperties(attributes, operationId),
|
|
3335
|
-
...(frameworkVersion ? {
|
|
3336
|
-
$ai_framework_version: frameworkVersion
|
|
3337
|
-
} : {})
|
|
3338
|
-
},
|
|
3339
|
-
error
|
|
3340
|
-
};
|
|
3341
|
-
}
|
|
3342
|
-
const aiSdkSpanMapper = {
|
|
3343
|
-
name: 'ai-sdk',
|
|
3344
|
-
canMap: shouldMapAiSdkSpan,
|
|
3345
|
-
map: span => {
|
|
3346
|
-
return buildAiSdkMapperResult(span);
|
|
3347
|
-
}
|
|
3348
|
-
};
|
|
3349
|
-
|
|
3350
|
-
const defaultSpanMappers = [aiSdkSpanMapper];
|
|
3351
|
-
|
|
3352
|
-
function pickMapper(span, mappers) {
|
|
3353
|
-
return mappers.find(mapper => {
|
|
3354
|
-
try {
|
|
3355
|
-
return mapper.canMap(span);
|
|
3356
|
-
} catch {
|
|
3357
|
-
return false;
|
|
3358
|
-
}
|
|
3359
|
-
});
|
|
3360
|
-
}
|
|
3361
|
-
function getTraceId(span, options, mapperTraceId) {
|
|
3362
|
-
if (mapperTraceId) {
|
|
3363
|
-
return mapperTraceId;
|
|
3364
|
-
}
|
|
3365
|
-
if (options.posthogTraceId) {
|
|
3366
|
-
return options.posthogTraceId;
|
|
3367
|
-
}
|
|
3368
|
-
const spanTraceId = span.spanContext?.().traceId;
|
|
3369
|
-
return spanTraceId || uuid.v4();
|
|
3370
|
-
}
|
|
3371
|
-
function buildPosthogParams(options, traceId, distinctId, modelParams, posthogProperties) {
|
|
3372
|
-
return {
|
|
3373
|
-
...modelParams,
|
|
3374
|
-
posthogDistinctId: distinctId,
|
|
3375
|
-
posthogTraceId: traceId,
|
|
3376
|
-
posthogProperties,
|
|
3377
|
-
posthogPrivacyMode: options.posthogPrivacyMode,
|
|
3378
|
-
posthogGroups: options.posthogGroups,
|
|
3379
|
-
posthogModelOverride: options.posthogModelOverride,
|
|
3380
|
-
posthogProviderOverride: options.posthogProviderOverride,
|
|
3381
|
-
posthogCostOverride: options.posthogCostOverride,
|
|
3382
|
-
posthogCaptureImmediate: options.posthogCaptureImmediate
|
|
3383
|
-
};
|
|
3384
|
-
}
|
|
3385
|
-
async function captureSpan(span, phClient, options = {}) {
|
|
3386
|
-
if (options.shouldExportSpan && options.shouldExportSpan({
|
|
3387
|
-
otelSpan: span
|
|
3388
|
-
}) === false) {
|
|
3389
|
-
return;
|
|
3390
|
-
}
|
|
3391
|
-
const mappers = options.mappers ?? defaultSpanMappers;
|
|
3392
|
-
const mapper = pickMapper(span, mappers);
|
|
3393
|
-
if (!mapper) {
|
|
3394
|
-
return;
|
|
3395
|
-
}
|
|
3396
|
-
const mapped = mapper.map(span, {
|
|
3397
|
-
options
|
|
3398
|
-
});
|
|
3399
|
-
if (!mapped) {
|
|
3400
|
-
return;
|
|
3401
|
-
}
|
|
3402
|
-
const traceId = getTraceId(span, options, mapped.traceId);
|
|
3403
|
-
const distinctId = mapped.distinctId ?? options.posthogDistinctId;
|
|
3404
|
-
const posthogProperties = {
|
|
3405
|
-
...options.posthogProperties,
|
|
3406
|
-
...mapped.posthogProperties
|
|
3407
|
-
};
|
|
3408
|
-
const params = buildPosthogParams(options, traceId, distinctId, mapped.modelParams ?? {}, posthogProperties);
|
|
3409
|
-
const baseURL = mapped.baseURL ?? '';
|
|
3410
|
-
const usage = mapped.usage ?? {};
|
|
3411
|
-
if (mapped.error !== undefined) {
|
|
3412
|
-
await sendEventWithErrorToPosthog({
|
|
3413
|
-
eventType: mapped.eventType,
|
|
3414
|
-
client: phClient,
|
|
3415
|
-
distinctId,
|
|
3416
|
-
traceId,
|
|
3417
|
-
model: mapped.model,
|
|
3418
|
-
provider: mapped.provider,
|
|
3419
|
-
input: mapped.input,
|
|
3420
|
-
output: mapped.output,
|
|
3421
|
-
latency: mapped.latency,
|
|
3422
|
-
baseURL,
|
|
3423
|
-
params: params,
|
|
3424
|
-
usage,
|
|
3425
|
-
tools: mapped.tools,
|
|
3426
|
-
error: mapped.error,
|
|
3427
|
-
captureImmediate: options.posthogCaptureImmediate
|
|
3428
|
-
});
|
|
3429
|
-
return;
|
|
3430
|
-
}
|
|
3431
|
-
await sendEventToPosthog({
|
|
3432
|
-
eventType: mapped.eventType,
|
|
3433
|
-
client: phClient,
|
|
3434
|
-
distinctId,
|
|
3435
|
-
traceId,
|
|
3436
|
-
model: mapped.model,
|
|
3437
|
-
provider: mapped.provider,
|
|
3438
|
-
input: mapped.input,
|
|
3439
|
-
output: mapped.output,
|
|
3440
|
-
latency: mapped.latency,
|
|
3441
|
-
timeToFirstToken: mapped.timeToFirstToken,
|
|
3442
|
-
baseURL,
|
|
3443
|
-
params: params,
|
|
3444
|
-
httpStatus: mapped.httpStatus ?? 200,
|
|
3445
|
-
usage,
|
|
3446
|
-
tools: mapped.tools,
|
|
3447
|
-
captureImmediate: options.posthogCaptureImmediate
|
|
3448
|
-
});
|
|
3449
|
-
}
|
|
3450
|
-
|
|
3451
|
-
class PostHogSpanProcessor {
|
|
3452
|
-
constructor(phClient, options = {}) {
|
|
3453
|
-
this.phClient = phClient;
|
|
3454
|
-
this.options = options;
|
|
3455
|
-
this.pendingCaptures = new Set();
|
|
3456
|
-
}
|
|
3457
|
-
onStart(_span, _parentContext) {
|
|
3458
|
-
// no-op
|
|
3459
|
-
}
|
|
3460
|
-
onEnd(span) {
|
|
3461
|
-
const capturePromise = captureSpan(span, this.phClient, this.options).catch(error => {
|
|
3462
|
-
console.error('Failed to capture telemetry span', error);
|
|
3463
|
-
}).finally(() => {
|
|
3464
|
-
this.pendingCaptures.delete(capturePromise);
|
|
3465
2667
|
});
|
|
3466
|
-
this.pendingCaptures.add(capturePromise);
|
|
3467
2668
|
}
|
|
3468
|
-
async shutdown() {
|
|
3469
|
-
await this.forceFlush();
|
|
3470
|
-
}
|
|
3471
|
-
async forceFlush() {
|
|
3472
|
-
while (this.pendingCaptures.size > 0) {
|
|
3473
|
-
await Promise.allSettled([...this.pendingCaptures]);
|
|
3474
|
-
}
|
|
3475
|
-
}
|
|
3476
|
-
}
|
|
3477
|
-
function createPostHogSpanProcessor(phClient, options = {}) {
|
|
3478
|
-
return new PostHogSpanProcessor(phClient, options);
|
|
3479
2669
|
}
|
|
3480
2670
|
|
|
3481
2671
|
class PostHogAnthropic extends AnthropicOriginal__default.default {
|
|
@@ -5358,9 +4548,7 @@ exports.AzureOpenAI = PostHogAzureOpenAI;
|
|
|
5358
4548
|
exports.GoogleGenAI = PostHogGoogleGenAI;
|
|
5359
4549
|
exports.LangChainCallbackHandler = LangChainCallbackHandler;
|
|
5360
4550
|
exports.OpenAI = PostHogOpenAI;
|
|
5361
|
-
exports.
|
|
4551
|
+
exports.PostHogTraceExporter = PostHogTraceExporter;
|
|
5362
4552
|
exports.Prompts = Prompts;
|
|
5363
|
-
exports.captureSpan = captureSpan;
|
|
5364
|
-
exports.createPostHogSpanProcessor = createPostHogSpanProcessor;
|
|
5365
4553
|
exports.withTracing = wrapVercelLanguageModel;
|
|
5366
4554
|
//# sourceMappingURL=index.cjs.map
|