@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.
- 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 +169 -13
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.mjs +169 -13
- 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 +5 -5
|
@@ -3,7 +3,7 @@ let _anthropic_ai_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
|
3
3
|
let uuid = require("uuid");
|
|
4
4
|
let _posthog_core = require("@posthog/core");
|
|
5
5
|
//#region package.json
|
|
6
|
-
var version = "8.14.
|
|
6
|
+
var version = "8.14.2";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/captureAiEvent.ts
|
|
9
9
|
/** @internal */
|
|
@@ -170,17 +170,26 @@ var BinaryContentRedactor = class {
|
|
|
170
170
|
this.visited = /* @__PURE__ */ new WeakSet();
|
|
171
171
|
return this.walk(value, mediaType ? new MediaTypeContext(void 0, void 0, mediaType) : MediaTypeContext.EMPTY);
|
|
172
172
|
}
|
|
173
|
+
/** Redact one leaf while a caller owns bounded, type-preserving traversal. @internal */
|
|
174
|
+
redactLeaf(value, context) {
|
|
175
|
+
return typeof value === "string" ? this.redactString(value, context) : this.placeholderFor(context.inferMediaType());
|
|
176
|
+
}
|
|
173
177
|
walk(value, ctx) {
|
|
174
178
|
if (value === null || value === void 0) return value;
|
|
175
|
-
if (typeof value === "string") return this.
|
|
179
|
+
if (typeof value === "string") return this.redactLeaf(value, ctx);
|
|
176
180
|
if (typeof value !== "object") return value;
|
|
177
|
-
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.
|
|
181
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return this.redactLeaf(value, ctx);
|
|
178
182
|
if (this.visited.has(value)) return null;
|
|
179
183
|
this.visited.add(value);
|
|
180
184
|
if (Array.isArray(value)) return value.map((item) => this.walk(item, ctx));
|
|
181
185
|
const obj = value;
|
|
182
186
|
const out = {};
|
|
183
|
-
for (const k of Object.keys(obj))
|
|
187
|
+
for (const k of Object.keys(obj)) Object.defineProperty(out, k, {
|
|
188
|
+
value: this.walk(obj[k], new MediaTypeContext(obj, k)),
|
|
189
|
+
enumerable: true,
|
|
190
|
+
writable: true,
|
|
191
|
+
configurable: true
|
|
192
|
+
});
|
|
184
193
|
return out;
|
|
185
194
|
}
|
|
186
195
|
redactString(value, ctx) {
|
|
@@ -200,11 +209,7 @@ var BinaryContentRedactor = class {
|
|
|
200
209
|
return `[base64 ${mediaType} redacted]`;
|
|
201
210
|
}
|
|
202
211
|
};
|
|
203
|
-
|
|
204
|
-
//#region src/sanitization.ts
|
|
205
|
-
const redactor = new BinaryContentRedactor();
|
|
206
|
-
const sanitize = (data, client) => isFullAiCaptureEnabled(client) ? data : redactor.redact(data);
|
|
207
|
-
const sanitizeAnthropic = (data, client) => sanitize(data, client);
|
|
212
|
+
new BinaryContentRedactor();
|
|
208
213
|
//#endregion
|
|
209
214
|
//#region src/utils.ts
|
|
210
215
|
const TOKEN_PROPERTY_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -253,9 +258,7 @@ function toContentString(content) {
|
|
|
253
258
|
}
|
|
254
259
|
return String(content);
|
|
255
260
|
}
|
|
256
|
-
const
|
|
257
|
-
return client.privacy_mode || privacyMode ? null : input;
|
|
258
|
-
};
|
|
261
|
+
const isPrivacyModeEnabled = (client, privacyMode) => Boolean(client.privacy_mode || privacyMode);
|
|
259
262
|
function toSafeString(input) {
|
|
260
263
|
if (input === void 0 || input === null) return "";
|
|
261
264
|
if (typeof input === "string") return input;
|
|
@@ -371,7 +374,7 @@ const captureAiGeneration = async (client, options) => {
|
|
|
371
374
|
const eventType = options.eventType ?? "$ai_generation";
|
|
372
375
|
const privacyMode = options.privacyMode ?? false;
|
|
373
376
|
const usage = options.usage ?? {};
|
|
374
|
-
const shouldRedact =
|
|
377
|
+
const shouldRedact = isPrivacyModeEnabled(client, privacyMode);
|
|
375
378
|
const safeInput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.input);
|
|
376
379
|
const safeOutput = shouldRedact ? null : (0, _posthog_core.toJsonSafeValue)(options.output);
|
|
377
380
|
let httpStatus = options.httpStatus;
|
|
@@ -453,22 +456,92 @@ const captureAiGeneration = async (client, options) => {
|
|
|
453
456
|
}
|
|
454
457
|
};
|
|
455
458
|
//#endregion
|
|
456
|
-
//#region src/
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
459
|
+
//#region src/toolResult.ts
|
|
460
|
+
const MAX_DEPTH = 20;
|
|
461
|
+
const MAX_ITEMS = 1e3;
|
|
462
|
+
const MAX_NODES = 1e4;
|
|
463
|
+
const TRUNCATED = "[Truncated]";
|
|
464
|
+
const UNSERIALIZABLE = "[Unserializable]";
|
|
465
|
+
const redactor = new BinaryContentRedactor();
|
|
466
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
467
|
+
/** @internal Preserve tool-result structure while bounding each string value. */
|
|
468
|
+
function formatToolResult(content, client, maxBytes = 5e3) {
|
|
469
|
+
try {
|
|
470
|
+
if (isFullAiCaptureEnabled(client)) return (0, _posthog_core.toJsonSafeValue)(content);
|
|
471
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
472
|
+
let remainingNodes = MAX_NODES;
|
|
473
|
+
const convert = (value, depth, context) => {
|
|
474
|
+
if (remainingNodes <= 0) return TRUNCATED;
|
|
475
|
+
remainingNodes--;
|
|
476
|
+
try {
|
|
477
|
+
if (value === null || typeof value !== "object") {
|
|
478
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
479
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
480
|
+
}
|
|
481
|
+
if (depth >= MAX_DEPTH) return TRUNCATED;
|
|
482
|
+
if (typeof Uint8Array !== "undefined" && value instanceof Uint8Array) return redactor.redactLeaf(value, context);
|
|
483
|
+
if (ancestors.has(value)) return "[Circular]";
|
|
484
|
+
ancestors.add(value);
|
|
485
|
+
try {
|
|
486
|
+
if (value instanceof Date) {
|
|
487
|
+
const safe = (0, _posthog_core.toJsonSafeValue)(value);
|
|
488
|
+
return typeof safe === "string" ? truncate(redactor.redactLeaf(safe, context), void 0, maxBytes) : safe;
|
|
489
|
+
}
|
|
490
|
+
let hasToJSONResult = false;
|
|
491
|
+
let toJSONResult;
|
|
492
|
+
try {
|
|
493
|
+
const toJSON = value.toJSON;
|
|
494
|
+
if (typeof toJSON === "function") {
|
|
495
|
+
toJSONResult = toJSON.call(value);
|
|
496
|
+
hasToJSONResult = true;
|
|
497
|
+
}
|
|
498
|
+
} catch {}
|
|
499
|
+
if (hasToJSONResult) return convert(toJSONResult, depth + 1, context);
|
|
500
|
+
if (Array.isArray(value)) {
|
|
501
|
+
const output = [];
|
|
502
|
+
const count = Math.min(value.length, MAX_ITEMS);
|
|
503
|
+
let index = 0;
|
|
504
|
+
for (; index < count && remainingNodes > 0; index++) output.push(convert(value[index], depth + 1, context));
|
|
505
|
+
if (value.length > index) output.push(TRUNCATED);
|
|
506
|
+
return output;
|
|
507
|
+
}
|
|
508
|
+
const input = value;
|
|
509
|
+
const output = {};
|
|
510
|
+
let count = 0;
|
|
511
|
+
let truncated = false;
|
|
512
|
+
for (const key in input) {
|
|
513
|
+
if (!propertyIsEnumerable.call(input, key)) break;
|
|
514
|
+
if (count >= MAX_ITEMS || remainingNodes <= 0) {
|
|
515
|
+
truncated = true;
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
const converted = convert(input[key], depth + 1, new MediaTypeContext(input, key));
|
|
519
|
+
Object.defineProperty(output, key, {
|
|
520
|
+
value: converted,
|
|
521
|
+
enumerable: true,
|
|
522
|
+
writable: true,
|
|
523
|
+
configurable: true
|
|
524
|
+
});
|
|
525
|
+
count++;
|
|
526
|
+
}
|
|
527
|
+
if (truncated) output[TRUNCATED] = "Additional properties omitted";
|
|
528
|
+
return output;
|
|
529
|
+
} finally {
|
|
530
|
+
ancestors.delete(value);
|
|
531
|
+
}
|
|
532
|
+
} catch {
|
|
533
|
+
return UNSERIALIZABLE;
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
return convert(content, 0, MediaTypeContext.EMPTY);
|
|
537
|
+
} catch {
|
|
538
|
+
return UNSERIALIZABLE;
|
|
539
|
+
}
|
|
468
540
|
}
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region src/claude-agent-sdk/formatting.ts
|
|
469
543
|
function formatContent(content, client, maxBytes = MAX_OUTPUT_SIZE) {
|
|
470
|
-
|
|
471
|
-
return isFullAiCaptureEnabled(client) ? redacted : capStrings(redacted, maxBytes);
|
|
544
|
+
return formatToolResult(content, client, maxBytes);
|
|
472
545
|
}
|
|
473
546
|
/** Read the system prompt out of the SDK options, whatever shape it takes. */
|
|
474
547
|
function extractSystemPrompt(options) {
|
|
@@ -507,7 +580,8 @@ function formatAssistantBlocks(blocks, client) {
|
|
|
507
580
|
return content;
|
|
508
581
|
}
|
|
509
582
|
/** Convert an Anthropic user message body into PostHog content items. */
|
|
510
|
-
function formatUserContent(content, client) {
|
|
583
|
+
function formatUserContent(content, client, privacyMode = false) {
|
|
584
|
+
if (isPrivacyModeEnabled(client, privacyMode)) return [];
|
|
511
585
|
if (typeof content === "string") return content;
|
|
512
586
|
if (!Array.isArray(content)) return [];
|
|
513
587
|
const formatted = [];
|
|
@@ -516,7 +590,7 @@ function formatUserContent(content, client) {
|
|
|
516
590
|
if (block.type === "tool_result") formatted.push({
|
|
517
591
|
type: "tool_result",
|
|
518
592
|
tool_use_id: block.tool_use_id,
|
|
519
|
-
content:
|
|
593
|
+
content: formatToolResult(block.content, client),
|
|
520
594
|
...typeof block.is_error === "boolean" ? { is_error: block.is_error } : {}
|
|
521
595
|
});
|
|
522
596
|
else if (typeof block.text === "string") formatted.push({
|
|
@@ -820,7 +894,7 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
820
894
|
yield message;
|
|
821
895
|
}
|
|
822
896
|
}
|
|
823
|
-
_beginTurn(state, userMessageUuid) {
|
|
897
|
+
_beginTurn(state, trace, userMessageUuid) {
|
|
824
898
|
if (state.turnActive) return;
|
|
825
899
|
state.turnActive = true;
|
|
826
900
|
let end = userMessageUuid ? state.pendingPrompts.findIndex((message) => message.uuid === userMessageUuid) : -1;
|
|
@@ -834,7 +908,7 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
834
908
|
while (start > 0 && state.pendingPrompts[start - 1].shouldQuery === false) start -= 1;
|
|
835
909
|
for (const message of state.pendingPrompts.splice(start, end - start + 1)) state.tracker.appendPendingInput([{
|
|
836
910
|
role: "user",
|
|
837
|
-
content: formatUserContent(message.message.content, this._client)
|
|
911
|
+
content: formatUserContent(message.message.content, this._client, trace.privacyMode)
|
|
838
912
|
}]);
|
|
839
913
|
}
|
|
840
914
|
async _handleMessage(message, state, trace) {
|
|
@@ -846,11 +920,11 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
846
920
|
} else if (message.type === "stream_event") {
|
|
847
921
|
if (message.parent_tool_use_id) return;
|
|
848
922
|
if (message.user_message_uuid) state.userMessageUuid = message.user_message_uuid;
|
|
849
|
-
if (message.event.type === "message_start") this._beginTurn(state, message.user_message_uuid);
|
|
923
|
+
if (message.event.type === "message_start") this._beginTurn(state, trace, message.user_message_uuid);
|
|
850
924
|
state.tracker.processStreamEvent(message.event, this._client, message.ttft_ms);
|
|
851
925
|
await this._captureCompletedGenerations(state, trace);
|
|
852
926
|
} else if (message.type === "assistant") {
|
|
853
|
-
if (!message.parent_tool_use_id) this._beginTurn(state, message.user_message_uuid);
|
|
927
|
+
if (!message.parent_tool_use_id) this._beginTurn(state, trace, message.user_message_uuid);
|
|
854
928
|
this._handleAssistantMessage(message, state, trace);
|
|
855
929
|
} else if (message.type === "user") {
|
|
856
930
|
if ("isReplay" in message && message.isReplay) return;
|
|
@@ -858,13 +932,13 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
858
932
|
for (const block of message.message.content) if (block.type === "tool_result") await this._finishToolSpan(block.tool_use_id, state, trace, block);
|
|
859
933
|
}
|
|
860
934
|
if (message.parent_tool_use_id) return;
|
|
861
|
-
const content = formatUserContent(message.message?.content, this._client);
|
|
935
|
+
const content = formatUserContent(message.message?.content, this._client, trace.privacyMode);
|
|
862
936
|
if (typeof content === "string" || Array.isArray(content) && content.length > 0) state.tracker.appendPendingInput([{
|
|
863
937
|
role: "user",
|
|
864
938
|
content
|
|
865
939
|
}]);
|
|
866
940
|
} else if (message.type === "result") try {
|
|
867
|
-
this._beginTurn(state, message.user_message_uuid);
|
|
941
|
+
this._beginTurn(state, trace, message.user_message_uuid);
|
|
868
942
|
state.tracker.finishCurrent();
|
|
869
943
|
await this._captureCompletedGenerations(state, trace, resultError(message), message);
|
|
870
944
|
if (message.total_cost_usd != null) {
|
|
@@ -954,7 +1028,7 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
954
1028
|
...parentSpanId ? { $ai_parent_id: parentSpanId } : {},
|
|
955
1029
|
$ai_span_name: block.name,
|
|
956
1030
|
$ai_span_type: "tool",
|
|
957
|
-
$ai_input_state:
|
|
1031
|
+
$ai_input_state: isPrivacyModeEnabled(this._client, trace.privacyMode ?? false) ? null : formatContent(block.input ?? {}, this._client)
|
|
958
1032
|
};
|
|
959
1033
|
state.pendingTools.set(properties.$ai_span_id, {
|
|
960
1034
|
startTime: performance.now(),
|
|
@@ -969,7 +1043,7 @@ var PostHogClaudeAgentProcessor = class {
|
|
|
969
1043
|
...tool.properties,
|
|
970
1044
|
$ai_latency: (performance.now() - tool.startTime) / 1e3,
|
|
971
1045
|
...result ? {
|
|
972
|
-
$ai_output_state:
|
|
1046
|
+
$ai_output_state: isPrivacyModeEnabled(this._client, trace.privacyMode ?? false) ? null : formatContent(result.content, this._client),
|
|
973
1047
|
$ai_is_error: result.is_error === true
|
|
974
1048
|
} : {}
|
|
975
1049
|
};
|