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