@posthog/ai 8.16.0 → 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 +154 -8
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +154 -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
|
@@ -220,6 +220,10 @@ const redactor = new BinaryContentRedactor();
|
|
|
220
220
|
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
221
221
|
const sanitizeLangChain = (data, client) => sanitize(data, client);
|
|
222
222
|
//#endregion
|
|
223
|
+
//#region src/privacyMode.ts
|
|
224
|
+
/** Per-call settings can turn redaction on but never off. */
|
|
225
|
+
const isPrivacyModeEnabled = (client, privacyMode = false) => privacyMode === true || client?.privacyMode === true || client?.privacy_mode === true || client?.options?.privacyMode === true;
|
|
226
|
+
//#endregion
|
|
223
227
|
//#region src/utils.ts
|
|
224
228
|
const STRING_FORMAT = "utf8";
|
|
225
229
|
new TextEncoder();
|
|
@@ -269,7 +273,6 @@ const getModelParams = (params, responseServiceTier) => {
|
|
|
269
273
|
if (responseServiceTier != null) modelParams.service_tier = responseServiceTier;
|
|
270
274
|
return modelParams;
|
|
271
275
|
};
|
|
272
|
-
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
273
276
|
const withPrivacyMode = (client, privacyMode, input) => {
|
|
274
277
|
return isPrivacyModeEnabled(client, privacyMode) ? null : input;
|
|
275
278
|
};
|
|
@@ -282,12 +285,40 @@ function sanitizeValues(obj) {
|
|
|
282
285
|
return jsonSafe;
|
|
283
286
|
}
|
|
284
287
|
//#endregion
|
|
288
|
+
//#region src/mcpCredentials.ts
|
|
289
|
+
const MCP_CREDENTIAL_FIELDS = ["headers", "authorization"];
|
|
290
|
+
const MCP_PROVIDER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
291
|
+
"openai.mcp",
|
|
292
|
+
"xai.mcp",
|
|
293
|
+
"google.mcp_server"
|
|
294
|
+
]);
|
|
295
|
+
const isMcpProviderTool = (tool) => (tool.type === "provider" || tool.type === "provider-defined") && typeof tool.id === "string" && MCP_PROVIDER_TOOL_IDS.has(tool.id);
|
|
296
|
+
const withoutMcpCredentials = (config) => {
|
|
297
|
+
const redacted = { ...config };
|
|
298
|
+
for (const field of MCP_CREDENTIAL_FIELDS) if (field in redacted) redacted[field] = "[REDACTED]";
|
|
299
|
+
return redacted;
|
|
300
|
+
};
|
|
301
|
+
/** Hides the credentials of a remote MCP tool definition; everything else is kept as sent. */
|
|
302
|
+
function redactMcpToolDefinition(tool) {
|
|
303
|
+
if (!isObject(tool)) return tool;
|
|
304
|
+
if (tool.type === "mcp") return withoutMcpCredentials(tool);
|
|
305
|
+
if (isMcpProviderTool(tool) && isObject(tool.args)) return {
|
|
306
|
+
...tool,
|
|
307
|
+
args: withoutMcpCredentials(tool.args)
|
|
308
|
+
};
|
|
309
|
+
return tool;
|
|
310
|
+
}
|
|
311
|
+
function redactMcpToolCredentials(tools) {
|
|
312
|
+
return Array.isArray(tools) ? tools.map(redactMcpToolDefinition) : tools;
|
|
313
|
+
}
|
|
314
|
+
//#endregion
|
|
285
315
|
//#region package.json
|
|
286
|
-
var version = "8.16.
|
|
316
|
+
var version = "8.16.2";
|
|
287
317
|
//#endregion
|
|
288
318
|
//#region src/serializeError.ts
|
|
289
319
|
const DEFAULT_MAX_DEPTH = 3;
|
|
290
320
|
const MAX_STACK_LINES = 20;
|
|
321
|
+
const OMITTED_FIELD = "requestBodyValues";
|
|
291
322
|
function serializeError(value, depth = DEFAULT_MAX_DEPTH) {
|
|
292
323
|
if (depth < 0 || value === null || typeof value !== "object") return value;
|
|
293
324
|
if (value instanceof Error) {
|
|
@@ -296,16 +327,17 @@ function serializeError(value, depth = DEFAULT_MAX_DEPTH) {
|
|
|
296
327
|
message: value.message,
|
|
297
328
|
stack: truncateStack(value.stack)
|
|
298
329
|
};
|
|
299
|
-
for (const key of Object.keys(value)) out[key] = serializeError(value
|
|
330
|
+
for (const key of Object.keys(value)) if (key !== OMITTED_FIELD) out[key] = serializeError(Reflect.get(value, key), depth - 1);
|
|
300
331
|
if (value.cause !== void 0) out.cause = serializeError(value.cause, depth - 1);
|
|
301
332
|
return out;
|
|
302
333
|
}
|
|
303
334
|
if (Array.isArray(value)) return value.map((item) => serializeError(item, depth - 1));
|
|
304
335
|
return value;
|
|
305
336
|
}
|
|
337
|
+
const omitRequestBody = (key, value) => key === OMITTED_FIELD ? void 0 : value;
|
|
306
338
|
function stringifyError(error) {
|
|
307
339
|
try {
|
|
308
|
-
return JSON.stringify(sanitizeValues(serializeError(error)));
|
|
340
|
+
return JSON.stringify(sanitizeValues(serializeError(error)), omitRequestBody);
|
|
309
341
|
} catch {
|
|
310
342
|
if (error instanceof Error) return JSON.stringify({
|
|
311
343
|
name: error.name,
|
|
@@ -314,6 +346,105 @@ function stringifyError(error) {
|
|
|
314
346
|
return JSON.stringify({ message: String(error) });
|
|
315
347
|
}
|
|
316
348
|
}
|
|
349
|
+
const CLASS_NAME = /^[A-Za-z_$][A-Za-z0-9_$.]{0,127}$/;
|
|
350
|
+
const PROVIDER_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
351
|
+
const PARAM = /^[A-Za-z0-9_.[\]-]{1,128}$/;
|
|
352
|
+
const REQUEST_ID = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
353
|
+
const MAX_CAUSES = 3;
|
|
354
|
+
const readField = (value, key) => {
|
|
355
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return;
|
|
356
|
+
try {
|
|
357
|
+
return Reflect.get(value, key);
|
|
358
|
+
} catch {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
const matching = (value, grammar) => typeof value === "string" && grammar.test(value) ? value : void 0;
|
|
363
|
+
const firstMatching = (values, grammar) => {
|
|
364
|
+
for (const value of values) {
|
|
365
|
+
const match = matching(value, grammar);
|
|
366
|
+
if (match !== void 0) return match;
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
const className = (value) => {
|
|
370
|
+
if (!(value instanceof Error)) return "NonErrorThrown";
|
|
371
|
+
const name = readField(value, "name");
|
|
372
|
+
return firstMatching([
|
|
373
|
+
name === "Error" ? void 0 : name,
|
|
374
|
+
readField(readField(value, "constructor"), "name"),
|
|
375
|
+
name
|
|
376
|
+
], CLASS_NAME) ?? "Error";
|
|
377
|
+
};
|
|
378
|
+
const httpStatus = (error) => {
|
|
379
|
+
for (const key of ["status", "statusCode"]) {
|
|
380
|
+
const value = readField(error, key);
|
|
381
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 100 && value <= 599) return value;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
const unwrapEnvelope = (body) => {
|
|
385
|
+
const inner = readField(body, "error");
|
|
386
|
+
return inner !== null && typeof inner === "object" ? inner : body;
|
|
387
|
+
};
|
|
388
|
+
const parsedResponseBody = (error) => {
|
|
389
|
+
const responseBody = readField(error, "responseBody");
|
|
390
|
+
if (typeof responseBody !== "string") return;
|
|
391
|
+
try {
|
|
392
|
+
return unwrapEnvelope(JSON.parse(responseBody));
|
|
393
|
+
} catch {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
const causeNames = (error) => {
|
|
398
|
+
const names = [];
|
|
399
|
+
let cause = readField(error, "cause");
|
|
400
|
+
while (cause !== void 0 && cause !== null && names.length < MAX_CAUSES) {
|
|
401
|
+
names.push(className(cause));
|
|
402
|
+
cause = readField(cause, "cause");
|
|
403
|
+
}
|
|
404
|
+
return names;
|
|
405
|
+
};
|
|
406
|
+
const describeError = (error) => {
|
|
407
|
+
const sources = [
|
|
408
|
+
error,
|
|
409
|
+
unwrapEnvelope(readField(error, "error")),
|
|
410
|
+
parsedResponseBody(error)
|
|
411
|
+
];
|
|
412
|
+
const codes = /* @__PURE__ */ new Set();
|
|
413
|
+
for (const source of sources) for (const key of [
|
|
414
|
+
"code",
|
|
415
|
+
"type",
|
|
416
|
+
"status"
|
|
417
|
+
]) {
|
|
418
|
+
const code = matching(readField(source, key), PROVIDER_CODE);
|
|
419
|
+
if (code !== void 0) codes.add(code);
|
|
420
|
+
}
|
|
421
|
+
const status = httpStatus(error);
|
|
422
|
+
const param = firstMatching(sources.map((source) => readField(source, "param")), PARAM);
|
|
423
|
+
const requestId = firstMatching([readField(error, "requestID"), readField(error, "request_id")], REQUEST_ID);
|
|
424
|
+
const causes = causeNames(error);
|
|
425
|
+
let summary = className(error);
|
|
426
|
+
if (status !== void 0) summary += `: ${status}`;
|
|
427
|
+
for (const code of codes) summary += ` ${code}`;
|
|
428
|
+
if (param !== void 0) summary += ` param=${param}`;
|
|
429
|
+
if (requestId !== void 0) summary += ` request_id=${requestId}`;
|
|
430
|
+
if (causes.length > 0) summary += ` (caused by ${causes.join(", ")})`;
|
|
431
|
+
return summary;
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* Describes an error for `$ai_error` without its message, stack, or arbitrary fields, which
|
|
435
|
+
* routinely echo the prompt. Only structured fields that pass a strict grammar are kept.
|
|
436
|
+
* The format matches the Python SDK.
|
|
437
|
+
*/
|
|
438
|
+
function summarizeErrorForPrivacy(error) {
|
|
439
|
+
try {
|
|
440
|
+
return describeError(error);
|
|
441
|
+
} catch {
|
|
442
|
+
return error instanceof Error ? "Error" : "NonErrorThrown";
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function formatAiError(error, privacyMode) {
|
|
446
|
+
return privacyMode ? summarizeErrorForPrivacy(error) : stringifyError(error);
|
|
447
|
+
}
|
|
317
448
|
function truncateStack(stack) {
|
|
318
449
|
if (!stack) return stack;
|
|
319
450
|
const lines = stack.split("\n");
|
|
@@ -564,6 +695,9 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
564
695
|
if (parentRunId && !this.parentTree[parentRunId]) return traceId;
|
|
565
696
|
return parentRunId;
|
|
566
697
|
}
|
|
698
|
+
_isPrivacyModeEnabled() {
|
|
699
|
+
return isPrivacyModeEnabled(this.client, this.privacyMode);
|
|
700
|
+
}
|
|
567
701
|
_safeCapture(message) {
|
|
568
702
|
try {
|
|
569
703
|
captureAiEvent(this.client, message);
|
|
@@ -603,7 +737,7 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
603
737
|
const interrupts = outputs.interrupts;
|
|
604
738
|
if (interrupts !== void 0) eventProperties["$ai_output_state"] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain({ __interrupt__: interrupts }, this.client));
|
|
605
739
|
} else {
|
|
606
|
-
eventProperties["$ai_error"] =
|
|
740
|
+
eventProperties["$ai_error"] = formatAiError(outputs, this._isPrivacyModeEnabled());
|
|
607
741
|
eventProperties["$ai_is_error"] = true;
|
|
608
742
|
}
|
|
609
743
|
} else if (outputs !== void 0) eventProperties["$ai_output_state"] = withPrivacyMode(this.client, this.privacyMode, sanitizeLangChain(outputs, this.client));
|
|
@@ -652,10 +786,10 @@ var LangChainCallbackHandler = class extends _langchain_core_callbacks_base.Base
|
|
|
652
786
|
...eventPropertiesServedTier
|
|
653
787
|
};
|
|
654
788
|
if (parentRunId) eventProperties["$ai_parent_id"] = parentRunId;
|
|
655
|
-
if (run.tools) eventProperties["$ai_tools"] = run.tools;
|
|
789
|
+
if (run.tools) eventProperties["$ai_tools"] = redactMcpToolCredentials(run.tools);
|
|
656
790
|
if (output instanceof Error) {
|
|
657
791
|
eventProperties["$ai_http_status"] = output.status || 500;
|
|
658
|
-
eventProperties["$ai_error"] =
|
|
792
|
+
eventProperties["$ai_error"] = formatAiError(output, this._isPrivacyModeEnabled());
|
|
659
793
|
eventProperties["$ai_is_error"] = true;
|
|
660
794
|
} else {
|
|
661
795
|
const [inputTokens, outputTokens, additionalTokenData] = this.parseUsage(output, run.provider, run.model);
|
|
@@ -950,7 +1084,11 @@ const stringify = (value) => {
|
|
|
950
1084
|
}
|
|
951
1085
|
}
|
|
952
1086
|
};
|
|
953
|
-
const toError = (error) =>
|
|
1087
|
+
const toError = (error, privacyMode) => {
|
|
1088
|
+
if (error instanceof Error) return error;
|
|
1089
|
+
return privacyMode ? Object.assign(/* @__PURE__ */ new Error(), { name: "NonErrorThrown" }) : new Error(stringify(error));
|
|
1090
|
+
};
|
|
1091
|
+
const toolMessageError = (message, privacyMode) => new Error(privacyMode ? "Tool returned an error" : toContentString(message.content));
|
|
954
1092
|
const safely = (callback) => {
|
|
955
1093
|
try {
|
|
956
1094
|
callback();
|
|
@@ -1025,6 +1163,7 @@ const toLLMResult = (response) => {
|
|
|
1025
1163
|
const createPostHogMiddleware = (options) => {
|
|
1026
1164
|
const { stateSchema, ...callbackOptions } = options;
|
|
1027
1165
|
const callback = new LangChainMiddlewareCallbackHandler(callbackOptions);
|
|
1166
|
+
const privacyMode = () => isPrivacyModeEnabled(callbackOptions.client, callbackOptions.privacyMode);
|
|
1028
1167
|
const middlewareStateSchema = stateSchema ? (0, _langchain_core_utils_types.extendInteropZodObject)(stateSchema, postHogStateSchema.shape) : postHogStateSchema;
|
|
1029
1168
|
return (0, langchain.createMiddleware)({
|
|
1030
1169
|
name: "PostHogMiddleware",
|
|
@@ -1066,7 +1205,7 @@ const createPostHogMiddleware = (options) => {
|
|
|
1066
1205
|
safely(() => callback.handleLLMEnd(toLLMResult(response), runId, parentRunId));
|
|
1067
1206
|
return response;
|
|
1068
1207
|
} catch (error) {
|
|
1069
|
-
safely(() => callback.handleLLMError(toError(error), runId));
|
|
1208
|
+
safely(() => callback.handleLLMError(toError(error, privacyMode()), runId));
|
|
1070
1209
|
throw error;
|
|
1071
1210
|
}
|
|
1072
1211
|
},
|
|
@@ -1087,11 +1226,11 @@ const createPostHogMiddleware = (options) => {
|
|
|
1087
1226
|
safely(() => callback.handleToolStart(serializedTool, stringify(request.toolCall.args), runId, parentRunId, void 0, void 0, toolName));
|
|
1088
1227
|
try {
|
|
1089
1228
|
const result = await handler(request);
|
|
1090
|
-
if (_langchain_core_messages.ToolMessage.isInstance(result) && result.status === "error") safely(() => callback.handleToolError(
|
|
1229
|
+
if (_langchain_core_messages.ToolMessage.isInstance(result) && result.status === "error") safely(() => callback.handleToolError(toolMessageError(result, privacyMode()), runId, parentRunId));
|
|
1091
1230
|
else safely(() => callback.handleToolEnd(result, runId, parentRunId));
|
|
1092
1231
|
return result;
|
|
1093
1232
|
} catch (error) {
|
|
1094
|
-
safely(() => callback.handleToolError(toError(error), runId));
|
|
1233
|
+
safely(() => callback.handleToolError(toError(error, privacyMode()), runId));
|
|
1095
1234
|
throw error;
|
|
1096
1235
|
}
|
|
1097
1236
|
}
|