agent-inspect 6.31.20 → 6.31.22
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-EVSIYDB2.mjs → chunk-EMWA5EKU.mjs} +324 -35
- package/packages/cli/dist/chunk-EMWA5EKU.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +403 -60
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +75 -31
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-NWDDK72G.mjs → src-VZHGOLTO.mjs} +3 -3
- package/packages/cli/dist/{src-NWDDK72G.mjs.map → src-VZHGOLTO.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +247 -5
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +6 -5
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +184 -31
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +2 -1
- package/packages/core/dist/chunk-GCZUWY47.mjs +182 -0
- package/packages/core/dist/chunk-GCZUWY47.mjs.map +1 -0
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-RBXD7BNX.mjs} +3 -3
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs.map → chunk-RBXD7BNX.mjs.map} +1 -1
- package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-S4NU55LU.mjs} +45 -3
- package/packages/core/dist/chunk-S4NU55LU.mjs.map +1 -0
- package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-UPGBMRL4.mjs} +49 -3
- package/packages/core/dist/chunk-UPGBMRL4.mjs.map +1 -0
- package/packages/core/dist/{chunk-GFQPPNSF.mjs → chunk-ZOF6ON65.mjs} +128 -103
- package/packages/core/dist/chunk-ZOF6ON65.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +82 -27
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +72 -27
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/logs.cjs +197 -1
- package/packages/core/dist/logs.cjs.map +1 -1
- package/packages/core/dist/logs.mjs +3 -2
- package/packages/core/dist/logs.mjs.map +1 -1
- package/packages/core/dist/persisted.cjs +197 -1
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +4 -3
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +243 -1
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +4 -3
- package/packages/cli/dist/chunk-EVSIYDB2.mjs.map +0 -1
- package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
- package/packages/core/dist/chunk-GFQPPNSF.mjs.map +0 -1
- package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
|
@@ -8114,6 +8114,121 @@ var init_tool_arguments = __esm({
|
|
|
8114
8114
|
}
|
|
8115
8115
|
});
|
|
8116
8116
|
|
|
8117
|
+
// packages/core/src/persisted/delivery-identity.ts
|
|
8118
|
+
function stripReaderDeliveryDiscriminator(eventId) {
|
|
8119
|
+
if (!SYNTHETIC_DELIVERY_ID.test(eventId)) return eventId;
|
|
8120
|
+
return eventId.replace(/:\d+$/, "");
|
|
8121
|
+
}
|
|
8122
|
+
function canonicalDigest(value) {
|
|
8123
|
+
if (value === void 0) return null;
|
|
8124
|
+
const encoded = encodeCanonicalStructured(value);
|
|
8125
|
+
return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
|
|
8126
|
+
}
|
|
8127
|
+
function capturedContentDigest(attributes) {
|
|
8128
|
+
if (!attributes || typeof attributes !== "object") {
|
|
8129
|
+
return { args: null, result: null };
|
|
8130
|
+
}
|
|
8131
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
|
|
8132
|
+
const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
|
|
8133
|
+
const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
|
|
8134
|
+
return {
|
|
8135
|
+
args: args === void 0 ? null : canonicalDigest(args),
|
|
8136
|
+
result: result === void 0 ? null : canonicalDigest(result)
|
|
8137
|
+
};
|
|
8138
|
+
}
|
|
8139
|
+
function timeKey(fields) {
|
|
8140
|
+
if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
|
|
8141
|
+
return fields.startedAt;
|
|
8142
|
+
}
|
|
8143
|
+
if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
|
|
8144
|
+
return fields.timestamp;
|
|
8145
|
+
}
|
|
8146
|
+
if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
|
|
8147
|
+
return String(fields.timestamp);
|
|
8148
|
+
}
|
|
8149
|
+
return null;
|
|
8150
|
+
}
|
|
8151
|
+
function deliverySemanticFingerprint(fields) {
|
|
8152
|
+
const content = capturedContentDigest(fields.attributes);
|
|
8153
|
+
return JSON.stringify({
|
|
8154
|
+
stableEventId: stripReaderDeliveryDiscriminator(fields.eventId),
|
|
8155
|
+
runId: fields.runId,
|
|
8156
|
+
kind: fields.kind,
|
|
8157
|
+
name: fields.name,
|
|
8158
|
+
status: fields.status ?? null,
|
|
8159
|
+
parentId: fields.parentId ?? null,
|
|
8160
|
+
sourceType: fields.sourceType ?? null,
|
|
8161
|
+
time: timeKey(fields),
|
|
8162
|
+
operationId: fields.operationId ?? null,
|
|
8163
|
+
attemptId: fields.attemptId ?? null,
|
|
8164
|
+
attemptNumber: fields.attemptNumber ?? null,
|
|
8165
|
+
retryOf: fields.retryOf ?? null,
|
|
8166
|
+
argsDigest: content.args,
|
|
8167
|
+
resultDigest: content.result
|
|
8168
|
+
});
|
|
8169
|
+
}
|
|
8170
|
+
function identityFieldsFromAttributes(attributes) {
|
|
8171
|
+
if (!attributes || typeof attributes !== "object") {
|
|
8172
|
+
return {
|
|
8173
|
+
operationId: null,
|
|
8174
|
+
attemptId: null,
|
|
8175
|
+
attemptNumber: null,
|
|
8176
|
+
retryOf: null
|
|
8177
|
+
};
|
|
8178
|
+
}
|
|
8179
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? attributes.metadata : void 0;
|
|
8180
|
+
const pickString3 = (key) => {
|
|
8181
|
+
const direct = attributes[key];
|
|
8182
|
+
if (typeof direct === "string" && direct.trim() !== "") return direct.trim();
|
|
8183
|
+
const nestedValue = nested?.[key];
|
|
8184
|
+
if (typeof nestedValue === "string" && nestedValue.trim() !== "") {
|
|
8185
|
+
return nestedValue.trim();
|
|
8186
|
+
}
|
|
8187
|
+
return null;
|
|
8188
|
+
};
|
|
8189
|
+
const pickNumber2 = () => {
|
|
8190
|
+
const direct = attributes.attemptNumber ?? attributes.attempt;
|
|
8191
|
+
if (typeof direct === "number" && Number.isFinite(direct)) return direct;
|
|
8192
|
+
const nestedValue = nested?.attemptNumber ?? nested?.attempt;
|
|
8193
|
+
if (typeof nestedValue === "number" && Number.isFinite(nestedValue)) {
|
|
8194
|
+
return nestedValue;
|
|
8195
|
+
}
|
|
8196
|
+
return null;
|
|
8197
|
+
};
|
|
8198
|
+
return {
|
|
8199
|
+
operationId: pickString3("operationId"),
|
|
8200
|
+
attemptId: pickString3("attemptId"),
|
|
8201
|
+
retryOf: pickString3("retryOf"),
|
|
8202
|
+
attemptNumber: pickNumber2()
|
|
8203
|
+
};
|
|
8204
|
+
}
|
|
8205
|
+
function hasDeliveryConflictMarker(attributes) {
|
|
8206
|
+
return attributes?.[DELIVERY_CONFLICT_ATTR] === true;
|
|
8207
|
+
}
|
|
8208
|
+
function stampDeliveryConflict(event) {
|
|
8209
|
+
return {
|
|
8210
|
+
...event,
|
|
8211
|
+
attributes: {
|
|
8212
|
+
...event.attributes ?? {},
|
|
8213
|
+
[DELIVERY_CONFLICT_ATTR]: true
|
|
8214
|
+
}
|
|
8215
|
+
};
|
|
8216
|
+
}
|
|
8217
|
+
var DELIVERY_CONFLICT_ATTR, IDENTITY_CONFLICT_ATTR, SYNTHETIC_DELIVERY_ID;
|
|
8218
|
+
var init_delivery_identity = __esm({
|
|
8219
|
+
"packages/core/src/persisted/delivery-identity.ts"() {
|
|
8220
|
+
init_canonical_equality();
|
|
8221
|
+
DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
|
|
8222
|
+
IDENTITY_CONFLICT_ATTR = {
|
|
8223
|
+
operationId: "agent_inspect.identity_conflict.operation_id",
|
|
8224
|
+
attemptId: "agent_inspect.identity_conflict.attempt_id",
|
|
8225
|
+
retryOf: "agent_inspect.identity_conflict.retry_of",
|
|
8226
|
+
attemptNumber: "agent_inspect.identity_conflict.attempt_number"
|
|
8227
|
+
};
|
|
8228
|
+
SYNTHETIC_DELIVERY_ID = /^(?:manual|inspect):[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:\d+$/;
|
|
8229
|
+
}
|
|
8230
|
+
});
|
|
8231
|
+
|
|
8117
8232
|
// packages/core/src/checks/retry-safety.ts
|
|
8118
8233
|
function fail2(ruleId, message, evidence, expected, actual) {
|
|
8119
8234
|
return {
|
|
@@ -8169,7 +8284,7 @@ function attemptIdOf(event) {
|
|
|
8169
8284
|
}
|
|
8170
8285
|
function countOperationAttempts(members) {
|
|
8171
8286
|
const identified = /* @__PURE__ */ new Set();
|
|
8172
|
-
|
|
8287
|
+
const unidentifiedFingerprints = /* @__PURE__ */ new Set();
|
|
8173
8288
|
for (const event of members) {
|
|
8174
8289
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
8175
8290
|
const id = attemptIdOf(event);
|
|
@@ -8177,13 +8292,13 @@ function countOperationAttempts(members) {
|
|
|
8177
8292
|
identified.add(id);
|
|
8178
8293
|
continue;
|
|
8179
8294
|
}
|
|
8180
|
-
|
|
8295
|
+
unidentifiedFingerprints.add(redeliveryFingerprint(event));
|
|
8181
8296
|
}
|
|
8182
8297
|
if (identified.size > 0) {
|
|
8183
|
-
return identified.size +
|
|
8298
|
+
return identified.size + unidentifiedFingerprints.size;
|
|
8184
8299
|
}
|
|
8185
8300
|
const numbered = /* @__PURE__ */ new Set();
|
|
8186
|
-
|
|
8301
|
+
const unnumberedFingerprints = /* @__PURE__ */ new Set();
|
|
8187
8302
|
for (const event of members) {
|
|
8188
8303
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
8189
8304
|
const num2 = attemptNumberOf(event);
|
|
@@ -8191,12 +8306,12 @@ function countOperationAttempts(members) {
|
|
|
8191
8306
|
numbered.add(num2);
|
|
8192
8307
|
continue;
|
|
8193
8308
|
}
|
|
8194
|
-
|
|
8309
|
+
unnumberedFingerprints.add(redeliveryFingerprint(event));
|
|
8195
8310
|
}
|
|
8196
8311
|
if (numbered.size > 0) {
|
|
8197
|
-
return numbered.size +
|
|
8312
|
+
return numbered.size + unnumberedFingerprints.size;
|
|
8198
8313
|
}
|
|
8199
|
-
return
|
|
8314
|
+
return unnumberedFingerprints.size;
|
|
8200
8315
|
}
|
|
8201
8316
|
function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
8202
8317
|
const workflow = workflowFor(event);
|
|
@@ -8246,13 +8361,87 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
|
8246
8361
|
}
|
|
8247
8362
|
return { kind: "unknown", reason: "ambiguous attempt identity" };
|
|
8248
8363
|
}
|
|
8249
|
-
function
|
|
8250
|
-
const
|
|
8364
|
+
function redeliveryFingerprint(event) {
|
|
8365
|
+
const workflow = workflowFor(event);
|
|
8366
|
+
return deliverySemanticFingerprint({
|
|
8367
|
+
eventId: event.eventId ?? "",
|
|
8368
|
+
runId: event.runId,
|
|
8369
|
+
kind: event.kind,
|
|
8370
|
+
name: event.name,
|
|
8371
|
+
status: event.status,
|
|
8372
|
+
parentId: event.parentId,
|
|
8373
|
+
timestamp: event.timestamp,
|
|
8374
|
+
startedAt: event.startedAt,
|
|
8375
|
+
sourceType: event.source?.type,
|
|
8376
|
+
attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
|
|
8377
|
+
operationId: workflow.operationId ?? null,
|
|
8378
|
+
attemptId: workflow.attemptId ?? null,
|
|
8379
|
+
attemptNumber: workflow.attemptNumber ?? null,
|
|
8380
|
+
retryOf: workflow.retryOf ?? null
|
|
8381
|
+
});
|
|
8382
|
+
}
|
|
8383
|
+
function identityValuesEqual(a, b) {
|
|
8384
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
8385
|
+
return Number.isFinite(a) && Number.isFinite(b) && a === b;
|
|
8386
|
+
}
|
|
8387
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
8388
|
+
return a.trim() === b.trim();
|
|
8389
|
+
}
|
|
8390
|
+
return a === b;
|
|
8391
|
+
}
|
|
8392
|
+
function directNestedIdentityConflicts(event) {
|
|
8393
|
+
const attrs = event.attributes;
|
|
8394
|
+
if (!attrs || typeof attrs !== "object") return [];
|
|
8395
|
+
const nested = attrs.metadata && typeof attrs.metadata === "object" && !Array.isArray(attrs.metadata) ? attrs.metadata : void 0;
|
|
8396
|
+
if (!nested) return [];
|
|
8397
|
+
const conflicts = [];
|
|
8398
|
+
for (const key of IDENTITY_KEYS) {
|
|
8399
|
+
const direct = attrs[key];
|
|
8400
|
+
const nestedValue = nested[key];
|
|
8401
|
+
if (direct === void 0 || nestedValue === void 0) continue;
|
|
8402
|
+
if (!identityValuesEqual(direct, nestedValue)) {
|
|
8403
|
+
conflicts.push(key);
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8406
|
+
return conflicts;
|
|
8407
|
+
}
|
|
8408
|
+
function hasConflictingAttemptIdReuse(members) {
|
|
8409
|
+
const byAttempt = /* @__PURE__ */ new Map();
|
|
8251
8410
|
for (const event of members) {
|
|
8411
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
8252
8412
|
const id = attemptIdOf(event);
|
|
8253
8413
|
if (!id) continue;
|
|
8254
|
-
|
|
8255
|
-
|
|
8414
|
+
const fingerprints = byAttempt.get(id) ?? /* @__PURE__ */ new Set();
|
|
8415
|
+
fingerprints.add(redeliveryFingerprint(event));
|
|
8416
|
+
byAttempt.set(id, fingerprints);
|
|
8417
|
+
}
|
|
8418
|
+
for (const fingerprints of byAttempt.values()) {
|
|
8419
|
+
if (fingerprints.size > 1) return true;
|
|
8420
|
+
}
|
|
8421
|
+
return false;
|
|
8422
|
+
}
|
|
8423
|
+
function hasConflictingEventIdReuse(members) {
|
|
8424
|
+
const byEventId = /* @__PURE__ */ new Map();
|
|
8425
|
+
for (const event of members) {
|
|
8426
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
8427
|
+
const eventId = event.eventId;
|
|
8428
|
+
if (!eventId) continue;
|
|
8429
|
+
if (hasDeliveryConflictMarker(event.attributes)) {
|
|
8430
|
+
return true;
|
|
8431
|
+
}
|
|
8432
|
+
const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
|
|
8433
|
+
fingerprints.add(redeliveryFingerprint(event));
|
|
8434
|
+
byEventId.set(eventId, fingerprints);
|
|
8435
|
+
}
|
|
8436
|
+
for (const fingerprints of byEventId.values()) {
|
|
8437
|
+
if (fingerprints.size > 1) return true;
|
|
8438
|
+
}
|
|
8439
|
+
return false;
|
|
8440
|
+
}
|
|
8441
|
+
function hasIdentityRepresentationConflict(members) {
|
|
8442
|
+
for (const event of members) {
|
|
8443
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
8444
|
+
if (directNestedIdentityConflicts(event).length > 0) return true;
|
|
8256
8445
|
}
|
|
8257
8446
|
return false;
|
|
8258
8447
|
}
|
|
@@ -8263,23 +8452,49 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8263
8452
|
const workflow = workflowFor(event);
|
|
8264
8453
|
const operationId = workflow.operationId;
|
|
8265
8454
|
if (!operationId) continue;
|
|
8266
|
-
const
|
|
8267
|
-
|
|
8268
|
-
|
|
8455
|
+
const key = `${event.runId}\0${operationId}`;
|
|
8456
|
+
const group = byOperation.get(key) ?? { operationId, members: [] };
|
|
8457
|
+
group.members.push(event);
|
|
8458
|
+
byOperation.set(key, group);
|
|
8269
8459
|
}
|
|
8270
8460
|
if (rules.maxAttempts !== void 0) {
|
|
8271
|
-
for (const
|
|
8272
|
-
if (
|
|
8461
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8462
|
+
if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
|
|
8273
8463
|
findings.push(
|
|
8274
8464
|
fail2(
|
|
8275
8465
|
"contract.retry.duplicate-attempt-id",
|
|
8276
|
-
`Operation ${operationId} has
|
|
8466
|
+
`Operation ${operationId} has conflicting attemptId reuse (distinct executions).`,
|
|
8277
8467
|
members.slice(0, 4).map(eventEvidence2),
|
|
8278
8468
|
"unique attemptId",
|
|
8279
8469
|
"duplicate"
|
|
8280
8470
|
)
|
|
8281
8471
|
);
|
|
8282
8472
|
}
|
|
8473
|
+
if (hasIdentityRepresentationConflict(members)) {
|
|
8474
|
+
findings.push(
|
|
8475
|
+
fail2(
|
|
8476
|
+
"contract.retry.ambiguous-identity",
|
|
8477
|
+
`Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
|
|
8478
|
+
members.slice(0, 4).map(eventEvidence2),
|
|
8479
|
+
"agreeing identity representation",
|
|
8480
|
+
"direct/nested conflict"
|
|
8481
|
+
)
|
|
8482
|
+
);
|
|
8483
|
+
}
|
|
8484
|
+
const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
|
|
8485
|
+
const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
|
|
8486
|
+
const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
|
|
8487
|
+
if (hasAttemptId && missingAttemptId) {
|
|
8488
|
+
findings.push(
|
|
8489
|
+
fail2(
|
|
8490
|
+
"contract.retry.ambiguous-identity",
|
|
8491
|
+
`Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
|
|
8492
|
+
members.slice(0, 4).map(eventEvidence2),
|
|
8493
|
+
"complete attempt identity",
|
|
8494
|
+
"partial attemptId coverage"
|
|
8495
|
+
)
|
|
8496
|
+
);
|
|
8497
|
+
}
|
|
8283
8498
|
const count = countOperationAttempts(members);
|
|
8284
8499
|
if (count > rules.maxAttempts) {
|
|
8285
8500
|
findings.push(
|
|
@@ -8295,7 +8510,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8295
8510
|
}
|
|
8296
8511
|
}
|
|
8297
8512
|
if (rules.requireTerminalResult) {
|
|
8298
|
-
for (const
|
|
8513
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8299
8514
|
const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
|
|
8300
8515
|
if (!hasTerminal) {
|
|
8301
8516
|
findings.push(
|
|
@@ -8315,7 +8530,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8315
8530
|
const workflow = workflowFor(event);
|
|
8316
8531
|
const fallbackOf = workflow.fallbackOf;
|
|
8317
8532
|
if (!fallbackOf) continue;
|
|
8318
|
-
const prior = byOperation.get(fallbackOf) ?? [];
|
|
8533
|
+
const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
|
|
8319
8534
|
const fallbackStart = eventTime(event);
|
|
8320
8535
|
const earlierFailure = prior.some(
|
|
8321
8536
|
(candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
|
|
@@ -8342,7 +8557,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8342
8557
|
for (const event of toolEvents) {
|
|
8343
8558
|
const name = resolveCanonicalToolName(event);
|
|
8344
8559
|
const workflow = workflowFor(event);
|
|
8345
|
-
const key = `${workflow.operationId ?? name}::${name}`;
|
|
8560
|
+
const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
|
|
8346
8561
|
const list2 = byToolOp.get(key) ?? [];
|
|
8347
8562
|
list2.push(event);
|
|
8348
8563
|
byToolOp.set(key, list2);
|
|
@@ -8400,7 +8615,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8400
8615
|
}
|
|
8401
8616
|
}
|
|
8402
8617
|
if (rules.requireRecoveredFailureVisible) {
|
|
8403
|
-
for (const
|
|
8618
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8404
8619
|
const ordered = sortByTime(members);
|
|
8405
8620
|
const toolish = ordered.filter(
|
|
8406
8621
|
(event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
|
|
@@ -8439,10 +8654,13 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8439
8654
|
}
|
|
8440
8655
|
return findings;
|
|
8441
8656
|
}
|
|
8657
|
+
var IDENTITY_KEYS;
|
|
8442
8658
|
var init_retry_safety = __esm({
|
|
8443
8659
|
"packages/core/src/checks/retry-safety.ts"() {
|
|
8444
8660
|
init_logical_events();
|
|
8661
|
+
init_delivery_identity();
|
|
8445
8662
|
init_metadata();
|
|
8663
|
+
IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
|
|
8446
8664
|
}
|
|
8447
8665
|
});
|
|
8448
8666
|
|
|
@@ -8658,15 +8876,8 @@ function attemptIdOf2(event) {
|
|
|
8658
8876
|
const value = workflowFor2(event).attemptId;
|
|
8659
8877
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
8660
8878
|
}
|
|
8661
|
-
function
|
|
8662
|
-
|
|
8663
|
-
for (const event of members) {
|
|
8664
|
-
const id = attemptIdOf2(event);
|
|
8665
|
-
if (!id) continue;
|
|
8666
|
-
if (seen.has(id)) return true;
|
|
8667
|
-
seen.add(id);
|
|
8668
|
-
}
|
|
8669
|
-
return false;
|
|
8879
|
+
function hasDuplicateAttemptIds(members) {
|
|
8880
|
+
return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
|
|
8670
8881
|
}
|
|
8671
8882
|
function findRetryTarget(members, retryOf) {
|
|
8672
8883
|
return members.find(
|
|
@@ -8754,7 +8965,7 @@ function evaluateRecoveryOperations(events, operations) {
|
|
|
8754
8965
|
}
|
|
8755
8966
|
for (const [operationKey, members] of groups) {
|
|
8756
8967
|
const ordered = sortByTime2(members);
|
|
8757
|
-
if (
|
|
8968
|
+
if (hasDuplicateAttemptIds(members)) {
|
|
8758
8969
|
findings.push(
|
|
8759
8970
|
fail3(
|
|
8760
8971
|
"contract.retry.operations.duplicate-attempt-id",
|
|
@@ -12878,6 +13089,7 @@ function resolveRunTiming(sorted, status) {
|
|
|
12878
13089
|
var TreeBuilder;
|
|
12879
13090
|
var init_tree_builder = __esm({
|
|
12880
13091
|
"packages/core/src/logs/tree-builder.ts"() {
|
|
13092
|
+
init_delivery_identity();
|
|
12881
13093
|
TreeBuilder = class {
|
|
12882
13094
|
constructor(options) {
|
|
12883
13095
|
void options?.config;
|
|
@@ -12893,7 +13105,47 @@ var init_tree_builder = __esm({
|
|
|
12893
13105
|
const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);
|
|
12894
13106
|
const nodes = /* @__PURE__ */ new Map();
|
|
12895
13107
|
for (const e of sorted) {
|
|
12896
|
-
nodes.
|
|
13108
|
+
const existing = nodes.get(e.eventId);
|
|
13109
|
+
if (!existing) {
|
|
13110
|
+
nodes.set(e.eventId, { event: e, children: [], depth: 0 });
|
|
13111
|
+
continue;
|
|
13112
|
+
}
|
|
13113
|
+
const existingAttrs = existing.event.attributes && typeof existing.event.attributes === "object" ? existing.event.attributes : void 0;
|
|
13114
|
+
const nextAttrs = e.attributes && typeof e.attributes === "object" ? e.attributes : void 0;
|
|
13115
|
+
const existingIdentity = identityFieldsFromAttributes(existingAttrs);
|
|
13116
|
+
const nextIdentity = identityFieldsFromAttributes(nextAttrs);
|
|
13117
|
+
const existingFp = deliverySemanticFingerprint({
|
|
13118
|
+
eventId: existing.event.eventId,
|
|
13119
|
+
runId: existing.event.runId,
|
|
13120
|
+
kind: existing.event.kind,
|
|
13121
|
+
name: existing.event.name,
|
|
13122
|
+
status: existing.event.status,
|
|
13123
|
+
parentId: existing.event.parentId,
|
|
13124
|
+
timestamp: existing.event.timestamp,
|
|
13125
|
+
sourceType: existing.event.source?.type,
|
|
13126
|
+
attributes: existingAttrs,
|
|
13127
|
+
...existingIdentity
|
|
13128
|
+
});
|
|
13129
|
+
const nextFp = deliverySemanticFingerprint({
|
|
13130
|
+
eventId: e.eventId,
|
|
13131
|
+
runId: e.runId,
|
|
13132
|
+
kind: e.kind,
|
|
13133
|
+
name: e.name,
|
|
13134
|
+
status: e.status,
|
|
13135
|
+
parentId: e.parentId,
|
|
13136
|
+
timestamp: e.timestamp,
|
|
13137
|
+
sourceType: e.source?.type,
|
|
13138
|
+
attributes: nextAttrs,
|
|
13139
|
+
...nextIdentity
|
|
13140
|
+
});
|
|
13141
|
+
if (existingFp === nextFp) {
|
|
13142
|
+
continue;
|
|
13143
|
+
}
|
|
13144
|
+
nodes.set(e.eventId, {
|
|
13145
|
+
event: stampDeliveryConflict(e),
|
|
13146
|
+
children: [],
|
|
13147
|
+
depth: 0
|
|
13148
|
+
});
|
|
12897
13149
|
}
|
|
12898
13150
|
const { roots, summary } = linkNodesVisibilityFirst(nodes);
|
|
12899
13151
|
const confidenceBreakdown = {
|
|
@@ -14170,6 +14422,12 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
14170
14422
|
["agent_inspect.retry_of", "retryOf", "string"],
|
|
14171
14423
|
["agent_inspect.attempt_number", "attemptNumber", "int"]
|
|
14172
14424
|
];
|
|
14425
|
+
const conflictMapping = [
|
|
14426
|
+
["agent_inspect.identity_conflict.operation_id", "operationId", "string"],
|
|
14427
|
+
["agent_inspect.identity_conflict.attempt_id", "attemptId", "string"],
|
|
14428
|
+
["agent_inspect.identity_conflict.retry_of", "retryOf", "string"],
|
|
14429
|
+
["agent_inspect.identity_conflict.attempt_number", "attemptNumber", "int"]
|
|
14430
|
+
];
|
|
14173
14431
|
const metadata = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? { ...attributes.metadata } : {};
|
|
14174
14432
|
for (const [dotted, camel, kind] of mapping) {
|
|
14175
14433
|
const raw = attributes[dotted];
|
|
@@ -14221,6 +14479,46 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
14221
14479
|
if (direct === void 0) attributes[camel] = promoted;
|
|
14222
14480
|
if (nested === void 0) metadata[camel] = promoted;
|
|
14223
14481
|
}
|
|
14482
|
+
for (const [dotted, camel, kind] of conflictMapping) {
|
|
14483
|
+
const raw = attributes[dotted];
|
|
14484
|
+
if (raw === void 0 || raw === null) continue;
|
|
14485
|
+
let alternate;
|
|
14486
|
+
if (kind === "int") {
|
|
14487
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
|
|
14488
|
+
if (!Number.isFinite(n) || n < 1) {
|
|
14489
|
+
warnings.push({
|
|
14490
|
+
code: "otlp_identity_invalid",
|
|
14491
|
+
message: `Ignoring invalid ${dotted} identity conflict value.`,
|
|
14492
|
+
severity: "warning",
|
|
14493
|
+
field: `${pathPrefix}.${dotted}`
|
|
14494
|
+
});
|
|
14495
|
+
continue;
|
|
14496
|
+
}
|
|
14497
|
+
alternate = Math.trunc(n);
|
|
14498
|
+
} else if (typeof raw === "string" && raw.trim() !== "") {
|
|
14499
|
+
alternate = raw.trim();
|
|
14500
|
+
} else {
|
|
14501
|
+
warnings.push({
|
|
14502
|
+
code: "otlp_identity_invalid",
|
|
14503
|
+
message: `Ignoring non-string ${dotted} identity conflict value.`,
|
|
14504
|
+
severity: "warning",
|
|
14505
|
+
field: `${pathPrefix}.${dotted}`
|
|
14506
|
+
});
|
|
14507
|
+
continue;
|
|
14508
|
+
}
|
|
14509
|
+
const preferred = attributes[camel];
|
|
14510
|
+
if (preferred !== void 0 && preferred !== alternate) {
|
|
14511
|
+
metadata[camel] = alternate;
|
|
14512
|
+
warnings.push({
|
|
14513
|
+
code: "otlp_identity_conflict",
|
|
14514
|
+
message: `Conflicting ${camel}: attributes.${camel} vs nested alternate from ${dotted}; retaining both.`,
|
|
14515
|
+
severity: "warning",
|
|
14516
|
+
field: `${pathPrefix}.${dotted}`
|
|
14517
|
+
});
|
|
14518
|
+
} else if (preferred === void 0) {
|
|
14519
|
+
metadata[camel] = alternate;
|
|
14520
|
+
}
|
|
14521
|
+
}
|
|
14224
14522
|
if (Object.keys(metadata).length > 0) {
|
|
14225
14523
|
attributes.metadata = metadata;
|
|
14226
14524
|
}
|
|
@@ -16960,7 +17258,7 @@ var init_src = __esm({
|
|
|
16960
17258
|
});
|
|
16961
17259
|
|
|
16962
17260
|
// package.json
|
|
16963
|
-
var version = "6.31.
|
|
17261
|
+
var version = "6.31.22";
|
|
16964
17262
|
|
|
16965
17263
|
// packages/cli/src/list.ts
|
|
16966
17264
|
init_advanced();
|
|
@@ -19568,6 +19866,7 @@ function exportOpenInference(tree, options) {
|
|
|
19568
19866
|
}
|
|
19569
19867
|
|
|
19570
19868
|
// packages/core/src/exporters/otlp-json-exporter.ts
|
|
19869
|
+
init_delivery_identity();
|
|
19571
19870
|
init_helpers();
|
|
19572
19871
|
var OTLP_STATUS_CODE_UNSET = 0;
|
|
19573
19872
|
var OTLP_STATUS_CODE_OK = 1;
|
|
@@ -19618,43 +19917,81 @@ var STRUCTURAL_IDENTITY_KEYS = [
|
|
|
19618
19917
|
"attemptNumber",
|
|
19619
19918
|
"attempt"
|
|
19620
19919
|
];
|
|
19621
|
-
function
|
|
19920
|
+
function nestedBag(bag) {
|
|
19622
19921
|
if (!bag || typeof bag !== "object") return void 0;
|
|
19623
|
-
const
|
|
19624
|
-
if (typeof
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
if (
|
|
19629
|
-
|
|
19630
|
-
|
|
19631
|
-
|
|
19922
|
+
const nested = bag.metadata;
|
|
19923
|
+
if (!nested || typeof nested !== "object" || Array.isArray(nested)) return void 0;
|
|
19924
|
+
return nested;
|
|
19925
|
+
}
|
|
19926
|
+
function pickBoundedIdentityString(bag, key, maxLen) {
|
|
19927
|
+
if (!bag || typeof bag !== "object") return {};
|
|
19928
|
+
const directRaw = bag[key];
|
|
19929
|
+
const nestedRaw = nestedBag(bag)?.[key];
|
|
19930
|
+
const direct = typeof directRaw === "string" && directRaw.trim() !== "" ? directRaw.trim().slice(0, maxLen) : void 0;
|
|
19931
|
+
const nested = typeof nestedRaw === "string" && nestedRaw.trim() !== "" ? nestedRaw.trim().slice(0, maxLen) : void 0;
|
|
19932
|
+
if (direct !== void 0 && nested !== void 0 && direct !== nested) {
|
|
19933
|
+
return { value: direct, conflictAlternate: nested };
|
|
19934
|
+
}
|
|
19935
|
+
if (direct !== void 0) return { value: direct };
|
|
19936
|
+
if (nested !== void 0) return { value: nested };
|
|
19937
|
+
return {};
|
|
19632
19938
|
}
|
|
19633
19939
|
function pickBoundedIdentityNumber(bag, key) {
|
|
19634
|
-
if (!bag || typeof bag !== "object") return
|
|
19635
|
-
const
|
|
19636
|
-
|
|
19637
|
-
const
|
|
19638
|
-
|
|
19639
|
-
|
|
19940
|
+
if (!bag || typeof bag !== "object") return {};
|
|
19941
|
+
const directRaw = bag[key];
|
|
19942
|
+
const nestedRaw = nestedBag(bag)?.[key];
|
|
19943
|
+
const direct = typeof directRaw === "number" && Number.isFinite(directRaw) ? directRaw : void 0;
|
|
19944
|
+
const nested = typeof nestedRaw === "number" && Number.isFinite(nestedRaw) ? nestedRaw : void 0;
|
|
19945
|
+
if (direct !== void 0 && nested !== void 0 && direct !== nested) {
|
|
19946
|
+
return { value: direct, conflictAlternate: nested };
|
|
19947
|
+
}
|
|
19948
|
+
if (direct !== void 0) return { value: direct };
|
|
19949
|
+
if (nested !== void 0) return { value: nested };
|
|
19950
|
+
return {};
|
|
19640
19951
|
}
|
|
19641
19952
|
function appendStructuralIdentityAttrs(attrs, meta2, maxLen) {
|
|
19953
|
+
const conflicts = [];
|
|
19642
19954
|
const operationId = pickBoundedIdentityString(meta2, "operationId", maxLen);
|
|
19643
|
-
if (operationId !== void 0) {
|
|
19644
|
-
attrs.push(stringAttr2("agent_inspect.operation_id", operationId));
|
|
19955
|
+
if (operationId.value !== void 0) {
|
|
19956
|
+
attrs.push(stringAttr2("agent_inspect.operation_id", operationId.value));
|
|
19957
|
+
}
|
|
19958
|
+
if (operationId.conflictAlternate !== void 0) {
|
|
19959
|
+
attrs.push(
|
|
19960
|
+
stringAttr2(IDENTITY_CONFLICT_ATTR.operationId, operationId.conflictAlternate)
|
|
19961
|
+
);
|
|
19962
|
+
conflicts.push("operationId");
|
|
19645
19963
|
}
|
|
19646
19964
|
const attemptId = pickBoundedIdentityString(meta2, "attemptId", maxLen);
|
|
19647
|
-
if (attemptId !== void 0) {
|
|
19648
|
-
attrs.push(stringAttr2("agent_inspect.attempt_id", attemptId));
|
|
19965
|
+
if (attemptId.value !== void 0) {
|
|
19966
|
+
attrs.push(stringAttr2("agent_inspect.attempt_id", attemptId.value));
|
|
19967
|
+
}
|
|
19968
|
+
if (attemptId.conflictAlternate !== void 0) {
|
|
19969
|
+
attrs.push(stringAttr2(IDENTITY_CONFLICT_ATTR.attemptId, attemptId.conflictAlternate));
|
|
19970
|
+
conflicts.push("attemptId");
|
|
19649
19971
|
}
|
|
19650
19972
|
const retryOf = pickBoundedIdentityString(meta2, "retryOf", maxLen);
|
|
19651
|
-
if (retryOf !== void 0) {
|
|
19652
|
-
attrs.push(stringAttr2("agent_inspect.retry_of", retryOf));
|
|
19973
|
+
if (retryOf.value !== void 0) {
|
|
19974
|
+
attrs.push(stringAttr2("agent_inspect.retry_of", retryOf.value));
|
|
19653
19975
|
}
|
|
19654
|
-
|
|
19655
|
-
|
|
19656
|
-
|
|
19976
|
+
if (retryOf.conflictAlternate !== void 0) {
|
|
19977
|
+
attrs.push(stringAttr2(IDENTITY_CONFLICT_ATTR.retryOf, retryOf.conflictAlternate));
|
|
19978
|
+
conflicts.push("retryOf");
|
|
19979
|
+
}
|
|
19980
|
+
const attemptNumberPrimary = pickBoundedIdentityNumber(meta2, "attemptNumber");
|
|
19981
|
+
const attemptNumber2 = attemptNumberPrimary.value !== void 0 || attemptNumberPrimary.conflictAlternate !== void 0 ? attemptNumberPrimary : pickBoundedIdentityNumber(meta2, "attempt");
|
|
19982
|
+
if (attemptNumber2.value !== void 0) {
|
|
19983
|
+
attrs.push(intAttr("agent_inspect.attempt_number", attemptNumber2.value));
|
|
19984
|
+
}
|
|
19985
|
+
if (attemptNumber2.conflictAlternate !== void 0) {
|
|
19986
|
+
attrs.push(
|
|
19987
|
+
intAttr(IDENTITY_CONFLICT_ATTR.attemptNumber, attemptNumber2.conflictAlternate)
|
|
19988
|
+
);
|
|
19989
|
+
conflicts.push("attemptNumber");
|
|
19657
19990
|
}
|
|
19991
|
+
if (meta2?.[DELIVERY_CONFLICT_ATTR] === true) {
|
|
19992
|
+
attrs.push(boolAttr(DELIVERY_CONFLICT_ATTR, true));
|
|
19993
|
+
}
|
|
19994
|
+
return conflicts;
|
|
19658
19995
|
}
|
|
19659
19996
|
function resolveSpanTimes(ev) {
|
|
19660
19997
|
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
@@ -19677,7 +20014,8 @@ function exportOtlpJson(tree, options) {
|
|
|
19677
20014
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
19678
20015
|
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
19679
20016
|
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1).",
|
|
19680
|
-
"When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump)."
|
|
20017
|
+
"When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump).",
|
|
20018
|
+
"When direct and nested identity disagree, export prefers direct for non-strict consumers and emits agent_inspect.identity_conflict.* for the nested alternate; this does not certify conflicting identity."
|
|
19681
20019
|
];
|
|
19682
20020
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
19683
20021
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -19725,11 +20063,16 @@ function exportOtlpJson(tree, options) {
|
|
|
19725
20063
|
if (typeof inp === "number") attrs.push(intAttr("gen_ai.usage.input_tokens", inp));
|
|
19726
20064
|
if (typeof outp === "number") attrs.push(intAttr("gen_ai.usage.output_tokens", outp));
|
|
19727
20065
|
}
|
|
19728
|
-
appendStructuralIdentityAttrs(
|
|
20066
|
+
const identityConflicts = appendStructuralIdentityAttrs(
|
|
19729
20067
|
attrs,
|
|
19730
20068
|
meta2 && typeof meta2 === "object" ? meta2 : void 0,
|
|
19731
20069
|
maxLen
|
|
19732
20070
|
);
|
|
20071
|
+
if (identityConflicts.length > 0) {
|
|
20072
|
+
warnings.push(
|
|
20073
|
+
`Identity representation conflict on event ${ev.eventId}: ${identityConflicts.join(", ")} (direct preferred; nested retained on agent_inspect.identity_conflict.*).`
|
|
20074
|
+
);
|
|
20075
|
+
}
|
|
19733
20076
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
19734
20077
|
const skipKeys = /* @__PURE__ */ new Set([
|
|
19735
20078
|
"tokens",
|