@tonyclaw/agent-inspector 3.0.7 → 3.0.9

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 (73) hide show
  1. package/.output/cli.js +245 -171
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/{CompareDrawer-C0Kbsm-Q.js → CompareDrawer-CJKL4LMm.js} +1 -1
  4. package/.output/public/assets/ProxyViewerContainer-DBUy29O-.js +106 -0
  5. package/.output/public/assets/ReplayDialog-BYanl-a_.js +1 -0
  6. package/.output/public/assets/{RequestAnatomy-fa0JXy5p.js → RequestAnatomy-DvPz1jqE.js} +1 -1
  7. package/.output/public/assets/ResponseView-sZnxp9GN.js +3 -0
  8. package/.output/public/assets/StreamingChunkSequence-G-tiYiBd.js +1 -0
  9. package/.output/public/assets/{_sessionId-D5fYH2C0.js → _sessionId-_hDcsmXq.js} +1 -1
  10. package/.output/public/assets/agent-inspector-58K1_MsC.ico +0 -0
  11. package/.output/public/assets/index-DAPAWsAd.js +1 -0
  12. package/.output/public/assets/index-DspnLqUW.css +1 -0
  13. package/.output/public/assets/{index-BEsqvywM.js → index-SuOSQb2_.js} +1 -1
  14. package/.output/public/assets/{json-viewer-B0QRbMSf.js → json-viewer-yQdhgjaw.js} +1 -1
  15. package/.output/public/assets/{main-CuKZD7n0.js → main-CgjcDxjR.js} +2 -2
  16. package/.output/server/_libs/radix-ui__react-dialog.mjs +2 -2
  17. package/.output/server/{_sessionId-DdBTK3qm.mjs → _sessionId-BGISf2En.mjs} +3 -3
  18. package/.output/server/_ssr/{CompareDrawer-m82cVZ73.mjs → CompareDrawer-s-UF9gW3.mjs} +2 -2
  19. package/.output/server/_ssr/{ProxyViewerContainer-7geuf78f.mjs → ProxyViewerContainer-C0Sbz9ED.mjs} +1033 -530
  20. package/.output/server/_ssr/{ReplayDialog-B8RlWLLH.mjs → ReplayDialog-DvS8gvJr.mjs} +58 -23
  21. package/.output/server/_ssr/{RequestAnatomy-BE7pmwpv.mjs → RequestAnatomy-BwhWglJL.mjs} +2 -2
  22. package/.output/server/_ssr/{ResponseView-D-sDsdQr.mjs → ResponseView-wBVreqQf.mjs} +2 -2
  23. package/.output/server/_ssr/{StreamingChunkSequence-DU_hThJr.mjs → StreamingChunkSequence-Dr6eg-MJ.mjs} +30 -20
  24. package/.output/server/_ssr/{index-D0sV8UbE.mjs → index-B98Wia1X.mjs} +2 -2
  25. package/.output/server/_ssr/index.mjs +2 -2
  26. package/.output/server/_ssr/{json-viewer-CaDh1zrw.mjs → json-viewer-D7L8y0FH.mjs} +2 -2
  27. package/.output/server/_ssr/{router-Zh2iZ_u0.mjs → router-g9mo0nWT.mjs} +459 -196
  28. package/.output/server/_tanstack-start-manifest_v-CbGc-o50.mjs +4 -0
  29. package/.output/server/index.mjs +76 -69
  30. package/package.json +1 -1
  31. package/src/assets/IDE/opencode.svg +1 -1
  32. package/src/assets/IDE/xiaomimimo.svg +1 -1
  33. package/src/cli/detect-tools.ts +2 -27
  34. package/src/cli/templates/codex-skill-onboard.ts +1 -1
  35. package/src/cli/templates/skill-onboard.ts +2 -3
  36. package/src/cli.ts +9 -86
  37. package/src/components/ProxyViewer.tsx +249 -37
  38. package/src/components/ProxyViewerContainer.tsx +167 -22
  39. package/src/components/clients/ClientLogo.tsx +38 -3
  40. package/src/components/ecosystem/AgentLabDialog.tsx +204 -3
  41. package/src/components/groups/GroupsDialog.tsx +28 -40
  42. package/src/components/providers/ImportWizardDialog.tsx +51 -101
  43. package/src/components/providers/ProvidersPanel.tsx +82 -68
  44. package/src/components/providers/SettingsDialog.tsx +11 -12
  45. package/src/components/proxy-viewer/AgentTraceSummary.tsx +15 -23
  46. package/src/components/proxy-viewer/ReplayDialog.tsx +65 -22
  47. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +33 -20
  48. package/src/components/proxy-viewer/TurnGroup.tsx +0 -16
  49. package/src/components/proxy-viewer/log-formats/anthropic.ts +5 -5
  50. package/src/components/proxy-viewer/log-formats/openai.ts +7 -10
  51. package/src/components/proxy-viewer/requestTools.ts +5 -2
  52. package/src/lib/apiClient.ts +43 -10
  53. package/src/lib/ecosystemContract.ts +32 -0
  54. package/src/lib/export-logs.ts +37 -3
  55. package/src/proxy/ecosystemRegistry.ts +244 -0
  56. package/src/proxy/ecosystemTasks.ts +153 -0
  57. package/src/proxy/platformCommands.ts +212 -0
  58. package/src/proxy/socketTracker.ts +84 -143
  59. package/src/routes/api/ecosystem.packages.$packageId.help.ts +16 -0
  60. package/src/routes/api/ecosystem.packages.$packageId.install.ts +16 -0
  61. package/src/routes/api/ecosystem.packages.$packageId.runner-presets.ts +19 -0
  62. package/src/routes/api/ecosystem.packages.$packageId.upgrade.ts +16 -0
  63. package/src/routes/api/ecosystem.packages.ts +1 -248
  64. package/src/routes/api/ecosystem.tasks.$taskId.ts +16 -0
  65. package/src/routes/api/ecosystem.tasks.ts +12 -0
  66. package/src/routes/api/providers.$providerId.test.log.ts +28 -24
  67. package/.output/public/assets/ProxyViewerContainer-p-rpYyiF.js +0 -106
  68. package/.output/public/assets/ReplayDialog-CM3dhP8v.js +0 -1
  69. package/.output/public/assets/ResponseView-Bq6sC7Ay.js +0 -3
  70. package/.output/public/assets/StreamingChunkSequence-CGOun3Df.js +0 -1
  71. package/.output/public/assets/index-C29Olfzt.js +0 -1
  72. package/.output/public/assets/index-DgANE0r3.css +0 -1
  73. package/.output/server/_tanstack-start-manifest_v-LCE-2AaF.mjs +0 -4
package/.output/cli.js CHANGED
@@ -61,62 +61,195 @@ var init_dataDir = __esm({
61
61
  }
62
62
  });
63
63
 
64
- // src/cli/detect-tools.ts
64
+ // src/proxy/platformCommands.ts
65
+ import { statSync } from "node:fs";
65
66
  import { execFileSync } from "node:child_process";
66
- import { existsSync as existsSync2 } from "node:fs";
67
- import { join as join2 } from "node:path";
68
- import { homedir } from "node:os";
69
- function which(bin) {
67
+ import { delimiter, isAbsolute as isAbsolute2, join as join2 } from "node:path";
68
+ function pathEntries(envPath) {
69
+ if (envPath === void 0 || envPath.length === 0) return [];
70
+ return envPath.split(delimiter).filter((entry) => entry.length > 0);
71
+ }
72
+ function windowsExecutableExtensions(envPathExt) {
73
+ const defaults = [".COM", ".EXE", ".BAT", ".CMD"];
74
+ if (envPathExt === void 0 || envPathExt.trim().length === 0) return defaults;
75
+ const parsed = envPathExt.split(";").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
76
+ return parsed.length > 0 ? parsed : defaults;
77
+ }
78
+ function isExecutableCandidate(path2, platform) {
70
79
  try {
71
- if (process.platform === "win32") {
72
- const out2 = execFileSync("where", [bin], {
80
+ const stat3 = statSync(path2);
81
+ if (!stat3.isFile()) return false;
82
+ if (platform === "win32" || process.platform === "win32") return true;
83
+ return (stat3.mode & 73) !== 0;
84
+ } catch {
85
+ return false;
86
+ }
87
+ }
88
+ function executableCandidates(bin, platform, env) {
89
+ if (isAbsolute2(bin)) return [bin];
90
+ const entries = pathEntries(env["PATH"] ?? env["Path"] ?? env["path"]);
91
+ if (platform !== "win32") return entries.map((entry) => join2(entry, bin));
92
+ const hasExtension = /\.[^\\/]+$/.test(bin);
93
+ const extensions = hasExtension ? [""] : windowsExecutableExtensions(env["PATHEXT"]);
94
+ const candidates = [];
95
+ for (const entry of entries) {
96
+ for (const extension of extensions) {
97
+ candidates.push(join2(entry, `${bin}${extension.toLowerCase()}`));
98
+ candidates.push(join2(entry, `${bin}${extension.toUpperCase()}`));
99
+ }
100
+ }
101
+ return candidates;
102
+ }
103
+ function resolveExecutableOnPath(bin, platform = process.platform, env = process.env) {
104
+ if (bin.trim().length === 0) return null;
105
+ for (const candidate of executableCandidates(bin, platform, env)) {
106
+ if (isExecutableCandidate(candidate, platform)) return candidate;
107
+ }
108
+ return null;
109
+ }
110
+ function openUrlCommand(targetUrl, platform = process.platform) {
111
+ switch (platform) {
112
+ case "darwin":
113
+ return { command: "open", args: [targetUrl] };
114
+ case "linux":
115
+ case "freebsd":
116
+ case "openbsd":
117
+ case "netbsd":
118
+ return { command: "xdg-open", args: [targetUrl] };
119
+ case "win32":
120
+ return { command: "cmd.exe", args: ["/d", "/s", "/c", "start", "", targetUrl] };
121
+ case "aix":
122
+ case "android":
123
+ case "cygwin":
124
+ case "haiku":
125
+ case "sunos":
126
+ return null;
127
+ }
128
+ return null;
129
+ }
130
+ function parseWindowsNetstatPids(output, targetPort) {
131
+ const pids = /* @__PURE__ */ new Set();
132
+ const targetToken = `:${targetPort}`;
133
+ for (const line of output.split(/\r?\n/)) {
134
+ const parts = line.trim().split(/\s+/);
135
+ if (parts.length < 5) continue;
136
+ const localAddress = parts[1] ?? "";
137
+ const pidStr = parts[4] ?? "";
138
+ if (!localAddress.endsWith(targetToken)) continue;
139
+ const pid = Number.parseInt(pidStr, 10);
140
+ if (Number.isInteger(pid) && pid > 0) pids.add(pid);
141
+ }
142
+ return [...pids];
143
+ }
144
+ function parseUnixLsofPids(output) {
145
+ const pids = /* @__PURE__ */ new Set();
146
+ for (const line of output.split(/\r?\n/)) {
147
+ const pid = Number.parseInt(line.trim(), 10);
148
+ if (Number.isInteger(pid) && pid > 0) pids.add(pid);
149
+ }
150
+ return [...pids];
151
+ }
152
+ function parseUnixSsPids(output) {
153
+ const pids = /* @__PURE__ */ new Set();
154
+ for (const match of output.matchAll(/pid=(\d+)/g)) {
155
+ const pid = Number.parseInt(match[1] ?? "", 10);
156
+ if (Number.isInteger(pid) && pid > 0) pids.add(pid);
157
+ }
158
+ return [...pids];
159
+ }
160
+ function findPidsByPort(targetPort, platform = process.platform) {
161
+ if (!Number.isInteger(targetPort) || targetPort <= 0 || targetPort > 65535) return [];
162
+ try {
163
+ if (platform === "win32") {
164
+ const output2 = execFileSync("netstat.exe", ["-ano", "-p", "TCP"], {
73
165
  encoding: "utf8",
74
- timeout: 3e3,
75
- windowsHide: true,
166
+ timeout: 5e3,
167
+ windowsHide: true
168
+ });
169
+ return parseWindowsNetstatPids(output2, targetPort);
170
+ }
171
+ try {
172
+ const output2 = execFileSync("lsof", [`-ti:${String(targetPort)}`], {
173
+ encoding: "utf8",
174
+ timeout: 5e3,
76
175
  stdio: ["ignore", "pipe", "ignore"]
77
176
  });
78
- const first = out2.split(/\r?\n/).find((line) => line.trim().length > 0);
79
- return first?.trim() ?? null;
177
+ const pids = parseUnixLsofPids(output2);
178
+ if (pids.length > 0) return pids;
179
+ } catch {
80
180
  }
81
- const out = execFileSync("sh", ["-c", `command -v ${bin}`], {
181
+ const output = execFileSync("ss", ["-tanp"], {
82
182
  encoding: "utf8",
83
- timeout: 3e3,
183
+ timeout: 5e3,
84
184
  stdio: ["ignore", "pipe", "ignore"]
85
185
  });
86
- return out.trim() || null;
186
+ return parseUnixSsPids(
187
+ output.split(/\r?\n/).filter((line) => line.includes(`:${String(targetPort)}`)).join("\n")
188
+ );
87
189
  } catch {
88
- return null;
190
+ return [];
191
+ }
192
+ }
193
+ function killPid(pid, platform = process.platform) {
194
+ if (!Number.isInteger(pid) || pid <= 0) return false;
195
+ try {
196
+ if (platform === "win32") {
197
+ execFileSync("taskkill.exe", ["/PID", String(pid), "/F"], {
198
+ encoding: "utf8",
199
+ timeout: 5e3,
200
+ windowsHide: true,
201
+ stdio: ["ignore", "pipe", "ignore"]
202
+ });
203
+ return true;
204
+ }
205
+ process.kill(pid, "SIGKILL");
206
+ return true;
207
+ } catch {
208
+ return false;
209
+ }
210
+ }
211
+ var init_platformCommands = __esm({
212
+ "src/proxy/platformCommands.ts"() {
213
+ "use strict";
89
214
  }
215
+ });
216
+
217
+ // src/cli/detect-tools.ts
218
+ import { existsSync as existsSync2 } from "node:fs";
219
+ import { join as join3 } from "node:path";
220
+ import { homedir } from "node:os";
221
+ function which(bin) {
222
+ return resolveExecutableOnPath(bin);
90
223
  }
91
224
  function tryDir(path2) {
92
225
  return existsSync2(path2) ? path2 : null;
93
226
  }
94
227
  function detectClaudeCode() {
95
- const configDir = tryDir(join2(homedir(), ".claude"));
228
+ const configDir = tryDir(join3(homedir(), ".claude"));
96
229
  const bin = which("claude");
97
230
  if (configDir === null && bin === null) return { found: false };
98
231
  return { found: true, path: configDir ?? bin ?? "" };
99
232
  }
100
233
  function detectOpenCode() {
101
- const configDir = tryDir(join2(homedir(), ".config", "opencode"));
234
+ const configDir = tryDir(join3(homedir(), ".config", "opencode"));
102
235
  const bin = which("opencode");
103
236
  if (configDir === null && bin === null) return { found: false };
104
237
  return { found: true, path: configDir ?? bin ?? "" };
105
238
  }
106
239
  function detectMiMo() {
107
- const configDir = tryDir(join2(homedir(), ".config", "mimocode")) ?? tryDir(join2(homedir(), ".mimocode"));
240
+ const configDir = tryDir(join3(homedir(), ".config", "mimocode")) ?? tryDir(join3(homedir(), ".mimocode"));
108
241
  const bin = which("mimo");
109
242
  if (configDir === null && bin === null) return { found: false };
110
243
  return { found: true, path: configDir ?? bin ?? "" };
111
244
  }
112
245
  function detectCursor() {
113
- const configDir = tryDir(join2(homedir(), ".cursor"));
246
+ const configDir = tryDir(join3(homedir(), ".cursor"));
114
247
  const bin = which("cursor");
115
248
  if (configDir === null && bin === null) return { found: false };
116
249
  return { found: true, path: configDir ?? bin ?? "" };
117
250
  }
118
251
  function detectCody() {
119
- const configDir = tryDir(join2(homedir(), ".config", "cody"));
252
+ const configDir = tryDir(join3(homedir(), ".config", "cody"));
120
253
  const bin = which("cody");
121
254
  if (configDir === null && bin === null) return { found: false };
122
255
  return { found: true, path: configDir ?? bin ?? "" };
@@ -139,6 +272,7 @@ var DETECTORS;
139
272
  var init_detect_tools = __esm({
140
273
  "src/cli/detect-tools.ts"() {
141
274
  "use strict";
275
+ init_platformCommands();
142
276
  DETECTORS = [
143
277
  { id: "claude-code", displayName: "Claude Code", detect: detectClaudeCode },
144
278
  { id: "opencode", displayName: "OpenCode", detect: detectOpenCode },
@@ -218,7 +352,7 @@ Test-Path (Join-Path $env:USERPROFILE ".codex\\config.toml")
218
352
  \`\`\`
219
353
 
220
354
  \`\`\`bash
221
- command -v agent-inspector || true
355
+ node -e "const fs=require('node:fs'),p=require('node:path');const names=process.platform==='win32'?['agent-inspector.cmd','agent-inspector.exe','agent-inspector']:['agent-inspector'];const found=(process.env.PATH||'').split(p.delimiter).some(d=>names.some(n=>fs.existsSync(p.join(d,n))));console.log(found?'agent-inspector: present':'agent-inspector: missing')"
222
356
  agent-inspector onboard --status
223
357
  test -d "$HOME/.codex" && echo "codex home: present" || echo "codex home: missing"
224
358
  test -f "$HOME/.codex/config.toml" && echo "config: present" || echo "config: missing"
@@ -572,14 +706,13 @@ if ((Test-Path $projMcp) -and (Select-String -Path $projMcp -Pattern 'agent-insp
572
706
  \`\`\`bash
573
707
  # Unix / macOS / WSL
574
708
  node --version # expect >= 18
575
- command -v claude >/dev/null && echo "claude-code: present" || echo "claude-code: not detected"
709
+ node -e "const fs=require('node:fs'),p=require('node:path');const names=process.platform==='win32'?['claude.cmd','claude.exe','claude']:['claude'];const found=(process.env.PATH||'').split(p.delimiter).some(d=>names.some(n=>fs.existsSync(p.join(d,n))));console.log(found?'claude-code: present':'claude-code: not detected')"
576
710
  \`\`\`
577
711
 
578
712
  \`\`\`powershell
579
713
  # Windows PowerShell \u2014 single-quoted so $env: expands correctly
580
714
  node --version # expect >= 18
581
- $null = Get-Command claude -ErrorAction SilentlyContinue
582
- if ($null) { Write-Host 'claude-code: present' } else { Write-Host 'claude-code: not detected' }
715
+ node -e "const fs=require('node:fs'),p=require('node:path');const names=process.platform==='win32'?['claude.cmd','claude.exe','claude']:['claude'];const found=(process.env.PATH||'').split(p.delimiter).some(d=>names.some(n=>fs.existsSync(p.join(d,n))));console.log(found?'claude-code: present':'claude-code: not detected')"
583
716
  \`\`\`
584
717
 
585
718
  > **PAUSE** \u2014 if Node is older than 18, ask the user to install a newer version (https://nodejs.org) before continuing. Use \`AskUserQuestion\` with header \`Node version\`.
@@ -956,7 +1089,7 @@ import {
956
1089
  rmdirSync
957
1090
  } from "node:fs";
958
1091
  import { homedir as homedir2 } from "node:os";
959
- import { dirname, join as join3 } from "node:path";
1092
+ import { dirname, join as join4 } from "node:path";
960
1093
  import { fileURLToPath } from "node:url";
961
1094
  function actionForStatus(label, state) {
962
1095
  switch (state) {
@@ -1212,15 +1345,15 @@ Exit codes:
1212
1345
  `);
1213
1346
  }
1214
1347
  function resolveTargets(flags) {
1215
- const claudeRoot = flags.skillDir ?? join3(homedir2(), ".claude");
1216
- const claudeSkillDir = join3(claudeRoot, "skills", SKILL_DIR_NAME);
1217
- const claudeCommandsDir = join3(claudeRoot, "commands");
1218
- const codexRoot = process.env["CODEX_HOME"] ?? join3(homedir2(), ".codex");
1219
- const codexSkillsDir = flags.codexSkillDir ?? join3(codexRoot, "skills");
1348
+ const claudeRoot = flags.skillDir ?? join4(homedir2(), ".claude");
1349
+ const claudeSkillDir = join4(claudeRoot, "skills", SKILL_DIR_NAME);
1350
+ const claudeCommandsDir = join4(claudeRoot, "commands");
1351
+ const codexRoot = process.env["CODEX_HOME"] ?? join4(homedir2(), ".codex");
1352
+ const codexSkillsDir = flags.codexSkillDir ?? join4(codexRoot, "skills");
1220
1353
  return {
1221
- claudeSkillFile: join3(claudeSkillDir, SKILL_FILE_NAME),
1222
- claudeCommandFile: join3(claudeCommandsDir, COMMAND_FILE_NAME),
1223
- codexSkillFile: join3(codexSkillsDir, SKILL_DIR_NAME, SKILL_FILE_NAME)
1354
+ claudeSkillFile: join4(claudeSkillDir, SKILL_FILE_NAME),
1355
+ claudeCommandFile: join4(claudeCommandsDir, COMMAND_FILE_NAME),
1356
+ codexSkillFile: join4(codexSkillsDir, SKILL_DIR_NAME, SKILL_FILE_NAME)
1224
1357
  };
1225
1358
  }
1226
1359
  function isObject2(value) {
@@ -1239,32 +1372,32 @@ function resolveOpenCodeConfigPath(flags) {
1239
1372
  if (flags.opencodeConfig !== null) {
1240
1373
  return flags.opencodeConfig;
1241
1374
  }
1242
- const configDir = join3(homedir2(), ".config", "opencode");
1243
- const jsoncPath = join3(configDir, "opencode.jsonc");
1375
+ const configDir = join4(homedir2(), ".config", "opencode");
1376
+ const jsoncPath = join4(configDir, "opencode.jsonc");
1244
1377
  if (existsSync3(jsoncPath)) {
1245
1378
  return jsoncPath;
1246
1379
  }
1247
- return join3(configDir, "opencode.json");
1380
+ return join4(configDir, "opencode.json");
1248
1381
  }
1249
1382
  function resolveMiMoConfigPath(flags) {
1250
1383
  if (flags.mimoConfig !== null) {
1251
1384
  return flags.mimoConfig;
1252
1385
  }
1253
- const configDir = join3(homedir2(), ".config", "mimocode");
1254
- const jsoncPath = join3(configDir, "mimocode.jsonc");
1386
+ const configDir = join4(homedir2(), ".config", "mimocode");
1387
+ const jsoncPath = join4(configDir, "mimocode.jsonc");
1255
1388
  if (existsSync3(jsoncPath)) {
1256
1389
  return jsoncPath;
1257
1390
  }
1258
- const jsonPath = join3(configDir, "mimocode.json");
1391
+ const jsonPath = join4(configDir, "mimocode.json");
1259
1392
  if (existsSync3(jsonPath)) {
1260
1393
  return jsonPath;
1261
1394
  }
1262
- const legacyDir = join3(homedir2(), ".mimocode");
1263
- const legacyJsoncPath = join3(legacyDir, "config.jsonc");
1395
+ const legacyDir = join4(homedir2(), ".mimocode");
1396
+ const legacyJsoncPath = join4(legacyDir, "config.jsonc");
1264
1397
  if (existsSync3(legacyJsoncPath)) {
1265
1398
  return legacyJsoncPath;
1266
1399
  }
1267
- const legacyJsonPath = join3(legacyDir, "config.json");
1400
+ const legacyJsonPath = join4(legacyDir, "config.json");
1268
1401
  if (existsSync3(legacyJsonPath)) {
1269
1402
  return legacyJsonPath;
1270
1403
  }
@@ -1643,8 +1776,8 @@ function buildDetectedSummary() {
1643
1776
  }
1644
1777
  function readPackageVersion() {
1645
1778
  const packageJsonPaths = [
1646
- join3(__dirname, "..", "package.json"),
1647
- join3(__dirname, "..", "..", "package.json")
1779
+ join4(__dirname, "..", "package.json"),
1780
+ join4(__dirname, "..", "..", "package.json")
1648
1781
  ];
1649
1782
  try {
1650
1783
  for (const packageJsonPath of packageJsonPaths) {
@@ -2224,8 +2357,8 @@ __export(doctor_exports, {
2224
2357
  parseDoctorArgs: () => parseDoctorArgs,
2225
2358
  runDoctor: () => runDoctor
2226
2359
  });
2227
- import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync } from "node:fs";
2228
- import { isAbsolute as isAbsolute2, join as join4, resolve } from "node:path";
2360
+ import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
2361
+ import { isAbsolute as isAbsolute3, join as join5, resolve } from "node:path";
2229
2362
  import { createConnection } from "node:net";
2230
2363
  function check2(name, severity, message, hint = "") {
2231
2364
  return {
@@ -2328,7 +2461,7 @@ function providerCountFromJson(raw) {
2328
2461
  }
2329
2462
  }
2330
2463
  function resolveMaybeRelative(base, value) {
2331
- return isAbsolute2(value) ? value : resolve(base, value);
2464
+ return isAbsolute3(value) ? value : resolve(base, value);
2332
2465
  }
2333
2466
  function resolveDefaultDataDir(env, platform, exists) {
2334
2467
  return resolveDataDir(exists, env, platform);
@@ -2340,10 +2473,10 @@ function providerConfigCandidates(options, deps) {
2340
2473
  }
2341
2474
  if (options.configDir !== null) {
2342
2475
  const dir = resolveMaybeRelative(deps.cwd, options.configDir);
2343
- return [join4(dir, "providers.json"), join4(dir, "config.json")];
2476
+ return [join5(dir, "providers.json"), join5(dir, "config.json")];
2344
2477
  }
2345
2478
  const dataDir = resolveDefaultDataDir(deps.env, deps.platform, deps.exists);
2346
- return [join4(dataDir, "providers.json"), join4(dataDir, "config.json")];
2479
+ return [join5(dataDir, "providers.json"), join5(dataDir, "config.json")];
2347
2480
  }
2348
2481
  function checkProviderConfig(options, deps) {
2349
2482
  const providersJson = options.providersJson ?? deps.env["AGENT_INSPECTOR_PROVIDERS_JSON"] ?? null;
@@ -2429,7 +2562,7 @@ async function checkProxyHealth(port, deps) {
2429
2562
  function findProjectRoot(startDir, deps) {
2430
2563
  let current = resolve(startDir);
2431
2564
  for (let i = 0; i < 6; i++) {
2432
- if (deps.exists(join4(current, "package.json"))) return current;
2565
+ if (deps.exists(join5(current, "package.json"))) return current;
2433
2566
  const next = resolve(current, "..");
2434
2567
  if (next === current) return startDir;
2435
2568
  current = next;
@@ -2437,7 +2570,7 @@ function findProjectRoot(startDir, deps) {
2437
2570
  return startDir;
2438
2571
  }
2439
2572
  function checkPackage(rootDir, deps) {
2440
- const packagePath = join4(rootDir, "package.json");
2573
+ const packagePath = join5(rootDir, "package.json");
2441
2574
  const text = deps.readText(packagePath);
2442
2575
  if (text === null) {
2443
2576
  return check2("Package metadata", "warn", "package.json was not found near the CLI bundle.");
@@ -2462,7 +2595,7 @@ function countFilesInDir(dir, deps) {
2462
2595
  if (files === null) return null;
2463
2596
  let count = 0;
2464
2597
  for (const file2 of files) {
2465
- const fileStat = deps.stat(join4(dir, file2));
2598
+ const fileStat = deps.stat(join5(dir, file2));
2466
2599
  if (fileStat !== null && !fileStat.isDirectory) count += 1;
2467
2600
  }
2468
2601
  return count;
@@ -2482,24 +2615,24 @@ function dirSize(dir, deps, depth = 0) {
2482
2615
  if (files === null) return null;
2483
2616
  let total = 0;
2484
2617
  for (const file2 of files) {
2485
- const childSize = dirSize(join4(dir, file2), deps, depth + 1);
2618
+ const childSize = dirSize(join5(dir, file2), deps, depth + 1);
2486
2619
  if (childSize !== null) total += childSize;
2487
2620
  }
2488
2621
  return total;
2489
2622
  }
2490
2623
  function verboseChecks(options, deps) {
2491
2624
  const dataDir = resolveDefaultDataDir(deps.env, deps.platform, deps.exists);
2492
- const logsDir = join4(dataDir, "logs");
2493
- const chunksDir = join4(dataDir, "chunks");
2625
+ const logsDir = join5(dataDir, "logs");
2626
+ const chunksDir = join5(dataDir, "chunks");
2494
2627
  const providerCandidates = providerConfigCandidates(options, deps);
2495
2628
  const captureMode = deps.env["AGENT_INSPECTOR_MODE"] ?? deps.env["AGENT_INSPECTOR_CAPTURE_MODE"] ?? "simple";
2496
2629
  const logCount = countFilesInDir(logsDir, deps);
2497
2630
  const logSize = dirSize(logsDir, deps);
2498
2631
  const chunkSize = dirSize(chunksDir, deps);
2499
2632
  const homeDir = deps.platform === "win32" ? deps.env["USERPROFILE"] ?? deps.env["APPDATA"] ?? null : deps.env["HOME"] ?? null;
2500
- const claudeSkill = homeDir === null ? null : join4(homeDir, ".claude", "skills", "agent-inspector-onboard", "SKILL.md");
2501
- const claudeCommand = homeDir === null ? null : join4(homeDir, ".claude", "commands", "agent-inspector-onboard.md");
2502
- const codexSkill = homeDir === null ? null : join4(homeDir, ".codex", "skills", "agent-inspector-onboard", "SKILL.md");
2633
+ const claudeSkill = homeDir === null ? null : join5(homeDir, ".claude", "skills", "agent-inspector-onboard", "SKILL.md");
2634
+ const claudeCommand = homeDir === null ? null : join5(homeDir, ".claude", "commands", "agent-inspector-onboard.md");
2635
+ const codexSkill = homeDir === null ? null : join5(homeDir, ".codex", "skills", "agent-inspector-onboard", "SKILL.md");
2503
2636
  const hasClaudeOnboarding = claudeSkill !== null && claudeCommand !== null && deps.exists(claudeSkill) && deps.exists(claudeCommand);
2504
2637
  const hasCodexOnboarding = codexSkill !== null && deps.exists(codexSkill);
2505
2638
  return [
@@ -2531,8 +2664,8 @@ function verboseChecks(options, deps) {
2531
2664
  ];
2532
2665
  }
2533
2666
  function checkExtensionSource(rootDir, deps) {
2534
- const extensionDir = join4(rootDir, "extensions", "chrome");
2535
- const missing = EXTENSION_REQUIRED_FILES.filter((file2) => !deps.exists(join4(extensionDir, file2)));
2667
+ const extensionDir = join5(rootDir, "extensions", "chrome");
2668
+ const missing = EXTENSION_REQUIRED_FILES.filter((file2) => !deps.exists(join5(extensionDir, file2)));
2536
2669
  if (missing.length === 0) {
2537
2670
  return check2(
2538
2671
  "Chrome extension source",
@@ -2548,7 +2681,7 @@ function checkExtensionSource(rootDir, deps) {
2548
2681
  );
2549
2682
  }
2550
2683
  function extensionManifestVersion(rootDir, deps) {
2551
- const manifestText = deps.readText(join4(rootDir, "extensions", "chrome", "manifest.json"));
2684
+ const manifestText = deps.readText(join5(rootDir, "extensions", "chrome", "manifest.json"));
2552
2685
  if (manifestText === null) return null;
2553
2686
  try {
2554
2687
  const manifest = JSON.parse(manifestText);
@@ -2560,7 +2693,7 @@ function extensionManifestVersion(rootDir, deps) {
2560
2693
  }
2561
2694
  }
2562
2695
  function checkExtensionPackage(rootDir, deps) {
2563
- const distDir = join4(rootDir, "dist", "chrome-extension");
2696
+ const distDir = join5(rootDir, "dist", "chrome-extension");
2564
2697
  const files = deps.listDir(distDir);
2565
2698
  if (files === null) {
2566
2699
  return check2(
@@ -2713,7 +2846,7 @@ function listDir(path2) {
2713
2846
  }
2714
2847
  function stat2(path2) {
2715
2848
  try {
2716
- const fileStat = statSync(path2);
2849
+ const fileStat = statSync2(path2);
2717
2850
  return { isDirectory: fileStat.isDirectory(), size: fileStat.size };
2718
2851
  } catch {
2719
2852
  return null;
@@ -2774,10 +2907,10 @@ var init_doctor = __esm({
2774
2907
 
2775
2908
  // src/cli.ts
2776
2909
  import { Buffer as Buffer3 } from "node:buffer";
2777
- import { spawn, execSync } from "node:child_process";
2910
+ import { spawn } from "node:child_process";
2778
2911
  import { createConnection as createConnection2 } from "node:net";
2779
2912
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2780
- import { dirname as dirname2, join as join5, resolve as resolvePath } from "node:path";
2913
+ import { dirname as dirname2, join as join6, resolve as resolvePath } from "node:path";
2781
2914
  import { existsSync as existsSync5 } from "node:fs";
2782
2915
 
2783
2916
  // src/cli/networkHints.ts
@@ -2902,7 +3035,8 @@ import http from "node:http";
2902
3035
  import { Buffer as Buffer2 } from "node:buffer";
2903
3036
 
2904
3037
  // src/proxy/socketTracker.ts
2905
- import { exec, execFile } from "node:child_process";
3038
+ import { execFile } from "node:child_process";
3039
+ import { readFile } from "node:fs/promises";
2906
3040
  import { promisify } from "node:util";
2907
3041
 
2908
3042
  // node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -4493,8 +4627,8 @@ function emoji() {
4493
4627
  }
4494
4628
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
4495
4629
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
4496
- var mac = (delimiter) => {
4497
- const escapedDelim = escapeRegex(delimiter ?? ":");
4630
+ var mac = (delimiter2) => {
4631
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
4498
4632
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
4499
4633
  };
4500
4634
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -16822,7 +16956,6 @@ for (const signal of ["SIGINT", "SIGTERM"]) {
16822
16956
  }
16823
16957
 
16824
16958
  // src/proxy/socketTracker.ts
16825
- var execAsync = promisify(exec);
16826
16959
  var execFileAsync = promisify(execFile);
16827
16960
  var CACHE_TTL_MS = 5 * 60 * 1e3;
16828
16961
  var RemotePortSchema = external_exports.number().int().min(1).max(65535);
@@ -16846,38 +16979,34 @@ async function lookupProcessInfo(pid) {
16846
16979
  const platform = process.platform;
16847
16980
  try {
16848
16981
  if (platform === "win32") {
16982
+ const psScript = [
16983
+ `$proc = Get-CimInstance Win32_Process -Filter "ProcessId=${pid}" -ErrorAction SilentlyContinue`,
16984
+ `if ($proc) { Write-Output $proc.CommandLine }`
16985
+ ].join("; ");
16849
16986
  const { stdout } = await execFileAsync(
16850
- "wmic.exe",
16851
- ["process", "where", `processid=${pid}`, "get", "commandline", "/value"],
16987
+ "powershell.exe",
16988
+ ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", psScript],
16852
16989
  {
16853
16990
  windowsHide: true,
16854
16991
  timeout: 3e3,
16855
16992
  maxBuffer: 64 * 1024
16856
16993
  }
16857
16994
  );
16858
- const lines = stdout.trim().split("\n").filter(Boolean);
16859
- for (const line of lines) {
16860
- if (line.includes("=")) {
16861
- const commandLine = (line.split("=")[1] ?? "").trim();
16862
- if (commandLine) {
16863
- return parseCommandLine(commandLine, "\\");
16864
- }
16865
- }
16866
- }
16995
+ const commandLine = stdout.trim();
16996
+ if (commandLine.length > 0) return parseCommandLine(commandLine, "\\");
16867
16997
  } else {
16868
16998
  try {
16869
- const { stdout } = await execAsync(`cat /proc/${pid}/cmdline 2>/dev/null | tr '\\0' ' '`, {
16870
- shell: "/bin/sh"
16871
- });
16872
- const commandLine = stdout.trim();
16999
+ const raw = await readFile(`/proc/${String(pid)}/cmdline`, "utf8");
17000
+ const commandLine = raw.replace(/\0/g, " ").trim();
16873
17001
  if (commandLine) {
16874
17002
  return parseCommandLine(commandLine, "/");
16875
17003
  }
16876
17004
  } catch {
16877
17005
  }
16878
17006
  if (platform === "darwin") {
16879
- const { stdout } = await execAsync(`ps -p ${pid} -o comm= 2>/dev/null`, {
16880
- shell: "/bin/sh"
17007
+ const { stdout } = await execFileAsync("ps", ["-p", String(pid), "-o", "comm="], {
17008
+ timeout: 3e3,
17009
+ maxBuffer: 64 * 1024
16881
17010
  });
16882
17011
  const exePath = stdout.trim();
16883
17012
  if (exePath) {
@@ -16925,10 +17054,11 @@ async function lookupPidByLocalPort(clientPort) {
16925
17054
  const platform = process.platform;
16926
17055
  try {
16927
17056
  if (platform === "win32") {
16928
- const { stdout } = await execAsync(
16929
- `netstat -ano | findstr :${clientPort} | findstr ESTABLISHED`,
16930
- { shell: "cmd.exe", timeout: 2e3, windowsHide: true }
16931
- );
17057
+ const { stdout } = await execFileAsync("netstat.exe", ["-ano", "-p", "TCP"], {
17058
+ windowsHide: true,
17059
+ timeout: 2e3,
17060
+ maxBuffer: 2 * 1024 * 1024
17061
+ });
16932
17062
  const clientToken = `:${clientPort}`;
16933
17063
  for (const rawLine of stdout.split("\n")) {
16934
17064
  const line = rawLine.trim();
@@ -16936,6 +17066,8 @@ async function lookupPidByLocalPort(clientPort) {
16936
17066
  const cols = line.split(/\s+/);
16937
17067
  if (cols.length < 5) continue;
16938
17068
  const localAddr = cols[1] ?? "";
17069
+ const state = cols[3] ?? "";
17070
+ if (state !== "ESTABLISHED") continue;
16939
17071
  if (!localAddr.endsWith(clientToken)) continue;
16940
17072
  const pidStr = cols[cols.length - 1] ?? "";
16941
17073
  const parsed = parseInt(pidStr, 10);
@@ -16944,9 +17076,13 @@ async function lookupPidByLocalPort(clientPort) {
16944
17076
  return null;
16945
17077
  }
16946
17078
  try {
16947
- const { stdout } = await execAsync(
16948
- `ss -tanp state established 'sport = :${clientPort}' 2>/dev/null | tail -n +2 | head -n 1`,
16949
- { shell: "/bin/sh" }
17079
+ const { stdout } = await execFileAsync(
17080
+ "ss",
17081
+ ["-tanp", "state", "established", "sport", `= :${clientPort}`],
17082
+ {
17083
+ timeout: 2e3,
17084
+ maxBuffer: 2 * 1024 * 1024
17085
+ }
16950
17086
  );
16951
17087
  const match = stdout.match(/pid=(\d+)/);
16952
17088
  if (match !== null) {
@@ -16956,10 +17092,12 @@ async function lookupPidByLocalPort(clientPort) {
16956
17092
  } catch {
16957
17093
  }
16958
17094
  try {
16959
- const { stdout } = await execAsync(
16960
- `lsof -ti tcp:${clientPort} -sTCP:ESTABLISHED 2>/dev/null`,
17095
+ const { stdout } = await execFileAsync(
17096
+ "lsof",
17097
+ ["-ti", `tcp:${clientPort}`, "-sTCP:ESTABLISHED"],
16961
17098
  {
16962
- shell: "/bin/sh"
17099
+ timeout: 2e3,
17100
+ maxBuffer: 64 * 1024
16963
17101
  }
16964
17102
  );
16965
17103
  const trimmed = stdout.trim().split("\n")[0] ?? "";
@@ -17098,6 +17236,7 @@ function toBuffer(chunk) {
17098
17236
  }
17099
17237
 
17100
17238
  // src/cli.ts
17239
+ init_platformCommands();
17101
17240
  var __filename2 = fileURLToPath2(import.meta.url);
17102
17241
  var __dirname2 = dirname2(__filename2);
17103
17242
  var DEFAULT_PORT3 = 9527;
@@ -17179,24 +17318,9 @@ async function waitForInspectorHealthy(port, timeoutMs, host) {
17179
17318
  return false;
17180
17319
  }
17181
17320
  function openBrowser(targetUrl) {
17182
- let command;
17183
- switch (process.platform) {
17184
- case "darwin":
17185
- command = ["open", targetUrl];
17186
- break;
17187
- case "linux":
17188
- command = ["xdg-open", targetUrl];
17189
- break;
17190
- case "win32":
17191
- command = ["cmd", "/c", "start", "", targetUrl];
17192
- break;
17193
- default:
17194
- break;
17195
- }
17196
- if (command === void 0) return;
17197
- const [bin, ...cmdArgs] = command;
17198
- if (bin === void 0) return;
17199
- const browserProcess = spawn(bin, cmdArgs, {
17321
+ const command = openUrlCommand(targetUrl);
17322
+ if (command === null) return;
17323
+ const browserProcess = spawn(command.command, command.args, {
17200
17324
  stdio: "ignore",
17201
17325
  detached: true,
17202
17326
  windowsHide: true
@@ -17242,7 +17366,7 @@ function pipeServerOutputStream(stream, target, context) {
17242
17366
  });
17243
17367
  }
17244
17368
  function resolveServerCommand(outputDir, serverPath) {
17245
- const brandedRuntime = join5(outputDir, BRANDED_WINDOWS_RUNTIME_EXE);
17369
+ const brandedRuntime = join6(outputDir, BRANDED_WINDOWS_RUNTIME_EXE);
17246
17370
  return process.platform === "win32" && existsSync5(brandedRuntime) ? { command: brandedRuntime, args: [serverPath] } : { command: process.execPath, args: [serverPath] };
17247
17371
  }
17248
17372
  function parseCaptureMode(value) {
@@ -17437,60 +17561,10 @@ async function runStart(args) {
17437
17561
  return;
17438
17562
  }
17439
17563
  function killProcessOnPort(targetPort) {
17440
- const platform = process.platform;
17441
- try {
17442
- let pids = [];
17443
- if (platform === "win32") {
17444
- const output = execSync(`netstat -ano | findstr :${targetPort}`, {
17445
- encoding: "utf8",
17446
- timeout: 5e3,
17447
- windowsHide: true
17448
- });
17449
- const lines = output.trim().split("\n");
17450
- for (const line of lines) {
17451
- const parts = line.trim().split(/\s+/);
17452
- if (parts.length >= 5) {
17453
- const localAddress = parts[1] ?? "";
17454
- const pidStr = parts[4] ?? "";
17455
- if (localAddress !== "" && pidStr !== "" && localAddress.includes(`:${targetPort}`)) {
17456
- const pid = parseInt(pidStr, 10);
17457
- if (!isNaN(pid) && pid > 0) {
17458
- pids.push(pid);
17459
- }
17460
- }
17461
- }
17462
- }
17463
- pids = [...new Set(pids)];
17464
- for (const pid of pids) {
17465
- try {
17466
- console.log(`Killing process ${pid} on port ${targetPort}...`);
17467
- execSync(`taskkill /PID ${pid} /F`, {
17468
- encoding: "utf8",
17469
- timeout: 5e3,
17470
- windowsHide: true
17471
- });
17472
- } catch {
17473
- }
17474
- }
17475
- } else {
17476
- const output = execSync(`lsof -ti:${targetPort}`, { encoding: "utf8", timeout: 5e3 });
17477
- const lines = output.trim().split("\n");
17478
- for (const line of lines) {
17479
- const pid = parseInt(line.trim(), 10);
17480
- if (!isNaN(pid) && pid > 0) {
17481
- pids.push(pid);
17482
- }
17483
- }
17484
- pids = [...new Set(pids)];
17485
- for (const pid of pids) {
17486
- try {
17487
- console.log(`Killing process ${pid} on port ${targetPort}...`);
17488
- execSync(`kill -9 ${pid}`, { encoding: "utf8", timeout: 5e3 });
17489
- } catch {
17490
- }
17491
- }
17492
- }
17493
- } catch {
17564
+ const pids = findPidsByPort(targetPort);
17565
+ for (const pid of pids) {
17566
+ console.log(`Killing process ${pid} on port ${targetPort}...`);
17567
+ killPid(pid);
17494
17568
  }
17495
17569
  }
17496
17570
  const legacyAliasPort = enableIdentityProxy && legacyAliasEnabled && port === DEFAULT_PORT3 ? LEGACY_ALIAS_PORT : null;
@@ -17561,11 +17635,11 @@ async function runStart(args) {
17561
17635
  openBrowser(url2);
17562
17636
  }
17563
17637
  const outputDir = __dirname2;
17564
- const serverPath = join5(outputDir, "../.output/server/index.mjs");
17638
+ const serverPath = join6(outputDir, "../.output/server/index.mjs");
17565
17639
  const serverCommand = resolveServerCommand(outputDir, serverPath);
17566
17640
  const serverEnv = { ...process.env };
17567
17641
  if (configDir !== void 0) {
17568
- let resolvedPath = join5(configDir);
17642
+ let resolvedPath = join6(configDir);
17569
17643
  const msysMatch = /^\\([a-z])\\(.*)$/i.exec(resolvedPath);
17570
17644
  if (msysMatch !== null) {
17571
17645
  const drive = (msysMatch[1] ?? "").toUpperCase();