@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.
Files changed (48) hide show
  1. package/README.md +35 -1
  2. package/dist/adk/index.cjs +16 -6
  3. package/dist/adk/index.cjs.map +1 -1
  4. package/dist/adk/index.mjs +16 -6
  5. package/dist/adk/index.mjs.map +1 -1
  6. package/dist/anthropic/index.cjs +156 -15
  7. package/dist/anthropic/index.cjs.map +1 -1
  8. package/dist/anthropic/index.d.ts +1 -0
  9. package/dist/anthropic/index.mjs +156 -15
  10. package/dist/anthropic/index.mjs.map +1 -1
  11. package/dist/claude-agent-sdk/index.cjs +111 -37
  12. package/dist/claude-agent-sdk/index.cjs.map +1 -1
  13. package/dist/claude-agent-sdk/index.mjs +111 -37
  14. package/dist/claude-agent-sdk/index.mjs.map +1 -1
  15. package/dist/gemini/index.cjs +175 -39
  16. package/dist/gemini/index.cjs.map +1 -1
  17. package/dist/gemini/index.d.ts +1 -1
  18. package/dist/gemini/index.mjs +175 -39
  19. package/dist/gemini/index.mjs.map +1 -1
  20. package/dist/index.cjs +15 -8
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.mjs +15 -8
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/langchain/index.cjs +15 -5
  25. package/dist/langchain/index.cjs.map +1 -1
  26. package/dist/langchain/index.mjs +15 -5
  27. package/dist/langchain/index.mjs.map +1 -1
  28. package/dist/langchain/middleware/index.cjs +15 -5
  29. package/dist/langchain/middleware/index.cjs.map +1 -1
  30. package/dist/langchain/middleware/index.mjs +15 -5
  31. package/dist/langchain/middleware/index.mjs.map +1 -1
  32. package/dist/openai/index.cjs +169 -13
  33. package/dist/openai/index.cjs.map +1 -1
  34. package/dist/openai/index.mjs +169 -13
  35. package/dist/openai/index.mjs.map +1 -1
  36. package/dist/openai-agents/index.cjs +15 -5
  37. package/dist/openai-agents/index.cjs.map +1 -1
  38. package/dist/openai-agents/index.mjs +15 -5
  39. package/dist/openai-agents/index.mjs.map +1 -1
  40. package/dist/otel/index.cjs +12 -3
  41. package/dist/otel/index.cjs.map +1 -1
  42. package/dist/otel/index.mjs +12 -3
  43. package/dist/otel/index.mjs.map +1 -1
  44. package/dist/vercel/index.cjs +15 -8
  45. package/dist/vercel/index.cjs.map +1 -1
  46. package/dist/vercel/index.mjs +15 -8
  47. package/dist/vercel/index.mjs.map +1 -1
  48. package/package.json +5 -5
@@ -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.redactString(value, ctx);
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.placeholderFor(ctx.inferMediaType());
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)) out[k] = this.walk(obj[k], new MediaTypeContext(obj, k));
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 withPrivacyMode = (client, privacyMode, input) => {
309
- return client.privacy_mode || privacyMode ? null : input;
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.0";
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 = withPrivacyMode(client, privacyMode, false) === null;
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: sanitizeAnthropic(mergeSystemPrompt(anthropicParams, "anthropic"), this.phClient),
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: sanitizeAnthropic(mergeSystemPrompt(anthropicParams, "anthropic"), this.phClient),
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: sanitizeAnthropic(mergeSystemPrompt(anthropicParams, "anthropic"), this.phClient),
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: sanitizeAnthropic(mergeSystemPrompt(anthropicParams, "anthropic"), this.phClient),
1106
+ input: this.formatInputForPostHog(anthropicParams, posthogParams.privacyMode),
966
1107
  output: [],
967
1108
  latency: (Date.now() - startTime) / 1e3,
968
1109
  baseURL: this.baseURL,