@posthog/ai 6.1.0 → 6.1.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 +61 -4
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +61 -4
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +59 -4
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +1 -0
- package/dist/gemini/index.mjs +59 -4
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +244 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +244 -25
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +132 -2
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +132 -2
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +133 -10
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +133 -10
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +65 -5
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +65 -5
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/langchain/index.mjs
CHANGED
|
@@ -535,6 +535,134 @@ class BaseCallbackHandler extends BaseCallbackHandlerMethodsClass {
|
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
+
// Type guards for safer type checking
|
|
539
|
+
|
|
540
|
+
const isString = value => {
|
|
541
|
+
return typeof value === 'string';
|
|
542
|
+
};
|
|
543
|
+
const isObject = value => {
|
|
544
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
548
|
+
|
|
549
|
+
// ============================================
|
|
550
|
+
// Base64 Detection Helpers
|
|
551
|
+
// ============================================
|
|
552
|
+
|
|
553
|
+
const isBase64DataUrl = str => {
|
|
554
|
+
return /^data:([^;]+);base64,/.test(str);
|
|
555
|
+
};
|
|
556
|
+
const isValidUrl = str => {
|
|
557
|
+
try {
|
|
558
|
+
new URL(str);
|
|
559
|
+
return true;
|
|
560
|
+
} catch {
|
|
561
|
+
// Not an absolute URL, check if it's a relative URL or path
|
|
562
|
+
return str.startsWith('/') || str.startsWith('./') || str.startsWith('../');
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
const isRawBase64 = str => {
|
|
566
|
+
// Skip if it's a valid URL or path
|
|
567
|
+
if (isValidUrl(str)) {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Check if it's a valid base64 string
|
|
572
|
+
// Base64 images are typically at least a few hundred chars, but we'll be conservative
|
|
573
|
+
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
574
|
+
};
|
|
575
|
+
function redactBase64DataUrl(str) {
|
|
576
|
+
if (!isString(str)) return str;
|
|
577
|
+
|
|
578
|
+
// Check for data URL format
|
|
579
|
+
if (isBase64DataUrl(str)) {
|
|
580
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Check for raw base64 (Vercel sends raw base64 for inline images)
|
|
584
|
+
if (isRawBase64(str)) {
|
|
585
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
586
|
+
}
|
|
587
|
+
return str;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// ============================================
|
|
591
|
+
// Common Message Processing
|
|
592
|
+
// ============================================
|
|
593
|
+
|
|
594
|
+
const processMessages = (messages, transformContent) => {
|
|
595
|
+
if (!messages) return messages;
|
|
596
|
+
const processContent = content => {
|
|
597
|
+
if (typeof content === 'string') return content;
|
|
598
|
+
if (!content) return content;
|
|
599
|
+
if (Array.isArray(content)) {
|
|
600
|
+
return content.map(transformContent);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Handle single object content
|
|
604
|
+
return transformContent(content);
|
|
605
|
+
};
|
|
606
|
+
const processMessage = msg => {
|
|
607
|
+
if (!isObject(msg) || !('content' in msg)) return msg;
|
|
608
|
+
return {
|
|
609
|
+
...msg,
|
|
610
|
+
content: processContent(msg.content)
|
|
611
|
+
};
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
// Handle both arrays and single messages
|
|
615
|
+
if (Array.isArray(messages)) {
|
|
616
|
+
return messages.map(processMessage);
|
|
617
|
+
}
|
|
618
|
+
return processMessage(messages);
|
|
619
|
+
};
|
|
620
|
+
const sanitizeLangChainImage = item => {
|
|
621
|
+
if (!isObject(item)) return item;
|
|
622
|
+
|
|
623
|
+
// OpenAI style
|
|
624
|
+
if (item.type === 'image_url' && 'image_url' in item && isObject(item.image_url) && 'url' in item.image_url) {
|
|
625
|
+
return {
|
|
626
|
+
...item,
|
|
627
|
+
image_url: {
|
|
628
|
+
...item.image_url,
|
|
629
|
+
url: redactBase64DataUrl(item.image_url.url)
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Direct image with data field
|
|
635
|
+
if (item.type === 'image' && 'data' in item) {
|
|
636
|
+
return {
|
|
637
|
+
...item,
|
|
638
|
+
data: redactBase64DataUrl(item.data)
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Anthropic style
|
|
643
|
+
if (item.type === 'image' && 'source' in item && isObject(item.source) && 'data' in item.source) {
|
|
644
|
+
return {
|
|
645
|
+
...item,
|
|
646
|
+
source: {
|
|
647
|
+
...item.source,
|
|
648
|
+
data: redactBase64DataUrl(item.source.data)
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Google style
|
|
654
|
+
if (item.type === 'media' && 'data' in item) {
|
|
655
|
+
return {
|
|
656
|
+
...item,
|
|
657
|
+
data: redactBase64DataUrl(item.data)
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
return item;
|
|
661
|
+
};
|
|
662
|
+
const sanitizeLangChain = data => {
|
|
663
|
+
return processMessages(data, sanitizeLangChainImage);
|
|
664
|
+
};
|
|
665
|
+
|
|
538
666
|
/** A run may either be a Span or a Generation */
|
|
539
667
|
|
|
540
668
|
/** Storage for run metadata */
|
|
@@ -715,7 +843,7 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
715
843
|
}) || 'generation';
|
|
716
844
|
const generation = {
|
|
717
845
|
name: runNameFound,
|
|
718
|
-
input: messages,
|
|
846
|
+
input: sanitizeLangChain(messages),
|
|
719
847
|
startTime: Date.now()
|
|
720
848
|
};
|
|
721
849
|
if (extraParams) {
|
|
@@ -980,7 +1108,9 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
980
1108
|
...message.additional_kwargs
|
|
981
1109
|
};
|
|
982
1110
|
}
|
|
983
|
-
|
|
1111
|
+
|
|
1112
|
+
// Sanitize the message content to redact base64 images
|
|
1113
|
+
return sanitizeLangChain(messageDict);
|
|
984
1114
|
}
|
|
985
1115
|
_parseUsageModel(usage) {
|
|
986
1116
|
const conversionList = [['promptTokens', 'input'], ['completionTokens', 'output'], ['input_tokens', 'input'], ['output_tokens', 'output'], ['prompt_token_count', 'input'], ['candidates_token_count', 'output'], ['inputTokenCount', 'input'], ['outputTokenCount', 'output'], ['input_token_count', 'input'], ['generated_token_count', 'output']];
|