@posthog/ai 7.5.4 → 7.6.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/dist/anthropic/index.cjs +71 -63
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +71 -63
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +106 -54
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.mjs +106 -54
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +308 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +308 -223
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +161 -136
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +161 -136
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +163 -133
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +163 -133
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +82 -57
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +82 -57
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/langchain/index.cjs
CHANGED
|
@@ -24,7 +24,7 @@ function _interopNamespace(e) {
|
|
|
24
24
|
|
|
25
25
|
var uuid__namespace = /*#__PURE__*/_interopNamespace(uuid);
|
|
26
26
|
|
|
27
|
-
var version = "7.
|
|
27
|
+
var version = "7.6.1";
|
|
28
28
|
|
|
29
29
|
// Type guards for safer type checking
|
|
30
30
|
|
|
@@ -35,6 +35,136 @@ const isObject = value => {
|
|
|
35
35
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
39
|
+
|
|
40
|
+
// ============================================
|
|
41
|
+
// Multimodal Feature Toggle
|
|
42
|
+
// ============================================
|
|
43
|
+
|
|
44
|
+
const isMultimodalEnabled = () => {
|
|
45
|
+
const val = process.env._INTERNAL_LLMA_MULTIMODAL || '';
|
|
46
|
+
return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes';
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// ============================================
|
|
50
|
+
// Base64 Detection Helpers
|
|
51
|
+
// ============================================
|
|
52
|
+
|
|
53
|
+
const isBase64DataUrl = str => {
|
|
54
|
+
return /^data:([^;]+);base64,/.test(str);
|
|
55
|
+
};
|
|
56
|
+
const isValidUrl = str => {
|
|
57
|
+
try {
|
|
58
|
+
new URL(str);
|
|
59
|
+
return true;
|
|
60
|
+
} catch {
|
|
61
|
+
// Not an absolute URL, check if it's a relative URL or path
|
|
62
|
+
return str.startsWith('/') || str.startsWith('./') || str.startsWith('../');
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const isRawBase64 = str => {
|
|
66
|
+
// Skip if it's a valid URL or path
|
|
67
|
+
if (isValidUrl(str)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Check if it's a valid base64 string
|
|
72
|
+
// Base64 images are typically at least a few hundred chars, but we'll be conservative
|
|
73
|
+
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
74
|
+
};
|
|
75
|
+
function redactBase64DataUrl(str) {
|
|
76
|
+
if (isMultimodalEnabled()) return str;
|
|
77
|
+
if (!isString(str)) return str;
|
|
78
|
+
|
|
79
|
+
// Check for data URL format
|
|
80
|
+
if (isBase64DataUrl(str)) {
|
|
81
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check for raw base64 (Vercel sends raw base64 for inline images)
|
|
85
|
+
if (isRawBase64(str)) {
|
|
86
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
87
|
+
}
|
|
88
|
+
return str;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ============================================
|
|
92
|
+
// Common Message Processing
|
|
93
|
+
// ============================================
|
|
94
|
+
|
|
95
|
+
const processMessages = (messages, transformContent) => {
|
|
96
|
+
if (!messages) return messages;
|
|
97
|
+
const processContent = content => {
|
|
98
|
+
if (typeof content === 'string') return content;
|
|
99
|
+
if (!content) return content;
|
|
100
|
+
if (Array.isArray(content)) {
|
|
101
|
+
return content.map(transformContent);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Handle single object content
|
|
105
|
+
return transformContent(content);
|
|
106
|
+
};
|
|
107
|
+
const processMessage = msg => {
|
|
108
|
+
if (!isObject(msg) || !('content' in msg)) return msg;
|
|
109
|
+
return {
|
|
110
|
+
...msg,
|
|
111
|
+
content: processContent(msg.content)
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Handle both arrays and single messages
|
|
116
|
+
if (Array.isArray(messages)) {
|
|
117
|
+
return messages.map(processMessage);
|
|
118
|
+
}
|
|
119
|
+
return processMessage(messages);
|
|
120
|
+
};
|
|
121
|
+
const sanitizeLangChainImage = item => {
|
|
122
|
+
if (!isObject(item)) return item;
|
|
123
|
+
|
|
124
|
+
// OpenAI style
|
|
125
|
+
if (item.type === 'image_url' && 'image_url' in item && isObject(item.image_url) && 'url' in item.image_url) {
|
|
126
|
+
return {
|
|
127
|
+
...item,
|
|
128
|
+
image_url: {
|
|
129
|
+
...item.image_url,
|
|
130
|
+
url: redactBase64DataUrl(item.image_url.url)
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Direct image with data field
|
|
136
|
+
if (item.type === 'image' && 'data' in item) {
|
|
137
|
+
return {
|
|
138
|
+
...item,
|
|
139
|
+
data: redactBase64DataUrl(item.data)
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Anthropic style
|
|
144
|
+
if (item.type === 'image' && 'source' in item && isObject(item.source) && 'data' in item.source) {
|
|
145
|
+
if (isMultimodalEnabled()) return item;
|
|
146
|
+
return {
|
|
147
|
+
...item,
|
|
148
|
+
source: {
|
|
149
|
+
...item.source,
|
|
150
|
+
data: redactBase64DataUrl(item.source.data)
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Google style
|
|
156
|
+
if (item.type === 'media' && 'data' in item) {
|
|
157
|
+
return {
|
|
158
|
+
...item,
|
|
159
|
+
data: redactBase64DataUrl(item.data)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return item;
|
|
163
|
+
};
|
|
164
|
+
const sanitizeLangChain = data => {
|
|
165
|
+
return processMessages(data, sanitizeLangChainImage);
|
|
166
|
+
};
|
|
167
|
+
|
|
38
168
|
/**
|
|
39
169
|
* Safely converts content to a string, preserving structure for objects/arrays.
|
|
40
170
|
* - If content is already a string, returns it as-is
|
|
@@ -284,6 +414,20 @@ function isSerializableLike(obj) {
|
|
|
284
414
|
return obj !== null && typeof obj === "object" && "lc_serializable" in obj && typeof obj.toJSON === "function";
|
|
285
415
|
}
|
|
286
416
|
/**
|
|
417
|
+
* Create a "not_implemented" serialization result for objects that cannot be serialized.
|
|
418
|
+
*/
|
|
419
|
+
function createNotImplemented(obj) {
|
|
420
|
+
let id;
|
|
421
|
+
if (obj !== null && typeof obj === "object") if ("lc_id" in obj && Array.isArray(obj.lc_id)) id = obj.lc_id;
|
|
422
|
+
else id = [obj.constructor?.name ?? "Object"];
|
|
423
|
+
else id = [typeof obj];
|
|
424
|
+
return {
|
|
425
|
+
lc: 1,
|
|
426
|
+
type: "not_implemented",
|
|
427
|
+
id
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
287
431
|
* Escape a value if it needs escaping (contains `lc` key).
|
|
288
432
|
*
|
|
289
433
|
* This is a simpler version of `serializeValue` that doesn't handle Serializable
|
|
@@ -291,18 +435,27 @@ function isSerializableLike(obj) {
|
|
|
291
435
|
* processed by `toJSON()`.
|
|
292
436
|
*
|
|
293
437
|
* @param value - The value to potentially escape.
|
|
438
|
+
* @param pathSet - WeakSet to track ancestor objects in the current path to detect circular references.
|
|
439
|
+
* Objects are removed after processing to allow shared references (same object in
|
|
440
|
+
* multiple places) while still detecting true circular references (ancestor in descendant).
|
|
294
441
|
* @returns The value with any `lc`-containing objects wrapped in escape markers.
|
|
295
442
|
*/
|
|
296
|
-
function escapeIfNeeded(value) {
|
|
443
|
+
function escapeIfNeeded(value, pathSet = /* @__PURE__ */ new WeakSet()) {
|
|
297
444
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
445
|
+
if (pathSet.has(value)) return createNotImplemented(value);
|
|
298
446
|
if (isSerializableLike(value)) return value;
|
|
447
|
+
pathSet.add(value);
|
|
299
448
|
const record = value;
|
|
300
|
-
if (needsEscaping(record))
|
|
449
|
+
if (needsEscaping(record)) {
|
|
450
|
+
pathSet.delete(value);
|
|
451
|
+
return escapeObject(record);
|
|
452
|
+
}
|
|
301
453
|
const result = {};
|
|
302
|
-
for (const [key, val] of Object.entries(record)) result[key] = escapeIfNeeded(val);
|
|
454
|
+
for (const [key, val] of Object.entries(record)) result[key] = escapeIfNeeded(val, pathSet);
|
|
455
|
+
pathSet.delete(value);
|
|
303
456
|
return result;
|
|
304
457
|
}
|
|
305
|
-
if (Array.isArray(value)) return value.map((item) => escapeIfNeeded(item));
|
|
458
|
+
if (Array.isArray(value)) return value.map((item) => escapeIfNeeded(item, pathSet));
|
|
306
459
|
return value;
|
|
307
460
|
}
|
|
308
461
|
|
|
@@ -428,7 +581,9 @@ var Serializable = class Serializable {
|
|
|
428
581
|
if (last in read && read[last] !== void 0) write[last] = write[last] || read[last];
|
|
429
582
|
});
|
|
430
583
|
const escapedKwargs = {};
|
|
431
|
-
|
|
584
|
+
const pathSet = /* @__PURE__ */ new WeakSet();
|
|
585
|
+
pathSet.add(this);
|
|
586
|
+
for (const [key, value] of Object.entries(kwargs)) escapedKwargs[key] = escapeIfNeeded(value, pathSet);
|
|
432
587
|
const kwargsWithSecrets = Object.keys(secrets).length ? replaceSecrets(escapedKwargs, secrets) : escapedKwargs;
|
|
433
588
|
const processedKwargs = mapKeys(kwargsWithSecrets, keyToJson, aliases);
|
|
434
589
|
return {
|
|
@@ -599,136 +754,6 @@ const isBaseCallbackHandler = (x) => {
|
|
|
599
754
|
return callbackHandler !== void 0 && typeof callbackHandler.copy === "function" && typeof callbackHandler.name === "string" && typeof callbackHandler.awaitHandlers === "boolean";
|
|
600
755
|
};
|
|
601
756
|
|
|
602
|
-
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
603
|
-
|
|
604
|
-
// ============================================
|
|
605
|
-
// Multimodal Feature Toggle
|
|
606
|
-
// ============================================
|
|
607
|
-
|
|
608
|
-
const isMultimodalEnabled = () => {
|
|
609
|
-
const val = process.env._INTERNAL_LLMA_MULTIMODAL || '';
|
|
610
|
-
return val.toLowerCase() === 'true' || val === '1' || val.toLowerCase() === 'yes';
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
// ============================================
|
|
614
|
-
// Base64 Detection Helpers
|
|
615
|
-
// ============================================
|
|
616
|
-
|
|
617
|
-
const isBase64DataUrl = str => {
|
|
618
|
-
return /^data:([^;]+);base64,/.test(str);
|
|
619
|
-
};
|
|
620
|
-
const isValidUrl = str => {
|
|
621
|
-
try {
|
|
622
|
-
new URL(str);
|
|
623
|
-
return true;
|
|
624
|
-
} catch {
|
|
625
|
-
// Not an absolute URL, check if it's a relative URL or path
|
|
626
|
-
return str.startsWith('/') || str.startsWith('./') || str.startsWith('../');
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
const isRawBase64 = str => {
|
|
630
|
-
// Skip if it's a valid URL or path
|
|
631
|
-
if (isValidUrl(str)) {
|
|
632
|
-
return false;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// Check if it's a valid base64 string
|
|
636
|
-
// Base64 images are typically at least a few hundred chars, but we'll be conservative
|
|
637
|
-
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
638
|
-
};
|
|
639
|
-
function redactBase64DataUrl(str) {
|
|
640
|
-
if (isMultimodalEnabled()) return str;
|
|
641
|
-
if (!isString(str)) return str;
|
|
642
|
-
|
|
643
|
-
// Check for data URL format
|
|
644
|
-
if (isBase64DataUrl(str)) {
|
|
645
|
-
return REDACTED_IMAGE_PLACEHOLDER;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// Check for raw base64 (Vercel sends raw base64 for inline images)
|
|
649
|
-
if (isRawBase64(str)) {
|
|
650
|
-
return REDACTED_IMAGE_PLACEHOLDER;
|
|
651
|
-
}
|
|
652
|
-
return str;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// ============================================
|
|
656
|
-
// Common Message Processing
|
|
657
|
-
// ============================================
|
|
658
|
-
|
|
659
|
-
const processMessages = (messages, transformContent) => {
|
|
660
|
-
if (!messages) return messages;
|
|
661
|
-
const processContent = content => {
|
|
662
|
-
if (typeof content === 'string') return content;
|
|
663
|
-
if (!content) return content;
|
|
664
|
-
if (Array.isArray(content)) {
|
|
665
|
-
return content.map(transformContent);
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// Handle single object content
|
|
669
|
-
return transformContent(content);
|
|
670
|
-
};
|
|
671
|
-
const processMessage = msg => {
|
|
672
|
-
if (!isObject(msg) || !('content' in msg)) return msg;
|
|
673
|
-
return {
|
|
674
|
-
...msg,
|
|
675
|
-
content: processContent(msg.content)
|
|
676
|
-
};
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
// Handle both arrays and single messages
|
|
680
|
-
if (Array.isArray(messages)) {
|
|
681
|
-
return messages.map(processMessage);
|
|
682
|
-
}
|
|
683
|
-
return processMessage(messages);
|
|
684
|
-
};
|
|
685
|
-
const sanitizeLangChainImage = item => {
|
|
686
|
-
if (!isObject(item)) return item;
|
|
687
|
-
|
|
688
|
-
// OpenAI style
|
|
689
|
-
if (item.type === 'image_url' && 'image_url' in item && isObject(item.image_url) && 'url' in item.image_url) {
|
|
690
|
-
return {
|
|
691
|
-
...item,
|
|
692
|
-
image_url: {
|
|
693
|
-
...item.image_url,
|
|
694
|
-
url: redactBase64DataUrl(item.image_url.url)
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// Direct image with data field
|
|
700
|
-
if (item.type === 'image' && 'data' in item) {
|
|
701
|
-
return {
|
|
702
|
-
...item,
|
|
703
|
-
data: redactBase64DataUrl(item.data)
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
// Anthropic style
|
|
708
|
-
if (item.type === 'image' && 'source' in item && isObject(item.source) && 'data' in item.source) {
|
|
709
|
-
if (isMultimodalEnabled()) return item;
|
|
710
|
-
return {
|
|
711
|
-
...item,
|
|
712
|
-
source: {
|
|
713
|
-
...item.source,
|
|
714
|
-
data: redactBase64DataUrl(item.source.data)
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// Google style
|
|
720
|
-
if (item.type === 'media' && 'data' in item) {
|
|
721
|
-
return {
|
|
722
|
-
...item,
|
|
723
|
-
data: redactBase64DataUrl(item.data)
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
return item;
|
|
727
|
-
};
|
|
728
|
-
const sanitizeLangChain = data => {
|
|
729
|
-
return processMessages(data, sanitizeLangChainImage);
|
|
730
|
-
};
|
|
731
|
-
|
|
732
757
|
/** A run may either be a Span or a Generation */
|
|
733
758
|
|
|
734
759
|
/** Storage for run metadata */
|