nextclaw 0.4.14 → 0.4.15
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/dist/cli/index.js
CHANGED
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from "fs";
|
|
82
82
|
import { join, resolve } from "path";
|
|
83
83
|
import { spawn } from "child_process";
|
|
84
|
-
import { createServer } from "net";
|
|
84
|
+
import { createServer, isIP } from "net";
|
|
85
85
|
import { fileURLToPath } from "url";
|
|
86
86
|
import { getDataDir, getPackageVersion as getCorePackageVersion } from "@nextclaw/core";
|
|
87
87
|
function resolveUiConfig(config2, overrides) {
|
|
@@ -92,6 +92,41 @@ function resolveUiApiBase(host, port) {
|
|
|
92
92
|
const normalizedHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
93
93
|
return `http://${normalizedHost}:${port}`;
|
|
94
94
|
}
|
|
95
|
+
function isLoopbackHost(host) {
|
|
96
|
+
const normalized = host.trim().toLowerCase();
|
|
97
|
+
return normalized === "127.0.0.1" || normalized === "localhost" || normalized === "::1";
|
|
98
|
+
}
|
|
99
|
+
var PUBLIC_IP_CHECK_URLS = ["https://api.ipify.org", "https://ifconfig.me/ip"];
|
|
100
|
+
async function fetchPublicIpFrom(url, timeoutMs) {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetch(url, {
|
|
105
|
+
signal: controller.signal,
|
|
106
|
+
headers: {
|
|
107
|
+
Accept: "text/plain"
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const text = (await response.text()).trim();
|
|
114
|
+
return isIP(text) ? text : null;
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
} finally {
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function resolvePublicIp(timeoutMs = 1500) {
|
|
122
|
+
for (const endpoint of PUBLIC_IP_CHECK_URLS) {
|
|
123
|
+
const candidate = await fetchPublicIpFrom(endpoint, timeoutMs);
|
|
124
|
+
if (candidate) {
|
|
125
|
+
return candidate;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
95
130
|
function isDevRuntime() {
|
|
96
131
|
return import.meta.url.includes("/src/cli/") || process.env.NEXTCLAW_DEV === "1";
|
|
97
132
|
}
|
|
@@ -989,6 +1024,12 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
989
1024
|
if (opts.uiOpen) {
|
|
990
1025
|
uiOverrides.open = true;
|
|
991
1026
|
}
|
|
1027
|
+
if (opts.public) {
|
|
1028
|
+
uiOverrides.enabled = true;
|
|
1029
|
+
if (!opts.uiHost) {
|
|
1030
|
+
uiOverrides.host = "0.0.0.0";
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
992
1033
|
await this.startGateway({ uiOverrides });
|
|
993
1034
|
}
|
|
994
1035
|
async ui(opts) {
|
|
@@ -1002,6 +1043,9 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1002
1043
|
if (opts.port) {
|
|
1003
1044
|
uiOverrides.port = Number(opts.port);
|
|
1004
1045
|
}
|
|
1046
|
+
if (opts.public && !opts.host) {
|
|
1047
|
+
uiOverrides.host = "0.0.0.0";
|
|
1048
|
+
}
|
|
1005
1049
|
await this.startGateway({ uiOverrides, allowMissingProvider: true });
|
|
1006
1050
|
}
|
|
1007
1051
|
async start(opts) {
|
|
@@ -1016,6 +1060,9 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1016
1060
|
if (opts.uiPort) {
|
|
1017
1061
|
uiOverrides.port = Number(opts.uiPort);
|
|
1018
1062
|
}
|
|
1063
|
+
if (opts.public && !opts.uiHost) {
|
|
1064
|
+
uiOverrides.host = "0.0.0.0";
|
|
1065
|
+
}
|
|
1019
1066
|
const devMode = isDevRuntime();
|
|
1020
1067
|
if (devMode) {
|
|
1021
1068
|
const requestedUiPort = Number.isFinite(Number(opts.uiPort)) ? Number(opts.uiPort) : 18792;
|
|
@@ -1072,6 +1119,9 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
1072
1119
|
if (opts.uiPort) {
|
|
1073
1120
|
uiOverrides.port = Number(opts.uiPort);
|
|
1074
1121
|
}
|
|
1122
|
+
if (opts.public && !opts.uiHost) {
|
|
1123
|
+
uiOverrides.host = "0.0.0.0";
|
|
1124
|
+
}
|
|
1075
1125
|
const devMode = isDevRuntime();
|
|
1076
1126
|
if (devMode && uiOverrides.port === void 0) {
|
|
1077
1127
|
uiOverrides.port = 18792;
|
|
@@ -2104,6 +2154,20 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
2104
2154
|
setPluginRuntimeBridge(null);
|
|
2105
2155
|
}
|
|
2106
2156
|
}
|
|
2157
|
+
async printPublicUiUrls(host, port) {
|
|
2158
|
+
if (isLoopbackHost(host)) {
|
|
2159
|
+
console.log('Public URL: disabled (UI host is loopback). Use "--public" or "--ui-host 0.0.0.0" to expose it.');
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
const publicIp = await resolvePublicIp();
|
|
2163
|
+
if (!publicIp) {
|
|
2164
|
+
console.log("Public URL: UI is exposed, but automatic public IP detection failed.");
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
const publicBase = `http://${publicIp}:${port}`;
|
|
2168
|
+
console.log(`Public UI (if firewall/NAT allows): ${publicBase}`);
|
|
2169
|
+
console.log(`Public API (if firewall/NAT allows): ${publicBase}/api`);
|
|
2170
|
+
}
|
|
2107
2171
|
startUiIfEnabled(uiConfig, uiStaticDir) {
|
|
2108
2172
|
if (!uiConfig.enabled) {
|
|
2109
2173
|
return;
|
|
@@ -2119,6 +2183,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
2119
2183
|
if (uiStaticDir) {
|
|
2120
2184
|
console.log(`\u2713 UI frontend: ${uiUrl}`);
|
|
2121
2185
|
}
|
|
2186
|
+
void this.printPublicUiUrls(uiServer.host, uiServer.port);
|
|
2122
2187
|
if (uiConfig.open) {
|
|
2123
2188
|
openBrowser(uiUrl);
|
|
2124
2189
|
}
|
|
@@ -2209,6 +2274,7 @@ ${this.logo} ${APP_NAME} is ready! (${source})`);
|
|
|
2209
2274
|
console.log(`\u2713 ${APP_NAME} started in background (PID ${state.pid})`);
|
|
2210
2275
|
console.log(`UI: ${uiUrl}`);
|
|
2211
2276
|
console.log(`API: ${apiUrl}`);
|
|
2277
|
+
await this.printPublicUiUrls(uiConfig.host, uiConfig.port);
|
|
2212
2278
|
console.log(`Logs: ${logPath}`);
|
|
2213
2279
|
console.log(`Stop: ${APP_NAME} stop`);
|
|
2214
2280
|
if (options.open) {
|
|
@@ -2480,11 +2546,11 @@ var runtime = new CliRuntime({ logo: LOGO });
|
|
|
2480
2546
|
program.name(APP_NAME2).description(`${LOGO} ${APP_NAME2} - ${APP_TAGLINE}`).version(getPackageVersion(), "-v, --version", "show version");
|
|
2481
2547
|
program.command("onboard").description(`Initialize ${APP_NAME2} configuration and workspace`).action(async () => runtime.onboard());
|
|
2482
2548
|
program.command("init").description(`Initialize ${APP_NAME2} configuration and workspace`).option("-f, --force", "Overwrite existing template files").action(async (opts) => runtime.init({ force: Boolean(opts.force) }));
|
|
2483
|
-
program.command("gateway").description(`Start the ${APP_NAME2} gateway`).option("-p, --port <port>", "Gateway port", "18790").option("-v, --verbose", "Verbose output", false).option("--ui", "Enable UI server", false).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--ui-open", "Open browser when UI starts", false).action(async (opts) => runtime.gateway(opts));
|
|
2484
|
-
program.command("ui").description(`Start the ${APP_NAME2} UI with gateway`).option("--host <host>", "UI host").option("--port <port>", "UI port").option("--no-open", "Disable opening browser").action(async (opts) => runtime.ui(opts));
|
|
2485
|
-
program.command("start").description(`Start the ${APP_NAME2} gateway + UI in the background`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).action(async (opts) => runtime.start(opts));
|
|
2486
|
-
program.command("restart").description(`Restart the ${APP_NAME2} background service`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after restart", false).action(async (opts) => runtime.restart(opts));
|
|
2487
|
-
program.command("serve").description(`Run the ${APP_NAME2} gateway + UI in the foreground`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).action(async (opts) => runtime.serve(opts));
|
|
2549
|
+
program.command("gateway").description(`Start the ${APP_NAME2} gateway`).option("-p, --port <port>", "Gateway port", "18790").option("-v, --verbose", "Verbose output", false).option("--ui", "Enable UI server", false).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--ui-open", "Open browser when UI starts", false).option("--public", "Expose UI on 0.0.0.0 and print public URL", false).action(async (opts) => runtime.gateway(opts));
|
|
2550
|
+
program.command("ui").description(`Start the ${APP_NAME2} UI with gateway`).option("--host <host>", "UI host").option("--port <port>", "UI port").option("--no-open", "Disable opening browser").option("--public", "Expose UI on 0.0.0.0 and print public URL", false).action(async (opts) => runtime.ui(opts));
|
|
2551
|
+
program.command("start").description(`Start the ${APP_NAME2} gateway + UI in the background`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).option("--public", "Expose UI on 0.0.0.0 and print public URL", false).action(async (opts) => runtime.start(opts));
|
|
2552
|
+
program.command("restart").description(`Restart the ${APP_NAME2} background service`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after restart", false).option("--public", "Expose UI on 0.0.0.0 and print public URL", false).action(async (opts) => runtime.restart(opts));
|
|
2553
|
+
program.command("serve").description(`Run the ${APP_NAME2} gateway + UI in the foreground`).option("--ui-host <host>", "UI host").option("--ui-port <port>", "UI port").option("--frontend", "Start UI frontend dev server").option("--frontend-port <port>", "UI frontend dev server port").option("--open", "Open browser after start", false).option("--public", "Expose UI on 0.0.0.0 and print public URL", false).action(async (opts) => runtime.serve(opts));
|
|
2488
2554
|
program.command("stop").description(`Stop the ${APP_NAME2} background service`).action(async () => runtime.stop());
|
|
2489
2555
|
program.command("agent").description("Interact with the agent directly").option("-m, --message <message>", "Message to send to the agent").option("-s, --session <session>", "Session ID", "cli:default").option("--no-markdown", "Disable Markdown rendering").action(async (opts) => runtime.agent(opts));
|
|
2490
2556
|
program.command("update").description(`Update ${APP_NAME2}`).option("--timeout <ms>", "Update command timeout in milliseconds").action(async (opts) => runtime.update(opts));
|