@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.
- package/.output/backend/nitro.json +1 -1
- package/.output/cli.js +6791 -6006
- package/.output/server/_ssr/index.mjs +1 -1
- package/.output/server/_ssr/{router-D18yUq36.mjs → router-Cj10mv-Z.mjs} +334 -5
- package/.output/server/index.mjs +1 -1
- package/.output/ui/assets/{CompareDrawer-DAUuIJ6G.js → CompareDrawer-uRiXFOCp.js} +1 -1
- package/.output/ui/assets/{InspectorPet-BRBVjOWI.js → InspectorPet-j-r6xk0V.js} +1 -1
- package/.output/ui/assets/{ProxyViewerContainer-D7Sq0ctc.js → ProxyViewerContainer-DnUrkMJF.js} +23 -23
- package/.output/ui/assets/{ReplayDialog-nDLsjOhs.js → ReplayDialog-B2URyHMv.js} +1 -1
- package/.output/ui/assets/{RequestAnatomy-zd4BDgL0.js → RequestAnatomy-CK0M0CJO.js} +1 -1
- package/.output/ui/assets/{ResponseView-AdIXGcSn.js → ResponseView-CYSVA4lT.js} +1 -1
- package/.output/ui/assets/{StreamingChunkSequence-CesTz8He.js → StreamingChunkSequence-CHf54ZUV.js} +1 -1
- package/.output/ui/assets/{_sessionId-QnBomgPD.js → _sessionId-BXULpTNP.js} +1 -1
- package/.output/ui/assets/{_sessionId-BAfzrhSU.js → _sessionId-E4lbj5-I.js} +1 -1
- package/.output/ui/assets/{index-D0rtCN9V.js → index-B4ixI3kG.js} +1 -1
- package/.output/ui/assets/{index-BcsdxBAd.js → index-BJ-71WLq.js} +1 -1
- package/.output/ui/assets/{index-DHpwr08Z.js → index-CW0ab9r3.js} +2 -2
- package/.output/ui/assets/{index-dNuk2dsU.js → index-Ce-lO51c.js} +1 -1
- package/.output/ui/assets/{json-viewer-BvFHglMb.js → json-viewer-C6E8aLaV.js} +1 -1
- package/.output/ui/assets/{jszip.min-B5Z7gNZB.js → jszip.min-DjWdTBbp.js} +1 -1
- package/.output/ui/index.html +1 -1
- package/README.md +53 -0
- package/package.json +17 -3
- package/src/backend/routes/api/-instances.ts +7 -109
- package/src/cli/instance.ts +21 -0
- package/src/cli/instanceApi.ts +213 -0
- package/src/cli/instanceArgs.ts +16 -0
- package/src/cli/instanceControl.ts +10 -0
- package/src/cli/instanceModel.ts +9 -0
- package/src/cli/rustBackendPackage.ts +458 -0
- package/src/cli.ts +171 -14
- package/src/components/ProxyViewer.tsx +4 -13
- package/src/components/proxy-viewer/proxyViewerLogic.ts +9 -0
- package/src/lib/backendImplementation.ts +16 -0
- package/src/lib/instanceContract.ts +3 -0
- package/src/lib/managedInstance.ts +9 -1
- package/src/mcp/instanceHandlers.ts +1 -0
- package/src/proxy/identityProxy.ts +148 -0
- package/src/proxy/sessionArchive.ts +0 -8
- 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-
|
|
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.
|
|
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,
|
package/.output/server/index.mjs
CHANGED
|
@@ -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-
|
|
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};
|