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