agent-inspect 6.31.21 → 6.31.23

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-P27XTK5U.mjs} +347 -36
  5. package/packages/cli/dist/chunk-P27XTK5U.mjs.map +1 -0
  6. package/packages/cli/dist/index.cjs +434 -63
  7. package/packages/cli/dist/index.cjs.map +1 -1
  8. package/packages/cli/dist/index.mjs +81 -33
  9. package/packages/cli/dist/index.mjs.map +1 -1
  10. package/packages/cli/dist/{src-VMGRSTG7.mjs → src-EWZYLDST.mjs} +3 -3
  11. package/packages/cli/dist/{src-VMGRSTG7.mjs.map → src-EWZYLDST.mjs.map} +1 -1
  12. package/packages/core/dist/advanced.cjs +280 -10
  13. package/packages/core/dist/advanced.cjs.map +1 -1
  14. package/packages/core/dist/advanced.mjs +6 -5
  15. package/packages/core/dist/advanced.mjs.map +1 -1
  16. package/packages/core/dist/checks.cjs +185 -27
  17. package/packages/core/dist/checks.cjs.map +1 -1
  18. package/packages/core/dist/checks.mjs +2 -1
  19. package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-77PUPLPG.mjs} +14 -8
  20. package/packages/core/dist/chunk-77PUPLPG.mjs.map +1 -0
  21. package/packages/core/dist/chunk-AN5MOADW.mjs +204 -0
  22. package/packages/core/dist/chunk-AN5MOADW.mjs.map +1 -0
  23. package/packages/core/dist/{chunk-4CDX5GDS.mjs → chunk-IMCM42W6.mjs} +110 -99
  24. package/packages/core/dist/chunk-IMCM42W6.mjs.map +1 -0
  25. package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-J2ST4VCX.mjs} +45 -3
  26. package/packages/core/dist/chunk-J2ST4VCX.mjs.map +1 -0
  27. package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-JJSL346L.mjs} +58 -3
  28. package/packages/core/dist/chunk-JJSL346L.mjs.map +1 -0
  29. package/packages/core/dist/exporters.cjs +91 -29
  30. package/packages/core/dist/exporters.cjs.map +1 -1
  31. package/packages/core/dist/exporters.mjs +78 -29
  32. package/packages/core/dist/exporters.mjs.map +1 -1
  33. package/packages/core/dist/logs.cjs +206 -1
  34. package/packages/core/dist/logs.cjs.map +1 -1
  35. package/packages/core/dist/logs.mjs +3 -2
  36. package/packages/core/dist/logs.mjs.map +1 -1
  37. package/packages/core/dist/persisted.cjs +226 -8
  38. package/packages/core/dist/persisted.cjs.map +1 -1
  39. package/packages/core/dist/persisted.mjs +9 -5
  40. package/packages/core/dist/persisted.mjs.map +1 -1
  41. package/packages/core/dist/readers.cjs +276 -6
  42. package/packages/core/dist/readers.cjs.map +1 -1
  43. package/packages/core/dist/readers.mjs +4 -3
  44. package/packages/cli/dist/chunk-N5JN26MW.mjs.map +0 -1
  45. package/packages/core/dist/chunk-4CDX5GDS.mjs.map +0 -1
  46. package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
  47. package/packages/core/dist/chunk-JE3TUFAQ.mjs.map +0 -1
  48. package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
@@ -2,6 +2,7 @@ import { OBSERVED_OUTCOME_METHODS, extractOutcomesFromPersistedEvents, outcomesM
2
2
  import { DEFAULT_CREDENTIAL_SENSITIVE_KEYS, isCredentialSensitiveKey } from './chunk-VLVCLAPB.mjs';
3
3
  import { projectLogicalEvents, resolveCanonicalToolName } from './chunk-AHUZNHFI.mjs';
4
4
  import { formatProgrammaticDiagnostic } from './chunk-S6LQBLX5.mjs';
5
+ import { canonicalStructuredEqual, hasDeliveryConflictMarker, deliverySemanticFingerprint, identityConflictFieldsFromAttributes, encodeCanonicalStructured } from './chunk-AN5MOADW.mjs';
5
6
  import { isAttributionConfidence, ATTRIBUTION_CONFIDENCES, ATTRIBUTION_CONFIDENCE_RANK } from './chunk-EE5Z2GQ3.mjs';
6
7
 
7
8
  // packages/core/src/sessions/metadata.ts
@@ -976,76 +977,6 @@ function evaluateControlRules(events, rules, runEvidence2, observationNames) {
976
977
  return findings;
977
978
  }
978
979
 
979
- // packages/core/src/checks/canonical-equality.ts
980
- var DEFAULT_MAX_DEPTH = 8;
981
- var DEFAULT_MAX_BYTES = 16384;
982
- function sortKeysDeep(input, depth, maxDepth) {
983
- if (depth > maxDepth) {
984
- throw new Error("AI_CHECK_CANONICAL_DEPTH_EXCEEDED");
985
- }
986
- if (input === null || typeof input !== "object") return input;
987
- if (Array.isArray(input)) {
988
- return input.map((item) => sortKeysDeep(item, depth + 1, maxDepth));
989
- }
990
- const record = input;
991
- const out = {};
992
- for (const key of Object.keys(record).sort()) {
993
- out[key] = sortKeysDeep(record[key], depth + 1, maxDepth);
994
- }
995
- return out;
996
- }
997
- function encodeCanonicalStructured(value, limits) {
998
- const maxDepth = DEFAULT_MAX_DEPTH;
999
- const maxBytes = DEFAULT_MAX_BYTES;
1000
- try {
1001
- const sorted = sortKeysDeep(value, 0, maxDepth);
1002
- const encoded = JSON.stringify(sorted);
1003
- if (encoded === void 0) {
1004
- return {
1005
- ok: false,
1006
- reason: "Value is not JSON-serializable for canonical comparison.",
1007
- code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
1008
- };
1009
- }
1010
- if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
1011
- return {
1012
- ok: false,
1013
- reason: "Canonical structured value exceeds bounded size limit.",
1014
- code: "AI_CHECK_CANONICAL_SIZE_EXCEEDED"
1015
- };
1016
- }
1017
- return { ok: true, value: encoded };
1018
- } catch (error) {
1019
- const message = error instanceof Error ? error.message : String(error);
1020
- if (message === "AI_CHECK_CANONICAL_DEPTH_EXCEEDED") {
1021
- return {
1022
- ok: false,
1023
- reason: "Canonical structured value exceeds bounded depth limit.",
1024
- code: "AI_CHECK_CANONICAL_DEPTH_EXCEEDED"
1025
- };
1026
- }
1027
- return {
1028
- ok: false,
1029
- reason: "Canonical structured encoding failed.",
1030
- code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
1031
- };
1032
- }
1033
- }
1034
- function canonicalStructuredEqual(left, right, limits) {
1035
- const a = encodeCanonicalStructured(left);
1036
- if (!a.ok) return { equal: false, reason: a.reason, code: a.code };
1037
- const b = encodeCanonicalStructured(right);
1038
- if (!b.ok) return { equal: false, reason: b.reason, code: b.code };
1039
- if (a.value !== b.value) {
1040
- return {
1041
- equal: false,
1042
- reason: "Canonical structured values differ.",
1043
- code: "AI_CHECK_CANONICAL_NOT_EQUAL"
1044
- };
1045
- }
1046
- return { equal: true };
1047
- }
1048
-
1049
980
  // packages/core/src/checks/tool-arguments.ts
1050
981
  function decodeToken(token) {
1051
982
  return token.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -1241,7 +1172,7 @@ function attemptIdOf(event) {
1241
1172
  }
1242
1173
  function countOperationAttempts(members) {
1243
1174
  const identified = /* @__PURE__ */ new Set();
1244
- let unidentified = 0;
1175
+ const unidentifiedFingerprints = /* @__PURE__ */ new Set();
1245
1176
  for (const event of members) {
1246
1177
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1247
1178
  const id = attemptIdOf(event);
@@ -1249,13 +1180,13 @@ function countOperationAttempts(members) {
1249
1180
  identified.add(id);
1250
1181
  continue;
1251
1182
  }
1252
- unidentified += 1;
1183
+ unidentifiedFingerprints.add(redeliveryFingerprint(event));
1253
1184
  }
1254
1185
  if (identified.size > 0) {
1255
- return identified.size + unidentified;
1186
+ return identified.size + unidentifiedFingerprints.size;
1256
1187
  }
1257
1188
  const numbered = /* @__PURE__ */ new Set();
1258
- let unnumbered = 0;
1189
+ const unnumberedFingerprints = /* @__PURE__ */ new Set();
1259
1190
  for (const event of members) {
1260
1191
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1261
1192
  const num = attemptNumberOf(event);
@@ -1263,12 +1194,12 @@ function countOperationAttempts(members) {
1263
1194
  numbered.add(num);
1264
1195
  continue;
1265
1196
  }
1266
- unnumbered += 1;
1197
+ unnumberedFingerprints.add(redeliveryFingerprint(event));
1267
1198
  }
1268
1199
  if (numbered.size > 0) {
1269
- return numbered.size + unnumbered;
1200
+ return numbered.size + unnumberedFingerprints.size;
1270
1201
  }
1271
- return unnumbered;
1202
+ return unnumberedFingerprints.size;
1272
1203
  }
1273
1204
  function classifyRetryAttempt(event, priorOrdered, allMembers) {
1274
1205
  const workflow = workflowFor(event);
@@ -1320,19 +1251,55 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
1320
1251
  }
1321
1252
  function redeliveryFingerprint(event) {
1322
1253
  const workflow = workflowFor(event);
1323
- const stableEventId = (event.eventId ?? "").replace(/:\d+$/, "");
1324
- return JSON.stringify({
1325
- stableEventId,
1254
+ return deliverySemanticFingerprint({
1255
+ eventId: event.eventId ?? "",
1326
1256
  runId: event.runId,
1327
1257
  kind: event.kind,
1328
1258
  name: event.name,
1329
1259
  status: event.status,
1260
+ parentId: event.parentId,
1261
+ timestamp: event.timestamp,
1262
+ startedAt: event.startedAt,
1263
+ sourceType: event.source?.type,
1264
+ attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
1330
1265
  operationId: workflow.operationId ?? null,
1331
1266
  attemptId: workflow.attemptId ?? null,
1332
1267
  attemptNumber: workflow.attemptNumber ?? null,
1333
1268
  retryOf: workflow.retryOf ?? null
1334
1269
  });
1335
1270
  }
1271
+ var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
1272
+ function identityValuesEqual(a, b) {
1273
+ if (typeof a === "number" && typeof b === "number") {
1274
+ return Number.isFinite(a) && Number.isFinite(b) && a === b;
1275
+ }
1276
+ if (typeof a === "string" && typeof b === "string") {
1277
+ return a.trim() === b.trim();
1278
+ }
1279
+ return a === b;
1280
+ }
1281
+ function directNestedIdentityConflicts(event) {
1282
+ const attrs2 = event.attributes;
1283
+ if (!attrs2 || typeof attrs2 !== "object") return [];
1284
+ const nested = attrs2.metadata && typeof attrs2.metadata === "object" && !Array.isArray(attrs2.metadata) ? attrs2.metadata : void 0;
1285
+ const conflicts = [];
1286
+ if (nested) {
1287
+ for (const key of IDENTITY_KEYS) {
1288
+ const direct = attrs2[key];
1289
+ const nestedValue = nested[key];
1290
+ if (direct === void 0 || nestedValue === void 0) continue;
1291
+ if (!identityValuesEqual(direct, nestedValue)) {
1292
+ conflicts.push(key);
1293
+ }
1294
+ }
1295
+ }
1296
+ for (const key of identityConflictFieldsFromAttributes(attrs2)) {
1297
+ if (IDENTITY_KEYS.includes(key) && !conflicts.includes(key)) {
1298
+ conflicts.push(key);
1299
+ }
1300
+ }
1301
+ return conflicts;
1302
+ }
1336
1303
  function hasConflictingAttemptIdReuse(members) {
1337
1304
  const byAttempt = /* @__PURE__ */ new Map();
1338
1305
  for (const event of members) {
@@ -1348,6 +1315,31 @@ function hasConflictingAttemptIdReuse(members) {
1348
1315
  }
1349
1316
  return false;
1350
1317
  }
1318
+ function hasConflictingEventIdReuse(members) {
1319
+ const byEventId = /* @__PURE__ */ new Map();
1320
+ for (const event of members) {
1321
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1322
+ const eventId = event.eventId;
1323
+ if (!eventId) continue;
1324
+ if (hasDeliveryConflictMarker(event.attributes)) {
1325
+ return true;
1326
+ }
1327
+ const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
1328
+ fingerprints.add(redeliveryFingerprint(event));
1329
+ byEventId.set(eventId, fingerprints);
1330
+ }
1331
+ for (const fingerprints of byEventId.values()) {
1332
+ if (fingerprints.size > 1) return true;
1333
+ }
1334
+ return false;
1335
+ }
1336
+ function hasIdentityRepresentationConflict(members) {
1337
+ for (const event of members) {
1338
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1339
+ if (directNestedIdentityConflicts(event).length > 0) return true;
1340
+ }
1341
+ return false;
1342
+ }
1351
1343
  function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1352
1344
  const findings = [];
1353
1345
  const byOperation = /* @__PURE__ */ new Map();
@@ -1355,13 +1347,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1355
1347
  const workflow = workflowFor(event);
1356
1348
  const operationId = workflow.operationId;
1357
1349
  if (!operationId) continue;
1358
- const list = byOperation.get(operationId) ?? [];
1359
- list.push(event);
1360
- byOperation.set(operationId, list);
1350
+ const key = `${event.runId}\0${operationId}`;
1351
+ const group = byOperation.get(key) ?? { operationId, members: [] };
1352
+ group.members.push(event);
1353
+ byOperation.set(key, group);
1361
1354
  }
1362
1355
  if (rules.maxAttempts !== void 0) {
1363
- for (const [operationId, members] of byOperation) {
1364
- if (hasConflictingAttemptIdReuse(members)) {
1356
+ for (const { operationId, members } of byOperation.values()) {
1357
+ if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
1365
1358
  findings.push(
1366
1359
  fail2(
1367
1360
  "contract.retry.duplicate-attempt-id",
@@ -1372,6 +1365,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1372
1365
  )
1373
1366
  );
1374
1367
  }
1368
+ if (hasIdentityRepresentationConflict(members)) {
1369
+ findings.push(
1370
+ fail2(
1371
+ "contract.retry.ambiguous-identity",
1372
+ `Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
1373
+ members.slice(0, 4).map(eventEvidence),
1374
+ "agreeing identity representation",
1375
+ "direct/nested conflict"
1376
+ )
1377
+ );
1378
+ }
1379
+ const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
1380
+ const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
1381
+ const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
1382
+ if (hasAttemptId && missingAttemptId) {
1383
+ findings.push(
1384
+ fail2(
1385
+ "contract.retry.ambiguous-identity",
1386
+ `Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
1387
+ members.slice(0, 4).map(eventEvidence),
1388
+ "complete attempt identity",
1389
+ "partial attemptId coverage"
1390
+ )
1391
+ );
1392
+ }
1375
1393
  const count = countOperationAttempts(members);
1376
1394
  if (count > rules.maxAttempts) {
1377
1395
  findings.push(
@@ -1387,7 +1405,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1387
1405
  }
1388
1406
  }
1389
1407
  if (rules.requireTerminalResult) {
1390
- for (const [operationId, members] of byOperation) {
1408
+ for (const { operationId, members } of byOperation.values()) {
1391
1409
  const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
1392
1410
  if (!hasTerminal) {
1393
1411
  findings.push(
@@ -1407,7 +1425,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1407
1425
  const workflow = workflowFor(event);
1408
1426
  const fallbackOf = workflow.fallbackOf;
1409
1427
  if (!fallbackOf) continue;
1410
- const prior = byOperation.get(fallbackOf) ?? [];
1428
+ const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
1411
1429
  const fallbackStart = eventTime(event);
1412
1430
  const earlierFailure = prior.some(
1413
1431
  (candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
@@ -1434,7 +1452,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1434
1452
  for (const event of toolEvents) {
1435
1453
  const name = resolveCanonicalToolName(event);
1436
1454
  const workflow = workflowFor(event);
1437
- const key = `${workflow.operationId ?? name}::${name}`;
1455
+ const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
1438
1456
  const list = byToolOp.get(key) ?? [];
1439
1457
  list.push(event);
1440
1458
  byToolOp.set(key, list);
@@ -1492,7 +1510,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1492
1510
  }
1493
1511
  }
1494
1512
  if (rules.requireRecoveredFailureVisible) {
1495
- for (const [operationId, members] of byOperation) {
1513
+ for (const { operationId, members } of byOperation.values()) {
1496
1514
  const ordered = sortByTime(members);
1497
1515
  const toolish = ordered.filter(
1498
1516
  (event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
@@ -1751,14 +1769,7 @@ function attemptIdOf2(event) {
1751
1769
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
1752
1770
  }
1753
1771
  function hasDuplicateAttemptIds(members) {
1754
- const seen = /* @__PURE__ */ new Set();
1755
- for (const event of members) {
1756
- const id = attemptIdOf2(event);
1757
- if (!id) continue;
1758
- if (seen.has(id)) return true;
1759
- seen.add(id);
1760
- }
1761
- return false;
1772
+ return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
1762
1773
  }
1763
1774
  function findRetryTarget(members, retryOf) {
1764
1775
  return members.find(
@@ -5338,5 +5349,5 @@ function runTraceChecks(input, options = {}) {
5338
5349
  }
5339
5350
 
5340
5351
  export { buildTraceFacts, createBaselineRegressionRule, createDecisionRule, createGuardrailRule, createLlmUsageRule, createMaxStepDurationRule, createObservedOutcomeRule, createRequireCompletedRule, createRetrievalRule, createRunDepthRule, createRunDurationRule, createRunEventCountRule, createRunStatusRule, createSafetyOversizedAttributeRule, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createStallDetectionRule, createStepOrderingRule, createStructureCycleRule, createStructureIncompleteRule, createStructureOrphanRule, createStructureParallelWidthRule, createStructureRelationshipRule, createToolFailureRule, createToolOrderingRule, createToolUsageRule, defineTraceContract, deriveFailureFacts, deriveRelationshipFacts, evaluateToolArgumentValue, evaluateTraceContract, evaluateTraceContractRead, explainTraceContract, extractSessionWorkflowMetadata, extractToolArgumentPayload, lintTraceContract, resolveJsonPointer, resolveTraceContractScope, runTraceChecks, sessionKeyForRun, summarizeSemanticParity, workflowMetadataForRun };
5341
- //# sourceMappingURL=chunk-4CDX5GDS.mjs.map
5342
- //# sourceMappingURL=chunk-4CDX5GDS.mjs.map
5352
+ //# sourceMappingURL=chunk-IMCM42W6.mjs.map
5353
+ //# sourceMappingURL=chunk-IMCM42W6.mjs.map