@posthog/ai 6.1.0 → 6.1.2
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 +141 -8
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +141 -8
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +135 -29
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +4 -21
- package/dist/gemini/index.mjs +135 -29
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +600 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -21
- package/dist/index.mjs +600 -77
- 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 +222 -21
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +222 -21
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +114 -8
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +114 -8
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/langchain/index.cjs
CHANGED
|
@@ -556,6 +556,134 @@ class BaseCallbackHandler extends BaseCallbackHandlerMethodsClass {
|
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
558
|
|
|
559
|
+
// Type guards for safer type checking
|
|
560
|
+
|
|
561
|
+
const isString = value => {
|
|
562
|
+
return typeof value === 'string';
|
|
563
|
+
};
|
|
564
|
+
const isObject = value => {
|
|
565
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
|
|
569
|
+
|
|
570
|
+
// ============================================
|
|
571
|
+
// Base64 Detection Helpers
|
|
572
|
+
// ============================================
|
|
573
|
+
|
|
574
|
+
const isBase64DataUrl = str => {
|
|
575
|
+
return /^data:([^;]+);base64,/.test(str);
|
|
576
|
+
};
|
|
577
|
+
const isValidUrl = str => {
|
|
578
|
+
try {
|
|
579
|
+
new URL(str);
|
|
580
|
+
return true;
|
|
581
|
+
} catch {
|
|
582
|
+
// Not an absolute URL, check if it's a relative URL or path
|
|
583
|
+
return str.startsWith('/') || str.startsWith('./') || str.startsWith('../');
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const isRawBase64 = str => {
|
|
587
|
+
// Skip if it's a valid URL or path
|
|
588
|
+
if (isValidUrl(str)) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Check if it's a valid base64 string
|
|
593
|
+
// Base64 images are typically at least a few hundred chars, but we'll be conservative
|
|
594
|
+
return str.length > 20 && /^[A-Za-z0-9+/]+=*$/.test(str);
|
|
595
|
+
};
|
|
596
|
+
function redactBase64DataUrl(str) {
|
|
597
|
+
if (!isString(str)) return str;
|
|
598
|
+
|
|
599
|
+
// Check for data URL format
|
|
600
|
+
if (isBase64DataUrl(str)) {
|
|
601
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Check for raw base64 (Vercel sends raw base64 for inline images)
|
|
605
|
+
if (isRawBase64(str)) {
|
|
606
|
+
return REDACTED_IMAGE_PLACEHOLDER;
|
|
607
|
+
}
|
|
608
|
+
return str;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// ============================================
|
|
612
|
+
// Common Message Processing
|
|
613
|
+
// ============================================
|
|
614
|
+
|
|
615
|
+
const processMessages = (messages, transformContent) => {
|
|
616
|
+
if (!messages) return messages;
|
|
617
|
+
const processContent = content => {
|
|
618
|
+
if (typeof content === 'string') return content;
|
|
619
|
+
if (!content) return content;
|
|
620
|
+
if (Array.isArray(content)) {
|
|
621
|
+
return content.map(transformContent);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Handle single object content
|
|
625
|
+
return transformContent(content);
|
|
626
|
+
};
|
|
627
|
+
const processMessage = msg => {
|
|
628
|
+
if (!isObject(msg) || !('content' in msg)) return msg;
|
|
629
|
+
return {
|
|
630
|
+
...msg,
|
|
631
|
+
content: processContent(msg.content)
|
|
632
|
+
};
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
// Handle both arrays and single messages
|
|
636
|
+
if (Array.isArray(messages)) {
|
|
637
|
+
return messages.map(processMessage);
|
|
638
|
+
}
|
|
639
|
+
return processMessage(messages);
|
|
640
|
+
};
|
|
641
|
+
const sanitizeLangChainImage = item => {
|
|
642
|
+
if (!isObject(item)) return item;
|
|
643
|
+
|
|
644
|
+
// OpenAI style
|
|
645
|
+
if (item.type === 'image_url' && 'image_url' in item && isObject(item.image_url) && 'url' in item.image_url) {
|
|
646
|
+
return {
|
|
647
|
+
...item,
|
|
648
|
+
image_url: {
|
|
649
|
+
...item.image_url,
|
|
650
|
+
url: redactBase64DataUrl(item.image_url.url)
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Direct image with data field
|
|
656
|
+
if (item.type === 'image' && 'data' in item) {
|
|
657
|
+
return {
|
|
658
|
+
...item,
|
|
659
|
+
data: redactBase64DataUrl(item.data)
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Anthropic style
|
|
664
|
+
if (item.type === 'image' && 'source' in item && isObject(item.source) && 'data' in item.source) {
|
|
665
|
+
return {
|
|
666
|
+
...item,
|
|
667
|
+
source: {
|
|
668
|
+
...item.source,
|
|
669
|
+
data: redactBase64DataUrl(item.source.data)
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Google style
|
|
675
|
+
if (item.type === 'media' && 'data' in item) {
|
|
676
|
+
return {
|
|
677
|
+
...item,
|
|
678
|
+
data: redactBase64DataUrl(item.data)
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
return item;
|
|
682
|
+
};
|
|
683
|
+
const sanitizeLangChain = data => {
|
|
684
|
+
return processMessages(data, sanitizeLangChainImage);
|
|
685
|
+
};
|
|
686
|
+
|
|
559
687
|
/** A run may either be a Span or a Generation */
|
|
560
688
|
|
|
561
689
|
/** Storage for run metadata */
|
|
@@ -736,7 +864,7 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
736
864
|
}) || 'generation';
|
|
737
865
|
const generation = {
|
|
738
866
|
name: runNameFound,
|
|
739
|
-
input: messages,
|
|
867
|
+
input: sanitizeLangChain(messages),
|
|
740
868
|
startTime: Date.now()
|
|
741
869
|
};
|
|
742
870
|
if (extraParams) {
|
|
@@ -1001,7 +1129,9 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
1001
1129
|
...message.additional_kwargs
|
|
1002
1130
|
};
|
|
1003
1131
|
}
|
|
1004
|
-
|
|
1132
|
+
|
|
1133
|
+
// Sanitize the message content to redact base64 images
|
|
1134
|
+
return sanitizeLangChain(messageDict);
|
|
1005
1135
|
}
|
|
1006
1136
|
_parseUsageModel(usage) {
|
|
1007
1137
|
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']];
|