@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.
@@ -4082,6 +4082,184 @@ function runTraceChecks(input, options = {}) {
4082
4082
  };
4083
4083
  }
4084
4084
 
4085
+ // packages/core/src/checks/canonical-equality.ts
4086
+ var DEFAULT_MAX_DEPTH = 8;
4087
+ var DEFAULT_MAX_BYTES = 16384;
4088
+ function sortKeysDeep(input, depth, maxDepth) {
4089
+ if (depth > maxDepth) {
4090
+ throw new Error("AI_CHECK_CANONICAL_DEPTH_EXCEEDED");
4091
+ }
4092
+ if (input === null || typeof input !== "object") return input;
4093
+ if (Array.isArray(input)) {
4094
+ return input.map((item) => sortKeysDeep(item, depth + 1, maxDepth));
4095
+ }
4096
+ const record = input;
4097
+ const out = {};
4098
+ for (const key of Object.keys(record).sort()) {
4099
+ out[key] = sortKeysDeep(record[key], depth + 1, maxDepth);
4100
+ }
4101
+ return out;
4102
+ }
4103
+ function encodeCanonicalStructured(value, limits) {
4104
+ const maxDepth = DEFAULT_MAX_DEPTH;
4105
+ const maxBytes = DEFAULT_MAX_BYTES;
4106
+ try {
4107
+ const sorted = sortKeysDeep(value, 0, maxDepth);
4108
+ const encoded = JSON.stringify(sorted);
4109
+ if (encoded === void 0) {
4110
+ return {
4111
+ ok: false,
4112
+ reason: "Value is not JSON-serializable for canonical comparison.",
4113
+ code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
4114
+ };
4115
+ }
4116
+ if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
4117
+ return {
4118
+ ok: false,
4119
+ reason: "Canonical structured value exceeds bounded size limit.",
4120
+ code: "AI_CHECK_CANONICAL_SIZE_EXCEEDED"
4121
+ };
4122
+ }
4123
+ return { ok: true, value: encoded };
4124
+ } catch (error) {
4125
+ const message = error instanceof Error ? error.message : String(error);
4126
+ if (message === "AI_CHECK_CANONICAL_DEPTH_EXCEEDED") {
4127
+ return {
4128
+ ok: false,
4129
+ reason: "Canonical structured value exceeds bounded depth limit.",
4130
+ code: "AI_CHECK_CANONICAL_DEPTH_EXCEEDED"
4131
+ };
4132
+ }
4133
+ return {
4134
+ ok: false,
4135
+ reason: "Canonical structured encoding failed.",
4136
+ code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
4137
+ };
4138
+ }
4139
+ }
4140
+
4141
+ // packages/core/src/persisted/delivery-identity.ts
4142
+ var DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
4143
+ var DELIVERY_EVENT_BASE_ATTR = "agent_inspect.delivery_event_base";
4144
+ var IDENTITY_CONFLICT_ATTR = {
4145
+ operationId: "agent_inspect.identity_conflict.operation_id",
4146
+ attemptId: "agent_inspect.identity_conflict.attempt_id",
4147
+ retryOf: "agent_inspect.identity_conflict.retry_of",
4148
+ attemptNumber: "agent_inspect.identity_conflict.attempt_number",
4149
+ /** Comma-separated field names when a conflict survives lossy bounding. */
4150
+ fields: "agent_inspect.identity_conflict.fields"
4151
+ };
4152
+ var MAX_DELIVERY_BASE_LEN = 500;
4153
+ function stripReaderDeliveryDiscriminator(eventId, attributes) {
4154
+ if (!eventId) return eventId;
4155
+ const rawBase = attributes?.[DELIVERY_EVENT_BASE_ATTR];
4156
+ if (typeof rawBase !== "string" || rawBase.trim() === "") return eventId;
4157
+ const base = rawBase.trim().slice(0, MAX_DELIVERY_BASE_LEN);
4158
+ if (eventId === base) return base;
4159
+ const prefix = `${base}:`;
4160
+ if (!eventId.startsWith(prefix)) return eventId;
4161
+ const suffix = eventId.slice(prefix.length);
4162
+ if (/^\d+$/.test(suffix)) return base;
4163
+ return eventId;
4164
+ }
4165
+ function deliveryEventBaseFromIndexedId(eventId) {
4166
+ if (!/:\d+$/.test(eventId)) return void 0;
4167
+ const base = eventId.replace(/:\d+$/, "");
4168
+ return base.length > 0 ? base.slice(0, MAX_DELIVERY_BASE_LEN) : void 0;
4169
+ }
4170
+ function canonicalDigest(value) {
4171
+ if (value === void 0) return null;
4172
+ const encoded = encodeCanonicalStructured(value);
4173
+ return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
4174
+ }
4175
+ function capturedContentDigest(attributes) {
4176
+ if (!attributes || typeof attributes !== "object") {
4177
+ return { args: null, result: null };
4178
+ }
4179
+ const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
4180
+ const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
4181
+ const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
4182
+ return {
4183
+ args: args === void 0 ? null : canonicalDigest(args),
4184
+ result: result === void 0 ? null : canonicalDigest(result)
4185
+ };
4186
+ }
4187
+ function timeKey(fields) {
4188
+ if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
4189
+ return fields.startedAt;
4190
+ }
4191
+ if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
4192
+ return fields.timestamp;
4193
+ }
4194
+ if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
4195
+ return String(fields.timestamp);
4196
+ }
4197
+ return null;
4198
+ }
4199
+ function deliverySemanticFingerprint(fields) {
4200
+ const content = capturedContentDigest(fields.attributes);
4201
+ return JSON.stringify({
4202
+ stableEventId: stripReaderDeliveryDiscriminator(fields.eventId, fields.attributes),
4203
+ runId: fields.runId,
4204
+ kind: fields.kind,
4205
+ name: fields.name,
4206
+ status: fields.status ?? null,
4207
+ parentId: fields.parentId ?? null,
4208
+ sourceType: fields.sourceType ?? null,
4209
+ time: timeKey(fields),
4210
+ operationId: fields.operationId ?? null,
4211
+ attemptId: fields.attemptId ?? null,
4212
+ attemptNumber: fields.attemptNumber ?? null,
4213
+ retryOf: fields.retryOf ?? null,
4214
+ argsDigest: content.args,
4215
+ resultDigest: content.result
4216
+ });
4217
+ }
4218
+ function identityFieldsFromAttributes(attributes) {
4219
+ if (!attributes || typeof attributes !== "object") {
4220
+ return {
4221
+ operationId: null,
4222
+ attemptId: null,
4223
+ attemptNumber: null,
4224
+ retryOf: null
4225
+ };
4226
+ }
4227
+ const nested = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? attributes.metadata : void 0;
4228
+ const pickString3 = (key) => {
4229
+ const direct = attributes[key];
4230
+ if (typeof direct === "string" && direct.trim() !== "") return direct.trim();
4231
+ const nestedValue = nested?.[key];
4232
+ if (typeof nestedValue === "string" && nestedValue.trim() !== "") {
4233
+ return nestedValue.trim();
4234
+ }
4235
+ return null;
4236
+ };
4237
+ const pickNumber2 = () => {
4238
+ const direct = attributes.attemptNumber ?? attributes.attempt;
4239
+ if (typeof direct === "number" && Number.isFinite(direct)) return direct;
4240
+ const nestedValue = nested?.attemptNumber ?? nested?.attempt;
4241
+ if (typeof nestedValue === "number" && Number.isFinite(nestedValue)) {
4242
+ return nestedValue;
4243
+ }
4244
+ return null;
4245
+ };
4246
+ return {
4247
+ operationId: pickString3("operationId"),
4248
+ attemptId: pickString3("attemptId"),
4249
+ retryOf: pickString3("retryOf"),
4250
+ attemptNumber: pickNumber2()
4251
+ };
4252
+ }
4253
+ function stampDeliveryConflict(event) {
4254
+ return {
4255
+ ...event,
4256
+ attributes: {
4257
+ ...event.attributes ?? {},
4258
+ [DELIVERY_CONFLICT_ATTR]: true
4259
+ }
4260
+ };
4261
+ }
4262
+
4085
4263
  // packages/core/src/checks/contract.ts
4086
4264
  new Set(OBSERVED_OUTCOME_METHODS);
4087
4265
 
@@ -4119,18 +4297,18 @@ function escapeMarkdown(value) {
4119
4297
  function escapeHtml(value) {
4120
4298
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
4121
4299
  }
4122
- function sortKeysDeep(input) {
4300
+ function sortKeysDeep2(input) {
4123
4301
  if (input === null || typeof input !== "object") return input;
4124
- if (Array.isArray(input)) return input.map(sortKeysDeep);
4302
+ if (Array.isArray(input)) return input.map(sortKeysDeep2);
4125
4303
  const o = input;
4126
4304
  const out = {};
4127
4305
  for (const k of Object.keys(o).sort()) {
4128
- out[k] = sortKeysDeep(o[k]);
4306
+ out[k] = sortKeysDeep2(o[k]);
4129
4307
  }
4130
4308
  return out;
4131
4309
  }
4132
4310
  function stableJson(value, pretty) {
4133
- const sorted = sortKeysDeep(value);
4311
+ const sorted = sortKeysDeep2(value);
4134
4312
  return pretty === true ? JSON.stringify(sorted, null, 2) : JSON.stringify(sorted);
4135
4313
  }
4136
4314
  function compactAttributes(attrs2, options) {
@@ -4667,6 +4845,11 @@ function compactAttributes2(entries) {
4667
4845
  }
4668
4846
  return Object.keys(out).length > 0 ? out : void 0;
4669
4847
  }
4848
+ function stampDeliveryEventBase(eventId, attributes) {
4849
+ const base = deliveryEventBaseFromIndexedId(eventId);
4850
+ if (!base) return attributes;
4851
+ return { ...attributes ?? {}, [DELIVERY_EVENT_BASE_ATTR]: base };
4852
+ }
4670
4853
  function traceEventToPersistedInspectEvent(event, options) {
4671
4854
  const eventIndex = options?.eventIndex ?? 0;
4672
4855
  const eventId = createPersistedEventId(event, eventIndex);
@@ -4696,7 +4879,7 @@ function traceEventToPersistedInspectEvent(event, options) {
4696
4879
  startedAt: tsStart.iso,
4697
4880
  confidence: "explicit",
4698
4881
  source,
4699
- attributes
4882
+ attributes: stampDeliveryEventBase(eventId, attributes)
4700
4883
  };
4701
4884
  }
4702
4885
  case "run_completed": {
@@ -4719,7 +4902,7 @@ function traceEventToPersistedInspectEvent(event, options) {
4719
4902
  durationMs: event.durationMs,
4720
4903
  confidence: "explicit",
4721
4904
  source,
4722
- attributes,
4905
+ attributes: stampDeliveryEventBase(eventId, attributes),
4723
4906
  error
4724
4907
  };
4725
4908
  }
@@ -4744,7 +4927,7 @@ function traceEventToPersistedInspectEvent(event, options) {
4744
4927
  startedAt: tsStart.iso,
4745
4928
  confidence: "explicit",
4746
4929
  source,
4747
- attributes
4930
+ attributes: stampDeliveryEventBase(eventId, attributes)
4748
4931
  };
4749
4932
  if (event.parentId !== void 0) {
4750
4933
  out.parentId = event.parentId;
@@ -4775,7 +4958,7 @@ function traceEventToPersistedInspectEvent(event, options) {
4775
4958
  durationMs: event.durationMs,
4776
4959
  confidence: "explicit",
4777
4960
  source,
4778
- attributes,
4961
+ attributes: stampDeliveryEventBase(eventId, attributes),
4779
4962
  error
4780
4963
  };
4781
4964
  }
@@ -4802,7 +4985,7 @@ function traceEventToPersistedInspectEvent(event, options) {
4802
4985
  timestamp: tsMain.iso,
4803
4986
  confidence: "explicit",
4804
4987
  source,
4805
- attributes
4988
+ attributes: stampDeliveryEventBase(eventId, attributes)
4806
4989
  };
4807
4990
  if (event.parentId !== void 0) {
4808
4991
  out.parentId = event.parentId;
@@ -4955,7 +5138,47 @@ var TreeBuilder = class {
4955
5138
  const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);
4956
5139
  const nodes = /* @__PURE__ */ new Map();
4957
5140
  for (const e of sorted) {
4958
- nodes.set(e.eventId, { event: e, children: [], depth: 0 });
5141
+ const existing = nodes.get(e.eventId);
5142
+ if (!existing) {
5143
+ nodes.set(e.eventId, { event: e, children: [], depth: 0 });
5144
+ continue;
5145
+ }
5146
+ const existingAttrs = existing.event.attributes && typeof existing.event.attributes === "object" ? existing.event.attributes : void 0;
5147
+ const nextAttrs = e.attributes && typeof e.attributes === "object" ? e.attributes : void 0;
5148
+ const existingIdentity = identityFieldsFromAttributes(existingAttrs);
5149
+ const nextIdentity = identityFieldsFromAttributes(nextAttrs);
5150
+ const existingFp = deliverySemanticFingerprint({
5151
+ eventId: existing.event.eventId,
5152
+ runId: existing.event.runId,
5153
+ kind: existing.event.kind,
5154
+ name: existing.event.name,
5155
+ status: existing.event.status,
5156
+ parentId: existing.event.parentId,
5157
+ timestamp: existing.event.timestamp,
5158
+ sourceType: existing.event.source?.type,
5159
+ attributes: existingAttrs,
5160
+ ...existingIdentity
5161
+ });
5162
+ const nextFp = deliverySemanticFingerprint({
5163
+ eventId: e.eventId,
5164
+ runId: e.runId,
5165
+ kind: e.kind,
5166
+ name: e.name,
5167
+ status: e.status,
5168
+ parentId: e.parentId,
5169
+ timestamp: e.timestamp,
5170
+ sourceType: e.source?.type,
5171
+ attributes: nextAttrs,
5172
+ ...nextIdentity
5173
+ });
5174
+ if (existingFp === nextFp) {
5175
+ continue;
5176
+ }
5177
+ nodes.set(e.eventId, {
5178
+ event: stampDeliveryConflict(e),
5179
+ children: [],
5180
+ depth: 0
5181
+ });
4959
5182
  }
4960
5183
  const { roots, summary } = linkNodesVisibilityFirst(nodes);
4961
5184
  const confidenceBreakdown = {
@@ -6420,6 +6643,12 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
6420
6643
  ["agent_inspect.retry_of", "retryOf", "string"],
6421
6644
  ["agent_inspect.attempt_number", "attemptNumber", "int"]
6422
6645
  ];
6646
+ const conflictMapping = [
6647
+ ["agent_inspect.identity_conflict.operation_id", "operationId", "string"],
6648
+ ["agent_inspect.identity_conflict.attempt_id", "attemptId", "string"],
6649
+ ["agent_inspect.identity_conflict.retry_of", "retryOf", "string"],
6650
+ ["agent_inspect.identity_conflict.attempt_number", "attemptNumber", "int"]
6651
+ ];
6423
6652
  const metadata = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? { ...attributes.metadata } : {};
6424
6653
  for (const [dotted, camel, kind] of mapping) {
6425
6654
  const raw = attributes[dotted];
@@ -6471,6 +6700,55 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
6471
6700
  if (direct === void 0) attributes[camel] = promoted;
6472
6701
  if (nested === void 0) metadata[camel] = promoted;
6473
6702
  }
6703
+ for (const [dotted, camel, kind] of conflictMapping) {
6704
+ const raw = attributes[dotted];
6705
+ if (raw === void 0 || raw === null) continue;
6706
+ let alternate;
6707
+ if (kind === "int") {
6708
+ const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
6709
+ if (!Number.isFinite(n) || n < 1) {
6710
+ warnings.push({
6711
+ code: "otlp_identity_invalid",
6712
+ message: `Ignoring invalid ${dotted} identity conflict value.`,
6713
+ severity: "warning",
6714
+ field: `${pathPrefix}.${dotted}`
6715
+ });
6716
+ continue;
6717
+ }
6718
+ alternate = Math.trunc(n);
6719
+ } else if (typeof raw === "string" && raw.trim() !== "") {
6720
+ alternate = raw.trim();
6721
+ } else {
6722
+ warnings.push({
6723
+ code: "otlp_identity_invalid",
6724
+ message: `Ignoring non-string ${dotted} identity conflict value.`,
6725
+ severity: "warning",
6726
+ field: `${pathPrefix}.${dotted}`
6727
+ });
6728
+ continue;
6729
+ }
6730
+ const preferred = attributes[camel];
6731
+ if (preferred !== void 0 && preferred !== alternate) {
6732
+ metadata[camel] = alternate;
6733
+ warnings.push({
6734
+ code: "otlp_identity_conflict",
6735
+ message: `Conflicting ${camel}: attributes.${camel} vs nested alternate from ${dotted}; retaining both.`,
6736
+ severity: "warning",
6737
+ field: `${pathPrefix}.${dotted}`
6738
+ });
6739
+ } else if (preferred === void 0) {
6740
+ metadata[camel] = alternate;
6741
+ }
6742
+ }
6743
+ const conflictFields = attributes["agent_inspect.identity_conflict.fields"];
6744
+ if (typeof conflictFields === "string" && conflictFields.trim() !== "") {
6745
+ warnings.push({
6746
+ code: "otlp_identity_conflict",
6747
+ message: `Identity representation conflict fields retained after OTLP bounding: ${conflictFields.trim().slice(0, 200)}.`,
6748
+ severity: "warning",
6749
+ field: `${pathPrefix}.agent_inspect.identity_conflict.fields`
6750
+ });
6751
+ }
6474
6752
  if (Object.keys(metadata).length > 0) {
6475
6753
  attributes.metadata = metadata;
6476
6754
  }
@@ -7657,43 +7935,85 @@ var STRUCTURAL_IDENTITY_KEYS = [
7657
7935
  "attemptNumber",
7658
7936
  "attempt"
7659
7937
  ];
7660
- function pickBoundedIdentityString(bag, key, maxLen) {
7938
+ function nestedBag(bag) {
7661
7939
  if (!bag || typeof bag !== "object") return void 0;
7662
- const direct = bag[key];
7663
- if (typeof direct === "string" && direct.trim() !== "") {
7664
- return direct.trim().slice(0, maxLen);
7665
- }
7666
- const nested = bag.metadata && typeof bag.metadata === "object" ? bag.metadata[key] : void 0;
7667
- if (typeof nested === "string" && nested.trim() !== "") {
7668
- return nested.trim().slice(0, maxLen);
7940
+ const nested = bag.metadata;
7941
+ if (!nested || typeof nested !== "object" || Array.isArray(nested)) return void 0;
7942
+ return nested;
7943
+ }
7944
+ function pickBoundedIdentityString(bag, key, maxLen) {
7945
+ if (!bag || typeof bag !== "object") return {};
7946
+ const directRaw = bag[key];
7947
+ const nestedRaw = nestedBag(bag)?.[key];
7948
+ const directFull = typeof directRaw === "string" && directRaw.trim() !== "" ? directRaw.trim() : void 0;
7949
+ const nestedFull = typeof nestedRaw === "string" && nestedRaw.trim() !== "" ? nestedRaw.trim() : void 0;
7950
+ const direct = directFull !== void 0 ? directFull.slice(0, maxLen) : void 0;
7951
+ const nested = nestedFull !== void 0 ? nestedFull.slice(0, maxLen) : void 0;
7952
+ if (directFull !== void 0 && nestedFull !== void 0 && directFull !== nestedFull) {
7953
+ return {
7954
+ value: direct,
7955
+ conflictAlternate: nested,
7956
+ truncatedCollision: direct === nested
7957
+ };
7669
7958
  }
7670
- return void 0;
7959
+ if (direct !== void 0) return { value: direct };
7960
+ if (nested !== void 0) return { value: nested };
7961
+ return {};
7671
7962
  }
7672
7963
  function pickBoundedIdentityNumber(bag, key) {
7673
- if (!bag || typeof bag !== "object") return void 0;
7674
- const direct = bag[key];
7675
- if (typeof direct === "number" && Number.isFinite(direct)) return direct;
7676
- const nested = bag.metadata && typeof bag.metadata === "object" ? bag.metadata[key] : void 0;
7677
- if (typeof nested === "number" && Number.isFinite(nested)) return nested;
7678
- return void 0;
7964
+ if (!bag || typeof bag !== "object") return {};
7965
+ const directRaw = bag[key];
7966
+ const nestedRaw = nestedBag(bag)?.[key];
7967
+ const direct = typeof directRaw === "number" && Number.isFinite(directRaw) ? directRaw : void 0;
7968
+ const nested = typeof nestedRaw === "number" && Number.isFinite(nestedRaw) ? nestedRaw : void 0;
7969
+ if (direct !== void 0 && nested !== void 0 && direct !== nested) {
7970
+ return { value: direct, conflictAlternate: nested };
7971
+ }
7972
+ if (direct !== void 0) return { value: direct };
7973
+ if (nested !== void 0) return { value: nested };
7974
+ return {};
7679
7975
  }
7680
7976
  function appendStructuralIdentityAttrs(attrs2, meta, maxLen) {
7681
- const operationId = pickBoundedIdentityString(meta, "operationId", maxLen);
7682
- if (operationId !== void 0) {
7683
- attrs2.push(stringAttr2("agent_inspect.operation_id", operationId));
7977
+ const conflicts = [];
7978
+ const emitString = (key, otlpKey, conflictKey) => {
7979
+ const picked = pickBoundedIdentityString(meta, key, maxLen);
7980
+ if (picked.value !== void 0) {
7981
+ attrs2.push(stringAttr2(otlpKey, picked.value));
7982
+ }
7983
+ if (picked.conflictAlternate !== void 0 || picked.truncatedCollision) {
7984
+ if (picked.conflictAlternate !== void 0) {
7985
+ attrs2.push(stringAttr2(conflictKey, picked.conflictAlternate));
7986
+ }
7987
+ conflicts.push(key);
7988
+ }
7989
+ };
7990
+ emitString("operationId", "agent_inspect.operation_id", IDENTITY_CONFLICT_ATTR.operationId);
7991
+ emitString("attemptId", "agent_inspect.attempt_id", IDENTITY_CONFLICT_ATTR.attemptId);
7992
+ emitString("retryOf", "agent_inspect.retry_of", IDENTITY_CONFLICT_ATTR.retryOf);
7993
+ const attemptNumberPrimary = pickBoundedIdentityNumber(meta, "attemptNumber");
7994
+ const attemptNumber = attemptNumberPrimary.value !== void 0 || attemptNumberPrimary.conflictAlternate !== void 0 ? attemptNumberPrimary : pickBoundedIdentityNumber(meta, "attempt");
7995
+ if (attemptNumber.value !== void 0) {
7996
+ attrs2.push(intAttr("agent_inspect.attempt_number", attemptNumber.value));
7997
+ }
7998
+ if (attemptNumber.conflictAlternate !== void 0) {
7999
+ attrs2.push(
8000
+ intAttr(IDENTITY_CONFLICT_ATTR.attemptNumber, attemptNumber.conflictAlternate)
8001
+ );
8002
+ conflicts.push("attemptNumber");
7684
8003
  }
7685
- const attemptId = pickBoundedIdentityString(meta, "attemptId", maxLen);
7686
- if (attemptId !== void 0) {
7687
- attrs2.push(stringAttr2("agent_inspect.attempt_id", attemptId));
8004
+ if (conflicts.length > 0) {
8005
+ attrs2.push(
8006
+ stringAttr2(IDENTITY_CONFLICT_ATTR.fields, conflicts.join(",").slice(0, maxLen))
8007
+ );
7688
8008
  }
7689
- const retryOf = pickBoundedIdentityString(meta, "retryOf", maxLen);
7690
- if (retryOf !== void 0) {
7691
- attrs2.push(stringAttr2("agent_inspect.retry_of", retryOf));
8009
+ if (meta?.[DELIVERY_CONFLICT_ATTR] === true) {
8010
+ attrs2.push(boolAttr(DELIVERY_CONFLICT_ATTR, true));
7692
8011
  }
7693
- const attemptNumber = pickBoundedIdentityNumber(meta, "attemptNumber") ?? pickBoundedIdentityNumber(meta, "attempt");
7694
- if (attemptNumber !== void 0) {
7695
- attrs2.push(intAttr("agent_inspect.attempt_number", attemptNumber));
8012
+ const deliveryBase = meta?.[DELIVERY_EVENT_BASE_ATTR];
8013
+ if (typeof deliveryBase === "string" && deliveryBase.trim() !== "") {
8014
+ attrs2.push(stringAttr2(DELIVERY_EVENT_BASE_ATTR, deliveryBase.trim().slice(0, maxLen)));
7696
8015
  }
8016
+ return conflicts;
7697
8017
  }
7698
8018
  function resolveSpanTimes(ev) {
7699
8019
  const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
@@ -7716,7 +8036,8 @@ function exportOtlpJson(tree, options) {
7716
8036
  "OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
7717
8037
  "Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
7718
8038
  "Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1).",
7719
- "When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump)."
8039
+ "When present on source events, operationId/attemptId/retryOf/attemptNumber are emitted as bounded agent_inspect.* identity attributes (not a broad attribute dump).",
8040
+ "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."
7720
8041
  ];
7721
8042
  const traceId = hexFrom2(`trace:${tree.runId}`, 16);
7722
8043
  const includeAttributes = options?.includeAttributes ?? false;
@@ -7764,11 +8085,16 @@ function exportOtlpJson(tree, options) {
7764
8085
  if (typeof inp === "number") attrs2.push(intAttr("gen_ai.usage.input_tokens", inp));
7765
8086
  if (typeof outp === "number") attrs2.push(intAttr("gen_ai.usage.output_tokens", outp));
7766
8087
  }
7767
- appendStructuralIdentityAttrs(
8088
+ const identityConflicts = appendStructuralIdentityAttrs(
7768
8089
  attrs2,
7769
8090
  meta && typeof meta === "object" ? meta : void 0,
7770
8091
  maxLen
7771
8092
  );
8093
+ if (identityConflicts.length > 0) {
8094
+ warnings.push(
8095
+ `Identity representation conflict on event ${ev.eventId}: ${identityConflicts.join(", ")} (direct preferred; nested retained on agent_inspect.identity_conflict.*).`
8096
+ );
8097
+ }
7772
8098
  if (includeAttributes && meta && typeof meta === "object") {
7773
8099
  const skipKeys = /* @__PURE__ */ new Set([
7774
8100
  "tokens",
@@ -9480,5 +9806,5 @@ async function runReadOnlyMcpServer(options = {}) {
9480
9806
  }
9481
9807
 
9482
9808
  export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, MCP_SERVER_INSTRUCTIONS, READ_ONLY_TOOLS, TRACE_DATA_UNTRUSTED_WARNING, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
9483
- //# sourceMappingURL=chunk-L5YP42Q6.mjs.map
9484
- //# sourceMappingURL=chunk-L5YP42Q6.mjs.map
9809
+ //# sourceMappingURL=chunk-XLIQEKWB.mjs.map
9810
+ //# sourceMappingURL=chunk-XLIQEKWB.mjs.map