agent-inspect 4.1.0 → 4.2.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.
- package/CHANGELOG.md +12 -0
- package/docs/CLI.md +17 -6
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-MT5G7JFO.mjs → chunk-5VSPJEZ7.mjs} +264 -11
- package/packages/cli/dist/chunk-5VSPJEZ7.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +700 -188
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +392 -151
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-DUGEOAZ7.mjs → src-VQT7QLGV.mjs} +3 -3
- package/packages/cli/dist/{src-DUGEOAZ7.mjs.map → src-VQT7QLGV.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +265 -8
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +79 -1
- package/packages/core/dist/advanced.d.ts +79 -1
- package/packages/core/dist/advanced.mjs +262 -9
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/cli/dist/chunk-MT5G7JFO.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolveTraceDir, TraceDirectory,
|
|
2
|
+
import { resolveTraceDir, parseDuration, buildSessionIndex, enrichSessionRunRecord, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, extractMetadata, filterTraces, truncateName, getTraceFilePath, buildRunSummary, formatDuration, formatTimestamp, isAgentInspectTrace, filterMetasBySessionScope, aggregateSessionCheckResults, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, persistedInspectEventsToTraceEvents, renderStepLine, renderErrorLine, getIndent, Redactor, validateEvent, isPersistedInspectEvent, nanoid, resolveRedactionProfile, applyProfileMetadataCaps, extractCorrelationMetadata, truncateStringForProfile, parseTraceJsonl } from './chunk-5VSPJEZ7.mjs';
|
|
3
3
|
import { realpathSync, constants as constants$1 } from 'fs';
|
|
4
|
-
import
|
|
4
|
+
import path11 from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
6
|
import { Command, Option } from 'commander';
|
|
7
7
|
import { unlink, stat, mkdir, writeFile, appendFile, rm, access, readFile, open, readdir, constants } from 'fs/promises';
|
|
@@ -11,7 +11,7 @@ import { createServer } from 'http';
|
|
|
11
11
|
import { createRequire } from 'module';
|
|
12
12
|
|
|
13
13
|
// package.json
|
|
14
|
-
var version = "4.
|
|
14
|
+
var version = "4.2.0";
|
|
15
15
|
|
|
16
16
|
// packages/cli/src/trace-dir-scale.ts
|
|
17
17
|
var TRACE_COUNT_WARN = 1e3;
|
|
@@ -895,7 +895,7 @@ function findReaderByFormat(format, readers) {
|
|
|
895
895
|
}
|
|
896
896
|
async function jsonlFilesInDirectory(dirPath) {
|
|
897
897
|
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
898
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) =>
|
|
898
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path11.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
|
|
899
899
|
}
|
|
900
900
|
async function resolveInput(input3) {
|
|
901
901
|
const cached = resolvedInputCache.get(input3);
|
|
@@ -5024,9 +5024,9 @@ Trace directory: ${traceDir}`);
|
|
|
5024
5024
|
if (validation !== void 0 && !validation.ok) {
|
|
5025
5025
|
process.exitCode = 1;
|
|
5026
5026
|
}
|
|
5027
|
-
const outPath = options.output !== void 0 && options.output.trim() !== "" ?
|
|
5027
|
+
const outPath = options.output !== void 0 && options.output.trim() !== "" ? path11.resolve(options.output.trim()) : void 0;
|
|
5028
5028
|
if (outPath !== void 0) {
|
|
5029
|
-
await mkdir(
|
|
5029
|
+
await mkdir(path11.dirname(outPath), { recursive: true });
|
|
5030
5030
|
await writeFile(outPath, result.content, "utf-8");
|
|
5031
5031
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
5032
5032
|
console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
|
|
@@ -5203,13 +5203,13 @@ function pairSteps(left, right) {
|
|
|
5203
5203
|
return pairs;
|
|
5204
5204
|
}
|
|
5205
5205
|
function compareLeafSteps(L, R, segments, opts, out) {
|
|
5206
|
-
const
|
|
5206
|
+
const path18 = buildPath(segments);
|
|
5207
5207
|
if (L.name !== R.name) {
|
|
5208
5208
|
out.push({
|
|
5209
5209
|
kind: "structure",
|
|
5210
5210
|
severity: "warning",
|
|
5211
5211
|
message: "Step name differs",
|
|
5212
|
-
path:
|
|
5212
|
+
path: path18,
|
|
5213
5213
|
left: L.name,
|
|
5214
5214
|
right: R.name
|
|
5215
5215
|
});
|
|
@@ -5219,7 +5219,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5219
5219
|
kind: "step-type",
|
|
5220
5220
|
severity: "warning",
|
|
5221
5221
|
message: "Step type differs",
|
|
5222
|
-
path:
|
|
5222
|
+
path: path18,
|
|
5223
5223
|
left: L.type,
|
|
5224
5224
|
right: R.type
|
|
5225
5225
|
});
|
|
@@ -5229,7 +5229,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5229
5229
|
kind: "step-status",
|
|
5230
5230
|
severity: "warning",
|
|
5231
5231
|
message: "Step status differs",
|
|
5232
|
-
path:
|
|
5232
|
+
path: path18,
|
|
5233
5233
|
left: L.status,
|
|
5234
5234
|
right: R.status
|
|
5235
5235
|
});
|
|
@@ -5241,7 +5241,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5241
5241
|
kind: "error",
|
|
5242
5242
|
severity: "error",
|
|
5243
5243
|
message: "Step error message differs",
|
|
5244
|
-
path:
|
|
5244
|
+
path: path18,
|
|
5245
5245
|
left: le || void 0,
|
|
5246
5246
|
right: re || void 0
|
|
5247
5247
|
});
|
|
@@ -5259,7 +5259,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5259
5259
|
kind: "duration",
|
|
5260
5260
|
severity: "info",
|
|
5261
5261
|
message: "Step duration differs",
|
|
5262
|
-
path:
|
|
5262
|
+
path: path18,
|
|
5263
5263
|
left: ld,
|
|
5264
5264
|
right: rd
|
|
5265
5265
|
});
|
|
@@ -5272,7 +5272,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5272
5272
|
kind: "metadata",
|
|
5273
5273
|
severity: "info",
|
|
5274
5274
|
message: "Step metadata differs",
|
|
5275
|
-
path:
|
|
5275
|
+
path: path18,
|
|
5276
5276
|
left: L.metadata,
|
|
5277
5277
|
right: R.metadata
|
|
5278
5278
|
});
|
|
@@ -5284,7 +5284,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5284
5284
|
kind: "output",
|
|
5285
5285
|
severity: "info",
|
|
5286
5286
|
message: "Output preview differs",
|
|
5287
|
-
path:
|
|
5287
|
+
path: path18,
|
|
5288
5288
|
left: L.outputPreview,
|
|
5289
5289
|
right: R.outputPreview
|
|
5290
5290
|
});
|
|
@@ -5444,11 +5444,11 @@ function diffRuns(left, right, options) {
|
|
|
5444
5444
|
}
|
|
5445
5445
|
|
|
5446
5446
|
// packages/core/src/diff/renderer.ts
|
|
5447
|
-
function formatPath(
|
|
5448
|
-
if (
|
|
5447
|
+
function formatPath(path18) {
|
|
5448
|
+
if (path18 === void 0 || path18.path.length === 0) {
|
|
5449
5449
|
return "(run)";
|
|
5450
5450
|
}
|
|
5451
|
-
return
|
|
5451
|
+
return path18.path.map((s) => s.name).join(" > ");
|
|
5452
5452
|
}
|
|
5453
5453
|
function formatValue(v, verbose) {
|
|
5454
5454
|
if (v === void 0) return "(undefined)";
|
|
@@ -5810,9 +5810,28 @@ async function searchCommand(options = {}) {
|
|
|
5810
5810
|
process.exitCode = 1;
|
|
5811
5811
|
}
|
|
5812
5812
|
}
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5813
|
+
function isModuleNotFound2(e) {
|
|
5814
|
+
return e !== null && typeof e === "object" && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "MODULE_NOT_FOUND");
|
|
5815
|
+
}
|
|
5816
|
+
function toStatus(raw) {
|
|
5817
|
+
if (raw === "success" || raw === "error" || raw === "running") return raw;
|
|
5818
|
+
return "unknown";
|
|
5819
|
+
}
|
|
5820
|
+
function indexedToMetadata(row, traceDir) {
|
|
5821
|
+
return {
|
|
5822
|
+
runId: row.runId,
|
|
5823
|
+
name: row.name ?? void 0,
|
|
5824
|
+
status: toStatus(row.status),
|
|
5825
|
+
startedAt: row.startedAt ?? void 0,
|
|
5826
|
+
endedAt: row.endedAt ?? void 0,
|
|
5827
|
+
durationMs: row.durationMs ?? void 0,
|
|
5828
|
+
eventCount: 0,
|
|
5829
|
+
filePath: path11.join(traceDir, row.file),
|
|
5830
|
+
fileSize: 0,
|
|
5831
|
+
createdAt: new Date(row.mtimeMs)
|
|
5832
|
+
};
|
|
5833
|
+
}
|
|
5834
|
+
async function loadFromScan(traceDir) {
|
|
5816
5835
|
const td = new TraceDirectory({ dir: traceDir });
|
|
5817
5836
|
const files = await td.list();
|
|
5818
5837
|
const metas = await loadTraceMetadataList(
|
|
@@ -5820,12 +5839,77 @@ async function loadSessionIndex(traceDir, correlateGroup) {
|
|
|
5820
5839
|
files,
|
|
5821
5840
|
(fileName) => td.getPath(fileName)
|
|
5822
5841
|
);
|
|
5823
|
-
|
|
5824
|
-
|
|
5842
|
+
return loadSessionRunRecords(metas);
|
|
5843
|
+
}
|
|
5844
|
+
async function newestTraceMtimeMs(traceDir) {
|
|
5845
|
+
const td = new TraceDirectory({ dir: traceDir });
|
|
5846
|
+
let newest = 0;
|
|
5847
|
+
for (const file of await td.list()) {
|
|
5848
|
+
try {
|
|
5849
|
+
const stats = await td.getFileStats(file);
|
|
5850
|
+
if (stats.mtimeMs > newest) newest = stats.mtimeMs;
|
|
5851
|
+
} catch {
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
return newest;
|
|
5855
|
+
}
|
|
5856
|
+
async function loadSessionRuns(traceDir) {
|
|
5857
|
+
try {
|
|
5858
|
+
const mod = await import('./src-VQT7QLGV.mjs');
|
|
5859
|
+
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
5860
|
+
const status = mod.indexStatus(dbPath);
|
|
5861
|
+
if (!status.healthy) {
|
|
5862
|
+
return { runs: await loadFromScan(traceDir), source: "scan" };
|
|
5863
|
+
}
|
|
5864
|
+
const newest = await newestTraceMtimeMs(traceDir);
|
|
5865
|
+
if (mod.isIndexStale(dbPath, newest)) {
|
|
5866
|
+
return { runs: await loadFromScan(traceDir), source: "scan" };
|
|
5867
|
+
}
|
|
5868
|
+
const indexed = mod.queryRuns(dbPath, { limit: 1e4 });
|
|
5869
|
+
if (indexed.length === 0) {
|
|
5870
|
+
return { runs: await loadFromScan(traceDir), source: "scan" };
|
|
5871
|
+
}
|
|
5872
|
+
const runs = [];
|
|
5873
|
+
for (const row of indexed) {
|
|
5874
|
+
runs.push(await enrichSessionRunRecord(indexedToMetadata(row, traceDir)));
|
|
5875
|
+
}
|
|
5876
|
+
runs.sort((a, b) => (a.startedAt ?? 0) - (b.startedAt ?? 0));
|
|
5877
|
+
return { runs, source: "index" };
|
|
5878
|
+
} catch (e) {
|
|
5879
|
+
if (!isModuleNotFound2(e)) ;
|
|
5880
|
+
return { runs: await loadFromScan(traceDir), source: "scan" };
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5883
|
+
|
|
5884
|
+
// packages/cli/src/sessions.ts
|
|
5885
|
+
async function loadSessionIndex(traceDir, options = {}) {
|
|
5886
|
+
const { runs } = await loadSessionRuns(traceDir);
|
|
5887
|
+
const staleThresholdMs = options.staleAfter && options.staleAfter.trim() !== "" ? parseDuration(options.staleAfter.trim()) : void 0;
|
|
5888
|
+
return buildSessionIndex(runs, {
|
|
5889
|
+
correlateByGroupId: options.correlateGroup === true,
|
|
5890
|
+
staleThresholdMs
|
|
5891
|
+
});
|
|
5825
5892
|
}
|
|
5826
5893
|
function findSession(index, sessionId) {
|
|
5827
5894
|
return index.sessions.find((session) => session.sessionId === sessionId);
|
|
5828
5895
|
}
|
|
5896
|
+
function latestSession(index) {
|
|
5897
|
+
if (index.sessions.length === 0) return void 0;
|
|
5898
|
+
return [...index.sessions].sort(
|
|
5899
|
+
(a, b) => Date.parse(b.lastActivity) - Date.parse(a.lastActivity)
|
|
5900
|
+
)[0];
|
|
5901
|
+
}
|
|
5902
|
+
function parseSinceCutoff(since) {
|
|
5903
|
+
if (!since || since.trim() === "") return void 0;
|
|
5904
|
+
return Date.now() - parseDuration(since.trim());
|
|
5905
|
+
}
|
|
5906
|
+
function sessionsInSinceWindow(index, since) {
|
|
5907
|
+
const cutoff = parseSinceCutoff(since);
|
|
5908
|
+
if (cutoff === void 0) return index.sessions;
|
|
5909
|
+
return index.sessions.filter(
|
|
5910
|
+
(session) => Date.parse(session.lastActivity) >= cutoff
|
|
5911
|
+
);
|
|
5912
|
+
}
|
|
5829
5913
|
function renderSessionsHuman(index, traceDir) {
|
|
5830
5914
|
if (index.sessions.length === 0) {
|
|
5831
5915
|
console.log("No sessions found");
|
|
@@ -5839,13 +5923,9 @@ function renderSessionsHuman(index, traceDir) {
|
|
|
5839
5923
|
}
|
|
5840
5924
|
console.log("Sessions:");
|
|
5841
5925
|
for (const session of index.sessions) {
|
|
5842
|
-
const
|
|
5843
|
-
(run) => session.runIds.includes(run.runId)
|
|
5844
|
-
);
|
|
5845
|
-
const workflowName = firstRun?.metadata && typeof firstRun.metadata.workflowName === "string" ? firstRun.metadata.workflowName : void 0;
|
|
5846
|
-
const suffix = workflowName ? ` workflow=${workflowName}` : "";
|
|
5926
|
+
const suffix = session.workflowId ? ` workflow=${session.workflowId}` : "";
|
|
5847
5927
|
console.log(
|
|
5848
|
-
` ${session.sessionId} (${session.runIds.length} run${session.runIds.length === 1 ? "" : "s"})${suffix}`
|
|
5928
|
+
` ${session.sessionId} [${session.status}] (${session.runIds.length} run${session.runIds.length === 1 ? "" : "s"})${suffix}`
|
|
5849
5929
|
);
|
|
5850
5930
|
}
|
|
5851
5931
|
if (index.unscopedRunIds.length > 0) {
|
|
@@ -5857,7 +5937,14 @@ function renderSessionsHuman(index, traceDir) {
|
|
|
5857
5937
|
}
|
|
5858
5938
|
function renderSessionHuman(session, index, options) {
|
|
5859
5939
|
console.log(`Session: ${session.sessionId}`);
|
|
5940
|
+
console.log(`Status: ${session.status}`);
|
|
5860
5941
|
console.log(`Runs: ${session.runIds.join(", ")}`);
|
|
5942
|
+
if (session.lastActivity) console.log(`Last activity: ${session.lastActivity}`);
|
|
5943
|
+
if (session.lastError) {
|
|
5944
|
+
console.log(
|
|
5945
|
+
`Last error: ${session.lastError.message} (run ${session.lastError.runId})`
|
|
5946
|
+
);
|
|
5947
|
+
}
|
|
5861
5948
|
if (session.handoffs.length > 0) {
|
|
5862
5949
|
console.log("");
|
|
5863
5950
|
console.log("Handoffs:");
|
|
@@ -5902,10 +5989,29 @@ function renderSessionHuman(session, index, options) {
|
|
|
5902
5989
|
}
|
|
5903
5990
|
}
|
|
5904
5991
|
}
|
|
5992
|
+
function collectHandoffs(index, sessionId) {
|
|
5993
|
+
const sessions = sessionId ? index.sessions.filter((s) => s.sessionId === sessionId) : index.sessions;
|
|
5994
|
+
const out = [];
|
|
5995
|
+
for (const session of sessions) {
|
|
5996
|
+
for (const edge of session.handoffs) {
|
|
5997
|
+
out.push({ ...edge, sessionId: session.sessionId });
|
|
5998
|
+
}
|
|
5999
|
+
}
|
|
6000
|
+
return out.sort((a, b) => {
|
|
6001
|
+
const session = a.sessionId.localeCompare(b.sessionId);
|
|
6002
|
+
if (session !== 0) return session;
|
|
6003
|
+
const from = a.from.localeCompare(b.from);
|
|
6004
|
+
if (from !== 0) return from;
|
|
6005
|
+
return a.to.localeCompare(b.to);
|
|
6006
|
+
});
|
|
6007
|
+
}
|
|
5905
6008
|
async function sessionsCommand(options = {}) {
|
|
5906
6009
|
try {
|
|
5907
6010
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
5908
|
-
const index = await loadSessionIndex(traceDir,
|
|
6011
|
+
const index = await loadSessionIndex(traceDir, {
|
|
6012
|
+
correlateGroup: options.correlateGroup,
|
|
6013
|
+
staleAfter: options.staleAfter
|
|
6014
|
+
});
|
|
5909
6015
|
if (options.json) {
|
|
5910
6016
|
console.log(
|
|
5911
6017
|
JSON.stringify(
|
|
@@ -5928,6 +6034,121 @@ async function sessionsCommand(options = {}) {
|
|
|
5928
6034
|
process.exitCode = 1;
|
|
5929
6035
|
}
|
|
5930
6036
|
}
|
|
6037
|
+
async function sessionsLatestCommand(options = {}) {
|
|
6038
|
+
try {
|
|
6039
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
6040
|
+
const index = await loadSessionIndex(traceDir, {
|
|
6041
|
+
correlateGroup: options.correlateGroup,
|
|
6042
|
+
staleAfter: options.staleAfter
|
|
6043
|
+
});
|
|
6044
|
+
const latest = latestSession(index);
|
|
6045
|
+
if (!latest) {
|
|
6046
|
+
if (options.json) {
|
|
6047
|
+
console.log(JSON.stringify({ ok: false, traceDir, reason: "no-sessions" }, null, 2));
|
|
6048
|
+
} else {
|
|
6049
|
+
console.log("No sessions found");
|
|
6050
|
+
console.log(`Trace directory: ${traceDir}`);
|
|
6051
|
+
}
|
|
6052
|
+
process.exitCode = 1;
|
|
6053
|
+
return;
|
|
6054
|
+
}
|
|
6055
|
+
if (options.json) {
|
|
6056
|
+
console.log(JSON.stringify({ ok: true, traceDir, session: latest }, null, 2));
|
|
6057
|
+
return;
|
|
6058
|
+
}
|
|
6059
|
+
console.log(`Latest session: ${latest.sessionId}`);
|
|
6060
|
+
console.log(`Status: ${latest.status}`);
|
|
6061
|
+
console.log(`Last activity: ${latest.lastActivity}`);
|
|
6062
|
+
console.log(`Runs: ${latest.runIds.join(", ")}`);
|
|
6063
|
+
} catch (e) {
|
|
6064
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
6065
|
+
console.error(`[AgentInspect] sessions latest failed: ${msg}`);
|
|
6066
|
+
process.exitCode = 1;
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
async function sessionsActivityCommand(options = {}) {
|
|
6070
|
+
try {
|
|
6071
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
6072
|
+
const index = await loadSessionIndex(traceDir, {
|
|
6073
|
+
correlateGroup: options.correlateGroup,
|
|
6074
|
+
staleAfter: options.staleAfter
|
|
6075
|
+
});
|
|
6076
|
+
const summary = buildActivitySummary(index, { since: options.since });
|
|
6077
|
+
if (options.json) {
|
|
6078
|
+
console.log(JSON.stringify({ ok: true, traceDir, ...summary }, null, 2));
|
|
6079
|
+
return;
|
|
6080
|
+
}
|
|
6081
|
+
console.log(renderActivitySummaryHuman(summary));
|
|
6082
|
+
} catch (e) {
|
|
6083
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
6084
|
+
console.error(`[AgentInspect] sessions activity failed: ${msg}`);
|
|
6085
|
+
process.exitCode = 1;
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
async function sessionsHandoffsCommand(options = {}) {
|
|
6089
|
+
try {
|
|
6090
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
6091
|
+
const index = await loadSessionIndex(traceDir, {
|
|
6092
|
+
correlateGroup: options.correlateGroup
|
|
6093
|
+
});
|
|
6094
|
+
const handoffs = collectHandoffs(index, options.session);
|
|
6095
|
+
if (options.json) {
|
|
6096
|
+
console.log(
|
|
6097
|
+
JSON.stringify({ ok: true, traceDir, count: handoffs.length, handoffs }, null, 2)
|
|
6098
|
+
);
|
|
6099
|
+
return;
|
|
6100
|
+
}
|
|
6101
|
+
if (handoffs.length === 0) {
|
|
6102
|
+
console.log("No handoffs found");
|
|
6103
|
+
return;
|
|
6104
|
+
}
|
|
6105
|
+
for (const edge of handoffs) {
|
|
6106
|
+
console.log(
|
|
6107
|
+
`${edge.sessionId}: ${edge.from} -> ${edge.to} (${edge.confidence})`
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
} catch (e) {
|
|
6111
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
6112
|
+
console.error(`[AgentInspect] sessions handoffs failed: ${msg}`);
|
|
6113
|
+
process.exitCode = 1;
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
6116
|
+
async function sessionsErrorsCommand(options = {}) {
|
|
6117
|
+
try {
|
|
6118
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
6119
|
+
const index = await loadSessionIndex(traceDir, {
|
|
6120
|
+
correlateGroup: options.correlateGroup,
|
|
6121
|
+
staleAfter: options.staleAfter
|
|
6122
|
+
});
|
|
6123
|
+
const scoped = sessionsInSinceWindow(index, options.since);
|
|
6124
|
+
const errors = scoped.filter((session) => session.status === "error");
|
|
6125
|
+
if (options.json) {
|
|
6126
|
+
console.log(
|
|
6127
|
+
JSON.stringify(
|
|
6128
|
+
{ ok: true, traceDir, count: errors.length, sessions: errors },
|
|
6129
|
+
null,
|
|
6130
|
+
2
|
|
6131
|
+
)
|
|
6132
|
+
);
|
|
6133
|
+
return;
|
|
6134
|
+
}
|
|
6135
|
+
if (errors.length === 0) {
|
|
6136
|
+
console.log("No error sessions found");
|
|
6137
|
+
return;
|
|
6138
|
+
}
|
|
6139
|
+
for (const session of errors) {
|
|
6140
|
+
const detail = session.lastError?.message ?? "error";
|
|
6141
|
+
console.log(`${session.sessionId} ${detail} (${session.runIds.length} runs)`);
|
|
6142
|
+
}
|
|
6143
|
+
} catch (e) {
|
|
6144
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
6145
|
+
console.error(`[AgentInspect] sessions errors failed: ${msg}`);
|
|
6146
|
+
process.exitCode = 1;
|
|
6147
|
+
}
|
|
6148
|
+
}
|
|
6149
|
+
async function sessionsShowCommand(sessionId, options = {}) {
|
|
6150
|
+
await sessionCommand(sessionId, options);
|
|
6151
|
+
}
|
|
5931
6152
|
async function sessionCommand(sessionId, options = {}) {
|
|
5932
6153
|
const id = typeof sessionId === "string" && sessionId.trim() !== "" ? sessionId.trim() : "";
|
|
5933
6154
|
if (id === "") {
|
|
@@ -6081,9 +6302,9 @@ async function reportCommand(runId, options = {}) {
|
|
|
6081
6302
|
redactionProfile,
|
|
6082
6303
|
correlation: !options.noCorrelation
|
|
6083
6304
|
});
|
|
6084
|
-
const outPath = options.output !== void 0 && options.output.trim() !== "" ?
|
|
6305
|
+
const outPath = options.output !== void 0 && options.output.trim() !== "" ? path11.resolve(options.output.trim()) : void 0;
|
|
6085
6306
|
if (outPath !== void 0) {
|
|
6086
|
-
await mkdir(
|
|
6307
|
+
await mkdir(path11.dirname(outPath), { recursive: true });
|
|
6087
6308
|
await writeFile(outPath, result.content, "utf-8");
|
|
6088
6309
|
console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
|
|
6089
6310
|
}
|
|
@@ -6330,17 +6551,17 @@ function applyRule(rule, value, replacement) {
|
|
|
6330
6551
|
}
|
|
6331
6552
|
return value;
|
|
6332
6553
|
}
|
|
6333
|
-
function childPath(
|
|
6554
|
+
function childPath(path18, key) {
|
|
6334
6555
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
6335
|
-
return
|
|
6556
|
+
return path18 ? `${path18}.${key}` : key;
|
|
6336
6557
|
}
|
|
6337
|
-
return `${
|
|
6558
|
+
return `${path18 || "$"}[${JSON.stringify(key)}]`;
|
|
6338
6559
|
}
|
|
6339
|
-
function indexPath(
|
|
6340
|
-
return `${
|
|
6560
|
+
function indexPath(path18, index) {
|
|
6561
|
+
return `${path18 || "$"}[${index}]`;
|
|
6341
6562
|
}
|
|
6342
|
-
function makeFinding(
|
|
6343
|
-
return preview === void 0 ? { path:
|
|
6563
|
+
function makeFinding(path18, detector, action, matchKind, severity = "warning", preview) {
|
|
6564
|
+
return preview === void 0 ? { path: path18, detector, action, severity, matchKind } : { path: path18, detector, action, severity, matchKind, preview };
|
|
6344
6565
|
}
|
|
6345
6566
|
function createRedactionProfile(profile = "local") {
|
|
6346
6567
|
switch (profile) {
|
|
@@ -6409,11 +6630,11 @@ var Redactor2 = class {
|
|
|
6409
6630
|
#recordFinding(state, finding) {
|
|
6410
6631
|
if (this.#collectFindings) state.findings.push(finding);
|
|
6411
6632
|
}
|
|
6412
|
-
#redactValue(value, key,
|
|
6633
|
+
#redactValue(value, key, path18, depth, state) {
|
|
6413
6634
|
if (depth > this.#maxDepth) {
|
|
6414
6635
|
this.#recordFinding(
|
|
6415
6636
|
state,
|
|
6416
|
-
makeFinding(
|
|
6637
|
+
makeFinding(path18, "structure.maxDepth", "truncate", "value", "warning")
|
|
6417
6638
|
);
|
|
6418
6639
|
return "[Truncated]";
|
|
6419
6640
|
}
|
|
@@ -6422,19 +6643,19 @@ var Redactor2 = class {
|
|
|
6422
6643
|
if (rule) {
|
|
6423
6644
|
this.#recordFinding(
|
|
6424
6645
|
state,
|
|
6425
|
-
makeFinding(
|
|
6646
|
+
makeFinding(path18, `key.${rule.key}`, actionForRule(rule), "key", "warning")
|
|
6426
6647
|
);
|
|
6427
6648
|
return applyRule(rule, value, this.#replacement);
|
|
6428
6649
|
}
|
|
6429
6650
|
}
|
|
6430
6651
|
for (const detector of this.#detectors) {
|
|
6431
|
-
const detections = detector.detect({ path:
|
|
6652
|
+
const detections = detector.detect({ path: path18, key, value });
|
|
6432
6653
|
for (const detection of detections) {
|
|
6433
6654
|
const action = detection.action ?? "replace";
|
|
6434
6655
|
this.#recordFinding(
|
|
6435
6656
|
state,
|
|
6436
6657
|
makeFinding(
|
|
6437
|
-
|
|
6658
|
+
path18,
|
|
6438
6659
|
detector.id,
|
|
6439
6660
|
action,
|
|
6440
6661
|
detection.matchKind ?? detector.matchKind ?? "custom",
|
|
@@ -6452,7 +6673,7 @@ var Redactor2 = class {
|
|
|
6452
6673
|
const out = [];
|
|
6453
6674
|
state.seen.set(value, out);
|
|
6454
6675
|
value.forEach((item, index) => {
|
|
6455
|
-
out[index] = this.#redactValue(item, void 0, indexPath(
|
|
6676
|
+
out[index] = this.#redactValue(item, void 0, indexPath(path18, index), depth + 1, state);
|
|
6456
6677
|
});
|
|
6457
6678
|
return out;
|
|
6458
6679
|
}
|
|
@@ -6464,7 +6685,7 @@ var Redactor2 = class {
|
|
|
6464
6685
|
out[entryKey] = this.#redactValue(
|
|
6465
6686
|
entryValue,
|
|
6466
6687
|
entryKey,
|
|
6467
|
-
childPath(
|
|
6688
|
+
childPath(path18 === "$" ? "" : path18, entryKey),
|
|
6468
6689
|
depth + 1,
|
|
6469
6690
|
state
|
|
6470
6691
|
);
|
|
@@ -6911,14 +7132,14 @@ function uniqueSorted(values) {
|
|
|
6911
7132
|
return [...new Set(values)].sort();
|
|
6912
7133
|
}
|
|
6913
7134
|
function isWithinDirectory(child, parent) {
|
|
6914
|
-
const relative =
|
|
6915
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
7135
|
+
const relative = path11.relative(parent, child);
|
|
7136
|
+
return relative === "" || !relative.startsWith("..") && !path11.isAbsolute(relative);
|
|
6916
7137
|
}
|
|
6917
7138
|
async function resolveOutputPath(inputPath, output2, force) {
|
|
6918
7139
|
if (output2 === void 0 || output2.trim() === "") return void 0;
|
|
6919
|
-
const inputAbs =
|
|
6920
|
-
const outputAbs =
|
|
6921
|
-
const inputDir =
|
|
7140
|
+
const inputAbs = path11.resolve(inputPath);
|
|
7141
|
+
const outputAbs = path11.resolve(output2.trim());
|
|
7142
|
+
const inputDir = path11.dirname(inputAbs);
|
|
6922
7143
|
if (!isWithinDirectory(outputAbs, inputDir)) {
|
|
6923
7144
|
throw new Error("Refusing to write migrated output outside the input directory.");
|
|
6924
7145
|
}
|
|
@@ -7039,7 +7260,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
7039
7260
|
process.exitCode = 1;
|
|
7040
7261
|
return;
|
|
7041
7262
|
}
|
|
7042
|
-
const inputPath =
|
|
7263
|
+
const inputPath = path11.resolve(input3.trim());
|
|
7043
7264
|
const dryRun = options.dryRun === true;
|
|
7044
7265
|
if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
|
|
7045
7266
|
console.error("migrate requires --dry-run or --output <path>.");
|
|
@@ -7058,7 +7279,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
7058
7279
|
);
|
|
7059
7280
|
const result = await buildMigration(inputPath, outputPath);
|
|
7060
7281
|
if (!dryRun && outputPath !== void 0) {
|
|
7061
|
-
await mkdir(
|
|
7282
|
+
await mkdir(path11.dirname(outputPath), { recursive: true });
|
|
7062
7283
|
await writeFile(outputPath, result.content, "utf-8");
|
|
7063
7284
|
}
|
|
7064
7285
|
printSummary2(result, dryRun);
|
|
@@ -7336,7 +7557,7 @@ function stripPrefix(name, prefixes) {
|
|
|
7336
7557
|
}
|
|
7337
7558
|
return name;
|
|
7338
7559
|
}
|
|
7339
|
-
function eventEvidence(event,
|
|
7560
|
+
function eventEvidence(event, path18) {
|
|
7340
7561
|
return {
|
|
7341
7562
|
runId: event.runId,
|
|
7342
7563
|
eventId: event.eventId,
|
|
@@ -7346,7 +7567,7 @@ function eventEvidence(event, path17) {
|
|
|
7346
7567
|
kind: event.kind,
|
|
7347
7568
|
name: event.name,
|
|
7348
7569
|
status: event.status,
|
|
7349
|
-
...
|
|
7570
|
+
...path18 ? { path: path18 } : {}
|
|
7350
7571
|
};
|
|
7351
7572
|
}
|
|
7352
7573
|
function runEvidence(run) {
|
|
@@ -7409,9 +7630,9 @@ function eventEndMs(event) {
|
|
|
7409
7630
|
function normalizedKey(value) {
|
|
7410
7631
|
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
7411
7632
|
}
|
|
7412
|
-
function lastPathSegment(
|
|
7413
|
-
const parts =
|
|
7414
|
-
return parts[parts.length - 1] ??
|
|
7633
|
+
function lastPathSegment(path18) {
|
|
7634
|
+
const parts = path18.split(".");
|
|
7635
|
+
return parts[parts.length - 1] ?? path18;
|
|
7415
7636
|
}
|
|
7416
7637
|
function valueType(value) {
|
|
7417
7638
|
if (Array.isArray(value)) return "array";
|
|
@@ -7425,12 +7646,12 @@ function serializedByteLength(value) {
|
|
|
7425
7646
|
return void 0;
|
|
7426
7647
|
}
|
|
7427
7648
|
}
|
|
7428
|
-
function pushValueEntries(entries, event, value,
|
|
7429
|
-
entries.push({ event, path:
|
|
7649
|
+
function pushValueEntries(entries, event, value, path18, key, depth = 0) {
|
|
7650
|
+
entries.push({ event, path: path18, key, value });
|
|
7430
7651
|
if (depth >= 8) return;
|
|
7431
7652
|
if (Array.isArray(value)) {
|
|
7432
7653
|
for (const [index, item] of value.entries()) {
|
|
7433
|
-
pushValueEntries(entries, event, item, `${
|
|
7654
|
+
pushValueEntries(entries, event, item, `${path18}.${index}`, String(index), depth + 1);
|
|
7434
7655
|
}
|
|
7435
7656
|
return;
|
|
7436
7657
|
}
|
|
@@ -7440,7 +7661,7 @@ function pushValueEntries(entries, event, value, path17, key, depth = 0) {
|
|
|
7440
7661
|
entries,
|
|
7441
7662
|
event,
|
|
7442
7663
|
value[nestedKey],
|
|
7443
|
-
`${
|
|
7664
|
+
`${path18}.${nestedKey}`,
|
|
7444
7665
|
nestedKey,
|
|
7445
7666
|
depth + 1
|
|
7446
7667
|
);
|
|
@@ -7521,9 +7742,9 @@ function eventDurationMs(event) {
|
|
|
7521
7742
|
}
|
|
7522
7743
|
function treeShape(nodes) {
|
|
7523
7744
|
const lines = [];
|
|
7524
|
-
const visit = (node,
|
|
7525
|
-
lines.push(`${
|
|
7526
|
-
node.children.forEach((child, index) => visit(child, `${
|
|
7745
|
+
const visit = (node, path18) => {
|
|
7746
|
+
lines.push(`${path18}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
|
|
7747
|
+
node.children.forEach((child, index) => visit(child, `${path18}.${index}`));
|
|
7527
7748
|
};
|
|
7528
7749
|
nodes.forEach((node, index) => visit(node, String(index)));
|
|
7529
7750
|
return lines;
|
|
@@ -7572,9 +7793,9 @@ function retrievalShape(context) {
|
|
|
7572
7793
|
function guardrailShape(context) {
|
|
7573
7794
|
return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
|
|
7574
7795
|
}
|
|
7575
|
-
function firstEvidenceForKind(context, kind,
|
|
7796
|
+
function firstEvidenceForKind(context, kind, path18) {
|
|
7576
7797
|
const event = context.events.find((candidate) => candidate.kind === kind);
|
|
7577
|
-
return event ? [eventEvidence(event,
|
|
7798
|
+
return event ? [eventEvidence(event, path18)] : runEvidence(context.selectedRun);
|
|
7578
7799
|
}
|
|
7579
7800
|
function baselineDiffFinding(message, evidence, expected, actual) {
|
|
7580
7801
|
return failFinding("baseline.regression", message, evidence, expected, actual);
|
|
@@ -7924,13 +8145,13 @@ function createStructureCycleRule() {
|
|
|
7924
8145
|
const seenCycles = /* @__PURE__ */ new Set();
|
|
7925
8146
|
const findings = [];
|
|
7926
8147
|
for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
|
|
7927
|
-
const
|
|
8148
|
+
const path18 = [];
|
|
7928
8149
|
const seenAt = /* @__PURE__ */ new Map();
|
|
7929
8150
|
let current = event;
|
|
7930
8151
|
while (current) {
|
|
7931
8152
|
const existing = seenAt.get(current.eventId);
|
|
7932
8153
|
if (existing !== void 0) {
|
|
7933
|
-
const cycle =
|
|
8154
|
+
const cycle = path18.slice(existing);
|
|
7934
8155
|
const key = cycle.map((item) => item.eventId).sort().join("\0");
|
|
7935
8156
|
if (!seenCycles.has(key)) {
|
|
7936
8157
|
seenCycles.add(key);
|
|
@@ -7946,8 +8167,8 @@ function createStructureCycleRule() {
|
|
|
7946
8167
|
}
|
|
7947
8168
|
break;
|
|
7948
8169
|
}
|
|
7949
|
-
seenAt.set(current.eventId,
|
|
7950
|
-
|
|
8170
|
+
seenAt.set(current.eventId, path18.length);
|
|
8171
|
+
path18.push(current);
|
|
7951
8172
|
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
7952
8173
|
}
|
|
7953
8174
|
}
|
|
@@ -8744,23 +8965,23 @@ function evaluatePromptInjection(text, options = {}) {
|
|
|
8744
8965
|
}
|
|
8745
8966
|
return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
|
|
8746
8967
|
}
|
|
8747
|
-
function validateSchemaField(value, field,
|
|
8968
|
+
function validateSchemaField(value, field, path18, evidence) {
|
|
8748
8969
|
const ruleId = "guardrail.structured-output";
|
|
8749
8970
|
if (field.type) {
|
|
8750
8971
|
const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
8751
8972
|
if (actual !== field.type) {
|
|
8752
|
-
evidence.push({ ruleId, path:
|
|
8973
|
+
evidence.push({ ruleId, path: path18, preview: `expected ${field.type}, got ${actual}` });
|
|
8753
8974
|
return;
|
|
8754
8975
|
}
|
|
8755
8976
|
}
|
|
8756
8977
|
if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
|
|
8757
|
-
evidence.push({ ruleId, path:
|
|
8978
|
+
evidence.push({ ruleId, path: path18, preview: "value not in enum" });
|
|
8758
8979
|
}
|
|
8759
8980
|
if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
|
|
8760
8981
|
const record = value;
|
|
8761
8982
|
for (const key of field.required) {
|
|
8762
8983
|
if (!(key in record)) {
|
|
8763
|
-
evidence.push({ ruleId, path: `${
|
|
8984
|
+
evidence.push({ ruleId, path: `${path18}.${key}`, preview: "missing required key" });
|
|
8764
8985
|
}
|
|
8765
8986
|
}
|
|
8766
8987
|
}
|
|
@@ -9087,7 +9308,7 @@ function asConfig(value) {
|
|
|
9087
9308
|
}
|
|
9088
9309
|
async function loadConfig(configPath) {
|
|
9089
9310
|
if (configPath === void 0) return {};
|
|
9090
|
-
const extension =
|
|
9311
|
+
const extension = path11.extname(configPath);
|
|
9091
9312
|
if (TS_CONFIG_EXTENSIONS.has(extension)) {
|
|
9092
9313
|
throw new Error(
|
|
9093
9314
|
"TypeScript check configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
@@ -9096,7 +9317,7 @@ async function loadConfig(configPath) {
|
|
|
9096
9317
|
if (!CONFIG_EXTENSIONS.has(extension)) {
|
|
9097
9318
|
throw new Error("Unsupported check config extension. Use .json, .js, .mjs, or .cjs.");
|
|
9098
9319
|
}
|
|
9099
|
-
const absolute =
|
|
9320
|
+
const absolute = path11.resolve(configPath);
|
|
9100
9321
|
if (extension === ".json") {
|
|
9101
9322
|
const raw = await readFile(absolute, "utf-8");
|
|
9102
9323
|
return asConfig(JSON.parse(raw));
|
|
@@ -9245,10 +9466,10 @@ function printHuman(result) {
|
|
|
9245
9466
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
9246
9467
|
}
|
|
9247
9468
|
for (const finding of result.findings) {
|
|
9248
|
-
const
|
|
9469
|
+
const path18 = finding.evidence[0]?.path;
|
|
9249
9470
|
const run = finding.evidence[0]?.runId;
|
|
9250
9471
|
const runPrefix = run ? `[${run}] ` : "";
|
|
9251
|
-
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${
|
|
9472
|
+
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
9252
9473
|
}
|
|
9253
9474
|
}
|
|
9254
9475
|
function readErrorResult(error) {
|
|
@@ -9448,7 +9669,7 @@ function createViewerServer(options = {}) {
|
|
|
9448
9669
|
return sendJson(res, 200, {
|
|
9449
9670
|
ok: true,
|
|
9450
9671
|
readOnly: true,
|
|
9451
|
-
traceDir:
|
|
9672
|
+
traceDir: path11.resolve(traceDir)
|
|
9452
9673
|
});
|
|
9453
9674
|
}
|
|
9454
9675
|
const td = new TraceDirectory({ dir: traceDir });
|
|
@@ -9466,7 +9687,7 @@ function createViewerServer(options = {}) {
|
|
|
9466
9687
|
runId: meta.runId,
|
|
9467
9688
|
name: meta.name,
|
|
9468
9689
|
status: meta.status,
|
|
9469
|
-
file:
|
|
9690
|
+
file: path11.basename(meta.filePath),
|
|
9470
9691
|
startedAt: meta.startedAt,
|
|
9471
9692
|
durationMs: meta.durationMs
|
|
9472
9693
|
}))
|
|
@@ -9581,7 +9802,7 @@ function startViewerServer(options = {}) {
|
|
|
9581
9802
|
resolve({
|
|
9582
9803
|
host,
|
|
9583
9804
|
port: resolvedPort,
|
|
9584
|
-
traceDir:
|
|
9805
|
+
traceDir: path11.resolve(traceDir),
|
|
9585
9806
|
url: `http://${host}:${resolvedPort}`
|
|
9586
9807
|
});
|
|
9587
9808
|
});
|
|
@@ -9786,10 +10007,10 @@ async function evalRun(input3, options = {}) {
|
|
|
9786
10007
|
diagnostics: []
|
|
9787
10008
|
};
|
|
9788
10009
|
}
|
|
9789
|
-
function evidenceForRun(run,
|
|
9790
|
-
return [{ runId: run.runId, ...
|
|
10010
|
+
function evidenceForRun(run, path18) {
|
|
10011
|
+
return [{ runId: run.runId, ...path18 !== void 0 ? { path: path18 } : {} }];
|
|
9791
10012
|
}
|
|
9792
|
-
function evidenceForEvent(event,
|
|
10013
|
+
function evidenceForEvent(event, path18) {
|
|
9793
10014
|
return [
|
|
9794
10015
|
{
|
|
9795
10016
|
runId: event.runId,
|
|
@@ -9797,7 +10018,7 @@ function evidenceForEvent(event, path17) {
|
|
|
9797
10018
|
...event.parentId !== void 0 ? { parentId: event.parentId } : {},
|
|
9798
10019
|
kind: event.kind,
|
|
9799
10020
|
name: event.name,
|
|
9800
|
-
...
|
|
10021
|
+
...path18 !== void 0 ? { path: path18 } : {}
|
|
9801
10022
|
}
|
|
9802
10023
|
];
|
|
9803
10024
|
}
|
|
@@ -9955,9 +10176,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
|
|
|
9955
10176
|
function tokenize(text) {
|
|
9956
10177
|
return [...text.toLowerCase().matchAll(/[a-z0-9][a-z0-9'-]{2,}/g)].map((match) => match[0].replace(/^['-]+|['-]+$/g, "")).filter((token) => token.length > 2 && !STOP_WORDS.has(token));
|
|
9957
10178
|
}
|
|
9958
|
-
function firstEvidence(fields, run,
|
|
10179
|
+
function firstEvidence(fields, run, path18) {
|
|
9959
10180
|
const first = fields[0];
|
|
9960
|
-
return first === void 0 ? evidenceForRun(run,
|
|
10181
|
+
return first === void 0 ? evidenceForRun(run, path18) : evidenceForEvent(first.node.event, first.path);
|
|
9961
10182
|
}
|
|
9962
10183
|
function collectSourceIds(nodes, keys) {
|
|
9963
10184
|
const wanted = keySet(keys);
|
|
@@ -10334,8 +10555,8 @@ function renderEvalMarkdown(result) {
|
|
|
10334
10555
|
if (result.findings.length > 0) {
|
|
10335
10556
|
lines.push("", "## Findings");
|
|
10336
10557
|
for (const finding of result.findings) {
|
|
10337
|
-
const
|
|
10338
|
-
lines.push(`- ${finding.ruleId}: ${finding.message}${
|
|
10558
|
+
const path18 = finding.evidence[0]?.path;
|
|
10559
|
+
lines.push(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
10339
10560
|
}
|
|
10340
10561
|
}
|
|
10341
10562
|
return `${lines.join("\n")}
|
|
@@ -10382,7 +10603,7 @@ function asConfig2(value) {
|
|
|
10382
10603
|
}
|
|
10383
10604
|
async function loadConfig2(configPath) {
|
|
10384
10605
|
if (configPath === void 0) return {};
|
|
10385
|
-
const extension =
|
|
10606
|
+
const extension = path11.extname(configPath);
|
|
10386
10607
|
if (TS_CONFIG_EXTENSIONS2.has(extension)) {
|
|
10387
10608
|
throw new Error(
|
|
10388
10609
|
"TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
@@ -10391,7 +10612,7 @@ async function loadConfig2(configPath) {
|
|
|
10391
10612
|
if (!CONFIG_EXTENSIONS2.has(extension)) {
|
|
10392
10613
|
throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
|
|
10393
10614
|
}
|
|
10394
|
-
const absolute =
|
|
10615
|
+
const absolute = path11.resolve(configPath);
|
|
10395
10616
|
if (extension === ".json") {
|
|
10396
10617
|
const raw = await readFile(absolute, "utf-8");
|
|
10397
10618
|
return asConfig2(JSON.parse(raw));
|
|
@@ -10528,8 +10749,8 @@ function printHuman2(result) {
|
|
|
10528
10749
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
10529
10750
|
}
|
|
10530
10751
|
for (const finding of result.findings) {
|
|
10531
|
-
const
|
|
10532
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
10752
|
+
const path18 = finding.evidence[0]?.path;
|
|
10753
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
10533
10754
|
}
|
|
10534
10755
|
}
|
|
10535
10756
|
function readErrorResult2(error) {
|
|
@@ -10767,8 +10988,8 @@ function printHuman3(result) {
|
|
|
10767
10988
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
10768
10989
|
}
|
|
10769
10990
|
for (const finding of result.findings) {
|
|
10770
|
-
const
|
|
10771
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
10991
|
+
const path18 = finding.evidence[0]?.path;
|
|
10992
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
10772
10993
|
}
|
|
10773
10994
|
console.log(`Note: ${result.note}`);
|
|
10774
10995
|
}
|
|
@@ -10887,8 +11108,8 @@ function renderCheckSection(result) {
|
|
|
10887
11108
|
`Diagnostics: ${result.diagnostics.length}`
|
|
10888
11109
|
];
|
|
10889
11110
|
for (const finding of result.findings.slice(0, 10)) {
|
|
10890
|
-
const
|
|
10891
|
-
lines.push(`- ${finding.ruleId}: ${finding.message} (${
|
|
11111
|
+
const path18 = finding.evidence[0]?.path ?? "(run)";
|
|
11112
|
+
lines.push(`- ${finding.ruleId}: ${finding.message} (${path18})`);
|
|
10892
11113
|
}
|
|
10893
11114
|
for (const diagnostic4 of result.diagnostics.slice(0, 10)) {
|
|
10894
11115
|
lines.push(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
@@ -10966,8 +11187,8 @@ function renderHtml(trace, check, diff) {
|
|
|
10966
11187
|
`;
|
|
10967
11188
|
}
|
|
10968
11189
|
async function writeArtifact(outputDir, relativePath, content, files) {
|
|
10969
|
-
const outPath =
|
|
10970
|
-
await mkdir(
|
|
11190
|
+
const outPath = path11.join(outputDir, relativePath);
|
|
11191
|
+
await mkdir(path11.dirname(outPath), { recursive: true });
|
|
10971
11192
|
await writeFile(outPath, content, "utf-8");
|
|
10972
11193
|
files.push(relativePath);
|
|
10973
11194
|
}
|
|
@@ -10983,7 +11204,7 @@ function manifestStatus(check, diff) {
|
|
|
10983
11204
|
return "ok";
|
|
10984
11205
|
}
|
|
10985
11206
|
async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
10986
|
-
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ?
|
|
11207
|
+
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path11.resolve(options.outputDir.trim()) : "";
|
|
10987
11208
|
if (outputDir === "") {
|
|
10988
11209
|
console.error("--output-dir is required.");
|
|
10989
11210
|
process.exitCode = 1;
|
|
@@ -11049,8 +11270,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
|
11049
11270
|
await writeArtifact(outputDir, "report.html", renderHtml(trace, check, diff), files);
|
|
11050
11271
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
11051
11272
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
11052
|
-
await mkdir(
|
|
11053
|
-
await appendFile(
|
|
11273
|
+
await mkdir(path11.dirname(path11.resolve(summaryTarget)), { recursive: true });
|
|
11274
|
+
await appendFile(path11.resolve(summaryTarget), `
|
|
11054
11275
|
${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
11055
11276
|
}
|
|
11056
11277
|
const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
|
|
@@ -11069,10 +11290,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
|
11069
11290
|
findings: diff?.findings.length ?? 0,
|
|
11070
11291
|
diagnostics: diff?.diagnostics.length ?? 0
|
|
11071
11292
|
},
|
|
11072
|
-
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary:
|
|
11293
|
+
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path11.resolve(summaryTarget) } : {},
|
|
11073
11294
|
note: NOTE
|
|
11074
11295
|
};
|
|
11075
|
-
await writeFile(
|
|
11296
|
+
await writeFile(path11.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
|
|
11076
11297
|
if (options.json === true) {
|
|
11077
11298
|
console.log(writeJson3(manifest).trimEnd());
|
|
11078
11299
|
} else {
|
|
@@ -11084,7 +11305,7 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
|
11084
11305
|
}
|
|
11085
11306
|
}
|
|
11086
11307
|
function validateReporterArtifactPath(options) {
|
|
11087
|
-
const outputDir =
|
|
11308
|
+
const outputDir = path11.resolve(options.outputDir);
|
|
11088
11309
|
const diagnostics = [];
|
|
11089
11310
|
const rawPath = options.relativePath;
|
|
11090
11311
|
if (rawPath.length === 0) {
|
|
@@ -11104,7 +11325,7 @@ function validateReporterArtifactPath(options) {
|
|
|
11104
11325
|
});
|
|
11105
11326
|
return { ok: false, outputDir, diagnostics };
|
|
11106
11327
|
}
|
|
11107
|
-
if (
|
|
11328
|
+
if (path11.isAbsolute(rawPath) || path11.win32.isAbsolute(rawPath)) {
|
|
11108
11329
|
diagnostics.push({
|
|
11109
11330
|
code: "artifact_path_absolute",
|
|
11110
11331
|
severity: "error",
|
|
@@ -11113,7 +11334,7 @@ function validateReporterArtifactPath(options) {
|
|
|
11113
11334
|
});
|
|
11114
11335
|
return { ok: false, outputDir, diagnostics };
|
|
11115
11336
|
}
|
|
11116
|
-
const normalized =
|
|
11337
|
+
const normalized = path11.posix.normalize(rawPath.replace(/\\/g, "/"));
|
|
11117
11338
|
const segments = normalized.split("/");
|
|
11118
11339
|
if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
|
|
11119
11340
|
diagnostics.push({
|
|
@@ -11124,9 +11345,9 @@ function validateReporterArtifactPath(options) {
|
|
|
11124
11345
|
});
|
|
11125
11346
|
return { ok: false, outputDir, diagnostics };
|
|
11126
11347
|
}
|
|
11127
|
-
const absolutePath =
|
|
11128
|
-
const relFromOutput =
|
|
11129
|
-
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") ||
|
|
11348
|
+
const absolutePath = path11.resolve(outputDir, normalized);
|
|
11349
|
+
const relFromOutput = path11.relative(outputDir, absolutePath);
|
|
11350
|
+
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path11.isAbsolute(relFromOutput)) {
|
|
11130
11351
|
diagnostics.push({
|
|
11131
11352
|
code: "artifact_path_escape",
|
|
11132
11353
|
severity: "error",
|
|
@@ -11272,23 +11493,23 @@ function readManifestDocument(value) {
|
|
|
11272
11493
|
};
|
|
11273
11494
|
}
|
|
11274
11495
|
function cwdRelative(filePath) {
|
|
11275
|
-
const relative =
|
|
11276
|
-
if (relative === "" || relative.startsWith("../") ||
|
|
11277
|
-
return
|
|
11496
|
+
const relative = path11.relative(process.cwd(), path11.resolve(filePath)).replace(/\\/g, "/");
|
|
11497
|
+
if (relative === "" || relative.startsWith("../") || path11.isAbsolute(relative)) {
|
|
11498
|
+
return path11.basename(filePath);
|
|
11278
11499
|
}
|
|
11279
11500
|
return relative;
|
|
11280
11501
|
}
|
|
11281
11502
|
async function readReporterManifest(filePath) {
|
|
11282
|
-
const absolute =
|
|
11503
|
+
const absolute = path11.resolve(filePath);
|
|
11283
11504
|
const raw = await readFile(absolute, "utf-8");
|
|
11284
11505
|
const document = readManifestDocument(JSON.parse(raw));
|
|
11285
11506
|
const manifest = document.manifest;
|
|
11286
11507
|
const results = manifest.results.map((result) => ({
|
|
11287
11508
|
testId: safeText(result.testId),
|
|
11288
11509
|
name: safeText(result.name),
|
|
11289
|
-
...result.file === void 0 ? {} : { file: safeText(
|
|
11510
|
+
...result.file === void 0 ? {} : { file: safeText(path11.basename(result.file)) },
|
|
11290
11511
|
status: result.status,
|
|
11291
|
-
...result.tracePath === void 0 ? {} : { tracePath: safeText(
|
|
11512
|
+
...result.tracePath === void 0 ? {} : { tracePath: safeText(path11.basename(result.tracePath)) },
|
|
11292
11513
|
artifacts: result.artifacts,
|
|
11293
11514
|
diagnostics: result.diagnostics
|
|
11294
11515
|
}));
|
|
@@ -11427,15 +11648,15 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
|
|
|
11427
11648
|
return;
|
|
11428
11649
|
}
|
|
11429
11650
|
const markdown = renderMarkdown2(result);
|
|
11430
|
-
const outputPath = options.output !== void 0 && options.output.trim() !== "" ?
|
|
11651
|
+
const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path11.resolve(options.output.trim()) : void 0;
|
|
11431
11652
|
if (outputPath !== void 0) {
|
|
11432
|
-
await mkdir(
|
|
11653
|
+
await mkdir(path11.dirname(outputPath), { recursive: true });
|
|
11433
11654
|
await writeFile(outputPath, markdown, "utf-8");
|
|
11434
11655
|
}
|
|
11435
11656
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
11436
11657
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
11437
|
-
const summaryPath =
|
|
11438
|
-
await mkdir(
|
|
11658
|
+
const summaryPath = path11.resolve(summaryTarget);
|
|
11659
|
+
await mkdir(path11.dirname(summaryPath), { recursive: true });
|
|
11439
11660
|
await appendFile(summaryPath, `
|
|
11440
11661
|
${markdown}`, "utf-8");
|
|
11441
11662
|
}
|
|
@@ -11583,8 +11804,8 @@ jobs:
|
|
|
11583
11804
|
}
|
|
11584
11805
|
async function planInit(options = {}) {
|
|
11585
11806
|
const framework = normalizeFramework(options.framework);
|
|
11586
|
-
const cwd =
|
|
11587
|
-
const demoPath = framework === "custom" ?
|
|
11807
|
+
const cwd = path11.resolve(options.cwd ?? process.cwd());
|
|
11808
|
+
const demoPath = framework === "custom" ? path11.join("examples", "agent-inspect-demo.mjs") : path11.join("examples", `agent-inspect-${framework}-demo.mjs`);
|
|
11588
11809
|
const candidates = [
|
|
11589
11810
|
{ rel: CONFIG_FILE, content: configTemplate(framework) },
|
|
11590
11811
|
{ rel: GITKEEP, content: "" },
|
|
@@ -11598,7 +11819,7 @@ async function planInit(options = {}) {
|
|
|
11598
11819
|
}
|
|
11599
11820
|
const files = [];
|
|
11600
11821
|
for (const candidate of candidates) {
|
|
11601
|
-
const abs =
|
|
11822
|
+
const abs = path11.join(cwd, candidate.rel);
|
|
11602
11823
|
try {
|
|
11603
11824
|
await access(abs);
|
|
11604
11825
|
files.push({
|
|
@@ -11619,12 +11840,12 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
11619
11840
|
if (entry.action === "skip") {
|
|
11620
11841
|
continue;
|
|
11621
11842
|
}
|
|
11622
|
-
const abs =
|
|
11843
|
+
const abs = path11.join(cwd, entry.path);
|
|
11623
11844
|
if (options.dryRun) {
|
|
11624
11845
|
written.push(entry.path);
|
|
11625
11846
|
continue;
|
|
11626
11847
|
}
|
|
11627
|
-
await mkdir(
|
|
11848
|
+
await mkdir(path11.dirname(abs), { recursive: true });
|
|
11628
11849
|
const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
|
|
11629
11850
|
await writeFile(abs, content, "utf-8");
|
|
11630
11851
|
written.push(entry.path);
|
|
@@ -11632,7 +11853,7 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
11632
11853
|
return written;
|
|
11633
11854
|
}
|
|
11634
11855
|
async function initCommand(options = {}) {
|
|
11635
|
-
const cwd =
|
|
11856
|
+
const cwd = path11.resolve(options.cwd ?? process.cwd());
|
|
11636
11857
|
try {
|
|
11637
11858
|
const plan = await planInit({ ...options, cwd });
|
|
11638
11859
|
const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
|
|
@@ -11723,7 +11944,7 @@ function envCheck(name, optional = true) {
|
|
|
11723
11944
|
};
|
|
11724
11945
|
}
|
|
11725
11946
|
async function traceDirWritable(traceDir) {
|
|
11726
|
-
const resolved =
|
|
11947
|
+
const resolved = path11.resolve(traceDir);
|
|
11727
11948
|
try {
|
|
11728
11949
|
await mkdir(resolved, { recursive: true });
|
|
11729
11950
|
await access(resolved, constants.W_OK);
|
|
@@ -11744,7 +11965,7 @@ async function traceDirWritable(traceDir) {
|
|
|
11744
11965
|
}
|
|
11745
11966
|
}
|
|
11746
11967
|
function resolvePackage(cwd, name) {
|
|
11747
|
-
const require2 = createRequire(
|
|
11968
|
+
const require2 = createRequire(path11.join(cwd, "package.json"));
|
|
11748
11969
|
try {
|
|
11749
11970
|
const pkgPath = require2.resolve(`${name}/package.json`);
|
|
11750
11971
|
const pkg = require2(pkgPath);
|
|
@@ -11755,7 +11976,7 @@ function resolvePackage(cwd, name) {
|
|
|
11755
11976
|
}
|
|
11756
11977
|
function importSmoke(cwd) {
|
|
11757
11978
|
const results = [];
|
|
11758
|
-
const require2 = createRequire(
|
|
11979
|
+
const require2 = createRequire(path11.join(cwd, "package.json"));
|
|
11759
11980
|
try {
|
|
11760
11981
|
require2.resolve("agent-inspect");
|
|
11761
11982
|
results.push({
|
|
@@ -11838,7 +12059,7 @@ function versionMismatchCheck(cwd) {
|
|
|
11838
12059
|
};
|
|
11839
12060
|
}
|
|
11840
12061
|
async function runDoctorChecks(options = {}) {
|
|
11841
|
-
const cwd =
|
|
12062
|
+
const cwd = path11.resolve(options.cwd ?? process2.cwd());
|
|
11842
12063
|
const traceDir = options.traceDir?.trim() || process2.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
|
|
11843
12064
|
const checks2 = [
|
|
11844
12065
|
nodeVersionCheck(),
|
|
@@ -11950,7 +12171,7 @@ function createTraceDirectoryIndexer() {
|
|
|
11950
12171
|
// packages/cli/src/index-cmd.ts
|
|
11951
12172
|
var INDEX_FILENAME = ".agent-inspect-index.json";
|
|
11952
12173
|
function traceIndexPath(traceDir) {
|
|
11953
|
-
return
|
|
12174
|
+
return path11.join(traceDir, INDEX_FILENAME);
|
|
11954
12175
|
}
|
|
11955
12176
|
function parseMaxEntries(raw) {
|
|
11956
12177
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -12058,14 +12279,14 @@ async function indexCleanCommand(options = {}) {
|
|
|
12058
12279
|
}
|
|
12059
12280
|
}
|
|
12060
12281
|
var PACKAGE = "@agent-inspect/index-sqlite";
|
|
12061
|
-
function
|
|
12282
|
+
function isModuleNotFound3(e) {
|
|
12062
12283
|
return e !== null && typeof e === "object" && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "MODULE_NOT_FOUND");
|
|
12063
12284
|
}
|
|
12064
12285
|
async function loadIndexSqlite() {
|
|
12065
12286
|
try {
|
|
12066
|
-
return await import('./src-
|
|
12287
|
+
return await import('./src-VQT7QLGV.mjs');
|
|
12067
12288
|
} catch (e) {
|
|
12068
|
-
if (
|
|
12289
|
+
if (isModuleNotFound3(e)) {
|
|
12069
12290
|
console.error(
|
|
12070
12291
|
`The optional SQLite index is not installed. Run: npm install ${PACKAGE}`
|
|
12071
12292
|
);
|
|
@@ -12086,14 +12307,14 @@ function parsePositiveInt(raw, flag) {
|
|
|
12086
12307
|
}
|
|
12087
12308
|
return parsed;
|
|
12088
12309
|
}
|
|
12089
|
-
async function
|
|
12310
|
+
async function newestTraceMtimeMs2(traceDir) {
|
|
12090
12311
|
let newest = 0;
|
|
12091
12312
|
try {
|
|
12092
12313
|
const files = await readdir(traceDir);
|
|
12093
12314
|
for (const file of files) {
|
|
12094
12315
|
if (!file.endsWith(".jsonl")) continue;
|
|
12095
12316
|
try {
|
|
12096
|
-
const s = await stat(
|
|
12317
|
+
const s = await stat(path11.join(traceDir, file));
|
|
12097
12318
|
if (s.mtimeMs > newest) newest = s.mtimeMs;
|
|
12098
12319
|
} catch {
|
|
12099
12320
|
}
|
|
@@ -12123,7 +12344,7 @@ async function indexSqliteStatusCommand(options = {}) {
|
|
|
12123
12344
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
12124
12345
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
12125
12346
|
const status = mod.indexStatus(dbPath);
|
|
12126
|
-
const stale = mod.isIndexStale(dbPath, await
|
|
12347
|
+
const stale = mod.isIndexStale(dbPath, await newestTraceMtimeMs2(traceDir));
|
|
12127
12348
|
if (options.json) {
|
|
12128
12349
|
console.log(JSON.stringify({ ok: true, traceDir, stale, ...status }, null, 2));
|
|
12129
12350
|
return;
|
|
@@ -12372,19 +12593,19 @@ function serializeWorkspaceManifest(manifest) {
|
|
|
12372
12593
|
}
|
|
12373
12594
|
var INDEX_DIR_NAME = "index";
|
|
12374
12595
|
function resolveWorkspaceLocation(cwd = process.cwd()) {
|
|
12375
|
-
const projectRoot =
|
|
12376
|
-
const workspaceDir =
|
|
12596
|
+
const projectRoot = path11.resolve(cwd);
|
|
12597
|
+
const workspaceDir = path11.join(projectRoot, WORKSPACE_DIR_NAME);
|
|
12377
12598
|
return {
|
|
12378
12599
|
projectRoot,
|
|
12379
12600
|
workspaceDir,
|
|
12380
|
-
manifestPath:
|
|
12601
|
+
manifestPath: path11.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
|
|
12381
12602
|
};
|
|
12382
12603
|
}
|
|
12383
12604
|
function resolveInsideWorkspace(workspaceDir, relative) {
|
|
12384
|
-
const base =
|
|
12385
|
-
const resolved =
|
|
12386
|
-
const rel =
|
|
12387
|
-
if (rel === "" || rel === "." || !rel.startsWith("..") && !
|
|
12605
|
+
const base = path11.resolve(workspaceDir);
|
|
12606
|
+
const resolved = path11.resolve(base, relative);
|
|
12607
|
+
const rel = path11.relative(base, resolved);
|
|
12608
|
+
if (rel === "" || rel === "." || !rel.startsWith("..") && !path11.isAbsolute(rel)) {
|
|
12388
12609
|
return resolved;
|
|
12389
12610
|
}
|
|
12390
12611
|
throw new Error(
|
|
@@ -12453,7 +12674,7 @@ async function createWorkspace(options = {}) {
|
|
|
12453
12674
|
created = false;
|
|
12454
12675
|
adopted = true;
|
|
12455
12676
|
} else {
|
|
12456
|
-
const project = options.project?.trim() ||
|
|
12677
|
+
const project = options.project?.trim() || path11.basename(location.projectRoot) || "workspace";
|
|
12457
12678
|
const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
|
|
12458
12679
|
manifest = createDefaultWorkspaceManifest({
|
|
12459
12680
|
project,
|
|
@@ -12592,7 +12813,7 @@ async function doctorWorkspace(location) {
|
|
|
12592
12813
|
const abs = resolveInsideWorkspace(location.workspaceDir, rel);
|
|
12593
12814
|
for (const file of await listJsonl(abs)) {
|
|
12594
12815
|
try {
|
|
12595
|
-
const s = await stat(
|
|
12816
|
+
const s = await stat(path11.join(abs, file));
|
|
12596
12817
|
newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
|
|
12597
12818
|
} catch {
|
|
12598
12819
|
checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
|
|
@@ -12640,7 +12861,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
|
|
|
12640
12861
|
const relPath = `${rel}/${entry}`;
|
|
12641
12862
|
removed.push(relPath);
|
|
12642
12863
|
if (!dryRun) {
|
|
12643
|
-
await rm(
|
|
12864
|
+
await rm(path11.join(abs, entry), { recursive: true, force: true });
|
|
12644
12865
|
}
|
|
12645
12866
|
}
|
|
12646
12867
|
}
|
|
@@ -13046,12 +13267,32 @@ function createCliProgram() {
|
|
|
13046
13267
|
).option("--json", "print results as JSON").action((opts) => {
|
|
13047
13268
|
runCommand(() => searchCommand(opts));
|
|
13048
13269
|
});
|
|
13049
|
-
program.command("sessions").description(
|
|
13270
|
+
const sessionsCmd = program.command("sessions").description(
|
|
13271
|
+
"Workflow sessions and activity from local trace metadata (read-only, v4.2+)"
|
|
13272
|
+
).option("--dir <path>", "trace directory").option(
|
|
13050
13273
|
"--correlate-group",
|
|
13051
13274
|
"treat shared groupId as a synthetic session when sessionId is absent"
|
|
13052
|
-
).option("--json", "print
|
|
13275
|
+
).option("--json", "print JSON output").option(
|
|
13276
|
+
"--stale-after <duration>",
|
|
13277
|
+
"mark sessions stale after inactivity (e.g. 24h, 7d)"
|
|
13278
|
+
).action((opts) => {
|
|
13053
13279
|
runCommand(() => sessionsCommand(opts));
|
|
13054
13280
|
});
|
|
13281
|
+
sessionsCmd.command("latest").description("Show the most recently active session").option("--dir <path>", "trace directory").option("--correlate-group", "include synthetic group: sessions").option("--stale-after <duration>", "staleness threshold for status derivation").option("--json", "print JSON result").action((opts) => {
|
|
13282
|
+
runCommand(() => sessionsLatestCommand(opts));
|
|
13283
|
+
});
|
|
13284
|
+
sessionsCmd.command("activity").description("Summarize recent session activity").option("--dir <path>", "trace directory").option("--since <duration>", "activity window (default 7d)").option("--correlate-group", "include synthetic group: sessions").option("--stale-after <duration>", "staleness threshold for status derivation").option("--json", "print JSON result").action((opts) => {
|
|
13285
|
+
runCommand(() => sessionsActivityCommand(opts));
|
|
13286
|
+
});
|
|
13287
|
+
sessionsCmd.command("show").description("Show one session (alias for session <id>)").argument("<session-id>", "session id").option("--dir <path>", "trace directory").option("--timeline", "include per-run timelines").option("--critical-path", "include critical path section").option("--diagnostics", "include ambiguity warnings").option("--json", "print JSON result").action((sessionId, opts) => {
|
|
13288
|
+
runCommand(() => sessionsShowCommand(sessionId, opts));
|
|
13289
|
+
});
|
|
13290
|
+
sessionsCmd.command("handoffs").description("List handoff edges across sessions").option("--dir <path>", "trace directory").option("--session <id>", "limit to one session").option("--correlate-group", "include synthetic group: sessions").option("--json", "print JSON result").action((opts) => {
|
|
13291
|
+
runCommand(() => sessionsHandoffsCommand(opts));
|
|
13292
|
+
});
|
|
13293
|
+
sessionsCmd.command("errors").description("List sessions with errors in a time window").option("--dir <path>", "trace directory").option("--since <duration>", "filter by last activity (default: all)").option("--correlate-group", "include synthetic group: sessions").option("--stale-after <duration>", "staleness threshold for status derivation").option("--json", "print JSON result").action((opts) => {
|
|
13294
|
+
runCommand(() => sessionsErrorsCommand(opts));
|
|
13295
|
+
});
|
|
13055
13296
|
program.command("session").description("Inspect one workflow session: runs, handoffs, retries (read-only)").argument("<session-id>", "session id (from sessions output)").option("--dir <path>", "trace directory").option("--timeline", "include per-run timelines").option("--critical-path", "include critical path section").option("--diagnostics", "include ambiguity warnings").option("--json", "print session view as JSON").action((sessionId, opts) => {
|
|
13056
13297
|
runCommand(() => sessionCommand(sessionId, opts));
|
|
13057
13298
|
});
|
|
@@ -13180,9 +13421,9 @@ function isPrimaryModule() {
|
|
|
13180
13421
|
if (!entry) return false;
|
|
13181
13422
|
const selfPath = fileURLToPath(import.meta.url);
|
|
13182
13423
|
try {
|
|
13183
|
-
return realpathSync(
|
|
13424
|
+
return realpathSync(path11.resolve(entry)) === realpathSync(path11.resolve(selfPath));
|
|
13184
13425
|
} catch {
|
|
13185
|
-
return
|
|
13426
|
+
return path11.resolve(entry) === path11.resolve(selfPath);
|
|
13186
13427
|
}
|
|
13187
13428
|
}
|
|
13188
13429
|
if (isPrimaryModule()) {
|