agent-inspect 4.2.0 → 4.3.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/docs/CLI.md +33 -0
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-5VSPJEZ7.mjs → chunk-BS5LSKZ3.mjs} +190 -6
- package/packages/cli/dist/chunk-BS5LSKZ3.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +2122 -1533
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +1863 -1496
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-VQT7QLGV.mjs → src-YFMPWEIS.mjs} +3 -3
- package/packages/cli/dist/{src-VQT7QLGV.mjs.map → src-YFMPWEIS.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +196 -3
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +93 -1
- package/packages/core/dist/advanced.d.ts +93 -1
- package/packages/core/dist/advanced.mjs +189 -4
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/cli/dist/chunk-5VSPJEZ7.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8a21bce: Add share-safe offline trace bundles (`agent-inspect bundle`) with automatic verify-safe, default share redaction profile, session/since targeting, and folder output for PR-ready evidence.
|
|
8
|
+
|
|
3
9
|
## 4.2.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/docs/CLI.md
CHANGED
|
@@ -37,6 +37,7 @@ Core commands:
|
|
|
37
37
|
- `scan` — best-effort local safety scan for trace capture risks
|
|
38
38
|
- `verify-safe` — best-effort local trace safety verification
|
|
39
39
|
- `artifacts` — create safe local CI trace artifact bundles and optional step summaries
|
|
40
|
+
- `bundle` — create share-safe offline trace bundles (redacted copies + verify-safe)
|
|
40
41
|
- `ci-summary` — summarize local reporter artifact manifests for CI
|
|
41
42
|
- `diff` — compare two manual traces (local, read-only)
|
|
42
43
|
- `timeline` — chronological view of one run (local JSONL)
|
|
@@ -860,6 +861,38 @@ agent-inspect index sqlite clean [--dir <path>] [--json]
|
|
|
860
861
|
|
|
861
862
|
If `@agent-inspect/index-sqlite` is not installed, these subcommands print a short install hint and exit non-zero.
|
|
862
863
|
|
|
864
|
+
### 6.24 `bundle`
|
|
865
|
+
|
|
866
|
+
Create a **share-safe offline trace bundle** as a local folder (v4.3+). Bundles are derived copies: original traces are read-only and never mutated. Automatic `verify-safe` runs before write; the command fails on `UNSAFE` unless `--allow-unsafe`. See [BUNDLES.md](BUNDLES.md).
|
|
867
|
+
|
|
868
|
+
```bash
|
|
869
|
+
agent-inspect bundle <run-id> [options]
|
|
870
|
+
agent-inspect bundle --session <session-id> [options]
|
|
871
|
+
agent-inspect bundle --since <duration> [options]
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Options:
|
|
875
|
+
|
|
876
|
+
- `--dir <path>` — trace directory
|
|
877
|
+
- `--session <session-id>` — bundle all runs in a session
|
|
878
|
+
- `--since <duration>` — bundle runs with activity since a window (e.g. `24h`, `7d`)
|
|
879
|
+
- `--profile <profile>` — `local`, `share` (default), or `strict` redaction for exported copies
|
|
880
|
+
- `--out <path>` — output directory; `.zip` suffix is stripped (folder-first)
|
|
881
|
+
- `--allow-unsafe` — write bundle even when verify-safe reports UNSAFE
|
|
882
|
+
- `--json` — print deterministic JSON manifest
|
|
883
|
+
|
|
884
|
+
Output includes `trace.html`, `trace.jsonl`, `summary.md`, `metadata.json`, `check-results.json`, `redaction-report.json`, and `assets/runs/` mirrors for multi-run bundles.
|
|
885
|
+
|
|
886
|
+
Examples:
|
|
887
|
+
|
|
888
|
+
```bash
|
|
889
|
+
npx agent-inspect bundle minimal-success --dir fixtures/traces --out ./bundle-out
|
|
890
|
+
npx agent-inspect bundle --session sess-handoff-001 --dir ./.agent-inspect --profile strict
|
|
891
|
+
npx agent-inspect bundle --since 24h --dir ./.agent-inspect --json
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
Recipe: [shareable-bundle-basic](../examples/recipes/shareable-bundle-basic/README.md).
|
|
895
|
+
|
|
863
896
|
## 7. Optional TUI behavior
|
|
864
897
|
|
|
865
898
|
`view --tui` delegates to `@agent-inspect/tui` and requires an interactive terminal. If the package is not installed, the CLI prints a short install hint.
|
package/package.json
CHANGED
|
@@ -3268,12 +3268,12 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3268
3268
|
handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
|
|
3269
3269
|
);
|
|
3270
3270
|
const ordered = [...runs].sort(compareRuns);
|
|
3271
|
-
const
|
|
3271
|
+
const path6 = [];
|
|
3272
3272
|
const visited = /* @__PURE__ */ new Set();
|
|
3273
3273
|
const pushRun = (run, confidence, source) => {
|
|
3274
3274
|
if (visited.has(run.runId)) return;
|
|
3275
3275
|
visited.add(run.runId);
|
|
3276
|
-
|
|
3276
|
+
path6.push({
|
|
3277
3277
|
runId: run.runId,
|
|
3278
3278
|
name: run.name,
|
|
3279
3279
|
startedAt: run.startedAt,
|
|
@@ -3298,7 +3298,7 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3298
3298
|
const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
|
|
3299
3299
|
pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
|
|
3300
3300
|
}
|
|
3301
|
-
return
|
|
3301
|
+
return path6;
|
|
3302
3302
|
}
|
|
3303
3303
|
function metaRunIdMatches(run, token, runById) {
|
|
3304
3304
|
const meta = extractSessionWorkflowMetadata(run.metadata);
|
|
@@ -3482,6 +3482,190 @@ async function isAgentInspectTrace(filePath) {
|
|
|
3482
3482
|
}
|
|
3483
3483
|
}
|
|
3484
3484
|
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3485
|
+
// packages/core/src/bundle/resolve.ts
|
|
3486
|
+
function parseSinceCutoff(since) {
|
|
3487
|
+
const trimmed = since.trim();
|
|
3488
|
+
if (trimmed === "") {
|
|
3489
|
+
throw new Error("--since requires a non-empty duration (e.g. 24h, 7d).");
|
|
3490
|
+
}
|
|
3491
|
+
return Date.now() - parseDuration(trimmed);
|
|
3492
|
+
}
|
|
3493
|
+
function runActivityMs(run) {
|
|
3494
|
+
if (run.startedAt !== void 0 && Number.isFinite(run.startedAt)) return run.startedAt;
|
|
3495
|
+
if (run.endedAt !== void 0 && Number.isFinite(run.endedAt)) return run.endedAt;
|
|
3496
|
+
return void 0;
|
|
3497
|
+
}
|
|
3498
|
+
function runsInSinceWindow(runs, since) {
|
|
3499
|
+
const cutoff = parseSinceCutoff(since);
|
|
3500
|
+
const ids = [];
|
|
3501
|
+
for (const run of runs) {
|
|
3502
|
+
const activity = runActivityMs(run);
|
|
3503
|
+
if (activity !== void 0 && activity >= cutoff) {
|
|
3504
|
+
ids.push(run.runId);
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
return ids.sort((a, b) => a.localeCompare(b));
|
|
3508
|
+
}
|
|
3509
|
+
function findSession(index, sessionId) {
|
|
3510
|
+
return index.sessions.find((session) => session.sessionId === sessionId);
|
|
3511
|
+
}
|
|
3512
|
+
function resolveBundleRunIds(index, runs, options) {
|
|
3513
|
+
const runId = options.runId?.trim();
|
|
3514
|
+
const sessionId = options.sessionId?.trim();
|
|
3515
|
+
const since = options.since?.trim();
|
|
3516
|
+
const modes = [runId ? 1 : 0, sessionId ? 1 : 0, since ? 1 : 0].reduce((a, b) => a + b, 0);
|
|
3517
|
+
if (modes === 0) {
|
|
3518
|
+
throw new Error(
|
|
3519
|
+
"bundle requires a run id, --session <sessionId>, or --since <duration>."
|
|
3520
|
+
);
|
|
3521
|
+
}
|
|
3522
|
+
if (modes > 1) {
|
|
3523
|
+
throw new Error(
|
|
3524
|
+
"bundle accepts only one target: a run id, --session, or --since (not combined)."
|
|
3525
|
+
);
|
|
3526
|
+
}
|
|
3527
|
+
if (runId) {
|
|
3528
|
+
const known = runs.some((run) => run.runId === runId);
|
|
3529
|
+
if (!known) {
|
|
3530
|
+
throw new Error(`Run "${runId}" was not found in the trace directory.`);
|
|
3531
|
+
}
|
|
3532
|
+
return { runIds: [runId] };
|
|
3533
|
+
}
|
|
3534
|
+
if (sessionId) {
|
|
3535
|
+
const session = findSession(index, sessionId);
|
|
3536
|
+
if (!session) {
|
|
3537
|
+
throw new Error(`Session "${sessionId}" was not found.`);
|
|
3538
|
+
}
|
|
3539
|
+
if (session.runIds.length === 0) {
|
|
3540
|
+
throw new Error(`Session "${sessionId}" has no runs to bundle.`);
|
|
3541
|
+
}
|
|
3542
|
+
return {
|
|
3543
|
+
runIds: [...session.runIds].sort((a, b) => a.localeCompare(b)),
|
|
3544
|
+
sessionId
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
const runIds = runsInSinceWindow(runs, since);
|
|
3548
|
+
if (runIds.length === 0) {
|
|
3549
|
+
throw new Error(`No runs matched --since ${since}.`);
|
|
3550
|
+
}
|
|
3551
|
+
return { runIds, since };
|
|
3552
|
+
}
|
|
3553
|
+
|
|
3554
|
+
// packages/core/src/bundle/safety-status.ts
|
|
3555
|
+
function aggregateBundleSafeStatus(statuses) {
|
|
3556
|
+
if (statuses.length === 0) return "UNKNOWN";
|
|
3557
|
+
if (statuses.some((status) => status === "UNSAFE")) return "UNSAFE";
|
|
3558
|
+
if (statuses.some((status) => status === "UNKNOWN")) return "UNKNOWN";
|
|
3559
|
+
if (statuses.some((status) => status === "SAFE WITH WARNINGS")) return "SAFE WITH WARNINGS";
|
|
3560
|
+
return "SAFE";
|
|
3561
|
+
}
|
|
3562
|
+
function toMetadataSafeStatus(status) {
|
|
3563
|
+
if (status === "SAFE WITH WARNINGS") return "SAFE_WITH_WARNINGS";
|
|
3564
|
+
return status;
|
|
3565
|
+
}
|
|
3566
|
+
function bundleFailsOnSafety(status, allowUnsafe) {
|
|
3567
|
+
if (allowUnsafe) return false;
|
|
3568
|
+
return status === "UNSAFE" || status === "UNKNOWN";
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3571
|
+
// packages/core/src/bundle/manifest.ts
|
|
3572
|
+
var BUNDLE_NOTE = "Generated locally by AgentInspect. Bundles are derived copies for review \u2014 not compliance or security certification. Review before sharing.";
|
|
3573
|
+
var PLACEHOLDER_NOTE = "No eval or performance artifacts were requested for this bundle.";
|
|
3574
|
+
function buildBundleMetadata(parts) {
|
|
3575
|
+
const aggregate = aggregateBundleSafeStatus(
|
|
3576
|
+
parts.checks.runs.map((run) => run.status)
|
|
3577
|
+
);
|
|
3578
|
+
return {
|
|
3579
|
+
createdAt: parts.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
3580
|
+
agentInspectVersion: parts.agentInspectVersion,
|
|
3581
|
+
redactionProfile: parts.profile,
|
|
3582
|
+
sourceTraceCount: parts.resolve.runIds.length,
|
|
3583
|
+
runIds: [...parts.resolve.runIds],
|
|
3584
|
+
safeStatus: toMetadataSafeStatus(aggregate),
|
|
3585
|
+
files: [...parts.files].sort((a, b) => a.localeCompare(b)),
|
|
3586
|
+
note: BUNDLE_NOTE,
|
|
3587
|
+
...parts.resolve.sessionId !== void 0 ? { sessionId: parts.resolve.sessionId } : {},
|
|
3588
|
+
...parts.resolve.since !== void 0 ? { since: parts.resolve.since } : {}
|
|
3589
|
+
};
|
|
3590
|
+
}
|
|
3591
|
+
function buildPlaceholderArtifact() {
|
|
3592
|
+
return {
|
|
3593
|
+
status: "not_requested",
|
|
3594
|
+
note: PLACEHOLDER_NOTE
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
|
|
3598
|
+
// packages/core/src/bundle/summary.ts
|
|
3599
|
+
function markdownTable(rows) {
|
|
3600
|
+
const lines = ["| Field | Value |", "| --- | --- |"];
|
|
3601
|
+
for (const [key, value] of rows) {
|
|
3602
|
+
lines.push(`| ${key} | ${value ?? "unknown"} |`);
|
|
3603
|
+
}
|
|
3604
|
+
return lines.join("\n");
|
|
3605
|
+
}
|
|
3606
|
+
function buildBundleSummaryMarkdown(parts) {
|
|
3607
|
+
const { metadata, checks, redaction } = parts;
|
|
3608
|
+
const lines = [
|
|
3609
|
+
"# AgentInspect trace bundle",
|
|
3610
|
+
"",
|
|
3611
|
+
metadata.note,
|
|
3612
|
+
"",
|
|
3613
|
+
"## Overview",
|
|
3614
|
+
"",
|
|
3615
|
+
markdownTable([
|
|
3616
|
+
["Created", metadata.createdAt],
|
|
3617
|
+
["AgentInspect", metadata.agentInspectVersion],
|
|
3618
|
+
["Redaction profile", metadata.redactionProfile],
|
|
3619
|
+
["Safe status", metadata.safeStatus],
|
|
3620
|
+
["Source traces", metadata.sourceTraceCount],
|
|
3621
|
+
["Runs", metadata.runIds.join(", ")],
|
|
3622
|
+
...metadata.sessionId ? [["Session", metadata.sessionId]] : [],
|
|
3623
|
+
...metadata.since ? [["Since", metadata.since]] : []
|
|
3624
|
+
]),
|
|
3625
|
+
"",
|
|
3626
|
+
"## Safety checks",
|
|
3627
|
+
"",
|
|
3628
|
+
`Aggregate: **${checks.aggregateStatus}**`,
|
|
3629
|
+
""
|
|
3630
|
+
];
|
|
3631
|
+
for (const run of checks.runs) {
|
|
3632
|
+
lines.push(
|
|
3633
|
+
`- \`${run.runId}\`: ${run.status} (${run.findings} finding(s), ${run.errors} error(s), ${run.warnings} warning(s))`
|
|
3634
|
+
);
|
|
3635
|
+
}
|
|
3636
|
+
lines.push("", "## Redaction", "", `Total findings: ${redaction.totalFindings}`, "");
|
|
3637
|
+
for (const run of redaction.runs) {
|
|
3638
|
+
const detectors = run.detectors.length > 0 ? run.detectors.join(", ") : "none";
|
|
3639
|
+
lines.push(`- \`${run.runId}\`: ${run.findings} finding(s); detectors: ${detectors}`);
|
|
3640
|
+
}
|
|
3641
|
+
lines.push(
|
|
3642
|
+
"",
|
|
3643
|
+
"## Files",
|
|
3644
|
+
"",
|
|
3645
|
+
...metadata.files.map((file) => `- \`${file}\``),
|
|
3646
|
+
"",
|
|
3647
|
+
"_Review every generated artifact before sharing outside your team._",
|
|
3648
|
+
""
|
|
3649
|
+
);
|
|
3650
|
+
return lines.join("\n");
|
|
3651
|
+
}
|
|
3652
|
+
function normalizeBundleOutputPath(out) {
|
|
3653
|
+
const trimmed = out.trim();
|
|
3654
|
+
if (trimmed === "") {
|
|
3655
|
+
throw new Error("--out requires a non-empty path.");
|
|
3656
|
+
}
|
|
3657
|
+
const resolved = path.resolve(trimmed);
|
|
3658
|
+
if (resolved.toLowerCase().endsWith(".zip")) {
|
|
3659
|
+
return resolved.slice(0, -4);
|
|
3660
|
+
}
|
|
3661
|
+
return resolved;
|
|
3662
|
+
}
|
|
3663
|
+
function defaultBundleOutputPath(runIds) {
|
|
3664
|
+
const label = runIds.length === 1 ? runIds[0] : `multi-${runIds.length}`;
|
|
3665
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3666
|
+
return path.resolve(`agent-inspect-bundle-${label}-${stamp}`);
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
export { Redactor, TraceDirectory, __commonJS, __require, __toESM, aggregateBundleSafeStatus, aggregateSessionCheckResults, applyProfileMetadataCaps, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildLocalExplanation, buildPlaceholderArtifact, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, bundleFailsOnSafety, defaultBundleOutputPath, enrichSessionRunRecord, extractCorrelationMetadata, extractMetadata, filterMetasBySessionScope, filterTraces, formatDuration2 as formatDuration, formatTimestamp, getIndent, getTraceFilePath, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadTraceMetadataList, nanoid, normalizeBundleOutputPath, parseDuration, parseDurationFilter, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderErrorLine, renderRunWhat, renderStepLine, renderTimeline, renderTraceStats, resolveBundleRunIds, resolveRedactionProfile, resolveTraceDir, searchTraces, source_default, truncateName, truncateStringForProfile, validateEvent };
|
|
3670
|
+
//# sourceMappingURL=chunk-BS5LSKZ3.mjs.map
|
|
3671
|
+
//# sourceMappingURL=chunk-BS5LSKZ3.mjs.map
|