agent-inspect 6.17.8 → 6.19.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 +23 -0
- package/README.md +1 -1
- package/docs/ADAPTERS.md +34 -4
- package/docs/AI-SDK-ADOPTION.md +25 -0
- package/docs/API.md +13 -10
- package/docs/CLI.md +6 -0
- package/docs/COMPARE.md +6 -0
- package/docs/FIRST-TRACE-IN-5-MINUTES.md +3 -1
- package/docs/LIMITATIONS.md +1 -0
- package/docs/OPENAI-AGENTS-LOCAL.md +1 -0
- package/docs/SAFE-TRACE-SHARING.md +2 -2
- package/docs/SUPPORT-LEVELS.md +1 -0
- package/docs/USE-CASES.md +1 -1
- package/docs/VSCODE.md +8 -0
- package/package.json +2 -2
- package/packages/cli/dist/{chunk-25LUDS4T.mjs → chunk-R7Y5SGH5.mjs} +348 -27
- package/packages/cli/dist/chunk-R7Y5SGH5.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +1622 -900
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +1235 -850
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-2FS6BLR7.mjs → src-T4EZERCX.mjs} +3 -3
- package/packages/cli/dist/{src-2FS6BLR7.mjs.map → src-T4EZERCX.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +180 -0
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +94 -4
- package/packages/core/dist/advanced.d.ts +94 -4
- package/packages/core/dist/advanced.mjs +177 -2
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +334 -5
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.d.cts +81 -4
- package/packages/core/dist/checks.d.ts +81 -4
- package/packages/core/dist/checks.mjs +1 -1
- package/packages/core/dist/{chunk-LQC7IED3.mjs → chunk-NABMW5DX.mjs} +336 -8
- package/packages/core/dist/chunk-NABMW5DX.mjs.map +1 -0
- package/packages/core/dist/{index-B9ZGvUVL.d.ts → index-AMAGuO_i.d.ts} +1 -1
- package/packages/core/dist/{index-DWu54Y28.d.cts → index-DCR816Yt.d.cts} +2 -2
- package/packages/core/dist/{index-DlwbVqEs.d.ts → index-DKwuGSe-.d.ts} +2 -2
- package/packages/core/dist/{index-B259NKkH.d.cts → index-vqr-g6ev.d.cts} +1 -1
- package/packages/core/dist/readers.d.cts +1 -1
- package/packages/core/dist/readers.d.ts +1 -1
- package/packages/cli/dist/chunk-25LUDS4T.mjs.map +0 -1
- package/packages/core/dist/chunk-LQC7IED3.mjs.map +0 -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 path33 = require('path');
|
|
8
8
|
var async_hooks = require('async_hooks');
|
|
9
9
|
var process3 = require('process');
|
|
10
10
|
var tty = require('tty');
|
|
@@ -22,7 +22,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
22
22
|
|
|
23
23
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
24
24
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
25
|
-
var
|
|
25
|
+
var path33__default = /*#__PURE__*/_interopDefault(path33);
|
|
26
26
|
var process3__default = /*#__PURE__*/_interopDefault(process3);
|
|
27
27
|
var tty__default = /*#__PURE__*/_interopDefault(tty);
|
|
28
28
|
|
|
@@ -866,7 +866,7 @@ function getDefaultTraceDir() {
|
|
|
866
866
|
if (typeof home !== "string" || home.trim() === "") {
|
|
867
867
|
return FALLBACK_TRACE_DIR;
|
|
868
868
|
}
|
|
869
|
-
return
|
|
869
|
+
return path33__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
|
|
870
870
|
} catch {
|
|
871
871
|
return FALLBACK_TRACE_DIR;
|
|
872
872
|
}
|
|
@@ -874,11 +874,11 @@ function getDefaultTraceDir() {
|
|
|
874
874
|
function getTraceFilePath(runId, traceDir) {
|
|
875
875
|
const baseDir = traceDir ?? getDefaultTraceDir();
|
|
876
876
|
let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
|
|
877
|
-
safeId =
|
|
877
|
+
safeId = path33__default.default.basename(safeId);
|
|
878
878
|
if (safeId === "" || safeId === "." || safeId === "..") {
|
|
879
879
|
safeId = "run_unknown";
|
|
880
880
|
}
|
|
881
|
-
return
|
|
881
|
+
return path33__default.default.join(baseDir, `${safeId}.jsonl`);
|
|
882
882
|
}
|
|
883
883
|
function formatError(error) {
|
|
884
884
|
if (error instanceof Error) {
|
|
@@ -935,7 +935,7 @@ var init_utils = __esm({
|
|
|
935
935
|
init_duration();
|
|
936
936
|
DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
|
|
937
937
|
RUNS_DIR_NAME = "runs";
|
|
938
|
-
FALLBACK_TRACE_DIR =
|
|
938
|
+
FALLBACK_TRACE_DIR = path33__default.default.join(
|
|
939
939
|
os__default.default.tmpdir(),
|
|
940
940
|
"agent-inspect",
|
|
941
941
|
RUNS_DIR_NAME
|
|
@@ -1306,6 +1306,14 @@ var init_inspector = __esm({
|
|
|
1306
1306
|
}
|
|
1307
1307
|
});
|
|
1308
1308
|
|
|
1309
|
+
// packages/core/src/adapters/preview-capture.ts
|
|
1310
|
+
var init_preview_capture = __esm({
|
|
1311
|
+
"packages/core/src/adapters/preview-capture.ts"() {
|
|
1312
|
+
init_redactor();
|
|
1313
|
+
init_redaction_profiles();
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1309
1317
|
// node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
1310
1318
|
function assembleStyles() {
|
|
1311
1319
|
const codes = /* @__PURE__ */ new Map();
|
|
@@ -1901,7 +1909,7 @@ var init_trace_directory = __esm({
|
|
|
1901
1909
|
this.#dir = resolveTraceDir(options);
|
|
1902
1910
|
}
|
|
1903
1911
|
getPath(filename) {
|
|
1904
|
-
return filename ?
|
|
1912
|
+
return filename ? path33__default.default.join(this.#dir, filename) : this.#dir;
|
|
1905
1913
|
}
|
|
1906
1914
|
async list() {
|
|
1907
1915
|
try {
|
|
@@ -1930,7 +1938,7 @@ function parseIsoToMs2(value) {
|
|
|
1930
1938
|
}
|
|
1931
1939
|
async function extractMetadata(filePath, _quickScan) {
|
|
1932
1940
|
const stats = await promises.stat(filePath);
|
|
1933
|
-
let runIdFromFile =
|
|
1941
|
+
let runIdFromFile = path33__default.default.basename(filePath);
|
|
1934
1942
|
if (runIdFromFile.endsWith(".jsonl")) {
|
|
1935
1943
|
runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
|
|
1936
1944
|
}
|
|
@@ -3800,12 +3808,12 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3800
3808
|
handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
|
|
3801
3809
|
);
|
|
3802
3810
|
const ordered = [...runs].sort(compareRuns);
|
|
3803
|
-
const
|
|
3811
|
+
const path44 = [];
|
|
3804
3812
|
const visited = /* @__PURE__ */ new Set();
|
|
3805
3813
|
const pushRun = (run, confidence, source) => {
|
|
3806
3814
|
if (visited.has(run.runId)) return;
|
|
3807
3815
|
visited.add(run.runId);
|
|
3808
|
-
|
|
3816
|
+
path44.push({
|
|
3809
3817
|
runId: run.runId,
|
|
3810
3818
|
name: run.name,
|
|
3811
3819
|
startedAt: run.startedAt,
|
|
@@ -3830,7 +3838,7 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3830
3838
|
const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
|
|
3831
3839
|
pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
|
|
3832
3840
|
}
|
|
3833
|
-
return
|
|
3841
|
+
return path44;
|
|
3834
3842
|
}
|
|
3835
3843
|
function metaRunIdMatches(run, token, runById) {
|
|
3836
3844
|
const meta2 = extractSessionWorkflowMetadata(run.metadata);
|
|
@@ -4159,7 +4167,7 @@ var init_summary = __esm({
|
|
|
4159
4167
|
});
|
|
4160
4168
|
function sanitizeBundleRunId(runId) {
|
|
4161
4169
|
let safe = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
|
|
4162
|
-
safe =
|
|
4170
|
+
safe = path33__default.default.basename(safe);
|
|
4163
4171
|
safe = safe.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
4164
4172
|
if (safe === "" || safe === "." || safe === "..") {
|
|
4165
4173
|
safe = "run_unknown";
|
|
@@ -4169,12 +4177,12 @@ function sanitizeBundleRunId(runId) {
|
|
|
4169
4177
|
function bundleRunAssetRelativePath(runId, extension) {
|
|
4170
4178
|
const safe = sanitizeBundleRunId(runId);
|
|
4171
4179
|
const ext = extension.startsWith(".") ? extension : `.${extension}`;
|
|
4172
|
-
return
|
|
4180
|
+
return path33__default.default.posix.join("assets", "runs", `${safe}${ext}`);
|
|
4173
4181
|
}
|
|
4174
4182
|
function assertBundlePathContained(outputDir, relativePath) {
|
|
4175
|
-
const base =
|
|
4176
|
-
const resolved =
|
|
4177
|
-
if (resolved !== base && !resolved.startsWith(base +
|
|
4183
|
+
const base = path33__default.default.resolve(outputDir);
|
|
4184
|
+
const resolved = path33__default.default.resolve(base, relativePath);
|
|
4185
|
+
if (resolved !== base && !resolved.startsWith(base + path33__default.default.sep)) {
|
|
4178
4186
|
throw new Error(`Bundle path escapes output directory: ${relativePath}`);
|
|
4179
4187
|
}
|
|
4180
4188
|
return resolved;
|
|
@@ -4184,7 +4192,7 @@ function normalizeBundleOutputPath(out, options) {
|
|
|
4184
4192
|
if (trimmed === "") {
|
|
4185
4193
|
throw new Error("--out requires a non-empty path.");
|
|
4186
4194
|
}
|
|
4187
|
-
const resolved =
|
|
4195
|
+
const resolved = path33__default.default.resolve(trimmed);
|
|
4188
4196
|
if (options?.preserveZipExtension !== true && resolved.toLowerCase().endsWith(".zip")) {
|
|
4189
4197
|
return resolved.slice(0, -4);
|
|
4190
4198
|
}
|
|
@@ -4193,7 +4201,7 @@ function normalizeBundleOutputPath(out, options) {
|
|
|
4193
4201
|
function defaultBundleOutputPath(runIds) {
|
|
4194
4202
|
const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
|
|
4195
4203
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4196
|
-
return
|
|
4204
|
+
return path33__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
|
|
4197
4205
|
}
|
|
4198
4206
|
var init_paths = __esm({
|
|
4199
4207
|
"packages/core/src/bundle/paths.ts"() {
|
|
@@ -4256,7 +4264,7 @@ function assertEvidenceRelativePath(relativePath) {
|
|
|
4256
4264
|
throw new Error("Evidence file path must be a non-empty relative path.");
|
|
4257
4265
|
}
|
|
4258
4266
|
const trimmed = relativePath.trim().replaceAll("\\", "/");
|
|
4259
|
-
if (
|
|
4267
|
+
if (path33__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
|
|
4260
4268
|
throw new Error(`Evidence file path must be relative: ${relativePath}`);
|
|
4261
4269
|
}
|
|
4262
4270
|
const parts = trimmed.split("/").filter((part) => part !== "");
|
|
@@ -5123,13 +5131,13 @@ function pairSteps(left, right) {
|
|
|
5123
5131
|
return pairs;
|
|
5124
5132
|
}
|
|
5125
5133
|
function compareLeafSteps(L, R, segments, opts, out) {
|
|
5126
|
-
const
|
|
5134
|
+
const path44 = buildPath(segments);
|
|
5127
5135
|
if (L.name !== R.name) {
|
|
5128
5136
|
out.push({
|
|
5129
5137
|
kind: "structure",
|
|
5130
5138
|
severity: "warning",
|
|
5131
5139
|
message: "Step name differs",
|
|
5132
|
-
path:
|
|
5140
|
+
path: path44,
|
|
5133
5141
|
left: L.name,
|
|
5134
5142
|
right: R.name
|
|
5135
5143
|
});
|
|
@@ -5139,7 +5147,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5139
5147
|
kind: "step-type",
|
|
5140
5148
|
severity: "warning",
|
|
5141
5149
|
message: "Step type differs",
|
|
5142
|
-
path:
|
|
5150
|
+
path: path44,
|
|
5143
5151
|
left: L.type,
|
|
5144
5152
|
right: R.type
|
|
5145
5153
|
});
|
|
@@ -5149,7 +5157,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5149
5157
|
kind: "step-status",
|
|
5150
5158
|
severity: "warning",
|
|
5151
5159
|
message: "Step status differs",
|
|
5152
|
-
path:
|
|
5160
|
+
path: path44,
|
|
5153
5161
|
left: L.status,
|
|
5154
5162
|
right: R.status
|
|
5155
5163
|
});
|
|
@@ -5161,7 +5169,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5161
5169
|
kind: "error",
|
|
5162
5170
|
severity: "error",
|
|
5163
5171
|
message: "Step error message differs",
|
|
5164
|
-
path:
|
|
5172
|
+
path: path44,
|
|
5165
5173
|
left: le || void 0,
|
|
5166
5174
|
right: re || void 0
|
|
5167
5175
|
});
|
|
@@ -5179,7 +5187,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5179
5187
|
kind: "duration",
|
|
5180
5188
|
severity: "info",
|
|
5181
5189
|
message: "Step duration differs",
|
|
5182
|
-
path:
|
|
5190
|
+
path: path44,
|
|
5183
5191
|
left: ld,
|
|
5184
5192
|
right: rd
|
|
5185
5193
|
});
|
|
@@ -5192,7 +5200,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5192
5200
|
kind: "metadata",
|
|
5193
5201
|
severity: "info",
|
|
5194
5202
|
message: "Step metadata differs",
|
|
5195
|
-
path:
|
|
5203
|
+
path: path44,
|
|
5196
5204
|
left: L.metadata,
|
|
5197
5205
|
right: R.metadata
|
|
5198
5206
|
});
|
|
@@ -5204,7 +5212,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
5204
5212
|
kind: "output",
|
|
5205
5213
|
severity: "info",
|
|
5206
5214
|
message: "Output preview differs",
|
|
5207
|
-
path:
|
|
5215
|
+
path: path44,
|
|
5208
5216
|
left: L.outputPreview,
|
|
5209
5217
|
right: R.outputPreview
|
|
5210
5218
|
});
|
|
@@ -5371,11 +5379,11 @@ var init_engine = __esm({
|
|
|
5371
5379
|
});
|
|
5372
5380
|
|
|
5373
5381
|
// packages/core/src/diff/renderer.ts
|
|
5374
|
-
function formatPath(
|
|
5375
|
-
if (
|
|
5382
|
+
function formatPath(path44) {
|
|
5383
|
+
if (path44 === void 0 || path44.path.length === 0) {
|
|
5376
5384
|
return "(run)";
|
|
5377
5385
|
}
|
|
5378
|
-
return
|
|
5386
|
+
return path44.path.map((s) => s.name).join(" > ");
|
|
5379
5387
|
}
|
|
5380
5388
|
function formatValue(v, verbose) {
|
|
5381
5389
|
if (v === void 0) return "(undefined)";
|
|
@@ -5755,11 +5763,11 @@ async function listFilesRecursive(root) {
|
|
|
5755
5763
|
async function walk(dir) {
|
|
5756
5764
|
const entries = await promises.readdir(dir, { withFileTypes: true });
|
|
5757
5765
|
for (const entry of entries) {
|
|
5758
|
-
const abs =
|
|
5766
|
+
const abs = path33__default.default.join(dir, entry.name);
|
|
5759
5767
|
if (entry.isDirectory()) {
|
|
5760
5768
|
await walk(abs);
|
|
5761
5769
|
} else if (entry.isFile()) {
|
|
5762
|
-
const rel =
|
|
5770
|
+
const rel = path33__default.default.relative(root, abs).split(path33__default.default.sep).join("/");
|
|
5763
5771
|
out.push(rel);
|
|
5764
5772
|
}
|
|
5765
5773
|
}
|
|
@@ -5769,7 +5777,7 @@ async function listFilesRecursive(root) {
|
|
|
5769
5777
|
}
|
|
5770
5778
|
async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
5771
5779
|
const unexpectedMode = options.unexpectedFiles ?? "fail";
|
|
5772
|
-
const root =
|
|
5780
|
+
const root = path33__default.default.resolve(rootPath);
|
|
5773
5781
|
const issues = [];
|
|
5774
5782
|
let rootStat;
|
|
5775
5783
|
try {
|
|
@@ -5799,7 +5807,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
|
5799
5807
|
checkedFiles: 0
|
|
5800
5808
|
};
|
|
5801
5809
|
}
|
|
5802
|
-
const manifestPath =
|
|
5810
|
+
const manifestPath = path33__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
|
|
5803
5811
|
let manifestText;
|
|
5804
5812
|
try {
|
|
5805
5813
|
manifestText = await promises.readFile(manifestPath, "utf-8");
|
|
@@ -5885,7 +5893,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
|
|
|
5885
5893
|
continue;
|
|
5886
5894
|
}
|
|
5887
5895
|
listed.add(rel);
|
|
5888
|
-
const abs =
|
|
5896
|
+
const abs = path33__default.default.join(root, ...rel.split("/"));
|
|
5889
5897
|
let bytes;
|
|
5890
5898
|
try {
|
|
5891
5899
|
bytes = await promises.readFile(abs);
|
|
@@ -6200,7 +6208,7 @@ function normalizeSuiteConfig(value) {
|
|
|
6200
6208
|
}
|
|
6201
6209
|
async function validateSuiteConfig(config, options) {
|
|
6202
6210
|
const diagnostics = [];
|
|
6203
|
-
const tracesDir =
|
|
6211
|
+
const tracesDir = path33__default.default.resolve(options.configDir, config.traces);
|
|
6204
6212
|
try {
|
|
6205
6213
|
await promises.access(tracesDir);
|
|
6206
6214
|
} catch {
|
|
@@ -6210,7 +6218,7 @@ async function validateSuiteConfig(config, options) {
|
|
|
6210
6218
|
}
|
|
6211
6219
|
for (const suiteCase of config.cases) {
|
|
6212
6220
|
if (suiteCase.input !== void 0) {
|
|
6213
|
-
const inputPath =
|
|
6221
|
+
const inputPath = path33__default.default.resolve(options.configDir, suiteCase.input);
|
|
6214
6222
|
try {
|
|
6215
6223
|
await promises.access(inputPath);
|
|
6216
6224
|
} catch {
|
|
@@ -6243,12 +6251,12 @@ async function fileExists(filePath) {
|
|
|
6243
6251
|
}
|
|
6244
6252
|
}
|
|
6245
6253
|
async function resolveSuiteConfigPath(options = {}) {
|
|
6246
|
-
const cwd =
|
|
6254
|
+
const cwd = path33__default.default.resolve(options.cwd ?? process.cwd());
|
|
6247
6255
|
if (options.configPath !== void 0 && options.configPath.trim() !== "") {
|
|
6248
|
-
return
|
|
6256
|
+
return path33__default.default.resolve(cwd, options.configPath.trim());
|
|
6249
6257
|
}
|
|
6250
6258
|
for (const name of DEFAULT_SUITE_CONFIG_NAMES) {
|
|
6251
|
-
const candidate =
|
|
6259
|
+
const candidate = path33__default.default.join(cwd, name);
|
|
6252
6260
|
if (await fileExists(candidate)) return candidate;
|
|
6253
6261
|
}
|
|
6254
6262
|
throw new Error(
|
|
@@ -6265,7 +6273,7 @@ async function loadSuiteConfig(options = {}) {
|
|
|
6265
6273
|
diagnostics: [diagnostic2("AI_SUITE_CONFIG_LOAD_FAILED", message)]
|
|
6266
6274
|
});
|
|
6267
6275
|
}
|
|
6268
|
-
const extension =
|
|
6276
|
+
const extension = path33__default.default.extname(configPath);
|
|
6269
6277
|
if (TS_CONFIG_EXTENSIONS.has(extension)) {
|
|
6270
6278
|
const message = "TypeScript suite configs require an explicit precompiled JavaScript config or future --config-loader support.";
|
|
6271
6279
|
throw Object.assign(new Error(message), {
|
|
@@ -6290,7 +6298,7 @@ async function loadSuiteConfig(options = {}) {
|
|
|
6290
6298
|
return {
|
|
6291
6299
|
config,
|
|
6292
6300
|
configPath,
|
|
6293
|
-
configDir:
|
|
6301
|
+
configDir: path33__default.default.dirname(configPath)
|
|
6294
6302
|
};
|
|
6295
6303
|
} catch (error) {
|
|
6296
6304
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -6340,7 +6348,7 @@ async function exists(filePath) {
|
|
|
6340
6348
|
}
|
|
6341
6349
|
async function resolveSuiteCaseTrace(suiteCase, options) {
|
|
6342
6350
|
if (suiteCase.trace !== void 0) {
|
|
6343
|
-
const tracePath =
|
|
6351
|
+
const tracePath = path33__default.default.resolve(options.configDir, suiteCase.trace);
|
|
6344
6352
|
if (await exists(tracePath)) {
|
|
6345
6353
|
return { caseId: suiteCase.id, tracePath, missing: false };
|
|
6346
6354
|
}
|
|
@@ -6356,7 +6364,7 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
|
|
|
6356
6364
|
if (await exists(directPath)) {
|
|
6357
6365
|
return { caseId: suiteCase.id, tracePath: directPath, runId: runKey, missing: false };
|
|
6358
6366
|
}
|
|
6359
|
-
const nestedPath =
|
|
6367
|
+
const nestedPath = path33__default.default.join(options.tracesDir, `${path33__default.default.basename(runKey)}.jsonl`);
|
|
6360
6368
|
if (await exists(nestedPath)) {
|
|
6361
6369
|
return { caseId: suiteCase.id, tracePath: nestedPath, runId: runKey, missing: false };
|
|
6362
6370
|
}
|
|
@@ -6812,6 +6820,330 @@ var init_logical_events = __esm({
|
|
|
6812
6820
|
}
|
|
6813
6821
|
});
|
|
6814
6822
|
|
|
6823
|
+
// packages/core/src/checks/derived-failure.ts
|
|
6824
|
+
function isRecord8(value) {
|
|
6825
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6826
|
+
}
|
|
6827
|
+
function pickString2(record, keys) {
|
|
6828
|
+
if (!record) return void 0;
|
|
6829
|
+
for (const key of keys) {
|
|
6830
|
+
const value = record[key];
|
|
6831
|
+
if (typeof value === "string" && value.trim() !== "") return value;
|
|
6832
|
+
}
|
|
6833
|
+
return void 0;
|
|
6834
|
+
}
|
|
6835
|
+
function pickNumber(record, keys) {
|
|
6836
|
+
if (!record) return void 0;
|
|
6837
|
+
for (const key of keys) {
|
|
6838
|
+
const value = record[key];
|
|
6839
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
6840
|
+
return value;
|
|
6841
|
+
}
|
|
6842
|
+
}
|
|
6843
|
+
return void 0;
|
|
6844
|
+
}
|
|
6845
|
+
function eventMetadata(event) {
|
|
6846
|
+
const attrs = isRecord8(event.attributes) ? event.attributes : void 0;
|
|
6847
|
+
const nested = attrs !== void 0 && isRecord8(attrs.metadata) ? attrs.metadata : void 0;
|
|
6848
|
+
return {
|
|
6849
|
+
...attrs ?? {},
|
|
6850
|
+
...nested ?? {}
|
|
6851
|
+
};
|
|
6852
|
+
}
|
|
6853
|
+
function canonicalName(event) {
|
|
6854
|
+
if (event.kind === "TOOL") return resolveCanonicalToolName(event);
|
|
6855
|
+
return event.name;
|
|
6856
|
+
}
|
|
6857
|
+
function linkKeys(event) {
|
|
6858
|
+
const meta2 = eventMetadata(event);
|
|
6859
|
+
const keys = [];
|
|
6860
|
+
for (const key of ["linkedStepId", "toolCallId", "mcpToolCallId"]) {
|
|
6861
|
+
const value = pickString2(meta2, [key]);
|
|
6862
|
+
if (value !== void 0) keys.push(`${key}:${value}`);
|
|
6863
|
+
}
|
|
6864
|
+
const stepId = pickString2(meta2, ["stepId"]);
|
|
6865
|
+
if (stepId !== void 0) keys.push(`stepId:${stepId}`);
|
|
6866
|
+
return keys;
|
|
6867
|
+
}
|
|
6868
|
+
function buildRunContexts(logicalEvents) {
|
|
6869
|
+
const byRun = /* @__PURE__ */ new Map();
|
|
6870
|
+
for (const event of logicalEvents) {
|
|
6871
|
+
const existing = byRun.get(event.runId) ?? {
|
|
6872
|
+
runId: event.runId,
|
|
6873
|
+
name: event.name
|
|
6874
|
+
};
|
|
6875
|
+
const meta2 = eventMetadata(event);
|
|
6876
|
+
if (event.kind === "RUN" || existing.name === event.runId) {
|
|
6877
|
+
existing.name = event.name || existing.name;
|
|
6878
|
+
}
|
|
6879
|
+
if (event.kind === "RUN" && event.status !== void 0 && event.status !== "running") {
|
|
6880
|
+
existing.status = event.status;
|
|
6881
|
+
}
|
|
6882
|
+
existing.retryOf ??= pickString2(meta2, ["retryOf"]);
|
|
6883
|
+
existing.attempt ??= pickNumber(meta2, ["attempt", "retryAttempt", "retryCount"]);
|
|
6884
|
+
existing.sessionId ??= pickString2(meta2, ["sessionId", "conversationId"]);
|
|
6885
|
+
existing.groupId ??= pickString2(meta2, ["groupId"]);
|
|
6886
|
+
existing.parentGroupId ??= pickString2(meta2, ["parentGroupId"]);
|
|
6887
|
+
existing.fallbackOf ??= pickString2(meta2, ["fallbackOf", "fallbackFrom"]);
|
|
6888
|
+
byRun.set(event.runId, existing);
|
|
6889
|
+
}
|
|
6890
|
+
return byRun;
|
|
6891
|
+
}
|
|
6892
|
+
function sameCorrelationScope(a, b) {
|
|
6893
|
+
if (a.sessionId && b.sessionId && a.sessionId === b.sessionId) return true;
|
|
6894
|
+
if (a.groupId && b.groupId && a.groupId === b.groupId) return true;
|
|
6895
|
+
if (a.parentGroupId && b.parentGroupId && a.parentGroupId === b.parentGroupId) {
|
|
6896
|
+
return true;
|
|
6897
|
+
}
|
|
6898
|
+
return false;
|
|
6899
|
+
}
|
|
6900
|
+
function isSuccessful(event) {
|
|
6901
|
+
return event.status === "ok";
|
|
6902
|
+
}
|
|
6903
|
+
function isFailure(event) {
|
|
6904
|
+
return event.status === "error";
|
|
6905
|
+
}
|
|
6906
|
+
function compareEventOrder(a, b) {
|
|
6907
|
+
const byTime = a.timestamp.localeCompare(b.timestamp);
|
|
6908
|
+
if (byTime !== 0) return byTime;
|
|
6909
|
+
return a.eventId.localeCompare(b.eventId);
|
|
6910
|
+
}
|
|
6911
|
+
function collectCandidates(failure, logicalEvents, runs) {
|
|
6912
|
+
const failureRun = runs.get(failure.runId);
|
|
6913
|
+
const failureLinks = new Set(linkKeys(failure));
|
|
6914
|
+
const failureName = canonicalName(failure);
|
|
6915
|
+
const failureAttempt = pickNumber(eventMetadata(failure), ["attempt", "retryAttempt", "retryCount"]) ?? failureRun?.attempt;
|
|
6916
|
+
const candidates = [];
|
|
6917
|
+
for (const event of logicalEvents) {
|
|
6918
|
+
if (event.eventId === failure.eventId) continue;
|
|
6919
|
+
if (event.status === "running") continue;
|
|
6920
|
+
const eventRun = runs.get(event.runId);
|
|
6921
|
+
const eventMeta = eventMetadata(event);
|
|
6922
|
+
const sameRun = event.runId === failure.runId;
|
|
6923
|
+
if (eventRun?.retryOf === failure.runId) {
|
|
6924
|
+
candidates.push({
|
|
6925
|
+
event,
|
|
6926
|
+
basis: "retryOf",
|
|
6927
|
+
confidence: "explicit",
|
|
6928
|
+
viaRunId: event.runId
|
|
6929
|
+
});
|
|
6930
|
+
continue;
|
|
6931
|
+
}
|
|
6932
|
+
if (eventRun?.fallbackOf === failure.runId || pickString2(eventMeta, ["fallbackOf", "fallbackFrom"]) === failure.runId) {
|
|
6933
|
+
candidates.push({
|
|
6934
|
+
event,
|
|
6935
|
+
basis: "fallbackOf",
|
|
6936
|
+
confidence: "explicit",
|
|
6937
|
+
viaRunId: event.runId
|
|
6938
|
+
});
|
|
6939
|
+
continue;
|
|
6940
|
+
}
|
|
6941
|
+
if (sameRun && compareEventOrder(failure, event) >= 0) continue;
|
|
6942
|
+
const eventLinks = linkKeys(event);
|
|
6943
|
+
const sharedLink = eventLinks.find((key) => failureLinks.has(key));
|
|
6944
|
+
if (sharedLink !== void 0) {
|
|
6945
|
+
candidates.push({
|
|
6946
|
+
event,
|
|
6947
|
+
basis: sharedLink.split(":")[0] ?? "linkedId",
|
|
6948
|
+
confidence: "explicit"
|
|
6949
|
+
});
|
|
6950
|
+
continue;
|
|
6951
|
+
}
|
|
6952
|
+
const eventAttempt = pickNumber(eventMeta, ["attempt", "retryAttempt", "retryCount"]) ?? eventRun?.attempt;
|
|
6953
|
+
const sameParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId === event.parentId;
|
|
6954
|
+
const differentParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId !== event.parentId;
|
|
6955
|
+
const sessionScoped = failureRun !== void 0 && eventRun !== void 0 && sameCorrelationScope(failureRun, eventRun);
|
|
6956
|
+
if (canonicalName(event) === failureName && failureAttempt !== void 0 && eventAttempt !== void 0 && eventAttempt > failureAttempt && !differentParent && (sameParent || sessionScoped || sameRun)) {
|
|
6957
|
+
candidates.push({
|
|
6958
|
+
event,
|
|
6959
|
+
basis: "attempt-progression",
|
|
6960
|
+
confidence: "correlated",
|
|
6961
|
+
...event.runId !== failure.runId ? { viaRunId: event.runId } : {}
|
|
6962
|
+
});
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6965
|
+
const byId = /* @__PURE__ */ new Map();
|
|
6966
|
+
for (const candidate of candidates) {
|
|
6967
|
+
const prev = byId.get(candidate.event.eventId);
|
|
6968
|
+
if (!prev || prev.confidence !== "explicit" && candidate.confidence === "explicit") {
|
|
6969
|
+
byId.set(candidate.event.eventId, candidate);
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6972
|
+
return [...byId.values()].sort((a, b) => compareEventOrder(a.event, b.event));
|
|
6973
|
+
}
|
|
6974
|
+
function classifyFailure(failure, candidates, runs, logicalEvents) {
|
|
6975
|
+
const successful = candidates.filter((c) => isSuccessful(c.event));
|
|
6976
|
+
const unsuccessful = candidates.filter((c) => !isSuccessful(c.event));
|
|
6977
|
+
const retryRunIds = Object.freeze(
|
|
6978
|
+
[...new Set(candidates.map((c) => c.viaRunId).filter((id) => id !== void 0))].sort(
|
|
6979
|
+
(a, b) => a.localeCompare(b)
|
|
6980
|
+
)
|
|
6981
|
+
);
|
|
6982
|
+
if (successful.length > 1) {
|
|
6983
|
+
const distinctRuns = new Set(successful.map((c) => c.event.runId));
|
|
6984
|
+
const distinctParents = new Set(
|
|
6985
|
+
successful.map((c) => c.event.parentId ?? "").filter((id) => id !== "")
|
|
6986
|
+
);
|
|
6987
|
+
if (distinctRuns.size > 1 || distinctParents.size > 1) {
|
|
6988
|
+
return {
|
|
6989
|
+
eventId: failure.eventId,
|
|
6990
|
+
runId: failure.runId,
|
|
6991
|
+
name: failure.name,
|
|
6992
|
+
kind: failure.kind,
|
|
6993
|
+
role: "unknown",
|
|
6994
|
+
confidence: "unknown",
|
|
6995
|
+
basis: Object.freeze(["ambiguous-recovery-candidates"]),
|
|
6996
|
+
recoveryEventIds: Object.freeze(
|
|
6997
|
+
successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
|
|
6998
|
+
),
|
|
6999
|
+
retryRunIds
|
|
7000
|
+
};
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
7003
|
+
if (successful.length >= 1) {
|
|
7004
|
+
const best = successful[0];
|
|
7005
|
+
return {
|
|
7006
|
+
eventId: failure.eventId,
|
|
7007
|
+
runId: failure.runId,
|
|
7008
|
+
name: failure.name,
|
|
7009
|
+
kind: failure.kind,
|
|
7010
|
+
role: "recovered",
|
|
7011
|
+
confidence: best.confidence,
|
|
7012
|
+
basis: Object.freeze([best.basis]),
|
|
7013
|
+
recoveryEventIds: Object.freeze(
|
|
7014
|
+
successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
|
|
7015
|
+
),
|
|
7016
|
+
retryRunIds
|
|
7017
|
+
};
|
|
7018
|
+
}
|
|
7019
|
+
if (candidates.length > 0) {
|
|
7020
|
+
const best = candidates[0];
|
|
7021
|
+
return {
|
|
7022
|
+
eventId: failure.eventId,
|
|
7023
|
+
runId: failure.runId,
|
|
7024
|
+
name: failure.name,
|
|
7025
|
+
kind: failure.kind,
|
|
7026
|
+
role: "transient",
|
|
7027
|
+
confidence: best.confidence,
|
|
7028
|
+
basis: Object.freeze([
|
|
7029
|
+
best.basis,
|
|
7030
|
+
unsuccessful.some((c) => c.event.status === void 0) ? "retry-incomplete" : "retry-without-success"
|
|
7031
|
+
]),
|
|
7032
|
+
recoveryEventIds: Object.freeze([]),
|
|
7033
|
+
retryRunIds
|
|
7034
|
+
};
|
|
7035
|
+
}
|
|
7036
|
+
const failureMeta = eventMetadata(failure);
|
|
7037
|
+
const declaredSuccessor = pickString2(failureMeta, [
|
|
7038
|
+
"retriedBy",
|
|
7039
|
+
"nextRetryRunId",
|
|
7040
|
+
"retryRunId"
|
|
7041
|
+
]);
|
|
7042
|
+
if (declaredSuccessor !== void 0 && !runs.has(declaredSuccessor)) {
|
|
7043
|
+
return {
|
|
7044
|
+
eventId: failure.eventId,
|
|
7045
|
+
runId: failure.runId,
|
|
7046
|
+
name: failure.name,
|
|
7047
|
+
kind: failure.kind,
|
|
7048
|
+
role: "transient",
|
|
7049
|
+
confidence: "explicit",
|
|
7050
|
+
basis: Object.freeze(["retry-declared", "retry-run-missing"]),
|
|
7051
|
+
recoveryEventIds: Object.freeze([]),
|
|
7052
|
+
retryRunIds: Object.freeze([declaredSuccessor])
|
|
7053
|
+
};
|
|
7054
|
+
}
|
|
7055
|
+
for (const run of runs.values()) {
|
|
7056
|
+
if (run.retryOf === failure.runId) {
|
|
7057
|
+
return {
|
|
7058
|
+
eventId: failure.eventId,
|
|
7059
|
+
runId: failure.runId,
|
|
7060
|
+
name: failure.name,
|
|
7061
|
+
kind: failure.kind,
|
|
7062
|
+
role: "transient",
|
|
7063
|
+
confidence: "explicit",
|
|
7064
|
+
basis: Object.freeze(["retryOf", "retry-run-missing-or-empty"]),
|
|
7065
|
+
recoveryEventIds: Object.freeze([]),
|
|
7066
|
+
retryRunIds: Object.freeze([run.runId])
|
|
7067
|
+
};
|
|
7068
|
+
}
|
|
7069
|
+
}
|
|
7070
|
+
const failureRun = runs.get(failure.runId);
|
|
7071
|
+
const hasSuccessorDeclared = [...runs.values()].some((run) => run.retryOf === failure.runId);
|
|
7072
|
+
const isFinalInChain = failureRun !== void 0 && !hasSuccessorDeclared && (failureRun.retryOf !== void 0 || failureRun.attempt !== void 0 && failureRun.attempt > 1 || pickNumber(eventMetadata(failure), ["attempt"]) !== void 0);
|
|
7073
|
+
if (isFinalInChain && failureRun?.status === "error" && !logicalEvents.some(
|
|
7074
|
+
(event) => event.runId === failure.runId && event.eventId !== failure.eventId && isSuccessful(event) && canonicalName(event) === canonicalName(failure)
|
|
7075
|
+
)) {
|
|
7076
|
+
return {
|
|
7077
|
+
eventId: failure.eventId,
|
|
7078
|
+
runId: failure.runId,
|
|
7079
|
+
name: failure.name,
|
|
7080
|
+
kind: failure.kind,
|
|
7081
|
+
role: "terminal",
|
|
7082
|
+
confidence: failureRun.retryOf !== void 0 ? "explicit" : "correlated",
|
|
7083
|
+
basis: Object.freeze(["final-retry-chain-member", "enclosing-run-error"]),
|
|
7084
|
+
recoveryEventIds: Object.freeze([]),
|
|
7085
|
+
retryRunIds: Object.freeze(
|
|
7086
|
+
failureRun.retryOf !== void 0 ? [failureRun.retryOf] : []
|
|
7087
|
+
)
|
|
7088
|
+
};
|
|
7089
|
+
}
|
|
7090
|
+
return {
|
|
7091
|
+
eventId: failure.eventId,
|
|
7092
|
+
runId: failure.runId,
|
|
7093
|
+
name: failure.name,
|
|
7094
|
+
kind: failure.kind,
|
|
7095
|
+
role: "unknown",
|
|
7096
|
+
confidence: "unknown",
|
|
7097
|
+
basis: Object.freeze(["no-explicit-or-correlated-recovery"]),
|
|
7098
|
+
recoveryEventIds: Object.freeze([]),
|
|
7099
|
+
retryRunIds: Object.freeze([])
|
|
7100
|
+
};
|
|
7101
|
+
}
|
|
7102
|
+
function deriveFailureFacts(logicalEvents) {
|
|
7103
|
+
const runs = buildRunContexts(logicalEvents);
|
|
7104
|
+
const failures = logicalEvents.filter((event) => isFailure(event)).sort(compareEventOrder);
|
|
7105
|
+
const failureFacts = failures.map(
|
|
7106
|
+
(failure) => classifyFailure(failure, collectCandidates(failure, logicalEvents, runs), runs, logicalEvents)
|
|
7107
|
+
);
|
|
7108
|
+
const byRole = /* @__PURE__ */ new Map([
|
|
7109
|
+
["transient", []],
|
|
7110
|
+
["recovered", []],
|
|
7111
|
+
["terminal", []],
|
|
7112
|
+
["unknown", []]
|
|
7113
|
+
]);
|
|
7114
|
+
for (const fact2 of failureFacts) {
|
|
7115
|
+
byRole.get(fact2.role).push(fact2);
|
|
7116
|
+
}
|
|
7117
|
+
for (const [role, list2] of byRole) {
|
|
7118
|
+
byRole.set(
|
|
7119
|
+
role,
|
|
7120
|
+
Object.freeze(
|
|
7121
|
+
[...list2].sort((a, b) => {
|
|
7122
|
+
const byRun = a.runId.localeCompare(b.runId);
|
|
7123
|
+
if (byRun !== 0) return byRun;
|
|
7124
|
+
return a.eventId.localeCompare(b.eventId);
|
|
7125
|
+
})
|
|
7126
|
+
)
|
|
7127
|
+
);
|
|
7128
|
+
}
|
|
7129
|
+
const failureRoleCounts = {
|
|
7130
|
+
transient: byRole.get("transient").length,
|
|
7131
|
+
recovered: byRole.get("recovered").length,
|
|
7132
|
+
terminal: byRole.get("terminal").length,
|
|
7133
|
+
unknown: byRole.get("unknown").length
|
|
7134
|
+
};
|
|
7135
|
+
return {
|
|
7136
|
+
failureFacts: Object.freeze(failureFacts),
|
|
7137
|
+
failuresByRole: byRole,
|
|
7138
|
+
failureRoleCounts
|
|
7139
|
+
};
|
|
7140
|
+
}
|
|
7141
|
+
var init_derived_failure = __esm({
|
|
7142
|
+
"packages/core/src/checks/derived-failure.ts"() {
|
|
7143
|
+
init_logical_events();
|
|
7144
|
+
}
|
|
7145
|
+
});
|
|
7146
|
+
|
|
6815
7147
|
// packages/core/src/checks/trace-facts.ts
|
|
6816
7148
|
function summarizeSemanticParity(events) {
|
|
6817
7149
|
const projection = projectLogicalEvents(events);
|
|
@@ -6822,6 +7154,7 @@ function summarizeSemanticParity(events) {
|
|
|
6822
7154
|
const finishedToolNames = Object.freeze(
|
|
6823
7155
|
finishedTools.map((event) => resolveCanonicalToolName(event)).sort((a, b) => a.localeCompare(b))
|
|
6824
7156
|
);
|
|
7157
|
+
const derived = deriveFailureFacts(logical);
|
|
6825
7158
|
return {
|
|
6826
7159
|
rawEventCount: events.length,
|
|
6827
7160
|
logicalEventCount: logical.length,
|
|
@@ -6832,13 +7165,16 @@ function summarizeSemanticParity(events) {
|
|
|
6832
7165
|
parentRemapCount: projection.diagnostics.filter(
|
|
6833
7166
|
(item) => item.code === "AI_LOGICAL_PARENT_REMAPPED"
|
|
6834
7167
|
).length,
|
|
6835
|
-
diagnostics: projection.diagnostics
|
|
7168
|
+
diagnostics: projection.diagnostics,
|
|
7169
|
+
failureRoleCounts: derived.failureRoleCounts
|
|
6836
7170
|
};
|
|
6837
7171
|
}
|
|
6838
7172
|
var init_trace_facts = __esm({
|
|
6839
7173
|
"packages/core/src/checks/trace-facts.ts"() {
|
|
6840
7174
|
init_programmatic();
|
|
7175
|
+
init_derived_failure();
|
|
6841
7176
|
init_logical_events();
|
|
7177
|
+
init_derived_failure();
|
|
6842
7178
|
formatProgrammaticDiagnostic(
|
|
6843
7179
|
"AI_TRACE_FACTS_INPUT_NOT_NORMALIZED"
|
|
6844
7180
|
);
|
|
@@ -7106,7 +7442,7 @@ function stripPrefix(name, prefixes) {
|
|
|
7106
7442
|
}
|
|
7107
7443
|
return name;
|
|
7108
7444
|
}
|
|
7109
|
-
function eventEvidence(event,
|
|
7445
|
+
function eventEvidence(event, path44) {
|
|
7110
7446
|
return {
|
|
7111
7447
|
runId: event.runId,
|
|
7112
7448
|
eventId: event.eventId,
|
|
@@ -7116,7 +7452,7 @@ function eventEvidence(event, path43) {
|
|
|
7116
7452
|
kind: event.kind,
|
|
7117
7453
|
name: event.name,
|
|
7118
7454
|
status: event.status,
|
|
7119
|
-
...
|
|
7455
|
+
...path44 ? { path: path44 } : {}
|
|
7120
7456
|
};
|
|
7121
7457
|
}
|
|
7122
7458
|
function runEvidence(run) {
|
|
@@ -7166,7 +7502,7 @@ function finishedEvents(context, kind) {
|
|
|
7166
7502
|
function toolInvocationEvents(context) {
|
|
7167
7503
|
return semanticEvents(context).filter((event) => event.kind === "TOOL");
|
|
7168
7504
|
}
|
|
7169
|
-
function
|
|
7505
|
+
function isRecord9(value) {
|
|
7170
7506
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7171
7507
|
}
|
|
7172
7508
|
function eventMap(events) {
|
|
@@ -7192,9 +7528,9 @@ function eventEndMs(event) {
|
|
|
7192
7528
|
function normalizedKey(value) {
|
|
7193
7529
|
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
7194
7530
|
}
|
|
7195
|
-
function lastPathSegment(
|
|
7196
|
-
const parts =
|
|
7197
|
-
return parts[parts.length - 1] ??
|
|
7531
|
+
function lastPathSegment(path44) {
|
|
7532
|
+
const parts = path44.split(".");
|
|
7533
|
+
return parts[parts.length - 1] ?? path44;
|
|
7198
7534
|
}
|
|
7199
7535
|
function valueType(value) {
|
|
7200
7536
|
if (Array.isArray(value)) return "array";
|
|
@@ -7208,22 +7544,22 @@ function serializedByteLength(value) {
|
|
|
7208
7544
|
return void 0;
|
|
7209
7545
|
}
|
|
7210
7546
|
}
|
|
7211
|
-
function pushValueEntries(entries, event, value,
|
|
7212
|
-
entries.push({ event, path:
|
|
7547
|
+
function pushValueEntries(entries, event, value, path44, key, depth = 0) {
|
|
7548
|
+
entries.push({ event, path: path44, key, value });
|
|
7213
7549
|
if (depth >= 8) return;
|
|
7214
7550
|
if (Array.isArray(value)) {
|
|
7215
7551
|
for (const [index, item] of value.entries()) {
|
|
7216
|
-
pushValueEntries(entries, event, item, `${
|
|
7552
|
+
pushValueEntries(entries, event, item, `${path44}.${index}`, String(index), depth + 1);
|
|
7217
7553
|
}
|
|
7218
7554
|
return;
|
|
7219
7555
|
}
|
|
7220
|
-
if (!
|
|
7556
|
+
if (!isRecord9(value)) return;
|
|
7221
7557
|
for (const nestedKey of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
|
|
7222
7558
|
pushValueEntries(
|
|
7223
7559
|
entries,
|
|
7224
7560
|
event,
|
|
7225
7561
|
value[nestedKey],
|
|
7226
|
-
`${
|
|
7562
|
+
`${path44}.${nestedKey}`,
|
|
7227
7563
|
nestedKey,
|
|
7228
7564
|
depth + 1
|
|
7229
7565
|
);
|
|
@@ -7262,18 +7598,18 @@ function isRawContentKey(key, forbiddenKeys) {
|
|
|
7262
7598
|
const normalized = normalizedKey(key);
|
|
7263
7599
|
return forbiddenKeys.some((forbidden) => normalized === normalizedKey(forbidden));
|
|
7264
7600
|
}
|
|
7265
|
-
function isSafeRawContentMetricPath(
|
|
7266
|
-
const leaf = normalizedKey(key ?? lastPathSegment(
|
|
7601
|
+
function isSafeRawContentMetricPath(path44, key, safePathPrefixes) {
|
|
7602
|
+
const leaf = normalizedKey(key ?? lastPathSegment(path44));
|
|
7267
7603
|
if (!SAFE_USAGE_LEAF_KEYS.has(leaf)) return false;
|
|
7268
|
-
const parts =
|
|
7604
|
+
const parts = path44.split(".").filter(Boolean);
|
|
7269
7605
|
if (parts.length < 2) return false;
|
|
7270
7606
|
const parent = parts[parts.length - 2] ?? "";
|
|
7271
7607
|
const parentNorm = normalizedKey(parent);
|
|
7272
7608
|
return safePathPrefixes.some((prefix) => parentNorm === normalizedKey(prefix));
|
|
7273
7609
|
}
|
|
7274
|
-
function isRawContentPath(
|
|
7275
|
-
if (isSafeRawContentMetricPath(
|
|
7276
|
-
return isRawContentKey(key ?? lastPathSegment(
|
|
7610
|
+
function isRawContentPath(path44, key, forbiddenKeys, safePathPrefixes) {
|
|
7611
|
+
if (isSafeRawContentMetricPath(path44, key, safePathPrefixes)) return false;
|
|
7612
|
+
return isRawContentKey(key ?? lastPathSegment(path44), forbiddenKeys);
|
|
7277
7613
|
}
|
|
7278
7614
|
function parentMarkedUnresolved(event) {
|
|
7279
7615
|
if (booleanAttr(event, [
|
|
@@ -7312,9 +7648,9 @@ function eventDurationMs(event) {
|
|
|
7312
7648
|
}
|
|
7313
7649
|
function treeShape(nodes) {
|
|
7314
7650
|
const lines = [];
|
|
7315
|
-
const visit = (node,
|
|
7316
|
-
lines.push(`${
|
|
7317
|
-
node.children.forEach((child, index) => visit(child, `${
|
|
7651
|
+
const visit = (node, path44) => {
|
|
7652
|
+
lines.push(`${path44}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
|
|
7653
|
+
node.children.forEach((child, index) => visit(child, `${path44}.${index}`));
|
|
7318
7654
|
};
|
|
7319
7655
|
nodes.forEach((node, index) => visit(node, String(index)));
|
|
7320
7656
|
return lines;
|
|
@@ -7363,9 +7699,9 @@ function retrievalShape(context) {
|
|
|
7363
7699
|
function guardrailShape(context) {
|
|
7364
7700
|
return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
|
|
7365
7701
|
}
|
|
7366
|
-
function firstEvidenceForKind(context, kind,
|
|
7702
|
+
function firstEvidenceForKind(context, kind, path44) {
|
|
7367
7703
|
const event = semanticEvents(context).find((candidate) => candidate.kind === kind);
|
|
7368
|
-
return event ? [eventEvidence(event,
|
|
7704
|
+
return event ? [eventEvidence(event, path44)] : runEvidence(context.selectedRun);
|
|
7369
7705
|
}
|
|
7370
7706
|
function baselineDiffFinding(message, evidence, expected, actual) {
|
|
7371
7707
|
return failFinding("baseline.regression", message, evidence, expected, actual);
|
|
@@ -7715,13 +8051,13 @@ function createStructureCycleRule() {
|
|
|
7715
8051
|
const seenCycles = /* @__PURE__ */ new Set();
|
|
7716
8052
|
const findings = [];
|
|
7717
8053
|
for (const event of [...semanticEvents(context)].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
|
|
7718
|
-
const
|
|
8054
|
+
const path44 = [];
|
|
7719
8055
|
const seenAt = /* @__PURE__ */ new Map();
|
|
7720
8056
|
let current = event;
|
|
7721
8057
|
while (current) {
|
|
7722
8058
|
const existing = seenAt.get(current.eventId);
|
|
7723
8059
|
if (existing !== void 0) {
|
|
7724
|
-
const cycle =
|
|
8060
|
+
const cycle = path44.slice(existing);
|
|
7725
8061
|
const key = cycle.map((item) => item.eventId).sort().join("\0");
|
|
7726
8062
|
if (!seenCycles.has(key)) {
|
|
7727
8063
|
seenCycles.add(key);
|
|
@@ -7737,8 +8073,8 @@ function createStructureCycleRule() {
|
|
|
7737
8073
|
}
|
|
7738
8074
|
break;
|
|
7739
8075
|
}
|
|
7740
|
-
seenAt.set(current.eventId,
|
|
7741
|
-
|
|
8076
|
+
seenAt.set(current.eventId, path44.length);
|
|
8077
|
+
path44.push(current);
|
|
7742
8078
|
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
7743
8079
|
}
|
|
7744
8080
|
}
|
|
@@ -8043,7 +8379,7 @@ function createSafetyOversizedAttributeRule(options) {
|
|
|
8043
8379
|
)
|
|
8044
8380
|
);
|
|
8045
8381
|
}
|
|
8046
|
-
if (
|
|
8382
|
+
if (isRecord9(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
|
|
8047
8383
|
findings.push(
|
|
8048
8384
|
failFinding(
|
|
8049
8385
|
"safety.oversizedAttribute",
|
|
@@ -8429,14 +8765,14 @@ var init_checks2 = __esm({
|
|
|
8429
8765
|
});
|
|
8430
8766
|
|
|
8431
8767
|
// packages/core/src/persisted/token-usage.ts
|
|
8432
|
-
function
|
|
8768
|
+
function isRecord10(value) {
|
|
8433
8769
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8434
8770
|
}
|
|
8435
8771
|
function nonNegativeFinite(value) {
|
|
8436
8772
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
8437
8773
|
}
|
|
8438
8774
|
function normalizeTokenUsage(value) {
|
|
8439
|
-
if (!
|
|
8775
|
+
if (!isRecord10(value)) return void 0;
|
|
8440
8776
|
const input3 = nonNegativeFinite(value.input);
|
|
8441
8777
|
const output2 = nonNegativeFinite(value.output);
|
|
8442
8778
|
const suppliedTotal = nonNegativeFinite(value.total);
|
|
@@ -9117,7 +9453,7 @@ function findReaderByFormat(format, readers) {
|
|
|
9117
9453
|
}
|
|
9118
9454
|
async function jsonlFilesInDirectory(dirPath) {
|
|
9119
9455
|
const entries = await promises.readdir(dirPath, { withFileTypes: true });
|
|
9120
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) =>
|
|
9456
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path33__default.default.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
|
|
9121
9457
|
}
|
|
9122
9458
|
async function resolveInput(input3) {
|
|
9123
9459
|
const cached2 = resolvedInputCache.get(input3);
|
|
@@ -9266,7 +9602,7 @@ function persistedEventsForParsedTrace(parsed) {
|
|
|
9266
9602
|
sourceName: "agent-inspect-jsonl-reader"
|
|
9267
9603
|
});
|
|
9268
9604
|
}
|
|
9269
|
-
function
|
|
9605
|
+
function isRecord11(value) {
|
|
9270
9606
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9271
9607
|
}
|
|
9272
9608
|
function isNonEmptyString4(value) {
|
|
@@ -9281,13 +9617,13 @@ function readStringField(record, keys) {
|
|
|
9281
9617
|
}
|
|
9282
9618
|
function readRecordField(record, key) {
|
|
9283
9619
|
const value = record[key];
|
|
9284
|
-
return
|
|
9620
|
+
return isRecord11(value) ? value : void 0;
|
|
9285
9621
|
}
|
|
9286
9622
|
function parseJsonDocument(content) {
|
|
9287
9623
|
return JSON.parse(content);
|
|
9288
9624
|
}
|
|
9289
9625
|
function looksLikeOpenInferenceSpan(value) {
|
|
9290
|
-
if (!
|
|
9626
|
+
if (!isRecord11(value)) return false;
|
|
9291
9627
|
const attributes = readRecordField(value, "attributes");
|
|
9292
9628
|
return readStringField(value, ["trace_id", "traceId"]) !== void 0 && readStringField(value, ["span_id", "spanId"]) !== void 0 && (readStringField(value, ["name"]) !== void 0 || attributes?.["openinference.span.kind"] !== void 0);
|
|
9293
9629
|
}
|
|
@@ -9312,7 +9648,7 @@ function extractOpenInferenceDocument(root) {
|
|
|
9312
9648
|
unsupportedFields
|
|
9313
9649
|
};
|
|
9314
9650
|
}
|
|
9315
|
-
if (!
|
|
9651
|
+
if (!isRecord11(root)) return void 0;
|
|
9316
9652
|
const rootFormat = root.format;
|
|
9317
9653
|
const rootCompatibility = root.compatibility;
|
|
9318
9654
|
const version2 = typeof root.version === "string" && root.version.trim() !== "" ? root.version : void 0;
|
|
@@ -9452,7 +9788,7 @@ function summarizeAttributeValue(value) {
|
|
|
9452
9788
|
if (Array.isArray(value)) {
|
|
9453
9789
|
return { type: "array", length: value.length };
|
|
9454
9790
|
}
|
|
9455
|
-
if (
|
|
9791
|
+
if (isRecord11(value)) {
|
|
9456
9792
|
return { type: "object", keyCount: Object.keys(value).length };
|
|
9457
9793
|
}
|
|
9458
9794
|
if (value === null) {
|
|
@@ -9539,7 +9875,7 @@ function mapOpenInferenceKind(span, attributes, pathPrefix) {
|
|
|
9539
9875
|
}
|
|
9540
9876
|
}
|
|
9541
9877
|
function mapOpenInferenceStatus(status) {
|
|
9542
|
-
if (!
|
|
9878
|
+
if (!isRecord11(status)) return void 0;
|
|
9543
9879
|
const rawCode = status.code;
|
|
9544
9880
|
if (typeof rawCode !== "string") return void 0;
|
|
9545
9881
|
switch (rawCode.toUpperCase()) {
|
|
@@ -9639,7 +9975,7 @@ function mapOpenInferenceSpan(span, index, version2) {
|
|
|
9639
9975
|
warnings.push(...kindWarnings);
|
|
9640
9976
|
const status = mapOpenInferenceStatus(span.status);
|
|
9641
9977
|
const tokenUsage = readOpenInferenceTokenUsage(rawAttributes);
|
|
9642
|
-
const errorMessage =
|
|
9978
|
+
const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
|
|
9643
9979
|
const event = {
|
|
9644
9980
|
schemaVersion: "0.2",
|
|
9645
9981
|
eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId,
|
|
@@ -9707,7 +10043,7 @@ function mapOpenInferenceEvents(document) {
|
|
|
9707
10043
|
};
|
|
9708
10044
|
}
|
|
9709
10045
|
function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
|
|
9710
|
-
if (!
|
|
10046
|
+
if (!isRecord11(value)) {
|
|
9711
10047
|
unsupportedFields.push(field);
|
|
9712
10048
|
warnings.push({
|
|
9713
10049
|
code: "otlp_attribute_value_invalid",
|
|
@@ -9729,15 +10065,15 @@ function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
|
|
|
9729
10065
|
if (typeof value.doubleValue === "number" && Number.isFinite(value.doubleValue)) {
|
|
9730
10066
|
return value.doubleValue;
|
|
9731
10067
|
}
|
|
9732
|
-
if (
|
|
10068
|
+
if (isRecord11(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
|
|
9733
10069
|
return value.arrayValue.values.map(
|
|
9734
10070
|
(item, index) => parseOtlpAnyValue(item, `${field}.arrayValue.values[${index}]`, warnings, unsupportedFields)
|
|
9735
10071
|
);
|
|
9736
10072
|
}
|
|
9737
|
-
if (
|
|
10073
|
+
if (isRecord11(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
|
|
9738
10074
|
const out = {};
|
|
9739
10075
|
for (const [index, item] of value.kvlistValue.values.entries()) {
|
|
9740
|
-
if (!
|
|
10076
|
+
if (!isRecord11(item) || typeof item.key !== "string") {
|
|
9741
10077
|
unsupportedFields.push(`${field}.kvlistValue.values[${index}]`);
|
|
9742
10078
|
continue;
|
|
9743
10079
|
}
|
|
@@ -9788,7 +10124,7 @@ function parseOtlpAttributes(value, pathPrefix) {
|
|
|
9788
10124
|
}
|
|
9789
10125
|
for (const [index, item] of value.entries()) {
|
|
9790
10126
|
const field = `${pathPrefix}[${index}]`;
|
|
9791
|
-
if (!
|
|
10127
|
+
if (!isRecord11(item) || typeof item.key !== "string") {
|
|
9792
10128
|
unsupportedFields.push(field);
|
|
9793
10129
|
warnings.push({
|
|
9794
10130
|
code: "otlp_attribute_invalid",
|
|
@@ -9811,16 +10147,16 @@ function parseOtlpAttributes(value, pathPrefix) {
|
|
|
9811
10147
|
return { attributes, warnings, unsupportedFields };
|
|
9812
10148
|
}
|
|
9813
10149
|
function looksLikeOtlpSpan(value) {
|
|
9814
|
-
return
|
|
10150
|
+
return isRecord11(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
|
|
9815
10151
|
}
|
|
9816
10152
|
function extractOtlpDocument(root) {
|
|
9817
|
-
if (!
|
|
10153
|
+
if (!isRecord11(root) || !Array.isArray(root.resourceSpans)) return void 0;
|
|
9818
10154
|
const spans = [];
|
|
9819
10155
|
const warnings = [];
|
|
9820
10156
|
const unsupportedFields = [];
|
|
9821
10157
|
for (const [resourceIndex, resourceSpan] of root.resourceSpans.entries()) {
|
|
9822
10158
|
const resourcePath = `resourceSpans[${resourceIndex}]`;
|
|
9823
|
-
if (!
|
|
10159
|
+
if (!isRecord11(resourceSpan)) {
|
|
9824
10160
|
unsupportedFields.push(resourcePath);
|
|
9825
10161
|
continue;
|
|
9826
10162
|
}
|
|
@@ -9843,7 +10179,7 @@ function extractOtlpDocument(root) {
|
|
|
9843
10179
|
}
|
|
9844
10180
|
for (const [scopeIndex, scopeSpan] of resourceSpan.scopeSpans.entries()) {
|
|
9845
10181
|
const scopePath = `${resourcePath}.scopeSpans[${scopeIndex}]`;
|
|
9846
|
-
if (!
|
|
10182
|
+
if (!isRecord11(scopeSpan)) {
|
|
9847
10183
|
unsupportedFields.push(scopePath);
|
|
9848
10184
|
continue;
|
|
9849
10185
|
}
|
|
@@ -9910,7 +10246,7 @@ function extractOtlpDocument(root) {
|
|
|
9910
10246
|
};
|
|
9911
10247
|
}
|
|
9912
10248
|
function mapOtlpStatus(status) {
|
|
9913
|
-
if (!
|
|
10249
|
+
if (!isRecord11(status)) return void 0;
|
|
9914
10250
|
const rawCode = status.code;
|
|
9915
10251
|
if (typeof rawCode !== "string") return void 0;
|
|
9916
10252
|
switch (rawCode.toUpperCase()) {
|
|
@@ -10010,7 +10346,7 @@ function mapOtlpEvents(value, pathPrefix) {
|
|
|
10010
10346
|
const events = [];
|
|
10011
10347
|
for (const [index, event] of value.entries()) {
|
|
10012
10348
|
const eventPath = `${pathPrefix}[${index}]`;
|
|
10013
|
-
if (!
|
|
10349
|
+
if (!isRecord11(event)) {
|
|
10014
10350
|
unsupportedFields.push(eventPath);
|
|
10015
10351
|
continue;
|
|
10016
10352
|
}
|
|
@@ -10148,7 +10484,7 @@ function mapOtlpSpan(context) {
|
|
|
10148
10484
|
warnings.push(...kindWarnings);
|
|
10149
10485
|
const status = mapOtlpStatus(span.status);
|
|
10150
10486
|
const tokenUsage = readOtlpTokenUsage(parsedSpanAttributes.attributes);
|
|
10151
|
-
const errorMessage =
|
|
10487
|
+
const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
|
|
10152
10488
|
const event = {
|
|
10153
10489
|
schemaVersion: "0.2",
|
|
10154
10490
|
eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId,
|
|
@@ -10824,7 +11160,7 @@ async function runSuiteCase(suiteCase, config, options) {
|
|
|
10824
11160
|
async function runSuite(options = {}) {
|
|
10825
11161
|
const startedAt = new Date(options.nowMs ?? Date.now()).toISOString();
|
|
10826
11162
|
const { config, configPath, configDir } = await loadSuiteConfig(options);
|
|
10827
|
-
const tracesDir =
|
|
11163
|
+
const tracesDir = path33__default.default.resolve(configDir, config.traces);
|
|
10828
11164
|
const cases = [];
|
|
10829
11165
|
const diagnostics = [];
|
|
10830
11166
|
for (const suiteCase of config.cases) {
|
|
@@ -11851,7 +12187,7 @@ function validateOptions(options) {
|
|
|
11851
12187
|
}
|
|
11852
12188
|
function isConfigLoadError(error) {
|
|
11853
12189
|
if (!(error instanceof Error)) return false;
|
|
11854
|
-
const ext =
|
|
12190
|
+
const ext = path33__default.default.extname(error.message);
|
|
11855
12191
|
if (error.message.includes("Unsupported suite config extension")) return true;
|
|
11856
12192
|
if (error.message.includes("TypeScript suite configs require")) return true;
|
|
11857
12193
|
if (error.message.includes("No suite config found")) return true;
|
|
@@ -12098,6 +12434,7 @@ var init_advanced = __esm({
|
|
|
12098
12434
|
init_inspector();
|
|
12099
12435
|
init_inspector_runtime();
|
|
12100
12436
|
init_trace_event_safety();
|
|
12437
|
+
init_preview_capture();
|
|
12101
12438
|
init_terminal();
|
|
12102
12439
|
init_utils();
|
|
12103
12440
|
init_types();
|
|
@@ -12245,8 +12582,8 @@ var init_load_sqlite = __esm({
|
|
|
12245
12582
|
}
|
|
12246
12583
|
});
|
|
12247
12584
|
function resolveIndexDbPath(traceDir, dbPath) {
|
|
12248
|
-
if (dbPath && dbPath.trim() !== "") return
|
|
12249
|
-
return
|
|
12585
|
+
if (dbPath && dbPath.trim() !== "") return path33__default.default.resolve(dbPath);
|
|
12586
|
+
return path33__default.default.join(path33__default.default.resolve(traceDir), INDEX_DB_FILENAME);
|
|
12250
12587
|
}
|
|
12251
12588
|
function str(value) {
|
|
12252
12589
|
return typeof value === "string" && value !== "" ? value : null;
|
|
@@ -12338,7 +12675,7 @@ async function buildIndex(options = {}) {
|
|
|
12338
12675
|
warnings.push(`index.unreadable: ${file}`);
|
|
12339
12676
|
}
|
|
12340
12677
|
}
|
|
12341
|
-
await promises.mkdir(
|
|
12678
|
+
await promises.mkdir(path33__default.default.dirname(dbPath), { recursive: true });
|
|
12342
12679
|
await promises.rm(dbPath, { force: true });
|
|
12343
12680
|
const Sqlite = loadBetterSqlite3();
|
|
12344
12681
|
const db = new Sqlite(dbPath);
|
|
@@ -12586,7 +12923,7 @@ var init_src = __esm({
|
|
|
12586
12923
|
});
|
|
12587
12924
|
|
|
12588
12925
|
// package.json
|
|
12589
|
-
var version = "6.
|
|
12926
|
+
var version = "6.19.0";
|
|
12590
12927
|
|
|
12591
12928
|
// packages/cli/src/list.ts
|
|
12592
12929
|
init_advanced();
|
|
@@ -13084,6 +13421,16 @@ function filterErrorEvents(events) {
|
|
|
13084
13421
|
return false;
|
|
13085
13422
|
});
|
|
13086
13423
|
}
|
|
13424
|
+
function pruneErrorTree(nodes) {
|
|
13425
|
+
const pruned = [];
|
|
13426
|
+
for (const node of nodes) {
|
|
13427
|
+
const children = pruneErrorTree(node.children);
|
|
13428
|
+
if (node.status === "error" || children.length > 0) {
|
|
13429
|
+
pruned.push({ ...node, children });
|
|
13430
|
+
}
|
|
13431
|
+
}
|
|
13432
|
+
return pruned;
|
|
13433
|
+
}
|
|
13087
13434
|
async function view(runId, options = {}) {
|
|
13088
13435
|
try {
|
|
13089
13436
|
const id = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "";
|
|
@@ -13156,11 +13503,44 @@ async function view(runId, options = {}) {
|
|
|
13156
13503
|
const errEvents = filterErrorEvents(events);
|
|
13157
13504
|
if (options.json) {
|
|
13158
13505
|
console.log(JSON.stringify(errEvents, null, 2));
|
|
13159
|
-
|
|
13506
|
+
return;
|
|
13507
|
+
}
|
|
13508
|
+
if (errEvents.length === 0) {
|
|
13160
13509
|
console.log("No errors found in trace");
|
|
13510
|
+
return;
|
|
13511
|
+
}
|
|
13512
|
+
const started2 = events.find(
|
|
13513
|
+
(e) => e.event === "run_started"
|
|
13514
|
+
);
|
|
13515
|
+
const completed2 = events.filter(
|
|
13516
|
+
(e) => e.event === "run_completed"
|
|
13517
|
+
);
|
|
13518
|
+
const last2 = completed2[completed2.length - 1];
|
|
13519
|
+
const status2 = last2 ? last2.status : "running";
|
|
13520
|
+
const durationLine2 = last2 !== void 0 && Number.isFinite(last2.durationMs) ? formatDuration2(last2.durationMs) : "-";
|
|
13521
|
+
const startedTs2 = started2 !== void 0 && Number.isFinite(started2.startTime) ? started2.startTime : started2?.timestamp;
|
|
13522
|
+
const startedLabel2 = startedTs2 !== void 0 ? formatTimestamp(startedTs2) : "-";
|
|
13523
|
+
console.log(`AgentInspect Run: ${started2?.name ?? id}`);
|
|
13524
|
+
console.log(`ID: ${id}`);
|
|
13525
|
+
console.log(`Status: ${status2}`);
|
|
13526
|
+
console.log(`Duration: ${durationLine2}`);
|
|
13527
|
+
console.log(`Started: ${startedLabel2}`);
|
|
13528
|
+
console.log("");
|
|
13529
|
+
console.log("Error Tree:");
|
|
13530
|
+
const pruned = pruneErrorTree(buildStepTree(events));
|
|
13531
|
+
if (pruned.length === 0) {
|
|
13532
|
+
if (last2?.status === "error") {
|
|
13533
|
+
console.log(
|
|
13534
|
+
renderErrorLine(
|
|
13535
|
+
last2.error ?? { message: "Run completed with error status" },
|
|
13536
|
+
0
|
|
13537
|
+
)
|
|
13538
|
+
);
|
|
13539
|
+
} else {
|
|
13540
|
+
console.log("No error steps recorded");
|
|
13541
|
+
}
|
|
13161
13542
|
} else {
|
|
13162
|
-
|
|
13163
|
-
console.log(JSON.stringify(errEvents, null, 2));
|
|
13543
|
+
printStepTree(pruned, 0, options.verbose === true);
|
|
13164
13544
|
}
|
|
13165
13545
|
return;
|
|
13166
13546
|
}
|
|
@@ -13205,7 +13585,7 @@ async function view(runId, options = {}) {
|
|
|
13205
13585
|
process.exitCode = 1;
|
|
13206
13586
|
}
|
|
13207
13587
|
}
|
|
13208
|
-
function
|
|
13588
|
+
function isRecord12(v) {
|
|
13209
13589
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
13210
13590
|
}
|
|
13211
13591
|
function isNonEmptyStringArray(v) {
|
|
@@ -13217,7 +13597,7 @@ function validateRedact(redact2) {
|
|
|
13217
13597
|
}
|
|
13218
13598
|
for (const r of redact2) {
|
|
13219
13599
|
if (typeof r === "string") continue;
|
|
13220
|
-
if (!
|
|
13600
|
+
if (!isRecord12(r)) {
|
|
13221
13601
|
throw new Error("Invalid config: redact entries must be strings or objects");
|
|
13222
13602
|
}
|
|
13223
13603
|
if (typeof r.key !== "string" || r.key.trim() === "") {
|
|
@@ -13236,7 +13616,7 @@ function validateRedact(redact2) {
|
|
|
13236
13616
|
}
|
|
13237
13617
|
}
|
|
13238
13618
|
function validateMappings(mappings) {
|
|
13239
|
-
if (!
|
|
13619
|
+
if (!isRecord12(mappings)) {
|
|
13240
13620
|
throw new Error("Invalid config: mappings must be an object");
|
|
13241
13621
|
}
|
|
13242
13622
|
}
|
|
@@ -13286,7 +13666,7 @@ async function loadLogIngestConfig(configPath) {
|
|
|
13286
13666
|
const msg = e instanceof Error ? e.message : String(e);
|
|
13287
13667
|
throw new Error(`Invalid JSON in config file: ${configPath} (${msg})`);
|
|
13288
13668
|
}
|
|
13289
|
-
if (!
|
|
13669
|
+
if (!isRecord12(parsed)) {
|
|
13290
13670
|
throw new Error("Invalid config: expected a JSON object at top-level");
|
|
13291
13671
|
}
|
|
13292
13672
|
const user = parsed;
|
|
@@ -13323,7 +13703,7 @@ async function loadLogIngestConfig(configPath) {
|
|
|
13323
13703
|
}
|
|
13324
13704
|
return mergeLogIngestConfig(DEFAULT_LOG_INGEST_CONFIG, user);
|
|
13325
13705
|
}
|
|
13326
|
-
function
|
|
13706
|
+
function isRecord13(v) {
|
|
13327
13707
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
13328
13708
|
}
|
|
13329
13709
|
var JsonLogParser = class {
|
|
@@ -13348,7 +13728,7 @@ var JsonLogParser = class {
|
|
|
13348
13728
|
});
|
|
13349
13729
|
continue;
|
|
13350
13730
|
}
|
|
13351
|
-
if (!
|
|
13731
|
+
if (!isRecord13(parsed)) {
|
|
13352
13732
|
warnings.push({
|
|
13353
13733
|
code: "MALFORMED_JSON",
|
|
13354
13734
|
message: "JSON log line must be an object",
|
|
@@ -13379,7 +13759,7 @@ var JsonLogParser = class {
|
|
|
13379
13759
|
return this.parseLines(lines, filePath);
|
|
13380
13760
|
}
|
|
13381
13761
|
};
|
|
13382
|
-
function
|
|
13762
|
+
function isRecord14(v) {
|
|
13383
13763
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
13384
13764
|
}
|
|
13385
13765
|
function findLastJsonObjectSubstring(line) {
|
|
@@ -13455,7 +13835,7 @@ var Log4jsParser = class {
|
|
|
13455
13835
|
});
|
|
13456
13836
|
continue;
|
|
13457
13837
|
}
|
|
13458
|
-
if (!
|
|
13838
|
+
if (!isRecord14(parsed)) {
|
|
13459
13839
|
warnings.push({
|
|
13460
13840
|
code: "UNSUPPORTED_LOG4JS_PAYLOAD",
|
|
13461
13841
|
message: "Embedded JSON payload must be an object",
|
|
@@ -14334,7 +14714,7 @@ var EXPORT_PAYLOAD_VERSION = "0.1.2";
|
|
|
14334
14714
|
// packages/core/src/exporters/redact-export.ts
|
|
14335
14715
|
init_redactor();
|
|
14336
14716
|
init_redaction_profiles();
|
|
14337
|
-
function
|
|
14717
|
+
function isRecord15(value) {
|
|
14338
14718
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14339
14719
|
}
|
|
14340
14720
|
function deepClone(value) {
|
|
@@ -14408,7 +14788,7 @@ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPrevi
|
|
|
14408
14788
|
0
|
|
14409
14789
|
);
|
|
14410
14790
|
const err = bounded.error;
|
|
14411
|
-
if (
|
|
14791
|
+
if (isRecord15(err) && typeof err.message === "string") {
|
|
14412
14792
|
bounded.error = {
|
|
14413
14793
|
...err,
|
|
14414
14794
|
message: truncateStringForProfile(
|
|
@@ -14438,7 +14818,7 @@ function redactErrorInfo(error, redactor, maxMetadataValueLength, maxPreviewLeng
|
|
|
14438
14818
|
maxPreviewLength
|
|
14439
14819
|
);
|
|
14440
14820
|
const redacted = record?.error;
|
|
14441
|
-
if (!
|
|
14821
|
+
if (!isRecord15(redacted) || typeof redacted.message !== "string") {
|
|
14442
14822
|
return void 0;
|
|
14443
14823
|
}
|
|
14444
14824
|
return {
|
|
@@ -14518,7 +14898,7 @@ function redactTraceEventsForReport(events, options) {
|
|
|
14518
14898
|
) : void 0;
|
|
14519
14899
|
const redactedActual = actualAttrs !== void 0 && "value" in actualAttrs ? actualAttrs.value : void 0;
|
|
14520
14900
|
const redactedEvidence = event.evidence !== void 0 ? redactEventAttributes(
|
|
14521
|
-
|
|
14901
|
+
isRecord15(event.evidence) ? event.evidence : { value: event.evidence },
|
|
14522
14902
|
redactor,
|
|
14523
14903
|
maxMetadataValueLength,
|
|
14524
14904
|
maxPreviewLength
|
|
@@ -15615,9 +15995,9 @@ Trace directory: ${traceDir}`);
|
|
|
15615
15995
|
process.exitCode = 1;
|
|
15616
15996
|
}
|
|
15617
15997
|
const resolvedOutput = resolveOutputOption(options);
|
|
15618
|
-
const outPath = resolvedOutput !== void 0 ?
|
|
15998
|
+
const outPath = resolvedOutput !== void 0 ? path33__default.default.resolve(resolvedOutput) : void 0;
|
|
15619
15999
|
if (outPath !== void 0) {
|
|
15620
|
-
await promises.mkdir(
|
|
16000
|
+
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
15621
16001
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
15622
16002
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
15623
16003
|
console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
|
|
@@ -15976,7 +16356,7 @@ function indexedToMetadata(row, traceDir) {
|
|
|
15976
16356
|
endedAt: row.endedAt ?? void 0,
|
|
15977
16357
|
durationMs: row.durationMs ?? void 0,
|
|
15978
16358
|
eventCount: 0,
|
|
15979
|
-
filePath:
|
|
16359
|
+
filePath: path33__default.default.join(traceDir, row.file),
|
|
15980
16360
|
fileSize: 0,
|
|
15981
16361
|
createdAt: new Date(row.mtimeMs)
|
|
15982
16362
|
};
|
|
@@ -16458,9 +16838,9 @@ async function reportCommand(runId, options = {}) {
|
|
|
16458
16838
|
...options.section ? { section: options.section } : {}
|
|
16459
16839
|
});
|
|
16460
16840
|
const resolvedOutput = resolveOutputOption(options);
|
|
16461
|
-
const outPath = resolvedOutput !== void 0 ?
|
|
16841
|
+
const outPath = resolvedOutput !== void 0 ? path33__default.default.resolve(resolvedOutput) : void 0;
|
|
16462
16842
|
if (outPath !== void 0) {
|
|
16463
|
-
await promises.mkdir(
|
|
16843
|
+
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
16464
16844
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
16465
16845
|
console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
|
|
16466
16846
|
}
|
|
@@ -16601,7 +16981,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
|
|
|
16601
16981
|
"retrieval",
|
|
16602
16982
|
"query"
|
|
16603
16983
|
];
|
|
16604
|
-
function
|
|
16984
|
+
function isRecord16(value) {
|
|
16605
16985
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16606
16986
|
}
|
|
16607
16987
|
function toKey2(key) {
|
|
@@ -16658,8 +17038,8 @@ function passesLuhn(value) {
|
|
|
16658
17038
|
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;
|
|
16659
17039
|
var EPOCH_MS_RE = /^1[0-9]{12}$/;
|
|
16660
17040
|
var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
16661
|
-
function pathSuggestsNonCard(
|
|
16662
|
-
const normalized =
|
|
17041
|
+
function pathSuggestsNonCard(path44) {
|
|
17042
|
+
const normalized = path44.toLowerCase().replace(/[^a-z0-9._]/g, "");
|
|
16663
17043
|
return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
|
|
16664
17044
|
normalized
|
|
16665
17045
|
) || /(^|\.)ts(\.|$)/.test(normalized);
|
|
@@ -16855,17 +17235,17 @@ function applyRule(rule, value, replacement) {
|
|
|
16855
17235
|
}
|
|
16856
17236
|
return value;
|
|
16857
17237
|
}
|
|
16858
|
-
function childPath(
|
|
17238
|
+
function childPath(path44, key) {
|
|
16859
17239
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
16860
|
-
return
|
|
17240
|
+
return path44 ? `${path44}.${key}` : key;
|
|
16861
17241
|
}
|
|
16862
|
-
return `${
|
|
17242
|
+
return `${path44 || "$"}[${JSON.stringify(key)}]`;
|
|
16863
17243
|
}
|
|
16864
|
-
function indexPath(
|
|
16865
|
-
return `${
|
|
17244
|
+
function indexPath(path44, index) {
|
|
17245
|
+
return `${path44 || "$"}[${index}]`;
|
|
16866
17246
|
}
|
|
16867
|
-
function makeFinding(
|
|
16868
|
-
return preview === void 0 ? { path:
|
|
17247
|
+
function makeFinding(path44, detector, action, matchKind, severity = "warning", preview) {
|
|
17248
|
+
return preview === void 0 ? { path: path44, detector, action, severity, matchKind } : { path: path44, detector, action, severity, matchKind, preview };
|
|
16869
17249
|
}
|
|
16870
17250
|
function createRedactionProfile(profile = "local") {
|
|
16871
17251
|
switch (profile) {
|
|
@@ -16934,11 +17314,11 @@ var Redactor2 = class {
|
|
|
16934
17314
|
#recordFinding(state, finding) {
|
|
16935
17315
|
if (this.#collectFindings) state.findings.push(finding);
|
|
16936
17316
|
}
|
|
16937
|
-
#redactValue(value, key,
|
|
17317
|
+
#redactValue(value, key, path44, depth, state) {
|
|
16938
17318
|
if (depth > this.#maxDepth) {
|
|
16939
17319
|
this.#recordFinding(
|
|
16940
17320
|
state,
|
|
16941
|
-
makeFinding(
|
|
17321
|
+
makeFinding(path44, "structure.maxDepth", "truncate", "value", "warning")
|
|
16942
17322
|
);
|
|
16943
17323
|
return "[Truncated]";
|
|
16944
17324
|
}
|
|
@@ -16947,19 +17327,19 @@ var Redactor2 = class {
|
|
|
16947
17327
|
if (rule) {
|
|
16948
17328
|
this.#recordFinding(
|
|
16949
17329
|
state,
|
|
16950
|
-
makeFinding(
|
|
17330
|
+
makeFinding(path44, `key.${rule.key}`, actionForRule(rule), "key", "warning")
|
|
16951
17331
|
);
|
|
16952
17332
|
return applyRule(rule, value, this.#replacement);
|
|
16953
17333
|
}
|
|
16954
17334
|
}
|
|
16955
17335
|
for (const detector of this.#detectors) {
|
|
16956
|
-
const detections = detector.detect({ path:
|
|
17336
|
+
const detections = detector.detect({ path: path44, key, value });
|
|
16957
17337
|
for (const detection of detections) {
|
|
16958
17338
|
const action = detection.action ?? "replace";
|
|
16959
17339
|
this.#recordFinding(
|
|
16960
17340
|
state,
|
|
16961
17341
|
makeFinding(
|
|
16962
|
-
|
|
17342
|
+
path44,
|
|
16963
17343
|
detector.id,
|
|
16964
17344
|
action,
|
|
16965
17345
|
detection.matchKind ?? detector.matchKind ?? "custom",
|
|
@@ -16977,11 +17357,11 @@ var Redactor2 = class {
|
|
|
16977
17357
|
const out = [];
|
|
16978
17358
|
state.seen.set(value, out);
|
|
16979
17359
|
value.forEach((item, index) => {
|
|
16980
|
-
out[index] = this.#redactValue(item, void 0, indexPath(
|
|
17360
|
+
out[index] = this.#redactValue(item, void 0, indexPath(path44, index), depth + 1, state);
|
|
16981
17361
|
});
|
|
16982
17362
|
return out;
|
|
16983
17363
|
}
|
|
16984
|
-
if (
|
|
17364
|
+
if (isRecord16(value)) {
|
|
16985
17365
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
16986
17366
|
const out = {};
|
|
16987
17367
|
state.seen.set(value, out);
|
|
@@ -16989,7 +17369,7 @@ var Redactor2 = class {
|
|
|
16989
17369
|
out[entryKey] = this.#redactValue(
|
|
16990
17370
|
entryValue,
|
|
16991
17371
|
entryKey,
|
|
16992
|
-
childPath(
|
|
17372
|
+
childPath(path44 === "$" ? "" : path44, entryKey),
|
|
16993
17373
|
depth + 1,
|
|
16994
17374
|
state
|
|
16995
17375
|
);
|
|
@@ -17005,6 +17385,233 @@ function createRedactor(options) {
|
|
|
17005
17385
|
function redact(value, options) {
|
|
17006
17386
|
return createRedactor(options).redact(value);
|
|
17007
17387
|
}
|
|
17388
|
+
var REDACTION_POLICY_LIMITS = {
|
|
17389
|
+
maxExtraKeys: 64,
|
|
17390
|
+
maxKeyLength: 64,
|
|
17391
|
+
maxPatterns: 32,
|
|
17392
|
+
maxPatternLength: 128,
|
|
17393
|
+
maxPatternIdLength: 64,
|
|
17394
|
+
maxTypedQuantifier: 64
|
|
17395
|
+
};
|
|
17396
|
+
var SAFE_TYPED_PATTERN = /^[A-Za-z0-9_@./:=<>\-[\]()|+*?{},\\\s^$]+$/;
|
|
17397
|
+
function isRecord17(value) {
|
|
17398
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
17399
|
+
}
|
|
17400
|
+
function escapeRegExp(value) {
|
|
17401
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17402
|
+
}
|
|
17403
|
+
function rejectRemotePolicyPath(policyPath) {
|
|
17404
|
+
const trimmed = policyPath.trim();
|
|
17405
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) {
|
|
17406
|
+
throw new Error(
|
|
17407
|
+
`--policy must be a local JSON file path (got a URL-like value). Remote policy fetch is not supported.`
|
|
17408
|
+
);
|
|
17409
|
+
}
|
|
17410
|
+
}
|
|
17411
|
+
function parseSeverity(value, label) {
|
|
17412
|
+
if (value === void 0) return "error";
|
|
17413
|
+
if (value === "info" || value === "warning" || value === "error") return value;
|
|
17414
|
+
throw new Error(`${label} severity must be info, warning, or error.`);
|
|
17415
|
+
}
|
|
17416
|
+
function validateExtraKey(key, index) {
|
|
17417
|
+
const label = `extraKeys[${index}]`;
|
|
17418
|
+
if (key.length === 0) throw new Error(`${label} must be a non-empty string.`);
|
|
17419
|
+
if (key.length > REDACTION_POLICY_LIMITS.maxKeyLength) {
|
|
17420
|
+
throw new Error(
|
|
17421
|
+
`${label} exceeds max length ${REDACTION_POLICY_LIMITS.maxKeyLength}.`
|
|
17422
|
+
);
|
|
17423
|
+
}
|
|
17424
|
+
if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(key)) {
|
|
17425
|
+
throw new Error(
|
|
17426
|
+
`${label} must be an identifier-like key (letters, digits, _, ., -).`
|
|
17427
|
+
);
|
|
17428
|
+
}
|
|
17429
|
+
return key;
|
|
17430
|
+
}
|
|
17431
|
+
function assertBoundedTypedPattern(pattern, label) {
|
|
17432
|
+
if (pattern.length === 0) throw new Error(`${label} must be non-empty.`);
|
|
17433
|
+
if (pattern.length > REDACTION_POLICY_LIMITS.maxPatternLength) {
|
|
17434
|
+
throw new Error(
|
|
17435
|
+
`${label} exceeds max length ${REDACTION_POLICY_LIMITS.maxPatternLength}.`
|
|
17436
|
+
);
|
|
17437
|
+
}
|
|
17438
|
+
if (!SAFE_TYPED_PATTERN.test(pattern)) {
|
|
17439
|
+
throw new Error(
|
|
17440
|
+
`${label} contains unsupported characters for bounded typed patterns.`
|
|
17441
|
+
);
|
|
17442
|
+
}
|
|
17443
|
+
if (/\(\?/.test(pattern) || /\\[1-9]/.test(pattern)) {
|
|
17444
|
+
throw new Error(
|
|
17445
|
+
`${label} rejects lookaround, backreferences, and nested quantifiers.`
|
|
17446
|
+
);
|
|
17447
|
+
}
|
|
17448
|
+
if (/\([^)]*[+*{][^)]*\)[+*{]/.test(pattern) || /\[[^\]]*[+*{][^\]]*\][+*{]/.test(pattern)) {
|
|
17449
|
+
throw new Error(`${label} rejects nested quantifiers.`);
|
|
17450
|
+
}
|
|
17451
|
+
if (/\.[*+]/.test(pattern) || /[*+]\{/.test(pattern)) {
|
|
17452
|
+
throw new Error(`${label} rejects unbounded .* / .+ style quantifiers.`);
|
|
17453
|
+
}
|
|
17454
|
+
for (const match of pattern.matchAll(/\{(\d+)(?:,(\d*))?\}/g)) {
|
|
17455
|
+
const min = Number(match[1]);
|
|
17456
|
+
const maxRaw = match[2];
|
|
17457
|
+
const max = maxRaw === void 0 || maxRaw === "" ? min : Number(maxRaw);
|
|
17458
|
+
if (!Number.isFinite(min) || !Number.isFinite(max) || min > REDACTION_POLICY_LIMITS.maxTypedQuantifier || max > REDACTION_POLICY_LIMITS.maxTypedQuantifier) {
|
|
17459
|
+
throw new Error(
|
|
17460
|
+
`${label} quantifiers must be <= ${REDACTION_POLICY_LIMITS.maxTypedQuantifier}.`
|
|
17461
|
+
);
|
|
17462
|
+
}
|
|
17463
|
+
}
|
|
17464
|
+
}
|
|
17465
|
+
function compilePatternDetector(input3, index) {
|
|
17466
|
+
const label = `patterns[${index}]`;
|
|
17467
|
+
if (!isRecord17(input3)) throw new Error(`${label} must be an object.`);
|
|
17468
|
+
const idRaw = input3.id;
|
|
17469
|
+
if (typeof idRaw !== "string" || idRaw.trim() === "") {
|
|
17470
|
+
throw new Error(`${label}.id must be a non-empty string.`);
|
|
17471
|
+
}
|
|
17472
|
+
const id = idRaw.trim();
|
|
17473
|
+
if (id.length > REDACTION_POLICY_LIMITS.maxPatternIdLength) {
|
|
17474
|
+
throw new Error(
|
|
17475
|
+
`${label}.id exceeds max length ${REDACTION_POLICY_LIMITS.maxPatternIdLength}.`
|
|
17476
|
+
);
|
|
17477
|
+
}
|
|
17478
|
+
if (!/^[A-Za-z][A-Za-z0-9._-]*$/.test(id)) {
|
|
17479
|
+
throw new Error(`${label}.id must be an identifier-like detector id.`);
|
|
17480
|
+
}
|
|
17481
|
+
const type = input3.type;
|
|
17482
|
+
if (type !== "literal" && type !== "prefix" && type !== "typed") {
|
|
17483
|
+
throw new Error(`${label}.type must be literal, prefix, or typed.`);
|
|
17484
|
+
}
|
|
17485
|
+
const severity = parseSeverity(input3.severity, label);
|
|
17486
|
+
let source;
|
|
17487
|
+
if (type === "typed") {
|
|
17488
|
+
if (typeof input3.pattern !== "string") {
|
|
17489
|
+
throw new Error(`${label}.pattern must be a string for typed patterns.`);
|
|
17490
|
+
}
|
|
17491
|
+
assertBoundedTypedPattern(input3.pattern, `${label}.pattern`);
|
|
17492
|
+
source = input3.pattern;
|
|
17493
|
+
} else {
|
|
17494
|
+
if (typeof input3.value !== "string") {
|
|
17495
|
+
throw new Error(`${label}.value must be a string for ${type} patterns.`);
|
|
17496
|
+
}
|
|
17497
|
+
if (input3.value.length === 0) {
|
|
17498
|
+
throw new Error(`${label}.value must be non-empty.`);
|
|
17499
|
+
}
|
|
17500
|
+
if (input3.value.length > REDACTION_POLICY_LIMITS.maxPatternLength) {
|
|
17501
|
+
throw new Error(
|
|
17502
|
+
`${label}.value exceeds max length ${REDACTION_POLICY_LIMITS.maxPatternLength}.`
|
|
17503
|
+
);
|
|
17504
|
+
}
|
|
17505
|
+
const escaped = escapeRegExp(input3.value);
|
|
17506
|
+
source = type === "prefix" ? `^${escaped}` : escaped;
|
|
17507
|
+
}
|
|
17508
|
+
let regex;
|
|
17509
|
+
try {
|
|
17510
|
+
regex = new RegExp(source);
|
|
17511
|
+
} catch (error) {
|
|
17512
|
+
throw new Error(
|
|
17513
|
+
`${label} failed to compile: ${error instanceof Error ? error.message : String(error)}`
|
|
17514
|
+
);
|
|
17515
|
+
}
|
|
17516
|
+
return {
|
|
17517
|
+
id: `policy.${id}`,
|
|
17518
|
+
severity,
|
|
17519
|
+
matchKind: "custom",
|
|
17520
|
+
detect({ value }) {
|
|
17521
|
+
if (typeof value !== "string") return [];
|
|
17522
|
+
regex.lastIndex = 0;
|
|
17523
|
+
return regex.test(value) ? [{ action: "replace", severity, matchKind: "custom" }] : [];
|
|
17524
|
+
}
|
|
17525
|
+
};
|
|
17526
|
+
}
|
|
17527
|
+
function compileRedactionPolicy(raw, policyPath) {
|
|
17528
|
+
if (!isRecord17(raw)) {
|
|
17529
|
+
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
17530
|
+
}
|
|
17531
|
+
const diagnostics = [];
|
|
17532
|
+
if (raw.version !== void 0 && raw.version !== 1) {
|
|
17533
|
+
throw new Error(`Unsupported redaction policy version (supported: 1).`);
|
|
17534
|
+
}
|
|
17535
|
+
const extraKeysRaw = raw.extraKeys;
|
|
17536
|
+
const extraKeys = [];
|
|
17537
|
+
if (extraKeysRaw !== void 0) {
|
|
17538
|
+
if (!Array.isArray(extraKeysRaw)) {
|
|
17539
|
+
throw new Error(`extraKeys must be an array of strings.`);
|
|
17540
|
+
}
|
|
17541
|
+
if (extraKeysRaw.length > REDACTION_POLICY_LIMITS.maxExtraKeys) {
|
|
17542
|
+
throw new Error(
|
|
17543
|
+
`extraKeys exceeds max count ${REDACTION_POLICY_LIMITS.maxExtraKeys}.`
|
|
17544
|
+
);
|
|
17545
|
+
}
|
|
17546
|
+
for (let i = 0; i < extraKeysRaw.length; i += 1) {
|
|
17547
|
+
const key = extraKeysRaw[i];
|
|
17548
|
+
if (typeof key !== "string") {
|
|
17549
|
+
throw new Error(`extraKeys[${i}] must be a string.`);
|
|
17550
|
+
}
|
|
17551
|
+
extraKeys.push(validateExtraKey(key, i));
|
|
17552
|
+
}
|
|
17553
|
+
}
|
|
17554
|
+
const patternsRaw = raw.patterns;
|
|
17555
|
+
const detectors = [];
|
|
17556
|
+
if (patternsRaw !== void 0) {
|
|
17557
|
+
if (!Array.isArray(patternsRaw)) {
|
|
17558
|
+
throw new Error(`patterns must be an array.`);
|
|
17559
|
+
}
|
|
17560
|
+
if (patternsRaw.length > REDACTION_POLICY_LIMITS.maxPatterns) {
|
|
17561
|
+
throw new Error(
|
|
17562
|
+
`patterns exceeds max count ${REDACTION_POLICY_LIMITS.maxPatterns}.`
|
|
17563
|
+
);
|
|
17564
|
+
}
|
|
17565
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
17566
|
+
for (let i = 0; i < patternsRaw.length; i += 1) {
|
|
17567
|
+
const detector = compilePatternDetector(
|
|
17568
|
+
patternsRaw[i],
|
|
17569
|
+
i
|
|
17570
|
+
);
|
|
17571
|
+
if (seenIds.has(detector.id)) {
|
|
17572
|
+
throw new Error(`Duplicate pattern id "${detector.id}".`);
|
|
17573
|
+
}
|
|
17574
|
+
seenIds.add(detector.id);
|
|
17575
|
+
detectors.push(detector);
|
|
17576
|
+
}
|
|
17577
|
+
}
|
|
17578
|
+
if (extraKeys.length === 0 && detectors.length === 0) {
|
|
17579
|
+
diagnostics.push({
|
|
17580
|
+
code: "AI_POLICY_EMPTY",
|
|
17581
|
+
message: "Redaction policy contained no extraKeys or patterns."
|
|
17582
|
+
});
|
|
17583
|
+
}
|
|
17584
|
+
return {
|
|
17585
|
+
path: policyPath,
|
|
17586
|
+
extraKeys,
|
|
17587
|
+
detectors,
|
|
17588
|
+
diagnostics
|
|
17589
|
+
};
|
|
17590
|
+
}
|
|
17591
|
+
async function loadRedactionPolicy(policyPath) {
|
|
17592
|
+
rejectRemotePolicyPath(policyPath);
|
|
17593
|
+
const resolved = path33__default.default.resolve(policyPath);
|
|
17594
|
+
let text;
|
|
17595
|
+
try {
|
|
17596
|
+
text = await promises.readFile(resolved, "utf-8");
|
|
17597
|
+
} catch (error) {
|
|
17598
|
+
throw new Error(
|
|
17599
|
+
`Failed to read --policy file "${resolved}": ${error instanceof Error ? error.message : String(error)}`
|
|
17600
|
+
);
|
|
17601
|
+
}
|
|
17602
|
+
let parsed;
|
|
17603
|
+
try {
|
|
17604
|
+
parsed = JSON.parse(text);
|
|
17605
|
+
} catch (error) {
|
|
17606
|
+
throw new Error(
|
|
17607
|
+
`Invalid JSON in --policy file "${resolved}": ${error instanceof Error ? error.message : String(error)}`
|
|
17608
|
+
);
|
|
17609
|
+
}
|
|
17610
|
+
return compileRedactionPolicy(parsed, resolved);
|
|
17611
|
+
}
|
|
17612
|
+
|
|
17613
|
+
// packages/core/src/entries/checks.ts
|
|
17614
|
+
init_checks2();
|
|
17008
17615
|
|
|
17009
17616
|
// packages/cli/src/trace-input.ts
|
|
17010
17617
|
init_advanced();
|
|
@@ -17036,12 +17643,19 @@ async function inputFromTarget(target, options, stdin) {
|
|
|
17036
17643
|
return { type: "file", path: runPath };
|
|
17037
17644
|
}
|
|
17038
17645
|
|
|
17039
|
-
// packages/cli/src/
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17646
|
+
// packages/cli/src/safety.ts
|
|
17647
|
+
var BEST_EFFORT_NOTE = "Best-effort local safety verification only; not a compliance, privacy, security, or regulatory certification.";
|
|
17648
|
+
var DEFAULT_MAX_STRING_LENGTH = 16384;
|
|
17649
|
+
var DEFAULT_MAX_ARRAY_LENGTH = 1e3;
|
|
17650
|
+
var DEFAULT_MAX_OBJECT_KEYS = 200;
|
|
17651
|
+
var DEFAULT_MAX_SERIALIZED_BYTES = 128 * 1024;
|
|
17652
|
+
function parseLimit3(value, label) {
|
|
17653
|
+
if (value === void 0) return void 0;
|
|
17654
|
+
const parsed = Number(value);
|
|
17655
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
17656
|
+
throw new Error(`${label} must be a non-negative number.`);
|
|
17043
17657
|
}
|
|
17044
|
-
|
|
17658
|
+
return parsed;
|
|
17045
17659
|
}
|
|
17046
17660
|
function stable2(value) {
|
|
17047
17661
|
if (Array.isArray(value)) return value.map(stable2);
|
|
@@ -17051,7 +17665,441 @@ function stable2(value) {
|
|
|
17051
17665
|
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable2(record[key])])
|
|
17052
17666
|
);
|
|
17053
17667
|
}
|
|
17054
|
-
function
|
|
17668
|
+
function safetyDiagnostic(code, message, severity = "error") {
|
|
17669
|
+
return { code, message, severity };
|
|
17670
|
+
}
|
|
17671
|
+
function warningDiagnostics(warnings, unsupportedFields) {
|
|
17672
|
+
return [
|
|
17673
|
+
...warnings.map(
|
|
17674
|
+
(warning) => safetyDiagnostic(
|
|
17675
|
+
warning.code,
|
|
17676
|
+
warning.message,
|
|
17677
|
+
warning.severity === "error" ? "error" : "warning"
|
|
17678
|
+
)
|
|
17679
|
+
),
|
|
17680
|
+
...unsupportedFields.map(
|
|
17681
|
+
(field) => safetyDiagnostic(
|
|
17682
|
+
"unsupported_field",
|
|
17683
|
+
`Reader reported unsupported field: ${field}`,
|
|
17684
|
+
"warning"
|
|
17685
|
+
)
|
|
17686
|
+
)
|
|
17687
|
+
];
|
|
17688
|
+
}
|
|
17689
|
+
function diagnosticFromCheck(item) {
|
|
17690
|
+
return safetyDiagnostic(item.code, item.message, item.severity);
|
|
17691
|
+
}
|
|
17692
|
+
function statusFrom(findings, diagnostics) {
|
|
17693
|
+
if (diagnostics.some((item) => item.severity === "error")) return "UNKNOWN";
|
|
17694
|
+
if (findings.some((item) => item.severity === "error")) return "UNSAFE";
|
|
17695
|
+
if (diagnostics.some((item) => item.severity === "warning")) return "SAFE WITH WARNINGS";
|
|
17696
|
+
if (findings.some((item) => item.severity === "warning")) return "SAFE WITH WARNINGS";
|
|
17697
|
+
return "SAFE";
|
|
17698
|
+
}
|
|
17699
|
+
function resultFromParts(parts) {
|
|
17700
|
+
const findings = [...parts.findings ?? []];
|
|
17701
|
+
const diagnostics = [...parts.diagnostics ?? []];
|
|
17702
|
+
const warnings = [...parts.warnings ?? []];
|
|
17703
|
+
const unsupportedFields = [...parts.unsupportedFields ?? []];
|
|
17704
|
+
const status = parts.status ?? statusFrom(findings, diagnostics);
|
|
17705
|
+
return {
|
|
17706
|
+
ok: status === "SAFE" || status === "SAFE WITH WARNINGS",
|
|
17707
|
+
command: parts.command,
|
|
17708
|
+
status,
|
|
17709
|
+
format: parts.format,
|
|
17710
|
+
...parts.runId !== void 0 ? { runId: parts.runId } : {},
|
|
17711
|
+
summary: {
|
|
17712
|
+
findings: findings.length,
|
|
17713
|
+
warnings: diagnostics.filter((item) => item.severity === "warning").length + findings.filter((item) => item.severity === "warning").length,
|
|
17714
|
+
errors: diagnostics.filter((item) => item.severity === "error").length + findings.filter((item) => item.severity === "error").length
|
|
17715
|
+
},
|
|
17716
|
+
findings,
|
|
17717
|
+
diagnostics,
|
|
17718
|
+
warnings,
|
|
17719
|
+
unsupportedFields,
|
|
17720
|
+
note: BEST_EFFORT_NOTE,
|
|
17721
|
+
...parts.sourceAssessment !== void 0 ? { sourceAssessment: parts.sourceAssessment } : {},
|
|
17722
|
+
...parts.artifactAssessment !== void 0 ? { artifactAssessment: parts.artifactAssessment } : {},
|
|
17723
|
+
...parts.redactionSummary !== void 0 ? { redactionSummary: parts.redactionSummary } : {}
|
|
17724
|
+
};
|
|
17725
|
+
}
|
|
17726
|
+
function layerFromResult(result) {
|
|
17727
|
+
return {
|
|
17728
|
+
status: result.status,
|
|
17729
|
+
summary: result.summary,
|
|
17730
|
+
findings: result.findings
|
|
17731
|
+
};
|
|
17732
|
+
}
|
|
17733
|
+
function readErrorResult(command, error) {
|
|
17734
|
+
if (error instanceof TraceReadError) {
|
|
17735
|
+
const code = error.code === "unsupported_format" ? "AI_SAFETY_UNSUPPORTED_FORMAT" : error.code === "ambiguous_format" ? "AI_SAFETY_AMBIGUOUS_FORMAT" : "AI_SAFETY_TRACE_UNREADABLE";
|
|
17736
|
+
return resultFromParts({
|
|
17737
|
+
command,
|
|
17738
|
+
format: "unknown",
|
|
17739
|
+
diagnostics: [safetyDiagnostic(code, error.message)],
|
|
17740
|
+
warnings: error.warnings
|
|
17741
|
+
});
|
|
17742
|
+
}
|
|
17743
|
+
return resultFromParts({
|
|
17744
|
+
command,
|
|
17745
|
+
format: "unknown",
|
|
17746
|
+
diagnostics: [
|
|
17747
|
+
safetyDiagnostic(
|
|
17748
|
+
"AI_SAFETY_TRACE_UNREADABLE",
|
|
17749
|
+
error instanceof Error ? error.message : String(error)
|
|
17750
|
+
)
|
|
17751
|
+
]
|
|
17752
|
+
});
|
|
17753
|
+
}
|
|
17754
|
+
function invalidArgumentResult(command, error) {
|
|
17755
|
+
return resultFromParts({
|
|
17756
|
+
command,
|
|
17757
|
+
format: "unknown",
|
|
17758
|
+
diagnostics: [
|
|
17759
|
+
safetyDiagnostic(
|
|
17760
|
+
"AI_SAFETY_INVALID_ARGUMENTS",
|
|
17761
|
+
error instanceof Error ? error.message : String(error)
|
|
17762
|
+
)
|
|
17763
|
+
]
|
|
17764
|
+
});
|
|
17765
|
+
}
|
|
17766
|
+
function buildSafetyRules(options) {
|
|
17767
|
+
const maxStringLength2 = parseLimit3(options.maxStringLength, "--max-string-length") ?? DEFAULT_MAX_STRING_LENGTH;
|
|
17768
|
+
const maxArrayLength = parseLimit3(options.maxArrayLength, "--max-array-length") ?? DEFAULT_MAX_ARRAY_LENGTH;
|
|
17769
|
+
const maxObjectKeys = parseLimit3(options.maxObjectKeys, "--max-object-keys") ?? DEFAULT_MAX_OBJECT_KEYS;
|
|
17770
|
+
const maxSerializedBytes = parseLimit3(options.maxSerializedBytes, "--max-serialized-bytes") ?? DEFAULT_MAX_SERIALIZED_BYTES;
|
|
17771
|
+
return [
|
|
17772
|
+
createSafetyRawContentRule(),
|
|
17773
|
+
createSafetyRedactionRule(),
|
|
17774
|
+
createSafetySecretPatternRule(),
|
|
17775
|
+
createSafetyOversizedAttributeRule({
|
|
17776
|
+
maxStringLength: maxStringLength2,
|
|
17777
|
+
maxArrayLength,
|
|
17778
|
+
maxObjectKeys,
|
|
17779
|
+
maxSerializedBytes
|
|
17780
|
+
})
|
|
17781
|
+
];
|
|
17782
|
+
}
|
|
17783
|
+
function flattenNodes2(nodes) {
|
|
17784
|
+
return nodes.flatMap((node) => [
|
|
17785
|
+
node,
|
|
17786
|
+
...flattenNodes2(
|
|
17787
|
+
node.children
|
|
17788
|
+
)
|
|
17789
|
+
]);
|
|
17790
|
+
}
|
|
17791
|
+
function detectorSeverity(finding) {
|
|
17792
|
+
return finding.severity;
|
|
17793
|
+
}
|
|
17794
|
+
function classifyRedactionDetector(detector) {
|
|
17795
|
+
if (detector === "value.creditCard" || detector === "value.email" || detector === "value.phone") {
|
|
17796
|
+
return { category: "personal-data", confidence: "high" };
|
|
17797
|
+
}
|
|
17798
|
+
if (detector === "value.ipv4" || detector === "value.ipv6") {
|
|
17799
|
+
return { category: "identifier", confidence: "medium" };
|
|
17800
|
+
}
|
|
17801
|
+
if (detector.startsWith("value.") && (detector.includes("Token") || detector.includes("Key") || detector.includes("jwt") || detector.includes("authorization") || detector.includes("bearer") || detector.includes("cookie") || detector.includes("privateKey") || detector.includes("github") || detector.includes("aws") || detector.includes("provider"))) {
|
|
17802
|
+
return { category: "credential", confidence: "high" };
|
|
17803
|
+
}
|
|
17804
|
+
if (detector.startsWith("key.")) {
|
|
17805
|
+
return { category: "credential", confidence: "medium" };
|
|
17806
|
+
}
|
|
17807
|
+
return { category: "credential", confidence: "medium" };
|
|
17808
|
+
}
|
|
17809
|
+
function redactionOptionsFromPolicy(policy) {
|
|
17810
|
+
if (policy === void 0) return {};
|
|
17811
|
+
return {
|
|
17812
|
+
...policy.extraKeys.length > 0 ? { extraKeys: [...policy.extraKeys] } : {},
|
|
17813
|
+
...policy.detectors.length > 0 ? { detectors: [...policy.detectors] } : {}
|
|
17814
|
+
};
|
|
17815
|
+
}
|
|
17816
|
+
function redactionDetectorFindings(read, runId, policy) {
|
|
17817
|
+
const runs = runId === void 0 ? read.runs : read.runs.filter((run) => run.runId === runId);
|
|
17818
|
+
const out = [];
|
|
17819
|
+
const policyOptions = redactionOptionsFromPolicy(policy);
|
|
17820
|
+
for (const run of runs) {
|
|
17821
|
+
for (const node of flattenNodes2(run.children)) {
|
|
17822
|
+
const attrs = node.event.attributes;
|
|
17823
|
+
if (attrs === void 0) continue;
|
|
17824
|
+
const result = createRedactor({
|
|
17825
|
+
profile: "share",
|
|
17826
|
+
...policyOptions
|
|
17827
|
+
}).redact(attrs);
|
|
17828
|
+
for (const finding of result.findings) {
|
|
17829
|
+
if (finding.action === "keep") continue;
|
|
17830
|
+
const taxonomy = classifyRedactionDetector(finding.detector);
|
|
17831
|
+
out.push({
|
|
17832
|
+
ruleId: "safety.redactDetector",
|
|
17833
|
+
severity: detectorSeverity(finding),
|
|
17834
|
+
status: finding.severity === "error" ? "fail" : "warning",
|
|
17835
|
+
message: `Redaction detector ${finding.detector} matched ${finding.matchKind} at ${finding.path}.`,
|
|
17836
|
+
expected: "redacted trace content",
|
|
17837
|
+
actual: finding.detector,
|
|
17838
|
+
evidence: [
|
|
17839
|
+
{
|
|
17840
|
+
runId: node.event.runId,
|
|
17841
|
+
eventId: node.event.eventId,
|
|
17842
|
+
...node.event.parentId !== void 0 ? { parentId: node.event.parentId } : {},
|
|
17843
|
+
kind: node.event.kind,
|
|
17844
|
+
name: node.event.name,
|
|
17845
|
+
...node.event.status !== void 0 ? { status: node.event.status } : {},
|
|
17846
|
+
path: `attributes.${finding.path.replace(/^\$\.?/, "")}`
|
|
17847
|
+
}
|
|
17848
|
+
],
|
|
17849
|
+
category: taxonomy.category,
|
|
17850
|
+
confidence: taxonomy.confidence,
|
|
17851
|
+
detector: finding.detector,
|
|
17852
|
+
action: finding.action
|
|
17853
|
+
});
|
|
17854
|
+
}
|
|
17855
|
+
}
|
|
17856
|
+
}
|
|
17857
|
+
return out.sort((a, b) => {
|
|
17858
|
+
const aEvidence = a.evidence[0];
|
|
17859
|
+
const bEvidence = b.evidence[0];
|
|
17860
|
+
return (aEvidence?.runId ?? "").localeCompare(bEvidence?.runId ?? "") || (aEvidence?.eventId ?? "").localeCompare(bEvidence?.eventId ?? "") || (aEvidence?.path ?? "").localeCompare(bEvidence?.path ?? "") || a.message.localeCompare(b.message);
|
|
17861
|
+
});
|
|
17862
|
+
}
|
|
17863
|
+
function exitCodeFor(result) {
|
|
17864
|
+
if (result.status === "SAFE" || result.status === "SAFE WITH WARNINGS") return 0;
|
|
17865
|
+
if (result.status === "UNSAFE") return 1;
|
|
17866
|
+
return 2;
|
|
17867
|
+
}
|
|
17868
|
+
function toResidualStatus(status) {
|
|
17869
|
+
if (status === "SAFE WITH WARNINGS") return "SAFE_WITH_WARNINGS";
|
|
17870
|
+
return status;
|
|
17871
|
+
}
|
|
17872
|
+
function toResidualSafetyAssessment(result) {
|
|
17873
|
+
const codes = [
|
|
17874
|
+
.../* @__PURE__ */ new Set([
|
|
17875
|
+
...result.diagnostics.map((item) => item.code),
|
|
17876
|
+
...result.findings.map((item) => item.ruleId)
|
|
17877
|
+
])
|
|
17878
|
+
].sort((a, b) => a.localeCompare(b));
|
|
17879
|
+
return {
|
|
17880
|
+
status: toResidualStatus(result.status),
|
|
17881
|
+
findings: result.summary.findings,
|
|
17882
|
+
warnings: result.summary.warnings,
|
|
17883
|
+
errors: result.summary.errors,
|
|
17884
|
+
codes,
|
|
17885
|
+
note: BEST_EFFORT_NOTE
|
|
17886
|
+
};
|
|
17887
|
+
}
|
|
17888
|
+
async function assessResidualFromContent(content, options = {}) {
|
|
17889
|
+
try {
|
|
17890
|
+
const policy = options.compiledPolicy ?? (options.policy !== void 0 ? await loadRedactionPolicy(options.policy) : void 0);
|
|
17891
|
+
const read = await openTrace(
|
|
17892
|
+
{ type: "string", content },
|
|
17893
|
+
{ format: options.format ?? "agent-inspect-jsonl" }
|
|
17894
|
+
);
|
|
17895
|
+
const result = assessOpenedTrace(read, {
|
|
17896
|
+
...options,
|
|
17897
|
+
...policy !== void 0 ? { compiledPolicy: policy } : {}
|
|
17898
|
+
});
|
|
17899
|
+
return toResidualSafetyAssessment(result);
|
|
17900
|
+
} catch (error) {
|
|
17901
|
+
if (error instanceof TraceReadError) {
|
|
17902
|
+
return toResidualSafetyAssessment(readErrorResult("verify-safe", error));
|
|
17903
|
+
}
|
|
17904
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17905
|
+
return {
|
|
17906
|
+
status: "UNKNOWN",
|
|
17907
|
+
findings: 0,
|
|
17908
|
+
warnings: 0,
|
|
17909
|
+
errors: 1,
|
|
17910
|
+
codes: ["AI_SAFETY_TRACE_UNREADABLE"],
|
|
17911
|
+
note: `${BEST_EFFORT_NOTE} Residual assessment requires a supported AgentInspect trace; ${message}`
|
|
17912
|
+
};
|
|
17913
|
+
}
|
|
17914
|
+
}
|
|
17915
|
+
function explainFinding(finding, blocksBundle) {
|
|
17916
|
+
const path44 = finding.evidence[0]?.path ?? "(unknown path)";
|
|
17917
|
+
const category = finding.category ?? "structure";
|
|
17918
|
+
const confidence = finding.confidence ?? "medium";
|
|
17919
|
+
const detector = finding.detector ?? finding.ruleId;
|
|
17920
|
+
const action = finding.action ?? "review";
|
|
17921
|
+
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.";
|
|
17922
|
+
return [
|
|
17923
|
+
` Matched: detector=${detector}; path=${path44}; category=${category}`,
|
|
17924
|
+
` Why: ${finding.message}`,
|
|
17925
|
+
` Confidence: ${confidence}`,
|
|
17926
|
+
` Redaction: ${redactionHint}`,
|
|
17927
|
+
` Override: configure a custom redaction/detector rule locally (see docs/SAFETY-POLICY.md); do not weaken defaults globally.`,
|
|
17928
|
+
` Bundle gate: ${blocksBundle ? "blocks share-safe bundle unless --allow-unsafe" : "does not block by itself (warning/info)"}`
|
|
17929
|
+
];
|
|
17930
|
+
}
|
|
17931
|
+
function findingExplanation(finding) {
|
|
17932
|
+
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
17933
|
+
return {
|
|
17934
|
+
ruleId: finding.ruleId,
|
|
17935
|
+
detector: finding.detector ?? finding.ruleId,
|
|
17936
|
+
path: finding.evidence[0]?.path,
|
|
17937
|
+
category: finding.category,
|
|
17938
|
+
confidence: finding.confidence,
|
|
17939
|
+
action: finding.action,
|
|
17940
|
+
blocksBundle: blocks,
|
|
17941
|
+
// Never include matched secret/PII values.
|
|
17942
|
+
message: finding.message
|
|
17943
|
+
};
|
|
17944
|
+
}
|
|
17945
|
+
function printHuman(result, explain = false) {
|
|
17946
|
+
console.log(`Safety status: ${result.status}`);
|
|
17947
|
+
console.log(`Format: ${result.format}`);
|
|
17948
|
+
if (result.runId !== void 0) console.log(`Run: ${result.runId}`);
|
|
17949
|
+
if (result.sourceAssessment !== void 0 && result.artifactAssessment !== void 0) {
|
|
17950
|
+
console.log(`Source assessment: ${result.sourceAssessment.status}`);
|
|
17951
|
+
console.log(`Artifact assessment: ${result.artifactAssessment.status}`);
|
|
17952
|
+
if (result.redactionSummary !== void 0) {
|
|
17953
|
+
console.log(
|
|
17954
|
+
`Redaction: profile=${result.redactionSummary.profile}, findings=${result.redactionSummary.findings}`
|
|
17955
|
+
);
|
|
17956
|
+
}
|
|
17957
|
+
}
|
|
17958
|
+
console.log(
|
|
17959
|
+
`Summary: ${result.summary.findings} finding(s), ${result.summary.warnings} warning(s), ${result.summary.errors} error(s)`
|
|
17960
|
+
);
|
|
17961
|
+
for (const diagnostic7 of result.diagnostics) {
|
|
17962
|
+
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
17963
|
+
}
|
|
17964
|
+
for (const finding of result.findings) {
|
|
17965
|
+
const path44 = finding.evidence[0]?.path;
|
|
17966
|
+
const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
|
|
17967
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path44 ? ` (${path44})` : ""}${taxonomy}`);
|
|
17968
|
+
if (explain) {
|
|
17969
|
+
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
17970
|
+
for (const line of explainFinding(finding, blocks)) {
|
|
17971
|
+
console.log(line);
|
|
17972
|
+
}
|
|
17973
|
+
}
|
|
17974
|
+
}
|
|
17975
|
+
console.log(`Note: ${result.note}`);
|
|
17976
|
+
}
|
|
17977
|
+
function printJson(result, explain = false) {
|
|
17978
|
+
const payload = explain === true ? { ...result, explanations: result.findings.map(findingExplanation) } : result;
|
|
17979
|
+
console.log(JSON.stringify(stable2(payload), null, 2));
|
|
17980
|
+
}
|
|
17981
|
+
async function safetyCommand(command, target, options, stdin) {
|
|
17982
|
+
let result;
|
|
17983
|
+
try {
|
|
17984
|
+
const policy = options.compiledPolicy ?? (options.policy !== void 0 ? await loadRedactionPolicy(options.policy) : void 0);
|
|
17985
|
+
const optionsWithPolicy = {
|
|
17986
|
+
...options,
|
|
17987
|
+
...policy !== void 0 ? { compiledPolicy: policy } : {}
|
|
17988
|
+
};
|
|
17989
|
+
const input3 = await inputFromTarget(target, optionsWithPolicy, stdin);
|
|
17990
|
+
const read = await openTrace(input3, {
|
|
17991
|
+
...options.format !== void 0 ? { format: options.format } : {}
|
|
17992
|
+
});
|
|
17993
|
+
const source = assessOpenedTrace(read, {
|
|
17994
|
+
...optionsWithPolicy,
|
|
17995
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
17996
|
+
});
|
|
17997
|
+
if (command === "scan") {
|
|
17998
|
+
result = { ...source, command: "scan" };
|
|
17999
|
+
} else {
|
|
18000
|
+
const profile = options.redactionProfile ?? "share";
|
|
18001
|
+
const rawContent = input3.type === "string" ? input3.content : input3.type === "file" ? await promises.readFile(input3.path, "utf-8") : void 0;
|
|
18002
|
+
if (rawContent === void 0) {
|
|
18003
|
+
result = {
|
|
18004
|
+
...source,
|
|
18005
|
+
command: "verify-safe",
|
|
18006
|
+
sourceAssessment: layerFromResult(source)
|
|
18007
|
+
};
|
|
18008
|
+
} else {
|
|
18009
|
+
const redacted = redactTraceContent(rawContent, profile, policy);
|
|
18010
|
+
const artifactRead = await openTrace(
|
|
18011
|
+
{ type: "string", content: redacted.content },
|
|
18012
|
+
{ format: options.format ?? "agent-inspect-jsonl" }
|
|
18013
|
+
);
|
|
18014
|
+
const artifact = assessOpenedTrace(artifactRead, {
|
|
18015
|
+
...optionsWithPolicy,
|
|
18016
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
18017
|
+
});
|
|
18018
|
+
const detectors = [
|
|
18019
|
+
...new Set(redacted.findings.map((finding) => finding.detector))
|
|
18020
|
+
].sort((a, b) => a.localeCompare(b));
|
|
18021
|
+
result = resultFromParts({
|
|
18022
|
+
command: "verify-safe",
|
|
18023
|
+
format: artifact.format,
|
|
18024
|
+
runId: artifact.runId ?? source.runId,
|
|
18025
|
+
findings: artifact.findings,
|
|
18026
|
+
diagnostics: artifact.diagnostics,
|
|
18027
|
+
warnings: artifact.warnings,
|
|
18028
|
+
unsupportedFields: artifact.unsupportedFields,
|
|
18029
|
+
status: artifact.status,
|
|
18030
|
+
sourceAssessment: layerFromResult(source),
|
|
18031
|
+
artifactAssessment: layerFromResult(artifact),
|
|
18032
|
+
redactionSummary: {
|
|
18033
|
+
profile,
|
|
18034
|
+
findings: redacted.findings.length,
|
|
18035
|
+
detectors
|
|
18036
|
+
}
|
|
18037
|
+
});
|
|
18038
|
+
}
|
|
18039
|
+
}
|
|
18040
|
+
} catch (error) {
|
|
18041
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18042
|
+
result = message.startsWith("--") || message.includes("--policy") ? invalidArgumentResult(command, error) : readErrorResult(command, error);
|
|
18043
|
+
}
|
|
18044
|
+
process.exitCode = exitCodeFor(result);
|
|
18045
|
+
if (options.json) printJson(result, options.explain === true);
|
|
18046
|
+
else printHuman(result, options.explain === true);
|
|
18047
|
+
}
|
|
18048
|
+
function scanCommand(target, options = {}, stdin = process.stdin) {
|
|
18049
|
+
return safetyCommand("scan", target, options, stdin);
|
|
18050
|
+
}
|
|
18051
|
+
function verifySafeCommand(target, options = {}, stdin = process.stdin) {
|
|
18052
|
+
return safetyCommand("verify-safe", target, options, stdin);
|
|
18053
|
+
}
|
|
18054
|
+
function assessOpenedTrace(read, options = {}) {
|
|
18055
|
+
try {
|
|
18056
|
+
const rules = buildSafetyRules(options);
|
|
18057
|
+
const checkResult = runTraceChecks(
|
|
18058
|
+
{ read },
|
|
18059
|
+
{
|
|
18060
|
+
rules,
|
|
18061
|
+
...options.runId !== void 0 ? { runId: options.runId } : {},
|
|
18062
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
18063
|
+
}
|
|
18064
|
+
);
|
|
18065
|
+
const detectorFindings = checkResult.diagnostics.length === 0 ? redactionDetectorFindings(read, checkResult.runId, options.compiledPolicy) : [];
|
|
18066
|
+
return resultFromParts({
|
|
18067
|
+
command: "verify-safe",
|
|
18068
|
+
format: checkResult.format,
|
|
18069
|
+
runId: checkResult.runId,
|
|
18070
|
+
findings: [...checkResult.findings, ...detectorFindings],
|
|
18071
|
+
diagnostics: [
|
|
18072
|
+
...checkResult.diagnostics.map(diagnosticFromCheck),
|
|
18073
|
+
...warningDiagnostics(read.warnings, read.unsupportedFields)
|
|
18074
|
+
],
|
|
18075
|
+
warnings: read.warnings,
|
|
18076
|
+
unsupportedFields: read.unsupportedFields
|
|
18077
|
+
});
|
|
18078
|
+
} catch (error) {
|
|
18079
|
+
return messageStartsWithDash(error) ? invalidArgumentResult("verify-safe", error) : readErrorResult("verify-safe", error);
|
|
18080
|
+
}
|
|
18081
|
+
}
|
|
18082
|
+
function messageStartsWithDash(error) {
|
|
18083
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
18084
|
+
return message.startsWith("--");
|
|
18085
|
+
}
|
|
18086
|
+
|
|
18087
|
+
// packages/cli/src/redact.ts
|
|
18088
|
+
function parseRedactionProfile3(value) {
|
|
18089
|
+
if (value === void 0 || value === "local" || value === "share" || value === "strict") {
|
|
18090
|
+
return value ?? "share";
|
|
18091
|
+
}
|
|
18092
|
+
throw new Error(`Unsupported --profile "${value}". Use local, share, or strict.`);
|
|
18093
|
+
}
|
|
18094
|
+
function stable3(value) {
|
|
18095
|
+
if (Array.isArray(value)) return value.map(stable3);
|
|
18096
|
+
if (value === null || typeof value !== "object") return value;
|
|
18097
|
+
const record = value;
|
|
18098
|
+
return Object.fromEntries(
|
|
18099
|
+
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable3(record[key])])
|
|
18100
|
+
);
|
|
18101
|
+
}
|
|
18102
|
+
function isMissingFileError3(error) {
|
|
17055
18103
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
17056
18104
|
}
|
|
17057
18105
|
async function contentFromTarget(target, options, stdin) {
|
|
@@ -17074,16 +18122,24 @@ async function contentFromTarget(target, options, stdin) {
|
|
|
17074
18122
|
}
|
|
17075
18123
|
return { content: await promises.readFile(runPath, "utf-8"), source: runPath };
|
|
17076
18124
|
}
|
|
17077
|
-
function
|
|
18125
|
+
function applyRedact(value, profile, policy) {
|
|
18126
|
+
const result = createRedactor({
|
|
18127
|
+
profile,
|
|
18128
|
+
...policy?.extraKeys.length ? { extraKeys: [...policy.extraKeys] } : {},
|
|
18129
|
+
...policy?.detectors.length ? { detectors: [...policy.detectors] } : {}
|
|
18130
|
+
}).redact(value);
|
|
18131
|
+
return { value: result.value, findings: result.findings };
|
|
18132
|
+
}
|
|
18133
|
+
function redactJsonText(content, profile, policy) {
|
|
17078
18134
|
const parsed = JSON.parse(content);
|
|
17079
|
-
const result =
|
|
18135
|
+
const result = applyRedact(parsed, profile, policy);
|
|
17080
18136
|
return {
|
|
17081
18137
|
content: `${JSON.stringify(result.value, null, 2)}
|
|
17082
18138
|
`,
|
|
17083
18139
|
findings: result.findings
|
|
17084
18140
|
};
|
|
17085
18141
|
}
|
|
17086
|
-
function redactJsonlText(content, profile) {
|
|
18142
|
+
function redactJsonlText(content, profile, policy) {
|
|
17087
18143
|
const lines = content.split(/\r?\n/);
|
|
17088
18144
|
const out = [];
|
|
17089
18145
|
const findings = [];
|
|
@@ -17096,7 +18152,7 @@ function redactJsonlText(content, profile) {
|
|
|
17096
18152
|
} catch {
|
|
17097
18153
|
throw new Error(`Input is not valid JSON or JSONL at line ${index + 1}.`);
|
|
17098
18154
|
}
|
|
17099
|
-
const result =
|
|
18155
|
+
const result = applyRedact(parsed, profile, policy);
|
|
17100
18156
|
out.push(JSON.stringify(result.value));
|
|
17101
18157
|
findings.push(
|
|
17102
18158
|
...result.findings.map((finding) => ({
|
|
@@ -17111,43 +18167,83 @@ function redactJsonlText(content, profile) {
|
|
|
17111
18167
|
findings
|
|
17112
18168
|
};
|
|
17113
18169
|
}
|
|
17114
|
-
function redactDocument(content, profile) {
|
|
18170
|
+
function redactDocument(content, profile, policy) {
|
|
17115
18171
|
const trimmed = content.trim();
|
|
17116
18172
|
if (trimmed.startsWith("{")) {
|
|
17117
18173
|
try {
|
|
17118
18174
|
const parsed = JSON.parse(trimmed);
|
|
17119
18175
|
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && ("schemaVersion" in parsed || "eventId" in parsed || "runId" in parsed)) {
|
|
17120
|
-
return redactJsonlText(content, profile);
|
|
18176
|
+
return redactJsonlText(content, profile, policy);
|
|
17121
18177
|
}
|
|
17122
18178
|
} catch {
|
|
17123
18179
|
}
|
|
17124
18180
|
}
|
|
17125
18181
|
try {
|
|
17126
|
-
return redactJsonText(content, profile);
|
|
18182
|
+
return redactJsonText(content, profile, policy);
|
|
17127
18183
|
} catch {
|
|
17128
|
-
return redactJsonlText(content, profile);
|
|
18184
|
+
return redactJsonlText(content, profile, policy);
|
|
17129
18185
|
}
|
|
17130
18186
|
}
|
|
17131
|
-
function redactTraceContent(content, profile) {
|
|
17132
|
-
return redactDocument(content, profile);
|
|
18187
|
+
function redactTraceContent(content, profile, policy) {
|
|
18188
|
+
return redactDocument(content, profile, policy);
|
|
18189
|
+
}
|
|
18190
|
+
function looksLikeAgentInspectTrace(content) {
|
|
18191
|
+
const trimmed = content.trim();
|
|
18192
|
+
if (!trimmed.startsWith("{")) return false;
|
|
18193
|
+
try {
|
|
18194
|
+
const firstLine = trimmed.split(/\r?\n/).find((line) => line.trim() !== "") ?? trimmed;
|
|
18195
|
+
const parsed = JSON.parse(firstLine);
|
|
18196
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && ("schemaVersion" in parsed || "eventId" in parsed || "runId" in parsed);
|
|
18197
|
+
} catch {
|
|
18198
|
+
return false;
|
|
18199
|
+
}
|
|
18200
|
+
}
|
|
18201
|
+
function printResidualWarning(assessment, sourceLooksLikeTrace) {
|
|
18202
|
+
if (assessment.status === "SAFE") return;
|
|
18203
|
+
if (assessment.status === "UNKNOWN" && !sourceLooksLikeTrace) return;
|
|
18204
|
+
const codes = assessment.codes.length > 0 ? ` codes=${assessment.codes.join(",")}` : "";
|
|
18205
|
+
console.error(
|
|
18206
|
+
`Residual safety: ${assessment.status} (findings=${assessment.findings}, warnings=${assessment.warnings}, errors=${assessment.errors})${codes}. Redact does not certify safe sharing; run verify-safe before publishing.`
|
|
18207
|
+
);
|
|
18208
|
+
}
|
|
18209
|
+
function residualExitCode(assessment) {
|
|
18210
|
+
if (assessment.status === "UNSAFE") return 1;
|
|
18211
|
+
if (assessment.status === "UNKNOWN") return 2;
|
|
18212
|
+
return 0;
|
|
17133
18213
|
}
|
|
17134
18214
|
async function redactCommand(target, options = {}, stdin = process.stdin) {
|
|
17135
18215
|
const profile = parseRedactionProfile3(resolveRedactionProfileOption(options));
|
|
18216
|
+
const policy = options.policy !== void 0 ? await loadRedactionPolicy(options.policy) : void 0;
|
|
17136
18217
|
const source = await contentFromTarget(target, options, stdin);
|
|
17137
|
-
const redacted = redactDocument(source.content, profile);
|
|
18218
|
+
const redacted = redactDocument(source.content, profile, policy);
|
|
17138
18219
|
const outputPath = resolveOutputOption(options);
|
|
18220
|
+
const residualAssessment = await assessResidualFromContent(redacted.content, {
|
|
18221
|
+
compiledPolicy: policy
|
|
18222
|
+
});
|
|
17139
18223
|
if (outputPath !== void 0) {
|
|
17140
18224
|
await promises.writeFile(outputPath, redacted.content, "utf-8");
|
|
17141
18225
|
}
|
|
18226
|
+
if (options.failOnResidual === true) {
|
|
18227
|
+
process.exitCode = residualExitCode(residualAssessment);
|
|
18228
|
+
}
|
|
17142
18229
|
if (options.json) {
|
|
17143
18230
|
console.log(
|
|
17144
18231
|
JSON.stringify(
|
|
17145
|
-
|
|
18232
|
+
stable3({
|
|
17146
18233
|
ok: true,
|
|
17147
18234
|
profile,
|
|
17148
18235
|
source: source.source,
|
|
17149
18236
|
output: outputPath,
|
|
17150
18237
|
findings: redacted.findings,
|
|
18238
|
+
residualAssessment,
|
|
18239
|
+
...policy !== void 0 ? {
|
|
18240
|
+
policy: {
|
|
18241
|
+
path: policy.path,
|
|
18242
|
+
extraKeys: policy.extraKeys.length,
|
|
18243
|
+
patterns: policy.detectors.length,
|
|
18244
|
+
diagnostics: policy.diagnostics
|
|
18245
|
+
}
|
|
18246
|
+
} : {},
|
|
17151
18247
|
content: outputPath === void 0 ? redacted.content : void 0
|
|
17152
18248
|
}),
|
|
17153
18249
|
null,
|
|
@@ -17156,6 +18252,7 @@ async function redactCommand(target, options = {}, stdin = process.stdin) {
|
|
|
17156
18252
|
);
|
|
17157
18253
|
return;
|
|
17158
18254
|
}
|
|
18255
|
+
printResidualWarning(residualAssessment, looksLikeAgentInspectTrace(redacted.content));
|
|
17159
18256
|
if (outputPath === void 0) {
|
|
17160
18257
|
process.stdout.write(redacted.content);
|
|
17161
18258
|
}
|
|
@@ -17438,7 +18535,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
17438
18535
|
|
|
17439
18536
|
// packages/cli/src/migrate.ts
|
|
17440
18537
|
init_advanced();
|
|
17441
|
-
function
|
|
18538
|
+
function isRecord18(value) {
|
|
17442
18539
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17443
18540
|
}
|
|
17444
18541
|
function parseTarget(value) {
|
|
@@ -17447,7 +18544,7 @@ function parseTarget(value) {
|
|
|
17447
18544
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
17448
18545
|
}
|
|
17449
18546
|
function formatOf(value) {
|
|
17450
|
-
if (!
|
|
18547
|
+
if (!isRecord18(value)) return "unknown";
|
|
17451
18548
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
17452
18549
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
17453
18550
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -17460,14 +18557,14 @@ function uniqueSorted(values) {
|
|
|
17460
18557
|
return [...new Set(values)].sort();
|
|
17461
18558
|
}
|
|
17462
18559
|
function isWithinDirectory(child, parent) {
|
|
17463
|
-
const relative =
|
|
17464
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
18560
|
+
const relative = path33__default.default.relative(parent, child);
|
|
18561
|
+
return relative === "" || !relative.startsWith("..") && !path33__default.default.isAbsolute(relative);
|
|
17465
18562
|
}
|
|
17466
18563
|
async function resolveOutputPath(inputPath, output2, force) {
|
|
17467
18564
|
if (output2 === void 0 || output2.trim() === "") return void 0;
|
|
17468
|
-
const inputAbs =
|
|
17469
|
-
const outputAbs =
|
|
17470
|
-
const inputDir =
|
|
18565
|
+
const inputAbs = path33__default.default.resolve(inputPath);
|
|
18566
|
+
const outputAbs = path33__default.default.resolve(output2.trim());
|
|
18567
|
+
const inputDir = path33__default.default.dirname(inputAbs);
|
|
17471
18568
|
if (!isWithinDirectory(outputAbs, inputDir)) {
|
|
17472
18569
|
throw new Error("Refusing to write migrated output outside the input directory.");
|
|
17473
18570
|
}
|
|
@@ -17588,7 +18685,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
17588
18685
|
process.exitCode = 1;
|
|
17589
18686
|
return;
|
|
17590
18687
|
}
|
|
17591
|
-
const inputPath =
|
|
18688
|
+
const inputPath = path33__default.default.resolve(input3.trim());
|
|
17592
18689
|
const dryRun = options.dryRun === true;
|
|
17593
18690
|
if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
|
|
17594
18691
|
console.error("migrate requires --dry-run or --output <path>.");
|
|
@@ -17607,7 +18704,7 @@ async function migrateCommand(input3, options = {}) {
|
|
|
17607
18704
|
);
|
|
17608
18705
|
const result = await buildMigration(inputPath, outputPath);
|
|
17609
18706
|
if (!dryRun && outputPath !== void 0) {
|
|
17610
|
-
await promises.mkdir(
|
|
18707
|
+
await promises.mkdir(path33__default.default.dirname(outputPath), { recursive: true });
|
|
17611
18708
|
await promises.writeFile(outputPath, result.content, "utf-8");
|
|
17612
18709
|
}
|
|
17613
18710
|
printSummary2(result, dryRun);
|
|
@@ -17616,16 +18713,13 @@ async function migrateCommand(input3, options = {}) {
|
|
|
17616
18713
|
console.error(`[AgentInspect] migrate failed: ${msg}`);
|
|
17617
18714
|
process.exitCode = 1;
|
|
17618
18715
|
}
|
|
17619
|
-
}
|
|
17620
|
-
init_advanced();
|
|
17621
|
-
|
|
17622
|
-
// packages/core/src/entries/checks.ts
|
|
17623
|
-
init_checks2();
|
|
18716
|
+
}
|
|
18717
|
+
init_advanced();
|
|
17624
18718
|
|
|
17625
18719
|
// packages/cli/src/evidence-on.ts
|
|
17626
18720
|
init_advanced();
|
|
17627
18721
|
function validateReporterArtifactPath(options) {
|
|
17628
|
-
const outputDir =
|
|
18722
|
+
const outputDir = path33__default.default.resolve(options.outputDir);
|
|
17629
18723
|
const diagnostics = [];
|
|
17630
18724
|
const rawPath = options.relativePath;
|
|
17631
18725
|
if (rawPath.length === 0) {
|
|
@@ -17645,7 +18739,7 @@ function validateReporterArtifactPath(options) {
|
|
|
17645
18739
|
});
|
|
17646
18740
|
return { ok: false, outputDir, diagnostics };
|
|
17647
18741
|
}
|
|
17648
|
-
if (
|
|
18742
|
+
if (path33__default.default.isAbsolute(rawPath) || path33__default.default.win32.isAbsolute(rawPath)) {
|
|
17649
18743
|
diagnostics.push({
|
|
17650
18744
|
code: "artifact_path_absolute",
|
|
17651
18745
|
severity: "error",
|
|
@@ -17654,7 +18748,7 @@ function validateReporterArtifactPath(options) {
|
|
|
17654
18748
|
});
|
|
17655
18749
|
return { ok: false, outputDir, diagnostics };
|
|
17656
18750
|
}
|
|
17657
|
-
const normalized =
|
|
18751
|
+
const normalized = path33__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
|
|
17658
18752
|
const segments = normalized.split("/");
|
|
17659
18753
|
if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
|
|
17660
18754
|
diagnostics.push({
|
|
@@ -17665,9 +18759,9 @@ function validateReporterArtifactPath(options) {
|
|
|
17665
18759
|
});
|
|
17666
18760
|
return { ok: false, outputDir, diagnostics };
|
|
17667
18761
|
}
|
|
17668
|
-
const absolutePath =
|
|
17669
|
-
const relFromOutput =
|
|
17670
|
-
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") ||
|
|
18762
|
+
const absolutePath = path33__default.default.resolve(outputDir, normalized);
|
|
18763
|
+
const relFromOutput = path33__default.default.relative(outputDir, absolutePath);
|
|
18764
|
+
if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path33__default.default.isAbsolute(relFromOutput)) {
|
|
17671
18765
|
diagnostics.push({
|
|
17672
18766
|
code: "artifact_path_escape",
|
|
17673
18767
|
severity: "error",
|
|
@@ -17693,7 +18787,7 @@ var EVIDENCE_CI_ARTIFACT_FILES = [
|
|
|
17693
18787
|
function createEvidenceCiArtifacts(options) {
|
|
17694
18788
|
const profile = options.redactionProfile ?? "share";
|
|
17695
18789
|
const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
|
|
17696
|
-
const join = (name) => prefix === "" ? name :
|
|
18790
|
+
const join = (name) => prefix === "" ? name : path33__default.default.posix.join(prefix, name);
|
|
17697
18791
|
const formatFor = (name) => {
|
|
17698
18792
|
if (name.endsWith(".html")) return "html";
|
|
17699
18793
|
if (name.endsWith(".jsonl")) return "jsonl";
|
|
@@ -17742,9 +18836,9 @@ function stableJson2(value) {
|
|
|
17742
18836
|
async function writeLocalEvidence(input3) {
|
|
17743
18837
|
const profile = input3.redactionProfile ?? "share";
|
|
17744
18838
|
const format = input3.format ?? "directory";
|
|
17745
|
-
const baseDir =
|
|
18839
|
+
const baseDir = path33__default.default.resolve(input3.outputDir);
|
|
17746
18840
|
await promises.mkdir(
|
|
17747
|
-
format === "zip" && baseDir.toLowerCase().endsWith(".zip") ?
|
|
18841
|
+
format === "zip" && baseDir.toLowerCase().endsWith(".zip") ? path33__default.default.dirname(baseDir) : baseDir,
|
|
17748
18842
|
{ recursive: true }
|
|
17749
18843
|
);
|
|
17750
18844
|
const sourceContents = /* @__PURE__ */ new Map();
|
|
@@ -17800,7 +18894,7 @@ async function writeLocalEvidence(input3) {
|
|
|
17800
18894
|
}
|
|
17801
18895
|
if (format === "zip") {
|
|
17802
18896
|
const zipPath = baseDir.toLowerCase().endsWith(".zip") ? baseDir : `${baseDir}.zip`;
|
|
17803
|
-
await promises.mkdir(
|
|
18897
|
+
await promises.mkdir(path33__default.default.dirname(zipPath), { recursive: true });
|
|
17804
18898
|
const archive = buildZipArchive(
|
|
17805
18899
|
files.map(([relativePath, content]) => ({
|
|
17806
18900
|
path: relativePath,
|
|
@@ -17815,16 +18909,16 @@ async function writeLocalEvidence(input3) {
|
|
|
17815
18909
|
let sidecarDir = baseDir;
|
|
17816
18910
|
if (baseDir.toLowerCase().endsWith(".html")) {
|
|
17817
18911
|
htmlPath = baseDir;
|
|
17818
|
-
sidecarDir =
|
|
18912
|
+
sidecarDir = path33__default.default.dirname(baseDir);
|
|
17819
18913
|
} else {
|
|
17820
18914
|
await promises.mkdir(baseDir, { recursive: true });
|
|
17821
|
-
htmlPath =
|
|
18915
|
+
htmlPath = path33__default.default.join(baseDir, "evidence.html");
|
|
17822
18916
|
sidecarDir = baseDir;
|
|
17823
18917
|
}
|
|
17824
18918
|
await promises.mkdir(sidecarDir, { recursive: true });
|
|
17825
18919
|
await promises.writeFile(htmlPath, evidencePackage["evidence.html"], "utf-8");
|
|
17826
18920
|
await promises.writeFile(
|
|
17827
|
-
|
|
18921
|
+
path33__default.default.join(sidecarDir, "evidence.json"),
|
|
17828
18922
|
evidencePackage["evidence.json"],
|
|
17829
18923
|
"utf-8"
|
|
17830
18924
|
);
|
|
@@ -17832,7 +18926,7 @@ async function writeLocalEvidence(input3) {
|
|
|
17832
18926
|
}
|
|
17833
18927
|
await promises.mkdir(baseDir, { recursive: true });
|
|
17834
18928
|
for (const [name, content] of files) {
|
|
17835
|
-
await promises.writeFile(
|
|
18929
|
+
await promises.writeFile(path33__default.default.join(baseDir, name), content, "utf-8");
|
|
17836
18930
|
}
|
|
17837
18931
|
return baseDir;
|
|
17838
18932
|
}
|
|
@@ -17856,11 +18950,11 @@ function checkResultToEvidenceJson(result, runIds) {
|
|
|
17856
18950
|
}
|
|
17857
18951
|
function defaultEvidenceDir(label) {
|
|
17858
18952
|
const safe = label.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 80) || "evidence";
|
|
17859
|
-
return
|
|
18953
|
+
return path33__default.default.join(".agent-inspect", "evidence", safe);
|
|
17860
18954
|
}
|
|
17861
18955
|
function resolveEvidenceOutputDir(evidenceDir, label) {
|
|
17862
18956
|
if (evidenceDir !== void 0 && evidenceDir.trim() !== "") {
|
|
17863
|
-
return
|
|
18957
|
+
return path33__default.default.resolve(evidenceDir.trim());
|
|
17864
18958
|
}
|
|
17865
18959
|
return defaultEvidenceDir(label);
|
|
17866
18960
|
}
|
|
@@ -18184,23 +19278,23 @@ function evaluatePromptInjection(text, options = {}) {
|
|
|
18184
19278
|
}
|
|
18185
19279
|
return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
|
|
18186
19280
|
}
|
|
18187
|
-
function validateSchemaField(value, field,
|
|
19281
|
+
function validateSchemaField(value, field, path44, evidence) {
|
|
18188
19282
|
const ruleId = "guardrail.structured-output";
|
|
18189
19283
|
if (field.type) {
|
|
18190
19284
|
const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
18191
19285
|
if (actual !== field.type) {
|
|
18192
|
-
evidence.push({ ruleId, path:
|
|
19286
|
+
evidence.push({ ruleId, path: path44, preview: `expected ${field.type}, got ${actual}` });
|
|
18193
19287
|
return;
|
|
18194
19288
|
}
|
|
18195
19289
|
}
|
|
18196
19290
|
if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
|
|
18197
|
-
evidence.push({ ruleId, path:
|
|
19291
|
+
evidence.push({ ruleId, path: path44, preview: "value not in enum" });
|
|
18198
19292
|
}
|
|
18199
19293
|
if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
|
|
18200
19294
|
const record = value;
|
|
18201
19295
|
for (const key of field.required) {
|
|
18202
19296
|
if (!(key in record)) {
|
|
18203
|
-
evidence.push({ ruleId, path: `${
|
|
19297
|
+
evidence.push({ ruleId, path: `${path44}.${key}`, preview: "missing required key" });
|
|
18204
19298
|
}
|
|
18205
19299
|
}
|
|
18206
19300
|
}
|
|
@@ -18929,7 +20023,7 @@ function parseCheckConfig(value) {
|
|
|
18929
20023
|
}
|
|
18930
20024
|
async function loadConfig(configPath) {
|
|
18931
20025
|
if (configPath === void 0) return {};
|
|
18932
|
-
const extension =
|
|
20026
|
+
const extension = path33__default.default.extname(configPath);
|
|
18933
20027
|
if (TS_CONFIG_EXTENSIONS2.has(extension)) {
|
|
18934
20028
|
throw new CheckConfigError(
|
|
18935
20029
|
"AI_CHECK_CONFIG_LOAD_FAILED",
|
|
@@ -18942,7 +20036,7 @@ async function loadConfig(configPath) {
|
|
|
18942
20036
|
"Unsupported check config extension. Use .json, .js, .mjs, or .cjs."
|
|
18943
20037
|
);
|
|
18944
20038
|
}
|
|
18945
|
-
const absolute =
|
|
20039
|
+
const absolute = path33__default.default.resolve(configPath);
|
|
18946
20040
|
try {
|
|
18947
20041
|
if (extension === ".json") {
|
|
18948
20042
|
const raw = await promises.readFile(absolute, "utf-8");
|
|
@@ -19136,7 +20230,7 @@ function buildRules(config, options, presetSelect = []) {
|
|
|
19136
20230
|
diagnostics
|
|
19137
20231
|
};
|
|
19138
20232
|
}
|
|
19139
|
-
function
|
|
20233
|
+
function exitCodeFor2(result) {
|
|
19140
20234
|
if (result.status === "pass") return 0;
|
|
19141
20235
|
if (result.status === "fail") return 1;
|
|
19142
20236
|
const codes = result.diagnostics.map((item) => item.code);
|
|
@@ -19157,16 +20251,16 @@ function exitCodeFor(result) {
|
|
|
19157
20251
|
}
|
|
19158
20252
|
return 1;
|
|
19159
20253
|
}
|
|
19160
|
-
function
|
|
19161
|
-
if (Array.isArray(value)) return value.map(
|
|
20254
|
+
function stable4(value) {
|
|
20255
|
+
if (Array.isArray(value)) return value.map(stable4);
|
|
19162
20256
|
if (value === null || typeof value !== "object") return value;
|
|
19163
20257
|
const record = value;
|
|
19164
20258
|
return Object.fromEntries(
|
|
19165
|
-
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key,
|
|
20259
|
+
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable4(record[key])])
|
|
19166
20260
|
);
|
|
19167
20261
|
}
|
|
19168
|
-
function
|
|
19169
|
-
console.log(JSON.stringify(
|
|
20262
|
+
function printJson2(result) {
|
|
20263
|
+
console.log(JSON.stringify(stable4(result), null, 2));
|
|
19170
20264
|
}
|
|
19171
20265
|
function isSafetyFinding(ruleId) {
|
|
19172
20266
|
return ruleId.startsWith("safety.") || ruleId.startsWith("guardrail.") || ruleId.includes("pii") || ruleId.includes("secret");
|
|
@@ -19203,7 +20297,7 @@ function printPresetClassSummary(result, preset) {
|
|
|
19203
20297
|
`Share safety: ${hasSafetyFindings || result.status === "fail" ? "FAIL" : result.status === "pass" ? "PASS" : "FAIL"}`
|
|
19204
20298
|
);
|
|
19205
20299
|
}
|
|
19206
|
-
function
|
|
20300
|
+
function printHuman2(result, options = {}) {
|
|
19207
20301
|
const scoped = result;
|
|
19208
20302
|
if (scoped.scopeLabel) {
|
|
19209
20303
|
console.log(`Scope: ${scoped.scopeKind} ${scoped.scopeLabel}`);
|
|
@@ -19223,13 +20317,13 @@ function printHuman(result, options = {}) {
|
|
|
19223
20317
|
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
19224
20318
|
}
|
|
19225
20319
|
for (const finding of result.findings) {
|
|
19226
|
-
const
|
|
20320
|
+
const path44 = finding.evidence[0]?.path;
|
|
19227
20321
|
const run = finding.evidence[0]?.runId;
|
|
19228
20322
|
const runPrefix = run ? `[${run}] ` : "";
|
|
19229
|
-
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${
|
|
20323
|
+
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path44 ? ` (${path44})` : ""}`);
|
|
19230
20324
|
}
|
|
19231
20325
|
}
|
|
19232
|
-
function
|
|
20326
|
+
function readErrorResult2(error) {
|
|
19233
20327
|
if (error instanceof TraceReadError) {
|
|
19234
20328
|
const code = error.code === "unsupported_format" ? "AI_CHECK_UNSUPPORTED_FORMAT" : error.code === "ambiguous_format" ? "AI_CHECK_AMBIGUOUS_FORMAT" : "AI_CHECK_TRACE_UNREADABLE";
|
|
19235
20329
|
return errorResult2(code, error.message);
|
|
@@ -19256,9 +20350,9 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
19256
20350
|
"AI_CHECK_CONFIG_NO_EFFECTIVE_RULES",
|
|
19257
20351
|
"Explicit --config has no effective check rules. Configure checks.select, checks.run, checks.tool, checks.llm, checks.structure, or checks.safety."
|
|
19258
20352
|
);
|
|
19259
|
-
if (options.json)
|
|
19260
|
-
else
|
|
19261
|
-
process.exitCode =
|
|
20353
|
+
if (options.json) printJson2(result);
|
|
20354
|
+
else printHuman2(result, options);
|
|
20355
|
+
process.exitCode = exitCodeFor2(result);
|
|
19262
20356
|
return;
|
|
19263
20357
|
}
|
|
19264
20358
|
let effectiveOptions = options;
|
|
@@ -19388,10 +20482,10 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
19388
20482
|
result = errorResult2(code, message);
|
|
19389
20483
|
}
|
|
19390
20484
|
} else {
|
|
19391
|
-
result =
|
|
20485
|
+
result = readErrorResult2(error);
|
|
19392
20486
|
}
|
|
19393
20487
|
}
|
|
19394
|
-
process.exitCode =
|
|
20488
|
+
process.exitCode = exitCodeFor2(result);
|
|
19395
20489
|
const failed = result.status !== "pass";
|
|
19396
20490
|
if (shouldEmitEvidence(options.evidenceOn, failed)) {
|
|
19397
20491
|
try {
|
|
@@ -19431,8 +20525,8 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
19431
20525
|
);
|
|
19432
20526
|
}
|
|
19433
20527
|
}
|
|
19434
|
-
if (options.json)
|
|
19435
|
-
else
|
|
20528
|
+
if (options.json) printJson2(result);
|
|
20529
|
+
else printHuman2(result, options);
|
|
19436
20530
|
}
|
|
19437
20531
|
|
|
19438
20532
|
// packages/viewer/src/server.ts
|
|
@@ -19589,7 +20683,7 @@ async function loadSuiteViewerData(options) {
|
|
|
19589
20683
|
for (const suiteCase of result.cases) {
|
|
19590
20684
|
cases.push(await enrichCase(suiteCase, baselinePath));
|
|
19591
20685
|
}
|
|
19592
|
-
const artifactsDir =
|
|
20686
|
+
const artifactsDir = path33__default.default.join(path33__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
|
|
19593
20687
|
return {
|
|
19594
20688
|
suiteName: result.suiteName,
|
|
19595
20689
|
configPath: result.configPath,
|
|
@@ -19785,19 +20879,19 @@ function serializeWorkspaceManifest(manifest) {
|
|
|
19785
20879
|
}
|
|
19786
20880
|
var INDEX_DIR_NAME = "index";
|
|
19787
20881
|
function resolveWorkspaceLocation(cwd = process.cwd()) {
|
|
19788
|
-
const projectRoot =
|
|
19789
|
-
const workspaceDir =
|
|
20882
|
+
const projectRoot = path33__default.default.resolve(cwd);
|
|
20883
|
+
const workspaceDir = path33__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
|
|
19790
20884
|
return {
|
|
19791
20885
|
projectRoot,
|
|
19792
20886
|
workspaceDir,
|
|
19793
|
-
manifestPath:
|
|
20887
|
+
manifestPath: path33__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
|
|
19794
20888
|
};
|
|
19795
20889
|
}
|
|
19796
20890
|
function resolveInsideWorkspace(workspaceDir, relative) {
|
|
19797
|
-
const base =
|
|
19798
|
-
const resolved =
|
|
19799
|
-
const rel =
|
|
19800
|
-
if (rel === "" || rel === "." || !rel.startsWith("..") && !
|
|
20891
|
+
const base = path33__default.default.resolve(workspaceDir);
|
|
20892
|
+
const resolved = path33__default.default.resolve(base, relative);
|
|
20893
|
+
const rel = path33__default.default.relative(base, resolved);
|
|
20894
|
+
if (rel === "" || rel === "." || !rel.startsWith("..") && !path33__default.default.isAbsolute(rel)) {
|
|
19801
20895
|
return resolved;
|
|
19802
20896
|
}
|
|
19803
20897
|
throw new Error(
|
|
@@ -19866,7 +20960,7 @@ async function createWorkspace(options = {}) {
|
|
|
19866
20960
|
created = false;
|
|
19867
20961
|
adopted = true;
|
|
19868
20962
|
} else {
|
|
19869
|
-
const project = options.project?.trim() ||
|
|
20963
|
+
const project = options.project?.trim() || path33__default.default.basename(location.projectRoot) || "workspace";
|
|
19870
20964
|
const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
|
|
19871
20965
|
manifest = createDefaultWorkspaceManifest({
|
|
19872
20966
|
project,
|
|
@@ -20005,7 +21099,7 @@ async function doctorWorkspace(location) {
|
|
|
20005
21099
|
const abs = resolveInsideWorkspace(location.workspaceDir, rel);
|
|
20006
21100
|
for (const file of await listJsonl(abs)) {
|
|
20007
21101
|
try {
|
|
20008
|
-
const s = await promises.stat(
|
|
21102
|
+
const s = await promises.stat(path33__default.default.join(abs, file));
|
|
20009
21103
|
newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
|
|
20010
21104
|
} catch {
|
|
20011
21105
|
checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
|
|
@@ -20053,7 +21147,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
|
|
|
20053
21147
|
const relPath = `${rel}/${entry}`;
|
|
20054
21148
|
removed.push(relPath);
|
|
20055
21149
|
if (!dryRun) {
|
|
20056
|
-
await promises.rm(
|
|
21150
|
+
await promises.rm(path33__default.default.join(abs, entry), { recursive: true, force: true });
|
|
20057
21151
|
}
|
|
20058
21152
|
}
|
|
20059
21153
|
}
|
|
@@ -20062,7 +21156,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
|
|
|
20062
21156
|
|
|
20063
21157
|
// packages/viewer/src/workspace-data.ts
|
|
20064
21158
|
async function loadWorkspaceViewerData(options) {
|
|
20065
|
-
const cwd =
|
|
21159
|
+
const cwd = path33__default.default.resolve(options.cwd ?? process.cwd());
|
|
20066
21160
|
const location = resolveWorkspaceLocation(cwd);
|
|
20067
21161
|
const manifestRead = await readWorkspaceManifestFile(location);
|
|
20068
21162
|
if (!manifestRead.ok || manifestRead.manifest === void 0) {
|
|
@@ -20075,7 +21169,7 @@ async function loadWorkspaceViewerData(options) {
|
|
|
20075
21169
|
const runs = [];
|
|
20076
21170
|
for (const rel of manifestRead.manifest.traceDirs) {
|
|
20077
21171
|
const traceDir = resolveTraceDir({
|
|
20078
|
-
dir:
|
|
21172
|
+
dir: path33__default.default.join(location.workspaceDir, rel)
|
|
20079
21173
|
});
|
|
20080
21174
|
const td = new TraceDirectory({ dir: traceDir });
|
|
20081
21175
|
const files = await td.list();
|
|
@@ -20089,7 +21183,7 @@ async function loadWorkspaceViewerData(options) {
|
|
|
20089
21183
|
runId: meta2.runId,
|
|
20090
21184
|
...meta2.name !== void 0 ? { name: meta2.name } : {},
|
|
20091
21185
|
status: meta2.status,
|
|
20092
|
-
file:
|
|
21186
|
+
file: path33__default.default.basename(meta2.filePath)
|
|
20093
21187
|
});
|
|
20094
21188
|
}
|
|
20095
21189
|
}
|
|
@@ -20100,8 +21194,8 @@ async function loadWorkspaceViewerData(options) {
|
|
|
20100
21194
|
doctor,
|
|
20101
21195
|
runs,
|
|
20102
21196
|
bundleDirs: [
|
|
20103
|
-
|
|
20104
|
-
|
|
21197
|
+
path33__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
|
|
21198
|
+
path33__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
|
|
20105
21199
|
]
|
|
20106
21200
|
};
|
|
20107
21201
|
}
|
|
@@ -20164,7 +21258,7 @@ function createViewerServer(options = {}) {
|
|
|
20164
21258
|
ok: true,
|
|
20165
21259
|
readOnly: true,
|
|
20166
21260
|
mode,
|
|
20167
|
-
traceDir:
|
|
21261
|
+
traceDir: path33__default.default.resolve(traceDir)
|
|
20168
21262
|
});
|
|
20169
21263
|
}
|
|
20170
21264
|
if (pathname === "/api/suite" && mode === "suite") {
|
|
@@ -20193,7 +21287,7 @@ function createViewerServer(options = {}) {
|
|
|
20193
21287
|
runId: meta2.runId,
|
|
20194
21288
|
name: meta2.name,
|
|
20195
21289
|
status: meta2.status,
|
|
20196
|
-
file:
|
|
21290
|
+
file: path33__default.default.basename(meta2.filePath),
|
|
20197
21291
|
startedAt: meta2.startedAt,
|
|
20198
21292
|
durationMs: meta2.durationMs
|
|
20199
21293
|
}))
|
|
@@ -20310,7 +21404,7 @@ function startViewerServer(options = {}) {
|
|
|
20310
21404
|
resolve({
|
|
20311
21405
|
host,
|
|
20312
21406
|
port: resolvedPort,
|
|
20313
|
-
traceDir:
|
|
21407
|
+
traceDir: path33__default.default.resolve(traceDir),
|
|
20314
21408
|
url: `http://${host}:${resolvedPort}/${modeQuery}`,
|
|
20315
21409
|
mode
|
|
20316
21410
|
});
|
|
@@ -20721,10 +21815,10 @@ async function evalRun(input3, options = {}) {
|
|
|
20721
21815
|
diagnostics: []
|
|
20722
21816
|
};
|
|
20723
21817
|
}
|
|
20724
|
-
function evidenceForRun(run,
|
|
20725
|
-
return [{ runId: run.runId, ...
|
|
21818
|
+
function evidenceForRun(run, path44) {
|
|
21819
|
+
return [{ runId: run.runId, ...path44 !== void 0 ? { path: path44 } : {} }];
|
|
20726
21820
|
}
|
|
20727
|
-
function evidenceForEvent(event,
|
|
21821
|
+
function evidenceForEvent(event, path44) {
|
|
20728
21822
|
return [
|
|
20729
21823
|
{
|
|
20730
21824
|
runId: event.runId,
|
|
@@ -20732,7 +21826,7 @@ function evidenceForEvent(event, path43) {
|
|
|
20732
21826
|
...event.parentId !== void 0 ? { parentId: event.parentId } : {},
|
|
20733
21827
|
kind: event.kind,
|
|
20734
21828
|
name: event.name,
|
|
20735
|
-
...
|
|
21829
|
+
...path44 !== void 0 ? { path: path44 } : {}
|
|
20736
21830
|
}
|
|
20737
21831
|
];
|
|
20738
21832
|
}
|
|
@@ -20890,9 +21984,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
|
|
|
20890
21984
|
function tokenize(text) {
|
|
20891
21985
|
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));
|
|
20892
21986
|
}
|
|
20893
|
-
function firstEvidence(fields, run,
|
|
21987
|
+
function firstEvidence(fields, run, path44) {
|
|
20894
21988
|
const first = fields[0];
|
|
20895
|
-
return first === void 0 ? evidenceForRun(run,
|
|
21989
|
+
return first === void 0 ? evidenceForRun(run, path44) : evidenceForEvent(first.node.event, first.path);
|
|
20896
21990
|
}
|
|
20897
21991
|
function collectSourceIds(nodes, keys) {
|
|
20898
21992
|
const wanted = keySet(keys);
|
|
@@ -21245,273 +22339,55 @@ var checks = {
|
|
|
21245
22339
|
"Answer contained banned unsupported-answer phrasing.",
|
|
21246
22340
|
firstEvidence(answers, context.run, "attributes.answer"),
|
|
21247
22341
|
{ bannedPhraseCount: banned.length },
|
|
21248
|
-
{ matchedPhraseCount: matches.length }
|
|
21249
|
-
)
|
|
21250
|
-
] : [];
|
|
21251
|
-
});
|
|
21252
|
-
}
|
|
21253
|
-
};
|
|
21254
|
-
function renderEvalMarkdown(result) {
|
|
21255
|
-
const lines = [
|
|
21256
|
-
`# AgentInspect Eval`,
|
|
21257
|
-
"",
|
|
21258
|
-
`Status: ${result.status}`,
|
|
21259
|
-
`Format: ${result.format}`,
|
|
21260
|
-
...result.runId !== void 0 ? [`Run: ${result.runId}`] : [],
|
|
21261
|
-
`Summary: ${result.summary.passed} passed, ${result.summary.failed} failed, ${result.summary.warnings} warnings, ${result.summary.errors} errors`
|
|
21262
|
-
];
|
|
21263
|
-
if (result.diagnostics.length > 0) {
|
|
21264
|
-
lines.push("", "## Diagnostics");
|
|
21265
|
-
for (const diagnostic7 of result.diagnostics) {
|
|
21266
|
-
lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
21267
|
-
}
|
|
21268
|
-
}
|
|
21269
|
-
if (result.findings.length > 0) {
|
|
21270
|
-
lines.push("", "## Findings");
|
|
21271
|
-
for (const finding of result.findings) {
|
|
21272
|
-
const path43 = finding.evidence[0]?.path;
|
|
21273
|
-
lines.push(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}`);
|
|
21274
|
-
}
|
|
21275
|
-
}
|
|
21276
|
-
return `${lines.join("\n")}
|
|
21277
|
-
`;
|
|
21278
|
-
}
|
|
21279
|
-
|
|
21280
|
-
// packages/cli/src/eval.ts
|
|
21281
|
-
var CONFIG_EXTENSIONS3 = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
21282
|
-
var TS_CONFIG_EXTENSIONS3 = /* @__PURE__ */ new Set([".ts", ".mts", ".cts"]);
|
|
21283
|
-
function diagnostic6(code, message, severity = "error") {
|
|
21284
|
-
return { code, message, severity };
|
|
21285
|
-
}
|
|
21286
|
-
function errorResult4(code, message, format = "unknown") {
|
|
21287
|
-
return {
|
|
21288
|
-
ok: false,
|
|
21289
|
-
status: "error",
|
|
21290
|
-
format,
|
|
21291
|
-
summary: { passed: 0, failed: 0, warnings: 0, errors: 1 },
|
|
21292
|
-
findings: [],
|
|
21293
|
-
diagnostics: [diagnostic6(code, message)]
|
|
21294
|
-
};
|
|
21295
|
-
}
|
|
21296
|
-
function parseNumber2(value, label) {
|
|
21297
|
-
if (value === void 0) return void 0;
|
|
21298
|
-
const parsed = Number(value);
|
|
21299
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
21300
|
-
throw new Error(`${label} must be a non-negative number.`);
|
|
21301
|
-
}
|
|
21302
|
-
return parsed;
|
|
21303
|
-
}
|
|
21304
|
-
function asStringArray3(value, label) {
|
|
21305
|
-
if (value === void 0) return void 0;
|
|
21306
|
-
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
21307
|
-
throw new Error(`${label} must be an array of strings.`);
|
|
21308
|
-
}
|
|
21309
|
-
return value;
|
|
21310
|
-
}
|
|
21311
|
-
function asConfig(value) {
|
|
21312
|
-
if (value === void 0 || value === null) return {};
|
|
21313
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
21314
|
-
throw new Error("Config must export an object.");
|
|
21315
|
-
}
|
|
21316
|
-
return value;
|
|
21317
|
-
}
|
|
21318
|
-
async function loadConfig2(configPath) {
|
|
21319
|
-
if (configPath === void 0) return {};
|
|
21320
|
-
const extension = path32__default.default.extname(configPath);
|
|
21321
|
-
if (TS_CONFIG_EXTENSIONS3.has(extension)) {
|
|
21322
|
-
throw new Error(
|
|
21323
|
-
"TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
21324
|
-
);
|
|
21325
|
-
}
|
|
21326
|
-
if (!CONFIG_EXTENSIONS3.has(extension)) {
|
|
21327
|
-
throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
|
|
21328
|
-
}
|
|
21329
|
-
const absolute = path32__default.default.resolve(configPath);
|
|
21330
|
-
if (extension === ".json") {
|
|
21331
|
-
const raw = await promises.readFile(absolute, "utf-8");
|
|
21332
|
-
return asConfig(JSON.parse(raw));
|
|
21333
|
-
}
|
|
21334
|
-
const mod = await import(url.pathToFileURL(absolute).href);
|
|
21335
|
-
return asConfig("default" in mod ? mod.default : mod);
|
|
21336
|
-
}
|
|
21337
|
-
function normalizeConfig2(config) {
|
|
21338
|
-
if (config.eval === void 0) return {};
|
|
21339
|
-
if (typeof config.eval !== "object" || Array.isArray(config.eval)) {
|
|
21340
|
-
throw new Error("eval config must be an object.");
|
|
21341
|
-
}
|
|
21342
|
-
return config.eval;
|
|
21343
|
-
}
|
|
21344
|
-
function maybeAdd(rules, value, makeRule) {
|
|
21345
|
-
if (value !== void 0) rules.push(makeRule(value));
|
|
21346
|
-
}
|
|
21347
|
-
function optionObject(value) {
|
|
21348
|
-
if (value === void 0 || value === false) return void 0;
|
|
21349
|
-
if (value === true) return {};
|
|
21350
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
21351
|
-
throw new Error("Eval heuristic config must be a boolean or object.");
|
|
21352
|
-
}
|
|
21353
|
-
return value;
|
|
21354
|
-
}
|
|
21355
|
-
function sourceIdsFromConfig(value) {
|
|
21356
|
-
if (value === void 0) return void 0;
|
|
21357
|
-
if (Array.isArray(value)) return { ids: asStringArray3(value, "eval.requiredSourceIds") ?? [] };
|
|
21358
|
-
if (typeof value !== "object" || Array.isArray(value)) {
|
|
21359
|
-
throw new Error("eval.requiredSourceIds must be an array or object.");
|
|
21360
|
-
}
|
|
21361
|
-
const ids = asStringArray3(value.ids, "eval.requiredSourceIds.ids") ?? [];
|
|
21362
|
-
return { ids, options: { sourceIdKeys: value.sourceIdKeys } };
|
|
21363
|
-
}
|
|
21364
|
-
function buildRules2(config, options) {
|
|
21365
|
-
const evalConfig = normalizeConfig2(config);
|
|
21366
|
-
const rules = [];
|
|
21367
|
-
if (evalConfig.requireSuccess || options.requireSuccess) rules.push(checks.requireSuccess());
|
|
21368
|
-
const requiredTools = [
|
|
21369
|
-
...asStringArray3(evalConfig.requiredTools, "eval.requiredTools") ?? [],
|
|
21370
|
-
...options.requiredTool ?? []
|
|
21371
|
-
];
|
|
21372
|
-
if (requiredTools.length > 0) rules.push(checks.requiredTools(requiredTools));
|
|
21373
|
-
const forbiddenTools = [
|
|
21374
|
-
...asStringArray3(evalConfig.forbiddenTools, "eval.forbiddenTools") ?? [],
|
|
21375
|
-
...options.forbidTool ?? [],
|
|
21376
|
-
...options.forbiddenTool ?? []
|
|
21377
|
-
];
|
|
21378
|
-
if (forbiddenTools.length > 0) rules.push(checks.forbiddenTools(forbiddenTools));
|
|
21379
|
-
const maxDurationMs = parseNumber2(options.maxDurationMs, "--max-duration-ms") ?? evalConfig.maxDurationMs;
|
|
21380
|
-
maybeAdd(rules, maxDurationMs, checks.maxDurationMs);
|
|
21381
|
-
const maxDepth = parseNumber2(options.maxDepth, "--max-depth") ?? evalConfig.maxDepth;
|
|
21382
|
-
maybeAdd(rules, maxDepth, checks.maxDepth);
|
|
21383
|
-
const maxRetries = parseNumber2(options.maxRetries, "--max-retries") ?? evalConfig.maxRetries;
|
|
21384
|
-
maybeAdd(rules, maxRetries, checks.maxRetries);
|
|
21385
|
-
const maxTotalTokens = parseNumber2(options.maxTotalTokens, "--max-total-tokens") ?? evalConfig.maxTotalTokens;
|
|
21386
|
-
maybeAdd(rules, maxTotalTokens, checks.maxTotalTokens);
|
|
21387
|
-
if (evalConfig.requiredRetrievalBeforeGeneration || options.requireRetrievalBeforeGeneration) {
|
|
21388
|
-
rules.push(checks.requiredRetrievalBeforeGeneration());
|
|
21389
|
-
}
|
|
21390
|
-
const requiredDecisionMetadata = [
|
|
21391
|
-
...asStringArray3(
|
|
21392
|
-
evalConfig.requiredDecisionMetadata,
|
|
21393
|
-
"eval.requiredDecisionMetadata"
|
|
21394
|
-
) ?? [],
|
|
21395
|
-
...options.requiredDecisionMetadata ?? []
|
|
21396
|
-
];
|
|
21397
|
-
if (requiredDecisionMetadata.length > 0) {
|
|
21398
|
-
rules.push(checks.requiredDecisionMetadata(requiredDecisionMetadata));
|
|
21399
|
-
}
|
|
21400
|
-
const contextOverlap = optionObject(evalConfig.contextOverlap);
|
|
21401
|
-
const minOverlap = parseNumber2(options.minContextOverlap, "--min-context-overlap");
|
|
21402
|
-
const minSharedTerms = parseNumber2(options.minSharedTerms, "--min-shared-terms");
|
|
21403
|
-
if (contextOverlap !== void 0 || options.contextOverlap || minOverlap !== void 0 || minSharedTerms !== void 0) {
|
|
21404
|
-
rules.push(checks.contextOverlap({ ...contextOverlap, minOverlap, minSharedTerms }));
|
|
21405
|
-
}
|
|
21406
|
-
const quoteOverlap = optionObject(evalConfig.quoteOverlap);
|
|
21407
|
-
if (quoteOverlap !== void 0 || options.quoteOverlap) {
|
|
21408
|
-
rules.push(checks.quoteOverlap(quoteOverlap));
|
|
21409
|
-
}
|
|
21410
|
-
const citationPresence = optionObject(evalConfig.citationPresence);
|
|
21411
|
-
if (citationPresence !== void 0 || options.citationPresence) {
|
|
21412
|
-
rules.push(checks.citationPresence(citationPresence));
|
|
21413
|
-
}
|
|
21414
|
-
const sourceIds = sourceIdsFromConfig(evalConfig.requiredSourceIds);
|
|
21415
|
-
const requiredSourceIds = [...sourceIds?.ids ?? [], ...options.requiredSourceId ?? []];
|
|
21416
|
-
if (requiredSourceIds.length > 0) {
|
|
21417
|
-
rules.push(checks.requiredSourceIds(requiredSourceIds, sourceIds?.options));
|
|
21418
|
-
}
|
|
21419
|
-
const cliAnswerLength = {
|
|
21420
|
-
minCharacters: parseNumber2(options.minAnswerCharacters, "--min-answer-characters"),
|
|
21421
|
-
maxCharacters: parseNumber2(options.maxAnswerCharacters, "--max-answer-characters"),
|
|
21422
|
-
minWords: parseNumber2(options.minAnswerWords, "--min-answer-words"),
|
|
21423
|
-
maxWords: parseNumber2(options.maxAnswerWords, "--max-answer-words")
|
|
21424
|
-
};
|
|
21425
|
-
const hasCliAnswerLength = Object.values(cliAnswerLength).some((value) => value !== void 0);
|
|
21426
|
-
if (evalConfig.answerLengthBounds !== void 0 || hasCliAnswerLength) {
|
|
21427
|
-
rules.push(checks.answerLengthBounds({ ...evalConfig.answerLengthBounds, ...cliAnswerLength }));
|
|
21428
|
-
}
|
|
21429
|
-
const bannedPhrases = [
|
|
21430
|
-
...asStringArray3(
|
|
21431
|
-
evalConfig.bannedUnsupportedPhrases,
|
|
21432
|
-
"eval.bannedUnsupportedPhrases"
|
|
21433
|
-
) ?? [],
|
|
21434
|
-
...options.bannedPhrase ?? []
|
|
21435
|
-
];
|
|
21436
|
-
if (bannedPhrases.length > 0) rules.push(checks.bannedUnsupportedPhrases(bannedPhrases));
|
|
21437
|
-
return rules.length > 0 ? rules : void 0;
|
|
21438
|
-
}
|
|
21439
|
-
function exitCodeFor2(result) {
|
|
21440
|
-
if (result.status === "pass") return 0;
|
|
21441
|
-
if (result.status === "fail") return 1;
|
|
21442
|
-
return 2;
|
|
21443
|
-
}
|
|
21444
|
-
function stable4(value) {
|
|
21445
|
-
if (Array.isArray(value)) return value.map(stable4);
|
|
21446
|
-
if (value === null || typeof value !== "object") return value;
|
|
21447
|
-
const record = value;
|
|
21448
|
-
return Object.fromEntries(
|
|
21449
|
-
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable4(record[key])])
|
|
21450
|
-
);
|
|
21451
|
-
}
|
|
21452
|
-
function printJson2(result) {
|
|
21453
|
-
console.log(JSON.stringify(stable4(result), null, 2));
|
|
21454
|
-
}
|
|
21455
|
-
function printHuman2(result) {
|
|
21456
|
-
console.log(`Eval status: ${result.status}`);
|
|
21457
|
-
console.log(`Format: ${result.format}`);
|
|
21458
|
-
if (result.runId !== void 0) console.log(`Run: ${result.runId}`);
|
|
21459
|
-
console.log(
|
|
21460
|
-
`Summary: ${result.summary.failed} failed, ${result.summary.warnings} warning(s), ${result.summary.errors} error(s)`
|
|
21461
|
-
);
|
|
21462
|
-
for (const diagnostic7 of result.diagnostics) {
|
|
21463
|
-
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
21464
|
-
}
|
|
21465
|
-
for (const finding of result.findings) {
|
|
21466
|
-
const path43 = finding.evidence[0]?.path;
|
|
21467
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}`);
|
|
21468
|
-
}
|
|
21469
|
-
}
|
|
21470
|
-
function readErrorResult2(error) {
|
|
21471
|
-
if (error instanceof TraceReadError) {
|
|
21472
|
-
const code = error.code === "unsupported_format" ? "AI_EVAL_UNSUPPORTED_FORMAT" : error.code === "ambiguous_format" ? "AI_EVAL_AMBIGUOUS_FORMAT" : "AI_EVAL_TRACE_UNREADABLE";
|
|
21473
|
-
return errorResult4(code, error.message);
|
|
21474
|
-
}
|
|
21475
|
-
return errorResult4(
|
|
21476
|
-
"AI_EVAL_TRACE_UNREADABLE",
|
|
21477
|
-
error instanceof Error ? error.message : String(error)
|
|
21478
|
-
);
|
|
21479
|
-
}
|
|
21480
|
-
async function evalCommand(target, options = {}, stdin = process.stdin) {
|
|
21481
|
-
let result;
|
|
21482
|
-
let phase = "config";
|
|
21483
|
-
try {
|
|
21484
|
-
const config = await loadConfig2(options.config);
|
|
21485
|
-
const rules = buildRules2(config, options);
|
|
21486
|
-
phase = "read";
|
|
21487
|
-
const input3 = await inputFromTarget(target, options, stdin);
|
|
21488
|
-
const read = await openTrace(input3, {
|
|
21489
|
-
...options.format !== void 0 ? { format: options.format } : {}
|
|
21490
|
-
});
|
|
21491
|
-
result = await evalRun(read, {
|
|
21492
|
-
...rules !== void 0 ? { checks: rules } : {},
|
|
21493
|
-
...options.run !== void 0 ? { runId: options.run } : {}
|
|
22342
|
+
{ matchedPhraseCount: matches.length }
|
|
22343
|
+
)
|
|
22344
|
+
] : [];
|
|
21494
22345
|
});
|
|
21495
|
-
}
|
|
21496
|
-
|
|
21497
|
-
|
|
21498
|
-
|
|
21499
|
-
|
|
21500
|
-
|
|
21501
|
-
|
|
22346
|
+
}
|
|
22347
|
+
};
|
|
22348
|
+
function renderEvalMarkdown(result) {
|
|
22349
|
+
const lines = [
|
|
22350
|
+
`# AgentInspect Eval`,
|
|
22351
|
+
"",
|
|
22352
|
+
`Status: ${result.status}`,
|
|
22353
|
+
`Format: ${result.format}`,
|
|
22354
|
+
...result.runId !== void 0 ? [`Run: ${result.runId}`] : [],
|
|
22355
|
+
`Summary: ${result.summary.passed} passed, ${result.summary.failed} failed, ${result.summary.warnings} warnings, ${result.summary.errors} errors`
|
|
22356
|
+
];
|
|
22357
|
+
if (result.diagnostics.length > 0) {
|
|
22358
|
+
lines.push("", "## Diagnostics");
|
|
22359
|
+
for (const diagnostic7 of result.diagnostics) {
|
|
22360
|
+
lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
21502
22361
|
}
|
|
21503
22362
|
}
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
|
|
21507
|
-
|
|
22363
|
+
if (result.findings.length > 0) {
|
|
22364
|
+
lines.push("", "## Findings");
|
|
22365
|
+
for (const finding of result.findings) {
|
|
22366
|
+
const path44 = finding.evidence[0]?.path;
|
|
22367
|
+
lines.push(`- ${finding.ruleId}: ${finding.message}${path44 ? ` (${path44})` : ""}`);
|
|
22368
|
+
}
|
|
22369
|
+
}
|
|
22370
|
+
return `${lines.join("\n")}
|
|
22371
|
+
`;
|
|
21508
22372
|
}
|
|
21509
|
-
|
|
21510
|
-
|
|
21511
|
-
var
|
|
21512
|
-
var
|
|
21513
|
-
|
|
21514
|
-
|
|
22373
|
+
|
|
22374
|
+
// packages/cli/src/eval.ts
|
|
22375
|
+
var CONFIG_EXTENSIONS3 = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
22376
|
+
var TS_CONFIG_EXTENSIONS3 = /* @__PURE__ */ new Set([".ts", ".mts", ".cts"]);
|
|
22377
|
+
function diagnostic6(code, message, severity = "error") {
|
|
22378
|
+
return { code, message, severity };
|
|
22379
|
+
}
|
|
22380
|
+
function errorResult4(code, message, format = "unknown") {
|
|
22381
|
+
return {
|
|
22382
|
+
ok: false,
|
|
22383
|
+
status: "error",
|
|
22384
|
+
format,
|
|
22385
|
+
summary: { passed: 0, failed: 0, warnings: 0, errors: 1 },
|
|
22386
|
+
findings: [],
|
|
22387
|
+
diagnostics: [diagnostic6(code, message)]
|
|
22388
|
+
};
|
|
22389
|
+
}
|
|
22390
|
+
function parseNumber2(value, label) {
|
|
21515
22391
|
if (value === void 0) return void 0;
|
|
21516
22392
|
const parsed = Number(value);
|
|
21517
22393
|
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
@@ -21519,368 +22395,210 @@ function parseLimit3(value, label) {
|
|
|
21519
22395
|
}
|
|
21520
22396
|
return parsed;
|
|
21521
22397
|
}
|
|
21522
|
-
function
|
|
21523
|
-
if (
|
|
21524
|
-
if (value
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
);
|
|
21529
|
-
}
|
|
21530
|
-
function safetyDiagnostic(code, message, severity = "error") {
|
|
21531
|
-
return { code, message, severity };
|
|
21532
|
-
}
|
|
21533
|
-
function warningDiagnostics(warnings, unsupportedFields) {
|
|
21534
|
-
return [
|
|
21535
|
-
...warnings.map(
|
|
21536
|
-
(warning) => safetyDiagnostic(
|
|
21537
|
-
warning.code,
|
|
21538
|
-
warning.message,
|
|
21539
|
-
warning.severity === "error" ? "error" : "warning"
|
|
21540
|
-
)
|
|
21541
|
-
),
|
|
21542
|
-
...unsupportedFields.map(
|
|
21543
|
-
(field) => safetyDiagnostic(
|
|
21544
|
-
"unsupported_field",
|
|
21545
|
-
`Reader reported unsupported field: ${field}`,
|
|
21546
|
-
"warning"
|
|
21547
|
-
)
|
|
21548
|
-
)
|
|
21549
|
-
];
|
|
22398
|
+
function asStringArray3(value, label) {
|
|
22399
|
+
if (value === void 0) return void 0;
|
|
22400
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
22401
|
+
throw new Error(`${label} must be an array of strings.`);
|
|
22402
|
+
}
|
|
22403
|
+
return value;
|
|
21550
22404
|
}
|
|
21551
|
-
function
|
|
21552
|
-
|
|
22405
|
+
function asConfig(value) {
|
|
22406
|
+
if (value === void 0 || value === null) return {};
|
|
22407
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
22408
|
+
throw new Error("Config must export an object.");
|
|
22409
|
+
}
|
|
22410
|
+
return value;
|
|
21553
22411
|
}
|
|
21554
|
-
function
|
|
21555
|
-
if (
|
|
21556
|
-
|
|
21557
|
-
if (
|
|
21558
|
-
|
|
21559
|
-
|
|
22412
|
+
async function loadConfig2(configPath) {
|
|
22413
|
+
if (configPath === void 0) return {};
|
|
22414
|
+
const extension = path33__default.default.extname(configPath);
|
|
22415
|
+
if (TS_CONFIG_EXTENSIONS3.has(extension)) {
|
|
22416
|
+
throw new Error(
|
|
22417
|
+
"TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
|
|
22418
|
+
);
|
|
22419
|
+
}
|
|
22420
|
+
if (!CONFIG_EXTENSIONS3.has(extension)) {
|
|
22421
|
+
throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
|
|
22422
|
+
}
|
|
22423
|
+
const absolute = path33__default.default.resolve(configPath);
|
|
22424
|
+
if (extension === ".json") {
|
|
22425
|
+
const raw = await promises.readFile(absolute, "utf-8");
|
|
22426
|
+
return asConfig(JSON.parse(raw));
|
|
22427
|
+
}
|
|
22428
|
+
const mod = await import(url.pathToFileURL(absolute).href);
|
|
22429
|
+
return asConfig("default" in mod ? mod.default : mod);
|
|
21560
22430
|
}
|
|
21561
|
-
function
|
|
21562
|
-
|
|
21563
|
-
|
|
21564
|
-
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
return {
|
|
21568
|
-
ok: status === "SAFE" || status === "SAFE WITH WARNINGS",
|
|
21569
|
-
command: parts.command,
|
|
21570
|
-
status,
|
|
21571
|
-
format: parts.format,
|
|
21572
|
-
...parts.runId !== void 0 ? { runId: parts.runId } : {},
|
|
21573
|
-
summary: {
|
|
21574
|
-
findings: findings.length,
|
|
21575
|
-
warnings: diagnostics.filter((item) => item.severity === "warning").length + findings.filter((item) => item.severity === "warning").length,
|
|
21576
|
-
errors: diagnostics.filter((item) => item.severity === "error").length + findings.filter((item) => item.severity === "error").length
|
|
21577
|
-
},
|
|
21578
|
-
findings,
|
|
21579
|
-
diagnostics,
|
|
21580
|
-
warnings,
|
|
21581
|
-
unsupportedFields,
|
|
21582
|
-
note: BEST_EFFORT_NOTE,
|
|
21583
|
-
...parts.sourceAssessment !== void 0 ? { sourceAssessment: parts.sourceAssessment } : {},
|
|
21584
|
-
...parts.artifactAssessment !== void 0 ? { artifactAssessment: parts.artifactAssessment } : {},
|
|
21585
|
-
...parts.redactionSummary !== void 0 ? { redactionSummary: parts.redactionSummary } : {}
|
|
21586
|
-
};
|
|
22431
|
+
function normalizeConfig2(config) {
|
|
22432
|
+
if (config.eval === void 0) return {};
|
|
22433
|
+
if (typeof config.eval !== "object" || Array.isArray(config.eval)) {
|
|
22434
|
+
throw new Error("eval config must be an object.");
|
|
22435
|
+
}
|
|
22436
|
+
return config.eval;
|
|
21587
22437
|
}
|
|
21588
|
-
function
|
|
21589
|
-
|
|
21590
|
-
status: result.status,
|
|
21591
|
-
summary: result.summary,
|
|
21592
|
-
findings: result.findings
|
|
21593
|
-
};
|
|
22438
|
+
function maybeAdd(rules, value, makeRule) {
|
|
22439
|
+
if (value !== void 0) rules.push(makeRule(value));
|
|
21594
22440
|
}
|
|
21595
|
-
function
|
|
21596
|
-
if (
|
|
21597
|
-
|
|
21598
|
-
|
|
21599
|
-
|
|
21600
|
-
format: "unknown",
|
|
21601
|
-
diagnostics: [safetyDiagnostic(code, error.message)],
|
|
21602
|
-
warnings: error.warnings
|
|
21603
|
-
});
|
|
22441
|
+
function optionObject(value) {
|
|
22442
|
+
if (value === void 0 || value === false) return void 0;
|
|
22443
|
+
if (value === true) return {};
|
|
22444
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
22445
|
+
throw new Error("Eval heuristic config must be a boolean or object.");
|
|
21604
22446
|
}
|
|
21605
|
-
return
|
|
21606
|
-
command,
|
|
21607
|
-
format: "unknown",
|
|
21608
|
-
diagnostics: [
|
|
21609
|
-
safetyDiagnostic(
|
|
21610
|
-
"AI_SAFETY_TRACE_UNREADABLE",
|
|
21611
|
-
error instanceof Error ? error.message : String(error)
|
|
21612
|
-
)
|
|
21613
|
-
]
|
|
21614
|
-
});
|
|
22447
|
+
return value;
|
|
21615
22448
|
}
|
|
21616
|
-
function
|
|
21617
|
-
return
|
|
21618
|
-
|
|
21619
|
-
|
|
21620
|
-
|
|
21621
|
-
|
|
21622
|
-
|
|
21623
|
-
|
|
21624
|
-
)
|
|
21625
|
-
]
|
|
21626
|
-
});
|
|
22449
|
+
function sourceIdsFromConfig(value) {
|
|
22450
|
+
if (value === void 0) return void 0;
|
|
22451
|
+
if (Array.isArray(value)) return { ids: asStringArray3(value, "eval.requiredSourceIds") ?? [] };
|
|
22452
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
22453
|
+
throw new Error("eval.requiredSourceIds must be an array or object.");
|
|
22454
|
+
}
|
|
22455
|
+
const ids = asStringArray3(value.ids, "eval.requiredSourceIds.ids") ?? [];
|
|
22456
|
+
return { ids, options: { sourceIdKeys: value.sourceIdKeys } };
|
|
21627
22457
|
}
|
|
21628
|
-
function
|
|
21629
|
-
const
|
|
21630
|
-
const
|
|
21631
|
-
|
|
21632
|
-
const
|
|
21633
|
-
|
|
21634
|
-
|
|
21635
|
-
createSafetyRedactionRule(),
|
|
21636
|
-
createSafetySecretPatternRule(),
|
|
21637
|
-
createSafetyOversizedAttributeRule({
|
|
21638
|
-
maxStringLength: maxStringLength2,
|
|
21639
|
-
maxArrayLength,
|
|
21640
|
-
maxObjectKeys,
|
|
21641
|
-
maxSerializedBytes
|
|
21642
|
-
})
|
|
22458
|
+
function buildRules2(config, options) {
|
|
22459
|
+
const evalConfig = normalizeConfig2(config);
|
|
22460
|
+
const rules = [];
|
|
22461
|
+
if (evalConfig.requireSuccess || options.requireSuccess) rules.push(checks.requireSuccess());
|
|
22462
|
+
const requiredTools = [
|
|
22463
|
+
...asStringArray3(evalConfig.requiredTools, "eval.requiredTools") ?? [],
|
|
22464
|
+
...options.requiredTool ?? []
|
|
21643
22465
|
];
|
|
21644
|
-
|
|
21645
|
-
|
|
21646
|
-
|
|
21647
|
-
|
|
21648
|
-
...
|
|
21649
|
-
|
|
21650
|
-
|
|
21651
|
-
|
|
21652
|
-
|
|
21653
|
-
|
|
21654
|
-
|
|
21655
|
-
|
|
21656
|
-
|
|
21657
|
-
|
|
21658
|
-
|
|
22466
|
+
if (requiredTools.length > 0) rules.push(checks.requiredTools(requiredTools));
|
|
22467
|
+
const forbiddenTools = [
|
|
22468
|
+
...asStringArray3(evalConfig.forbiddenTools, "eval.forbiddenTools") ?? [],
|
|
22469
|
+
...options.forbidTool ?? [],
|
|
22470
|
+
...options.forbiddenTool ?? []
|
|
22471
|
+
];
|
|
22472
|
+
if (forbiddenTools.length > 0) rules.push(checks.forbiddenTools(forbiddenTools));
|
|
22473
|
+
const maxDurationMs = parseNumber2(options.maxDurationMs, "--max-duration-ms") ?? evalConfig.maxDurationMs;
|
|
22474
|
+
maybeAdd(rules, maxDurationMs, checks.maxDurationMs);
|
|
22475
|
+
const maxDepth = parseNumber2(options.maxDepth, "--max-depth") ?? evalConfig.maxDepth;
|
|
22476
|
+
maybeAdd(rules, maxDepth, checks.maxDepth);
|
|
22477
|
+
const maxRetries = parseNumber2(options.maxRetries, "--max-retries") ?? evalConfig.maxRetries;
|
|
22478
|
+
maybeAdd(rules, maxRetries, checks.maxRetries);
|
|
22479
|
+
const maxTotalTokens = parseNumber2(options.maxTotalTokens, "--max-total-tokens") ?? evalConfig.maxTotalTokens;
|
|
22480
|
+
maybeAdd(rules, maxTotalTokens, checks.maxTotalTokens);
|
|
22481
|
+
if (evalConfig.requiredRetrievalBeforeGeneration || options.requireRetrievalBeforeGeneration) {
|
|
22482
|
+
rules.push(checks.requiredRetrievalBeforeGeneration());
|
|
21659
22483
|
}
|
|
21660
|
-
|
|
21661
|
-
|
|
22484
|
+
const requiredDecisionMetadata = [
|
|
22485
|
+
...asStringArray3(
|
|
22486
|
+
evalConfig.requiredDecisionMetadata,
|
|
22487
|
+
"eval.requiredDecisionMetadata"
|
|
22488
|
+
) ?? [],
|
|
22489
|
+
...options.requiredDecisionMetadata ?? []
|
|
22490
|
+
];
|
|
22491
|
+
if (requiredDecisionMetadata.length > 0) {
|
|
22492
|
+
rules.push(checks.requiredDecisionMetadata(requiredDecisionMetadata));
|
|
21662
22493
|
}
|
|
21663
|
-
|
|
21664
|
-
|
|
22494
|
+
const contextOverlap = optionObject(evalConfig.contextOverlap);
|
|
22495
|
+
const minOverlap = parseNumber2(options.minContextOverlap, "--min-context-overlap");
|
|
22496
|
+
const minSharedTerms = parseNumber2(options.minSharedTerms, "--min-shared-terms");
|
|
22497
|
+
if (contextOverlap !== void 0 || options.contextOverlap || minOverlap !== void 0 || minSharedTerms !== void 0) {
|
|
22498
|
+
rules.push(checks.contextOverlap({ ...contextOverlap, minOverlap, minSharedTerms }));
|
|
21665
22499
|
}
|
|
21666
|
-
|
|
21667
|
-
|
|
22500
|
+
const quoteOverlap = optionObject(evalConfig.quoteOverlap);
|
|
22501
|
+
if (quoteOverlap !== void 0 || options.quoteOverlap) {
|
|
22502
|
+
rules.push(checks.quoteOverlap(quoteOverlap));
|
|
21668
22503
|
}
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
|
|
21672
|
-
const runs = runId === void 0 ? read.runs : read.runs.filter((run) => run.runId === runId);
|
|
21673
|
-
const out = [];
|
|
21674
|
-
for (const run of runs) {
|
|
21675
|
-
for (const node of flattenNodes2(run.children)) {
|
|
21676
|
-
const attrs = node.event.attributes;
|
|
21677
|
-
if (attrs === void 0) continue;
|
|
21678
|
-
const result = redact(attrs, { profile: "share" });
|
|
21679
|
-
for (const finding of result.findings) {
|
|
21680
|
-
if (finding.action === "keep") continue;
|
|
21681
|
-
const taxonomy = classifyRedactionDetector(finding.detector);
|
|
21682
|
-
out.push({
|
|
21683
|
-
ruleId: "safety.redactDetector",
|
|
21684
|
-
severity: detectorSeverity(finding),
|
|
21685
|
-
status: finding.severity === "error" ? "fail" : "warning",
|
|
21686
|
-
message: `Redaction detector ${finding.detector} matched ${finding.matchKind} at ${finding.path}.`,
|
|
21687
|
-
expected: "redacted trace content",
|
|
21688
|
-
actual: finding.detector,
|
|
21689
|
-
evidence: [
|
|
21690
|
-
{
|
|
21691
|
-
runId: node.event.runId,
|
|
21692
|
-
eventId: node.event.eventId,
|
|
21693
|
-
...node.event.parentId !== void 0 ? { parentId: node.event.parentId } : {},
|
|
21694
|
-
kind: node.event.kind,
|
|
21695
|
-
name: node.event.name,
|
|
21696
|
-
...node.event.status !== void 0 ? { status: node.event.status } : {},
|
|
21697
|
-
path: `attributes.${finding.path.replace(/^\$\.?/, "")}`
|
|
21698
|
-
}
|
|
21699
|
-
],
|
|
21700
|
-
category: taxonomy.category,
|
|
21701
|
-
confidence: taxonomy.confidence,
|
|
21702
|
-
detector: finding.detector,
|
|
21703
|
-
action: finding.action
|
|
21704
|
-
});
|
|
21705
|
-
}
|
|
21706
|
-
}
|
|
22504
|
+
const citationPresence = optionObject(evalConfig.citationPresence);
|
|
22505
|
+
if (citationPresence !== void 0 || options.citationPresence) {
|
|
22506
|
+
rules.push(checks.citationPresence(citationPresence));
|
|
21707
22507
|
}
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
|
|
21712
|
-
}
|
|
22508
|
+
const sourceIds = sourceIdsFromConfig(evalConfig.requiredSourceIds);
|
|
22509
|
+
const requiredSourceIds = [...sourceIds?.ids ?? [], ...options.requiredSourceId ?? []];
|
|
22510
|
+
if (requiredSourceIds.length > 0) {
|
|
22511
|
+
rules.push(checks.requiredSourceIds(requiredSourceIds, sourceIds?.options));
|
|
22512
|
+
}
|
|
22513
|
+
const cliAnswerLength = {
|
|
22514
|
+
minCharacters: parseNumber2(options.minAnswerCharacters, "--min-answer-characters"),
|
|
22515
|
+
maxCharacters: parseNumber2(options.maxAnswerCharacters, "--max-answer-characters"),
|
|
22516
|
+
minWords: parseNumber2(options.minAnswerWords, "--min-answer-words"),
|
|
22517
|
+
maxWords: parseNumber2(options.maxAnswerWords, "--max-answer-words")
|
|
22518
|
+
};
|
|
22519
|
+
const hasCliAnswerLength = Object.values(cliAnswerLength).some((value) => value !== void 0);
|
|
22520
|
+
if (evalConfig.answerLengthBounds !== void 0 || hasCliAnswerLength) {
|
|
22521
|
+
rules.push(checks.answerLengthBounds({ ...evalConfig.answerLengthBounds, ...cliAnswerLength }));
|
|
22522
|
+
}
|
|
22523
|
+
const bannedPhrases = [
|
|
22524
|
+
...asStringArray3(
|
|
22525
|
+
evalConfig.bannedUnsupportedPhrases,
|
|
22526
|
+
"eval.bannedUnsupportedPhrases"
|
|
22527
|
+
) ?? [],
|
|
22528
|
+
...options.bannedPhrase ?? []
|
|
22529
|
+
];
|
|
22530
|
+
if (bannedPhrases.length > 0) rules.push(checks.bannedUnsupportedPhrases(bannedPhrases));
|
|
22531
|
+
return rules.length > 0 ? rules : void 0;
|
|
21713
22532
|
}
|
|
21714
22533
|
function exitCodeFor3(result) {
|
|
21715
|
-
if (result.status === "
|
|
21716
|
-
if (result.status === "
|
|
22534
|
+
if (result.status === "pass") return 0;
|
|
22535
|
+
if (result.status === "fail") return 1;
|
|
21717
22536
|
return 2;
|
|
21718
22537
|
}
|
|
21719
|
-
function
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
const
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
return [
|
|
21727
|
-
` Matched: detector=${detector}; path=${path43}; category=${category}`,
|
|
21728
|
-
` Why: ${finding.message}`,
|
|
21729
|
-
` Confidence: ${confidence}`,
|
|
21730
|
-
` Redaction: ${redactionHint}`,
|
|
21731
|
-
` Override: configure a custom redaction/detector rule locally (see docs/SAFETY-POLICY.md); do not weaken defaults globally.`,
|
|
21732
|
-
` Bundle gate: ${blocksBundle ? "blocks share-safe bundle unless --allow-unsafe" : "does not block by itself (warning/info)"}`
|
|
21733
|
-
];
|
|
22538
|
+
function stable5(value) {
|
|
22539
|
+
if (Array.isArray(value)) return value.map(stable5);
|
|
22540
|
+
if (value === null || typeof value !== "object") return value;
|
|
22541
|
+
const record = value;
|
|
22542
|
+
return Object.fromEntries(
|
|
22543
|
+
Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable5(record[key])])
|
|
22544
|
+
);
|
|
21734
22545
|
}
|
|
21735
|
-
function
|
|
21736
|
-
|
|
21737
|
-
return {
|
|
21738
|
-
ruleId: finding.ruleId,
|
|
21739
|
-
detector: finding.detector ?? finding.ruleId,
|
|
21740
|
-
path: finding.evidence[0]?.path,
|
|
21741
|
-
category: finding.category,
|
|
21742
|
-
confidence: finding.confidence,
|
|
21743
|
-
action: finding.action,
|
|
21744
|
-
blocksBundle: blocks,
|
|
21745
|
-
// Never include matched secret/PII values.
|
|
21746
|
-
message: finding.message
|
|
21747
|
-
};
|
|
22546
|
+
function printJson3(result) {
|
|
22547
|
+
console.log(JSON.stringify(stable5(result), null, 2));
|
|
21748
22548
|
}
|
|
21749
|
-
function printHuman3(result
|
|
21750
|
-
console.log(`
|
|
22549
|
+
function printHuman3(result) {
|
|
22550
|
+
console.log(`Eval status: ${result.status}`);
|
|
21751
22551
|
console.log(`Format: ${result.format}`);
|
|
21752
22552
|
if (result.runId !== void 0) console.log(`Run: ${result.runId}`);
|
|
21753
|
-
if (result.sourceAssessment !== void 0 && result.artifactAssessment !== void 0) {
|
|
21754
|
-
console.log(`Source assessment: ${result.sourceAssessment.status}`);
|
|
21755
|
-
console.log(`Artifact assessment: ${result.artifactAssessment.status}`);
|
|
21756
|
-
if (result.redactionSummary !== void 0) {
|
|
21757
|
-
console.log(
|
|
21758
|
-
`Redaction: profile=${result.redactionSummary.profile}, findings=${result.redactionSummary.findings}`
|
|
21759
|
-
);
|
|
21760
|
-
}
|
|
21761
|
-
}
|
|
21762
22553
|
console.log(
|
|
21763
|
-
`Summary: ${result.summary.
|
|
22554
|
+
`Summary: ${result.summary.failed} failed, ${result.summary.warnings} warning(s), ${result.summary.errors} error(s)`
|
|
21764
22555
|
);
|
|
21765
22556
|
for (const diagnostic7 of result.diagnostics) {
|
|
21766
22557
|
console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
21767
22558
|
}
|
|
21768
22559
|
for (const finding of result.findings) {
|
|
21769
|
-
const
|
|
21770
|
-
|
|
21771
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}${taxonomy}`);
|
|
21772
|
-
if (explain) {
|
|
21773
|
-
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
21774
|
-
for (const line of explainFinding(finding, blocks)) {
|
|
21775
|
-
console.log(line);
|
|
21776
|
-
}
|
|
21777
|
-
}
|
|
22560
|
+
const path44 = finding.evidence[0]?.path;
|
|
22561
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path44 ? ` (${path44})` : ""}`);
|
|
21778
22562
|
}
|
|
21779
|
-
console.log(`Note: ${result.note}`);
|
|
21780
22563
|
}
|
|
21781
|
-
function
|
|
21782
|
-
|
|
21783
|
-
|
|
22564
|
+
function readErrorResult3(error) {
|
|
22565
|
+
if (error instanceof TraceReadError) {
|
|
22566
|
+
const code = error.code === "unsupported_format" ? "AI_EVAL_UNSUPPORTED_FORMAT" : error.code === "ambiguous_format" ? "AI_EVAL_AMBIGUOUS_FORMAT" : "AI_EVAL_TRACE_UNREADABLE";
|
|
22567
|
+
return errorResult4(code, error.message);
|
|
22568
|
+
}
|
|
22569
|
+
return errorResult4(
|
|
22570
|
+
"AI_EVAL_TRACE_UNREADABLE",
|
|
22571
|
+
error instanceof Error ? error.message : String(error)
|
|
22572
|
+
);
|
|
21784
22573
|
}
|
|
21785
|
-
async function
|
|
22574
|
+
async function evalCommand(target, options = {}, stdin = process.stdin) {
|
|
21786
22575
|
let result;
|
|
22576
|
+
let phase = "config";
|
|
21787
22577
|
try {
|
|
22578
|
+
const config = await loadConfig2(options.config);
|
|
22579
|
+
const rules = buildRules2(config, options);
|
|
22580
|
+
phase = "read";
|
|
21788
22581
|
const input3 = await inputFromTarget(target, options, stdin);
|
|
21789
22582
|
const read = await openTrace(input3, {
|
|
21790
22583
|
...options.format !== void 0 ? { format: options.format } : {}
|
|
21791
22584
|
});
|
|
21792
|
-
|
|
21793
|
-
...
|
|
22585
|
+
result = await evalRun(read, {
|
|
22586
|
+
...rules !== void 0 ? { checks: rules } : {},
|
|
21794
22587
|
...options.run !== void 0 ? { runId: options.run } : {}
|
|
21795
22588
|
});
|
|
21796
|
-
|
|
21797
|
-
|
|
22589
|
+
} catch (error) {
|
|
22590
|
+
if (phase === "config") {
|
|
22591
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
22592
|
+
const code = message.startsWith("--") ? "AI_EVAL_INVALID_ARGUMENTS" : error instanceof SyntaxError || message.includes("Unsupported eval config extension") || message.includes("TypeScript eval configs") || message.includes("Config must") || message.includes("eval config") || message.includes("must be an array") ? "AI_EVAL_INVALID_CONFIG" : "AI_EVAL_CONFIG_LOAD_FAILED";
|
|
22593
|
+
result = errorResult4(code, message);
|
|
21798
22594
|
} else {
|
|
21799
|
-
|
|
21800
|
-
const rawContent = input3.type === "string" ? input3.content : input3.type === "file" ? await promises.readFile(input3.path, "utf-8") : void 0;
|
|
21801
|
-
if (rawContent === void 0) {
|
|
21802
|
-
result = {
|
|
21803
|
-
...source,
|
|
21804
|
-
command: "verify-safe",
|
|
21805
|
-
sourceAssessment: layerFromResult(source)
|
|
21806
|
-
};
|
|
21807
|
-
} else {
|
|
21808
|
-
const redacted = redactTraceContent(rawContent, profile);
|
|
21809
|
-
const artifactRead = await openTrace(
|
|
21810
|
-
{ type: "string", content: redacted.content },
|
|
21811
|
-
{ format: options.format ?? "agent-inspect-jsonl" }
|
|
21812
|
-
);
|
|
21813
|
-
const artifact = assessOpenedTrace(artifactRead, {
|
|
21814
|
-
...options,
|
|
21815
|
-
...options.run !== void 0 ? { runId: options.run } : {}
|
|
21816
|
-
});
|
|
21817
|
-
const detectors = [
|
|
21818
|
-
...new Set(redacted.findings.map((finding) => finding.detector))
|
|
21819
|
-
].sort((a, b) => a.localeCompare(b));
|
|
21820
|
-
result = resultFromParts({
|
|
21821
|
-
command: "verify-safe",
|
|
21822
|
-
format: artifact.format,
|
|
21823
|
-
runId: artifact.runId ?? source.runId,
|
|
21824
|
-
findings: artifact.findings,
|
|
21825
|
-
diagnostics: artifact.diagnostics,
|
|
21826
|
-
warnings: artifact.warnings,
|
|
21827
|
-
unsupportedFields: artifact.unsupportedFields,
|
|
21828
|
-
status: artifact.status,
|
|
21829
|
-
sourceAssessment: layerFromResult(source),
|
|
21830
|
-
artifactAssessment: layerFromResult(artifact),
|
|
21831
|
-
redactionSummary: {
|
|
21832
|
-
profile,
|
|
21833
|
-
findings: redacted.findings.length,
|
|
21834
|
-
detectors
|
|
21835
|
-
}
|
|
21836
|
-
});
|
|
21837
|
-
}
|
|
22595
|
+
result = readErrorResult3(error);
|
|
21838
22596
|
}
|
|
21839
|
-
} catch (error) {
|
|
21840
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
21841
|
-
result = message.startsWith("--") ? invalidArgumentResult(command, error) : readErrorResult3(command, error);
|
|
21842
22597
|
}
|
|
21843
22598
|
process.exitCode = exitCodeFor3(result);
|
|
21844
|
-
if (options.json) printJson3(result
|
|
21845
|
-
else
|
|
21846
|
-
|
|
21847
|
-
function scanCommand(target, options = {}, stdin = process.stdin) {
|
|
21848
|
-
return safetyCommand("scan", target, options, stdin);
|
|
21849
|
-
}
|
|
21850
|
-
function verifySafeCommand(target, options = {}, stdin = process.stdin) {
|
|
21851
|
-
return safetyCommand("verify-safe", target, options, stdin);
|
|
21852
|
-
}
|
|
21853
|
-
function assessOpenedTrace(read, options = {}) {
|
|
21854
|
-
try {
|
|
21855
|
-
const rules = buildSafetyRules(options);
|
|
21856
|
-
const checkResult = runTraceChecks(
|
|
21857
|
-
{ read },
|
|
21858
|
-
{
|
|
21859
|
-
rules,
|
|
21860
|
-
...options.runId !== void 0 ? { runId: options.runId } : {},
|
|
21861
|
-
...options.run !== void 0 ? { runId: options.run } : {}
|
|
21862
|
-
}
|
|
21863
|
-
);
|
|
21864
|
-
const detectorFindings = checkResult.diagnostics.length === 0 ? redactionDetectorFindings(read, checkResult.runId) : [];
|
|
21865
|
-
return resultFromParts({
|
|
21866
|
-
command: "verify-safe",
|
|
21867
|
-
format: checkResult.format,
|
|
21868
|
-
runId: checkResult.runId,
|
|
21869
|
-
findings: [...checkResult.findings, ...detectorFindings],
|
|
21870
|
-
diagnostics: [
|
|
21871
|
-
...checkResult.diagnostics.map(diagnosticFromCheck),
|
|
21872
|
-
...warningDiagnostics(read.warnings, read.unsupportedFields)
|
|
21873
|
-
],
|
|
21874
|
-
warnings: read.warnings,
|
|
21875
|
-
unsupportedFields: read.unsupportedFields
|
|
21876
|
-
});
|
|
21877
|
-
} catch (error) {
|
|
21878
|
-
return messageStartsWithDash(error) ? invalidArgumentResult("verify-safe", error) : readErrorResult3("verify-safe", error);
|
|
21879
|
-
}
|
|
21880
|
-
}
|
|
21881
|
-
function messageStartsWithDash(error) {
|
|
21882
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
21883
|
-
return message.startsWith("--");
|
|
22599
|
+
if (options.json) printJson3(result);
|
|
22600
|
+
else if (options.markdown) console.log(renderEvalMarkdown(result).trimEnd());
|
|
22601
|
+
else printHuman3(result);
|
|
21884
22602
|
}
|
|
21885
22603
|
init_advanced();
|
|
21886
22604
|
var NOTE = "Generated locally by AgentInspect. Artifacts are best-effort summaries, not compliance or security certification.";
|
|
@@ -21956,8 +22674,8 @@ function renderCheckSection(result) {
|
|
|
21956
22674
|
`Diagnostics: ${result.diagnostics.length}`
|
|
21957
22675
|
];
|
|
21958
22676
|
for (const finding of result.findings.slice(0, 10)) {
|
|
21959
|
-
const
|
|
21960
|
-
lines.push(`- ${finding.ruleId}: ${finding.message} (${
|
|
22677
|
+
const path44 = finding.evidence[0]?.path ?? "(run)";
|
|
22678
|
+
lines.push(`- ${finding.ruleId}: ${finding.message} (${path44})`);
|
|
21961
22679
|
}
|
|
21962
22680
|
for (const diagnostic7 of result.diagnostics.slice(0, 10)) {
|
|
21963
22681
|
lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
|
|
@@ -22035,8 +22753,8 @@ function renderHtml(trace, check, diff) {
|
|
|
22035
22753
|
`;
|
|
22036
22754
|
}
|
|
22037
22755
|
async function writeArtifact(outputDir, relativePath, content, files) {
|
|
22038
|
-
const outPath =
|
|
22039
|
-
await promises.mkdir(
|
|
22756
|
+
const outPath = path33__default.default.join(outputDir, relativePath);
|
|
22757
|
+
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
22040
22758
|
await promises.writeFile(outPath, content, "utf-8");
|
|
22041
22759
|
files.push(relativePath);
|
|
22042
22760
|
}
|
|
@@ -22065,7 +22783,7 @@ function shouldWriteEvidence(options, status) {
|
|
|
22065
22783
|
return status === "unsafe" || status === "regression" || status === "unknown" || status === "warning";
|
|
22066
22784
|
}
|
|
22067
22785
|
async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
22068
|
-
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ?
|
|
22786
|
+
const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path33__default.default.resolve(options.outputDir.trim()) : "";
|
|
22069
22787
|
if (outputDir === "") {
|
|
22070
22788
|
console.error("--output-dir is required.");
|
|
22071
22789
|
process.exitCode = 1;
|
|
@@ -22179,7 +22897,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
|
22179
22897
|
finishedToolNames: [...parity.finishedToolNames],
|
|
22180
22898
|
pairedCount: parity.pairedCount,
|
|
22181
22899
|
parentRemapCount: parity.parentRemapCount,
|
|
22182
|
-
contractStatus: check.status === "pass" ? "pass" : check.status === "fail" ? "fail" : "error"
|
|
22900
|
+
contractStatus: check.status === "pass" ? "pass" : check.status === "fail" ? "fail" : "error",
|
|
22901
|
+
...parity.failureRoleCounts !== void 0 ? { failureRoleCounts: { ...parity.failureRoleCounts } } : {}
|
|
22183
22902
|
}
|
|
22184
22903
|
});
|
|
22185
22904
|
await writeArtifact(outputDir, "evidence.html", evidencePackage["evidence.html"], files);
|
|
@@ -22205,8 +22924,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
|
|
|
22205
22924
|
}
|
|
22206
22925
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
22207
22926
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
22208
|
-
await promises.mkdir(
|
|
22209
|
-
await promises.appendFile(
|
|
22927
|
+
await promises.mkdir(path33__default.default.dirname(path33__default.default.resolve(summaryTarget)), { recursive: true });
|
|
22928
|
+
await promises.appendFile(path33__default.default.resolve(summaryTarget), `
|
|
22210
22929
|
${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
22211
22930
|
}
|
|
22212
22931
|
const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
|
|
@@ -22225,10 +22944,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
|
|
|
22225
22944
|
findings: diff?.findings.length ?? 0,
|
|
22226
22945
|
diagnostics: diff?.diagnostics.length ?? 0
|
|
22227
22946
|
},
|
|
22228
|
-
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary:
|
|
22947
|
+
...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path33__default.default.resolve(summaryTarget) } : {},
|
|
22229
22948
|
note: NOTE
|
|
22230
22949
|
};
|
|
22231
|
-
await promises.writeFile(
|
|
22950
|
+
await promises.writeFile(path33__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
|
|
22232
22951
|
if (options.json === true) {
|
|
22233
22952
|
console.log(writeJson3(manifest).trimEnd());
|
|
22234
22953
|
} else {
|
|
@@ -22289,8 +23008,8 @@ async function resolveOutputDir(options, runIds, cwd, format) {
|
|
|
22289
23008
|
const location = resolveWorkspaceLocation(cwd);
|
|
22290
23009
|
const manifest = await readWorkspaceManifestFile(location);
|
|
22291
23010
|
if (manifest.ok && manifest.manifest) {
|
|
22292
|
-
const rel =
|
|
22293
|
-
if (!rel.startsWith("..") && !
|
|
23011
|
+
const rel = path33__default.default.relative(location.workspaceDir, normalized);
|
|
23012
|
+
if (!rel.startsWith("..") && !path33__default.default.isAbsolute(rel)) {
|
|
22294
23013
|
return resolveInsideWorkspace(location.workspaceDir, rel);
|
|
22295
23014
|
}
|
|
22296
23015
|
}
|
|
@@ -22306,7 +23025,7 @@ async function resolveOutputDir(options, runIds, cwd, format) {
|
|
|
22306
23025
|
const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
|
|
22307
23026
|
const base2 = resolveInsideWorkspace(
|
|
22308
23027
|
location.workspaceDir,
|
|
22309
|
-
|
|
23028
|
+
path33__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
|
|
22310
23029
|
);
|
|
22311
23030
|
return format === "zip" ? `${base2}.zip` : base2;
|
|
22312
23031
|
}
|
|
@@ -22711,19 +23430,19 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
22711
23430
|
let sidecarDir = outputDir;
|
|
22712
23431
|
if (outputDir.toLowerCase().endsWith(".html")) {
|
|
22713
23432
|
htmlPath = outputDir;
|
|
22714
|
-
sidecarDir =
|
|
23433
|
+
sidecarDir = path33__default.default.dirname(outputDir);
|
|
22715
23434
|
} else {
|
|
22716
23435
|
await promises.mkdir(outputDir, { recursive: true });
|
|
22717
|
-
htmlPath =
|
|
23436
|
+
htmlPath = path33__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
|
|
22718
23437
|
sidecarDir = outputDir;
|
|
22719
23438
|
}
|
|
22720
23439
|
await promises.mkdir(sidecarDir, { recursive: true });
|
|
22721
23440
|
await promises.writeFile(htmlPath, htmlContent, "utf-8");
|
|
22722
|
-
await promises.writeFile(
|
|
23441
|
+
await promises.writeFile(path33__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
|
|
22723
23442
|
outputPath = htmlPath;
|
|
22724
23443
|
} else if (format === "zip") {
|
|
22725
23444
|
const zipPath = outputDir.toLowerCase().endsWith(".zip") ? outputDir : `${outputDir}.zip`;
|
|
22726
|
-
const zipParent =
|
|
23445
|
+
const zipParent = path33__default.default.dirname(zipPath);
|
|
22727
23446
|
await promises.mkdir(zipParent, { recursive: true });
|
|
22728
23447
|
const entries = [
|
|
22729
23448
|
...[...packaged.entries()].map(([relativePath, content]) => ({
|
|
@@ -22739,10 +23458,10 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
22739
23458
|
await promises.mkdir(outputDir, { recursive: true });
|
|
22740
23459
|
for (const [relativePath, content] of packaged.entries()) {
|
|
22741
23460
|
const outPath = assertBundlePathContained(outputDir, relativePath);
|
|
22742
|
-
await promises.mkdir(
|
|
23461
|
+
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
22743
23462
|
await promises.writeFile(outPath, content, "utf-8");
|
|
22744
23463
|
}
|
|
22745
|
-
await promises.writeFile(
|
|
23464
|
+
await promises.writeFile(path33__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
|
|
22746
23465
|
if (!files.includes(EVIDENCE_MANIFEST_FILENAME)) {
|
|
22747
23466
|
files.push(EVIDENCE_MANIFEST_FILENAME);
|
|
22748
23467
|
}
|
|
@@ -22791,7 +23510,7 @@ function writeJson5(value) {
|
|
|
22791
23510
|
`;
|
|
22792
23511
|
}
|
|
22793
23512
|
async function bundleVerifyCommand(targetPath, options = {}) {
|
|
22794
|
-
const root =
|
|
23513
|
+
const root = path33__default.default.resolve(targetPath.trim() || ".");
|
|
22795
23514
|
const result = await verifyEvidenceDirectory(root, {
|
|
22796
23515
|
unexpectedFiles: options.unexpected ?? "fail"
|
|
22797
23516
|
});
|
|
@@ -22833,7 +23552,7 @@ function writeJson6(value) {
|
|
|
22833
23552
|
}
|
|
22834
23553
|
async function resolveHtmlPath(root) {
|
|
22835
23554
|
const candidates = [
|
|
22836
|
-
|
|
23555
|
+
path33__default.default.join(root, "evidence.html"),
|
|
22837
23556
|
root.toLowerCase().endsWith(".html") ? root : ""
|
|
22838
23557
|
].filter(Boolean);
|
|
22839
23558
|
for (const candidate of candidates) {
|
|
@@ -22848,7 +23567,7 @@ async function resolveHtmlPath(root) {
|
|
|
22848
23567
|
);
|
|
22849
23568
|
}
|
|
22850
23569
|
async function bundleOpenCommand(targetPath, options = {}) {
|
|
22851
|
-
const root =
|
|
23570
|
+
const root = path33__default.default.resolve(targetPath.trim() || ".");
|
|
22852
23571
|
try {
|
|
22853
23572
|
await promises.access(root);
|
|
22854
23573
|
} catch {
|
|
@@ -22865,7 +23584,7 @@ async function bundleOpenCommand(targetPath, options = {}) {
|
|
|
22865
23584
|
try {
|
|
22866
23585
|
const info = await promises.stat(root);
|
|
22867
23586
|
if (info.isFile() && root.toLowerCase().endsWith(".html")) {
|
|
22868
|
-
verifyRoot =
|
|
23587
|
+
verifyRoot = path33__default.default.dirname(root);
|
|
22869
23588
|
}
|
|
22870
23589
|
} catch {
|
|
22871
23590
|
}
|
|
@@ -22897,7 +23616,7 @@ async function bundleOpenCommand(targetPath, options = {}) {
|
|
|
22897
23616
|
let htmlPath;
|
|
22898
23617
|
try {
|
|
22899
23618
|
htmlPath = await resolveHtmlPath(
|
|
22900
|
-
root.toLowerCase().endsWith(".html") ?
|
|
23619
|
+
root.toLowerCase().endsWith(".html") ? path33__default.default.dirname(root) : root
|
|
22901
23620
|
);
|
|
22902
23621
|
if (root.toLowerCase().endsWith(".html")) {
|
|
22903
23622
|
htmlPath = root;
|
|
@@ -22913,7 +23632,7 @@ async function bundleOpenCommand(targetPath, options = {}) {
|
|
|
22913
23632
|
return;
|
|
22914
23633
|
}
|
|
22915
23634
|
try {
|
|
22916
|
-
await promises.readFile(
|
|
23635
|
+
await promises.readFile(path33__default.default.join(path33__default.default.dirname(htmlPath), "evidence.json"), "utf-8");
|
|
22917
23636
|
} catch {
|
|
22918
23637
|
}
|
|
22919
23638
|
const fileUrl = url.pathToFileURL(htmlPath).href;
|
|
@@ -22999,24 +23718,24 @@ function resolveTargetPath(client, projectLocal) {
|
|
|
22999
23718
|
if (projectLocal) {
|
|
23000
23719
|
switch (client) {
|
|
23001
23720
|
case "cursor":
|
|
23002
|
-
return
|
|
23721
|
+
return path33__default.default.join(".cursor", "mcp.json");
|
|
23003
23722
|
case "claude-code":
|
|
23004
|
-
return
|
|
23723
|
+
return path33__default.default.join(".mcp.json");
|
|
23005
23724
|
case "codex":
|
|
23006
|
-
return
|
|
23725
|
+
return path33__default.default.join(".codex", "config.toml.json");
|
|
23007
23726
|
case "gemini":
|
|
23008
|
-
return
|
|
23727
|
+
return path33__default.default.join(".gemini", "settings.json");
|
|
23009
23728
|
}
|
|
23010
23729
|
}
|
|
23011
23730
|
switch (client) {
|
|
23012
23731
|
case "cursor":
|
|
23013
|
-
return
|
|
23732
|
+
return path33__default.default.join("~", ".cursor", "mcp.json");
|
|
23014
23733
|
case "claude-code":
|
|
23015
|
-
return
|
|
23734
|
+
return path33__default.default.join("~", ".claude.json");
|
|
23016
23735
|
case "codex":
|
|
23017
|
-
return
|
|
23736
|
+
return path33__default.default.join("~", ".codex", "config.toml");
|
|
23018
23737
|
case "gemini":
|
|
23019
|
-
return
|
|
23738
|
+
return path33__default.default.join("~", ".gemini", "settings.json");
|
|
23020
23739
|
}
|
|
23021
23740
|
}
|
|
23022
23741
|
async function mcpConfigureCommand(options) {
|
|
@@ -23040,8 +23759,8 @@ async function mcpConfigureCommand(options) {
|
|
|
23040
23759
|
];
|
|
23041
23760
|
let wrote = false;
|
|
23042
23761
|
if (!dryRun && projectLocal) {
|
|
23043
|
-
const abs =
|
|
23044
|
-
await promises.mkdir(
|
|
23762
|
+
const abs = path33__default.default.resolve(targetPath);
|
|
23763
|
+
await promises.mkdir(path33__default.default.dirname(abs), { recursive: true });
|
|
23045
23764
|
await promises.writeFile(abs, `${JSON.stringify(config, null, 2)}
|
|
23046
23765
|
`, "utf8");
|
|
23047
23766
|
wrote = true;
|
|
@@ -23201,23 +23920,23 @@ function readManifestDocument(value) {
|
|
|
23201
23920
|
};
|
|
23202
23921
|
}
|
|
23203
23922
|
function cwdRelative(filePath) {
|
|
23204
|
-
const relative =
|
|
23205
|
-
if (relative === "" || relative.startsWith("../") ||
|
|
23206
|
-
return
|
|
23923
|
+
const relative = path33__default.default.relative(process.cwd(), path33__default.default.resolve(filePath)).replace(/\\/g, "/");
|
|
23924
|
+
if (relative === "" || relative.startsWith("../") || path33__default.default.isAbsolute(relative)) {
|
|
23925
|
+
return path33__default.default.basename(filePath);
|
|
23207
23926
|
}
|
|
23208
23927
|
return relative;
|
|
23209
23928
|
}
|
|
23210
23929
|
async function readReporterManifest(filePath) {
|
|
23211
|
-
const absolute =
|
|
23930
|
+
const absolute = path33__default.default.resolve(filePath);
|
|
23212
23931
|
const raw = await promises.readFile(absolute, "utf-8");
|
|
23213
23932
|
const document = readManifestDocument(JSON.parse(raw));
|
|
23214
23933
|
const manifest = document.manifest;
|
|
23215
23934
|
const results = manifest.results.map((result) => ({
|
|
23216
23935
|
testId: safeText(result.testId),
|
|
23217
23936
|
name: safeText(result.name),
|
|
23218
|
-
...result.file === void 0 ? {} : { file: safeText(
|
|
23937
|
+
...result.file === void 0 ? {} : { file: safeText(path33__default.default.basename(result.file)) },
|
|
23219
23938
|
status: result.status,
|
|
23220
|
-
...result.tracePath === void 0 ? {} : { tracePath: safeText(
|
|
23939
|
+
...result.tracePath === void 0 ? {} : { tracePath: safeText(path33__default.default.basename(result.tracePath)) },
|
|
23221
23940
|
artifacts: result.artifacts,
|
|
23222
23941
|
diagnostics: result.diagnostics
|
|
23223
23942
|
}));
|
|
@@ -23356,15 +24075,15 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
|
|
|
23356
24075
|
return;
|
|
23357
24076
|
}
|
|
23358
24077
|
const markdown = renderMarkdown2(result);
|
|
23359
|
-
const outputPath = options.output !== void 0 && options.output.trim() !== "" ?
|
|
24078
|
+
const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path33__default.default.resolve(options.output.trim()) : void 0;
|
|
23360
24079
|
if (outputPath !== void 0) {
|
|
23361
|
-
await promises.mkdir(
|
|
24080
|
+
await promises.mkdir(path33__default.default.dirname(outputPath), { recursive: true });
|
|
23362
24081
|
await promises.writeFile(outputPath, markdown, "utf-8");
|
|
23363
24082
|
}
|
|
23364
24083
|
const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
|
|
23365
24084
|
if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
|
|
23366
|
-
const summaryPath =
|
|
23367
|
-
await promises.mkdir(
|
|
24085
|
+
const summaryPath = path33__default.default.resolve(summaryTarget);
|
|
24086
|
+
await promises.mkdir(path33__default.default.dirname(summaryPath), { recursive: true });
|
|
23368
24087
|
await promises.appendFile(summaryPath, `
|
|
23369
24088
|
${markdown}`, "utf-8");
|
|
23370
24089
|
}
|
|
@@ -23549,7 +24268,7 @@ jobs:
|
|
|
23549
24268
|
}
|
|
23550
24269
|
async function planInit(options = {}) {
|
|
23551
24270
|
const framework = normalizeFramework(options.framework);
|
|
23552
|
-
const cwd =
|
|
24271
|
+
const cwd = path33__default.default.resolve(options.cwd ?? process.cwd());
|
|
23553
24272
|
const demoPath = framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${framework}-demo.mjs`;
|
|
23554
24273
|
const candidates = [
|
|
23555
24274
|
{ rel: CONFIG_FILE, content: configTemplate(framework) },
|
|
@@ -23564,7 +24283,7 @@ async function planInit(options = {}) {
|
|
|
23564
24283
|
}
|
|
23565
24284
|
const files = [];
|
|
23566
24285
|
for (const candidate of candidates) {
|
|
23567
|
-
const abs =
|
|
24286
|
+
const abs = path33__default.default.join(cwd, candidate.rel);
|
|
23568
24287
|
try {
|
|
23569
24288
|
await promises.access(abs);
|
|
23570
24289
|
files.push({
|
|
@@ -23585,12 +24304,12 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
23585
24304
|
if (entry.action === "skip") {
|
|
23586
24305
|
continue;
|
|
23587
24306
|
}
|
|
23588
|
-
const abs =
|
|
24307
|
+
const abs = path33__default.default.join(cwd, entry.path);
|
|
23589
24308
|
if (options.dryRun) {
|
|
23590
24309
|
written.push(entry.path);
|
|
23591
24310
|
continue;
|
|
23592
24311
|
}
|
|
23593
|
-
await promises.mkdir(
|
|
24312
|
+
await promises.mkdir(path33__default.default.dirname(abs), { recursive: true });
|
|
23594
24313
|
const demoPath = plan.framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${plan.framework}-demo.mjs`;
|
|
23595
24314
|
const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate(demoPath) : demoTemplate(plan.framework);
|
|
23596
24315
|
await promises.writeFile(abs, content, "utf-8");
|
|
@@ -23599,7 +24318,7 @@ async function writePlannedFiles(plan, cwd, options) {
|
|
|
23599
24318
|
return written;
|
|
23600
24319
|
}
|
|
23601
24320
|
async function initCommand(options = {}) {
|
|
23602
|
-
const cwd =
|
|
24321
|
+
const cwd = path33__default.default.resolve(options.cwd ?? process.cwd());
|
|
23603
24322
|
try {
|
|
23604
24323
|
const plan = await planInit({ ...options, cwd });
|
|
23605
24324
|
const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
|
|
@@ -23694,7 +24413,7 @@ function envCheck(name, optional = true) {
|
|
|
23694
24413
|
};
|
|
23695
24414
|
}
|
|
23696
24415
|
async function traceDirWritable(traceDir) {
|
|
23697
|
-
const resolved =
|
|
24416
|
+
const resolved = path33__default.default.resolve(traceDir);
|
|
23698
24417
|
try {
|
|
23699
24418
|
await promises.mkdir(resolved, { recursive: true });
|
|
23700
24419
|
await promises.access(resolved, promises.constants.W_OK);
|
|
@@ -23715,10 +24434,10 @@ async function traceDirWritable(traceDir) {
|
|
|
23715
24434
|
}
|
|
23716
24435
|
}
|
|
23717
24436
|
function readPackageVersionNearEntry(entryPath, packageName) {
|
|
23718
|
-
let dir =
|
|
23719
|
-
const { root } =
|
|
24437
|
+
let dir = path33__default.default.dirname(path33__default.default.resolve(entryPath));
|
|
24438
|
+
const { root } = path33__default.default.parse(dir);
|
|
23720
24439
|
while (true) {
|
|
23721
|
-
const candidate =
|
|
24440
|
+
const candidate = path33__default.default.join(dir, "package.json");
|
|
23722
24441
|
if (fs.existsSync(candidate)) {
|
|
23723
24442
|
try {
|
|
23724
24443
|
const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
@@ -23729,14 +24448,14 @@ function readPackageVersionNearEntry(entryPath, packageName) {
|
|
|
23729
24448
|
}
|
|
23730
24449
|
}
|
|
23731
24450
|
if (dir === root) break;
|
|
23732
|
-
const parent =
|
|
24451
|
+
const parent = path33__default.default.dirname(dir);
|
|
23733
24452
|
if (parent === dir) break;
|
|
23734
24453
|
dir = parent;
|
|
23735
24454
|
}
|
|
23736
24455
|
return void 0;
|
|
23737
24456
|
}
|
|
23738
24457
|
function resolveInstalledPackage(cwd, name) {
|
|
23739
|
-
const require2 = module$1.createRequire(
|
|
24458
|
+
const require2 = module$1.createRequire(path33__default.default.join(cwd, "package.json"));
|
|
23740
24459
|
try {
|
|
23741
24460
|
const entry = require2.resolve(name);
|
|
23742
24461
|
let version2;
|
|
@@ -23834,7 +24553,7 @@ function versionMismatchCheck(cwd) {
|
|
|
23834
24553
|
};
|
|
23835
24554
|
}
|
|
23836
24555
|
async function runDoctorChecks(options = {}) {
|
|
23837
|
-
const cwd =
|
|
24556
|
+
const cwd = path33__default.default.resolve(options.cwd ?? process3__default.default.cwd());
|
|
23838
24557
|
const traceDir = options.traceDir?.trim() || process3__default.default.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
|
|
23839
24558
|
const checks2 = [
|
|
23840
24559
|
nodeVersionCheck(),
|
|
@@ -24074,7 +24793,7 @@ function parsePluginManifest(input3) {
|
|
|
24074
24793
|
};
|
|
24075
24794
|
}
|
|
24076
24795
|
async function readPluginManifestFile(packageDir) {
|
|
24077
|
-
const manifestPath =
|
|
24796
|
+
const manifestPath = path33__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
|
|
24078
24797
|
try {
|
|
24079
24798
|
const raw = await promises.readFile(manifestPath, "utf8");
|
|
24080
24799
|
const parsed = parsePluginManifest(JSON.parse(raw));
|
|
@@ -24149,7 +24868,7 @@ function createTraceDirectoryIndexer() {
|
|
|
24149
24868
|
// packages/cli/src/plugins.ts
|
|
24150
24869
|
async function readPackageName(packageDir) {
|
|
24151
24870
|
try {
|
|
24152
|
-
const raw = await promises.readFile(
|
|
24871
|
+
const raw = await promises.readFile(path33__default.default.join(packageDir, "package.json"), "utf8");
|
|
24153
24872
|
const parsed = JSON.parse(raw);
|
|
24154
24873
|
return typeof parsed.name === "string" ? parsed.name : void 0;
|
|
24155
24874
|
} catch {
|
|
@@ -24157,7 +24876,7 @@ async function readPackageName(packageDir) {
|
|
|
24157
24876
|
}
|
|
24158
24877
|
}
|
|
24159
24878
|
async function discoverPlugins(cwd = process.cwd()) {
|
|
24160
|
-
const nodeModules =
|
|
24879
|
+
const nodeModules = path33__default.default.join(cwd, "node_modules");
|
|
24161
24880
|
const found = [];
|
|
24162
24881
|
let entries;
|
|
24163
24882
|
try {
|
|
@@ -24168,7 +24887,7 @@ async function discoverPlugins(cwd = process.cwd()) {
|
|
|
24168
24887
|
for (const entry of entries.sort()) {
|
|
24169
24888
|
if (entry.startsWith("@")) continue;
|
|
24170
24889
|
if (!isPluginPackageName(entry)) continue;
|
|
24171
|
-
const packageDir =
|
|
24890
|
+
const packageDir = path33__default.default.join(nodeModules, entry);
|
|
24172
24891
|
const manifestRead = await readPluginManifestFile(packageDir);
|
|
24173
24892
|
found.push({
|
|
24174
24893
|
packageName: entry,
|
|
@@ -24181,7 +24900,7 @@ async function discoverPlugins(cwd = process.cwd()) {
|
|
|
24181
24900
|
return found;
|
|
24182
24901
|
}
|
|
24183
24902
|
async function validatePluginPackage(packageRef, cwd = process.cwd()) {
|
|
24184
|
-
const packageDir =
|
|
24903
|
+
const packageDir = path33__default.default.isAbsolute(packageRef) ? packageRef : path33__default.default.join(cwd, "node_modules", packageRef);
|
|
24185
24904
|
const packageName = await readPackageName(packageDir) ?? packageRef;
|
|
24186
24905
|
const errors = [];
|
|
24187
24906
|
const warnings = [];
|
|
@@ -24258,7 +24977,7 @@ async function pluginsValidateCommand(packageRef, cwd) {
|
|
|
24258
24977
|
init_advanced();
|
|
24259
24978
|
var INDEX_FILENAME = ".agent-inspect-index.json";
|
|
24260
24979
|
function traceIndexPath(traceDir) {
|
|
24261
|
-
return
|
|
24980
|
+
return path33__default.default.join(traceDir, INDEX_FILENAME);
|
|
24262
24981
|
}
|
|
24263
24982
|
function parseMaxEntries(raw) {
|
|
24264
24983
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -24404,7 +25123,7 @@ async function newestTraceMtimeMs2(traceDir) {
|
|
|
24404
25123
|
for (const file of files) {
|
|
24405
25124
|
if (!file.endsWith(".jsonl")) continue;
|
|
24406
25125
|
try {
|
|
24407
|
-
const s = await promises.stat(
|
|
25126
|
+
const s = await promises.stat(path33__default.default.join(traceDir, file));
|
|
24408
25127
|
if (s.mtimeMs > newest) newest = s.mtimeMs;
|
|
24409
25128
|
} catch {
|
|
24410
25129
|
}
|
|
@@ -24659,11 +25378,11 @@ function printJson5(value) {
|
|
|
24659
25378
|
console.log(JSON.stringify(value, null, 2));
|
|
24660
25379
|
}
|
|
24661
25380
|
function resolveCwd(options) {
|
|
24662
|
-
return
|
|
25381
|
+
return path33__default.default.resolve(options.cwd ?? process.cwd());
|
|
24663
25382
|
}
|
|
24664
25383
|
async function suiteInitCommand(options = {}) {
|
|
24665
25384
|
const cwd = resolveCwd(options);
|
|
24666
|
-
const configPath =
|
|
25385
|
+
const configPath = path33__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
|
|
24667
25386
|
const template = options.template?.trim();
|
|
24668
25387
|
const suiteConfig = template !== void 0 && template !== "" ? resolveSuiteTemplate(template) : defaultSuiteConfigTemplate();
|
|
24669
25388
|
if (options.dryRun) {
|
|
@@ -24782,13 +25501,13 @@ async function suiteListCommand(options = {}) {
|
|
|
24782
25501
|
}
|
|
24783
25502
|
async function writeSuiteArtifact(result, configOutputDir, options) {
|
|
24784
25503
|
const cwd = resolveCwd(options);
|
|
24785
|
-
const outputDir =
|
|
25504
|
+
const outputDir = path33__default.default.resolve(
|
|
24786
25505
|
cwd,
|
|
24787
25506
|
options.output ?? configOutputDir ?? DEFAULT_SUITE_ARTIFACTS_DIR
|
|
24788
25507
|
);
|
|
24789
25508
|
await promises.mkdir(outputDir, { recursive: true });
|
|
24790
25509
|
const stamp = result.startedAt.replace(/[:.]/g, "-");
|
|
24791
|
-
const filePath =
|
|
25510
|
+
const filePath = path33__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
|
|
24792
25511
|
await promises.writeFile(filePath, `${JSON.stringify(result, null, 2)}
|
|
24793
25512
|
`, "utf-8");
|
|
24794
25513
|
return filePath;
|
|
@@ -24846,7 +25565,7 @@ async function loadSuiteResultFromInput(options) {
|
|
|
24846
25565
|
if (options.input === void 0 || options.input.trim() === "") {
|
|
24847
25566
|
throw new Error("Pass --input <suite-run.json> from a prior suite run.");
|
|
24848
25567
|
}
|
|
24849
|
-
const inputPath =
|
|
25568
|
+
const inputPath = path33__default.default.resolve(cwd, options.input.trim());
|
|
24850
25569
|
const raw = await promises.readFile(inputPath, "utf-8");
|
|
24851
25570
|
return JSON.parse(raw);
|
|
24852
25571
|
}
|
|
@@ -24889,9 +25608,9 @@ function normalizeMetrics2(raw) {
|
|
|
24889
25608
|
}
|
|
24890
25609
|
async function writeArtifacts(result, outputDir) {
|
|
24891
25610
|
await promises.mkdir(outputDir, { recursive: true });
|
|
24892
|
-
const jsonPath =
|
|
24893
|
-
const markdownPath =
|
|
24894
|
-
const htmlPath =
|
|
25611
|
+
const jsonPath = path33__default.default.join(outputDir, "cohort-results.json");
|
|
25612
|
+
const markdownPath = path33__default.default.join(outputDir, "cohort-summary.md");
|
|
25613
|
+
const htmlPath = path33__default.default.join(outputDir, "cohort-report.html");
|
|
24895
25614
|
await promises.writeFile(jsonPath, `${renderCohortReport(result, { format: "json" })}
|
|
24896
25615
|
`, "utf-8");
|
|
24897
25616
|
await promises.writeFile(
|
|
@@ -24920,7 +25639,7 @@ async function cohortCommand(options = {}) {
|
|
|
24920
25639
|
const format = options.format ?? (options.json ? "json" : "markdown");
|
|
24921
25640
|
let artifacts;
|
|
24922
25641
|
if (options.output !== void 0 && options.output.trim() !== "") {
|
|
24923
|
-
artifacts = await writeArtifacts(result,
|
|
25642
|
+
artifacts = await writeArtifacts(result, path33__default.default.resolve(options.output.trim()));
|
|
24924
25643
|
}
|
|
24925
25644
|
if (options.json || format === "json") {
|
|
24926
25645
|
console.log(
|
|
@@ -24993,11 +25712,11 @@ function parseDuration2(value) {
|
|
|
24993
25712
|
async function writeArtifacts2(result, outputDir) {
|
|
24994
25713
|
await promises.mkdir(outputDir, { recursive: true });
|
|
24995
25714
|
const paths = {
|
|
24996
|
-
jsonPath:
|
|
24997
|
-
markdownPath:
|
|
24998
|
-
htmlPath:
|
|
24999
|
-
junitPath:
|
|
25000
|
-
githubPath:
|
|
25715
|
+
jsonPath: path33__default.default.join(outputDir, "gate-results.json"),
|
|
25716
|
+
markdownPath: path33__default.default.join(outputDir, "gate-summary.md"),
|
|
25717
|
+
htmlPath: path33__default.default.join(outputDir, "gate-report.html"),
|
|
25718
|
+
junitPath: path33__default.default.join(outputDir, "junit.xml"),
|
|
25719
|
+
githubPath: path33__default.default.join(outputDir, "github-step-summary.md")
|
|
25001
25720
|
};
|
|
25002
25721
|
await promises.writeFile(
|
|
25003
25722
|
paths.jsonPath,
|
|
@@ -25065,7 +25784,7 @@ async function gateCommand(options = {}) {
|
|
|
25065
25784
|
const result = await runGate(runs, gateOptions);
|
|
25066
25785
|
let artifacts;
|
|
25067
25786
|
if (options.output !== void 0 && options.output.trim() !== "") {
|
|
25068
|
-
artifacts = await writeArtifacts2(result,
|
|
25787
|
+
artifacts = await writeArtifacts2(result, path33__default.default.resolve(options.output.trim()));
|
|
25069
25788
|
}
|
|
25070
25789
|
const failed = !result.ok;
|
|
25071
25790
|
if (shouldEmitEvidence(options.evidenceOn, failed)) {
|
|
@@ -25372,7 +26091,7 @@ function createCliProgram() {
|
|
|
25372
26091
|
"openinference-json",
|
|
25373
26092
|
"otlp-json"
|
|
25374
26093
|
])
|
|
25375
|
-
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").option("--explain", "explain each finding (path, confidence, redaction, override, bundle gate)").option("--max-string-length <number>", "unsafe threshold for string values").option("--max-array-length <number>", "unsafe threshold for array values").option("--max-object-keys <number>", "unsafe threshold for object key counts").option("--max-serialized-bytes <number>", "unsafe threshold for serialized values").action((target, opts) => {
|
|
26094
|
+
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").option("--explain", "explain each finding (path, confidence, redaction, override, bundle gate)").option("--max-string-length <number>", "unsafe threshold for string values").option("--max-array-length <number>", "unsafe threshold for array values").option("--max-object-keys <number>", "unsafe threshold for object key counts").option("--max-serialized-bytes <number>", "unsafe threshold for serialized values").option("--policy <path>", "local JSON redaction policy (extraKeys + bounded patterns)").action((target, opts) => {
|
|
25376
26095
|
runCommand(() => scanCommand(target, opts));
|
|
25377
26096
|
});
|
|
25378
26097
|
program.command("verify-safe").description("Best-effort local trace safety verification").argument("<trace-path-or-run-id>", "trace file, directory, stdin -, or run id").option("--dir <path>", "trace directory for run-id lookup").addOption(
|
|
@@ -25381,7 +26100,7 @@ function createCliProgram() {
|
|
|
25381
26100
|
"openinference-json",
|
|
25382
26101
|
"otlp-json"
|
|
25383
26102
|
])
|
|
25384
|
-
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").option("--explain", "explain each finding (path, confidence, redaction, override, bundle gate)").option("--max-string-length <number>", "unsafe threshold for string values").option("--max-array-length <number>", "unsafe threshold for array values").option("--max-object-keys <number>", "unsafe threshold for object key counts").option("--max-serialized-bytes <number>", "unsafe threshold for serialized values").action((target, opts) => {
|
|
26103
|
+
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").option("--explain", "explain each finding (path, confidence, redaction, override, bundle gate)").option("--max-string-length <number>", "unsafe threshold for string values").option("--max-array-length <number>", "unsafe threshold for array values").option("--max-object-keys <number>", "unsafe threshold for object key counts").option("--max-serialized-bytes <number>", "unsafe threshold for serialized values").option("--policy <path>", "local JSON redaction policy (extraKeys + bounded patterns)").action((target, opts) => {
|
|
25385
26104
|
runCommand(() => verifySafeCommand(target, opts));
|
|
25386
26105
|
});
|
|
25387
26106
|
program.command("artifacts").description("Create safe local CI trace artifacts").argument("<trace-path-or-run-id>", "trace file, directory, stdin -, or run id").requiredOption("--output-dir <path>", "directory for generated artifacts").option("--dir <path>", "trace directory for run-id lookup").addOption(
|
|
@@ -25541,7 +26260,10 @@ function createCliProgram() {
|
|
|
25541
26260
|
"--redaction-profile <profile>",
|
|
25542
26261
|
"alias for --profile (canonical spelling)"
|
|
25543
26262
|
).choices(["local", "share", "strict"])
|
|
25544
|
-
).option("-o, --output <path>", "write redacted content to a file").option("--out <path>", "alias for --output").option("--json", "print deterministic JSON wrapper with findings").
|
|
26263
|
+
).option("-o, --output <path>", "write redacted content to a file").option("--out <path>", "alias for --output").option("--json", "print deterministic JSON wrapper with findings").option("--policy <path>", "local JSON redaction policy (extraKeys + bounded patterns)").option(
|
|
26264
|
+
"--fail-on-residual",
|
|
26265
|
+
"exit non-zero when residual safety is UNSAFE or UNKNOWN (opt-in)"
|
|
26266
|
+
).action((target, opts) => {
|
|
25545
26267
|
runCommand(() => redactCommand(target, opts));
|
|
25546
26268
|
});
|
|
25547
26269
|
program.command("explain").description("Explain a local trace with deterministic facts (no provider calls)").argument("<trace-path-or-run-id>", "trace file, directory, stdin -, or run id").option("--dir <path>", "trace directory for run-id lookup").addOption(
|
|
@@ -25723,9 +26445,9 @@ function isPrimaryModule() {
|
|
|
25723
26445
|
if (!entry) return false;
|
|
25724
26446
|
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)));
|
|
25725
26447
|
try {
|
|
25726
|
-
return fs.realpathSync(
|
|
26448
|
+
return fs.realpathSync(path33__default.default.resolve(entry)) === fs.realpathSync(path33__default.default.resolve(selfPath));
|
|
25727
26449
|
} catch {
|
|
25728
|
-
return
|
|
26450
|
+
return path33__default.default.resolve(entry) === path33__default.default.resolve(selfPath);
|
|
25729
26451
|
}
|
|
25730
26452
|
}
|
|
25731
26453
|
if (isPrimaryModule()) {
|