@tonyclaw/agent-inspector 3.0.38 → 3.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/cli.js +249 -84
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-BXQWabQJ.js → CompareDrawer-BjQ2HH8j.js} +1 -1
- package/.output/public/assets/{InspectorPet-CpQEXKcr.js → InspectorPet-DDScgJ7_.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-C3iHhtkc.js +126 -0
- package/.output/public/assets/{ReplayDialog-CnYt4UKE.js → ReplayDialog-BujXVTMJ.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BI25al3m.js → RequestAnatomy-iK2nOuCP.js} +1 -1
- package/.output/public/assets/{ResponseView-D3y-I9nb.js → ResponseView-iAuOJxem.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-n90dYzPp.js → StreamingChunkSequence-DiZ21icS.js} +1 -1
- package/.output/public/assets/{_sessionId-DLbOYm3h.js → _sessionId-CLTlZx8L.js} +1 -1
- package/.output/public/assets/{_sessionId-CogrNhCS.js → _sessionId-D3WwDIit.js} +1 -1
- package/.output/public/assets/{index-I5zN_KrA.js → index--ND7WRCU.js} +1 -1
- package/.output/public/assets/{index-DXGp27k9.js → index-DGuDxV-I.js} +1 -1
- package/.output/public/assets/index-fXi7tXyH.js +76 -0
- package/.output/public/assets/{index-BWWA1Rf6.js → index-nN3UPNM0.js} +6 -6
- package/.output/public/assets/{json-viewer-BoB2BfHg.js → json-viewer-CzcwNVJa.js} +1 -1
- package/.output/public/assets/{jszip.min-CAXkxQd6.js → jszip.min-DAbOCDPI.js} +1 -1
- package/.output/server/{_sessionId-_hORwhWH.mjs → _sessionId-DSetUDiv.mjs} +1 -1
- package/.output/server/{_sessionId-DScqlEFC.mjs → _sessionId-DtRKr8Jt.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BtGm5i_L.mjs → CompareDrawer-Cns26sqx.mjs} +2 -2
- package/.output/server/_ssr/{InspectorPet-BnN6lVqM.mjs → InspectorPet-CyWBvBuh.mjs} +1 -1
- package/.output/server/_ssr/{ProxyViewerContainer-aduEJ_Xy.mjs → ProxyViewerContainer-CimBv5WL.mjs} +58 -23
- package/.output/server/_ssr/{ReplayDialog-BSGZ-TFs.mjs → ReplayDialog-DrM897xL.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-DN_eSnDN.mjs → RequestAnatomy-BRgezegq.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-Dk9Td_HM.mjs → ResponseView-D7u7r-lA.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-DthH8Lx4.mjs → StreamingChunkSequence-DM26ZaVC.mjs} +2 -2
- package/.output/server/_ssr/{index-CqeZgFFF.mjs → index-BeWedHzY.mjs} +2 -2
- package/.output/server/_ssr/{index-DvVHL942.mjs → index-C284XGkZ.mjs} +1 -1
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-DLKA2jUq.mjs → json-viewer-CD_GbR7V.mjs} +2 -2
- package/.output/server/_ssr/{router-CRKEDn6n.mjs → router-DxPlMfLZ.mjs} +125 -58
- package/.output/server/{_tanstack-start-manifest_v-pQO9kTmV.mjs → _tanstack-start-manifest_v-82w9tFI-.mjs} +1 -1
- package/.output/server/index.mjs +84 -84
- package/.output/workers/logFinalizer.worker.js +6 -1
- package/.output/workers/sessionWorkerEntry.js +6 -1
- package/README.md +42 -10
- package/package.json +1 -1
- package/src/cli/doctor.ts +17 -10
- package/src/cli/networkHints.ts +15 -8
- package/src/cli/onboard.ts +10 -3
- package/src/cli.ts +90 -56
- package/src/components/ProxyViewer.tsx +11 -2
- package/src/components/ProxyViewerContainer.tsx +2 -1
- package/src/components/pi-agent/PiAgentPanel.tsx +2 -1
- package/src/components/providers/SettingsDialog.tsx +24 -7
- package/src/lib/apiClient.ts +9 -2
- package/src/lib/basePath.ts +83 -0
- package/src/lib/sessionUrl.ts +4 -2
- package/src/mcp/loopback.ts +2 -1
- package/src/mcp/server.ts +6 -2
- package/src/proxy/identityProxy.ts +98 -6
- package/src/proxy/privateDataPath.ts +15 -1
- package/src/proxy/sessionInfo.ts +10 -3
- package/src/proxy/upstream.ts +3 -1
- package/src/router.tsx +7 -1
- package/src/routes/__root.tsx +9 -3
- package/.output/public/assets/ProxyViewerContainer-8pNJsCJ5.js +0 -126
- package/.output/public/assets/index-Ca0grOxW.js +0 -76
package/.output/cli.js
CHANGED
|
@@ -14,12 +14,76 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// src/lib/basePath.ts
|
|
18
|
+
function trimSlashes(value) {
|
|
19
|
+
return value.replace(/^\/+/u, "").replace(/\/+$/u, "");
|
|
20
|
+
}
|
|
21
|
+
function normalizeBasePath(value) {
|
|
22
|
+
const trimmed = value?.trim();
|
|
23
|
+
if (trimmed === void 0 || trimmed.length === 0 || trimmed === "/") return "";
|
|
24
|
+
const path2 = trimSlashes(trimmed);
|
|
25
|
+
if (path2.length === 0) return "";
|
|
26
|
+
return `/${path2}`;
|
|
27
|
+
}
|
|
28
|
+
function readDocumentBasePath() {
|
|
29
|
+
if (typeof document === "undefined") return void 0;
|
|
30
|
+
return document.querySelector(`meta[name="${AGENT_INSPECTOR_BASE_PATH_META_NAME}"]`)?.getAttribute("content") ?? void 0;
|
|
31
|
+
}
|
|
32
|
+
function readProcessBasePath() {
|
|
33
|
+
if (typeof process === "undefined") return void 0;
|
|
34
|
+
return process.env[AGENT_INSPECTOR_BASE_PATH_ENV];
|
|
35
|
+
}
|
|
36
|
+
function getConfiguredBasePath(env) {
|
|
37
|
+
return normalizeBasePath(
|
|
38
|
+
env?.[AGENT_INSPECTOR_BASE_PATH_ENV] ?? readProcessBasePath() ?? readDocumentBasePath() ?? import.meta.env?.BASE_URL ?? DEFAULT_AGENT_INSPECTOR_BASE_PATH
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function withBasePath(path2, basePath = getConfiguredBasePath()) {
|
|
42
|
+
const normalized = normalizeBasePath(basePath);
|
|
43
|
+
if (/^[a-z][a-z0-9+.-]*:/iu.test(path2)) return path2;
|
|
44
|
+
if (normalized.length === 0) return path2;
|
|
45
|
+
if (path2.length === 0 || path2 === "/") return normalized;
|
|
46
|
+
if (path2.startsWith(`${normalized}/`) || path2 === normalized) return path2;
|
|
47
|
+
return path2.startsWith("/") ? `${normalized}${path2}` : `${normalized}/${path2}`;
|
|
48
|
+
}
|
|
49
|
+
function stripBasePath(pathname, basePath = getConfiguredBasePath()) {
|
|
50
|
+
const normalized = normalizeBasePath(basePath);
|
|
51
|
+
if (normalized.length === 0) return pathname;
|
|
52
|
+
if (pathname === normalized) return "/";
|
|
53
|
+
if (pathname.startsWith(`${normalized}/`)) return pathname.slice(normalized.length);
|
|
54
|
+
return pathname;
|
|
55
|
+
}
|
|
56
|
+
function appendBasePathToOrigin(origin, path2, basePath) {
|
|
57
|
+
const normalized = normalizeBasePath(basePath);
|
|
58
|
+
if (normalized.length === 0 && path2 === "/") return origin;
|
|
59
|
+
return `${origin}${withBasePath(path2, normalized)}`;
|
|
60
|
+
}
|
|
61
|
+
function stripBasePathFromRequestPath(rawPath, basePath) {
|
|
62
|
+
const url2 = new URL(rawPath, "http://localhost");
|
|
63
|
+
return `${stripBasePath(url2.pathname, basePath)}${url2.search}`;
|
|
64
|
+
}
|
|
65
|
+
var AGENT_INSPECTOR_BASE_PATH_ENV, AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV, AGENT_INSPECTOR_BASE_PATH_META_NAME, DEFAULT_AGENT_INSPECTOR_BASE_PATH;
|
|
66
|
+
var init_basePath = __esm({
|
|
67
|
+
"src/lib/basePath.ts"() {
|
|
68
|
+
"use strict";
|
|
69
|
+
AGENT_INSPECTOR_BASE_PATH_ENV = "AGENT_INSPECTOR_BASE_PATH";
|
|
70
|
+
AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV = "AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH";
|
|
71
|
+
AGENT_INSPECTOR_BASE_PATH_META_NAME = "agent-inspector-base-path";
|
|
72
|
+
DEFAULT_AGENT_INSPECTOR_BASE_PATH = "/inspector";
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
17
76
|
// src/proxy/privateDataPath.ts
|
|
18
77
|
import { spawnSync } from "node:child_process";
|
|
19
78
|
import { chmodSync, existsSync, lstatSync, mkdirSync, readdirSync, statSync } from "node:fs";
|
|
20
79
|
import { dirname, join } from "node:path";
|
|
80
|
+
function windowsSystemPath(executable) {
|
|
81
|
+
const systemRoot = process.env["SystemRoot"] ?? "C:\\Windows";
|
|
82
|
+
return `${systemRoot}\\System32\\${executable}`;
|
|
83
|
+
}
|
|
21
84
|
function runWindowsCommand(executable, args) {
|
|
22
|
-
const
|
|
85
|
+
const resolved = process.platform === "win32" && /^(whoami|icacls)\.exe$/iu.test(executable) ? windowsSystemPath(executable) : executable;
|
|
86
|
+
const result = spawnSync(resolved, [...args], {
|
|
23
87
|
encoding: "utf8",
|
|
24
88
|
shell: false,
|
|
25
89
|
windowsHide: true
|
|
@@ -1265,6 +1329,11 @@ function actionForStatus(label, state) {
|
|
|
1265
1329
|
}
|
|
1266
1330
|
}
|
|
1267
1331
|
function parseFlags(argv) {
|
|
1332
|
+
const defaultMcpUrl = appendBasePathToOrigin(
|
|
1333
|
+
DEFAULT_ORIGIN,
|
|
1334
|
+
"/api/mcp",
|
|
1335
|
+
getConfiguredBasePath(process.env)
|
|
1336
|
+
);
|
|
1268
1337
|
const flags = {
|
|
1269
1338
|
force: false,
|
|
1270
1339
|
dryRun: false,
|
|
@@ -1276,12 +1345,12 @@ function parseFlags(argv) {
|
|
|
1276
1345
|
opencodeOnly: false,
|
|
1277
1346
|
opencodeConfig: null,
|
|
1278
1347
|
opencodeTransport: "local",
|
|
1279
|
-
opencodeMcpUrl:
|
|
1348
|
+
opencodeMcpUrl: defaultMcpUrl,
|
|
1280
1349
|
mimo: false,
|
|
1281
1350
|
mimoOnly: false,
|
|
1282
1351
|
mimoConfig: null,
|
|
1283
1352
|
mimoTransport: "local",
|
|
1284
|
-
mimoMcpUrl:
|
|
1353
|
+
mimoMcpUrl: defaultMcpUrl,
|
|
1285
1354
|
uninstall: false,
|
|
1286
1355
|
status: false,
|
|
1287
1356
|
json: false,
|
|
@@ -2473,10 +2542,11 @@ Next steps:
|
|
|
2473
2542
|
}
|
|
2474
2543
|
return 0;
|
|
2475
2544
|
}
|
|
2476
|
-
var __filename, __dirname, DEFAULT_PORT, DEFAULT_MCP_URL, LEGACY_MCP_URL, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
2545
|
+
var __filename, __dirname, DEFAULT_PORT, DEFAULT_ORIGIN, DEFAULT_MCP_URL, LEGACY_MCP_URL, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
2477
2546
|
var init_onboard = __esm({
|
|
2478
2547
|
"src/cli/onboard.ts"() {
|
|
2479
2548
|
"use strict";
|
|
2549
|
+
init_basePath();
|
|
2480
2550
|
init_detect_tools();
|
|
2481
2551
|
init_command_onboard();
|
|
2482
2552
|
init_codex_skill_onboard();
|
|
@@ -2484,7 +2554,8 @@ var init_onboard = __esm({
|
|
|
2484
2554
|
__filename = fileURLToPath(import.meta.url);
|
|
2485
2555
|
__dirname = dirname2(__filename);
|
|
2486
2556
|
DEFAULT_PORT = 9527;
|
|
2487
|
-
|
|
2557
|
+
DEFAULT_ORIGIN = `http://localhost:${DEFAULT_PORT}`;
|
|
2558
|
+
DEFAULT_MCP_URL = `${DEFAULT_ORIGIN}/api/mcp`;
|
|
2488
2559
|
LEGACY_MCP_URL = "http://localhost:9527/api/mcp";
|
|
2489
2560
|
SKILL_DIR_NAME = "agent-inspector-onboard";
|
|
2490
2561
|
SKILL_FILE_NAME = "SKILL.md";
|
|
@@ -2682,14 +2753,17 @@ function checkProviderConfig(options, deps) {
|
|
|
2682
2753
|
);
|
|
2683
2754
|
}
|
|
2684
2755
|
async function checkProxyHealth(port, deps) {
|
|
2685
|
-
const
|
|
2756
|
+
const basePath = getConfiguredBasePath(deps.env);
|
|
2757
|
+
const health = await deps.fetchHealth(port, basePath);
|
|
2686
2758
|
const url2 = `http://localhost:${port}`;
|
|
2759
|
+
const proxyUrl = appendBasePathToOrigin(url2, "/proxy", basePath);
|
|
2760
|
+
const healthPath = appendBasePathToOrigin("", "/api/health", basePath);
|
|
2687
2761
|
if (health.ok) {
|
|
2688
2762
|
return check2(
|
|
2689
2763
|
"Proxy health",
|
|
2690
2764
|
"pass",
|
|
2691
|
-
`agent-inspector is healthy at ${url2}.`,
|
|
2692
|
-
`Proxy URL: ${
|
|
2765
|
+
`agent-inspector is healthy at ${appendBasePathToOrigin(url2, "/", basePath)}.`,
|
|
2766
|
+
`Proxy URL: ${proxyUrl}`
|
|
2693
2767
|
);
|
|
2694
2768
|
}
|
|
2695
2769
|
if (await deps.isPortOpen(port)) {
|
|
@@ -2697,7 +2771,7 @@ async function checkProxyHealth(port, deps) {
|
|
|
2697
2771
|
return check2(
|
|
2698
2772
|
"Proxy health",
|
|
2699
2773
|
"fail",
|
|
2700
|
-
`Port ${port} is accepting connections, but
|
|
2774
|
+
`Port ${port} is accepting connections, but ${healthPath} is not healthy${suffix}.`,
|
|
2701
2775
|
"Stop that process, choose --port <n>, or start agent-inspector with --force-restart."
|
|
2702
2776
|
);
|
|
2703
2777
|
}
|
|
@@ -2950,14 +3024,17 @@ function doctorHelp() {
|
|
|
2950
3024
|
""
|
|
2951
3025
|
].join("\n");
|
|
2952
3026
|
}
|
|
2953
|
-
async function fetchHealth(port) {
|
|
3027
|
+
async function fetchHealth(port, basePath) {
|
|
2954
3028
|
const controller = new AbortController();
|
|
2955
3029
|
const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
|
|
2956
3030
|
try {
|
|
2957
|
-
const response = await fetch(
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3031
|
+
const response = await fetch(
|
|
3032
|
+
appendBasePathToOrigin(`http://127.0.0.1:${port}`, "/api/health", basePath),
|
|
3033
|
+
{
|
|
3034
|
+
cache: "no-store",
|
|
3035
|
+
signal: controller.signal
|
|
3036
|
+
}
|
|
3037
|
+
);
|
|
2961
3038
|
return { ok: response.ok, status: response.status };
|
|
2962
3039
|
} catch {
|
|
2963
3040
|
return { ok: false, status: null };
|
|
@@ -3036,6 +3113,7 @@ var DEFAULT_PORT2, PROBE_TIMEOUT_MS, EXTENSION_REQUIRED_FILES;
|
|
|
3036
3113
|
var init_doctor = __esm({
|
|
3037
3114
|
"src/cli/doctor.ts"() {
|
|
3038
3115
|
"use strict";
|
|
3116
|
+
init_basePath();
|
|
3039
3117
|
init_dataDir();
|
|
3040
3118
|
DEFAULT_PORT2 = 9527;
|
|
3041
3119
|
PROBE_TIMEOUT_MS = 2e3;
|
|
@@ -3055,6 +3133,7 @@ var init_doctor = __esm({
|
|
|
3055
3133
|
});
|
|
3056
3134
|
|
|
3057
3135
|
// src/cli.ts
|
|
3136
|
+
init_basePath();
|
|
3058
3137
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
3059
3138
|
import { spawn } from "node:child_process";
|
|
3060
3139
|
import { createConnection as createConnection2 } from "node:net";
|
|
@@ -3063,6 +3142,7 @@ import { dirname as dirname3, join as join7, resolve as resolvePath } from "node
|
|
|
3063
3142
|
import { existsSync as existsSync6 } from "node:fs";
|
|
3064
3143
|
|
|
3065
3144
|
// src/cli/networkHints.ts
|
|
3145
|
+
init_basePath();
|
|
3066
3146
|
import { networkInterfaces } from "node:os";
|
|
3067
3147
|
function localUrlForPort(port) {
|
|
3068
3148
|
return `http://localhost:${String(port)}`;
|
|
@@ -3137,19 +3217,23 @@ function networkUrlsForBindHost(port, host, interfaces = networkInterfaces()) {
|
|
|
3137
3217
|
if (isWildcardHost(host)) return collectNetworkUrls(port, interfaces);
|
|
3138
3218
|
return [urlForHost(port, host)];
|
|
3139
3219
|
}
|
|
3140
|
-
function
|
|
3220
|
+
function accessUrl(origin, path2, basePath) {
|
|
3221
|
+
return appendBasePathToOrigin(origin, path2, basePath);
|
|
3222
|
+
}
|
|
3223
|
+
function formatAccessHintLines(port, networkUrls, host = void 0, basePath = "") {
|
|
3224
|
+
const normalizedBasePath = normalizeBasePath(basePath);
|
|
3141
3225
|
const localUrl = localUrlForPort(port);
|
|
3142
3226
|
const hostLabel = isWildcardHost(host) ? "all interfaces (0.0.0.0)" : trimHost(host) ?? "";
|
|
3143
3227
|
const lines = ["Access URLs:", ` Bind host: ${hostLabel}`];
|
|
3144
3228
|
if (isLoopbackHost(host) || isWildcardHost(host)) {
|
|
3145
|
-
lines.push(` Local UI: ${localUrl}`);
|
|
3146
|
-
lines.push(` Local proxy: ${localUrl
|
|
3147
|
-
lines.push(` Local MCP: ${localUrl
|
|
3229
|
+
lines.push(` Local UI: ${accessUrl(localUrl, "/", normalizedBasePath)}`);
|
|
3230
|
+
lines.push(` Local proxy: ${accessUrl(localUrl, "/proxy", normalizedBasePath)}`);
|
|
3231
|
+
lines.push(` Local MCP: ${accessUrl(localUrl, "/api/mcp", normalizedBasePath)}`);
|
|
3148
3232
|
} else {
|
|
3149
3233
|
const boundUrl = urlForHost(port, host);
|
|
3150
|
-
lines.push(` Bound UI: ${boundUrl}`);
|
|
3151
|
-
lines.push(` Bound proxy: ${boundUrl
|
|
3152
|
-
lines.push(` Bound MCP: ${boundUrl
|
|
3234
|
+
lines.push(` Bound UI: ${accessUrl(boundUrl, "/", normalizedBasePath)}`);
|
|
3235
|
+
lines.push(` Bound proxy: ${accessUrl(boundUrl, "/proxy", normalizedBasePath)}`);
|
|
3236
|
+
lines.push(` Bound MCP: ${accessUrl(boundUrl, "/api/mcp", normalizedBasePath)}`);
|
|
3153
3237
|
lines.push(" Localhost: may not work because the server is bound to a specific host");
|
|
3154
3238
|
}
|
|
3155
3239
|
const firstNetworkUrl = networkUrls[0];
|
|
@@ -3158,8 +3242,8 @@ function formatAccessHintLines(port, networkUrls, host = void 0) {
|
|
|
3158
3242
|
} else if (firstNetworkUrl === void 0) {
|
|
3159
3243
|
lines.push(" Network: no non-loopback IPv4 address detected");
|
|
3160
3244
|
} else {
|
|
3161
|
-
lines.push(` Network UI: ${firstNetworkUrl}`);
|
|
3162
|
-
lines.push(` Network proxy: ${firstNetworkUrl
|
|
3245
|
+
lines.push(` Network UI: ${accessUrl(firstNetworkUrl, "/", normalizedBasePath)}`);
|
|
3246
|
+
lines.push(` Network proxy: ${accessUrl(firstNetworkUrl, "/proxy", normalizedBasePath)}`);
|
|
3163
3247
|
const moreUrls = networkUrls.slice(1);
|
|
3164
3248
|
if (moreUrls.length > 0) {
|
|
3165
3249
|
lines.push(` Other IPs: ${moreUrls.join(", ")}`);
|
|
@@ -3180,6 +3264,7 @@ function shouldSuppressServerOutputLine(line, context) {
|
|
|
3180
3264
|
}
|
|
3181
3265
|
|
|
3182
3266
|
// src/proxy/identityProxy.ts
|
|
3267
|
+
init_basePath();
|
|
3183
3268
|
import http from "node:http";
|
|
3184
3269
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
3185
3270
|
import { timingSafeEqual } from "node:crypto";
|
|
@@ -18193,6 +18278,30 @@ var DOCUMENT_CONTENT_SECURITY_POLICY = [
|
|
|
18193
18278
|
"style-src 'self' 'unsafe-inline'",
|
|
18194
18279
|
"worker-src 'self' blob:"
|
|
18195
18280
|
].join("; ");
|
|
18281
|
+
function htmlAttributeEscape(value) {
|
|
18282
|
+
return value.replace(/&/gu, "&").replace(/"/gu, """).replace(/</gu, "<").replace(/>/gu, ">");
|
|
18283
|
+
}
|
|
18284
|
+
function rewriteHtmlForBasePath(html, basePath) {
|
|
18285
|
+
const normalized = normalizeBasePath(basePath);
|
|
18286
|
+
if (normalized.length === 0) return html;
|
|
18287
|
+
const escaped = htmlAttributeEscape(normalized);
|
|
18288
|
+
const meta3 = `<meta name="${AGENT_INSPECTOR_BASE_PATH_META_NAME}" content="${escaped}">`;
|
|
18289
|
+
const withMeta = html.includes(`name="${AGENT_INSPECTOR_BASE_PATH_META_NAME}"`) ? html : html.replace(/<head(\s[^>]*)?>/iu, (match) => `${match}${meta3}`);
|
|
18290
|
+
const escapedBase = normalized.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
18291
|
+
return withMeta.replace(
|
|
18292
|
+
new RegExp(`\\b(href|src|action)=("|')/(?!/|${escapedBase.slice(1)}(?:/|$))`, "giu"),
|
|
18293
|
+
(_match, attr, quote) => `${attr}=${quote}${normalized}/`
|
|
18294
|
+
);
|
|
18295
|
+
}
|
|
18296
|
+
function javaScriptStringEscape(value) {
|
|
18297
|
+
return value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"');
|
|
18298
|
+
}
|
|
18299
|
+
function rewriteJavaScriptForBasePath(source, basePath) {
|
|
18300
|
+
const normalized = normalizeBasePath(basePath);
|
|
18301
|
+
if (normalized.length === 0) return source;
|
|
18302
|
+
const escaped = javaScriptStringEscape(normalized);
|
|
18303
|
+
return source.replace(/\bbasepath:\s*""/gu, `basepath:"${escaped}"`).replace(/return"\/"\+([A-Za-z_$][\w$]*)/gu, `return"${escaped}/"+$1`).replace(/(["'])\/assets\//gu, `$1${normalized}/assets/`);
|
|
18304
|
+
}
|
|
18196
18305
|
function isLoopbackPeer(address) {
|
|
18197
18306
|
if (address === void 0) return false;
|
|
18198
18307
|
const normalized = address.toLowerCase();
|
|
@@ -18240,7 +18349,8 @@ function isSafeMethod(method) {
|
|
|
18240
18349
|
return normalized === "GET" || normalized === "HEAD" || normalized === "OPTIONS";
|
|
18241
18350
|
}
|
|
18242
18351
|
function isPublicHealthPath(pathname) {
|
|
18243
|
-
|
|
18352
|
+
const path2 = stripBasePath(pathname, getConfiguredBasePath(process.env));
|
|
18353
|
+
return path2 === "/livez" || path2 === "/readyz" || path2 === "/api/health";
|
|
18244
18354
|
}
|
|
18245
18355
|
function configuredPositiveInteger(value, fallback) {
|
|
18246
18356
|
return value !== void 0 && Number.isSafeInteger(value) && value > 0 ? value : fallback;
|
|
@@ -18253,7 +18363,10 @@ function declaredContentLength(value) {
|
|
|
18253
18363
|
}
|
|
18254
18364
|
function isBrowserMutationAllowed(input) {
|
|
18255
18365
|
if (isSafeMethod(input.method)) return true;
|
|
18256
|
-
const pathname =
|
|
18366
|
+
const pathname = stripBasePath(
|
|
18367
|
+
new URL(input.path, "http://localhost").pathname,
|
|
18368
|
+
getConfiguredBasePath(process.env)
|
|
18369
|
+
);
|
|
18257
18370
|
if (pathname === "/proxy" || pathname.startsWith("/proxy/")) return true;
|
|
18258
18371
|
const fetchSite = input.secFetchSite?.toLowerCase();
|
|
18259
18372
|
const browserRequest = input.origin !== void 0 || fetchSite !== void 0;
|
|
@@ -18273,7 +18386,10 @@ function isIdentityProxyRequestAllowed(input) {
|
|
|
18273
18386
|
if (input.options.restrictRemoteControl !== true) return true;
|
|
18274
18387
|
if (input.options.allowRemoteControl === true) return true;
|
|
18275
18388
|
if (isLoopbackPeer(input.remoteAddress)) return true;
|
|
18276
|
-
const pathname =
|
|
18389
|
+
const pathname = stripBasePath(
|
|
18390
|
+
new URL(input.path, "http://localhost").pathname,
|
|
18391
|
+
getConfiguredBasePath(process.env)
|
|
18392
|
+
);
|
|
18277
18393
|
if (pathname === "/proxy" || pathname.startsWith("/proxy/")) {
|
|
18278
18394
|
if (input.options.allowUnauthenticatedRemoteProxy === true) return true;
|
|
18279
18395
|
const proxyCredential = bearerToken(input.proxyAuthorization) ?? input.proxyTokenHeader ?? null;
|
|
@@ -18364,6 +18480,9 @@ function forceCloseIdentityProxy(server) {
|
|
|
18364
18480
|
server.close();
|
|
18365
18481
|
}
|
|
18366
18482
|
async function handleRequest(req, res, options) {
|
|
18483
|
+
const basePath = getConfiguredBasePath(process.env);
|
|
18484
|
+
const upstreamPath = stripBasePathFromRequestPath(req.url ?? "/", basePath);
|
|
18485
|
+
const requestUrl = new URL(req.url ?? "/", "http://localhost");
|
|
18367
18486
|
if (!isTrustedIdentityProxyHost(req.headers.host, options)) {
|
|
18368
18487
|
res.writeHead(400, {
|
|
18369
18488
|
"content-type": "application/json; charset=utf-8",
|
|
@@ -18373,6 +18492,15 @@ async function handleRequest(req, res, options) {
|
|
|
18373
18492
|
req.resume();
|
|
18374
18493
|
return;
|
|
18375
18494
|
}
|
|
18495
|
+
if (basePath.length > 0 && requestUrl.pathname.startsWith("/assets/")) {
|
|
18496
|
+
res.writeHead(307, {
|
|
18497
|
+
location: `${basePath}${requestUrl.pathname}${requestUrl.search}`,
|
|
18498
|
+
"cache-control": "no-store"
|
|
18499
|
+
});
|
|
18500
|
+
res.end();
|
|
18501
|
+
req.resume();
|
|
18502
|
+
return;
|
|
18503
|
+
}
|
|
18376
18504
|
if (!isBrowserMutationAllowed({
|
|
18377
18505
|
path: req.url ?? "/",
|
|
18378
18506
|
method: req.method,
|
|
@@ -18445,6 +18573,7 @@ async function handleRequest(req, res, options) {
|
|
|
18445
18573
|
for (const [name, value] of Object.entries(req.headers)) {
|
|
18446
18574
|
const lowerName = name.toLowerCase();
|
|
18447
18575
|
if (REQUEST_HOP_BY_HOP.has(lowerName)) continue;
|
|
18576
|
+
if (basePath.length > 0 && lowerName === "accept-encoding") continue;
|
|
18448
18577
|
if (lowerName.startsWith(IDENTITY_HEADER_PREFIX)) continue;
|
|
18449
18578
|
if (value === void 0) continue;
|
|
18450
18579
|
upstreamHeaders[name] = value;
|
|
@@ -18470,7 +18599,7 @@ async function handleRequest(req, res, options) {
|
|
|
18470
18599
|
{
|
|
18471
18600
|
hostname: options.upstreamHost,
|
|
18472
18601
|
port: options.upstreamPort,
|
|
18473
|
-
path:
|
|
18602
|
+
path: upstreamPath,
|
|
18474
18603
|
method: req.method,
|
|
18475
18604
|
headers: upstreamHeaders
|
|
18476
18605
|
},
|
|
@@ -18480,19 +18609,40 @@ async function handleRequest(req, res, options) {
|
|
|
18480
18609
|
return;
|
|
18481
18610
|
}
|
|
18482
18611
|
const outHeaders = {};
|
|
18612
|
+
const contentType = firstHeader(proxyRes.headers["content-type"]);
|
|
18613
|
+
const shouldRewriteHtml = basePath.length > 0 && contentType?.toLowerCase().includes("text/html") === true;
|
|
18614
|
+
const shouldRewriteJavaScript = basePath.length > 0 && (contentType?.toLowerCase().includes("javascript") === true || upstreamPath.split("?", 1)[0]?.endsWith(".js") === true);
|
|
18615
|
+
const shouldRewriteBody = shouldRewriteHtml || shouldRewriteJavaScript;
|
|
18483
18616
|
for (const [name, value] of Object.entries(proxyRes.headers)) {
|
|
18484
|
-
|
|
18617
|
+
const lowerName = name.toLowerCase();
|
|
18618
|
+
if (RESPONSE_HOP_BY_HOP.has(lowerName)) continue;
|
|
18619
|
+
if (shouldRewriteBody && lowerName === "content-length") continue;
|
|
18485
18620
|
if (value === void 0) continue;
|
|
18486
18621
|
outHeaders[name] = value;
|
|
18487
18622
|
}
|
|
18488
18623
|
for (const [name, value] of Object.entries(BASE_SECURITY_HEADERS)) {
|
|
18489
18624
|
outHeaders[name] = value;
|
|
18490
18625
|
}
|
|
18491
|
-
const contentType = firstHeader(proxyRes.headers["content-type"]);
|
|
18492
18626
|
if (contentType?.toLowerCase().includes("text/html") === true) {
|
|
18493
18627
|
outHeaders["content-security-policy"] = DOCUMENT_CONTENT_SECURITY_POLICY;
|
|
18494
18628
|
}
|
|
18495
18629
|
res.writeHead(proxyRes.statusCode ?? 502, outHeaders);
|
|
18630
|
+
if (shouldRewriteBody) {
|
|
18631
|
+
const chunks = [];
|
|
18632
|
+
proxyRes.on("data", (chunk) => {
|
|
18633
|
+
chunks.push(toBuffer(chunk));
|
|
18634
|
+
});
|
|
18635
|
+
proxyRes.on("end", () => {
|
|
18636
|
+
const body = Buffer3.concat(chunks).toString("utf8");
|
|
18637
|
+
res.end(
|
|
18638
|
+
shouldRewriteHtml ? rewriteHtmlForBasePath(body, basePath) : rewriteJavaScriptForBasePath(body, basePath)
|
|
18639
|
+
);
|
|
18640
|
+
});
|
|
18641
|
+
proxyRes.on("error", () => {
|
|
18642
|
+
if (!res.writableEnded) res.destroy();
|
|
18643
|
+
});
|
|
18644
|
+
return;
|
|
18645
|
+
}
|
|
18496
18646
|
proxyRes.pipe(res);
|
|
18497
18647
|
}
|
|
18498
18648
|
);
|
|
@@ -18591,14 +18741,17 @@ if (subcommand === "doctor") {
|
|
|
18591
18741
|
process.exit(code);
|
|
18592
18742
|
}
|
|
18593
18743
|
await runStart(process.argv.slice(2));
|
|
18594
|
-
async function isInspectorHealthy(port, host) {
|
|
18744
|
+
async function isInspectorHealthy(port, host, basePath = "") {
|
|
18595
18745
|
const controller = new AbortController();
|
|
18596
18746
|
const timeout = setTimeout(() => controller.abort(), LOCAL_PROBE_TIMEOUT_MS);
|
|
18597
18747
|
try {
|
|
18598
|
-
const response = await fetch(
|
|
18599
|
-
|
|
18600
|
-
|
|
18601
|
-
|
|
18748
|
+
const response = await fetch(
|
|
18749
|
+
appendBasePathToOrigin(urlForHost(port, probeHostForBindHost(host)), "/api/health", basePath),
|
|
18750
|
+
{
|
|
18751
|
+
cache: "no-store",
|
|
18752
|
+
signal: controller.signal
|
|
18753
|
+
}
|
|
18754
|
+
);
|
|
18602
18755
|
return response.ok;
|
|
18603
18756
|
} catch {
|
|
18604
18757
|
return false;
|
|
@@ -18606,14 +18759,17 @@ async function isInspectorHealthy(port, host) {
|
|
|
18606
18759
|
clearTimeout(timeout);
|
|
18607
18760
|
}
|
|
18608
18761
|
}
|
|
18609
|
-
async function getRunningCaptureMode(port, host) {
|
|
18762
|
+
async function getRunningCaptureMode(port, host, basePath = "") {
|
|
18610
18763
|
const controller = new AbortController();
|
|
18611
18764
|
const timeout = setTimeout(() => controller.abort(), LOCAL_PROBE_TIMEOUT_MS);
|
|
18612
18765
|
try {
|
|
18613
|
-
const response = await fetch(
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18766
|
+
const response = await fetch(
|
|
18767
|
+
appendBasePathToOrigin(urlForHost(port, probeHostForBindHost(host)), "/api/config", basePath),
|
|
18768
|
+
{
|
|
18769
|
+
cache: "no-store",
|
|
18770
|
+
signal: controller.signal
|
|
18771
|
+
}
|
|
18772
|
+
);
|
|
18617
18773
|
if (!response.ok) return null;
|
|
18618
18774
|
const raw = await response.json();
|
|
18619
18775
|
return readCaptureMode(raw);
|
|
@@ -18642,10 +18798,10 @@ function sleep(ms) {
|
|
|
18642
18798
|
setTimeout(resolve2, ms);
|
|
18643
18799
|
});
|
|
18644
18800
|
}
|
|
18645
|
-
async function waitForInspectorHealthy(port, timeoutMs, host) {
|
|
18801
|
+
async function waitForInspectorHealthy(port, timeoutMs, host, basePath = "") {
|
|
18646
18802
|
const start = Date.now();
|
|
18647
18803
|
while (Date.now() - start < timeoutMs) {
|
|
18648
|
-
if (await isInspectorHealthy(port, host)) return true;
|
|
18804
|
+
if (await isInspectorHealthy(port, host, basePath)) return true;
|
|
18649
18805
|
await sleep(250);
|
|
18650
18806
|
}
|
|
18651
18807
|
return false;
|
|
@@ -18720,9 +18876,9 @@ function readCaptureMode(raw) {
|
|
|
18720
18876
|
const value = descriptor?.value;
|
|
18721
18877
|
return typeof value === "string" ? parseCaptureMode(value) : null;
|
|
18722
18878
|
}
|
|
18723
|
-
function printAccessHints(port, host) {
|
|
18879
|
+
function printAccessHints(port, host, basePath = "") {
|
|
18724
18880
|
const networkUrls = networkUrlsForBindHost(port, host);
|
|
18725
|
-
for (const line of formatAccessHintLines(port, networkUrls, host)) {
|
|
18881
|
+
for (const line of formatAccessHintLines(port, networkUrls, host, basePath)) {
|
|
18726
18882
|
console.log(line);
|
|
18727
18883
|
}
|
|
18728
18884
|
if (!isLoopbackHost(host)) {
|
|
@@ -18966,12 +19122,19 @@ async function runStart(args) {
|
|
|
18966
19122
|
const upstreamPort = enableIdentityProxy ? pickUpstreamPort(port, legacyAliasPort) : port;
|
|
18967
19123
|
const upstreamHost = enableIdentityProxy ? DEFAULT_BIND_HOST : host;
|
|
18968
19124
|
process.env["PORT"] = String(upstreamPort);
|
|
19125
|
+
const basePath = getConfiguredBasePath(process.env);
|
|
18969
19126
|
const url2 = urlForHost(port, host);
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
19127
|
+
const uiUrl = appendBasePathToOrigin(url2, "/", basePath);
|
|
19128
|
+
const proxyUrl = appendBasePathToOrigin(url2, "/proxy", basePath);
|
|
19129
|
+
const proxyMessagesUrl = appendBasePathToOrigin(url2, "/proxy/v1/messages", basePath);
|
|
19130
|
+
const legacyUrl = legacyAliasPort === null ? null : appendBasePathToOrigin(localUrlForPort(legacyAliasPort), "/", basePath);
|
|
19131
|
+
const legacyProxyUrl = legacyAliasPort === null ? null : appendBasePathToOrigin(localUrlForPort(legacyAliasPort), "/proxy", basePath);
|
|
19132
|
+
const legacyMcpUrl = legacyAliasPort === null ? null : appendBasePathToOrigin(localUrlForPort(legacyAliasPort), "/api/mcp", basePath);
|
|
19133
|
+
if (!forceRestart && await isInspectorHealthy(port, host, basePath)) {
|
|
19134
|
+
console.log(`agent-inspector is already running at ${uiUrl}`);
|
|
19135
|
+
printAccessHints(port, host, basePath);
|
|
18973
19136
|
if (captureModeWasSpecified) {
|
|
18974
|
-
const runningMode = await getRunningCaptureMode(port, host);
|
|
19137
|
+
const runningMode = await getRunningCaptureMode(port, host, basePath);
|
|
18975
19138
|
if (runningMode !== null && runningMode !== captureMode) {
|
|
18976
19139
|
console.log(`Existing instance capture mode is ${runningMode}; requested ${captureMode}.`);
|
|
18977
19140
|
console.log(`Use --force-restart to restart with ${captureMode} mode.`);
|
|
@@ -18979,7 +19142,7 @@ async function runStart(args) {
|
|
|
18979
19142
|
}
|
|
18980
19143
|
console.log(`Use --force-restart to restart the existing instance.`);
|
|
18981
19144
|
if (open && openWasSpecified) {
|
|
18982
|
-
openBrowser(
|
|
19145
|
+
openBrowser(uiUrl);
|
|
18983
19146
|
}
|
|
18984
19147
|
return;
|
|
18985
19148
|
}
|
|
@@ -19026,44 +19189,42 @@ async function runStart(args) {
|
|
|
19026
19189
|
console.error(`Failed to start Agent Inspector background supervisor: ${err.message}`);
|
|
19027
19190
|
});
|
|
19028
19191
|
supervisorProcess.unref();
|
|
19029
|
-
if (await waitForInspectorHealthy(port, 1e4, host)) {
|
|
19030
|
-
console.log(`agent-inspector background server is ready at ${
|
|
19031
|
-
printAccessHints(port, host);
|
|
19032
|
-
if (
|
|
19033
|
-
console.log(` Legacy proxy:
|
|
19034
|
-
console.log(` Legacy MCP:
|
|
19192
|
+
if (await waitForInspectorHealthy(port, 1e4, host, basePath)) {
|
|
19193
|
+
console.log(`agent-inspector background server is ready at ${uiUrl}`);
|
|
19194
|
+
printAccessHints(port, host, basePath);
|
|
19195
|
+
if (legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
19196
|
+
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
19197
|
+
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
19035
19198
|
}
|
|
19036
19199
|
console.log(``);
|
|
19037
19200
|
console.log(`Route AI coding tools through the identity proxy for accurate PID attribution:`);
|
|
19038
|
-
console.log(` Claude Code: ANTHROPIC_BASE_URL
|
|
19039
|
-
console.log(` OpenCode: LLM_BASE_URL
|
|
19040
|
-
console.log(` MiMo Code: OPENAI_BASE_URL
|
|
19201
|
+
console.log(` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`);
|
|
19202
|
+
console.log(` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`);
|
|
19203
|
+
console.log(` MiMo Code: OPENAI_BASE_URL=${proxyUrl} mimo`);
|
|
19041
19204
|
if (open && openWasSpecified) {
|
|
19042
|
-
openBrowser(
|
|
19205
|
+
openBrowser(uiUrl);
|
|
19043
19206
|
}
|
|
19044
19207
|
return;
|
|
19045
19208
|
}
|
|
19046
|
-
console.error(`agent-inspector background server did not become ready at ${
|
|
19209
|
+
console.error(`agent-inspector background server did not become ready at ${uiUrl}.`);
|
|
19047
19210
|
process.exitCode = 1;
|
|
19048
19211
|
return;
|
|
19049
19212
|
}
|
|
19050
|
-
console.log(`Server running at ${
|
|
19213
|
+
console.log(`Server running at ${uiUrl}`);
|
|
19051
19214
|
console.log(` Capture mode: ${captureMode}`);
|
|
19052
|
-
console.log(` Proxy: ${
|
|
19053
|
-
printAccessHints(port, host);
|
|
19054
|
-
if (
|
|
19055
|
-
console.log(` Legacy UI:
|
|
19056
|
-
console.log(` Legacy proxy:
|
|
19057
|
-
console.log(` Legacy MCP:
|
|
19215
|
+
console.log(` Proxy: ${proxyUrl}`);
|
|
19216
|
+
printAccessHints(port, host, basePath);
|
|
19217
|
+
if (legacyUrl !== null && legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
19218
|
+
console.log(` Legacy UI: ${legacyUrl}`);
|
|
19219
|
+
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
19220
|
+
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
19058
19221
|
}
|
|
19059
19222
|
console.log(``);
|
|
19060
19223
|
console.log(`Route AI coding tools through the proxy:`);
|
|
19061
|
-
console.log(` Claude Code: ANTHROPIC_BASE_URL=${
|
|
19062
|
-
console.log(` OpenCode: LLM_BASE_URL=${
|
|
19063
|
-
console.log(` MiMo Code: OPENAI_BASE_URL=${
|
|
19064
|
-
console.log(
|
|
19065
|
-
` Direct HTTP: curl ${url2}/proxy/v1/messages -d '{"model":"...","messages":[...]}'`
|
|
19066
|
-
);
|
|
19224
|
+
console.log(` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`);
|
|
19225
|
+
console.log(` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`);
|
|
19226
|
+
console.log(` MiMo Code: OPENAI_BASE_URL=${proxyUrl} mimo`);
|
|
19227
|
+
console.log(` Direct HTTP: curl ${proxyMessagesUrl} -d '{"model":"...","messages":[...]}'`);
|
|
19067
19228
|
console.log(
|
|
19068
19229
|
` Remote/container tools: use the Network proxy URL above when shown; otherwise restart with --host 0.0.0.0 or a reachable IP.`
|
|
19069
19230
|
);
|
|
@@ -19075,7 +19236,7 @@ async function runStart(args) {
|
|
|
19075
19236
|
` Example: ROUTES='{"claude-":"https://api.anthropic.com","MiniMax":"https://api.minimaxi.com/anthropic"}'`
|
|
19076
19237
|
);
|
|
19077
19238
|
if (open) {
|
|
19078
|
-
openBrowser(
|
|
19239
|
+
openBrowser(uiUrl);
|
|
19079
19240
|
}
|
|
19080
19241
|
const outputDir = __dirname2;
|
|
19081
19242
|
const serverPath = join7(outputDir, "../.output/server/index.mjs");
|
|
@@ -19098,6 +19259,9 @@ async function runStart(args) {
|
|
|
19098
19259
|
}
|
|
19099
19260
|
serverEnv["HOST"] = upstreamHost;
|
|
19100
19261
|
serverEnv["NITRO_HOST"] = upstreamHost;
|
|
19262
|
+
if (enableIdentityProxy && basePath.length > 0) {
|
|
19263
|
+
serverEnv[AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV] = "1";
|
|
19264
|
+
}
|
|
19101
19265
|
serverEnv["AGENT_INSPECTOR_PUBLIC_PORT"] = String(port);
|
|
19102
19266
|
serverEnv["PROXY_PORT"] = String(port);
|
|
19103
19267
|
serverEnv["AGENT_INSPECTOR_CAPTURE_MODE"] = captureMode;
|
|
@@ -19173,29 +19337,30 @@ async function runStart(args) {
|
|
|
19173
19337
|
}
|
|
19174
19338
|
if (background) {
|
|
19175
19339
|
serverProcess.unref();
|
|
19176
|
-
|
|
19177
|
-
|
|
19340
|
+
const upstreamProbeBasePath = enableIdentityProxy ? "" : basePath;
|
|
19341
|
+
if (await waitForInspectorHealthy(upstreamPort, 5e3, host, upstreamProbeBasePath)) {
|
|
19342
|
+
console.log(`agent-inspector background server is ready at ${uiUrl}`);
|
|
19178
19343
|
if (identityProxies.length > 0) {
|
|
19179
19344
|
console.log(`Identity proxy ready on port ${port} (PID-attributing proxy).`);
|
|
19180
19345
|
}
|
|
19181
|
-
printAccessHints(port, host);
|
|
19182
|
-
if (
|
|
19183
|
-
console.log(` Legacy proxy:
|
|
19184
|
-
console.log(` Legacy MCP:
|
|
19346
|
+
printAccessHints(port, host, basePath);
|
|
19347
|
+
if (legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
19348
|
+
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
19349
|
+
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
19185
19350
|
}
|
|
19186
19351
|
if (identityProxies.length > 0) {
|
|
19187
19352
|
console.log(
|
|
19188
19353
|
``,
|
|
19189
19354
|
`Route AI coding tools through the identity proxy for accurate PID attribution:`,
|
|
19190
|
-
` Claude Code: ANTHROPIC_BASE_URL
|
|
19191
|
-
` OpenCode: LLM_BASE_URL
|
|
19192
|
-
` MiMo Code: OPENAI_BASE_URL
|
|
19193
|
-
|
|
19355
|
+
` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`,
|
|
19356
|
+
` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`,
|
|
19357
|
+
` MiMo Code: OPENAI_BASE_URL=${proxyUrl} mimo`,
|
|
19358
|
+
legacyProxyUrl === null ? ` Override the port with --port <n> when needed.` : ` Legacy configs using ${legacyProxyUrl} still work.`
|
|
19194
19359
|
);
|
|
19195
19360
|
}
|
|
19196
19361
|
return;
|
|
19197
19362
|
}
|
|
19198
|
-
console.error(`agent-inspector background server did not become ready at ${
|
|
19363
|
+
console.error(`agent-inspector background server did not become ready at ${uiUrl}.`);
|
|
19199
19364
|
process.exitCode = 1;
|
|
19200
19365
|
return;
|
|
19201
19366
|
}
|
package/.output/nitro.json
CHANGED