squad-openclaw 2026.2.1807 → 2026.2.1810
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +86 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1041,9 +1041,9 @@ function ensureDevicePaired(keys, operatorToken) {
|
|
|
1041
1041
|
console.log(`[relay-client] Device pairing entry created in paired.json`);
|
|
1042
1042
|
return true;
|
|
1043
1043
|
}
|
|
1044
|
-
function signDeviceIdentity(keys, clientId, clientMode, role, scopes, token) {
|
|
1044
|
+
function signDeviceIdentity(keys, clientId, clientMode, role, scopes, token, challengeNonce) {
|
|
1045
1045
|
const signedAtMs = Date.now();
|
|
1046
|
-
const nonce = crypto2.randomBytes(16).toString("hex");
|
|
1046
|
+
const nonce = challengeNonce || crypto2.randomBytes(16).toString("hex");
|
|
1047
1047
|
const scopeStr = scopes.join(",");
|
|
1048
1048
|
const payload = `v2|${keys.deviceId}|${clientId}|${clientMode}|${role}|${scopeStr}|${signedAtMs}|${token ?? ""}|${nonce}`;
|
|
1049
1049
|
const privateKey = crypto2.createPrivateKey(keys.privateKeyPem);
|
|
@@ -1078,7 +1078,7 @@ var RelayClient = class {
|
|
|
1078
1078
|
claimToken: config.claimToken ?? state.claimToken ?? null,
|
|
1079
1079
|
roomId: config.roomId ?? state.roomId ?? null
|
|
1080
1080
|
};
|
|
1081
|
-
this.pendingClaimToken = this.config.claimToken;
|
|
1081
|
+
this.pendingClaimToken = this.config.roomId ? null : this.config.claimToken;
|
|
1082
1082
|
this.deviceKeys = loadOrCreateRelayDeviceKeys();
|
|
1083
1083
|
const newEntry = ensureDevicePaired(this.deviceKeys, this.config.operatorToken);
|
|
1084
1084
|
if (newEntry) {
|
|
@@ -1265,6 +1265,12 @@ var RelayClient = class {
|
|
|
1265
1265
|
}
|
|
1266
1266
|
return;
|
|
1267
1267
|
}
|
|
1268
|
+
if (typeof msg.type === "string" && msg.type.startsWith("relay.")) {
|
|
1269
|
+
if (msg.type === "relay.e2e.exchange" && msg.publicKey) {
|
|
1270
|
+
this.handleE2EExchange(userId, msg.publicKey);
|
|
1271
|
+
}
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1268
1274
|
let conn = this.userConnections.get(userId);
|
|
1269
1275
|
if (!conn || conn.localWs.readyState !== NodeWebSocket.OPEN) {
|
|
1270
1276
|
this.createUserConnection(userId);
|
|
@@ -1272,24 +1278,12 @@ var RelayClient = class {
|
|
|
1272
1278
|
if (!conn) return;
|
|
1273
1279
|
}
|
|
1274
1280
|
if (msg.type === "req" && msg.method === "connect") {
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1281
|
+
if (!conn.challengeNonce) {
|
|
1282
|
+
console.log(`[relay-client] Connect request for ${userId} deferred \u2014 waiting for challenge nonce`);
|
|
1283
|
+
conn.pendingConnect = msg;
|
|
1284
|
+
return;
|
|
1278
1285
|
}
|
|
1279
|
-
|
|
1280
|
-
const role = params.role ?? "operator";
|
|
1281
|
-
const scopes = params.scopes ?? [];
|
|
1282
|
-
params.device = signDeviceIdentity(
|
|
1283
|
-
this.deviceKeys,
|
|
1284
|
-
client.id ?? "cli",
|
|
1285
|
-
client.mode ?? "ui",
|
|
1286
|
-
role,
|
|
1287
|
-
scopes,
|
|
1288
|
-
this.config.operatorToken
|
|
1289
|
-
);
|
|
1290
|
-
msg.params = params;
|
|
1291
|
-
conn.connectHandshakeComplete = false;
|
|
1292
|
-
console.log(`[relay-client] Injected device identity for user ${userId}: ${this.deviceKeys.deviceId.substring(0, 12)}...`);
|
|
1286
|
+
this.injectDeviceIdentity(conn, msg);
|
|
1293
1287
|
}
|
|
1294
1288
|
if (conn.localWs.readyState === NodeWebSocket.CONNECTING) {
|
|
1295
1289
|
conn.localWs.once("open", () => {
|
|
@@ -1299,6 +1293,28 @@ var RelayClient = class {
|
|
|
1299
1293
|
}
|
|
1300
1294
|
conn.localWs.send(JSON.stringify(msg));
|
|
1301
1295
|
}
|
|
1296
|
+
/** Inject auth token and device identity into a connect request */
|
|
1297
|
+
injectDeviceIdentity(conn, msg) {
|
|
1298
|
+
const params = msg.params ?? {};
|
|
1299
|
+
if (this.config.operatorToken) {
|
|
1300
|
+
params.auth = { token: this.config.operatorToken };
|
|
1301
|
+
}
|
|
1302
|
+
const client = params.client ?? {};
|
|
1303
|
+
const role = params.role ?? "operator";
|
|
1304
|
+
const scopes = params.scopes ?? [];
|
|
1305
|
+
params.device = signDeviceIdentity(
|
|
1306
|
+
this.deviceKeys,
|
|
1307
|
+
client.id ?? "cli",
|
|
1308
|
+
client.mode ?? "ui",
|
|
1309
|
+
role,
|
|
1310
|
+
scopes,
|
|
1311
|
+
this.config.operatorToken,
|
|
1312
|
+
conn.challengeNonce
|
|
1313
|
+
);
|
|
1314
|
+
msg.params = params;
|
|
1315
|
+
conn.connectHandshakeComplete = false;
|
|
1316
|
+
console.log(`[relay-client] Injected device identity for ${conn.userId}: nonce=${conn.challengeNonce?.substring(0, 12)}...`);
|
|
1317
|
+
}
|
|
1302
1318
|
/** Create a local WS connection to the gateway for a specific user */
|
|
1303
1319
|
createUserConnection(userId) {
|
|
1304
1320
|
const existing = this.userConnections.get(userId);
|
|
@@ -1315,7 +1331,9 @@ var RelayClient = class {
|
|
|
1315
1331
|
localWs,
|
|
1316
1332
|
userId,
|
|
1317
1333
|
e2e: null,
|
|
1318
|
-
connectHandshakeComplete: false
|
|
1334
|
+
connectHandshakeComplete: false,
|
|
1335
|
+
challengeNonce: null,
|
|
1336
|
+
pendingConnect: null
|
|
1319
1337
|
};
|
|
1320
1338
|
this.userConnections.set(userId, conn);
|
|
1321
1339
|
localWs.on("open", () => {
|
|
@@ -1350,6 +1368,22 @@ var RelayClient = class {
|
|
|
1350
1368
|
const conn = this.userConnections.get(userId);
|
|
1351
1369
|
if (!conn) return;
|
|
1352
1370
|
const parsed = msg;
|
|
1371
|
+
if (parsed.type === "event" && parsed.event === "connect.challenge") {
|
|
1372
|
+
const payload = parsed.payload;
|
|
1373
|
+
if (payload?.nonce) {
|
|
1374
|
+
conn.challengeNonce = payload.nonce;
|
|
1375
|
+
console.log(`[relay-client] Captured challenge nonce for ${userId}: ${conn.challengeNonce.substring(0, 12)}...`);
|
|
1376
|
+
if (conn.pendingConnect) {
|
|
1377
|
+
const pending = conn.pendingConnect;
|
|
1378
|
+
conn.pendingConnect = null;
|
|
1379
|
+
console.log(`[relay-client] Flushing deferred connect for ${userId}`);
|
|
1380
|
+
this.injectDeviceIdentity(conn, pending);
|
|
1381
|
+
if (conn.localWs.readyState === NodeWebSocket.OPEN) {
|
|
1382
|
+
conn.localWs.send(JSON.stringify(pending));
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1353
1387
|
if (parsed.type === "res" && parsed.id === "connect-1" && parsed.ok) {
|
|
1354
1388
|
conn.connectHandshakeComplete = true;
|
|
1355
1389
|
}
|
|
@@ -1439,9 +1473,40 @@ function startRelayClient(api, relayUrl) {
|
|
|
1439
1473
|
|
|
1440
1474
|
// src/index.ts
|
|
1441
1475
|
function squadAppPlugin(api) {
|
|
1476
|
+
const toolExecutors = /* @__PURE__ */ new Map();
|
|
1477
|
+
const origRegisterTool = api.registerTool.bind(api);
|
|
1478
|
+
api.registerTool = (toolDef) => {
|
|
1479
|
+
if (toolDef.name && typeof toolDef.execute === "function") {
|
|
1480
|
+
toolExecutors.set(toolDef.name, toolDef.execute);
|
|
1481
|
+
}
|
|
1482
|
+
return origRegisterTool(toolDef);
|
|
1483
|
+
};
|
|
1442
1484
|
registerEntityTools(api);
|
|
1443
1485
|
registerFilesystemTools(api);
|
|
1444
1486
|
registerVersionMethods(api);
|
|
1487
|
+
api.registerGatewayMethod(
|
|
1488
|
+
"tools.invoke",
|
|
1489
|
+
async ({ params, respond }) => {
|
|
1490
|
+
const tool = params?.tool;
|
|
1491
|
+
const args = params?.args ?? {};
|
|
1492
|
+
if (!tool) {
|
|
1493
|
+
respond(false, { errorMessage: "Missing 'tool' parameter" });
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
const executeFn = toolExecutors.get(tool);
|
|
1497
|
+
if (!executeFn) {
|
|
1498
|
+
respond(false, { errorMessage: `Unknown tool: ${tool}` });
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
try {
|
|
1502
|
+
const result = await executeFn(`ws-${Date.now()}`, args);
|
|
1503
|
+
respond(true, result);
|
|
1504
|
+
} catch (err2) {
|
|
1505
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
1506
|
+
respond(false, { errorMessage: msg });
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
);
|
|
1445
1510
|
const relayEnabled = api.pluginConfig?.["relay.enabled"] ?? true;
|
|
1446
1511
|
if (relayEnabled) {
|
|
1447
1512
|
const relayUrl = api.pluginConfig?.["relay.url"] || "wss://relay.squad.ceo";
|
package/package.json
CHANGED