nodeclaw 0.1.0-alpha.1 → 0.2.0-alpha.2

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.
@@ -1,9 +1,9 @@
1
1
  // src/index.ts
2
- var VERSION = "0.1.0";
2
+ var VERSION = "0.2.0";
3
3
  var PROTOCOL_VERSION = 3;
4
4
 
5
5
  export {
6
6
  VERSION,
7
7
  PROTOCOL_VERSION
8
8
  };
9
- //# sourceMappingURL=chunk-F5XQ5PZF.js.map
9
+ //# sourceMappingURL=chunk-AMDUWOYB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export const VERSION = \"0.1.0\";\nexport const PROTOCOL_VERSION = 3;\n"],"mappings":";AAAO,IAAM,UAAU;AAChB,IAAM,mBAAmB;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export const VERSION = \"0.2.0\";\nexport const PROTOCOL_VERSION = 3;\n"],"mappings":";AAAO,IAAM,UAAU;AAChB,IAAM,mBAAmB;","names":[]}
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  PROTOCOL_VERSION,
4
4
  VERSION
5
- } from "./chunk-F5XQ5PZF.js";
5
+ } from "./chunk-AMDUWOYB.js";
6
6
 
7
7
  // src/cli.ts
8
8
  import { Command } from "commander";
@@ -174,7 +174,9 @@ function clearDeviceAuthToken(filePath, deviceId, role) {
174
174
  import { z } from "zod";
175
175
  var GatewayConfigSchema = z.object({
176
176
  url: z.string().url().default("ws://127.0.0.1:18789"),
177
- tlsVerify: z.boolean().default(true)
177
+ tlsVerify: z.boolean().default(true),
178
+ /** Gateway auth token — required when the gateway has auth.mode=token. */
179
+ token: z.string().optional()
178
180
  });
179
181
  var DeviceConfigSchema = z.object({
180
182
  name: z.string().default(""),
@@ -230,6 +232,14 @@ function loadConfig(env) {
230
232
  }
231
233
  return NodeClawConfigSchema.parse({});
232
234
  }
235
+ function saveConfig(config, env) {
236
+ const configPath = resolveConfigPath(env);
237
+ fs3.mkdirSync(path4.dirname(configPath), { recursive: true });
238
+ fs3.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
239
+ `, {
240
+ mode: 384
241
+ });
242
+ }
233
243
 
234
244
  // src/client/gateway-client.ts
235
245
  import { randomUUID } from "crypto";
@@ -237,7 +247,7 @@ import { WebSocket } from "ws";
237
247
 
238
248
  // src/protocol/constants.ts
239
249
  var PROTOCOL_VERSION2 = 3;
240
- var CLIENT_NAME = "nodeclaw";
250
+ var CLIENT_NAME = "node-host";
241
251
  var CLIENT_MODES = {
242
252
  NODE: "node",
243
253
  BACKEND: "backend",
@@ -608,6 +618,7 @@ async function pairWithGateway(opts) {
608
618
  let timeoutTimer = null;
609
619
  const client = new GatewayClient({
610
620
  url: opts.gatewayUrl,
621
+ token: opts.gatewayToken,
611
622
  deviceIdentity: identity,
612
623
  role,
613
624
  scopes: ["node.invoke"],
@@ -625,6 +636,12 @@ async function pairWithGateway(opts) {
625
636
  hello.auth.deviceToken,
626
637
  hello.auth.scopes
627
638
  );
639
+ const config = loadConfig(opts.env);
640
+ config.gateway.url = opts.gatewayUrl;
641
+ if (opts.gatewayToken) {
642
+ config.gateway.token = opts.gatewayToken;
643
+ }
644
+ saveConfig(config, opts.env);
628
645
  cleanup();
629
646
  resolve({
630
647
  deviceId: identity.deviceId,
@@ -678,11 +695,12 @@ Run "openclaw nodes approve" on your gateway to approve this device.`
678
695
 
679
696
  // src/cli/pair.ts
680
697
  function registerPairCommand(program2) {
681
- program2.command("pair").description("Pair this device with an OpenClaw gateway").argument("<gateway-url>", "WebSocket URL of the gateway (e.g. wss://host:18789)").option("-n, --name <name>", "Display name for this device").action(async (gatewayUrl, opts) => {
698
+ program2.command("pair").description("Pair this device with an OpenClaw gateway").argument("<gateway-url>", "WebSocket URL of the gateway (e.g. wss://host:18789)").option("-n, --name <name>", "Display name for this device").option("-t, --token <token>", "Gateway auth token (required when gateway has auth.mode=token)").action(async (gatewayUrl, opts) => {
682
699
  try {
683
700
  const result = await pairWithGateway({
684
701
  gatewayUrl,
685
- deviceName: opts.name
702
+ deviceName: opts.name,
703
+ gatewayToken: opts.token
686
704
  });
687
705
  console.log(result.message);
688
706
  console.log(`Device ID: ${result.deviceId}`);
@@ -740,6 +758,7 @@ async function startNode(opts = {}) {
740
758
  const router = opts.router ?? new CommandRouter();
741
759
  const client = new GatewayClient({
742
760
  url: config.gateway.url,
761
+ token: config.gateway.token,
743
762
  deviceIdentity: identity,
744
763
  deviceToken: storedAuth.token,
745
764
  role,
@@ -1576,11 +1595,12 @@ function registerDoctorCommand(program2) {
1576
1595
 
1577
1596
  // src/cli/install-service.ts
1578
1597
  import fs9 from "fs";
1579
- import path8 from "path";
1598
+ import path9 from "path";
1580
1599
  import os7 from "os";
1581
1600
 
1582
1601
  // src/service/systemd.ts
1583
1602
  import os5 from "os";
1603
+ import path8 from "path";
1584
1604
  import { execFileSync as execFileSync2 } from "child_process";
1585
1605
  function resolveNodeClawPath() {
1586
1606
  try {
@@ -1592,10 +1612,14 @@ function resolveNodeClawPath() {
1592
1612
  return "/usr/local/bin/nodeclaw";
1593
1613
  }
1594
1614
  }
1615
+ function resolveNodeBinDir() {
1616
+ return path8.dirname(process.execPath);
1617
+ }
1595
1618
  function generateSystemdUnit(opts = {}) {
1596
1619
  const execPath = opts.execPath || resolveNodeClawPath();
1597
- const user = opts.user || os5.userInfo().username;
1598
1620
  const workdir = opts.workdir || os5.homedir();
1621
+ const nodeBinDir = resolveNodeBinDir();
1622
+ const pathEnv = `PATH=${nodeBinDir}:/usr/local/bin:/usr/bin:/bin`;
1599
1623
  return `[Unit]
1600
1624
  Description=NodeClaw - OpenClaw Node Client
1601
1625
  After=network-online.target
@@ -1606,12 +1630,12 @@ Type=simple
1606
1630
  ExecStart=${execPath} start
1607
1631
  Restart=always
1608
1632
  RestartSec=5
1609
- User=${user}
1610
1633
  WorkingDirectory=${workdir}
1611
1634
  Environment=NODE_ENV=production
1635
+ Environment=${pathEnv}
1612
1636
 
1613
1637
  [Install]
1614
- WantedBy=multi-user.target
1638
+ WantedBy=default.target
1615
1639
  `;
1616
1640
  }
1617
1641
 
@@ -1670,14 +1694,14 @@ function registerInstallServiceCommand(program2) {
1670
1694
  console.log(unit);
1671
1695
  return;
1672
1696
  }
1673
- const unitPath = path8.join(
1697
+ const unitPath = path9.join(
1674
1698
  os7.homedir(),
1675
1699
  ".config",
1676
1700
  "systemd",
1677
1701
  "user",
1678
1702
  "nodeclaw.service"
1679
1703
  );
1680
- fs9.mkdirSync(path8.dirname(unitPath), { recursive: true });
1704
+ fs9.mkdirSync(path9.dirname(unitPath), { recursive: true });
1681
1705
  fs9.writeFileSync(unitPath, unit);
1682
1706
  console.log(`Service file written to ${unitPath}`);
1683
1707
  console.log("To enable: systemctl --user enable --now nodeclaw");
@@ -1687,13 +1711,13 @@ function registerInstallServiceCommand(program2) {
1687
1711
  console.log(plist);
1688
1712
  return;
1689
1713
  }
1690
- const plistPath = path8.join(
1714
+ const plistPath = path9.join(
1691
1715
  os7.homedir(),
1692
1716
  "Library",
1693
1717
  "LaunchAgents",
1694
1718
  "ai.nodeclaw.plist"
1695
1719
  );
1696
- fs9.mkdirSync(path8.dirname(plistPath), { recursive: true });
1720
+ fs9.mkdirSync(path9.dirname(plistPath), { recursive: true });
1697
1721
  fs9.writeFileSync(plistPath, plist);
1698
1722
  console.log(`Plist written to ${plistPath}`);
1699
1723
  console.log("To load: launchctl load " + plistPath);
@@ -1705,7 +1729,7 @@ function registerInstallServiceCommand(program2) {
1705
1729
  program2.command("uninstall-service").description("Remove installed service").action(() => {
1706
1730
  const platform = process.platform;
1707
1731
  if (platform === "linux") {
1708
- const unitPath = path8.join(
1732
+ const unitPath = path9.join(
1709
1733
  os7.homedir(),
1710
1734
  ".config",
1711
1735
  "systemd",
@@ -1720,7 +1744,7 @@ function registerInstallServiceCommand(program2) {
1720
1744
  console.log("Service file not found.");
1721
1745
  }
1722
1746
  } else if (platform === "darwin") {
1723
- const plistPath = path8.join(
1747
+ const plistPath = path9.join(
1724
1748
  os7.homedir(),
1725
1749
  "Library",
1726
1750
  "LaunchAgents",
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/pairing/pair.ts","../src/crypto/identity.ts","../src/crypto/device-auth.ts","../src/crypto/token-store.ts","../src/config/schema.ts","../src/config/paths.ts","../src/config/loader.ts","../src/client/gateway-client.ts","../src/protocol/constants.ts","../src/protocol/guards.ts","../src/cli/pair.ts","../src/runtime/router.ts","../src/runtime/node-runtime.ts","../src/handlers/system-run.ts","../src/handlers/node-events.ts","../src/handlers/system-run-prepare.ts","../src/handlers/system-info.ts","../src/handlers/system-which.ts","../src/handlers/exec-approvals.ts","../src/handlers/index.ts","../src/cli/start.ts","../src/cli/status.ts","../src/cli/unpair.ts","../src/cli/version.ts","../src/cli/doctor.ts","../src/cli/install-service.ts","../src/service/systemd.ts","../src/service/launchd.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { VERSION } from \"./index.js\";\nimport { registerPairCommand } from \"./cli/pair.js\";\nimport { registerStartCommand } from \"./cli/start.js\";\nimport { registerStatusCommand } from \"./cli/status.js\";\nimport { registerUnpairCommand } from \"./cli/unpair.js\";\nimport { registerVersionCommand } from \"./cli/version.js\";\nimport { registerDoctorCommand } from \"./cli/doctor.js\";\nimport { registerInstallServiceCommand } from \"./cli/install-service.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"nodeclaw\")\n .description(\"Minimal OpenClaw node protocol client\")\n .version(VERSION);\n\nregisterPairCommand(program);\nregisterStartCommand(program);\nregisterStatusCommand(program);\nregisterUnpairCommand(program);\nregisterVersionCommand(program);\nregisterDoctorCommand(program);\nregisterInstallServiceCommand(program);\n\nprogram.parse();\n","import os from \"node:os\";\nimport {\n loadOrCreateIdentity,\n storeDeviceAuthToken,\n loadDeviceAuthToken,\n} from \"../crypto/index.js\";\nimport { resolveIdentityPath, resolveTokenStorePath } from \"../config/index.js\";\nimport { GatewayClient } from \"../client/index.js\";\nimport { VERSION } from \"../index.js\";\nimport type { HelloOk, NodePairRequestParams } from \"../protocol/index.js\";\n\nexport type PairOptions = {\n gatewayUrl: string;\n deviceName?: string;\n env?: NodeJS.ProcessEnv;\n};\n\nexport type PairResult = {\n deviceId: string;\n paired: boolean;\n message: string;\n};\n\nexport async function pairWithGateway(opts: PairOptions): Promise<PairResult> {\n const identityPath = resolveIdentityPath(opts.env);\n const tokenStorePath = resolveTokenStorePath(opts.env);\n const identity = loadOrCreateIdentity(identityPath);\n const role = \"node\";\n\n // Check if already paired\n const existingToken = loadDeviceAuthToken(tokenStorePath, identity.deviceId, role);\n if (existingToken) {\n return {\n deviceId: identity.deviceId,\n paired: true,\n message: \"Already paired with gateway.\",\n };\n }\n\n return new Promise<PairResult>((resolve, reject) => {\n let pairRequestSent = false;\n let timeoutTimer: NodeJS.Timeout | null = null;\n\n const client = new GatewayClient({\n url: opts.gatewayUrl,\n deviceIdentity: identity,\n role,\n scopes: [\"node.invoke\"],\n caps: [\"system\"],\n commands: [\"system.run\", \"system.run.prepare\", \"system.which\"],\n clientDisplayName: opts.deviceName || os.hostname(),\n platform: process.platform,\n mode: \"node\",\n onHelloOk: (hello: HelloOk) => {\n // Connected successfully — if we get a deviceToken, pairing is done\n if (hello.auth?.deviceToken) {\n storeDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n role,\n hello.auth.deviceToken,\n hello.auth.scopes,\n );\n cleanup();\n resolve({\n deviceId: identity.deviceId,\n paired: true,\n message: \"Paired successfully!\",\n });\n return;\n }\n\n // No device token — send pair request\n if (!pairRequestSent) {\n pairRequestSent = true;\n const params: NodePairRequestParams = {\n nodeId: identity.deviceId,\n displayName: opts.deviceName || os.hostname(),\n platform: process.platform,\n version: VERSION,\n caps: [\"system\"],\n commands: [\"system.run\", \"system.run.prepare\", \"system.which\"],\n };\n void client\n .request(\"node.pair.request\", params)\n .then(() => {\n console.log(\n 'Pairing request sent. Waiting for approval on the gateway...\\n' +\n `Run \"openclaw nodes approve\" on your gateway to approve this device.`,\n );\n })\n .catch((err) => {\n cleanup();\n reject(new Error(`Pair request failed: ${String(err)}`));\n });\n }\n },\n onConnectError: (err) => {\n // If it's a pairing-required error, that's expected during pairing flow\n if (!pairRequestSent) {\n // Will reconnect and try again\n }\n },\n onClose: () => {\n // reconnect will be handled by the client\n },\n });\n\n const cleanup = () => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n client.stop();\n };\n\n // Timeout after 5 minutes\n timeoutTimer = setTimeout(() => {\n cleanup();\n reject(new Error(\"Pairing timed out after 5 minutes. Try again.\"));\n }, 5 * 60 * 1000);\n\n client.start();\n });\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type DeviceIdentity = {\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n};\n\ntype StoredIdentity = {\n version: 1;\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n createdAtMs: number;\n};\n\nconst ED25519_SPKI_PREFIX = Buffer.from(\"302a300506032b6570032100\", \"hex\");\n\nexport function base64UrlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(/=+$/g, \"\");\n}\n\nexport function base64UrlDecode(input: string): Buffer {\n const normalized = input.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n return Buffer.from(padded, \"base64\");\n}\n\nfunction derivePublicKeyRaw(publicKeyPem: string): Buffer {\n const key = crypto.createPublicKey(publicKeyPem);\n const spki = key.export({ type: \"spki\", format: \"der\" }) as Buffer;\n if (\n spki.length === ED25519_SPKI_PREFIX.length + 32 &&\n spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)\n ) {\n return spki.subarray(ED25519_SPKI_PREFIX.length);\n }\n return spki;\n}\n\nfunction fingerprintPublicKey(publicKeyPem: string): string {\n const raw = derivePublicKeyRaw(publicKeyPem);\n return crypto.createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nexport function generateIdentity(): DeviceIdentity {\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ed25519\");\n const publicKeyPem = publicKey.export({ type: \"spki\", format: \"pem\" }).toString();\n const privateKeyPem = privateKey.export({ type: \"pkcs8\", format: \"pem\" }).toString();\n const deviceId = fingerprintPublicKey(publicKeyPem);\n return { deviceId, publicKeyPem, privateKeyPem };\n}\n\nexport function loadOrCreateIdentity(filePath: string): DeviceIdentity {\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as StoredIdentity;\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKeyPem === \"string\" &&\n typeof parsed.privateKeyPem === \"string\"\n ) {\n const derivedId = fingerprintPublicKey(parsed.publicKeyPem);\n if (derivedId && derivedId !== parsed.deviceId) {\n const updated: StoredIdentity = { ...parsed, deviceId: derivedId };\n fs.writeFileSync(filePath, `${JSON.stringify(updated, null, 2)}\\n`, { mode: 0o600 });\n return { deviceId: derivedId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };\n }\n return { deviceId: parsed.deviceId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };\n }\n }\n } catch {\n // fall through to regenerate\n }\n\n const identity = generateIdentity();\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const stored: StoredIdentity = {\n version: 1,\n deviceId: identity.deviceId,\n publicKeyPem: identity.publicKeyPem,\n privateKeyPem: identity.privateKeyPem,\n createdAtMs: Date.now(),\n };\n fs.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}\\n`, { mode: 0o600 });\n return identity;\n}\n\nexport function signDevicePayload(privateKeyPem: string, payload: string): string {\n const key = crypto.createPrivateKey(privateKeyPem);\n const sig = crypto.sign(null, Buffer.from(payload, \"utf8\"), key);\n return base64UrlEncode(sig);\n}\n\nexport function verifyDeviceSignature(\n publicKeyPem: string,\n payload: string,\n signatureBase64Url: string,\n): boolean {\n try {\n const key = crypto.createPublicKey(publicKeyPem);\n const sig = base64UrlDecode(signatureBase64Url);\n return crypto.verify(null, Buffer.from(payload, \"utf8\"), key, sig);\n } catch {\n return false;\n }\n}\n\nexport function publicKeyRawBase64Url(publicKeyPem: string): string {\n return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));\n}\n\nexport function deriveDeviceId(publicKeyPem: string): string {\n return fingerprintPublicKey(publicKeyPem);\n}\n","export type DeviceAuthPayloadV3Params = {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token?: string | null;\n nonce: string;\n platform?: string | null;\n deviceFamily?: string | null;\n};\n\nfunction normalizeMetadataForAuth(value?: string | null): string {\n if (typeof value !== \"string\") {\n return \"\";\n }\n const trimmed = value.trim();\n if (!trimmed) {\n return \"\";\n }\n // ASCII-lowercase only (matches OpenClaw's cross-runtime normalization)\n return trimmed.replace(/[A-Z]/g, (ch) =>\n String.fromCharCode(ch.charCodeAt(0) + 32),\n );\n}\n\nexport function buildDeviceAuthPayloadV3(\n params: DeviceAuthPayloadV3Params,\n): string {\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n const platform = normalizeMetadataForAuth(params.platform);\n const deviceFamily = normalizeMetadataForAuth(params.deviceFamily);\n return [\n \"v3\",\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n params.nonce,\n platform,\n deviceFamily,\n ].join(\"|\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type DeviceAuthEntry = {\n token: string;\n scopes: string[];\n issuedAtMs: number;\n};\n\ntype DeviceAuthStore = {\n version: 1;\n deviceId: string;\n tokens: Record<string, DeviceAuthEntry>;\n};\n\nfunction readStore(filePath: string): DeviceAuthStore | null {\n try {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as DeviceAuthStore;\n if (\n parsed?.version !== 1 ||\n typeof parsed.deviceId !== \"string\" ||\n !parsed.tokens ||\n typeof parsed.tokens !== \"object\"\n ) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction writeStore(filePath: string, store: DeviceAuthStore): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}\\n`, {\n mode: 0o600,\n });\n}\n\nexport function loadDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n): DeviceAuthEntry | null {\n const store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n return null;\n }\n const entry = store.tokens[role];\n if (!entry || typeof entry.token !== \"string\") {\n return null;\n }\n return entry;\n}\n\nexport function storeDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n token: string,\n scopes: string[] = [],\n): DeviceAuthEntry {\n let store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n store = { version: 1, deviceId, tokens: {} };\n }\n const entry: DeviceAuthEntry = {\n token,\n scopes,\n issuedAtMs: Date.now(),\n };\n store.tokens[role] = entry;\n writeStore(filePath, store);\n return entry;\n}\n\nexport function clearDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n): void {\n const store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n return;\n }\n delete store.tokens[role];\n writeStore(filePath, store);\n}\n","import { z } from \"zod\";\n\nexport const GatewayConfigSchema = z.object({\n url: z.string().url().default(\"ws://127.0.0.1:18789\"),\n tlsVerify: z.boolean().default(true),\n});\n\nexport const DeviceConfigSchema = z.object({\n name: z.string().default(\"\"),\n workdir: z.string().default(\"\"),\n});\n\nexport const ExecConfigSchema = z.object({\n blockedCommands: z.array(z.string()).default([]),\n timeoutMs: z.number().int().min(0).default(60_000),\n maxConcurrent: z.number().int().min(1).default(3),\n});\n\nexport const LogConfigSchema = z.object({\n level: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n path: z.string().optional(),\n});\n\nexport const NodeClawConfigSchema = z.object({\n gateway: GatewayConfigSchema.default({}),\n device: DeviceConfigSchema.default({}),\n exec: ExecConfigSchema.default({}),\n log: LogConfigSchema.default({}),\n});\n\nexport type NodeClawConfig = z.infer<typeof NodeClawConfigSchema>;\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\nexport type DeviceConfig = z.infer<typeof DeviceConfigSchema>;\nexport type ExecConfig = z.infer<typeof ExecConfigSchema>;\nexport type LogConfig = z.infer<typeof LogConfigSchema>;\n","import path from \"node:path\";\nimport os from \"node:os\";\n\nexport function resolveBaseDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.NODECLAW_HOME) {\n return env.NODECLAW_HOME;\n }\n return path.join(os.homedir(), \".nodeclaw\");\n}\n\nexport function resolveConfigPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"config.json\");\n}\n\nexport function resolveIdentityPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"identity\", \"device.json\");\n}\n\nexport function resolveTokenStorePath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"identity\", \"device-auth.json\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { NodeClawConfigSchema, type NodeClawConfig } from \"./schema.js\";\nimport { resolveBaseDir, resolveConfigPath } from \"./paths.js\";\n\nexport function ensureConfigDir(env?: NodeJS.ProcessEnv): void {\n const baseDir = resolveBaseDir(env);\n fs.mkdirSync(baseDir, { recursive: true });\n}\n\nexport function loadConfig(env?: NodeJS.ProcessEnv): NodeClawConfig {\n const configPath = resolveConfigPath(env);\n try {\n if (fs.existsSync(configPath)) {\n const raw = fs.readFileSync(configPath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n return NodeClawConfigSchema.parse(parsed);\n }\n } catch {\n // Fall through to defaults\n }\n return NodeClawConfigSchema.parse({});\n}\n\nexport function saveConfig(\n config: NodeClawConfig,\n env?: NodeJS.ProcessEnv,\n): void {\n const configPath = resolveConfigPath(env);\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, {\n mode: 0o600,\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { WebSocket } from \"ws\";\nimport {\n signDevicePayload,\n publicKeyRawBase64Url,\n buildDeviceAuthPayloadV3,\n} from \"../crypto/index.js\";\nimport {\n PROTOCOL_VERSION,\n CLIENT_NAME,\n CLIENT_MODES,\n isEventFrame,\n isResponseFrame,\n type ConnectParams,\n type HelloOk,\n type EventFrame,\n} from \"../protocol/index.js\";\nimport { VERSION } from \"../index.js\";\nimport type { GatewayClientOptions } from \"./types.js\";\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (err: unknown) => void;\n timeout: NodeJS.Timeout | null;\n};\n\nconst DEFAULT_CONNECT_TIMEOUT_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst MAX_BACKOFF_MS = 30_000;\nconst FORCE_STOP_GRACE_MS = 250;\n\nexport type ConnectionHealth = {\n connected: boolean;\n connectedAtMs: number | null;\n lastTickMs: number | null;\n reconnectCount: number;\n tickIntervalMs: number;\n};\n\nexport class GatewayClient {\n private ws: WebSocket | null = null;\n private opts: GatewayClientOptions;\n private pending = new Map<string, Pending>();\n private backoffMs = 1000;\n private closed = false;\n private connectNonce: string | null = null;\n private connectSent = false;\n private connectTimer: NodeJS.Timeout | null = null;\n private lastTick: number | null = null;\n private tickIntervalMs = 30_000;\n private tickTimer: NodeJS.Timeout | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private readonly requestTimeoutMs: number;\n private connectedAtMs: number | null = null;\n private reconnectCount = 0;\n\n constructor(opts: GatewayClientOptions) {\n this.opts = opts;\n this.requestTimeoutMs =\n typeof opts.requestTimeoutMs === \"number\"\n ? Math.max(1, opts.requestTimeoutMs)\n : DEFAULT_REQUEST_TIMEOUT_MS;\n }\n\n start(): void {\n if (this.closed) {\n return;\n }\n const url = this.opts.url;\n\n const ws = new WebSocket(url, {\n maxPayload: 25 * 1024 * 1024,\n rejectUnauthorized: this.opts.tlsVerify !== false,\n });\n this.ws = ws;\n\n ws.on(\"open\", () => {\n this.queueConnect();\n });\n ws.on(\"message\", (data) => {\n const raw =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString(\"utf8\")\n : Buffer.from(data as ArrayBuffer).toString(\"utf8\");\n this.handleMessage(raw);\n });\n ws.on(\"close\", (code, reason) => {\n const reasonText =\n typeof reason === \"string\"\n ? reason\n : Buffer.isBuffer(reason)\n ? reason.toString(\"utf8\")\n : \"\";\n if (this.ws === ws) {\n this.ws = null;\n }\n this.flushPendingErrors(\n new Error(`gateway closed (${code}): ${reasonText}`),\n );\n this.scheduleReconnect();\n this.opts.onClose?.(code, reasonText);\n });\n ws.on(\"error\", (err) => {\n if (!this.connectSent) {\n this.opts.onConnectError?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n });\n }\n\n stop(): void {\n this.closed = true;\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n this.tickTimer = null;\n }\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n const ws = this.ws;\n this.ws = null;\n if (ws) {\n ws.close();\n setTimeout(() => {\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n }, FORCE_STOP_GRACE_MS).unref();\n }\n this.flushPendingErrors(new Error(\"gateway client stopped\"));\n }\n\n async stopAndWait(timeoutMs = 1000): Promise<void> {\n this.stop();\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, Math.min(timeoutMs, FORCE_STOP_GRACE_MS + 100));\n timer.unref();\n });\n }\n\n async request<T = unknown>(\n method: string,\n params?: unknown,\n opts?: { timeoutMs?: number },\n ): Promise<T> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error(\"gateway not connected\");\n }\n const id = randomUUID();\n const frame = { type: \"req\" as const, id, method, params };\n this.ws.send(JSON.stringify(frame));\n\n const timeoutMs = opts?.timeoutMs ?? this.requestTimeoutMs;\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`request ${method} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeout,\n });\n });\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.connectSent;\n }\n\n getHealth(): ConnectionHealth {\n return {\n connected: this.isConnected(),\n connectedAtMs: this.connectedAtMs,\n lastTickMs: this.lastTick,\n reconnectCount: this.reconnectCount,\n tickIntervalMs: this.tickIntervalMs,\n };\n }\n\n private queueConnect(): void {\n this.connectNonce = null;\n this.connectSent = false;\n const connectTimeoutMs = this.opts.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n }\n this.connectTimer = setTimeout(() => {\n if (this.connectSent || this.ws?.readyState !== WebSocket.OPEN) {\n return;\n }\n this.opts.onConnectError?.(new Error(\"gateway connect challenge timeout\"));\n this.ws?.close(1008, \"connect challenge timeout\");\n }, connectTimeoutMs);\n }\n\n private sendConnect(): void {\n if (this.connectSent) {\n return;\n }\n const nonce = this.connectNonce?.trim() ?? \"\";\n if (!nonce) {\n this.opts.onConnectError?.(new Error(\"gateway connect challenge missing nonce\"));\n this.ws?.close(1008, \"connect challenge missing nonce\");\n return;\n }\n this.connectSent = true;\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n\n const role = this.opts.role ?? \"node\";\n const scopes = this.opts.scopes ?? [\"node.invoke\"];\n const platform = this.opts.platform ?? process.platform;\n const signedAtMs = Date.now();\n\n // Build device auth\n const device = (() => {\n if (!this.opts.deviceIdentity) {\n return undefined;\n }\n const payload = buildDeviceAuthPayloadV3({\n deviceId: this.opts.deviceIdentity.deviceId,\n clientId: this.opts.clientName ?? CLIENT_NAME,\n clientMode: this.opts.mode ?? CLIENT_MODES.NODE,\n role,\n scopes,\n signedAtMs,\n token: this.opts.token ?? this.opts.deviceToken ?? null,\n nonce,\n platform,\n deviceFamily: this.opts.deviceFamily,\n });\n const signature = signDevicePayload(\n this.opts.deviceIdentity.privateKeyPem,\n payload,\n );\n return {\n id: this.opts.deviceIdentity.deviceId,\n publicKey: publicKeyRawBase64Url(this.opts.deviceIdentity.publicKeyPem),\n signature,\n signedAt: signedAtMs,\n nonce,\n };\n })();\n\n const auth =\n this.opts.token || this.opts.deviceToken\n ? {\n token: this.opts.token,\n deviceToken: this.opts.deviceToken,\n }\n : undefined;\n\n const params: ConnectParams = {\n minProtocol: PROTOCOL_VERSION,\n maxProtocol: PROTOCOL_VERSION,\n client: {\n id: this.opts.clientName ?? CLIENT_NAME,\n displayName: this.opts.clientDisplayName,\n version: this.opts.clientVersion ?? VERSION,\n platform,\n deviceFamily: this.opts.deviceFamily,\n mode: this.opts.mode ?? CLIENT_MODES.NODE,\n instanceId: this.opts.instanceId,\n },\n caps: this.opts.caps ?? [],\n commands: this.opts.commands,\n permissions: this.opts.permissions,\n pathEnv: this.opts.pathEnv,\n auth,\n role,\n scopes,\n device,\n };\n\n void this.request<HelloOk>(\"connect\", params)\n .then((helloOk) => {\n this.backoffMs = 1000;\n this.connectedAtMs = Date.now();\n this.tickIntervalMs =\n typeof helloOk.policy?.tickIntervalMs === \"number\"\n ? helloOk.policy.tickIntervalMs\n : 30_000;\n this.lastTick = Date.now();\n this.startTickWatch();\n this.opts.onHelloOk?.(helloOk);\n })\n .catch((err) => {\n this.opts.onConnectError?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n this.ws?.close(1008, \"connect failed\");\n });\n }\n\n private handleMessage(raw: string): void {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return;\n }\n\n if (isEventFrame(parsed)) {\n this.lastTick = Date.now();\n if (parsed.event === \"connect.challenge\") {\n const payload = parsed.payload as { nonce?: unknown } | undefined;\n const nonce =\n payload && typeof payload.nonce === \"string\" ? payload.nonce : null;\n if (!nonce || nonce.trim().length === 0) {\n this.opts.onConnectError?.(\n new Error(\"gateway connect challenge missing nonce\"),\n );\n this.ws?.close(1008, \"connect challenge missing nonce\");\n return;\n }\n this.connectNonce = nonce.trim();\n this.sendConnect();\n return;\n }\n if (parsed.event === \"tick\") {\n this.lastTick = Date.now();\n }\n this.opts.onEvent?.(parsed);\n return;\n }\n\n if (isResponseFrame(parsed)) {\n this.lastTick = Date.now();\n const pending = this.pending.get(parsed.id);\n if (!pending) {\n return;\n }\n this.pending.delete(parsed.id);\n if (pending.timeout) {\n clearTimeout(pending.timeout);\n }\n if (parsed.ok) {\n pending.resolve(parsed.payload);\n } else {\n pending.reject(\n new Error(\n parsed.error?.message ?? `request failed: ${parsed.error?.code ?? \"unknown\"}`,\n ),\n );\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed) {\n return;\n }\n this.connectedAtMs = null;\n this.reconnectCount++;\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n this.tickTimer = null;\n }\n const delay = this.backoffMs;\n this.backoffMs = Math.min(this.backoffMs * 2, MAX_BACKOFF_MS);\n this.reconnectTimer = setTimeout(() => this.start(), delay);\n this.reconnectTimer.unref();\n }\n\n private flushPendingErrors(err: Error): void {\n for (const [, p] of this.pending) {\n if (p.timeout) {\n clearTimeout(p.timeout);\n }\n p.reject(err);\n }\n this.pending.clear();\n }\n\n private startTickWatch(): void {\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n }\n const interval = Math.max(this.tickIntervalMs, 1000);\n this.tickTimer = setInterval(() => {\n if (this.closed || !this.lastTick) {\n return;\n }\n const gap = Date.now() - this.lastTick;\n if (gap > this.tickIntervalMs * 2) {\n this.ws?.close(4000, \"tick timeout\");\n }\n }, interval);\n this.tickTimer.unref();\n }\n}\n","export const PROTOCOL_VERSION = 3;\n\nexport const CLIENT_NAME = \"nodeclaw\";\n\nexport const CLIENT_MODES = {\n NODE: \"node\",\n BACKEND: \"backend\",\n PROBE: \"probe\",\n} as const;\n\nexport type ClientMode = (typeof CLIENT_MODES)[keyof typeof CLIENT_MODES];\n","import type { EventFrame, ResponseFrame, RequestFrame } from \"./frames.js\";\nimport type { NodeInvokeRequestPayload } from \"./nodes.js\";\n\nexport function isEventFrame(msg: unknown): msg is EventFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"event\" &&\n typeof (msg as Record<string, unknown>).event === \"string\"\n );\n}\n\nexport function isResponseFrame(msg: unknown): msg is ResponseFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"res\" &&\n typeof (msg as Record<string, unknown>).id === \"string\" &&\n typeof (msg as Record<string, unknown>).ok === \"boolean\"\n );\n}\n\nexport function isRequestFrame(msg: unknown): msg is RequestFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"req\" &&\n typeof (msg as Record<string, unknown>).id === \"string\" &&\n typeof (msg as Record<string, unknown>).method === \"string\"\n );\n}\n\nexport function coerceNodeInvokePayload(\n payload: unknown,\n): NodeInvokeRequestPayload | null {\n if (typeof payload !== \"object\" || payload === null) {\n return null;\n }\n const obj = payload as Record<string, unknown>;\n if (typeof obj.id !== \"string\" || typeof obj.command !== \"string\") {\n return null;\n }\n return {\n id: obj.id,\n nodeId: typeof obj.nodeId === \"string\" ? obj.nodeId : \"\",\n command: obj.command,\n paramsJSON:\n typeof obj.paramsJSON === \"string\" ? obj.paramsJSON : undefined,\n timeoutMs:\n typeof obj.timeoutMs === \"number\" ? obj.timeoutMs : undefined,\n idempotencyKey:\n typeof obj.idempotencyKey === \"string\"\n ? obj.idempotencyKey\n : undefined,\n };\n}\n","import type { Command } from \"commander\";\nimport { pairWithGateway } from \"../pairing/index.js\";\n\nexport function registerPairCommand(program: Command): void {\n program\n .command(\"pair\")\n .description(\"Pair this device with an OpenClaw gateway\")\n .argument(\"<gateway-url>\", \"WebSocket URL of the gateway (e.g. wss://host:18789)\")\n .option(\"-n, --name <name>\", \"Display name for this device\")\n .action(async (gatewayUrl: string, opts: { name?: string }) => {\n try {\n const result = await pairWithGateway({\n gatewayUrl,\n deviceName: opts.name,\n });\n console.log(result.message);\n console.log(`Device ID: ${result.deviceId}`);\n process.exit(0);\n } catch (err) {\n console.error(`Pairing failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n });\n}\n","import type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type InvokeHandler = (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n) => Promise<void>;\n\nexport class CommandRouter {\n private handlers = new Map<string, InvokeHandler>();\n\n register(command: string, handler: InvokeHandler): void {\n this.handlers.set(command, handler);\n }\n\n async dispatch(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> {\n const handler = this.handlers.get(payload.command);\n if (handler) {\n await handler(payload, client);\n return;\n }\n\n // Unknown command — send error result\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"UNKNOWN_COMMAND\",\n message: `Unknown command: ${payload.command}`,\n },\n };\n await client.request(\"node.invoke.result\", result);\n }\n}\n","import os from \"node:os\";\nimport {\n loadOrCreateIdentity,\n loadDeviceAuthToken,\n} from \"../crypto/index.js\";\nimport {\n loadConfig,\n resolveIdentityPath,\n resolveTokenStorePath,\n type NodeClawConfig,\n} from \"../config/index.js\";\nimport { GatewayClient } from \"../client/index.js\";\nimport { coerceNodeInvokePayload, type EventFrame } from \"../protocol/index.js\";\nimport { VERSION } from \"../index.js\";\nimport { CommandRouter } from \"./router.js\";\n\nexport type NodeRuntimeOptions = {\n config?: NodeClawConfig;\n env?: NodeJS.ProcessEnv;\n router?: CommandRouter;\n};\n\nexport async function startNode(opts: NodeRuntimeOptions = {}): Promise<{\n client: GatewayClient;\n router: CommandRouter;\n stop: () => void;\n}> {\n const config = opts.config ?? loadConfig(opts.env);\n const identityPath = resolveIdentityPath(opts.env);\n const tokenStorePath = resolveTokenStorePath(opts.env);\n const identity = loadOrCreateIdentity(identityPath);\n const role = \"node\";\n\n const storedAuth = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n role,\n );\n if (!storedAuth) {\n throw new Error(\n \"Not paired with a gateway. Run 'nodeclaw pair <gateway-url>' first.\",\n );\n }\n\n const router = opts.router ?? new CommandRouter();\n\n const client = new GatewayClient({\n url: config.gateway.url,\n deviceIdentity: identity,\n deviceToken: storedAuth.token,\n role,\n scopes: [\"node.invoke\"],\n caps: [\"system\"],\n commands: [\n \"system.run\",\n \"system.run.prepare\",\n \"system.which\",\n \"system.execApprovals.get\",\n \"system.execApprovals.set\",\n ],\n clientDisplayName: config.device.name || os.hostname(),\n clientVersion: VERSION,\n platform: process.platform,\n mode: \"node\",\n tlsVerify: config.gateway.tlsVerify,\n onHelloOk: (hello) => {\n console.log(\n `Connected to gateway (protocol ${hello.protocol ?? \"?\"}, connId: ${hello.server?.connId ?? \"?\"})`,\n );\n },\n onEvent: (evt: EventFrame) => {\n if (evt.event === \"node.invoke.request\") {\n const invokePayload = coerceNodeInvokePayload(evt.payload);\n if (invokePayload) {\n void router.dispatch(invokePayload, client).catch((err) => {\n console.error(\n `Handler error for ${invokePayload.command}: ${String(err)}`,\n );\n });\n }\n }\n },\n onConnectError: (err) => {\n console.error(`Connection error: ${err.message}`);\n },\n onClose: (code, reason) => {\n if (code !== 1000) {\n console.log(`Disconnected (${code}): ${reason || \"unknown\"}`);\n }\n },\n });\n\n client.start();\n\n return {\n client,\n router,\n stop: () => client.stop(),\n };\n}\n","import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\nimport type { ExecConfig } from \"../config/index.js\";\nimport { emitExecStarted, emitExecFinished, emitExecDenied } from \"./node-events.js\";\n\nconst OUTPUT_CAP = 200_000; // 200KB max output capture\n\ntype SystemRunParams = {\n command: string[];\n cwd?: string;\n env?: Record<string, string>;\n timeoutMs?: number;\n sessionKey?: string;\n runId?: string;\n suppressNotifyOnExit?: boolean;\n};\n\ntype RunResult = {\n exitCode: number | null;\n stdout: string;\n stderr: string;\n timedOut: boolean;\n truncated: boolean;\n};\n\nlet activeCount = 0;\n\nfunction parseRunParams(paramsJSON?: string | null): SystemRunParams | null {\n if (!paramsJSON) {\n return null;\n }\n try {\n const parsed = JSON.parse(paramsJSON) as unknown;\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as Record<string, unknown>;\n let command: string[] | null = null;\n if (Array.isArray(obj.command)) {\n command = (obj.command as string[]).filter((s) => typeof s === \"string\");\n } else if (typeof obj.command === \"string\" && obj.command.trim()) {\n command = [obj.command];\n } else if (typeof obj.rawCommand === \"string\" && obj.rawCommand.trim()) {\n command = [\"sh\", \"-c\", obj.rawCommand as string];\n }\n if (!command || command.length === 0) {\n return null;\n }\n return {\n command,\n cwd: typeof obj.cwd === \"string\" ? obj.cwd : undefined,\n env:\n typeof obj.env === \"object\" && obj.env !== null\n ? (obj.env as Record<string, string>)\n : undefined,\n timeoutMs:\n typeof obj.timeoutMs === \"number\" ? obj.timeoutMs : undefined,\n sessionKey:\n typeof obj.sessionKey === \"string\" ? obj.sessionKey : undefined,\n runId: typeof obj.runId === \"string\" ? obj.runId : undefined,\n suppressNotifyOnExit:\n typeof obj.suppressNotifyOnExit === \"boolean\"\n ? obj.suppressNotifyOnExit\n : undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction isPathWithinWorkdir(testPath: string, workdir: string): boolean {\n if (!workdir) {\n return true; // no workdir restriction\n }\n const resolved = path.resolve(testPath);\n const resolvedWorkdir = path.resolve(workdir);\n return resolved === resolvedWorkdir || resolved.startsWith(resolvedWorkdir + path.sep);\n}\n\nfunction isBlockedCommand(\n command: string[],\n blockedCommands: string[],\n): boolean {\n if (blockedCommands.length === 0) {\n return false;\n }\n const cmdStr = command.join(\" \");\n return blockedCommands.some(\n (blocked) => cmdStr === blocked || cmdStr.startsWith(blocked + \" \"),\n );\n}\n\nfunction runCommand(\n params: SystemRunParams,\n execConfig: ExecConfig,\n): Promise<RunResult> {\n return new Promise<RunResult>((resolve) => {\n const timeoutMs = params.timeoutMs ?? execConfig.timeoutMs;\n const [bin, ...args] = params.command;\n const cwd = params.cwd || undefined;\n const env = params.env\n ? { ...process.env, ...params.env }\n : undefined;\n\n const proc = spawn(bin, args, {\n cwd,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let truncated = false;\n let timedOut = false;\n let totalOutput = 0;\n\n const appendOutput = (\n target: \"stdout\" | \"stderr\",\n chunk: Buffer,\n ): void => {\n const remaining = OUTPUT_CAP - totalOutput;\n if (remaining <= 0) {\n truncated = true;\n return;\n }\n const text = chunk.toString(\"utf8\");\n const toAppend = text.length > remaining ? text.slice(0, remaining) : text;\n totalOutput += toAppend.length;\n if (target === \"stdout\") {\n stdout += toAppend;\n } else {\n stderr += toAppend;\n }\n if (totalOutput >= OUTPUT_CAP) {\n truncated = true;\n }\n };\n\n proc.stdout.on(\"data\", (chunk: Buffer) => appendOutput(\"stdout\", chunk));\n proc.stderr.on(\"data\", (chunk: Buffer) => appendOutput(\"stderr\", chunk));\n\n let timeoutTimer: NodeJS.Timeout | null = null;\n if (timeoutMs > 0) {\n timeoutTimer = setTimeout(() => {\n timedOut = true;\n try {\n proc.kill(\"SIGKILL\");\n } catch {\n // ignore\n }\n }, timeoutMs);\n }\n\n proc.on(\"close\", (code) => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n }\n resolve({\n exitCode: code,\n stdout,\n stderr,\n timedOut,\n truncated,\n });\n });\n\n proc.on(\"error\", (err) => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n }\n resolve({\n exitCode: null,\n stdout,\n stderr: stderr + (stderr ? \"\\n\" : \"\") + err.message,\n timedOut: false,\n truncated,\n });\n });\n });\n}\n\nexport function createSystemRunHandler(execConfig: ExecConfig, workdir: string) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const sendResult = async (result: NodeInvokeResultParams) => {\n await client.request(\"node.invoke.result\", result);\n };\n\n const params = parseRunParams(payload.paramsJSON);\n if (!params) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid system.run params\" },\n });\n return;\n }\n\n const commandText = params.command.join(\" \");\n const sessionKey = params.sessionKey ?? \"\";\n const runId = params.runId ?? randomUUID();\n const suppressNotifyOnExit = params.suppressNotifyOnExit;\n\n // Security: check blocked commands\n if (isBlockedCommand(params.command, execConfig.blockedCommands)) {\n void emitExecDenied(client, {\n sessionKey,\n runId,\n command: commandText,\n reason: \"allowlist-miss\",\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"BLOCKED\", message: \"Command is blocked by policy\" },\n });\n return;\n }\n\n // Security: validate cwd is within workdir\n if (params.cwd && !isPathWithinWorkdir(params.cwd, workdir)) {\n void emitExecDenied(client, {\n sessionKey,\n runId,\n command: commandText,\n reason: \"security=deny\",\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"WORKDIR_VIOLATION\",\n message: `Working directory ${params.cwd} is outside allowed workdir ${workdir}`,\n },\n });\n return;\n }\n\n // Check concurrent limit\n if (activeCount >= execConfig.maxConcurrent) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"RESOURCE_EXHAUSTED\",\n message: `Max concurrent executions (${execConfig.maxConcurrent}) reached`,\n },\n });\n return;\n }\n\n activeCount++;\n void emitExecStarted(client, {\n sessionKey,\n runId,\n command: commandText,\n suppressNotifyOnExit,\n });\n try {\n const result = await runCommand(params, execConfig);\n void emitExecFinished(client, {\n sessionKey,\n runId,\n command: commandText,\n exitCode: result.exitCode,\n timedOut: result.timedOut,\n success: result.exitCode === 0 && !result.timedOut,\n output: result.stdout + result.stderr,\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n timedOut: result.timedOut,\n truncated: result.truncated,\n }),\n });\n } catch (err) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"EXEC_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n },\n });\n } finally {\n activeCount--;\n }\n };\n}\n\n// For testing\nexport { parseRunParams, isPathWithinWorkdir, isBlockedCommand, runCommand };\nexport type { SystemRunParams, RunResult };\n","import type { GatewayClient } from \"../client/index.js\";\nimport type { NodeEventParams } from \"../protocol/index.js\";\n\nconst EVENT_OUTPUT_MAX = 20_000; // 20KB tail for event output\n\nfunction tailOutput(output: string, max: number): string {\n if (output.length <= max) return output;\n return output.slice(-max);\n}\n\nexport async function emitNodeEvent(\n client: GatewayClient,\n event: string,\n payload: Record<string, unknown>,\n): Promise<void> {\n const params: NodeEventParams = {\n event,\n payloadJSON: JSON.stringify(payload),\n };\n try {\n await client.request(\"node.event\", params);\n } catch {\n // Best-effort event emission\n }\n}\n\nexport async function emitExecStarted(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.started\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n\nexport async function emitExecFinished(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n exitCode?: number | null;\n timedOut?: boolean;\n success?: boolean;\n output?: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.finished\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n exitCode: opts.exitCode,\n timedOut: opts.timedOut,\n success: opts.success,\n output: opts.output ? tailOutput(opts.output, EVENT_OUTPUT_MAX) : undefined,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n\nexport async function emitExecDenied(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n reason: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.denied\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n reason: opts.reason,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n","import path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type SystemRunApprovalPlan = {\n argv: string[];\n cwd: string | null;\n commandText: string;\n commandPreview?: string | null;\n agentId: string | null;\n sessionKey: string | null;\n mutableFileOperand?: {\n argvIndex: number;\n path: string;\n sha256: string;\n } | null;\n};\n\ntype PrepareParams = {\n command?: unknown;\n rawCommand?: unknown;\n cwd?: unknown;\n agentId?: unknown;\n sessionKey?: unknown;\n};\n\nfunction resolveCommandArgv(params: PrepareParams): string[] | null {\n if (Array.isArray(params.command)) {\n const argv = params.command.filter(\n (s): s is string => typeof s === \"string\",\n );\n return argv.length > 0 ? argv : null;\n }\n if (typeof params.command === \"string\" && params.command.trim()) {\n return [params.command.trim()];\n }\n if (typeof params.rawCommand === \"string\" && params.rawCommand.trim()) {\n return [\"sh\", \"-c\", params.rawCommand.trim()];\n }\n return null;\n}\n\nfunction resolveMutableFileOperand(\n argv: string[],\n): SystemRunApprovalPlan[\"mutableFileOperand\"] {\n // Check if any argv element past index 0 is an existing file\n // This is a simplified version of OpenClaw's mutable file operand detection\n for (let i = 1; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith(\"-\")) continue;\n try {\n const resolved = path.resolve(arg);\n if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {\n const content = fs.readFileSync(resolved);\n const sha256 = crypto\n .createHash(\"sha256\")\n .update(content)\n .digest(\"hex\");\n return { argvIndex: i, path: resolved, sha256 };\n }\n } catch {\n // skip\n }\n }\n return null;\n}\n\nexport async function systemRunPrepareHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n): Promise<void> {\n let params: PrepareParams = {};\n if (payload.paramsJSON) {\n try {\n params = JSON.parse(payload.paramsJSON) as PrepareParams;\n } catch {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid params\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n const argv = resolveCommandArgv(params);\n if (!argv) {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"No command provided\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n\n const cwd =\n typeof params.cwd === \"string\" && params.cwd.trim()\n ? path.resolve(params.cwd.trim())\n : null;\n const agentId =\n typeof params.agentId === \"string\" ? params.agentId : null;\n const sessionKey =\n typeof params.sessionKey === \"string\" ? params.sessionKey : null;\n\n const plan: SystemRunApprovalPlan = {\n argv,\n cwd,\n commandText: argv.join(\" \"),\n commandPreview: argv.length > 3 ? argv.slice(0, 3).join(\" \") + \"...\" : null,\n agentId,\n sessionKey,\n mutableFileOperand: resolveMutableFileOperand(argv),\n };\n\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({ plan }),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import os from \"node:os\";\nimport fs from \"node:fs\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type SystemInfo = {\n cpu: {\n model: string;\n cores: number;\n };\n memory: {\n totalBytes: number;\n freeBytes: number;\n usedBytes: number;\n };\n disk?: {\n totalBytes: number;\n freeBytes: number;\n usedBytes: number;\n };\n uptime: number;\n platform: string;\n arch: string;\n hostname: string;\n nodeVersion: string;\n};\n\nexport function getSystemInfo(workdir?: string): SystemInfo {\n const cpus = os.cpus();\n const totalMem = os.totalmem();\n const freeMem = os.freemem();\n\n const info: SystemInfo = {\n cpu: {\n model: cpus.length > 0 ? cpus[0].model : \"unknown\",\n cores: cpus.length,\n },\n memory: {\n totalBytes: totalMem,\n freeBytes: freeMem,\n usedBytes: totalMem - freeMem,\n },\n uptime: os.uptime(),\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n nodeVersion: process.version,\n };\n\n // Disk info via statfs (Node 20+)\n const statfsPath = workdir || \"/\";\n try {\n const stats = fs.statfsSync(statfsPath);\n info.disk = {\n totalBytes: stats.blocks * stats.bsize,\n freeBytes: stats.bavail * stats.bsize,\n usedBytes: (stats.blocks - stats.bavail) * stats.bsize,\n };\n } catch {\n // Disk info unavailable\n }\n\n return info;\n}\n\nexport async function systemInfoHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n workdir?: string,\n): Promise<void> {\n const info = getSystemInfo(workdir);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(info),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import { execFileSync } from \"node:child_process\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nfunction whichBin(bin: string): string | null {\n try {\n const result = execFileSync(\"which\", [bin], {\n encoding: \"utf8\",\n timeout: 5000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function resolveWhich(bins: string[]): Record<string, string | null> {\n const result: Record<string, string | null> = {};\n for (const bin of bins) {\n result[bin] = whichBin(bin);\n }\n return result;\n}\n\nexport async function systemWhichHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n): Promise<void> {\n let bins: string[] = [];\n if (payload.paramsJSON) {\n try {\n const parsed = JSON.parse(payload.paramsJSON) as { bins?: string[] };\n if (Array.isArray(parsed.bins)) {\n bins = parsed.bins.filter((b): b is string => typeof b === \"string\");\n }\n } catch {\n // ignore\n }\n }\n\n const resolved = resolveWhich(bins);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({ bins: resolved }),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\nimport { resolveBaseDir } from \"../config/index.js\";\n\nexport type ExecAllowlistEntry = {\n id?: string;\n pattern: string;\n lastUsedAt?: number;\n lastUsedCommand?: string;\n lastResolvedPath?: string;\n};\n\nexport type ExecApprovalsDefaults = {\n security?: string; // \"deny\" | \"allowlist\" | \"full\"\n ask?: string; // \"off\" | \"on-miss\" | \"always\"\n askFallback?: string;\n autoAllowSkills?: boolean;\n};\n\nexport type ExecApprovalsAgent = ExecApprovalsDefaults & {\n allowlist?: ExecAllowlistEntry[];\n};\n\nexport type ExecApprovalsFile = {\n version: 1;\n socket?: {\n path?: string;\n token?: string;\n };\n defaults?: ExecApprovalsDefaults;\n agents?: Record<string, ExecApprovalsAgent>;\n};\n\nexport type ExecApprovalsSnapshot = {\n path: string;\n exists: boolean;\n raw: string | null;\n file: ExecApprovalsFile;\n hash: string;\n};\n\nfunction resolveExecApprovalsPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"exec-approvals.json\");\n}\n\nfunction hashRaw(raw: string | null): string {\n return crypto\n .createHash(\"sha256\")\n .update(raw ?? \"\")\n .digest(\"hex\");\n}\n\nfunction loadExecApprovalsFile(filePath: string): ExecApprovalsSnapshot {\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as ExecApprovalsFile;\n if (parsed?.version === 1) {\n return { path: filePath, exists: true, raw, file: parsed, hash: hashRaw(raw) };\n }\n }\n } catch {\n // fall through\n }\n const defaultFile: ExecApprovalsFile = { version: 1 };\n return { path: filePath, exists: false, raw: null, file: defaultFile, hash: hashRaw(null) };\n}\n\nfunction saveExecApprovalsFile(\n filePath: string,\n file: ExecApprovalsFile,\n): ExecApprovalsSnapshot {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const raw = JSON.stringify(file, null, 2) + \"\\n\";\n fs.writeFileSync(filePath, raw, { mode: 0o600 });\n return { path: filePath, exists: true, raw, file, hash: hashRaw(raw) };\n}\n\nexport function createExecApprovalsGetHandler(env?: NodeJS.ProcessEnv) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const filePath = resolveExecApprovalsPath(env);\n const snapshot = loadExecApprovalsFile(filePath);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(snapshot),\n };\n await client.request(\"node.invoke.result\", result);\n };\n}\n\nexport function createExecApprovalsSetHandler(env?: NodeJS.ProcessEnv) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const filePath = resolveExecApprovalsPath(env);\n\n let params: { file?: ExecApprovalsFile; baseHash?: string | null } = {};\n if (payload.paramsJSON) {\n try {\n params = JSON.parse(payload.paramsJSON) as typeof params;\n } catch {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid params\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n // CAS: check base hash if provided\n if (params.baseHash) {\n const current = loadExecApprovalsFile(filePath);\n if (current.hash !== params.baseHash) {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"HASH_MISMATCH\",\n message: \"Exec approvals file was modified concurrently\",\n },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n const file = params.file ?? { version: 1 as const };\n const snapshot = saveExecApprovalsFile(filePath, file);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(snapshot),\n };\n await client.request(\"node.invoke.result\", result);\n };\n}\n","import { loadConfig } from \"../config/index.js\";\nimport type { CommandRouter } from \"../runtime/router.js\";\nimport { createSystemRunHandler } from \"./system-run.js\";\nimport { systemRunPrepareHandler } from \"./system-run-prepare.js\";\nimport { systemInfoHandler } from \"./system-info.js\";\nimport { systemWhichHandler } from \"./system-which.js\";\nimport {\n createExecApprovalsGetHandler,\n createExecApprovalsSetHandler,\n} from \"./exec-approvals.js\";\n\nexport function registerAllHandlers(\n router: CommandRouter,\n env?: NodeJS.ProcessEnv,\n): void {\n const config = loadConfig(env);\n const workdir = config.device.workdir;\n\n router.register(\n \"system.run\",\n createSystemRunHandler(config.exec, workdir),\n );\n\n router.register(\"system.run.prepare\", systemRunPrepareHandler);\n\n router.register(\"system.info\", (payload, client) =>\n systemInfoHandler(payload, client, workdir),\n );\n\n router.register(\"system.which\", systemWhichHandler);\n\n router.register(\n \"system.execApprovals.get\",\n createExecApprovalsGetHandler(env),\n );\n\n router.register(\n \"system.execApprovals.set\",\n createExecApprovalsSetHandler(env),\n );\n}\n","import type { Command } from \"commander\";\nimport { startNode } from \"../runtime/index.js\";\nimport { registerAllHandlers } from \"../handlers/index.js\";\n\nexport function registerStartCommand(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the node daemon (foreground)\")\n .action(async () => {\n try {\n const { router, stop } = await startNode();\n registerAllHandlers(router);\n\n console.log(\"NodeClaw running. Press Ctrl+C to stop.\");\n\n const shutdown = () => {\n console.log(\"\\nShutting down...\");\n stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Keep process alive\n await new Promise(() => {});\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport {\n loadConfig,\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport { loadOrCreateIdentity, loadDeviceAuthToken } from \"../crypto/index.js\";\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show connection and pairing status\")\n .action(() => {\n const config = loadConfig();\n const identityPath = resolveIdentityPath();\n const tokenStorePath = resolveTokenStorePath();\n\n let identity;\n try {\n identity = loadOrCreateIdentity(identityPath);\n } catch {\n console.log(\"Device identity: not initialized\");\n return;\n }\n\n const token = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n \"node\",\n );\n\n console.log(`Gateway URL: ${config.gateway.url}`);\n console.log(`Device name: ${config.device.name || \"(default)\"}`);\n console.log(`Device ID: ${identity.deviceId}`);\n console.log(`Paired: ${token ? \"yes\" : \"no\"}`);\n if (config.device.workdir) {\n console.log(`Workdir: ${config.device.workdir}`);\n }\n });\n}\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport {\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport {\n loadOrCreateIdentity,\n clearDeviceAuthToken,\n} from \"../crypto/index.js\";\n\nexport function registerUnpairCommand(program: Command): void {\n program\n .command(\"unpair\")\n .description(\"Remove pairing token and disconnect\")\n .option(\"--full\", \"Also delete device identity (generates new ID on next pair)\")\n .action((opts: { full?: boolean }) => {\n const identityPath = resolveIdentityPath();\n const tokenStorePath = resolveTokenStorePath();\n\n try {\n const identity = loadOrCreateIdentity(identityPath);\n clearDeviceAuthToken(tokenStorePath, identity.deviceId, \"node\");\n console.log(\"Pairing token removed.\");\n } catch {\n console.log(\"No pairing token found.\");\n }\n\n if (opts.full) {\n try {\n if (fs.existsSync(identityPath)) {\n fs.unlinkSync(identityPath);\n console.log(\"Device identity deleted.\");\n }\n } catch (err) {\n console.error(\n `Failed to delete identity: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { VERSION, PROTOCOL_VERSION } from \"../index.js\";\n\nexport function registerVersionCommand(program: Command): void {\n program\n .command(\"info\")\n .description(\"Show version and protocol information\")\n .action(() => {\n console.log(`NodeClaw v${VERSION}`);\n console.log(`Protocol: ${PROTOCOL_VERSION}`);\n console.log(`Node.js: ${process.version}`);\n console.log(`Platform: ${process.platform}`);\n console.log(`Arch: ${process.arch}`);\n });\n}\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport {\n loadConfig,\n resolveBaseDir,\n resolveConfigPath,\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport { loadOrCreateIdentity, loadDeviceAuthToken } from \"../crypto/index.js\";\n\ntype Check = {\n name: string;\n status: \"ok\" | \"warn\" | \"fail\";\n detail: string;\n};\n\nfunction runChecks(): Check[] {\n const checks: Check[] = [];\n\n // Node.js version\n const nodeVersion = parseInt(process.version.slice(1), 10);\n checks.push({\n name: \"Node.js version\",\n status: nodeVersion >= 20 ? \"ok\" : \"fail\",\n detail: `${process.version} ${nodeVersion >= 20 ? \"(>= 20)\" : \"(requires >= 20)\"}`,\n });\n\n // Config directory\n const baseDir = resolveBaseDir();\n checks.push({\n name: \"Config directory\",\n status: fs.existsSync(baseDir) ? \"ok\" : \"warn\",\n detail: baseDir,\n });\n\n // Config file\n const configPath = resolveConfigPath();\n if (fs.existsSync(configPath)) {\n try {\n loadConfig();\n checks.push({ name: \"Config file\", status: \"ok\", detail: configPath });\n } catch {\n checks.push({\n name: \"Config file\",\n status: \"fail\",\n detail: `${configPath} (invalid)`,\n });\n }\n } else {\n checks.push({\n name: \"Config file\",\n status: \"warn\",\n detail: `${configPath} (not found, using defaults)`,\n });\n }\n\n // Device identity\n const identityPath = resolveIdentityPath();\n if (fs.existsSync(identityPath)) {\n try {\n const identity = loadOrCreateIdentity(identityPath);\n checks.push({\n name: \"Device identity\",\n status: \"ok\",\n detail: `${identity.deviceId.slice(0, 16)}...`,\n });\n } catch {\n checks.push({\n name: \"Device identity\",\n status: \"fail\",\n detail: `${identityPath} (corrupt)`,\n });\n }\n } else {\n checks.push({\n name: \"Device identity\",\n status: \"warn\",\n detail: \"Not initialized (will be created on first pair)\",\n });\n }\n\n // Pairing token\n const tokenStorePath = resolveTokenStorePath();\n try {\n const identity = loadOrCreateIdentity(identityPath);\n const token = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n \"node\",\n );\n checks.push({\n name: \"Pairing token\",\n status: token ? \"ok\" : \"warn\",\n detail: token ? \"Stored\" : \"Not paired\",\n });\n } catch {\n checks.push({\n name: \"Pairing token\",\n status: \"warn\",\n detail: \"Cannot check (no identity)\",\n });\n }\n\n // Gateway URL\n const config = loadConfig();\n checks.push({\n name: \"Gateway URL\",\n status: config.gateway.url ? \"ok\" : \"fail\",\n detail: config.gateway.url || \"(not configured)\",\n });\n\n // Workdir\n if (config.device.workdir) {\n const exists = fs.existsSync(config.device.workdir);\n checks.push({\n name: \"Workdir\",\n status: exists ? \"ok\" : \"fail\",\n detail: `${config.device.workdir} ${exists ? \"\" : \"(not found)\"}`,\n });\n } else {\n checks.push({\n name: \"Workdir\",\n status: \"warn\",\n detail: \"Not configured (exec allowed anywhere)\",\n });\n }\n\n return checks;\n}\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Check configuration, connectivity, and service status\")\n .action(() => {\n const checks = runChecks();\n let hasFailures = false;\n\n for (const check of checks) {\n const icon =\n check.status === \"ok\"\n ? \"[OK] \"\n : check.status === \"warn\"\n ? \"[WARN]\"\n : \"[FAIL]\";\n if (check.status === \"fail\") {\n hasFailures = true;\n }\n console.log(`${icon} ${check.name}: ${check.detail}`);\n }\n\n if (hasFailures) {\n process.exitCode = 1;\n }\n });\n}\n\n// For testing\nexport { runChecks };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport type { Command } from \"commander\";\nimport { generateSystemdUnit } from \"../service/systemd.js\";\nimport { generateLaunchdPlist } from \"../service/launchd.js\";\nimport { loadConfig } from \"../config/index.js\";\n\nexport function registerInstallServiceCommand(program: Command): void {\n program\n .command(\"install-service\")\n .description(\"Install systemd (Linux) or launchd (macOS) service\")\n .option(\"--dry-run\", \"Print the service file without writing\")\n .action((opts: { dryRun?: boolean }) => {\n const config = loadConfig();\n const platform = process.platform;\n const workdir = config.device.workdir || os.homedir();\n\n if (platform === \"linux\") {\n const unit = generateSystemdUnit({ workdir });\n if (opts.dryRun) {\n console.log(unit);\n return;\n }\n const unitPath = path.join(\n os.homedir(),\n \".config\",\n \"systemd\",\n \"user\",\n \"nodeclaw.service\",\n );\n fs.mkdirSync(path.dirname(unitPath), { recursive: true });\n fs.writeFileSync(unitPath, unit);\n console.log(`Service file written to ${unitPath}`);\n console.log(\"To enable: systemctl --user enable --now nodeclaw\");\n } else if (platform === \"darwin\") {\n const plist = generateLaunchdPlist({ workdir });\n if (opts.dryRun) {\n console.log(plist);\n return;\n }\n const plistPath = path.join(\n os.homedir(),\n \"Library\",\n \"LaunchAgents\",\n \"ai.nodeclaw.plist\",\n );\n fs.mkdirSync(path.dirname(plistPath), { recursive: true });\n fs.writeFileSync(plistPath, plist);\n console.log(`Plist written to ${plistPath}`);\n console.log(\"To load: launchctl load \" + plistPath);\n } else {\n console.error(`Service installation not supported on ${platform}`);\n process.exit(1);\n }\n });\n\n program\n .command(\"uninstall-service\")\n .description(\"Remove installed service\")\n .action(() => {\n const platform = process.platform;\n if (platform === \"linux\") {\n const unitPath = path.join(\n os.homedir(),\n \".config\",\n \"systemd\",\n \"user\",\n \"nodeclaw.service\",\n );\n if (fs.existsSync(unitPath)) {\n fs.unlinkSync(unitPath);\n console.log(\"Service file removed.\");\n console.log(\"Run: systemctl --user daemon-reload\");\n } else {\n console.log(\"Service file not found.\");\n }\n } else if (platform === \"darwin\") {\n const plistPath = path.join(\n os.homedir(),\n \"Library\",\n \"LaunchAgents\",\n \"ai.nodeclaw.plist\",\n );\n if (fs.existsSync(plistPath)) {\n fs.unlinkSync(plistPath);\n console.log(\"Plist removed.\");\n console.log(\"Run: launchctl unload \" + plistPath);\n } else {\n console.log(\"Plist not found.\");\n }\n } else {\n console.error(`Service uninstall not supported on ${platform}`);\n process.exit(1);\n }\n });\n}\n","import os from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\n\nexport type SystemdOptions = {\n execPath?: string;\n user?: string;\n workdir?: string;\n};\n\nfunction resolveNodeClawPath(): string {\n try {\n return execFileSync(\"which\", [\"nodeclaw\"], {\n encoding: \"utf8\",\n timeout: 5000,\n }).trim();\n } catch {\n return \"/usr/local/bin/nodeclaw\";\n }\n}\n\nexport function generateSystemdUnit(opts: SystemdOptions = {}): string {\n const execPath = opts.execPath || resolveNodeClawPath();\n const user = opts.user || os.userInfo().username;\n const workdir = opts.workdir || os.homedir();\n\n return `[Unit]\nDescription=NodeClaw - OpenClaw Node Client\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${execPath} start\nRestart=always\nRestartSec=5\nUser=${user}\nWorkingDirectory=${workdir}\nEnvironment=NODE_ENV=production\n\n[Install]\nWantedBy=multi-user.target\n`;\n}\n","import os from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\n\nexport type LaunchdOptions = {\n execPath?: string;\n workdir?: string;\n label?: string;\n};\n\nfunction resolveNodeClawPath(): string {\n try {\n return execFileSync(\"which\", [\"nodeclaw\"], {\n encoding: \"utf8\",\n timeout: 5000,\n }).trim();\n } catch {\n return \"/usr/local/bin/nodeclaw\";\n }\n}\n\nexport function generateLaunchdPlist(opts: LaunchdOptions = {}): string {\n const execPath = opts.execPath || resolveNodeClawPath();\n const workdir = opts.workdir || os.homedir();\n const label = opts.label || \"ai.nodeclaw\";\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${label}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${execPath}</string>\n <string>start</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>${workdir}</string>\n <key>StandardOutPath</key>\n <string>/tmp/nodeclaw.stdout.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/nodeclaw.stderr.log</string>\n</dict>\n</plist>\n`;\n}\n"],"mappings":"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","names":["os","fs","path","path","fs","path","fs","PROTOCOL_VERSION","PROTOCOL_VERSION","os","program","os","os","randomUUID","path","path","randomUUID","path","crypto","fs","os","fs","crypto","fs","path","path","crypto","fs","program","program","fs","program","fs","program","fs","fs","program","fs","path","os","os","execFileSync","os","execFileSync","resolveNodeClawPath","program","os","path","fs"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/pairing/pair.ts","../src/crypto/identity.ts","../src/crypto/device-auth.ts","../src/crypto/token-store.ts","../src/config/schema.ts","../src/config/paths.ts","../src/config/loader.ts","../src/client/gateway-client.ts","../src/protocol/constants.ts","../src/protocol/guards.ts","../src/cli/pair.ts","../src/runtime/router.ts","../src/runtime/node-runtime.ts","../src/handlers/system-run.ts","../src/handlers/node-events.ts","../src/handlers/system-run-prepare.ts","../src/handlers/system-info.ts","../src/handlers/system-which.ts","../src/handlers/exec-approvals.ts","../src/handlers/index.ts","../src/cli/start.ts","../src/cli/status.ts","../src/cli/unpair.ts","../src/cli/version.ts","../src/cli/doctor.ts","../src/cli/install-service.ts","../src/service/systemd.ts","../src/service/launchd.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { VERSION } from \"./index.js\";\nimport { registerPairCommand } from \"./cli/pair.js\";\nimport { registerStartCommand } from \"./cli/start.js\";\nimport { registerStatusCommand } from \"./cli/status.js\";\nimport { registerUnpairCommand } from \"./cli/unpair.js\";\nimport { registerVersionCommand } from \"./cli/version.js\";\nimport { registerDoctorCommand } from \"./cli/doctor.js\";\nimport { registerInstallServiceCommand } from \"./cli/install-service.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"nodeclaw\")\n .description(\"Minimal OpenClaw node protocol client\")\n .version(VERSION);\n\nregisterPairCommand(program);\nregisterStartCommand(program);\nregisterStatusCommand(program);\nregisterUnpairCommand(program);\nregisterVersionCommand(program);\nregisterDoctorCommand(program);\nregisterInstallServiceCommand(program);\n\nprogram.parse();\n","import os from \"node:os\";\nimport {\n loadOrCreateIdentity,\n storeDeviceAuthToken,\n loadDeviceAuthToken,\n} from \"../crypto/index.js\";\nimport { resolveIdentityPath, resolveTokenStorePath, loadConfig, saveConfig } from \"../config/index.js\";\nimport { GatewayClient } from \"../client/index.js\";\nimport { VERSION } from \"../index.js\";\nimport type { HelloOk, NodePairRequestParams } from \"../protocol/index.js\";\n\nexport type PairOptions = {\n gatewayUrl: string;\n deviceName?: string;\n /** Gateway auth token (required when the gateway has auth.mode=token). */\n gatewayToken?: string;\n env?: NodeJS.ProcessEnv;\n};\n\nexport type PairResult = {\n deviceId: string;\n paired: boolean;\n message: string;\n};\n\nexport async function pairWithGateway(opts: PairOptions): Promise<PairResult> {\n const identityPath = resolveIdentityPath(opts.env);\n const tokenStorePath = resolveTokenStorePath(opts.env);\n const identity = loadOrCreateIdentity(identityPath);\n const role = \"node\";\n\n // Check if already paired\n const existingToken = loadDeviceAuthToken(tokenStorePath, identity.deviceId, role);\n if (existingToken) {\n return {\n deviceId: identity.deviceId,\n paired: true,\n message: \"Already paired with gateway.\",\n };\n }\n\n return new Promise<PairResult>((resolve, reject) => {\n let pairRequestSent = false;\n let timeoutTimer: NodeJS.Timeout | null = null;\n\n const client = new GatewayClient({\n url: opts.gatewayUrl,\n token: opts.gatewayToken,\n deviceIdentity: identity,\n role,\n scopes: [\"node.invoke\"],\n caps: [\"system\"],\n commands: [\"system.run\", \"system.run.prepare\", \"system.which\"],\n clientDisplayName: opts.deviceName || os.hostname(),\n platform: process.platform,\n mode: \"node\",\n onHelloOk: (hello: HelloOk) => {\n // Connected successfully — if we get a deviceToken, pairing is done\n if (hello.auth?.deviceToken) {\n storeDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n role,\n hello.auth.deviceToken,\n hello.auth.scopes,\n );\n // Persist gateway URL and token to config so `nodeclaw start` works\n const config = loadConfig(opts.env);\n config.gateway.url = opts.gatewayUrl;\n if (opts.gatewayToken) {\n config.gateway.token = opts.gatewayToken;\n }\n saveConfig(config, opts.env);\n cleanup();\n resolve({\n deviceId: identity.deviceId,\n paired: true,\n message: \"Paired successfully!\",\n });\n return;\n }\n\n // No device token — send pair request\n if (!pairRequestSent) {\n pairRequestSent = true;\n const params: NodePairRequestParams = {\n nodeId: identity.deviceId,\n displayName: opts.deviceName || os.hostname(),\n platform: process.platform,\n version: VERSION,\n caps: [\"system\"],\n commands: [\"system.run\", \"system.run.prepare\", \"system.which\"],\n };\n void client\n .request(\"node.pair.request\", params)\n .then(() => {\n console.log(\n 'Pairing request sent. Waiting for approval on the gateway...\\n' +\n `Run \"openclaw nodes approve\" on your gateway to approve this device.`,\n );\n })\n .catch((err) => {\n cleanup();\n reject(new Error(`Pair request failed: ${String(err)}`));\n });\n }\n },\n onConnectError: (err) => {\n // If it's a pairing-required error, that's expected during pairing flow\n if (!pairRequestSent) {\n // Will reconnect and try again\n }\n },\n onClose: () => {\n // reconnect will be handled by the client\n },\n });\n\n const cleanup = () => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n client.stop();\n };\n\n // Timeout after 5 minutes\n timeoutTimer = setTimeout(() => {\n cleanup();\n reject(new Error(\"Pairing timed out after 5 minutes. Try again.\"));\n }, 5 * 60 * 1000);\n\n client.start();\n });\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type DeviceIdentity = {\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n};\n\ntype StoredIdentity = {\n version: 1;\n deviceId: string;\n publicKeyPem: string;\n privateKeyPem: string;\n createdAtMs: number;\n};\n\nconst ED25519_SPKI_PREFIX = Buffer.from(\"302a300506032b6570032100\", \"hex\");\n\nexport function base64UrlEncode(buf: Buffer): string {\n return buf\n .toString(\"base64\")\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(/=+$/g, \"\");\n}\n\nexport function base64UrlDecode(input: string): Buffer {\n const normalized = input.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n return Buffer.from(padded, \"base64\");\n}\n\nfunction derivePublicKeyRaw(publicKeyPem: string): Buffer {\n const key = crypto.createPublicKey(publicKeyPem);\n const spki = key.export({ type: \"spki\", format: \"der\" }) as Buffer;\n if (\n spki.length === ED25519_SPKI_PREFIX.length + 32 &&\n spki.subarray(0, ED25519_SPKI_PREFIX.length).equals(ED25519_SPKI_PREFIX)\n ) {\n return spki.subarray(ED25519_SPKI_PREFIX.length);\n }\n return spki;\n}\n\nfunction fingerprintPublicKey(publicKeyPem: string): string {\n const raw = derivePublicKeyRaw(publicKeyPem);\n return crypto.createHash(\"sha256\").update(raw).digest(\"hex\");\n}\n\nexport function generateIdentity(): DeviceIdentity {\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ed25519\");\n const publicKeyPem = publicKey.export({ type: \"spki\", format: \"pem\" }).toString();\n const privateKeyPem = privateKey.export({ type: \"pkcs8\", format: \"pem\" }).toString();\n const deviceId = fingerprintPublicKey(publicKeyPem);\n return { deviceId, publicKeyPem, privateKeyPem };\n}\n\nexport function loadOrCreateIdentity(filePath: string): DeviceIdentity {\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as StoredIdentity;\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKeyPem === \"string\" &&\n typeof parsed.privateKeyPem === \"string\"\n ) {\n const derivedId = fingerprintPublicKey(parsed.publicKeyPem);\n if (derivedId && derivedId !== parsed.deviceId) {\n const updated: StoredIdentity = { ...parsed, deviceId: derivedId };\n fs.writeFileSync(filePath, `${JSON.stringify(updated, null, 2)}\\n`, { mode: 0o600 });\n return { deviceId: derivedId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };\n }\n return { deviceId: parsed.deviceId, publicKeyPem: parsed.publicKeyPem, privateKeyPem: parsed.privateKeyPem };\n }\n }\n } catch {\n // fall through to regenerate\n }\n\n const identity = generateIdentity();\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const stored: StoredIdentity = {\n version: 1,\n deviceId: identity.deviceId,\n publicKeyPem: identity.publicKeyPem,\n privateKeyPem: identity.privateKeyPem,\n createdAtMs: Date.now(),\n };\n fs.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}\\n`, { mode: 0o600 });\n return identity;\n}\n\nexport function signDevicePayload(privateKeyPem: string, payload: string): string {\n const key = crypto.createPrivateKey(privateKeyPem);\n const sig = crypto.sign(null, Buffer.from(payload, \"utf8\"), key);\n return base64UrlEncode(sig);\n}\n\nexport function verifyDeviceSignature(\n publicKeyPem: string,\n payload: string,\n signatureBase64Url: string,\n): boolean {\n try {\n const key = crypto.createPublicKey(publicKeyPem);\n const sig = base64UrlDecode(signatureBase64Url);\n return crypto.verify(null, Buffer.from(payload, \"utf8\"), key, sig);\n } catch {\n return false;\n }\n}\n\nexport function publicKeyRawBase64Url(publicKeyPem: string): string {\n return base64UrlEncode(derivePublicKeyRaw(publicKeyPem));\n}\n\nexport function deriveDeviceId(publicKeyPem: string): string {\n return fingerprintPublicKey(publicKeyPem);\n}\n","export type DeviceAuthPayloadV3Params = {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token?: string | null;\n nonce: string;\n platform?: string | null;\n deviceFamily?: string | null;\n};\n\nfunction normalizeMetadataForAuth(value?: string | null): string {\n if (typeof value !== \"string\") {\n return \"\";\n }\n const trimmed = value.trim();\n if (!trimmed) {\n return \"\";\n }\n // ASCII-lowercase only (matches OpenClaw's cross-runtime normalization)\n return trimmed.replace(/[A-Z]/g, (ch) =>\n String.fromCharCode(ch.charCodeAt(0) + 32),\n );\n}\n\nexport function buildDeviceAuthPayloadV3(\n params: DeviceAuthPayloadV3Params,\n): string {\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n const platform = normalizeMetadataForAuth(params.platform);\n const deviceFamily = normalizeMetadataForAuth(params.deviceFamily);\n return [\n \"v3\",\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n params.nonce,\n platform,\n deviceFamily,\n ].join(\"|\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type DeviceAuthEntry = {\n token: string;\n scopes: string[];\n issuedAtMs: number;\n};\n\ntype DeviceAuthStore = {\n version: 1;\n deviceId: string;\n tokens: Record<string, DeviceAuthEntry>;\n};\n\nfunction readStore(filePath: string): DeviceAuthStore | null {\n try {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as DeviceAuthStore;\n if (\n parsed?.version !== 1 ||\n typeof parsed.deviceId !== \"string\" ||\n !parsed.tokens ||\n typeof parsed.tokens !== \"object\"\n ) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction writeStore(filePath: string, store: DeviceAuthStore): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}\\n`, {\n mode: 0o600,\n });\n}\n\nexport function loadDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n): DeviceAuthEntry | null {\n const store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n return null;\n }\n const entry = store.tokens[role];\n if (!entry || typeof entry.token !== \"string\") {\n return null;\n }\n return entry;\n}\n\nexport function storeDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n token: string,\n scopes: string[] = [],\n): DeviceAuthEntry {\n let store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n store = { version: 1, deviceId, tokens: {} };\n }\n const entry: DeviceAuthEntry = {\n token,\n scopes,\n issuedAtMs: Date.now(),\n };\n store.tokens[role] = entry;\n writeStore(filePath, store);\n return entry;\n}\n\nexport function clearDeviceAuthToken(\n filePath: string,\n deviceId: string,\n role: string,\n): void {\n const store = readStore(filePath);\n if (!store || store.deviceId !== deviceId) {\n return;\n }\n delete store.tokens[role];\n writeStore(filePath, store);\n}\n","import { z } from \"zod\";\n\nexport const GatewayConfigSchema = z.object({\n url: z.string().url().default(\"ws://127.0.0.1:18789\"),\n tlsVerify: z.boolean().default(true),\n /** Gateway auth token — required when the gateway has auth.mode=token. */\n token: z.string().optional(),\n});\n\nexport const DeviceConfigSchema = z.object({\n name: z.string().default(\"\"),\n workdir: z.string().default(\"\"),\n});\n\nexport const ExecConfigSchema = z.object({\n blockedCommands: z.array(z.string()).default([]),\n timeoutMs: z.number().int().min(0).default(60_000),\n maxConcurrent: z.number().int().min(1).default(3),\n});\n\nexport const LogConfigSchema = z.object({\n level: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n path: z.string().optional(),\n});\n\nexport const NodeClawConfigSchema = z.object({\n gateway: GatewayConfigSchema.default({}),\n device: DeviceConfigSchema.default({}),\n exec: ExecConfigSchema.default({}),\n log: LogConfigSchema.default({}),\n});\n\nexport type NodeClawConfig = z.infer<typeof NodeClawConfigSchema>;\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\nexport type DeviceConfig = z.infer<typeof DeviceConfigSchema>;\nexport type ExecConfig = z.infer<typeof ExecConfigSchema>;\nexport type LogConfig = z.infer<typeof LogConfigSchema>;\n","import path from \"node:path\";\nimport os from \"node:os\";\n\nexport function resolveBaseDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.NODECLAW_HOME) {\n return env.NODECLAW_HOME;\n }\n return path.join(os.homedir(), \".nodeclaw\");\n}\n\nexport function resolveConfigPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"config.json\");\n}\n\nexport function resolveIdentityPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"identity\", \"device.json\");\n}\n\nexport function resolveTokenStorePath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"identity\", \"device-auth.json\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { NodeClawConfigSchema, type NodeClawConfig } from \"./schema.js\";\nimport { resolveBaseDir, resolveConfigPath } from \"./paths.js\";\n\nexport function ensureConfigDir(env?: NodeJS.ProcessEnv): void {\n const baseDir = resolveBaseDir(env);\n fs.mkdirSync(baseDir, { recursive: true });\n}\n\nexport function loadConfig(env?: NodeJS.ProcessEnv): NodeClawConfig {\n const configPath = resolveConfigPath(env);\n try {\n if (fs.existsSync(configPath)) {\n const raw = fs.readFileSync(configPath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n return NodeClawConfigSchema.parse(parsed);\n }\n } catch {\n // Fall through to defaults\n }\n return NodeClawConfigSchema.parse({});\n}\n\nexport function saveConfig(\n config: NodeClawConfig,\n env?: NodeJS.ProcessEnv,\n): void {\n const configPath = resolveConfigPath(env);\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, {\n mode: 0o600,\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport { WebSocket } from \"ws\";\nimport {\n signDevicePayload,\n publicKeyRawBase64Url,\n buildDeviceAuthPayloadV3,\n} from \"../crypto/index.js\";\nimport {\n PROTOCOL_VERSION,\n CLIENT_NAME,\n CLIENT_MODES,\n isEventFrame,\n isResponseFrame,\n type ConnectParams,\n type HelloOk,\n type EventFrame,\n} from \"../protocol/index.js\";\nimport { VERSION } from \"../index.js\";\nimport type { GatewayClientOptions } from \"./types.js\";\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (err: unknown) => void;\n timeout: NodeJS.Timeout | null;\n};\n\nconst DEFAULT_CONNECT_TIMEOUT_MS = 2_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\nconst MAX_BACKOFF_MS = 30_000;\nconst FORCE_STOP_GRACE_MS = 250;\n\nexport type ConnectionHealth = {\n connected: boolean;\n connectedAtMs: number | null;\n lastTickMs: number | null;\n reconnectCount: number;\n tickIntervalMs: number;\n};\n\nexport class GatewayClient {\n private ws: WebSocket | null = null;\n private opts: GatewayClientOptions;\n private pending = new Map<string, Pending>();\n private backoffMs = 1000;\n private closed = false;\n private connectNonce: string | null = null;\n private connectSent = false;\n private connectTimer: NodeJS.Timeout | null = null;\n private lastTick: number | null = null;\n private tickIntervalMs = 30_000;\n private tickTimer: NodeJS.Timeout | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private readonly requestTimeoutMs: number;\n private connectedAtMs: number | null = null;\n private reconnectCount = 0;\n\n constructor(opts: GatewayClientOptions) {\n this.opts = opts;\n this.requestTimeoutMs =\n typeof opts.requestTimeoutMs === \"number\"\n ? Math.max(1, opts.requestTimeoutMs)\n : DEFAULT_REQUEST_TIMEOUT_MS;\n }\n\n start(): void {\n if (this.closed) {\n return;\n }\n const url = this.opts.url;\n\n const ws = new WebSocket(url, {\n maxPayload: 25 * 1024 * 1024,\n rejectUnauthorized: this.opts.tlsVerify !== false,\n });\n this.ws = ws;\n\n ws.on(\"open\", () => {\n this.queueConnect();\n });\n ws.on(\"message\", (data) => {\n const raw =\n typeof data === \"string\"\n ? data\n : Buffer.isBuffer(data)\n ? data.toString(\"utf8\")\n : Buffer.from(data as ArrayBuffer).toString(\"utf8\");\n this.handleMessage(raw);\n });\n ws.on(\"close\", (code, reason) => {\n const reasonText =\n typeof reason === \"string\"\n ? reason\n : Buffer.isBuffer(reason)\n ? reason.toString(\"utf8\")\n : \"\";\n if (this.ws === ws) {\n this.ws = null;\n }\n this.flushPendingErrors(\n new Error(`gateway closed (${code}): ${reasonText}`),\n );\n this.scheduleReconnect();\n this.opts.onClose?.(code, reasonText);\n });\n ws.on(\"error\", (err) => {\n if (!this.connectSent) {\n this.opts.onConnectError?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n });\n }\n\n stop(): void {\n this.closed = true;\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n this.tickTimer = null;\n }\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n const ws = this.ws;\n this.ws = null;\n if (ws) {\n ws.close();\n setTimeout(() => {\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n }, FORCE_STOP_GRACE_MS).unref();\n }\n this.flushPendingErrors(new Error(\"gateway client stopped\"));\n }\n\n async stopAndWait(timeoutMs = 1000): Promise<void> {\n this.stop();\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, Math.min(timeoutMs, FORCE_STOP_GRACE_MS + 100));\n timer.unref();\n });\n }\n\n async request<T = unknown>(\n method: string,\n params?: unknown,\n opts?: { timeoutMs?: number },\n ): Promise<T> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error(\"gateway not connected\");\n }\n const id = randomUUID();\n const frame = { type: \"req\" as const, id, method, params };\n this.ws.send(JSON.stringify(frame));\n\n const timeoutMs = opts?.timeoutMs ?? this.requestTimeoutMs;\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`request ${method} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeout,\n });\n });\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.connectSent;\n }\n\n getHealth(): ConnectionHealth {\n return {\n connected: this.isConnected(),\n connectedAtMs: this.connectedAtMs,\n lastTickMs: this.lastTick,\n reconnectCount: this.reconnectCount,\n tickIntervalMs: this.tickIntervalMs,\n };\n }\n\n private queueConnect(): void {\n this.connectNonce = null;\n this.connectSent = false;\n const connectTimeoutMs = this.opts.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n }\n this.connectTimer = setTimeout(() => {\n if (this.connectSent || this.ws?.readyState !== WebSocket.OPEN) {\n return;\n }\n this.opts.onConnectError?.(new Error(\"gateway connect challenge timeout\"));\n this.ws?.close(1008, \"connect challenge timeout\");\n }, connectTimeoutMs);\n }\n\n private sendConnect(): void {\n if (this.connectSent) {\n return;\n }\n const nonce = this.connectNonce?.trim() ?? \"\";\n if (!nonce) {\n this.opts.onConnectError?.(new Error(\"gateway connect challenge missing nonce\"));\n this.ws?.close(1008, \"connect challenge missing nonce\");\n return;\n }\n this.connectSent = true;\n if (this.connectTimer) {\n clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n\n const role = this.opts.role ?? \"node\";\n const scopes = this.opts.scopes ?? [\"node.invoke\"];\n const platform = this.opts.platform ?? process.platform;\n const signedAtMs = Date.now();\n\n // Build device auth\n const device = (() => {\n if (!this.opts.deviceIdentity) {\n return undefined;\n }\n const payload = buildDeviceAuthPayloadV3({\n deviceId: this.opts.deviceIdentity.deviceId,\n clientId: this.opts.clientName ?? CLIENT_NAME,\n clientMode: this.opts.mode ?? CLIENT_MODES.NODE,\n role,\n scopes,\n signedAtMs,\n token: this.opts.token ?? this.opts.deviceToken ?? null,\n nonce,\n platform,\n deviceFamily: this.opts.deviceFamily,\n });\n const signature = signDevicePayload(\n this.opts.deviceIdentity.privateKeyPem,\n payload,\n );\n return {\n id: this.opts.deviceIdentity.deviceId,\n publicKey: publicKeyRawBase64Url(this.opts.deviceIdentity.publicKeyPem),\n signature,\n signedAt: signedAtMs,\n nonce,\n };\n })();\n\n const auth =\n this.opts.token || this.opts.deviceToken\n ? {\n token: this.opts.token,\n deviceToken: this.opts.deviceToken,\n }\n : undefined;\n\n const params: ConnectParams = {\n minProtocol: PROTOCOL_VERSION,\n maxProtocol: PROTOCOL_VERSION,\n client: {\n id: this.opts.clientName ?? CLIENT_NAME,\n displayName: this.opts.clientDisplayName,\n version: this.opts.clientVersion ?? VERSION,\n platform,\n deviceFamily: this.opts.deviceFamily,\n mode: this.opts.mode ?? CLIENT_MODES.NODE,\n instanceId: this.opts.instanceId,\n },\n caps: this.opts.caps ?? [],\n commands: this.opts.commands,\n permissions: this.opts.permissions,\n pathEnv: this.opts.pathEnv,\n auth,\n role,\n scopes,\n device,\n };\n\n void this.request<HelloOk>(\"connect\", params)\n .then((helloOk) => {\n this.backoffMs = 1000;\n this.connectedAtMs = Date.now();\n this.tickIntervalMs =\n typeof helloOk.policy?.tickIntervalMs === \"number\"\n ? helloOk.policy.tickIntervalMs\n : 30_000;\n this.lastTick = Date.now();\n this.startTickWatch();\n this.opts.onHelloOk?.(helloOk);\n })\n .catch((err) => {\n this.opts.onConnectError?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n this.ws?.close(1008, \"connect failed\");\n });\n }\n\n private handleMessage(raw: string): void {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return;\n }\n\n if (isEventFrame(parsed)) {\n this.lastTick = Date.now();\n if (parsed.event === \"connect.challenge\") {\n const payload = parsed.payload as { nonce?: unknown } | undefined;\n const nonce =\n payload && typeof payload.nonce === \"string\" ? payload.nonce : null;\n if (!nonce || nonce.trim().length === 0) {\n this.opts.onConnectError?.(\n new Error(\"gateway connect challenge missing nonce\"),\n );\n this.ws?.close(1008, \"connect challenge missing nonce\");\n return;\n }\n this.connectNonce = nonce.trim();\n this.sendConnect();\n return;\n }\n if (parsed.event === \"tick\") {\n this.lastTick = Date.now();\n }\n this.opts.onEvent?.(parsed);\n return;\n }\n\n if (isResponseFrame(parsed)) {\n this.lastTick = Date.now();\n const pending = this.pending.get(parsed.id);\n if (!pending) {\n return;\n }\n this.pending.delete(parsed.id);\n if (pending.timeout) {\n clearTimeout(pending.timeout);\n }\n if (parsed.ok) {\n pending.resolve(parsed.payload);\n } else {\n pending.reject(\n new Error(\n parsed.error?.message ?? `request failed: ${parsed.error?.code ?? \"unknown\"}`,\n ),\n );\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.closed) {\n return;\n }\n this.connectedAtMs = null;\n this.reconnectCount++;\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n this.tickTimer = null;\n }\n const delay = this.backoffMs;\n this.backoffMs = Math.min(this.backoffMs * 2, MAX_BACKOFF_MS);\n this.reconnectTimer = setTimeout(() => this.start(), delay);\n this.reconnectTimer.unref();\n }\n\n private flushPendingErrors(err: Error): void {\n for (const [, p] of this.pending) {\n if (p.timeout) {\n clearTimeout(p.timeout);\n }\n p.reject(err);\n }\n this.pending.clear();\n }\n\n private startTickWatch(): void {\n if (this.tickTimer) {\n clearInterval(this.tickTimer);\n }\n const interval = Math.max(this.tickIntervalMs, 1000);\n this.tickTimer = setInterval(() => {\n if (this.closed || !this.lastTick) {\n return;\n }\n const gap = Date.now() - this.lastTick;\n if (gap > this.tickIntervalMs * 2) {\n this.ws?.close(4000, \"tick timeout\");\n }\n }, interval);\n this.tickTimer.unref();\n }\n}\n","export const PROTOCOL_VERSION = 3;\n\n// Must match the gateway's GATEWAY_CLIENT_IDS.NODE_HOST value.\nexport const CLIENT_NAME = \"node-host\";\n\nexport const CLIENT_MODES = {\n NODE: \"node\",\n BACKEND: \"backend\",\n PROBE: \"probe\",\n} as const;\n\nexport type ClientMode = (typeof CLIENT_MODES)[keyof typeof CLIENT_MODES];\n","import type { EventFrame, ResponseFrame, RequestFrame } from \"./frames.js\";\nimport type { NodeInvokeRequestPayload } from \"./nodes.js\";\n\nexport function isEventFrame(msg: unknown): msg is EventFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"event\" &&\n typeof (msg as Record<string, unknown>).event === \"string\"\n );\n}\n\nexport function isResponseFrame(msg: unknown): msg is ResponseFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"res\" &&\n typeof (msg as Record<string, unknown>).id === \"string\" &&\n typeof (msg as Record<string, unknown>).ok === \"boolean\"\n );\n}\n\nexport function isRequestFrame(msg: unknown): msg is RequestFrame {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as Record<string, unknown>).type === \"req\" &&\n typeof (msg as Record<string, unknown>).id === \"string\" &&\n typeof (msg as Record<string, unknown>).method === \"string\"\n );\n}\n\nexport function coerceNodeInvokePayload(\n payload: unknown,\n): NodeInvokeRequestPayload | null {\n if (typeof payload !== \"object\" || payload === null) {\n return null;\n }\n const obj = payload as Record<string, unknown>;\n if (typeof obj.id !== \"string\" || typeof obj.command !== \"string\") {\n return null;\n }\n return {\n id: obj.id,\n nodeId: typeof obj.nodeId === \"string\" ? obj.nodeId : \"\",\n command: obj.command,\n paramsJSON:\n typeof obj.paramsJSON === \"string\" ? obj.paramsJSON : undefined,\n timeoutMs:\n typeof obj.timeoutMs === \"number\" ? obj.timeoutMs : undefined,\n idempotencyKey:\n typeof obj.idempotencyKey === \"string\"\n ? obj.idempotencyKey\n : undefined,\n };\n}\n","import type { Command } from \"commander\";\nimport { pairWithGateway } from \"../pairing/index.js\";\n\nexport function registerPairCommand(program: Command): void {\n program\n .command(\"pair\")\n .description(\"Pair this device with an OpenClaw gateway\")\n .argument(\"<gateway-url>\", \"WebSocket URL of the gateway (e.g. wss://host:18789)\")\n .option(\"-n, --name <name>\", \"Display name for this device\")\n .option(\"-t, --token <token>\", \"Gateway auth token (required when gateway has auth.mode=token)\")\n .action(async (gatewayUrl: string, opts: { name?: string; token?: string }) => {\n try {\n const result = await pairWithGateway({\n gatewayUrl,\n deviceName: opts.name,\n gatewayToken: opts.token,\n });\n console.log(result.message);\n console.log(`Device ID: ${result.deviceId}`);\n process.exit(0);\n } catch (err) {\n console.error(`Pairing failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n });\n}\n","import type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type InvokeHandler = (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n) => Promise<void>;\n\nexport class CommandRouter {\n private handlers = new Map<string, InvokeHandler>();\n\n register(command: string, handler: InvokeHandler): void {\n this.handlers.set(command, handler);\n }\n\n async dispatch(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> {\n const handler = this.handlers.get(payload.command);\n if (handler) {\n await handler(payload, client);\n return;\n }\n\n // Unknown command — send error result\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"UNKNOWN_COMMAND\",\n message: `Unknown command: ${payload.command}`,\n },\n };\n await client.request(\"node.invoke.result\", result);\n }\n}\n","import os from \"node:os\";\nimport {\n loadOrCreateIdentity,\n loadDeviceAuthToken,\n} from \"../crypto/index.js\";\nimport {\n loadConfig,\n resolveIdentityPath,\n resolveTokenStorePath,\n type NodeClawConfig,\n} from \"../config/index.js\";\nimport { GatewayClient } from \"../client/index.js\";\nimport { coerceNodeInvokePayload, type EventFrame } from \"../protocol/index.js\";\nimport { VERSION } from \"../index.js\";\nimport { CommandRouter } from \"./router.js\";\n\nexport type NodeRuntimeOptions = {\n config?: NodeClawConfig;\n env?: NodeJS.ProcessEnv;\n router?: CommandRouter;\n};\n\nexport async function startNode(opts: NodeRuntimeOptions = {}): Promise<{\n client: GatewayClient;\n router: CommandRouter;\n stop: () => void;\n}> {\n const config = opts.config ?? loadConfig(opts.env);\n const identityPath = resolveIdentityPath(opts.env);\n const tokenStorePath = resolveTokenStorePath(opts.env);\n const identity = loadOrCreateIdentity(identityPath);\n const role = \"node\";\n\n const storedAuth = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n role,\n );\n if (!storedAuth) {\n throw new Error(\n \"Not paired with a gateway. Run 'nodeclaw pair <gateway-url>' first.\",\n );\n }\n\n const router = opts.router ?? new CommandRouter();\n\n const client = new GatewayClient({\n url: config.gateway.url,\n token: config.gateway.token,\n deviceIdentity: identity,\n deviceToken: storedAuth.token,\n role,\n scopes: [\"node.invoke\"],\n caps: [\"system\"],\n commands: [\n \"system.run\",\n \"system.run.prepare\",\n \"system.which\",\n \"system.execApprovals.get\",\n \"system.execApprovals.set\",\n ],\n clientDisplayName: config.device.name || os.hostname(),\n clientVersion: VERSION,\n platform: process.platform,\n mode: \"node\",\n tlsVerify: config.gateway.tlsVerify,\n onHelloOk: (hello) => {\n console.log(\n `Connected to gateway (protocol ${hello.protocol ?? \"?\"}, connId: ${hello.server?.connId ?? \"?\"})`,\n );\n },\n onEvent: (evt: EventFrame) => {\n if (evt.event === \"node.invoke.request\") {\n const invokePayload = coerceNodeInvokePayload(evt.payload);\n if (invokePayload) {\n void router.dispatch(invokePayload, client).catch((err) => {\n console.error(\n `Handler error for ${invokePayload.command}: ${String(err)}`,\n );\n });\n }\n }\n },\n onConnectError: (err) => {\n console.error(`Connection error: ${err.message}`);\n },\n onClose: (code, reason) => {\n if (code !== 1000) {\n console.log(`Disconnected (${code}): ${reason || \"unknown\"}`);\n }\n },\n });\n\n client.start();\n\n return {\n client,\n router,\n stop: () => client.stop(),\n };\n}\n","import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\nimport type { ExecConfig } from \"../config/index.js\";\nimport { emitExecStarted, emitExecFinished, emitExecDenied } from \"./node-events.js\";\n\nconst OUTPUT_CAP = 200_000; // 200KB max output capture\n\ntype SystemRunParams = {\n command: string[];\n cwd?: string;\n env?: Record<string, string>;\n timeoutMs?: number;\n sessionKey?: string;\n runId?: string;\n suppressNotifyOnExit?: boolean;\n};\n\ntype RunResult = {\n exitCode: number | null;\n stdout: string;\n stderr: string;\n timedOut: boolean;\n truncated: boolean;\n};\n\nlet activeCount = 0;\n\nfunction parseRunParams(paramsJSON?: string | null): SystemRunParams | null {\n if (!paramsJSON) {\n return null;\n }\n try {\n const parsed = JSON.parse(paramsJSON) as unknown;\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as Record<string, unknown>;\n let command: string[] | null = null;\n if (Array.isArray(obj.command)) {\n command = (obj.command as string[]).filter((s) => typeof s === \"string\");\n } else if (typeof obj.command === \"string\" && obj.command.trim()) {\n command = [obj.command];\n } else if (typeof obj.rawCommand === \"string\" && obj.rawCommand.trim()) {\n command = [\"sh\", \"-c\", obj.rawCommand as string];\n }\n if (!command || command.length === 0) {\n return null;\n }\n return {\n command,\n cwd: typeof obj.cwd === \"string\" ? obj.cwd : undefined,\n env:\n typeof obj.env === \"object\" && obj.env !== null\n ? (obj.env as Record<string, string>)\n : undefined,\n timeoutMs:\n typeof obj.timeoutMs === \"number\" ? obj.timeoutMs : undefined,\n sessionKey:\n typeof obj.sessionKey === \"string\" ? obj.sessionKey : undefined,\n runId: typeof obj.runId === \"string\" ? obj.runId : undefined,\n suppressNotifyOnExit:\n typeof obj.suppressNotifyOnExit === \"boolean\"\n ? obj.suppressNotifyOnExit\n : undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction isPathWithinWorkdir(testPath: string, workdir: string): boolean {\n if (!workdir) {\n return true; // no workdir restriction\n }\n const resolved = path.resolve(testPath);\n const resolvedWorkdir = path.resolve(workdir);\n return resolved === resolvedWorkdir || resolved.startsWith(resolvedWorkdir + path.sep);\n}\n\nfunction isBlockedCommand(\n command: string[],\n blockedCommands: string[],\n): boolean {\n if (blockedCommands.length === 0) {\n return false;\n }\n const cmdStr = command.join(\" \");\n return blockedCommands.some(\n (blocked) => cmdStr === blocked || cmdStr.startsWith(blocked + \" \"),\n );\n}\n\nfunction runCommand(\n params: SystemRunParams,\n execConfig: ExecConfig,\n): Promise<RunResult> {\n return new Promise<RunResult>((resolve) => {\n const timeoutMs = params.timeoutMs ?? execConfig.timeoutMs;\n const [bin, ...args] = params.command;\n const cwd = params.cwd || undefined;\n const env = params.env\n ? { ...process.env, ...params.env }\n : undefined;\n\n const proc = spawn(bin, args, {\n cwd,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let truncated = false;\n let timedOut = false;\n let totalOutput = 0;\n\n const appendOutput = (\n target: \"stdout\" | \"stderr\",\n chunk: Buffer,\n ): void => {\n const remaining = OUTPUT_CAP - totalOutput;\n if (remaining <= 0) {\n truncated = true;\n return;\n }\n const text = chunk.toString(\"utf8\");\n const toAppend = text.length > remaining ? text.slice(0, remaining) : text;\n totalOutput += toAppend.length;\n if (target === \"stdout\") {\n stdout += toAppend;\n } else {\n stderr += toAppend;\n }\n if (totalOutput >= OUTPUT_CAP) {\n truncated = true;\n }\n };\n\n proc.stdout.on(\"data\", (chunk: Buffer) => appendOutput(\"stdout\", chunk));\n proc.stderr.on(\"data\", (chunk: Buffer) => appendOutput(\"stderr\", chunk));\n\n let timeoutTimer: NodeJS.Timeout | null = null;\n if (timeoutMs > 0) {\n timeoutTimer = setTimeout(() => {\n timedOut = true;\n try {\n proc.kill(\"SIGKILL\");\n } catch {\n // ignore\n }\n }, timeoutMs);\n }\n\n proc.on(\"close\", (code) => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n }\n resolve({\n exitCode: code,\n stdout,\n stderr,\n timedOut,\n truncated,\n });\n });\n\n proc.on(\"error\", (err) => {\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n }\n resolve({\n exitCode: null,\n stdout,\n stderr: stderr + (stderr ? \"\\n\" : \"\") + err.message,\n timedOut: false,\n truncated,\n });\n });\n });\n}\n\nexport function createSystemRunHandler(execConfig: ExecConfig, workdir: string) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const sendResult = async (result: NodeInvokeResultParams) => {\n await client.request(\"node.invoke.result\", result);\n };\n\n const params = parseRunParams(payload.paramsJSON);\n if (!params) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid system.run params\" },\n });\n return;\n }\n\n const commandText = params.command.join(\" \");\n const sessionKey = params.sessionKey ?? \"\";\n const runId = params.runId ?? randomUUID();\n const suppressNotifyOnExit = params.suppressNotifyOnExit;\n\n // Security: check blocked commands\n if (isBlockedCommand(params.command, execConfig.blockedCommands)) {\n void emitExecDenied(client, {\n sessionKey,\n runId,\n command: commandText,\n reason: \"allowlist-miss\",\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"BLOCKED\", message: \"Command is blocked by policy\" },\n });\n return;\n }\n\n // Security: validate cwd is within workdir\n if (params.cwd && !isPathWithinWorkdir(params.cwd, workdir)) {\n void emitExecDenied(client, {\n sessionKey,\n runId,\n command: commandText,\n reason: \"security=deny\",\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"WORKDIR_VIOLATION\",\n message: `Working directory ${params.cwd} is outside allowed workdir ${workdir}`,\n },\n });\n return;\n }\n\n // Check concurrent limit\n if (activeCount >= execConfig.maxConcurrent) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"RESOURCE_EXHAUSTED\",\n message: `Max concurrent executions (${execConfig.maxConcurrent}) reached`,\n },\n });\n return;\n }\n\n activeCount++;\n void emitExecStarted(client, {\n sessionKey,\n runId,\n command: commandText,\n suppressNotifyOnExit,\n });\n try {\n const result = await runCommand(params, execConfig);\n void emitExecFinished(client, {\n sessionKey,\n runId,\n command: commandText,\n exitCode: result.exitCode,\n timedOut: result.timedOut,\n success: result.exitCode === 0 && !result.timedOut,\n output: result.stdout + result.stderr,\n suppressNotifyOnExit,\n });\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n timedOut: result.timedOut,\n truncated: result.truncated,\n }),\n });\n } catch (err) {\n await sendResult({\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"EXEC_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n },\n });\n } finally {\n activeCount--;\n }\n };\n}\n\n// For testing\nexport { parseRunParams, isPathWithinWorkdir, isBlockedCommand, runCommand };\nexport type { SystemRunParams, RunResult };\n","import type { GatewayClient } from \"../client/index.js\";\nimport type { NodeEventParams } from \"../protocol/index.js\";\n\nconst EVENT_OUTPUT_MAX = 20_000; // 20KB tail for event output\n\nfunction tailOutput(output: string, max: number): string {\n if (output.length <= max) return output;\n return output.slice(-max);\n}\n\nexport async function emitNodeEvent(\n client: GatewayClient,\n event: string,\n payload: Record<string, unknown>,\n): Promise<void> {\n const params: NodeEventParams = {\n event,\n payloadJSON: JSON.stringify(payload),\n };\n try {\n await client.request(\"node.event\", params);\n } catch {\n // Best-effort event emission\n }\n}\n\nexport async function emitExecStarted(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.started\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n\nexport async function emitExecFinished(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n exitCode?: number | null;\n timedOut?: boolean;\n success?: boolean;\n output?: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.finished\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n exitCode: opts.exitCode,\n timedOut: opts.timedOut,\n success: opts.success,\n output: opts.output ? tailOutput(opts.output, EVENT_OUTPUT_MAX) : undefined,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n\nexport async function emitExecDenied(\n client: GatewayClient,\n opts: {\n sessionKey: string;\n runId: string;\n command?: string;\n reason: string;\n suppressNotifyOnExit?: boolean;\n },\n): Promise<void> {\n await emitNodeEvent(client, \"exec.denied\", {\n sessionKey: opts.sessionKey,\n runId: opts.runId,\n host: \"node\",\n command: opts.command,\n reason: opts.reason,\n suppressNotifyOnExit: opts.suppressNotifyOnExit,\n });\n}\n","import path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type SystemRunApprovalPlan = {\n argv: string[];\n cwd: string | null;\n commandText: string;\n commandPreview?: string | null;\n agentId: string | null;\n sessionKey: string | null;\n mutableFileOperand?: {\n argvIndex: number;\n path: string;\n sha256: string;\n } | null;\n};\n\ntype PrepareParams = {\n command?: unknown;\n rawCommand?: unknown;\n cwd?: unknown;\n agentId?: unknown;\n sessionKey?: unknown;\n};\n\nfunction resolveCommandArgv(params: PrepareParams): string[] | null {\n if (Array.isArray(params.command)) {\n const argv = params.command.filter(\n (s): s is string => typeof s === \"string\",\n );\n return argv.length > 0 ? argv : null;\n }\n if (typeof params.command === \"string\" && params.command.trim()) {\n return [params.command.trim()];\n }\n if (typeof params.rawCommand === \"string\" && params.rawCommand.trim()) {\n return [\"sh\", \"-c\", params.rawCommand.trim()];\n }\n return null;\n}\n\nfunction resolveMutableFileOperand(\n argv: string[],\n): SystemRunApprovalPlan[\"mutableFileOperand\"] {\n // Check if any argv element past index 0 is an existing file\n // This is a simplified version of OpenClaw's mutable file operand detection\n for (let i = 1; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith(\"-\")) continue;\n try {\n const resolved = path.resolve(arg);\n if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {\n const content = fs.readFileSync(resolved);\n const sha256 = crypto\n .createHash(\"sha256\")\n .update(content)\n .digest(\"hex\");\n return { argvIndex: i, path: resolved, sha256 };\n }\n } catch {\n // skip\n }\n }\n return null;\n}\n\nexport async function systemRunPrepareHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n): Promise<void> {\n let params: PrepareParams = {};\n if (payload.paramsJSON) {\n try {\n params = JSON.parse(payload.paramsJSON) as PrepareParams;\n } catch {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid params\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n const argv = resolveCommandArgv(params);\n if (!argv) {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"No command provided\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n\n const cwd =\n typeof params.cwd === \"string\" && params.cwd.trim()\n ? path.resolve(params.cwd.trim())\n : null;\n const agentId =\n typeof params.agentId === \"string\" ? params.agentId : null;\n const sessionKey =\n typeof params.sessionKey === \"string\" ? params.sessionKey : null;\n\n const plan: SystemRunApprovalPlan = {\n argv,\n cwd,\n commandText: argv.join(\" \"),\n commandPreview: argv.length > 3 ? argv.slice(0, 3).join(\" \") + \"...\" : null,\n agentId,\n sessionKey,\n mutableFileOperand: resolveMutableFileOperand(argv),\n };\n\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({ plan }),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import os from \"node:os\";\nimport fs from \"node:fs\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nexport type SystemInfo = {\n cpu: {\n model: string;\n cores: number;\n };\n memory: {\n totalBytes: number;\n freeBytes: number;\n usedBytes: number;\n };\n disk?: {\n totalBytes: number;\n freeBytes: number;\n usedBytes: number;\n };\n uptime: number;\n platform: string;\n arch: string;\n hostname: string;\n nodeVersion: string;\n};\n\nexport function getSystemInfo(workdir?: string): SystemInfo {\n const cpus = os.cpus();\n const totalMem = os.totalmem();\n const freeMem = os.freemem();\n\n const info: SystemInfo = {\n cpu: {\n model: cpus.length > 0 ? cpus[0].model : \"unknown\",\n cores: cpus.length,\n },\n memory: {\n totalBytes: totalMem,\n freeBytes: freeMem,\n usedBytes: totalMem - freeMem,\n },\n uptime: os.uptime(),\n platform: process.platform,\n arch: process.arch,\n hostname: os.hostname(),\n nodeVersion: process.version,\n };\n\n // Disk info via statfs (Node 20+)\n const statfsPath = workdir || \"/\";\n try {\n const stats = fs.statfsSync(statfsPath);\n info.disk = {\n totalBytes: stats.blocks * stats.bsize,\n freeBytes: stats.bavail * stats.bsize,\n usedBytes: (stats.blocks - stats.bavail) * stats.bsize,\n };\n } catch {\n // Disk info unavailable\n }\n\n return info;\n}\n\nexport async function systemInfoHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n workdir?: string,\n): Promise<void> {\n const info = getSystemInfo(workdir);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(info),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import { execFileSync } from \"node:child_process\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\n\nfunction whichBin(bin: string): string | null {\n try {\n const result = execFileSync(\"which\", [bin], {\n encoding: \"utf8\",\n timeout: 5000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n}\n\nexport function resolveWhich(bins: string[]): Record<string, string | null> {\n const result: Record<string, string | null> = {};\n for (const bin of bins) {\n result[bin] = whichBin(bin);\n }\n return result;\n}\n\nexport async function systemWhichHandler(\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n): Promise<void> {\n let bins: string[] = [];\n if (payload.paramsJSON) {\n try {\n const parsed = JSON.parse(payload.paramsJSON) as { bins?: string[] };\n if (Array.isArray(parsed.bins)) {\n bins = parsed.bins.filter((b): b is string => typeof b === \"string\");\n }\n } catch {\n // ignore\n }\n }\n\n const resolved = resolveWhich(bins);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify({ bins: resolved }),\n };\n await client.request(\"node.invoke.result\", result);\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { GatewayClient } from \"../client/index.js\";\nimport type { NodeInvokeRequestPayload, NodeInvokeResultParams } from \"../protocol/index.js\";\nimport { resolveBaseDir } from \"../config/index.js\";\n\nexport type ExecAllowlistEntry = {\n id?: string;\n pattern: string;\n lastUsedAt?: number;\n lastUsedCommand?: string;\n lastResolvedPath?: string;\n};\n\nexport type ExecApprovalsDefaults = {\n security?: string; // \"deny\" | \"allowlist\" | \"full\"\n ask?: string; // \"off\" | \"on-miss\" | \"always\"\n askFallback?: string;\n autoAllowSkills?: boolean;\n};\n\nexport type ExecApprovalsAgent = ExecApprovalsDefaults & {\n allowlist?: ExecAllowlistEntry[];\n};\n\nexport type ExecApprovalsFile = {\n version: 1;\n socket?: {\n path?: string;\n token?: string;\n };\n defaults?: ExecApprovalsDefaults;\n agents?: Record<string, ExecApprovalsAgent>;\n};\n\nexport type ExecApprovalsSnapshot = {\n path: string;\n exists: boolean;\n raw: string | null;\n file: ExecApprovalsFile;\n hash: string;\n};\n\nfunction resolveExecApprovalsPath(env?: NodeJS.ProcessEnv): string {\n return path.join(resolveBaseDir(env), \"exec-approvals.json\");\n}\n\nfunction hashRaw(raw: string | null): string {\n return crypto\n .createHash(\"sha256\")\n .update(raw ?? \"\")\n .digest(\"hex\");\n}\n\nfunction loadExecApprovalsFile(filePath: string): ExecApprovalsSnapshot {\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, \"utf8\");\n const parsed = JSON.parse(raw) as ExecApprovalsFile;\n if (parsed?.version === 1) {\n return { path: filePath, exists: true, raw, file: parsed, hash: hashRaw(raw) };\n }\n }\n } catch {\n // fall through\n }\n const defaultFile: ExecApprovalsFile = { version: 1 };\n return { path: filePath, exists: false, raw: null, file: defaultFile, hash: hashRaw(null) };\n}\n\nfunction saveExecApprovalsFile(\n filePath: string,\n file: ExecApprovalsFile,\n): ExecApprovalsSnapshot {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const raw = JSON.stringify(file, null, 2) + \"\\n\";\n fs.writeFileSync(filePath, raw, { mode: 0o600 });\n return { path: filePath, exists: true, raw, file, hash: hashRaw(raw) };\n}\n\nexport function createExecApprovalsGetHandler(env?: NodeJS.ProcessEnv) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const filePath = resolveExecApprovalsPath(env);\n const snapshot = loadExecApprovalsFile(filePath);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(snapshot),\n };\n await client.request(\"node.invoke.result\", result);\n };\n}\n\nexport function createExecApprovalsSetHandler(env?: NodeJS.ProcessEnv) {\n return async (\n payload: NodeInvokeRequestPayload,\n client: GatewayClient,\n ): Promise<void> => {\n const filePath = resolveExecApprovalsPath(env);\n\n let params: { file?: ExecApprovalsFile; baseHash?: string | null } = {};\n if (payload.paramsJSON) {\n try {\n params = JSON.parse(payload.paramsJSON) as typeof params;\n } catch {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: { code: \"INVALID_PARAMS\", message: \"Invalid params\" },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n // CAS: check base hash if provided\n if (params.baseHash) {\n const current = loadExecApprovalsFile(filePath);\n if (current.hash !== params.baseHash) {\n await client.request(\"node.invoke.result\", {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: false,\n error: {\n code: \"HASH_MISMATCH\",\n message: \"Exec approvals file was modified concurrently\",\n },\n } satisfies NodeInvokeResultParams);\n return;\n }\n }\n\n const file = params.file ?? { version: 1 as const };\n const snapshot = saveExecApprovalsFile(filePath, file);\n const result: NodeInvokeResultParams = {\n id: payload.id,\n nodeId: payload.nodeId,\n ok: true,\n payloadJSON: JSON.stringify(snapshot),\n };\n await client.request(\"node.invoke.result\", result);\n };\n}\n","import { loadConfig } from \"../config/index.js\";\nimport type { CommandRouter } from \"../runtime/router.js\";\nimport { createSystemRunHandler } from \"./system-run.js\";\nimport { systemRunPrepareHandler } from \"./system-run-prepare.js\";\nimport { systemInfoHandler } from \"./system-info.js\";\nimport { systemWhichHandler } from \"./system-which.js\";\nimport {\n createExecApprovalsGetHandler,\n createExecApprovalsSetHandler,\n} from \"./exec-approvals.js\";\n\nexport function registerAllHandlers(\n router: CommandRouter,\n env?: NodeJS.ProcessEnv,\n): void {\n const config = loadConfig(env);\n const workdir = config.device.workdir;\n\n router.register(\n \"system.run\",\n createSystemRunHandler(config.exec, workdir),\n );\n\n router.register(\"system.run.prepare\", systemRunPrepareHandler);\n\n router.register(\"system.info\", (payload, client) =>\n systemInfoHandler(payload, client, workdir),\n );\n\n router.register(\"system.which\", systemWhichHandler);\n\n router.register(\n \"system.execApprovals.get\",\n createExecApprovalsGetHandler(env),\n );\n\n router.register(\n \"system.execApprovals.set\",\n createExecApprovalsSetHandler(env),\n );\n}\n","import type { Command } from \"commander\";\nimport { startNode } from \"../runtime/index.js\";\nimport { registerAllHandlers } from \"../handlers/index.js\";\n\nexport function registerStartCommand(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the node daemon (foreground)\")\n .action(async () => {\n try {\n const { router, stop } = await startNode();\n registerAllHandlers(router);\n\n console.log(\"NodeClaw running. Press Ctrl+C to stop.\");\n\n const shutdown = () => {\n console.log(\"\\nShutting down...\");\n stop();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Keep process alive\n await new Promise(() => {});\n } catch (err) {\n console.error(\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport {\n loadConfig,\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport { loadOrCreateIdentity, loadDeviceAuthToken } from \"../crypto/index.js\";\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show connection and pairing status\")\n .action(() => {\n const config = loadConfig();\n const identityPath = resolveIdentityPath();\n const tokenStorePath = resolveTokenStorePath();\n\n let identity;\n try {\n identity = loadOrCreateIdentity(identityPath);\n } catch {\n console.log(\"Device identity: not initialized\");\n return;\n }\n\n const token = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n \"node\",\n );\n\n console.log(`Gateway URL: ${config.gateway.url}`);\n console.log(`Device name: ${config.device.name || \"(default)\"}`);\n console.log(`Device ID: ${identity.deviceId}`);\n console.log(`Paired: ${token ? \"yes\" : \"no\"}`);\n if (config.device.workdir) {\n console.log(`Workdir: ${config.device.workdir}`);\n }\n });\n}\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport {\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport {\n loadOrCreateIdentity,\n clearDeviceAuthToken,\n} from \"../crypto/index.js\";\n\nexport function registerUnpairCommand(program: Command): void {\n program\n .command(\"unpair\")\n .description(\"Remove pairing token and disconnect\")\n .option(\"--full\", \"Also delete device identity (generates new ID on next pair)\")\n .action((opts: { full?: boolean }) => {\n const identityPath = resolveIdentityPath();\n const tokenStorePath = resolveTokenStorePath();\n\n try {\n const identity = loadOrCreateIdentity(identityPath);\n clearDeviceAuthToken(tokenStorePath, identity.deviceId, \"node\");\n console.log(\"Pairing token removed.\");\n } catch {\n console.log(\"No pairing token found.\");\n }\n\n if (opts.full) {\n try {\n if (fs.existsSync(identityPath)) {\n fs.unlinkSync(identityPath);\n console.log(\"Device identity deleted.\");\n }\n } catch (err) {\n console.error(\n `Failed to delete identity: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { VERSION, PROTOCOL_VERSION } from \"../index.js\";\n\nexport function registerVersionCommand(program: Command): void {\n program\n .command(\"info\")\n .description(\"Show version and protocol information\")\n .action(() => {\n console.log(`NodeClaw v${VERSION}`);\n console.log(`Protocol: ${PROTOCOL_VERSION}`);\n console.log(`Node.js: ${process.version}`);\n console.log(`Platform: ${process.platform}`);\n console.log(`Arch: ${process.arch}`);\n });\n}\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport {\n loadConfig,\n resolveBaseDir,\n resolveConfigPath,\n resolveIdentityPath,\n resolveTokenStorePath,\n} from \"../config/index.js\";\nimport { loadOrCreateIdentity, loadDeviceAuthToken } from \"../crypto/index.js\";\n\ntype Check = {\n name: string;\n status: \"ok\" | \"warn\" | \"fail\";\n detail: string;\n};\n\nfunction runChecks(): Check[] {\n const checks: Check[] = [];\n\n // Node.js version\n const nodeVersion = parseInt(process.version.slice(1), 10);\n checks.push({\n name: \"Node.js version\",\n status: nodeVersion >= 20 ? \"ok\" : \"fail\",\n detail: `${process.version} ${nodeVersion >= 20 ? \"(>= 20)\" : \"(requires >= 20)\"}`,\n });\n\n // Config directory\n const baseDir = resolveBaseDir();\n checks.push({\n name: \"Config directory\",\n status: fs.existsSync(baseDir) ? \"ok\" : \"warn\",\n detail: baseDir,\n });\n\n // Config file\n const configPath = resolveConfigPath();\n if (fs.existsSync(configPath)) {\n try {\n loadConfig();\n checks.push({ name: \"Config file\", status: \"ok\", detail: configPath });\n } catch {\n checks.push({\n name: \"Config file\",\n status: \"fail\",\n detail: `${configPath} (invalid)`,\n });\n }\n } else {\n checks.push({\n name: \"Config file\",\n status: \"warn\",\n detail: `${configPath} (not found, using defaults)`,\n });\n }\n\n // Device identity\n const identityPath = resolveIdentityPath();\n if (fs.existsSync(identityPath)) {\n try {\n const identity = loadOrCreateIdentity(identityPath);\n checks.push({\n name: \"Device identity\",\n status: \"ok\",\n detail: `${identity.deviceId.slice(0, 16)}...`,\n });\n } catch {\n checks.push({\n name: \"Device identity\",\n status: \"fail\",\n detail: `${identityPath} (corrupt)`,\n });\n }\n } else {\n checks.push({\n name: \"Device identity\",\n status: \"warn\",\n detail: \"Not initialized (will be created on first pair)\",\n });\n }\n\n // Pairing token\n const tokenStorePath = resolveTokenStorePath();\n try {\n const identity = loadOrCreateIdentity(identityPath);\n const token = loadDeviceAuthToken(\n tokenStorePath,\n identity.deviceId,\n \"node\",\n );\n checks.push({\n name: \"Pairing token\",\n status: token ? \"ok\" : \"warn\",\n detail: token ? \"Stored\" : \"Not paired\",\n });\n } catch {\n checks.push({\n name: \"Pairing token\",\n status: \"warn\",\n detail: \"Cannot check (no identity)\",\n });\n }\n\n // Gateway URL\n const config = loadConfig();\n checks.push({\n name: \"Gateway URL\",\n status: config.gateway.url ? \"ok\" : \"fail\",\n detail: config.gateway.url || \"(not configured)\",\n });\n\n // Workdir\n if (config.device.workdir) {\n const exists = fs.existsSync(config.device.workdir);\n checks.push({\n name: \"Workdir\",\n status: exists ? \"ok\" : \"fail\",\n detail: `${config.device.workdir} ${exists ? \"\" : \"(not found)\"}`,\n });\n } else {\n checks.push({\n name: \"Workdir\",\n status: \"warn\",\n detail: \"Not configured (exec allowed anywhere)\",\n });\n }\n\n return checks;\n}\n\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Check configuration, connectivity, and service status\")\n .action(() => {\n const checks = runChecks();\n let hasFailures = false;\n\n for (const check of checks) {\n const icon =\n check.status === \"ok\"\n ? \"[OK] \"\n : check.status === \"warn\"\n ? \"[WARN]\"\n : \"[FAIL]\";\n if (check.status === \"fail\") {\n hasFailures = true;\n }\n console.log(`${icon} ${check.name}: ${check.detail}`);\n }\n\n if (hasFailures) {\n process.exitCode = 1;\n }\n });\n}\n\n// For testing\nexport { runChecks };\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport type { Command } from \"commander\";\nimport { generateSystemdUnit } from \"../service/systemd.js\";\nimport { generateLaunchdPlist } from \"../service/launchd.js\";\nimport { loadConfig } from \"../config/index.js\";\n\nexport function registerInstallServiceCommand(program: Command): void {\n program\n .command(\"install-service\")\n .description(\"Install systemd (Linux) or launchd (macOS) service\")\n .option(\"--dry-run\", \"Print the service file without writing\")\n .action((opts: { dryRun?: boolean }) => {\n const config = loadConfig();\n const platform = process.platform;\n const workdir = config.device.workdir || os.homedir();\n\n if (platform === \"linux\") {\n const unit = generateSystemdUnit({ workdir });\n if (opts.dryRun) {\n console.log(unit);\n return;\n }\n const unitPath = path.join(\n os.homedir(),\n \".config\",\n \"systemd\",\n \"user\",\n \"nodeclaw.service\",\n );\n fs.mkdirSync(path.dirname(unitPath), { recursive: true });\n fs.writeFileSync(unitPath, unit);\n console.log(`Service file written to ${unitPath}`);\n console.log(\"To enable: systemctl --user enable --now nodeclaw\");\n } else if (platform === \"darwin\") {\n const plist = generateLaunchdPlist({ workdir });\n if (opts.dryRun) {\n console.log(plist);\n return;\n }\n const plistPath = path.join(\n os.homedir(),\n \"Library\",\n \"LaunchAgents\",\n \"ai.nodeclaw.plist\",\n );\n fs.mkdirSync(path.dirname(plistPath), { recursive: true });\n fs.writeFileSync(plistPath, plist);\n console.log(`Plist written to ${plistPath}`);\n console.log(\"To load: launchctl load \" + plistPath);\n } else {\n console.error(`Service installation not supported on ${platform}`);\n process.exit(1);\n }\n });\n\n program\n .command(\"uninstall-service\")\n .description(\"Remove installed service\")\n .action(() => {\n const platform = process.platform;\n if (platform === \"linux\") {\n const unitPath = path.join(\n os.homedir(),\n \".config\",\n \"systemd\",\n \"user\",\n \"nodeclaw.service\",\n );\n if (fs.existsSync(unitPath)) {\n fs.unlinkSync(unitPath);\n console.log(\"Service file removed.\");\n console.log(\"Run: systemctl --user daemon-reload\");\n } else {\n console.log(\"Service file not found.\");\n }\n } else if (platform === \"darwin\") {\n const plistPath = path.join(\n os.homedir(),\n \"Library\",\n \"LaunchAgents\",\n \"ai.nodeclaw.plist\",\n );\n if (fs.existsSync(plistPath)) {\n fs.unlinkSync(plistPath);\n console.log(\"Plist removed.\");\n console.log(\"Run: launchctl unload \" + plistPath);\n } else {\n console.log(\"Plist not found.\");\n }\n } else {\n console.error(`Service uninstall not supported on ${platform}`);\n process.exit(1);\n }\n });\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport { execFileSync } from \"node:child_process\";\n\nexport type SystemdOptions = {\n execPath?: string;\n user?: string;\n workdir?: string;\n};\n\nfunction resolveNodeClawPath(): string {\n try {\n return execFileSync(\"which\", [\"nodeclaw\"], {\n encoding: \"utf8\",\n timeout: 5000,\n }).trim();\n } catch {\n return \"/usr/local/bin/nodeclaw\";\n }\n}\n\n/** Return the directory containing the current node binary. */\nfunction resolveNodeBinDir(): string {\n return path.dirname(process.execPath);\n}\n\nexport function generateSystemdUnit(opts: SystemdOptions = {}): string {\n const execPath = opts.execPath || resolveNodeClawPath();\n const workdir = opts.workdir || os.homedir();\n\n // Ensure the node binary directory is in PATH so /usr/bin/env node resolves\n // correctly even in systemd's minimal environment (e.g. when node comes from\n // nvm and isn't in /usr/local/bin).\n const nodeBinDir = resolveNodeBinDir();\n const pathEnv = `PATH=${nodeBinDir}:/usr/local/bin:/usr/bin:/bin`;\n\n // User-mode systemd services must NOT include User= (it belongs only in\n // system-wide unit files) and WantedBy must be default.target, not\n // multi-user.target (which is a system target unavailable to user managers).\n return `[Unit]\nDescription=NodeClaw - OpenClaw Node Client\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${execPath} start\nRestart=always\nRestartSec=5\nWorkingDirectory=${workdir}\nEnvironment=NODE_ENV=production\nEnvironment=${pathEnv}\n\n[Install]\nWantedBy=default.target\n`;\n}\n","import os from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\n\nexport type LaunchdOptions = {\n execPath?: string;\n workdir?: string;\n label?: string;\n};\n\nfunction resolveNodeClawPath(): string {\n try {\n return execFileSync(\"which\", [\"nodeclaw\"], {\n encoding: \"utf8\",\n timeout: 5000,\n }).trim();\n } catch {\n return \"/usr/local/bin/nodeclaw\";\n }\n}\n\nexport function generateLaunchdPlist(opts: LaunchdOptions = {}): string {\n const execPath = opts.execPath || resolveNodeClawPath();\n const workdir = opts.workdir || os.homedir();\n const label = opts.label || \"ai.nodeclaw\";\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${label}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${execPath}</string>\n <string>start</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>${workdir}</string>\n <key>StandardOutPath</key>\n <string>/tmp/nodeclaw.stdout.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/nodeclaw.stderr.log</string>\n</dict>\n</plist>\n`;\n}\n"],"mappings":"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","names":["os","fs","path","path","fs","path","fs","path","PROTOCOL_VERSION","PROTOCOL_VERSION","os","program","os","os","randomUUID","path","path","randomUUID","path","crypto","fs","os","fs","crypto","fs","path","path","crypto","fs","program","program","fs","program","fs","program","fs","fs","program","fs","path","os","os","path","execFileSync","os","execFileSync","resolveNodeClawPath","program","os","path","fs"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare const VERSION = "0.1.0";
1
+ declare const VERSION = "0.2.0";
2
2
  declare const PROTOCOL_VERSION = 3;
3
3
 
4
4
  export { PROTOCOL_VERSION, VERSION };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PROTOCOL_VERSION,
3
3
  VERSION
4
- } from "./chunk-F5XQ5PZF.js";
4
+ } from "./chunk-AMDUWOYB.js";
5
5
  export {
6
6
  PROTOCOL_VERSION,
7
7
  VERSION
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodeclaw",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.2.0-alpha.2",
4
4
  "description": "Minimal OpenClaw node protocol client \u2014 everything a node needs, nothing it doesn't.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,12 +8,19 @@
8
8
  "bin": {
9
9
  "nodeclaw": "dist/cli.js"
10
10
  },
11
+ "files": [
12
+ "dist/",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "homepage": "https://github.com/scottgl9/NodeClaw",
11
17
  "repository": {
12
18
  "type": "git",
13
19
  "url": "https://github.com/scottgl9/NodeClaw.git"
14
20
  },
15
21
  "publishConfig": {
16
- "registry": "https://registry.npmjs.org/"
22
+ "registry": "https://registry.npmjs.org/",
23
+ "access": "public"
17
24
  },
18
25
  "scripts": {
19
26
  "build": "tsup",
@@ -26,7 +33,12 @@
26
33
  "openclaw",
27
34
  "node",
28
35
  "remote-execution",
29
- "websocket"
36
+ "websocket",
37
+ "ai-agent",
38
+ "local-ai",
39
+ "edge",
40
+ "raspberry-pi",
41
+ "automation"
30
42
  ],
31
43
  "license": "MIT",
32
44
  "engines": {
@@ -49,10 +61,5 @@
49
61
  "onlyBuiltDependencies": [
50
62
  "esbuild"
51
63
  ]
52
- },
53
- "files": [
54
- "dist/",
55
- "README.md",
56
- "LICENSE"
57
- ]
64
+ }
58
65
  }