@tonyclaw/agent-inspector 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.output/cli.js +344 -53
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/{CompareDrawer-sVLGhCO3.js → CompareDrawer-Bp7_x-5N.js} +1 -1
  4. package/.output/public/assets/{ProxyViewerContainer-p9QvzZ6U.js → ProxyViewerContainer-USuxPy-K.js} +13 -13
  5. package/.output/public/assets/{ReplayDialog-DxbFUqNW.js → ReplayDialog-DFHCd0yx.js} +1 -1
  6. package/.output/public/assets/{RequestAnatomy-CSmGQa_g.js → RequestAnatomy-ehyrskxt.js} +1 -1
  7. package/.output/public/assets/{ResponseView-B5f89c8Z.js → ResponseView-BNGyc8e_.js} +1 -1
  8. package/.output/public/assets/{StreamingChunkSequence-BzqpY0TN.js → StreamingChunkSequence-Bjs4Lqwn.js} +1 -1
  9. package/.output/public/assets/_sessionId-D_SeK_qp.js +1 -0
  10. package/.output/public/assets/index-BGGOWR7A.js +1 -0
  11. package/.output/public/assets/index-CIL46Z2y.css +1 -0
  12. package/.output/public/assets/{json-viewer-CKNMihlh.js → json-viewer-6uV_YXws.js} +1 -1
  13. package/.output/public/assets/{main-yWf8dv9w.js → main-FSGUGtEL.js} +2 -2
  14. package/.output/server/{_sessionId-DfHd0gd8.mjs → _sessionId-_bf9vUww.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-DGYAUWgF.mjs → CompareDrawer-DIth2DQM.mjs} +3 -3
  16. package/.output/server/_ssr/{ProxyViewerContainer-fawglkTo.mjs → ProxyViewerContainer-249bTH-T.mjs} +24 -30
  17. package/.output/server/_ssr/{ReplayDialog-B4vlKa2W.mjs → ReplayDialog-C1aGx0y1.mjs} +4 -4
  18. package/.output/server/_ssr/{RequestAnatomy-BNQvEIZK.mjs → RequestAnatomy-D2bCiEJn.mjs} +2 -2
  19. package/.output/server/_ssr/{ResponseView-X6X6G16_.mjs → ResponseView-DP6k4Xs_.mjs} +3 -3
  20. package/.output/server/_ssr/{StreamingChunkSequence-BPVN3MnF.mjs → StreamingChunkSequence-HyXZV-b5.mjs} +3 -3
  21. package/.output/server/_ssr/{index-CXmpc2X5.mjs → index-Bt47f9pn.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-3XC3eq4R.mjs → json-viewer-Co-YRwUP.mjs} +2 -2
  24. package/.output/server/_ssr/{router-C0B2qvIM.mjs → router-to_OJirX.mjs} +383 -43
  25. package/.output/server/{_tanstack-start-manifest_v-7tfsmd2I.mjs → _tanstack-start-manifest_v-Bd-2YRWo.mjs} +1 -1
  26. package/.output/server/index.mjs +63 -63
  27. package/README.md +47 -7
  28. package/package.json +3 -2
  29. package/scripts/setup-codex-skill.mjs +38 -0
  30. package/scripts/setup-windows-runtime.mjs +4 -3
  31. package/src/cli/onboard.ts +175 -68
  32. package/src/cli/templates/codex-skill-onboard.ts +210 -0
  33. package/src/components/providers/ProviderCard.tsx +2 -27
  34. package/src/components/providers/ProvidersPanel.tsx +16 -0
  35. package/src/knowledge/openclawClient.ts +34 -5
  36. package/src/knowledge/openclawGatewayClient.ts +237 -0
  37. package/src/knowledge/openclawMarkdown.ts +146 -0
  38. package/src/lib/providerTestPrompt.ts +78 -0
  39. package/src/routes/api/providers.$providerId.test.log.ts +9 -22
  40. package/.output/public/assets/_sessionId-BF7ftHV3.js +0 -1
  41. package/.output/public/assets/index-BU0PpLby.js +0 -1
  42. package/.output/public/assets/index-CpWG2hFn.css +0 -1
package/.output/cli.js CHANGED
@@ -114,6 +114,208 @@ var init_command_onboard = __esm({
114
114
  }
115
115
  });
116
116
 
117
+ // src/cli/templates/codex-skill-onboard.ts
118
+ function renderCodexSkillOnboard(ctx) {
119
+ const { version, port } = ctx;
120
+ return `---
121
+ name: agent-inspector-onboard
122
+ description: Guide Codex users through connecting Agent Inspector v${version} as a local MCP server.
123
+ metadata:
124
+ author: agent-inspector
125
+ version: ${version}
126
+ ---
127
+
128
+ # Agent Inspector onboard for Codex
129
+
130
+ Use this skill when the user wants to set up Agent Inspector inside Codex, connect the Agent Inspector MCP server, inspect captured model traffic from Codex, or turn Inspector sessions into reviewable knowledge candidates.
131
+
132
+ Agent Inspector runs a local web UI, proxy, REST API, and MCP endpoint on the same port. The default MCP endpoint is:
133
+
134
+ \`\`\`text
135
+ http://localhost:${port}/api/mcp
136
+ \`\`\`
137
+
138
+ This skill is installed at \`~/.codex/skills/agent-inspector-onboard/SKILL.md\`.
139
+ Codex user-level configuration lives in \`~/.codex/config.toml\`. Codex supports streamable HTTP MCP servers with \`mcp_servers.<id>.url\`, so no extra stdio bridge package is needed.
140
+
141
+ Keep this setup local and explicit. Agent Inspector MCP tools can read captured requests and provider configuration, so only wire it into trusted local Codex environments.
142
+
143
+ ---
144
+
145
+ ## Phase 0: Preflight
146
+
147
+ Check that the package and Codex home exist without printing secrets.
148
+
149
+ \`\`\`powershell
150
+ Get-Command agent-inspector -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source
151
+ Test-Path (Join-Path $env:USERPROFILE ".codex")
152
+ Test-Path (Join-Path $env:USERPROFILE ".codex\\config.toml")
153
+ \`\`\`
154
+
155
+ \`\`\`bash
156
+ command -v agent-inspector || true
157
+ test -d "$HOME/.codex" && echo "codex home: present" || echo "codex home: missing"
158
+ test -f "$HOME/.codex/config.toml" && echo "config: present" || echo "config: missing"
159
+ \`\`\`
160
+
161
+ If \`agent-inspector\` is missing, ask the user to install it first:
162
+
163
+ \`\`\`bash
164
+ npm install -g @tonyclaw/agent-inspector
165
+ \`\`\`
166
+
167
+ Do not read \`~/.codex/auth.json\`, token files, or unrelated Codex state files.
168
+
169
+ ---
170
+
171
+ ## Phase 1: Start Agent Inspector
172
+
173
+ Start or reuse Agent Inspector before wiring MCP. Prefer the installed binary so Windows users get the branded runtime in Task Manager.
174
+
175
+ \`\`\`powershell
176
+ agent-inspector --background --no-open
177
+ Invoke-RestMethod -Uri "http://localhost:${port}/api/health" -TimeoutSec 3
178
+ \`\`\`
179
+
180
+ \`\`\`bash
181
+ agent-inspector --background --no-open
182
+ curl -fsS "http://localhost:${port}/api/health"
183
+ \`\`\`
184
+
185
+ If the health check fails, show only the relevant error and ask whether to diagnose startup before editing Codex config.
186
+
187
+ ---
188
+
189
+ ## Phase 2: Wire Codex MCP
190
+
191
+ Add an \`agent-inspector\` MCP server to \`~/.codex/config.toml\`. Preserve the user's existing config and merge the table instead of replacing the file.
192
+
193
+ Recommended user-level config:
194
+
195
+ \`\`\`toml
196
+ [mcp_servers.agent-inspector]
197
+ url = "http://localhost:${port}/api/mcp"
198
+ startup_timeout_sec = 30
199
+ tool_timeout_sec = 60
200
+ \`\`\`
201
+
202
+ If the user's Codex environment is managed by an admin allowlist, they may also need a matching identity rule in the managed requirements layer:
203
+
204
+ \`\`\`toml
205
+ [mcp_servers.agent-inspector.identity]
206
+ url = "http://localhost:${port}/api/mcp"
207
+ \`\`\`
208
+
209
+ When editing:
210
+
211
+ - Ask before changing \`~/.codex/config.toml\`.
212
+ - Keep existing \`mcp_servers.*\`, \`projects.*\`, profiles, sandbox, approval, and model settings intact.
213
+ - Do not write provider API keys into Codex config.
214
+ - Do not expose Agent Inspector MCP beyond localhost.
215
+
216
+ ---
217
+
218
+ ## Phase 3: Restart and verify Codex
219
+
220
+ Tell the user that Codex loads MCP servers at session startup. After saving \`config.toml\`, they should start a new Codex session or restart the Codex app.
221
+
222
+ Before restart, verify the HTTP endpoint itself:
223
+
224
+ \`\`\`bash
225
+ curl -sS -X POST "http://localhost:${port}/api/mcp" \\
226
+ -H "Content-Type: application/json" \\
227
+ -H "Accept: application/json, text/event-stream" \\
228
+ -d '{
229
+ "jsonrpc": "2.0",
230
+ "id": 1,
231
+ "method": "initialize",
232
+ "params": {
233
+ "protocolVersion": "2025-03-26",
234
+ "capabilities": {},
235
+ "clientInfo": { "name": "codex-onboard-check", "version": "0" }
236
+ }
237
+ }'
238
+ \`\`\`
239
+
240
+ Expected signal: a 200 response containing \`serverInfo\` with \`agent-inspector\`.
241
+
242
+ ---
243
+
244
+ ## Phase 4: First Inspector query
245
+
246
+ After Codex restarts with the MCP server configured, ask Codex to use Agent Inspector:
247
+
248
+ \`\`\`text
249
+ Use Agent Inspector to list the latest captured logs.
250
+ \`\`\`
251
+
252
+ The expected tool is \`inspector_list_logs\`. If no logs exist yet, that is still a successful MCP connection.
253
+
254
+ Useful follow-up tools:
255
+
256
+ - \`inspector_list_logs\`
257
+ - \`inspector_get_log\`
258
+ - \`inspector_get_log_chunks\`
259
+ - \`inspector_list_sessions\`
260
+ - \`inspector_test_provider\`
261
+ - \`inspector_create_session_knowledge\`
262
+ - \`inspector_list_knowledge_candidates\`
263
+ - \`inspector_search_knowledge\`
264
+ - \`inspector_get_project_context\`
265
+
266
+ Provider mutation tools expose and modify local provider configuration. Ask for explicit user confirmation before using \`inspector_add_provider\`, \`inspector_update_provider\`, or \`inspector_replay_log\`.
267
+
268
+ ---
269
+
270
+ ## Phase 5: Capture and memory review
271
+
272
+ To capture Codex traffic through Agent Inspector, route a model client through:
273
+
274
+ \`\`\`text
275
+ http://localhost:${port}/proxy
276
+ \`\`\`
277
+
278
+ For Anthropic-compatible tools, set \`ANTHROPIC_BASE_URL=http://localhost:${port}/proxy\`. For OpenAI-compatible tools, set \`OPENAI_BASE_URL=http://localhost:${port}/proxy\`.
279
+
280
+ For a Provider Test memory probe, run a provider test in the Agent Inspector UI:
281
+
282
+ 1. Open \`http://localhost:${port}\`.
283
+ 2. Go to Settings -> Providers.
284
+ 3. Add or edit a Provider.
285
+ 4. Run Test.
286
+ 5. Check the \`provider-test\` session.
287
+
288
+ Then ask Codex:
289
+
290
+ \`\`\`text
291
+ Use Agent Inspector to create knowledge candidates for the provider-test session, then list the candidates.
292
+ \`\`\`
293
+
294
+ Expected flow:
295
+
296
+ - Raw Trace stays in Agent Inspector logs.
297
+ - Session Episode is reconstructed from the session.
298
+ - Memory Candidate is generated for review.
299
+ - Promotion to OpenClaw happens only after review through Agent Inspector.
300
+
301
+ Stop after showing candidates unless the user explicitly approves promotion.
302
+ `;
303
+ }
304
+ var REQUIRED_CODEX_PHASE_HEADINGS;
305
+ var init_codex_skill_onboard = __esm({
306
+ "src/cli/templates/codex-skill-onboard.ts"() {
307
+ "use strict";
308
+ REQUIRED_CODEX_PHASE_HEADINGS = [
309
+ "Phase 0: Preflight",
310
+ "Phase 1: Start Agent Inspector",
311
+ "Phase 2: Wire Codex MCP",
312
+ "Phase 3: Restart and verify Codex",
313
+ "Phase 4: First Inspector query",
314
+ "Phase 5: Capture and memory review"
315
+ ];
316
+ }
317
+ });
318
+
117
319
  // src/cli/templates/skill-onboard.ts
118
320
  function renderSkillOnboard(ctx) {
119
321
  const { version, port, detectedSummary } = ctx;
@@ -660,7 +862,10 @@ function parseFlags(argv) {
660
862
  dryRun: false,
661
863
  skipProvider: false,
662
864
  skipToolWire: false,
663
- skillDir: null
865
+ codexOnly: false,
866
+ skipCodexSkill: false,
867
+ skillDir: null,
868
+ codexSkillDir: null
664
869
  };
665
870
  for (let i = 0; i < argv.length; i++) {
666
871
  const arg = argv[i];
@@ -679,6 +884,12 @@ function parseFlags(argv) {
679
884
  case "--skip-tool-wire":
680
885
  flags.skipToolWire = true;
681
886
  break;
887
+ case "--codex-only":
888
+ flags.codexOnly = true;
889
+ break;
890
+ case "--skip-codex-skill":
891
+ flags.skipCodexSkill = true;
892
+ break;
682
893
  case "--skill-dir": {
683
894
  const next = argv[i + 1];
684
895
  if (next === void 0) {
@@ -689,6 +900,18 @@ function parseFlags(argv) {
689
900
  i++;
690
901
  break;
691
902
  }
903
+ case "--codex-skill-dir": {
904
+ const next = argv[i + 1];
905
+ if (next === void 0) {
906
+ process.stderr.write(
907
+ "agent-inspector onboard: --codex-skill-dir requires a path argument\n"
908
+ );
909
+ process.exit(2);
910
+ }
911
+ flags.codexSkillDir = next;
912
+ i++;
913
+ break;
914
+ }
692
915
  case "--help":
693
916
  case "-h":
694
917
  printHelp();
@@ -703,18 +926,21 @@ function parseFlags(argv) {
703
926
  return flags;
704
927
  }
705
928
  function printHelp() {
706
- process.stdout.write(`agent-inspector onboard \u2014 install the agent-inspector Claude Code skill
929
+ process.stdout.write(`agent-inspector onboard - install Agent Inspector onboarding skills
707
930
 
708
931
  Usage:
709
932
  agent-inspector onboard [options]
710
933
 
711
934
  Options:
712
- --force Overwrite the existing skill and slash command if they exist
713
- --dry-run Print target paths and a template preview, write nothing
714
- --skip-provider Skip the provider-setup phase in the skill body
715
- --skip-tool-wire Skip the wire-tool phase in the skill body
716
- --skill-dir <path> Override the target skill directory (default: ~/.claude/skills)
717
- -h, --help Show this help
935
+ --force Overwrite existing generated skills and slash command
936
+ --dry-run Print target paths and template previews, write nothing
937
+ --skip-provider Skip the provider-setup phase in the Claude skill body
938
+ --skip-tool-wire Skip the wire-tool phase in the Claude skill body
939
+ --skip-codex-skill Install only the Claude Code skill and slash command
940
+ --codex-only Install only the Codex skill
941
+ --skill-dir <path> Override the target Claude root directory (default: ~/.claude)
942
+ --codex-skill-dir <path> Override the target Codex skills directory (default: ~/.codex/skills)
943
+ -h, --help Show this help
718
944
 
719
945
  Exit codes:
720
946
  0 success (or already installed)
@@ -724,11 +950,14 @@ Exit codes:
724
950
  }
725
951
  function resolveTargets(flags) {
726
952
  const claudeRoot = flags.skillDir ?? join2(homedir2(), ".claude");
727
- const skillDir = join2(claudeRoot, "skills", SKILL_DIR_NAME);
728
- const commandsDir = join2(claudeRoot, "commands");
953
+ const claudeSkillDir = join2(claudeRoot, "skills", SKILL_DIR_NAME);
954
+ const claudeCommandsDir = join2(claudeRoot, "commands");
955
+ const codexRoot = process.env["CODEX_HOME"] ?? join2(homedir2(), ".codex");
956
+ const codexSkillsDir = flags.codexSkillDir ?? join2(codexRoot, "skills");
729
957
  return {
730
- skillFile: join2(skillDir, SKILL_FILE_NAME),
731
- commandFile: join2(commandsDir, COMMAND_FILE_NAME)
958
+ claudeSkillFile: join2(claudeSkillDir, SKILL_FILE_NAME),
959
+ claudeCommandFile: join2(claudeCommandsDir, COMMAND_FILE_NAME),
960
+ codexSkillFile: join2(codexSkillsDir, SKILL_DIR_NAME, SKILL_FILE_NAME)
732
961
  };
733
962
  }
734
963
  function isObject(value) {
@@ -743,6 +972,54 @@ function buildDetectedSummary() {
743
972
  return ` - Detected: ${presentList}
744
973
  - Not detected: ${absentList}`;
745
974
  }
975
+ function readPackageVersion() {
976
+ try {
977
+ const raw = JSON.parse(readFileSync(join2(__dirname, "..", "package.json"), "utf8"));
978
+ if (isObject(raw) && typeof raw["version"] === "string") {
979
+ return raw["version"];
980
+ }
981
+ } catch {
982
+ }
983
+ return "0.0.0";
984
+ }
985
+ function buildPlannedFiles(flags, targets, version) {
986
+ const installClaude = !flags.codexOnly;
987
+ const installCodex = !flags.skipCodexSkill;
988
+ const detectedSummary = installClaude ? buildDetectedSummary() : "";
989
+ const claudeSkillBody = installClaude ? renderSkillOnboard({
990
+ version,
991
+ port: DEFAULT_PORT,
992
+ detectedSummary
993
+ }) : "";
994
+ const commandBody = installClaude ? renderCommandOnboard() : "";
995
+ const codexSkillBody = installCodex ? renderCodexSkillOnboard({
996
+ version,
997
+ port: DEFAULT_PORT
998
+ }) : "";
999
+ return [
1000
+ {
1001
+ label: "Claude skill",
1002
+ path: targets.claudeSkillFile,
1003
+ body: claudeSkillBody,
1004
+ enabled: installClaude
1005
+ },
1006
+ {
1007
+ label: "Claude command",
1008
+ path: targets.claudeCommandFile,
1009
+ body: commandBody,
1010
+ enabled: installClaude
1011
+ },
1012
+ {
1013
+ label: "Codex skill",
1014
+ path: targets.codexSkillFile,
1015
+ body: codexSkillBody,
1016
+ enabled: installCodex
1017
+ }
1018
+ ];
1019
+ }
1020
+ function shouldWrite(file, force) {
1021
+ return file.enabled && (force || !existsSync2(file.path));
1022
+ }
746
1023
  function runOnboard(argv) {
747
1024
  try {
748
1025
  return Promise.resolve(runOnboardSync(argv));
@@ -756,62 +1033,69 @@ function runOnboard(argv) {
756
1033
  }
757
1034
  function runOnboardSync(argv) {
758
1035
  const flags = parseFlags(argv);
759
- const { skillFile, commandFile } = resolveTargets(flags);
760
- if (!flags.force && existsSync2(skillFile)) {
761
- process.stdout.write(`agent-inspector onboard: already installed at ${skillFile}
762
- `);
763
- process.stdout.write("Re-run with --force to refresh.\n");
764
- return 0;
765
- }
766
- let version = "0.0.0";
767
- try {
768
- const raw = JSON.parse(readFileSync(join2(__dirname, "..", "package.json"), "utf8"));
769
- if (isObject(raw) && typeof raw["version"] === "string") {
770
- version = raw["version"];
771
- }
772
- } catch {
1036
+ const targets = resolveTargets(flags);
1037
+ const version = readPackageVersion();
1038
+ const plannedFiles = buildPlannedFiles(flags, targets, version);
1039
+ const enabledFiles = plannedFiles.filter((file) => file.enabled);
1040
+ if (enabledFiles.length === 0) {
1041
+ process.stderr.write("agent-inspector onboard: no onboarding target selected\n");
1042
+ return 2;
773
1043
  }
774
- const detectedSummary = buildDetectedSummary();
775
- const skillBody = renderSkillOnboard({
776
- version,
777
- port: DEFAULT_PORT,
778
- detectedSummary
779
- });
780
- const commandBody = renderCommandOnboard();
781
1044
  if (flags.dryRun) {
782
1045
  process.stdout.write(`agent-inspector onboard --dry-run
783
1046
 
784
1047
  `);
785
- process.stdout.write(`Skill target: ${skillFile}
1048
+ for (const file of enabledFiles) {
1049
+ const status = existsSync2(file.path) ? "exists" : "missing";
1050
+ process.stdout.write(`${file.label}: ${file.path} (${status})
786
1051
  `);
787
- process.stdout.write(`Command target: ${commandFile}
788
-
1052
+ }
1053
+ process.stdout.write(`
1054
+ Claude skill headings:
1055
+ `);
1056
+ if (!flags.codexOnly) {
1057
+ for (const heading of REQUIRED_PHASE_HEADINGS) {
1058
+ process.stdout.write(` - ${heading}
789
1059
  `);
790
- process.stdout.write(`Skill preview (first 5 lines + headings):
1060
+ }
1061
+ } else {
1062
+ process.stdout.write(` (disabled by --codex-only)
791
1063
  `);
792
- const previewLines = skillBody.split("\n").slice(0, 5);
793
- process.stdout.write(`${previewLines.join("\n")}
1064
+ }
1065
+ process.stdout.write(`
1066
+ Codex skill headings:
794
1067
  `);
795
- process.stdout.write(`...
1068
+ if (!flags.skipCodexSkill) {
1069
+ for (const heading of REQUIRED_CODEX_PHASE_HEADINGS) {
1070
+ process.stdout.write(` - ${heading}
796
1071
  `);
797
- for (const heading of REQUIRED_PHASE_HEADINGS) {
798
- process.stdout.write(` - ${heading}
1072
+ }
1073
+ } else {
1074
+ process.stdout.write(` (disabled by --skip-codex-skill)
799
1075
  `);
800
1076
  }
801
- process.stdout.write(`
1077
+ if (!flags.codexOnly) {
1078
+ process.stdout.write(`
802
1079
  Detected tools:
803
- ${detectedSummary}
1080
+ ${buildDetectedSummary()}
804
1081
  `);
1082
+ }
805
1083
  process.stdout.write(`
806
1084
  No files were written.
807
1085
  `);
808
1086
  return 0;
809
1087
  }
810
- mkdirSync(join2(skillFile, ".."), { recursive: true });
811
- mkdirSync(join2(commandFile, ".."), { recursive: true });
1088
+ const filesToWrite = plannedFiles.filter((file) => shouldWrite(file, flags.force));
1089
+ if (filesToWrite.length === 0) {
1090
+ process.stdout.write("agent-inspector onboard: all selected onboarding files already exist\n");
1091
+ process.stdout.write("Re-run with --force to refresh.\n");
1092
+ return 0;
1093
+ }
812
1094
  try {
813
- writeFileSync(skillFile, skillBody, "utf8");
814
- writeFileSync(commandFile, commandBody, "utf8");
1095
+ for (const file of filesToWrite) {
1096
+ mkdirSync(dirname(file.path), { recursive: true });
1097
+ writeFileSync(file.path, file.body, "utf8");
1098
+ }
815
1099
  } catch (err) {
816
1100
  const msg = err instanceof Error ? err.message : String(err);
817
1101
  process.stderr.write(`agent-inspector onboard: failed to write files: ${msg}
@@ -820,16 +1104,22 @@ No files were written.
820
1104
  }
821
1105
  const firstTool = detectFirst();
822
1106
  const toolHint = firstTool !== null ? firstTool.displayName : "no known tool detected";
823
- process.stdout.write(`Installed skill to: ${skillFile}
824
- `);
825
- process.stdout.write(`Installed command to: ${commandFile}
1107
+ for (const file of filesToWrite) {
1108
+ process.stdout.write(`Installed ${file.label} to: ${file.path}
826
1109
  `);
1110
+ }
827
1111
  process.stdout.write(`
828
1112
  Next steps:
829
1113
  `);
830
- process.stdout.write(` - Open Claude Code and run: /agent-inspector:onboard
1114
+ if (!flags.codexOnly) {
1115
+ process.stdout.write(` - Open Claude Code and run: /agent-inspector:onboard
831
1116
  `);
832
- process.stdout.write(` - Or refresh later: agent-inspector onboard --force
1117
+ }
1118
+ if (!flags.skipCodexSkill) {
1119
+ process.stdout.write(` - Open Codex and ask to use the agent-inspector-onboard skill
1120
+ `);
1121
+ }
1122
+ process.stdout.write(` - Refresh later: agent-inspector onboard --force
833
1123
  `);
834
1124
  process.stdout.write(` - Detected primary tool: ${toolHint}
835
1125
  `);
@@ -841,6 +1131,7 @@ var init_onboard = __esm({
841
1131
  "use strict";
842
1132
  init_detect_tools();
843
1133
  init_command_onboard();
1134
+ init_codex_skill_onboard();
844
1135
  init_skill_onboard();
845
1136
  __filename = fileURLToPath(import.meta.url);
846
1137
  __dirname = dirname(__filename);
@@ -1,5 +1,5 @@
1
1
  {
2
- "date": "2026-06-20T04:11:16.437Z",
2
+ "date": "2026-06-20T06:54:42.224Z",
3
3
  "preset": "node-server",
4
4
  "framework": {
5
5
  "name": "nitro",
@@ -1 +1 @@
1
- import{r as h,j as t}from"./main-yWf8dv9w.js";import{c as X,g as O,r as P,a as q,X as Y,b as x,B as Z,f as $,R as ee,C as te,M as _,d as J,e as M,h as B,i as re,j as ne}from"./ProxyViewerContainer-p9QvzZ6U.js";import{J as N}from"./json-viewer-CKNMihlh.js";const se=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],ae=X("equal",se),oe="";function j(e){if(e.length===0)return oe;let r="";for(let n=0;n<e.length;n++){const s=e[n];s!==void 0&&(typeof s=="number"?r+=`[${s}]`:n===0?r+=s:r+=`.${s}`)}return r}function de(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(de(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 ie(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,s){const d=j(e);if(E(r,n)){s.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const o=Object.keys(r.value),a=Object.keys(n.value),m=new Set(a);for(const i of o){const f=r.value[i];if(f!==void 0)if(!m.has(i))s.push({kind:"removed",path:j([...e,i]),value:f});else{const p=n.value[i];if(p===void 0)continue;R([...e,i],f,p,s)}}for(const i of a){if(o.includes(i))continue;const f=n.value[i];f!==void 0&&s.push({kind:"added",path:j([...e,i]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const o=Math.min(r.value.length,n.value.length);for(let a=0;a<o;a++){const m=r.value[a],i=n.value[a];m===void 0||i===void 0||R([...e,a],m,i,s)}for(let a=o;a<n.value.length;a++){const m=n.value[a];m!==void 0&&s.push({kind:"added",path:j([...e,a]),value:m})}for(let a=o;a<r.value.length;a++){const m=r.value[a];m!==void 0&&s.push({kind:"removed",path:j([...e,a]),value:m})}}}function E(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 s=e.value[n],d=r.value[n];if(s===void 0||d===void 0||!E(s,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),s=Object.keys(r.value);if(n.length!==s.length)return!1;for(const d of n){const o=e.value[d],a=r.value[d];if(o===void 0||a===void 0||!E(o,a))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 w(e,r=2){return JSON.stringify(S(e),null,r)}function S(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(S);case"object":{const r={};for(const[n,s]of Object.entries(e.value))r[n]=S(s);return r}}}function L(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 le(e){const r=[];let n=0;for(;n<e.length;){const s=e[n];if(s!==void 0&&A(s)){const d=L(s.path);let o=n+1;for(;o<e.length;){const a=e[o];if(a===void 0||!A(a)||L(a.path)!==d)break;o++}if(o-n>1){const a=[];for(let m=n;m<o;m++){const i=e[m];i!==void 0&&i.kind==="equal"&&a.push(i)}r.push({kind:"equal-run",ops:a}),n=o;continue}}s!==void 0&&r.push({kind:"single",op:s}),n++}return r}const V={added:{icon:J,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:_,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:ae,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function ce({ops:e,expanded:r,onToggle:n}){const s=e[0],d=e[e.length-1];if(s===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const o=s.path,a=d.path,m=e.length===1?o:`${o} … ${a}`,i=s.value.kind==="array"?`${e.length} equal arrays`:s.value.kind==="object"?`${e.length} equal objects`:"equal",f=V.equal;return t.jsxs("div",{className:x("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:x("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:x("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${o} … ${a}`,children:m}),t.jsx("span",{className:x("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",i,")"]})]}),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(N,{text:w(p.value),defaultExpandDepth:0})]},p.path))})]})}function ue({op:e,idx:r,copiedPath:n,onCopyPath:s,expanded:d,onToggle:o}){const a=V[e.kind],m=a.icon,i=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:x("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",a.border,a.bg),children:[t.jsxs("button",{type:"button",onClick:o,disabled:!i,className:x("w-full flex items-center gap-2 text-xs text-left rounded-sm",i?"cursor-pointer":"cursor-default"),"aria-expanded":i?d:void 0,"aria-label":i?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[i?t.jsx(B,{className:x("size-3 shrink-0 transition-transform",a.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(m,{className:x("size-3.5 shrink-0",a.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:x("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",a.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:a.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),s(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),s(e.path))},className:x("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(re,{className:"size-3"}):t.jsx(ne,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:x("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&&i?"2000px":"0"},"aria-hidden":!d,children:d&&i&&e.kind!=="equal"?t.jsx(me,{op:e}):null})]})}function me({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(N,{text:w(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(N,{text:w(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(N,{text:w(e.right),defaultExpandDepth:0})]})]})}function xe({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:x("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(_,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>r("added"),disabled:e.added===0,className:x("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(J,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:x("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 fe({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:x("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(ee,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:x("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(te,{className:"size-3"}),"Split"]})]})}function K({log:e,side:r}){const n=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(Z,{variant:"outline",className:x("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",children:["#",e.id]}),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:["Cache +",$(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["Cache ~",$(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:n,children:["session: ",n]})]})}function ge({left:e,right:r,onClose:n}){const s=h.useMemo(()=>{const l=O(P(e)).analyzeRequest(e.rawRequestBody),c=O(P(r)).analyzeRequest(r.rawRequestBody),u=D(l.comparisonValue),g=D(c.comparisonValue);return ie(u,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),d=h.useMemo(()=>le(s),[s]),o=h.useMemo(()=>{let l=0,c=0,u=0;for(const g of d)if(g.kind==="single")switch(g.op.kind){case"added":l++;break;case"removed":c++;break;case"changed":u++;break}return{added:l,removed:c,changed:u}},[d]),[a,m]=h.useState(new Set),i=l=>{m(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})},[f,p]=h.useState(new Set),b=l=>{p(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})};h.useEffect(()=>{p(new Set)},[e.id,r.id]);const[y,F]=h.useState("unified"),T=h.useRef(null),[U,z]=h.useState(null),k=h.useRef(null),H=l=>{window.navigator.clipboard.writeText(l).then(()=>{z(l),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500)})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const G=l=>{const c=d.findIndex(I=>I.kind==="single"&&I.op.kind===l);if(c===-1)return;const u=T.current;if(u===null)return;const g=u.querySelector(`[data-diff-idx="${c}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const l=u=>{u.key==="Escape"&&n()};document.addEventListener("keydown",l);const c=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",l),document.body.style.overflow=c}},[n]);const Q=q(e)===q(r),W=s.length===1&&s[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:n,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:x("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:l=>l.stopPropagation(),onKeyDown:l=>l.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(K,{log:e,side:"left"}),t.jsx(K,{log:r,side:"right"})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(fe,{mode:y,onChange:F}),t.jsx("button",{type:"button",onClick:n,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(Y,{className:"size-4"})})]})]}),!Q&&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."}),W?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(xe,{counts:o,onJumpTo:G}),t.jsx("div",{ref:T,className:"flex-1 min-h-0 overflow-y-auto",children:y==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:d.map((l,c)=>{if(l.kind==="equal-run")return t.jsx(ce,{ops:l.ops,expanded:a.has(c),onToggle:()=>i(c)},`r${c}`);const u=l.op;return t.jsx(ue,{op:u,idx:c,copiedPath:U,onCopyPath:H,expanded:f.has(c),onToggle:()=>b(c)},`o${c}`)})}):t.jsx(pe,{grouped:d,left:e,right:r})})]})]})]})}function pe({grouped:e,left:r,right:n}){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",{children:["Left (Log #",r.id,")"]}),t.jsxs("span",{children:["Right (Log #",n.id,")"]})]}),e.map((s,d)=>{if(s.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[s.ops.length," equal siblings collapsed — switch to Unified to expand"]},d);const o=s.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)})]},d):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)]})]},d):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)]})]},d):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)})]})]},d)})]})}export{ge as CompareDrawer};
1
+ import{r as h,j as t}from"./main-FSGUGtEL.js";import{c as X,g as O,r as P,a as q,X as Y,b as x,B as Z,f as $,R as ee,C as te,M as _,d as J,e as M,h as B,i as re,j as ne}from"./ProxyViewerContainer-USuxPy-K.js";import{J as N}from"./json-viewer-6uV_YXws.js";const se=[["line",{x1:"5",x2:"19",y1:"9",y2:"9",key:"1nwqeh"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15",key:"g8yjpy"}]],ae=X("equal",se),oe="";function j(e){if(e.length===0)return oe;let r="";for(let n=0;n<e.length;n++){const s=e[n];s!==void 0&&(typeof s=="number"?r+=`[${s}]`:n===0?r+=s:r+=`.${s}`)}return r}function de(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(de(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 ie(e,r){const n=[];return R([],e,r,n),n}function R(e,r,n,s){const d=j(e);if(E(r,n)){s.push({kind:"equal",path:d,value:r});return}if(r.kind!==n.kind){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="primitive"&&n.kind==="primitive"){s.push({kind:"changed",path:d,left:r,right:n});return}if(r.kind==="object"&&n.kind==="object"){const o=Object.keys(r.value),a=Object.keys(n.value),m=new Set(a);for(const i of o){const f=r.value[i];if(f!==void 0)if(!m.has(i))s.push({kind:"removed",path:j([...e,i]),value:f});else{const p=n.value[i];if(p===void 0)continue;R([...e,i],f,p,s)}}for(const i of a){if(o.includes(i))continue;const f=n.value[i];f!==void 0&&s.push({kind:"added",path:j([...e,i]),value:f})}return}if(r.kind==="array"&&n.kind==="array"){const o=Math.min(r.value.length,n.value.length);for(let a=0;a<o;a++){const m=r.value[a],i=n.value[a];m===void 0||i===void 0||R([...e,a],m,i,s)}for(let a=o;a<n.value.length;a++){const m=n.value[a];m!==void 0&&s.push({kind:"added",path:j([...e,a]),value:m})}for(let a=o;a<r.value.length;a++){const m=r.value[a];m!==void 0&&s.push({kind:"removed",path:j([...e,a]),value:m})}}}function E(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 s=e.value[n],d=r.value[n];if(s===void 0||d===void 0||!E(s,d))return!1}return!0}if(e.kind==="object"&&r.kind==="object"){const n=Object.keys(e.value),s=Object.keys(r.value);if(n.length!==s.length)return!1;for(const d of n){const o=e.value[d],a=r.value[d];if(o===void 0||a===void 0||!E(o,a))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 w(e,r=2){return JSON.stringify(S(e),null,r)}function S(e){switch(e.kind){case"primitive":return e.value;case"array":return e.value.map(S);case"object":{const r={};for(const[n,s]of Object.entries(e.value))r[n]=S(s);return r}}}function L(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 le(e){const r=[];let n=0;for(;n<e.length;){const s=e[n];if(s!==void 0&&A(s)){const d=L(s.path);let o=n+1;for(;o<e.length;){const a=e[o];if(a===void 0||!A(a)||L(a.path)!==d)break;o++}if(o-n>1){const a=[];for(let m=n;m<o;m++){const i=e[m];i!==void 0&&i.kind==="equal"&&a.push(i)}r.push({kind:"equal-run",ops:a}),n=o;continue}}s!==void 0&&r.push({kind:"single",op:s}),n++}return r}const V={added:{icon:J,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:_,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:ae,accent:"text-muted-foreground/70",bg:"bg-muted/20 hover:bg-muted/30",border:"border-l-muted-foreground/20",label:"EQUAL"}};function ce({ops:e,expanded:r,onToggle:n}){const s=e[0],d=e[e.length-1];if(s===void 0||d===void 0)return t.jsx("div",{className:"text-muted-foreground/40 text-xs",children:"—"});const o=s.path,a=d.path,m=e.length===1?o:`${o} … ${a}`,i=s.value.kind==="array"?`${e.length} equal arrays`:s.value.kind==="object"?`${e.length} equal objects`:"equal",f=V.equal;return t.jsxs("div",{className:x("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:x("size-3 transition-transform shrink-0",r&&"rotate-90")}),t.jsx(f.icon,{className:x("size-3 shrink-0",f.accent)}),t.jsx("span",{className:"font-mono truncate flex-1",title:`${o} … ${a}`,children:m}),t.jsx("span",{className:x("text-[10px] uppercase tracking-wider shrink-0",f.accent),children:f.label}),t.jsxs("span",{className:"text-muted-foreground/60 shrink-0",children:["(",i,")"]})]}),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(N,{text:w(p.value),defaultExpandDepth:0})]},p.path))})]})}function ue({op:e,idx:r,copiedPath:n,onCopyPath:s,expanded:d,onToggle:o}){const a=V[e.kind],m=a.icon,i=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:x("border-l-4 rounded-sm px-3 py-2 my-0.5 transition-colors",a.border,a.bg),children:[t.jsxs("button",{type:"button",onClick:o,disabled:!i,className:x("w-full flex items-center gap-2 text-xs text-left rounded-sm",i?"cursor-pointer":"cursor-default"),"aria-expanded":i?d:void 0,"aria-label":i?d?`Collapse ${e.path||"root"}`:`Expand ${e.path||"root"}`:void 0,children:[i?t.jsx(B,{className:x("size-3 shrink-0 transition-transform",a.accent,d&&"rotate-90")}):t.jsx("span",{className:"size-3 shrink-0","aria-hidden":"true"}),t.jsx(m,{className:x("size-3.5 shrink-0",a.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:x("text-[9px] font-bold uppercase tracking-wider shrink-0 px-1.5 py-0.5 rounded",a.accent,e.kind==="equal"?"bg-muted/40":"bg-background/60"),children:a.label}),e.path!==""&&t.jsx("span",{role:"button",tabIndex:0,onClick:b=>{b.stopPropagation(),s(e.path)},onKeyDown:b=>{(b.key==="Enter"||b.key===" ")&&(b.stopPropagation(),b.preventDefault(),s(e.path))},className:x("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(re,{className:"size-3"}):t.jsx(ne,{className:"size-3"})})]}),f.map((b,y)=>t.jsx("div",{className:x("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&&i?"2000px":"0"},"aria-hidden":!d,children:d&&i&&e.kind!=="equal"?t.jsx(me,{op:e}):null})]})}function me({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(N,{text:w(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(N,{text:w(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(N,{text:w(e.right),defaultExpandDepth:0})]})]})}function xe({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:x("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(_,{className:"size-3"}),e.removed," removed"]}),t.jsxs("button",{type:"button",onClick:()=>r("added"),disabled:e.added===0,className:x("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(J,{className:"size-3"}),e.added," added"]}),t.jsxs("button",{type:"button",onClick:()=>r("changed"),disabled:e.changed===0,className:x("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 fe({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:x("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(ee,{className:"size-3"}),"Unified"]}),t.jsxs("button",{type:"button",onClick:()=>r("split"),"aria-pressed":e==="split",className:x("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(te,{className:"size-3"}),"Split"]})]})}function K({log:e,side:r}){const n=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(Z,{variant:"outline",className:x("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",children:["#",e.id]}),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:["Cache +",$(e.cacheCreationInputTokens)]}),e.cacheReadInputTokens!==null&&e.cacheReadInputTokens>0&&t.jsxs("span",{className:"text-purple-400",children:["Cache ~",$(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:n,children:["session: ",n]})]})}function ge({left:e,right:r,onClose:n}){const s=h.useMemo(()=>{const l=O(P(e)).analyzeRequest(e.rawRequestBody),c=O(P(r)).analyzeRequest(r.rawRequestBody),u=D(l.comparisonValue),g=D(c.comparisonValue);return ie(u,g)},[e.apiFormat,e.path,e.rawRequestBody,r.apiFormat,r.path,r.rawRequestBody]),d=h.useMemo(()=>le(s),[s]),o=h.useMemo(()=>{let l=0,c=0,u=0;for(const g of d)if(g.kind==="single")switch(g.op.kind){case"added":l++;break;case"removed":c++;break;case"changed":u++;break}return{added:l,removed:c,changed:u}},[d]),[a,m]=h.useState(new Set),i=l=>{m(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})},[f,p]=h.useState(new Set),b=l=>{p(c=>{const u=new Set(c);return u.has(l)?u.delete(l):u.add(l),u})};h.useEffect(()=>{p(new Set)},[e.id,r.id]);const[y,F]=h.useState("unified"),T=h.useRef(null),[U,z]=h.useState(null),k=h.useRef(null),H=l=>{window.navigator.clipboard.writeText(l).then(()=>{z(l),k.current!==null&&clearTimeout(k.current),k.current=setTimeout(()=>z(null),1500)})};h.useEffect(()=>()=>{k.current!==null&&clearTimeout(k.current)},[]);const G=l=>{const c=d.findIndex(I=>I.kind==="single"&&I.op.kind===l);if(c===-1)return;const u=T.current;if(u===null)return;const g=u.querySelector(`[data-diff-idx="${c}"]`);g!==null&&g.scrollIntoView({behavior:"smooth",block:"center"})};h.useEffect(()=>{const l=u=>{u.key==="Escape"&&n()};document.addEventListener("keydown",l);const c=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",l),document.body.style.overflow=c}},[n]);const Q=q(e)===q(r),W=s.length===1&&s[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:n,"aria-label":"Close compare drawer",className:"absolute inset-0 bg-black/40 cursor-default",tabIndex:-1}),t.jsxs("div",{className:x("relative bg-background border-l border-border shadow-xl","w-full md:w-[70vw] max-w-[1100px] flex flex-col h-full"),onClick:l=>l.stopPropagation(),onKeyDown:l=>l.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(K,{log:e,side:"left"}),t.jsx(K,{log:r,side:"right"})]}),t.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[t.jsx(fe,{mode:y,onChange:F}),t.jsx("button",{type:"button",onClick:n,"aria-label":"Close",className:"p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer",children:t.jsx(Y,{className:"size-4"})})]})]}),!Q&&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."}),W?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(xe,{counts:o,onJumpTo:G}),t.jsx("div",{ref:T,className:"flex-1 min-h-0 overflow-y-auto",children:y==="unified"?t.jsx("div",{className:"px-3 py-2 space-y-0.5",children:d.map((l,c)=>{if(l.kind==="equal-run")return t.jsx(ce,{ops:l.ops,expanded:a.has(c),onToggle:()=>i(c)},`r${c}`);const u=l.op;return t.jsx(ue,{op:u,idx:c,copiedPath:U,onCopyPath:H,expanded:f.has(c),onToggle:()=>b(c)},`o${c}`)})}):t.jsx(pe,{grouped:d,left:e,right:r})})]})]})]})}function pe({grouped:e,left:r,right:n}){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",{children:["Left (Log #",r.id,")"]}),t.jsxs("span",{children:["Right (Log #",n.id,")"]})]}),e.map((s,d)=>{if(s.kind==="equal-run")return t.jsxs("div",{className:"col-span-3 px-2 py-1 text-xs text-muted-foreground/60",children:[s.ops.length," equal siblings collapsed — switch to Unified to expand"]},d);const o=s.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)})]},d):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)]})]},d):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)]})]},d):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)})]})]},d)})]})}export{ge as CompareDrawer};