agent-inspect 4.2.0 → 4.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 (97) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/docs/API.md +3 -0
  3. package/docs/CLI.md +36 -0
  4. package/docs/SCHEMA.md +27 -1
  5. package/package.json +1 -1
  6. package/packages/cli/dist/{chunk-5VSPJEZ7.mjs → chunk-ORHDQUT6.mjs} +385 -10
  7. package/packages/cli/dist/chunk-ORHDQUT6.mjs.map +1 -0
  8. package/packages/cli/dist/index.cjs +2548 -1567
  9. package/packages/cli/dist/index.cjs.map +1 -1
  10. package/packages/cli/dist/index.mjs +2028 -1495
  11. package/packages/cli/dist/index.mjs.map +1 -1
  12. package/packages/cli/dist/{src-VQT7QLGV.mjs → src-FJOHPC4X.mjs} +3 -3
  13. package/packages/cli/dist/{src-VQT7QLGV.mjs.map → src-FJOHPC4X.mjs.map} +1 -1
  14. package/packages/core/dist/advanced.cjs +397 -12
  15. package/packages/core/dist/advanced.cjs.map +1 -1
  16. package/packages/core/dist/advanced.d.cts +105 -9
  17. package/packages/core/dist/advanced.d.ts +105 -9
  18. package/packages/core/dist/advanced.mjs +219 -17
  19. package/packages/core/dist/advanced.mjs.map +1 -1
  20. package/packages/core/dist/checks.cjs +117 -18
  21. package/packages/core/dist/checks.cjs.map +1 -1
  22. package/packages/core/dist/checks.d.cts +11 -3
  23. package/packages/core/dist/checks.d.ts +11 -3
  24. package/packages/core/dist/checks.mjs +42 -1
  25. package/packages/core/dist/checks.mjs.map +1 -1
  26. package/packages/core/dist/{chunk-2ZXEMWGK.mjs → chunk-3USJVBLA.mjs} +3 -3
  27. package/packages/core/dist/{chunk-2ZXEMWGK.mjs.map → chunk-3USJVBLA.mjs.map} +1 -1
  28. package/packages/core/dist/{chunk-HY7H3CQM.mjs → chunk-CAWPF22J.mjs} +4 -3
  29. package/packages/core/dist/chunk-CAWPF22J.mjs.map +1 -0
  30. package/packages/core/dist/{chunk-XUNJMAPD.mjs → chunk-KNYL56KZ.mjs} +38 -3
  31. package/packages/core/dist/chunk-KNYL56KZ.mjs.map +1 -0
  32. package/packages/core/dist/{chunk-IZBJAZGF.mjs → chunk-P366CCL2.mjs} +34 -3
  33. package/packages/core/dist/chunk-P366CCL2.mjs.map +1 -0
  34. package/packages/core/dist/{chunk-4JVGFNQH.mjs → chunk-ULCGIRTC.mjs} +95 -8
  35. package/packages/core/dist/chunk-ULCGIRTC.mjs.map +1 -0
  36. package/packages/core/dist/chunk-VFO76UH3.mjs +228 -0
  37. package/packages/core/dist/chunk-VFO76UH3.mjs.map +1 -0
  38. package/packages/core/dist/{chunk-NQZPZ2FN.mjs → chunk-WRE4CNPF.mjs} +6 -3
  39. package/packages/core/dist/chunk-WRE4CNPF.mjs.map +1 -0
  40. package/packages/core/dist/{chunk-A4V2H3YU.mjs → chunk-ZWA5RWMV.mjs} +40 -4
  41. package/packages/core/dist/chunk-ZWA5RWMV.mjs.map +1 -0
  42. package/packages/core/dist/{context-DjY-jvQk.d.cts → context-BbfkMYjz.d.cts} +5 -3
  43. package/packages/core/dist/{context-BDZmi53V.d.ts → context-Cp8NRbBX.d.ts} +5 -3
  44. package/packages/core/dist/diff.cjs.map +1 -1
  45. package/packages/core/dist/diff.d.cts +3 -3
  46. package/packages/core/dist/diff.d.ts +3 -3
  47. package/packages/core/dist/diff.mjs +1 -1
  48. package/packages/core/dist/exporters.cjs +137 -1
  49. package/packages/core/dist/exporters.cjs.map +1 -1
  50. package/packages/core/dist/exporters.d.cts +6 -3
  51. package/packages/core/dist/exporters.d.ts +6 -3
  52. package/packages/core/dist/exporters.mjs +71 -6
  53. package/packages/core/dist/exporters.mjs.map +1 -1
  54. package/packages/core/dist/index.cjs +181 -6
  55. package/packages/core/dist/index.cjs.map +1 -1
  56. package/packages/core/dist/index.d.cts +14 -7
  57. package/packages/core/dist/index.d.ts +14 -7
  58. package/packages/core/dist/index.mjs +51 -7
  59. package/packages/core/dist/index.mjs.map +1 -1
  60. package/packages/core/dist/{inspect-event-CYAV7Hxm.d.cts → inspect-event-IqwOHbGo.d.cts} +1 -1
  61. package/packages/core/dist/{inspect-event-CYAV7Hxm.d.ts → inspect-event-IqwOHbGo.d.ts} +1 -1
  62. package/packages/core/dist/{log-config-BNQ9UTmP.d.cts → log-config-CW8w5YQ9.d.cts} +1 -1
  63. package/packages/core/dist/{log-config-D3Yp1SZN.d.ts → log-config-SRA4xTp8.d.ts} +1 -1
  64. package/packages/core/dist/logs.d.cts +3 -3
  65. package/packages/core/dist/logs.d.ts +3 -3
  66. package/packages/core/dist/{persisted-inspect-event-BLvb0jSX.d.ts → persisted-inspect-event-DruwqARZ.d.ts} +1 -1
  67. package/packages/core/dist/{persisted-inspect-event-D5SjBz9b.d.cts → persisted-inspect-event-Gd-W8vB7.d.cts} +1 -1
  68. package/packages/core/dist/persisted.cjs +67 -1
  69. package/packages/core/dist/persisted.cjs.map +1 -1
  70. package/packages/core/dist/persisted.d.cts +5 -5
  71. package/packages/core/dist/persisted.d.ts +5 -5
  72. package/packages/core/dist/persisted.mjs +3 -3
  73. package/packages/core/dist/readers.cjs +72 -3
  74. package/packages/core/dist/readers.cjs.map +1 -1
  75. package/packages/core/dist/readers.d.cts +2 -2
  76. package/packages/core/dist/readers.d.ts +2 -2
  77. package/packages/core/dist/readers.mjs +5 -5
  78. package/packages/core/dist/readers.mjs.map +1 -1
  79. package/packages/core/dist/{types-CQun9LW6.d.ts → types-B1X87dUW.d.cts} +16 -2
  80. package/packages/core/dist/{types-C-llnPH0.d.cts → types-BVkjSd0q.d.ts} +16 -2
  81. package/packages/core/dist/types-CvsKGweN.d.cts +12 -0
  82. package/packages/core/dist/types-CvsKGweN.d.ts +12 -0
  83. package/packages/core/dist/writers.cjs +2 -1
  84. package/packages/core/dist/writers.cjs.map +1 -1
  85. package/packages/core/dist/writers.d.cts +2 -2
  86. package/packages/core/dist/writers.d.ts +2 -2
  87. package/packages/core/dist/writers.mjs +3 -4
  88. package/packages/core/dist/writers.mjs.map +1 -1
  89. package/packages/cli/dist/chunk-5VSPJEZ7.mjs.map +0 -1
  90. package/packages/core/dist/chunk-4JVGFNQH.mjs.map +0 -1
  91. package/packages/core/dist/chunk-A4V2H3YU.mjs.map +0 -1
  92. package/packages/core/dist/chunk-EDTQHZPM.mjs +0 -88
  93. package/packages/core/dist/chunk-EDTQHZPM.mjs.map +0 -1
  94. package/packages/core/dist/chunk-HY7H3CQM.mjs.map +0 -1
  95. package/packages/core/dist/chunk-IZBJAZGF.mjs.map +0 -1
  96. package/packages/core/dist/chunk-NQZPZ2FN.mjs.map +0 -1
  97. package/packages/core/dist/chunk-XUNJMAPD.mjs.map +0 -1
@@ -275,6 +275,9 @@ function isTraceEvent(value) {
275
275
  case "step_completed": {
276
276
  return typeof value.runId === "string" && typeof value.stepId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
277
277
  }
278
+ case "outcome_observed": {
279
+ return typeof value.runId === "string" && typeof value.outcomeId === "string" && typeof value.name === "string" && typeof value.expectation === "string" && (value.status === "passed" || value.status === "failed" || value.status === "unknown" || value.status === "skipped") && typeof value.observedAt === "number";
280
+ }
278
281
  default:
279
282
  return false;
280
283
  }
@@ -292,7 +295,8 @@ var INSPECT_KINDS = [
292
295
  "RESULT",
293
296
  "ERROR",
294
297
  "LOGIC",
295
- "LOG"
298
+ "LOG",
299
+ "OUTCOME"
296
300
  ];
297
301
  var ATTRIBUTION_CONFIDENCES = [
298
302
  "explicit",
@@ -584,6 +588,32 @@ function fromLegacyStepCompleted(event) {
584
588
  if (error) out.error = error;
585
589
  return out;
586
590
  }
591
+ function fromLegacyOutcomeObserved(event) {
592
+ const attrs = event.attributes ?? {};
593
+ const observedAtRaw = attrs.observedAt;
594
+ const observedAt = typeof observedAtRaw === "string" ? Date.parse(observedAtRaw) : typeof observedAtRaw === "number" && Number.isFinite(observedAtRaw) ? observedAtRaw : resolveTimes(event).timestamp;
595
+ const status = attrs.outcomeStatus;
596
+ const out = {
597
+ schemaVersion: "0.1",
598
+ event: "outcome_observed",
599
+ timestamp: observedAt,
600
+ runId: event.runId,
601
+ outcomeId: typeof attrs.outcomeId === "string" ? attrs.outcomeId : event.eventId,
602
+ name: event.name,
603
+ expectation: typeof attrs.expectation === "string" ? attrs.expectation : event.name,
604
+ status: status === "passed" || status === "failed" || status === "unknown" || status === "skipped" ? status : "unknown",
605
+ observedAt
606
+ };
607
+ if (event.parentId !== void 0) out.parentId = event.parentId;
608
+ if (typeof attrs.method === "string") out.method = attrs.method;
609
+ if (attrs.actual !== void 0) out.actual = attrs.actual;
610
+ if (event.outputSummary !== void 0) out.actual = event.outputSummary;
611
+ if (attrs.evidence !== void 0) out.evidence = attrs.evidence;
612
+ return out;
613
+ }
614
+ function fromNativeOutcome(event) {
615
+ return [fromLegacyOutcomeObserved(event)];
616
+ }
587
617
  function fromNativeRun(event) {
588
618
  const { timestamp, startTime, endTime } = resolveTimes(event);
589
619
  const runStatus = mapPersistedStatusToRunStatus(event.status);
@@ -671,9 +701,13 @@ function persistedInspectEventToTraceEvents(event) {
671
701
  if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
672
702
  if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
673
703
  if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
704
+ if (legacyEvent === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
674
705
  if (event.kind === "RUN") {
675
706
  return fromNativeRun(event);
676
707
  }
708
+ if (event.kind === "OUTCOME") {
709
+ return fromNativeOutcome(event);
710
+ }
677
711
  return fromNativeStep(event);
678
712
  }
679
713
 
@@ -1012,6 +1046,9 @@ function validateEvent(event) {
1012
1046
  case "step_completed": {
1013
1047
  return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
1014
1048
  }
1049
+ case "outcome_observed": {
1050
+ return nonEmptyString(event.runId) && nonEmptyString(event.outcomeId) && nonEmptyString(event.name) && nonEmptyString(event.expectation) && (event.status === "passed" || event.status === "failed" || event.status === "unknown" || event.status === "skipped") && finiteNumber(event.observedAt);
1051
+ }
1015
1052
  default:
1016
1053
  return false;
1017
1054
  }
@@ -1956,9 +1993,111 @@ function createInspectorRuntime(options = {}) {
1956
1993
  return runtime;
1957
1994
  }
1958
1995
 
1996
+ // packages/core/src/outcomes/types.ts
1997
+ var OBSERVED_OUTCOME_STATUSES = [
1998
+ "passed",
1999
+ "failed",
2000
+ "unknown",
2001
+ "skipped"
2002
+ ];
2003
+ var OBSERVED_OUTCOME_METHODS = [
2004
+ "dom",
2005
+ "accessibility",
2006
+ "snapshot",
2007
+ "network",
2008
+ "storage",
2009
+ "filesystem",
2010
+ "database",
2011
+ "queue",
2012
+ "custom"
2013
+ ];
2014
+ var OUTCOME_LEGACY_EVENT = "outcome_observed";
2015
+
2016
+ // packages/core/src/outcomes/validate.ts
2017
+ function normalizeName(name) {
2018
+ const trimmed = name.trim();
2019
+ if (trimmed === "") {
2020
+ throw new Error("observeOutcome requires a non-empty name.");
2021
+ }
2022
+ return trimmed.slice(0, 100);
2023
+ }
2024
+ function normalizeExpectation(value) {
2025
+ const trimmed = value.trim();
2026
+ if (trimmed === "") {
2027
+ throw new Error("observeOutcome requires a non-empty expectation.");
2028
+ }
2029
+ return trimmed.slice(0, 500);
2030
+ }
2031
+ function parseObservedOutcomeStatus(value) {
2032
+ const trimmed = value.trim().toLowerCase();
2033
+ if (OBSERVED_OUTCOME_STATUSES.includes(trimmed)) {
2034
+ return trimmed;
2035
+ }
2036
+ throw new Error(
2037
+ `Unsupported observation status "${value}". Use passed, failed, unknown, or skipped.`
2038
+ );
2039
+ }
2040
+ function parseMethod(value) {
2041
+ if (value === void 0 || value.trim() === "") return void 0;
2042
+ const trimmed = value.trim().toLowerCase();
2043
+ if (OBSERVED_OUTCOME_METHODS.includes(trimmed)) {
2044
+ return trimmed;
2045
+ }
2046
+ throw new Error(`Unsupported observation method "${value}".`);
2047
+ }
2048
+ function parseObservedAt(value, fallback) {
2049
+ if (value === void 0) return fallback;
2050
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2051
+ if (typeof value === "string") {
2052
+ const parsed = Date.parse(value);
2053
+ if (Number.isFinite(parsed)) return parsed;
2054
+ }
2055
+ return fallback;
2056
+ }
2057
+ function normalizeObserveOutcomeInput(name, options, nowMs = Date.now()) {
2058
+ return {
2059
+ name: normalizeName(name),
2060
+ expectation: normalizeExpectation(options.expectation),
2061
+ status: options.status,
2062
+ ...options.method !== void 0 ? { method: parseMethod(options.method) } : {},
2063
+ ...options.actual !== void 0 ? { actual: options.actual } : {},
2064
+ ...options.evidence !== void 0 ? { evidence: options.evidence } : {},
2065
+ observedAt: parseObservedAt(options.observedAt, nowMs)
2066
+ };
2067
+ }
2068
+
2069
+ // packages/core/src/outcomes/extract.ts
2070
+ function fromOutcomeObservedEvent(event) {
2071
+ return {
2072
+ outcomeId: event.outcomeId,
2073
+ runId: event.runId,
2074
+ ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
2075
+ name: event.name,
2076
+ expectation: event.expectation,
2077
+ status: event.status,
2078
+ ...event.method !== void 0 ? { method: event.method } : {},
2079
+ ...event.actual !== void 0 ? { actual: event.actual } : {},
2080
+ ...event.evidence !== void 0 ? { evidence: event.evidence } : {},
2081
+ observedAt: event.observedAt
2082
+ };
2083
+ }
2084
+ function extractOutcomesFromTraceEvents(events) {
2085
+ const out = [];
2086
+ for (const event of events) {
2087
+ if (event.event === OUTCOME_LEGACY_EVENT) {
2088
+ out.push(fromOutcomeObservedEvent(event));
2089
+ }
2090
+ }
2091
+ return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));
2092
+ }
2093
+ function parseObservationFilter(value) {
2094
+ if (value === void 0 || value.trim() === "") return void 0;
2095
+ return parseObservedOutcomeStatus(value);
2096
+ }
2097
+
1959
2098
  // packages/core/src/inspector.ts
1960
2099
  var INSPECTOR_PERSISTED_SCHEMA_VERSION = "1.0";
1961
- function normalizeName(name, fallback) {
2100
+ function normalizeName2(name, fallback) {
1962
2101
  if (typeof name !== "string" || name.trim() === "") return fallback;
1963
2102
  return truncateName(name.trim(), 100);
1964
2103
  }
@@ -2059,7 +2198,7 @@ function createInspector(options = {}) {
2059
2198
  if (options.enabled === false) {
2060
2199
  return Promise.resolve(fn());
2061
2200
  }
2062
- const runName = normalizeName(name, "unnamed-run");
2201
+ const runName = normalizeName2(name, "unnamed-run");
2063
2202
  const runId = runOptions.runId ?? createRunId();
2064
2203
  const traceDir = runOptions.traceDir ?? options.traceDir ?? getDefaultTraceDir();
2065
2204
  const metadata = mergeMetadata(options.metadata, runOptions.metadata);
@@ -2139,7 +2278,7 @@ function createInspector(options = {}) {
2139
2278
  return Promise.resolve(fn());
2140
2279
  }
2141
2280
  const context = runtime.getCurrentContext();
2142
- const stepName = normalizeName(name, "unnamed-step");
2281
+ const stepName = normalizeName2(name, "unnamed-step");
2143
2282
  const stepId = createStepId();
2144
2283
  const parentId = runtime.getCurrentStepId();
2145
2284
  const stepType = stepOptions.type ?? "logic";
@@ -2219,7 +2358,7 @@ function createInspector(options = {}) {
2219
2358
  run,
2220
2359
  step,
2221
2360
  tool(name, fn, toolOptions) {
2222
- const toolName = normalizeName(name, "unknown-tool");
2361
+ const toolName = normalizeName2(name, "unknown-tool");
2223
2362
  return step(`tool:${toolName}`, fn, {
2224
2363
  ...toolOptions,
2225
2364
  type: "tool",
@@ -2230,7 +2369,7 @@ function createInspector(options = {}) {
2230
2369
  });
2231
2370
  },
2232
2371
  llm(name, fn, llmOptions) {
2233
- const model = normalizeName(name, "unknown-model");
2372
+ const model = normalizeName2(name, "unknown-model");
2234
2373
  return step(`llm:${model}`, fn, {
2235
2374
  ...llmOptions,
2236
2375
  type: "llm",
@@ -2243,6 +2382,41 @@ function createInspector(options = {}) {
2243
2382
  observe(name, fn, observeOptions) {
2244
2383
  return async (...args) => step(name, () => Promise.resolve(fn(...args)), observeOptions);
2245
2384
  },
2385
+ async observeOutcome(name, outcomeOptions) {
2386
+ const ctx = runtime.getCurrentContext();
2387
+ if (!ctx) return;
2388
+ let normalized;
2389
+ try {
2390
+ normalized = normalizeObserveOutcomeInput(name, outcomeOptions);
2391
+ } catch {
2392
+ return;
2393
+ }
2394
+ const outcomeId = createStepId();
2395
+ const parentId = runtime.getCurrentStepId();
2396
+ await write({
2397
+ schemaVersion: INSPECTOR_PERSISTED_SCHEMA_VERSION,
2398
+ eventId: outcomeId,
2399
+ runId: ctx.runId,
2400
+ ...parentId !== void 0 ? { parentId } : {},
2401
+ kind: "OUTCOME",
2402
+ name: normalized.name,
2403
+ status: normalized.status === "failed" ? "error" : "ok",
2404
+ timestamp: new Date(normalized.observedAt).toISOString(),
2405
+ confidence: "explicit",
2406
+ source: { type: "manual", name: "createInspector" },
2407
+ attributes: {
2408
+ legacyEvent: "outcome_observed",
2409
+ outcomeId,
2410
+ outcomeStatus: normalized.status,
2411
+ expectation: normalized.expectation,
2412
+ ...normalized.method !== void 0 ? { method: normalized.method } : {},
2413
+ ...normalized.actual !== void 0 ? { actual: normalized.actual } : {},
2414
+ ...normalized.evidence !== void 0 ? { evidence: normalized.evidence } : {},
2415
+ observedAt: new Date(normalized.observedAt).toISOString()
2416
+ },
2417
+ ...normalized.actual !== void 0 ? { outputSummary: normalized.actual } : {}
2418
+ });
2419
+ },
2246
2420
  getDiagnostics() {
2247
2421
  return runtime.getDiagnostics();
2248
2422
  },
@@ -3867,8 +4041,9 @@ async function searchTraces(metas, options) {
3867
4041
  }
3868
4042
  const limit = options.limit ?? 50;
3869
4043
  const sessionId = options.session?.trim();
4044
+ const observationStatus = parseObservationFilter(options.observation);
3870
4045
  const hasContentFilter = Boolean(
3871
- options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
4046
+ options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter || observationStatus
3872
4047
  );
3873
4048
  const results = [];
3874
4049
  const sessionLabel = sessionId && sessionId !== "" ? sessionId : void 0;
@@ -3913,6 +4088,22 @@ async function searchTraces(metas, options) {
3913
4088
  statusFilter: options.status
3914
4089
  });
3915
4090
  results.push(...stepMatches);
4091
+ if (observationStatus) {
4092
+ const outcomes = extractOutcomesFromTraceEvents(events);
4093
+ const matched = outcomes.filter((outcome) => outcome.status === observationStatus);
4094
+ for (const outcome of matched) {
4095
+ results.push({
4096
+ runId: m.runId,
4097
+ runName: m.name,
4098
+ runStatus: m.status,
4099
+ stepName: outcome.name,
4100
+ timestamp: outcome.observedAt,
4101
+ matchReason: `observation status=${outcome.status}`,
4102
+ matchedFields: ["outcome.status", "outcome.name"],
4103
+ filePath: m.filePath
4104
+ });
4105
+ }
4106
+ }
3916
4107
  }
3917
4108
  results.sort((a, b) => {
3918
4109
  const ta = a.timestamp ?? 0;
@@ -4301,9 +4492,10 @@ function buildActivitySummary(index, options = {}) {
4301
4492
  entries
4302
4493
  };
4303
4494
  }
4304
- function renderActivitySummaryHuman(summary) {
4495
+ function renderActivitySummaryHuman(summary, options) {
4305
4496
  const lines = [];
4306
- const todayStart = /* @__PURE__ */ new Date();
4497
+ const nowMs = options?.nowMs ?? Date.now();
4498
+ const todayStart = new Date(nowMs);
4307
4499
  todayStart.setHours(0, 0, 0, 0);
4308
4500
  const todayMs = todayStart.getTime();
4309
4501
  const today = summary.entries.filter(
@@ -4734,12 +4926,12 @@ function buildCriticalPath(runs, handoffs) {
4734
4926
  handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
4735
4927
  );
4736
4928
  const ordered = [...runs].sort(compareRuns);
4737
- const path5 = [];
4929
+ const path6 = [];
4738
4930
  const visited = /* @__PURE__ */ new Set();
4739
4931
  const pushRun = (run, confidence, source) => {
4740
4932
  if (visited.has(run.runId)) return;
4741
4933
  visited.add(run.runId);
4742
- path5.push({
4934
+ path6.push({
4743
4935
  runId: run.runId,
4744
4936
  name: run.name,
4745
4937
  startedAt: run.startedAt,
@@ -4764,7 +4956,7 @@ function buildCriticalPath(runs, handoffs) {
4764
4956
  const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
4765
4957
  pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
4766
4958
  }
4767
- return path5;
4959
+ return path6;
4768
4960
  }
4769
4961
  function metaRunIdMatches(run, token, runById) {
4770
4962
  const meta = extractSessionWorkflowMetadata(run.metadata);
@@ -4884,6 +5076,190 @@ async function isAgentInspectTrace(filePath) {
4884
5076
  }
4885
5077
  }
4886
5078
 
5079
+ // packages/core/src/bundle/resolve.ts
5080
+ function parseSinceCutoff(since) {
5081
+ const trimmed = since.trim();
5082
+ if (trimmed === "") {
5083
+ throw new Error("--since requires a non-empty duration (e.g. 24h, 7d).");
5084
+ }
5085
+ return Date.now() - parseDuration(trimmed);
5086
+ }
5087
+ function runActivityMs(run) {
5088
+ if (run.startedAt !== void 0 && Number.isFinite(run.startedAt)) return run.startedAt;
5089
+ if (run.endedAt !== void 0 && Number.isFinite(run.endedAt)) return run.endedAt;
5090
+ return void 0;
5091
+ }
5092
+ function runsInSinceWindow(runs, since) {
5093
+ const cutoff = parseSinceCutoff(since);
5094
+ const ids = [];
5095
+ for (const run of runs) {
5096
+ const activity = runActivityMs(run);
5097
+ if (activity !== void 0 && activity >= cutoff) {
5098
+ ids.push(run.runId);
5099
+ }
5100
+ }
5101
+ return ids.sort((a, b) => a.localeCompare(b));
5102
+ }
5103
+ function findSession(index, sessionId) {
5104
+ return index.sessions.find((session) => session.sessionId === sessionId);
5105
+ }
5106
+ function resolveBundleRunIds(index, runs, options) {
5107
+ const runId = options.runId?.trim();
5108
+ const sessionId = options.sessionId?.trim();
5109
+ const since = options.since?.trim();
5110
+ const modes = [runId ? 1 : 0, sessionId ? 1 : 0, since ? 1 : 0].reduce((a, b) => a + b, 0);
5111
+ if (modes === 0) {
5112
+ throw new Error(
5113
+ "bundle requires a run id, --session <sessionId>, or --since <duration>."
5114
+ );
5115
+ }
5116
+ if (modes > 1) {
5117
+ throw new Error(
5118
+ "bundle accepts only one target: a run id, --session, or --since (not combined)."
5119
+ );
5120
+ }
5121
+ if (runId) {
5122
+ const known = runs.some((run) => run.runId === runId);
5123
+ if (!known) {
5124
+ throw new Error(`Run "${runId}" was not found in the trace directory.`);
5125
+ }
5126
+ return { runIds: [runId] };
5127
+ }
5128
+ if (sessionId) {
5129
+ const session = findSession(index, sessionId);
5130
+ if (!session) {
5131
+ throw new Error(`Session "${sessionId}" was not found.`);
5132
+ }
5133
+ if (session.runIds.length === 0) {
5134
+ throw new Error(`Session "${sessionId}" has no runs to bundle.`);
5135
+ }
5136
+ return {
5137
+ runIds: [...session.runIds].sort((a, b) => a.localeCompare(b)),
5138
+ sessionId
5139
+ };
5140
+ }
5141
+ const runIds = runsInSinceWindow(runs, since);
5142
+ if (runIds.length === 0) {
5143
+ throw new Error(`No runs matched --since ${since}.`);
5144
+ }
5145
+ return { runIds, since };
5146
+ }
5147
+
5148
+ // packages/core/src/bundle/safety-status.ts
5149
+ function aggregateBundleSafeStatus(statuses) {
5150
+ if (statuses.length === 0) return "UNKNOWN";
5151
+ if (statuses.some((status) => status === "UNSAFE")) return "UNSAFE";
5152
+ if (statuses.some((status) => status === "UNKNOWN")) return "UNKNOWN";
5153
+ if (statuses.some((status) => status === "SAFE WITH WARNINGS")) return "SAFE WITH WARNINGS";
5154
+ return "SAFE";
5155
+ }
5156
+ function toMetadataSafeStatus(status) {
5157
+ if (status === "SAFE WITH WARNINGS") return "SAFE_WITH_WARNINGS";
5158
+ return status;
5159
+ }
5160
+ function bundleFailsOnSafety(status, allowUnsafe) {
5161
+ if (allowUnsafe) return false;
5162
+ return status === "UNSAFE" || status === "UNKNOWN";
5163
+ }
5164
+
5165
+ // packages/core/src/bundle/manifest.ts
5166
+ var BUNDLE_NOTE = "Generated locally by AgentInspect. Bundles are derived copies for review \u2014 not compliance or security certification. Review before sharing.";
5167
+ var PLACEHOLDER_NOTE = "No eval or performance artifacts were requested for this bundle.";
5168
+ function buildBundleMetadata(parts) {
5169
+ const aggregate = aggregateBundleSafeStatus(
5170
+ parts.checks.runs.map((run) => run.status)
5171
+ );
5172
+ return {
5173
+ createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
5174
+ agentInspectVersion: parts.agentInspectVersion,
5175
+ redactionProfile: parts.profile,
5176
+ sourceTraceCount: parts.resolve.runIds.length,
5177
+ runIds: [...parts.resolve.runIds],
5178
+ safeStatus: toMetadataSafeStatus(aggregate),
5179
+ files: [...parts.files].sort((a, b) => a.localeCompare(b)),
5180
+ note: BUNDLE_NOTE,
5181
+ ...parts.resolve.sessionId !== void 0 ? { sessionId: parts.resolve.sessionId } : {},
5182
+ ...parts.resolve.since !== void 0 ? { since: parts.resolve.since } : {}
5183
+ };
5184
+ }
5185
+ function buildPlaceholderArtifact() {
5186
+ return {
5187
+ status: "not_requested",
5188
+ note: PLACEHOLDER_NOTE
5189
+ };
5190
+ }
5191
+
5192
+ // packages/core/src/bundle/summary.ts
5193
+ function markdownTable(rows) {
5194
+ const lines = ["| Field | Value |", "| --- | --- |"];
5195
+ for (const [key, value] of rows) {
5196
+ lines.push(`| ${key} | ${value ?? "unknown"} |`);
5197
+ }
5198
+ return lines.join("\n");
5199
+ }
5200
+ function buildBundleSummaryMarkdown(parts) {
5201
+ const { metadata, checks, redaction } = parts;
5202
+ const lines = [
5203
+ "# AgentInspect trace bundle",
5204
+ "",
5205
+ metadata.note,
5206
+ "",
5207
+ "## Overview",
5208
+ "",
5209
+ markdownTable([
5210
+ ["Created", metadata.createdAt],
5211
+ ["AgentInspect", metadata.agentInspectVersion],
5212
+ ["Redaction profile", metadata.redactionProfile],
5213
+ ["Safe status", metadata.safeStatus],
5214
+ ["Source traces", metadata.sourceTraceCount],
5215
+ ["Runs", metadata.runIds.join(", ")],
5216
+ ...metadata.sessionId ? [["Session", metadata.sessionId]] : [],
5217
+ ...metadata.since ? [["Since", metadata.since]] : []
5218
+ ]),
5219
+ "",
5220
+ "## Safety checks",
5221
+ "",
5222
+ `Aggregate: **${checks.aggregateStatus}**`,
5223
+ ""
5224
+ ];
5225
+ for (const run of checks.runs) {
5226
+ lines.push(
5227
+ `- \`${run.runId}\`: ${run.status} (${run.findings} finding(s), ${run.errors} error(s), ${run.warnings} warning(s))`
5228
+ );
5229
+ }
5230
+ lines.push("", "## Redaction", "", `Total findings: ${redaction.totalFindings}`, "");
5231
+ for (const run of redaction.runs) {
5232
+ const detectors = run.detectors.length > 0 ? run.detectors.join(", ") : "none";
5233
+ lines.push(`- \`${run.runId}\`: ${run.findings} finding(s); detectors: ${detectors}`);
5234
+ }
5235
+ lines.push(
5236
+ "",
5237
+ "## Files",
5238
+ "",
5239
+ ...metadata.files.map((file) => `- \`${file}\``),
5240
+ "",
5241
+ "_Review every generated artifact before sharing outside your team._",
5242
+ ""
5243
+ );
5244
+ return lines.join("\n");
5245
+ }
5246
+ function normalizeBundleOutputPath(out) {
5247
+ const trimmed = out.trim();
5248
+ if (trimmed === "") {
5249
+ throw new Error("--out requires a non-empty path.");
5250
+ }
5251
+ const resolved = path__default.default.resolve(trimmed);
5252
+ if (resolved.toLowerCase().endsWith(".zip")) {
5253
+ return resolved.slice(0, -4);
5254
+ }
5255
+ return resolved;
5256
+ }
5257
+ function defaultBundleOutputPath(runIds) {
5258
+ const label = runIds.length === 1 ? runIds[0] : `multi-${runIds.length}`;
5259
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5260
+ return path__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
5261
+ }
5262
+
4887
5263
  // packages/core/src/inspect-run.ts
4888
5264
  function normalizeRunName(name) {
4889
5265
  if (typeof name !== "string" || name.trim() === "") {
@@ -5026,18 +5402,24 @@ exports.RUNS_DIR_NAME = RUNS_DIR_NAME;
5026
5402
  exports.SESSION_WORKFLOW_KEYS = SESSION_WORKFLOW_KEYS;
5027
5403
  exports.TERMINAL_INDENT = TERMINAL_INDENT;
5028
5404
  exports.TraceDirectory = TraceDirectory;
5405
+ exports.aggregateBundleSafeStatus = aggregateBundleSafeStatus;
5029
5406
  exports.aggregateSessionCheckResults = aggregateSessionCheckResults;
5030
5407
  exports.buildActivitySummary = buildActivitySummary;
5408
+ exports.buildBundleMetadata = buildBundleMetadata;
5409
+ exports.buildBundleSummaryMarkdown = buildBundleSummaryMarkdown;
5031
5410
  exports.buildLocalExplanation = buildLocalExplanation;
5411
+ exports.buildPlaceholderArtifact = buildPlaceholderArtifact;
5032
5412
  exports.buildRunSummary = buildRunSummary;
5033
5413
  exports.buildRunTimeline = buildRunTimeline;
5034
5414
  exports.buildRunWhatSummary = buildRunWhatSummary;
5035
5415
  exports.buildSessionIndex = buildSessionIndex;
5036
5416
  exports.buildTraceStats = buildTraceStats;
5417
+ exports.bundleFailsOnSafety = bundleFailsOnSafety;
5037
5418
  exports.createInspector = createInspector;
5038
5419
  exports.createInspectorRuntime = createInspectorRuntime;
5039
5420
  exports.createRunId = createRunId;
5040
5421
  exports.createStepId = createStepId;
5422
+ exports.defaultBundleOutputPath = defaultBundleOutputPath;
5041
5423
  exports.deriveSessionStatus = deriveSessionStatus;
5042
5424
  exports.enrichSessionRunRecord = enrichSessionRunRecord;
5043
5425
  exports.enrichSessionSummary = enrichSessionSummary;
@@ -5076,6 +5458,7 @@ exports.listTraceFiles = listTraceFiles;
5076
5458
  exports.loadSessionRunRecords = loadSessionRunRecords;
5077
5459
  exports.loadTraceMetadataList = loadTraceMetadataList;
5078
5460
  exports.maybeInspectRun = maybeInspectRun;
5461
+ exports.normalizeBundleOutputPath = normalizeBundleOutputPath;
5079
5462
  exports.parseDuration = parseDuration;
5080
5463
  exports.parseDurationFilter = parseDurationFilter;
5081
5464
  exports.parseTraceJsonl = parseTraceJsonl;
@@ -5096,6 +5479,7 @@ exports.renderRunWhat = renderRunWhat;
5096
5479
  exports.renderStepLine = renderStepLine;
5097
5480
  exports.renderTimeline = renderTimeline;
5098
5481
  exports.renderTraceStats = renderTraceStats;
5482
+ exports.resolveBundleRunIds = resolveBundleRunIds;
5099
5483
  exports.resolveRedactionProfile = resolveRedactionProfile;
5100
5484
  exports.resolveTraceDir = resolveTraceDir;
5101
5485
  exports.resolveTraceSafetyOptions = resolveTraceSafetyOptions;
@@ -5104,6 +5488,7 @@ exports.runWithStepContext = runWithStepContext;
5104
5488
  exports.searchTraces = searchTraces;
5105
5489
  exports.serializeEvent = serializeEvent;
5106
5490
  exports.sessionKeyForRun = sessionKeyForRun;
5491
+ exports.toMetadataSafeStatus = toMetadataSafeStatus;
5107
5492
  exports.traceMetasToSessionRunRecords = traceMetasToSessionRunRecords;
5108
5493
  exports.truncateName = truncateName;
5109
5494
  exports.unknownTraceFormatMessage = unknownTraceFormatMessage;