agent-inspect 2.2.0 → 2.4.0

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +31 -4
  2. package/README.md +47 -4
  3. package/docs/ADAPTER-CONFORMANCE.md +25 -5
  4. package/docs/ADAPTERS.md +102 -11
  5. package/docs/CLI.md +54 -1
  6. package/docs/SCHEMA.md +1 -0
  7. package/package.json +2 -2
  8. package/packages/cli/dist/index.cjs +757 -14
  9. package/packages/cli/dist/index.cjs.map +1 -1
  10. package/packages/cli/dist/index.mjs +757 -14
  11. package/packages/cli/dist/index.mjs.map +1 -1
  12. package/packages/core/dist/advanced.cjs +581 -3
  13. package/packages/core/dist/advanced.cjs.map +1 -1
  14. package/packages/core/dist/advanced.d.cts +172 -8
  15. package/packages/core/dist/advanced.d.ts +172 -8
  16. package/packages/core/dist/advanced.mjs +572 -4
  17. package/packages/core/dist/advanced.mjs.map +1 -1
  18. package/packages/core/dist/checks.d.cts +2 -2
  19. package/packages/core/dist/checks.d.ts +2 -2
  20. package/packages/core/dist/{context-yv2VSDQF.d.ts → context-BDZmi53V.d.ts} +3 -3
  21. package/packages/core/dist/{context-CSKnzpXR.d.cts → context-DjY-jvQk.d.cts} +3 -3
  22. package/packages/core/dist/diff.d.cts +3 -3
  23. package/packages/core/dist/diff.d.ts +3 -3
  24. package/packages/core/dist/exporters.d.cts +3 -3
  25. package/packages/core/dist/exporters.d.ts +3 -3
  26. package/packages/core/dist/index.d.cts +6 -6
  27. package/packages/core/dist/index.d.ts +6 -6
  28. package/packages/core/dist/{inspect-event-CevRYp58.d.cts → inspect-event-CYAV7Hxm.d.cts} +1 -1
  29. package/packages/core/dist/{inspect-event-CevRYp58.d.ts → inspect-event-CYAV7Hxm.d.ts} +1 -1
  30. package/packages/core/dist/{log-config-8aE5Kxtr.d.cts → log-config-BNQ9UTmP.d.cts} +1 -1
  31. package/packages/core/dist/{log-config-DVimQJho.d.ts → log-config-D3Yp1SZN.d.ts} +1 -1
  32. package/packages/core/dist/logs.d.cts +3 -3
  33. package/packages/core/dist/logs.d.ts +3 -3
  34. package/packages/core/dist/{persisted-inspect-event-D-WpXeZX.d.ts → persisted-inspect-event-BLvb0jSX.d.ts} +1 -1
  35. package/packages/core/dist/{persisted-inspect-event-DHcHPUKv.d.cts → persisted-inspect-event-D5SjBz9b.d.cts} +1 -1
  36. package/packages/core/dist/persisted.d.cts +5 -5
  37. package/packages/core/dist/persisted.d.ts +5 -5
  38. package/packages/core/dist/readers.d.cts +2 -2
  39. package/packages/core/dist/readers.d.ts +2 -2
  40. package/packages/core/dist/{types-DgMN3qow.d.cts → types-C-llnPH0.d.cts} +1 -1
  41. package/packages/core/dist/{types-D-Y1kOU-.d.ts → types-CQun9LW6.d.ts} +1 -1
  42. package/packages/core/dist/writers.d.cts +2 -2
  43. package/packages/core/dist/writers.d.ts +2 -2
@@ -3866,10 +3866,12 @@ async function searchTraces(metas, options) {
3866
3866
  durationFilter = parseDurationFilter(options.duration);
3867
3867
  }
3868
3868
  const limit = options.limit ?? 50;
3869
+ const sessionId = options.session?.trim();
3869
3870
  const hasContentFilter = Boolean(
3870
3871
  options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
3871
3872
  );
3872
3873
  const results = [];
3874
+ const sessionLabel = sessionId && sessionId !== "" ? sessionId : void 0;
3873
3875
  if (!hasContentFilter) {
3874
3876
  for (const m of filtered) {
3875
3877
  results.push({
@@ -3878,9 +3880,10 @@ async function searchTraces(metas, options) {
3878
3880
  runStatus: m.status,
3879
3881
  timestamp: m.startedAt,
3880
3882
  durationMs: m.durationMs,
3881
- matchReason: "trace in directory",
3882
- matchedFields: ["run"],
3883
- filePath: m.filePath
3883
+ matchReason: sessionLabel ? `trace in session ${sessionLabel}` : "trace in directory",
3884
+ matchedFields: sessionLabel ? ["run", "session"] : ["run"],
3885
+ filePath: m.filePath,
3886
+ ...sessionLabel ? { sessionId: sessionLabel } : {}
3884
3887
  });
3885
3888
  }
3886
3889
  return results.slice(0, limit);
@@ -4019,6 +4022,571 @@ async function loadTraceMetadataList(_traceDir, fileNames, getPath) {
4019
4022
  }
4020
4023
  return metas;
4021
4024
  }
4025
+
4026
+ // packages/core/src/sessions/metadata.ts
4027
+ function isNonEmptyString3(value) {
4028
+ return typeof value === "string" && value.trim() !== "";
4029
+ }
4030
+ function finitePositiveInt(value) {
4031
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
4032
+ return void 0;
4033
+ }
4034
+ return Math.trunc(value);
4035
+ }
4036
+ function extractSessionWorkflowMetadata(record) {
4037
+ if (!record) return void 0;
4038
+ const out = {};
4039
+ let found = false;
4040
+ const assignString = (key, value) => {
4041
+ if (isNonEmptyString3(value)) {
4042
+ out[key] = value.trim();
4043
+ found = true;
4044
+ }
4045
+ };
4046
+ assignString("sessionId", record.sessionId);
4047
+ assignString("conversationId", record.conversationId);
4048
+ assignString("groupId", record.groupId);
4049
+ assignString("parentGroupId", record.parentGroupId);
4050
+ assignString("retryOf", record.retryOf);
4051
+ assignString("retryReason", record.retryReason);
4052
+ assignString("handoffFrom", record.handoffFrom);
4053
+ assignString("handoffTo", record.handoffTo);
4054
+ assignString("subAgentId", record.subAgentId);
4055
+ assignString("subAgentName", record.subAgentName);
4056
+ assignString("jobId", record.jobId);
4057
+ assignString("queueName", record.queueName);
4058
+ assignString("workflowName", record.workflowName);
4059
+ assignString("workflowStep", record.workflowStep);
4060
+ assignString("toolCallId", record.toolCallId);
4061
+ assignString("mcpToolCallId", record.mcpToolCallId);
4062
+ assignString("linkedStepId", record.linkedStepId);
4063
+ assignString("correlationId", record.correlationId);
4064
+ assignString("requestId", record.requestId);
4065
+ assignString("decisionId", record.decisionId);
4066
+ const attempt = finitePositiveInt(record.attempt);
4067
+ if (attempt !== void 0) {
4068
+ out.attempt = attempt;
4069
+ found = true;
4070
+ }
4071
+ return found ? out : void 0;
4072
+ }
4073
+ function sessionKeyForRun(meta, options) {
4074
+ if (meta?.sessionId) return meta.sessionId;
4075
+ if (options?.correlateByGroupId && meta?.groupId) {
4076
+ return `group:${meta.groupId}`;
4077
+ }
4078
+ return void 0;
4079
+ }
4080
+
4081
+ // packages/core/src/sessions/types.ts
4082
+ var SESSION_WORKFLOW_KEYS = [
4083
+ "sessionId",
4084
+ "conversationId",
4085
+ "groupId",
4086
+ "parentGroupId",
4087
+ "attempt",
4088
+ "retryOf",
4089
+ "retryReason",
4090
+ "handoffFrom",
4091
+ "handoffTo",
4092
+ "subAgentId",
4093
+ "subAgentName",
4094
+ "jobId",
4095
+ "queueName",
4096
+ "workflowName",
4097
+ "workflowStep",
4098
+ "toolCallId",
4099
+ "mcpToolCallId",
4100
+ "linkedStepId",
4101
+ "correlationId",
4102
+ "requestId",
4103
+ "decisionId"
4104
+ ];
4105
+
4106
+ // packages/core/src/sessions/load.ts
4107
+ async function enrichSessionRunRecord(meta) {
4108
+ let metadata;
4109
+ try {
4110
+ const events = await readTraceEventsFromFile(meta.filePath);
4111
+ for (const event of events) {
4112
+ if (event.event !== "run_started") continue;
4113
+ if (event.metadata && typeof event.metadata === "object") {
4114
+ metadata = event.metadata;
4115
+ }
4116
+ break;
4117
+ }
4118
+ } catch {
4119
+ }
4120
+ return {
4121
+ runId: meta.runId,
4122
+ name: meta.name,
4123
+ status: meta.status,
4124
+ startedAt: meta.startedAt,
4125
+ endedAt: meta.endedAt,
4126
+ durationMs: meta.durationMs,
4127
+ filePath: meta.filePath,
4128
+ metadata
4129
+ };
4130
+ }
4131
+ async function loadSessionRunRecords(metas) {
4132
+ const out = [];
4133
+ for (const meta of metas) {
4134
+ out.push(await enrichSessionRunRecord(meta));
4135
+ }
4136
+ return out;
4137
+ }
4138
+
4139
+ // packages/core/src/sessions/scope.ts
4140
+ function metaToSessionRunRecord(meta) {
4141
+ return {
4142
+ runId: meta.runId,
4143
+ name: meta.name,
4144
+ status: meta.status,
4145
+ startedAt: meta.startedAt,
4146
+ endedAt: meta.endedAt,
4147
+ durationMs: meta.durationMs,
4148
+ filePath: meta.filePath,
4149
+ metadata: void 0
4150
+ };
4151
+ }
4152
+ function filterMetasBySessionScope(metas, records, options) {
4153
+ const sessionId = options.sessionId?.trim();
4154
+ const groupId = options.groupId?.trim();
4155
+ const warnings = [];
4156
+ if (sessionId) {
4157
+ const index = buildSessionIndex(records, {
4158
+ correlateByGroupId: options.correlateByGroupId === true
4159
+ });
4160
+ warnings.push(...index.warnings);
4161
+ const session = index.sessions.find((item) => item.sessionId === sessionId);
4162
+ if (!session) {
4163
+ return {
4164
+ metas: [],
4165
+ scopeLabel: sessionId,
4166
+ scopeKind: "session",
4167
+ runIds: [],
4168
+ warnings,
4169
+ notFound: true
4170
+ };
4171
+ }
4172
+ const runIdSet = new Set(session.runIds);
4173
+ const filtered = metas.filter((meta) => runIdSet.has(meta.runId));
4174
+ return {
4175
+ metas: filtered,
4176
+ scopeLabel: sessionId,
4177
+ scopeKind: "session",
4178
+ runIds: session.runIds,
4179
+ warnings,
4180
+ notFound: false
4181
+ };
4182
+ }
4183
+ if (groupId) {
4184
+ const runIds = records.filter((run) => extractSessionWorkflowMetadata(run.metadata)?.groupId === groupId).map((run) => run.runId).sort();
4185
+ if (runIds.length === 0) {
4186
+ return {
4187
+ metas: [],
4188
+ scopeLabel: groupId,
4189
+ scopeKind: "group",
4190
+ runIds: [],
4191
+ warnings,
4192
+ notFound: true
4193
+ };
4194
+ }
4195
+ const runIdSet = new Set(runIds);
4196
+ return {
4197
+ metas: metas.filter((meta) => runIdSet.has(meta.runId)),
4198
+ scopeLabel: groupId,
4199
+ scopeKind: "group",
4200
+ runIds,
4201
+ warnings,
4202
+ notFound: false
4203
+ };
4204
+ }
4205
+ return {
4206
+ metas: [...metas],
4207
+ scopeLabel: "",
4208
+ scopeKind: "session",
4209
+ runIds: [],
4210
+ warnings,
4211
+ notFound: false
4212
+ };
4213
+ }
4214
+ function traceMetasToSessionRunRecords(metas) {
4215
+ return metas.map(metaToSessionRunRecord);
4216
+ }
4217
+
4218
+ // packages/core/src/sessions/cohort.ts
4219
+ function groupSessionCohorts(runs, options = {}) {
4220
+ const groupBy = options.groupBy ?? "session";
4221
+ const cohorts = [];
4222
+ if (groupBy === "session") {
4223
+ const index = buildSessionIndex(runs, options);
4224
+ for (const session of index.sessions) {
4225
+ cohorts.push({
4226
+ key: session.sessionId,
4227
+ kind: "session",
4228
+ runIds: [...session.runIds]
4229
+ });
4230
+ }
4231
+ if (index.unscopedRunIds.length > 0) {
4232
+ cohorts.push({
4233
+ key: "__unscoped__",
4234
+ kind: "session",
4235
+ runIds: [...index.unscopedRunIds]
4236
+ });
4237
+ }
4238
+ return cohorts.sort((a, b) => a.key.localeCompare(b.key));
4239
+ }
4240
+ const byGroup = /* @__PURE__ */ new Map();
4241
+ const unscoped = [];
4242
+ for (const run of runs) {
4243
+ const groupId = extractSessionWorkflowMetadata(run.metadata)?.groupId;
4244
+ if (!groupId) {
4245
+ unscoped.push(run.runId);
4246
+ continue;
4247
+ }
4248
+ const bucket = byGroup.get(groupId) ?? [];
4249
+ bucket.push(run.runId);
4250
+ byGroup.set(groupId, bucket);
4251
+ }
4252
+ for (const [key, runIds] of [...byGroup.entries()].sort(
4253
+ ([a], [b]) => a.localeCompare(b)
4254
+ )) {
4255
+ cohorts.push({
4256
+ key,
4257
+ kind: "group",
4258
+ runIds: runIds.sort()
4259
+ });
4260
+ }
4261
+ if (unscoped.length > 0) {
4262
+ cohorts.push({
4263
+ key: "__unscoped__",
4264
+ kind: "group",
4265
+ runIds: unscoped.sort()
4266
+ });
4267
+ }
4268
+ return cohorts;
4269
+ }
4270
+
4271
+ // packages/core/src/sessions/checks.ts
4272
+ function emptySummary() {
4273
+ return { passed: 0, failed: 0, warnings: 0, errors: 0 };
4274
+ }
4275
+ function mergeSummary(target, source) {
4276
+ return {
4277
+ passed: target.passed + source.passed,
4278
+ failed: target.failed + source.failed,
4279
+ warnings: target.warnings + source.warnings,
4280
+ errors: target.errors + source.errors
4281
+ };
4282
+ }
4283
+ function sessionDiagnostic(code, message) {
4284
+ return { code, message, severity: "error" };
4285
+ }
4286
+ function aggregateSessionCheckResults(perRun, scope) {
4287
+ if (scope.notFound) {
4288
+ return {
4289
+ ok: false,
4290
+ status: "error",
4291
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
4292
+ scopeKind: scope.scopeKind,
4293
+ scopeLabel: scope.scopeLabel,
4294
+ runIds: [],
4295
+ runResults: [],
4296
+ summary: { ...emptySummary(), errors: 1 },
4297
+ findings: [],
4298
+ diagnostics: [
4299
+ sessionDiagnostic(
4300
+ "AI_CHECK_INVALID_ARGUMENTS",
4301
+ `${scope.scopeKind} not found: ${scope.scopeLabel}`
4302
+ )
4303
+ ],
4304
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
4305
+ };
4306
+ }
4307
+ if (scope.empty || perRun.length === 0) {
4308
+ return {
4309
+ ok: false,
4310
+ status: "error",
4311
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
4312
+ scopeKind: scope.scopeKind,
4313
+ scopeLabel: scope.scopeLabel,
4314
+ runIds: scope.runIds,
4315
+ runResults: [],
4316
+ summary: { ...emptySummary(), errors: 1 },
4317
+ findings: [],
4318
+ diagnostics: [
4319
+ sessionDiagnostic(
4320
+ "AI_CHECK_TRACE_UNREADABLE",
4321
+ `No readable traces in ${scope.scopeKind}: ${scope.scopeLabel}`
4322
+ )
4323
+ ],
4324
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
4325
+ };
4326
+ }
4327
+ let summary = emptySummary();
4328
+ const findings = [];
4329
+ const diagnostics = [];
4330
+ const runResults = [];
4331
+ for (const result of perRun) {
4332
+ summary = mergeSummary(summary, result.summary);
4333
+ findings.push(...result.findings);
4334
+ diagnostics.push(...result.diagnostics);
4335
+ if (result.runId) {
4336
+ runResults.push({ runId: result.runId, status: result.status });
4337
+ }
4338
+ }
4339
+ runResults.sort((a, b) => a.runId.localeCompare(b.runId));
4340
+ findings.sort((a, b) => {
4341
+ const runCmp = (a.evidence[0]?.runId ?? "").localeCompare(
4342
+ b.evidence[0]?.runId ?? ""
4343
+ );
4344
+ if (runCmp !== 0) return runCmp;
4345
+ return a.ruleId.localeCompare(b.ruleId);
4346
+ });
4347
+ const hasErrors = diagnostics.some((item) => item.severity === "error");
4348
+ const status = hasErrors ? "error" : summary.failed > 0 ? "fail" : "pass";
4349
+ return {
4350
+ ok: status === "pass",
4351
+ status,
4352
+ format: perRun[0]?.format ?? "agent-inspect-jsonl",
4353
+ scopeKind: scope.scopeKind,
4354
+ scopeLabel: scope.scopeLabel,
4355
+ runIds: scope.runIds,
4356
+ runResults,
4357
+ summary,
4358
+ findings,
4359
+ diagnostics,
4360
+ ...scope.sessionWarnings?.length ? { sessionWarnings: [...scope.sessionWarnings] } : {}
4361
+ };
4362
+ }
4363
+
4364
+ // packages/core/src/sessions/index.ts
4365
+ function compareRuns(a, b) {
4366
+ const aStart = a.startedAt ?? 0;
4367
+ const bStart = b.startedAt ?? 0;
4368
+ if (aStart !== bStart) return aStart - bStart;
4369
+ return a.runId.localeCompare(b.runId);
4370
+ }
4371
+ function buildGroups(runIds, metaByRunId) {
4372
+ const byGroup = /* @__PURE__ */ new Map();
4373
+ for (const runId of runIds) {
4374
+ const groupId = metaByRunId.get(runId)?.groupId;
4375
+ if (!groupId) continue;
4376
+ const existing = byGroup.get(groupId);
4377
+ if (existing) {
4378
+ existing.runIds.push(runId);
4379
+ } else {
4380
+ byGroup.set(groupId, {
4381
+ groupId,
4382
+ parentGroupId: metaByRunId.get(runId)?.parentGroupId,
4383
+ runIds: [runId]
4384
+ });
4385
+ }
4386
+ }
4387
+ return [...byGroup.values()].map((group) => ({
4388
+ ...group,
4389
+ runIds: [...group.runIds].sort((a, b) => a.localeCompare(b))
4390
+ }));
4391
+ }
4392
+ function buildHandoffs(runIds, metaByRunId, warnings, sessionId) {
4393
+ const edges = [];
4394
+ const seen = /* @__PURE__ */ new Set();
4395
+ const pushEdge = (edge) => {
4396
+ const key = `${edge.from}->${edge.to}:${edge.confidence}`;
4397
+ if (seen.has(key)) return;
4398
+ seen.add(key);
4399
+ edges.push(edge);
4400
+ };
4401
+ for (const runId of runIds) {
4402
+ const meta = metaByRunId.get(runId);
4403
+ if (!meta) continue;
4404
+ if (meta.handoffFrom && meta.handoffTo) {
4405
+ pushEdge({
4406
+ from: meta.handoffFrom,
4407
+ to: meta.handoffTo,
4408
+ source: "manual",
4409
+ confidence: "explicit"
4410
+ });
4411
+ continue;
4412
+ }
4413
+ if (meta.handoffFrom) {
4414
+ pushEdge({
4415
+ from: meta.handoffFrom,
4416
+ to: runId,
4417
+ source: "manual",
4418
+ confidence: "explicit"
4419
+ });
4420
+ }
4421
+ if (meta.handoffTo) {
4422
+ pushEdge({
4423
+ from: runId,
4424
+ to: meta.handoffTo,
4425
+ source: "manual",
4426
+ confidence: "explicit"
4427
+ });
4428
+ }
4429
+ if (meta.subAgentId && meta.parentGroupId && !meta.handoffFrom && !meta.handoffTo) {
4430
+ pushEdge({
4431
+ from: meta.parentGroupId,
4432
+ to: meta.subAgentId,
4433
+ source: "inferred",
4434
+ confidence: "correlated"
4435
+ });
4436
+ warnings.push({
4437
+ code: "ambiguous-handoff-endpoints",
4438
+ message: "Handoff inferred from parentGroupId and subAgentId without explicit handoffFrom/handoffTo.",
4439
+ runId,
4440
+ sessionId
4441
+ });
4442
+ }
4443
+ }
4444
+ return edges.sort((a, b) => {
4445
+ const from = a.from.localeCompare(b.from);
4446
+ if (from !== 0) return from;
4447
+ return a.to.localeCompare(b.to);
4448
+ });
4449
+ }
4450
+ function buildRetries(runIds, metaByRunId, warnings, sessionId) {
4451
+ const retries = [];
4452
+ for (const runId of runIds) {
4453
+ const meta = metaByRunId.get(runId);
4454
+ if (!meta) continue;
4455
+ if (meta.retryOf) {
4456
+ retries.push({
4457
+ runId,
4458
+ retryOf: meta.retryOf,
4459
+ attempt: meta.attempt,
4460
+ source: "manual",
4461
+ confidence: "explicit"
4462
+ });
4463
+ continue;
4464
+ }
4465
+ if (meta.attempt !== void 0 && meta.attempt > 1) {
4466
+ retries.push({
4467
+ runId,
4468
+ attempt: meta.attempt,
4469
+ source: "inferred",
4470
+ confidence: "correlated"
4471
+ });
4472
+ warnings.push({
4473
+ code: "ambiguous-retry-link",
4474
+ message: "attempt > 1 without retryOf; retry link is correlated only.",
4475
+ runId,
4476
+ sessionId
4477
+ });
4478
+ }
4479
+ }
4480
+ return retries.sort((a, b) => a.runId.localeCompare(b.runId));
4481
+ }
4482
+ function buildCriticalPath(runs, handoffs) {
4483
+ const runById = new Map(runs.map((run) => [run.runId, run]));
4484
+ const explicitTargets = new Set(
4485
+ handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.to)
4486
+ );
4487
+ const explicitSources = new Set(
4488
+ handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
4489
+ );
4490
+ const ordered = [...runs].sort(compareRuns);
4491
+ const path5 = [];
4492
+ const visited = /* @__PURE__ */ new Set();
4493
+ const pushRun = (run, confidence, source) => {
4494
+ if (visited.has(run.runId)) return;
4495
+ visited.add(run.runId);
4496
+ path5.push({
4497
+ runId: run.runId,
4498
+ name: run.name,
4499
+ startedAt: run.startedAt,
4500
+ durationMs: run.durationMs,
4501
+ confidence,
4502
+ source
4503
+ });
4504
+ };
4505
+ for (const edge of handoffs) {
4506
+ if (edge.confidence !== "explicit") continue;
4507
+ const fromRun = [...runById.values()].find(
4508
+ (run) => run.runId === edge.from || metaRunIdMatches(run, edge.from, runById)
4509
+ );
4510
+ const toRun = [...runById.values()].find(
4511
+ (run) => run.runId === edge.to || metaRunIdMatches(run, edge.to, runById)
4512
+ );
4513
+ if (fromRun) pushRun(fromRun, "explicit", "manual");
4514
+ if (toRun) pushRun(toRun, "explicit", "manual");
4515
+ }
4516
+ for (const run of ordered) {
4517
+ if (visited.has(run.runId)) continue;
4518
+ const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
4519
+ pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
4520
+ }
4521
+ return path5;
4522
+ }
4523
+ function metaRunIdMatches(run, token, runById) {
4524
+ const meta = extractSessionWorkflowMetadata(run.metadata);
4525
+ return meta?.subAgentId === token || meta?.groupId === token || runById.has(token);
4526
+ }
4527
+ function buildSessionIndex(inputRuns, options = {}) {
4528
+ const warnings = [];
4529
+ const runs = [...inputRuns].sort(compareRuns);
4530
+ const metaByRunId = /* @__PURE__ */ new Map();
4531
+ for (const run of runs) {
4532
+ metaByRunId.set(run.runId, extractSessionWorkflowMetadata(run.metadata));
4533
+ }
4534
+ const sessionsByKey = /* @__PURE__ */ new Map();
4535
+ const unscopedRunIds = [];
4536
+ for (const run of runs) {
4537
+ const meta = metaByRunId.get(run.runId);
4538
+ const key = sessionKeyForRun(meta, {
4539
+ correlateByGroupId: options.correlateByGroupId === true
4540
+ });
4541
+ if (!key) {
4542
+ unscopedRunIds.push(run.runId);
4543
+ continue;
4544
+ }
4545
+ const bucket = sessionsByKey.get(key) ?? [];
4546
+ bucket.push(run);
4547
+ sessionsByKey.set(key, bucket);
4548
+ }
4549
+ const sessions = [...sessionsByKey.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([sessionId, sessionRuns]) => {
4550
+ const runIds = sessionRuns.map((run) => run.runId).sort();
4551
+ const handoffs = buildHandoffs(runIds, metaByRunId, warnings, sessionId);
4552
+ const retries = buildRetries(runIds, metaByRunId, warnings, sessionId);
4553
+ const groups = buildGroups(runIds, metaByRunId);
4554
+ const criticalPath = buildCriticalPath(sessionRuns, handoffs);
4555
+ const confidences = new Set(handoffs.map((edge) => edge.confidence));
4556
+ if (confidences.has("explicit") && confidences.has("correlated")) {
4557
+ warnings.push({
4558
+ code: "mixed-confidence-group",
4559
+ message: "Session aggregates explicit and correlated handoff edges.",
4560
+ sessionId
4561
+ });
4562
+ }
4563
+ return {
4564
+ sessionId,
4565
+ runIds,
4566
+ groups,
4567
+ handoffs,
4568
+ retries,
4569
+ criticalPath
4570
+ };
4571
+ });
4572
+ if (sessions.length === 0 && runs.length > 0) {
4573
+ warnings.push({
4574
+ code: "missing-session-id",
4575
+ message: "No sessionId (or correlated groupId) found on input runs."
4576
+ });
4577
+ }
4578
+ warnings.sort((a, b) => {
4579
+ const code = a.code.localeCompare(b.code);
4580
+ if (code !== 0) return code;
4581
+ return (a.runId ?? "").localeCompare(b.runId ?? "");
4582
+ });
4583
+ return {
4584
+ runs,
4585
+ sessions,
4586
+ unscopedRunIds: unscopedRunIds.sort(),
4587
+ warnings
4588
+ };
4589
+ }
4022
4590
  var KNOWN_EVENTS = /* @__PURE__ */ new Set([
4023
4591
  "run_started",
4024
4592
  "run_completed",
@@ -4202,19 +4770,25 @@ exports.MAX_NAME_LENGTH = MAX_NAME_LENGTH;
4202
4770
  exports.MAX_TERMINAL_DEPTH = MAX_TERMINAL_DEPTH;
4203
4771
  exports.MAX_TERMINAL_NAME_LENGTH = MAX_TERMINAL_NAME_LENGTH;
4204
4772
  exports.RUNS_DIR_NAME = RUNS_DIR_NAME;
4773
+ exports.SESSION_WORKFLOW_KEYS = SESSION_WORKFLOW_KEYS;
4205
4774
  exports.TERMINAL_INDENT = TERMINAL_INDENT;
4206
4775
  exports.TraceDirectory = TraceDirectory;
4776
+ exports.aggregateSessionCheckResults = aggregateSessionCheckResults;
4207
4777
  exports.buildLocalExplanation = buildLocalExplanation;
4208
4778
  exports.buildRunSummary = buildRunSummary;
4209
4779
  exports.buildRunTimeline = buildRunTimeline;
4210
4780
  exports.buildRunWhatSummary = buildRunWhatSummary;
4781
+ exports.buildSessionIndex = buildSessionIndex;
4211
4782
  exports.buildTraceStats = buildTraceStats;
4212
4783
  exports.createInspector = createInspector;
4213
4784
  exports.createInspectorRuntime = createInspectorRuntime;
4214
4785
  exports.createRunId = createRunId;
4215
4786
  exports.createStepId = createStepId;
4787
+ exports.enrichSessionRunRecord = enrichSessionRunRecord;
4216
4788
  exports.ensureTraceDir = ensureTraceDir;
4217
4789
  exports.extractMetadata = extractMetadata;
4790
+ exports.extractSessionWorkflowMetadata = extractSessionWorkflowMetadata;
4791
+ exports.filterMetasBySessionScope = filterMetasBySessionScope;
4218
4792
  exports.filterTraces = filterTraces;
4219
4793
  exports.formatDuration = formatDuration2;
4220
4794
  exports.formatError = formatError;
@@ -4233,6 +4807,7 @@ exports.getRunIdFromTraceFileName = getRunIdFromTraceFileName;
4233
4807
  exports.getTraceDirFromContext = getTraceDirFromContext;
4234
4808
  exports.getTraceFilePath = getTraceFilePath;
4235
4809
  exports.getTraceSafetyFromContext = getTraceSafetyFromContext;
4810
+ exports.groupSessionCohorts = groupSessionCohorts;
4236
4811
  exports.hasActiveContext = hasActiveContext;
4237
4812
  exports.initializeTraceFile = initializeTraceFile;
4238
4813
  exports.isAgentInspectEnabled = isAgentInspectEnabled;
@@ -4242,6 +4817,7 @@ exports.isStepStatus = isStepStatus;
4242
4817
  exports.isStepType = isStepType;
4243
4818
  exports.isTraceEvent = isTraceEvent;
4244
4819
  exports.listTraceFiles = listTraceFiles;
4820
+ exports.loadSessionRunRecords = loadSessionRunRecords;
4245
4821
  exports.loadTraceMetadataList = loadTraceMetadataList;
4246
4822
  exports.maybeInspectRun = maybeInspectRun;
4247
4823
  exports.parseDuration = parseDuration;
@@ -4270,6 +4846,8 @@ exports.runWithContext = runWithContext;
4270
4846
  exports.runWithStepContext = runWithStepContext;
4271
4847
  exports.searchTraces = searchTraces;
4272
4848
  exports.serializeEvent = serializeEvent;
4849
+ exports.sessionKeyForRun = sessionKeyForRun;
4850
+ exports.traceMetasToSessionRunRecords = traceMetasToSessionRunRecords;
4273
4851
  exports.truncateName = truncateName;
4274
4852
  exports.unknownTraceFormatMessage = unknownTraceFormatMessage;
4275
4853
  exports.validateEvent = validateEvent;