@nordbyte/nordrelay 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/dist/access-control.js +3 -0
- package/dist/agent-feature-matrix.js +42 -0
- package/dist/agent-updates.js +294 -0
- package/dist/bot.js +169 -209
- package/dist/channel-actions.js +372 -0
- package/dist/operations.js +33 -8
- package/dist/relay-runtime.js +128 -24
- package/dist/session-format.js +72 -3
- package/dist/web-dashboard-assets.js +2 -0
- package/dist/web-dashboard-client.js +275 -0
- package/dist/web-dashboard-style.js +9 -0
- package/dist/web-dashboard.js +62 -244
- package/package.json +1 -1
- package/plugins/nordrelay/scripts/nordrelay.mjs +56 -9
|
@@ -49,8 +49,8 @@ function parseArgs(argv) {
|
|
|
49
49
|
home: process.env.NORDRELAY_HOME || DEFAULT_HOME,
|
|
50
50
|
dropPendingUpdates: !envFlag("NORDRELAY_KEEP_PENDING_UPDATES"),
|
|
51
51
|
force: false,
|
|
52
|
-
host:
|
|
53
|
-
port:
|
|
52
|
+
host: undefined,
|
|
53
|
+
port: undefined,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
for (let i = 0; i < copy.length; i += 1) {
|
|
@@ -175,9 +175,31 @@ async function readPid(pidFile) {
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
function resolveDashboardEndpoint(options, settings = {}) {
|
|
179
|
+
const host = options.host || process.env.NORDRELAY_DASHBOARD_HOST || "127.0.0.1";
|
|
180
|
+
const rawPort = options.port ?? Number.parseInt(process.env.NORDRELAY_DASHBOARD_PORT || "31878", 10);
|
|
181
|
+
if (!Number.isFinite(rawPort) || rawPort <= 0) {
|
|
182
|
+
if (settings.strict) {
|
|
183
|
+
throw new Error("Dashboard port must be a positive number.");
|
|
184
|
+
}
|
|
185
|
+
return { host, port: 31878 };
|
|
186
|
+
}
|
|
187
|
+
const port = rawPort;
|
|
188
|
+
return { host, port };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function formatDashboardUrl(endpoint) {
|
|
192
|
+
const host = endpoint.host || "127.0.0.1";
|
|
193
|
+
const displayHost = host === "0.0.0.0" || host === "" ? "127.0.0.1" : host === "::" ? "::1" : host;
|
|
194
|
+
const formattedHost = displayHost.includes(":") && !displayHost.startsWith("[") ? `[${displayHost}]` : displayHost;
|
|
195
|
+
const bindHint = displayHost === host ? "" : ` (binds ${host || "all interfaces"})`;
|
|
196
|
+
return `http://${formattedHost}:${endpoint.port}/${bindHint}`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function commandStart(options, settings = {}) {
|
|
179
200
|
await mkdirp(options.home);
|
|
180
201
|
loadEnvFiles(options.home);
|
|
202
|
+
const dashboard = resolveDashboardEndpoint(options);
|
|
181
203
|
|
|
182
204
|
const currentPid = await readPid(options.pidFile);
|
|
183
205
|
if (isProcessRunning(currentPid)) {
|
|
@@ -210,6 +232,9 @@ async function commandStart(options) {
|
|
|
210
232
|
console.log(`Started ${APP_NAME} ${VERSION} with PID ${child.pid}`);
|
|
211
233
|
console.log(`Workspace: ${state.workspace || "-"}`);
|
|
212
234
|
console.log(`Mode: ${state.sessionMode || "per Telegram context"}`);
|
|
235
|
+
if (!settings.skipWebHint) {
|
|
236
|
+
console.log(`WebUI: ${formatDashboardUrl(dashboard)} (run \`nordrelay web\` to start it)`);
|
|
237
|
+
}
|
|
213
238
|
console.log(`Log: ${options.logFile}`);
|
|
214
239
|
return;
|
|
215
240
|
}
|
|
@@ -225,9 +250,27 @@ async function commandStart(options) {
|
|
|
225
250
|
}
|
|
226
251
|
|
|
227
252
|
console.log(`Started ${APP_NAME} ${VERSION} with PID ${child.pid}`);
|
|
253
|
+
if (!settings.skipWebHint) {
|
|
254
|
+
console.log(`WebUI: ${formatDashboardUrl(dashboard)} (run \`nordrelay web\` to start it)`);
|
|
255
|
+
}
|
|
228
256
|
console.log(`Startup is still in progress. Log: ${options.logFile}`);
|
|
229
257
|
}
|
|
230
258
|
|
|
259
|
+
async function ensureConnectorStartedForWeb(options) {
|
|
260
|
+
const currentPid = await readPid(options.pidFile);
|
|
261
|
+
if (isProcessRunning(currentPid)) {
|
|
262
|
+
console.log(`NordRelay connector already running with PID ${currentPid}.`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
console.log("Starting NordRelay connector...");
|
|
267
|
+
const previousExitCode = process.exitCode;
|
|
268
|
+
await commandStart(options, { skipWebHint: true });
|
|
269
|
+
if (process.exitCode && process.exitCode !== previousExitCode) {
|
|
270
|
+
throw new Error(`NordRelay connector failed to start. See ${options.logFile}.`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
231
274
|
async function waitForState(stateFile, pid, timeoutMs) {
|
|
232
275
|
const deadline = Date.now() + timeoutMs;
|
|
233
276
|
while (Date.now() < deadline) {
|
|
@@ -268,6 +311,7 @@ async function commandStop(options) {
|
|
|
268
311
|
|
|
269
312
|
async function commandStatus(options) {
|
|
270
313
|
loadEnvFiles(options.home);
|
|
314
|
+
const dashboard = resolveDashboardEndpoint(options);
|
|
271
315
|
const pid = await readPid(options.pidFile);
|
|
272
316
|
const state = await readJson(options.stateFile, {});
|
|
273
317
|
const running = isProcessRunning(pid);
|
|
@@ -282,6 +326,7 @@ async function commandStatus(options) {
|
|
|
282
326
|
console.log(`OpenClaw CLI: ${state.openClawCli || "-"}`);
|
|
283
327
|
console.log(`Claude Code CLI: ${state.claudeCodeCli || "-"}`);
|
|
284
328
|
console.log(`OpenClaw Gateway: ${state.openClawGateway || process.env.OPENCLAW_GATEWAY_URL || "-"}`);
|
|
329
|
+
console.log(`WebUI: ${formatDashboardUrl(dashboard)}`);
|
|
285
330
|
console.log(`Log: ${options.logFile}`);
|
|
286
331
|
if (state.error) console.log(`Error: ${state.error}`);
|
|
287
332
|
}
|
|
@@ -472,8 +517,8 @@ async function checkOpenClawGateway() {
|
|
|
472
517
|
async function commandWeb(options) {
|
|
473
518
|
await mkdirp(options.home);
|
|
474
519
|
loadEnvFiles(options.home);
|
|
475
|
-
const host = options
|
|
476
|
-
|
|
520
|
+
const { host, port } = resolveDashboardEndpoint(options, { strict: true });
|
|
521
|
+
await ensureConnectorStartedForWeb(options);
|
|
477
522
|
const entry = await resolveWebRuntimeEntry();
|
|
478
523
|
if (!entry) {
|
|
479
524
|
throw new Error(`Missing dashboard runtime. Run \`npm install\` and \`npm run build\` in ${RUNTIME_ROOT}.`);
|
|
@@ -564,21 +609,23 @@ async function commandForeground(options) {
|
|
|
564
609
|
});
|
|
565
610
|
|
|
566
611
|
const previousState = await readJson(options.stateFile, {});
|
|
612
|
+
const stoppedBySignal = exit.signal === "SIGTERM" || exit.signal === "SIGINT";
|
|
613
|
+
const stopped = exit.code === 0 || stoppedBySignal;
|
|
567
614
|
await writeJsonAtomic(options.stateFile, {
|
|
568
|
-
status:
|
|
615
|
+
status: stopped ? "stopped" : "error",
|
|
569
616
|
pid: process.pid,
|
|
570
617
|
updatedAt: nowIso(),
|
|
571
618
|
exitCode: exit.code,
|
|
572
619
|
signal: exit.signal,
|
|
573
|
-
error:
|
|
620
|
+
error: stopped ? undefined : previousState.error,
|
|
574
621
|
logFile: options.logFile,
|
|
575
622
|
});
|
|
576
623
|
|
|
577
|
-
if (exit.signal) {
|
|
624
|
+
if (exit.signal && !stoppedBySignal) {
|
|
578
625
|
process.kill(process.pid, exit.signal);
|
|
579
626
|
return;
|
|
580
627
|
}
|
|
581
|
-
process.exit(exit.code ??
|
|
628
|
+
process.exit(stopped ? 0 : exit.code ?? 1);
|
|
582
629
|
}
|
|
583
630
|
|
|
584
631
|
async function resolveRuntimeEntry() {
|