@posthog/ai 8.16.1 → 8.16.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 +12 -0
- package/dist/adk/index.cjs +147 -9
- package/dist/adk/index.cjs.map +1 -1
- package/dist/adk/index.mjs +147 -9
- package/dist/adk/index.mjs.map +1 -1
- 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/claude-agent-sdk/index.cjs +147 -9
- package/dist/claude-agent-sdk/index.cjs.map +1 -1
- package/dist/claude-agent-sdk/index.mjs +147 -9
- package/dist/claude-agent-sdk/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +141 -8
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.mjs +141 -8
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +149 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +149 -15
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +141 -7
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.d.ts +1 -0
- package/dist/langchain/index.mjs +141 -7
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/langchain/middleware/index.cjs +150 -11
- package/dist/langchain/middleware/index.cjs.map +1 -1
- package/dist/langchain/middleware/index.mjs +150 -11
- package/dist/langchain/middleware/index.mjs.map +1 -1
- package/dist/openai/index.cjs +141 -8
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +141 -8
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openai-agents/index.cjs +104 -3
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.mjs +104 -3
- package/dist/openai-agents/index.mjs.map +1 -1
- package/dist/otel/index.cjs +216 -4
- package/dist/otel/index.cjs.map +1 -1
- package/dist/otel/index.d.ts +22 -1
- package/dist/otel/index.mjs +216 -4
- package/dist/otel/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +149 -15
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +149 -15
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/langchain/index.cjs
CHANGED
|
@@ -215,6 +215,10 @@ const redactor = new BinaryContentRedactor();
|
|
|
215
215
|
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
216
216
|
const sanitizeLangChain = (data, client) => sanitize(data, client);
|
|
217
217
|
//#endregion
|
|
218
|
+
//#region src/privacyMode.ts
|
|
219
|
+
/** Per-call settings can turn redaction on but never off. */
|
|
220
|
+
const isPrivacyModeEnabled = (client, privacyMode = false) => privacyMode === true || client?.privacyMode === true || client?.privacy_mode === true || client?.options?.privacyMode === true;
|
|
221
|
+
//#endregion
|
|
218
222
|
//#region src/utils.ts
|
|
219
223
|
const STRING_FORMAT = "utf8";
|
|
220
224
|
new TextEncoder();
|
|
@@ -264,7 +268,6 @@ const getModelParams = (params, responseServiceTier) => {
|
|
|
264
268
|
if (responseServiceTier != null) modelParams.service_tier = responseServiceTier;
|
|
265
269
|
return modelParams;
|
|
266
270
|
};
|
|
267
|
-
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
268
271
|
const withPrivacyMode = (client, privacyMode, input) => {
|
|
269
272
|
return isPrivacyModeEnabled(client, privacyMode) ? null : input;
|
|
270
273
|
};
|
|
@@ -277,12 +280,40 @@ function sanitizeValues(obj) {
|
|
|
277
280
|
return jsonSafe;
|
|
278
281
|
}
|
|
279
282
|
//#endregion
|
|
283
|
+
//#region src/mcpCredentials.ts
|
|
284
|
+
const MCP_CREDENTIAL_FIELDS = ["headers", "authorization"];
|
|
285
|
+
const MCP_PROVIDER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
286
|
+
"openai.mcp",
|
|
287
|
+
"xai.mcp",
|
|
288
|
+
"google.mcp_server"
|
|
289
|
+
]);
|
|
290
|
+
const isMcpProviderTool = (tool) => (tool.type === "provider" || tool.type === "provider-defined") && typeof tool.id === "string" && MCP_PROVIDER_TOOL_IDS.has(tool.id);
|
|
291
|
+
const withoutMcpCredentials = (config) => {
|
|
292
|
+
const redacted = { ...config };
|
|
293
|
+
for (const field of MCP_CREDENTIAL_FIELDS) if (field in redacted) redacted[field] = "[REDACTED]";
|
|
294
|
+
return redacted;
|
|
295
|
+
};
|
|
296
|
+
/** Hides the credentials of a remote MCP tool definition; everything else is kept as sent. */
|
|
297
|
+
function redactMcpToolDefinition(tool) {
|
|
298
|
+
if (!isObject(tool)) return tool;
|
|
299
|
+
if (tool.type === "mcp") return withoutMcpCredentials(tool);
|
|
300
|
+
if (isMcpProviderTool(tool) && isObject(tool.args)) return {
|
|
301
|
+
...tool,
|
|
302
|
+
args: withoutMcpCredentials(tool.args)
|
|
303
|
+
};
|
|
304
|
+
return tool;
|
|
305
|
+
}
|
|
306
|
+
function redactMcpToolCredentials(tools) {
|
|
307
|
+
return Array.isArray(tools) ? tools.map(redactMcpToolDefinition) : tools;
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
280
310
|
//#region package.json
|
|
281
|
-
var version = "8.16.
|
|
311
|
+
var version = "8.16.2";
|
|
282
312
|
//#endregion
|
|
283
313
|
//#region src/serializeError.ts
|
|
284
314
|
const DEFAULT_MAX_DEPTH = 3;
|
|
285
315
|
const MAX_STACK_LINES = 20;
|
|
316
|
+
const OMITTED_FIELD = "requestBodyValues";
|
|
286
317
|
function serializeError(value, depth = DEFAULT_MAX_DEPTH) {
|
|
287
318
|
if (depth < 0 || value === null || typeof value !== "object") return value;
|
|
288
319
|
if (value instanceof Error) {
|
|
@@ -291,16 +322,17 @@ function serializeError(value, depth = DEFAULT_MAX_DEPTH) {
|
|
|
291
322
|
message: value.message,
|
|
292
323
|
stack: truncateStack(value.stack)
|
|
293
324
|
};
|
|
294
|
-
for (const key of Object.keys(value)) out[key] = serializeError(value
|
|
325
|
+
for (const key of Object.keys(value)) if (key !== OMITTED_FIELD) out[key] = serializeError(Reflect.get(value, key), depth - 1);
|
|
295
326
|
if (value.cause !== void 0) out.cause = serializeError(value.cause, depth - 1);
|
|
296
327
|
return out;
|
|
297
328
|
}
|
|
298
329
|
if (Array.isArray(value)) return value.map((item) => serializeError(item, depth - 1));
|
|
299
330
|
return value;
|
|
300
331
|
}
|
|
332
|
+
const omitRequestBody = (key, value) => key === OMITTED_FIELD ? void 0 : value;
|
|
301
333
|
function stringifyError(error) {
|
|
302
334
|
try {
|
|
303
|
-
return JSON.stringify(sanitizeValues(serializeError(error)));
|
|
335
|
+
return JSON.stringify(sanitizeValues(serializeError(error)), omitRequestBody);
|
|
304
336
|
} catch {
|
|
305
337
|
if (error instanceof Error) return JSON.stringify({
|
|
306
338
|
name: error.name,
|
|
@@ -309,6 +341,105 @@ function stringifyError(error) {
|
|
|
309
341
|
return JSON.stringify({ message: String(error) });
|
|
310
342
|
}
|
|
311
343
|
}
|
|
344
|
+
const CLASS_NAME = /^[A-Za-z_$][A-Za-z0-9_$.]{0,127}$/;
|
|
345
|
+
const PROVIDER_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
346
|
+
const PARAM = /^[A-Za-z0-9_.[\]-]{1,128}$/;
|
|
347
|
+
const REQUEST_ID = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
348
|
+
const MAX_CAUSES = 3;
|
|
349
|
+
const readField = (value, key) => {
|
|
350
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return;
|
|
351
|
+
try {
|
|
352
|
+
return Reflect.get(value, key);
|
|
353
|
+
} catch {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
const matching = (value, grammar) => typeof value === "string" && grammar.test(value) ? value : void 0;
|
|
358
|
+
const firstMatching = (values, grammar) => {
|
|
359
|
+
for (const value of values) {
|
|
360
|
+
const match = matching(value, grammar);
|
|
361
|
+
if (match !== void 0) return match;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
const className = (value) => {
|
|
365
|
+
if (!(value instanceof Error)) return "NonErrorThrown";
|
|
366
|
+
const name = readField(value, "name");
|
|
367
|
+
return firstMatching([
|
|
368
|
+
name === "Error" ? void 0 : name,
|
|
369
|
+
readField(readField(value, "constructor"), "name"),
|
|
370
|
+
name
|
|
371
|
+
], CLASS_NAME) ?? "Error";
|
|
372
|
+
};
|
|
373
|
+
const httpStatus = (error) => {
|
|
374
|
+
for (const key of ["status", "statusCode"]) {
|
|
375
|
+
const value = readField(error, key);
|
|
376
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599) return value;
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
const unwrapEnvelope = (body) => {
|
|
380
|
+
const inner = readField(body, "error");
|
|
381
|
+
return inner !== null && typeof inner === "object" ? inner : body;
|
|
382
|
+
};
|
|
383
|
+
const parsedResponseBody = (error) => {
|
|
384
|
+
const responseBody = readField(error, "responseBody");
|
|
385
|
+
if (typeof responseBody !== "string") return;
|
|
386
|
+
try {
|
|
387
|
+
return unwrapEnvelope(JSON.parse(responseBody));
|
|
388
|
+
} catch {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
const causeNames = (error) => {
|
|
393
|
+
const names = [];
|
|
394
|
+
let cause = readField(error, "cause");
|
|
395
|
+
while (cause !== void 0 && cause !== null && names.length < MAX_CAUSES) {
|
|
396
|
+
names.push(className(cause));
|
|
397
|
+
cause = readField(cause, "cause");
|
|
398
|
+
}
|
|
399
|
+
return names;
|
|
400
|
+
};
|
|
401
|
+
const describeError = (error) => {
|
|
402
|
+
const sources = [
|
|
403
|
+
error,
|
|
404
|
+
unwrapEnvelope(readField(error, "error")),
|
|
405
|
+
parsedResponseBody(error)
|
|
406
|
+
];
|
|
407
|
+
const codes = /* @__PURE__ */ new Set();
|
|
408
|
+
for (const source of sources) for (const key of [
|
|
409
|
+
"code",
|
|
410
|
+
"type",
|
|
411
|
+
"status"
|
|
412
|
+
]) {
|
|
413
|
+
const code = matching(readField(source, key), PROVIDER_CODE);
|
|
414
|
+
if (code !== void 0) codes.add(code);
|
|
415
|
+
}
|
|
416
|
+
const status = httpStatus(error);
|
|
417
|
+
const param = firstMatching(sources.map((source) => readField(source, "param")), PARAM);
|
|
418
|
+
const requestId = firstMatching([readField(error, "requestID"), readField(error, "request_id")], REQUEST_ID);
|
|
419
|
+
const causes = causeNames(error);
|
|
420
|
+
let summary = className(error);
|
|
421
|
+
if (status !== void 0) summary += `: ${status}`;
|
|
422
|
+
for (const code of codes) summary += ` ${code}`;
|
|
423
|
+
if (param !== void 0) summary += ` param=${param}`;
|
|
424
|
+
if (requestId !== void 0) summary += ` request_id=${requestId}`;
|
|
425
|
+
if (causes.length > 0) summary += ` (caused by ${causes.join(", ")})`;
|
|
426
|
+
return summary;
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* Describes an error for `$ai_error` without its message, stack, or arbitrary fields, which
|
|
430
|
+
* routinely echo the prompt. Only structured fields that pass a strict grammar are kept.
|
|
431
|
+
* The format matches the Python SDK.
|
|
432
|
+
*/
|
|
433
|
+
function summarizeErrorForPrivacy(error) {
|
|
434
|
+
try {
|
|
435
|
+
return describeError(error);
|
|
436
|
+
} catch {
|
|
437
|
+
return error instanceof Error ? "Error" : "NonErrorThrown";
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function formatAiError(error, privacyMode) {
|
|
441
|
+
return privacyMode ? summarizeErrorForPrivacy(error) : stringifyError(error);
|
|
442
|
+
}
|
|
312
443
|
function truncateStack(stack) {
|
|
313
444
|
if (!stack) return stack;
|
|
314
445
|
const lines = stack.split("\n");
|
|
@@ -559,6 +690,9 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
559
690
|
if (parentRunId && !this.parentTree[parentRunId]) return traceId;
|
|
560
691
|
return parentRunId;
|
|
561
692
|
}
|
|
693
|
+
_isPrivacyModeEnabled() {
|
|
694
|
+
return isPrivacyModeEnabled(this.client, this.privacyMode);
|
|
695
|
+
}
|
|
562
696
|
_safeCapture(message) {
|
|
563
697
|
try {
|
|
564
698
|
captureAiEvent(this.client, message);
|
|
@@ -598,7 +732,7 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
598
732
|
const interrupts = outputs.interrupts;
|
|
599
733
|
if (interrupts !== void 0) eventProperties["$ai_output_state"] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain({ __interrupt__: interrupts }, this.client));
|
|
600
734
|
} else {
|
|
601
|
-
eventProperties["$ai_error"] =
|
|
735
|
+
eventProperties["$ai_error"] = formatAiError(outputs, this._isPrivacyModeEnabled());
|
|
602
736
|
eventProperties["$ai_is_error"] = true;
|
|
603
737
|
}
|
|
604
738
|
} else if (outputs !== void 0) eventProperties["$ai_output_state"] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain(outputs, this.client));
|
|
@@ -647,10 +781,10 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
647
781
|
...eventPropertiesServedTier
|
|
648
782
|
};
|
|
649
783
|
if (parentRunId) eventProperties["$ai_parent_id"] = parentRunId;
|
|
650
|
-
if (run.tools) eventProperties["$ai_tools"] = run.tools;
|
|
784
|
+
if (run.tools) eventProperties["$ai_tools"] = redactMcpToolCredentials(run.tools);
|
|
651
785
|
if (output instanceof Error) {
|
|
652
786
|
eventProperties["$ai_http_status"] = output.status || 500;
|
|
653
|
-
eventProperties["$ai_error"] =
|
|
787
|
+
eventProperties["$ai_error"] = formatAiError(output, this._isPrivacyModeEnabled());
|
|
654
788
|
eventProperties["$ai_is_error"] = true;
|
|
655
789
|
} else {
|
|
656
790
|
const [inputTokens, outputTokens, additionalTokenData] = this.parseUsage(output, run.provider, run.model);
|