@posthog/ai 8.14.1 → 8.14.3
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 +35 -1
- package/dist/adk/index.cjs +16 -6
- package/dist/adk/index.cjs.map +1 -1
- package/dist/adk/index.mjs +16 -6
- package/dist/adk/index.mjs.map +1 -1
- package/dist/anthropic/index.cjs +156 -15
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.d.ts +1 -0
- package/dist/anthropic/index.mjs +156 -15
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/claude-agent-sdk/index.cjs +111 -37
- package/dist/claude-agent-sdk/index.cjs.map +1 -1
- package/dist/claude-agent-sdk/index.mjs +111 -37
- package/dist/claude-agent-sdk/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +175 -39
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.d.ts +1 -1
- package/dist/gemini/index.mjs +175 -39
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +15 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +15 -8
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +15 -5
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +15 -5
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/langchain/middleware/index.cjs +15 -5
- package/dist/langchain/middleware/index.cjs.map +1 -1
- package/dist/langchain/middleware/index.mjs +15 -5
- package/dist/langchain/middleware/index.mjs.map +1 -1
- package/dist/openai/index.cjs +181 -21
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +181 -21
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openai-agents/index.cjs +15 -5
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.mjs +15 -5
- package/dist/openai-agents/index.mjs.map +1 -1
- package/dist/otel/index.cjs +12 -3
- package/dist/otel/index.cjs.map +1 -1
- package/dist/otel/index.mjs +12 -3
- package/dist/otel/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +15 -8
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +15 -8
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/gemini/index.cjs
CHANGED
|
@@ -5,11 +5,6 @@ Object.defineProperties(exports, {
|
|
|
5
5
|
let _google_genai = require("@google/genai");
|
|
6
6
|
let uuid = require("uuid");
|
|
7
7
|
let _posthog_core = require("@posthog/core");
|
|
8
|
-
//#region src/typeGuards.ts
|
|
9
|
-
const isString = (value) => {
|
|
10
|
-
return typeof value === "string";
|
|
11
|
-
};
|
|
12
|
-
//#endregion
|
|
13
8
|
//#region src/captureAiEvent.ts
|
|
14
9
|
/** @internal */
|
|
15
10
|
function isFullAiCaptureEnabled(client) {
|
|
@@ -32,6 +27,14 @@ async function captureAiEventImmediate(client, event) {
|
|
|
32
27
|
await client.captureImmediate(event);
|
|
33
28
|
}
|
|
34
29
|
//#endregion
|
|
30
|
+
//#region src/typeGuards.ts
|
|
31
|
+
const isString = (value) => {
|
|
32
|
+
return typeof value === "string";
|
|
33
|
+
};
|
|
34
|
+
const isObject = (value) => {
|
|
35
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
35
38
|
//#region src/sanitization/base64_recognizer.ts
|
|
36
39
|
const DATA_URL_PREFIX_RE = /^data:([^;,\s]+)(?:;[^;,\s]+)*;base64,/i;
|
|
37
40
|
const BASE64_ALPHABET_RE = /^[A-Za-z0-9+/_=-]+$/;
|
|
@@ -175,17 +178,26 @@ var BinaryContentRedactor = class {
|
|
|
175
178
|
this.visited = /* @__PURE__ */ new WeakSet();
|
|
176
179
|
return this.walk(value, mediaType ? new MediaTypeContext(void 0, void 0, mediaType) : MediaTypeContext.EMPTY);
|
|
177
180
|
}
|
|
181
|
+
/** Redact one leaf while a caller owns bounded, type-preserving traversal. @internal */
|
|
182
|
+
redactLeaf(value, context) {
|
|
183
|
+
return typeof value === "string" ? this.redactString(value, context) : this.placeholderFor(context.inferMediaType());
|
|
184
|
+
}
|
|
178
185
|
walk(value, ctx) {
|
|
179
186
|
if (value === null || value === void 0) return value;
|
|
180
|
-
if (typeof value === "string") return this.
|
|
187
|
+
if (typeof value === "string") return this.redactLeaf(value, ctx);
|
|
181
188
|
if (typeof value !== "object") return value;
|
|
182
|
-
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.
|
|
189
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.redactLeaf(value, ctx);
|
|
183
190
|
if (this.visited.has(value)) return null;
|
|
184
191
|
this.visited.add(value);
|
|
185
192
|
if (Array.isArray(value)) return value.map((item) => this.walk(item, ctx));
|
|
186
193
|
const obj = value;
|
|
187
194
|
const out = {};
|
|
188
|
-
for (const k of Object.keys(obj))
|
|
195
|
+
for (const k of Object.keys(obj)) Object.defineProperty(out, k, {
|
|
196
|
+
value: this.walk(obj[k], new MediaTypeContext(obj, k)),
|
|
197
|
+
enumerable: true,
|
|
198
|
+
writable: true,
|
|
199
|
+
configurable: true
|
|
200
|
+
});
|
|
189
201
|
return out;
|
|
190
202
|
}
|
|
191
203
|
redactString(value, ctx) {
|
|
@@ -207,11 +219,11 @@ var BinaryContentRedactor = class {
|
|
|
207
219
|
};
|
|
208
220
|
//#endregion
|
|
209
221
|
//#region src/sanitization.ts
|
|
210
|
-
const redactor = new BinaryContentRedactor();
|
|
222
|
+
const redactor$1 = new BinaryContentRedactor();
|
|
211
223
|
function redactBase64DataUrl(str, mediaType) {
|
|
212
|
-
return redactor.redact(str, mediaType);
|
|
224
|
+
return redactor$1.redact(str, mediaType);
|
|
213
225
|
}
|
|
214
|
-
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
226
|
+
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor$1.redact(data);
|
|
215
227
|
const sanitizeGemini = (data, client) => sanitize(data, client);
|
|
216
228
|
//#endregion
|
|
217
229
|
//#region src/utils.ts
|
|
@@ -356,8 +368,9 @@ const formatResponseGemini = (response, client) => {
|
|
|
356
368
|
});
|
|
357
369
|
return output;
|
|
358
370
|
};
|
|
371
|
+
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
359
372
|
const withPrivacyMode = (client, privacyMode, input) => {
|
|
360
|
-
return client
|
|
373
|
+
return isPrivacyModeEnabled(client, privacyMode) ? null : input;
|
|
361
374
|
};
|
|
362
375
|
function toSafeString(input) {
|
|
363
376
|
if (input === void 0 || input === null) return "";
|
|
@@ -439,7 +452,7 @@ function addDefaults(params) {
|
|
|
439
452
|
}
|
|
440
453
|
//#endregion
|
|
441
454
|
//#region package.json
|
|
442
|
-
var version = "8.14.
|
|
455
|
+
var version = "8.14.3";
|
|
443
456
|
//#endregion
|
|
444
457
|
//#region src/serializeError.ts
|
|
445
458
|
const DEFAULT_MAX_DEPTH = 3;
|
|
@@ -526,7 +539,7 @@ const captureAiGeneration = async (client, options) => {
|
|
|
526
539
|
const eventType = options.eventType ?? "$ai_generation";
|
|
527
540
|
const privacyMode = options.privacyMode ?? false;
|
|
528
541
|
const usage = options.usage ?? {};
|
|
529
|
-
const shouldRedact =
|
|
542
|
+
const shouldRedact = isPrivacyModeEnabled(client, privacyMode);
|
|
530
543
|
const safeInput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.input);
|
|
531
544
|
const safeOutput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.output);
|
|
532
545
|
let httpStatus = options.httpStatus;
|
|
@@ -608,6 +621,89 @@ const captureAiGeneration = async (client, options) => {
|
|
|
608
621
|
}
|
|
609
622
|
};
|
|
610
623
|
//#endregion
|
|
624
|
+
//#region src/toolResult.ts
|
|
625
|
+
const MAX_DEPTH = 20;
|
|
626
|
+
const MAX_ITEMS = 1e3;
|
|
627
|
+
const MAX_NODES = 1e4;
|
|
628
|
+
const TRUNCATED = "[Truncated]";
|
|
629
|
+
const UNSERIALIZABLE = "[Unserializable]";
|
|
630
|
+
const redactor = new BinaryContentRedactor();
|
|
631
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
632
|
+
/** @internal Preserve tool-result structure while bounding each string value. */
|
|
633
|
+
function formatToolResult(content, client, maxBytes = 5e3) {
|
|
634
|
+
try {
|
|
635
|
+
if (isFullAiCaptureEnabled(client)) return (0, _posthog_core.toJsonSafeValue)(content);
|
|
636
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
637
|
+
let remainingNodes = MAX_NODES;
|
|
638
|
+
const convert = (value, depth, context) => {
|
|
639
|
+
if (remainingNodes <= 0) return TRUNCATED;
|
|
640
|
+
remainingNodes--;
|
|
641
|
+
try {
|
|
642
|
+
if (value === null || typeof value !== "object") {
|
|
643
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
644
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
645
|
+
}
|
|
646
|
+
if (depth >= MAX_DEPTH) return TRUNCATED;
|
|
647
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return redactor.redactLeaf(value, context);
|
|
648
|
+
if (ancestors.has(value)) return "[Circular]";
|
|
649
|
+
ancestors.add(value);
|
|
650
|
+
try {
|
|
651
|
+
if (value instanceof Date) {
|
|
652
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
653
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
654
|
+
}
|
|
655
|
+
let hasToJSONResult = false;
|
|
656
|
+
let toJSONResult;
|
|
657
|
+
try {
|
|
658
|
+
const toJSON = value.toJSON;
|
|
659
|
+
if (typeof toJSON === "function") {
|
|
660
|
+
toJSONResult = toJSON.call(value);
|
|
661
|
+
hasToJSONResult = true;
|
|
662
|
+
}
|
|
663
|
+
} catch {}
|
|
664
|
+
if (hasToJSONResult) return convert(toJSONResult, depth + 1, context);
|
|
665
|
+
if (Array.isArray(value)) {
|
|
666
|
+
const output = [];
|
|
667
|
+
const count = Math.min(value.length, MAX_ITEMS);
|
|
668
|
+
let index = 0;
|
|
669
|
+
for (; index < count && remainingNodes > 0; index++) output.push(convert(value[index], depth + 1, context));
|
|
670
|
+
if (value.length > index) output.push(TRUNCATED);
|
|
671
|
+
return output;
|
|
672
|
+
}
|
|
673
|
+
const input = value;
|
|
674
|
+
const output = {};
|
|
675
|
+
let count = 0;
|
|
676
|
+
let truncated = false;
|
|
677
|
+
for (const key in input) {
|
|
678
|
+
if (!propertyIsEnumerable.call(input, key)) break;
|
|
679
|
+
if (count >= MAX_ITEMS || remainingNodes <= 0) {
|
|
680
|
+
truncated = true;
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
const converted = convert(input[key], depth + 1, new MediaTypeContext(input, key));
|
|
684
|
+
Object.defineProperty(output, key, {
|
|
685
|
+
value: converted,
|
|
686
|
+
enumerable: true,
|
|
687
|
+
writable: true,
|
|
688
|
+
configurable: true
|
|
689
|
+
});
|
|
690
|
+
count++;
|
|
691
|
+
}
|
|
692
|
+
if (truncated) output[TRUNCATED] = "Additional properties omitted";
|
|
693
|
+
return output;
|
|
694
|
+
} finally {
|
|
695
|
+
ancestors.delete(value);
|
|
696
|
+
}
|
|
697
|
+
} catch {
|
|
698
|
+
return UNSERIALIZABLE;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
return convert(content, 0, MediaTypeContext.EMPTY);
|
|
702
|
+
} catch {
|
|
703
|
+
return UNSERIALIZABLE;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
//#endregion
|
|
611
707
|
//#region src/gemini/usage.ts
|
|
612
708
|
/** Map Gemini usage metadata to PostHog's provider-agnostic token fields. */
|
|
613
709
|
function mapGeminiUsage(metadata, additionalUsage = {}) {
|
|
@@ -624,6 +720,12 @@ function mapGeminiUsage(metadata, additionalUsage = {}) {
|
|
|
624
720
|
//#endregion
|
|
625
721
|
//#region src/gemini/index.ts
|
|
626
722
|
const TOOL_RESULT_MAX_BYTES = 5e3;
|
|
723
|
+
function geminiFunctionResponseContent(response) {
|
|
724
|
+
return response.parts !== void 0 ? {
|
|
725
|
+
...response.response !== void 0 && { response: response.response },
|
|
726
|
+
parts: response.parts
|
|
727
|
+
} : response.response ?? {};
|
|
728
|
+
}
|
|
627
729
|
var PostHogGoogleGenAI = class {
|
|
628
730
|
constructor(config) {
|
|
629
731
|
const { posthog, ...geminiConfig } = config;
|
|
@@ -650,7 +752,7 @@ var WrappedModels = class {
|
|
|
650
752
|
...posthogParams,
|
|
651
753
|
model: geminiParams.model,
|
|
652
754
|
provider: "gemini",
|
|
653
|
-
input: this.formatInputForPostHog(geminiParams),
|
|
755
|
+
input: this.formatInputForPostHog(geminiParams, posthogParams.privacyMode),
|
|
654
756
|
output: formatResponseGemini(response, this.phClient),
|
|
655
757
|
latency,
|
|
656
758
|
baseURL: "https://generativelanguage.googleapis.com",
|
|
@@ -667,7 +769,7 @@ var WrappedModels = class {
|
|
|
667
769
|
...posthogParams,
|
|
668
770
|
model: geminiParams.model,
|
|
669
771
|
provider: "gemini",
|
|
670
|
-
input: this.formatInputForPostHog(geminiParams),
|
|
772
|
+
input: this.formatInputForPostHog(geminiParams, posthogParams.privacyMode),
|
|
671
773
|
output: [],
|
|
672
774
|
latency,
|
|
673
775
|
baseURL: "https://generativelanguage.googleapis.com",
|
|
@@ -734,7 +836,7 @@ var WrappedModels = class {
|
|
|
734
836
|
...posthogParams,
|
|
735
837
|
model: geminiParams.model,
|
|
736
838
|
provider: "gemini",
|
|
737
|
-
input: this.formatInputForPostHog(geminiParams),
|
|
839
|
+
input: this.formatInputForPostHog(geminiParams, posthogParams.privacyMode),
|
|
738
840
|
output: [],
|
|
739
841
|
latency,
|
|
740
842
|
baseURL: "https://generativelanguage.googleapis.com",
|
|
@@ -756,7 +858,7 @@ var WrappedModels = class {
|
|
|
756
858
|
...posthogParams,
|
|
757
859
|
model: geminiParams.model,
|
|
758
860
|
provider: "gemini",
|
|
759
|
-
input: this.formatInputForPostHog(geminiParams),
|
|
861
|
+
input: this.formatInputForPostHog(geminiParams, posthogParams.privacyMode),
|
|
760
862
|
output,
|
|
761
863
|
latency,
|
|
762
864
|
timeToFirstToken,
|
|
@@ -840,28 +942,16 @@ var WrappedModels = class {
|
|
|
840
942
|
} else if (part && typeof part === "object" && "functionResponse" in part) {
|
|
841
943
|
const functionResponse = part.functionResponse;
|
|
842
944
|
if (functionResponse?.name) {
|
|
843
|
-
const content = functionResponse
|
|
844
|
-
...functionResponse.response !== void 0 && { response: functionResponse.response },
|
|
845
|
-
parts: functionResponse.parts
|
|
846
|
-
} : functionResponse.response ?? {};
|
|
945
|
+
const content = geminiFunctionResponseContent(functionResponse);
|
|
847
946
|
blocks.push({
|
|
848
947
|
type: "tool_result",
|
|
849
948
|
...functionResponse.id != null && { tool_use_id: functionResponse.id },
|
|
850
|
-
content
|
|
949
|
+
content
|
|
851
950
|
});
|
|
852
951
|
}
|
|
853
952
|
}
|
|
854
953
|
return blocks;
|
|
855
954
|
}
|
|
856
|
-
boundToolResult(content) {
|
|
857
|
-
if (isFullAiCaptureEnabled(this.phClient)) return content;
|
|
858
|
-
try {
|
|
859
|
-
const serialized = JSON.stringify(content);
|
|
860
|
-
return utf8ByteLength(serialized) > TOOL_RESULT_MAX_BYTES ? truncate(serialized, void 0, TOOL_RESULT_MAX_BYTES) : content;
|
|
861
|
-
} catch {
|
|
862
|
-
return "[Unserializable tool result]";
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
955
|
formatInput(contents) {
|
|
866
956
|
if (typeof contents === "string") return [{
|
|
867
957
|
role: "user",
|
|
@@ -936,17 +1026,63 @@ var WrappedModels = class {
|
|
|
936
1026
|
}
|
|
937
1027
|
return null;
|
|
938
1028
|
}
|
|
939
|
-
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
const
|
|
943
|
-
|
|
944
|
-
|
|
1029
|
+
boundToolResult(content) {
|
|
1030
|
+
const normalized = formatToolResult(content, this.phClient, Infinity);
|
|
1031
|
+
if (isFullAiCaptureEnabled(this.phClient)) return normalized;
|
|
1032
|
+
const serialized = JSON.stringify(normalized);
|
|
1033
|
+
return serialized !== void 0 && utf8ByteLength(serialized) > TOOL_RESULT_MAX_BYTES ? truncate(serialized, void 0, TOOL_RESULT_MAX_BYTES) : normalized;
|
|
1034
|
+
}
|
|
1035
|
+
formatInputForPostHog(params, privacyMode) {
|
|
1036
|
+
try {
|
|
1037
|
+
if (isPrivacyModeEnabled(this.phClient, privacyMode)) return null;
|
|
1038
|
+
const preparePart = (part) => {
|
|
1039
|
+
if (!isObject(part) || !Object.hasOwn(part, "functionResponse") || !isObject(part.functionResponse)) return part;
|
|
1040
|
+
const response = part.functionResponse;
|
|
1041
|
+
const hasParts = response.parts !== void 0;
|
|
1042
|
+
const hasResponse = Object.hasOwn(response, "response");
|
|
1043
|
+
if (!hasParts && !hasResponse) return part;
|
|
1044
|
+
const formatted = this.boundToolResult(geminiFunctionResponseContent(response));
|
|
1045
|
+
const prepared = { ...response };
|
|
1046
|
+
if (hasParts && isObject(formatted)) {
|
|
1047
|
+
if (hasResponse) prepared.response = formatted.response;
|
|
1048
|
+
prepared.parts = formatted.parts;
|
|
1049
|
+
} else {
|
|
1050
|
+
prepared.response = formatted;
|
|
1051
|
+
if (hasParts) delete prepared.parts;
|
|
1052
|
+
}
|
|
1053
|
+
return {
|
|
1054
|
+
...part,
|
|
1055
|
+
functionResponse: prepared
|
|
1056
|
+
};
|
|
1057
|
+
};
|
|
1058
|
+
const prepareContent = (content) => {
|
|
1059
|
+
const part = preparePart(content);
|
|
1060
|
+
if (!isObject(part)) return part;
|
|
1061
|
+
const originalParts = Object.hasOwn(part, "parts") ? part.parts : void 0;
|
|
1062
|
+
const originalContent = Object.hasOwn(part, "content") ? part.content : void 0;
|
|
1063
|
+
const parts = Array.isArray(originalParts) ? originalParts.map(preparePart) : void 0;
|
|
1064
|
+
const blocks = Array.isArray(originalContent) ? originalContent.map(preparePart) : void 0;
|
|
1065
|
+
const partsChanged = parts?.some((value, index) => value !== originalParts[index]);
|
|
1066
|
+
const contentChanged = blocks?.some((value, index) => value !== originalContent[index]);
|
|
1067
|
+
if (!partsChanged && !contentChanged) return part;
|
|
1068
|
+
return {
|
|
1069
|
+
...part,
|
|
1070
|
+
...partsChanged && { parts },
|
|
1071
|
+
...contentChanged && { content: blocks }
|
|
1072
|
+
};
|
|
1073
|
+
};
|
|
1074
|
+
const contents = Array.isArray(params.contents) ? params.contents.map(prepareContent) : prepareContent(params.contents);
|
|
1075
|
+
const sanitized = sanitizeGemini(contents, this.phClient);
|
|
1076
|
+
const messages = this.formatInput(sanitized);
|
|
1077
|
+
const systemInstruction = this.extractSystemInstruction(params);
|
|
1078
|
+
if (systemInstruction && !messages.some((message) => message.role === "system")) return [{
|
|
945
1079
|
role: "system",
|
|
946
1080
|
content: systemInstruction
|
|
947
1081
|
}, ...messages];
|
|
1082
|
+
return messages;
|
|
1083
|
+
} catch {
|
|
1084
|
+
return "[Unserializable]";
|
|
948
1085
|
}
|
|
949
|
-
return messages;
|
|
950
1086
|
}
|
|
951
1087
|
};
|
|
952
1088
|
/**
|