agent-inspect 6.31.7 → 6.31.9
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-QV73NM25.mjs → chunk-SWUZRRDT.mjs} +158 -21
- package/packages/cli/dist/chunk-SWUZRRDT.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +312 -52
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +156 -36
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-KFOBXFPN.mjs → src-XFIPYODW.mjs} +3 -3
- package/packages/cli/dist/{src-KFOBXFPN.mjs.map → src-XFIPYODW.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +200 -24
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +1 -1
- package/packages/core/dist/advanced.d.ts +1 -1
- package/packages/core/dist/advanced.mjs +89 -15
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.mjs +2 -2
- package/packages/core/dist/{chunk-LXYPM2ZO.mjs → chunk-2CCRUI42.mjs} +19 -318
- package/packages/core/dist/chunk-2CCRUI42.mjs.map +1 -0
- package/packages/core/dist/{chunk-QLYUWKK7.mjs → chunk-2IRRUNIN.mjs} +11 -5
- package/packages/core/dist/chunk-2IRRUNIN.mjs.map +1 -0
- package/packages/core/dist/{chunk-VQUB3WRI.mjs → chunk-3SPBELJB.mjs} +14 -3
- package/packages/core/dist/chunk-3SPBELJB.mjs.map +1 -0
- package/packages/core/dist/{chunk-3RV3JILQ.mjs → chunk-IJJSPJXV.mjs} +20 -12
- package/packages/core/dist/chunk-IJJSPJXV.mjs.map +1 -0
- package/packages/core/dist/chunk-L5WLVBW4.mjs +355 -0
- package/packages/core/dist/chunk-L5WLVBW4.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +110 -18
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +110 -18
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/index.cjs +12 -1
- package/packages/core/dist/index.cjs.map +1 -1
- package/packages/core/dist/index.mjs +2 -2
- package/packages/core/dist/persisted.cjs +344 -9
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.d.cts +8 -1
- package/packages/core/dist/persisted.d.ts +8 -1
- package/packages/core/dist/persisted.mjs +3 -2
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +377 -87
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +3 -3
- package/packages/cli/dist/chunk-QV73NM25.mjs.map +0 -1
- package/packages/core/dist/chunk-3RV3JILQ.mjs.map +0 -1
- package/packages/core/dist/chunk-FWK3Q3OJ.mjs +0 -56
- package/packages/core/dist/chunk-FWK3Q3OJ.mjs.map +0 -1
- package/packages/core/dist/chunk-LXYPM2ZO.mjs.map +0 -1
- package/packages/core/dist/chunk-QLYUWKK7.mjs.map +0 -1
- package/packages/core/dist/chunk-VQUB3WRI.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getCurrentContext, getCurrentDepth, getParentStepId, getTraceSafetyFromContext, runWithStepContext, printStepStart, printStepComplete, printError, printFailedAt, inspectRun } from './chunk-
|
|
2
|
-
export { createInspector, getCurrentCorrelationMetadata, inspectRun, maybeInspectRun } from './chunk-
|
|
1
|
+
import { getCurrentContext, getCurrentDepth, getParentStepId, getTraceSafetyFromContext, runWithStepContext, printStepStart, printStepComplete, printError, printFailedAt, inspectRun } from './chunk-3SPBELJB.mjs';
|
|
2
|
+
export { createInspector, getCurrentCorrelationMetadata, inspectRun, maybeInspectRun } from './chunk-3SPBELJB.mjs';
|
|
3
3
|
import { normalizeObserveOutcomeInput, prepareOutcomeEventForDisk } from './chunk-N5PZAI6Q.mjs';
|
|
4
4
|
import './chunk-BT7CATSD.mjs';
|
|
5
5
|
import { prepareTraceEventForDisk, writeTraceEvent } from './chunk-DK3OW6UI.mjs';
|
|
@@ -1023,12 +1023,12 @@ function persistedInspectEventToTraceEvents(event) {
|
|
|
1023
1023
|
if (!isPersistedInspectEvent(event)) {
|
|
1024
1024
|
throw new Error("Invalid PersistedInspectEvent: failed isPersistedInspectEvent");
|
|
1025
1025
|
}
|
|
1026
|
-
const
|
|
1027
|
-
if (
|
|
1028
|
-
if (
|
|
1029
|
-
if (
|
|
1030
|
-
if (
|
|
1031
|
-
if (
|
|
1026
|
+
const legacyEvent2 = event.attributes?.legacyEvent;
|
|
1027
|
+
if (legacyEvent2 === "run_started") return [fromLegacyRunStarted(event)];
|
|
1028
|
+
if (legacyEvent2 === "run_completed") return [fromLegacyRunCompleted(event)];
|
|
1029
|
+
if (legacyEvent2 === "step_started") return [fromLegacyStepStarted(event)];
|
|
1030
|
+
if (legacyEvent2 === "step_completed") return [fromLegacyStepCompleted(event)];
|
|
1031
|
+
if (legacyEvent2 === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
|
|
1032
1032
|
if (event.kind === "RUN") {
|
|
1033
1033
|
return fromNativeRun(event);
|
|
1034
1034
|
}
|
|
@@ -1049,6 +1049,336 @@ function persistedInspectEventsToTraceEvents(events, options) {
|
|
|
1049
1049
|
return out;
|
|
1050
1050
|
}
|
|
1051
1051
|
|
|
1052
|
+
// packages/core/src/diagnostics/programmatic.ts
|
|
1053
|
+
var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
|
|
1054
|
+
AI_TRACE_INPUT_INVALID: {
|
|
1055
|
+
code: "AI_TRACE_INPUT_INVALID",
|
|
1056
|
+
summary: 'Expected { type: "file", path }, { type: "directory", path }, { type: "string", content }, { type: "buffer", content }, or { type: "stdin" }.',
|
|
1057
|
+
remediation: "For a file path, use openTraceFile(path).",
|
|
1058
|
+
relatedCodes: ["invalid_input"]
|
|
1059
|
+
},
|
|
1060
|
+
AI_TRACE_FORMAT_UNSUPPORTED: {
|
|
1061
|
+
code: "AI_TRACE_FORMAT_UNSUPPORTED",
|
|
1062
|
+
summary: "No trace reader could detect the input format.",
|
|
1063
|
+
remediation: "Pass an AgentInspect JSONL file via openTraceFile, or set options.format to a registered reader.",
|
|
1064
|
+
relatedCodes: ["unsupported_format"]
|
|
1065
|
+
},
|
|
1066
|
+
AI_TRACE_FORMAT_AMBIGUOUS: {
|
|
1067
|
+
code: "AI_TRACE_FORMAT_AMBIGUOUS",
|
|
1068
|
+
summary: "Multiple trace readers matched the input with equal confidence.",
|
|
1069
|
+
remediation: "Set options.format explicitly to disambiguate the reader.",
|
|
1070
|
+
relatedCodes: ["ambiguous_format"]
|
|
1071
|
+
},
|
|
1072
|
+
AI_TRACE_FACTS_INPUT_NOT_NORMALIZED: {
|
|
1073
|
+
code: "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED",
|
|
1074
|
+
summary: "TraceFacts requires TraceReadResult or PersistedInspectEvent[].",
|
|
1075
|
+
remediation: "Use openTraceFile() to normalize a JSONL trace first."
|
|
1076
|
+
},
|
|
1077
|
+
AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED: {
|
|
1078
|
+
code: "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
|
|
1079
|
+
summary: "Multiple runs are available; select a run before executing checks.",
|
|
1080
|
+
remediation: "Pass options.runId or TraceCheckInput.selectedRun.",
|
|
1081
|
+
relatedCodes: ["AI_CHECK_RUN_SELECTION_REQUIRED"]
|
|
1082
|
+
},
|
|
1083
|
+
AI_TRACE_RELATIONSHIP_SELF_PARENT: {
|
|
1084
|
+
code: "AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
1085
|
+
summary: "A parentId equals its own event/step id.",
|
|
1086
|
+
remediation: "Reject at capture (AI_LANGGRAPH_SELF_PARENT_REJECTED) or drop via logical projection; do not invent replacement parents.",
|
|
1087
|
+
relatedCodes: [
|
|
1088
|
+
"AI_LANGGRAPH_SELF_PARENT_REJECTED",
|
|
1089
|
+
"AI_LOGICAL_SELF_PARENT_REMOVED"
|
|
1090
|
+
]
|
|
1091
|
+
},
|
|
1092
|
+
AI_TRACE_RELATIONSHIP_CYCLE: {
|
|
1093
|
+
code: "AI_TRACE_RELATIONSHIP_CYCLE",
|
|
1094
|
+
summary: "Trace contains a parentId cycle.",
|
|
1095
|
+
remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
|
|
1096
|
+
relatedCodes: ["structure.cycle"]
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
function formatProgrammaticDiagnostic(code, detail) {
|
|
1100
|
+
const spec = PROGRAMMATIC_DIAGNOSTIC_SPECS[code];
|
|
1101
|
+
const summary = detail?.trim() ? detail.trim() : spec.summary;
|
|
1102
|
+
return `${code}: ${summary} Remediation: ${spec.remediation}`;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// packages/core/src/checks/logical-events.ts
|
|
1106
|
+
function isRecord3(value) {
|
|
1107
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1108
|
+
}
|
|
1109
|
+
function legacyEvent(event) {
|
|
1110
|
+
const value = event.attributes?.legacyEvent;
|
|
1111
|
+
return typeof value === "string" ? value : void 0;
|
|
1112
|
+
}
|
|
1113
|
+
function stepIdOf(event) {
|
|
1114
|
+
const value = event.attributes?.stepId;
|
|
1115
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
1116
|
+
return void 0;
|
|
1117
|
+
}
|
|
1118
|
+
function cloneEvent(event) {
|
|
1119
|
+
return {
|
|
1120
|
+
...event,
|
|
1121
|
+
...event.attributes !== void 0 ? { attributes: { ...event.attributes } } : {},
|
|
1122
|
+
...event.error !== void 0 ? { error: { ...event.error } } : {},
|
|
1123
|
+
...event.tokenUsage !== void 0 ? { tokenUsage: { ...event.tokenUsage } } : {},
|
|
1124
|
+
...event.source !== void 0 ? { source: { ...event.source } } : {}
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
function mergeAttributes(start, complete) {
|
|
1128
|
+
const merged = {
|
|
1129
|
+
...isRecord3(complete.attributes) ? complete.attributes : {},
|
|
1130
|
+
...isRecord3(start.attributes) ? start.attributes : {}
|
|
1131
|
+
};
|
|
1132
|
+
merged.legacyEvent = start.attributes?.legacyEvent ?? complete.attributes?.legacyEvent;
|
|
1133
|
+
merged.legacyCompleteEvent = complete.attributes?.legacyEvent;
|
|
1134
|
+
if (complete.attributes?.errorStack !== void 0) {
|
|
1135
|
+
merged.errorStack = complete.attributes.errorStack;
|
|
1136
|
+
}
|
|
1137
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1138
|
+
}
|
|
1139
|
+
function pairStartComplete(start, complete) {
|
|
1140
|
+
const attributes = mergeAttributes(start, complete);
|
|
1141
|
+
const paired = {
|
|
1142
|
+
...cloneEvent(start),
|
|
1143
|
+
status: complete.status,
|
|
1144
|
+
timestamp: complete.timestamp ?? start.timestamp,
|
|
1145
|
+
...complete.endedAt !== void 0 ? { endedAt: complete.endedAt } : {},
|
|
1146
|
+
...complete.durationMs !== void 0 ? { durationMs: complete.durationMs } : {},
|
|
1147
|
+
...complete.error !== void 0 ? { error: { ...complete.error } } : {},
|
|
1148
|
+
...complete.tokenUsage !== void 0 && start.tokenUsage === void 0 ? { tokenUsage: { ...complete.tokenUsage } } : {},
|
|
1149
|
+
...attributes !== void 0 ? { attributes } : {}
|
|
1150
|
+
};
|
|
1151
|
+
return {
|
|
1152
|
+
...paired,
|
|
1153
|
+
sourceEventIds: Object.freeze([start.eventId, complete.eventId]),
|
|
1154
|
+
projection: {
|
|
1155
|
+
paired: true,
|
|
1156
|
+
absorbedEventIds: Object.freeze([complete.eventId]),
|
|
1157
|
+
parentNormalized: false,
|
|
1158
|
+
...start.parentId !== void 0 ? { originalParentId: start.parentId } : {}
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function asLogical(event, extras) {
|
|
1163
|
+
return {
|
|
1164
|
+
...cloneEvent(event),
|
|
1165
|
+
sourceEventIds: Object.freeze([event.eventId]),
|
|
1166
|
+
projection: {
|
|
1167
|
+
paired: false,
|
|
1168
|
+
absorbedEventIds: Object.freeze([]),
|
|
1169
|
+
parentNormalized: extras?.parentNormalized === true,
|
|
1170
|
+
...{}
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
function projectLogicalEvents(events) {
|
|
1175
|
+
const diagnostics = [];
|
|
1176
|
+
const byRun = /* @__PURE__ */ new Map();
|
|
1177
|
+
for (const event of events) {
|
|
1178
|
+
const list = byRun.get(event.runId) ?? [];
|
|
1179
|
+
list.push(event);
|
|
1180
|
+
byRun.set(event.runId, list);
|
|
1181
|
+
}
|
|
1182
|
+
const absorbedIds = /* @__PURE__ */ new Set();
|
|
1183
|
+
const logicalByRawId = /* @__PURE__ */ new Map();
|
|
1184
|
+
const stepIdToLogicalId = /* @__PURE__ */ new Map();
|
|
1185
|
+
const logical = [];
|
|
1186
|
+
const orderedRuns = [...byRun.keys()].sort((a, b) => a.localeCompare(b));
|
|
1187
|
+
for (const runId of orderedRuns) {
|
|
1188
|
+
const runEvents = byRun.get(runId) ?? [];
|
|
1189
|
+
const starts = [];
|
|
1190
|
+
const completes = [];
|
|
1191
|
+
const others = [];
|
|
1192
|
+
for (const event of runEvents) {
|
|
1193
|
+
const legacy = legacyEvent(event);
|
|
1194
|
+
if (legacy === "step_started" || legacy === "run_started" && event.status === "running") {
|
|
1195
|
+
starts.push(event);
|
|
1196
|
+
} else if (legacy === "step_completed" || legacy === "run_completed") {
|
|
1197
|
+
completes.push(event);
|
|
1198
|
+
} else {
|
|
1199
|
+
others.push(event);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
const usedCompletes = /* @__PURE__ */ new Set();
|
|
1203
|
+
for (const start of starts) {
|
|
1204
|
+
const stepId = stepIdOf(start);
|
|
1205
|
+
let match;
|
|
1206
|
+
if (legacyEvent(start) === "run_started") {
|
|
1207
|
+
const candidates = completes.filter(
|
|
1208
|
+
(c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "run_completed"
|
|
1209
|
+
);
|
|
1210
|
+
if (candidates.length > 1) {
|
|
1211
|
+
diagnostics.push({
|
|
1212
|
+
code: "AI_LOGICAL_PAIR_AMBIGUOUS",
|
|
1213
|
+
message: `Multiple run_completed rows for run ${runId}; using first by eventId.`,
|
|
1214
|
+
eventIds: candidates.map((c) => c.eventId)
|
|
1215
|
+
});
|
|
1216
|
+
candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
|
|
1217
|
+
}
|
|
1218
|
+
match = candidates[0];
|
|
1219
|
+
} else if (stepId) {
|
|
1220
|
+
const candidates = completes.filter(
|
|
1221
|
+
(c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "step_completed" && stepIdOf(c) === stepId
|
|
1222
|
+
);
|
|
1223
|
+
if (candidates.length > 1) {
|
|
1224
|
+
diagnostics.push({
|
|
1225
|
+
code: "AI_LOGICAL_PAIR_AMBIGUOUS",
|
|
1226
|
+
message: `Multiple step_completed rows for stepId ${stepId}; using first by eventId.`,
|
|
1227
|
+
eventIds: candidates.map((c) => c.eventId)
|
|
1228
|
+
});
|
|
1229
|
+
candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
|
|
1230
|
+
}
|
|
1231
|
+
match = candidates[0];
|
|
1232
|
+
}
|
|
1233
|
+
if (match) {
|
|
1234
|
+
usedCompletes.add(match.eventId);
|
|
1235
|
+
absorbedIds.add(match.eventId);
|
|
1236
|
+
const paired = pairStartComplete(start, match);
|
|
1237
|
+
logical.push(paired);
|
|
1238
|
+
logicalByRawId.set(start.eventId, paired);
|
|
1239
|
+
logicalByRawId.set(match.eventId, paired);
|
|
1240
|
+
if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, paired.eventId);
|
|
1241
|
+
} else {
|
|
1242
|
+
diagnostics.push({
|
|
1243
|
+
code: "AI_LOGICAL_PAIR_UNMATCHED_START",
|
|
1244
|
+
message: `No matching complete for start ${start.eventId}.`,
|
|
1245
|
+
eventIds: [start.eventId]
|
|
1246
|
+
});
|
|
1247
|
+
const alone = asLogical(start);
|
|
1248
|
+
logical.push(alone);
|
|
1249
|
+
logicalByRawId.set(start.eventId, alone);
|
|
1250
|
+
if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
for (const complete of completes) {
|
|
1254
|
+
if (usedCompletes.has(complete.eventId)) continue;
|
|
1255
|
+
diagnostics.push({
|
|
1256
|
+
code: "AI_LOGICAL_PAIR_UNMATCHED_COMPLETE",
|
|
1257
|
+
message: `No matching start for complete ${complete.eventId}.`,
|
|
1258
|
+
eventIds: [complete.eventId]
|
|
1259
|
+
});
|
|
1260
|
+
const alone = asLogical(complete);
|
|
1261
|
+
logical.push(alone);
|
|
1262
|
+
logicalByRawId.set(complete.eventId, alone);
|
|
1263
|
+
const stepId = stepIdOf(complete);
|
|
1264
|
+
if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
|
|
1265
|
+
stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
for (const event of others) {
|
|
1269
|
+
const alone = asLogical(event);
|
|
1270
|
+
logical.push(alone);
|
|
1271
|
+
logicalByRawId.set(event.eventId, alone);
|
|
1272
|
+
const stepId = stepIdOf(event);
|
|
1273
|
+
if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
|
|
1274
|
+
stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
const logicalById = new Map(logical.map((e) => [e.eventId, e]));
|
|
1279
|
+
const normalized = [];
|
|
1280
|
+
for (const event of logical) {
|
|
1281
|
+
const originalParentId = event.parentId;
|
|
1282
|
+
if (!originalParentId) {
|
|
1283
|
+
normalized.push(event);
|
|
1284
|
+
continue;
|
|
1285
|
+
}
|
|
1286
|
+
let nextParent = originalParentId;
|
|
1287
|
+
let remapped = false;
|
|
1288
|
+
const viaAbsorbed = logicalByRawId.get(originalParentId);
|
|
1289
|
+
if (viaAbsorbed && viaAbsorbed.eventId !== originalParentId) {
|
|
1290
|
+
nextParent = viaAbsorbed.eventId;
|
|
1291
|
+
remapped = true;
|
|
1292
|
+
} else if (!logicalById.has(originalParentId)) {
|
|
1293
|
+
const viaStep = stepIdToLogicalId.get(`${event.runId}:${originalParentId}`);
|
|
1294
|
+
if (viaStep) {
|
|
1295
|
+
nextParent = viaStep;
|
|
1296
|
+
remapped = true;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
if (!remapped) {
|
|
1300
|
+
if (originalParentId === event.eventId) {
|
|
1301
|
+
diagnostics.push({
|
|
1302
|
+
code: "AI_LOGICAL_SELF_PARENT_REMOVED",
|
|
1303
|
+
message: formatProgrammaticDiagnostic(
|
|
1304
|
+
"AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
1305
|
+
`Removed self-parent edge on ${event.eventId}.`
|
|
1306
|
+
),
|
|
1307
|
+
eventIds: [event.eventId]
|
|
1308
|
+
});
|
|
1309
|
+
const { parentId: _drop, ...rest } = event;
|
|
1310
|
+
normalized.push({
|
|
1311
|
+
...rest,
|
|
1312
|
+
projection: {
|
|
1313
|
+
...event.projection,
|
|
1314
|
+
parentNormalized: true,
|
|
1315
|
+
originalParentId
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
|
|
1321
|
+
const mapping = event.attributes?.parentMapping;
|
|
1322
|
+
const unresolved = mapping === "unresolved" || event.attributes?.parentUnresolved === true || event.attributes?.unresolvedParent === true || // LangGraph/framework scaffolding sentinel labels are not event ids.
|
|
1323
|
+
/^LangGraph$/i.test(originalParentId) || originalParentId.startsWith("unresolved:");
|
|
1324
|
+
if (!unresolved) {
|
|
1325
|
+
diagnostics.push({
|
|
1326
|
+
code: "AI_LOGICAL_PARENT_UNRESOLVED",
|
|
1327
|
+
message: `Parent ${originalParentId} unresolved for ${event.eventId}.`,
|
|
1328
|
+
eventIds: [event.eventId]
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
normalized.push(event);
|
|
1333
|
+
continue;
|
|
1334
|
+
}
|
|
1335
|
+
if (nextParent === event.eventId) {
|
|
1336
|
+
diagnostics.push({
|
|
1337
|
+
code: "AI_LOGICAL_SELF_PARENT_REMOVED",
|
|
1338
|
+
message: formatProgrammaticDiagnostic(
|
|
1339
|
+
"AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
1340
|
+
`Removed self-parent edge on ${event.eventId} (was ${originalParentId}).`
|
|
1341
|
+
),
|
|
1342
|
+
eventIds: [event.eventId]
|
|
1343
|
+
});
|
|
1344
|
+
const { parentId: _drop, ...rest } = event;
|
|
1345
|
+
normalized.push({
|
|
1346
|
+
...rest,
|
|
1347
|
+
projection: {
|
|
1348
|
+
...event.projection,
|
|
1349
|
+
parentNormalized: true,
|
|
1350
|
+
originalParentId
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
diagnostics.push({
|
|
1356
|
+
code: "AI_LOGICAL_PARENT_REMAPPED",
|
|
1357
|
+
message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
|
|
1358
|
+
eventIds: [event.eventId]
|
|
1359
|
+
});
|
|
1360
|
+
normalized.push({
|
|
1361
|
+
...event,
|
|
1362
|
+
parentId: nextParent,
|
|
1363
|
+
projection: {
|
|
1364
|
+
...event.projection,
|
|
1365
|
+
parentNormalized: true,
|
|
1366
|
+
originalParentId
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
const rawIndex = new Map(events.map((e, i) => [e.eventId, i]));
|
|
1371
|
+
normalized.sort((a, b) => {
|
|
1372
|
+
const ai = rawIndex.get(a.sourceEventIds[0]) ?? 0;
|
|
1373
|
+
const bi = rawIndex.get(b.sourceEventIds[0]) ?? 0;
|
|
1374
|
+
return ai - bi || a.eventId.localeCompare(b.eventId);
|
|
1375
|
+
});
|
|
1376
|
+
return {
|
|
1377
|
+
logicalEvents: Object.freeze(normalized),
|
|
1378
|
+
diagnostics: Object.freeze(diagnostics)
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1052
1382
|
// packages/core/src/logs/tree-builder.ts
|
|
1053
1383
|
function inc(map, key) {
|
|
1054
1384
|
map[key] = (map[key] ?? 0) + 1;
|
|
@@ -1221,15 +1551,20 @@ var TreeBuilder = class {
|
|
|
1221
1551
|
};
|
|
1222
1552
|
|
|
1223
1553
|
// packages/core/src/persisted/tree-bridge.ts
|
|
1554
|
+
function logicalToPersisted(event) {
|
|
1555
|
+
const { sourceEventIds: _sourceEventIds, projection: _projection, ...rest } = event;
|
|
1556
|
+
return rest;
|
|
1557
|
+
}
|
|
1224
1558
|
function persistedInspectEventsToRunTrees(events, options) {
|
|
1225
|
-
const
|
|
1559
|
+
const sourceEvents = options?.coalesceLifecycle === true ? projectLogicalEvents(events).logicalEvents.map(logicalToPersisted) : events;
|
|
1560
|
+
const inspectEvents = persistedInspectEventsToInspectEvents(sourceEvents, {
|
|
1226
1561
|
skipInvalid: options?.skipInvalid
|
|
1227
1562
|
});
|
|
1228
1563
|
return new TreeBuilder().build(inspectEvents);
|
|
1229
1564
|
}
|
|
1230
|
-
function traceEventsToPersistedRunTrees(events) {
|
|
1565
|
+
function traceEventsToPersistedRunTrees(events, options) {
|
|
1231
1566
|
const persisted = traceEventsToPersistedInspectEvents(events);
|
|
1232
|
-
return persistedInspectEventsToRunTrees(persisted);
|
|
1567
|
+
return persistedInspectEventsToRunTrees(persisted, options);
|
|
1233
1568
|
}
|
|
1234
1569
|
|
|
1235
1570
|
exports.inspectEventToPersistedInspectEvent = inspectEventToPersistedInspectEvent;
|