@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/anthropic/index.mjs
CHANGED
|
@@ -2,6 +2,11 @@ import AnthropicOriginal from "@anthropic-ai/sdk";
|
|
|
2
2
|
import { v4 } from "uuid";
|
|
3
3
|
import { toJsonSafeValue, uuidv7 } from "@posthog/core";
|
|
4
4
|
import { Stream } from "@anthropic-ai/sdk/streaming";
|
|
5
|
+
//#region src/typeGuards.ts
|
|
6
|
+
const isObject = (value) => {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
5
10
|
//#region src/captureAiEvent.ts
|
|
6
11
|
/** @internal */
|
|
7
12
|
function isFullAiCaptureEnabled(client) {
|
|
@@ -167,17 +172,26 @@ var BinaryContentRedactor = class {
|
|
|
167
172
|
this.visited = /* @__PURE__ */ new WeakSet();
|
|
168
173
|
return this.walk(value, mediaType ? new MediaTypeContext(void 0, void 0, mediaType) : MediaTypeContext.EMPTY);
|
|
169
174
|
}
|
|
175
|
+
/** Redact one leaf while a caller owns bounded, type-preserving traversal. @internal */
|
|
176
|
+
redactLeaf(value, context) {
|
|
177
|
+
return typeof value === "string" ? this.redactString(value, context) : this.placeholderFor(context.inferMediaType());
|
|
178
|
+
}
|
|
170
179
|
walk(value, ctx) {
|
|
171
180
|
if (value === null || value === void 0) return value;
|
|
172
|
-
if (typeof value === "string") return this.
|
|
181
|
+
if (typeof value === "string") return this.redactLeaf(value, ctx);
|
|
173
182
|
if (typeof value !== "object") return value;
|
|
174
|
-
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.
|
|
183
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.redactLeaf(value, ctx);
|
|
175
184
|
if (this.visited.has(value)) return null;
|
|
176
185
|
this.visited.add(value);
|
|
177
186
|
if (Array.isArray(value)) return value.map((item) => this.walk(item, ctx));
|
|
178
187
|
const obj = value;
|
|
179
188
|
const out = {};
|
|
180
|
-
for (const k of Object.keys(obj))
|
|
189
|
+
for (const k of Object.keys(obj)) Object.defineProperty(out, k, {
|
|
190
|
+
value: this.walk(obj[k], new MediaTypeContext(obj, k)),
|
|
191
|
+
enumerable: true,
|
|
192
|
+
writable: true,
|
|
193
|
+
configurable: true
|
|
194
|
+
});
|
|
181
195
|
return out;
|
|
182
196
|
}
|
|
183
197
|
redactString(value, ctx) {
|
|
@@ -199,8 +213,8 @@ var BinaryContentRedactor = class {
|
|
|
199
213
|
};
|
|
200
214
|
//#endregion
|
|
201
215
|
//#region src/sanitization.ts
|
|
202
|
-
const redactor = new BinaryContentRedactor();
|
|
203
|
-
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
216
|
+
const redactor$1 = new BinaryContentRedactor();
|
|
217
|
+
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor$1.redact(data);
|
|
204
218
|
const sanitizeAnthropic = (data, client) => sanitize(data, client);
|
|
205
219
|
//#endregion
|
|
206
220
|
//#region src/utils.ts
|
|
@@ -222,9 +236,10 @@ function hasTokenOverrides(posthogProperties) {
|
|
|
222
236
|
function getTokensSource(posthogProperties) {
|
|
223
237
|
return hasTokenOverrides(posthogProperties) ? "passthrough" : "sdk";
|
|
224
238
|
}
|
|
239
|
+
const MAX_OUTPUT_SIZE = 2e5;
|
|
225
240
|
const STRING_FORMAT = "utf8";
|
|
226
|
-
new TextEncoder();
|
|
227
|
-
new TextDecoder(STRING_FORMAT, { fatal: false });
|
|
241
|
+
const sharedTextEncoder = new TextEncoder();
|
|
242
|
+
const sharedTextDecoder = new TextDecoder(STRING_FORMAT, { fatal: false });
|
|
228
243
|
const getModelParams = (params, responseServiceTier) => {
|
|
229
244
|
if (!params) return {};
|
|
230
245
|
const modelParams = {};
|
|
@@ -278,8 +293,27 @@ const mergeSystemPrompt = (params, provider) => {
|
|
|
278
293
|
}
|
|
279
294
|
return params.messages;
|
|
280
295
|
};
|
|
281
|
-
const
|
|
282
|
-
|
|
296
|
+
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
297
|
+
function toSafeString(input) {
|
|
298
|
+
if (input === void 0 || input === null) return "";
|
|
299
|
+
if (typeof input === "string") return input;
|
|
300
|
+
try {
|
|
301
|
+
return JSON.stringify(input);
|
|
302
|
+
} catch {
|
|
303
|
+
console.warn("Failed to stringify input", input);
|
|
304
|
+
return "";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const truncate = (input, client, maxBytes = MAX_OUTPUT_SIZE) => {
|
|
308
|
+
const str = toSafeString(input);
|
|
309
|
+
if (str === "") return "";
|
|
310
|
+
if (isFullAiCaptureEnabled(client)) return str;
|
|
311
|
+
const buffer = sharedTextEncoder.encode(str);
|
|
312
|
+
if (buffer.length <= maxBytes) return sharedTextDecoder.decode(buffer);
|
|
313
|
+
const truncatedBuffer = buffer.slice(0, maxBytes);
|
|
314
|
+
let truncatedStr = sharedTextDecoder.decode(truncatedBuffer);
|
|
315
|
+
if (truncatedStr.endsWith("�")) truncatedStr = truncatedStr.slice(0, -1);
|
|
316
|
+
return `${truncatedStr}... [truncated]`;
|
|
283
317
|
};
|
|
284
318
|
/**
|
|
285
319
|
* Extract available tool calls from the request parameters.
|
|
@@ -340,7 +374,7 @@ function addDefaults(params) {
|
|
|
340
374
|
}
|
|
341
375
|
//#endregion
|
|
342
376
|
//#region package.json
|
|
343
|
-
var version = "8.14.
|
|
377
|
+
var version = "8.14.3";
|
|
344
378
|
//#endregion
|
|
345
379
|
//#region src/serializeError.ts
|
|
346
380
|
const DEFAULT_MAX_DEPTH = 3;
|
|
@@ -427,7 +461,7 @@ const captureAiGeneration = async (client, options) => {
|
|
|
427
461
|
const eventType = options.eventType ?? "$ai_generation";
|
|
428
462
|
const privacyMode = options.privacyMode ?? false;
|
|
429
463
|
const usage = options.usage ?? {};
|
|
430
|
-
const shouldRedact =
|
|
464
|
+
const shouldRedact = isPrivacyModeEnabled(client, privacyMode);
|
|
431
465
|
const safeInput = shouldRedact ? null : toJsonSafeValue(options.input);
|
|
432
466
|
const safeOutput = shouldRedact ? null : toJsonSafeValue(options.output);
|
|
433
467
|
let httpStatus = options.httpStatus;
|
|
@@ -745,6 +779,89 @@ function monitoredStreamTee(source, createStream) {
|
|
|
745
779
|
}), controller)];
|
|
746
780
|
}
|
|
747
781
|
//#endregion
|
|
782
|
+
//#region src/toolResult.ts
|
|
783
|
+
const MAX_DEPTH = 20;
|
|
784
|
+
const MAX_ITEMS = 1e3;
|
|
785
|
+
const MAX_NODES = 1e4;
|
|
786
|
+
const TRUNCATED = "[Truncated]";
|
|
787
|
+
const UNSERIALIZABLE = "[Unserializable]";
|
|
788
|
+
const redactor = new BinaryContentRedactor();
|
|
789
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
790
|
+
/** @internal Preserve tool-result structure while bounding each string value. */
|
|
791
|
+
function formatToolResult(content, client, maxBytes = 5e3) {
|
|
792
|
+
try {
|
|
793
|
+
if (isFullAiCaptureEnabled(client)) return toJsonSafeValue(content);
|
|
794
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
795
|
+
let remainingNodes = MAX_NODES;
|
|
796
|
+
const convert = (value, depth, context) => {
|
|
797
|
+
if (remainingNodes <= 0) return TRUNCATED;
|
|
798
|
+
remainingNodes--;
|
|
799
|
+
try {
|
|
800
|
+
if (value === null || typeof value !== "object") {
|
|
801
|
+
const safe = toJsonSafeValue(value);
|
|
802
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
803
|
+
}
|
|
804
|
+
if (depth >= MAX_DEPTH) return TRUNCATED;
|
|
805
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return redactor.redactLeaf(value, context);
|
|
806
|
+
if (ancestors.has(value)) return "[Circular]";
|
|
807
|
+
ancestors.add(value);
|
|
808
|
+
try {
|
|
809
|
+
if (value instanceof Date) {
|
|
810
|
+
const safe = toJsonSafeValue(value);
|
|
811
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
812
|
+
}
|
|
813
|
+
let hasToJSONResult = false;
|
|
814
|
+
let toJSONResult;
|
|
815
|
+
try {
|
|
816
|
+
const toJSON = value.toJSON;
|
|
817
|
+
if (typeof toJSON === "function") {
|
|
818
|
+
toJSONResult = toJSON.call(value);
|
|
819
|
+
hasToJSONResult = true;
|
|
820
|
+
}
|
|
821
|
+
} catch {}
|
|
822
|
+
if (hasToJSONResult) return convert(toJSONResult, depth + 1, context);
|
|
823
|
+
if (Array.isArray(value)) {
|
|
824
|
+
const output = [];
|
|
825
|
+
const count = Math.min(value.length, MAX_ITEMS);
|
|
826
|
+
let index = 0;
|
|
827
|
+
for (; index < count && remainingNodes > 0; index++) output.push(convert(value[index], depth + 1, context));
|
|
828
|
+
if (value.length > index) output.push(TRUNCATED);
|
|
829
|
+
return output;
|
|
830
|
+
}
|
|
831
|
+
const input = value;
|
|
832
|
+
const output = {};
|
|
833
|
+
let count = 0;
|
|
834
|
+
let truncated = false;
|
|
835
|
+
for (const key in input) {
|
|
836
|
+
if (!propertyIsEnumerable.call(input, key)) break;
|
|
837
|
+
if (count >= MAX_ITEMS || remainingNodes <= 0) {
|
|
838
|
+
truncated = true;
|
|
839
|
+
break;
|
|
840
|
+
}
|
|
841
|
+
const converted = convert(input[key], depth + 1, new MediaTypeContext(input, key));
|
|
842
|
+
Object.defineProperty(output, key, {
|
|
843
|
+
value: converted,
|
|
844
|
+
enumerable: true,
|
|
845
|
+
writable: true,
|
|
846
|
+
configurable: true
|
|
847
|
+
});
|
|
848
|
+
count++;
|
|
849
|
+
}
|
|
850
|
+
if (truncated) output[TRUNCATED] = "Additional properties omitted";
|
|
851
|
+
return output;
|
|
852
|
+
} finally {
|
|
853
|
+
ancestors.delete(value);
|
|
854
|
+
}
|
|
855
|
+
} catch {
|
|
856
|
+
return UNSERIALIZABLE;
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
return convert(content, 0, MediaTypeContext.EMPTY);
|
|
860
|
+
} catch {
|
|
861
|
+
return UNSERIALIZABLE;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
748
865
|
//#region src/anthropic/index.ts
|
|
749
866
|
var PostHogAnthropic = class extends AnthropicOriginal {
|
|
750
867
|
constructor(config) {
|
|
@@ -760,6 +877,30 @@ var WrappedMessages = class extends AnthropicOriginal.Messages {
|
|
|
760
877
|
this.phClient = phClient;
|
|
761
878
|
this.baseURL = parentClient.baseURL;
|
|
762
879
|
}
|
|
880
|
+
formatInputForPostHog(params, privacyMode) {
|
|
881
|
+
try {
|
|
882
|
+
if (isPrivacyModeEnabled(this.phClient, privacyMode)) return null;
|
|
883
|
+
const input = mergeSystemPrompt(params, "anthropic");
|
|
884
|
+
const messages = Array.isArray(input) ? input.map((message) => {
|
|
885
|
+
if (!isObject(message) || !Array.isArray(message.content)) return message;
|
|
886
|
+
const originalContent = message.content;
|
|
887
|
+
const content = originalContent.map((block) => {
|
|
888
|
+
if (isObject(block) && typeof block.type === "string" && (block.type === "tool_result" || block.type.endsWith("_tool_result")) && Object.hasOwn(block, "content")) return {
|
|
889
|
+
...block,
|
|
890
|
+
content: formatToolResult(block.content, this.phClient, Infinity)
|
|
891
|
+
};
|
|
892
|
+
return block;
|
|
893
|
+
});
|
|
894
|
+
return content.some((block, index) => block !== originalContent[index]) ? {
|
|
895
|
+
...message,
|
|
896
|
+
content
|
|
897
|
+
} : message;
|
|
898
|
+
}) : input;
|
|
899
|
+
return sanitizeAnthropic(messages, this.phClient);
|
|
900
|
+
} catch {
|
|
901
|
+
return "[Unserializable]";
|
|
902
|
+
}
|
|
903
|
+
}
|
|
763
904
|
create(body, options) {
|
|
764
905
|
const { providerParams: anthropicParams, posthogParams } = extractPosthogParams(body);
|
|
765
906
|
const startTime = Date.now();
|
|
@@ -866,7 +1007,7 @@ var WrappedMessages = class extends AnthropicOriginal.Messages {
|
|
|
866
1007
|
...posthogParams,
|
|
867
1008
|
model: anthropicParams.model,
|
|
868
1009
|
provider: "anthropic",
|
|
869
|
-
input:
|
|
1010
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
870
1011
|
output: formattedOutput,
|
|
871
1012
|
latency,
|
|
872
1013
|
timeToFirstToken,
|
|
@@ -883,7 +1024,7 @@ var WrappedMessages = class extends AnthropicOriginal.Messages {
|
|
|
883
1024
|
...posthogParams,
|
|
884
1025
|
model: anthropicParams.model,
|
|
885
1026
|
provider: "anthropic",
|
|
886
|
-
input:
|
|
1027
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
887
1028
|
output: [],
|
|
888
1029
|
latency: (Date.now() - startTime) / 1e3,
|
|
889
1030
|
baseURL: this.baseURL,
|
|
@@ -911,7 +1052,7 @@ var WrappedMessages = class extends AnthropicOriginal.Messages {
|
|
|
911
1052
|
...posthogParams,
|
|
912
1053
|
model: anthropicParams.model,
|
|
913
1054
|
provider: "anthropic",
|
|
914
|
-
input:
|
|
1055
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
915
1056
|
output: formatResponseAnthropic(result),
|
|
916
1057
|
latency,
|
|
917
1058
|
baseURL: this.baseURL,
|
|
@@ -935,7 +1076,7 @@ var WrappedMessages = class extends AnthropicOriginal.Messages {
|
|
|
935
1076
|
...posthogParams,
|
|
936
1077
|
model: anthropicParams.model,
|
|
937
1078
|
provider: "anthropic",
|
|
938
|
-
input:
|
|
1079
|
+
input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
|
|
939
1080
|
output: [],
|
|
940
1081
|
latency: (Date.now() - startTime) / 1e3,
|
|
941
1082
|
baseURL: this.baseURL,
|