@tonyclaw/agent-inspector 2.1.24 → 3.0.1
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/cli.js +85 -30
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-DsHSCHSx.js → CompareDrawer-BgcAk1te.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-GI3xErl5.js → ProxyViewerContainer-7b_uwvT7.js} +6 -6
- package/.output/public/assets/{ReplayDialog-D0ixqStX.js → ReplayDialog-7Pvhjbjk.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BG5mb14k.js → RequestAnatomy-BX-UKYQg.js} +1 -1
- package/.output/public/assets/{ResponseView-Bgns6xum.js → ResponseView-zFxGX8xH.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-BeqKXAS6.js → StreamingChunkSequence-DzXzVtBF.js} +1 -1
- package/.output/public/assets/{_sessionId-Nme0kuTf.js → _sessionId-CmsUOEIS.js} +1 -1
- package/.output/public/assets/{index-hbDdeKtc.js → index-DXR7RB48.js} +1 -1
- package/.output/public/assets/index-MfTE52Ty.js +1 -0
- package/.output/public/assets/{json-viewer-CWxF2eLV.js → json-viewer-CiMN_9sG.js} +1 -1
- package/.output/public/assets/{main-BDfcCp_1.js → main-Ba9x64uY.js} +2 -2
- package/.output/server/{_sessionId-DOHtZHvJ.mjs → _sessionId-B8GZtC4P.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-HMfALocK.mjs → CompareDrawer-SBDtZDAp.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-DgnyaJPd.mjs → ProxyViewerContainer-B__2O0zh.mjs} +12 -12
- package/.output/server/_ssr/{ReplayDialog-DyIQdJHE.mjs → ReplayDialog-D0u1VHz_.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-8v4e8mYT.mjs → RequestAnatomy-ClvQ3RFh.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-D17WnkXv.mjs → ResponseView-B4UAvUym.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-CALVBf-R.mjs → StreamingChunkSequence-D_aiGGzz.mjs} +2 -2
- package/.output/server/_ssr/{index-D8EDemF-.mjs → index-DuWacKr6.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-BgrtJGqX.mjs → json-viewer-CmNMVinH.mjs} +2 -2
- package/.output/server/_ssr/{router-D3qLyERI.mjs → router-BP46kVrE.mjs} +30 -5
- package/.output/server/{_tanstack-start-manifest_v-6qZpokPP.mjs → _tanstack-start-manifest_v-DltuTRfm.mjs} +1 -1
- package/.output/server/index.mjs +61 -61
- package/README.md +30 -8
- package/package.json +1 -1
- package/src/cli/doctor.ts +1 -1
- package/src/cli/onboard.ts +15 -9
- package/src/cli.ts +96 -34
- package/src/components/ProxyViewer.tsx +2 -2
- package/src/components/providers/SettingsDialog.tsx +2 -2
- package/src/lib/serverPort.ts +9 -3
- package/src/proxy/sessionProcess.ts +22 -1
- package/src/proxy/socketTracker.ts +1 -1
- package/.output/public/assets/index-CUKpd9jb.js +0 -1
package/.output/cli.js
CHANGED
|
@@ -1403,6 +1403,9 @@ function stringArrayEquals(value, expected) {
|
|
|
1403
1403
|
}
|
|
1404
1404
|
return value.every((item, index) => item === expected[index]);
|
|
1405
1405
|
}
|
|
1406
|
+
function knownMcpEndpoints(endpoint) {
|
|
1407
|
+
return endpoint === DEFAULT_MCP_URL ? [DEFAULT_MCP_URL, LEGACY_MCP_URL] : [endpoint];
|
|
1408
|
+
}
|
|
1406
1409
|
function isAgentLocalEntry(value, endpoint, ignoreEnabled) {
|
|
1407
1410
|
if (!isObject2(value)) {
|
|
1408
1411
|
return false;
|
|
@@ -1412,13 +1415,11 @@ function isAgentLocalEntry(value, endpoint, ignoreEnabled) {
|
|
|
1412
1415
|
return false;
|
|
1413
1416
|
}
|
|
1414
1417
|
const env = value["environment"];
|
|
1415
|
-
const
|
|
1416
|
-
|
|
1417
|
-
"stdio",
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
]);
|
|
1421
|
-
const usesEnv = stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio"]) && isObject2(env) && env["AGENT_INSPECTOR_MCP_URL"] === endpoint;
|
|
1418
|
+
const endpoints = knownMcpEndpoints(endpoint);
|
|
1419
|
+
const usesUrlArg = endpoints.some(
|
|
1420
|
+
(candidate) => stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio", "--url", candidate])
|
|
1421
|
+
);
|
|
1422
|
+
const usesEnv = stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio"]) && isObject2(env) && endpoints.some((candidate) => env["AGENT_INSPECTOR_MCP_URL"] === candidate);
|
|
1422
1423
|
return value["type"] === "local" && (usesUrlArg || usesEnv);
|
|
1423
1424
|
}
|
|
1424
1425
|
function isAgentRemoteEntry(value, endpoint, ignoreEnabled) {
|
|
@@ -1429,7 +1430,7 @@ function isAgentRemoteEntry(value, endpoint, ignoreEnabled) {
|
|
|
1429
1430
|
if (!ignoreEnabled && enabled === false) {
|
|
1430
1431
|
return false;
|
|
1431
1432
|
}
|
|
1432
|
-
return value["type"] === "remote" && value["url"] ===
|
|
1433
|
+
return value["type"] === "remote" && knownMcpEndpoints(endpoint).some((candidate) => value["url"] === candidate);
|
|
1433
1434
|
}
|
|
1434
1435
|
function isKnownAgentEntry(value, endpoint, ignoreEnabled) {
|
|
1435
1436
|
return isAgentLocalEntry(value, endpoint, ignoreEnabled) || isAgentRemoteEntry(value, endpoint, ignoreEnabled);
|
|
@@ -2190,7 +2191,7 @@ Next steps:
|
|
|
2190
2191
|
}
|
|
2191
2192
|
return 0;
|
|
2192
2193
|
}
|
|
2193
|
-
var __filename, __dirname, DEFAULT_PORT, DEFAULT_MCP_URL, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
2194
|
+
var __filename, __dirname, DEFAULT_PORT, DEFAULT_MCP_URL, LEGACY_MCP_URL, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
2194
2195
|
var init_onboard = __esm({
|
|
2195
2196
|
"src/cli/onboard.ts"() {
|
|
2196
2197
|
"use strict";
|
|
@@ -2200,8 +2201,9 @@ var init_onboard = __esm({
|
|
|
2200
2201
|
init_skill_onboard();
|
|
2201
2202
|
__filename = fileURLToPath(import.meta.url);
|
|
2202
2203
|
__dirname = dirname(__filename);
|
|
2203
|
-
DEFAULT_PORT =
|
|
2204
|
+
DEFAULT_PORT = 9527;
|
|
2204
2205
|
DEFAULT_MCP_URL = `http://localhost:${DEFAULT_PORT}/api/mcp`;
|
|
2206
|
+
LEGACY_MCP_URL = "http://localhost:25947/api/mcp";
|
|
2205
2207
|
SKILL_DIR_NAME = "agent-inspector-onboard";
|
|
2206
2208
|
SKILL_FILE_NAME = "SKILL.md";
|
|
2207
2209
|
COMMAND_FILE_NAME = process.platform === "win32" ? "agent-inspector-onboard.md" : "agent-inspector:onboard.md";
|
|
@@ -2753,7 +2755,7 @@ var init_doctor = __esm({
|
|
|
2753
2755
|
"src/cli/doctor.ts"() {
|
|
2754
2756
|
"use strict";
|
|
2755
2757
|
init_dataDir();
|
|
2756
|
-
DEFAULT_PORT2 =
|
|
2758
|
+
DEFAULT_PORT2 = 9527;
|
|
2757
2759
|
PROBE_TIMEOUT_MS = 2e3;
|
|
2758
2760
|
EXTENSION_REQUIRED_FILES = [
|
|
2759
2761
|
"manifest.json",
|
|
@@ -17098,8 +17100,9 @@ function toBuffer(chunk) {
|
|
|
17098
17100
|
// src/cli.ts
|
|
17099
17101
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
17100
17102
|
var __dirname2 = dirname2(__filename2);
|
|
17101
|
-
var DEFAULT_PORT3 =
|
|
17102
|
-
var
|
|
17103
|
+
var DEFAULT_PORT3 = 9527;
|
|
17104
|
+
var LEGACY_ALIAS_PORT = 25947;
|
|
17105
|
+
var DEFAULT_UPSTREAM_PORT = 9529;
|
|
17103
17106
|
var LOCAL_PROBE_TIMEOUT_MS = 2e3;
|
|
17104
17107
|
var BRANDED_WINDOWS_RUNTIME_EXE = "agent-inspector.exe";
|
|
17105
17108
|
var DEFAULT_CAPTURE_MODE = "simple";
|
|
@@ -17198,6 +17201,8 @@ function openBrowser(targetUrl) {
|
|
|
17198
17201
|
detached: true,
|
|
17199
17202
|
windowsHide: true
|
|
17200
17203
|
});
|
|
17204
|
+
browserProcess.once("error", () => {
|
|
17205
|
+
});
|
|
17201
17206
|
browserProcess.unref();
|
|
17202
17207
|
}
|
|
17203
17208
|
function waitForProcessExit(child) {
|
|
@@ -17264,6 +17269,19 @@ function printAccessHints(port, host) {
|
|
|
17264
17269
|
console.log(line);
|
|
17265
17270
|
}
|
|
17266
17271
|
}
|
|
17272
|
+
function pickUpstreamPort(publicPort, legacyAliasPort) {
|
|
17273
|
+
const candidates = [
|
|
17274
|
+
DEFAULT_UPSTREAM_PORT,
|
|
17275
|
+
publicPort + 2 <= 65535 ? publicPort + 2 : publicPort - 2,
|
|
17276
|
+
LEGACY_ALIAS_PORT + 2
|
|
17277
|
+
];
|
|
17278
|
+
for (const candidate of candidates) {
|
|
17279
|
+
if (Number.isInteger(candidate) && candidate > 0 && candidate <= 65535 && candidate !== publicPort && candidate !== legacyAliasPort) {
|
|
17280
|
+
return candidate;
|
|
17281
|
+
}
|
|
17282
|
+
}
|
|
17283
|
+
return DEFAULT_UPSTREAM_PORT;
|
|
17284
|
+
}
|
|
17267
17285
|
async function tryStartIdentityProxy(identityPort, upstreamPort, upstreamHost) {
|
|
17268
17286
|
try {
|
|
17269
17287
|
const server = await startIdentityProxy({
|
|
@@ -17281,7 +17299,7 @@ async function tryStartIdentityProxy(identityPort, upstreamPort, upstreamHost) {
|
|
|
17281
17299
|
}
|
|
17282
17300
|
}
|
|
17283
17301
|
async function runStart(args) {
|
|
17284
|
-
const envPort = process.env["PORT"];
|
|
17302
|
+
const envPort = process.env["AGENT_INSPECTOR_PORT"] ?? process.env["PORT"];
|
|
17285
17303
|
const portDefault = envPort !== void 0 ? Number(envPort) : DEFAULT_PORT3;
|
|
17286
17304
|
const envHost = process.env["NITRO_HOST"] ?? process.env["HOST"];
|
|
17287
17305
|
const envMode = process.env["AGENT_INSPECTOR_CAPTURE_MODE"] ?? process.env["AGENT_INSPECTOR_MODE"];
|
|
@@ -17296,7 +17314,7 @@ async function runStart(args) {
|
|
|
17296
17314
|
let captureMode = DEFAULT_CAPTURE_MODE;
|
|
17297
17315
|
let captureModeWasSpecified = false;
|
|
17298
17316
|
let enableIdentityProxy = true;
|
|
17299
|
-
let
|
|
17317
|
+
let legacyAliasEnabled = true;
|
|
17300
17318
|
if (envMode !== void 0 && envMode !== "") {
|
|
17301
17319
|
const parsedMode = parseCaptureMode(envMode);
|
|
17302
17320
|
if (parsedMode === null) {
|
|
@@ -17402,10 +17420,13 @@ async function runStart(args) {
|
|
|
17402
17420
|
process.exitCode = 1;
|
|
17403
17421
|
return;
|
|
17404
17422
|
}
|
|
17405
|
-
|
|
17423
|
+
port = parsed;
|
|
17406
17424
|
i++;
|
|
17407
17425
|
break;
|
|
17408
17426
|
}
|
|
17427
|
+
case "--no-legacy-port":
|
|
17428
|
+
legacyAliasEnabled = false;
|
|
17429
|
+
break;
|
|
17409
17430
|
default:
|
|
17410
17431
|
break;
|
|
17411
17432
|
}
|
|
@@ -17472,7 +17493,8 @@ async function runStart(args) {
|
|
|
17472
17493
|
} catch {
|
|
17473
17494
|
}
|
|
17474
17495
|
}
|
|
17475
|
-
const
|
|
17496
|
+
const legacyAliasPort = enableIdentityProxy && legacyAliasEnabled && port === DEFAULT_PORT3 ? LEGACY_ALIAS_PORT : null;
|
|
17497
|
+
const upstreamPort = enableIdentityProxy ? pickUpstreamPort(port, legacyAliasPort) : port;
|
|
17476
17498
|
process.env["PORT"] = String(upstreamPort);
|
|
17477
17499
|
const url2 = urlForHost(port, host);
|
|
17478
17500
|
if (!forceRestart && await isInspectorHealthy(port, host)) {
|
|
@@ -17501,8 +17523,8 @@ async function runStart(args) {
|
|
|
17501
17523
|
const restartPorts = /* @__PURE__ */ new Set();
|
|
17502
17524
|
restartPorts.add(port);
|
|
17503
17525
|
if (enableIdentityProxy) {
|
|
17504
|
-
restartPorts.add(identityProxyPort);
|
|
17505
17526
|
restartPorts.add(upstreamPort);
|
|
17527
|
+
if (legacyAliasPort !== null) restartPorts.add(legacyAliasPort);
|
|
17506
17528
|
}
|
|
17507
17529
|
for (const targetPort of restartPorts) {
|
|
17508
17530
|
killProcessOnPort(targetPort);
|
|
@@ -17512,6 +17534,11 @@ async function runStart(args) {
|
|
|
17512
17534
|
console.log(` Capture mode: ${captureMode}`);
|
|
17513
17535
|
console.log(` Proxy: ${url2}/proxy`);
|
|
17514
17536
|
printAccessHints(port, host);
|
|
17537
|
+
if (legacyAliasPort !== null) {
|
|
17538
|
+
console.log(` Legacy UI: http://localhost:${legacyAliasPort}`);
|
|
17539
|
+
console.log(` Legacy proxy: http://localhost:${legacyAliasPort}/proxy`);
|
|
17540
|
+
console.log(` Legacy MCP: http://localhost:${legacyAliasPort}/api/mcp`);
|
|
17541
|
+
}
|
|
17515
17542
|
console.log(``);
|
|
17516
17543
|
console.log(`Route AI coding tools through the proxy:`);
|
|
17517
17544
|
console.log(` Claude Code: ANTHROPIC_BASE_URL=${url2}/proxy claude`);
|
|
@@ -17556,6 +17583,8 @@ async function runStart(args) {
|
|
|
17556
17583
|
serverEnv["HOST"] = host;
|
|
17557
17584
|
serverEnv["NITRO_HOST"] = host;
|
|
17558
17585
|
}
|
|
17586
|
+
serverEnv["AGENT_INSPECTOR_PUBLIC_PORT"] = String(port);
|
|
17587
|
+
serverEnv["PROXY_PORT"] = String(port);
|
|
17559
17588
|
serverEnv["AGENT_INSPECTOR_CAPTURE_MODE"] = captureMode;
|
|
17560
17589
|
const serverProcess = spawn(serverCommand.command, serverCommand.args, {
|
|
17561
17590
|
stdio: background ? ["ignore", "ignore", "ignore"] : ["ignore", "pipe", "pipe"],
|
|
@@ -17563,6 +17592,10 @@ async function runStart(args) {
|
|
|
17563
17592
|
env: serverEnv,
|
|
17564
17593
|
windowsHide: background
|
|
17565
17594
|
});
|
|
17595
|
+
serverProcess.once("error", (err) => {
|
|
17596
|
+
console.error(`Failed to start Agent Inspector runtime: ${err.message}`);
|
|
17597
|
+
});
|
|
17598
|
+
const serverExit = waitForProcessExit(serverProcess);
|
|
17566
17599
|
if (!background) {
|
|
17567
17600
|
pipeServerOutput(serverProcess, {
|
|
17568
17601
|
enableIdentityProxy,
|
|
@@ -17570,23 +17603,39 @@ async function runStart(args) {
|
|
|
17570
17603
|
upstreamPort
|
|
17571
17604
|
});
|
|
17572
17605
|
}
|
|
17573
|
-
const
|
|
17606
|
+
const identityProxies = [];
|
|
17607
|
+
if (enableIdentityProxy) {
|
|
17608
|
+
const primaryProxy = await tryStartIdentityProxy(port, upstreamPort, host);
|
|
17609
|
+
if (primaryProxy !== null) {
|
|
17610
|
+
identityProxies.push({ label: "primary", port, server: primaryProxy });
|
|
17611
|
+
}
|
|
17612
|
+
if (legacyAliasPort !== null) {
|
|
17613
|
+
const legacyProxy = await tryStartIdentityProxy(legacyAliasPort, upstreamPort, host);
|
|
17614
|
+
if (legacyProxy !== null) {
|
|
17615
|
+
identityProxies.push({ label: "legacy", port: legacyAliasPort, server: legacyProxy });
|
|
17616
|
+
}
|
|
17617
|
+
}
|
|
17618
|
+
}
|
|
17574
17619
|
if (background) {
|
|
17575
17620
|
serverProcess.unref();
|
|
17576
17621
|
if (await waitForInspectorHealthy(upstreamPort, 5e3, host)) {
|
|
17577
17622
|
console.log(`agent-inspector background server is ready at ${url2}`);
|
|
17578
|
-
if (
|
|
17579
|
-
console.log(`Identity proxy ready on port ${
|
|
17623
|
+
if (identityProxies.length > 0) {
|
|
17624
|
+
console.log(`Identity proxy ready on port ${port} (PID-attributing proxy).`);
|
|
17580
17625
|
}
|
|
17581
17626
|
printAccessHints(port, host);
|
|
17582
|
-
if (
|
|
17627
|
+
if (legacyAliasPort !== null) {
|
|
17628
|
+
console.log(` Legacy proxy: http://localhost:${legacyAliasPort}/proxy`);
|
|
17629
|
+
console.log(` Legacy MCP: http://localhost:${legacyAliasPort}/api/mcp`);
|
|
17630
|
+
}
|
|
17631
|
+
if (identityProxies.length > 0) {
|
|
17583
17632
|
console.log(
|
|
17584
17633
|
``,
|
|
17585
17634
|
`Route AI coding tools through the identity proxy for accurate PID attribution:`,
|
|
17586
|
-
` Claude Code: ANTHROPIC_BASE_URL=http://localhost:${
|
|
17587
|
-
` OpenCode: LLM_BASE_URL=http://localhost:${
|
|
17588
|
-
` MiMo Code: OPENAI_BASE_URL=http://localhost:${
|
|
17589
|
-
`
|
|
17635
|
+
` Claude Code: ANTHROPIC_BASE_URL=http://localhost:${port}/proxy claude`,
|
|
17636
|
+
` OpenCode: LLM_BASE_URL=http://localhost:${port}/proxy opencode`,
|
|
17637
|
+
` MiMo Code: OPENAI_BASE_URL=http://localhost:${port}/proxy mimo`,
|
|
17638
|
+
legacyAliasPort === null ? ` Override the port with --port <n> when needed.` : ` Legacy configs using http://localhost:${legacyAliasPort}/proxy still work.`
|
|
17590
17639
|
);
|
|
17591
17640
|
}
|
|
17592
17641
|
return;
|
|
@@ -17595,15 +17644,21 @@ async function runStart(args) {
|
|
|
17595
17644
|
process.exitCode = 1;
|
|
17596
17645
|
return;
|
|
17597
17646
|
}
|
|
17598
|
-
if (
|
|
17647
|
+
if (identityProxies.length > 0) {
|
|
17599
17648
|
console.log(``);
|
|
17600
17649
|
console.log(`Identity proxy ready at ${url2} (PID-attributing public entrypoint).`);
|
|
17650
|
+
if (legacyAliasPort !== null) {
|
|
17651
|
+
const legacyReady = identityProxies.some((proxy) => proxy.label === "legacy");
|
|
17652
|
+
if (legacyReady) {
|
|
17653
|
+
console.log(` Legacy alias ready at http://localhost:${legacyAliasPort}.`);
|
|
17654
|
+
}
|
|
17655
|
+
}
|
|
17601
17656
|
if (upstreamPort !== port) {
|
|
17602
17657
|
console.log(` Internal runtime port ${upstreamPort} is hidden behind the public proxy.`);
|
|
17603
17658
|
}
|
|
17604
17659
|
}
|
|
17605
|
-
process.exitCode = await
|
|
17606
|
-
|
|
17607
|
-
await new Promise((resolve2) =>
|
|
17660
|
+
process.exitCode = await serverExit;
|
|
17661
|
+
for (const proxy of identityProxies) {
|
|
17662
|
+
await new Promise((resolve2) => proxy.server.close(() => resolve2()));
|
|
17608
17663
|
}
|
|
17609
17664
|
}
|
package/.output/nitro.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as h,j as t}from"./main-BDfcCp_1.js";import{c as Z,g as $,r as L,a as q,X as ee,b as m,B as te,f as P,R as re,C as ne,M as V,d as _,e as M,h as B,i as se,j as ae,k as oe,L as ie}from"./ProxyViewerContainer-GI3xErl5.js";const de=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],le=Z("equal",de),ce="";function j(e){if(e.length===0)return ce;let r="";for(let n=0;n<e.length;n++){const a=e[n];a!==void 0&&(typeof a=="number"?r+=`[${a}]`:n===0?r+=a:r+=`.${a}`)}return r}function ue(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function D(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(r=>C(r))};if(ue(e)){const r={};for(const n of Object.keys(e).sort())r[n]=C(e[n]);return{kind:"object",value:r}}return{kind:"primitive",value:null}}function xe(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,a){const d=j(e);if(S(r,n)){a.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const i=Object.keys(r.value),s=Object.keys(n.value),o=new Set(s);for(const l of i){const f=r.value[l];if(f!==void 0)if(!o.has(l))a.push({kind:"removed",path:j([...e,l]),value:f});else{const p=n.value[l];if(p===void 0)continue;R([...e,l],f,p,a)}}for(const l of s){if(i.includes(l))continue;const f=n.value[l];f!==void 0&&a.push({kind:"added",path:j([...e,l]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const i=Math.min(r.value.length,n.value.length);for(let s=0;s<i;s++){const o=r.value[s],l=n.value[s];o===void 0||l===void 0||R([...e,s],o,l,a)}for(let s=i;s<n.value.length;s++){const o=n.value[s];o!==void 0&&a.push({kind:"added",path:j([...e,s]),value:o})}for(let s=i;s<r.value.length;s++){const o=r.value[s];o!==void 0&&a.push({kind:"removed",path:j([...e,s]),value:o})}}}function S(e,r){if(e.kind!==r.kind)return!1;if(e.kind==="primitive"&&r.kind==="primitive")return e.value===r.value;if(e.kind==="array"&&r.kind==="array"){if(e.value.length!==r.value.length)return!1;for(let n=0;n<e.value.length;n++){const a=e.value[n],d=r.value[n];if(a===void 0||d===void 0||!S(a,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),a=Object.keys(r.value);if(n.length!==a.length)return!1;for(const d of n){const i=e.value[d],s=r.value[d];if(i===void 0||s===void 0||!S(i,s))return!1}return!0}return!1}function v(e,r=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>r&&(n=`${n.slice(0,r-1)}…`),n}function N(e,r=2){return JSON.stringify(E(e),null,r)}function E(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(E);case"object":{const r={};for(const[n,a]of Object.entries(e.value))r[n]=E(a);return r}}}function w({text:e,defaultExpandDepth:r}){return t.jsx(h.Suspense,{fallback:t.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading JSON..."}),children:t.jsx(ie,{text:e,defaultExpandDepth:r})})}function K(e){if(e==="")return"";for(let r=e.length-1;r>=0;r--){const n=e[r];if(n==="."||n==="[")return e.substring(0,r)}return""}function A(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function me(e){const r=[];let n=0;for(;n<e.length;){const a=e[n];if(a!==void 0&&A(a)){const d=K(a.path);let i=n+1;for(;i<e.length;){const s=e[i];if(s===void 0||!A(s)||K(s.path)!==d)break;i++}if(i-n>1){const s=[];for(let o=n;o<i;o++){const l=e[o];l!==void 0&&l.kind==="equal"&&s.push(l)}r.push({kind:"equal-run",ops:s}),n=i;continue}}a!==void 0&&r.push({kind:"single",op:a}),n++}return r}const F={added:{icon:_,accent:"text-emerald-600 dark:text-emerald-400",bg:"bg-emerald-500/5 hover:bg-emerald-500/10",border:"border-l-emerald-500",label:"ADDED"},removed:{icon:V,accent:"text-rose-600 dark:text-rose-400",bg:"bg-rose-500/5 hover:bg-rose-500/10",border:"border-l-rose-500",label:"REMOVED"},changed:{icon:M,accent:"text-amber-600 dark:text-amber-400",bg:"bg-amber-500/5 hover:bg-amber-500/10",border:"border-l-amber-500",label:"CHANGED"},equal:{icon:le,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function fe({ops:e,expanded:r,onToggle:n}){const a=e[0],d=e[e.length-1];if(a===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const i=a.path,s=d.path,o=e.length===1?i:`${i} … ${s}`,l=a.value.kind==="array"?`${e.length} equal arrays`:a.value.kind==="object"?`${e.length} equal objects`:"equal",f=F.equal;return t.jsxs("div",{className:m("border-l-4 rounded-sm",f.border,f.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(B,{className:m("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:m("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${i} … ${s}`,children:o}),t.jsx("span",{className:m("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",l,")"]})]}),r&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(p=>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:p.path}),t.jsx(w,{text:N(p.value),defaultExpandDepth:0})]},p.path))})]})}function pe({op:e,idx:r,copiedPath:n,onCopyPath:a,expanded:d,onToggle:i}){const s=F[e.kind],o=s.icon,l=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,f=e.kind==="changed"?[{text:v(e.left,400),tone:"text-rose-700 dark:text-rose-300 line-through"},{text:v(e.right,400),tone:"text-emerald-700 dark:text-emerald-300"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-rose-700 dark:text-rose-300 line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-emerald-700 dark:text-emerald-300"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],p=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":r,"data-diff-kind":e.kind,className:m("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",s.border,s.bg),children:[t.jsxs("button",{type:"button",onClick:i,disabled:!l,className:m("w-full flex items-center gap-2 text-xs text-left rounded-sm",l?"cursor-pointer":"cursor-default"),"aria-expanded":l?d:void 0,"aria-label":l?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[l?t.jsx(B,{className:m("size-3 shrink-0 transition-transform",s.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(o,{className:m("size-3.5 shrink-0",s.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:m("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",s.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:s.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:m("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",p?"text-emerald-500":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":p?"Copied":"Copy",title:p?"Copied!":"Copy",children:p?t.jsx(se,{className:"size-3"}):t.jsx(ae,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:m("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},y)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:d&&l?"2000px":"0"},"aria-hidden":!d,children:d&&l&&e.kind!=="equal"?t.jsx(he,{op:e}):null})]})}function he({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 r=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!r&&!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:"border border-rose-500/30 rounded p-2 bg-rose-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-rose-500 mb-1",children:"Old"}),t.jsx(w,{text:N(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"border border-emerald-500/30 rounded p-2 bg-emerald-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-emerald-500 mb-1",children:"New"}),t.jsx(w,{text:N(e.right),defaultExpandDepth:0})]})]})}function be({counts:e,onJumpTo:r}){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:()=>r("removed"),disabled:e.removed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-rose-500/40 text-rose-600 dark:text-rose-400 bg-rose-500/10 hover:bg-rose-500/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:()=>r("added"),disabled:e.added===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 hover:bg-emerald-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(_,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-amber-500/40 text-amber-600 dark:text-amber-400 bg-amber-500/10 hover:bg-amber-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(M,{className:"size-3"}),e.changed," changed"]})]})}function ve({mode:e,onChange:r}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>r("unified"),"aria-pressed":e==="unified",className:m("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(re,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:m("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(ne,{className:"size-3"}),"Split"]})]})}function J({log:e,side:r,displayNumber:n}){const a=q(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(te,{variant:"outline",className:m("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",r==="left"?"border-rose-500/40 text-rose-400":"border-emerald-500/40 text-emerald-400"),children:r==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-blue-400/80",title:`Log ID ${String(e.id)}`,children:["#",n]}),e.model!==null&&t.jsx("span",{className:"font-mono text-muted-foreground truncate",children:e.model})]}),t.jsxs("div",{className:"flex items-center gap-3 text-muted-foreground font-mono",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-emerald-400",children:["KV Cache +",P(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["KV Cache ~",P(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 ye({left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a,onClose:d}){const i=h.useMemo(()=>{const c=$(L(e)).analyzeRequest(e.rawRequestBody),u=$(L(r)).analyzeRequest(r.rawRequestBody),x=D(c.comparisonValue),g=D(u.comparisonValue);return xe(x,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),s=h.useMemo(()=>me(i),[i]),o=h.useMemo(()=>{let c=0,u=0,x=0;for(const g of s)if(g.kind==="single")switch(g.op.kind){case"added":c++;break;case"removed":u++;break;case"changed":x++;break}return{added:c,removed:u,changed:x}},[s]),[l,f]=h.useState(new Set),p=c=>{f(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})},[b,y]=h.useState(new Set),U=c=>{y(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})};h.useEffect(()=>{y(new Set)},[e.id,r.id]);const[T,H]=h.useState("unified"),I=h.useRef(null),[G,z]=h.useState(null),k=h.useRef(null),Q=c=>{oe(c).then(u=>{u&&(z(c),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500))})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const W=c=>{const u=s.findIndex(O=>O.kind==="single"&&O.op.kind===c);if(u===-1)return;const x=I.current;if(x===null)return;const g=x.querySelector(`[data-diff-idx="${u}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const c=x=>{x.key==="Escape"&&d()};document.addEventListener("keydown",c);const u=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",c),document.body.style.overflow=u}},[d]);const X=q(e)===q(r),Y=i.length===1&&i[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:d,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:m("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:c=>c.stopPropagation(),onKeyDown:c=>c.stopPropagation(),children:[t.jsxs("div",{className:"flex items-start gap-4 px-4 py-3 border-b border-border",children:[t.jsxs("div",{className:"flex-1 flex gap-4 min-w-0",children:[t.jsx(J,{log:e,side:"left",displayNumber:n}),t.jsx(J,{log:r,side:"right",displayNumber:a})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(ve,{mode:T,onChange:H}),t.jsx("button",{type:"button",onClick:d,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(ee,{className:"size-4"})})]})]}),!X&&t.jsx("div",{className:"px-4 py-1.5 text-xs text-amber-400 bg-amber-500/10 border-b border-border",children:"Heads up: the two selected logs are from different sessions."}),Y?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(be,{counts:o,onJumpTo:W}),t.jsx("div",{ref:I,className:"flex-1 min-h-0 overflow-y-auto",children:T==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:s.map((c,u)=>{if(c.kind==="equal-run")return t.jsx(fe,{ops:c.ops,expanded:l.has(u),onToggle:()=>p(u)},`r${u}`);const x=c.op;return t.jsx(pe,{op:x,idx:u,copiedPath:G,onCopyPath:Q,expanded:b.has(u),onToggle:()=>U(u)},`o${u}`)})}):t.jsx(ge,{grouped:s,left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a})})]})]})]})}function ge({grouped:e,left:r,right:n,leftDisplayNumber:a,rightDisplayNumber:d}){return t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 gap-y-0.5 px-3 py-2 text-xs",children:[t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 col-span-3 pb-2 mb-2 border-b border-border text-[10px] uppercase tracking-wider text-muted-foreground",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{title:`Log ID ${String(r.id)}`,children:["Left (Log #",a,")"]}),t.jsxs("span",{title:`Log ID ${String(n.id)}`,children:["Right (Log #",d,")"]})]}),e.map((i,s)=>{if(i.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[i.ops.length," equal siblings collapsed — switch to Unified to expand"]},s);const o=i.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-3 grid grid-cols-[200px_1fr_1fr] gap-x-2 px-2 py-0.5 text-muted-foreground",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)})]},s):o.kind==="added"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-emerald-400/70 bg-emerald-500/5",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-emerald-300/90",children:["+ ",v(o.value,400)]})]},s):o.kind==="removed"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-rose-400/70 bg-rose-500/5",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-rose-300/90 line-through",children:["− ",v(o.value,400)]})]},s):t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-amber-400/70 bg-amber-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsx("div",{className:"font-mono text-rose-300/90 break-all line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono text-emerald-300/90 break-all",children:v(o.right,400)})]})]},s)})]})}export{ye as CompareDrawer};
|
|
1
|
+
import{r as h,j as t}from"./main-Ba9x64uY.js";import{c as Z,g as $,r as L,a as q,X as ee,b as m,B as te,f as P,R as re,C as ne,M as V,d as _,e as M,h as B,i as se,j as ae,k as oe,L as ie}from"./ProxyViewerContainer-7b_uwvT7.js";const de=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],le=Z("equal",de),ce="";function j(e){if(e.length===0)return ce;let r="";for(let n=0;n<e.length;n++){const a=e[n];a!==void 0&&(typeof a=="number"?r+=`[${a}]`:n===0?r+=a:r+=`.${a}`)}return r}function ue(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function D(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(r=>C(r))};if(ue(e)){const r={};for(const n of Object.keys(e).sort())r[n]=C(e[n]);return{kind:"object",value:r}}return{kind:"primitive",value:null}}function xe(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,a){const d=j(e);if(S(r,n)){a.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){a.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const i=Object.keys(r.value),s=Object.keys(n.value),o=new Set(s);for(const l of i){const f=r.value[l];if(f!==void 0)if(!o.has(l))a.push({kind:"removed",path:j([...e,l]),value:f});else{const p=n.value[l];if(p===void 0)continue;R([...e,l],f,p,a)}}for(const l of s){if(i.includes(l))continue;const f=n.value[l];f!==void 0&&a.push({kind:"added",path:j([...e,l]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const i=Math.min(r.value.length,n.value.length);for(let s=0;s<i;s++){const o=r.value[s],l=n.value[s];o===void 0||l===void 0||R([...e,s],o,l,a)}for(let s=i;s<n.value.length;s++){const o=n.value[s];o!==void 0&&a.push({kind:"added",path:j([...e,s]),value:o})}for(let s=i;s<r.value.length;s++){const o=r.value[s];o!==void 0&&a.push({kind:"removed",path:j([...e,s]),value:o})}}}function S(e,r){if(e.kind!==r.kind)return!1;if(e.kind==="primitive"&&r.kind==="primitive")return e.value===r.value;if(e.kind==="array"&&r.kind==="array"){if(e.value.length!==r.value.length)return!1;for(let n=0;n<e.value.length;n++){const a=e.value[n],d=r.value[n];if(a===void 0||d===void 0||!S(a,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),a=Object.keys(r.value);if(n.length!==a.length)return!1;for(const d of n){const i=e.value[d],s=r.value[d];if(i===void 0||s===void 0||!S(i,s))return!1}return!0}return!1}function v(e,r=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>r&&(n=`${n.slice(0,r-1)}…`),n}function N(e,r=2){return JSON.stringify(E(e),null,r)}function E(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(E);case"object":{const r={};for(const[n,a]of Object.entries(e.value))r[n]=E(a);return r}}}function w({text:e,defaultExpandDepth:r}){return t.jsx(h.Suspense,{fallback:t.jsx("div",{className:"text-xs text-muted-foreground",children:"Loading JSON..."}),children:t.jsx(ie,{text:e,defaultExpandDepth:r})})}function K(e){if(e==="")return"";for(let r=e.length-1;r>=0;r--){const n=e[r];if(n==="."||n==="[")return e.substring(0,r)}return""}function A(e){return e.kind==="equal"&&(e.value.kind==="object"||e.value.kind==="array")}function me(e){const r=[];let n=0;for(;n<e.length;){const a=e[n];if(a!==void 0&&A(a)){const d=K(a.path);let i=n+1;for(;i<e.length;){const s=e[i];if(s===void 0||!A(s)||K(s.path)!==d)break;i++}if(i-n>1){const s=[];for(let o=n;o<i;o++){const l=e[o];l!==void 0&&l.kind==="equal"&&s.push(l)}r.push({kind:"equal-run",ops:s}),n=i;continue}}a!==void 0&&r.push({kind:"single",op:a}),n++}return r}const F={added:{icon:_,accent:"text-emerald-600 dark:text-emerald-400",bg:"bg-emerald-500/5 hover:bg-emerald-500/10",border:"border-l-emerald-500",label:"ADDED"},removed:{icon:V,accent:"text-rose-600 dark:text-rose-400",bg:"bg-rose-500/5 hover:bg-rose-500/10",border:"border-l-rose-500",label:"REMOVED"},changed:{icon:M,accent:"text-amber-600 dark:text-amber-400",bg:"bg-amber-500/5 hover:bg-amber-500/10",border:"border-l-amber-500",label:"CHANGED"},equal:{icon:le,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function fe({ops:e,expanded:r,onToggle:n}){const a=e[0],d=e[e.length-1];if(a===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const i=a.path,s=d.path,o=e.length===1?i:`${i} … ${s}`,l=a.value.kind==="array"?`${e.length} equal arrays`:a.value.kind==="object"?`${e.length} equal objects`:"equal",f=F.equal;return t.jsxs("div",{className:m("border-l-4 rounded-sm",f.border,f.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(B,{className:m("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:m("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${i} … ${s}`,children:o}),t.jsx("span",{className:m("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",l,")"]})]}),r&&t.jsx("div",{className:"ml-5 mt-1 mb-2 space-y-2 pr-2",children:e.map(p=>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:p.path}),t.jsx(w,{text:N(p.value),defaultExpandDepth:0})]},p.path))})]})}function pe({op:e,idx:r,copiedPath:n,onCopyPath:a,expanded:d,onToggle:i}){const s=F[e.kind],o=s.icon,l=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,f=e.kind==="changed"?[{text:v(e.left,400),tone:"text-rose-700 dark:text-rose-300 line-through"},{text:v(e.right,400),tone:"text-emerald-700 dark:text-emerald-300"}]:e.kind==="removed"?[{text:v(e.value,400),tone:"text-rose-700 dark:text-rose-300 line-through"}]:e.kind==="added"?[{text:v(e.value,400),tone:"text-emerald-700 dark:text-emerald-300"}]:[{text:v(e.value,400),tone:"text-muted-foreground"}],p=n===e.path&&e.path!=="";return t.jsxs("div",{"data-diff-idx":r,"data-diff-kind":e.kind,className:m("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",s.border,s.bg),children:[t.jsxs("button",{type:"button",onClick:i,disabled:!l,className:m("w-full flex items-center gap-2 text-xs text-left rounded-sm",l?"cursor-pointer":"cursor-default"),"aria-expanded":l?d:void 0,"aria-label":l?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[l?t.jsx(B,{className:m("size-3 shrink-0 transition-transform",s.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(o,{className:m("size-3.5 shrink-0",s.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:m("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",s.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:s.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:m("shrink-0 p-1 rounded transition-colors cursor-pointer inline-flex items-center justify-center",p?"text-emerald-500":"text-muted-foreground/50 hover:text-foreground hover:bg-muted"),"aria-label":p?"Copied":"Copy",title:p?"Copied!":"Copy",children:p?t.jsx(se,{className:"size-3"}):t.jsx(ae,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:m("font-mono text-xs mt-1 break-all pl-5",b.tone),children:b.text},y)),t.jsx("div",{className:"overflow-hidden transition-all duration-200",style:{maxHeight:d&&l?"2000px":"0"},"aria-hidden":!d,children:d&&l&&e.kind!=="equal"?t.jsx(he,{op:e}):null})]})}function he({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 r=e.left.kind==="object"||e.left.kind==="array",n=e.right.kind==="object"||e.right.kind==="array";return!r&&!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:"border border-rose-500/30 rounded p-2 bg-rose-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-rose-500 mb-1",children:"Old"}),t.jsx(w,{text:N(e.left),defaultExpandDepth:0})]}),t.jsxs("div",{className:"border border-emerald-500/30 rounded p-2 bg-emerald-500/5",children:[t.jsx("div",{className:"text-[10px] uppercase tracking-wider text-emerald-500 mb-1",children:"New"}),t.jsx(w,{text:N(e.right),defaultExpandDepth:0})]})]})}function be({counts:e,onJumpTo:r}){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:()=>r("removed"),disabled:e.removed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.removed>0?"border-rose-500/40 text-rose-600 dark:text-rose-400 bg-rose-500/10 hover:bg-rose-500/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:()=>r("added"),disabled:e.added===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.added>0?"border-emerald-500/40 text-emerald-600 dark:text-emerald-400 bg-emerald-500/10 hover:bg-emerald-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.added>0?"Jump to first added":"No additions",children:[t.jsx(_,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:m("inline-flex items-center gap-1 px-2 py-0.5 rounded-full border cursor-pointer transition-colors",e.changed>0?"border-amber-500/40 text-amber-600 dark:text-amber-400 bg-amber-500/10 hover:bg-amber-500/20":"border-border text-muted-foreground/40 cursor-not-allowed"),title:e.changed>0?"Jump to first changed":"No changes",children:[t.jsx(M,{className:"size-3"}),e.changed," changed"]})]})}function ve({mode:e,onChange:r}){return t.jsxs("div",{className:"inline-flex rounded-md border border-border overflow-hidden",children:[t.jsxs("button",{type:"button",onClick:()=>r("unified"),"aria-pressed":e==="unified",className:m("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(re,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:m("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(ne,{className:"size-3"}),"Split"]})]})}function J({log:e,side:r,displayNumber:n}){const a=q(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(te,{variant:"outline",className:m("text-[10px] px-1.5 py-0 h-5 font-mono shrink-0",r==="left"?"border-rose-500/40 text-rose-400":"border-emerald-500/40 text-emerald-400"),children:r==="left"?"← Left":"Right →"}),t.jsxs("span",{className:"font-mono text-blue-400/80",title:`Log ID ${String(e.id)}`,children:["#",n]}),e.model!==null&&t.jsx("span",{className:"font-mono text-muted-foreground truncate",children:e.model})]}),t.jsxs("div",{className:"flex items-center gap-3 text-muted-foreground font-mono",children:[e.cacheCreationInputTokens!==null&&e.cacheCreationInputTokens>0&&t.jsxs("span",{className:"text-emerald-400",children:["KV Cache +",P(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["KV Cache ~",P(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 ye({left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a,onClose:d}){const i=h.useMemo(()=>{const c=$(L(e)).analyzeRequest(e.rawRequestBody),u=$(L(r)).analyzeRequest(r.rawRequestBody),x=D(c.comparisonValue),g=D(u.comparisonValue);return xe(x,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),s=h.useMemo(()=>me(i),[i]),o=h.useMemo(()=>{let c=0,u=0,x=0;for(const g of s)if(g.kind==="single")switch(g.op.kind){case"added":c++;break;case"removed":u++;break;case"changed":x++;break}return{added:c,removed:u,changed:x}},[s]),[l,f]=h.useState(new Set),p=c=>{f(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})},[b,y]=h.useState(new Set),U=c=>{y(u=>{const x=new Set(u);return x.has(c)?x.delete(c):x.add(c),x})};h.useEffect(()=>{y(new Set)},[e.id,r.id]);const[T,H]=h.useState("unified"),I=h.useRef(null),[G,z]=h.useState(null),k=h.useRef(null),Q=c=>{oe(c).then(u=>{u&&(z(c),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500))})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const W=c=>{const u=s.findIndex(O=>O.kind==="single"&&O.op.kind===c);if(u===-1)return;const x=I.current;if(x===null)return;const g=x.querySelector(`[data-diff-idx="${u}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const c=x=>{x.key==="Escape"&&d()};document.addEventListener("keydown",c);const u=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",c),document.body.style.overflow=u}},[d]);const X=q(e)===q(r),Y=i.length===1&&i[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:d,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:m("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:c=>c.stopPropagation(),onKeyDown:c=>c.stopPropagation(),children:[t.jsxs("div",{className:"flex items-start gap-4 px-4 py-3 border-b border-border",children:[t.jsxs("div",{className:"flex-1 flex gap-4 min-w-0",children:[t.jsx(J,{log:e,side:"left",displayNumber:n}),t.jsx(J,{log:r,side:"right",displayNumber:a})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(ve,{mode:T,onChange:H}),t.jsx("button",{type:"button",onClick:d,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(ee,{className:"size-4"})})]})]}),!X&&t.jsx("div",{className:"px-4 py-1.5 text-xs text-amber-400 bg-amber-500/10 border-b border-border",children:"Heads up: the two selected logs are from different sessions."}),Y?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(be,{counts:o,onJumpTo:W}),t.jsx("div",{ref:I,className:"flex-1 min-h-0 overflow-y-auto",children:T==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:s.map((c,u)=>{if(c.kind==="equal-run")return t.jsx(fe,{ops:c.ops,expanded:l.has(u),onToggle:()=>p(u)},`r${u}`);const x=c.op;return t.jsx(pe,{op:x,idx:u,copiedPath:G,onCopyPath:Q,expanded:b.has(u),onToggle:()=>U(u)},`o${u}`)})}):t.jsx(ge,{grouped:s,left:e,right:r,leftDisplayNumber:n,rightDisplayNumber:a})})]})]})]})}function ge({grouped:e,left:r,right:n,leftDisplayNumber:a,rightDisplayNumber:d}){return t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 gap-y-0.5 px-3 py-2 text-xs",children:[t.jsxs("div",{className:"grid grid-cols-[200px_1fr_1fr] gap-x-2 col-span-3 pb-2 mb-2 border-b border-border text-[10px] uppercase tracking-wider text-muted-foreground",children:[t.jsx("span",{children:"Path"}),t.jsxs("span",{title:`Log ID ${String(r.id)}`,children:["Left (Log #",a,")"]}),t.jsxs("span",{title:`Log ID ${String(n.id)}`,children:["Right (Log #",d,")"]})]}),e.map((i,s)=>{if(i.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[i.ops.length," equal siblings collapsed — switch to Unified to expand"]},s);const o=i.op;return o.kind==="equal"?t.jsxs("div",{className:"col-span-3 grid grid-cols-[200px_1fr_1fr] gap-x-2 px-2 py-0.5 text-muted-foreground",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)})]},s):o.kind==="added"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-emerald-400/70 bg-emerald-500/5",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-emerald-300/90",children:["+ ",v(o.value,400)]})]},s):o.kind==="removed"?t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-rose-400/70 bg-rose-500/5",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-rose-300/90 line-through",children:["− ",v(o.value,400)]})]},s):t.jsxs("div",{className:"col-span-3 px-2 py-1 rounded text-xs border-l-2 border-l-amber-400/70 bg-amber-500/5",children:[t.jsx("div",{className:"font-mono text-xs text-muted-foreground mb-1",children:o.path}),t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsx("div",{className:"font-mono text-rose-300/90 break-all line-through",children:v(o.left,400)}),t.jsx("div",{className:"font-mono text-emerald-300/90 break-all",children:v(o.right,400)})]})]},s)})]})}export{ye as CompareDrawer};
|