agent-inspect 6.31.21 → 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 +6 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-EMWA5EKU.mjs} +300 -31
- package/packages/cli/dist/chunk-EMWA5EKU.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +379 -56
- 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-VMGRSTG7.mjs → src-VZHGOLTO.mjs} +3 -3
- package/packages/cli/dist/{src-VMGRSTG7.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 +160 -27
- 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-4CDX5GDS.mjs → chunk-ZOF6ON65.mjs} +104 -99
- 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-N5JN26MW.mjs.map +0 -1
- package/packages/core/dist/chunk-4CDX5GDS.mjs.map +0 -1
- package/packages/core/dist/chunk-EIP5CNEL.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);
|
|
@@ -8248,19 +8363,48 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
|
8248
8363
|
}
|
|
8249
8364
|
function redeliveryFingerprint(event) {
|
|
8250
8365
|
const workflow = workflowFor(event);
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
stableEventId,
|
|
8366
|
+
return deliverySemanticFingerprint({
|
|
8367
|
+
eventId: event.eventId ?? "",
|
|
8254
8368
|
runId: event.runId,
|
|
8255
8369
|
kind: event.kind,
|
|
8256
8370
|
name: event.name,
|
|
8257
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,
|
|
8258
8377
|
operationId: workflow.operationId ?? null,
|
|
8259
8378
|
attemptId: workflow.attemptId ?? null,
|
|
8260
8379
|
attemptNumber: workflow.attemptNumber ?? null,
|
|
8261
8380
|
retryOf: workflow.retryOf ?? null
|
|
8262
8381
|
});
|
|
8263
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
|
+
}
|
|
8264
8408
|
function hasConflictingAttemptIdReuse(members) {
|
|
8265
8409
|
const byAttempt = /* @__PURE__ */ new Map();
|
|
8266
8410
|
for (const event of members) {
|
|
@@ -8276,6 +8420,31 @@ function hasConflictingAttemptIdReuse(members) {
|
|
|
8276
8420
|
}
|
|
8277
8421
|
return false;
|
|
8278
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;
|
|
8445
|
+
}
|
|
8446
|
+
return false;
|
|
8447
|
+
}
|
|
8279
8448
|
function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
8280
8449
|
const findings = [];
|
|
8281
8450
|
const byOperation = /* @__PURE__ */ new Map();
|
|
@@ -8283,13 +8452,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8283
8452
|
const workflow = workflowFor(event);
|
|
8284
8453
|
const operationId = workflow.operationId;
|
|
8285
8454
|
if (!operationId) continue;
|
|
8286
|
-
const
|
|
8287
|
-
|
|
8288
|
-
|
|
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);
|
|
8289
8459
|
}
|
|
8290
8460
|
if (rules.maxAttempts !== void 0) {
|
|
8291
|
-
for (const
|
|
8292
|
-
if (hasConflictingAttemptIdReuse(members)) {
|
|
8461
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8462
|
+
if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
|
|
8293
8463
|
findings.push(
|
|
8294
8464
|
fail2(
|
|
8295
8465
|
"contract.retry.duplicate-attempt-id",
|
|
@@ -8300,6 +8470,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8300
8470
|
)
|
|
8301
8471
|
);
|
|
8302
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
|
+
}
|
|
8303
8498
|
const count = countOperationAttempts(members);
|
|
8304
8499
|
if (count > rules.maxAttempts) {
|
|
8305
8500
|
findings.push(
|
|
@@ -8315,7 +8510,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8315
8510
|
}
|
|
8316
8511
|
}
|
|
8317
8512
|
if (rules.requireTerminalResult) {
|
|
8318
|
-
for (const
|
|
8513
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8319
8514
|
const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
|
|
8320
8515
|
if (!hasTerminal) {
|
|
8321
8516
|
findings.push(
|
|
@@ -8335,7 +8530,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8335
8530
|
const workflow = workflowFor(event);
|
|
8336
8531
|
const fallbackOf = workflow.fallbackOf;
|
|
8337
8532
|
if (!fallbackOf) continue;
|
|
8338
|
-
const prior = byOperation.get(fallbackOf) ?? [];
|
|
8533
|
+
const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
|
|
8339
8534
|
const fallbackStart = eventTime(event);
|
|
8340
8535
|
const earlierFailure = prior.some(
|
|
8341
8536
|
(candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
|
|
@@ -8362,7 +8557,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8362
8557
|
for (const event of toolEvents) {
|
|
8363
8558
|
const name = resolveCanonicalToolName(event);
|
|
8364
8559
|
const workflow = workflowFor(event);
|
|
8365
|
-
const key = `${workflow.operationId ?? name}::${name}`;
|
|
8560
|
+
const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
|
|
8366
8561
|
const list2 = byToolOp.get(key) ?? [];
|
|
8367
8562
|
list2.push(event);
|
|
8368
8563
|
byToolOp.set(key, list2);
|
|
@@ -8420,7 +8615,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8420
8615
|
}
|
|
8421
8616
|
}
|
|
8422
8617
|
if (rules.requireRecoveredFailureVisible) {
|
|
8423
|
-
for (const
|
|
8618
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
8424
8619
|
const ordered = sortByTime(members);
|
|
8425
8620
|
const toolish = ordered.filter(
|
|
8426
8621
|
(event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
|
|
@@ -8459,10 +8654,13 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
8459
8654
|
}
|
|
8460
8655
|
return findings;
|
|
8461
8656
|
}
|
|
8657
|
+
var IDENTITY_KEYS;
|
|
8462
8658
|
var init_retry_safety = __esm({
|
|
8463
8659
|
"packages/core/src/checks/retry-safety.ts"() {
|
|
8464
8660
|
init_logical_events();
|
|
8661
|
+
init_delivery_identity();
|
|
8465
8662
|
init_metadata();
|
|
8663
|
+
IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
|
|
8466
8664
|
}
|
|
8467
8665
|
});
|
|
8468
8666
|
|
|
@@ -8679,14 +8877,7 @@ function attemptIdOf2(event) {
|
|
|
8679
8877
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
8680
8878
|
}
|
|
8681
8879
|
function hasDuplicateAttemptIds(members) {
|
|
8682
|
-
|
|
8683
|
-
for (const event of members) {
|
|
8684
|
-
const id = attemptIdOf2(event);
|
|
8685
|
-
if (!id) continue;
|
|
8686
|
-
if (seen.has(id)) return true;
|
|
8687
|
-
seen.add(id);
|
|
8688
|
-
}
|
|
8689
|
-
return false;
|
|
8880
|
+
return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
|
|
8690
8881
|
}
|
|
8691
8882
|
function findRetryTarget(members, retryOf) {
|
|
8692
8883
|
return members.find(
|
|
@@ -12898,6 +13089,7 @@ function resolveRunTiming(sorted, status) {
|
|
|
12898
13089
|
var TreeBuilder;
|
|
12899
13090
|
var init_tree_builder = __esm({
|
|
12900
13091
|
"packages/core/src/logs/tree-builder.ts"() {
|
|
13092
|
+
init_delivery_identity();
|
|
12901
13093
|
TreeBuilder = class {
|
|
12902
13094
|
constructor(options) {
|
|
12903
13095
|
void options?.config;
|
|
@@ -12913,7 +13105,47 @@ var init_tree_builder = __esm({
|
|
|
12913
13105
|
const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);
|
|
12914
13106
|
const nodes = /* @__PURE__ */ new Map();
|
|
12915
13107
|
for (const e of sorted) {
|
|
12916
|
-
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
|
+
});
|
|
12917
13149
|
}
|
|
12918
13150
|
const { roots, summary } = linkNodesVisibilityFirst(nodes);
|
|
12919
13151
|
const confidenceBreakdown = {
|
|
@@ -14190,6 +14422,12 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
14190
14422
|
["agent_inspect.retry_of", "retryOf", "string"],
|
|
14191
14423
|
["agent_inspect.attempt_number", "attemptNumber", "int"]
|
|
14192
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
|
+
];
|
|
14193
14431
|
const metadata = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? { ...attributes.metadata } : {};
|
|
14194
14432
|
for (const [dotted, camel, kind] of mapping) {
|
|
14195
14433
|
const raw = attributes[dotted];
|
|
@@ -14241,6 +14479,46 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
14241
14479
|
if (direct === void 0) attributes[camel] = promoted;
|
|
14242
14480
|
if (nested === void 0) metadata[camel] = promoted;
|
|
14243
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
|
+
}
|
|
14244
14522
|
if (Object.keys(metadata).length > 0) {
|
|
14245
14523
|
attributes.metadata = metadata;
|
|
14246
14524
|
}
|
|
@@ -16980,7 +17258,7 @@ var init_src = __esm({
|
|
|
16980
17258
|
});
|
|
16981
17259
|
|
|
16982
17260
|
// package.json
|
|
16983
|
-
var version = "6.31.
|
|
17261
|
+
var version = "6.31.22";
|
|
16984
17262
|
|
|
16985
17263
|
// packages/cli/src/list.ts
|
|
16986
17264
|
init_advanced();
|
|
@@ -19588,6 +19866,7 @@ function exportOpenInference(tree, options) {
|
|
|
19588
19866
|
}
|
|
19589
19867
|
|
|
19590
19868
|
// packages/core/src/exporters/otlp-json-exporter.ts
|
|
19869
|
+
init_delivery_identity();
|
|
19591
19870
|
init_helpers();
|
|
19592
19871
|
var OTLP_STATUS_CODE_UNSET = 0;
|
|
19593
19872
|
var OTLP_STATUS_CODE_OK = 1;
|
|
@@ -19638,43 +19917,81 @@ var STRUCTURAL_IDENTITY_KEYS = [
|
|
|
19638
19917
|
"attemptNumber",
|
|
19639
19918
|
"attempt"
|
|
19640
19919
|
];
|
|
19641
|
-
function
|
|
19920
|
+
function nestedBag(bag) {
|
|
19642
19921
|
if (!bag || typeof bag !== "object") return void 0;
|
|
19643
|
-
const
|
|
19644
|
-
if (typeof
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
if (
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
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 {};
|
|
19652
19938
|
}
|
|
19653
19939
|
function pickBoundedIdentityNumber(bag, key) {
|
|
19654
|
-
if (!bag || typeof bag !== "object") return
|
|
19655
|
-
const
|
|
19656
|
-
|
|
19657
|
-
const
|
|
19658
|
-
|
|
19659
|
-
|
|
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 {};
|
|
19660
19951
|
}
|
|
19661
19952
|
function appendStructuralIdentityAttrs(attrs, meta2, maxLen) {
|
|
19953
|
+
const conflicts = [];
|
|
19662
19954
|
const operationId = pickBoundedIdentityString(meta2, "operationId", maxLen);
|
|
19663
|
-
if (operationId !== void 0) {
|
|
19664
|
-
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");
|
|
19665
19963
|
}
|
|
19666
19964
|
const attemptId = pickBoundedIdentityString(meta2, "attemptId", maxLen);
|
|
19667
|
-
if (attemptId !== void 0) {
|
|
19668
|
-
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");
|
|
19669
19971
|
}
|
|
19670
19972
|
const retryOf = pickBoundedIdentityString(meta2, "retryOf", maxLen);
|
|
19671
|
-
if (retryOf !== void 0) {
|
|
19672
|
-
attrs.push(stringAttr2("agent_inspect.retry_of", retryOf));
|
|
19973
|
+
if (retryOf.value !== void 0) {
|
|
19974
|
+
attrs.push(stringAttr2("agent_inspect.retry_of", retryOf.value));
|
|
19673
19975
|
}
|
|
19674
|
-
|
|
19675
|
-
|
|
19676
|
-
|
|
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");
|
|
19677
19990
|
}
|
|
19991
|
+
if (meta2?.[DELIVERY_CONFLICT_ATTR] === true) {
|
|
19992
|
+
attrs.push(boolAttr(DELIVERY_CONFLICT_ATTR, true));
|
|
19993
|
+
}
|
|
19994
|
+
return conflicts;
|
|
19678
19995
|
}
|
|
19679
19996
|
function resolveSpanTimes(ev) {
|
|
19680
19997
|
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
@@ -19697,7 +20014,8 @@ function exportOtlpJson(tree, options) {
|
|
|
19697
20014
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
19698
20015
|
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
19699
20016
|
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1).",
|
|
19700
|
-
"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."
|
|
19701
20019
|
];
|
|
19702
20020
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
19703
20021
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -19745,11 +20063,16 @@ function exportOtlpJson(tree, options) {
|
|
|
19745
20063
|
if (typeof inp === "number") attrs.push(intAttr("gen_ai.usage.input_tokens", inp));
|
|
19746
20064
|
if (typeof outp === "number") attrs.push(intAttr("gen_ai.usage.output_tokens", outp));
|
|
19747
20065
|
}
|
|
19748
|
-
appendStructuralIdentityAttrs(
|
|
20066
|
+
const identityConflicts = appendStructuralIdentityAttrs(
|
|
19749
20067
|
attrs,
|
|
19750
20068
|
meta2 && typeof meta2 === "object" ? meta2 : void 0,
|
|
19751
20069
|
maxLen
|
|
19752
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
|
+
}
|
|
19753
20076
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
19754
20077
|
const skipKeys = /* @__PURE__ */ new Set([
|
|
19755
20078
|
"tokens",
|