@posthog/ai 8.14.0 → 8.14.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/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 +169 -13
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +169 -13
- 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 +5 -5
package/dist/anthropic/index.cjs
CHANGED
|
@@ -29,6 +29,11 @@ _anthropic_ai_sdk = __toESM(_anthropic_ai_sdk);
|
|
|
29
29
|
let uuid = require("uuid");
|
|
30
30
|
let _posthog_core = require("@posthog/core");
|
|
31
31
|
let _anthropic_ai_sdk_streaming = require("@anthropic-ai/sdk/streaming");
|
|
32
|
+
//#region src/typeGuards.ts
|
|
33
|
+
const isObject = (value) => {
|
|
34
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
32
37
|
//#region src/captureAiEvent.ts
|
|
33
38
|
/** @internal */
|
|
34
39
|
function isFullAiCaptureEnabled(client) {
|
|
@@ -194,17 +199,26 @@ var BinaryContentRedactor = class {
|
|
|
194
199
|
this.visited = /* @__PURE__ */ new WeakSet();
|
|
195
200
|
return this.walk(value, mediaType ? new MediaTypeContext(void 0, void 0, mediaType) : MediaTypeContext.EMPTY);
|
|
196
201
|
}
|
|
202
|
+
/** Redact one leaf while a caller owns bounded, type-preserving traversal. @internal */
|
|
203
|
+
redactLeaf(value, context) {
|
|
204
|
+
return typeof value === "string" ? this.redactString(value, context) : this.placeholderFor(context.inferMediaType());
|
|
205
|
+
}
|
|
197
206
|
walk(value, ctx) {
|
|
198
207
|
if (value === null || value === void 0) return value;
|
|
199
|
-
if (typeof value === "string") return this.
|
|
208
|
+
if (typeof value === "string") return this.redactLeaf(value, ctx);
|
|
200
209
|
if (typeof value !== "object") return value;
|
|
201
|
-
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.
|
|
210
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.redactLeaf(value, ctx);
|
|
202
211
|
if (this.visited.has(value)) return null;
|
|
203
212
|
this.visited.add(value);
|
|
204
213
|
if (Array.isArray(value)) return value.map((item) => this.walk(item, ctx));
|
|
205
214
|
const obj = value;
|
|
206
215
|
const out = {};
|
|
207
|
-
for (const k of Object.keys(obj))
|
|
216
|
+
for (const k of Object.keys(obj)) Object.defineProperty(out, k, {
|
|
217
|
+
value: this.walk(obj[k], new MediaTypeContext(obj, k)),
|
|
218
|
+
enumerable: true,
|
|
219
|
+
writable: true,
|
|
220
|
+
configurable: true
|
|
221
|
+
});
|
|
208
222
|
return out;
|
|
209
223
|
}
|
|
210
224
|
redactString(value, ctx) {
|
|
@@ -226,8 +240,8 @@ var BinaryContentRedactor = class {
|
|
|
226
240
|
};
|
|
227
241
|
//#endregion
|
|
228
242
|
//#region src/sanitization.ts
|
|
229
|
-
const redactor = new BinaryContentRedactor();
|
|
230
|
-
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
243
|
+
const redactor$1 = new BinaryContentRedactor();
|
|
244
|
+
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor$1.redact(data);
|
|
231
245
|
const sanitizeAnthropic = (data, client) => sanitize(data, client);
|
|
232
246
|
//#endregion
|
|
233
247
|
//#region src/utils.ts
|
|
@@ -249,9 +263,10 @@ function hasTokenOverrides(posthogProperties) {
|
|
|
249
263
|
function getTokensSource(posthogProperties) {
|
|
250
264
|
return hasTokenOverrides(posthogProperties) ? "passthrough" : "sdk";
|
|
251
265
|
}
|
|
266
|
+
const MAX_OUTPUT_SIZE = 2e5;
|
|
252
267
|
const STRING_FORMAT = "utf8";
|
|
253
|
-
new TextEncoder();
|
|
254
|
-
new TextDecoder(STRING_FORMAT, { fatal: false });
|
|
268
|
+
const sharedTextEncoder = new TextEncoder();
|
|
269
|
+
const sharedTextDecoder = new TextDecoder(STRING_FORMAT, { fatal: false });
|
|
255
270
|
const getModelParams = (params, responseServiceTier) => {
|
|
256
271
|
if (!params) return {};
|
|
257
272
|
const modelParams = {};
|
|
@@ -305,8 +320,27 @@ const mergeSystemPrompt = (params, provider) => {
|
|
|
305
320
|
}
|
|
306
321
|
return params.messages;
|
|
307
322
|
};
|
|
308
|
-
const
|
|
309
|
-
|
|
323
|
+
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
324
|
+
function toSafeString(input) {
|
|
325
|
+
if (input === void 0 || input === null) return "";
|
|
326
|
+
if (typeof input === "string") return input;
|
|
327
|
+
try {
|
|
328
|
+
return JSON.stringify(input);
|
|
329
|
+
} catch {
|
|
330
|
+
console.warn("Failed to stringify input", input);
|
|
331
|
+
return "";
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const truncate = (input, client, maxBytes = MAX_OUTPUT_SIZE) => {
|
|
335
|
+
const str = toSafeString(input);
|
|
336
|
+
if (str === "") return "";
|
|
337
|
+
if (isFullAiCaptureEnabled(client)) return str;
|
|
338
|
+
const buffer = sharedTextEncoder.encode(str);
|
|
339
|
+
if (buffer.length <= maxBytes) return sharedTextDecoder.decode(buffer);
|
|
340
|
+
const truncatedBuffer = buffer.slice(0, maxBytes);
|
|
341
|
+
let truncatedStr = sharedTextDecoder.decode(truncatedBuffer);
|
|
342
|
+
if (truncatedStr.endsWith("�")) truncatedStr = truncatedStr.slice(0, -1);
|
|
343
|
+
return `${truncatedStr}... [truncated]`;
|
|
310
344
|
};
|
|
311
345
|
/**
|
|
312
346
|
* Extract available tool calls from the request parameters.
|
|
@@ -367,7 +401,7 @@ function addDefaults(params) {
|
|
|
367
401
|
}
|
|
368
402
|
//#endregion
|
|
369
403
|
//#region package.json
|
|
370
|
-
var version = "8.14.
|
|
404
|
+
var version = "8.14.2";
|
|
371
405
|
//#endregion
|
|
372
406
|
//#region src/serializeError.ts
|
|
373
407
|
const DEFAULT_MAX_DEPTH = 3;
|
|
@@ -454,7 +488,7 @@ const captureAiGeneration = async (client, options) => {
|
|
|
454
488
|
const eventType = options.eventType ?? "$ai_generation";
|
|
455
489
|
const privacyMode = options.privacyMode ?? false;
|
|
456
490
|
const usage = options.usage ?? {};
|
|
457
|
-
const shouldRedact =
|
|
491
|
+
const shouldRedact = isPrivacyModeEnabled(client, privacyMode);
|
|
458
492
|
const safeInput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.input);
|
|
459
493
|
const safeOutput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.output);
|
|
460
494
|
let httpStatus = options.httpStatus;
|
|
@@ -772,6 +806,89 @@ function monitoredStreamTee(source, createStream) {
|
|
|
772
806
|
}), controller)];
|
|
773
807
|
}
|
|
774
808
|
//#endregion
|
|
809
|
+
//#region src/toolResult.ts
|
|
810
|
+
const MAX_DEPTH = 20;
|
|
811
|
+
const MAX_ITEMS = 1e3;
|
|
812
|
+
const MAX_NODES = 1e4;
|
|
813
|
+
const TRUNCATED = "[Truncated]";
|
|
814
|
+
const UNSERIALIZABLE = "[Unserializable]";
|
|
815
|
+
const redactor = new BinaryContentRedactor();
|
|
816
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
817
|
+
/** @internal Preserve tool-result structure while bounding each string value. */
|
|
818
|
+
function formatToolResult(content, client, maxBytes = 5e3) {
|
|
819
|
+
try {
|
|
820
|
+
if (isFullAiCaptureEnabled(client)) return (0, _posthog_core.toJsonSafeValue)(content);
|
|
821
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
822
|
+
let remainingNodes = MAX_NODES;
|
|
823
|
+
const convert = (value, depth, context) => {
|
|
824
|
+
if (remainingNodes <= 0) return TRUNCATED;
|
|
825
|
+
remainingNodes--;
|
|
826
|
+
try {
|
|
827
|
+
if (value === null || typeof value !== "object") {
|
|
828
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
829
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
830
|
+
}
|
|
831
|
+
if (depth >= MAX_DEPTH) return TRUNCATED;
|
|
832
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return redactor.redactLeaf(value, context);
|
|
833
|
+
if (ancestors.has(value)) return "[Circular]";
|
|
834
|
+
ancestors.add(value);
|
|
835
|
+
try {
|
|
836
|
+
if (value instanceof Date) {
|
|
837
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
838
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
839
|
+
}
|
|
840
|
+
let hasToJSONResult = false;
|
|
841
|
+
let toJSONResult;
|
|
842
|
+
try {
|
|
843
|
+
const toJSON = value.toJSON;
|
|
844
|
+
if (typeof toJSON === "function") {
|
|
845
|
+
toJSONResult = toJSON.call(value);
|
|
846
|
+
hasToJSONResult = true;
|
|
847
|
+
}
|
|
848
|
+
} catch {}
|
|
849
|
+
if (hasToJSONResult) return convert(toJSONResult, depth + 1, context);
|
|
850
|
+
if (Array.isArray(value)) {
|
|
851
|
+
const output = [];
|
|
852
|
+
const count = Math.min(value.length, MAX_ITEMS);
|
|
853
|
+
let index = 0;
|
|
854
|
+
for (; index < count && remainingNodes > 0; index++) output.push(convert(value[index], depth + 1, context));
|
|
855
|
+
if (value.length > index) output.push(TRUNCATED);
|
|
856
|
+
return output;
|
|
857
|
+
}
|
|
858
|
+
const input = value;
|
|
859
|
+
const output = {};
|
|
860
|
+
let count = 0;
|
|
861
|
+
let truncated = false;
|
|
862
|
+
for (const key in input) {
|
|
863
|
+
if (!propertyIsEnumerable.call(input, key)) break;
|
|
864
|
+
if (count >= MAX_ITEMS || remainingNodes <= 0) {
|
|
865
|
+
truncated = true;
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
const converted = convert(input[key], depth + 1, new MediaTypeContext(input, key));
|
|
869
|
+
Object.defineProperty(output, key, {
|
|
870
|
+
value: converted,
|
|
871
|
+
enumerable: true,
|
|
872
|
+
writable: true,
|
|
873
|
+
configurable: true
|
|
874
|
+
});
|
|
875
|
+
count++;
|
|
876
|
+
}
|
|
877
|
+
if (truncated) output[TRUNCATED] = "Additional properties omitted";
|
|
878
|
+
return output;
|
|
879
|
+
} finally {
|
|
880
|
+
ancestors.delete(value);
|
|
881
|
+
}
|
|
882
|
+
} catch {
|
|
883
|
+
return UNSERIALIZABLE;
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
return convert(content, 0, MediaTypeContext.EMPTY);
|
|
887
|
+
} catch {
|
|
888
|
+
return UNSERIALIZABLE;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
//#endregion
|
|
775
892
|
//#region src/anthropic/index.ts
|
|
776
893
|
var PostHogAnthropic = class extends _anthropic_ai_sdk.default {
|
|
777
894
|
constructor(config) {
|
|
@@ -787,6 +904,30 @@ var WrappedMessages = class extends _anthropic_ai_sdk.default.Messages {
|
|
|
787
904
|
this.phClient = phClient;
|
|
788
905
|
this.baseURL = parentClient.baseURL;
|
|
789
906
|
}
|
|
907
|
+
formatInputForPostHog(params, privacyMode) {
|
|
908
|
+
try {
|
|
909
|
+
if (isPrivacyModeEnabled(this.phClient, privacyMode)) return null;
|
|
910
|
+
const input = mergeSystemPrompt(params, "anthropic");
|
|
911
|
+
const messages = Array.isArray(input) ? input.map((message) => {
|
|
912
|
+
if (!isObject(message) || !Array.isArray(message.content)) return message;
|
|
913
|
+
const originalContent = message.content;
|
|
914
|
+
const content = originalContent.map((block) => {
|
|
915
|
+
if (isObject(block) && typeof block.type === "string" && (block.type === "tool_result" || block.type.endsWith("_tool_result")) && Object.hasOwn(block, "content")) return {
|
|
916
|
+
...block,
|
|
917
|
+
content: formatToolResult(block.content, this.phClient, Infinity)
|
|
918
|
+
};
|
|
919
|
+
return block;
|
|
920
|
+
});
|
|
921
|
+
return content.some((block, index) => block !== originalContent[index]) ? {
|
|
922
|
+
...message,
|
|
923
|
+
content
|
|
924
|
+
} : message;
|
|
925
|
+
}) : input;
|
|
926
|
+
return sanitizeAnthropic(messages, this.phClient);
|
|
927
|
+
} catch {
|
|
928
|
+
return "[Unserializable]";
|
|
929
|
+
}
|
|
930
|
+
}
|
|
790
931
|
create(body, options) {
|
|
791
932
|
const { providerParams: anthropicParams, posthogParams } = extractPosthogParams(body);
|
|
792
933
|
const startTime = Date.now();
|
|
@@ -893,7 +1034,7 @@ var WrappedMessages = class extends _anthropic_ai_sdk.default.Messages {
|
|
|
893
1034
|
...posthogParams,
|
|
894
1035
|
model: anthropicParams.model,
|
|
895
1036
|
provider: "anthropic",
|
|
896
|
-
input:
|
|
1037
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
897
1038
|
output: formattedOutput,
|
|
898
1039
|
latency,
|
|
899
1040
|
timeToFirstToken,
|
|
@@ -910,7 +1051,7 @@ var WrappedMessages = class extends _anthropic_ai_sdk.default.Messages {
|
|
|
910
1051
|
...posthogParams,
|
|
911
1052
|
model: anthropicParams.model,
|
|
912
1053
|
provider: "anthropic",
|
|
913
|
-
input:
|
|
1054
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
914
1055
|
output: [],
|
|
915
1056
|
latency: (Date.now() - startTime) / 1e3,
|
|
916
1057
|
baseURL: this.baseURL,
|
|
@@ -938,7 +1079,7 @@ var WrappedMessages = class extends _anthropic_ai_sdk.default.Messages {
|
|
|
938
1079
|
...posthogParams,
|
|
939
1080
|
model: anthropicParams.model,
|
|
940
1081
|
provider: "anthropic",
|
|
941
|
-
input:
|
|
1082
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
942
1083
|
output: formatResponseAnthropic(result),
|
|
943
1084
|
latency,
|
|
944
1085
|
baseURL: this.baseURL,
|
|
@@ -962,7 +1103,7 @@ var WrappedMessages = class extends _anthropic_ai_sdk.default.Messages {
|
|
|
962
1103
|
...posthogParams,
|
|
963
1104
|
model: anthropicParams.model,
|
|
964
1105
|
provider: "anthropic",
|
|
965
|
-
input:
|
|
1106
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
966
1107
|
output: [],
|
|
967
1108
|
latency: (Date.now() - startTime) / 1e3,
|
|
968
1109
|
baseURL: this.baseURL,
|