@nextclaw/remote 0.1.14 → 0.1.16
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/index.d.ts +14 -1
- package/dist/index.js +76 -4
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -206,4 +206,17 @@ declare class RemoteServiceModule {
|
|
|
206
206
|
stop(): Promise<void>;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
type PlatformSessionTokenState = {
|
|
210
|
+
valid: false;
|
|
211
|
+
reason: "missing" | "malformed" | "expired";
|
|
212
|
+
payload: Record<string, unknown> | null;
|
|
213
|
+
} | {
|
|
214
|
+
valid: true;
|
|
215
|
+
reason: "valid";
|
|
216
|
+
payload: Record<string, unknown>;
|
|
217
|
+
};
|
|
218
|
+
declare function decodePlatformSessionTokenPayload(token: string): Record<string, unknown> | null;
|
|
219
|
+
declare function readPlatformSessionTokenState(token: string | null | undefined): PlatformSessionTokenState;
|
|
220
|
+
declare function isValidPlatformSessionToken(token: string | null | undefined): token is string;
|
|
221
|
+
|
|
222
|
+
export { type PlatformSessionTokenState, type RegisteredRemoteDevice, type RelayRequestFrame, type RemoteConnectCommandOptions, RemoteConnector, type RemoteConnectorRunOptions, type RemoteDoctorCommandOptions, type RemoteEnableCommandOptions, type RemoteLogger, RemotePlatformClient, type RemotePlatformClientDeps, RemoteRelayBridge, type RemoteRunContext, RemoteRuntimeActions, type RemoteRuntimeState, RemoteServiceModule, type RemoteServiceStateView, type RemoteStatusCommandOptions, type RemoteStatusSnapshot, RemoteStatusStore, type RemoteStatusWriter, buildConfiguredRemoteState, decodePlatformSessionTokenPayload, delay, isValidPlatformSessionToken, normalizeOptionalString, readPlatformSessionTokenState, redactWsUrl, registerRemoteCommands, resolveRemoteStatusSnapshot };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ function registerRemoteCommands(program, runtime) {
|
|
|
5
5
|
remote.command("disable").description("Disable service-managed remote access").action(async () => runtime.disable());
|
|
6
6
|
remote.command("status").description("Show remote access status").option("--json", "Print JSON").action(async (opts) => runtime.status(opts));
|
|
7
7
|
remote.command("doctor").description("Run remote access diagnostics").option("--json", "Print JSON").action(async (opts) => runtime.doctor(opts));
|
|
8
|
-
remote.command("connect").description("Foreground debug mode: register this machine and keep the connector online").option("--api-base <url>", "Platform API base (supports /v1 suffix)").option("--local-origin <url>", "Local NextClaw UI origin (default: active service or http://127.0.0.1:
|
|
8
|
+
remote.command("connect").description("Foreground debug mode: register this machine and keep the connector online").option("--api-base <url>", "Platform API base (supports /v1 suffix)").option("--local-origin <url>", "Local NextClaw UI origin (default: active service or http://127.0.0.1:55667)").option("--name <name>", "Device display name").option("--once", "Connect once without auto-reconnect", false).action(async (opts) => runtime.connect(opts));
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// src/remote-runtime-actions.ts
|
|
@@ -53,6 +53,68 @@ var RemoteRuntimeActions = class {
|
|
|
53
53
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
54
54
|
import { dirname, join } from "path";
|
|
55
55
|
import { hostname, platform as readPlatform } from "os";
|
|
56
|
+
|
|
57
|
+
// src/platform-session-token.ts
|
|
58
|
+
function decodeBase64UrlSegment(segment) {
|
|
59
|
+
try {
|
|
60
|
+
return Buffer.from(segment, "base64url").toString("utf-8");
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function decodePlatformSessionTokenPayload(token) {
|
|
66
|
+
const segments = token.split(".");
|
|
67
|
+
if (segments.length !== 3 || segments[0] !== "nca" || !segments[1]) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const raw = decodeBase64UrlSegment(segments[1]);
|
|
71
|
+
if (!raw) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(raw);
|
|
76
|
+
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function readPlatformSessionTokenState(token) {
|
|
82
|
+
if (typeof token !== "string" || token.trim().length === 0) {
|
|
83
|
+
return {
|
|
84
|
+
valid: false,
|
|
85
|
+
reason: "missing",
|
|
86
|
+
payload: null
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const trimmed = token.trim();
|
|
90
|
+
const payload = decodePlatformSessionTokenPayload(trimmed);
|
|
91
|
+
if (!payload) {
|
|
92
|
+
return {
|
|
93
|
+
valid: false,
|
|
94
|
+
reason: "malformed",
|
|
95
|
+
payload: null
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const exp = typeof payload.exp === "number" && Number.isFinite(payload.exp) ? payload.exp : Number.NaN;
|
|
99
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
100
|
+
if (!Number.isFinite(exp) || exp <= now) {
|
|
101
|
+
return {
|
|
102
|
+
valid: false,
|
|
103
|
+
reason: "expired",
|
|
104
|
+
payload
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
valid: true,
|
|
109
|
+
reason: "valid",
|
|
110
|
+
payload
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function isValidPlatformSessionToken(token) {
|
|
114
|
+
return readPlatformSessionTokenState(token).valid;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/remote-platform-client.ts
|
|
56
118
|
function ensureDir(path) {
|
|
57
119
|
mkdirSync(path, { recursive: true });
|
|
58
120
|
}
|
|
@@ -169,16 +231,23 @@ var RemotePlatformClient = class {
|
|
|
169
231
|
const providers = config.providers;
|
|
170
232
|
const nextclawProvider = providers.nextclaw;
|
|
171
233
|
const token = typeof nextclawProvider?.apiKey === "string" ? nextclawProvider.apiKey.trim() : "";
|
|
172
|
-
|
|
234
|
+
const tokenState = readPlatformSessionTokenState(token);
|
|
235
|
+
if (tokenState.reason === "missing") {
|
|
173
236
|
throw new Error('NextClaw platform token is missing. Run "nextclaw login" first.');
|
|
174
237
|
}
|
|
238
|
+
if (tokenState.reason === "expired") {
|
|
239
|
+
throw new Error('NextClaw platform token expired. Run "nextclaw login" or browser sign-in again.');
|
|
240
|
+
}
|
|
241
|
+
if (tokenState.reason === "malformed") {
|
|
242
|
+
throw new Error('NextClaw platform token is invalid. Run "nextclaw login" again.');
|
|
243
|
+
}
|
|
175
244
|
const configuredApiBase = normalizeOptionalString(config.remote.platformApiBase) ?? (typeof nextclawProvider?.apiBase === "string" ? nextclawProvider.apiBase.trim() : "");
|
|
176
245
|
const rawApiBase = normalizeOptionalString(opts.apiBase) ?? configuredApiBase;
|
|
177
246
|
if (!rawApiBase) {
|
|
178
247
|
throw new Error("Platform API base is missing. Pass --api-base, run nextclaw login, or set remote.platformApiBase.");
|
|
179
248
|
}
|
|
180
249
|
const platformBase = this.deps.resolvePlatformBase(rawApiBase);
|
|
181
|
-
return { platformBase, token, config };
|
|
250
|
+
return { platformBase, token: token.trim(), config };
|
|
182
251
|
}
|
|
183
252
|
resolveLocalOrigin(config, opts) {
|
|
184
253
|
const explicitOrigin = normalizeOptionalString(opts.localOrigin);
|
|
@@ -189,7 +258,7 @@ var RemotePlatformClient = class {
|
|
|
189
258
|
if (state && this.deps.isProcessRunning?.(state.pid) && Number.isFinite(state.uiPort)) {
|
|
190
259
|
return `http://127.0.0.1:${state.uiPort}`;
|
|
191
260
|
}
|
|
192
|
-
const configuredPort = typeof config.ui?.port === "number" && Number.isFinite(config.ui.port) ? config.ui.port :
|
|
261
|
+
const configuredPort = typeof config.ui?.port === "number" && Number.isFinite(config.ui.port) ? config.ui.port : 55667;
|
|
193
262
|
return `http://127.0.0.1:${configuredPort}`;
|
|
194
263
|
}
|
|
195
264
|
resolveDisplayName(config, opts) {
|
|
@@ -656,8 +725,11 @@ export {
|
|
|
656
725
|
RemoteServiceModule,
|
|
657
726
|
RemoteStatusStore,
|
|
658
727
|
buildConfiguredRemoteState,
|
|
728
|
+
decodePlatformSessionTokenPayload,
|
|
659
729
|
delay,
|
|
730
|
+
isValidPlatformSessionToken,
|
|
660
731
|
normalizeOptionalString,
|
|
732
|
+
readPlatformSessionTokenState,
|
|
661
733
|
redactWsUrl,
|
|
662
734
|
registerRemoteCommands,
|
|
663
735
|
resolveRemoteStatusSnapshot
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/remote",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Remote access runtime for NextClaw device registration, relay bridging, and service-managed connectivity.",
|
|
6
6
|
"type": "module",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"commander": "^12.1.0",
|
|
32
|
-
"@nextclaw/
|
|
33
|
-
"@nextclaw/
|
|
32
|
+
"@nextclaw/server": "0.10.20",
|
|
33
|
+
"@nextclaw/core": "0.9.8"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^20.17.6",
|