agent-inspect 6.10.0 → 6.12.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/README.md +33 -15
- package/docs/ADOPTION.md +4 -0
- package/docs/CLI.md +11 -0
- package/docs/COMPARE.md +22 -0
- package/docs/DEMO-SCRIPT.md +12 -0
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-36IJ76LH.mjs → chunk-XTAA733P.mjs} +2 -2
- package/packages/cli/dist/{chunk-36IJ76LH.mjs.map → chunk-XTAA733P.mjs.map} +1 -1
- package/packages/cli/dist/index.cjs +376 -218
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +297 -148
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-YFN3Q3GP.mjs → src-G7PM24W2.mjs} +3 -3
- package/packages/cli/dist/{src-YFN3Q3GP.mjs.map → src-G7PM24W2.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +143 -0
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +40 -2
- package/packages/core/dist/advanced.d.ts +40 -2
- package/packages/core/dist/advanced.mjs +146 -4
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/{chunk-KDDU2R5P.mjs → chunk-LFWZEO2L.mjs} +2 -2
- package/packages/core/dist/{chunk-KDDU2R5P.mjs.map → chunk-LFWZEO2L.mjs.map} +1 -1
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var crypto = require('crypto');
|
|
5
5
|
var promises = require('fs/promises');
|
|
6
6
|
var os = require('os');
|
|
7
|
-
var
|
|
7
|
+
var path30 = require('path');
|
|
8
8
|
var async_hooks = require('async_hooks');
|
|
9
9
|
var process3 = require('process');
|
|
10
10
|
var tty = require('tty');
|
|
@@ -20,7 +20,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
20
20
|
|
|
21
21
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
22
22
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
23
|
-
var
|
|
23
|
+
var path30__default = /*#__PURE__*/_interopDefault(path30);
|
|
24
24
|
var process3__default = /*#__PURE__*/_interopDefault(process3);
|
|
25
25
|
var tty__default = /*#__PURE__*/_interopDefault(tty);
|
|
26
26
|
|
|
@@ -864,7 +864,7 @@ function getDefaultTraceDir() {
|
|
|
864
864
|
if (typeof home !== "string" || home.trim() === "") {
|
|
865
865
|
return FALLBACK_TRACE_DIR;
|
|
866
866
|
}
|
|
867
|
-
return
|
|
867
|
+
return path30__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
|
|
868
868
|
} catch {
|
|
869
869
|
return FALLBACK_TRACE_DIR;
|
|
870
870
|
}
|
|
@@ -872,11 +872,11 @@ function getDefaultTraceDir() {
|
|
|
872
872
|
function getTraceFilePath(runId, traceDir) {
|
|
873
873
|
const baseDir = traceDir ?? getDefaultTraceDir();
|
|
874
874
|
let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
|
|
875
|
-
safeId =
|
|
875
|
+
safeId = path30__default.default.basename(safeId);
|
|
876
876
|
if (safeId === "" || safeId === "." || safeId === "..") {
|
|
877
877
|
safeId = "run_unknown";
|
|
878
878
|
}
|
|
879
|
-
return
|
|
879
|
+
return path30__default.default.join(baseDir, `${safeId}.jsonl`);
|
|
880
880
|
}
|
|
881
881
|
function formatError(error) {
|
|
882
882
|
if (error instanceof Error) {
|
|
@@ -933,7 +933,7 @@ var init_utils = __esm({
|
|
|
933
933
|
init_duration();
|
|
934
934
|
DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
|
|
935
935
|
RUNS_DIR_NAME = "runs";
|
|
936
|
-
FALLBACK_TRACE_DIR =
|
|
936
|
+
FALLBACK_TRACE_DIR = path30__default.default.join(
|
|
937
937
|
os__default.default.tmpdir(),
|
|
938
938
|
"agent-inspect",
|
|
939
939
|
RUNS_DIR_NAME
|
|
@@ -1899,7 +1899,7 @@ var init_trace_directory = __esm({
|
|
|
1899
1899
|
this.#dir = resolveTraceDir(options);
|
|
1900
1900
|
}
|
|
1901
1901
|
getPath(filename) {
|
|
1902
|
-
return filename ?
|
|
1902
|
+
return filename ? path30__default.default.join(this.#dir, filename) : this.#dir;
|
|
1903
1903
|
}
|
|
1904
1904
|
async list() {
|
|
1905
1905
|
try {
|
|
@@ -1928,7 +1928,7 @@ function parseIsoToMs2(value) {
|
|
|
1928
1928
|
}
|
|
1929
1929
|
async function extractMetadata(filePath, _quickScan) {
|
|
1930
1930
|
const stats = await promises.stat(filePath);
|
|
1931
|
-
let runIdFromFile =
|
|
1931
|
+
let runIdFromFile = path30__default.default.basename(filePath);
|
|
1932
1932
|
if (runIdFromFile.endsWith(".jsonl")) {
|
|
1933
1933
|
runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
|
|
1934
1934
|
}
|
|
@@ -2720,6 +2720,14 @@ var init_what = __esm({
|
|
|
2720
2720
|
}
|
|
2721
2721
|
});
|
|
2722
2722
|
|
|
2723
|
+
// packages/core/src/causal-failure.ts
|
|
2724
|
+
var init_causal_failure = __esm({
|
|
2725
|
+
"packages/core/src/causal-failure.ts"() {
|
|
2726
|
+
init_extract();
|
|
2727
|
+
init_timeline();
|
|
2728
|
+
}
|
|
2729
|
+
});
|
|
2730
|
+
|
|
2723
2731
|
// packages/core/src/explain.ts
|
|
2724
2732
|
function toDisplayStatus(status) {
|
|
2725
2733
|
if (status === "ok") return "success";
|
|
@@ -3773,12 +3781,12 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3773
3781
|
handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
|
|
3774
3782
|
);
|
|
3775
3783
|
const ordered = [...runs].sort(compareRuns);
|
|
3776
|
-
const
|
|
3784
|
+
const path41 = [];
|
|
3777
3785
|
const visited = /* @__PURE__ */ new Set();
|
|
3778
3786
|
const pushRun = (run, confidence, source) => {
|
|
3779
3787
|
if (visited.has(run.runId)) return;
|
|
3780
3788
|
visited.add(run.runId);
|
|
3781
|
-
|
|
3789
|
+
path41.push({
|
|
3782
3790
|
runId: run.runId,
|
|
3783
3791
|
name: run.name,
|
|
3784
3792
|
startedAt: run.startedAt,
|
|
@@ -3803,7 +3811,7 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3803
3811
|
const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
|
|
3804
3812
|
pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
|
|
3805
3813
|
}
|
|
3806
|
-
return
|
|
3814
|
+
return path41;
|
|
3807
3815
|
}
|
|
3808
3816
|
function metaRunIdMatches(run, token, runById) {
|
|
3809
3817
|
const meta2 = extractSessionWorkflowMetadata(run.metadata);
|
|
@@ -4132,7 +4140,7 @@ var init_summary = __esm({
|
|
|
4132
4140
|
});
|
|
4133
4141
|
function sanitizeBundleRunId(runId) {
|
|
4134
4142
|
let safe = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
|
|
4135
|
-
safe =
|
|
4143
|
+
safe = path30__default.default.basename(safe);
|
|
4136
4144
|
safe = safe.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
4137
4145
|
if (safe === "" || safe === "." || safe === "..") {
|
|
4138
4146
|
safe = "run_unknown";
|
|
@@ -4142,12 +4150,12 @@ function sanitizeBundleRunId(runId) {
|
|
|
4142
4150
|
function bundleRunAssetRelativePath(runId, extension) {
|
|
4143
4151
|
const safe = sanitizeBundleRunId(runId);
|
|
4144
4152
|
const ext = extension.startsWith(".") ? extension : `.${extension}`;
|
|
4145
|
-
return
|
|
4153
|
+
return path30__default.default.posix.join("assets", "runs", `${safe}${ext}`);
|
|
4146
4154
|
}
|
|
4147
4155
|
function assertBundlePathContained(outputDir, relativePath) {
|
|
4148
|
-
const base =
|
|
4149
|
-
const resolved =
|
|
4150
|
-
if (resolved !== base && !resolved.startsWith(base +
|
|
4156
|
+
const base = path30__default.default.resolve(outputDir);
|
|
4157
|
+
const resolved = path30__default.default.resolve(base, relativePath);
|
|
4158
|
+
if (resolved !== base && !resolved.startsWith(base + path30__default.default.sep)) {
|
|
4151
4159
|
throw new Error(`Bundle path escapes output directory: ${relativePath}`);
|
|
4152
4160
|
}
|
|
4153
4161
|
return resolved;
|
|
@@ -4157,7 +4165,7 @@ function normalizeBundleOutputPath(out, options) {
|
|
|
4157
4165
|
if (trimmed === "") {
|
|
4158
4166
|
throw new Error("--out requires a non-empty path.");
|
|
4159
4167
|
}
|
|
4160
|
-
const resolved =
|
|
4168
|
+
const resolved = path30__default.default.resolve(trimmed);
|
|
4161
4169
|
if (options?.preserveZipExtension !== true && resolved.toLowerCase().endsWith(".zip")) {
|
|
4162
4170
|
return resolved.slice(0, -4);
|
|
4163
4171
|
}
|
|
@@ -4166,7 +4174,7 @@ function normalizeBundleOutputPath(out, options) {
|
|
|
4166
4174
|
function defaultBundleOutputPath(runIds) {
|
|
4167
4175
|
const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
|
|
4168
4176
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4169
|
-
return
|
|
4177
|
+
return path30__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
|
|
4170
4178
|
}
|
|
4171
4179
|
var init_paths = __esm({
|
|
4172
4180
|
"packages/core/src/bundle/paths.ts"() {
|
|
@@ -4229,7 +4237,7 @@ function assertEvidenceRelativePath(relativePath) {
|
|
|
4229
4237
|
throw new Error("Evidence file path must be a non-empty relative path.");
|
|
4230
4238
|
}
|
|
4231
4239
|
const trimmed = relativePath.trim().replaceAll("\\", "/");
|
|
4232
|
-
if (
|
|
4240
|
+
if (path30__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
|
|
4233
4241
|
throw new Error(`Evidence file path must be relative: ${relativePath}`);
|
|
4234
4242
|
}
|
|
4235
4243
|
const parts = trimmed.split("/").filter((part) => part !== "");
|
|
@@ -5095,13 +5103,13 @@ function pairSteps(left, right) {
|
|
|
5095
5103
|
return pairs;
|
|
5096
5104
|
}
|
|
5097
5105
|
function compareLeafSteps(L, R, segments, opts, out) {
|
|
5098
|
-
const
|
|
5106
|
+
const path41 = buildPath(segments);
|
|
5099
5107
|
if (L.name !== R.name) {
|
|
5100
5108
|
out.push({
|
|
5101
5109
|
kind: "structure",
|
|
5102
5110
|
severity: "warning",
|
|
5103
5111
|
message: "Step name differs",
|
|
5104
|
-
path:
|
|
5112
|
+
path: path41,
|
|
5105
5113
|
left: L.name,
|
|
5106
5114
|
right: R.name
|
|
5107
5115
|
});
|
|
@@ -5111,7 +5119,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5111
5119
|
kind: "step-type",
|
|
5112
5120
|
severity: "warning",
|
|
5113
5121
|
message: "Step type differs",
|
|
5114
|
-
path:
|
|
5122
|
+
path: path41,
|
|
5115
5123
|
left: L.type,
|
|
5116
5124
|
right: R.type
|
|
5117
5125
|
});
|
|
@@ -5121,7 +5129,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5121
5129
|
kind: "step-status",
|
|
5122
5130
|
severity: "warning",
|
|
5123
5131
|
message: "Step status differs",
|
|
5124
|
-
path:
|
|
5132
|
+
path: path41,
|
|
5125
5133
|
left: L.status,
|
|
5126
5134
|
right: R.status
|
|
5127
5135
|
});
|
|
@@ -5133,7 +5141,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5133
5141
|
kind: "error",
|
|
5134
5142
|
severity: "error",
|
|
5135
5143
|
message: "Step error message differs",
|
|
5136
|
-
path:
|
|
5144
|
+
path: path41,
|
|
5137
5145
|
left: le || void 0,
|
|
5138
5146
|
right: re || void 0
|
|
5139
5147
|
});
|
|
@@ -5151,7 +5159,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5151
5159
|
kind: "duration",
|
|
5152
5160
|
severity: "info",
|
|
5153
5161
|
message: "Step duration differs",
|
|
5154
|
-
path:
|
|
5162
|
+
path: path41,
|
|
5155
5163
|
left: ld,
|
|
5156
5164
|
right: rd
|
|
5157
5165
|
});
|
|
@@ -5164,7 +5172,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5164
5172
|
kind: "metadata",
|
|
5165
5173
|
severity: "info",
|
|
5166
5174
|
message: "Step metadata differs",
|
|
5167
|
-
path:
|
|
5175
|
+
path: path41,
|
|
5168
5176
|
left: L.metadata,
|
|
5169
5177
|
right: R.metadata
|
|
5170
5178
|
});
|
|
@@ -5176,7 +5184,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5176
5184
|
kind: "output",
|
|
5177
5185
|
severity: "info",
|
|
5178
5186
|
message: "Output preview differs",
|
|
5179
|
-
path:
|
|
5187
|
+
path: path41,
|
|
5180
5188
|
left: L.outputPreview,
|
|
5181
5189
|
right: R.outputPreview
|
|
5182
5190
|
});
|
|
@@ -5343,11 +5351,11 @@ var init_engine = __esm({
|
|
|
5343
5351
|
});
|
|
5344
5352
|
|
|
5345
5353
|
// packages/core/src/diff/renderer.ts
|
|
5346
|
-
function formatPath(
|
|
5347
|
-
if (
|
|
5354
|
+
function formatPath(path41) {
|
|
5355
|
+
if (path41 === void 0 || path41.path.length === 0) {
|
|
5348
5356
|
return "(run)";
|
|
5349
5357
|
}
|
|
5350
|
-
return
|
|
5358
|
+
return path41.path.map((s) => s.name).join(" > ");
|
|
5351
5359
|
}
|
|
5352
5360
|
function formatValue(v, verbose) {
|
|
5353
5361
|
if (v === void 0) return "(undefined)";
|
|
@@ -5727,11 +5735,11 @@ async function listFilesRecursive(root) {
|
|
|
5727
5735
|
async function walk(dir) {
|
|
5728
5736
|
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
5729
5737
|
for (const entry of entries) {
|
|
5730
|
-
const abs =
|
|
5738
|
+
const abs = path30__default.default.join(dir, entry.name);
|
|
5731
5739
|
if (entry.isDirectory()) {
|
|
5732
5740
|
await walk(abs);
|
|
5733
5741
|
} else if (entry.isFile()) {
|
|
5734
|
-
const rel =
|
|
5742
|
+
const rel = path30__default.default.relative(root, abs).split(path30__default.default.sep).join("/");
|
|
5735
5743
|
out.push(rel);
|
|
5736
5744
|
}
|
|
5737
5745
|
}
|
|
@@ -5741,7 +5749,7 @@ async function listFilesRecursive(root) {
|
|
|
5741
5749
|
}
|
|
5742
5750
|
async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
5743
5751
|
const unexpectedMode = options.unexpectedFiles ?? "fail";
|
|
5744
|
-
const root =
|
|
5752
|
+
const root = path30__default.default.resolve(rootPath);
|
|
5745
5753
|
const issues = [];
|
|
5746
5754
|
let rootStat;
|
|
5747
5755
|
try {
|
|
@@ -5771,7 +5779,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
|
5771
5779
|
checkedFiles: 0
|
|
5772
5780
|
};
|
|
5773
5781
|
}
|
|
5774
|
-
const manifestPath =
|
|
5782
|
+
const manifestPath = path30__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
|
|
5775
5783
|
let manifestText;
|
|
5776
5784
|
try {
|
|
5777
5785
|
manifestText = await promises.readFile(manifestPath, "utf-8");
|
|
@@ -5857,7 +5865,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
|
5857
5865
|
continue;
|
|
5858
5866
|
}
|
|
5859
5867
|
listed.add(rel);
|
|
5860
|
-
const abs =
|
|
5868
|
+
const abs = path30__default.default.join(root, ...rel.split("/"));
|
|
5861
5869
|
let bytes;
|
|
5862
5870
|
try {
|
|
5863
5871
|
bytes = await promises.readFile(abs);
|
|
@@ -6171,7 +6179,7 @@ function normalizeSuiteConfig(value) {
|
|
|
6171
6179
|
}
|
|
6172
6180
|
async function validateSuiteConfig(config, options) {
|
|
6173
6181
|
const diagnostics = [];
|
|
6174
|
-
const tracesDir =
|
|
6182
|
+
const tracesDir = path30__default.default.resolve(options.configDir, config.traces);
|
|
6175
6183
|
try {
|
|
6176
6184
|
await promises.access(tracesDir);
|
|
6177
6185
|
} catch {
|
|
@@ -6181,7 +6189,7 @@ async function validateSuiteConfig(config, options) {
|
|
|
6181
6189
|
}
|
|
6182
6190
|
for (const suiteCase of config.cases) {
|
|
6183
6191
|
if (suiteCase.input !== void 0) {
|
|
6184
|
-
const inputPath =
|
|
6192
|
+
const inputPath = path30__default.default.resolve(options.configDir, suiteCase.input);
|
|
6185
6193
|
try {
|
|
6186
6194
|
await promises.access(inputPath);
|
|
6187
6195
|
} catch {
|
|
@@ -6214,12 +6222,12 @@ async function fileExists(filePath) {
|
|
|
6214
6222
|
}
|
|
6215
6223
|
}
|
|
6216
6224
|
async function resolveSuiteConfigPath(options = {}) {
|
|
6217
|
-
const cwd =
|
|
6225
|
+
const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
|
|
6218
6226
|
if (options.configPath !== void 0 && options.configPath.trim() !== "") {
|
|
6219
|
-
return
|
|
6227
|
+
return path30__default.default.resolve(cwd, options.configPath.trim());
|
|
6220
6228
|
}
|
|
6221
6229
|
for (const name of DEFAULT_SUITE_CONFIG_NAMES) {
|
|
6222
|
-
const candidate =
|
|
6230
|
+
const candidate = path30__default.default.join(cwd, name);
|
|
6223
6231
|
if (await fileExists(candidate)) return candidate;
|
|
6224
6232
|
}
|
|
6225
6233
|
throw new Error(
|
|
@@ -6236,7 +6244,7 @@ async function loadSuiteConfig(options = {}) {
|
|
|
6236
6244
|
diagnostics: [diagnostic2("AI_SUITE_CONFIG_LOAD_FAILED", message)]
|
|
6237
6245
|
});
|
|
6238
6246
|
}
|
|
6239
|
-
const extension =
|
|
6247
|
+
const extension = path30__default.default.extname(configPath);
|
|
6240
6248
|
if (TS_CONFIG_EXTENSIONS.has(extension)) {
|
|
6241
6249
|
const message = "TypeScript suite configs require an explicit precompiled JavaScript config or future --config-loader support.";
|
|
6242
6250
|
throw Object.assign(new Error(message), {
|
|
@@ -6261,7 +6269,7 @@ async function loadSuiteConfig(options = {}) {
|
|
|
6261
6269
|
return {
|
|
6262
6270
|
config,
|
|
6263
6271
|
configPath,
|
|
6264
|
-
configDir:
|
|
6272
|
+
configDir: path30__default.default.dirname(configPath)
|
|
6265
6273
|
};
|
|
6266
6274
|
} catch (error) {
|
|
6267
6275
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -6311,7 +6319,7 @@ async function exists(filePath) {
|
|
|
6311
6319
|
}
|
|
6312
6320
|
async function resolveSuiteCaseTrace(suiteCase, options) {
|
|
6313
6321
|
if (suiteCase.trace !== void 0) {
|
|
6314
|
-
const tracePath =
|
|
6322
|
+
const tracePath = path30__default.default.resolve(options.configDir, suiteCase.trace);
|
|
6315
6323
|
if (await exists(tracePath)) {
|
|
6316
6324
|
return { caseId: suiteCase.id, tracePath, missing: false };
|
|
6317
6325
|
}
|
|
@@ -6327,7 +6335,7 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
|
|
|
6327
6335
|
if (await exists(directPath)) {
|
|
6328
6336
|
return { caseId: suiteCase.id, tracePath: directPath, runId: runKey, missing: false };
|
|
6329
6337
|
}
|
|
6330
|
-
const nestedPath =
|
|
6338
|
+
const nestedPath = path30__default.default.join(options.tracesDir, `${path30__default.default.basename(runKey)}.jsonl`);
|
|
6331
6339
|
if (await exists(nestedPath)) {
|
|
6332
6340
|
return { caseId: suiteCase.id, tracePath: nestedPath, runId: runKey, missing: false };
|
|
6333
6341
|
}
|
|
@@ -6569,7 +6577,7 @@ function stripPrefix(name, prefixes) {
|
|
|
6569
6577
|
}
|
|
6570
6578
|
return name;
|
|
6571
6579
|
}
|
|
6572
|
-
function eventEvidence(event,
|
|
6580
|
+
function eventEvidence(event, path41) {
|
|
6573
6581
|
return {
|
|
6574
6582
|
runId: event.runId,
|
|
6575
6583
|
eventId: event.eventId,
|
|
@@ -6579,7 +6587,7 @@ function eventEvidence(event, path40) {
|
|
|
6579
6587
|
kind: event.kind,
|
|
6580
6588
|
name: event.name,
|
|
6581
6589
|
status: event.status,
|
|
6582
|
-
...
|
|
6590
|
+
...path41 ? { path: path41 } : {}
|
|
6583
6591
|
};
|
|
6584
6592
|
}
|
|
6585
6593
|
function runEvidence(run) {
|
|
@@ -6646,9 +6654,9 @@ function eventEndMs(event) {
|
|
|
6646
6654
|
function normalizedKey(value) {
|
|
6647
6655
|
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
6648
6656
|
}
|
|
6649
|
-
function lastPathSegment(
|
|
6650
|
-
const parts =
|
|
6651
|
-
return parts[parts.length - 1] ??
|
|
6657
|
+
function lastPathSegment(path41) {
|
|
6658
|
+
const parts = path41.split(".");
|
|
6659
|
+
return parts[parts.length - 1] ?? path41;
|
|
6652
6660
|
}
|
|
6653
6661
|
function valueType(value) {
|
|
6654
6662
|
if (Array.isArray(value)) return "array";
|
|
@@ -6662,12 +6670,12 @@ function serializedByteLength(value) {
|
|
|
6662
6670
|
return void 0;
|
|
6663
6671
|
}
|
|
6664
6672
|
}
|
|
6665
|
-
function pushValueEntries(entries, event, value,
|
|
6666
|
-
entries.push({ event, path:
|
|
6673
|
+
function pushValueEntries(entries, event, value, path41, key, depth = 0) {
|
|
6674
|
+
entries.push({ event, path: path41, key, value });
|
|
6667
6675
|
if (depth >= 8) return;
|
|
6668
6676
|
if (Array.isArray(value)) {
|
|
6669
6677
|
for (const [index, item] of value.entries()) {
|
|
6670
|
-
pushValueEntries(entries, event, item, `${
|
|
6678
|
+
pushValueEntries(entries, event, item, `${path41}.${index}`, String(index), depth + 1);
|
|
6671
6679
|
}
|
|
6672
6680
|
return;
|
|
6673
6681
|
}
|
|
@@ -6677,7 +6685,7 @@ function pushValueEntries(entries, event, value, path40, key, depth = 0) {
|
|
|
6677
6685
|
entries,
|
|
6678
6686
|
event,
|
|
6679
6687
|
value[nestedKey],
|
|
6680
|
-
`${
|
|
6688
|
+
`${path41}.${nestedKey}`,
|
|
6681
6689
|
nestedKey,
|
|
6682
6690
|
depth + 1
|
|
6683
6691
|
);
|
|
@@ -6718,18 +6726,18 @@ function isRawContentKey(key, forbiddenKeys) {
|
|
|
6718
6726
|
const normalized = normalizedKey(key);
|
|
6719
6727
|
return forbiddenKeys.some((forbidden) => normalized === normalizedKey(forbidden));
|
|
6720
6728
|
}
|
|
6721
|
-
function isSafeRawContentMetricPath(
|
|
6722
|
-
const leaf = normalizedKey(key ?? lastPathSegment(
|
|
6729
|
+
function isSafeRawContentMetricPath(path41, key, safePathPrefixes) {
|
|
6730
|
+
const leaf = normalizedKey(key ?? lastPathSegment(path41));
|
|
6723
6731
|
if (!SAFE_USAGE_LEAF_KEYS.has(leaf)) return false;
|
|
6724
|
-
const parts =
|
|
6732
|
+
const parts = path41.split(".").filter(Boolean);
|
|
6725
6733
|
if (parts.length < 2) return false;
|
|
6726
6734
|
const parent = parts[parts.length - 2] ?? "";
|
|
6727
6735
|
const parentNorm = normalizedKey(parent);
|
|
6728
6736
|
return safePathPrefixes.some((prefix) => parentNorm === normalizedKey(prefix));
|
|
6729
6737
|
}
|
|
6730
|
-
function isRawContentPath(
|
|
6731
|
-
if (isSafeRawContentMetricPath(
|
|
6732
|
-
return isRawContentKey(key ?? lastPathSegment(
|
|
6738
|
+
function isRawContentPath(path41, key, forbiddenKeys, safePathPrefixes) {
|
|
6739
|
+
if (isSafeRawContentMetricPath(path41, key, safePathPrefixes)) return false;
|
|
6740
|
+
return isRawContentKey(key ?? lastPathSegment(path41), forbiddenKeys);
|
|
6733
6741
|
}
|
|
6734
6742
|
function parentMarkedUnresolved(event) {
|
|
6735
6743
|
if (booleanAttr(event, [
|
|
@@ -6771,9 +6779,9 @@ function eventDurationMs(event) {
|
|
|
6771
6779
|
}
|
|
6772
6780
|
function treeShape(nodes) {
|
|
6773
6781
|
const lines = [];
|
|
6774
|
-
const visit = (node,
|
|
6775
|
-
lines.push(`${
|
|
6776
|
-
node.children.forEach((child, index) => visit(child, `${
|
|
6782
|
+
const visit = (node, path41) => {
|
|
6783
|
+
lines.push(`${path41}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
|
|
6784
|
+
node.children.forEach((child, index) => visit(child, `${path41}.${index}`));
|
|
6777
6785
|
};
|
|
6778
6786
|
nodes.forEach((node, index) => visit(node, String(index)));
|
|
6779
6787
|
return lines;
|
|
@@ -6822,9 +6830,9 @@ function retrievalShape(context) {
|
|
|
6822
6830
|
function guardrailShape(context) {
|
|
6823
6831
|
return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
|
|
6824
6832
|
}
|
|
6825
|
-
function firstEvidenceForKind(context, kind,
|
|
6833
|
+
function firstEvidenceForKind(context, kind, path41) {
|
|
6826
6834
|
const event = context.events.find((candidate) => candidate.kind === kind);
|
|
6827
|
-
return event ? [eventEvidence(event,
|
|
6835
|
+
return event ? [eventEvidence(event, path41)] : runEvidence(context.selectedRun);
|
|
6828
6836
|
}
|
|
6829
6837
|
function baselineDiffFinding(message, evidence, expected, actual) {
|
|
6830
6838
|
return failFinding("baseline.regression", message, evidence, expected, actual);
|
|
@@ -7174,13 +7182,13 @@ function createStructureCycleRule() {
|
|
|
7174
7182
|
const seenCycles = /* @__PURE__ */ new Set();
|
|
7175
7183
|
const findings = [];
|
|
7176
7184
|
for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
|
|
7177
|
-
const
|
|
7185
|
+
const path41 = [];
|
|
7178
7186
|
const seenAt = /* @__PURE__ */ new Map();
|
|
7179
7187
|
let current = event;
|
|
7180
7188
|
while (current) {
|
|
7181
7189
|
const existing = seenAt.get(current.eventId);
|
|
7182
7190
|
if (existing !== void 0) {
|
|
7183
|
-
const cycle =
|
|
7191
|
+
const cycle = path41.slice(existing);
|
|
7184
7192
|
const key = cycle.map((item) => item.eventId).sort().join("\0");
|
|
7185
7193
|
if (!seenCycles.has(key)) {
|
|
7186
7194
|
seenCycles.add(key);
|
|
@@ -7196,8 +7204,8 @@ function createStructureCycleRule() {
|
|
|
7196
7204
|
}
|
|
7197
7205
|
break;
|
|
7198
7206
|
}
|
|
7199
|
-
seenAt.set(current.eventId,
|
|
7200
|
-
|
|
7207
|
+
seenAt.set(current.eventId, path41.length);
|
|
7208
|
+
path41.push(current);
|
|
7201
7209
|
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
7202
7210
|
}
|
|
7203
7211
|
}
|
|
@@ -8420,7 +8428,7 @@ function findReaderByFormat(format, readers) {
|
|
|
8420
8428
|
}
|
|
8421
8429
|
async function jsonlFilesInDirectory(dirPath) {
|
|
8422
8430
|
const entries = await promises.readdir(dirPath, { withFileTypes: true });
|
|
8423
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) =>
|
|
8431
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path30__default.default.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
|
|
8424
8432
|
}
|
|
8425
8433
|
async function resolveInput(input3) {
|
|
8426
8434
|
const cached2 = resolvedInputCache.get(input3);
|
|
@@ -10119,7 +10127,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
10119
10127
|
async function runSuite(options = {}) {
|
|
10120
10128
|
const startedAt = new Date(options.nowMs ?? Date.now()).toISOString();
|
|
10121
10129
|
const { config, configPath, configDir } = await loadSuiteConfig(options);
|
|
10122
|
-
const tracesDir =
|
|
10130
|
+
const tracesDir = path30__default.default.resolve(configDir, config.traces);
|
|
10123
10131
|
const cases = [];
|
|
10124
10132
|
const diagnostics = [];
|
|
10125
10133
|
for (const suiteCase of config.cases) {
|
|
@@ -11146,7 +11154,7 @@ function validateOptions(options) {
|
|
|
11146
11154
|
}
|
|
11147
11155
|
function isConfigLoadError(error) {
|
|
11148
11156
|
if (!(error instanceof Error)) return false;
|
|
11149
|
-
const ext =
|
|
11157
|
+
const ext = path30__default.default.extname(error.message);
|
|
11150
11158
|
if (error.message.includes("Unsupported suite config extension")) return true;
|
|
11151
11159
|
if (error.message.includes("TypeScript suite configs require")) return true;
|
|
11152
11160
|
if (error.message.includes("No suite config found")) return true;
|
|
@@ -11403,6 +11411,7 @@ var init_advanced = __esm({
|
|
|
11403
11411
|
init_trace_filter();
|
|
11404
11412
|
init_timeline();
|
|
11405
11413
|
init_what();
|
|
11414
|
+
init_causal_failure();
|
|
11406
11415
|
init_explain();
|
|
11407
11416
|
init_stats();
|
|
11408
11417
|
init_search();
|
|
@@ -11539,8 +11548,8 @@ var init_load_sqlite = __esm({
|
|
|
11539
11548
|
}
|
|
11540
11549
|
});
|
|
11541
11550
|
function resolveIndexDbPath(traceDir, dbPath) {
|
|
11542
|
-
if (dbPath && dbPath.trim() !== "") return
|
|
11543
|
-
return
|
|
11551
|
+
if (dbPath && dbPath.trim() !== "") return path30__default.default.resolve(dbPath);
|
|
11552
|
+
return path30__default.default.join(path30__default.default.resolve(traceDir), INDEX_DB_FILENAME);
|
|
11544
11553
|
}
|
|
11545
11554
|
function str(value) {
|
|
11546
11555
|
return typeof value === "string" && value !== "" ? value : null;
|
|
@@ -11632,7 +11641,7 @@ async function buildIndex(options = {}) {
|
|
|
11632
11641
|
warnings.push(`index.unreadable: ${file}`);
|
|
11633
11642
|
}
|
|
11634
11643
|
}
|
|
11635
|
-
await promises.mkdir(
|
|
11644
|
+
await promises.mkdir(path30__default.default.dirname(dbPath), { recursive: true });
|
|
11636
11645
|
await promises.rm(dbPath, { force: true });
|
|
11637
11646
|
const Sqlite = loadBetterSqlite3();
|
|
11638
11647
|
const db = new Sqlite(dbPath);
|
|
@@ -11880,7 +11889,7 @@ var init_src = __esm({
|
|
|
11880
11889
|
});
|
|
11881
11890
|
|
|
11882
11891
|
// package.json
|
|
11883
|
-
var version = "6.
|
|
11892
|
+
var version = "6.12.0";
|
|
11884
11893
|
|
|
11885
11894
|
// packages/cli/src/list.ts
|
|
11886
11895
|
init_advanced();
|
|
@@ -14902,9 +14911,9 @@ Trace directory: ${traceDir}`);
|
|
|
14902
14911
|
process.exitCode = 1;
|
|
14903
14912
|
}
|
|
14904
14913
|
const resolvedOutput = resolveOutputOption(options);
|
|
14905
|
-
const outPath = resolvedOutput !== void 0 ?
|
|
14914
|
+
const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
|
|
14906
14915
|
if (outPath !== void 0) {
|
|
14907
|
-
await promises.mkdir(
|
|
14916
|
+
await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
|
|
14908
14917
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
14909
14918
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
14910
14919
|
console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
|
|
@@ -15263,7 +15272,7 @@ function indexedToMetadata(row, traceDir) {
|
|
|
15263
15272
|
endedAt: row.endedAt ?? void 0,
|
|
15264
15273
|
durationMs: row.durationMs ?? void 0,
|
|
15265
15274
|
eventCount: 0,
|
|
15266
|
-
filePath:
|
|
15275
|
+
filePath: path30__default.default.join(traceDir, row.file),
|
|
15267
15276
|
fileSize: 0,
|
|
15268
15277
|
createdAt: new Date(row.mtimeMs)
|
|
15269
15278
|
};
|
|
@@ -15745,9 +15754,9 @@ async function reportCommand(runId, options = {}) {
|
|
|
15745
15754
|
...options.section ? { section: options.section } : {}
|
|
15746
15755
|
});
|
|
15747
15756
|
const resolvedOutput = resolveOutputOption(options);
|
|
15748
|
-
const outPath = resolvedOutput !== void 0 ?
|
|
15757
|
+
const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
|
|
15749
15758
|
if (outPath !== void 0) {
|
|
15750
|
-
await promises.mkdir(
|
|
15759
|
+
await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
|
|
15751
15760
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
15752
15761
|
console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
|
|
15753
15762
|
}
|
|
@@ -15876,8 +15885,8 @@ function passesLuhn(value) {
|
|
|
15876
15885
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
15877
15886
|
var EPOCH_MS_RE = /^1[0-9]{12}$/;
|
|
15878
15887
|
var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
15879
|
-
function pathSuggestsNonCard(
|
|
15880
|
-
const normalized =
|
|
15888
|
+
function pathSuggestsNonCard(path41) {
|
|
15889
|
+
const normalized = path41.toLowerCase().replace(/[^a-z0-9._]/g, "");
|
|
15881
15890
|
return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
|
|
15882
15891
|
normalized
|
|
15883
15892
|
) || /(^|\.)ts(\.|$)/.test(normalized);
|
|
@@ -16064,17 +16073,17 @@ function applyRule(rule, value, replacement) {
|
|
|
16064
16073
|
}
|
|
16065
16074
|
return value;
|
|
16066
16075
|
}
|
|
16067
|
-
function childPath(
|
|
16076
|
+
function childPath(path41, key) {
|
|
16068
16077
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
16069
|
-
return
|
|
16078
|
+
return path41 ? `${path41}.${key}` : key;
|
|
16070
16079
|
}
|
|
16071
|
-
return `${
|
|
16080
|
+
return `${path41 || "$"}[${JSON.stringify(key)}]`;
|
|
16072
16081
|
}
|
|
16073
|
-
function indexPath(
|
|
16074
|
-
return `${
|
|
16082
|
+
function indexPath(path41, index) {
|
|
16083
|
+
return `${path41 || "$"}[${index}]`;
|
|
16075
16084
|
}
|
|
16076
|
-
function makeFinding(
|
|
16077
|
-
return preview === void 0 ? { path:
|
|
16085
|
+
function makeFinding(path41, detector, action, matchKind, severity = "warning", preview) {
|
|
16086
|
+
return preview === void 0 ? { path: path41, detector, action, severity, matchKind } : { path: path41, detector, action, severity, matchKind, preview };
|
|
16078
16087
|
}
|
|
16079
16088
|
function createRedactionProfile(profile = "local") {
|
|
16080
16089
|
switch (profile) {
|
|
@@ -16143,11 +16152,11 @@ var Redactor2 = class {
|
|
|
16143
16152
|
#recordFinding(state, finding) {
|
|
16144
16153
|
if (this.#collectFindings) state.findings.push(finding);
|
|
16145
16154
|
}
|
|
16146
|
-
#redactValue(value, key,
|
|
16155
|
+
#redactValue(value, key, path41, depth, state) {
|
|
16147
16156
|
if (depth > this.#maxDepth) {
|
|
16148
16157
|
this.#recordFinding(
|
|
16149
16158
|
state,
|
|
16150
|
-
makeFinding(
|
|
16159
|
+
makeFinding(path41, "structure.maxDepth", "truncate", "value", "warning")
|
|
16151
16160
|
);
|
|
16152
16161
|
return "[Truncated]";
|
|
16153
16162
|
}
|
|
@@ -16156,19 +16165,19 @@ var Redactor2 = class {
|
|
|
16156
16165
|
if (rule) {
|
|
16157
16166
|
this.#recordFinding(
|
|
16158
16167
|
state,
|
|
16159
|
-
makeFinding(
|
|
16168
|
+
makeFinding(path41, `key.${rule.key}`, actionForRule(rule), "key", "warning")
|
|
16160
16169
|
);
|
|
16161
16170
|
return applyRule(rule, value, this.#replacement);
|
|
16162
16171
|
}
|
|
16163
16172
|
}
|
|
16164
16173
|
for (const detector of this.#detectors) {
|
|
16165
|
-
const detections = detector.detect({ path:
|
|
16174
|
+
const detections = detector.detect({ path: path41, key, value });
|
|
16166
16175
|
for (const detection of detections) {
|
|
16167
16176
|
const action = detection.action ?? "replace";
|
|
16168
16177
|
this.#recordFinding(
|
|
16169
16178
|
state,
|
|
16170
16179
|
makeFinding(
|
|
16171
|
-
|
|
16180
|
+
path41,
|
|
16172
16181
|
detector.id,
|
|
16173
16182
|
action,
|
|
16174
16183
|
detection.matchKind ?? detector.matchKind ?? "custom",
|
|
@@ -16186,7 +16195,7 @@ var Redactor2 = class {
|
|
|
16186
16195
|
const out = [];
|
|
16187
16196
|
state.seen.set(value, out);
|
|
16188
16197
|
value.forEach((item, index) => {
|
|
16189
|
-
out[index] = this.#redactValue(item, void 0, indexPath(
|
|
16198
|
+
out[index] = this.#redactValue(item, void 0, indexPath(path41, index), depth + 1, state);
|
|
16190
16199
|
});
|
|
16191
16200
|
return out;
|
|
16192
16201
|
}
|
|
@@ -16198,7 +16207,7 @@ var Redactor2 = class {
|
|
|
16198
16207
|
out[entryKey] = this.#redactValue(
|
|
16199
16208
|
entryValue,
|
|
16200
16209
|
entryKey,
|
|
16201
|
-
childPath(
|
|
16210
|
+
childPath(path41 === "$" ? "" : path41, entryKey),
|
|
16202
16211
|
depth + 1,
|
|
16203
16212
|
state
|
|
16204
16213
|
);
|
|
@@ -16669,14 +16678,14 @@ function uniqueSorted(values) {
|
|
|
16669
16678
|
return [...new Set(values)].sort();
|
|
16670
16679
|
}
|
|
16671
16680
|
function isWithinDirectory(child, parent) {
|
|
16672
|
-
const relative =
|
|
16673
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
16681
|
+
const relative = path30__default.default.relative(parent, child);
|
|
16682
|
+
return relative === "" || !relative.startsWith("..") && !path30__default.default.isAbsolute(relative);
|
|
16674
16683
|
}
|
|
16675
16684
|
async function resolveOutputPath(inputPath, output2, force) {
|
|
16676
16685
|
if (output2 === void 0 || output2.trim() === "") return void 0;
|
|
16677
|
-
const inputAbs =
|
|
16678
|
-
const outputAbs =
|
|
16679
|
-
const inputDir =
|
|
16686
|
+
const inputAbs = path30__default.default.resolve(inputPath);
|
|
16687
|
+
const outputAbs = path30__default.default.resolve(output2.trim());
|
|
16688
|
+
const inputDir = path30__default.default.dirname(inputAbs);
|
|
16680
16689
|
if (!isWithinDirectory(outputAbs, inputDir)) {
|
|
16681
16690
|
throw new Error("Refusing to write migrated output outside the input directory.");
|
|
16682
16691
|
}
|
|
@@ -16797,7 +16806,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
16797
16806
|
process.exitCode = 1;
|
|
16798
16807
|
return;
|
|
16799
16808
|
}
|
|
16800
|
-
const inputPath =
|
|
16809
|
+
const inputPath = path30__default.default.resolve(input3.trim());
|
|
16801
16810
|
const dryRun = options.dryRun === true;
|
|
16802
16811
|
if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
|
|
16803
16812
|
console.error("migrate requires --dry-run or --output <path>.");
|
|
@@ -16816,7 +16825,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
16816
16825
|
);
|
|
16817
16826
|
const result = await buildMigration(inputPath, outputPath);
|
|
16818
16827
|
if (!dryRun && outputPath !== void 0) {
|
|
16819
|
-
await promises.mkdir(
|
|
16828
|
+
await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
|
|
16820
16829
|
await promises.writeFile(outputPath, result.content, "utf-8");
|
|
16821
16830
|
}
|
|
16822
16831
|
printSummary2(result, dryRun);
|
|
@@ -17150,23 +17159,23 @@ function evaluatePromptInjection(text, options = {}) {
|
|
|
17150
17159
|
}
|
|
17151
17160
|
return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
|
|
17152
17161
|
}
|
|
17153
|
-
function validateSchemaField(value, field,
|
|
17162
|
+
function validateSchemaField(value, field, path41, evidence) {
|
|
17154
17163
|
const ruleId = "guardrail.structured-output";
|
|
17155
17164
|
if (field.type) {
|
|
17156
17165
|
const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
17157
17166
|
if (actual !== field.type) {
|
|
17158
|
-
evidence.push({ ruleId, path:
|
|
17167
|
+
evidence.push({ ruleId, path: path41, preview: `expected ${field.type}, got ${actual}` });
|
|
17159
17168
|
return;
|
|
17160
17169
|
}
|
|
17161
17170
|
}
|
|
17162
17171
|
if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
|
|
17163
|
-
evidence.push({ ruleId, path:
|
|
17172
|
+
evidence.push({ ruleId, path: path41, preview: "value not in enum" });
|
|
17164
17173
|
}
|
|
17165
17174
|
if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
|
|
17166
17175
|
const record = value;
|
|
17167
17176
|
for (const key of field.required) {
|
|
17168
17177
|
if (!(key in record)) {
|
|
17169
|
-
evidence.push({ ruleId, path: `${
|
|
17178
|
+
evidence.push({ ruleId, path: `${path41}.${key}`, preview: "missing required key" });
|
|
17170
17179
|
}
|
|
17171
17180
|
}
|
|
17172
17181
|
}
|
|
@@ -17493,7 +17502,7 @@ function asConfig(value) {
|
|
|
17493
17502
|
}
|
|
17494
17503
|
async function loadConfig(configPath) {
|
|
17495
17504
|
if (configPath === void 0) return {};
|
|
17496
|
-
const extension =
|
|
17505
|
+
const extension = path30__default.default.extname(configPath);
|
|
17497
17506
|
if (TS_CONFIG_EXTENSIONS2.has(extension)) {
|
|
17498
17507
|
throw new Error(
|
|
17499
17508
|
"TypeScript check configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
@@ -17502,7 +17511,7 @@ async function loadConfig(configPath) {
|
|
|
17502
17511
|
if (!CONFIG_EXTENSIONS2.has(extension)) {
|
|
17503
17512
|
throw new Error("Unsupported check config extension. Use .json, .js, .mjs, or .cjs.");
|
|
17504
17513
|
}
|
|
17505
|
-
const absolute =
|
|
17514
|
+
const absolute = path30__default.default.resolve(configPath);
|
|
17506
17515
|
if (extension === ".json") {
|
|
17507
17516
|
const raw = await promises.readFile(absolute, "utf-8");
|
|
17508
17517
|
return asConfig(JSON.parse(raw));
|
|
@@ -17678,10 +17687,10 @@ function printHuman(result) {
|
|
|
17678
17687
|
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
17679
17688
|
}
|
|
17680
17689
|
for (const finding of result.findings) {
|
|
17681
|
-
const
|
|
17690
|
+
const path41 = finding.evidence[0]?.path;
|
|
17682
17691
|
const run = finding.evidence[0]?.runId;
|
|
17683
17692
|
const runPrefix = run ? `[${run}] ` : "";
|
|
17684
|
-
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${
|
|
17693
|
+
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
|
|
17685
17694
|
}
|
|
17686
17695
|
}
|
|
17687
17696
|
function readErrorResult(error) {
|
|
@@ -17949,7 +17958,7 @@ async function loadSuiteViewerData(options) {
|
|
|
17949
17958
|
for (const suiteCase of result.cases) {
|
|
17950
17959
|
cases.push(await enrichCase(suiteCase, baselinePath));
|
|
17951
17960
|
}
|
|
17952
|
-
const artifactsDir =
|
|
17961
|
+
const artifactsDir = path30__default.default.join(path30__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
|
|
17953
17962
|
return {
|
|
17954
17963
|
suiteName: result.suiteName,
|
|
17955
17964
|
configPath: result.configPath,
|
|
@@ -18145,19 +18154,19 @@ function serializeWorkspaceManifest(manifest) {
|
|
|
18145
18154
|
}
|
|
18146
18155
|
var INDEX_DIR_NAME = "index";
|
|
18147
18156
|
function resolveWorkspaceLocation(cwd = process.cwd()) {
|
|
18148
|
-
const projectRoot =
|
|
18149
|
-
const workspaceDir =
|
|
18157
|
+
const projectRoot = path30__default.default.resolve(cwd);
|
|
18158
|
+
const workspaceDir = path30__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
|
|
18150
18159
|
return {
|
|
18151
18160
|
projectRoot,
|
|
18152
18161
|
workspaceDir,
|
|
18153
|
-
manifestPath:
|
|
18162
|
+
manifestPath: path30__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
|
|
18154
18163
|
};
|
|
18155
18164
|
}
|
|
18156
18165
|
function resolveInsideWorkspace(workspaceDir, relative) {
|
|
18157
|
-
const base =
|
|
18158
|
-
const resolved =
|
|
18159
|
-
const rel =
|
|
18160
|
-
if (rel === "" || rel === "." || !rel.startsWith("..") && !
|
|
18166
|
+
const base = path30__default.default.resolve(workspaceDir);
|
|
18167
|
+
const resolved = path30__default.default.resolve(base, relative);
|
|
18168
|
+
const rel = path30__default.default.relative(base, resolved);
|
|
18169
|
+
if (rel === "" || rel === "." || !rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
|
|
18161
18170
|
return resolved;
|
|
18162
18171
|
}
|
|
18163
18172
|
throw new Error(
|
|
@@ -18226,7 +18235,7 @@ async function createWorkspace(options = {}) {
|
|
|
18226
18235
|
created = false;
|
|
18227
18236
|
adopted = true;
|
|
18228
18237
|
} else {
|
|
18229
|
-
const project = options.project?.trim() ||
|
|
18238
|
+
const project = options.project?.trim() || path30__default.default.basename(location.projectRoot) || "workspace";
|
|
18230
18239
|
const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
|
|
18231
18240
|
manifest = createDefaultWorkspaceManifest({
|
|
18232
18241
|
project,
|
|
@@ -18365,7 +18374,7 @@ async function doctorWorkspace(location) {
|
|
|
18365
18374
|
const abs = resolveInsideWorkspace(location.workspaceDir, rel);
|
|
18366
18375
|
for (const file of await listJsonl(abs)) {
|
|
18367
18376
|
try {
|
|
18368
|
-
const s = await promises.stat(
|
|
18377
|
+
const s = await promises.stat(path30__default.default.join(abs, file));
|
|
18369
18378
|
newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
|
|
18370
18379
|
} catch {
|
|
18371
18380
|
checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
|
|
@@ -18413,7 +18422,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
|
|
|
18413
18422
|
const relPath = `${rel}/${entry}`;
|
|
18414
18423
|
removed.push(relPath);
|
|
18415
18424
|
if (!dryRun) {
|
|
18416
|
-
await promises.rm(
|
|
18425
|
+
await promises.rm(path30__default.default.join(abs, entry), { recursive: true, force: true });
|
|
18417
18426
|
}
|
|
18418
18427
|
}
|
|
18419
18428
|
}
|
|
@@ -18422,7 +18431,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
|
|
|
18422
18431
|
|
|
18423
18432
|
// packages/viewer/src/workspace-data.ts
|
|
18424
18433
|
async function loadWorkspaceViewerData(options) {
|
|
18425
|
-
const cwd =
|
|
18434
|
+
const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
|
|
18426
18435
|
const location = resolveWorkspaceLocation(cwd);
|
|
18427
18436
|
const manifestRead = await readWorkspaceManifestFile(location);
|
|
18428
18437
|
if (!manifestRead.ok || manifestRead.manifest === void 0) {
|
|
@@ -18435,7 +18444,7 @@ async function loadWorkspaceViewerData(options) {
|
|
|
18435
18444
|
const runs = [];
|
|
18436
18445
|
for (const rel of manifestRead.manifest.traceDirs) {
|
|
18437
18446
|
const traceDir = resolveTraceDir({
|
|
18438
|
-
dir:
|
|
18447
|
+
dir: path30__default.default.join(location.workspaceDir, rel)
|
|
18439
18448
|
});
|
|
18440
18449
|
const td = new TraceDirectory({ dir: traceDir });
|
|
18441
18450
|
const files = await td.list();
|
|
@@ -18449,7 +18458,7 @@ async function loadWorkspaceViewerData(options) {
|
|
|
18449
18458
|
runId: meta2.runId,
|
|
18450
18459
|
...meta2.name !== void 0 ? { name: meta2.name } : {},
|
|
18451
18460
|
status: meta2.status,
|
|
18452
|
-
file:
|
|
18461
|
+
file: path30__default.default.basename(meta2.filePath)
|
|
18453
18462
|
});
|
|
18454
18463
|
}
|
|
18455
18464
|
}
|
|
@@ -18460,8 +18469,8 @@ async function loadWorkspaceViewerData(options) {
|
|
|
18460
18469
|
doctor,
|
|
18461
18470
|
runs,
|
|
18462
18471
|
bundleDirs: [
|
|
18463
|
-
|
|
18464
|
-
|
|
18472
|
+
path30__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
|
|
18473
|
+
path30__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
|
|
18465
18474
|
]
|
|
18466
18475
|
};
|
|
18467
18476
|
}
|
|
@@ -18524,7 +18533,7 @@ function createViewerServer(options = {}) {
|
|
|
18524
18533
|
ok: true,
|
|
18525
18534
|
readOnly: true,
|
|
18526
18535
|
mode,
|
|
18527
|
-
traceDir:
|
|
18536
|
+
traceDir: path30__default.default.resolve(traceDir)
|
|
18528
18537
|
});
|
|
18529
18538
|
}
|
|
18530
18539
|
if (pathname === "/api/suite" && mode === "suite") {
|
|
@@ -18553,7 +18562,7 @@ function createViewerServer(options = {}) {
|
|
|
18553
18562
|
runId: meta2.runId,
|
|
18554
18563
|
name: meta2.name,
|
|
18555
18564
|
status: meta2.status,
|
|
18556
|
-
file:
|
|
18565
|
+
file: path30__default.default.basename(meta2.filePath),
|
|
18557
18566
|
startedAt: meta2.startedAt,
|
|
18558
18567
|
durationMs: meta2.durationMs
|
|
18559
18568
|
}))
|
|
@@ -18670,7 +18679,7 @@ function startViewerServer(options = {}) {
|
|
|
18670
18679
|
resolve({
|
|
18671
18680
|
host,
|
|
18672
18681
|
port: resolvedPort,
|
|
18673
|
-
traceDir:
|
|
18682
|
+
traceDir: path30__default.default.resolve(traceDir),
|
|
18674
18683
|
url: `http://${host}:${resolvedPort}/${modeQuery}`,
|
|
18675
18684
|
mode
|
|
18676
18685
|
});
|
|
@@ -19041,10 +19050,10 @@ async function evalRun(input3, options = {}) {
|
|
|
19041
19050
|
diagnostics: []
|
|
19042
19051
|
};
|
|
19043
19052
|
}
|
|
19044
|
-
function evidenceForRun(run,
|
|
19045
|
-
return [{ runId: run.runId, ...
|
|
19053
|
+
function evidenceForRun(run, path41) {
|
|
19054
|
+
return [{ runId: run.runId, ...path41 !== void 0 ? { path: path41 } : {} }];
|
|
19046
19055
|
}
|
|
19047
|
-
function evidenceForEvent(event,
|
|
19056
|
+
function evidenceForEvent(event, path41) {
|
|
19048
19057
|
return [
|
|
19049
19058
|
{
|
|
19050
19059
|
runId: event.runId,
|
|
@@ -19052,7 +19061,7 @@ function evidenceForEvent(event, path40) {
|
|
|
19052
19061
|
...event.parentId !== void 0 ? { parentId: event.parentId } : {},
|
|
19053
19062
|
kind: event.kind,
|
|
19054
19063
|
name: event.name,
|
|
19055
|
-
...
|
|
19064
|
+
...path41 !== void 0 ? { path: path41 } : {}
|
|
19056
19065
|
}
|
|
19057
19066
|
];
|
|
19058
19067
|
}
|
|
@@ -19210,9 +19219,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
|
|
|
19210
19219
|
function tokenize(text) {
|
|
19211
19220
|
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));
|
|
19212
19221
|
}
|
|
19213
|
-
function firstEvidence(fields, run,
|
|
19222
|
+
function firstEvidence(fields, run, path41) {
|
|
19214
19223
|
const first = fields[0];
|
|
19215
|
-
return first === void 0 ? evidenceForRun(run,
|
|
19224
|
+
return first === void 0 ? evidenceForRun(run, path41) : evidenceForEvent(first.node.event, first.path);
|
|
19216
19225
|
}
|
|
19217
19226
|
function collectSourceIds(nodes, keys) {
|
|
19218
19227
|
const wanted = keySet(keys);
|
|
@@ -19589,8 +19598,8 @@ function renderEvalMarkdown(result) {
|
|
|
19589
19598
|
if (result.findings.length > 0) {
|
|
19590
19599
|
lines.push("", "## Findings");
|
|
19591
19600
|
for (const finding of result.findings) {
|
|
19592
|
-
const
|
|
19593
|
-
lines.push(`- ${finding.ruleId}: ${finding.message}${
|
|
19601
|
+
const path41 = finding.evidence[0]?.path;
|
|
19602
|
+
lines.push(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
|
|
19594
19603
|
}
|
|
19595
19604
|
}
|
|
19596
19605
|
return `${lines.join("\n")}
|
|
@@ -19637,7 +19646,7 @@ function asConfig2(value) {
|
|
|
19637
19646
|
}
|
|
19638
19647
|
async function loadConfig2(configPath) {
|
|
19639
19648
|
if (configPath === void 0) return {};
|
|
19640
|
-
const extension =
|
|
19649
|
+
const extension = path30__default.default.extname(configPath);
|
|
19641
19650
|
if (TS_CONFIG_EXTENSIONS3.has(extension)) {
|
|
19642
19651
|
throw new Error(
|
|
19643
19652
|
"TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
@@ -19646,7 +19655,7 @@ async function loadConfig2(configPath) {
|
|
|
19646
19655
|
if (!CONFIG_EXTENSIONS3.has(extension)) {
|
|
19647
19656
|
throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
|
|
19648
19657
|
}
|
|
19649
|
-
const absolute =
|
|
19658
|
+
const absolute = path30__default.default.resolve(configPath);
|
|
19650
19659
|
if (extension === ".json") {
|
|
19651
19660
|
const raw = await promises.readFile(absolute, "utf-8");
|
|
19652
19661
|
return asConfig2(JSON.parse(raw));
|
|
@@ -19783,8 +19792,8 @@ function printHuman2(result) {
|
|
|
19783
19792
|
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
19784
19793
|
}
|
|
19785
19794
|
for (const finding of result.findings) {
|
|
19786
|
-
const
|
|
19787
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
19795
|
+
const path41 = finding.evidence[0]?.path;
|
|
19796
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
|
|
19788
19797
|
}
|
|
19789
19798
|
}
|
|
19790
19799
|
function readErrorResult2(error) {
|
|
@@ -20037,14 +20046,14 @@ function exitCodeFor3(result) {
|
|
|
20037
20046
|
return 2;
|
|
20038
20047
|
}
|
|
20039
20048
|
function explainFinding(finding, blocksBundle) {
|
|
20040
|
-
const
|
|
20049
|
+
const path41 = finding.evidence[0]?.path ?? "(unknown path)";
|
|
20041
20050
|
const category = finding.category ?? "structure";
|
|
20042
20051
|
const confidence = finding.confidence ?? "medium";
|
|
20043
20052
|
const detector = finding.detector ?? finding.ruleId;
|
|
20044
20053
|
const action = finding.action ?? "review";
|
|
20045
20054
|
const redactionHint = category === "credential" || category === "personal-data" || category === "raw-content" || action.includes("redact") ? "Usually removable by share/strict redaction before bundling." : "May require omitting the field, lowering limits, or an explicit local override.";
|
|
20046
20055
|
return [
|
|
20047
|
-
` Matched: detector=${detector}; path=${
|
|
20056
|
+
` Matched: detector=${detector}; path=${path41}; category=${category}`,
|
|
20048
20057
|
` Why: ${finding.message}`,
|
|
20049
20058
|
` Confidence: ${confidence}`,
|
|
20050
20059
|
` Redaction: ${redactionHint}`,
|
|
@@ -20086,9 +20095,9 @@ function printHuman3(result, explain = false) {
|
|
|
20086
20095
|
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
20087
20096
|
}
|
|
20088
20097
|
for (const finding of result.findings) {
|
|
20089
|
-
const
|
|
20098
|
+
const path41 = finding.evidence[0]?.path;
|
|
20090
20099
|
const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
|
|
20091
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
20100
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}${taxonomy}`);
|
|
20092
20101
|
if (explain) {
|
|
20093
20102
|
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
20094
20103
|
for (const line of explainFinding(finding, blocks)) {
|
|
@@ -20204,7 +20213,7 @@ function messageStartsWithDash(error) {
|
|
|
20204
20213
|
}
|
|
20205
20214
|
init_advanced();
|
|
20206
20215
|
function validateReporterArtifactPath(options) {
|
|
20207
|
-
const outputDir =
|
|
20216
|
+
const outputDir = path30__default.default.resolve(options.outputDir);
|
|
20208
20217
|
const diagnostics = [];
|
|
20209
20218
|
const rawPath = options.relativePath;
|
|
20210
20219
|
if (rawPath.length === 0) {
|
|
@@ -20224,7 +20233,7 @@ function validateReporterArtifactPath(options) {
|
|
|
20224
20233
|
});
|
|
20225
20234
|
return { ok: false, outputDir, diagnostics };
|
|
20226
20235
|
}
|
|
20227
|
-
if (
|
|
20236
|
+
if (path30__default.default.isAbsolute(rawPath) || path30__default.default.win32.isAbsolute(rawPath)) {
|
|
20228
20237
|
diagnostics.push({
|
|
20229
20238
|
code: "artifact_path_absolute",
|
|
20230
20239
|
severity: "error",
|
|
@@ -20233,7 +20242,7 @@ function validateReporterArtifactPath(options) {
|
|
|
20233
20242
|
});
|
|
20234
20243
|
return { ok: false, outputDir, diagnostics };
|
|
20235
20244
|
}
|
|
20236
|
-
const normalized =
|
|
20245
|
+
const normalized = path30__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
|
|
20237
20246
|
const segments = normalized.split("/");
|
|
20238
20247
|
if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
|
|
20239
20248
|
diagnostics.push({
|
|
@@ -20244,9 +20253,9 @@ function validateReporterArtifactPath(options) {
|
|
|
20244
20253
|
});
|
|
20245
20254
|
return { ok: false, outputDir, diagnostics };
|
|
20246
20255
|
}
|
|
20247
|
-
const absolutePath =
|
|
20248
|
-
const relFromOutput =
|
|
20249
|
-
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") ||
|
|
20256
|
+
const absolutePath = path30__default.default.resolve(outputDir, normalized);
|
|
20257
|
+
const relFromOutput = path30__default.default.relative(outputDir, absolutePath);
|
|
20258
|
+
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path30__default.default.isAbsolute(relFromOutput)) {
|
|
20250
20259
|
diagnostics.push({
|
|
20251
20260
|
code: "artifact_path_escape",
|
|
20252
20261
|
severity: "error",
|
|
@@ -20272,7 +20281,7 @@ var EVIDENCE_CI_ARTIFACT_FILES = [
|
|
|
20272
20281
|
function createEvidenceCiArtifacts(options) {
|
|
20273
20282
|
const profile = options.redactionProfile;
|
|
20274
20283
|
const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
|
|
20275
|
-
const join = (name) => prefix === "" ? name :
|
|
20284
|
+
const join = (name) => prefix === "" ? name : path30__default.default.posix.join(prefix, name);
|
|
20276
20285
|
const formatFor = (name) => {
|
|
20277
20286
|
if (name.endsWith(".html")) return "html";
|
|
20278
20287
|
if (name.endsWith(".jsonl")) return "jsonl";
|
|
@@ -20361,8 +20370,8 @@ function renderCheckSection(result) {
|
|
|
20361
20370
|
`Diagnostics: ${result.diagnostics.length}`
|
|
20362
20371
|
];
|
|
20363
20372
|
for (const finding of result.findings.slice(0, 10)) {
|
|
20364
|
-
const
|
|
20365
|
-
lines.push(`- ${finding.ruleId}: ${finding.message} (${
|
|
20373
|
+
const path41 = finding.evidence[0]?.path ?? "(run)";
|
|
20374
|
+
lines.push(`- ${finding.ruleId}: ${finding.message} (${path41})`);
|
|
20366
20375
|
}
|
|
20367
20376
|
for (const diagnostic7 of result.diagnostics.slice(0, 10)) {
|
|
20368
20377
|
lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
@@ -20440,8 +20449,8 @@ function renderHtml(trace, check, diff) {
|
|
|
20440
20449
|
`;
|
|
20441
20450
|
}
|
|
20442
20451
|
async function writeArtifact(outputDir, relativePath, content, files) {
|
|
20443
|
-
const outPath =
|
|
20444
|
-
await promises.mkdir(
|
|
20452
|
+
const outPath = path30__default.default.join(outputDir, relativePath);
|
|
20453
|
+
await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
|
|
20445
20454
|
await promises.writeFile(outPath, content, "utf-8");
|
|
20446
20455
|
files.push(relativePath);
|
|
20447
20456
|
}
|
|
@@ -20470,7 +20479,7 @@ function shouldWriteEvidence(options, status) {
|
|
|
20470
20479
|
return status === "unsafe" || status === "regression" || status === "unknown" || status === "warning";
|
|
20471
20480
|
}
|
|
20472
20481
|
async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
20473
|
-
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ?
|
|
20482
|
+
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path30__default.default.resolve(options.outputDir.trim()) : "";
|
|
20474
20483
|
if (outputDir === "") {
|
|
20475
20484
|
console.error("--output-dir is required.");
|
|
20476
20485
|
process.exitCode = 1;
|
|
@@ -20598,8 +20607,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
|
20598
20607
|
}
|
|
20599
20608
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
20600
20609
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
20601
|
-
await promises.mkdir(
|
|
20602
|
-
await promises.appendFile(
|
|
20610
|
+
await promises.mkdir(path30__default.default.dirname(path30__default.default.resolve(summaryTarget)), { recursive: true });
|
|
20611
|
+
await promises.appendFile(path30__default.default.resolve(summaryTarget), `
|
|
20603
20612
|
${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
20604
20613
|
}
|
|
20605
20614
|
const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
|
|
@@ -20618,10 +20627,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
|
20618
20627
|
findings: diff?.findings.length ?? 0,
|
|
20619
20628
|
diagnostics: diff?.diagnostics.length ?? 0
|
|
20620
20629
|
},
|
|
20621
|
-
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary:
|
|
20630
|
+
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path30__default.default.resolve(summaryTarget) } : {},
|
|
20622
20631
|
note: NOTE
|
|
20623
20632
|
};
|
|
20624
|
-
await promises.writeFile(
|
|
20633
|
+
await promises.writeFile(path30__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
|
|
20625
20634
|
if (options.json === true) {
|
|
20626
20635
|
console.log(writeJson3(manifest).trimEnd());
|
|
20627
20636
|
} else {
|
|
@@ -20682,8 +20691,8 @@ async function resolveOutputDir(options, runIds, cwd, format) {
|
|
|
20682
20691
|
const location = resolveWorkspaceLocation(cwd);
|
|
20683
20692
|
const manifest = await readWorkspaceManifestFile(location);
|
|
20684
20693
|
if (manifest.ok && manifest.manifest) {
|
|
20685
|
-
const rel =
|
|
20686
|
-
if (!rel.startsWith("..") && !
|
|
20694
|
+
const rel = path30__default.default.relative(location.workspaceDir, normalized);
|
|
20695
|
+
if (!rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
|
|
20687
20696
|
return resolveInsideWorkspace(location.workspaceDir, rel);
|
|
20688
20697
|
}
|
|
20689
20698
|
}
|
|
@@ -20699,7 +20708,7 @@ async function resolveOutputDir(options, runIds, cwd, format) {
|
|
|
20699
20708
|
const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
|
|
20700
20709
|
const base2 = resolveInsideWorkspace(
|
|
20701
20710
|
location.workspaceDir,
|
|
20702
|
-
|
|
20711
|
+
path30__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
|
|
20703
20712
|
);
|
|
20704
20713
|
return format === "zip" ? `${base2}.zip` : base2;
|
|
20705
20714
|
}
|
|
@@ -21104,19 +21113,19 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
21104
21113
|
let sidecarDir = outputDir;
|
|
21105
21114
|
if (outputDir.toLowerCase().endsWith(".html")) {
|
|
21106
21115
|
htmlPath = outputDir;
|
|
21107
|
-
sidecarDir =
|
|
21116
|
+
sidecarDir = path30__default.default.dirname(outputDir);
|
|
21108
21117
|
} else {
|
|
21109
21118
|
await promises.mkdir(outputDir, { recursive: true });
|
|
21110
|
-
htmlPath =
|
|
21119
|
+
htmlPath = path30__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
|
|
21111
21120
|
sidecarDir = outputDir;
|
|
21112
21121
|
}
|
|
21113
21122
|
await promises.mkdir(sidecarDir, { recursive: true });
|
|
21114
21123
|
await promises.writeFile(htmlPath, htmlContent, "utf-8");
|
|
21115
|
-
await promises.writeFile(
|
|
21124
|
+
await promises.writeFile(path30__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
|
|
21116
21125
|
outputPath = htmlPath;
|
|
21117
21126
|
} else if (format === "zip") {
|
|
21118
21127
|
const zipPath = outputDir.toLowerCase().endsWith(".zip") ? outputDir : `${outputDir}.zip`;
|
|
21119
|
-
const zipParent =
|
|
21128
|
+
const zipParent = path30__default.default.dirname(zipPath);
|
|
21120
21129
|
await promises.mkdir(zipParent, { recursive: true });
|
|
21121
21130
|
const entries = [
|
|
21122
21131
|
...[...packaged.entries()].map(([relativePath, content]) => ({
|
|
@@ -21132,10 +21141,10 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
21132
21141
|
await promises.mkdir(outputDir, { recursive: true });
|
|
21133
21142
|
for (const [relativePath, content] of packaged.entries()) {
|
|
21134
21143
|
const outPath = assertBundlePathContained(outputDir, relativePath);
|
|
21135
|
-
await promises.mkdir(
|
|
21144
|
+
await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
|
|
21136
21145
|
await promises.writeFile(outPath, content, "utf-8");
|
|
21137
21146
|
}
|
|
21138
|
-
await promises.writeFile(
|
|
21147
|
+
await promises.writeFile(path30__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
|
|
21139
21148
|
if (!files.includes(EVIDENCE_MANIFEST_FILENAME)) {
|
|
21140
21149
|
files.push(EVIDENCE_MANIFEST_FILENAME);
|
|
21141
21150
|
}
|
|
@@ -21184,7 +21193,7 @@ function writeJson5(value) {
|
|
|
21184
21193
|
`;
|
|
21185
21194
|
}
|
|
21186
21195
|
async function bundleVerifyCommand(targetPath, options = {}) {
|
|
21187
|
-
const root =
|
|
21196
|
+
const root = path30__default.default.resolve(targetPath.trim() || ".");
|
|
21188
21197
|
const result = await verifyEvidenceDirectory(root, {
|
|
21189
21198
|
unexpectedFiles: options.unexpected ?? "fail"
|
|
21190
21199
|
});
|
|
@@ -21217,6 +21226,141 @@ async function bundleVerifyCommand(targetPath, options = {}) {
|
|
|
21217
21226
|
process.exitCode = 1;
|
|
21218
21227
|
}
|
|
21219
21228
|
}
|
|
21229
|
+
var CLIENTS = [
|
|
21230
|
+
"cursor",
|
|
21231
|
+
"claude-code",
|
|
21232
|
+
"codex",
|
|
21233
|
+
"gemini"
|
|
21234
|
+
];
|
|
21235
|
+
function isMcpConfigureClient(value) {
|
|
21236
|
+
return CLIENTS.includes(value);
|
|
21237
|
+
}
|
|
21238
|
+
function buildServerBlock(traceDir) {
|
|
21239
|
+
return {
|
|
21240
|
+
command: "npx",
|
|
21241
|
+
args: ["-y", "@agent-inspect/mcp-server", "--dir", traceDir],
|
|
21242
|
+
env: {
|
|
21243
|
+
AGENT_INSPECT_TRACE_DIR: traceDir,
|
|
21244
|
+
AGENT_INSPECT_MCP_REDACTION_PROFILE: "share"
|
|
21245
|
+
}
|
|
21246
|
+
};
|
|
21247
|
+
}
|
|
21248
|
+
function buildMcpClientConfig(client, traceDir) {
|
|
21249
|
+
const server = buildServerBlock(traceDir);
|
|
21250
|
+
switch (client) {
|
|
21251
|
+
case "cursor":
|
|
21252
|
+
return {
|
|
21253
|
+
mcpServers: {
|
|
21254
|
+
"agent-inspect": server
|
|
21255
|
+
}
|
|
21256
|
+
};
|
|
21257
|
+
case "claude-code":
|
|
21258
|
+
return {
|
|
21259
|
+
mcpServers: {
|
|
21260
|
+
"agent-inspect": server
|
|
21261
|
+
}
|
|
21262
|
+
};
|
|
21263
|
+
case "codex":
|
|
21264
|
+
return {
|
|
21265
|
+
mcp_servers: {
|
|
21266
|
+
"agent-inspect": {
|
|
21267
|
+
command: server.command,
|
|
21268
|
+
args: server.args,
|
|
21269
|
+
env: server.env
|
|
21270
|
+
}
|
|
21271
|
+
}
|
|
21272
|
+
};
|
|
21273
|
+
case "gemini":
|
|
21274
|
+
return {
|
|
21275
|
+
mcpServers: {
|
|
21276
|
+
"agent-inspect": server
|
|
21277
|
+
}
|
|
21278
|
+
};
|
|
21279
|
+
default: {
|
|
21280
|
+
const _exhaustive = client;
|
|
21281
|
+
return _exhaustive;
|
|
21282
|
+
}
|
|
21283
|
+
}
|
|
21284
|
+
}
|
|
21285
|
+
function resolveTargetPath(client, projectLocal) {
|
|
21286
|
+
if (projectLocal) {
|
|
21287
|
+
switch (client) {
|
|
21288
|
+
case "cursor":
|
|
21289
|
+
return path30__default.default.join(".cursor", "mcp.json");
|
|
21290
|
+
case "claude-code":
|
|
21291
|
+
return path30__default.default.join(".mcp.json");
|
|
21292
|
+
case "codex":
|
|
21293
|
+
return path30__default.default.join(".codex", "config.toml.json");
|
|
21294
|
+
case "gemini":
|
|
21295
|
+
return path30__default.default.join(".gemini", "settings.json");
|
|
21296
|
+
}
|
|
21297
|
+
}
|
|
21298
|
+
switch (client) {
|
|
21299
|
+
case "cursor":
|
|
21300
|
+
return path30__default.default.join("~", ".cursor", "mcp.json");
|
|
21301
|
+
case "claude-code":
|
|
21302
|
+
return path30__default.default.join("~", ".claude.json");
|
|
21303
|
+
case "codex":
|
|
21304
|
+
return path30__default.default.join("~", ".codex", "config.toml");
|
|
21305
|
+
case "gemini":
|
|
21306
|
+
return path30__default.default.join("~", ".gemini", "settings.json");
|
|
21307
|
+
}
|
|
21308
|
+
}
|
|
21309
|
+
async function mcpConfigureCommand(options) {
|
|
21310
|
+
if (!isMcpConfigureClient(options.client)) {
|
|
21311
|
+
throw new Error(
|
|
21312
|
+
`Unsupported client "${String(options.client)}". Use: ${CLIENTS.join(", ")}`
|
|
21313
|
+
);
|
|
21314
|
+
}
|
|
21315
|
+
const traceDir = options.dir?.trim() || ".agent-inspect";
|
|
21316
|
+
const projectLocal = Boolean(options.projectLocal);
|
|
21317
|
+
const write = Boolean(options.write);
|
|
21318
|
+
const yes = Boolean(options.yes);
|
|
21319
|
+
const dryRun = !(write && yes && projectLocal);
|
|
21320
|
+
const config = buildMcpClientConfig(options.client, traceDir);
|
|
21321
|
+
const targetPath = resolveTargetPath(options.client, projectLocal);
|
|
21322
|
+
const notes = [
|
|
21323
|
+
"Read-only MCP server; no network upload; share redaction by default.",
|
|
21324
|
+
"Dry-run by default. Pass --project-local --write --yes to write a project file.",
|
|
21325
|
+
"User-level paths are never auto-written by this command.",
|
|
21326
|
+
"Remove the agent-inspect server block to uninstall."
|
|
21327
|
+
];
|
|
21328
|
+
let wrote = false;
|
|
21329
|
+
if (!dryRun && projectLocal) {
|
|
21330
|
+
const abs = path30__default.default.resolve(targetPath);
|
|
21331
|
+
await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
|
|
21332
|
+
await promises.writeFile(abs, `${JSON.stringify(config, null, 2)}
|
|
21333
|
+
`, "utf8");
|
|
21334
|
+
wrote = true;
|
|
21335
|
+
}
|
|
21336
|
+
const result = {
|
|
21337
|
+
client: options.client,
|
|
21338
|
+
dryRun,
|
|
21339
|
+
wrote,
|
|
21340
|
+
targetPath,
|
|
21341
|
+
config,
|
|
21342
|
+
notes
|
|
21343
|
+
};
|
|
21344
|
+
if (options.json) {
|
|
21345
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
21346
|
+
`);
|
|
21347
|
+
} else {
|
|
21348
|
+
process.stdout.write(
|
|
21349
|
+
[
|
|
21350
|
+
`Client: ${result.client}`,
|
|
21351
|
+
`Mode: ${result.dryRun ? "dry-run" : "write"}`,
|
|
21352
|
+
`Target: ${result.targetPath}`,
|
|
21353
|
+
`Wrote: ${result.wrote}`,
|
|
21354
|
+
"",
|
|
21355
|
+
JSON.stringify(result.config, null, 2),
|
|
21356
|
+
"",
|
|
21357
|
+
...result.notes.map((note) => `- ${note}`),
|
|
21358
|
+
""
|
|
21359
|
+
].join("\n")
|
|
21360
|
+
);
|
|
21361
|
+
}
|
|
21362
|
+
return result;
|
|
21363
|
+
}
|
|
21220
21364
|
var NOTE2 = "Generated locally by AgentInspect from reporter artifact manifests. Trace contents are not embedded.";
|
|
21221
21365
|
var MAX_TEXT = 180;
|
|
21222
21366
|
var FRAMEWORKS = /* @__PURE__ */ new Set(["vitest", "jest", "manual"]);
|
|
@@ -21344,23 +21488,23 @@ function readManifestDocument(value) {
|
|
|
21344
21488
|
};
|
|
21345
21489
|
}
|
|
21346
21490
|
function cwdRelative(filePath) {
|
|
21347
|
-
const relative =
|
|
21348
|
-
if (relative === "" || relative.startsWith("../") ||
|
|
21349
|
-
return
|
|
21491
|
+
const relative = path30__default.default.relative(process.cwd(), path30__default.default.resolve(filePath)).replace(/\\/g, "/");
|
|
21492
|
+
if (relative === "" || relative.startsWith("../") || path30__default.default.isAbsolute(relative)) {
|
|
21493
|
+
return path30__default.default.basename(filePath);
|
|
21350
21494
|
}
|
|
21351
21495
|
return relative;
|
|
21352
21496
|
}
|
|
21353
21497
|
async function readReporterManifest(filePath) {
|
|
21354
|
-
const absolute =
|
|
21498
|
+
const absolute = path30__default.default.resolve(filePath);
|
|
21355
21499
|
const raw = await promises.readFile(absolute, "utf-8");
|
|
21356
21500
|
const document = readManifestDocument(JSON.parse(raw));
|
|
21357
21501
|
const manifest = document.manifest;
|
|
21358
21502
|
const results = manifest.results.map((result) => ({
|
|
21359
21503
|
testId: safeText(result.testId),
|
|
21360
21504
|
name: safeText(result.name),
|
|
21361
|
-
...result.file === void 0 ? {} : { file: safeText(
|
|
21505
|
+
...result.file === void 0 ? {} : { file: safeText(path30__default.default.basename(result.file)) },
|
|
21362
21506
|
status: result.status,
|
|
21363
|
-
...result.tracePath === void 0 ? {} : { tracePath: safeText(
|
|
21507
|
+
...result.tracePath === void 0 ? {} : { tracePath: safeText(path30__default.default.basename(result.tracePath)) },
|
|
21364
21508
|
artifacts: result.artifacts,
|
|
21365
21509
|
diagnostics: result.diagnostics
|
|
21366
21510
|
}));
|
|
@@ -21499,15 +21643,15 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
|
|
|
21499
21643
|
return;
|
|
21500
21644
|
}
|
|
21501
21645
|
const markdown = renderMarkdown2(result);
|
|
21502
|
-
const outputPath = options.output !== void 0 && options.output.trim() !== "" ?
|
|
21646
|
+
const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path30__default.default.resolve(options.output.trim()) : void 0;
|
|
21503
21647
|
if (outputPath !== void 0) {
|
|
21504
|
-
await promises.mkdir(
|
|
21648
|
+
await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
|
|
21505
21649
|
await promises.writeFile(outputPath, markdown, "utf-8");
|
|
21506
21650
|
}
|
|
21507
21651
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
21508
21652
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
21509
|
-
const summaryPath =
|
|
21510
|
-
await promises.mkdir(
|
|
21653
|
+
const summaryPath = path30__default.default.resolve(summaryTarget);
|
|
21654
|
+
await promises.mkdir(path30__default.default.dirname(summaryPath), { recursive: true });
|
|
21511
21655
|
await promises.appendFile(summaryPath, `
|
|
21512
21656
|
${markdown}`, "utf-8");
|
|
21513
21657
|
}
|
|
@@ -21655,7 +21799,7 @@ jobs:
|
|
|
21655
21799
|
}
|
|
21656
21800
|
async function planInit(options = {}) {
|
|
21657
21801
|
const framework = normalizeFramework(options.framework);
|
|
21658
|
-
const cwd =
|
|
21802
|
+
const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
|
|
21659
21803
|
const demoPath = framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${framework}-demo.mjs`;
|
|
21660
21804
|
const candidates = [
|
|
21661
21805
|
{ rel: CONFIG_FILE, content: configTemplate(framework) },
|
|
@@ -21670,7 +21814,7 @@ async function planInit(options = {}) {
|
|
|
21670
21814
|
}
|
|
21671
21815
|
const files = [];
|
|
21672
21816
|
for (const candidate of candidates) {
|
|
21673
|
-
const abs =
|
|
21817
|
+
const abs = path30__default.default.join(cwd, candidate.rel);
|
|
21674
21818
|
try {
|
|
21675
21819
|
await promises.access(abs);
|
|
21676
21820
|
files.push({
|
|
@@ -21691,12 +21835,12 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
21691
21835
|
if (entry.action === "skip") {
|
|
21692
21836
|
continue;
|
|
21693
21837
|
}
|
|
21694
|
-
const abs =
|
|
21838
|
+
const abs = path30__default.default.join(cwd, entry.path);
|
|
21695
21839
|
if (options.dryRun) {
|
|
21696
21840
|
written.push(entry.path);
|
|
21697
21841
|
continue;
|
|
21698
21842
|
}
|
|
21699
|
-
await promises.mkdir(
|
|
21843
|
+
await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
|
|
21700
21844
|
const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
|
|
21701
21845
|
await promises.writeFile(abs, content, "utf-8");
|
|
21702
21846
|
written.push(entry.path);
|
|
@@ -21704,7 +21848,7 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
21704
21848
|
return written;
|
|
21705
21849
|
}
|
|
21706
21850
|
async function initCommand(options = {}) {
|
|
21707
|
-
const cwd =
|
|
21851
|
+
const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
|
|
21708
21852
|
try {
|
|
21709
21853
|
const plan = await planInit({ ...options, cwd });
|
|
21710
21854
|
const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
|
|
@@ -21795,7 +21939,7 @@ function envCheck(name, optional = true) {
|
|
|
21795
21939
|
};
|
|
21796
21940
|
}
|
|
21797
21941
|
async function traceDirWritable(traceDir) {
|
|
21798
|
-
const resolved =
|
|
21942
|
+
const resolved = path30__default.default.resolve(traceDir);
|
|
21799
21943
|
try {
|
|
21800
21944
|
await promises.mkdir(resolved, { recursive: true });
|
|
21801
21945
|
await promises.access(resolved, promises.constants.W_OK);
|
|
@@ -21816,10 +21960,10 @@ async function traceDirWritable(traceDir) {
|
|
|
21816
21960
|
}
|
|
21817
21961
|
}
|
|
21818
21962
|
function readPackageVersionNearEntry(entryPath, packageName) {
|
|
21819
|
-
let dir =
|
|
21820
|
-
const { root } =
|
|
21963
|
+
let dir = path30__default.default.dirname(path30__default.default.resolve(entryPath));
|
|
21964
|
+
const { root } = path30__default.default.parse(dir);
|
|
21821
21965
|
while (true) {
|
|
21822
|
-
const candidate =
|
|
21966
|
+
const candidate = path30__default.default.join(dir, "package.json");
|
|
21823
21967
|
if (fs.existsSync(candidate)) {
|
|
21824
21968
|
try {
|
|
21825
21969
|
const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
@@ -21830,14 +21974,14 @@ function readPackageVersionNearEntry(entryPath, packageName) {
|
|
|
21830
21974
|
}
|
|
21831
21975
|
}
|
|
21832
21976
|
if (dir === root) break;
|
|
21833
|
-
const parent =
|
|
21977
|
+
const parent = path30__default.default.dirname(dir);
|
|
21834
21978
|
if (parent === dir) break;
|
|
21835
21979
|
dir = parent;
|
|
21836
21980
|
}
|
|
21837
21981
|
return void 0;
|
|
21838
21982
|
}
|
|
21839
21983
|
function resolveInstalledPackage(cwd, name) {
|
|
21840
|
-
const require2 = module$1.createRequire(
|
|
21984
|
+
const require2 = module$1.createRequire(path30__default.default.join(cwd, "package.json"));
|
|
21841
21985
|
try {
|
|
21842
21986
|
const entry = require2.resolve(name);
|
|
21843
21987
|
let version2;
|
|
@@ -21935,7 +22079,7 @@ function versionMismatchCheck(cwd) {
|
|
|
21935
22079
|
};
|
|
21936
22080
|
}
|
|
21937
22081
|
async function runDoctorChecks(options = {}) {
|
|
21938
|
-
const cwd =
|
|
22082
|
+
const cwd = path30__default.default.resolve(options.cwd ?? process3__default.default.cwd());
|
|
21939
22083
|
const traceDir = options.traceDir?.trim() || process3__default.default.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
|
|
21940
22084
|
const checks2 = [
|
|
21941
22085
|
nodeVersionCheck(),
|
|
@@ -22175,7 +22319,7 @@ function parsePluginManifest(input3) {
|
|
|
22175
22319
|
};
|
|
22176
22320
|
}
|
|
22177
22321
|
async function readPluginManifestFile(packageDir) {
|
|
22178
|
-
const manifestPath =
|
|
22322
|
+
const manifestPath = path30__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
|
|
22179
22323
|
try {
|
|
22180
22324
|
const raw = await promises.readFile(manifestPath, "utf8");
|
|
22181
22325
|
const parsed = parsePluginManifest(JSON.parse(raw));
|
|
@@ -22250,7 +22394,7 @@ function createTraceDirectoryIndexer() {
|
|
|
22250
22394
|
// packages/cli/src/plugins.ts
|
|
22251
22395
|
async function readPackageName(packageDir) {
|
|
22252
22396
|
try {
|
|
22253
|
-
const raw = await promises.readFile(
|
|
22397
|
+
const raw = await promises.readFile(path30__default.default.join(packageDir, "package.json"), "utf8");
|
|
22254
22398
|
const parsed = JSON.parse(raw);
|
|
22255
22399
|
return typeof parsed.name === "string" ? parsed.name : void 0;
|
|
22256
22400
|
} catch {
|
|
@@ -22258,7 +22402,7 @@ async function readPackageName(packageDir) {
|
|
|
22258
22402
|
}
|
|
22259
22403
|
}
|
|
22260
22404
|
async function discoverPlugins(cwd = process.cwd()) {
|
|
22261
|
-
const nodeModules =
|
|
22405
|
+
const nodeModules = path30__default.default.join(cwd, "node_modules");
|
|
22262
22406
|
const found = [];
|
|
22263
22407
|
let entries;
|
|
22264
22408
|
try {
|
|
@@ -22269,7 +22413,7 @@ async function discoverPlugins(cwd = process.cwd()) {
|
|
|
22269
22413
|
for (const entry of entries.sort()) {
|
|
22270
22414
|
if (entry.startsWith("@")) continue;
|
|
22271
22415
|
if (!isPluginPackageName(entry)) continue;
|
|
22272
|
-
const packageDir =
|
|
22416
|
+
const packageDir = path30__default.default.join(nodeModules, entry);
|
|
22273
22417
|
const manifestRead = await readPluginManifestFile(packageDir);
|
|
22274
22418
|
found.push({
|
|
22275
22419
|
packageName: entry,
|
|
@@ -22282,7 +22426,7 @@ async function discoverPlugins(cwd = process.cwd()) {
|
|
|
22282
22426
|
return found;
|
|
22283
22427
|
}
|
|
22284
22428
|
async function validatePluginPackage(packageRef, cwd = process.cwd()) {
|
|
22285
|
-
const packageDir =
|
|
22429
|
+
const packageDir = path30__default.default.isAbsolute(packageRef) ? packageRef : path30__default.default.join(cwd, "node_modules", packageRef);
|
|
22286
22430
|
const packageName = await readPackageName(packageDir) ?? packageRef;
|
|
22287
22431
|
const errors = [];
|
|
22288
22432
|
const warnings = [];
|
|
@@ -22359,7 +22503,7 @@ async function pluginsValidateCommand(packageRef, cwd) {
|
|
|
22359
22503
|
init_advanced();
|
|
22360
22504
|
var INDEX_FILENAME = ".agent-inspect-index.json";
|
|
22361
22505
|
function traceIndexPath(traceDir) {
|
|
22362
|
-
return
|
|
22506
|
+
return path30__default.default.join(traceDir, INDEX_FILENAME);
|
|
22363
22507
|
}
|
|
22364
22508
|
function parseMaxEntries(raw) {
|
|
22365
22509
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -22505,7 +22649,7 @@ async function newestTraceMtimeMs2(traceDir) {
|
|
|
22505
22649
|
for (const file of files) {
|
|
22506
22650
|
if (!file.endsWith(".jsonl")) continue;
|
|
22507
22651
|
try {
|
|
22508
|
-
const s = await promises.stat(
|
|
22652
|
+
const s = await promises.stat(path30__default.default.join(traceDir, file));
|
|
22509
22653
|
if (s.mtimeMs > newest) newest = s.mtimeMs;
|
|
22510
22654
|
} catch {
|
|
22511
22655
|
}
|
|
@@ -22760,11 +22904,11 @@ function printJson5(value) {
|
|
|
22760
22904
|
console.log(JSON.stringify(value, null, 2));
|
|
22761
22905
|
}
|
|
22762
22906
|
function resolveCwd(options) {
|
|
22763
|
-
return
|
|
22907
|
+
return path30__default.default.resolve(options.cwd ?? process.cwd());
|
|
22764
22908
|
}
|
|
22765
22909
|
async function suiteInitCommand(options = {}) {
|
|
22766
22910
|
const cwd = resolveCwd(options);
|
|
22767
|
-
const configPath =
|
|
22911
|
+
const configPath = path30__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
|
|
22768
22912
|
const template = options.template?.trim();
|
|
22769
22913
|
const suiteConfig = template !== void 0 && template !== "" ? resolveSuiteTemplate(template) : defaultSuiteConfigTemplate();
|
|
22770
22914
|
if (options.dryRun) {
|
|
@@ -22883,13 +23027,13 @@ async function suiteListCommand(options = {}) {
|
|
|
22883
23027
|
}
|
|
22884
23028
|
async function writeSuiteArtifact(result, configOutputDir, options) {
|
|
22885
23029
|
const cwd = resolveCwd(options);
|
|
22886
|
-
const outputDir =
|
|
23030
|
+
const outputDir = path30__default.default.resolve(
|
|
22887
23031
|
cwd,
|
|
22888
23032
|
options.output ?? configOutputDir ?? DEFAULT_SUITE_ARTIFACTS_DIR
|
|
22889
23033
|
);
|
|
22890
23034
|
await promises.mkdir(outputDir, { recursive: true });
|
|
22891
23035
|
const stamp = result.startedAt.replace(/[:.]/g, "-");
|
|
22892
|
-
const filePath =
|
|
23036
|
+
const filePath = path30__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
|
|
22893
23037
|
await promises.writeFile(filePath, `${JSON.stringify(result, null, 2)}
|
|
22894
23038
|
`, "utf-8");
|
|
22895
23039
|
return filePath;
|
|
@@ -22947,7 +23091,7 @@ async function loadSuiteResultFromInput(options) {
|
|
|
22947
23091
|
if (options.input === void 0 || options.input.trim() === "") {
|
|
22948
23092
|
throw new Error("Pass --input <suite-run.json> from a prior suite run.");
|
|
22949
23093
|
}
|
|
22950
|
-
const inputPath =
|
|
23094
|
+
const inputPath = path30__default.default.resolve(cwd, options.input.trim());
|
|
22951
23095
|
const raw = await promises.readFile(inputPath, "utf-8");
|
|
22952
23096
|
return JSON.parse(raw);
|
|
22953
23097
|
}
|
|
@@ -22984,9 +23128,9 @@ function normalizeMetrics2(raw) {
|
|
|
22984
23128
|
}
|
|
22985
23129
|
async function writeArtifacts(result, outputDir) {
|
|
22986
23130
|
await promises.mkdir(outputDir, { recursive: true });
|
|
22987
|
-
const jsonPath =
|
|
22988
|
-
const markdownPath =
|
|
22989
|
-
const htmlPath =
|
|
23131
|
+
const jsonPath = path30__default.default.join(outputDir, "cohort-results.json");
|
|
23132
|
+
const markdownPath = path30__default.default.join(outputDir, "cohort-summary.md");
|
|
23133
|
+
const htmlPath = path30__default.default.join(outputDir, "cohort-report.html");
|
|
22990
23134
|
await promises.writeFile(jsonPath, `${renderCohortReport(result, { format: "json" })}
|
|
22991
23135
|
`, "utf-8");
|
|
22992
23136
|
await promises.writeFile(
|
|
@@ -23014,7 +23158,7 @@ async function cohortCommand(options = {}) {
|
|
|
23014
23158
|
const format = options.format ?? (options.json ? "json" : "markdown");
|
|
23015
23159
|
let artifacts;
|
|
23016
23160
|
if (options.output !== void 0 && options.output.trim() !== "") {
|
|
23017
|
-
artifacts = await writeArtifacts(result,
|
|
23161
|
+
artifacts = await writeArtifacts(result, path30__default.default.resolve(options.output.trim()));
|
|
23018
23162
|
}
|
|
23019
23163
|
if (options.json || format === "json") {
|
|
23020
23164
|
console.log(
|
|
@@ -23087,11 +23231,11 @@ function parseDuration2(value) {
|
|
|
23087
23231
|
async function writeArtifacts2(result, outputDir) {
|
|
23088
23232
|
await promises.mkdir(outputDir, { recursive: true });
|
|
23089
23233
|
const paths = {
|
|
23090
|
-
jsonPath:
|
|
23091
|
-
markdownPath:
|
|
23092
|
-
htmlPath:
|
|
23093
|
-
junitPath:
|
|
23094
|
-
githubPath:
|
|
23234
|
+
jsonPath: path30__default.default.join(outputDir, "gate-results.json"),
|
|
23235
|
+
markdownPath: path30__default.default.join(outputDir, "gate-summary.md"),
|
|
23236
|
+
htmlPath: path30__default.default.join(outputDir, "gate-report.html"),
|
|
23237
|
+
junitPath: path30__default.default.join(outputDir, "junit.xml"),
|
|
23238
|
+
githubPath: path30__default.default.join(outputDir, "github-step-summary.md")
|
|
23095
23239
|
};
|
|
23096
23240
|
await promises.writeFile(
|
|
23097
23241
|
paths.jsonPath,
|
|
@@ -23159,7 +23303,7 @@ async function gateCommand(options = {}) {
|
|
|
23159
23303
|
const result = await runGate(runs, gateOptions);
|
|
23160
23304
|
let artifacts;
|
|
23161
23305
|
if (options.output !== void 0 && options.output.trim() !== "") {
|
|
23162
|
-
artifacts = await writeArtifacts2(result,
|
|
23306
|
+
artifacts = await writeArtifacts2(result, path30__default.default.resolve(options.output.trim()));
|
|
23163
23307
|
}
|
|
23164
23308
|
if (options.json || format === "json") {
|
|
23165
23309
|
console.log(JSON.stringify({ ...result, artifacts: artifacts ?? null }, null, 2));
|
|
@@ -23691,6 +23835,20 @@ function createCliProgram() {
|
|
|
23691
23835
|
).option("--format <format>", "markdown, json, or html", "markdown").option("-o, --output <dir>", "write cohort-results.json, cohort-summary.md, cohort-report.html").option("--json", "print deterministic JSON result").action((opts) => {
|
|
23692
23836
|
runCommand(() => cohortCommand(opts));
|
|
23693
23837
|
});
|
|
23838
|
+
const mcpCmd = program.command("mcp").description("Configure local coding-agent MCP clients (read-only; dry-run by default)");
|
|
23839
|
+
mcpCmd.command("configure").description("Print or write MCP client config for Cursor/Claude/Codex/Gemini").requiredOption(
|
|
23840
|
+
"--client <name>",
|
|
23841
|
+
"cursor | claude-code | codex | gemini"
|
|
23842
|
+
).option("--dir <path>", "trace directory for the MCP server", ".agent-inspect").option("--project-local", "target a project-local config path").option("--write", "write config (requires --project-local --yes)").option("--yes", "confirm write").option("--json", "print deterministic JSON result").action((opts) => {
|
|
23843
|
+
runCommand(async () => {
|
|
23844
|
+
if (!isMcpConfigureClient(opts.client)) {
|
|
23845
|
+
throw new Error(
|
|
23846
|
+
`Unsupported --client "${opts.client}". Use: cursor, claude-code, codex, gemini`
|
|
23847
|
+
);
|
|
23848
|
+
}
|
|
23849
|
+
await mcpConfigureCommand({ ...opts, client: opts.client });
|
|
23850
|
+
});
|
|
23851
|
+
});
|
|
23694
23852
|
program.command("gate").description("Run deterministic CI quality gates over traces or suites (v5.2+)").option("--dir <path>", "trace directory for threshold checks").option("--suite <path>", "suite config path").option("--max-error-rate <percent>", "maximum allowed error rate percentage").option("--max-p95-duration <ms>", "maximum allowed p95 run duration in ms").option("--forbid-tool <name>", "forbidden tool name (repeatable or comma-separated)").option(
|
|
23695
23853
|
"--require-observation <name>",
|
|
23696
23854
|
"required passed observation (repeatable or comma-separated)"
|
|
@@ -23707,9 +23865,9 @@ function isPrimaryModule() {
|
|
|
23707
23865
|
if (!entry) return false;
|
|
23708
23866
|
const selfPath = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
23709
23867
|
try {
|
|
23710
|
-
return fs.realpathSync(
|
|
23868
|
+
return fs.realpathSync(path30__default.default.resolve(entry)) === fs.realpathSync(path30__default.default.resolve(selfPath));
|
|
23711
23869
|
} catch {
|
|
23712
|
-
return
|
|
23870
|
+
return path30__default.default.resolve(entry) === path30__default.default.resolve(selfPath);
|
|
23713
23871
|
}
|
|
23714
23872
|
}
|
|
23715
23873
|
if (isPrimaryModule()) {
|