@nextclaw/remote 0.1.99 → 0.1.101

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 CHANGED
@@ -242,4 +242,5 @@ declare function decodePlatformSessionTokenPayload(token: string): Record<string
242
242
  declare function readPlatformSessionTokenState(token: string | null | undefined): PlatformSessionTokenState;
243
243
  declare function isValidPlatformSessionToken(token: string | null | undefined): token is string;
244
244
  //#endregion
245
- export { PlatformSessionTokenState, RegisteredRemoteDevice, RelayRequestFrame, RemoteConnectCommandOptions, RemoteConnector, RemoteConnectorRunOptions, RemoteDoctorCommandOptions, RemoteEnableCommandOptions, RemoteLogger, RemotePlatformClient, RemotePlatformClientDeps, RemoteRelayBridge, RemoteRunContext, RemoteRuntimeActions, RemoteRuntimeState, RemoteServiceModule, RemoteServiceStateView, RemoteStatusCommandOptions, RemoteStatusSnapshot, RemoteStatusStore, RemoteStatusWriter, buildConfiguredRemoteState, decodePlatformSessionTokenPayload, delay, isValidPlatformSessionToken, normalizeOptionalString, readPlatformSessionTokenState, redactWsUrl, registerRemoteCommands, resolveRemoteStatusSnapshot };
245
+ export { PlatformSessionTokenState, RegisteredRemoteDevice, RelayRequestFrame, RemoteConnectCommandOptions, RemoteConnector, RemoteConnectorRunOptions, RemoteDoctorCommandOptions, RemoteEnableCommandOptions, RemoteLogger, RemotePlatformClient, RemotePlatformClientDeps, RemoteRelayBridge, RemoteRunContext, RemoteRuntimeActions, RemoteRuntimeState, RemoteServiceModule, RemoteServiceStateView, RemoteStatusCommandOptions, RemoteStatusSnapshot, RemoteStatusStore, RemoteStatusWriter, buildConfiguredRemoteState, decodePlatformSessionTokenPayload, delay, isValidPlatformSessionToken, normalizeOptionalString, readPlatformSessionTokenState, redactWsUrl, registerRemoteCommands, resolveRemoteStatusSnapshot };
246
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/register-remote-commands.ts","../src/remote-runtime-actions.ts","../src/remote-platform-client.ts","../src/remote-relay-bridge.ts","../src/remote-connector.ts","../src/remote-status-store.ts","../src/remote-service-module.ts","../src/platform-session-token.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1080,3 +1080,5 @@ var RemoteServiceModule = class {
1080
1080
  };
1081
1081
  //#endregion
1082
1082
  export { RemoteConnector, RemotePlatformClient, RemoteRelayBridge, RemoteRuntimeActions, RemoteServiceModule, RemoteStatusStore, buildConfiguredRemoteState, decodePlatformSessionTokenPayload, delay, isValidPlatformSessionToken, normalizeOptionalString, readPlatformSessionTokenState, redactWsUrl, registerRemoteCommands, resolveRemoteStatusSnapshot };
1083
+
1084
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["readPlatform","WebSocket","normalizeOptionalString"],"sources":["../src/register-remote-commands.ts","../src/remote-runtime-actions.ts","../src/platform-session-token.ts","../src/remote-platform-client.ts","../src/remote-relay-bridge.ts","../src/remote-app-stream.ts","../src/remote-app.adapter.ts","../src/remote-connector-error.ts","../src/remote-connector-retry.utils.ts","../src/remote-connector-websocket-error.utils.ts","../src/remote-connector.ts","../src/remote-status-store.ts","../src/remote-service-module.ts"],"sourcesContent":["import type { Command } from \"commander\";\nimport type {\n RemoteConnectCommandOptions,\n RemoteDoctorCommandOptions,\n RemoteEnableCommandOptions,\n RemoteStatusCommandOptions\n} from \"./types.js\";\n\ntype RemoteCommandRuntime = {\n enable: (opts?: RemoteEnableCommandOptions) => Promise<void>;\n disable: () => Promise<void>;\n status: (opts?: RemoteStatusCommandOptions) => Promise<void>;\n doctor: (opts?: RemoteDoctorCommandOptions) => Promise<void>;\n connect: (opts?: RemoteConnectCommandOptions) => Promise<void>;\n};\n\nexport function registerRemoteCommands(program: Command, runtime: RemoteCommandRuntime): void {\n const remote = program.command(\"remote\").description(\"Manage remote access\");\n\n remote\n .command(\"enable\")\n .description(\"Enable service-managed remote access\")\n .option(\"--api-base <url>\", \"Platform API base (supports /v1 suffix)\")\n .option(\"--name <name>\", \"Device display name\")\n .action(async (opts) => runtime.enable(opts));\n\n remote\n .command(\"disable\")\n .description(\"Disable service-managed remote access\")\n .action(async () => runtime.disable());\n\n remote\n .command(\"status\")\n .description(\"Show remote access status\")\n .option(\"--json\", \"Print JSON\")\n .action(async (opts) => runtime.status(opts));\n\n remote\n .command(\"doctor\")\n .description(\"Run remote access diagnostics\")\n .option(\"--json\", \"Print JSON\")\n .action(async (opts) => runtime.doctor(opts));\n\n remote\n .command(\"connect\")\n .description(\"Foreground debug mode: register this machine and keep the connector online\")\n .option(\"--api-base <url>\", \"Platform API base (supports /v1 suffix)\")\n .option(\"--local-origin <url>\", \"Local NextClaw UI origin (default: active service or http://127.0.0.1:55667)\")\n .option(\"--name <name>\", \"Device display name\")\n .option(\"--once\", \"Connect once without auto-reconnect\", false)\n .action(async (opts) => runtime.connect(opts));\n}\n","import type { Config } from \"@nextclaw/core\";\nimport type {\n RemoteConnectCommandOptions,\n RemoteDoctorCommandOptions,\n RemoteEnableCommandOptions,\n RemoteStatusCommandOptions\n} from \"./types.js\";\n\ntype RemoteConfigChange = {\n changed: boolean;\n config: Config;\n};\n\ntype RemoteCommandDriver = {\n connect: (opts?: RemoteConnectCommandOptions) => Promise<void>;\n enableConfig: (opts?: RemoteEnableCommandOptions) => RemoteConfigChange;\n disableConfig: () => RemoteConfigChange;\n status: (opts?: RemoteStatusCommandOptions) => Promise<void>;\n doctor: (opts?: RemoteDoctorCommandOptions) => Promise<void>;\n};\n\nexport class RemoteRuntimeActions {\n constructor(\n private readonly deps: {\n appName: string;\n initAuto: (source: string) => Promise<void>;\n remoteCommands: RemoteCommandDriver;\n restartBackgroundService: (reason: string) => Promise<boolean>;\n hasRunningManagedService: () => boolean;\n }\n ) {}\n\n async connect(opts: RemoteConnectCommandOptions = {}): Promise<void> {\n await this.deps.remoteCommands.connect(opts);\n }\n\n async enable(opts: RemoteEnableCommandOptions = {}): Promise<void> {\n await this.deps.initAuto(\"remote enable\");\n const result = this.deps.remoteCommands.enableConfig(opts);\n console.log(\"✓ Remote access enabled\");\n if (result.config.remote.deviceName.trim()) {\n console.log(`Instance: ${result.config.remote.deviceName.trim()}`);\n }\n if (result.config.remote.platformApiBase.trim()) {\n console.log(`Platform: ${result.config.remote.platformApiBase.trim()}`);\n }\n if (this.deps.hasRunningManagedService()) {\n await this.deps.restartBackgroundService(\"remote configuration updated\");\n console.log(\"✓ Applied remote settings to running background service\");\n return;\n }\n console.log(`Tip: Run \"${this.deps.appName} start\" to bring the managed remote connector online.`);\n }\n\n async disable(): Promise<void> {\n const result = this.deps.remoteCommands.disableConfig();\n console.log(result.changed ? \"✓ Remote access disabled\" : \"Remote access was already disabled\");\n if (this.deps.hasRunningManagedService()) {\n await this.deps.restartBackgroundService(\"remote access disabled\");\n console.log(\"✓ Running background service restarted without remote access\");\n }\n }\n\n async status(opts: RemoteStatusCommandOptions = {}): Promise<void> {\n await this.deps.remoteCommands.status(opts);\n }\n\n async doctor(opts: RemoteDoctorCommandOptions = {}): Promise<void> {\n await this.deps.remoteCommands.doctor(opts);\n }\n}\n","export type PlatformSessionTokenState =\n | {\n valid: false;\n reason: \"missing\" | \"malformed\" | \"expired\";\n payload: Record<string, unknown> | null;\n }\n | {\n valid: true;\n reason: \"valid\";\n payload: Record<string, unknown>;\n };\n\nfunction decodeBase64UrlSegment(segment: string): string | null {\n try {\n return Buffer.from(segment, \"base64url\").toString(\"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport function decodePlatformSessionTokenPayload(token: string): Record<string, unknown> | null {\n const segments = token.split(\".\");\n if (segments.length !== 3 || segments[0] !== \"nca\" || !segments[1]) {\n return null;\n }\n const raw = decodeBase64UrlSegment(segments[1]);\n if (!raw) {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as unknown;\n return typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nexport function readPlatformSessionTokenState(token: string | null | undefined): PlatformSessionTokenState {\n if (typeof token !== \"string\" || token.trim().length === 0) {\n return {\n valid: false,\n reason: \"missing\",\n payload: null,\n };\n }\n const trimmed = token.trim();\n const payload = decodePlatformSessionTokenPayload(trimmed);\n if (!payload) {\n return {\n valid: false,\n reason: \"malformed\",\n payload: null,\n };\n }\n const exp = typeof payload.exp === \"number\" && Number.isFinite(payload.exp) ? payload.exp : Number.NaN;\n const now = Math.floor(Date.now() / 1000);\n if (!Number.isFinite(exp) || exp <= now) {\n return {\n valid: false,\n reason: \"expired\",\n payload,\n };\n }\n return {\n valid: true,\n reason: \"valid\",\n payload,\n };\n}\n\nexport function isValidPlatformSessionToken(token: string | null | undefined): token is string {\n return readPlatformSessionTokenState(token).valid;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { hostname, platform as readPlatform } from \"node:os\";\nimport type {\n RegisteredRemoteDevice,\n RemoteConnectCommandOptions,\n RemoteConnectorRunOptions,\n RemotePlatformClientDeps,\n RemoteRunContext\n} from \"./types.js\";\nimport { readPlatformSessionTokenState } from \"./platform-session-token.js\";\n\nfunction ensureDir(path: string): void {\n mkdirSync(path, { recursive: true });\n}\n\nfunction readJsonFile<T>(path: string): T | null {\n if (!existsSync(path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(path, \"utf-8\")) as T;\n } catch {\n return null;\n }\n}\n\nfunction writeJsonFile(path: string, value: unknown): void {\n ensureDir(dirname(path));\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\");\n}\n\nfunction maskToken(value: string): string {\n if (value.length <= 12) {\n return \"<redacted>\";\n }\n return `${value.slice(0, 6)}...${value.slice(-4)}`;\n}\n\nexport function normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolveDelay, rejectDelay) => {\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolveDelay();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n rejectDelay(new Error(\"Remote connector aborted.\"));\n };\n if (signal) {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n });\n}\n\nexport function redactWsUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const token = parsed.searchParams.get(\"token\");\n if (token) {\n parsed.searchParams.set(\"token\", maskToken(token));\n }\n return parsed.toString();\n } catch {\n return url;\n }\n}\n\nexport class RemotePlatformClient {\n constructor(private readonly deps: RemotePlatformClientDeps) {}\n\n private get remoteDir(): string {\n return join(this.deps.getDataDir(), \"remote\");\n }\n\n private get devicePath(): string {\n return join(this.remoteDir, \"device.json\");\n }\n\n resolveRunContext(opts: RemoteConnectorRunOptions): RemoteRunContext {\n const { platformBase, token, config } = this.resolvePlatformAccess(opts);\n return {\n config,\n platformBase,\n token,\n localOrigin: this.resolveLocalOrigin(config, opts),\n displayName: this.resolveDisplayName(config, opts),\n deviceInstallId: this.ensureDeviceInstallId(),\n autoReconnect: opts.once ? false : (opts.autoReconnect ?? config.remote.autoReconnect)\n };\n }\n\n async registerDevice(params: {\n platformBase: string;\n token: string;\n deviceInstallId: string;\n displayName: string;\n localOrigin: string;\n }): Promise<RegisteredRemoteDevice> {\n const response = await fetch(`${params.platformBase}/platform/remote/instances/register`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${params.token}`\n },\n body: JSON.stringify({\n deviceInstallId: params.deviceInstallId,\n displayName: params.displayName,\n platform: readPlatform(),\n appVersion: this.deps.getPackageVersion(),\n localOrigin: params.localOrigin\n })\n });\n const payload = (await response.json()) as {\n ok?: boolean;\n data?: {\n instance?: {\n id: string;\n instanceInstallId: string;\n displayName: string;\n platform: string;\n appVersion: string;\n localOrigin: string;\n status: \"online\" | \"offline\";\n lastSeenAt: string;\n createdAt: string;\n updatedAt: string;\n };\n device?: RegisteredRemoteDevice;\n };\n error?: { message?: string };\n };\n const instance = payload.data?.instance;\n if (response.ok && payload.ok && instance) {\n return {\n id: instance.id,\n deviceInstallId: instance.instanceInstallId,\n displayName: instance.displayName,\n platform: instance.platform,\n appVersion: instance.appVersion,\n localOrigin: instance.localOrigin,\n status: instance.status,\n lastSeenAt: instance.lastSeenAt,\n createdAt: instance.createdAt,\n updatedAt: instance.updatedAt\n };\n }\n if (!response.ok || !payload.ok || !payload.data?.device) {\n throw new Error(payload.error?.message ?? `Failed to register remote instance (${response.status}).`);\n }\n return payload.data.device;\n }\n\n private ensureDeviceInstallId(): string {\n const existing = readJsonFile<{ deviceInstallId?: string }>(this.devicePath);\n if (existing?.deviceInstallId?.trim()) {\n return existing.deviceInstallId.trim();\n }\n const deviceInstallId = crypto.randomUUID();\n ensureDir(this.remoteDir);\n writeJsonFile(this.devicePath, { deviceInstallId });\n return deviceInstallId;\n }\n\n private resolvePlatformAccess(opts: RemoteConnectCommandOptions): {\n platformBase: string;\n token: string;\n config: ReturnType<RemotePlatformClientDeps[\"loadConfig\"]>;\n } {\n const config = this.deps.loadConfig();\n const providers = config.providers as Record<string, { apiBase?: string | null; apiKey?: string }>;\n const nextclawProvider = providers.nextclaw;\n const token = typeof nextclawProvider?.apiKey === \"string\" ? nextclawProvider.apiKey.trim() : \"\";\n const tokenState = readPlatformSessionTokenState(token);\n if (tokenState.reason === \"missing\") {\n throw new Error('NextClaw platform token is missing. Run \"nextclaw login\" first.');\n }\n if (tokenState.reason === \"expired\") {\n throw new Error('NextClaw platform token expired. Run \"nextclaw login\" or browser sign-in again.');\n }\n if (tokenState.reason === \"malformed\") {\n throw new Error('NextClaw platform token is invalid. Run \"nextclaw login\" again.');\n }\n const configuredApiBase =\n normalizeOptionalString(config.remote.platformApiBase)\n ?? (typeof nextclawProvider?.apiBase === \"string\" ? nextclawProvider.apiBase.trim() : \"\");\n const rawApiBase = normalizeOptionalString(opts.apiBase) ?? configuredApiBase;\n if (!rawApiBase) {\n throw new Error(\"Platform API base is missing. Pass --api-base, run nextclaw login, or set remote.platformApiBase.\");\n }\n const platformBase = this.deps.resolvePlatformBase(rawApiBase);\n return { platformBase, token: token.trim(), config };\n }\n\n private resolveLocalOrigin(\n config: ReturnType<RemotePlatformClientDeps[\"loadConfig\"]>,\n opts: RemoteConnectCommandOptions\n ): string {\n const explicitOrigin = normalizeOptionalString(opts.localOrigin);\n if (explicitOrigin) {\n return explicitOrigin.replace(/\\/$/, \"\");\n }\n const state = this.deps.readManagedServiceState?.();\n if (state && this.deps.isProcessRunning?.(state.pid) && Number.isFinite(state.uiPort)) {\n return `http://127.0.0.1:${state.uiPort}`;\n }\n const configuredPort =\n typeof config.ui?.port === \"number\" && Number.isFinite(config.ui.port)\n ? config.ui.port\n : 55667;\n return `http://127.0.0.1:${configuredPort}`;\n }\n\n private resolveDisplayName(\n config: ReturnType<RemotePlatformClientDeps[\"loadConfig\"]>,\n opts: RemoteConnectCommandOptions\n ): string {\n return normalizeOptionalString(opts.name) ?? normalizeOptionalString(config.remote.deviceName) ?? hostname();\n }\n}\n","import { ensureUiBridgeSecret } from \"@nextclaw/server\";\n\nexport type RelayRequestFrame = {\n type: \"request\";\n requestId: string;\n method: string;\n path: string;\n headers: Array<[string, string]>;\n bodyBase64?: string;\n};\n\nfunction encodeBase64(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString(\"base64\");\n}\n\nfunction decodeBase64(base64: string | undefined): Uint8Array {\n if (!base64) {\n return new Uint8Array();\n }\n return new Uint8Array(Buffer.from(base64, \"base64\"));\n}\n\nexport class RemoteRelayBridge {\n constructor(private readonly localOrigin: string) {}\n\n async ensureLocalUiHealthy(): Promise<void> {\n const response = await fetch(`${this.localOrigin}/api/health`);\n if (!response.ok) {\n throw new Error(`Local UI is not healthy at ${this.localOrigin}. Start NextClaw first.`);\n }\n }\n\n async forward(frame: RelayRequestFrame, socket: WebSocket): Promise<void> {\n const bridgeCookie = await this.requestBridgeCookie();\n const url = new URL(frame.path, this.localOrigin);\n const headers = this.createForwardHeaders(frame.headers, bridgeCookie);\n const response = await fetch(url, {\n method: frame.method,\n headers,\n body: frame.method === \"GET\" || frame.method === \"HEAD\" ? undefined : decodeBase64(frame.bodyBase64)\n });\n const responseHeaders = Array.from(response.headers.entries()).filter(([key]) => {\n const lower = key.toLowerCase();\n return ![\"content-length\", \"connection\", \"transfer-encoding\", \"set-cookie\"].includes(lower);\n });\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (response.body && contentType.startsWith(\"text/event-stream\")) {\n await this.sendStreamingResponse({ frame, response, responseHeaders, socket });\n return;\n }\n const responseBody = response.body ? new Uint8Array(await response.arrayBuffer()) : new Uint8Array();\n socket.send(JSON.stringify({\n type: \"response\",\n requestId: frame.requestId,\n status: response.status,\n headers: responseHeaders,\n bodyBase64: encodeBase64(responseBody)\n }));\n }\n\n private createForwardHeaders(headersList: Array<[string, string]>, bridgeCookie: string | null): Headers {\n const headers = new Headers();\n for (const [key, value] of headersList) {\n const lower = key.toLowerCase();\n if ([\n \"host\",\n \"connection\",\n \"content-length\",\n \"cookie\",\n \"x-forwarded-for\",\n \"x-forwarded-proto\",\n \"cf-connecting-ip\"\n ].includes(lower)) {\n continue;\n }\n headers.set(key, value);\n }\n if (bridgeCookie) {\n headers.set(\"cookie\", bridgeCookie);\n }\n return headers;\n }\n\n async requestBridgeCookie(): Promise<string | null> {\n const response = await fetch(`${this.localOrigin}/api/auth/bridge`, {\n method: \"POST\",\n headers: {\n \"x-nextclaw-ui-bridge-secret\": ensureUiBridgeSecret()\n }\n });\n const payload = (await response.json()) as { ok?: boolean; data?: { cookie?: string | null }; error?: { message?: string } };\n if (!response.ok || !payload.ok) {\n throw new Error(payload.error?.message ?? `Failed to request local auth bridge (${response.status}).`);\n }\n return typeof payload.data?.cookie === \"string\" && payload.data.cookie.trim().length > 0\n ? payload.data.cookie.trim()\n : null;\n }\n\n private async sendStreamingResponse(params: {\n frame: RelayRequestFrame;\n response: Response;\n responseHeaders: Array<[string, string]>;\n socket: WebSocket;\n }): Promise<void> {\n params.socket.send(JSON.stringify({\n type: \"response.start\",\n requestId: params.frame.requestId,\n status: params.response.status,\n headers: params.responseHeaders\n }));\n const reader = params.response.body?.getReader();\n if (!reader) {\n params.socket.send(JSON.stringify({\n type: \"response.end\",\n requestId: params.frame.requestId\n }));\n return;\n }\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n break;\n }\n if (value && value.length > 0) {\n params.socket.send(JSON.stringify({\n type: \"response.chunk\",\n requestId: params.frame.requestId,\n bodyBase64: encodeBase64(value)\n }));\n }\n }\n } finally {\n reader.releaseLock();\n }\n params.socket.send(JSON.stringify({\n type: \"response.end\",\n requestId: params.frame.requestId\n }));\n }\n}\n","type RemoteStreamEvent = {\n event: string;\n payload?: unknown;\n};\n\nfunction parseRemoteSseFrame(frame: string): RemoteStreamEvent | null {\n const lines = frame.split(\"\\n\");\n let event = \"\";\n const dataLines: string[] = [];\n for (const raw of lines) {\n const line = raw.trimEnd();\n if (!line || line.startsWith(\":\")) {\n continue;\n }\n if (line.startsWith(\"event:\")) {\n event = line.slice(6).trim();\n continue;\n }\n if (line.startsWith(\"data:\")) {\n dataLines.push(line.slice(5).trimStart());\n }\n }\n if (!event) {\n return null;\n }\n const data = dataLines.join(\"\\n\");\n if (!data) {\n return { event };\n }\n try {\n return { event, payload: JSON.parse(data) };\n } catch {\n return { event, payload: data };\n }\n}\n\nfunction processRemoteStreamFrame(params: {\n rawFrame: string;\n onEvent: (frame: RemoteStreamEvent) => void;\n}): void {\n const frame = parseRemoteSseFrame(params.rawFrame);\n if (!frame) {\n return;\n }\n params.onEvent(frame);\n}\n\nfunction flushRemoteStreamFrames(params: {\n bufferState: { value: string };\n onEvent: (frame: RemoteStreamEvent) => void;\n}): void {\n let boundary = params.bufferState.value.indexOf(\"\\n\\n\");\n while (boundary !== -1) {\n processRemoteStreamFrame({\n rawFrame: params.bufferState.value.slice(0, boundary),\n onEvent: params.onEvent\n });\n params.bufferState.value = params.bufferState.value.slice(boundary + 2);\n boundary = params.bufferState.value.indexOf(\"\\n\\n\");\n }\n}\n\nexport async function readRemoteAppStreamResult(params: {\n response: Response;\n onEvent: (frame: RemoteStreamEvent) => void;\n}): Promise<void> {\n const reader = params.response.body?.getReader();\n if (!reader) {\n throw new Error(\"SSE response body unavailable.\");\n }\n\n const decoder = new TextDecoder();\n const bufferState = { value: \"\" };\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n break;\n }\n bufferState.value += decoder.decode(value, { stream: true });\n flushRemoteStreamFrames({\n bufferState,\n onEvent: params.onEvent\n });\n }\n\n if (bufferState.value.trim()) {\n processRemoteStreamFrame({\n rawFrame: bufferState.value,\n onEvent: params.onEvent\n });\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import type { UiServerEvent } from \"@nextclaw/server\";\nimport WebSocket, { type RawData } from \"ws\";\nimport { RemoteRelayBridge } from \"./remote-relay-bridge.js\";\nimport { readRemoteAppStreamResult } from \"./remote-app-stream.js\";\n\ntype RemoteTarget = {\n method: string;\n path: string;\n body?: unknown;\n};\n\ntype ConnectorClientCommand =\n | { type: \"client.request\"; clientId: string; id: string; target: RemoteTarget }\n | { type: \"client.stream.open\"; clientId: string; streamId: string; target: RemoteTarget }\n | { type: \"client.stream.cancel\"; clientId: string; streamId: string };\n\nfunction toWebSocketUrl(origin: string, path: string): string {\n const normalizedOrigin = origin.replace(/\\/$/, \"\");\n if (normalizedOrigin.startsWith(\"https://\")) {\n return `${normalizedOrigin.replace(/^https:/, \"wss:\")}${path}`;\n }\n if (normalizedOrigin.startsWith(\"http://\")) {\n return `${normalizedOrigin.replace(/^http:/, \"ws:\")}${path}`;\n }\n return `${normalizedOrigin}${path}`;\n}\n\nfunction readErrorMessage(body: unknown, fallback: string): string {\n if (typeof body === \"object\" && body && \"error\" in body) {\n const typed = body as { error?: { message?: string } };\n if (typed.error?.message) {\n return typed.error.message;\n }\n }\n if (typeof body === \"string\" && body.trim()) {\n return body.trim();\n }\n return fallback;\n}\n\nexport class RemoteAppAdapter {\n private readonly relayBridge: RemoteRelayBridge;\n private readonly activeStreams = new Map<string, AbortController>();\n private localEventSocket: WebSocket | null = null;\n private eventReconnectTimer: NodeJS.Timeout | null = null;\n private shuttingDown = false;\n\n constructor(\n private readonly localOrigin: string,\n private readonly platformSocket: {\n readonly readyState: number;\n send(data: string): void;\n }\n ) {\n this.relayBridge = new RemoteRelayBridge(localOrigin);\n }\n\n async start(): Promise<void> {\n await this.ensureEventSocket();\n }\n\n stop(): void {\n this.shuttingDown = true;\n if (this.eventReconnectTimer) {\n clearTimeout(this.eventReconnectTimer);\n this.eventReconnectTimer = null;\n }\n this.localEventSocket?.close();\n this.localEventSocket = null;\n for (const controller of this.activeStreams.values()) {\n controller.abort();\n }\n this.activeStreams.clear();\n }\n\n async handle(frame: ConnectorClientCommand): Promise<void> {\n if (frame.type === \"client.request\") {\n await this.handleRequest(frame);\n return;\n }\n if (frame.type === \"client.stream.open\") {\n void this.handleStream(frame);\n return;\n }\n if (frame.type === \"client.stream.cancel\") {\n this.activeStreams.get(frame.streamId)?.abort();\n this.activeStreams.delete(frame.streamId);\n }\n }\n\n private async handleRequest(frame: Extract<ConnectorClientCommand, { type: \"client.request\" }>): Promise<void> {\n const bridgeCookie = await this.relayBridge.requestBridgeCookie();\n const response = await fetch(new URL(frame.target.path, this.localOrigin), {\n method: frame.target.method,\n headers: this.createJsonHeaders(bridgeCookie),\n body: this.buildRequestBody(frame.target)\n });\n const body = await this.readResponseBody(response);\n this.send({\n type: \"client.response\",\n clientId: frame.clientId,\n id: frame.id,\n status: response.status,\n body\n });\n }\n\n private async handleStream(frame: Extract<ConnectorClientCommand, { type: \"client.stream.open\" }>): Promise<void> {\n const controller = new AbortController();\n this.activeStreams.set(frame.streamId, controller);\n\n try {\n const response = await this.openStreamResponse(frame, controller);\n if (!response) {\n return;\n }\n await readRemoteAppStreamResult({\n response,\n onEvent: (event) => {\n this.send({\n type: \"client.stream.event\",\n clientId: frame.clientId,\n streamId: frame.streamId,\n event: event.event,\n payload: event.payload\n });\n }\n });\n this.send({\n type: \"client.stream.end\",\n clientId: frame.clientId,\n streamId: frame.streamId\n });\n } catch (error) {\n if (controller.signal.aborted) {\n return;\n }\n this.send({\n type: \"client.stream.error\",\n clientId: frame.clientId,\n streamId: frame.streamId,\n message: error instanceof Error ? error.message : String(error)\n });\n } finally {\n this.activeStreams.delete(frame.streamId);\n }\n }\n\n private async openStreamResponse(\n frame: Extract<ConnectorClientCommand, { type: \"client.stream.open\" }>,\n controller: AbortController\n ): Promise<Response | null> {\n const bridgeCookie = await this.relayBridge.requestBridgeCookie();\n const response = await fetch(new URL(frame.target.path, this.localOrigin), {\n method: frame.target.method,\n headers: this.createStreamHeaders(bridgeCookie),\n body: this.buildRequestBody(frame.target),\n signal: controller.signal\n });\n if (response.ok) {\n return response;\n }\n const errorBody = await this.readResponseBody(response);\n this.send({\n type: \"client.stream.error\",\n clientId: frame.clientId,\n streamId: frame.streamId,\n message: readErrorMessage(errorBody, `HTTP ${response.status}`)\n });\n return null;\n }\n\n private async ensureEventSocket(): Promise<void> {\n if (this.localEventSocket && this.localEventSocket.readyState === WebSocket.OPEN) {\n return;\n }\n const bridgeCookie = await this.relayBridge.requestBridgeCookie();\n await new Promise<void>((resolve, reject) => {\n const socket = new WebSocket(toWebSocketUrl(this.localOrigin, \"/ws\"), {\n headers: bridgeCookie ? { Cookie: bridgeCookie } : undefined\n });\n this.localEventSocket = socket;\n\n socket.on(\"open\", () => resolve());\n socket.on(\"message\", (data: RawData) => {\n try {\n const event = JSON.parse(String(data ?? \"\")) as UiServerEvent;\n this.send({\n type: \"client.event\",\n event\n });\n } catch (error) {\n console.error(\"Failed to parse local ui event:\", error);\n }\n });\n socket.on(\"close\", () => {\n this.localEventSocket = null;\n if (!this.shuttingDown) {\n this.scheduleEventReconnect();\n }\n });\n socket.on(\"error\", (error: Error) => {\n if (!this.shuttingDown) {\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n });\n }\n\n private scheduleEventReconnect(): void {\n if (this.eventReconnectTimer) {\n return;\n }\n this.eventReconnectTimer = setTimeout(() => {\n this.eventReconnectTimer = null;\n void this.ensureEventSocket().catch(() => undefined);\n }, 3_000);\n }\n\n private buildRequestBody(target: RemoteTarget): Uint8Array | undefined {\n if (target.method === \"GET\" || target.method === \"HEAD\") {\n return undefined;\n }\n if (target.body === undefined) {\n return undefined;\n }\n return new TextEncoder().encode(JSON.stringify(target.body));\n }\n\n private createJsonHeaders(bridgeCookie: string | null): Headers {\n const headers = new Headers({\n \"Content-Type\": \"application/json\"\n });\n if (bridgeCookie) {\n headers.set(\"cookie\", bridgeCookie);\n }\n return headers;\n }\n\n private createStreamHeaders(bridgeCookie: string | null): Headers {\n const headers = this.createJsonHeaders(bridgeCookie);\n headers.set(\"Accept\", \"text/event-stream\");\n return headers;\n }\n\n private async readResponseBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"application/json\")) {\n return await response.json();\n }\n const text = await response.text();\n return text;\n }\n\n private send(frame: Record<string, unknown>): void {\n if (this.platformSocket.readyState !== WebSocket.OPEN) {\n return;\n }\n this.platformSocket.send(JSON.stringify(frame));\n }\n}\n","const TERMINAL_REMOTE_ERROR_PATTERNS = [\n /invalid or expired token/i,\n /missing bearer token/i,\n /token expired/i,\n /token is invalid/i,\n /run \"nextclaw login\"/i,\n /replaced by a newer connector session/i,\n /already owned by (?:running )?nextclaw service/i,\n /already owned by local nextclaw process/i,\n /unexpected server response:\\s*400/i,\n /unexpected server response:\\s*401/i,\n /unexpected server response:\\s*403/i,\n /unexpected server response:\\s*404/i,\n /invalid url/i,\n /unsupported protocol/i\n];\n\nexport function isTerminalRemoteConnectorError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return TERMINAL_REMOTE_ERROR_PATTERNS.some((pattern) => pattern.test(message));\n}\n\nexport function describeUnexpectedRemoteConnectorClose(event: {\n code?: unknown;\n reason?: unknown;\n wasClean?: unknown;\n}): string | null {\n const code = typeof event.code === \"number\" && Number.isFinite(event.code) ? event.code : null;\n const reason = typeof event.reason === \"string\" ? event.reason.trim() : \"\";\n const wasClean = typeof event.wasClean === \"boolean\" ? event.wasClean : null;\n\n if ((code === null || code === 1000) && !reason) {\n return null;\n }\n\n const detailParts: string[] = [];\n if (code !== null) {\n detailParts.push(`code ${code}`);\n }\n if (wasClean !== null) {\n detailParts.push(wasClean ? \"clean\" : \"unclean\");\n }\n\n const detail = detailParts.length > 0 ? ` (${detailParts.join(\", \")})` : \"\";\n if (reason) {\n return `Remote connector websocket closed${detail}: ${reason}`;\n }\n return `Remote connector websocket closed${detail}.`;\n}\n","const BASE_RECONNECT_DELAY_MS = 3_000;\nconst MAX_RECONNECT_DELAY_MS = 30 * 60_000;\nconst RECONNECT_JITTER_RATIO = 0.2;\n\nexport function resolveReconnectDelayMs(attempt: number, random: () => number): number {\n const exponentialDelayMs = Math.min(\n BASE_RECONNECT_DELAY_MS * 2 ** Math.max(0, attempt - 1),\n MAX_RECONNECT_DELAY_MS\n );\n const jitterRatio = ((random() * 2) - 1) * RECONNECT_JITTER_RATIO;\n return Math.max(\n BASE_RECONNECT_DELAY_MS,\n Math.round(exponentialDelayMs * (1 + jitterRatio))\n );\n}\n\nexport function formatReconnectDelay(delayMs: number): string {\n const seconds = delayMs / 1000;\n return Number.isInteger(seconds) ? `${seconds}s` : `${seconds.toFixed(1)}s`;\n}\n","export function readRemoteConnectorSocketErrorMessage(event: Event): string {\n const typedEvent = event as unknown as { message?: unknown; error?: unknown };\n if (typeof typedEvent.message === \"string\") {\n const directMessage = typedEvent.message.trim();\n if (directMessage.length > 0) {\n return directMessage;\n }\n }\n const nestedError = typedEvent.error;\n if (nestedError instanceof Error && nestedError.message.trim().length > 0) {\n return nestedError.message.trim();\n }\n if (typeof nestedError === \"string\" && nestedError.trim().length > 0) {\n return nestedError.trim();\n }\n if (\n typeof nestedError === \"object\"\n && nestedError\n && typeof (nestedError as { message?: unknown }).message === \"string\"\n ) {\n const nestedMessage = (nestedError as { message: string }).message.trim();\n if (nestedMessage.length > 0) {\n return nestedMessage;\n }\n }\n return \"Remote connector websocket failed.\";\n}\n","import { RemoteAppAdapter } from \"./remote-app.adapter.js\";\nimport {\n describeUnexpectedRemoteConnectorClose,\n isTerminalRemoteConnectorError\n} from \"./remote-connector-error.js\";\nimport { RemoteRelayBridge, type RelayRequestFrame } from \"./remote-relay-bridge.js\";\nimport {\n formatReconnectDelay,\n resolveReconnectDelayMs\n} from \"./remote-connector-retry.utils.js\";\nimport { readRemoteConnectorSocketErrorMessage } from \"./remote-connector-websocket-error.utils.js\";\nimport { delay, redactWsUrl, type RemotePlatformClient } from \"./remote-platform-client.js\";\nimport type {\n RegisteredRemoteDevice,\n RemoteConnectorRunOptions,\n RemoteLogger,\n RemoteRunContext\n} from \"./types.js\";\n\nconst CONNECTOR_KEEPALIVE_INTERVAL_MS = 25_000;\nconst CONNECTOR_KEEPALIVE_FRAME = JSON.stringify({ type: \"connector.ping\" });\n\nexport class RemoteConnector {\n constructor(\n private readonly deps: {\n platformClient: RemotePlatformClient;\n relayBridgeFactory?: (localOrigin: string) => RemoteRelayBridge;\n logger?: RemoteLogger;\n createSocket?: (wsUrl: string) => WebSocket;\n delayFn?: typeof delay;\n random?: () => number;\n }\n ) {}\n private get logger(): RemoteLogger {\n return this.deps.logger ?? console;\n }\n private get delayFn(): typeof delay {\n return this.deps.delayFn ?? delay;\n }\n private get random(): () => number {\n return this.deps.random ?? Math.random;\n }\n private createSocket(wsUrl: string): WebSocket {\n return this.deps.createSocket?.(wsUrl) ?? new WebSocket(wsUrl);\n }\n\n private async connectOnce(params: {\n wsUrl: string;\n relayBridge: RemoteRelayBridge;\n signal?: AbortSignal;\n statusStore?: RemoteConnectorRunOptions[\"statusStore\"];\n displayName: string;\n deviceId: string;\n platformBase: string;\n localOrigin: string;\n }): Promise<\"closed\" | \"aborted\"> {\n return await new Promise<\"closed\" | \"aborted\">((resolve, reject) => {\n const socket = this.createSocket(params.wsUrl);\n const appAdapter = new RemoteAppAdapter(params.localOrigin, socket);\n let keepaliveTimer: ReturnType<typeof setInterval> | null = null;\n let settled = false;\n let aborted = false;\n const cleanup = () => {\n if (keepaliveTimer) {\n clearInterval(keepaliveTimer);\n keepaliveTimer = null;\n }\n params.signal?.removeEventListener(\"abort\", onAbort);\n };\n const finishResolve = (value: \"closed\" | \"aborted\") => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n resolve(value);\n };\n\n const finishReject = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n reject(error);\n };\n const onAbort = () => {\n aborted = true;\n try {\n socket.close(1000, \"Remote connector aborted\");\n } catch {\n finishResolve(\"aborted\");\n }\n };\n\n if (params.signal) {\n if (params.signal.aborted) {\n onAbort();\n } else {\n params.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n socket.addEventListener(\"open\", () => {\n keepaliveTimer = setInterval(() => {\n if (socket.readyState !== 1) {\n return;\n }\n try {\n socket.send(CONNECTOR_KEEPALIVE_FRAME);\n } catch {\n // Let the close/error event drive reconnect behavior.\n }\n }, CONNECTOR_KEEPALIVE_INTERVAL_MS);\n params.statusStore?.write({\n enabled: true,\n state: \"connected\",\n deviceId: params.deviceId,\n deviceName: params.displayName,\n platformBase: params.platformBase,\n localOrigin: params.localOrigin,\n lastConnectedAt: new Date().toISOString(),\n lastError: null\n });\n this.logger.info(`✓ Remote connector connected: ${redactWsUrl(params.wsUrl)}`);\n void appAdapter.start().catch((error) => {\n this.logger.error(`Remote event bridge error: ${error instanceof Error ? error.message : String(error)}`);\n });\n });\n\n socket.addEventListener(\"message\", (event) => {\n this.handleSocketMessage({\n data: event.data,\n relayBridge: params.relayBridge,\n appAdapter,\n socket\n });\n });\n\n socket.addEventListener(\"close\", (event) => {\n appAdapter.stop();\n const closeMessage = describeUnexpectedRemoteConnectorClose(event ?? {});\n if (!aborted && closeMessage) {\n finishReject(new Error(closeMessage));\n return;\n }\n finishResolve(aborted ? \"aborted\" : \"closed\");\n });\n\n socket.addEventListener(\"error\", (event) => {\n appAdapter.stop();\n if (aborted) {\n finishResolve(\"aborted\");\n return;\n }\n finishReject(new Error(readRemoteConnectorSocketErrorMessage(event)));\n });\n });\n }\n\n private handleSocketMessage(params: {\n data: unknown;\n relayBridge: RemoteRelayBridge;\n appAdapter: RemoteAppAdapter;\n socket: WebSocket;\n }): void {\n void (async () => {\n const frame = this.parseRelayFrame(params.data);\n if (!frame) {\n return;\n }\n try {\n if (frame.type === \"request\") {\n await params.relayBridge.forward(frame, params.socket);\n return;\n }\n await params.appAdapter.handle(frame);\n } catch (error) {\n if (frame.type === \"request\") {\n params.socket.send(JSON.stringify({\n type: \"response.error\",\n requestId: frame.requestId,\n message: error instanceof Error ? error.message : String(error)\n }));\n return;\n }\n if (frame.type === \"client.request\") {\n params.socket.send(JSON.stringify({\n type: \"client.request.error\",\n clientId: frame.clientId,\n id: frame.id,\n message: error instanceof Error ? error.message : String(error)\n }));\n return;\n }\n params.socket.send(JSON.stringify({\n type: \"client.stream.error\",\n clientId: frame.clientId,\n streamId: frame.streamId,\n message: error instanceof Error ? error.message : String(error)\n }));\n }\n })();\n }\n\n private parseRelayFrame(data: unknown): (\n | RelayRequestFrame\n | {\n type: \"client.request\";\n clientId: string;\n id: string;\n target: { method: string; path: string; body?: unknown };\n }\n | {\n type: \"client.stream.open\";\n clientId: string;\n streamId: string;\n target: { method: string; path: string; body?: unknown };\n }\n | {\n type: \"client.stream.cancel\";\n clientId: string;\n streamId: string;\n }\n ) | null {\n try {\n const frame = JSON.parse(String(data ?? \"\"));\n if (typeof frame !== \"object\" || !frame || typeof frame.type !== \"string\") {\n return null;\n }\n if (frame.type === \"request\") {\n return frame as RelayRequestFrame;\n }\n if (\n frame.type === \"client.request\"\n || frame.type === \"client.stream.open\"\n || frame.type === \"client.stream.cancel\"\n ) {\n return frame as {\n type: \"client.request\";\n clientId: string;\n id: string;\n target: { method: string; path: string; body?: unknown };\n };\n }\n return null;\n } catch {\n return null;\n }\n }\n\n private async ensureDevice(params: {\n device: RegisteredRemoteDevice | null;\n context: RemoteRunContext;\n }): Promise<RegisteredRemoteDevice> {\n if (params.device) {\n return params.device;\n }\n const device = await this.deps.platformClient.registerDevice({\n platformBase: params.context.platformBase,\n token: params.context.token,\n deviceInstallId: params.context.deviceInstallId,\n displayName: params.context.displayName,\n localOrigin: params.context.localOrigin\n });\n this.logger.info(`✓ Remote instance registered: ${device.displayName} (${device.id})`);\n this.logger.info(`✓ Local origin: ${params.context.localOrigin}`);\n this.logger.info(`✓ Platform: ${params.context.platformBase}`);\n return device;\n }\n\n private writeRemoteState(\n statusStore: RemoteConnectorRunOptions[\"statusStore\"],\n next: Parameters<NonNullable<RemoteConnectorRunOptions[\"statusStore\"]>[\"write\"]>[0]\n ): void {\n statusStore?.write(next);\n }\n\n private async runCycle(params: {\n device: RegisteredRemoteDevice | null;\n context: RemoteRunContext;\n relayBridge: RemoteRelayBridge;\n opts: RemoteConnectorRunOptions;\n }): Promise<{\n device: RegisteredRemoteDevice | null;\n outcome: \"aborted\" | \"retry\" | \"stop\";\n retryFailure: boolean;\n lastError: string | null;\n }> {\n let device = params.device;\n try {\n this.writeRemoteState(params.opts.statusStore, {\n enabled: true,\n state: \"connecting\",\n deviceId: params.device?.id,\n deviceName: params.context.displayName,\n platformBase: params.context.platformBase,\n localOrigin: params.context.localOrigin,\n lastError: null\n });\n device = await this.ensureDevice({ device, context: params.context });\n const wsUrl =\n `${params.context.platformBase.replace(/^http/i, \"ws\")}/platform/remote/connect`\n + `?instanceId=${encodeURIComponent(device.id)}&token=${encodeURIComponent(params.context.token)}`;\n const outcome = await this.connectOnce({\n wsUrl,\n relayBridge: params.relayBridge,\n signal: params.opts.signal,\n statusStore: params.opts.statusStore,\n displayName: params.context.displayName,\n deviceId: device.id,\n platformBase: params.context.platformBase,\n localOrigin: params.context.localOrigin\n });\n if (outcome !== \"aborted\") {\n this.writeRemoteState(params.opts.statusStore, {\n enabled: true,\n state: \"disconnected\",\n deviceId: device.id,\n deviceName: params.context.displayName,\n platformBase: params.context.platformBase,\n localOrigin: params.context.localOrigin,\n lastError: null\n });\n }\n return {\n device,\n outcome: outcome === \"aborted\" ? \"aborted\" : \"retry\",\n retryFailure: false,\n lastError: null\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.writeRemoteState(params.opts.statusStore, {\n enabled: true,\n state: \"error\",\n deviceId: params.device?.id,\n deviceName: params.context.displayName,\n platformBase: params.context.platformBase,\n localOrigin: params.context.localOrigin,\n lastError: message\n });\n this.logger.error(`Remote connector error: ${message}`);\n return {\n device,\n outcome: isTerminalRemoteConnectorError(error) ? \"stop\" : \"retry\",\n retryFailure: true,\n lastError: message\n };\n }\n }\n\n async run(opts: RemoteConnectorRunOptions = {}): Promise<void> {\n const context = this.deps.platformClient.resolveRunContext(opts);\n const relayBridge = (this.deps.relayBridgeFactory ?? ((localOrigin) => new RemoteRelayBridge(localOrigin)))(\n context.localOrigin\n );\n await relayBridge.ensureLocalUiHealthy();\n let device: RegisteredRemoteDevice | null = null;\n let preserveRuntimeError = false;\n let consecutiveReconnectFailures = 0;\n\n while (!opts.signal?.aborted) {\n const cycle = await this.runCycle({ device, context, relayBridge, opts });\n device = cycle.device;\n consecutiveReconnectFailures = cycle.retryFailure ? consecutiveReconnectFailures + 1 : 0;\n if (cycle.outcome === \"stop\") {\n preserveRuntimeError = true;\n break;\n }\n if (cycle.outcome === \"aborted\" || !context.autoReconnect || opts.signal?.aborted) {\n break;\n }\n const reconnectDelayMs = resolveReconnectDelayMs(cycle.retryFailure ? consecutiveReconnectFailures : 1, this.random);\n this.logger.warn(\n `Remote connector disconnected. Reconnecting in ${formatReconnectDelay(reconnectDelayMs)}...`\n );\n try {\n await this.delayFn(reconnectDelayMs, opts.signal);\n } catch {\n break;\n }\n }\n\n if (preserveRuntimeError) {\n return;\n }\n\n this.writeRemoteState(opts.statusStore, {\n enabled: opts.mode === \"service\" ? true : Boolean(context.config.remote.enabled),\n state: opts.signal?.aborted ? \"disconnected\" : \"disabled\",\n deviceId: device?.id,\n deviceName: context.displayName,\n platformBase: context.platformBase,\n localOrigin: context.localOrigin,\n lastError: null\n });\n }\n}\n","import { hostname } from \"node:os\";\nimport type { Config } from \"@nextclaw/core\";\nimport type { RemoteRuntimeState, RemoteStatusSnapshot, RemoteStatusWriter } from \"./types.js\";\n\nfunction normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function buildConfiguredRemoteState(config: Config): RemoteRuntimeState {\n const remote = config.remote;\n return {\n enabled: Boolean(remote.enabled),\n mode: \"service\",\n state: remote.enabled ? \"disconnected\" : \"disabled\",\n ...(normalizeOptionalString(remote.deviceName) ? { deviceName: normalizeOptionalString(remote.deviceName) } : {}),\n ...(normalizeOptionalString(remote.platformApiBase) ? { platformBase: normalizeOptionalString(remote.platformApiBase) } : {}),\n updatedAt: new Date().toISOString()\n };\n}\n\nexport function resolveRemoteStatusSnapshot(params: {\n config: Config;\n currentRemoteState?: RemoteRuntimeState | null;\n fallbackDeviceName?: string;\n}): RemoteStatusSnapshot {\n if (params.currentRemoteState) {\n return {\n configuredEnabled: Boolean(params.config.remote.enabled),\n runtime: params.currentRemoteState\n };\n }\n\n if (params.config.remote.enabled) {\n return {\n configuredEnabled: true,\n runtime: {\n ...buildConfiguredRemoteState(params.config),\n deviceName:\n normalizeOptionalString(params.config.remote.deviceName)\n ?? normalizeOptionalString(params.fallbackDeviceName)\n ?? hostname()\n }\n };\n }\n\n return {\n configuredEnabled: false,\n runtime: null\n };\n}\n\nexport class RemoteStatusStore implements RemoteStatusWriter {\n constructor(\n private readonly mode: RemoteRuntimeState[\"mode\"],\n private readonly deps: {\n writeRemoteState: (next: RemoteRuntimeState) => void;\n }\n ) {}\n\n write(next: Omit<RemoteRuntimeState, \"mode\" | \"updatedAt\">): void {\n this.deps.writeRemoteState({\n ...next,\n mode: this.mode,\n updatedAt: new Date().toISOString()\n });\n }\n}\n","import type { Config } from \"@nextclaw/core\";\nimport type { RemoteConnector } from \"./remote-connector.js\";\nimport type { RemoteLogger, RemoteStatusWriter } from \"./types.js\";\n\nexport class RemoteServiceModule {\n private abortController: AbortController | null = null;\n private runTask: Promise<void> | null = null;\n private releaseOwnership: (() => void) | null = null;\n\n constructor(\n private readonly deps: {\n loadConfig: () => Config;\n uiEnabled: boolean;\n localOrigin: string;\n statusStore: RemoteStatusWriter;\n createConnector: (logger: RemoteLogger) => RemoteConnector;\n claimOwnership?: () => { ok: true; release: () => void } | { ok: false; error: string };\n logger?: RemoteLogger;\n }\n ) {}\n\n start(): Promise<void> | null {\n if (this.runTask) {\n return this.runTask;\n }\n\n if (!this.deps.uiEnabled) {\n return null;\n }\n\n const config = this.deps.loadConfig();\n if (!config.remote.enabled) {\n this.deps.statusStore.write({\n enabled: false,\n state: \"disabled\",\n deviceName: undefined,\n deviceId: undefined,\n platformBase: undefined,\n localOrigin: this.deps.localOrigin,\n lastError: null,\n lastConnectedAt: null\n });\n return null;\n }\n\n const logger = this.deps.logger ?? {\n info: (message: string) => console.log(`[remote] ${message}`),\n warn: (message: string) => console.warn(`[remote] ${message}`),\n error: (message: string) => console.error(`[remote] ${message}`)\n };\n\n const ownership = this.deps.claimOwnership?.();\n if (ownership && !ownership.ok) {\n this.deps.statusStore.write({\n enabled: true,\n state: \"error\",\n deviceName: config.remote.deviceName || undefined,\n deviceId: undefined,\n platformBase: config.remote.platformApiBase || undefined,\n localOrigin: this.deps.localOrigin,\n lastError: ownership.error,\n lastConnectedAt: null\n });\n logger.error(ownership.error);\n return null;\n }\n this.releaseOwnership = ownership?.release ?? null;\n\n this.abortController = new AbortController();\n const connector = this.deps.createConnector(logger);\n this.runTask = connector.run({\n mode: \"service\",\n signal: this.abortController.signal,\n autoReconnect: config.remote.autoReconnect,\n localOrigin: this.deps.localOrigin,\n statusStore: this.deps.statusStore\n });\n\n void this.runTask.catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n const latestConfig = this.deps.loadConfig();\n this.deps.statusStore.write({\n enabled: true,\n state: \"error\",\n deviceName: latestConfig.remote.deviceName || undefined,\n deviceId: undefined,\n platformBase: latestConfig.remote.platformApiBase || undefined,\n localOrigin: this.deps.localOrigin,\n lastError: message\n });\n logger.error(message);\n }).finally(() => {\n this.releaseOwnership?.();\n this.releaseOwnership = null;\n });\n\n return this.runTask;\n }\n\n async restart(): Promise<void> {\n await this.stop();\n this.start();\n }\n\n async stop(): Promise<void> {\n this.abortController?.abort();\n try {\n await this.runTask;\n } catch {\n // Ignore connector shutdown errors after abort.\n } finally {\n this.abortController = null;\n this.runTask = null;\n this.releaseOwnership?.();\n this.releaseOwnership = null;\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/remote",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "private": false,
5
5
  "description": "Remote access runtime for NextClaw device registration, relay bridging, and service-managed connectivity.",
6
6
  "type": "module",
@@ -30,9 +30,9 @@
30
30
  "dependencies": {
31
31
  "commander": "^12.1.0",
32
32
  "ws": "^8.18.0",
33
- "@nextclaw/core": "0.12.21",
34
- "@nextclaw/kernel": "0.1.11",
35
- "@nextclaw/server": "0.12.22"
33
+ "@nextclaw/core": "0.12.23",
34
+ "@nextclaw/server": "0.12.24",
35
+ "@nextclaw/kernel": "0.1.13"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^20.17.6",
@@ -41,7 +41,7 @@
41
41
  "typescript": "^5.6.3"
42
42
  },
43
43
  "scripts": {
44
- "build": "tsdown src/index.ts --dts --clean --target es2022 --no-fixedExtension",
44
+ "build": "tsdown src/index.ts --dts.sourcemap --clean --target es2022 --no-fixedExtension",
45
45
  "lint": "eslint .",
46
46
  "tsc": "tsc -p tsconfig.json"
47
47
  }