agent-inspect 6.8.0 → 6.9.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 +6 -0
- package/README.md +1 -1
- package/docs/CLI.md +10 -3
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-TO4VENHV.mjs → chunk-WQ5XMFH2.mjs} +109 -17
- package/packages/cli/dist/chunk-WQ5XMFH2.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +357 -66
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +252 -53
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-Z5W27YCW.mjs → src-C4EUHTER.mjs} +3 -3
- package/packages/cli/dist/{src-Z5W27YCW.mjs.map → src-C4EUHTER.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +15 -6
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +4 -1
- package/packages/core/dist/advanced.d.ts +4 -1
- package/packages/core/dist/advanced.mjs +3 -2
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +105 -14
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.d.cts +2 -2
- package/packages/core/dist/checks.d.ts +2 -2
- package/packages/core/dist/checks.mjs +1 -1
- package/packages/core/dist/{chunk-EQVXDGGU.mjs → chunk-QT6CQ2XA.mjs} +107 -16
- package/packages/core/dist/chunk-QT6CQ2XA.mjs.map +1 -0
- package/packages/core/dist/{index-BblJEdYZ.d.ts → index-BO7l0iAe.d.ts} +44 -1
- package/packages/core/dist/{index-DyKk7iR9.d.cts → index-mdFcxSOR.d.cts} +44 -1
- package/packages/cli/dist/chunk-TO4VENHV.mjs.map +0 -1
- package/packages/core/dist/chunk-EQVXDGGU.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, enrichSessionRunRecord, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, extractMetadata, filterTraces, truncateName, getTraceFilePath, buildRunSummary, formatDuration, formatTimestamp, isAgentInspectTrace, openTrace, TraceReadError, filterMetasBySessionScope, runTraceChecks, aggregateSessionCheckResults, createBaselineRegressionRule, resolveBundleRunIds, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, buildBundleMetadata, buildBundleSummaryMarkdown, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, renderErrorLine, getIndent, Redactor, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, assertBundlePathContained, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, escapeMarkdown, escapeHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, resolveRedactionProfile, applyProfileMetadataCaps, flattenTree, safeString, compactAttributes, stableJson, truncateStringForProfile } from './chunk-
|
|
2
|
+
import { createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, enrichSessionRunRecord, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, extractMetadata, filterTraces, truncateName, getTraceFilePath, buildRunSummary, formatDuration, formatTimestamp, isAgentInspectTrace, openTrace, TraceReadError, filterMetasBySessionScope, runTraceChecks, aggregateSessionCheckResults, createBaselineRegressionRule, resolveBundleRunIds, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, buildBundleMetadata, buildBundleSummaryMarkdown, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, renderErrorLine, getIndent, Redactor, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, assertBundlePathContained, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, escapeMarkdown, escapeHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, resolveRedactionProfile, applyProfileMetadataCaps, flattenTree, safeString, compactAttributes, stableJson, truncateStringForProfile } from './chunk-WQ5XMFH2.mjs';
|
|
3
3
|
import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
|
|
4
4
|
import path14 from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
@@ -11,7 +11,7 @@ import { createServer } from 'http';
|
|
|
11
11
|
import { createRequire } from 'module';
|
|
12
12
|
|
|
13
13
|
// package.json
|
|
14
|
-
var version = "6.
|
|
14
|
+
var version = "6.9.0";
|
|
15
15
|
|
|
16
16
|
// packages/cli/src/trace-dir-scale.ts
|
|
17
17
|
var TRACE_COUNT_WARN = 1e3;
|
|
@@ -3808,7 +3808,7 @@ async function newestTraceMtimeMs(traceDir) {
|
|
|
3808
3808
|
}
|
|
3809
3809
|
async function loadSessionRuns(traceDir) {
|
|
3810
3810
|
try {
|
|
3811
|
-
const mod = await import('./src-
|
|
3811
|
+
const mod = await import('./src-C4EUHTER.mjs');
|
|
3812
3812
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
3813
3813
|
const status = mod.indexStatus(dbPath);
|
|
3814
3814
|
if (!status.healthy) {
|
|
@@ -4309,7 +4309,12 @@ var SHARE_PROFILE_EXTRA_KEYS = [
|
|
|
4309
4309
|
"organizationId",
|
|
4310
4310
|
"traceId",
|
|
4311
4311
|
"spanId",
|
|
4312
|
-
"parentSpanId"
|
|
4312
|
+
"parentSpanId",
|
|
4313
|
+
"currentTask",
|
|
4314
|
+
"task",
|
|
4315
|
+
"userInput",
|
|
4316
|
+
"requestText",
|
|
4317
|
+
"conversationText"
|
|
4313
4318
|
];
|
|
4314
4319
|
var STRICT_PROFILE_EXTRA_KEYS = [
|
|
4315
4320
|
"prompt",
|
|
@@ -4377,6 +4382,61 @@ function passesLuhn(value) {
|
|
|
4377
4382
|
}
|
|
4378
4383
|
return sum % 10 === 0;
|
|
4379
4384
|
}
|
|
4385
|
+
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;
|
|
4386
|
+
var EPOCH_MS_RE = /^1[0-9]{12}$/;
|
|
4387
|
+
var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
4388
|
+
function pathSuggestsNonCard(path25) {
|
|
4389
|
+
const normalized = path25.toLowerCase().replace(/[^a-z0-9._]/g, "");
|
|
4390
|
+
return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
|
|
4391
|
+
normalized
|
|
4392
|
+
) || /(^|\.)ts(\.|$)/.test(normalized);
|
|
4393
|
+
}
|
|
4394
|
+
function isUuidLike(value) {
|
|
4395
|
+
return UUID_RE.test(value.trim());
|
|
4396
|
+
}
|
|
4397
|
+
function isPlausibleCardCandidate(candidate, fullValue) {
|
|
4398
|
+
const digits = digitsOnly(candidate);
|
|
4399
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
4400
|
+
if (!passesLuhn(candidate)) return false;
|
|
4401
|
+
const trimmed = fullValue.trim();
|
|
4402
|
+
if (isUuidLike(trimmed)) return false;
|
|
4403
|
+
if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\d+$/.test(trimmed)) {
|
|
4404
|
+
return false;
|
|
4405
|
+
}
|
|
4406
|
+
const start = fullValue.indexOf(candidate);
|
|
4407
|
+
if (start >= 0) {
|
|
4408
|
+
const before = fullValue[start - 1];
|
|
4409
|
+
const after = fullValue[start + candidate.length];
|
|
4410
|
+
if (before && /[A-Za-z0-9_]/.test(before)) return false;
|
|
4411
|
+
if (after && /[A-Za-z0-9_]/.test(after)) return false;
|
|
4412
|
+
}
|
|
4413
|
+
return true;
|
|
4414
|
+
}
|
|
4415
|
+
function looksLikePathOrPackageOrUrl(value) {
|
|
4416
|
+
const trimmed = value.trim();
|
|
4417
|
+
if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(trimmed)) return true;
|
|
4418
|
+
if (/^webpack:/i.test(trimmed)) return true;
|
|
4419
|
+
if (/^@[A-Za-z0-9_.-]+\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;
|
|
4420
|
+
if (/^[A-Za-z]:[\\/]/.test(trimmed) || /^[/\\]/.test(trimmed)) return true;
|
|
4421
|
+
if (/[\\/]/.test(trimmed) && !/\s/.test(trimmed)) return true;
|
|
4422
|
+
return false;
|
|
4423
|
+
}
|
|
4424
|
+
function emailMatchIsPathAdjacent(value, index, length) {
|
|
4425
|
+
const before = value[index - 1];
|
|
4426
|
+
const after = value[index + length];
|
|
4427
|
+
return before === "/" || before === "\\" || after === "/" || after === "\\";
|
|
4428
|
+
}
|
|
4429
|
+
function valueContainsEmail(value) {
|
|
4430
|
+
if (looksLikePathOrPackageOrUrl(value)) return false;
|
|
4431
|
+
EMAIL_RE.lastIndex = 0;
|
|
4432
|
+
for (const match of value.matchAll(EMAIL_RE)) {
|
|
4433
|
+
const text = match[0] ?? "";
|
|
4434
|
+
const index = match.index ?? 0;
|
|
4435
|
+
if (emailMatchIsPathAdjacent(value, index, text.length)) continue;
|
|
4436
|
+
return true;
|
|
4437
|
+
}
|
|
4438
|
+
return false;
|
|
4439
|
+
}
|
|
4380
4440
|
var credentialDetectors = [
|
|
4381
4441
|
patternDetector({
|
|
4382
4442
|
id: "value.authorizationHeader",
|
|
@@ -4424,10 +4484,12 @@ var credentialDetectors = [
|
|
|
4424
4484
|
matchKind: "value",
|
|
4425
4485
|
detect(input3) {
|
|
4426
4486
|
if (typeof input3.value !== "string") return [];
|
|
4487
|
+
if (pathSuggestsNonCard(input3.path)) return [];
|
|
4488
|
+
if (isUuidLike(input3.value)) return [];
|
|
4427
4489
|
const candidatePattern = /(?:\d[ -]?){13,19}/g;
|
|
4428
4490
|
for (const match of input3.value.matchAll(candidatePattern)) {
|
|
4429
4491
|
const candidate = match[0] ?? "";
|
|
4430
|
-
if (
|
|
4492
|
+
if (isPlausibleCardCandidate(candidate, input3.value)) {
|
|
4431
4493
|
return [{ action: "replace", severity: "error", matchKind: "value" }];
|
|
4432
4494
|
}
|
|
4433
4495
|
}
|
|
@@ -4436,10 +4498,15 @@ var credentialDetectors = [
|
|
|
4436
4498
|
}
|
|
4437
4499
|
];
|
|
4438
4500
|
var identifierDetectors = [
|
|
4439
|
-
|
|
4501
|
+
{
|
|
4440
4502
|
id: "value.email",
|
|
4441
|
-
|
|
4442
|
-
|
|
4503
|
+
severity: "warning",
|
|
4504
|
+
matchKind: "value",
|
|
4505
|
+
detect(input3) {
|
|
4506
|
+
if (typeof input3.value !== "string") return [];
|
|
4507
|
+
return valueContainsEmail(input3.value) ? [{ action: "replace", severity: "warning", matchKind: "value" }] : [];
|
|
4508
|
+
}
|
|
4509
|
+
},
|
|
4443
4510
|
patternDetector({
|
|
4444
4511
|
id: "value.phone",
|
|
4445
4512
|
pattern: /\b(?:\+\d{1,3}[\s.-]?)?(?:\(?\d{3}\)?[\s.-])\d{3}[\s.-]\d{4}\b/
|
|
@@ -4760,6 +4827,16 @@ function redactJsonlText(content, profile) {
|
|
|
4760
4827
|
};
|
|
4761
4828
|
}
|
|
4762
4829
|
function redactDocument(content, profile) {
|
|
4830
|
+
const trimmed = content.trim();
|
|
4831
|
+
if (trimmed.startsWith("{")) {
|
|
4832
|
+
try {
|
|
4833
|
+
const parsed = JSON.parse(trimmed);
|
|
4834
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && ("schemaVersion" in parsed || "eventId" in parsed || "runId" in parsed)) {
|
|
4835
|
+
return redactJsonlText(content, profile);
|
|
4836
|
+
}
|
|
4837
|
+
} catch {
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4763
4840
|
try {
|
|
4764
4841
|
return redactJsonText(content, profile);
|
|
4765
4842
|
} catch {
|
|
@@ -8235,8 +8312,6 @@ async function evalCommand(target, options = {}, stdin = process.stdin) {
|
|
|
8235
8312
|
else if (options.markdown) console.log(renderEvalMarkdown(result).trimEnd());
|
|
8236
8313
|
else printHuman2(result);
|
|
8237
8314
|
}
|
|
8238
|
-
|
|
8239
|
-
// packages/cli/src/safety.ts
|
|
8240
8315
|
var BEST_EFFORT_NOTE = "Best-effort local safety verification only; not a compliance, privacy, security, or regulatory certification.";
|
|
8241
8316
|
var DEFAULT_MAX_STRING_LENGTH = 16384;
|
|
8242
8317
|
var DEFAULT_MAX_ARRAY_LENGTH = 1e3;
|
|
@@ -8294,7 +8369,7 @@ function resultFromParts(parts) {
|
|
|
8294
8369
|
const diagnostics = [...parts.diagnostics ?? []];
|
|
8295
8370
|
const warnings = [...parts.warnings ?? []];
|
|
8296
8371
|
const unsupportedFields = [...parts.unsupportedFields ?? []];
|
|
8297
|
-
const status = statusFrom(findings, diagnostics);
|
|
8372
|
+
const status = parts.status ?? statusFrom(findings, diagnostics);
|
|
8298
8373
|
return {
|
|
8299
8374
|
ok: status === "SAFE" || status === "SAFE WITH WARNINGS",
|
|
8300
8375
|
command: parts.command,
|
|
@@ -8310,7 +8385,17 @@ function resultFromParts(parts) {
|
|
|
8310
8385
|
diagnostics,
|
|
8311
8386
|
warnings,
|
|
8312
8387
|
unsupportedFields,
|
|
8313
|
-
note: BEST_EFFORT_NOTE
|
|
8388
|
+
note: BEST_EFFORT_NOTE,
|
|
8389
|
+
...parts.sourceAssessment !== void 0 ? { sourceAssessment: parts.sourceAssessment } : {},
|
|
8390
|
+
...parts.artifactAssessment !== void 0 ? { artifactAssessment: parts.artifactAssessment } : {},
|
|
8391
|
+
...parts.redactionSummary !== void 0 ? { redactionSummary: parts.redactionSummary } : {}
|
|
8392
|
+
};
|
|
8393
|
+
}
|
|
8394
|
+
function layerFromResult(result) {
|
|
8395
|
+
return {
|
|
8396
|
+
status: result.status,
|
|
8397
|
+
summary: result.summary,
|
|
8398
|
+
findings: result.findings
|
|
8314
8399
|
};
|
|
8315
8400
|
}
|
|
8316
8401
|
function readErrorResult3(command, error) {
|
|
@@ -8374,6 +8459,21 @@ function flattenNodes(nodes) {
|
|
|
8374
8459
|
function detectorSeverity(finding) {
|
|
8375
8460
|
return finding.severity;
|
|
8376
8461
|
}
|
|
8462
|
+
function classifyRedactionDetector(detector) {
|
|
8463
|
+
if (detector === "value.creditCard" || detector === "value.email" || detector === "value.phone") {
|
|
8464
|
+
return { category: "personal-data", confidence: "high" };
|
|
8465
|
+
}
|
|
8466
|
+
if (detector === "value.ipv4" || detector === "value.ipv6") {
|
|
8467
|
+
return { category: "identifier", confidence: "medium" };
|
|
8468
|
+
}
|
|
8469
|
+
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"))) {
|
|
8470
|
+
return { category: "credential", confidence: "high" };
|
|
8471
|
+
}
|
|
8472
|
+
if (detector.startsWith("key.")) {
|
|
8473
|
+
return { category: "credential", confidence: "medium" };
|
|
8474
|
+
}
|
|
8475
|
+
return { category: "credential", confidence: "medium" };
|
|
8476
|
+
}
|
|
8377
8477
|
function redactionDetectorFindings(read, runId) {
|
|
8378
8478
|
const runs = runId === void 0 ? read.runs : read.runs.filter((run) => run.runId === runId);
|
|
8379
8479
|
const out = [];
|
|
@@ -8384,6 +8484,7 @@ function redactionDetectorFindings(read, runId) {
|
|
|
8384
8484
|
const result = redact(attrs, { profile: "share" });
|
|
8385
8485
|
for (const finding of result.findings) {
|
|
8386
8486
|
if (finding.action === "keep") continue;
|
|
8487
|
+
const taxonomy = classifyRedactionDetector(finding.detector);
|
|
8387
8488
|
out.push({
|
|
8388
8489
|
ruleId: "safety.redactDetector",
|
|
8389
8490
|
severity: detectorSeverity(finding),
|
|
@@ -8401,7 +8502,11 @@ function redactionDetectorFindings(read, runId) {
|
|
|
8401
8502
|
...node.event.status !== void 0 ? { status: node.event.status } : {},
|
|
8402
8503
|
path: `attributes.${finding.path.replace(/^\$\.?/, "")}`
|
|
8403
8504
|
}
|
|
8404
|
-
]
|
|
8505
|
+
],
|
|
8506
|
+
category: taxonomy.category,
|
|
8507
|
+
confidence: taxonomy.confidence,
|
|
8508
|
+
detector: finding.detector,
|
|
8509
|
+
action: finding.action
|
|
8405
8510
|
});
|
|
8406
8511
|
}
|
|
8407
8512
|
}
|
|
@@ -8417,13 +8522,49 @@ function exitCodeFor3(result) {
|
|
|
8417
8522
|
if (result.status === "UNSAFE") return 1;
|
|
8418
8523
|
return 2;
|
|
8419
8524
|
}
|
|
8420
|
-
function
|
|
8421
|
-
|
|
8525
|
+
function explainFinding(finding, blocksBundle) {
|
|
8526
|
+
const path25 = finding.evidence[0]?.path ?? "(unknown path)";
|
|
8527
|
+
const category = finding.category ?? "structure";
|
|
8528
|
+
const confidence = finding.confidence ?? "medium";
|
|
8529
|
+
const detector = finding.detector ?? finding.ruleId;
|
|
8530
|
+
const action = finding.action ?? "review";
|
|
8531
|
+
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.";
|
|
8532
|
+
return [
|
|
8533
|
+
` Matched: detector=${detector}; path=${path25}; category=${category}`,
|
|
8534
|
+
` Why: ${finding.message}`,
|
|
8535
|
+
` Confidence: ${confidence}`,
|
|
8536
|
+
` Redaction: ${redactionHint}`,
|
|
8537
|
+
` Override: configure a custom redaction/detector rule locally (see docs/SAFETY-POLICY.md); do not weaken defaults globally.`,
|
|
8538
|
+
` Bundle gate: ${blocksBundle ? "blocks share-safe bundle unless --allow-unsafe" : "does not block by itself (warning/info)"}`
|
|
8539
|
+
];
|
|
8540
|
+
}
|
|
8541
|
+
function findingExplanation(finding) {
|
|
8542
|
+
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
8543
|
+
return {
|
|
8544
|
+
ruleId: finding.ruleId,
|
|
8545
|
+
detector: finding.detector ?? finding.ruleId,
|
|
8546
|
+
path: finding.evidence[0]?.path,
|
|
8547
|
+
category: finding.category,
|
|
8548
|
+
confidence: finding.confidence,
|
|
8549
|
+
action: finding.action,
|
|
8550
|
+
blocksBundle: blocks,
|
|
8551
|
+
// Never include matched secret/PII values.
|
|
8552
|
+
message: finding.message
|
|
8553
|
+
};
|
|
8422
8554
|
}
|
|
8423
|
-
function printHuman3(result) {
|
|
8555
|
+
function printHuman3(result, explain = false) {
|
|
8424
8556
|
console.log(`Safety status: ${result.status}`);
|
|
8425
8557
|
console.log(`Format: ${result.format}`);
|
|
8426
8558
|
if (result.runId !== void 0) console.log(`Run: ${result.runId}`);
|
|
8559
|
+
if (result.sourceAssessment !== void 0 && result.artifactAssessment !== void 0) {
|
|
8560
|
+
console.log(`Source assessment: ${result.sourceAssessment.status}`);
|
|
8561
|
+
console.log(`Artifact assessment: ${result.artifactAssessment.status}`);
|
|
8562
|
+
if (result.redactionSummary !== void 0) {
|
|
8563
|
+
console.log(
|
|
8564
|
+
`Redaction: profile=${result.redactionSummary.profile}, findings=${result.redactionSummary.findings}`
|
|
8565
|
+
);
|
|
8566
|
+
}
|
|
8567
|
+
}
|
|
8427
8568
|
console.log(
|
|
8428
8569
|
`Summary: ${result.summary.findings} finding(s), ${result.summary.warnings} warning(s), ${result.summary.errors} error(s)`
|
|
8429
8570
|
);
|
|
@@ -8432,45 +8573,82 @@ function printHuman3(result) {
|
|
|
8432
8573
|
}
|
|
8433
8574
|
for (const finding of result.findings) {
|
|
8434
8575
|
const path25 = finding.evidence[0]?.path;
|
|
8435
|
-
|
|
8576
|
+
const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
|
|
8577
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path25 ? ` (${path25})` : ""}${taxonomy}`);
|
|
8578
|
+
if (explain) {
|
|
8579
|
+
const blocks = finding.severity === "error" || finding.status === "fail";
|
|
8580
|
+
for (const line of explainFinding(finding, blocks)) {
|
|
8581
|
+
console.log(line);
|
|
8582
|
+
}
|
|
8583
|
+
}
|
|
8436
8584
|
}
|
|
8437
8585
|
console.log(`Note: ${result.note}`);
|
|
8438
8586
|
}
|
|
8587
|
+
function printJson3(result, explain = false) {
|
|
8588
|
+
const payload = explain === true ? { ...result, explanations: result.findings.map(findingExplanation) } : result;
|
|
8589
|
+
console.log(JSON.stringify(stable4(payload), null, 2));
|
|
8590
|
+
}
|
|
8439
8591
|
async function safetyCommand(command, target, options, stdin) {
|
|
8440
8592
|
let result;
|
|
8441
8593
|
try {
|
|
8442
|
-
const rules = buildSafetyRules(options);
|
|
8443
8594
|
const input3 = await inputFromTarget(target, options, stdin);
|
|
8444
8595
|
const read = await openTrace(input3, {
|
|
8445
8596
|
...options.format !== void 0 ? { format: options.format } : {}
|
|
8446
8597
|
});
|
|
8447
|
-
const
|
|
8448
|
-
|
|
8449
|
-
{
|
|
8450
|
-
rules,
|
|
8451
|
-
...options.run !== void 0 ? { runId: options.run } : {}
|
|
8452
|
-
}
|
|
8453
|
-
);
|
|
8454
|
-
const detectorFindings = checkResult.diagnostics.length === 0 ? redactionDetectorFindings(read, checkResult.runId) : [];
|
|
8455
|
-
result = resultFromParts({
|
|
8456
|
-
command,
|
|
8457
|
-
format: checkResult.format,
|
|
8458
|
-
runId: checkResult.runId,
|
|
8459
|
-
findings: [...checkResult.findings, ...detectorFindings],
|
|
8460
|
-
diagnostics: [
|
|
8461
|
-
...checkResult.diagnostics.map(diagnosticFromCheck),
|
|
8462
|
-
...warningDiagnostics(read.warnings, read.unsupportedFields)
|
|
8463
|
-
],
|
|
8464
|
-
warnings: read.warnings,
|
|
8465
|
-
unsupportedFields: read.unsupportedFields
|
|
8598
|
+
const source = assessOpenedTrace(read, {
|
|
8599
|
+
...options,
|
|
8600
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
8466
8601
|
});
|
|
8602
|
+
if (command === "scan") {
|
|
8603
|
+
result = { ...source, command: "scan" };
|
|
8604
|
+
} else {
|
|
8605
|
+
const profile = options.redactionProfile ?? "share";
|
|
8606
|
+
const rawContent = input3.type === "string" ? input3.content : input3.type === "file" ? await readFile(input3.path, "utf-8") : void 0;
|
|
8607
|
+
if (rawContent === void 0) {
|
|
8608
|
+
result = {
|
|
8609
|
+
...source,
|
|
8610
|
+
command: "verify-safe",
|
|
8611
|
+
sourceAssessment: layerFromResult(source)
|
|
8612
|
+
};
|
|
8613
|
+
} else {
|
|
8614
|
+
const redacted = redactTraceContent(rawContent, profile);
|
|
8615
|
+
const artifactRead = await openTrace(
|
|
8616
|
+
{ type: "string", content: redacted.content },
|
|
8617
|
+
{ format: options.format ?? "agent-inspect-jsonl" }
|
|
8618
|
+
);
|
|
8619
|
+
const artifact = assessOpenedTrace(artifactRead, {
|
|
8620
|
+
...options,
|
|
8621
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
8622
|
+
});
|
|
8623
|
+
const detectors = [
|
|
8624
|
+
...new Set(redacted.findings.map((finding) => finding.detector))
|
|
8625
|
+
].sort((a, b) => a.localeCompare(b));
|
|
8626
|
+
result = resultFromParts({
|
|
8627
|
+
command: "verify-safe",
|
|
8628
|
+
format: artifact.format,
|
|
8629
|
+
runId: artifact.runId ?? source.runId,
|
|
8630
|
+
findings: artifact.findings,
|
|
8631
|
+
diagnostics: artifact.diagnostics,
|
|
8632
|
+
warnings: artifact.warnings,
|
|
8633
|
+
unsupportedFields: artifact.unsupportedFields,
|
|
8634
|
+
status: artifact.status,
|
|
8635
|
+
sourceAssessment: layerFromResult(source),
|
|
8636
|
+
artifactAssessment: layerFromResult(artifact),
|
|
8637
|
+
redactionSummary: {
|
|
8638
|
+
profile,
|
|
8639
|
+
findings: redacted.findings.length,
|
|
8640
|
+
detectors
|
|
8641
|
+
}
|
|
8642
|
+
});
|
|
8643
|
+
}
|
|
8644
|
+
}
|
|
8467
8645
|
} catch (error) {
|
|
8468
8646
|
const message = error instanceof Error ? error.message : String(error);
|
|
8469
8647
|
result = message.startsWith("--") ? invalidArgumentResult(command, error) : readErrorResult3(command, error);
|
|
8470
8648
|
}
|
|
8471
8649
|
process.exitCode = exitCodeFor3(result);
|
|
8472
|
-
if (options.json) printJson3(result);
|
|
8473
|
-
else printHuman3(result);
|
|
8650
|
+
if (options.json) printJson3(result, options.explain === true);
|
|
8651
|
+
else printHuman3(result, options.explain === true);
|
|
8474
8652
|
}
|
|
8475
8653
|
function scanCommand(target, options = {}, stdin = process.stdin) {
|
|
8476
8654
|
return safetyCommand("scan", target, options, stdin);
|
|
@@ -8949,15 +9127,8 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
8949
9127
|
process.exitCode = 1;
|
|
8950
9128
|
return;
|
|
8951
9129
|
}
|
|
8952
|
-
const
|
|
8953
|
-
const
|
|
8954
|
-
checkRuns.push({
|
|
8955
|
-
runId,
|
|
8956
|
-
status,
|
|
8957
|
-
errors: safety.summary.errors,
|
|
8958
|
-
warnings: safety.summary.warnings,
|
|
8959
|
-
findings: safety.summary.findings
|
|
8960
|
-
});
|
|
9130
|
+
const sourceSafety = assessOpenedTrace(read, { run: runId });
|
|
9131
|
+
const sourceStatus = safetyStatusFromAssess(sourceSafety.status);
|
|
8961
9132
|
const redacted = redactTraceContent(rawContent, toReportProfile(profile));
|
|
8962
9133
|
redactedJsonlByRun.set(runId, redacted.content);
|
|
8963
9134
|
combinedJsonl += redacted.content.endsWith("\n") ? redacted.content : `${redacted.content}
|
|
@@ -8970,6 +9141,34 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
8970
9141
|
findings: redacted.findings.length,
|
|
8971
9142
|
detectors
|
|
8972
9143
|
});
|
|
9144
|
+
let artifactSafety = sourceSafety;
|
|
9145
|
+
try {
|
|
9146
|
+
const artifactRead = await openTrace(
|
|
9147
|
+
{ type: "string", content: redacted.content },
|
|
9148
|
+
{ format: "agent-inspect-jsonl" }
|
|
9149
|
+
);
|
|
9150
|
+
artifactSafety = assessOpenedTrace(artifactRead, { run: runId });
|
|
9151
|
+
} catch {
|
|
9152
|
+
artifactSafety = {
|
|
9153
|
+
...sourceSafety,
|
|
9154
|
+
status: "UNKNOWN",
|
|
9155
|
+
ok: false,
|
|
9156
|
+
summary: {
|
|
9157
|
+
findings: sourceSafety.summary.findings,
|
|
9158
|
+
warnings: sourceSafety.summary.warnings,
|
|
9159
|
+
errors: Math.max(1, sourceSafety.summary.errors)
|
|
9160
|
+
}
|
|
9161
|
+
};
|
|
9162
|
+
}
|
|
9163
|
+
const status = safetyStatusFromAssess(artifactSafety.status);
|
|
9164
|
+
checkRuns.push({
|
|
9165
|
+
runId,
|
|
9166
|
+
status,
|
|
9167
|
+
sourceStatus,
|
|
9168
|
+
errors: artifactSafety.summary.errors,
|
|
9169
|
+
warnings: artifactSafety.summary.warnings,
|
|
9170
|
+
findings: artifactSafety.summary.findings
|
|
9171
|
+
});
|
|
8973
9172
|
const selected = read.runs.find((run) => run.runId === runId);
|
|
8974
9173
|
const runReport = exportRunTree(selected ?? read.runs[0], {
|
|
8975
9174
|
format: "html",
|
|
@@ -8998,13 +9197,13 @@ async function bundleCommand(runIdArg, options = {}) {
|
|
|
8998
9197
|
console.log(
|
|
8999
9198
|
writeJson4({
|
|
9000
9199
|
ok: false,
|
|
9001
|
-
error: `Bundle safety status is ${checks2.aggregateStatus}. Pass --allow-unsafe to override.`,
|
|
9200
|
+
error: `Bundle artifact safety status is ${checks2.aggregateStatus}. Pass --allow-unsafe to override.`,
|
|
9002
9201
|
checks: checks2
|
|
9003
9202
|
}).trimEnd()
|
|
9004
9203
|
);
|
|
9005
9204
|
} else {
|
|
9006
9205
|
console.error(
|
|
9007
|
-
`[AgentInspect] bundle refused: safety status is ${checks2.aggregateStatus}. Pass --allow-unsafe to override.`
|
|
9206
|
+
`[AgentInspect] bundle refused: artifact safety status is ${checks2.aggregateStatus}. Pass --allow-unsafe to override.`
|
|
9008
9207
|
);
|
|
9009
9208
|
}
|
|
9010
9209
|
process.exitCode = 1;
|
|
@@ -10423,7 +10622,7 @@ function isModuleNotFound4(e) {
|
|
|
10423
10622
|
}
|
|
10424
10623
|
async function loadIndexSqlite() {
|
|
10425
10624
|
try {
|
|
10426
|
-
return await import('./src-
|
|
10625
|
+
return await import('./src-C4EUHTER.mjs');
|
|
10427
10626
|
} catch (e) {
|
|
10428
10627
|
if (isModuleNotFound4(e)) {
|
|
10429
10628
|
console.error(
|
|
@@ -11335,7 +11534,7 @@ function createCliProgram() {
|
|
|
11335
11534
|
"openinference-json",
|
|
11336
11535
|
"otlp-json"
|
|
11337
11536
|
])
|
|
11338
|
-
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").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) => {
|
|
11537
|
+
).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) => {
|
|
11339
11538
|
runCommand(() => scanCommand(target, opts));
|
|
11340
11539
|
});
|
|
11341
11540
|
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(
|
|
@@ -11344,7 +11543,7 @@ function createCliProgram() {
|
|
|
11344
11543
|
"openinference-json",
|
|
11345
11544
|
"otlp-json"
|
|
11346
11545
|
])
|
|
11347
|
-
).option("--run <run-id>", "select a run when the trace contains multiple runs").option("--json", "print deterministic JSON safety result").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) => {
|
|
11546
|
+
).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) => {
|
|
11348
11547
|
runCommand(() => verifySafeCommand(target, opts));
|
|
11349
11548
|
});
|
|
11350
11549
|
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(
|