agent-inspect 1.2.0 → 1.3.0

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.
@@ -193,6 +193,51 @@ function isPersistedInspectEvent(value) {
193
193
  return true;
194
194
  }
195
195
 
196
+ // packages/core/src/correlation-metadata.ts
197
+ var TRACE_CORRELATION_KEYS = [
198
+ "correlationId",
199
+ "requestId",
200
+ "decisionId",
201
+ "groupId"
202
+ ];
203
+ function isNonEmptyString2(value) {
204
+ return typeof value === "string" && value.length > 0;
205
+ }
206
+ function extractCorrelationMetadata(record) {
207
+ if (!record) {
208
+ return void 0;
209
+ }
210
+ const out = {};
211
+ let found = false;
212
+ for (const key of TRACE_CORRELATION_KEYS) {
213
+ const value = record[key];
214
+ if (isNonEmptyString2(value)) {
215
+ out[key] = value;
216
+ found = true;
217
+ }
218
+ }
219
+ return found ? out : void 0;
220
+ }
221
+ function buildRunStartedMetadata(options) {
222
+ if (!options) {
223
+ return void 0;
224
+ }
225
+ const merged = options.metadata !== void 0 ? { ...options.metadata } : {};
226
+ if (isNonEmptyString2(options.correlationId)) {
227
+ merged.correlationId = options.correlationId;
228
+ }
229
+ if (isNonEmptyString2(options.requestId)) {
230
+ merged.requestId = options.requestId;
231
+ }
232
+ if (isNonEmptyString2(options.decisionId)) {
233
+ merged.decisionId = options.decisionId;
234
+ }
235
+ if (isNonEmptyString2(options.groupId)) {
236
+ merged.groupId = options.groupId;
237
+ }
238
+ return Object.keys(merged).length > 0 ? merged : void 0;
239
+ }
240
+
196
241
  // packages/core/src/persisted/from-trace-event.ts
197
242
  function sanitizeIdPart(value) {
198
243
  return value.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -299,9 +344,14 @@ function traceEventToPersistedInspectEvent(event, options) {
299
344
  switch (event.event) {
300
345
  case "run_started": {
301
346
  const tsStart = toIsoTimestamp(event.startTime);
347
+ const correlation = extractCorrelationMetadata(event.metadata);
302
348
  const attributes = compactAttributes({
303
349
  legacyEvent: "run_started",
304
350
  metadata: event.metadata !== void 0 ? { ...event.metadata } : void 0,
351
+ correlationId: correlation?.correlationId,
352
+ requestId: correlation?.requestId,
353
+ decisionId: correlation?.decisionId,
354
+ groupId: correlation?.groupId,
305
355
  invalidTimestamp: tsMain.invalidTimestamp || tsStart.invalidTimestamp ? true : void 0
306
356
  });
307
357
  return {
@@ -1138,7 +1188,7 @@ function stableHash(value) {
1138
1188
  const h = crypto__default.default.createHash("sha256").update(value, "utf8").digest("hex");
1139
1189
  return h.slice(0, 8);
1140
1190
  }
1141
- function compileRules(rules) {
1191
+ function compileRules(rules, extraKeys) {
1142
1192
  const out = /* @__PURE__ */ new Map();
1143
1193
  const set = (r) => {
1144
1194
  const k = toKey(r.key);
@@ -1147,6 +1197,11 @@ function compileRules(rules) {
1147
1197
  for (const k of DEFAULT_REDACT_KEYS) {
1148
1198
  set({ key: k, strategy: "full" });
1149
1199
  }
1200
+ for (const k of extraKeys ?? []) {
1201
+ if (typeof k === "string" && k.length > 0) {
1202
+ set({ key: k, strategy: "full" });
1203
+ }
1204
+ }
1150
1205
  for (const r of rules ?? []) {
1151
1206
  if (typeof r === "string") {
1152
1207
  set({ key: r, strategy: "full" });
@@ -1164,7 +1219,7 @@ function compileRules(rules) {
1164
1219
  var Redactor = class {
1165
1220
  #rules;
1166
1221
  constructor(options) {
1167
- this.#rules = compileRules(options?.rules);
1222
+ this.#rules = compileRules(options?.rules, options?.extraKeys);
1168
1223
  }
1169
1224
  redactValue(key, value) {
1170
1225
  const k = toKey(key);
@@ -1869,6 +1924,91 @@ function warn(message, error) {
1869
1924
  }
1870
1925
  console.warn(`${base}: ${formatError(error).message}`);
1871
1926
  }
1927
+
1928
+ // packages/core/src/redaction-profiles.ts
1929
+ var SHARE_PROFILE_EXTRA_KEYS = [
1930
+ "userEmail",
1931
+ "customerEmail",
1932
+ "phone",
1933
+ "phoneNumber",
1934
+ "address",
1935
+ "ip",
1936
+ "ipAddress",
1937
+ "sessionId",
1938
+ "requestId",
1939
+ "correlationId",
1940
+ "decisionId",
1941
+ "groupId",
1942
+ "customerId",
1943
+ "userId",
1944
+ "accountId",
1945
+ "tenantId",
1946
+ "orgId",
1947
+ "organizationId",
1948
+ "traceId",
1949
+ "spanId",
1950
+ "parentSpanId"
1951
+ ];
1952
+ var STRICT_PROFILE_EXTRA_KEYS = [
1953
+ "prompt",
1954
+ "completion",
1955
+ "input",
1956
+ "output",
1957
+ "inputPreview",
1958
+ "outputPreview",
1959
+ "message",
1960
+ "messages",
1961
+ "transcript",
1962
+ "context",
1963
+ "document",
1964
+ "documents",
1965
+ "chunk",
1966
+ "chunks",
1967
+ "retrieval",
1968
+ "query"
1969
+ ];
1970
+ function resolveRedactionProfile(profile = "local") {
1971
+ switch (profile) {
1972
+ case "local":
1973
+ return { profile: "local", extraKeys: [] };
1974
+ case "share":
1975
+ return {
1976
+ profile: "share",
1977
+ extraKeys: SHARE_PROFILE_EXTRA_KEYS,
1978
+ maxMetadataValueLengthCap: 500,
1979
+ maxPreviewLengthCap: 200
1980
+ };
1981
+ case "strict":
1982
+ return {
1983
+ profile: "strict",
1984
+ extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],
1985
+ maxMetadataValueLengthCap: 200,
1986
+ maxPreviewLengthCap: 80
1987
+ };
1988
+ default:
1989
+ return { profile: "local", extraKeys: [] };
1990
+ }
1991
+ }
1992
+ function isPreviewKey(key) {
1993
+ return key.toLowerCase().includes("preview");
1994
+ }
1995
+ function applyProfileMetadataCaps(maxMetadataValueLength, maxPreviewLength, resolved) {
1996
+ let meta = maxMetadataValueLength;
1997
+ let preview = maxPreviewLength;
1998
+ if (resolved.maxMetadataValueLengthCap !== void 0) {
1999
+ meta = Math.min(meta, resolved.maxMetadataValueLengthCap);
2000
+ }
2001
+ if (resolved.maxPreviewLengthCap !== void 0) {
2002
+ preview = Math.min(preview, resolved.maxPreviewLengthCap);
2003
+ }
2004
+ return { maxMetadataValueLength: meta, maxPreviewLength: preview };
2005
+ }
2006
+ function truncateStringForProfile(value, key, maxMetadataValueLength, maxPreviewLength) {
2007
+ const max = isPreviewKey(key) ? maxPreviewLength : maxMetadataValueLength;
2008
+ if (max <= 0) return "\u2026";
2009
+ if (value.length <= max) return value;
2010
+ return `${value.slice(0, max)}\u2026`;
2011
+ }
1872
2012
  function isRecord7(value) {
1873
2013
  return typeof value === "object" && value !== null && !Array.isArray(value);
1874
2014
  }
@@ -2072,7 +2212,7 @@ var DEFAULT_MAX_EVENT_BYTES = 65536;
2072
2212
  function isRecord8(value) {
2073
2213
  return typeof value === "object" && value !== null && !Array.isArray(value);
2074
2214
  }
2075
- function isPreviewKey(key) {
2215
+ function isPreviewKey2(key) {
2076
2216
  return key.toLowerCase().includes("preview");
2077
2217
  }
2078
2218
  function truncateString(value, maxLen) {
@@ -2095,11 +2235,28 @@ function resolveTraceSafetyOptions(options) {
2095
2235
  redactEnabled = true;
2096
2236
  redactionRules = redact.rules;
2097
2237
  }
2238
+ const profile = options?.redactionProfile ?? "local";
2239
+ const resolvedProfile = resolveRedactionProfile(profile);
2240
+ const userMaxMetadata = typeof options?.maxMetadataValueLength === "number" && Number.isFinite(options.maxMetadataValueLength) && options.maxMetadataValueLength >= 0 ? Math.floor(options.maxMetadataValueLength) : void 0;
2241
+ const userMaxPreview = typeof options?.maxPreviewLength === "number" && Number.isFinite(options.maxPreviewLength) && options.maxPreviewLength >= 0 ? Math.floor(options.maxPreviewLength) : void 0;
2242
+ let maxMetadataValueLength = userMaxMetadata ?? DEFAULT_MAX_METADATA_VALUE_LENGTH;
2243
+ let maxPreviewLength = userMaxPreview ?? DEFAULT_MAX_PREVIEW_LENGTH;
2244
+ if (redactEnabled && profile !== "local") {
2245
+ const capped = applyProfileMetadataCaps(
2246
+ maxMetadataValueLength,
2247
+ maxPreviewLength,
2248
+ resolvedProfile
2249
+ );
2250
+ maxMetadataValueLength = capped.maxMetadataValueLength;
2251
+ maxPreviewLength = capped.maxPreviewLength;
2252
+ }
2098
2253
  return {
2099
2254
  redactEnabled,
2100
2255
  redactionRules,
2101
- maxMetadataValueLength: typeof options?.maxMetadataValueLength === "number" && Number.isFinite(options.maxMetadataValueLength) && options.maxMetadataValueLength >= 0 ? Math.floor(options.maxMetadataValueLength) : DEFAULT_MAX_METADATA_VALUE_LENGTH,
2102
- maxPreviewLength: typeof options?.maxPreviewLength === "number" && Number.isFinite(options.maxPreviewLength) && options.maxPreviewLength >= 0 ? Math.floor(options.maxPreviewLength) : DEFAULT_MAX_PREVIEW_LENGTH,
2256
+ redactionProfile: profile,
2257
+ profileExtraKeys: redactEnabled ? resolvedProfile.extraKeys : [],
2258
+ maxMetadataValueLength,
2259
+ maxPreviewLength,
2103
2260
  maxEventBytes: typeof options?.maxEventBytes === "number" && Number.isFinite(options.maxEventBytes) && options.maxEventBytes > 0 ? Math.floor(options.maxEventBytes) : DEFAULT_MAX_EVENT_BYTES
2104
2261
  };
2105
2262
  }
@@ -2107,7 +2264,7 @@ function boundMetadataValue(key, value, opts, seen, depth) {
2107
2264
  if (depth > 32) return "[MaxDepth]";
2108
2265
  if (value === null || typeof value !== "object") {
2109
2266
  if (typeof value === "string") {
2110
- const max = isPreviewKey(key) ? opts.maxPreviewLength : opts.maxMetadataValueLength;
2267
+ const max = isPreviewKey2(key) ? opts.maxPreviewLength : opts.maxMetadataValueLength;
2111
2268
  return truncateString(value, max);
2112
2269
  }
2113
2270
  return value;
@@ -2133,7 +2290,10 @@ function boundMetadataValue(key, value, opts, seen, depth) {
2133
2290
  }
2134
2291
  function redactMetadata(metadata, opts) {
2135
2292
  if (!opts.redactEnabled) return { ...metadata };
2136
- const redactor = new Redactor({ rules: opts.redactionRules });
2293
+ const redactor = new Redactor({
2294
+ rules: opts.redactionRules,
2295
+ extraKeys: opts.profileExtraKeys
2296
+ });
2137
2297
  return redactor.redactRecord(metadata);
2138
2298
  }
2139
2299
  function prepareMetadataForDisk(metadata, opts) {
@@ -2305,6 +2465,13 @@ function getCurrentRunId() {
2305
2465
  return void 0;
2306
2466
  }
2307
2467
  }
2468
+ function getCurrentCorrelationMetadata() {
2469
+ try {
2470
+ return extractCorrelationMetadata(storage.getStore()?.metadata);
2471
+ } catch {
2472
+ return void 0;
2473
+ }
2474
+ }
2308
2475
  function getCurrentRunName() {
2309
2476
  try {
2310
2477
  return storage.getStore()?.runName;
@@ -3948,12 +4115,13 @@ async function inspectRun(name, fn, options) {
3948
4115
  const runId = createRunId();
3949
4116
  const traceDir = resolveTraceDir({ dir: options?.traceDir });
3950
4117
  const traceSafety = resolveTraceSafetyOptions(options);
4118
+ const runMetadata = buildRunStartedMetadata(options);
3951
4119
  const context = {
3952
4120
  runId,
3953
4121
  runName,
3954
4122
  traceDir,
3955
4123
  silent: options?.silent ?? false,
3956
- metadata: options?.metadata
4124
+ metadata: runMetadata
3957
4125
  };
3958
4126
  return runWithContext(context, async () => {
3959
4127
  const startTime = Date.now();
@@ -3969,7 +4137,7 @@ async function inspectRun(name, fn, options) {
3969
4137
  runId,
3970
4138
  name: runName,
3971
4139
  startTime,
3972
- ...options?.metadata !== void 0 ? { metadata: options.metadata } : {}
4140
+ ...runMetadata !== void 0 ? { metadata: runMetadata } : {}
3973
4141
  };
3974
4142
  await writeTraceEvent(
3975
4143
  prepareTraceEventForDisk(started, traceSafety),
@@ -4254,6 +4422,134 @@ function observe(agent, options) {
4254
4422
  // packages/core/src/exporters/types.ts
4255
4423
  var EXPORT_PAYLOAD_VERSION = "0.1.2";
4256
4424
 
4425
+ // packages/core/src/exporters/redact-export.ts
4426
+ function isRecord10(value) {
4427
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4428
+ }
4429
+ function deepClone(value) {
4430
+ if (value === null || typeof value !== "object") {
4431
+ return value;
4432
+ }
4433
+ if (Array.isArray(value)) {
4434
+ return value.map((item) => deepClone(item));
4435
+ }
4436
+ const out = {};
4437
+ for (const [k, v] of Object.entries(value)) {
4438
+ out[k] = deepClone(v);
4439
+ }
4440
+ return out;
4441
+ }
4442
+ function boundAttributeValues(record, maxMetadataValueLength, maxPreviewLength, seen, depth) {
4443
+ if (depth > 32) {
4444
+ return { truncated: true, reason: "maxDepth" };
4445
+ }
4446
+ const out = {};
4447
+ for (const [key, value] of Object.entries(record)) {
4448
+ out[key] = boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth);
4449
+ }
4450
+ return out;
4451
+ }
4452
+ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth) {
4453
+ if (value === null || typeof value !== "object") {
4454
+ if (typeof value === "string") {
4455
+ return truncateStringForProfile(
4456
+ value,
4457
+ key,
4458
+ maxMetadataValueLength,
4459
+ maxPreviewLength
4460
+ );
4461
+ }
4462
+ return value;
4463
+ }
4464
+ if (seen.has(value)) return "[Circular]";
4465
+ seen.add(value);
4466
+ if (Array.isArray(value)) {
4467
+ return value.slice(0, 50).map(
4468
+ (item, index) => boundValue(
4469
+ item,
4470
+ String(index),
4471
+ maxMetadataValueLength,
4472
+ maxPreviewLength,
4473
+ seen,
4474
+ depth + 1
4475
+ )
4476
+ );
4477
+ }
4478
+ return boundAttributeValues(
4479
+ value,
4480
+ maxMetadataValueLength,
4481
+ maxPreviewLength,
4482
+ seen,
4483
+ depth + 1
4484
+ );
4485
+ }
4486
+ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPreviewLength) {
4487
+ if (!attrs || Object.keys(attrs).length === 0) {
4488
+ return attrs;
4489
+ }
4490
+ const redacted = redactor.redactRecord(attrs);
4491
+ const seen = /* @__PURE__ */ new WeakSet();
4492
+ const bounded = boundAttributeValues(
4493
+ redacted,
4494
+ maxMetadataValueLength,
4495
+ maxPreviewLength,
4496
+ seen,
4497
+ 0
4498
+ );
4499
+ const err = bounded.error;
4500
+ if (isRecord10(err) && typeof err.message === "string") {
4501
+ bounded.error = {
4502
+ ...err,
4503
+ message: truncateStringForProfile(
4504
+ err.message,
4505
+ "message",
4506
+ maxMetadataValueLength,
4507
+ maxPreviewLength
4508
+ ),
4509
+ ...typeof err.stack === "string" ? {
4510
+ stack: truncateStringForProfile(
4511
+ err.stack,
4512
+ "stack",
4513
+ maxMetadataValueLength,
4514
+ maxPreviewLength
4515
+ )
4516
+ } : {}
4517
+ };
4518
+ }
4519
+ return bounded;
4520
+ }
4521
+ function redactRunTreeForExport(tree, options) {
4522
+ const profile = options?.redactionProfile ?? "local";
4523
+ if (profile === "local") {
4524
+ return deepClone(tree);
4525
+ }
4526
+ const resolved = resolveRedactionProfile(profile);
4527
+ const { maxMetadataValueLength, maxPreviewLength } = applyProfileMetadataCaps(
4528
+ 2e3,
4529
+ 500,
4530
+ resolved
4531
+ );
4532
+ const redactor = new Redactor({ extraKeys: resolved.extraKeys });
4533
+ const clone = deepClone(tree);
4534
+ function walk(nodes) {
4535
+ for (const node of nodes) {
4536
+ if (node.event.attributes !== void 0) {
4537
+ node.event.attributes = redactEventAttributes(
4538
+ node.event.attributes,
4539
+ redactor,
4540
+ maxMetadataValueLength,
4541
+ maxPreviewLength
4542
+ );
4543
+ }
4544
+ if (node.children.length > 0) {
4545
+ walk(node.children);
4546
+ }
4547
+ }
4548
+ }
4549
+ walk(clone.children);
4550
+ return clone;
4551
+ }
4552
+
4257
4553
  // packages/core/src/exporters/html-exporter.ts
4258
4554
  function renderTreeHtml(nodes, ulClass = "tree") {
4259
4555
  if (nodes.length === 0) return "";
@@ -4990,20 +5286,22 @@ function mergeExportDefaults(options) {
4990
5286
  includeErrors: options.includeErrors ?? true,
4991
5287
  pretty: options.pretty ?? true,
4992
5288
  redacted: options.redacted ?? true,
4993
- maxAttributeLength: options.maxAttributeLength ?? 500
5289
+ maxAttributeLength: options.maxAttributeLength ?? 500,
5290
+ redactionProfile: options.redactionProfile ?? "local"
4994
5291
  };
4995
5292
  }
4996
5293
  function exportRunTree(tree, options) {
4997
5294
  const opts = mergeExportDefaults(options);
5295
+ const exportTree = opts.redactionProfile === "local" ? tree : redactRunTreeForExport(tree, { redactionProfile: opts.redactionProfile });
4998
5296
  switch (opts.format) {
4999
5297
  case "markdown":
5000
- return exportMarkdown(tree, opts);
5298
+ return exportMarkdown(exportTree, opts);
5001
5299
  case "html":
5002
- return exportHtml(tree, opts);
5300
+ return exportHtml(exportTree, opts);
5003
5301
  case "openinference":
5004
- return exportOpenInference(tree, opts);
5302
+ return exportOpenInference(exportTree, opts);
5005
5303
  case "otlp-json":
5006
- return exportOtlpJson(tree, opts);
5304
+ return exportOtlpJson(exportTree, opts);
5007
5305
  default: {
5008
5306
  const _x = opts.format;
5009
5307
  throw new Error(`Unsupported export format: ${String(_x)}`);
@@ -5062,6 +5360,7 @@ exports.formatError = formatError;
5062
5360
  exports.formatTerminalName = formatTerminalName;
5063
5361
  exports.formatTimestamp = formatTimestamp;
5064
5362
  exports.getCurrentContext = getCurrentContext;
5363
+ exports.getCurrentCorrelationMetadata = getCurrentCorrelationMetadata;
5065
5364
  exports.getCurrentDepth = getCurrentDepth;
5066
5365
  exports.getCurrentRunId = getCurrentRunId;
5067
5366
  exports.getCurrentRunName = getCurrentRunName;
@@ -5110,12 +5409,14 @@ exports.printStepComplete = printStepComplete;
5110
5409
  exports.printStepStart = printStepStart;
5111
5410
  exports.readTraceEvents = readTraceEvents;
5112
5411
  exports.readTraceFile = readTraceFile;
5412
+ exports.redactRunTreeForExport = redactRunTreeForExport;
5113
5413
  exports.renderErrorLine = renderErrorLine;
5114
5414
  exports.renderRunDiff = renderRunDiff;
5115
5415
  exports.renderRunSummary = renderRunSummary;
5116
5416
  exports.renderRunTree = renderRunTree;
5117
5417
  exports.renderRunTrees = renderRunTrees;
5118
5418
  exports.renderStepLine = renderStepLine;
5419
+ exports.resolveRedactionProfile = resolveRedactionProfile;
5119
5420
  exports.resolveTraceDir = resolveTraceDir;
5120
5421
  exports.resolveTraceSafetyOptions = resolveTraceSafetyOptions;
5121
5422
  exports.runWithContext = runWithContext;