@agent-inspect/mcp-server 6.31.9 → 6.31.11

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.
@@ -1682,7 +1682,7 @@ function stepMixLine(summary) {
1682
1682
  if (summary.logicSteps > 0) parts.push(`${summary.logicSteps} logic`);
1683
1683
  return parts.length > 0 ? parts.join(", ") : "none";
1684
1684
  }
1685
- function outcomeLine(summary) {
1685
+ function executionLine(summary) {
1686
1686
  if (summary.status === "success") {
1687
1687
  return summary.errorSteps > 0 ? "Completed with step errors recorded." : "Completed successfully.";
1688
1688
  }
@@ -1700,7 +1700,7 @@ function outcomeLine(summary) {
1700
1700
  if (summary.status === "running") {
1701
1701
  return "Run is still in progress (no run_completed).";
1702
1702
  }
1703
- return "Outcome unknown \u2014 inspect events may be incomplete.";
1703
+ return "Execution status unknown \u2014 inspect events may be incomplete.";
1704
1704
  }
1705
1705
  function buildRunWhatSummary(events) {
1706
1706
  const base = buildRunSummary(events);
@@ -1791,7 +1791,7 @@ function renderRunWhat(summary, options = {}) {
1791
1791
  lines.push(`Correlation: ${parts.join(", ")}`);
1792
1792
  }
1793
1793
  }
1794
- lines.push(`Outcome: ${outcomeLine(summary)}`);
1794
+ lines.push(`Execution: ${executionLine(summary)}`);
1795
1795
  if (summary.longestStep && summary.totalSteps > 0) {
1796
1796
  lines.push(
1797
1797
  `Slowest: ${summary.longestStep.name} (${formatDuration2(summary.longestStep.durationMs)}, ${summary.longestStep.type})`
@@ -1945,6 +1945,369 @@ function findFirstCausalFailure(events, options = {}) {
1945
1945
  );
1946
1946
  }
1947
1947
 
1948
+ // packages/core/src/diagnostics/programmatic.ts
1949
+ var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
1950
+ AI_TRACE_INPUT_INVALID: {
1951
+ code: "AI_TRACE_INPUT_INVALID",
1952
+ summary: 'Expected { type: "file", path }, { type: "directory", path }, { type: "string", content }, { type: "buffer", content }, or { type: "stdin" }.',
1953
+ remediation: "For a file path, use openTraceFile(path).",
1954
+ relatedCodes: ["invalid_input"]
1955
+ },
1956
+ AI_TRACE_FORMAT_UNSUPPORTED: {
1957
+ code: "AI_TRACE_FORMAT_UNSUPPORTED",
1958
+ summary: "No trace reader could detect the input format.",
1959
+ remediation: "Pass an AgentInspect JSONL file via openTraceFile, or set options.format to a registered reader.",
1960
+ relatedCodes: ["unsupported_format"]
1961
+ },
1962
+ AI_TRACE_FORMAT_AMBIGUOUS: {
1963
+ code: "AI_TRACE_FORMAT_AMBIGUOUS",
1964
+ summary: "Multiple trace readers matched the input with equal confidence.",
1965
+ remediation: "Set options.format explicitly to disambiguate the reader.",
1966
+ relatedCodes: ["ambiguous_format"]
1967
+ },
1968
+ AI_TRACE_FACTS_INPUT_NOT_NORMALIZED: {
1969
+ code: "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED",
1970
+ summary: "TraceFacts requires TraceReadResult or PersistedInspectEvent[].",
1971
+ remediation: "Use openTraceFile() to normalize a JSONL trace first."
1972
+ },
1973
+ AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED: {
1974
+ code: "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
1975
+ summary: "Multiple runs are available; select a run before executing checks.",
1976
+ remediation: "Pass options.runId or TraceCheckInput.selectedRun.",
1977
+ relatedCodes: ["AI_CHECK_RUN_SELECTION_REQUIRED"]
1978
+ },
1979
+ AI_TRACE_RELATIONSHIP_SELF_PARENT: {
1980
+ code: "AI_TRACE_RELATIONSHIP_SELF_PARENT",
1981
+ summary: "A parentId equals its own event/step id.",
1982
+ remediation: "Reject at capture (AI_LANGGRAPH_SELF_PARENT_REJECTED) or drop via logical projection; do not invent replacement parents.",
1983
+ relatedCodes: [
1984
+ "AI_LANGGRAPH_SELF_PARENT_REJECTED",
1985
+ "AI_LOGICAL_SELF_PARENT_REMOVED"
1986
+ ]
1987
+ },
1988
+ AI_TRACE_RELATIONSHIP_CYCLE: {
1989
+ code: "AI_TRACE_RELATIONSHIP_CYCLE",
1990
+ summary: "Trace contains a parentId cycle.",
1991
+ remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
1992
+ relatedCodes: ["structure.cycle"]
1993
+ },
1994
+ AI_TRACE_CONTRACT_INPUT_INVALID: {
1995
+ code: "AI_TRACE_CONTRACT_INPUT_INVALID",
1996
+ summary: "evaluateTraceContract expects ({ read }, contract) or use evaluateTraceContractRead(read, contract).",
1997
+ remediation: "Pass TraceCheckInput as the first argument: evaluateTraceContract({ read }, contract).",
1998
+ relatedCodes: ["AI_CHECK_INVALID_ARGUMENTS"]
1999
+ },
2000
+ AI_INSPECT_RUN_UNSUPPORTED_OPTION: {
2001
+ code: "AI_INSPECT_RUN_UNSUPPORTED_OPTION",
2002
+ summary: 'inspectRun does not accept a "writer" option.',
2003
+ remediation: "Use createInspector({ writer }) then inspector.run(...). inspectRun persists via the global JSONL path (schema 0.1)."
2004
+ }
2005
+ });
2006
+ function formatProgrammaticDiagnostic(code, detail) {
2007
+ const spec = PROGRAMMATIC_DIAGNOSTIC_SPECS[code];
2008
+ const summary = detail?.trim() ? detail.trim() : spec.summary;
2009
+ return `${code}: ${summary} Remediation: ${spec.remediation}`;
2010
+ }
2011
+
2012
+ // packages/core/src/checks/logical-events.ts
2013
+ function isRecord6(value) {
2014
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2015
+ }
2016
+ function legacyEvent(event) {
2017
+ const value = event.attributes?.legacyEvent;
2018
+ return typeof value === "string" ? value : void 0;
2019
+ }
2020
+ function stepIdOf(event) {
2021
+ const value = event.attributes?.stepId;
2022
+ if (typeof value === "string" && value.trim() !== "") return value;
2023
+ return void 0;
2024
+ }
2025
+ function cloneEvent(event) {
2026
+ return {
2027
+ ...event,
2028
+ ...event.attributes !== void 0 ? { attributes: { ...event.attributes } } : {},
2029
+ ...event.error !== void 0 ? { error: { ...event.error } } : {},
2030
+ ...event.tokenUsage !== void 0 ? { tokenUsage: { ...event.tokenUsage } } : {},
2031
+ ...event.source !== void 0 ? { source: { ...event.source } } : {}
2032
+ };
2033
+ }
2034
+ function mergeAttributes(start, complete) {
2035
+ const merged = {
2036
+ ...isRecord6(complete.attributes) ? complete.attributes : {},
2037
+ ...isRecord6(start.attributes) ? start.attributes : {}
2038
+ };
2039
+ merged.legacyEvent = start.attributes?.legacyEvent ?? complete.attributes?.legacyEvent;
2040
+ merged.legacyCompleteEvent = complete.attributes?.legacyEvent;
2041
+ if (complete.attributes?.errorStack !== void 0) {
2042
+ merged.errorStack = complete.attributes.errorStack;
2043
+ }
2044
+ return Object.keys(merged).length > 0 ? merged : void 0;
2045
+ }
2046
+ function pairStartComplete(start, complete) {
2047
+ const attributes = mergeAttributes(start, complete);
2048
+ const paired = {
2049
+ ...cloneEvent(start),
2050
+ status: complete.status,
2051
+ timestamp: complete.timestamp ?? start.timestamp,
2052
+ ...complete.endedAt !== void 0 ? { endedAt: complete.endedAt } : {},
2053
+ ...complete.durationMs !== void 0 ? { durationMs: complete.durationMs } : {},
2054
+ ...complete.error !== void 0 ? { error: { ...complete.error } } : {},
2055
+ ...complete.tokenUsage !== void 0 && start.tokenUsage === void 0 ? { tokenUsage: { ...complete.tokenUsage } } : {},
2056
+ ...attributes !== void 0 ? { attributes } : {}
2057
+ };
2058
+ return {
2059
+ ...paired,
2060
+ sourceEventIds: Object.freeze([start.eventId, complete.eventId]),
2061
+ projection: {
2062
+ paired: true,
2063
+ absorbedEventIds: Object.freeze([complete.eventId]),
2064
+ parentNormalized: false,
2065
+ ...start.parentId !== void 0 ? { originalParentId: start.parentId } : {}
2066
+ }
2067
+ };
2068
+ }
2069
+ function asLogical(event, extras) {
2070
+ return {
2071
+ ...cloneEvent(event),
2072
+ sourceEventIds: Object.freeze([event.eventId]),
2073
+ projection: {
2074
+ paired: false,
2075
+ absorbedEventIds: Object.freeze([]),
2076
+ parentNormalized: extras?.parentNormalized === true,
2077
+ ...{}
2078
+ }
2079
+ };
2080
+ }
2081
+ function projectLogicalEvents(events) {
2082
+ const diagnostics = [];
2083
+ const byRun = /* @__PURE__ */ new Map();
2084
+ for (const event of events) {
2085
+ const list = byRun.get(event.runId) ?? [];
2086
+ list.push(event);
2087
+ byRun.set(event.runId, list);
2088
+ }
2089
+ const absorbedIds = /* @__PURE__ */ new Set();
2090
+ const logicalByRawId = /* @__PURE__ */ new Map();
2091
+ const stepIdToLogicalId = /* @__PURE__ */ new Map();
2092
+ const logical = [];
2093
+ const orderedRuns = [...byRun.keys()].sort((a, b) => a.localeCompare(b));
2094
+ for (const runId of orderedRuns) {
2095
+ const runEvents = byRun.get(runId) ?? [];
2096
+ const starts = [];
2097
+ const completes = [];
2098
+ const others = [];
2099
+ for (const event of runEvents) {
2100
+ const legacy = legacyEvent(event);
2101
+ if (legacy === "step_started" || legacy === "run_started" && event.status === "running") {
2102
+ starts.push(event);
2103
+ } else if (legacy === "step_completed" || legacy === "run_completed") {
2104
+ completes.push(event);
2105
+ } else {
2106
+ others.push(event);
2107
+ }
2108
+ }
2109
+ const usedCompletes = /* @__PURE__ */ new Set();
2110
+ for (const start of starts) {
2111
+ const stepId = stepIdOf(start);
2112
+ let match;
2113
+ if (legacyEvent(start) === "run_started") {
2114
+ const candidates = completes.filter(
2115
+ (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "run_completed"
2116
+ );
2117
+ if (candidates.length > 1) {
2118
+ diagnostics.push({
2119
+ code: "AI_LOGICAL_PAIR_AMBIGUOUS",
2120
+ message: `Multiple run_completed rows for run ${runId}; using first by eventId.`,
2121
+ eventIds: candidates.map((c) => c.eventId)
2122
+ });
2123
+ candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
2124
+ }
2125
+ match = candidates[0];
2126
+ } else if (stepId) {
2127
+ const candidates = completes.filter(
2128
+ (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "step_completed" && stepIdOf(c) === stepId
2129
+ );
2130
+ if (candidates.length > 1) {
2131
+ diagnostics.push({
2132
+ code: "AI_LOGICAL_PAIR_AMBIGUOUS",
2133
+ message: `Multiple step_completed rows for stepId ${stepId}; using first by eventId.`,
2134
+ eventIds: candidates.map((c) => c.eventId)
2135
+ });
2136
+ candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
2137
+ }
2138
+ match = candidates[0];
2139
+ }
2140
+ if (match) {
2141
+ usedCompletes.add(match.eventId);
2142
+ absorbedIds.add(match.eventId);
2143
+ const paired = pairStartComplete(start, match);
2144
+ logical.push(paired);
2145
+ logicalByRawId.set(start.eventId, paired);
2146
+ logicalByRawId.set(match.eventId, paired);
2147
+ if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, paired.eventId);
2148
+ } else {
2149
+ diagnostics.push({
2150
+ code: "AI_LOGICAL_PAIR_UNMATCHED_START",
2151
+ message: `No matching complete for start ${start.eventId}.`,
2152
+ eventIds: [start.eventId]
2153
+ });
2154
+ const alone = asLogical(start);
2155
+ logical.push(alone);
2156
+ logicalByRawId.set(start.eventId, alone);
2157
+ if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2158
+ }
2159
+ }
2160
+ for (const complete of completes) {
2161
+ if (usedCompletes.has(complete.eventId)) continue;
2162
+ diagnostics.push({
2163
+ code: "AI_LOGICAL_PAIR_UNMATCHED_COMPLETE",
2164
+ message: `No matching start for complete ${complete.eventId}.`,
2165
+ eventIds: [complete.eventId]
2166
+ });
2167
+ const alone = asLogical(complete);
2168
+ logical.push(alone);
2169
+ logicalByRawId.set(complete.eventId, alone);
2170
+ const stepId = stepIdOf(complete);
2171
+ if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
2172
+ stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2173
+ }
2174
+ }
2175
+ for (const event of others) {
2176
+ const alone = asLogical(event);
2177
+ logical.push(alone);
2178
+ logicalByRawId.set(event.eventId, alone);
2179
+ const stepId = stepIdOf(event);
2180
+ if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
2181
+ stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2182
+ }
2183
+ }
2184
+ }
2185
+ const logicalById = new Map(logical.map((e) => [e.eventId, e]));
2186
+ const normalized = [];
2187
+ for (const event of logical) {
2188
+ const originalParentId = event.parentId;
2189
+ if (!originalParentId) {
2190
+ normalized.push(event);
2191
+ continue;
2192
+ }
2193
+ let nextParent = originalParentId;
2194
+ let remapped = false;
2195
+ const viaAbsorbed = logicalByRawId.get(originalParentId);
2196
+ if (viaAbsorbed && viaAbsorbed.eventId !== originalParentId) {
2197
+ nextParent = viaAbsorbed.eventId;
2198
+ remapped = true;
2199
+ } else if (!logicalById.has(originalParentId)) {
2200
+ const viaStep = stepIdToLogicalId.get(`${event.runId}:${originalParentId}`);
2201
+ if (viaStep) {
2202
+ nextParent = viaStep;
2203
+ remapped = true;
2204
+ }
2205
+ }
2206
+ if (!remapped) {
2207
+ if (originalParentId === event.eventId) {
2208
+ diagnostics.push({
2209
+ code: "AI_LOGICAL_SELF_PARENT_REMOVED",
2210
+ message: formatProgrammaticDiagnostic(
2211
+ "AI_TRACE_RELATIONSHIP_SELF_PARENT",
2212
+ `Removed self-parent edge on ${event.eventId}.`
2213
+ ),
2214
+ eventIds: [event.eventId]
2215
+ });
2216
+ const { parentId: _drop, ...rest } = event;
2217
+ normalized.push({
2218
+ ...rest,
2219
+ projection: {
2220
+ ...event.projection,
2221
+ parentNormalized: true,
2222
+ originalParentId
2223
+ }
2224
+ });
2225
+ continue;
2226
+ }
2227
+ if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
2228
+ const mapping = event.attributes?.parentMapping;
2229
+ const unresolved = mapping === "unresolved" || event.attributes?.parentUnresolved === true || event.attributes?.unresolvedParent === true || // LangGraph/framework scaffolding sentinel labels are not event ids.
2230
+ /^LangGraph$/i.test(originalParentId) || originalParentId.startsWith("unresolved:");
2231
+ if (!unresolved) {
2232
+ diagnostics.push({
2233
+ code: "AI_LOGICAL_PARENT_UNRESOLVED",
2234
+ message: `Parent ${originalParentId} unresolved for ${event.eventId}.`,
2235
+ eventIds: [event.eventId]
2236
+ });
2237
+ }
2238
+ }
2239
+ normalized.push(event);
2240
+ continue;
2241
+ }
2242
+ if (nextParent === event.eventId) {
2243
+ diagnostics.push({
2244
+ code: "AI_LOGICAL_SELF_PARENT_REMOVED",
2245
+ message: formatProgrammaticDiagnostic(
2246
+ "AI_TRACE_RELATIONSHIP_SELF_PARENT",
2247
+ `Removed self-parent edge on ${event.eventId} (was ${originalParentId}).`
2248
+ ),
2249
+ eventIds: [event.eventId]
2250
+ });
2251
+ const { parentId: _drop, ...rest } = event;
2252
+ normalized.push({
2253
+ ...rest,
2254
+ projection: {
2255
+ ...event.projection,
2256
+ parentNormalized: true,
2257
+ originalParentId
2258
+ }
2259
+ });
2260
+ continue;
2261
+ }
2262
+ diagnostics.push({
2263
+ code: "AI_LOGICAL_PARENT_REMAPPED",
2264
+ message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
2265
+ eventIds: [event.eventId]
2266
+ });
2267
+ normalized.push({
2268
+ ...event,
2269
+ parentId: nextParent,
2270
+ projection: {
2271
+ ...event.projection,
2272
+ parentNormalized: true,
2273
+ originalParentId
2274
+ }
2275
+ });
2276
+ }
2277
+ const rawIndex = new Map(events.map((e, i) => [e.eventId, i]));
2278
+ normalized.sort((a, b) => {
2279
+ const ai = rawIndex.get(a.sourceEventIds[0]) ?? 0;
2280
+ const bi = rawIndex.get(b.sourceEventIds[0]) ?? 0;
2281
+ return ai - bi || a.eventId.localeCompare(b.eventId);
2282
+ });
2283
+ return {
2284
+ logicalEvents: Object.freeze(normalized),
2285
+ diagnostics: Object.freeze(diagnostics)
2286
+ };
2287
+ }
2288
+ function resolveCanonicalToolName(event) {
2289
+ const attrs2 = event.attributes;
2290
+ const direct = pickString(attrs2, ["toolName", "tool"]);
2291
+ if (direct) return direct;
2292
+ const metadata = attrs2?.metadata;
2293
+ if (isRecord6(metadata)) {
2294
+ const nested = pickString(metadata, ["toolName", "tool"]);
2295
+ if (nested) return nested;
2296
+ }
2297
+ for (const prefix of ["tool:", "function:", "mcp-tools:"]) {
2298
+ if (event.name.startsWith(prefix)) return event.name.slice(prefix.length);
2299
+ }
2300
+ return event.name;
2301
+ }
2302
+ function pickString(record, keys) {
2303
+ if (!record) return void 0;
2304
+ for (const key of keys) {
2305
+ const value = record[key];
2306
+ if (typeof value === "string" && value.trim() !== "") return value.trim();
2307
+ }
2308
+ return void 0;
2309
+ }
2310
+
1948
2311
  // packages/core/src/search.ts
1949
2312
  function parseDurationFilter(expr) {
1950
2313
  const raw = expr.trim();
@@ -2044,708 +2407,357 @@ async function searchTraces(metas, options) {
2044
2407
  statusFilter: options.status
2045
2408
  });
2046
2409
  results.push(...stepMatches);
2047
- if (observationStatus) {
2048
- const outcomes = extractOutcomesFromTraceEvents(events);
2049
- const matched = outcomes.filter((outcome) => outcome.status === observationStatus);
2050
- for (const outcome of matched) {
2051
- results.push({
2052
- runId: m.runId,
2053
- runName: m.name,
2054
- runStatus: m.status,
2055
- stepName: outcome.name,
2056
- timestamp: outcome.observedAt,
2057
- matchReason: `observation status=${outcome.status}`,
2058
- matchedFields: ["outcome.status", "outcome.name"],
2059
- filePath: m.filePath
2060
- });
2061
- }
2062
- }
2063
- }
2064
- results.sort((a, b) => {
2065
- const ta = a.timestamp ?? 0;
2066
- const tb = b.timestamp ?? 0;
2067
- if (ta !== tb) return tb - ta;
2068
- const runCmp = a.runId.localeCompare(b.runId);
2069
- if (runCmp !== 0) return runCmp;
2070
- return (a.stepName ?? "").localeCompare(b.stepName ?? "");
2071
- });
2072
- return results.slice(0, limit);
2073
- }
2074
- function matchRunLevel(m, opts) {
2075
- if (opts.stepTypeFilter || opts.toolQuery) return [];
2076
- if (opts.statusFilter && m.status !== opts.statusFilter) return [];
2077
- if (opts.nameQuery && !nameMatches(m.name ?? m.runId, opts.nameQuery)) {
2078
- return [];
2079
- }
2080
- if (opts.durationFilter && !durationMatches(m.durationMs, opts.durationFilter)) {
2081
- return [];
2082
- }
2083
- const fields = [];
2084
- if (opts.statusFilter) fields.push("run.status");
2085
- if (opts.nameQuery) fields.push("run.name");
2086
- if (opts.durationFilter) fields.push("run.durationMs");
2087
- if (fields.length === 0) return [];
2088
- return [
2089
- {
2090
- runId: m.runId,
2091
- runName: m.name,
2092
- runStatus: m.status,
2093
- timestamp: m.startedAt,
2094
- durationMs: m.durationMs,
2095
- matchReason: `run match: ${fields.join(", ")}`,
2096
- matchedFields: fields,
2097
- filePath: m.filePath
2098
- }
2099
- ];
2100
- }
2101
- function matchStepLevel(m, events, opts) {
2102
- const out = [];
2103
- const started = /* @__PURE__ */ new Map();
2104
- for (const e of events) {
2105
- if (e.event === "step_started") {
2106
- started.set(e.stepId, e);
2107
- }
2108
- }
2109
- for (const e of events) {
2110
- if (e.event !== "step_completed") continue;
2111
- const c = e;
2112
- const s = started.get(c.stepId);
2113
- if (!s) continue;
2114
- const fields = [];
2115
- const stepType = s.type;
2116
- if (opts.stepTypeFilter && stepType !== opts.stepTypeFilter) {
2117
- continue;
2118
- }
2119
- const hasStepFilters = opts.stepTypeFilter || opts.nameQuery || opts.toolQuery || opts.durationFilter || opts.statusFilter === "error" || opts.statusFilter === "success";
2120
- if (!hasStepFilters) continue;
2121
- if (opts.statusFilter === "error" && c.status === "error") {
2122
- fields.push("step.status");
2123
- } else if (opts.statusFilter === "success" && c.status === "success") {
2124
- fields.push("step.status");
2125
- } else if (opts.statusFilter === "error" || opts.statusFilter === "success") {
2126
- continue;
2127
- }
2128
- if (opts.nameQuery) {
2129
- if (!nameMatches(s.name, opts.nameQuery)) continue;
2130
- fields.push("step.name");
2131
- }
2132
- if (opts.toolQuery) {
2133
- const toolName = typeof s.metadata?.toolName === "string" ? s.metadata.toolName : s.name;
2134
- if (!nameMatches(toolName, opts.toolQuery)) continue;
2135
- fields.push("step.tool");
2136
- }
2137
- if (opts.durationFilter) {
2138
- if (!durationMatches(c.durationMs, opts.durationFilter)) continue;
2139
- fields.push("step.durationMs");
2140
- }
2141
- if (opts.stepTypeFilter) {
2142
- fields.push("step.type");
2143
- }
2144
- if (fields.length === 0) continue;
2145
- out.push({
2146
- runId: m.runId,
2147
- runName: m.name,
2148
- runStatus: m.status,
2149
- stepId: c.stepId,
2150
- stepName: s.name,
2151
- stepType,
2152
- timestamp: s.startTime ?? s.timestamp,
2153
- durationMs: c.durationMs,
2154
- matchReason: `step match: ${fields.join(", ")}`,
2155
- matchedFields: fields,
2156
- filePath: m.filePath
2157
- });
2158
- }
2159
- return out;
2160
- }
2161
- async function loadTraceMetadataList(_traceDir, fileNames, getPath) {
2162
- const metas = [];
2163
- for (const fileName of fileNames) {
2164
- try {
2165
- const filePath = getPath(fileName);
2166
- const meta = await extractMetadata(filePath);
2167
- metas.push(meta);
2168
- } catch {
2169
- }
2170
- }
2171
- return metas;
2172
- }
2173
-
2174
- // packages/core/src/sessions/metadata.ts
2175
- function isNonEmptyString3(value) {
2176
- return typeof value === "string" && value.trim() !== "";
2177
- }
2178
- function finitePositiveInt(value) {
2179
- if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
2180
- return void 0;
2181
- }
2182
- return Math.trunc(value);
2183
- }
2184
- function extractSessionWorkflowMetadata(record) {
2185
- if (!record) return void 0;
2186
- const out = {};
2187
- let found = false;
2188
- const assignString = (key, value) => {
2189
- if (isNonEmptyString3(value)) {
2190
- out[key] = value.trim();
2191
- found = true;
2192
- }
2193
- };
2194
- assignString("sessionId", record.sessionId);
2195
- assignString("conversationId", record.conversationId);
2196
- assignString("groupId", record.groupId);
2197
- assignString("parentGroupId", record.parentGroupId);
2198
- assignString("retryOf", record.retryOf);
2199
- assignString("retryReason", record.retryReason);
2200
- assignString("handoffFrom", record.handoffFrom);
2201
- assignString("handoffTo", record.handoffTo);
2202
- assignString("subAgentId", record.subAgentId);
2203
- assignString("subAgentName", record.subAgentName);
2204
- assignString("jobId", record.jobId);
2205
- assignString("queueName", record.queueName);
2206
- assignString("workflowName", record.workflowName);
2207
- assignString("workflowStep", record.workflowStep);
2208
- assignString("toolCallId", record.toolCallId);
2209
- assignString("mcpToolCallId", record.mcpToolCallId);
2210
- assignString("linkedStepId", record.linkedStepId);
2211
- assignString("operationId", record.operationId);
2212
- assignString("attemptId", record.attemptId);
2213
- assignString("fallbackOf", record.fallbackOf);
2214
- assignString("idempotencyKey", record.idempotencyKey);
2215
- assignString("correlationId", record.correlationId);
2216
- assignString("requestId", record.requestId);
2217
- assignString("decisionId", record.decisionId);
2218
- const attempt = finitePositiveInt(record.attempt);
2219
- if (attempt !== void 0) {
2220
- out.attempt = attempt;
2221
- found = true;
2222
- }
2223
- const attemptNumber = finitePositiveInt(record.attemptNumber);
2224
- if (attemptNumber !== void 0) {
2225
- out.attemptNumber = attemptNumber;
2226
- found = true;
2227
- }
2228
- return found ? out : void 0;
2229
- }
2230
-
2231
- // packages/core/src/bundle/safety-status.ts
2232
- function aggregateBundleSafeStatus(statuses) {
2233
- if (statuses.length === 0) return "UNKNOWN";
2234
- if (statuses.some((status) => status === "UNSAFE")) return "UNSAFE";
2235
- if (statuses.some((status) => status === "UNKNOWN")) return "UNKNOWN";
2236
- if (statuses.some((status) => status === "SAFE WITH WARNINGS")) return "SAFE WITH WARNINGS";
2237
- return "SAFE";
2238
- }
2239
- function toMetadataSafeStatus(status) {
2240
- if (status === "SAFE WITH WARNINGS") return "SAFE_WITH_WARNINGS";
2241
- return status;
2242
- }
2243
- function bundleFailsOnSafety(status, allowUnsafe) {
2244
- return status === "UNSAFE" || status === "UNKNOWN";
2245
- }
2246
-
2247
- // packages/core/src/bundle/manifest.ts
2248
- var BUNDLE_NOTE = "Generated locally by AgentInspect. Bundles are derived copies for review \u2014 not compliance or security certification. Review before sharing.";
2249
- function buildBundleMetadata(parts) {
2250
- const aggregate = aggregateBundleSafeStatus(
2251
- parts.checks.runs.map((run) => run.status)
2252
- );
2253
- return {
2254
- createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2255
- agentInspectVersion: parts.agentInspectVersion,
2256
- redactionProfile: parts.profile,
2257
- sourceTraceCount: parts.resolve.runIds.length,
2258
- runIds: [...parts.resolve.runIds],
2259
- safeStatus: toMetadataSafeStatus(aggregate),
2260
- files: [...parts.files].sort((a, b) => a.localeCompare(b)),
2261
- note: BUNDLE_NOTE,
2262
- ...parts.resolve.sessionId !== void 0 ? { sessionId: parts.resolve.sessionId } : {},
2263
- ...parts.resolve.since !== void 0 ? { since: parts.resolve.since } : {}
2264
- };
2265
- }
2266
-
2267
- // packages/core/src/evidence/types.ts
2268
- var EVIDENCE_FORMAT_VERSION = "1.0";
2269
- var EVIDENCE_ASSESSMENT_NOTE = "Best-effort local safety verification only; not a compliance certification.";
2270
- var EVIDENCE_MANIFEST_FILENAME = "evidence.json";
2271
- function sha256Hex(data) {
2272
- const hash = createHash("sha256");
2273
- if (typeof data === "string") {
2274
- hash.update(data, "utf8");
2275
- } else {
2276
- hash.update(data);
2410
+ if (observationStatus) {
2411
+ const outcomes = extractOutcomesFromTraceEvents(events);
2412
+ const matched = outcomes.filter((outcome) => outcome.status === observationStatus);
2413
+ for (const outcome of matched) {
2414
+ results.push({
2415
+ runId: m.runId,
2416
+ runName: m.name,
2417
+ runStatus: m.status,
2418
+ stepName: outcome.name,
2419
+ timestamp: outcome.observedAt,
2420
+ matchReason: `observation status=${outcome.status}`,
2421
+ matchedFields: ["outcome.status", "outcome.name"],
2422
+ filePath: m.filePath
2423
+ });
2424
+ }
2425
+ }
2277
2426
  }
2278
- return hash.digest("hex");
2427
+ results.sort((a, b) => {
2428
+ const ta = a.timestamp ?? 0;
2429
+ const tb = b.timestamp ?? 0;
2430
+ if (ta !== tb) return tb - ta;
2431
+ const runCmp = a.runId.localeCompare(b.runId);
2432
+ if (runCmp !== 0) return runCmp;
2433
+ return (a.stepName ?? "").localeCompare(b.stepName ?? "");
2434
+ });
2435
+ return results.slice(0, limit);
2279
2436
  }
2280
- function assertEvidenceRelativePath(relativePath) {
2281
- if (typeof relativePath !== "string" || relativePath.trim() === "") {
2282
- throw new Error("Evidence file path must be a non-empty relative path.");
2283
- }
2284
- const trimmed = relativePath.trim().replaceAll("\\", "/");
2285
- if (path14.isAbsolute(trimmed) || trimmed.startsWith("/")) {
2286
- throw new Error(`Evidence file path must be relative: ${relativePath}`);
2437
+ function matchRunLevel(m, opts) {
2438
+ if (opts.stepTypeFilter || opts.toolQuery) return [];
2439
+ if (opts.statusFilter && m.status !== opts.statusFilter) return [];
2440
+ if (opts.nameQuery && !nameMatches(m.name ?? m.runId, opts.nameQuery)) {
2441
+ return [];
2287
2442
  }
2288
- const parts = trimmed.split("/").filter((part) => part !== "");
2289
- if (parts.length === 0) {
2290
- throw new Error(`Evidence file path must be relative: ${relativePath}`);
2443
+ if (opts.durationFilter && !durationMatches(m.durationMs, opts.durationFilter)) {
2444
+ return [];
2291
2445
  }
2292
- for (const part of parts) {
2293
- if (part === "." || part === "..") {
2294
- throw new Error(`Evidence file path must not contain "." or "..": ${relativePath}`);
2446
+ const fields = [];
2447
+ if (opts.statusFilter) fields.push("run.status");
2448
+ if (opts.nameQuery) fields.push("run.name");
2449
+ if (opts.durationFilter) fields.push("run.durationMs");
2450
+ if (fields.length === 0) return [];
2451
+ return [
2452
+ {
2453
+ runId: m.runId,
2454
+ runName: m.name,
2455
+ runStatus: m.status,
2456
+ timestamp: m.startedAt,
2457
+ durationMs: m.durationMs,
2458
+ matchReason: `run match: ${fields.join(", ")}`,
2459
+ matchedFields: fields,
2460
+ filePath: m.filePath
2295
2461
  }
2296
- }
2297
- return parts.join("/");
2298
- }
2299
-
2300
- // packages/core/src/evidence/manifest.ts
2301
- function stable(value) {
2302
- if (Array.isArray(value)) return value.map(stable);
2303
- if (value === null || typeof value !== "object") return value;
2304
- const record = value;
2305
- return Object.fromEntries(
2306
- Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable(record[key])])
2307
- );
2308
- }
2309
- function serializeEvidenceManifest(manifest) {
2310
- return `${JSON.stringify(stable(manifest), null, 2)}
2311
- `;
2462
+ ];
2312
2463
  }
2313
- function inferEvidenceFileRole(relativePath) {
2314
- const normalized = assertEvidenceRelativePath(relativePath);
2315
- const base = normalized.includes("/") ? normalized.slice(normalized.lastIndexOf("/") + 1) : normalized;
2316
- if (base === "evidence.html" || base === "trace.html" || base.endsWith(".html")) {
2317
- return "report";
2318
- }
2319
- if (base === "trace.jsonl" || base.endsWith(".jsonl")) {
2320
- return "redacted-trace";
2321
- }
2322
- if (base === "check-results.json") {
2323
- return "checks";
2324
- }
2325
- if (base === "contract.resolved.json") {
2326
- return "contract";
2327
- }
2328
- if (base === "redaction-report.json") {
2329
- return "redaction-report";
2330
- }
2331
- if (base === "summary.md") {
2332
- return "summary";
2464
+ function matchStepLevel(m, events, opts) {
2465
+ const out = [];
2466
+ const started = /* @__PURE__ */ new Map();
2467
+ for (const e of events) {
2468
+ if (e.event === "step_started") {
2469
+ started.set(e.stepId, e);
2470
+ }
2333
2471
  }
2334
- return "other";
2335
- }
2336
- function buildEvidenceFileEntries(files) {
2337
- const byPath = /* @__PURE__ */ new Map();
2338
- for (const file of files) {
2339
- const relativePath = assertEvidenceRelativePath(file.path);
2340
- if (relativePath === EVIDENCE_MANIFEST_FILENAME) {
2341
- throw new Error(
2342
- `Do not include ${EVIDENCE_MANIFEST_FILENAME} in packaged file hashes (self-hash is undefined).`
2343
- );
2472
+ for (const e of events) {
2473
+ if (e.event !== "step_completed") continue;
2474
+ const c = e;
2475
+ const s = started.get(c.stepId);
2476
+ if (!s) continue;
2477
+ const fields = [];
2478
+ const stepType = s.type;
2479
+ if (opts.stepTypeFilter && stepType !== opts.stepTypeFilter) {
2480
+ continue;
2344
2481
  }
2345
- if (byPath.has(relativePath)) {
2346
- throw new Error(`Duplicate evidence file path: ${relativePath}`);
2482
+ const hasStepFilters = opts.stepTypeFilter || opts.nameQuery || opts.toolQuery || opts.durationFilter || opts.statusFilter === "error" || opts.statusFilter === "success";
2483
+ if (!hasStepFilters) continue;
2484
+ if (opts.statusFilter === "error" && c.status === "error") {
2485
+ fields.push("step.status");
2486
+ } else if (opts.statusFilter === "success" && c.status === "success") {
2487
+ fields.push("step.status");
2488
+ } else if (opts.statusFilter === "error" || opts.statusFilter === "success") {
2489
+ continue;
2347
2490
  }
2348
- byPath.set(relativePath, {
2349
- path: relativePath,
2350
- sha256: sha256Hex(file.content),
2351
- role: file.role ?? inferEvidenceFileRole(relativePath)
2352
- });
2353
- }
2354
- return [...byPath.values()].sort((a, b) => a.path.localeCompare(b.path));
2355
- }
2356
- function buildEvidenceManifest(parts) {
2357
- const runIds = [...parts.runIds];
2358
- if (runIds.length === 0) {
2359
- throw new Error("Evidence manifest requires at least one run id.");
2360
- }
2361
- for (const item of parts.sourceHashes) {
2362
- if (!runIds.includes(item.runId)) {
2363
- throw new Error(`sourceHashes runId "${item.runId}" is not listed in source.runIds.`);
2491
+ if (opts.nameQuery) {
2492
+ if (!nameMatches(s.name, opts.nameQuery)) continue;
2493
+ fields.push("step.name");
2364
2494
  }
2365
- if (item.algorithm !== "sha256") {
2366
- throw new Error(`Unsupported source hash algorithm: ${item.algorithm}`);
2495
+ if (opts.toolQuery) {
2496
+ const toolName = typeof s.metadata?.toolName === "string" ? s.metadata.toolName : s.name;
2497
+ if (!nameMatches(toolName, opts.toolQuery)) continue;
2498
+ fields.push("step.tool");
2367
2499
  }
2500
+ if (opts.durationFilter) {
2501
+ if (!durationMatches(c.durationMs, opts.durationFilter)) continue;
2502
+ fields.push("step.durationMs");
2503
+ }
2504
+ if (opts.stepTypeFilter) {
2505
+ fields.push("step.type");
2506
+ }
2507
+ if (fields.length === 0) continue;
2508
+ out.push({
2509
+ runId: m.runId,
2510
+ runName: m.name,
2511
+ runStatus: m.status,
2512
+ stepId: c.stepId,
2513
+ stepName: s.name,
2514
+ stepType,
2515
+ timestamp: s.startTime ?? s.timestamp,
2516
+ durationMs: c.durationMs,
2517
+ matchReason: `step match: ${fields.join(", ")}`,
2518
+ matchedFields: fields,
2519
+ filePath: m.filePath
2520
+ });
2368
2521
  }
2369
- const assessment = {
2370
- status: parts.assessmentStatus,
2371
- note: parts.note ?? EVIDENCE_ASSESSMENT_NOTE
2372
- };
2373
- if (parts.sourceStatus !== void 0) {
2374
- assessment.sourceStatus = parts.sourceStatus;
2375
- }
2376
- return {
2377
- evidenceFormatVersion: EVIDENCE_FORMAT_VERSION,
2378
- generator: {
2379
- name: parts.generatorName ?? "agent-inspect",
2380
- version: parts.generatorVersion
2381
- },
2382
- createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2383
- source: {
2384
- runIds,
2385
- traceSchemaVersions: [...parts.traceSchemaVersions].sort((a, b) => a.localeCompare(b)),
2386
- sourceHashes: [...parts.sourceHashes].sort((a, b) => a.runId.localeCompare(b.runId))
2387
- },
2388
- policy: {
2389
- redactionProfile: parts.redactionProfile,
2390
- verificationPolicy: parts.verificationPolicy ?? parts.redactionProfile
2391
- },
2392
- assessment,
2393
- ...parts.semantics !== void 0 ? { semantics: { ...parts.semantics } } : {},
2394
- ...parts.contract !== void 0 ? { contract: { ...parts.contract } } : {},
2395
- files: buildEvidenceFileEntries(parts.files)
2396
- };
2397
- }
2398
-
2399
- // packages/core/src/diagnostics/programmatic.ts
2400
- var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
2401
- AI_TRACE_INPUT_INVALID: {
2402
- code: "AI_TRACE_INPUT_INVALID",
2403
- summary: 'Expected { type: "file", path }, { type: "directory", path }, { type: "string", content }, { type: "buffer", content }, or { type: "stdin" }.',
2404
- remediation: "For a file path, use openTraceFile(path).",
2405
- relatedCodes: ["invalid_input"]
2406
- },
2407
- AI_TRACE_FORMAT_UNSUPPORTED: {
2408
- code: "AI_TRACE_FORMAT_UNSUPPORTED",
2409
- summary: "No trace reader could detect the input format.",
2410
- remediation: "Pass an AgentInspect JSONL file via openTraceFile, or set options.format to a registered reader.",
2411
- relatedCodes: ["unsupported_format"]
2412
- },
2413
- AI_TRACE_FORMAT_AMBIGUOUS: {
2414
- code: "AI_TRACE_FORMAT_AMBIGUOUS",
2415
- summary: "Multiple trace readers matched the input with equal confidence.",
2416
- remediation: "Set options.format explicitly to disambiguate the reader.",
2417
- relatedCodes: ["ambiguous_format"]
2418
- },
2419
- AI_TRACE_FACTS_INPUT_NOT_NORMALIZED: {
2420
- code: "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED",
2421
- summary: "TraceFacts requires TraceReadResult or PersistedInspectEvent[].",
2422
- remediation: "Use openTraceFile() to normalize a JSONL trace first."
2423
- },
2424
- AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED: {
2425
- code: "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
2426
- summary: "Multiple runs are available; select a run before executing checks.",
2427
- remediation: "Pass options.runId or TraceCheckInput.selectedRun.",
2428
- relatedCodes: ["AI_CHECK_RUN_SELECTION_REQUIRED"]
2429
- },
2430
- AI_TRACE_RELATIONSHIP_SELF_PARENT: {
2431
- code: "AI_TRACE_RELATIONSHIP_SELF_PARENT",
2432
- summary: "A parentId equals its own event/step id.",
2433
- remediation: "Reject at capture (AI_LANGGRAPH_SELF_PARENT_REJECTED) or drop via logical projection; do not invent replacement parents.",
2434
- relatedCodes: [
2435
- "AI_LANGGRAPH_SELF_PARENT_REJECTED",
2436
- "AI_LOGICAL_SELF_PARENT_REMOVED"
2437
- ]
2438
- },
2439
- AI_TRACE_RELATIONSHIP_CYCLE: {
2440
- code: "AI_TRACE_RELATIONSHIP_CYCLE",
2441
- summary: "Trace contains a parentId cycle.",
2442
- remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
2443
- relatedCodes: ["structure.cycle"]
2444
- }
2445
- });
2446
- function formatProgrammaticDiagnostic(code, detail) {
2447
- const spec = PROGRAMMATIC_DIAGNOSTIC_SPECS[code];
2448
- const summary = detail?.trim() ? detail.trim() : spec.summary;
2449
- return `${code}: ${summary} Remediation: ${spec.remediation}`;
2450
- }
2451
-
2452
- // packages/core/src/checks/logical-events.ts
2453
- function isRecord6(value) {
2454
- return typeof value === "object" && value !== null && !Array.isArray(value);
2455
- }
2456
- function legacyEvent(event) {
2457
- const value = event.attributes?.legacyEvent;
2458
- return typeof value === "string" ? value : void 0;
2522
+ return out;
2459
2523
  }
2460
- function stepIdOf(event) {
2461
- const value = event.attributes?.stepId;
2462
- if (typeof value === "string" && value.trim() !== "") return value;
2463
- return void 0;
2524
+ async function loadTraceMetadataList(_traceDir, fileNames, getPath) {
2525
+ const metas = [];
2526
+ for (const fileName of fileNames) {
2527
+ try {
2528
+ const filePath = getPath(fileName);
2529
+ const meta = await extractMetadata(filePath);
2530
+ metas.push(meta);
2531
+ } catch {
2532
+ }
2533
+ }
2534
+ return metas;
2464
2535
  }
2465
- function cloneEvent(event) {
2466
- return {
2467
- ...event,
2468
- ...event.attributes !== void 0 ? { attributes: { ...event.attributes } } : {},
2469
- ...event.error !== void 0 ? { error: { ...event.error } } : {},
2470
- ...event.tokenUsage !== void 0 ? { tokenUsage: { ...event.tokenUsage } } : {},
2471
- ...event.source !== void 0 ? { source: { ...event.source } } : {}
2472
- };
2536
+
2537
+ // packages/core/src/sessions/metadata.ts
2538
+ function isNonEmptyString3(value) {
2539
+ return typeof value === "string" && value.trim() !== "";
2473
2540
  }
2474
- function mergeAttributes(start, complete) {
2475
- const merged = {
2476
- ...isRecord6(complete.attributes) ? complete.attributes : {},
2477
- ...isRecord6(start.attributes) ? start.attributes : {}
2478
- };
2479
- merged.legacyEvent = start.attributes?.legacyEvent ?? complete.attributes?.legacyEvent;
2480
- merged.legacyCompleteEvent = complete.attributes?.legacyEvent;
2481
- if (complete.attributes?.errorStack !== void 0) {
2482
- merged.errorStack = complete.attributes.errorStack;
2541
+ function finitePositiveInt(value) {
2542
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
2543
+ return void 0;
2483
2544
  }
2484
- return Object.keys(merged).length > 0 ? merged : void 0;
2545
+ return Math.trunc(value);
2485
2546
  }
2486
- function pairStartComplete(start, complete) {
2487
- const attributes = mergeAttributes(start, complete);
2488
- const paired = {
2489
- ...cloneEvent(start),
2490
- status: complete.status,
2491
- timestamp: complete.timestamp ?? start.timestamp,
2492
- ...complete.endedAt !== void 0 ? { endedAt: complete.endedAt } : {},
2493
- ...complete.durationMs !== void 0 ? { durationMs: complete.durationMs } : {},
2494
- ...complete.error !== void 0 ? { error: { ...complete.error } } : {},
2495
- ...complete.tokenUsage !== void 0 && start.tokenUsage === void 0 ? { tokenUsage: { ...complete.tokenUsage } } : {},
2496
- ...attributes !== void 0 ? { attributes } : {}
2497
- };
2498
- return {
2499
- ...paired,
2500
- sourceEventIds: Object.freeze([start.eventId, complete.eventId]),
2501
- projection: {
2502
- paired: true,
2503
- absorbedEventIds: Object.freeze([complete.eventId]),
2504
- parentNormalized: false,
2505
- ...start.parentId !== void 0 ? { originalParentId: start.parentId } : {}
2547
+ function extractSessionWorkflowMetadata(record) {
2548
+ if (!record) return void 0;
2549
+ const out = {};
2550
+ let found = false;
2551
+ const assignString = (key, value) => {
2552
+ if (isNonEmptyString3(value)) {
2553
+ out[key] = value.trim();
2554
+ found = true;
2506
2555
  }
2507
2556
  };
2557
+ assignString("sessionId", record.sessionId);
2558
+ assignString("conversationId", record.conversationId);
2559
+ assignString("groupId", record.groupId);
2560
+ assignString("parentGroupId", record.parentGroupId);
2561
+ assignString("retryOf", record.retryOf);
2562
+ assignString("retryReason", record.retryReason);
2563
+ assignString("handoffFrom", record.handoffFrom);
2564
+ assignString("handoffTo", record.handoffTo);
2565
+ assignString("subAgentId", record.subAgentId);
2566
+ assignString("subAgentName", record.subAgentName);
2567
+ assignString("jobId", record.jobId);
2568
+ assignString("queueName", record.queueName);
2569
+ assignString("workflowName", record.workflowName);
2570
+ assignString("workflowStep", record.workflowStep);
2571
+ assignString("toolCallId", record.toolCallId);
2572
+ assignString("mcpToolCallId", record.mcpToolCallId);
2573
+ assignString("linkedStepId", record.linkedStepId);
2574
+ assignString("operationId", record.operationId);
2575
+ assignString("attemptId", record.attemptId);
2576
+ assignString("fallbackOf", record.fallbackOf);
2577
+ assignString("idempotencyKey", record.idempotencyKey);
2578
+ assignString("correlationId", record.correlationId);
2579
+ assignString("requestId", record.requestId);
2580
+ assignString("decisionId", record.decisionId);
2581
+ const attempt = finitePositiveInt(record.attempt);
2582
+ if (attempt !== void 0) {
2583
+ out.attempt = attempt;
2584
+ found = true;
2585
+ }
2586
+ const attemptNumber = finitePositiveInt(record.attemptNumber);
2587
+ if (attemptNumber !== void 0) {
2588
+ out.attemptNumber = attemptNumber;
2589
+ found = true;
2590
+ }
2591
+ return found ? out : void 0;
2508
2592
  }
2509
- function asLogical(event, extras) {
2510
- return {
2511
- ...cloneEvent(event),
2512
- sourceEventIds: Object.freeze([event.eventId]),
2513
- projection: {
2514
- paired: false,
2515
- absorbedEventIds: Object.freeze([]),
2516
- parentNormalized: extras?.parentNormalized === true,
2517
- ...{}
2518
- }
2519
- };
2593
+
2594
+ // packages/core/src/bundle/safety-status.ts
2595
+ function aggregateBundleSafeStatus(statuses) {
2596
+ if (statuses.length === 0) return "UNKNOWN";
2597
+ if (statuses.some((status) => status === "UNSAFE")) return "UNSAFE";
2598
+ if (statuses.some((status) => status === "UNKNOWN")) return "UNKNOWN";
2599
+ if (statuses.some((status) => status === "SAFE WITH WARNINGS")) return "SAFE WITH WARNINGS";
2600
+ return "SAFE";
2520
2601
  }
2521
- function projectLogicalEvents(events) {
2522
- const diagnostics = [];
2523
- const byRun = /* @__PURE__ */ new Map();
2524
- for (const event of events) {
2525
- const list = byRun.get(event.runId) ?? [];
2526
- list.push(event);
2527
- byRun.set(event.runId, list);
2528
- }
2529
- const absorbedIds = /* @__PURE__ */ new Set();
2530
- const logicalByRawId = /* @__PURE__ */ new Map();
2531
- const stepIdToLogicalId = /* @__PURE__ */ new Map();
2532
- const logical = [];
2533
- const orderedRuns = [...byRun.keys()].sort((a, b) => a.localeCompare(b));
2534
- for (const runId of orderedRuns) {
2535
- const runEvents = byRun.get(runId) ?? [];
2536
- const starts = [];
2537
- const completes = [];
2538
- const others = [];
2539
- for (const event of runEvents) {
2540
- const legacy = legacyEvent(event);
2541
- if (legacy === "step_started" || legacy === "run_started" && event.status === "running") {
2542
- starts.push(event);
2543
- } else if (legacy === "step_completed" || legacy === "run_completed") {
2544
- completes.push(event);
2545
- } else {
2546
- others.push(event);
2547
- }
2548
- }
2549
- const usedCompletes = /* @__PURE__ */ new Set();
2550
- for (const start of starts) {
2551
- const stepId = stepIdOf(start);
2552
- let match;
2553
- if (legacyEvent(start) === "run_started") {
2554
- const candidates = completes.filter(
2555
- (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "run_completed"
2556
- );
2557
- if (candidates.length > 1) {
2558
- diagnostics.push({
2559
- code: "AI_LOGICAL_PAIR_AMBIGUOUS",
2560
- message: `Multiple run_completed rows for run ${runId}; using first by eventId.`,
2561
- eventIds: candidates.map((c) => c.eventId)
2562
- });
2563
- candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
2564
- }
2565
- match = candidates[0];
2566
- } else if (stepId) {
2567
- const candidates = completes.filter(
2568
- (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "step_completed" && stepIdOf(c) === stepId
2569
- );
2570
- if (candidates.length > 1) {
2571
- diagnostics.push({
2572
- code: "AI_LOGICAL_PAIR_AMBIGUOUS",
2573
- message: `Multiple step_completed rows for stepId ${stepId}; using first by eventId.`,
2574
- eventIds: candidates.map((c) => c.eventId)
2575
- });
2576
- candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
2577
- }
2578
- match = candidates[0];
2579
- }
2580
- if (match) {
2581
- usedCompletes.add(match.eventId);
2582
- absorbedIds.add(match.eventId);
2583
- const paired = pairStartComplete(start, match);
2584
- logical.push(paired);
2585
- logicalByRawId.set(start.eventId, paired);
2586
- logicalByRawId.set(match.eventId, paired);
2587
- if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, paired.eventId);
2588
- } else {
2589
- diagnostics.push({
2590
- code: "AI_LOGICAL_PAIR_UNMATCHED_START",
2591
- message: `No matching complete for start ${start.eventId}.`,
2592
- eventIds: [start.eventId]
2593
- });
2594
- const alone = asLogical(start);
2595
- logical.push(alone);
2596
- logicalByRawId.set(start.eventId, alone);
2597
- if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2598
- }
2599
- }
2600
- for (const complete of completes) {
2601
- if (usedCompletes.has(complete.eventId)) continue;
2602
- diagnostics.push({
2603
- code: "AI_LOGICAL_PAIR_UNMATCHED_COMPLETE",
2604
- message: `No matching start for complete ${complete.eventId}.`,
2605
- eventIds: [complete.eventId]
2606
- });
2607
- const alone = asLogical(complete);
2608
- logical.push(alone);
2609
- logicalByRawId.set(complete.eventId, alone);
2610
- const stepId = stepIdOf(complete);
2611
- if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
2612
- stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2613
- }
2614
- }
2615
- for (const event of others) {
2616
- const alone = asLogical(event);
2617
- logical.push(alone);
2618
- logicalByRawId.set(event.eventId, alone);
2619
- const stepId = stepIdOf(event);
2620
- if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
2621
- stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
2622
- }
2623
- }
2602
+ function toMetadataSafeStatus(status) {
2603
+ if (status === "SAFE WITH WARNINGS") return "SAFE_WITH_WARNINGS";
2604
+ return status;
2605
+ }
2606
+ function bundleFailsOnSafety(status, allowUnsafe) {
2607
+ return status === "UNSAFE" || status === "UNKNOWN";
2608
+ }
2609
+
2610
+ // packages/core/src/bundle/manifest.ts
2611
+ var BUNDLE_NOTE = "Generated locally by AgentInspect. Bundles are derived copies for review \u2014 not compliance or security certification. Review before sharing.";
2612
+ function buildBundleMetadata(parts) {
2613
+ const aggregate = aggregateBundleSafeStatus(
2614
+ parts.checks.runs.map((run) => run.status)
2615
+ );
2616
+ return {
2617
+ createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2618
+ agentInspectVersion: parts.agentInspectVersion,
2619
+ redactionProfile: parts.profile,
2620
+ sourceTraceCount: parts.resolve.runIds.length,
2621
+ runIds: [...parts.resolve.runIds],
2622
+ safeStatus: toMetadataSafeStatus(aggregate),
2623
+ files: [...parts.files].sort((a, b) => a.localeCompare(b)),
2624
+ note: BUNDLE_NOTE,
2625
+ ...parts.resolve.sessionId !== void 0 ? { sessionId: parts.resolve.sessionId } : {},
2626
+ ...parts.resolve.since !== void 0 ? { since: parts.resolve.since } : {}
2627
+ };
2628
+ }
2629
+
2630
+ // packages/core/src/evidence/types.ts
2631
+ var EVIDENCE_FORMAT_VERSION = "1.0";
2632
+ var EVIDENCE_ASSESSMENT_NOTE = "Best-effort local safety verification only; not a compliance certification.";
2633
+ var EVIDENCE_MANIFEST_FILENAME = "evidence.json";
2634
+ function sha256Hex(data) {
2635
+ const hash = createHash("sha256");
2636
+ if (typeof data === "string") {
2637
+ hash.update(data, "utf8");
2638
+ } else {
2639
+ hash.update(data);
2624
2640
  }
2625
- const logicalById = new Map(logical.map((e) => [e.eventId, e]));
2626
- const normalized = [];
2627
- for (const event of logical) {
2628
- const originalParentId = event.parentId;
2629
- if (!originalParentId) {
2630
- normalized.push(event);
2631
- continue;
2632
- }
2633
- let nextParent = originalParentId;
2634
- let remapped = false;
2635
- const viaAbsorbed = logicalByRawId.get(originalParentId);
2636
- if (viaAbsorbed && viaAbsorbed.eventId !== originalParentId) {
2637
- nextParent = viaAbsorbed.eventId;
2638
- remapped = true;
2639
- } else if (!logicalById.has(originalParentId)) {
2640
- const viaStep = stepIdToLogicalId.get(`${event.runId}:${originalParentId}`);
2641
- if (viaStep) {
2642
- nextParent = viaStep;
2643
- remapped = true;
2644
- }
2641
+ return hash.digest("hex");
2642
+ }
2643
+ function assertEvidenceRelativePath(relativePath) {
2644
+ if (typeof relativePath !== "string" || relativePath.trim() === "") {
2645
+ throw new Error("Evidence file path must be a non-empty relative path.");
2646
+ }
2647
+ const trimmed = relativePath.trim().replaceAll("\\", "/");
2648
+ if (path14.isAbsolute(trimmed) || trimmed.startsWith("/")) {
2649
+ throw new Error(`Evidence file path must be relative: ${relativePath}`);
2650
+ }
2651
+ const parts = trimmed.split("/").filter((part) => part !== "");
2652
+ if (parts.length === 0) {
2653
+ throw new Error(`Evidence file path must be relative: ${relativePath}`);
2654
+ }
2655
+ for (const part of parts) {
2656
+ if (part === "." || part === "..") {
2657
+ throw new Error(`Evidence file path must not contain "." or "..": ${relativePath}`);
2645
2658
  }
2646
- if (!remapped) {
2647
- if (originalParentId === event.eventId) {
2648
- diagnostics.push({
2649
- code: "AI_LOGICAL_SELF_PARENT_REMOVED",
2650
- message: formatProgrammaticDiagnostic(
2651
- "AI_TRACE_RELATIONSHIP_SELF_PARENT",
2652
- `Removed self-parent edge on ${event.eventId}.`
2653
- ),
2654
- eventIds: [event.eventId]
2655
- });
2656
- const { parentId: _drop, ...rest } = event;
2657
- normalized.push({
2658
- ...rest,
2659
- projection: {
2660
- ...event.projection,
2661
- parentNormalized: true,
2662
- originalParentId
2663
- }
2664
- });
2665
- continue;
2666
- }
2667
- if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
2668
- const mapping = event.attributes?.parentMapping;
2669
- const unresolved = mapping === "unresolved" || event.attributes?.parentUnresolved === true || event.attributes?.unresolvedParent === true || // LangGraph/framework scaffolding sentinel labels are not event ids.
2670
- /^LangGraph$/i.test(originalParentId) || originalParentId.startsWith("unresolved:");
2671
- if (!unresolved) {
2672
- diagnostics.push({
2673
- code: "AI_LOGICAL_PARENT_UNRESOLVED",
2674
- message: `Parent ${originalParentId} unresolved for ${event.eventId}.`,
2675
- eventIds: [event.eventId]
2676
- });
2677
- }
2678
- }
2679
- normalized.push(event);
2680
- continue;
2659
+ }
2660
+ return parts.join("/");
2661
+ }
2662
+
2663
+ // packages/core/src/evidence/manifest.ts
2664
+ function stable(value) {
2665
+ if (Array.isArray(value)) return value.map(stable);
2666
+ if (value === null || typeof value !== "object") return value;
2667
+ const record = value;
2668
+ return Object.fromEntries(
2669
+ Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable(record[key])])
2670
+ );
2671
+ }
2672
+ function serializeEvidenceManifest(manifest) {
2673
+ return `${JSON.stringify(stable(manifest), null, 2)}
2674
+ `;
2675
+ }
2676
+ function inferEvidenceFileRole(relativePath) {
2677
+ const normalized = assertEvidenceRelativePath(relativePath);
2678
+ const base = normalized.includes("/") ? normalized.slice(normalized.lastIndexOf("/") + 1) : normalized;
2679
+ if (base === "evidence.html" || base === "trace.html" || base.endsWith(".html")) {
2680
+ return "report";
2681
+ }
2682
+ if (base === "trace.jsonl" || base.endsWith(".jsonl")) {
2683
+ return "redacted-trace";
2684
+ }
2685
+ if (base === "check-results.json") {
2686
+ return "checks";
2687
+ }
2688
+ if (base === "contract.resolved.json") {
2689
+ return "contract";
2690
+ }
2691
+ if (base === "redaction-report.json") {
2692
+ return "redaction-report";
2693
+ }
2694
+ if (base === "summary.md") {
2695
+ return "summary";
2696
+ }
2697
+ return "other";
2698
+ }
2699
+ function buildEvidenceFileEntries(files) {
2700
+ const byPath = /* @__PURE__ */ new Map();
2701
+ for (const file of files) {
2702
+ const relativePath = assertEvidenceRelativePath(file.path);
2703
+ if (relativePath === EVIDENCE_MANIFEST_FILENAME) {
2704
+ throw new Error(
2705
+ `Do not include ${EVIDENCE_MANIFEST_FILENAME} in packaged file hashes (self-hash is undefined).`
2706
+ );
2681
2707
  }
2682
- if (nextParent === event.eventId) {
2683
- diagnostics.push({
2684
- code: "AI_LOGICAL_SELF_PARENT_REMOVED",
2685
- message: formatProgrammaticDiagnostic(
2686
- "AI_TRACE_RELATIONSHIP_SELF_PARENT",
2687
- `Removed self-parent edge on ${event.eventId} (was ${originalParentId}).`
2688
- ),
2689
- eventIds: [event.eventId]
2690
- });
2691
- const { parentId: _drop, ...rest } = event;
2692
- normalized.push({
2693
- ...rest,
2694
- projection: {
2695
- ...event.projection,
2696
- parentNormalized: true,
2697
- originalParentId
2698
- }
2699
- });
2700
- continue;
2708
+ if (byPath.has(relativePath)) {
2709
+ throw new Error(`Duplicate evidence file path: ${relativePath}`);
2701
2710
  }
2702
- diagnostics.push({
2703
- code: "AI_LOGICAL_PARENT_REMAPPED",
2704
- message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
2705
- eventIds: [event.eventId]
2706
- });
2707
- normalized.push({
2708
- ...event,
2709
- parentId: nextParent,
2710
- projection: {
2711
- ...event.projection,
2712
- parentNormalized: true,
2713
- originalParentId
2714
- }
2711
+ byPath.set(relativePath, {
2712
+ path: relativePath,
2713
+ sha256: sha256Hex(file.content),
2714
+ role: file.role ?? inferEvidenceFileRole(relativePath)
2715
2715
  });
2716
2716
  }
2717
- const rawIndex = new Map(events.map((e, i) => [e.eventId, i]));
2718
- normalized.sort((a, b) => {
2719
- const ai = rawIndex.get(a.sourceEventIds[0]) ?? 0;
2720
- const bi = rawIndex.get(b.sourceEventIds[0]) ?? 0;
2721
- return ai - bi || a.eventId.localeCompare(b.eventId);
2722
- });
2723
- return {
2724
- logicalEvents: Object.freeze(normalized),
2725
- diagnostics: Object.freeze(diagnostics)
2726
- };
2717
+ return [...byPath.values()].sort((a, b) => a.path.localeCompare(b.path));
2727
2718
  }
2728
- function resolveCanonicalToolName(event) {
2729
- const attrs2 = event.attributes;
2730
- const direct = pickString(attrs2, ["toolName", "tool"]);
2731
- if (direct) return direct;
2732
- const metadata = attrs2?.metadata;
2733
- if (isRecord6(metadata)) {
2734
- const nested = pickString(metadata, ["toolName", "tool"]);
2735
- if (nested) return nested;
2719
+ function buildEvidenceManifest(parts) {
2720
+ const runIds = [...parts.runIds];
2721
+ if (runIds.length === 0) {
2722
+ throw new Error("Evidence manifest requires at least one run id.");
2736
2723
  }
2737
- for (const prefix of ["tool:", "function:", "mcp-tools:"]) {
2738
- if (event.name.startsWith(prefix)) return event.name.slice(prefix.length);
2724
+ for (const item of parts.sourceHashes) {
2725
+ if (!runIds.includes(item.runId)) {
2726
+ throw new Error(`sourceHashes runId "${item.runId}" is not listed in source.runIds.`);
2727
+ }
2728
+ if (item.algorithm !== "sha256") {
2729
+ throw new Error(`Unsupported source hash algorithm: ${item.algorithm}`);
2730
+ }
2739
2731
  }
2740
- return event.name;
2741
- }
2742
- function pickString(record, keys) {
2743
- if (!record) return void 0;
2744
- for (const key of keys) {
2745
- const value = record[key];
2746
- if (typeof value === "string" && value.trim() !== "") return value.trim();
2732
+ const assessment = {
2733
+ status: parts.assessmentStatus,
2734
+ note: parts.note ?? EVIDENCE_ASSESSMENT_NOTE
2735
+ };
2736
+ if (parts.sourceStatus !== void 0) {
2737
+ assessment.sourceStatus = parts.sourceStatus;
2747
2738
  }
2748
- return void 0;
2739
+ return {
2740
+ evidenceFormatVersion: EVIDENCE_FORMAT_VERSION,
2741
+ generator: {
2742
+ name: parts.generatorName ?? "agent-inspect",
2743
+ version: parts.generatorVersion
2744
+ },
2745
+ createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2746
+ source: {
2747
+ runIds,
2748
+ traceSchemaVersions: [...parts.traceSchemaVersions].sort((a, b) => a.localeCompare(b)),
2749
+ sourceHashes: [...parts.sourceHashes].sort((a, b) => a.runId.localeCompare(b.runId))
2750
+ },
2751
+ policy: {
2752
+ redactionProfile: parts.redactionProfile,
2753
+ verificationPolicy: parts.verificationPolicy ?? parts.redactionProfile
2754
+ },
2755
+ assessment,
2756
+ ...parts.semantics !== void 0 ? { semantics: { ...parts.semantics } } : {},
2757
+ ...parts.contract !== void 0 ? { contract: { ...parts.contract } } : {},
2758
+ ...parts.inputs !== void 0 ? { inputs: { ...parts.inputs } } : {},
2759
+ files: buildEvidenceFileEntries(parts.files)
2760
+ };
2749
2761
  }
2750
2762
 
2751
2763
  // packages/core/src/checks/derived-failure.ts
@@ -3419,7 +3431,11 @@ function emptySummary() {
3419
3431
  failed: 0,
3420
3432
  warnings: 0,
3421
3433
  errors: 0,
3422
- rulesEvaluated: 0
3434
+ rulesEvaluated: 0,
3435
+ rulesPassed: 0,
3436
+ rulesWarning: 0,
3437
+ rulesFailed: 0,
3438
+ rulesError: 0
3423
3439
  };
3424
3440
  }
3425
3441
  function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
@@ -3431,7 +3447,11 @@ function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
3431
3447
  summary: {
3432
3448
  ...emptySummary(),
3433
3449
  errors: diagnostics.filter((item) => item.severity === "error").length,
3434
- rulesEvaluated: ruleExecutions.length
3450
+ rulesEvaluated: ruleExecutions.length,
3451
+ rulesPassed: ruleExecutions.filter((item) => item.status === "pass").length,
3452
+ rulesWarning: ruleExecutions.filter((item) => item.status === "warning").length,
3453
+ rulesFailed: ruleExecutions.filter((item) => item.status === "fail").length,
3454
+ rulesError: ruleExecutions.filter((item) => item.status === "error").length
3435
3455
  },
3436
3456
  findings: [],
3437
3457
  diagnostics: [...diagnostics],
@@ -3591,7 +3611,7 @@ function normalizeFinding(rule, finding) {
3591
3611
  ...finding.action !== void 0 ? { action: finding.action } : {}
3592
3612
  };
3593
3613
  }
3594
- function summarize(findings, diagnostics, rulesEvaluated) {
3614
+ function summarize(findings, diagnostics, ruleExecutions) {
3595
3615
  return {
3596
3616
  passed: findings.filter((finding) => finding.status === "pass").length,
3597
3617
  failed: findings.filter(
@@ -3601,7 +3621,11 @@ function summarize(findings, diagnostics, rulesEvaluated) {
3601
3621
  (finding) => finding.status === "warning" || finding.severity === "warning"
3602
3622
  ).length,
3603
3623
  errors: diagnostics.filter((item) => item.severity === "error").length,
3604
- rulesEvaluated
3624
+ rulesEvaluated: ruleExecutions.length,
3625
+ rulesPassed: ruleExecutions.filter((item) => item.status === "pass").length,
3626
+ rulesWarning: ruleExecutions.filter((item) => item.status === "warning").length,
3627
+ rulesFailed: ruleExecutions.filter((item) => item.status === "fail").length,
3628
+ rulesError: ruleExecutions.filter((item) => item.status === "error").length
3605
3629
  };
3606
3630
  }
3607
3631
  function classifyRuleExecution(findings, threw) {
@@ -4042,7 +4066,7 @@ function runTraceChecks(input, options = {}) {
4042
4066
  }
4043
4067
  const eventById = new Map(input.read.events.map((event) => [event.eventId, event]));
4044
4068
  const sortedFindings = findings.sort(compareFindings(eventById));
4045
- const summary = summarize(sortedFindings, diagnostics, ruleExecutions.length);
4069
+ const summary = summarize(sortedFindings, diagnostics, ruleExecutions);
4046
4070
  const status = summary.failed > 0 ? "fail" : "pass";
4047
4071
  return {
4048
4072
  ok: status === "pass",
@@ -8185,6 +8209,15 @@ function actionForRule(rule) {
8185
8209
  if (rule.strategy === "full") return "replace";
8186
8210
  return rule.strategy;
8187
8211
  }
8212
+ function isCompleteRedactionMarker(value, replacement = "[REDACTED]") {
8213
+ if (typeof value !== "string") return false;
8214
+ const trimmed = value.trim();
8215
+ if (trimmed.length === 0) return false;
8216
+ if (trimmed === replacement) return true;
8217
+ if (/^\[HASH:[A-Za-z0-9_-]+\]$/.test(trimmed)) return true;
8218
+ if (/^\[REDACTED:[^\]]*\]$/.test(trimmed)) return true;
8219
+ return false;
8220
+ }
8188
8221
  function applyRule(rule, value, replacement) {
8189
8222
  if (rule.strategy === "full") return replacement;
8190
8223
  const asString = stringifyScalar(value);
@@ -8299,6 +8332,9 @@ var Redactor2 = class {
8299
8332
  if (key !== void 0) {
8300
8333
  const rule = findCompiledKeyRule(key, this.#rules);
8301
8334
  if (rule) {
8335
+ if (isCompleteRedactionMarker(value, this.#replacement)) {
8336
+ return value;
8337
+ }
8302
8338
  this.#recordFinding(
8303
8339
  state,
8304
8340
  makeFinding(path16, `key.${rule.key}`, actionForRule(rule), "key", "warning")
@@ -9275,5 +9311,5 @@ async function runReadOnlyMcpServer(options = {}) {
9275
9311
  }
9276
9312
 
9277
9313
  export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, MCP_SERVER_INSTRUCTIONS, READ_ONLY_TOOLS, TRACE_DATA_UNTRUSTED_WARNING, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
9278
- //# sourceMappingURL=chunk-U3JBHSNB.mjs.map
9279
- //# sourceMappingURL=chunk-U3JBHSNB.mjs.map
9314
+ //# sourceMappingURL=chunk-FWSGOK3F.mjs.map
9315
+ //# sourceMappingURL=chunk-FWSGOK3F.mjs.map