@tonyclaw/agent-inspector 3.0.46 → 3.0.48

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.
Files changed (40) hide show
  1. package/.output/backend/nitro.json +1 -1
  2. package/.output/cli.js +6791 -6006
  3. package/.output/server/_ssr/index.mjs +1 -1
  4. package/.output/server/_ssr/{router-D18yUq36.mjs → router-Cj10mv-Z.mjs} +334 -5
  5. package/.output/server/index.mjs +1 -1
  6. package/.output/ui/assets/{CompareDrawer-DAUuIJ6G.js → CompareDrawer-uRiXFOCp.js} +1 -1
  7. package/.output/ui/assets/{InspectorPet-BRBVjOWI.js → InspectorPet-j-r6xk0V.js} +1 -1
  8. package/.output/ui/assets/{ProxyViewerContainer-D7Sq0ctc.js → ProxyViewerContainer-DnUrkMJF.js} +23 -23
  9. package/.output/ui/assets/{ReplayDialog-nDLsjOhs.js → ReplayDialog-B2URyHMv.js} +1 -1
  10. package/.output/ui/assets/{RequestAnatomy-zd4BDgL0.js → RequestAnatomy-CK0M0CJO.js} +1 -1
  11. package/.output/ui/assets/{ResponseView-AdIXGcSn.js → ResponseView-CYSVA4lT.js} +1 -1
  12. package/.output/ui/assets/{StreamingChunkSequence-CesTz8He.js → StreamingChunkSequence-CHf54ZUV.js} +1 -1
  13. package/.output/ui/assets/{_sessionId-QnBomgPD.js → _sessionId-BXULpTNP.js} +1 -1
  14. package/.output/ui/assets/{_sessionId-BAfzrhSU.js → _sessionId-E4lbj5-I.js} +1 -1
  15. package/.output/ui/assets/{index-D0rtCN9V.js → index-B4ixI3kG.js} +1 -1
  16. package/.output/ui/assets/{index-BcsdxBAd.js → index-BJ-71WLq.js} +1 -1
  17. package/.output/ui/assets/{index-DHpwr08Z.js → index-CW0ab9r3.js} +2 -2
  18. package/.output/ui/assets/{index-dNuk2dsU.js → index-Ce-lO51c.js} +1 -1
  19. package/.output/ui/assets/{json-viewer-BvFHglMb.js → json-viewer-C6E8aLaV.js} +1 -1
  20. package/.output/ui/assets/{jszip.min-B5Z7gNZB.js → jszip.min-DjWdTBbp.js} +1 -1
  21. package/.output/ui/index.html +1 -1
  22. package/README.md +53 -0
  23. package/package.json +17 -3
  24. package/src/backend/routes/api/-instances.ts +7 -109
  25. package/src/cli/instance.ts +21 -0
  26. package/src/cli/instanceApi.ts +213 -0
  27. package/src/cli/instanceArgs.ts +16 -0
  28. package/src/cli/instanceControl.ts +10 -0
  29. package/src/cli/instanceModel.ts +9 -0
  30. package/src/cli/rustBackendPackage.ts +458 -0
  31. package/src/cli.ts +171 -14
  32. package/src/components/ProxyViewer.tsx +4 -13
  33. package/src/components/proxy-viewer/proxyViewerLogic.ts +9 -0
  34. package/src/lib/backendImplementation.ts +16 -0
  35. package/src/lib/instanceContract.ts +3 -0
  36. package/src/lib/managedInstance.ts +9 -1
  37. package/src/mcp/instanceHandlers.ts +1 -0
  38. package/src/proxy/identityProxy.ts +148 -0
  39. package/src/proxy/sessionArchive.ts +0 -8
  40. package/src/proxy/sqliteLogIndex.ts +0 -40
@@ -1162,7 +1162,7 @@ var getBaseManifest = getProdBaseManifest;
1162
1162
  var createEarlyHintsForRequest = createEarlyHintsCollector;
1163
1163
  async function loadEntries() {
1164
1164
  const [routerEntry, startEntry, pluginAdapters] = await Promise.all([
1165
- import("./router-D18yUq36.mjs"),
1165
+ import("./router-Cj10mv-Z.mjs"),
1166
1166
  import("./start-COQu_AgD.mjs"),
1167
1167
  import("./empty-plugin-adapters-BFgPZ6_d.mjs")
1168
1168
  ]);
@@ -18,6 +18,7 @@ import assert from "node:assert/strict";
18
18
  import { M as McpServer, W as WebStandardStreamableHTTPServerTransport, R as ResourceTemplate } from "../_libs/modelcontextprotocol__server.mjs";
19
19
  import { J as JSZip } from "../_libs/jszip.mjs";
20
20
  import { homedir } from "node:os";
21
+ import { createRequire } from "node:module";
21
22
  import { o as object, c as string, f as array, n as number, r as record, g as _enum, u as union, j as unknown, a as literal, e as boolean, k as discriminatedUnion, _ as _null, b as lazy, q as url, d as datetime } from "../_libs/zod.mjs";
22
23
  import "../_libs/react.mjs";
23
24
  import "../_libs/tanstack__router-core.mjs";
@@ -13588,11 +13589,17 @@ const Route$K = createFileRoute("/api/models")({
13588
13589
  }
13589
13590
  });
13590
13591
  const name = "@tonyclaw/agent-inspector";
13591
- const version = "3.0.46";
13592
+ const version = "3.0.48";
13592
13593
  const packageJson = {
13593
13594
  name,
13594
13595
  version
13595
13596
  };
13597
+ const BackendImplementationSchema = _enum(["typescript", "rust"]);
13598
+ function parseBackendImplementation(value) {
13599
+ if (value === void 0) return "typescript";
13600
+ const parsed = BackendImplementationSchema.safeParse(value.trim().toLowerCase());
13601
+ return parsed.success ? parsed.data : null;
13602
+ }
13596
13603
  const INSTANCE_API_SCHEMA_VERSION = 1;
13597
13604
  function isCanonicalPublicBasePath(value) {
13598
13605
  const normalized = normalizePublicBasePath(value);
@@ -13626,6 +13633,7 @@ const InstanceStatusOutputSchema = object({
13626
13633
  upstreamPort: number().int().min(1).max(65535),
13627
13634
  basePath: string().refine(isCanonicalPublicBasePath, "Invalid public Base Path"),
13628
13635
  captureMode: _enum(["simple", "full"]),
13636
+ backend: BackendImplementationSchema.default("typescript"),
13629
13637
  uiEnabled: boolean(),
13630
13638
  dataDir: string().min(1),
13631
13639
  supervisorPid: number().int().positive().nullable(),
@@ -13675,6 +13683,7 @@ const InstanceStartRequestSchema = object({
13675
13683
  "Host must be a hostname or IP address without protocol, path, or whitespace"
13676
13684
  ).optional(),
13677
13685
  captureMode: _enum(["simple", "full"]).optional(),
13686
+ backend: BackendImplementationSchema.optional(),
13678
13687
  uiEnabled: boolean().optional(),
13679
13688
  dataDir: string().trim().min(1).max(32767).optional()
13680
13689
  }).strict();
@@ -13894,6 +13903,7 @@ function lifecycleRequest(input) {
13894
13903
  basePath: input.basePath,
13895
13904
  host: input.host,
13896
13905
  captureMode: input.captureMode,
13906
+ backend: input.backend,
13897
13907
  uiEnabled: input.uiEnabled,
13898
13908
  dataDir: input.dataDir
13899
13909
  };
@@ -17521,6 +17531,7 @@ const MANAGED_INSTANCE_TOKEN_HEADER = "x-agent-inspector-instance-token";
17521
17531
  const MANAGED_INSTANCE_SHUTDOWN_MESSAGE_TYPE = "agent-inspector:managed-shutdown";
17522
17532
  const AGENT_INSPECTOR_CLI_ENTRY_ENV = "AGENT_INSPECTOR_CLI_ENTRY";
17523
17533
  const MANAGED_INSTANCE_ENV = {
17534
+ backend: "AGENT_INSPECTOR_INSTANCE_BACKEND",
17524
17535
  name: "AGENT_INSPECTOR_INSTANCE_NAME",
17525
17536
  instanceId: "AGENT_INSPECTOR_INSTANCE_ID",
17526
17537
  launchId: "AGENT_INSPECTOR_INSTANCE_LAUNCH_ID",
@@ -17537,6 +17548,7 @@ function isRecord$1(value) {
17537
17548
  }
17538
17549
  function readManagedInstanceLaunch(env = process.env) {
17539
17550
  const values = [
17551
+ env[MANAGED_INSTANCE_ENV.backend],
17540
17552
  env[MANAGED_INSTANCE_ENV.name],
17541
17553
  env[MANAGED_INSTANCE_ENV.instanceId],
17542
17554
  env[MANAGED_INSTANCE_ENV.launchId],
@@ -17548,12 +17560,15 @@ function readManagedInstanceLaunch(env = process.env) {
17548
17560
  return { kind: "unmanaged" };
17549
17561
  }
17550
17562
  const name2 = nonEmpty(env[MANAGED_INSTANCE_ENV.name]);
17563
+ const backend = parseBackendImplementation(
17564
+ nonEmpty(env[MANAGED_INSTANCE_ENV.backend]) ?? void 0
17565
+ );
17551
17566
  const instanceId = nonEmpty(env[MANAGED_INSTANCE_ENV.instanceId]);
17552
17567
  const launchId = nonEmpty(env[MANAGED_INSTANCE_ENV.launchId]);
17553
17568
  const controlToken = nonEmpty(env[MANAGED_INSTANCE_ENV.controlToken]);
17554
17569
  const startedAt = nonEmpty(env[MANAGED_INSTANCE_ENV.startedAt]);
17555
17570
  const upstreamPort = Number(env[MANAGED_INSTANCE_ENV.upstreamPort]);
17556
- if (name2 === null || instanceId === null || launchId === null || controlToken === null || controlToken.length < 32 || startedAt === null || !Number.isFinite(Date.parse(startedAt)) || !Number.isInteger(upstreamPort) || upstreamPort < 1 || upstreamPort > 65535) {
17571
+ if (name2 === null || backend === null || instanceId === null || launchId === null || controlToken === null || controlToken.length < 32 || startedAt === null || !Number.isFinite(Date.parse(startedAt)) || !Number.isInteger(upstreamPort) || upstreamPort < 1 || upstreamPort > 65535) {
17557
17572
  return {
17558
17573
  kind: "invalid",
17559
17574
  message: "Managed instance launch environment is incomplete or invalid."
@@ -17561,7 +17576,7 @@ function readManagedInstanceLaunch(env = process.env) {
17561
17576
  }
17562
17577
  return {
17563
17578
  kind: "managed",
17564
- launch: { name: name2, instanceId, launchId, controlToken, startedAt, upstreamPort }
17579
+ launch: { backend, name: name2, instanceId, launchId, controlToken, startedAt, upstreamPort }
17565
17580
  };
17566
17581
  }
17567
17582
  function parseManagedInstanceShutdownMessage(value) {
@@ -17658,17 +17673,19 @@ function isRecord(value) {
17658
17673
  function parseIdentity(value) {
17659
17674
  if (!isRecord(value)) return null;
17660
17675
  const schemaVersion = value["schemaVersion"];
17676
+ const backend = BackendImplementationSchema.safeParse(value["backend"] ?? "typescript");
17661
17677
  const instanceId = value["instanceId"];
17662
17678
  const launchId = value["launchId"];
17663
17679
  const supervisorPid = value["supervisorPid"];
17664
17680
  const startedAt = value["startedAt"];
17665
17681
  const publicPort = value["publicPort"];
17666
17682
  const upstreamPort = value["upstreamPort"];
17667
- if (schemaVersion !== 1 || typeof instanceId !== "string" || instanceId.length === 0 || typeof launchId !== "string" || launchId.length === 0 || typeof supervisorPid !== "number" || !Number.isInteger(supervisorPid) || supervisorPid < 1 || typeof startedAt !== "string" || !Number.isFinite(Date.parse(startedAt)) || typeof publicPort !== "number" || !Number.isInteger(publicPort) || publicPort < 1 || publicPort > 65535 || typeof upstreamPort !== "number" || !Number.isInteger(upstreamPort) || upstreamPort < 1 || upstreamPort > 65535) {
17683
+ if (schemaVersion !== 1 || !backend.success || typeof instanceId !== "string" || instanceId.length === 0 || typeof launchId !== "string" || launchId.length === 0 || typeof supervisorPid !== "number" || !Number.isInteger(supervisorPid) || supervisorPid < 1 || typeof startedAt !== "string" || !Number.isFinite(Date.parse(startedAt)) || typeof publicPort !== "number" || !Number.isInteger(publicPort) || publicPort < 1 || publicPort > 65535 || typeof upstreamPort !== "number" || !Number.isInteger(upstreamPort) || upstreamPort < 1 || upstreamPort > 65535) {
17668
17684
  return null;
17669
17685
  }
17670
17686
  return {
17671
17687
  schemaVersion: 1,
17688
+ backend: backend.data,
17672
17689
  instanceId,
17673
17690
  launchId,
17674
17691
  supervisorPid,
@@ -17714,7 +17731,7 @@ async function probeInstanceControl(expected, fetchImpl = fetch, timeoutMs = DEF
17714
17731
  if (!response.ok) return { kind: "identity-mismatch" };
17715
17732
  const identity = parseIdentity(await responseJson(response));
17716
17733
  if (identity === null) return { kind: "invalid-response" };
17717
- if (identity.instanceId !== expected.instanceId || identity.launchId !== expected.launchId || identity.publicPort !== expected.publicPort) {
17734
+ if (identity.instanceId !== expected.instanceId || identity.launchId !== expected.launchId || identity.backend !== (expected.backend ?? "typescript") || identity.publicPort !== expected.publicPort) {
17718
17735
  return { kind: "identity-mismatch" };
17719
17736
  }
17720
17737
  return { kind: "running", identity };
@@ -17811,6 +17828,7 @@ const InstanceRecordSchema = object({
17811
17828
  upstreamPort: PortSchema,
17812
17829
  basePath: NormalizedBasePathSchema,
17813
17830
  captureMode: CaptureModeSchema,
17831
+ backend: BackendImplementationSchema.default("typescript"),
17814
17832
  uiEnabled: boolean().default(true),
17815
17833
  dataDir: string().min(1).refine((path2) => isAbsolute(path2)),
17816
17834
  launch: InstanceLaunchSchema
@@ -17848,6 +17866,7 @@ function createInstanceRecord(input, factory = {}) {
17848
17866
  upstreamPort: input.upstreamPort,
17849
17867
  basePath: basePath.value,
17850
17868
  captureMode: input.captureMode,
17869
+ backend: input.backend ?? "typescript",
17851
17870
  uiEnabled: input.uiEnabled ?? true,
17852
17871
  dataDir: input.dataDir,
17853
17872
  launch: createLaunch(factory, now)
@@ -18335,6 +18354,304 @@ async function planInstancePorts(options) {
18335
18354
  `No available named-instance port pair was found from ${String(DEFAULT_NAMED_INSTANCE_PUBLIC_PORT)} through 65535.`
18336
18355
  );
18337
18356
  }
18357
+ const RUST_BACKEND_IDENTITY_FLAG = "--agent-inspector-package-identity";
18358
+ const RUST_BACKEND_CLI_PROTOCOL = "agent-inspector-cli-backend-v1";
18359
+ const RUST_BACKEND_IDENTITY_TIMEOUT_MS = 2e3;
18360
+ const RustBackendIdentitySchema = object({
18361
+ schemaVersion: literal(1),
18362
+ name: literal("agent-inspector-backend"),
18363
+ packageVersion: string().min(1),
18364
+ target: string().min(1),
18365
+ binary: string().min(1),
18366
+ cliProtocol: literal(RUST_BACKEND_CLI_PROTOCOL),
18367
+ productionReady: literal(true),
18368
+ capabilities: object({
18369
+ nodeProtectedIngress: literal(true),
18370
+ basePath: literal(true),
18371
+ namedInstances: literal(true),
18372
+ gracefulShutdown: literal(true)
18373
+ }).strict()
18374
+ }).strict();
18375
+ const RustBackendPackageJsonSchema = object({
18376
+ name: string().min(1),
18377
+ version: string().min(1),
18378
+ os: array(string()).min(1),
18379
+ cpu: array(string()).min(1),
18380
+ libc: array(string()).optional(),
18381
+ agentInspectorRustBackend: object({
18382
+ schemaVersion: literal(1),
18383
+ target: string().min(1),
18384
+ binary: string().min(1),
18385
+ manifest: string().min(1),
18386
+ identityFlag: literal(RUST_BACKEND_IDENTITY_FLAG),
18387
+ cliProtocol: literal(RUST_BACKEND_CLI_PROTOCOL)
18388
+ }).strict()
18389
+ }).passthrough();
18390
+ const RustBackendBinaryManifestSchema = object({
18391
+ schemaVersion: literal(1),
18392
+ packageName: string().min(1),
18393
+ packageVersion: string().min(1),
18394
+ target: string().min(1),
18395
+ binary: string().min(1),
18396
+ sha256: string().regex(/^[a-f0-9]{64}$/u),
18397
+ identity: RustBackendIdentitySchema
18398
+ }).strict();
18399
+ function packageFailure(code, message) {
18400
+ return { kind: "error", error: { code, message } };
18401
+ }
18402
+ function targetFailure(message) {
18403
+ return { kind: "error", error: { code: "unsupported_platform", message } };
18404
+ }
18405
+ function detectLinuxLibc() {
18406
+ if (process.platform !== "linux") return "not-applicable";
18407
+ const report = process.report.getReport();
18408
+ const header = objectProperty(report, "header");
18409
+ const glibcVersion = objectProperty(header, "glibcVersionRuntime");
18410
+ if (typeof glibcVersion === "string" && glibcVersion.length > 0) {
18411
+ return "glibc";
18412
+ }
18413
+ const sharedObjects = objectProperty(report, "sharedObjects");
18414
+ return Array.isArray(sharedObjects) && sharedObjects.some((path2) => typeof path2 === "string" && path2.toLowerCase().includes("musl")) ? "musl" : "unknown";
18415
+ }
18416
+ function objectProperty(value, name2) {
18417
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
18418
+ return Object.getOwnPropertyDescriptor(value, name2)?.value;
18419
+ }
18420
+ function resolveRustBackendTarget(platform = process.platform, arch = process.arch, libc = platform === "linux" ? detectLinuxLibc() : "not-applicable") {
18421
+ switch (platform) {
18422
+ case "win32":
18423
+ return arch === "x64" ? {
18424
+ kind: "success",
18425
+ value: {
18426
+ packageName: "@tonyclaw/agent-inspector-backend-win32-x64-msvc",
18427
+ target: "x86_64-pc-windows-msvc",
18428
+ binary: "bin/agent-inspector-backend.exe",
18429
+ os: "win32",
18430
+ cpu: "x64",
18431
+ libc: null
18432
+ }
18433
+ } : targetFailure(`Rust backend packages do not support Windows ${arch}.`);
18434
+ case "linux":
18435
+ if (arch !== "x64")
18436
+ return targetFailure(`Rust backend packages do not support Linux ${arch}.`);
18437
+ if (libc !== "glibc") {
18438
+ return targetFailure(
18439
+ `The Linux Rust backend package requires glibc; detected ${libc}. No binary was started.`
18440
+ );
18441
+ }
18442
+ return {
18443
+ kind: "success",
18444
+ value: {
18445
+ packageName: "@tonyclaw/agent-inspector-backend-linux-x64-gnu",
18446
+ target: "x86_64-unknown-linux-gnu",
18447
+ binary: "bin/agent-inspector-backend",
18448
+ os: "linux",
18449
+ cpu: "x64",
18450
+ libc: "glibc"
18451
+ }
18452
+ };
18453
+ case "darwin":
18454
+ return arch === "arm64" ? {
18455
+ kind: "success",
18456
+ value: {
18457
+ packageName: "@tonyclaw/agent-inspector-backend-darwin-arm64",
18458
+ target: "aarch64-apple-darwin",
18459
+ binary: "bin/agent-inspector-backend",
18460
+ os: "darwin",
18461
+ cpu: "arm64",
18462
+ libc: null
18463
+ }
18464
+ } : targetFailure(`Rust backend packages do not support macOS ${arch}.`);
18465
+ default:
18466
+ return targetFailure(`Rust backend packages do not support ${platform} ${arch}.`);
18467
+ }
18468
+ }
18469
+ function readJson(path2) {
18470
+ try {
18471
+ const value = JSON.parse(readFileSync(path2, "utf8"));
18472
+ return { kind: "success", value };
18473
+ } catch {
18474
+ return { kind: "error" };
18475
+ }
18476
+ }
18477
+ function isConfinedPath(root, candidate) {
18478
+ const child = relative(root, candidate);
18479
+ return child.length > 0 && !child.startsWith("..") && !isAbsolute(child);
18480
+ }
18481
+ function identitiesMatch(left, right) {
18482
+ return left.schemaVersion === right.schemaVersion && left.name === right.name && left.packageVersion === right.packageVersion && left.target === right.target && left.binary === right.binary && left.cliProtocol === right.cliProtocol && left.productionReady === right.productionReady && left.capabilities.nodeProtectedIngress === right.capabilities.nodeProtectedIngress && left.capabilities.basePath === right.capabilities.basePath && left.capabilities.namedInstances === right.capabilities.namedInstances && left.capabilities.gracefulShutdown === right.capabilities.gracefulShutdown;
18483
+ }
18484
+ function probeBinaryIdentity(binaryPath, identityFlag) {
18485
+ const result = spawnSync(binaryPath, [identityFlag], {
18486
+ encoding: "utf8",
18487
+ windowsHide: true,
18488
+ timeout: RUST_BACKEND_IDENTITY_TIMEOUT_MS,
18489
+ maxBuffer: 64 * 1024
18490
+ });
18491
+ if (result.error !== void 0) {
18492
+ return { kind: "error", message: result.error.message };
18493
+ }
18494
+ if (result.status !== 0) {
18495
+ return {
18496
+ kind: "error",
18497
+ message: `identity command exited with status ${String(result.status)}`
18498
+ };
18499
+ }
18500
+ let raw;
18501
+ try {
18502
+ raw = JSON.parse(result.stdout);
18503
+ } catch {
18504
+ return { kind: "error", message: "identity command did not return JSON" };
18505
+ }
18506
+ const parsed = RustBackendIdentitySchema.safeParse(raw);
18507
+ return parsed.success ? { kind: "success", value: parsed.data } : { kind: "error", message: "identity command returned an unsupported contract" };
18508
+ }
18509
+ const packageRequire = createRequire(import.meta.url);
18510
+ function defaultResolvePackageJson(specifier) {
18511
+ try {
18512
+ return packageRequire.resolve(specifier);
18513
+ } catch {
18514
+ const suffix = "/package.json";
18515
+ const packageName = specifier.endsWith(suffix) ? specifier.slice(0, -suffix.length) : "";
18516
+ const directoryName = packageName.split("/").at(-1);
18517
+ if (directoryName !== void 0 && directoryName.length > 0) {
18518
+ const localPackageJson = resolve(
18519
+ dirname(fileURLToPath(import.meta.url)),
18520
+ "../packages",
18521
+ directoryName,
18522
+ "package.json"
18523
+ );
18524
+ if (existsSync(localPackageJson)) return localPackageJson;
18525
+ }
18526
+ return packageRequire.resolve(specifier);
18527
+ }
18528
+ }
18529
+ function resolveRustBackendPackage(options) {
18530
+ const target = resolveRustBackendTarget(options.platform, options.arch, options.libc);
18531
+ if (target.kind === "error") return { kind: "error", error: target.error };
18532
+ const packageJsonSpecifier = `${target.value.packageName}/package.json`;
18533
+ let packageJsonPath2;
18534
+ try {
18535
+ packageJsonPath2 = (options.resolvePackageJson ?? defaultResolvePackageJson)(
18536
+ packageJsonSpecifier
18537
+ );
18538
+ } catch {
18539
+ return packageFailure(
18540
+ "package_missing",
18541
+ `Rust backend ${target.value.target} was requested, but optional package ${target.value.packageName}@${options.rootVersion} is not installed. Reinstall without omitting optional dependencies; no TypeScript fallback was used.`
18542
+ );
18543
+ }
18544
+ const rawPackage = readJson(packageJsonPath2);
18545
+ if (rawPackage.kind === "error") {
18546
+ return packageFailure("package_invalid", `Cannot read ${packageJsonSpecifier}.`);
18547
+ }
18548
+ const packageJson2 = RustBackendPackageJsonSchema.safeParse(rawPackage.value);
18549
+ if (!packageJson2.success) {
18550
+ return packageFailure(
18551
+ "package_invalid",
18552
+ `Package ${target.value.packageName} does not contain the Rust backend package contract.`
18553
+ );
18554
+ }
18555
+ if (packageJson2.data.name !== target.value.packageName || packageJson2.data.version !== options.rootVersion) {
18556
+ return packageFailure(
18557
+ "version_mismatch",
18558
+ `Rust backend package must exactly match @tonyclaw/agent-inspector@${options.rootVersion}; found ${packageJson2.data.name}@${packageJson2.data.version}.`
18559
+ );
18560
+ }
18561
+ const metadata = packageJson2.data.agentInspectorRustBackend;
18562
+ const expectedLibc = target.value.libc === null ? void 0 : [target.value.libc];
18563
+ if (metadata.target !== target.value.target || metadata.binary !== target.value.binary || metadata.manifest !== "binary-manifest.json" || packageJson2.data.os.length !== 1 || packageJson2.data.os[0] !== target.value.os || packageJson2.data.cpu.length !== 1 || packageJson2.data.cpu[0] !== target.value.cpu || JSON.stringify(packageJson2.data.libc) !== JSON.stringify(expectedLibc)) {
18564
+ return packageFailure(
18565
+ "target_mismatch",
18566
+ `Package ${target.value.packageName} does not match target ${target.value.target}.`
18567
+ );
18568
+ }
18569
+ const packageRoot = dirname(packageJsonPath2);
18570
+ const manifestPath = resolve(packageRoot, metadata.manifest);
18571
+ const binaryPath = resolve(packageRoot, metadata.binary);
18572
+ if (!isConfinedPath(packageRoot, manifestPath) || !isConfinedPath(packageRoot, binaryPath)) {
18573
+ return packageFailure(
18574
+ "package_invalid",
18575
+ `Package ${target.value.packageName} contains an unsafe artifact path.`
18576
+ );
18577
+ }
18578
+ const rawManifest = readJson(manifestPath);
18579
+ if (rawManifest.kind === "error") {
18580
+ return packageFailure(
18581
+ "manifest_invalid",
18582
+ `Rust backend package ${target.value.packageName} is incomplete: binary-manifest.json is missing or invalid.`
18583
+ );
18584
+ }
18585
+ const manifest = RustBackendBinaryManifestSchema.safeParse(rawManifest.value);
18586
+ if (!manifest.success) {
18587
+ return packageFailure(
18588
+ "manifest_invalid",
18589
+ `Rust backend package ${target.value.packageName} has an invalid target manifest.`
18590
+ );
18591
+ }
18592
+ if (manifest.data.packageName !== target.value.packageName || manifest.data.packageVersion !== options.rootVersion || manifest.data.identity.packageVersion !== options.rootVersion) {
18593
+ return packageFailure(
18594
+ "version_mismatch",
18595
+ `Rust backend manifest must exactly match @tonyclaw/agent-inspector@${options.rootVersion}.`
18596
+ );
18597
+ }
18598
+ if (manifest.data.target !== target.value.target || manifest.data.binary !== target.value.binary || manifest.data.identity.target !== target.value.target || manifest.data.identity.binary !== target.value.binary) {
18599
+ return packageFailure(
18600
+ "target_mismatch",
18601
+ `Rust backend manifest identity does not match target ${target.value.target}.`
18602
+ );
18603
+ }
18604
+ let binaryBytes;
18605
+ try {
18606
+ const stats = statSync(binaryPath);
18607
+ if (!stats.isFile()) {
18608
+ return packageFailure("binary_invalid", `Rust backend artifact is not a regular file.`);
18609
+ }
18610
+ if (target.value.os !== "win32" && (stats.mode & 73) === 0) {
18611
+ return packageFailure("binary_invalid", `Rust backend artifact is not executable.`);
18612
+ }
18613
+ binaryBytes = readFileSync(binaryPath);
18614
+ } catch {
18615
+ return packageFailure(
18616
+ "binary_missing",
18617
+ `Rust backend binary ${target.value.binary} is missing from ${target.value.packageName}.`
18618
+ );
18619
+ }
18620
+ const sha256 = createHash("sha256").update(binaryBytes).digest("hex");
18621
+ if (sha256 !== manifest.data.sha256) {
18622
+ return packageFailure(
18623
+ "hash_mismatch",
18624
+ `Rust backend binary integrity check failed for ${target.value.packageName}; no binary was started.`
18625
+ );
18626
+ }
18627
+ const probed = (options.identityProbe ?? probeBinaryIdentity)(binaryPath, metadata.identityFlag);
18628
+ if (probed.kind === "error") {
18629
+ return packageFailure(
18630
+ "identity_failed",
18631
+ `Rust backend binary did not pass the production identity gate: ${probed.message}. No TypeScript fallback was used.`
18632
+ );
18633
+ }
18634
+ if (!identitiesMatch(probed.value, manifest.data.identity)) {
18635
+ return packageFailure(
18636
+ "identity_mismatch",
18637
+ `Rust backend binary identity differs from its signed package manifest; no binary was started.`
18638
+ );
18639
+ }
18640
+ return {
18641
+ kind: "success",
18642
+ value: {
18643
+ command: binaryPath,
18644
+ args: [],
18645
+ packageName: target.value.packageName,
18646
+ packageVersion: options.rootVersion,
18647
+ target: target.value.target,
18648
+ sha256
18649
+ }
18650
+ };
18651
+ }
18652
+ function resolvePreferredBackendImplementation(options) {
18653
+ return resolveRustBackendPackage(options).kind === "success" ? "rust" : "typescript";
18654
+ }
18338
18655
  const DEFAULT_INSTANCE_HOST = "127.0.0.1";
18339
18656
  const DEFAULT_INSTANCE_CAPTURE_MODE = "simple";
18340
18657
  const INSTANCE_READY_TIMEOUT_MS = 15e3;
@@ -18388,6 +18705,7 @@ function statusOutput(record2, live, checkedAt = /* @__PURE__ */ new Date()) {
18388
18705
  upstreamPort: record2.upstreamPort,
18389
18706
  basePath: displayBasePath(record2.basePath),
18390
18707
  captureMode: record2.captureMode,
18708
+ backend: record2.backend,
18391
18709
  uiEnabled: record2.uiEnabled,
18392
18710
  dataDir: record2.dataDir,
18393
18711
  supervisorPid: live.supervisorPid,
@@ -18438,6 +18756,7 @@ function connectionOutput(instance) {
18438
18756
  }
18439
18757
  function expectedIdentity(record2) {
18440
18758
  return {
18759
+ backend: record2.backend,
18441
18760
  instanceId: record2.instanceId,
18442
18761
  launchId: record2.launch.launchId,
18443
18762
  controlToken: record2.launch.controlToken,
@@ -18485,6 +18804,8 @@ function buildInstanceLaunchArgs(record2, open2) {
18485
18804
  const args = [
18486
18805
  "--background",
18487
18806
  "--no-open",
18807
+ "--backend",
18808
+ record2.backend,
18488
18809
  "--port",
18489
18810
  String(record2.publicPort),
18490
18811
  "--host",
@@ -18505,6 +18826,7 @@ async function defaultLaunch(record2, open2, cliEntry) {
18505
18826
  [AGENT_INSPECTOR_CLI_ENTRY_ENV]: cliEntry,
18506
18827
  AGENT_INSPECTOR_DATA_DIR: record2.dataDir,
18507
18828
  [AGENT_INSPECTOR_BASE_PATH_ENV]: displayBasePath(record2.basePath),
18829
+ [MANAGED_INSTANCE_ENV.backend]: record2.backend,
18508
18830
  [MANAGED_INSTANCE_ENV.name]: record2.name,
18509
18831
  [MANAGED_INSTANCE_ENV.instanceId]: record2.instanceId,
18510
18832
  [MANAGED_INSTANCE_ENV.launchId]: record2.launch.launchId,
@@ -18622,6 +18944,7 @@ function readRequiredRecord(root, name2) {
18622
18944
  }
18623
18945
  function overridesDiffer(record2, action) {
18624
18946
  const { overrides } = action;
18947
+ if (overrides.backend !== null && overrides.backend !== record2.backend) return true;
18625
18948
  if (overrides.port !== null && overrides.port !== record2.publicPort) return true;
18626
18949
  if (overrides.basePath !== null && overrides.basePath !== record2.basePath) return true;
18627
18950
  if (overrides.host !== null && overrides.host !== record2.host) return true;
@@ -18644,6 +18967,7 @@ function updatedRecord(record2, action, pair, dataDir2) {
18644
18967
  upstreamPort: pair.upstreamPort,
18645
18968
  basePath: action.overrides.basePath ?? record2.basePath,
18646
18969
  captureMode: action.overrides.captureMode ?? record2.captureMode,
18970
+ backend: action.overrides.backend ?? record2.backend,
18647
18971
  uiEnabled: action.overrides.uiEnabled ?? record2.uiEnabled,
18648
18972
  dataDir: dataDir2
18649
18973
  };
@@ -18672,6 +18996,9 @@ function validateInstanceDataDirectory(rawPath, records, excludeName) {
18672
18996
  }
18673
18997
  return success(assigned.value.path);
18674
18998
  }
18999
+ function resolveDefaultInstanceBackend(deps) {
19000
+ return deps.resolveDefaultBackend?.() ?? resolvePreferredBackendImplementation({ rootVersion: packageJson.version });
19001
+ }
18675
19002
  async function createNewRecord(root, action, deps) {
18676
19003
  const recordsResult = listInstanceRecords(root);
18677
19004
  if (recordsResult.kind === "error") return fromRegistry(recordsResult);
@@ -18695,6 +19022,7 @@ async function createNewRecord(root, action, deps) {
18695
19022
  upstreamPort: pairResult.value.upstreamPort,
18696
19023
  basePath: action.overrides.basePath ?? getConfiguredBasePath(process.env),
18697
19024
  captureMode: action.overrides.captureMode ?? DEFAULT_INSTANCE_CAPTURE_MODE,
19025
+ backend: action.overrides.backend ?? resolveDefaultInstanceBackend(deps),
18698
19026
  uiEnabled: action.overrides.uiEnabled ?? true,
18699
19027
  dataDir: dataDirResult.value
18700
19028
  });
@@ -18867,6 +19195,7 @@ async function listAction(root, deps) {
18867
19195
  }
18868
19196
  function requestActionOverrides(input) {
18869
19197
  return {
19198
+ backend: input.backend ?? null,
18870
19199
  port: input.port ?? null,
18871
19200
  basePath: input.basePath === void 0 ? null : normalizePublicBasePath(input.basePath),
18872
19201
  host: input.host ?? null,
@@ -20,7 +20,7 @@ const assets = {
20
20
  "/assets/index-D4LX-sw-.js": {
21
21
  "type": "text/javascript; charset=utf-8",
22
22
  "etag": '"4ca46-80Birfu694YvXXxcAJa6ekM4QWE"',
23
- "mtime": "2026-07-16T13:07:01.787Z",
23
+ "mtime": "2026-07-17T06:44:30.821Z",
24
24
  "size": 313926,
25
25
  "path": "../backend-public/assets/index-D4LX-sw-.js"
26
26
  }
@@ -1 +1 @@
1
- import{r as p,j as t,x as f,C as z,E as ne}from"./index-DHpwr08Z.js";import{c as re,g as A,r as D,a as R,X as ae,B as oe,R as ie,C as de,M as V,b as J,d as B,e as F,f as le,h as ce,L as ue}from"./ProxyViewerContainer-D7Sq0ctc.js";const me=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],xe=re("equal",me),fe="";function y(e){if(e.length===0)return fe;let s="";for(let n=0;n<e.length;n++){const a=e[n];a!==void 0&&(typeof a=="number"?s+=`[${a}]`:n===0?s+=a:s+=`.${a}`)}return s}function pe(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function $(e){if(typeof e=="string")try{return C(JSON.parse(e))}catch{return{kind:"primitive",value:e}}return C(e)}function C(e){if(e===null)return{kind:"primitive",value:null};if(typeof e=="string")return{kind:"primitive",value:e};if(typeof e=="number")return{kind:"primitive",value:e};if(typeof e=="boolean")return{kind:"primitive",value:e};if(Array.isArray(e))return{kind:"array",value:e.map(s=>C(s))};if(pe(e)){const s={};for(const n of Object.keys(e).sort())s[n]=C(e[n]);return{kind:"object",value:s}}return{kind:"primitive",value:null}}function he(e,s){const n=[];return S([],e,s,n),n}function S(e,s,n,a){const c=y(e);if(q(s,n)){a.push({kind:"equal",path:c,value:s});return}if(s.kind!==n.kind){a.push({kind:"changed",path:c,left:s,right:n});return}if(s.kind==="primitive"&&n.kind==="primitive"){a.push({kind:"changed",path:c,left:s,right:n});return}if(s.kind==="object"&&n.kind==="object"){const l=Object.keys(s.value),r=Object.keys(n.value),o=new Set(r);for(const d of l){const x=s.value[d];if(x!==void 0)if(!o.has(d))a.push({kind:"removed",path:y([...e,d]),value:x});else{const h=n.value[d];if(h===void 0)continue;S([...e,d],x,h,a)}}for(const d of r){if(l.includes(d))continue;const x=n.value[d];x!==void 0&&a.push({kind:"added",path:y([...e,d]),value:x})}return}if(s.kind==="array"&&n.kind==="array"){const l=Math.min(s.value.length,n.value.length);for(let r=0;r<l;r++){const o=s.value[r],d=n.value[r];o===void 0||d===void 0||S([...e,r],o,d,a)}for(let r=l;r<n.value.length;r++){const o=n.value[r];o!==void 0&&a.push({kind:"added",path:y([...e,r]),value:o})}for(let r=l;r<s.value.length;r++){const o=s.value[r];o!==void 0&&a.push({kind:"removed",path:y([...e,r]),value:o})}}}function q(e,s){if(e.kind!==s.kind)return!1;if(e.kind==="primitive"&&s.kind==="primitive")return e.value===s.value;if(e.kind==="array"&&s.kind==="array"){if(e.value.length!==s.value.length)return!1;for(let n=0;n<e.value.length;n++){const a=e.value[n],c=s.value[n];if(a===void 0||c===void 0||!q(a,c))return!1}return!0}if(e.kind==="object"&&s.kind==="object"){const n=Object.keys(e.value),a=Object.keys(s.value);if(n.length!==a.length)return!1;for(const c of n){const l=e.value[c],r=s.value[c];if(l===void 0||r===void 0||!q(l,r))return!1}return!0}return!1}function v(e,s=80){let n;switch(e.kind){case"primitive":n=e.value===null?"null":JSON.stringify(e.value);break;case"array":n=`[… ${e.value.length} items]`;break;case"object":n=`{… ${Object.keys(e.value).length} keys}`;break}return n.length>s&&(n=`${n.slice(0,s-1)}…`),n}const be="flex flex-col gap-3 border-b border-border px-3 py-3 sm:flex-row sm:items-start sm:gap-4 sm:px-4",ge="grid min-w-0 grid-cols-1 gap-x-2 gap-y-0.5 px-3 py-2 text-xs md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]";function N(e,s=2){return JSON.stringify(T(e),null,s)}function T(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(T);case"object":{const s={};for(const[n,a]of Object.entries(e.value))s[n]=T(a);return s}}}function w({text:e,defaultExpandDepth:s}){return t.jsx(p.Suspense,{fallback:t.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading JSON..."}),children:t.jsx(ue,{text:e,defaultExpandDepth:s})})}function _(e){if(e==="")return"";for(let s=e.length-1;s>=0;s--){const n=e[s];if(n==="."||n==="[")return e.substring(0,s)}return""}function K(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function ve(e){const s=[];let n=0;for(;n<e.length;){const a=e[n];if(a!==void 0&&K(a)){const c=_(a.path);let l=n+1;for(;l<e.length;){const r=e[l];if(r===void 0||!K(r)||_(r.path)!==c)break;l++}if(l-n>1){const r=[];for(let o=n;o<l;o++){const d=e[o];d!==void 0&&d.kind==="equal"&&r.push(d)}s.push({kind:"equal-run",ops:r}),n=l;continue}}a!==void 0&&s.push({kind:"single",op:a}),n++}return s}const H={added:{icon:J,accent:"text-status-success",bg:"bg-status-success/5 hover:bg-status-success/10",border:"border-l-status-success",label:"ADDED"},removed:{icon:V,accent:"text-status-danger",bg:"bg-status-danger/5 hover:bg-status-danger/10",border:"border-l-status-danger",label:"REMOVED"},changed:{icon:B,accent:"text-status-watch",bg:"bg-status-watch/5 hover:bg-status-watch/10",border:"border-l-status-watch",label:"CHANGED"},equal:{icon:xe,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function ke({ops:e,expanded:s,onToggle:n}){const a=e[0],c=e[e.length-1];if(a===void 0||c===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const l=a.path,r=c.path,o=e.length===1?l:`${l} … ${r}`,d=a.value.kind==="array"?`${e.length} equal arrays`:a.value.kind==="object"?`${e.length} equal objects`:"equal",x=H.equal;return t.jsxs("div",{className:f("border-l-4 rounded-sm",x.border,x.bg),children:[t.jsxs("button",{type:"button",onClick:n,className:"w-full text-left flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground cursor-pointer",children:[t.jsx(F,{className:f("size-3 transition-transform shrink-0",s&&"rotate-90")}),t.jsx(x.icon,{className:f("size-3 shrink-0",x.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${l} … ${r}`,children:o}),t.jsx("span",{className:f("text-[10px] uppercase tracking-wider shrink-0",x.accent),children:x.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",d,")"]})]}),s&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(h=>t.jsxs("div",{className:"border border-border/50 rounded p-2 bg-muted/20",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:h.path}),t.jsx(w,{text:N(h.value),defaultExpandDepth:0})]},h.path))})]})}function je({op:e,idx:s,copiedPath:n,onCopyPath:a,expanded:c,onToggle:l}){const r=H[e.kind],o=r.icon,d=e.kind==="added"||e.kind==="removed"?e.value.kind==="object"||e.value.kind==="array":e.kind==="changed"?e.left.kind==="object"||e.left.kind==="array"||e.right.kind==="object"||e.right.kind==="array":!1,x=e.kind==="changed"?[{text:v(e.left,400),tone:"text-status-danger line-through"},{text:v(e.right,400),tone:"text-status-success"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-status-danger line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-status-success"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],h=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":s,"data-diff-kind":e.kind,className:f("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",r.border,r.bg),children:[t.jsxs("button",{type:"button",onClick:l,disabled:!d,className:f("w-full flex items-center gap-2 text-xs text-left rounded-sm",d?"cursor-pointer":"cursor-default"),"aria-expanded":d?c:void 0,"aria-label":d?c?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[d?t.jsx(F,{className:f("size-3 shrink-0 transition-transform",r.accent,c&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(o,{className:f("size-3.5 shrink-0",r.accent),strokeWidth:2.5}),t.jsx("span",{className:"font-mono truncate flex-1 min-w-0",title:e.path||"(root)",children:e.path===""?"(root)":e.path}),t.jsx("span",{className:f("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",r.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:r.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),a(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),a(e.path))},className:f("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",h?"text-status-success":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":h?"Copied":"Copy",title:h?"Copied!":"Copy",children:h?t.jsx(le,{className:"size-3"}):t.jsx(ce,{className:"size-3"})})]}),x.map((b,E)=>t.jsx("div",{className:f("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},E)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:c&&d?"2000px":"0"},"aria-hidden":!c,children:c&&d&&e.kind!=="equal"?t.jsx(ye,{op:e}):null})]})}function ye({op:e}){if(e.kind==="added"||e.kind==="removed")return t.jsx("div",{className:"pl-5 mt-2 border border-border/50 rounded p-2 bg-muted/20",children:t.jsx(w,{text:N(e.value),defaultExpandDepth:0})});const s=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!s&&!n?t.jsx("div",{className:"pl-5 mt-2 text-xs text-muted-foreground/70 italic",children:"Primitive values are shown inline above."}):t.jsxs("div",{className:"pl-5 mt-2 grid grid-cols-1 md:grid-cols-2 gap-2",children:[t.jsxs("div",{className:"rounded border border-status-danger/30 bg-status-danger/5 p-2",children:[t.jsx("div",{className:"mb-1 text-[10px] uppercase tracking-wider text-status-danger",children:"Old"}),t.jsx(w,{text:N(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"rounded border border-status-success/30 bg-status-success/5 p-2",children:[t.jsx("div",{className:"mb-1 text-[10px] uppercase tracking-wider text-status-success",children:"New"}),t.jsx(w,{text:N(e.right),defaultExpandDepth:0})]})]})}function Ne({counts:e,onJumpTo:s}){const n=e.added+e.removed+e.changed;return t.jsxs("div",{className:"px-4 py-2 border-b border-border bg-muted/20 flex items-center gap-2 text-xs flex-wrap",children:[t.jsxs("span",{className:"text-muted-foreground font-medium",children:[n," ",n===1?"change":"changes"]}),t.jsxs("button",{type:"button",onClick:()=>s("removed"),disabled:e.removed===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-status-danger/40 bg-status-danger/10 text-status-danger hover:bg-status-danger/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.removed>0?"Jump to first removed":"No removals",children:[t.jsx(V,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>s("added"),disabled:e.added===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-status-success/40 bg-status-success/10 text-status-success hover:bg-status-success/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(J,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>s("changed"),disabled:e.changed===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-status-watch/40 bg-status-watch/10 text-status-watch hover:bg-status-watch/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(B,{className:"size-3"}),e.changed," changed"]})]})}function we({mode:e,onChange:s}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>s("unified"),"aria-pressed":e==="unified",className:f("flex items-center gap-1 px-2 py-1 text-xs transition-colors cursor-pointer",e==="unified"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Unified view (single column, emphasized diffs)",children:[t.jsx(ie,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>s("split"),"aria-pressed":e==="split",className:f("flex items-center gap-1 px-2 py-1 text-xs transition-colors border-l border-border cursor-pointer",e==="split"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Split view (path | left | right)",children:[t.jsx(de,{className:"size-3"}),"Split"]})]})}function M({log:e,side:s,displayNumber:n}){const a=R(e);return t.jsxs("div",{className:"flex-1 min-w-0 space-y-1 text-xs",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(oe,{variant:"outline",className:f("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",s==="left"?"border-status-danger/40 text-status-danger":"border-status-success/40 text-status-success"),children:s==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-status-info",title:`Log ID ${String(e.id)}`,children:["#",n]}),e.model!==null&&t.jsx("span",{className:"min-w-0 truncate font-mono leading-snug text-muted-foreground",children:e.model})]}),t.jsxs("div",{className:"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 font-mono text-muted-foreground",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-status-success",children:["KV Cache +",z(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-status-accent",children:["KV Cache ~",z(e.cacheReadInputTokens)]}),t.jsx("span",{className:"truncate",title:e.timestamp,children:e.timestamp})]}),t.jsxs("div",{className:"text-muted-foreground/70 font-mono truncate",title:a,children:["session: ",a]})]})}function Se({left:e,right:s,leftDisplayNumber:n,rightDisplayNumber:a,onClose:c}){const l=p.useRef(null),r=p.useRef(null),o=p.useRef(null),d=p.useMemo(()=>{const i=A(D(e)).analyzeRequest(e.rawRequestBody),u=A(D(s)).analyzeRequest(s.rawRequestBody),m=$(i.comparisonValue),g=$(u.comparisonValue);return he(m,g)},[e.apiFormat,e.path,e.rawRequestBody,s.apiFormat,s.path,s.rawRequestBody]),x=p.useMemo(()=>ve(d),[d]),h=p.useMemo(()=>{let i=0,u=0,m=0;for(const g of x)if(g.kind==="single")switch(g.op.kind){case"added":i++;break;case"removed":u++;break;case"changed":m++;break}return{added:i,removed:u,changed:m}},[x]),[b,E]=p.useState(new Set),U=i=>{E(u=>{const m=new Set(u);return m.has(i)?m.delete(i):m.add(i),m})},[G,I]=p.useState(new Set),Q=i=>{I(u=>{const m=new Set(u);return m.has(i)?m.delete(i):m.add(i),m})};p.useEffect(()=>{I(new Set)},[e.id,s.id]);const[O,W]=p.useState("unified"),P=p.useRef(null),[X,L]=p.useState(null),j=p.useRef(null),Y=i=>{ne(i).then(u=>{u&&(L(i),j.current!==null&&clearTimeout(j.current),j.current=setTimeout(()=>L(null),1500))})};p.useEffect(()=>()=>{j.current!==null&&clearTimeout(j.current)},[]);const Z=i=>{const u=x.findIndex(k=>k.kind==="single"&&k.op.kind===i);if(u===-1)return;const m=P.current;if(m===null)return;const g=m.querySelector(`[data-diff-idx="${u}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};p.useEffect(()=>{o.current=document.activeElement instanceof HTMLElement?document.activeElement:null,r.current?.focus();const i=m=>{m.key==="Escape"&&c()};document.addEventListener("keydown",i);const u=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",i),document.body.style.overflow=u,o.current?.focus()}},[c]);const ee=i=>{if(i.stopPropagation(),i.key!=="Tab")return;const u=l.current;if(u===null)return;const m=Array.from(u.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])')),g=m[0],k=m[m.length-1];if(!(g===void 0||k===void 0)){if(i.shiftKey&&document.activeElement===g){i.preventDefault(),k.focus();return}!i.shiftKey&&document.activeElement===k&&(i.preventDefault(),g.focus())}},te=R(e)===R(s),se=d.length===1&&d[0]?.kind==="equal";return t.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",role:"dialog","aria-modal":"true","aria-label":"Compare two log requests",children:[t.jsx("button",{type:"button",onClick:c,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{ref:l,className:f("relative overflow-x-hidden bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:i=>i.stopPropagation(),onKeyDown:ee,children:[t.jsxs("div",{className:be,children:[t.jsxs("div",{className:"grid min-w-0 flex-1 grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4",children:[t.jsx(M,{log:e,side:"left",displayNumber:n}),t.jsx(M,{log:s,side:"right",displayNumber:a})]}),t.jsxs("div",{className:"flex w-full shrink-0 items-center justify-between gap-2 sm:w-auto sm:justify-start",children:[t.jsx(we,{mode:O,onChange:W}),t.jsx("button",{ref:r,type:"button",onClick:c,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(ae,{className:"size-4"})})]})]}),!te&&t.jsx("div",{className:"border-b border-border bg-warning/10 px-4 py-1.5 text-xs text-foreground",children:"Heads up: the two selected logs are from different sessions."}),se?t.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto flex items-center justify-center text-muted-foreground text-sm",children:"The two Request payloads are identical."}):t.jsxs(t.Fragment,{children:[t.jsx(Ne,{counts:h,onJumpTo:Z}),t.jsx("div",{ref:P,className:"flex-1 min-h-0 overflow-y-auto",children:O==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:x.map((i,u)=>{if(i.kind==="equal-run")return t.jsx(ke,{ops:i.ops,expanded:b.has(u),onToggle:()=>U(u)},`r${u}`);const m=i.op;return t.jsx(je,{op:m,idx:u,copiedPath:X,onCopyPath:Y,expanded:G.has(u),onToggle:()=>Q(u)},`o${u}`)})}):t.jsx(Ce,{grouped:x,left:e,right:s,leftDisplayNumber:n,rightDisplayNumber:a})})]})]})]})}function Ce({grouped:e,left:s,right:n,leftDisplayNumber:a,rightDisplayNumber:c}){return t.jsxs("div",{"data-compare-layout":"responsive-split",className:ge,children:[t.jsxs("div",{className:"col-span-1 mb-2 grid grid-cols-1 gap-x-2 gap-y-1 border-b border-border pb-2 text-[10px] uppercase tracking-wider text-muted-foreground md:col-span-3 md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{title:`Log ID ${String(s.id)}`,children:["Left (Log #",a,")"]}),t.jsxs("span",{title:`Log ID ${String(n.id)}`,children:["Right (Log #",c,")"]})]}),e.map((l,r)=>{if(l.kind==="equal-run")return t.jsxs("div",{className:"col-span-1 px-2 py-1 text-xs text-muted-foreground/60 md:col-span-3",children:[l.ops.length," equal siblings collapsed — switch to Unified to expand"]},r);const o=l.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-1 grid min-w-0 grid-cols-1 gap-x-2 gap-y-1 px-2 py-0.5 text-muted-foreground md:col-span-3 md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]",children:[t.jsx("span",{className:"font-mono text-xs truncate",title:o.path,children:o.path}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)})]},r):o.kind==="added"?t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-success bg-status-success/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-status-success",children:["+ ",v(o.value,400)]})]},r):o.kind==="removed"?t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-danger bg-status-danger/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-status-danger line-through",children:["− ",v(o.value,400)]})]},r):t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-watch bg-status-watch/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[t.jsx("div",{className:"font-mono break-all text-status-danger line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono break-all text-status-success",children:v(o.right,400)})]})]},r)})]})}export{be as COMPARE_RESPONSIVE_HEADER_CLASS_NAME,ge as COMPARE_RESPONSIVE_SPLIT_CLASS_NAME,Se as CompareDrawer};
1
+ import{r as p,j as t,x as f,C as z,E as ne}from"./index-CW0ab9r3.js";import{c as re,g as A,r as D,a as R,X as ae,B as oe,R as ie,C as de,M as V,b as J,d as B,e as F,f as le,h as ce,L as ue}from"./ProxyViewerContainer-DnUrkMJF.js";const me=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],xe=re("equal",me),fe="";function y(e){if(e.length===0)return fe;let s="";for(let n=0;n<e.length;n++){const a=e[n];a!==void 0&&(typeof a=="number"?s+=`[${a}]`:n===0?s+=a:s+=`.${a}`)}return s}function pe(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function $(e){if(typeof e=="string")try{return C(JSON.parse(e))}catch{return{kind:"primitive",value:e}}return C(e)}function C(e){if(e===null)return{kind:"primitive",value:null};if(typeof e=="string")return{kind:"primitive",value:e};if(typeof e=="number")return{kind:"primitive",value:e};if(typeof e=="boolean")return{kind:"primitive",value:e};if(Array.isArray(e))return{kind:"array",value:e.map(s=>C(s))};if(pe(e)){const s={};for(const n of Object.keys(e).sort())s[n]=C(e[n]);return{kind:"object",value:s}}return{kind:"primitive",value:null}}function he(e,s){const n=[];return S([],e,s,n),n}function S(e,s,n,a){const c=y(e);if(q(s,n)){a.push({kind:"equal",path:c,value:s});return}if(s.kind!==n.kind){a.push({kind:"changed",path:c,left:s,right:n});return}if(s.kind==="primitive"&&n.kind==="primitive"){a.push({kind:"changed",path:c,left:s,right:n});return}if(s.kind==="object"&&n.kind==="object"){const l=Object.keys(s.value),r=Object.keys(n.value),o=new Set(r);for(const d of l){const x=s.value[d];if(x!==void 0)if(!o.has(d))a.push({kind:"removed",path:y([...e,d]),value:x});else{const h=n.value[d];if(h===void 0)continue;S([...e,d],x,h,a)}}for(const d of r){if(l.includes(d))continue;const x=n.value[d];x!==void 0&&a.push({kind:"added",path:y([...e,d]),value:x})}return}if(s.kind==="array"&&n.kind==="array"){const l=Math.min(s.value.length,n.value.length);for(let r=0;r<l;r++){const o=s.value[r],d=n.value[r];o===void 0||d===void 0||S([...e,r],o,d,a)}for(let r=l;r<n.value.length;r++){const o=n.value[r];o!==void 0&&a.push({kind:"added",path:y([...e,r]),value:o})}for(let r=l;r<s.value.length;r++){const o=s.value[r];o!==void 0&&a.push({kind:"removed",path:y([...e,r]),value:o})}}}function q(e,s){if(e.kind!==s.kind)return!1;if(e.kind==="primitive"&&s.kind==="primitive")return e.value===s.value;if(e.kind==="array"&&s.kind==="array"){if(e.value.length!==s.value.length)return!1;for(let n=0;n<e.value.length;n++){const a=e.value[n],c=s.value[n];if(a===void 0||c===void 0||!q(a,c))return!1}return!0}if(e.kind==="object"&&s.kind==="object"){const n=Object.keys(e.value),a=Object.keys(s.value);if(n.length!==a.length)return!1;for(const c of n){const l=e.value[c],r=s.value[c];if(l===void 0||r===void 0||!q(l,r))return!1}return!0}return!1}function v(e,s=80){let n;switch(e.kind){case"primitive":n=e.value===null?"null":JSON.stringify(e.value);break;case"array":n=`[… ${e.value.length} items]`;break;case"object":n=`{… ${Object.keys(e.value).length} keys}`;break}return n.length>s&&(n=`${n.slice(0,s-1)}…`),n}const be="flex flex-col gap-3 border-b border-border px-3 py-3 sm:flex-row sm:items-start sm:gap-4 sm:px-4",ge="grid min-w-0 grid-cols-1 gap-x-2 gap-y-0.5 px-3 py-2 text-xs md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]";function N(e,s=2){return JSON.stringify(T(e),null,s)}function T(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(T);case"object":{const s={};for(const[n,a]of Object.entries(e.value))s[n]=T(a);return s}}}function w({text:e,defaultExpandDepth:s}){return t.jsx(p.Suspense,{fallback:t.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading JSON..."}),children:t.jsx(ue,{text:e,defaultExpandDepth:s})})}function _(e){if(e==="")return"";for(let s=e.length-1;s>=0;s--){const n=e[s];if(n==="."||n==="[")return e.substring(0,s)}return""}function K(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function ve(e){const s=[];let n=0;for(;n<e.length;){const a=e[n];if(a!==void 0&&K(a)){const c=_(a.path);let l=n+1;for(;l<e.length;){const r=e[l];if(r===void 0||!K(r)||_(r.path)!==c)break;l++}if(l-n>1){const r=[];for(let o=n;o<l;o++){const d=e[o];d!==void 0&&d.kind==="equal"&&r.push(d)}s.push({kind:"equal-run",ops:r}),n=l;continue}}a!==void 0&&s.push({kind:"single",op:a}),n++}return s}const H={added:{icon:J,accent:"text-status-success",bg:"bg-status-success/5 hover:bg-status-success/10",border:"border-l-status-success",label:"ADDED"},removed:{icon:V,accent:"text-status-danger",bg:"bg-status-danger/5 hover:bg-status-danger/10",border:"border-l-status-danger",label:"REMOVED"},changed:{icon:B,accent:"text-status-watch",bg:"bg-status-watch/5 hover:bg-status-watch/10",border:"border-l-status-watch",label:"CHANGED"},equal:{icon:xe,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function ke({ops:e,expanded:s,onToggle:n}){const a=e[0],c=e[e.length-1];if(a===void 0||c===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const l=a.path,r=c.path,o=e.length===1?l:`${l} … ${r}`,d=a.value.kind==="array"?`${e.length} equal arrays`:a.value.kind==="object"?`${e.length} equal objects`:"equal",x=H.equal;return t.jsxs("div",{className:f("border-l-4 rounded-sm",x.border,x.bg),children:[t.jsxs("button",{type:"button",onClick:n,className:"w-full text-left flex items-center gap-2 px-3 py-1.5 text-xs text-muted-foreground cursor-pointer",children:[t.jsx(F,{className:f("size-3 transition-transform shrink-0",s&&"rotate-90")}),t.jsx(x.icon,{className:f("size-3 shrink-0",x.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${l} … ${r}`,children:o}),t.jsx("span",{className:f("text-[10px] uppercase tracking-wider shrink-0",x.accent),children:x.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",d,")"]})]}),s&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(h=>t.jsxs("div",{className:"border border-border/50 rounded p-2 bg-muted/20",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:h.path}),t.jsx(w,{text:N(h.value),defaultExpandDepth:0})]},h.path))})]})}function je({op:e,idx:s,copiedPath:n,onCopyPath:a,expanded:c,onToggle:l}){const r=H[e.kind],o=r.icon,d=e.kind==="added"||e.kind==="removed"?e.value.kind==="object"||e.value.kind==="array":e.kind==="changed"?e.left.kind==="object"||e.left.kind==="array"||e.right.kind==="object"||e.right.kind==="array":!1,x=e.kind==="changed"?[{text:v(e.left,400),tone:"text-status-danger line-through"},{text:v(e.right,400),tone:"text-status-success"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-status-danger line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-status-success"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],h=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":s,"data-diff-kind":e.kind,className:f("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",r.border,r.bg),children:[t.jsxs("button",{type:"button",onClick:l,disabled:!d,className:f("w-full flex items-center gap-2 text-xs text-left rounded-sm",d?"cursor-pointer":"cursor-default"),"aria-expanded":d?c:void 0,"aria-label":d?c?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[d?t.jsx(F,{className:f("size-3 shrink-0 transition-transform",r.accent,c&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(o,{className:f("size-3.5 shrink-0",r.accent),strokeWidth:2.5}),t.jsx("span",{className:"font-mono truncate flex-1 min-w-0",title:e.path||"(root)",children:e.path===""?"(root)":e.path}),t.jsx("span",{className:f("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",r.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:r.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),a(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),a(e.path))},className:f("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",h?"text-status-success":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":h?"Copied":"Copy",title:h?"Copied!":"Copy",children:h?t.jsx(le,{className:"size-3"}):t.jsx(ce,{className:"size-3"})})]}),x.map((b,E)=>t.jsx("div",{className:f("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},E)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:c&&d?"2000px":"0"},"aria-hidden":!c,children:c&&d&&e.kind!=="equal"?t.jsx(ye,{op:e}):null})]})}function ye({op:e}){if(e.kind==="added"||e.kind==="removed")return t.jsx("div",{className:"pl-5 mt-2 border border-border/50 rounded p-2 bg-muted/20",children:t.jsx(w,{text:N(e.value),defaultExpandDepth:0})});const s=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!s&&!n?t.jsx("div",{className:"pl-5 mt-2 text-xs text-muted-foreground/70 italic",children:"Primitive values are shown inline above."}):t.jsxs("div",{className:"pl-5 mt-2 grid grid-cols-1 md:grid-cols-2 gap-2",children:[t.jsxs("div",{className:"rounded border border-status-danger/30 bg-status-danger/5 p-2",children:[t.jsx("div",{className:"mb-1 text-[10px] uppercase tracking-wider text-status-danger",children:"Old"}),t.jsx(w,{text:N(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"rounded border border-status-success/30 bg-status-success/5 p-2",children:[t.jsx("div",{className:"mb-1 text-[10px] uppercase tracking-wider text-status-success",children:"New"}),t.jsx(w,{text:N(e.right),defaultExpandDepth:0})]})]})}function Ne({counts:e,onJumpTo:s}){const n=e.added+e.removed+e.changed;return t.jsxs("div",{className:"px-4 py-2 border-b border-border bg-muted/20 flex items-center gap-2 text-xs flex-wrap",children:[t.jsxs("span",{className:"text-muted-foreground font-medium",children:[n," ",n===1?"change":"changes"]}),t.jsxs("button",{type:"button",onClick:()=>s("removed"),disabled:e.removed===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-status-danger/40 bg-status-danger/10 text-status-danger hover:bg-status-danger/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.removed>0?"Jump to first removed":"No removals",children:[t.jsx(V,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>s("added"),disabled:e.added===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-status-success/40 bg-status-success/10 text-status-success hover:bg-status-success/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(J,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>s("changed"),disabled:e.changed===0,className:f("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-status-watch/40 bg-status-watch/10 text-status-watch hover:bg-status-watch/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(B,{className:"size-3"}),e.changed," changed"]})]})}function we({mode:e,onChange:s}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>s("unified"),"aria-pressed":e==="unified",className:f("flex items-center gap-1 px-2 py-1 text-xs transition-colors cursor-pointer",e==="unified"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Unified view (single column, emphasized diffs)",children:[t.jsx(ie,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>s("split"),"aria-pressed":e==="split",className:f("flex items-center gap-1 px-2 py-1 text-xs transition-colors border-l border-border cursor-pointer",e==="split"?"bg-muted text-foreground":"hover:bg-muted/50 text-muted-foreground"),title:"Split view (path | left | right)",children:[t.jsx(de,{className:"size-3"}),"Split"]})]})}function M({log:e,side:s,displayNumber:n}){const a=R(e);return t.jsxs("div",{className:"flex-1 min-w-0 space-y-1 text-xs",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(oe,{variant:"outline",className:f("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",s==="left"?"border-status-danger/40 text-status-danger":"border-status-success/40 text-status-success"),children:s==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-status-info",title:`Log ID ${String(e.id)}`,children:["#",n]}),e.model!==null&&t.jsx("span",{className:"min-w-0 truncate font-mono leading-snug text-muted-foreground",children:e.model})]}),t.jsxs("div",{className:"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 font-mono text-muted-foreground",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-status-success",children:["KV Cache +",z(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-status-accent",children:["KV Cache ~",z(e.cacheReadInputTokens)]}),t.jsx("span",{className:"truncate",title:e.timestamp,children:e.timestamp})]}),t.jsxs("div",{className:"text-muted-foreground/70 font-mono truncate",title:a,children:["session: ",a]})]})}function Se({left:e,right:s,leftDisplayNumber:n,rightDisplayNumber:a,onClose:c}){const l=p.useRef(null),r=p.useRef(null),o=p.useRef(null),d=p.useMemo(()=>{const i=A(D(e)).analyzeRequest(e.rawRequestBody),u=A(D(s)).analyzeRequest(s.rawRequestBody),m=$(i.comparisonValue),g=$(u.comparisonValue);return he(m,g)},[e.apiFormat,e.path,e.rawRequestBody,s.apiFormat,s.path,s.rawRequestBody]),x=p.useMemo(()=>ve(d),[d]),h=p.useMemo(()=>{let i=0,u=0,m=0;for(const g of x)if(g.kind==="single")switch(g.op.kind){case"added":i++;break;case"removed":u++;break;case"changed":m++;break}return{added:i,removed:u,changed:m}},[x]),[b,E]=p.useState(new Set),U=i=>{E(u=>{const m=new Set(u);return m.has(i)?m.delete(i):m.add(i),m})},[G,I]=p.useState(new Set),Q=i=>{I(u=>{const m=new Set(u);return m.has(i)?m.delete(i):m.add(i),m})};p.useEffect(()=>{I(new Set)},[e.id,s.id]);const[O,W]=p.useState("unified"),P=p.useRef(null),[X,L]=p.useState(null),j=p.useRef(null),Y=i=>{ne(i).then(u=>{u&&(L(i),j.current!==null&&clearTimeout(j.current),j.current=setTimeout(()=>L(null),1500))})};p.useEffect(()=>()=>{j.current!==null&&clearTimeout(j.current)},[]);const Z=i=>{const u=x.findIndex(k=>k.kind==="single"&&k.op.kind===i);if(u===-1)return;const m=P.current;if(m===null)return;const g=m.querySelector(`[data-diff-idx="${u}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};p.useEffect(()=>{o.current=document.activeElement instanceof HTMLElement?document.activeElement:null,r.current?.focus();const i=m=>{m.key==="Escape"&&c()};document.addEventListener("keydown",i);const u=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",i),document.body.style.overflow=u,o.current?.focus()}},[c]);const ee=i=>{if(i.stopPropagation(),i.key!=="Tab")return;const u=l.current;if(u===null)return;const m=Array.from(u.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])')),g=m[0],k=m[m.length-1];if(!(g===void 0||k===void 0)){if(i.shiftKey&&document.activeElement===g){i.preventDefault(),k.focus();return}!i.shiftKey&&document.activeElement===k&&(i.preventDefault(),g.focus())}},te=R(e)===R(s),se=d.length===1&&d[0]?.kind==="equal";return t.jsxs("div",{className:"fixed inset-0 z-50 flex justify-end",role:"dialog","aria-modal":"true","aria-label":"Compare two log requests",children:[t.jsx("button",{type:"button",onClick:c,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{ref:l,className:f("relative overflow-x-hidden bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:i=>i.stopPropagation(),onKeyDown:ee,children:[t.jsxs("div",{className:be,children:[t.jsxs("div",{className:"grid min-w-0 flex-1 grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4",children:[t.jsx(M,{log:e,side:"left",displayNumber:n}),t.jsx(M,{log:s,side:"right",displayNumber:a})]}),t.jsxs("div",{className:"flex w-full shrink-0 items-center justify-between gap-2 sm:w-auto sm:justify-start",children:[t.jsx(we,{mode:O,onChange:W}),t.jsx("button",{ref:r,type:"button",onClick:c,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(ae,{className:"size-4"})})]})]}),!te&&t.jsx("div",{className:"border-b border-border bg-warning/10 px-4 py-1.5 text-xs text-foreground",children:"Heads up: the two selected logs are from different sessions."}),se?t.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto flex items-center justify-center text-muted-foreground text-sm",children:"The two Request payloads are identical."}):t.jsxs(t.Fragment,{children:[t.jsx(Ne,{counts:h,onJumpTo:Z}),t.jsx("div",{ref:P,className:"flex-1 min-h-0 overflow-y-auto",children:O==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:x.map((i,u)=>{if(i.kind==="equal-run")return t.jsx(ke,{ops:i.ops,expanded:b.has(u),onToggle:()=>U(u)},`r${u}`);const m=i.op;return t.jsx(je,{op:m,idx:u,copiedPath:X,onCopyPath:Y,expanded:G.has(u),onToggle:()=>Q(u)},`o${u}`)})}):t.jsx(Ce,{grouped:x,left:e,right:s,leftDisplayNumber:n,rightDisplayNumber:a})})]})]})]})}function Ce({grouped:e,left:s,right:n,leftDisplayNumber:a,rightDisplayNumber:c}){return t.jsxs("div",{"data-compare-layout":"responsive-split",className:ge,children:[t.jsxs("div",{className:"col-span-1 mb-2 grid grid-cols-1 gap-x-2 gap-y-1 border-b border-border pb-2 text-[10px] uppercase tracking-wider text-muted-foreground md:col-span-3 md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{title:`Log ID ${String(s.id)}`,children:["Left (Log #",a,")"]}),t.jsxs("span",{title:`Log ID ${String(n.id)}`,children:["Right (Log #",c,")"]})]}),e.map((l,r)=>{if(l.kind==="equal-run")return t.jsxs("div",{className:"col-span-1 px-2 py-1 text-xs text-muted-foreground/60 md:col-span-3",children:[l.ops.length," equal siblings collapsed — switch to Unified to expand"]},r);const o=l.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-1 grid min-w-0 grid-cols-1 gap-x-2 gap-y-1 px-2 py-0.5 text-muted-foreground md:col-span-3 md:grid-cols-[200px_minmax(0,1fr)_minmax(0,1fr)]",children:[t.jsx("span",{className:"font-mono text-xs truncate",title:o.path,children:o.path}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)}),t.jsx("span",{className:"font-mono text-xs break-all opacity-60",children:v(o.value,200)})]},r):o.kind==="added"?t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-success bg-status-success/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-status-success",children:["+ ",v(o.value,400)]})]},r):o.kind==="removed"?t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-danger bg-status-danger/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-0.5",children:o.path}),t.jsxs("div",{className:"font-mono break-all text-status-danger line-through",children:["− ",v(o.value,400)]})]},r):t.jsxs("div",{className:"col-span-1 rounded border-l-2 border-l-status-watch bg-status-watch/5 px-2 py-1 text-xs md:col-span-3",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[t.jsx("div",{className:"font-mono break-all text-status-danger line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono break-all text-status-success",children:v(o.right,400)})]})]},r)})]})}export{be as COMPARE_RESPONSIVE_HEADER_CLASS_NAME,ge as COMPARE_RESPONSIVE_SPLIT_CLASS_NAME,Se as CompareDrawer};