agent-inspect 5.4.0 → 6.1.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - v6.1.0 client-hosted ingestion for @agent-inspect/studio: file-drop, GitHub artifact import, optional HTTP ingest with token validation, and manual bundle upload. All ingest channels disabled by default; self-hosted only.
8
+
9
+ ## 6.0.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Add self-hosted Studio (`@agent-inspect/studio`): optional read-only multi-project analyzer with `agent-inspect studio`, SQLite metadata cache, registry import, search/diff/reports views, optional basic auth, and self-hosting docs. Localhost by default; no maintainer cloud; no default upload.
14
+
3
15
  ## 5.4.0
4
16
 
5
17
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-inspect",
3
- "version": "5.4.0",
3
+ "version": "6.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Trace, check, and safely share TypeScript AI-agent runs locally — no account, no upload, metadata-only by default",
@@ -206,7 +206,7 @@
206
206
  },
207
207
  "scripts": {
208
208
  "clean": "pnpm -r exec -- rm -rf dist",
209
- "build": "pnpm exec tsup --config tsup.core.config.ts && pnpm exec tsup --config tsup.cli.config.ts && pnpm exec tsup --config tsup.langchain.config.ts && pnpm exec tsup --config tsup.tui.config.ts && pnpm exec tsup --config tsup.ai-sdk.config.ts && pnpm exec tsup --config tsup.vitest.config.ts && pnpm exec tsup --config tsup.jest.config.ts && pnpm exec tsup --config tsup.openai-agents.config.ts && pnpm exec tsup --config tsup.harness.config.ts && pnpm exec tsup --config tsup.redact.config.ts && pnpm exec tsup --config tsup.eval.config.ts && pnpm exec tsup --config tsup.mcp.config.ts && pnpm exec tsup --config tsup.guardrails.config.ts && pnpm exec tsup --config tsup.circuit.config.ts && pnpm exec tsup --config tsup.viewer.config.ts && pnpm exec tsup --config tsup.mcp-server.config.ts && pnpm exec tsup --config tsup.adapter-sdk.config.ts && pnpm exec tsup --config tsup.vscode.config.ts && pnpm exec tsup --config tsup.index-sqlite.config.ts",
209
+ "build": "pnpm exec tsup --config tsup.core.config.ts && pnpm exec tsup --config tsup.cli.config.ts && pnpm exec tsup --config tsup.langchain.config.ts && pnpm exec tsup --config tsup.tui.config.ts && pnpm exec tsup --config tsup.ai-sdk.config.ts && pnpm exec tsup --config tsup.vitest.config.ts && pnpm exec tsup --config tsup.jest.config.ts && pnpm exec tsup --config tsup.openai-agents.config.ts && pnpm exec tsup --config tsup.harness.config.ts && pnpm exec tsup --config tsup.redact.config.ts && pnpm exec tsup --config tsup.eval.config.ts && pnpm exec tsup --config tsup.mcp.config.ts && pnpm exec tsup --config tsup.guardrails.config.ts && pnpm exec tsup --config tsup.circuit.config.ts && pnpm exec tsup --config tsup.viewer.config.ts && pnpm exec tsup --config tsup.mcp-server.config.ts && pnpm exec tsup --config tsup.adapter-sdk.config.ts && pnpm exec tsup --config tsup.vscode.config.ts && pnpm exec tsup --config tsup.index-sqlite.config.ts && pnpm exec tsup --config tsup.studio.config.ts",
210
210
  "typecheck": "tsc --noEmit",
211
211
  "test": "vitest run",
212
212
  "test:watch": "vitest",
@@ -10729,7 +10729,7 @@ var init_src = __esm({
10729
10729
  });
10730
10730
 
10731
10731
  // package.json
10732
- var version = "5.4.0";
10732
+ var version = "6.1.0";
10733
10733
 
10734
10734
  // packages/cli/src/list.ts
10735
10735
  init_advanced();
@@ -17899,6 +17899,167 @@ async function serveCommand(options = {}) {
17899
17899
  });
17900
17900
  }
17901
17901
 
17902
+ // packages/cli/src/studio-cmd.ts
17903
+ var PACKAGE = "@agent-inspect/studio";
17904
+ function isModuleNotFound3(e) {
17905
+ return e !== null && typeof e === "object" && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "MODULE_NOT_FOUND");
17906
+ }
17907
+ async function loadStudio() {
17908
+ try {
17909
+ return await import('@agent-inspect/studio');
17910
+ } catch (e) {
17911
+ if (isModuleNotFound3(e)) {
17912
+ console.error(
17913
+ `The optional Studio analyzer is not installed. Run: npm install ${PACKAGE}`
17914
+ );
17915
+ process.exitCode = 1;
17916
+ return null;
17917
+ }
17918
+ const msg = e instanceof Error ? e.message : String(e);
17919
+ console.error(`[AgentInspect] failed to load ${PACKAGE}: ${msg}`);
17920
+ process.exitCode = 1;
17921
+ return null;
17922
+ }
17923
+ }
17924
+ function parsePort2(value) {
17925
+ if (value === void 0) return void 0;
17926
+ const parsed = Number(value);
17927
+ if (!Number.isInteger(parsed) || parsed <= 0 || parsed > 65535) {
17928
+ throw new Error("--port must be an integer between 1 and 65535.");
17929
+ }
17930
+ return parsed;
17931
+ }
17932
+ function summarizeFileDropResult(result) {
17933
+ if (result.skipped) {
17934
+ console.log(`[AgentInspect studio] file-drop skipped: ${result.reason ?? "disabled"}`);
17935
+ return;
17936
+ }
17937
+ console.log(
17938
+ `[AgentInspect studio] file-drop scanned=${result.scanned} imported=${result.imported} skipped=${result.skippedFiles}`
17939
+ );
17940
+ for (const warning of result.warnings) {
17941
+ console.warn(`[AgentInspect studio] ${warning}`);
17942
+ }
17943
+ for (const error of result.errors) {
17944
+ console.error(`[AgentInspect studio] ${error}`);
17945
+ }
17946
+ }
17947
+ function summarizeGitHubResult(result) {
17948
+ if (result.skipped) {
17949
+ console.log(`[AgentInspect studio] github import skipped: ${result.reason ?? "disabled"}`);
17950
+ return;
17951
+ }
17952
+ if (result.imported) {
17953
+ console.log(
17954
+ `[AgentInspect studio] github artifact imported to ${result.destPath ?? "(unknown)"}`
17955
+ );
17956
+ } else if (result.destPath) {
17957
+ console.log(`[AgentInspect studio] github artifact unchanged: ${result.destPath}`);
17958
+ }
17959
+ for (const warning of result.registryImportWarnings) {
17960
+ console.warn(`[AgentInspect studio] ${warning}`);
17961
+ }
17962
+ for (const error of result.errors) {
17963
+ console.error(`[AgentInspect studio] ${error}`);
17964
+ }
17965
+ }
17966
+ async function studioImportBundleCommand(options) {
17967
+ const mod = await loadStudio();
17968
+ if (!mod) return;
17969
+ const result = await mod.runStudioBundleUploadImport({
17970
+ ...options.workspace !== void 0 ? { workspacePath: options.workspace } : {},
17971
+ ...options.db !== void 0 ? { dbPath: options.db } : {},
17972
+ bundlePath: options.path,
17973
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {}
17974
+ });
17975
+ if (result.skipped) {
17976
+ console.log(`[AgentInspect studio] bundle import skipped: ${result.reason ?? "disabled"}`);
17977
+ } else if (result.imported) {
17978
+ console.log(`[AgentInspect studio] bundle imported to ${result.destPath ?? "(unknown)"}`);
17979
+ } else if (result.destPath) {
17980
+ console.log(`[AgentInspect studio] bundle unchanged: ${result.destPath}`);
17981
+ }
17982
+ for (const warning of result.registryImportWarnings) {
17983
+ console.warn(`[AgentInspect studio] ${warning}`);
17984
+ }
17985
+ for (const error of result.errors) {
17986
+ console.error(`[AgentInspect studio] ${error}`);
17987
+ }
17988
+ if (result.errors.length > 0) process.exitCode = 1;
17989
+ }
17990
+ async function studioImportGitHubCommand(options) {
17991
+ const mod = await loadStudio();
17992
+ if (!mod) return;
17993
+ const result = await mod.runStudioGitHubArtifactImport({
17994
+ ...options.workspace !== void 0 ? { workspacePath: options.workspace } : {},
17995
+ ...options.db !== void 0 ? { dbPath: options.db } : {},
17996
+ repo: options.repo,
17997
+ runId: options.runId,
17998
+ artifact: options.artifact,
17999
+ ...options.tokenEnv !== void 0 ? { tokenEnv: options.tokenEnv } : {},
18000
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {}
18001
+ });
18002
+ summarizeGitHubResult(result);
18003
+ if (result.errors.length > 0) {
18004
+ process.exitCode = 1;
18005
+ }
18006
+ }
18007
+ async function studioImportDropCommand(options = {}) {
18008
+ const mod = await loadStudio();
18009
+ if (!mod) return;
18010
+ const result = await mod.runStudioFileDropImport({
18011
+ ...options.workspace !== void 0 ? { workspacePath: options.workspace } : {},
18012
+ ...options.db !== void 0 ? { dbPath: options.db } : {},
18013
+ ...options.dir !== void 0 ? { dropDir: options.dir } : {},
18014
+ ...options.archive === true ? { archiveAfterImport: true } : {},
18015
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {}
18016
+ });
18017
+ summarizeFileDropResult(result);
18018
+ if (result.errors.length > 0) {
18019
+ process.exitCode = 1;
18020
+ }
18021
+ }
18022
+ async function studioCommand(options = {}) {
18023
+ const mod = await loadStudio();
18024
+ if (!mod) return;
18025
+ const ingest = options.ingest?.trim();
18026
+ if (ingest && ingest !== "file-drop" && ingest !== "http") {
18027
+ throw new Error(`Unsupported --ingest channel: ${ingest}. Supported: file-drop, http`);
18028
+ }
18029
+ const port = parsePort2(options.port);
18030
+ const host = options.host?.trim();
18031
+ const info = await mod.startStudioServer({
18032
+ ...host !== void 0 && host.length > 0 ? { host } : {},
18033
+ ...port !== void 0 ? { port } : {},
18034
+ ...options.workspace !== void 0 ? { workspacePath: options.workspace } : {},
18035
+ ...options.db !== void 0 ? { dbPath: options.db } : {},
18036
+ ...options.server === true ? { server: true } : {},
18037
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
18038
+ ...options.auth === "basic" ? { auth: "basic" } : {},
18039
+ ...options.passwordEnv !== void 0 ? { passwordEnv: options.passwordEnv } : {},
18040
+ ...ingest === "file-drop" ? { ingestFileDrop: true } : {},
18041
+ ...ingest === "http" ? { ingestHttp: true } : {},
18042
+ ...options.ingestTokenEnv !== void 0 ? { ingestTokenEnv: options.ingestTokenEnv } : {},
18043
+ ...options.archiveFileDrop === true ? { archiveFileDrop: true } : {}
18044
+ });
18045
+ if (ingest === "file-drop") {
18046
+ console.log(`[AgentInspect studio] file-drop ingest enabled for startup scan`);
18047
+ }
18048
+ if (ingest === "http") {
18049
+ console.log(`[AgentInspect studio] HTTP ingest enabled (token required on POST routes)`);
18050
+ }
18051
+ console.log(`AgentInspect studio (read-only): ${info.url}`);
18052
+ if (options.open === true && info.host !== "127.0.0.1" && info.host !== "localhost") {
18053
+ console.warn("Skipping browser open for non-local host binding.");
18054
+ } else if (options.open === true) {
18055
+ const openMod = await import('child_process');
18056
+ openMod.exec(`open ${info.url}`, () => {
18057
+ });
18058
+ }
18059
+ await new Promise(() => {
18060
+ });
18061
+ }
18062
+
17902
18063
  // packages/eval/src/index.ts
17903
18064
  function isTraceReadResult(value) {
17904
18065
  return value !== null && typeof value === "object" && "runs" in value && "events" in value && "format" in value;
@@ -20701,23 +20862,23 @@ async function indexCleanCommand(options = {}) {
20701
20862
 
20702
20863
  // packages/cli/src/index-sqlite-cmd.ts
20703
20864
  init_advanced();
20704
- var PACKAGE = "@agent-inspect/index-sqlite";
20705
- function isModuleNotFound3(e) {
20865
+ var PACKAGE2 = "@agent-inspect/index-sqlite";
20866
+ function isModuleNotFound4(e) {
20706
20867
  return e !== null && typeof e === "object" && "code" in e && (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "MODULE_NOT_FOUND");
20707
20868
  }
20708
20869
  async function loadIndexSqlite() {
20709
20870
  try {
20710
20871
  return await Promise.resolve().then(() => (init_src(), src_exports));
20711
20872
  } catch (e) {
20712
- if (isModuleNotFound3(e)) {
20873
+ if (isModuleNotFound4(e)) {
20713
20874
  console.error(
20714
- `The optional SQLite index is not installed. Run: npm install ${PACKAGE}`
20875
+ `The optional SQLite index is not installed. Run: npm install ${PACKAGE2}`
20715
20876
  );
20716
20877
  process.exitCode = 1;
20717
20878
  return null;
20718
20879
  }
20719
20880
  const msg = e instanceof Error ? e.message : String(e);
20720
- console.error(`[AgentInspect] failed to load ${PACKAGE}: ${msg}`);
20881
+ console.error(`[AgentInspect] failed to load ${PACKAGE2}: ${msg}`);
20721
20882
  process.exitCode = 1;
20722
20883
  return null;
20723
20884
  }
@@ -21565,6 +21726,21 @@ function createCliProgram() {
21565
21726
  program.command("viewer").description("Start localhost read-only viewer (traces, suite, or workspace) (v5.3+)").option("--dir <path>", "trace directory (trace mode)").option("--suite", "suite evidence mode").option("--workspace", "workspace mode").option("--config <path>", "suite config path (suite mode)").option("--host <host>", "bind host (default 127.0.0.1)", "127.0.0.1").option("--port <number>", "bind port (default 7337)", "7337").option("--open", "open browser locally when host is localhost").action((opts) => {
21566
21727
  runCommand(() => serveCommand(opts));
21567
21728
  });
21729
+ const studioCmd = program.command("studio").description(
21730
+ "Start self-hosted read-only Studio analyzer (requires @agent-inspect/studio) (v6.0+)"
21731
+ ).option("--workspace <path>", "studio registry manifest path").option("--db <path>", "studio database path (sqlite file or postgres URL)").option("--host <host>", "bind host (default 127.0.0.1)", "127.0.0.1").option("--port <number>", "bind port (default 7340)", "7340").option("--server", "bind for network access (0.0.0.0; requires explicit opt-in)").option("--auth <mode>", "auth mode: none or basic", "none").option("--password-env <name>", "env var for basic-auth password").option("--ingest <channel>", "enable ingest channel on startup (file-drop, http)").option("--ingest-token-env <name>", "env var for HTTP ingest token (default STUDIO_INGEST_TOKEN)").option("--archive-file-drop", "archive file-drop sources after successful import").option("--open", "open browser locally when host is localhost").action((opts) => {
21732
+ runCommand(() => studioCommand(opts));
21733
+ });
21734
+ const studioImportCmd = studioCmd.command("import").description("Import external evidence into Studio (v6.1+)");
21735
+ studioImportCmd.command("drop").description("Import allowlisted files from a file-drop directory").option("--workspace <path>", "studio registry manifest path").option("--db <path>", "studio database path (sqlite file or postgres URL)").option("--dir <path>", "file-drop directory (defaults to registry import.fileDropDir)").option("--archive", "move imported files into .imported/ under the drop dir").action((opts) => {
21736
+ runCommand(() => studioImportDropCommand(opts));
21737
+ });
21738
+ studioImportCmd.command("github").description("Download a GitHub Actions artifact into the studio import dirs").requiredOption("--repo <owner/name>", "GitHub repository").requiredOption("--run-id <id>", "workflow run id").requiredOption("--artifact <name>", "artifact name").option("--workspace <path>", "studio registry manifest path").option("--db <path>", "studio database path (sqlite file or postgres URL)").option("--token-env <name>", "env var for GitHub token (default GITHUB_TOKEN)").action((opts) => {
21739
+ runCommand(() => studioImportGitHubCommand(opts));
21740
+ });
21741
+ studioImportCmd.command("bundle").description("Import a local share-safe bundle directory into Studio").requiredOption("--path <dir>", "bundle directory path").option("--workspace <path>", "studio registry manifest path").option("--db <path>", "studio database path (sqlite file or postgres URL)").action((opts) => {
21742
+ runCommand(() => studioImportBundleCommand(opts));
21743
+ });
21568
21744
  program.command("eval").description("Run deterministic local evals against a trace").argument("<trace-path-or-run-id>", "trace file, directory, stdin -, or run id").option("--dir <path>", "trace directory for run-id lookup").addOption(
21569
21745
  new commander.Option("--format <format>", "trace input format").choices([
21570
21746
  "agent-inspect-jsonl",