@agent-inspect/mcp-server 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.
- package/dist/{chunk-L5YP42Q6.mjs → chunk-XLIQEKWB.mjs} +367 -41
- package/dist/chunk-XLIQEKWB.mjs.map +1 -0
- package/dist/cli.cjs +365 -39
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +365 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-L5YP42Q6.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -4092,6 +4092,184 @@ function runTraceChecks(input, options = {}) {
|
|
|
4092
4092
|
};
|
|
4093
4093
|
}
|
|
4094
4094
|
|
|
4095
|
+
// packages/core/src/checks/canonical-equality.ts
|
|
4096
|
+
var DEFAULT_MAX_DEPTH = 8;
|
|
4097
|
+
var DEFAULT_MAX_BYTES = 16384;
|
|
4098
|
+
function sortKeysDeep(input, depth, maxDepth) {
|
|
4099
|
+
if (depth > maxDepth) {
|
|
4100
|
+
throw new Error("AI_CHECK_CANONICAL_DEPTH_EXCEEDED");
|
|
4101
|
+
}
|
|
4102
|
+
if (input === null || typeof input !== "object") return input;
|
|
4103
|
+
if (Array.isArray(input)) {
|
|
4104
|
+
return input.map((item) => sortKeysDeep(item, depth + 1, maxDepth));
|
|
4105
|
+
}
|
|
4106
|
+
const record = input;
|
|
4107
|
+
const out = {};
|
|
4108
|
+
for (const key of Object.keys(record).sort()) {
|
|
4109
|
+
out[key] = sortKeysDeep(record[key], depth + 1, maxDepth);
|
|
4110
|
+
}
|
|
4111
|
+
return out;
|
|
4112
|
+
}
|
|
4113
|
+
function encodeCanonicalStructured(value, limits) {
|
|
4114
|
+
const maxDepth = DEFAULT_MAX_DEPTH;
|
|
4115
|
+
const maxBytes = DEFAULT_MAX_BYTES;
|
|
4116
|
+
try {
|
|
4117
|
+
const sorted = sortKeysDeep(value, 0, maxDepth);
|
|
4118
|
+
const encoded = JSON.stringify(sorted);
|
|
4119
|
+
if (encoded === void 0) {
|
|
4120
|
+
return {
|
|
4121
|
+
ok: false,
|
|
4122
|
+
reason: "Value is not JSON-serializable for canonical comparison.",
|
|
4123
|
+
code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
|
|
4124
|
+
};
|
|
4125
|
+
}
|
|
4126
|
+
if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
|
|
4127
|
+
return {
|
|
4128
|
+
ok: false,
|
|
4129
|
+
reason: "Canonical structured value exceeds bounded size limit.",
|
|
4130
|
+
code: "AI_CHECK_CANONICAL_SIZE_EXCEEDED"
|
|
4131
|
+
};
|
|
4132
|
+
}
|
|
4133
|
+
return { ok: true, value: encoded };
|
|
4134
|
+
} catch (error) {
|
|
4135
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4136
|
+
if (message === "AI_CHECK_CANONICAL_DEPTH_EXCEEDED") {
|
|
4137
|
+
return {
|
|
4138
|
+
ok: false,
|
|
4139
|
+
reason: "Canonical structured value exceeds bounded depth limit.",
|
|
4140
|
+
code: "AI_CHECK_CANONICAL_DEPTH_EXCEEDED"
|
|
4141
|
+
};
|
|
4142
|
+
}
|
|
4143
|
+
return {
|
|
4144
|
+
ok: false,
|
|
4145
|
+
reason: "Canonical structured encoding failed.",
|
|
4146
|
+
code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
|
|
4147
|
+
};
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
// packages/core/src/persisted/delivery-identity.ts
|
|
4152
|
+
var DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
|
|
4153
|
+
var DELIVERY_EVENT_BASE_ATTR = "agent_inspect.delivery_event_base";
|
|
4154
|
+
var IDENTITY_CONFLICT_ATTR = {
|
|
4155
|
+
operationId: "agent_inspect.identity_conflict.operation_id",
|
|
4156
|
+
attemptId: "agent_inspect.identity_conflict.attempt_id",
|
|
4157
|
+
retryOf: "agent_inspect.identity_conflict.retry_of",
|
|
4158
|
+
attemptNumber: "agent_inspect.identity_conflict.attempt_number",
|
|
4159
|
+
/** Comma-separated field names when a conflict survives lossy bounding. */
|
|
4160
|
+
fields: "agent_inspect.identity_conflict.fields"
|
|
4161
|
+
};
|
|
4162
|
+
var MAX_DELIVERY_BASE_LEN = 500;
|
|
4163
|
+
function stripReaderDeliveryDiscriminator(eventId, attributes) {
|
|
4164
|
+
if (!eventId) return eventId;
|
|
4165
|
+
const rawBase = attributes?.[DELIVERY_EVENT_BASE_ATTR];
|
|
4166
|
+
if (typeof rawBase !== "string" || rawBase.trim() === "") return eventId;
|
|
4167
|
+
const base = rawBase.trim().slice(0, MAX_DELIVERY_BASE_LEN);
|
|
4168
|
+
if (eventId === base) return base;
|
|
4169
|
+
const prefix = `${base}:`;
|
|
4170
|
+
if (!eventId.startsWith(prefix)) return eventId;
|
|
4171
|
+
const suffix = eventId.slice(prefix.length);
|
|
4172
|
+
if (/^\d+$/.test(suffix)) return base;
|
|
4173
|
+
return eventId;
|
|
4174
|
+
}
|
|
4175
|
+
function deliveryEventBaseFromIndexedId(eventId) {
|
|
4176
|
+
if (!/:\d+$/.test(eventId)) return void 0;
|
|
4177
|
+
const base = eventId.replace(/:\d+$/, "");
|
|
4178
|
+
return base.length > 0 ? base.slice(0, MAX_DELIVERY_BASE_LEN) : void 0;
|
|
4179
|
+
}
|
|
4180
|
+
function canonicalDigest(value) {
|
|
4181
|
+
if (value === void 0) return null;
|
|
4182
|
+
const encoded = encodeCanonicalStructured(value);
|
|
4183
|
+
return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
|
|
4184
|
+
}
|
|
4185
|
+
function capturedContentDigest(attributes) {
|
|
4186
|
+
if (!attributes || typeof attributes !== "object") {
|
|
4187
|
+
return { args: null, result: null };
|
|
4188
|
+
}
|
|
4189
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
|
|
4190
|
+
const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
|
|
4191
|
+
const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
|
|
4192
|
+
return {
|
|
4193
|
+
args: args === void 0 ? null : canonicalDigest(args),
|
|
4194
|
+
result: result === void 0 ? null : canonicalDigest(result)
|
|
4195
|
+
};
|
|
4196
|
+
}
|
|
4197
|
+
function timeKey(fields) {
|
|
4198
|
+
if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
|
|
4199
|
+
return fields.startedAt;
|
|
4200
|
+
}
|
|
4201
|
+
if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
|
|
4202
|
+
return fields.timestamp;
|
|
4203
|
+
}
|
|
4204
|
+
if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
|
|
4205
|
+
return String(fields.timestamp);
|
|
4206
|
+
}
|
|
4207
|
+
return null;
|
|
4208
|
+
}
|
|
4209
|
+
function deliverySemanticFingerprint(fields) {
|
|
4210
|
+
const content = capturedContentDigest(fields.attributes);
|
|
4211
|
+
return JSON.stringify({
|
|
4212
|
+
stableEventId: stripReaderDeliveryDiscriminator(fields.eventId, fields.attributes),
|
|
4213
|
+
runId: fields.runId,
|
|
4214
|
+
kind: fields.kind,
|
|
4215
|
+
name: fields.name,
|
|
4216
|
+
status: fields.status ?? null,
|
|
4217
|
+
parentId: fields.parentId ?? null,
|
|
4218
|
+
sourceType: fields.sourceType ?? null,
|
|
4219
|
+
time: timeKey(fields),
|
|
4220
|
+
operationId: fields.operationId ?? null,
|
|
4221
|
+
attemptId: fields.attemptId ?? null,
|
|
4222
|
+
attemptNumber: fields.attemptNumber ?? null,
|
|
4223
|
+
retryOf: fields.retryOf ?? null,
|
|
4224
|
+
argsDigest: content.args,
|
|
4225
|
+
resultDigest: content.result
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
function identityFieldsFromAttributes(attributes) {
|
|
4229
|
+
if (!attributes || typeof attributes !== "object") {
|
|
4230
|
+
return {
|
|
4231
|
+
operationId: null,
|
|
4232
|
+
attemptId: null,
|
|
4233
|
+
attemptNumber: null,
|
|
4234
|
+
retryOf: null
|
|
4235
|
+
};
|
|
4236
|
+
}
|
|
4237
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? attributes.metadata : void 0;
|
|
4238
|
+
const pickString3 = (key) => {
|
|
4239
|
+
const direct = attributes[key];
|
|
4240
|
+
if (typeof direct === "string" && direct.trim() !== "") return direct.trim();
|
|
4241
|
+
const nestedValue = nested?.[key];
|
|
4242
|
+
if (typeof nestedValue === "string" && nestedValue.trim() !== "") {
|
|
4243
|
+
return nestedValue.trim();
|
|
4244
|
+
}
|
|
4245
|
+
return null;
|
|
4246
|
+
};
|
|
4247
|
+
const pickNumber2 = () => {
|
|
4248
|
+
const direct = attributes.attemptNumber ?? attributes.attempt;
|
|
4249
|
+
if (typeof direct === "number" && Number.isFinite(direct)) return direct;
|
|
4250
|
+
const nestedValue = nested?.attemptNumber ?? nested?.attempt;
|
|
4251
|
+
if (typeof nestedValue === "number" && Number.isFinite(nestedValue)) {
|
|
4252
|
+
return nestedValue;
|
|
4253
|
+
}
|
|
4254
|
+
return null;
|
|
4255
|
+
};
|
|
4256
|
+
return {
|
|
4257
|
+
operationId: pickString3("operationId"),
|
|
4258
|
+
attemptId: pickString3("attemptId"),
|
|
4259
|
+
retryOf: pickString3("retryOf"),
|
|
4260
|
+
attemptNumber: pickNumber2()
|
|
4261
|
+
};
|
|
4262
|
+
}
|
|
4263
|
+
function stampDeliveryConflict(event) {
|
|
4264
|
+
return {
|
|
4265
|
+
...event,
|
|
4266
|
+
attributes: {
|
|
4267
|
+
...event.attributes ?? {},
|
|
4268
|
+
[DELIVERY_CONFLICT_ATTR]: true
|
|
4269
|
+
}
|
|
4270
|
+
};
|
|
4271
|
+
}
|
|
4272
|
+
|
|
4095
4273
|
// packages/core/src/checks/contract.ts
|
|
4096
4274
|
new Set(OBSERVED_OUTCOME_METHODS);
|
|
4097
4275
|
|
|
@@ -4129,18 +4307,18 @@ function escapeMarkdown(value) {
|
|
|
4129
4307
|
function escapeHtml(value) {
|
|
4130
4308
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4131
4309
|
}
|
|
4132
|
-
function
|
|
4310
|
+
function sortKeysDeep2(input) {
|
|
4133
4311
|
if (input === null || typeof input !== "object") return input;
|
|
4134
|
-
if (Array.isArray(input)) return input.map(
|
|
4312
|
+
if (Array.isArray(input)) return input.map(sortKeysDeep2);
|
|
4135
4313
|
const o = input;
|
|
4136
4314
|
const out = {};
|
|
4137
4315
|
for (const k of Object.keys(o).sort()) {
|
|
4138
|
-
out[k] =
|
|
4316
|
+
out[k] = sortKeysDeep2(o[k]);
|
|
4139
4317
|
}
|
|
4140
4318
|
return out;
|
|
4141
4319
|
}
|
|
4142
4320
|
function stableJson(value, pretty) {
|
|
4143
|
-
const sorted =
|
|
4321
|
+
const sorted = sortKeysDeep2(value);
|
|
4144
4322
|
return pretty === true ? JSON.stringify(sorted, null, 2) : JSON.stringify(sorted);
|
|
4145
4323
|
}
|
|
4146
4324
|
function compactAttributes(attrs2, options) {
|
|
@@ -4677,6 +4855,11 @@ function compactAttributes2(entries) {
|
|
|
4677
4855
|
}
|
|
4678
4856
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
4679
4857
|
}
|
|
4858
|
+
function stampDeliveryEventBase(eventId, attributes) {
|
|
4859
|
+
const base = deliveryEventBaseFromIndexedId(eventId);
|
|
4860
|
+
if (!base) return attributes;
|
|
4861
|
+
return { ...attributes ?? {}, [DELIVERY_EVENT_BASE_ATTR]: base };
|
|
4862
|
+
}
|
|
4680
4863
|
function traceEventToPersistedInspectEvent(event, options) {
|
|
4681
4864
|
const eventIndex = options?.eventIndex ?? 0;
|
|
4682
4865
|
const eventId = createPersistedEventId(event, eventIndex);
|
|
@@ -4706,7 +4889,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
4706
4889
|
startedAt: tsStart.iso,
|
|
4707
4890
|
confidence: "explicit",
|
|
4708
4891
|
source,
|
|
4709
|
-
attributes
|
|
4892
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
4710
4893
|
};
|
|
4711
4894
|
}
|
|
4712
4895
|
case "run_completed": {
|
|
@@ -4729,7 +4912,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
4729
4912
|
durationMs: event.durationMs,
|
|
4730
4913
|
confidence: "explicit",
|
|
4731
4914
|
source,
|
|
4732
|
-
attributes,
|
|
4915
|
+
attributes: stampDeliveryEventBase(eventId, attributes),
|
|
4733
4916
|
error
|
|
4734
4917
|
};
|
|
4735
4918
|
}
|
|
@@ -4754,7 +4937,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
4754
4937
|
startedAt: tsStart.iso,
|
|
4755
4938
|
confidence: "explicit",
|
|
4756
4939
|
source,
|
|
4757
|
-
attributes
|
|
4940
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
4758
4941
|
};
|
|
4759
4942
|
if (event.parentId !== void 0) {
|
|
4760
4943
|
out.parentId = event.parentId;
|
|
@@ -4785,7 +4968,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
4785
4968
|
durationMs: event.durationMs,
|
|
4786
4969
|
confidence: "explicit",
|
|
4787
4970
|
source,
|
|
4788
|
-
attributes,
|
|
4971
|
+
attributes: stampDeliveryEventBase(eventId, attributes),
|
|
4789
4972
|
error
|
|
4790
4973
|
};
|
|
4791
4974
|
}
|
|
@@ -4812,7 +4995,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
4812
4995
|
timestamp: tsMain.iso,
|
|
4813
4996
|
confidence: "explicit",
|
|
4814
4997
|
source,
|
|
4815
|
-
attributes
|
|
4998
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
4816
4999
|
};
|
|
4817
5000
|
if (event.parentId !== void 0) {
|
|
4818
5001
|
out.parentId = event.parentId;
|
|
@@ -4965,7 +5148,47 @@ var TreeBuilder = class {
|
|
|
4965
5148
|
const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);
|
|
4966
5149
|
const nodes = /* @__PURE__ */ new Map();
|
|
4967
5150
|
for (const e of sorted) {
|
|
4968
|
-
nodes.
|
|
5151
|
+
const existing = nodes.get(e.eventId);
|
|
5152
|
+
if (!existing) {
|
|
5153
|
+
nodes.set(e.eventId, { event: e, children: [], depth: 0 });
|
|
5154
|
+
continue;
|
|
5155
|
+
}
|
|
5156
|
+
const existingAttrs = existing.event.attributes && typeof existing.event.attributes === "object" ? existing.event.attributes : void 0;
|
|
5157
|
+
const nextAttrs = e.attributes && typeof e.attributes === "object" ? e.attributes : void 0;
|
|
5158
|
+
const existingIdentity = identityFieldsFromAttributes(existingAttrs);
|
|
5159
|
+
const nextIdentity = identityFieldsFromAttributes(nextAttrs);
|
|
5160
|
+
const existingFp = deliverySemanticFingerprint({
|
|
5161
|
+
eventId: existing.event.eventId,
|
|
5162
|
+
runId: existing.event.runId,
|
|
5163
|
+
kind: existing.event.kind,
|
|
5164
|
+
name: existing.event.name,
|
|
5165
|
+
status: existing.event.status,
|
|
5166
|
+
parentId: existing.event.parentId,
|
|
5167
|
+
timestamp: existing.event.timestamp,
|
|
5168
|
+
sourceType: existing.event.source?.type,
|
|
5169
|
+
attributes: existingAttrs,
|
|
5170
|
+
...existingIdentity
|
|
5171
|
+
});
|
|
5172
|
+
const nextFp = deliverySemanticFingerprint({
|
|
5173
|
+
eventId: e.eventId,
|
|
5174
|
+
runId: e.runId,
|
|
5175
|
+
kind: e.kind,
|
|
5176
|
+
name: e.name,
|
|
5177
|
+
status: e.status,
|
|
5178
|
+
parentId: e.parentId,
|
|
5179
|
+
timestamp: e.timestamp,
|
|
5180
|
+
sourceType: e.source?.type,
|
|
5181
|
+
attributes: nextAttrs,
|
|
5182
|
+
...nextIdentity
|
|
5183
|
+
});
|
|
5184
|
+
if (existingFp === nextFp) {
|
|
5185
|
+
continue;
|
|
5186
|
+
}
|
|
5187
|
+
nodes.set(e.eventId, {
|
|
5188
|
+
event: stampDeliveryConflict(e),
|
|
5189
|
+
children: [],
|
|
5190
|
+
depth: 0
|
|
5191
|
+
});
|
|
4969
5192
|
}
|
|
4970
5193
|
const { roots, summary } = linkNodesVisibilityFirst(nodes);
|
|
4971
5194
|
const confidenceBreakdown = {
|
|
@@ -6430,6 +6653,12 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
6430
6653
|
["agent_inspect.retry_of", "retryOf", "string"],
|
|
6431
6654
|
["agent_inspect.attempt_number", "attemptNumber", "int"]
|
|
6432
6655
|
];
|
|
6656
|
+
const conflictMapping = [
|
|
6657
|
+
["agent_inspect.identity_conflict.operation_id", "operationId", "string"],
|
|
6658
|
+
["agent_inspect.identity_conflict.attempt_id", "attemptId", "string"],
|
|
6659
|
+
["agent_inspect.identity_conflict.retry_of", "retryOf", "string"],
|
|
6660
|
+
["agent_inspect.identity_conflict.attempt_number", "attemptNumber", "int"]
|
|
6661
|
+
];
|
|
6433
6662
|
const metadata = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? { ...attributes.metadata } : {};
|
|
6434
6663
|
for (const [dotted, camel, kind] of mapping) {
|
|
6435
6664
|
const raw = attributes[dotted];
|
|
@@ -6481,6 +6710,55 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
6481
6710
|
if (direct === void 0) attributes[camel] = promoted;
|
|
6482
6711
|
if (nested === void 0) metadata[camel] = promoted;
|
|
6483
6712
|
}
|
|
6713
|
+
for (const [dotted, camel, kind] of conflictMapping) {
|
|
6714
|
+
const raw = attributes[dotted];
|
|
6715
|
+
if (raw === void 0 || raw === null) continue;
|
|
6716
|
+
let alternate;
|
|
6717
|
+
if (kind === "int") {
|
|
6718
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
|
|
6719
|
+
if (!Number.isFinite(n) || n < 1) {
|
|
6720
|
+
warnings.push({
|
|
6721
|
+
code: "otlp_identity_invalid",
|
|
6722
|
+
message: `Ignoring invalid ${dotted} identity conflict value.`,
|
|
6723
|
+
severity: "warning",
|
|
6724
|
+
field: `${pathPrefix}.${dotted}`
|
|
6725
|
+
});
|
|
6726
|
+
continue;
|
|
6727
|
+
}
|
|
6728
|
+
alternate = Math.trunc(n);
|
|
6729
|
+
} else if (typeof raw === "string" && raw.trim() !== "") {
|
|
6730
|
+
alternate = raw.trim();
|
|
6731
|
+
} else {
|
|
6732
|
+
warnings.push({
|
|
6733
|
+
code: "otlp_identity_invalid",
|
|
6734
|
+
message: `Ignoring non-string ${dotted} identity conflict value.`,
|
|
6735
|
+
severity: "warning",
|
|
6736
|
+
field: `${pathPrefix}.${dotted}`
|
|
6737
|
+
});
|
|
6738
|
+
continue;
|
|
6739
|
+
}
|
|
6740
|
+
const preferred = attributes[camel];
|
|
6741
|
+
if (preferred !== void 0 && preferred !== alternate) {
|
|
6742
|
+
metadata[camel] = alternate;
|
|
6743
|
+
warnings.push({
|
|
6744
|
+
code: "otlp_identity_conflict",
|
|
6745
|
+
message: `Conflicting ${camel}: attributes.${camel} vs nested alternate from ${dotted}; retaining both.`,
|
|
6746
|
+
severity: "warning",
|
|
6747
|
+
field: `${pathPrefix}.${dotted}`
|
|
6748
|
+
});
|
|
6749
|
+
} else if (preferred === void 0) {
|
|
6750
|
+
metadata[camel] = alternate;
|
|
6751
|
+
}
|
|
6752
|
+
}
|
|
6753
|
+
const conflictFields = attributes["agent_inspect.identity_conflict.fields"];
|
|
6754
|
+
if (typeof conflictFields === "string" && conflictFields.trim() !== "") {
|
|
6755
|
+
warnings.push({
|
|
6756
|
+
code: "otlp_identity_conflict",
|
|
6757
|
+
message: `Identity representation conflict fields retained after OTLP bounding: ${conflictFields.trim().slice(0, 200)}.`,
|
|
6758
|
+
severity: "warning",
|
|
6759
|
+
field: `${pathPrefix}.agent_inspect.identity_conflict.fields`
|
|
6760
|
+
});
|
|
6761
|
+
}
|
|
6484
6762
|
if (Object.keys(metadata).length > 0) {
|
|
6485
6763
|
attributes.metadata = metadata;
|
|
6486
6764
|
}
|
|
@@ -7667,43 +7945,85 @@ var STRUCTURAL_IDENTITY_KEYS = [
|
|
|
7667
7945
|
"attemptNumber",
|
|
7668
7946
|
"attempt"
|
|
7669
7947
|
];
|
|
7670
|
-
function
|
|
7948
|
+
function nestedBag(bag) {
|
|
7671
7949
|
if (!bag || typeof bag !== "object") return void 0;
|
|
7672
|
-
const
|
|
7673
|
-
if (typeof
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
if (
|
|
7678
|
-
|
|
7950
|
+
const nested = bag.metadata;
|
|
7951
|
+
if (!nested || typeof nested !== "object" || Array.isArray(nested)) return void 0;
|
|
7952
|
+
return nested;
|
|
7953
|
+
}
|
|
7954
|
+
function pickBoundedIdentityString(bag, key, maxLen) {
|
|
7955
|
+
if (!bag || typeof bag !== "object") return {};
|
|
7956
|
+
const directRaw = bag[key];
|
|
7957
|
+
const nestedRaw = nestedBag(bag)?.[key];
|
|
7958
|
+
const directFull = typeof directRaw === "string" && directRaw.trim() !== "" ? directRaw.trim() : void 0;
|
|
7959
|
+
const nestedFull = typeof nestedRaw === "string" && nestedRaw.trim() !== "" ? nestedRaw.trim() : void 0;
|
|
7960
|
+
const direct = directFull !== void 0 ? directFull.slice(0, maxLen) : void 0;
|
|
7961
|
+
const nested = nestedFull !== void 0 ? nestedFull.slice(0, maxLen) : void 0;
|
|
7962
|
+
if (directFull !== void 0 && nestedFull !== void 0 && directFull !== nestedFull) {
|
|
7963
|
+
return {
|
|
7964
|
+
value: direct,
|
|
7965
|
+
conflictAlternate: nested,
|
|
7966
|
+
truncatedCollision: direct === nested
|
|
7967
|
+
};
|
|
7679
7968
|
}
|
|
7680
|
-
|
|
7969
|
+
if (direct !== void 0) return { value: direct };
|
|
7970
|
+
if (nested !== void 0) return { value: nested };
|
|
7971
|
+
return {};
|
|
7681
7972
|
}
|
|
7682
7973
|
function pickBoundedIdentityNumber(bag, key) {
|
|
7683
|
-
if (!bag || typeof bag !== "object") return
|
|
7684
|
-
const
|
|
7685
|
-
|
|
7686
|
-
const
|
|
7687
|
-
|
|
7688
|
-
|
|
7974
|
+
if (!bag || typeof bag !== "object") return {};
|
|
7975
|
+
const directRaw = bag[key];
|
|
7976
|
+
const nestedRaw = nestedBag(bag)?.[key];
|
|
7977
|
+
const direct = typeof directRaw === "number" && Number.isFinite(directRaw) ? directRaw : void 0;
|
|
7978
|
+
const nested = typeof nestedRaw === "number" && Number.isFinite(nestedRaw) ? nestedRaw : void 0;
|
|
7979
|
+
if (direct !== void 0 && nested !== void 0 && direct !== nested) {
|
|
7980
|
+
return { value: direct, conflictAlternate: nested };
|
|
7981
|
+
}
|
|
7982
|
+
if (direct !== void 0) return { value: direct };
|
|
7983
|
+
if (nested !== void 0) return { value: nested };
|
|
7984
|
+
return {};
|
|
7689
7985
|
}
|
|
7690
7986
|
function appendStructuralIdentityAttrs(attrs2, meta, maxLen) {
|
|
7691
|
-
const
|
|
7692
|
-
|
|
7693
|
-
|
|
7987
|
+
const conflicts = [];
|
|
7988
|
+
const emitString = (key, otlpKey, conflictKey) => {
|
|
7989
|
+
const picked = pickBoundedIdentityString(meta, key, maxLen);
|
|
7990
|
+
if (picked.value !== void 0) {
|
|
7991
|
+
attrs2.push(stringAttr2(otlpKey, picked.value));
|
|
7992
|
+
}
|
|
7993
|
+
if (picked.conflictAlternate !== void 0 || picked.truncatedCollision) {
|
|
7994
|
+
if (picked.conflictAlternate !== void 0) {
|
|
7995
|
+
attrs2.push(stringAttr2(conflictKey, picked.conflictAlternate));
|
|
7996
|
+
}
|
|
7997
|
+
conflicts.push(key);
|
|
7998
|
+
}
|
|
7999
|
+
};
|
|
8000
|
+
emitString("operationId", "agent_inspect.operation_id", IDENTITY_CONFLICT_ATTR.operationId);
|
|
8001
|
+
emitString("attemptId", "agent_inspect.attempt_id", IDENTITY_CONFLICT_ATTR.attemptId);
|
|
8002
|
+
emitString("retryOf", "agent_inspect.retry_of", IDENTITY_CONFLICT_ATTR.retryOf);
|
|
8003
|
+
const attemptNumberPrimary = pickBoundedIdentityNumber(meta, "attemptNumber");
|
|
8004
|
+
const attemptNumber = attemptNumberPrimary.value !== void 0 || attemptNumberPrimary.conflictAlternate !== void 0 ? attemptNumberPrimary : pickBoundedIdentityNumber(meta, "attempt");
|
|
8005
|
+
if (attemptNumber.value !== void 0) {
|
|
8006
|
+
attrs2.push(intAttr("agent_inspect.attempt_number", attemptNumber.value));
|
|
8007
|
+
}
|
|
8008
|
+
if (attemptNumber.conflictAlternate !== void 0) {
|
|
8009
|
+
attrs2.push(
|
|
8010
|
+
intAttr(IDENTITY_CONFLICT_ATTR.attemptNumber, attemptNumber.conflictAlternate)
|
|
8011
|
+
);
|
|
8012
|
+
conflicts.push("attemptNumber");
|
|
7694
8013
|
}
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
8014
|
+
if (conflicts.length > 0) {
|
|
8015
|
+
attrs2.push(
|
|
8016
|
+
stringAttr2(IDENTITY_CONFLICT_ATTR.fields, conflicts.join(",").slice(0, maxLen))
|
|
8017
|
+
);
|
|
7698
8018
|
}
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
attrs2.push(stringAttr2("agent_inspect.retry_of", retryOf));
|
|
8019
|
+
if (meta?.[DELIVERY_CONFLICT_ATTR] === true) {
|
|
8020
|
+
attrs2.push(boolAttr(DELIVERY_CONFLICT_ATTR, true));
|
|
7702
8021
|
}
|
|
7703
|
-
const
|
|
7704
|
-
if (
|
|
7705
|
-
attrs2.push(
|
|
8022
|
+
const deliveryBase = meta?.[DELIVERY_EVENT_BASE_ATTR];
|
|
8023
|
+
if (typeof deliveryBase === "string" && deliveryBase.trim() !== "") {
|
|
8024
|
+
attrs2.push(stringAttr2(DELIVERY_EVENT_BASE_ATTR, deliveryBase.trim().slice(0, maxLen)));
|
|
7706
8025
|
}
|
|
8026
|
+
return conflicts;
|
|
7707
8027
|
}
|
|
7708
8028
|
function resolveSpanTimes(ev) {
|
|
7709
8029
|
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
@@ -7726,7 +8046,8 @@ function exportOtlpJson(tree, options) {
|
|
|
7726
8046
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
7727
8047
|
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
7728
8048
|
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1).",
|
|
7729
|
-
"When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump)."
|
|
8049
|
+
"When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump).",
|
|
8050
|
+
"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."
|
|
7730
8051
|
];
|
|
7731
8052
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
7732
8053
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -7774,11 +8095,16 @@ function exportOtlpJson(tree, options) {
|
|
|
7774
8095
|
if (typeof inp === "number") attrs2.push(intAttr("gen_ai.usage.input_tokens", inp));
|
|
7775
8096
|
if (typeof outp === "number") attrs2.push(intAttr("gen_ai.usage.output_tokens", outp));
|
|
7776
8097
|
}
|
|
7777
|
-
appendStructuralIdentityAttrs(
|
|
8098
|
+
const identityConflicts = appendStructuralIdentityAttrs(
|
|
7778
8099
|
attrs2,
|
|
7779
8100
|
meta && typeof meta === "object" ? meta : void 0,
|
|
7780
8101
|
maxLen
|
|
7781
8102
|
);
|
|
8103
|
+
if (identityConflicts.length > 0) {
|
|
8104
|
+
warnings.push(
|
|
8105
|
+
`Identity representation conflict on event ${ev.eventId}: ${identityConflicts.join(", ")} (direct preferred; nested retained on agent_inspect.identity_conflict.*).`
|
|
8106
|
+
);
|
|
8107
|
+
}
|
|
7782
8108
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
7783
8109
|
const skipKeys = /* @__PURE__ */ new Set([
|
|
7784
8110
|
"tokens",
|