@posthog/ai 4.0.1 → 4.2.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/CHANGELOG.md +8 -0
- package/lib/anthropic/index.cjs.js +32 -25
- package/lib/anthropic/index.cjs.js.map +1 -1
- package/lib/anthropic/index.d.ts +1 -0
- package/lib/anthropic/index.esm.js +32 -25
- package/lib/anthropic/index.esm.js.map +1 -1
- package/lib/index.cjs.js +131 -55
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.esm.js +131 -55
- package/lib/index.esm.js.map +1 -1
- package/lib/langchain/index.cjs.js.map +1 -1
- package/lib/langchain/index.esm.js.map +1 -1
- package/lib/openai/index.cjs.js +32 -25
- package/lib/openai/index.cjs.js.map +1 -1
- package/lib/openai/index.d.ts +1 -0
- package/lib/openai/index.esm.js +32 -25
- package/lib/openai/index.esm.js.map +1 -1
- package/lib/posthog-ai/src/utils.d.ts +5 -1
- package/lib/posthog-ai/src/vercel/middleware.d.ts +2 -0
- package/lib/vercel/index.cjs.js +132 -55
- package/lib/vercel/index.cjs.js.map +1 -1
- package/lib/vercel/index.d.ts +1 -0
- package/lib/vercel/index.esm.js +132 -55
- package/lib/vercel/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/utils.ts +48 -20
- package/src/vercel/middleware.ts +68 -19
package/lib/index.cjs.js
CHANGED
|
@@ -32,6 +32,9 @@ var OpenAIOrignal__default = /*#__PURE__*/_interopDefaultLegacy(OpenAIOrignal);
|
|
|
32
32
|
var uuid__namespace = /*#__PURE__*/_interopNamespace(uuid);
|
|
33
33
|
var AnthropicOriginal__default = /*#__PURE__*/_interopDefaultLegacy(AnthropicOriginal);
|
|
34
34
|
|
|
35
|
+
// limit large outputs by truncating to 200kb (approx 200k bytes)
|
|
36
|
+
const MAX_OUTPUT_SIZE = 200000;
|
|
37
|
+
const STRING_FORMAT = 'utf8';
|
|
35
38
|
const getModelParams = params => {
|
|
36
39
|
if (!params) {
|
|
37
40
|
return {};
|
|
@@ -87,13 +90,26 @@ const mergeSystemPrompt = (params, provider) => {
|
|
|
87
90
|
const withPrivacyMode = (client, privacyMode, input) => {
|
|
88
91
|
return client.privacy_mode || privacyMode ? null : input;
|
|
89
92
|
};
|
|
93
|
+
const truncate = str => {
|
|
94
|
+
try {
|
|
95
|
+
const buffer$1 = buffer.Buffer.from(str, STRING_FORMAT);
|
|
96
|
+
if (buffer$1.length <= MAX_OUTPUT_SIZE) {
|
|
97
|
+
return str;
|
|
98
|
+
}
|
|
99
|
+
const truncatedBuffer = buffer$1.slice(0, MAX_OUTPUT_SIZE);
|
|
100
|
+
return `${truncatedBuffer.toString(STRING_FORMAT)}... [truncated]`;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error('Error truncating, likely not a string');
|
|
103
|
+
return str;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
90
106
|
function sanitizeValues(obj) {
|
|
91
107
|
if (obj === undefined || obj === null) {
|
|
92
108
|
return obj;
|
|
93
109
|
}
|
|
94
110
|
const jsonSafe = JSON.parse(JSON.stringify(obj));
|
|
95
111
|
if (typeof jsonSafe === 'string') {
|
|
96
|
-
return buffer.Buffer.from(jsonSafe,
|
|
112
|
+
return buffer.Buffer.from(jsonSafe, STRING_FORMAT).toString(STRING_FORMAT);
|
|
97
113
|
} else if (Array.isArray(jsonSafe)) {
|
|
98
114
|
return jsonSafe.map(sanitizeValues);
|
|
99
115
|
} else if (jsonSafe && typeof jsonSafe === 'object') {
|
|
@@ -116,7 +132,8 @@ const sendEventToPosthog = ({
|
|
|
116
132
|
usage = {},
|
|
117
133
|
isError = false,
|
|
118
134
|
error,
|
|
119
|
-
tools
|
|
135
|
+
tools,
|
|
136
|
+
fullDebug = false
|
|
120
137
|
}) => {
|
|
121
138
|
if (client.capture) {
|
|
122
139
|
// sanitize input and output for UTF-8 validity
|
|
@@ -151,32 +168,37 @@ const sendEventToPosthog = ({
|
|
|
151
168
|
$ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
|
|
152
169
|
} : {})
|
|
153
170
|
};
|
|
171
|
+
const properties = {
|
|
172
|
+
$ai_provider: params.posthogProviderOverride ?? provider,
|
|
173
|
+
$ai_model: params.posthogModelOverride ?? model,
|
|
174
|
+
$ai_model_parameters: getModelParams(params),
|
|
175
|
+
$ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeInput),
|
|
176
|
+
$ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeOutput),
|
|
177
|
+
$ai_http_status: httpStatus,
|
|
178
|
+
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
179
|
+
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
180
|
+
...additionalTokenValues,
|
|
181
|
+
$ai_latency: latency,
|
|
182
|
+
$ai_trace_id: traceId,
|
|
183
|
+
$ai_base_url: baseURL,
|
|
184
|
+
...params.posthogProperties,
|
|
185
|
+
...(distinctId ? {} : {
|
|
186
|
+
$process_person_profile: false
|
|
187
|
+
}),
|
|
188
|
+
...(tools ? {
|
|
189
|
+
$ai_tools: tools
|
|
190
|
+
} : {}),
|
|
191
|
+
...errorData,
|
|
192
|
+
...costOverrideData
|
|
193
|
+
};
|
|
194
|
+
if (fullDebug) {
|
|
195
|
+
// @ts-ignore
|
|
196
|
+
console.log('Sending event to PostHog', properties);
|
|
197
|
+
}
|
|
154
198
|
client.capture({
|
|
155
199
|
distinctId: distinctId ?? traceId,
|
|
156
200
|
event: '$ai_generation',
|
|
157
|
-
properties
|
|
158
|
-
$ai_provider: params.posthogProviderOverride ?? provider,
|
|
159
|
-
$ai_model: params.posthogModelOverride ?? model,
|
|
160
|
-
$ai_model_parameters: getModelParams(params),
|
|
161
|
-
$ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeInput),
|
|
162
|
-
$ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeOutput),
|
|
163
|
-
$ai_http_status: httpStatus,
|
|
164
|
-
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
165
|
-
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
166
|
-
...additionalTokenValues,
|
|
167
|
-
$ai_latency: latency,
|
|
168
|
-
$ai_trace_id: traceId,
|
|
169
|
-
$ai_base_url: baseURL,
|
|
170
|
-
...params.posthogProperties,
|
|
171
|
-
...(distinctId ? {} : {
|
|
172
|
-
$process_person_profile: false
|
|
173
|
-
}),
|
|
174
|
-
...(tools ? {
|
|
175
|
-
$ai_tools: tools
|
|
176
|
-
} : {}),
|
|
177
|
-
...errorData,
|
|
178
|
-
...costOverrideData
|
|
179
|
-
},
|
|
201
|
+
properties,
|
|
180
202
|
groups: params.posthogGroups
|
|
181
203
|
});
|
|
182
204
|
}
|
|
@@ -515,14 +537,27 @@ const mapVercelParams = params => {
|
|
|
515
537
|
};
|
|
516
538
|
};
|
|
517
539
|
const mapVercelPrompt = prompt => {
|
|
518
|
-
|
|
540
|
+
// normalize single inputs into an array of messages
|
|
541
|
+
let promptsArray;
|
|
542
|
+
if (typeof prompt === 'string') {
|
|
543
|
+
promptsArray = [{
|
|
544
|
+
role: 'user',
|
|
545
|
+
content: prompt
|
|
546
|
+
}];
|
|
547
|
+
} else if (!Array.isArray(prompt)) {
|
|
548
|
+
promptsArray = [prompt];
|
|
549
|
+
} else {
|
|
550
|
+
promptsArray = prompt;
|
|
551
|
+
}
|
|
552
|
+
// Map and truncate individual content
|
|
553
|
+
const inputs = promptsArray.map(p => {
|
|
519
554
|
let content = {};
|
|
520
555
|
if (Array.isArray(p.content)) {
|
|
521
556
|
content = p.content.map(c => {
|
|
522
557
|
if (c.type === 'text') {
|
|
523
558
|
return {
|
|
524
559
|
type: 'text',
|
|
525
|
-
content: c.text
|
|
560
|
+
content: truncate(c.text)
|
|
526
561
|
};
|
|
527
562
|
} else if (c.type === 'image') {
|
|
528
563
|
return {
|
|
@@ -568,7 +603,7 @@ const mapVercelPrompt = prompt => {
|
|
|
568
603
|
} else {
|
|
569
604
|
content = {
|
|
570
605
|
type: 'text',
|
|
571
|
-
text: p.content
|
|
606
|
+
text: truncate(p.content)
|
|
572
607
|
};
|
|
573
608
|
}
|
|
574
609
|
return {
|
|
@@ -576,48 +611,85 @@ const mapVercelPrompt = prompt => {
|
|
|
576
611
|
content
|
|
577
612
|
};
|
|
578
613
|
});
|
|
614
|
+
try {
|
|
615
|
+
// Trim the inputs array until its JSON size fits within MAX_OUTPUT_SIZE
|
|
616
|
+
let serialized = JSON.stringify(inputs);
|
|
617
|
+
while (buffer.Buffer.byteLength(serialized, 'utf8') > MAX_OUTPUT_SIZE && inputs.length > 0) {
|
|
618
|
+
// Remove oldest message
|
|
619
|
+
inputs.shift();
|
|
620
|
+
// add blank message to beginning of array
|
|
621
|
+
inputs.unshift({
|
|
622
|
+
role: 'assistant',
|
|
623
|
+
content: '[removed message due to size limit]'
|
|
624
|
+
});
|
|
625
|
+
serialized = JSON.stringify(inputs);
|
|
626
|
+
}
|
|
627
|
+
} catch (error) {
|
|
628
|
+
console.error('Error stringifying inputs');
|
|
629
|
+
return [{
|
|
630
|
+
role: 'posthog',
|
|
631
|
+
content: 'An error occurred while processing your request. Please try again.'
|
|
632
|
+
}];
|
|
633
|
+
}
|
|
634
|
+
return inputs;
|
|
579
635
|
};
|
|
580
636
|
const mapVercelOutput = result => {
|
|
637
|
+
// normalize string results to object
|
|
638
|
+
const normalizedResult = typeof result === 'string' ? {
|
|
639
|
+
text: result
|
|
640
|
+
} : result;
|
|
581
641
|
const output = {
|
|
582
|
-
...(
|
|
583
|
-
text:
|
|
642
|
+
...(normalizedResult.text ? {
|
|
643
|
+
text: normalizedResult.text
|
|
584
644
|
} : {}),
|
|
585
|
-
...(
|
|
586
|
-
object:
|
|
645
|
+
...(normalizedResult.object ? {
|
|
646
|
+
object: normalizedResult.object
|
|
587
647
|
} : {}),
|
|
588
|
-
...(
|
|
589
|
-
reasoning:
|
|
648
|
+
...(normalizedResult.reasoning ? {
|
|
649
|
+
reasoning: normalizedResult.reasoning
|
|
590
650
|
} : {}),
|
|
591
|
-
...(
|
|
592
|
-
response:
|
|
651
|
+
...(normalizedResult.response ? {
|
|
652
|
+
response: normalizedResult.response
|
|
593
653
|
} : {}),
|
|
594
|
-
...(
|
|
595
|
-
finishReason:
|
|
654
|
+
...(normalizedResult.finishReason ? {
|
|
655
|
+
finishReason: normalizedResult.finishReason
|
|
596
656
|
} : {}),
|
|
597
|
-
...(
|
|
598
|
-
usage:
|
|
657
|
+
...(normalizedResult.usage ? {
|
|
658
|
+
usage: normalizedResult.usage
|
|
599
659
|
} : {}),
|
|
600
|
-
...(
|
|
601
|
-
warnings:
|
|
660
|
+
...(normalizedResult.warnings ? {
|
|
661
|
+
warnings: normalizedResult.warnings
|
|
602
662
|
} : {}),
|
|
603
|
-
...(
|
|
604
|
-
toolCalls:
|
|
663
|
+
...(normalizedResult.providerMetadata ? {
|
|
664
|
+
toolCalls: normalizedResult.providerMetadata
|
|
665
|
+
} : {}),
|
|
666
|
+
...(normalizedResult.files ? {
|
|
667
|
+
files: normalizedResult.files.map(file => ({
|
|
668
|
+
name: file.name,
|
|
669
|
+
size: file.size,
|
|
670
|
+
type: file.type
|
|
671
|
+
}))
|
|
605
672
|
} : {})
|
|
606
673
|
};
|
|
607
|
-
// if text and no object or reasoning, return text
|
|
608
674
|
if (output.text && !output.object && !output.reasoning) {
|
|
609
675
|
return [{
|
|
610
|
-
content: output.text,
|
|
676
|
+
content: truncate(output.text),
|
|
677
|
+
role: 'assistant'
|
|
678
|
+
}];
|
|
679
|
+
}
|
|
680
|
+
// otherwise stringify and truncate
|
|
681
|
+
try {
|
|
682
|
+
const jsonOutput = JSON.stringify(output);
|
|
683
|
+
return [{
|
|
684
|
+
content: truncate(jsonOutput),
|
|
611
685
|
role: 'assistant'
|
|
612
686
|
}];
|
|
687
|
+
} catch (error) {
|
|
688
|
+
console.error('Error stringifying output');
|
|
689
|
+
return [];
|
|
613
690
|
}
|
|
614
|
-
return [{
|
|
615
|
-
content: JSON.stringify(output),
|
|
616
|
-
role: 'assistant'
|
|
617
|
-
}];
|
|
618
691
|
};
|
|
619
692
|
const extractProvider = model => {
|
|
620
|
-
// vercel provider is in the format of provider.endpoint
|
|
621
693
|
const provider = model.provider.toLowerCase();
|
|
622
694
|
const providerName = provider.split('.')[0];
|
|
623
695
|
return providerName;
|
|
@@ -673,7 +745,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
673
745
|
inputTokens: result.usage.promptTokens,
|
|
674
746
|
outputTokens: result.usage.completionTokens,
|
|
675
747
|
...additionalTokenValues
|
|
676
|
-
}
|
|
748
|
+
},
|
|
749
|
+
fullDebug: options.fullDebug
|
|
677
750
|
});
|
|
678
751
|
return result;
|
|
679
752
|
} catch (error) {
|
|
@@ -695,7 +768,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
695
768
|
outputTokens: 0
|
|
696
769
|
},
|
|
697
770
|
isError: true,
|
|
698
|
-
error: JSON.stringify(error)
|
|
771
|
+
error: truncate(JSON.stringify(error)),
|
|
772
|
+
fullDebug: options.fullDebug
|
|
699
773
|
});
|
|
700
774
|
throw error;
|
|
701
775
|
}
|
|
@@ -761,7 +835,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
761
835
|
baseURL,
|
|
762
836
|
params: mergedParams,
|
|
763
837
|
httpStatus: 200,
|
|
764
|
-
usage
|
|
838
|
+
usage,
|
|
839
|
+
fullDebug: options.fullDebug
|
|
765
840
|
});
|
|
766
841
|
}
|
|
767
842
|
});
|
|
@@ -787,7 +862,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
787
862
|
outputTokens: 0
|
|
788
863
|
},
|
|
789
864
|
isError: true,
|
|
790
|
-
error: JSON.stringify(error)
|
|
865
|
+
error: truncate(JSON.stringify(error)),
|
|
866
|
+
fullDebug: options.fullDebug
|
|
791
867
|
});
|
|
792
868
|
throw error;
|
|
793
869
|
}
|