clawdentity 0.0.4 → 0.0.5
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/bin.js +524 -614
- package/dist/index.js +524 -614
- package/dist/postinstall.js +0 -0
- package/package.json +17 -16
- package/skill-bundle/openclaw-skill/dist/relay-to-peer.mjs +165 -18
- package/skill-bundle/openclaw-skill/skill/SKILL.md +15 -8
- package/skill-bundle/openclaw-skill/skill/references/clawdentity-protocol.md +18 -16
package/dist/bin.js
CHANGED
|
@@ -18495,9 +18495,9 @@ var createConfigCommand = () => {
|
|
|
18495
18495
|
|
|
18496
18496
|
// src/commands/connector.ts
|
|
18497
18497
|
import { execFile as execFileCallback } from "child_process";
|
|
18498
|
-
import { mkdir as mkdir4, readFile as
|
|
18498
|
+
import { mkdir as mkdir4, readFile as readFile3, rm, writeFile as writeFile4 } from "fs/promises";
|
|
18499
18499
|
import { homedir as homedir2 } from "os";
|
|
18500
|
-
import { dirname as dirname3, join as
|
|
18500
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
18501
18501
|
import { fileURLToPath } from "url";
|
|
18502
18502
|
import { promisify } from "util";
|
|
18503
18503
|
|
|
@@ -19151,271 +19151,15 @@ import { mkdir as mkdir3, rename as rename2, writeFile as writeFile3 } from "fs/
|
|
|
19151
19151
|
import {
|
|
19152
19152
|
createServer
|
|
19153
19153
|
} from "http";
|
|
19154
|
-
import { dirname as dirname2, join as
|
|
19154
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
19155
19155
|
import { WebSocket as NodeWebSocket } from "ws";
|
|
19156
|
-
|
|
19157
|
-
// ../../packages/connector/src/relay-echo.ts
|
|
19158
|
-
import { readFile as readFile3 } from "fs/promises";
|
|
19159
|
-
import { join as join4 } from "path";
|
|
19160
|
-
var OPENCLAW_RELAY_RUNTIME_CONFIG_FILENAME = "openclaw-relay.json";
|
|
19161
|
-
var PEERS_CONFIG_FILENAME = "peers.json";
|
|
19162
|
-
var ECHO_EMPTY_MESSAGE_FALLBACK = "(no message content)";
|
|
19163
|
-
var MIN_ECHO_MAX_LENGTH = 50;
|
|
19164
|
-
var MAX_ECHO_MAX_LENGTH = 2e3;
|
|
19165
|
-
var DEFAULT_RELAY_ECHO_ENABLED = true;
|
|
19166
|
-
var DEFAULT_RELAY_ECHO_CHANNEL = "last";
|
|
19167
|
-
var DEFAULT_RELAY_ECHO_MAX_LENGTH = 500;
|
|
19168
|
-
function isRecord4(value) {
|
|
19169
|
-
return typeof value === "object" && value !== null;
|
|
19170
|
-
}
|
|
19171
|
-
function parseAbsoluteHttpUrl(value, field) {
|
|
19172
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
19173
|
-
throw new Error(`${field} must be a non-empty string`);
|
|
19174
|
-
}
|
|
19175
|
-
let parsed;
|
|
19176
|
-
try {
|
|
19177
|
-
parsed = new URL(value.trim());
|
|
19178
|
-
} catch {
|
|
19179
|
-
throw new Error(`${field} must be a valid absolute URL`);
|
|
19180
|
-
}
|
|
19181
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
19182
|
-
throw new Error(`${field} must use http or https`);
|
|
19183
|
-
}
|
|
19184
|
-
if (parsed.pathname === "/" && parsed.search.length === 0 && parsed.hash.length === 0) {
|
|
19185
|
-
return parsed.origin;
|
|
19186
|
-
}
|
|
19187
|
-
return parsed.toString();
|
|
19188
|
-
}
|
|
19189
|
-
function parseBoolean(value, field) {
|
|
19190
|
-
if (typeof value !== "boolean") {
|
|
19191
|
-
throw new Error(`${field} must be a boolean`);
|
|
19192
|
-
}
|
|
19193
|
-
return value;
|
|
19194
|
-
}
|
|
19195
|
-
function parsePositiveInt(value, field, min, max) {
|
|
19196
|
-
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
19197
|
-
if (!Number.isInteger(parsed) || parsed < min || parsed > max) {
|
|
19198
|
-
throw new Error(`${field} must be an integer between ${min} and ${max}`);
|
|
19199
|
-
}
|
|
19200
|
-
return parsed;
|
|
19201
|
-
}
|
|
19202
|
-
function parseOptionalString(value, field) {
|
|
19203
|
-
if (value === void 0) {
|
|
19204
|
-
return void 0;
|
|
19205
|
-
}
|
|
19206
|
-
if (typeof value !== "string") {
|
|
19207
|
-
throw new Error(`${field} must be a string`);
|
|
19208
|
-
}
|
|
19209
|
-
const trimmed = value.trim();
|
|
19210
|
-
if (trimmed.length === 0) {
|
|
19211
|
-
return void 0;
|
|
19212
|
-
}
|
|
19213
|
-
return trimmed;
|
|
19214
|
-
}
|
|
19215
|
-
function parseEchoConfig(value) {
|
|
19216
|
-
if (value === void 0) {
|
|
19217
|
-
return {
|
|
19218
|
-
enabled: DEFAULT_RELAY_ECHO_ENABLED,
|
|
19219
|
-
channel: DEFAULT_RELAY_ECHO_CHANNEL,
|
|
19220
|
-
maxLength: DEFAULT_RELAY_ECHO_MAX_LENGTH
|
|
19221
|
-
};
|
|
19222
|
-
}
|
|
19223
|
-
if (!isRecord4(value)) {
|
|
19224
|
-
throw new Error("echo config must be an object");
|
|
19225
|
-
}
|
|
19226
|
-
return {
|
|
19227
|
-
enabled: value.enabled === void 0 ? DEFAULT_RELAY_ECHO_ENABLED : parseBoolean(value.enabled, "echo.enabled"),
|
|
19228
|
-
channel: parseOptionalString(value.channel, "echo.channel") ?? DEFAULT_RELAY_ECHO_CHANNEL,
|
|
19229
|
-
to: parseOptionalString(value.to, "echo.to"),
|
|
19230
|
-
maxLength: value.maxLength === void 0 ? DEFAULT_RELAY_ECHO_MAX_LENGTH : parsePositiveInt(
|
|
19231
|
-
value.maxLength,
|
|
19232
|
-
"echo.maxLength",
|
|
19233
|
-
MIN_ECHO_MAX_LENGTH,
|
|
19234
|
-
MAX_ECHO_MAX_LENGTH
|
|
19235
|
-
)
|
|
19236
|
-
};
|
|
19237
|
-
}
|
|
19238
|
-
async function loadRelayRuntimeConfigFile(input) {
|
|
19239
|
-
const relayRuntimeConfigPath = join4(
|
|
19240
|
-
input.configDir,
|
|
19241
|
-
OPENCLAW_RELAY_RUNTIME_CONFIG_FILENAME
|
|
19242
|
-
);
|
|
19243
|
-
let raw;
|
|
19244
|
-
try {
|
|
19245
|
-
raw = await readFile3(relayRuntimeConfigPath, "utf8");
|
|
19246
|
-
} catch (error48) {
|
|
19247
|
-
if (typeof error48 === "object" && error48 !== null && "code" in error48 && error48.code === "ENOENT") {
|
|
19248
|
-
return void 0;
|
|
19249
|
-
}
|
|
19250
|
-
throw new Error(
|
|
19251
|
-
`Unable to read relay runtime config at ${relayRuntimeConfigPath}`
|
|
19252
|
-
);
|
|
19253
|
-
}
|
|
19254
|
-
let parsed;
|
|
19255
|
-
try {
|
|
19256
|
-
parsed = JSON.parse(raw);
|
|
19257
|
-
} catch {
|
|
19258
|
-
throw new Error(
|
|
19259
|
-
`Unable to parse relay runtime config at ${relayRuntimeConfigPath}`
|
|
19260
|
-
);
|
|
19261
|
-
}
|
|
19262
|
-
if (!isRecord4(parsed)) {
|
|
19263
|
-
throw new Error("Relay runtime config root must be a JSON object");
|
|
19264
|
-
}
|
|
19265
|
-
const config2 = parsed;
|
|
19266
|
-
const openclawBaseUrl = config2.openclawBaseUrl === void 0 ? void 0 : parseAbsoluteHttpUrl(config2.openclawBaseUrl, "openclawBaseUrl");
|
|
19267
|
-
return {
|
|
19268
|
-
openclawBaseUrl,
|
|
19269
|
-
echo: parseEchoConfig(config2.echo)
|
|
19270
|
-
};
|
|
19271
|
-
}
|
|
19272
|
-
function compactString(value) {
|
|
19273
|
-
return value.replaceAll(/\s+/g, " ").trim();
|
|
19274
|
-
}
|
|
19275
|
-
function toCompactJson(value) {
|
|
19276
|
-
try {
|
|
19277
|
-
const raw = JSON.stringify(value);
|
|
19278
|
-
if (typeof raw !== "string" || raw.length === 0) {
|
|
19279
|
-
return ECHO_EMPTY_MESSAGE_FALLBACK;
|
|
19280
|
-
}
|
|
19281
|
-
return raw;
|
|
19282
|
-
} catch {
|
|
19283
|
-
return ECHO_EMPTY_MESSAGE_FALLBACK;
|
|
19284
|
-
}
|
|
19285
|
-
}
|
|
19286
|
-
function truncateMessage(value, maxLength) {
|
|
19287
|
-
if (value.length <= maxLength) {
|
|
19288
|
-
return value;
|
|
19289
|
-
}
|
|
19290
|
-
return `${value.slice(0, maxLength)}...`;
|
|
19291
|
-
}
|
|
19292
|
-
function extractRelayMessageContent(payload) {
|
|
19293
|
-
if (typeof payload === "string") {
|
|
19294
|
-
const compact = compactString(payload);
|
|
19295
|
-
return compact.length > 0 ? compact : ECHO_EMPTY_MESSAGE_FALLBACK;
|
|
19296
|
-
}
|
|
19297
|
-
if (isRecord4(payload)) {
|
|
19298
|
-
for (const candidateKey of ["message", "text", "content"]) {
|
|
19299
|
-
const candidateValue = payload[candidateKey];
|
|
19300
|
-
if (typeof candidateValue === "string") {
|
|
19301
|
-
const compact = compactString(candidateValue);
|
|
19302
|
-
if (compact.length > 0) {
|
|
19303
|
-
return compact;
|
|
19304
|
-
}
|
|
19305
|
-
}
|
|
19306
|
-
}
|
|
19307
|
-
}
|
|
19308
|
-
return toCompactJson(payload);
|
|
19309
|
-
}
|
|
19310
|
-
function formatInboundRelayEcho(input) {
|
|
19311
|
-
const content = truncateMessage(
|
|
19312
|
-
extractRelayMessageContent(input.payload),
|
|
19313
|
-
input.maxLength
|
|
19314
|
-
);
|
|
19315
|
-
return `\u{1F517} [${input.fromLabel}]: ${content}`;
|
|
19316
|
-
}
|
|
19317
|
-
function formatOutboundRelayEcho(input) {
|
|
19318
|
-
const content = truncateMessage(
|
|
19319
|
-
extractRelayMessageContent(input.payload),
|
|
19320
|
-
input.maxLength
|
|
19321
|
-
);
|
|
19322
|
-
return `\u21A9\uFE0F Reply to [${input.toLabel}]: ${content}`;
|
|
19323
|
-
}
|
|
19324
|
-
async function loadPeerLabelsByDid(input) {
|
|
19325
|
-
const peersPath = join4(input.configDir, PEERS_CONFIG_FILENAME);
|
|
19326
|
-
let raw;
|
|
19327
|
-
try {
|
|
19328
|
-
raw = await readFile3(peersPath, "utf8");
|
|
19329
|
-
} catch (error48) {
|
|
19330
|
-
if (typeof error48 === "object" && error48 !== null && "code" in error48 && error48.code === "ENOENT") {
|
|
19331
|
-
return /* @__PURE__ */ new Map();
|
|
19332
|
-
}
|
|
19333
|
-
throw new Error(`Unable to read peers config at ${peersPath}`);
|
|
19334
|
-
}
|
|
19335
|
-
let parsed;
|
|
19336
|
-
try {
|
|
19337
|
-
parsed = JSON.parse(raw);
|
|
19338
|
-
} catch {
|
|
19339
|
-
throw new Error(`Unable to parse peers config at ${peersPath}`);
|
|
19340
|
-
}
|
|
19341
|
-
if (!isRecord4(parsed) || !isRecord4(parsed.peers)) {
|
|
19342
|
-
return /* @__PURE__ */ new Map();
|
|
19343
|
-
}
|
|
19344
|
-
const labels = /* @__PURE__ */ new Map();
|
|
19345
|
-
for (const [alias, entry] of Object.entries(parsed.peers)) {
|
|
19346
|
-
if (!isRecord4(entry) || typeof entry.did !== "string") {
|
|
19347
|
-
continue;
|
|
19348
|
-
}
|
|
19349
|
-
const did = entry.did.trim();
|
|
19350
|
-
if (did.length === 0) {
|
|
19351
|
-
continue;
|
|
19352
|
-
}
|
|
19353
|
-
const name = typeof entry.name === "string" && entry.name.trim().length > 0 ? entry.name.trim() : alias.trim();
|
|
19354
|
-
if (name.length === 0) {
|
|
19355
|
-
continue;
|
|
19356
|
-
}
|
|
19357
|
-
labels.set(did, name);
|
|
19358
|
-
}
|
|
19359
|
-
return labels;
|
|
19360
|
-
}
|
|
19361
|
-
function resolvePeerLabel(input) {
|
|
19362
|
-
if (input.peerDid !== void 0) {
|
|
19363
|
-
const byDid = input.peerLabelsByDid.get(input.peerDid);
|
|
19364
|
-
if (typeof byDid === "string" && byDid.length > 0) {
|
|
19365
|
-
return byDid;
|
|
19366
|
-
}
|
|
19367
|
-
}
|
|
19368
|
-
const fallback = input.fallbackLabel.trim();
|
|
19369
|
-
if (fallback.length > 0) {
|
|
19370
|
-
return fallback;
|
|
19371
|
-
}
|
|
19372
|
-
return input.peerDid?.trim() || "Unknown peer";
|
|
19373
|
-
}
|
|
19374
|
-
async function sendRelayEchoToOpenclaw(input) {
|
|
19375
|
-
if (!input.echoConfig.enabled) {
|
|
19376
|
-
return;
|
|
19377
|
-
}
|
|
19378
|
-
const payload = {
|
|
19379
|
-
message: input.message,
|
|
19380
|
-
name: "Clawdentity Relay",
|
|
19381
|
-
wakeMode: "now",
|
|
19382
|
-
deliver: true,
|
|
19383
|
-
channel: input.echoConfig.channel
|
|
19384
|
-
};
|
|
19385
|
-
if (input.echoConfig.to !== void 0) {
|
|
19386
|
-
payload.to = input.echoConfig.to;
|
|
19387
|
-
}
|
|
19388
|
-
const headers = {
|
|
19389
|
-
"content-type": "application/json"
|
|
19390
|
-
};
|
|
19391
|
-
if (input.requestId !== void 0 && input.requestId.trim().length > 0) {
|
|
19392
|
-
headers["x-request-id"] = input.requestId.trim();
|
|
19393
|
-
}
|
|
19394
|
-
if (input.hookToken !== void 0 && input.hookToken.trim().length > 0) {
|
|
19395
|
-
headers["x-openclaw-token"] = input.hookToken.trim();
|
|
19396
|
-
}
|
|
19397
|
-
const response = await input.fetchImpl(input.endpoint, {
|
|
19398
|
-
method: "POST",
|
|
19399
|
-
headers,
|
|
19400
|
-
body: JSON.stringify(payload)
|
|
19401
|
-
});
|
|
19402
|
-
if (!response.ok) {
|
|
19403
|
-
input.logger.warn("connector.relay_echo.rejected", {
|
|
19404
|
-
status: response.status,
|
|
19405
|
-
requestId: input.requestId
|
|
19406
|
-
});
|
|
19407
|
-
throw new Error(`Relay echo rejected with status ${response.status}`);
|
|
19408
|
-
}
|
|
19409
|
-
}
|
|
19410
|
-
|
|
19411
|
-
// ../../packages/connector/src/runtime.ts
|
|
19412
19156
|
var REGISTRY_AUTH_FILENAME = "registry-auth.json";
|
|
19413
19157
|
var AGENTS_DIR_NAME2 = "agents";
|
|
19414
19158
|
var REFRESH_SINGLE_FLIGHT_PREFIX = "connector-runtime";
|
|
19415
19159
|
var NONCE_SIZE = 16;
|
|
19416
19160
|
var MAX_OUTBOUND_BODY_BYTES = 1024 * 1024;
|
|
19417
19161
|
var ACCESS_TOKEN_REFRESH_SKEW_MS = 3e4;
|
|
19418
|
-
function
|
|
19162
|
+
function isRecord4(value) {
|
|
19419
19163
|
return typeof value === "object" && value !== null;
|
|
19420
19164
|
}
|
|
19421
19165
|
function toPathWithQuery2(url2) {
|
|
@@ -19465,38 +19209,9 @@ function normalizeWebSocketUrl(urlInput) {
|
|
|
19465
19209
|
}
|
|
19466
19210
|
return parsed.toString();
|
|
19467
19211
|
}
|
|
19468
|
-
function
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
parsed = new URL(value);
|
|
19472
|
-
} catch {
|
|
19473
|
-
throw new Error("OpenClaw base URL is invalid");
|
|
19474
|
-
}
|
|
19475
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
19476
|
-
throw new Error("OpenClaw base URL is invalid");
|
|
19477
|
-
}
|
|
19478
|
-
if (parsed.pathname === "/" && parsed.search.length === 0 && parsed.hash.length === 0) {
|
|
19479
|
-
return parsed.origin;
|
|
19480
|
-
}
|
|
19481
|
-
return parsed.toString();
|
|
19482
|
-
}
|
|
19483
|
-
async function resolveOpenclawRuntimeSettings(input) {
|
|
19484
|
-
const fileConfig = await loadRelayRuntimeConfigFile({
|
|
19485
|
-
configDir: input.configDir
|
|
19486
|
-
});
|
|
19487
|
-
const baseUrlFromOption = input.openclawBaseUrlOption?.trim();
|
|
19488
|
-
const baseUrlFromEnv = process.env.OPENCLAW_BASE_URL?.trim();
|
|
19489
|
-
const openclawBaseUrl = parseOpenclawBaseUrl(
|
|
19490
|
-
baseUrlFromOption || baseUrlFromEnv || fileConfig?.openclawBaseUrl || DEFAULT_OPENCLAW_BASE_URL
|
|
19491
|
-
);
|
|
19492
|
-
return {
|
|
19493
|
-
openclawBaseUrl,
|
|
19494
|
-
echoConfig: fileConfig?.echo ?? {
|
|
19495
|
-
enabled: DEFAULT_RELAY_ECHO_ENABLED,
|
|
19496
|
-
channel: DEFAULT_RELAY_ECHO_CHANNEL,
|
|
19497
|
-
maxLength: DEFAULT_RELAY_ECHO_MAX_LENGTH
|
|
19498
|
-
}
|
|
19499
|
-
};
|
|
19212
|
+
function resolveOpenclawBaseUrl(input) {
|
|
19213
|
+
const value = input?.trim() || process.env.OPENCLAW_BASE_URL?.trim() || DEFAULT_OPENCLAW_BASE_URL;
|
|
19214
|
+
return value;
|
|
19500
19215
|
}
|
|
19501
19216
|
function resolveOpenclawHookPath(input) {
|
|
19502
19217
|
const value = input?.trim() || process.env.OPENCLAW_HOOK_PATH?.trim() || DEFAULT_OPENCLAW_HOOK_PATH;
|
|
@@ -19536,7 +19251,7 @@ function shouldRefreshAccessToken(auth, nowMs) {
|
|
|
19536
19251
|
return expiresAtMs <= nowMs + ACCESS_TOKEN_REFRESH_SKEW_MS;
|
|
19537
19252
|
}
|
|
19538
19253
|
function parseOutboundRelayRequest(payload) {
|
|
19539
|
-
if (!
|
|
19254
|
+
if (!isRecord4(payload)) {
|
|
19540
19255
|
throw new AppError({
|
|
19541
19256
|
code: "CONNECTOR_OUTBOUND_INVALID_REQUEST",
|
|
19542
19257
|
message: "Outbound relay request must be an object",
|
|
@@ -19594,7 +19309,7 @@ function createWebSocketFactory() {
|
|
|
19594
19309
|
};
|
|
19595
19310
|
}
|
|
19596
19311
|
async function writeRegistryAuthAtomic(input) {
|
|
19597
|
-
const targetPath =
|
|
19312
|
+
const targetPath = join4(
|
|
19598
19313
|
input.configDir,
|
|
19599
19314
|
AGENTS_DIR_NAME2,
|
|
19600
19315
|
input.agentName,
|
|
@@ -19691,63 +19406,14 @@ async function startConnectorRuntime(input) {
|
|
|
19691
19406
|
accessToken: currentAuth.accessToken,
|
|
19692
19407
|
secretKey
|
|
19693
19408
|
});
|
|
19694
|
-
const openclawRuntimeSettings = await resolveOpenclawRuntimeSettings({
|
|
19695
|
-
configDir: input.configDir,
|
|
19696
|
-
openclawBaseUrlOption: input.openclawBaseUrl
|
|
19697
|
-
});
|
|
19698
|
-
const peerLabelsByDid = await loadPeerLabelsByDid({
|
|
19699
|
-
configDir: input.configDir
|
|
19700
|
-
});
|
|
19701
|
-
const openclawHookPath = resolveOpenclawHookPath(input.openclawHookPath);
|
|
19702
|
-
const openclawHookToken = resolveOpenclawHookToken(input.openclawHookToken);
|
|
19703
|
-
const openclawHookUrl = new URL(
|
|
19704
|
-
openclawHookPath,
|
|
19705
|
-
openclawRuntimeSettings.openclawBaseUrl
|
|
19706
|
-
).toString();
|
|
19707
|
-
const queueRelayEcho = (echoInput) => {
|
|
19708
|
-
void sendRelayEchoToOpenclaw({
|
|
19709
|
-
endpoint: openclawHookUrl,
|
|
19710
|
-
echoConfig: openclawRuntimeSettings.echoConfig,
|
|
19711
|
-
fetchImpl,
|
|
19712
|
-
hookToken: openclawHookToken,
|
|
19713
|
-
logger: logger12,
|
|
19714
|
-
message: echoInput.message,
|
|
19715
|
-
requestId: echoInput.requestId
|
|
19716
|
-
}).catch((error48) => {
|
|
19717
|
-
logger12.warn("connector.relay_echo.failed", {
|
|
19718
|
-
direction: echoInput.direction,
|
|
19719
|
-
errorName: error48 instanceof Error ? error48.name : "unknown",
|
|
19720
|
-
requestId: echoInput.requestId
|
|
19721
|
-
});
|
|
19722
|
-
});
|
|
19723
|
-
};
|
|
19724
19409
|
const connectorClient = new ConnectorClient({
|
|
19725
19410
|
connectorUrl: wsParsed.toString(),
|
|
19726
19411
|
connectionHeaders: upgradeHeaders,
|
|
19727
|
-
openclawBaseUrl:
|
|
19728
|
-
openclawHookPath,
|
|
19729
|
-
openclawHookToken,
|
|
19412
|
+
openclawBaseUrl: resolveOpenclawBaseUrl(input.openclawBaseUrl),
|
|
19413
|
+
openclawHookPath: resolveOpenclawHookPath(input.openclawHookPath),
|
|
19414
|
+
openclawHookToken: resolveOpenclawHookToken(input.openclawHookToken),
|
|
19730
19415
|
fetchImpl,
|
|
19731
19416
|
logger: logger12,
|
|
19732
|
-
hooks: {
|
|
19733
|
-
onDeliverSucceeded: (frame) => {
|
|
19734
|
-
const fromLabel = resolvePeerLabel({
|
|
19735
|
-
peerLabelsByDid,
|
|
19736
|
-
peerDid: frame.fromAgentDid,
|
|
19737
|
-
fallbackLabel: frame.fromAgentDid
|
|
19738
|
-
});
|
|
19739
|
-
const echoMessage = formatInboundRelayEcho({
|
|
19740
|
-
fromLabel,
|
|
19741
|
-
payload: frame.payload,
|
|
19742
|
-
maxLength: openclawRuntimeSettings.echoConfig.maxLength
|
|
19743
|
-
});
|
|
19744
|
-
queueRelayEcho({
|
|
19745
|
-
direction: "inbound",
|
|
19746
|
-
message: echoMessage,
|
|
19747
|
-
requestId: frame.id
|
|
19748
|
-
});
|
|
19749
|
-
}
|
|
19750
|
-
},
|
|
19751
19417
|
webSocketFactory: createWebSocketFactory()
|
|
19752
19418
|
});
|
|
19753
19419
|
const outboundBaseUrl = normalizeOutboundBaseUrl(input.outboundBaseUrl);
|
|
@@ -19833,22 +19499,6 @@ async function startConnectorRuntime(input) {
|
|
|
19833
19499
|
const requestBody = await readRequestJson(req);
|
|
19834
19500
|
const relayRequest = parseOutboundRelayRequest(requestBody);
|
|
19835
19501
|
await relayToPeer(relayRequest);
|
|
19836
|
-
const toLabel = resolvePeerLabel({
|
|
19837
|
-
peerLabelsByDid,
|
|
19838
|
-
peerDid: relayRequest.peerDid,
|
|
19839
|
-
fallbackLabel: relayRequest.peer
|
|
19840
|
-
});
|
|
19841
|
-
const requestId = typeof req.headers["x-request-id"] === "string" ? req.headers["x-request-id"] : void 0;
|
|
19842
|
-
const echoMessage = formatOutboundRelayEcho({
|
|
19843
|
-
toLabel,
|
|
19844
|
-
payload: relayRequest.payload,
|
|
19845
|
-
maxLength: openclawRuntimeSettings.echoConfig.maxLength
|
|
19846
|
-
});
|
|
19847
|
-
queueRelayEcho({
|
|
19848
|
-
direction: "outbound",
|
|
19849
|
-
message: echoMessage,
|
|
19850
|
-
requestId
|
|
19851
|
-
});
|
|
19852
19502
|
writeJson(res, 202, { accepted: true, peer: relayRequest.peer });
|
|
19853
19503
|
} catch (error48) {
|
|
19854
19504
|
if (error48 instanceof AppError) {
|
|
@@ -19927,14 +19577,16 @@ var IDENTITY_FILE_NAME2 = "identity.json";
|
|
|
19927
19577
|
var AIT_FILE_NAME2 = "ait.jwt";
|
|
19928
19578
|
var SECRET_KEY_FILE_NAME = "secret.key";
|
|
19929
19579
|
var REGISTRY_AUTH_FILE_NAME2 = "registry-auth.json";
|
|
19580
|
+
var OPENCLAW_RELAY_RUNTIME_FILE_NAME = "openclaw-relay.json";
|
|
19581
|
+
var OPENCLAW_CONNECTORS_FILE_NAME = "openclaw-connectors.json";
|
|
19930
19582
|
var SERVICE_LOG_DIR_NAME = "logs";
|
|
19931
19583
|
var DEFAULT_CONNECTOR_BASE_URL2 = "http://127.0.0.1:19400";
|
|
19932
19584
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH2 = "/v1/outbound";
|
|
19933
|
-
function
|
|
19585
|
+
function isRecord5(value) {
|
|
19934
19586
|
return typeof value === "object" && value !== null;
|
|
19935
19587
|
}
|
|
19936
19588
|
function getErrorCode(error48) {
|
|
19937
|
-
if (!
|
|
19589
|
+
if (!isRecord5(error48)) {
|
|
19938
19590
|
return void 0;
|
|
19939
19591
|
}
|
|
19940
19592
|
return typeof error48.code === "string" ? error48.code : void 0;
|
|
@@ -20010,13 +19662,43 @@ function normalizeOutboundPath2(pathValue) {
|
|
|
20010
19662
|
}
|
|
20011
19663
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
20012
19664
|
}
|
|
20013
|
-
function
|
|
19665
|
+
function resolveConnectorBaseUrlFromEnv() {
|
|
20014
19666
|
const value = process.env.CLAWDENTITY_CONNECTOR_BASE_URL;
|
|
20015
19667
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
20016
|
-
return
|
|
19668
|
+
return void 0;
|
|
20017
19669
|
}
|
|
20018
19670
|
return parseConnectorBaseUrl(value.trim());
|
|
20019
19671
|
}
|
|
19672
|
+
async function readConnectorAssignedBaseUrl(configDir, agentName, readFileImpl) {
|
|
19673
|
+
const assignmentsPath = join5(configDir, OPENCLAW_CONNECTORS_FILE_NAME);
|
|
19674
|
+
let raw;
|
|
19675
|
+
try {
|
|
19676
|
+
raw = await readFileImpl(assignmentsPath, "utf8");
|
|
19677
|
+
} catch (error48) {
|
|
19678
|
+
if (getErrorCode(error48) === "ENOENT") {
|
|
19679
|
+
return void 0;
|
|
19680
|
+
}
|
|
19681
|
+
throw error48;
|
|
19682
|
+
}
|
|
19683
|
+
let parsed;
|
|
19684
|
+
try {
|
|
19685
|
+
parsed = JSON.parse(raw);
|
|
19686
|
+
} catch {
|
|
19687
|
+
throw createCliError3(
|
|
19688
|
+
"CLI_CONNECTOR_INVALID_ASSIGNMENTS",
|
|
19689
|
+
"Connector assignments config is invalid JSON",
|
|
19690
|
+
{ assignmentsPath }
|
|
19691
|
+
);
|
|
19692
|
+
}
|
|
19693
|
+
if (!isRecord5(parsed) || !isRecord5(parsed.agents)) {
|
|
19694
|
+
return void 0;
|
|
19695
|
+
}
|
|
19696
|
+
const entry = parsed.agents[agentName];
|
|
19697
|
+
if (!isRecord5(entry) || typeof entry.connectorBaseUrl !== "string") {
|
|
19698
|
+
return void 0;
|
|
19699
|
+
}
|
|
19700
|
+
return parseConnectorBaseUrl(entry.connectorBaseUrl);
|
|
19701
|
+
}
|
|
20020
19702
|
function resolveConnectorOutboundPath() {
|
|
20021
19703
|
const value = process.env.CLAWDENTITY_CONNECTOR_OUTBOUND_PATH;
|
|
20022
19704
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
@@ -20051,6 +19733,34 @@ async function readRequiredTrimmedFile(filePath, label, readFileImpl) {
|
|
|
20051
19733
|
}
|
|
20052
19734
|
return trimmed;
|
|
20053
19735
|
}
|
|
19736
|
+
async function readRelayRuntimeConfig(configDir, readFileImpl) {
|
|
19737
|
+
const filePath = join5(configDir, OPENCLAW_RELAY_RUNTIME_FILE_NAME);
|
|
19738
|
+
let raw;
|
|
19739
|
+
try {
|
|
19740
|
+
raw = await readFileImpl(filePath, "utf8");
|
|
19741
|
+
} catch (error48) {
|
|
19742
|
+
if (getErrorCode(error48) === "ENOENT") {
|
|
19743
|
+
return void 0;
|
|
19744
|
+
}
|
|
19745
|
+
throw error48;
|
|
19746
|
+
}
|
|
19747
|
+
let parsed;
|
|
19748
|
+
try {
|
|
19749
|
+
parsed = JSON.parse(raw);
|
|
19750
|
+
} catch {
|
|
19751
|
+
return void 0;
|
|
19752
|
+
}
|
|
19753
|
+
if (!isRecord5(parsed)) {
|
|
19754
|
+
return void 0;
|
|
19755
|
+
}
|
|
19756
|
+
const openclawHookToken = typeof parsed.openclawHookToken === "string" && parsed.openclawHookToken.trim().length > 0 ? parsed.openclawHookToken.trim() : void 0;
|
|
19757
|
+
if (!openclawHookToken) {
|
|
19758
|
+
return void 0;
|
|
19759
|
+
}
|
|
19760
|
+
return {
|
|
19761
|
+
openclawHookToken
|
|
19762
|
+
};
|
|
19763
|
+
}
|
|
20054
19764
|
function parseJsonRecord(value, code, message2) {
|
|
20055
19765
|
let parsed;
|
|
20056
19766
|
try {
|
|
@@ -20058,7 +19768,7 @@ function parseJsonRecord(value, code, message2) {
|
|
|
20058
19768
|
} catch {
|
|
20059
19769
|
throw createCliError3(code, message2);
|
|
20060
19770
|
}
|
|
20061
|
-
if (!
|
|
19771
|
+
if (!isRecord5(parsed)) {
|
|
20062
19772
|
throw createCliError3(code, message2);
|
|
20063
19773
|
}
|
|
20064
19774
|
return parsed;
|
|
@@ -20098,7 +19808,7 @@ async function loadDefaultConnectorModule() {
|
|
|
20098
19808
|
};
|
|
20099
19809
|
}
|
|
20100
19810
|
function resolveWaitPromise(runtime) {
|
|
20101
|
-
if (!runtime || !
|
|
19811
|
+
if (!runtime || !isRecord5(runtime)) {
|
|
20102
19812
|
return void 0;
|
|
20103
19813
|
}
|
|
20104
19814
|
if (typeof runtime.waitUntilStopped === "function") {
|
|
@@ -20163,7 +19873,7 @@ function buildConnectorStartArgs(agentName, commandOptions) {
|
|
|
20163
19873
|
}
|
|
20164
19874
|
function resolveCliEntryPath(resolveCurrentModulePathImpl) {
|
|
20165
19875
|
const modulePath = resolveCurrentModulePathImpl?.() ?? fileURLToPath(import.meta.url);
|
|
20166
|
-
return
|
|
19876
|
+
return join5(dirname3(modulePath), "..", "bin.js");
|
|
20167
19877
|
}
|
|
20168
19878
|
function escapeXml(value) {
|
|
20169
19879
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
@@ -20261,7 +19971,7 @@ async function installConnectorServiceForAgent(agentName, commandOptions = {}, d
|
|
|
20261
19971
|
);
|
|
20262
19972
|
const configDir = serviceDependencies.getConfigDirImpl();
|
|
20263
19973
|
const homeDir = serviceDependencies.getHomeDirImpl();
|
|
20264
|
-
const logsDir =
|
|
19974
|
+
const logsDir = join5(configDir, SERVICE_LOG_DIR_NAME);
|
|
20265
19975
|
const serviceName = sanitizeServiceSegment(
|
|
20266
19976
|
`clawdentity-connector-${agentName}`
|
|
20267
19977
|
);
|
|
@@ -20271,12 +19981,12 @@ async function installConnectorServiceForAgent(agentName, commandOptions = {}, d
|
|
|
20271
19981
|
resolveCliEntryPath(serviceDependencies.resolveCurrentModulePathImpl),
|
|
20272
19982
|
...startArgs
|
|
20273
19983
|
];
|
|
20274
|
-
const outputLogPath =
|
|
20275
|
-
const errorLogPath =
|
|
19984
|
+
const outputLogPath = join5(logsDir, `${serviceName}.out.log`);
|
|
19985
|
+
const errorLogPath = join5(logsDir, `${serviceName}.err.log`);
|
|
20276
19986
|
await serviceDependencies.mkdirImpl(logsDir, { recursive: true });
|
|
20277
19987
|
if (platform === "systemd") {
|
|
20278
|
-
const serviceDir =
|
|
20279
|
-
const serviceFilePath2 =
|
|
19988
|
+
const serviceDir = join5(homeDir, ".config", "systemd", "user");
|
|
19989
|
+
const serviceFilePath2 = join5(serviceDir, `${serviceName}.service`);
|
|
20280
19990
|
await serviceDependencies.mkdirImpl(serviceDir, { recursive: true });
|
|
20281
19991
|
await serviceDependencies.writeFileImpl(
|
|
20282
19992
|
serviceFilePath2,
|
|
@@ -20315,9 +20025,9 @@ async function installConnectorServiceForAgent(agentName, commandOptions = {}, d
|
|
|
20315
20025
|
serviceFilePath: serviceFilePath2
|
|
20316
20026
|
};
|
|
20317
20027
|
}
|
|
20318
|
-
const launchAgentsDir =
|
|
20028
|
+
const launchAgentsDir = join5(homeDir, "Library", "LaunchAgents");
|
|
20319
20029
|
const serviceNameWithDomain = `com.clawdentity.${serviceName}`;
|
|
20320
|
-
const serviceFilePath =
|
|
20030
|
+
const serviceFilePath = join5(
|
|
20321
20031
|
launchAgentsDir,
|
|
20322
20032
|
`${serviceNameWithDomain}.plist`
|
|
20323
20033
|
);
|
|
@@ -20376,7 +20086,7 @@ async function uninstallConnectorServiceForAgent(agentName, commandOptions = {},
|
|
|
20376
20086
|
`clawdentity-connector-${agentName}`
|
|
20377
20087
|
);
|
|
20378
20088
|
if (platform === "systemd") {
|
|
20379
|
-
const serviceFilePath2 =
|
|
20089
|
+
const serviceFilePath2 = join5(
|
|
20380
20090
|
homeDir,
|
|
20381
20091
|
".config",
|
|
20382
20092
|
"systemd",
|
|
@@ -20407,7 +20117,7 @@ async function uninstallConnectorServiceForAgent(agentName, commandOptions = {},
|
|
|
20407
20117
|
};
|
|
20408
20118
|
}
|
|
20409
20119
|
const serviceNameWithDomain = `com.clawdentity.${serviceName}`;
|
|
20410
|
-
const serviceFilePath =
|
|
20120
|
+
const serviceFilePath = join5(
|
|
20411
20121
|
homeDir,
|
|
20412
20122
|
"Library",
|
|
20413
20123
|
"LaunchAgents",
|
|
@@ -20431,38 +20141,42 @@ async function uninstallConnectorServiceForAgent(agentName, commandOptions = {},
|
|
|
20431
20141
|
async function startConnectorForAgent(agentName, commandOptions = {}, dependencies = {}) {
|
|
20432
20142
|
const resolveConfigImpl = dependencies.resolveConfigImpl ?? resolveConfig;
|
|
20433
20143
|
const getConfigDirImpl = dependencies.getConfigDirImpl ?? getConfigDir;
|
|
20434
|
-
const readFileImpl = dependencies.readFileImpl ?? ((path, encoding) =>
|
|
20144
|
+
const readFileImpl = dependencies.readFileImpl ?? ((path, encoding) => readFile3(path, encoding));
|
|
20435
20145
|
const loadConnectorModule = dependencies.loadConnectorModule ?? loadDefaultConnectorModule;
|
|
20436
20146
|
const configDir = getConfigDirImpl();
|
|
20437
|
-
const agentDirectory =
|
|
20147
|
+
const agentDirectory = join5(configDir, AGENTS_DIR_NAME3, agentName);
|
|
20438
20148
|
const [
|
|
20439
20149
|
rawAit,
|
|
20440
20150
|
rawSecretKey,
|
|
20441
20151
|
rawIdentity,
|
|
20442
20152
|
rawRegistryAuth,
|
|
20153
|
+
assignedConnectorBaseUrl,
|
|
20154
|
+
relayRuntimeConfig,
|
|
20443
20155
|
config2,
|
|
20444
20156
|
connectorModule
|
|
20445
20157
|
] = await Promise.all([
|
|
20446
20158
|
readRequiredTrimmedFile(
|
|
20447
|
-
|
|
20159
|
+
join5(agentDirectory, AIT_FILE_NAME2),
|
|
20448
20160
|
AIT_FILE_NAME2,
|
|
20449
20161
|
readFileImpl
|
|
20450
20162
|
),
|
|
20451
20163
|
readRequiredTrimmedFile(
|
|
20452
|
-
|
|
20164
|
+
join5(agentDirectory, SECRET_KEY_FILE_NAME),
|
|
20453
20165
|
SECRET_KEY_FILE_NAME,
|
|
20454
20166
|
readFileImpl
|
|
20455
20167
|
),
|
|
20456
20168
|
readRequiredTrimmedFile(
|
|
20457
|
-
|
|
20169
|
+
join5(agentDirectory, IDENTITY_FILE_NAME2),
|
|
20458
20170
|
IDENTITY_FILE_NAME2,
|
|
20459
20171
|
readFileImpl
|
|
20460
20172
|
),
|
|
20461
20173
|
readRequiredTrimmedFile(
|
|
20462
|
-
|
|
20174
|
+
join5(agentDirectory, REGISTRY_AUTH_FILE_NAME2),
|
|
20463
20175
|
REGISTRY_AUTH_FILE_NAME2,
|
|
20464
20176
|
readFileImpl
|
|
20465
20177
|
),
|
|
20178
|
+
readConnectorAssignedBaseUrl(configDir, agentName, readFileImpl),
|
|
20179
|
+
readRelayRuntimeConfig(configDir, readFileImpl),
|
|
20466
20180
|
resolveConfigImpl(),
|
|
20467
20181
|
loadConnectorModule()
|
|
20468
20182
|
]);
|
|
@@ -20474,7 +20188,8 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20474
20188
|
}
|
|
20475
20189
|
const identity = parseAgentIdentity(rawIdentity);
|
|
20476
20190
|
const registryAuth = parseRegistryAuth(rawRegistryAuth);
|
|
20477
|
-
const
|
|
20191
|
+
const openclawHookToken = commandOptions.openclawHookToken ?? relayRuntimeConfig?.openclawHookToken;
|
|
20192
|
+
const outboundBaseUrl = resolveConnectorBaseUrlFromEnv() ?? assignedConnectorBaseUrl ?? DEFAULT_CONNECTOR_BASE_URL2;
|
|
20478
20193
|
const outboundPath = resolveConnectorOutboundPath();
|
|
20479
20194
|
const runtime = await connectorModule.startConnectorRuntime({
|
|
20480
20195
|
agentName,
|
|
@@ -20485,7 +20200,7 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20485
20200
|
proxyWebsocketUrl: commandOptions.proxyWsUrl,
|
|
20486
20201
|
openclawBaseUrl: commandOptions.openclawBaseUrl,
|
|
20487
20202
|
openclawHookPath: commandOptions.openclawHookPath,
|
|
20488
|
-
openclawHookToken
|
|
20203
|
+
openclawHookToken,
|
|
20489
20204
|
credentials: {
|
|
20490
20205
|
agentDid: identity.did,
|
|
20491
20206
|
ait: rawAit,
|
|
@@ -20497,8 +20212,8 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20497
20212
|
tokenType: registryAuth.tokenType
|
|
20498
20213
|
}
|
|
20499
20214
|
});
|
|
20500
|
-
const outboundUrl = runtime &&
|
|
20501
|
-
const proxyWebsocketUrl = runtime &&
|
|
20215
|
+
const outboundUrl = runtime && isRecord5(runtime) && typeof runtime.outboundUrl === "string" ? runtime.outboundUrl : resolveOutboundUrl(outboundBaseUrl, outboundPath);
|
|
20216
|
+
const proxyWebsocketUrl = runtime && isRecord5(runtime) ? typeof runtime.websocketUrl === "string" ? runtime.websocketUrl : typeof runtime.proxyWebsocketUrl === "string" ? runtime.proxyWebsocketUrl : void 0 : void 0;
|
|
20502
20217
|
return {
|
|
20503
20218
|
outboundUrl,
|
|
20504
20219
|
proxyWebsocketUrl,
|
|
@@ -20629,7 +20344,7 @@ function createConnectorCommand(dependencies = {}) {
|
|
|
20629
20344
|
// src/commands/invite.ts
|
|
20630
20345
|
import { Command as Command6 } from "commander";
|
|
20631
20346
|
var logger7 = createLogger({ service: "cli", module: "invite" });
|
|
20632
|
-
var
|
|
20347
|
+
var isRecord6 = (value) => {
|
|
20633
20348
|
return typeof value === "object" && value !== null;
|
|
20634
20349
|
};
|
|
20635
20350
|
function parseNonEmptyString6(value) {
|
|
@@ -20670,7 +20385,7 @@ function toRegistryRequestUrl(registryUrl, path) {
|
|
|
20670
20385
|
return new URL(path.slice(1), normalizedBaseUrl).toString();
|
|
20671
20386
|
}
|
|
20672
20387
|
function extractRegistryErrorCode(payload) {
|
|
20673
|
-
if (!
|
|
20388
|
+
if (!isRecord6(payload)) {
|
|
20674
20389
|
return void 0;
|
|
20675
20390
|
}
|
|
20676
20391
|
const envelope = payload;
|
|
@@ -20681,7 +20396,7 @@ function extractRegistryErrorCode(payload) {
|
|
|
20681
20396
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
20682
20397
|
}
|
|
20683
20398
|
function extractRegistryErrorMessage3(payload) {
|
|
20684
|
-
if (!
|
|
20399
|
+
if (!isRecord6(payload)) {
|
|
20685
20400
|
return void 0;
|
|
20686
20401
|
}
|
|
20687
20402
|
const envelope = payload;
|
|
@@ -20755,13 +20470,13 @@ function mapRedeemInviteError(status, payload) {
|
|
|
20755
20470
|
return `Invite redeem failed (${status})`;
|
|
20756
20471
|
}
|
|
20757
20472
|
function parseInviteRecord(payload) {
|
|
20758
|
-
if (!
|
|
20473
|
+
if (!isRecord6(payload)) {
|
|
20759
20474
|
throw createCliError4(
|
|
20760
20475
|
"CLI_INVITE_CREATE_INVALID_RESPONSE",
|
|
20761
20476
|
"Invite response is invalid"
|
|
20762
20477
|
);
|
|
20763
20478
|
}
|
|
20764
|
-
const source =
|
|
20479
|
+
const source = isRecord6(payload.invite) ? payload.invite : payload;
|
|
20765
20480
|
const code = parseNonEmptyString6(source.code);
|
|
20766
20481
|
if (code.length === 0) {
|
|
20767
20482
|
throw createCliError4(
|
|
@@ -20786,15 +20501,15 @@ function parseInviteRecord(payload) {
|
|
|
20786
20501
|
return invite;
|
|
20787
20502
|
}
|
|
20788
20503
|
function parseInviteRedeemResponse(payload) {
|
|
20789
|
-
if (!
|
|
20504
|
+
if (!isRecord6(payload)) {
|
|
20790
20505
|
throw createCliError4(
|
|
20791
20506
|
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20792
20507
|
"Invite redeem response is invalid"
|
|
20793
20508
|
);
|
|
20794
20509
|
}
|
|
20795
|
-
const apiKeySource =
|
|
20510
|
+
const apiKeySource = isRecord6(payload.apiKey) ? payload.apiKey : payload;
|
|
20796
20511
|
const apiKeyToken = parseNonEmptyString6(
|
|
20797
|
-
|
|
20512
|
+
isRecord6(payload.apiKey) ? payload.apiKey.token : payload.token
|
|
20798
20513
|
);
|
|
20799
20514
|
if (apiKeyToken.length === 0) {
|
|
20800
20515
|
throw createCliError4(
|
|
@@ -20952,9 +20667,11 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20952
20667
|
};
|
|
20953
20668
|
|
|
20954
20669
|
// src/commands/openclaw.ts
|
|
20955
|
-
import {
|
|
20670
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
20671
|
+
import { existsSync } from "fs";
|
|
20672
|
+
import { chmod as chmod3, copyFile, mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
20956
20673
|
import { homedir as homedir3 } from "os";
|
|
20957
|
-
import { dirname as dirname4, join as
|
|
20674
|
+
import { dirname as dirname4, join as join6, resolve as resolvePath } from "path";
|
|
20958
20675
|
import { Command as Command7 } from "commander";
|
|
20959
20676
|
var logger8 = createLogger({ service: "cli", module: "openclaw" });
|
|
20960
20677
|
var CLAWDENTITY_DIR_NAME = ".clawdentity";
|
|
@@ -20964,25 +20681,32 @@ var SECRET_KEY_FILE_NAME2 = "secret.key";
|
|
|
20964
20681
|
var PEERS_FILE_NAME = "peers.json";
|
|
20965
20682
|
var OPENCLAW_DIR_NAME = ".openclaw";
|
|
20966
20683
|
var OPENCLAW_CONFIG_FILE_NAME = "openclaw.json";
|
|
20684
|
+
var LEGACY_OPENCLAW_STATE_DIR_NAMES = [".clawdbot", ".moldbot", ".moltbot"];
|
|
20685
|
+
var LEGACY_OPENCLAW_CONFIG_FILE_NAMES = ["clawdbot.json", "moldbot.json", "moltbot.json"];
|
|
20967
20686
|
var OPENCLAW_AGENT_FILE_NAME = "openclaw-agent-name";
|
|
20968
|
-
var
|
|
20687
|
+
var OPENCLAW_RELAY_RUNTIME_FILE_NAME2 = "openclaw-relay.json";
|
|
20688
|
+
var OPENCLAW_CONNECTORS_FILE_NAME2 = "openclaw-connectors.json";
|
|
20969
20689
|
var SKILL_DIR_NAME = "clawdentity-openclaw-relay";
|
|
20970
20690
|
var RELAY_MODULE_FILE_NAME = "relay-to-peer.mjs";
|
|
20691
|
+
var RELAY_RUNTIME_FILE_NAME = "clawdentity-relay.json";
|
|
20692
|
+
var RELAY_PEERS_FILE_NAME = "clawdentity-peers.json";
|
|
20971
20693
|
var HOOK_MAPPING_ID = "clawdentity-send-to-peer";
|
|
20972
20694
|
var HOOK_PATH_SEND_TO_PEER = "send-to-peer";
|
|
20973
20695
|
var OPENCLAW_SEND_TO_PEER_HOOK_PATH = "hooks/send-to-peer";
|
|
20974
20696
|
var DEFAULT_OPENCLAW_BASE_URL2 = "http://127.0.0.1:18789";
|
|
20975
|
-
var
|
|
20976
|
-
var
|
|
20977
|
-
var
|
|
20978
|
-
var
|
|
20979
|
-
var
|
|
20697
|
+
var DEFAULT_CONNECTOR_PORT = 19400;
|
|
20698
|
+
var DEFAULT_CONNECTOR_OUTBOUND_PATH3 = "/v1/outbound";
|
|
20699
|
+
var CONNECTOR_HOST_LOOPBACK = "127.0.0.1";
|
|
20700
|
+
var CONNECTOR_HOST_DOCKER = "host.docker.internal";
|
|
20701
|
+
var CONNECTOR_HOST_DOCKER_GATEWAY = "gateway.docker.internal";
|
|
20702
|
+
var CONNECTOR_HOST_LINUX_BRIDGE = "172.17.0.1";
|
|
20980
20703
|
var INVITE_CODE_PREFIX = "clawd1_";
|
|
20981
20704
|
var PEER_ALIAS_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
20982
20705
|
var FILE_MODE3 = 384;
|
|
20706
|
+
var OPENCLAW_HOOK_TOKEN_BYTES = 32;
|
|
20983
20707
|
var textEncoder2 = new TextEncoder();
|
|
20984
20708
|
var textDecoder = new TextDecoder();
|
|
20985
|
-
function
|
|
20709
|
+
function isRecord7(value) {
|
|
20986
20710
|
return typeof value === "object" && value !== null;
|
|
20987
20711
|
}
|
|
20988
20712
|
function createCliError5(code, message2, details) {
|
|
@@ -20994,7 +20718,7 @@ function createCliError5(code, message2, details) {
|
|
|
20994
20718
|
});
|
|
20995
20719
|
}
|
|
20996
20720
|
function getErrorCode2(error48) {
|
|
20997
|
-
if (!
|
|
20721
|
+
if (!isRecord7(error48)) {
|
|
20998
20722
|
return void 0;
|
|
20999
20723
|
}
|
|
21000
20724
|
return typeof error48.code === "string" ? error48.code : void 0;
|
|
@@ -21064,82 +20788,13 @@ function parseHttpUrl(value, input) {
|
|
|
21064
20788
|
}
|
|
21065
20789
|
return parsedUrl.toString();
|
|
21066
20790
|
}
|
|
21067
|
-
function
|
|
20791
|
+
function parseOpenclawBaseUrl(value) {
|
|
21068
20792
|
return parseHttpUrl(value, {
|
|
21069
20793
|
label: "OpenClaw base URL",
|
|
21070
20794
|
code: "CLI_OPENCLAW_INVALID_OPENCLAW_BASE_URL",
|
|
21071
20795
|
message: "OpenClaw base URL must be a valid URL"
|
|
21072
20796
|
});
|
|
21073
20797
|
}
|
|
21074
|
-
function parseBooleanValue(value, label) {
|
|
21075
|
-
if (typeof value === "boolean") {
|
|
21076
|
-
return value;
|
|
21077
|
-
}
|
|
21078
|
-
if (typeof value === "string") {
|
|
21079
|
-
const normalized = value.trim().toLowerCase();
|
|
21080
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
|
|
21081
|
-
return true;
|
|
21082
|
-
}
|
|
21083
|
-
if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
|
|
21084
|
-
return false;
|
|
21085
|
-
}
|
|
21086
|
-
}
|
|
21087
|
-
throw createCliError5(
|
|
21088
|
-
"CLI_OPENCLAW_INVALID_INPUT",
|
|
21089
|
-
`${label} must be true or false`,
|
|
21090
|
-
{ label }
|
|
21091
|
-
);
|
|
21092
|
-
}
|
|
21093
|
-
function parseRelayEchoChannel(value) {
|
|
21094
|
-
return parseNonEmptyString7(value, "relay echo channel");
|
|
21095
|
-
}
|
|
21096
|
-
function parseRelayEchoMaxLength(value) {
|
|
21097
|
-
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
21098
|
-
if (!Number.isInteger(parsed) || parsed < MIN_RELAY_ECHO_MAX_LENGTH || parsed > MAX_RELAY_ECHO_MAX_LENGTH) {
|
|
21099
|
-
throw createCliError5(
|
|
21100
|
-
"CLI_OPENCLAW_INVALID_ECHO_MAX_LENGTH",
|
|
21101
|
-
`echo max length must be an integer between ${MIN_RELAY_ECHO_MAX_LENGTH} and ${MAX_RELAY_ECHO_MAX_LENGTH}`
|
|
21102
|
-
);
|
|
21103
|
-
}
|
|
21104
|
-
return parsed;
|
|
21105
|
-
}
|
|
21106
|
-
function parseRelayEchoEnabled(value) {
|
|
21107
|
-
return parseBooleanValue(value, "relay echo enabled");
|
|
21108
|
-
}
|
|
21109
|
-
function parseRelayEchoTo(value) {
|
|
21110
|
-
if (value === void 0) {
|
|
21111
|
-
return void 0;
|
|
21112
|
-
}
|
|
21113
|
-
if (typeof value !== "string") {
|
|
21114
|
-
throw createCliError5(
|
|
21115
|
-
"CLI_OPENCLAW_INVALID_INPUT",
|
|
21116
|
-
"relay echo target must be a string",
|
|
21117
|
-
{ label: "relay echo target" }
|
|
21118
|
-
);
|
|
21119
|
-
}
|
|
21120
|
-
const trimmed = value.trim();
|
|
21121
|
-
if (trimmed.length === 0) {
|
|
21122
|
-
return void 0;
|
|
21123
|
-
}
|
|
21124
|
-
return trimmed;
|
|
21125
|
-
}
|
|
21126
|
-
function defaultRelayEchoConfig() {
|
|
21127
|
-
return {
|
|
21128
|
-
enabled: DEFAULT_RELAY_ECHO_ENABLED2,
|
|
21129
|
-
channel: DEFAULT_RELAY_ECHO_CHANNEL2,
|
|
21130
|
-
maxLength: DEFAULT_RELAY_ECHO_MAX_LENGTH2
|
|
21131
|
-
};
|
|
21132
|
-
}
|
|
21133
|
-
function resolveSetupRelayEchoConfig(input) {
|
|
21134
|
-
const current = input.existingConfig?.echo ?? defaultRelayEchoConfig();
|
|
21135
|
-
const options = input.options;
|
|
21136
|
-
return {
|
|
21137
|
-
enabled: options.echoEnabled === void 0 ? current.enabled : parseRelayEchoEnabled(options.echoEnabled),
|
|
21138
|
-
channel: options.echoChannel === void 0 ? current.channel : parseRelayEchoChannel(options.echoChannel),
|
|
21139
|
-
to: options.echoTo === void 0 ? current.to : parseRelayEchoTo(options.echoTo),
|
|
21140
|
-
maxLength: options.echoMaxLength === void 0 ? current.maxLength : parseRelayEchoMaxLength(options.echoMaxLength)
|
|
21141
|
-
};
|
|
21142
|
-
}
|
|
21143
20798
|
function parseAgentDid2(value, label) {
|
|
21144
20799
|
const did = parseNonEmptyString7(value, label);
|
|
21145
20800
|
try {
|
|
@@ -21158,7 +20813,7 @@ function parseAgentDid2(value, label) {
|
|
|
21158
20813
|
return did;
|
|
21159
20814
|
}
|
|
21160
20815
|
function parseInvitePayload(value) {
|
|
21161
|
-
if (!
|
|
20816
|
+
if (!isRecord7(value)) {
|
|
21162
20817
|
throw createCliError5(
|
|
21163
20818
|
"CLI_OPENCLAW_INVALID_INVITE",
|
|
21164
20819
|
"invite payload must be an object"
|
|
@@ -21207,23 +20862,86 @@ function resolveHomeDir(homeDir) {
|
|
|
21207
20862
|
}
|
|
21208
20863
|
return homedir3();
|
|
21209
20864
|
}
|
|
20865
|
+
function resolveHomePrefixedPath(input, homeDir) {
|
|
20866
|
+
const trimmed = input.trim();
|
|
20867
|
+
if (trimmed.startsWith("~")) {
|
|
20868
|
+
return resolvePath(trimmed.replace(/^~(?=$|[\\/])/, homeDir));
|
|
20869
|
+
}
|
|
20870
|
+
return resolvePath(trimmed);
|
|
20871
|
+
}
|
|
20872
|
+
function readNonEmptyEnvPath(value, homeDir) {
|
|
20873
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
20874
|
+
return void 0;
|
|
20875
|
+
}
|
|
20876
|
+
return resolveHomePrefixedPath(value, homeDir);
|
|
20877
|
+
}
|
|
20878
|
+
function resolveOpenclawHomeDir(homeDir) {
|
|
20879
|
+
const envOpenclawHome = readNonEmptyEnvPath(process.env.OPENCLAW_HOME, homeDir);
|
|
20880
|
+
return envOpenclawHome ?? homeDir;
|
|
20881
|
+
}
|
|
20882
|
+
function resolveDefaultOpenclawStateDir(openclawHomeDir) {
|
|
20883
|
+
const newStateDir = join6(openclawHomeDir, OPENCLAW_DIR_NAME);
|
|
20884
|
+
if (existsSync(newStateDir)) {
|
|
20885
|
+
return newStateDir;
|
|
20886
|
+
}
|
|
20887
|
+
for (const legacyDirName of LEGACY_OPENCLAW_STATE_DIR_NAMES) {
|
|
20888
|
+
const legacyStateDir = join6(openclawHomeDir, legacyDirName);
|
|
20889
|
+
if (existsSync(legacyStateDir)) {
|
|
20890
|
+
return legacyStateDir;
|
|
20891
|
+
}
|
|
20892
|
+
}
|
|
20893
|
+
return newStateDir;
|
|
20894
|
+
}
|
|
21210
20895
|
function resolveOpenclawDir(openclawDir, homeDir) {
|
|
21211
20896
|
if (typeof openclawDir === "string" && openclawDir.trim().length > 0) {
|
|
21212
|
-
return openclawDir
|
|
20897
|
+
return resolveHomePrefixedPath(openclawDir, homeDir);
|
|
20898
|
+
}
|
|
20899
|
+
const envStateDir = readNonEmptyEnvPath(
|
|
20900
|
+
process.env.OPENCLAW_STATE_DIR ?? process.env.CLAWDBOT_STATE_DIR,
|
|
20901
|
+
homeDir
|
|
20902
|
+
);
|
|
20903
|
+
if (envStateDir !== void 0) {
|
|
20904
|
+
return envStateDir;
|
|
21213
20905
|
}
|
|
21214
|
-
|
|
20906
|
+
const envConfigPath = readNonEmptyEnvPath(
|
|
20907
|
+
process.env.OPENCLAW_CONFIG_PATH ?? process.env.CLAWDBOT_CONFIG_PATH,
|
|
20908
|
+
homeDir
|
|
20909
|
+
);
|
|
20910
|
+
if (envConfigPath !== void 0) {
|
|
20911
|
+
return dirname4(envConfigPath);
|
|
20912
|
+
}
|
|
20913
|
+
const openclawHomeDir = resolveOpenclawHomeDir(homeDir);
|
|
20914
|
+
return resolveDefaultOpenclawStateDir(openclawHomeDir);
|
|
21215
20915
|
}
|
|
21216
20916
|
function resolveAgentDirectory(homeDir, agentName) {
|
|
21217
|
-
return
|
|
20917
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, AGENTS_DIR_NAME4, agentName);
|
|
21218
20918
|
}
|
|
21219
20919
|
function resolvePeersPath(homeDir) {
|
|
21220
|
-
return
|
|
20920
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, PEERS_FILE_NAME);
|
|
21221
20921
|
}
|
|
21222
|
-
function resolveOpenclawConfigPath(openclawDir) {
|
|
21223
|
-
|
|
20922
|
+
function resolveOpenclawConfigPath(openclawDir, homeDir) {
|
|
20923
|
+
const envConfigPath = readNonEmptyEnvPath(
|
|
20924
|
+
process.env.OPENCLAW_CONFIG_PATH ?? process.env.CLAWDBOT_CONFIG_PATH,
|
|
20925
|
+
homeDir
|
|
20926
|
+
);
|
|
20927
|
+
if (envConfigPath !== void 0) {
|
|
20928
|
+
return envConfigPath;
|
|
20929
|
+
}
|
|
20930
|
+
const configCandidates = [
|
|
20931
|
+
join6(openclawDir, OPENCLAW_CONFIG_FILE_NAME),
|
|
20932
|
+
...LEGACY_OPENCLAW_CONFIG_FILE_NAMES.map(
|
|
20933
|
+
(fileName) => join6(openclawDir, fileName)
|
|
20934
|
+
)
|
|
20935
|
+
];
|
|
20936
|
+
for (const candidate of configCandidates) {
|
|
20937
|
+
if (existsSync(candidate)) {
|
|
20938
|
+
return candidate;
|
|
20939
|
+
}
|
|
20940
|
+
}
|
|
20941
|
+
return configCandidates[0];
|
|
21224
20942
|
}
|
|
21225
20943
|
function resolveDefaultTransformSource(openclawDir) {
|
|
21226
|
-
return
|
|
20944
|
+
return join6(
|
|
21227
20945
|
openclawDir,
|
|
21228
20946
|
"workspace",
|
|
21229
20947
|
"skills",
|
|
@@ -21232,16 +20950,25 @@ function resolveDefaultTransformSource(openclawDir) {
|
|
|
21232
20950
|
);
|
|
21233
20951
|
}
|
|
21234
20952
|
function resolveTransformTargetPath(openclawDir) {
|
|
21235
|
-
return
|
|
20953
|
+
return join6(openclawDir, "hooks", "transforms", RELAY_MODULE_FILE_NAME);
|
|
21236
20954
|
}
|
|
21237
20955
|
function resolveOpenclawAgentNamePath(homeDir) {
|
|
21238
|
-
return
|
|
20956
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, OPENCLAW_AGENT_FILE_NAME);
|
|
21239
20957
|
}
|
|
21240
20958
|
function resolveRelayRuntimeConfigPath(homeDir) {
|
|
21241
|
-
return
|
|
20959
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, OPENCLAW_RELAY_RUNTIME_FILE_NAME2);
|
|
20960
|
+
}
|
|
20961
|
+
function resolveConnectorAssignmentsPath(homeDir) {
|
|
20962
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, OPENCLAW_CONNECTORS_FILE_NAME2);
|
|
20963
|
+
}
|
|
20964
|
+
function resolveTransformRuntimePath(openclawDir) {
|
|
20965
|
+
return join6(openclawDir, "hooks", "transforms", RELAY_RUNTIME_FILE_NAME);
|
|
20966
|
+
}
|
|
20967
|
+
function resolveTransformPeersPath(openclawDir) {
|
|
20968
|
+
return join6(openclawDir, "hooks", "transforms", RELAY_PEERS_FILE_NAME);
|
|
21242
20969
|
}
|
|
21243
20970
|
async function readJsonFile(filePath) {
|
|
21244
|
-
const raw = await
|
|
20971
|
+
const raw = await readFile4(filePath, "utf8");
|
|
21245
20972
|
try {
|
|
21246
20973
|
return JSON.parse(raw);
|
|
21247
20974
|
} catch {
|
|
@@ -21253,13 +20980,13 @@ async function readJsonFile(filePath) {
|
|
|
21253
20980
|
async function ensureLocalAgentCredentials(homeDir, agentName) {
|
|
21254
20981
|
const agentDir = resolveAgentDirectory(homeDir, agentName);
|
|
21255
20982
|
const requiredFiles = [
|
|
21256
|
-
|
|
21257
|
-
|
|
20983
|
+
join6(agentDir, SECRET_KEY_FILE_NAME2),
|
|
20984
|
+
join6(agentDir, AIT_FILE_NAME3)
|
|
21258
20985
|
];
|
|
21259
20986
|
for (const filePath of requiredFiles) {
|
|
21260
20987
|
let content;
|
|
21261
20988
|
try {
|
|
21262
|
-
content = await
|
|
20989
|
+
content = await readFile4(filePath, "utf8");
|
|
21263
20990
|
} catch (error48) {
|
|
21264
20991
|
if (getErrorCode2(error48) === "ENOENT") {
|
|
21265
20992
|
throw createCliError5(
|
|
@@ -21333,7 +21060,7 @@ async function loadPeersConfig(peersPath) {
|
|
|
21333
21060
|
}
|
|
21334
21061
|
throw error48;
|
|
21335
21062
|
}
|
|
21336
|
-
if (!
|
|
21063
|
+
if (!isRecord7(parsed)) {
|
|
21337
21064
|
throw createCliError5(
|
|
21338
21065
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21339
21066
|
"Peer config root must be a JSON object",
|
|
@@ -21344,7 +21071,7 @@ async function loadPeersConfig(peersPath) {
|
|
|
21344
21071
|
if (peersValue === void 0) {
|
|
21345
21072
|
return { peers: {} };
|
|
21346
21073
|
}
|
|
21347
|
-
if (!
|
|
21074
|
+
if (!isRecord7(peersValue)) {
|
|
21348
21075
|
throw createCliError5(
|
|
21349
21076
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21350
21077
|
"Peer config peers field must be an object",
|
|
@@ -21354,7 +21081,7 @@ async function loadPeersConfig(peersPath) {
|
|
|
21354
21081
|
const peers = {};
|
|
21355
21082
|
for (const [alias, value] of Object.entries(peersValue)) {
|
|
21356
21083
|
const normalizedAlias = parsePeerAlias(alias);
|
|
21357
|
-
if (!
|
|
21084
|
+
if (!isRecord7(value)) {
|
|
21358
21085
|
throw createCliError5(
|
|
21359
21086
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21360
21087
|
"Peer entry must be an object",
|
|
@@ -21376,35 +21103,100 @@ async function savePeersConfig(peersPath, config2) {
|
|
|
21376
21103
|
await writeSecureFile3(peersPath, `${JSON.stringify(config2, null, 2)}
|
|
21377
21104
|
`);
|
|
21378
21105
|
}
|
|
21379
|
-
function
|
|
21380
|
-
|
|
21381
|
-
|
|
21382
|
-
|
|
21383
|
-
|
|
21106
|
+
function parseConnectorBaseUrlForAssignment(value, label) {
|
|
21107
|
+
return parseHttpUrl(value, {
|
|
21108
|
+
label,
|
|
21109
|
+
code: "CLI_OPENCLAW_INVALID_CONNECTOR_BASE_URL",
|
|
21110
|
+
message: "Connector base URL must be a valid URL"
|
|
21111
|
+
});
|
|
21112
|
+
}
|
|
21113
|
+
function parseConnectorAssignments(value, connectorAssignmentsPath) {
|
|
21114
|
+
if (!isRecord7(value)) {
|
|
21384
21115
|
throw createCliError5(
|
|
21385
|
-
"
|
|
21386
|
-
"
|
|
21387
|
-
{
|
|
21116
|
+
"CLI_OPENCLAW_INVALID_CONNECTOR_ASSIGNMENTS",
|
|
21117
|
+
"Connector assignments config must be an object",
|
|
21118
|
+
{ connectorAssignmentsPath }
|
|
21388
21119
|
);
|
|
21389
21120
|
}
|
|
21390
|
-
const
|
|
21391
|
-
|
|
21392
|
-
return {
|
|
21393
|
-
|
|
21394
|
-
|
|
21395
|
-
|
|
21396
|
-
|
|
21121
|
+
const agentsRaw = value.agents;
|
|
21122
|
+
if (!isRecord7(agentsRaw)) {
|
|
21123
|
+
return { agents: {} };
|
|
21124
|
+
}
|
|
21125
|
+
const agents = {};
|
|
21126
|
+
for (const [agentName, entryValue] of Object.entries(agentsRaw)) {
|
|
21127
|
+
if (!isRecord7(entryValue)) {
|
|
21128
|
+
throw createCliError5(
|
|
21129
|
+
"CLI_OPENCLAW_INVALID_CONNECTOR_ASSIGNMENTS",
|
|
21130
|
+
"Connector assignment entry must be an object",
|
|
21131
|
+
{ connectorAssignmentsPath, agentName }
|
|
21132
|
+
);
|
|
21133
|
+
}
|
|
21134
|
+
const connectorBaseUrl = parseConnectorBaseUrlForAssignment(
|
|
21135
|
+
entryValue.connectorBaseUrl,
|
|
21136
|
+
"connectorBaseUrl"
|
|
21137
|
+
);
|
|
21138
|
+
const updatedAt = typeof entryValue.updatedAt === "string" && entryValue.updatedAt.trim().length > 0 ? entryValue.updatedAt.trim() : nowIso();
|
|
21139
|
+
agents[assertValidAgentName(agentName)] = {
|
|
21140
|
+
connectorBaseUrl,
|
|
21141
|
+
updatedAt
|
|
21397
21142
|
};
|
|
21143
|
+
}
|
|
21144
|
+
return { agents };
|
|
21145
|
+
}
|
|
21146
|
+
async function loadConnectorAssignments(connectorAssignmentsPath) {
|
|
21147
|
+
let parsed;
|
|
21148
|
+
try {
|
|
21149
|
+
parsed = await readJsonFile(connectorAssignmentsPath);
|
|
21398
21150
|
} catch (error48) {
|
|
21399
|
-
|
|
21400
|
-
|
|
21401
|
-
|
|
21402
|
-
|
|
21403
|
-
);
|
|
21151
|
+
if (getErrorCode2(error48) === "ENOENT") {
|
|
21152
|
+
return { agents: {} };
|
|
21153
|
+
}
|
|
21154
|
+
throw error48;
|
|
21404
21155
|
}
|
|
21156
|
+
return parseConnectorAssignments(parsed, connectorAssignmentsPath);
|
|
21157
|
+
}
|
|
21158
|
+
async function saveConnectorAssignments(connectorAssignmentsPath, config2) {
|
|
21159
|
+
await writeSecureFile3(
|
|
21160
|
+
connectorAssignmentsPath,
|
|
21161
|
+
`${JSON.stringify(config2, null, 2)}
|
|
21162
|
+
`
|
|
21163
|
+
);
|
|
21164
|
+
}
|
|
21165
|
+
function parseConnectorPortFromBaseUrl(baseUrl) {
|
|
21166
|
+
const parsed = new URL(baseUrl);
|
|
21167
|
+
if (parsed.port) {
|
|
21168
|
+
return Number(parsed.port);
|
|
21169
|
+
}
|
|
21170
|
+
return parsed.protocol === "https:" ? 443 : 80;
|
|
21171
|
+
}
|
|
21172
|
+
function allocateConnectorPort(assignments, agentName) {
|
|
21173
|
+
const existing = assignments.agents[agentName];
|
|
21174
|
+
if (existing) {
|
|
21175
|
+
return parseConnectorPortFromBaseUrl(existing.connectorBaseUrl);
|
|
21176
|
+
}
|
|
21177
|
+
const usedPorts = /* @__PURE__ */ new Set();
|
|
21178
|
+
for (const entry of Object.values(assignments.agents)) {
|
|
21179
|
+
usedPorts.add(parseConnectorPortFromBaseUrl(entry.connectorBaseUrl));
|
|
21180
|
+
}
|
|
21181
|
+
let nextPort = DEFAULT_CONNECTOR_PORT;
|
|
21182
|
+
while (usedPorts.has(nextPort)) {
|
|
21183
|
+
nextPort += 1;
|
|
21184
|
+
}
|
|
21185
|
+
return nextPort;
|
|
21186
|
+
}
|
|
21187
|
+
function buildConnectorBaseUrl(host, port) {
|
|
21188
|
+
return `http://${host}:${port}`;
|
|
21189
|
+
}
|
|
21190
|
+
function buildRelayConnectorBaseUrls(port) {
|
|
21191
|
+
return [
|
|
21192
|
+
buildConnectorBaseUrl(CONNECTOR_HOST_DOCKER, port),
|
|
21193
|
+
buildConnectorBaseUrl(CONNECTOR_HOST_DOCKER_GATEWAY, port),
|
|
21194
|
+
buildConnectorBaseUrl(CONNECTOR_HOST_LINUX_BRIDGE, port),
|
|
21195
|
+
buildConnectorBaseUrl(CONNECTOR_HOST_LOOPBACK, port)
|
|
21196
|
+
];
|
|
21405
21197
|
}
|
|
21406
21198
|
function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
21407
|
-
if (!
|
|
21199
|
+
if (!isRecord7(value)) {
|
|
21408
21200
|
throw createCliError5(
|
|
21409
21201
|
"CLI_OPENCLAW_INVALID_RELAY_RUNTIME_CONFIG",
|
|
21410
21202
|
"Relay runtime config must be an object",
|
|
@@ -21412,11 +21204,11 @@ function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
|
21412
21204
|
);
|
|
21413
21205
|
}
|
|
21414
21206
|
const updatedAt = typeof value.updatedAt === "string" && value.updatedAt.trim().length > 0 ? value.updatedAt.trim() : void 0;
|
|
21415
|
-
const
|
|
21207
|
+
const openclawHookToken = typeof value.openclawHookToken === "string" && value.openclawHookToken.trim().length > 0 ? value.openclawHookToken.trim() : void 0;
|
|
21416
21208
|
return {
|
|
21417
|
-
openclawBaseUrl:
|
|
21418
|
-
|
|
21419
|
-
|
|
21209
|
+
openclawBaseUrl: parseOpenclawBaseUrl(value.openclawBaseUrl),
|
|
21210
|
+
openclawHookToken,
|
|
21211
|
+
updatedAt
|
|
21420
21212
|
};
|
|
21421
21213
|
}
|
|
21422
21214
|
async function loadRelayRuntimeConfig(relayRuntimeConfigPath) {
|
|
@@ -21431,11 +21223,11 @@ async function loadRelayRuntimeConfig(relayRuntimeConfigPath) {
|
|
|
21431
21223
|
}
|
|
21432
21224
|
return parseRelayRuntimeConfig(parsed, relayRuntimeConfigPath);
|
|
21433
21225
|
}
|
|
21434
|
-
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl,
|
|
21226
|
+
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, openclawHookToken) {
|
|
21435
21227
|
const config2 = {
|
|
21436
21228
|
openclawBaseUrl,
|
|
21437
|
-
|
|
21438
|
-
|
|
21229
|
+
...openclawHookToken ? { openclawHookToken } : {},
|
|
21230
|
+
updatedAt: nowIso()
|
|
21439
21231
|
};
|
|
21440
21232
|
await writeSecureFile3(
|
|
21441
21233
|
relayRuntimeConfigPath,
|
|
@@ -21443,13 +21235,13 @@ async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, r
|
|
|
21443
21235
|
`
|
|
21444
21236
|
);
|
|
21445
21237
|
}
|
|
21446
|
-
async function
|
|
21238
|
+
async function resolveOpenclawBaseUrl2(input) {
|
|
21447
21239
|
if (typeof input.optionValue === "string" && input.optionValue.trim().length > 0) {
|
|
21448
|
-
return
|
|
21240
|
+
return parseOpenclawBaseUrl(input.optionValue);
|
|
21449
21241
|
}
|
|
21450
21242
|
const envOpenclawBaseUrl = process.env.OPENCLAW_BASE_URL;
|
|
21451
21243
|
if (typeof envOpenclawBaseUrl === "string" && envOpenclawBaseUrl.trim().length > 0) {
|
|
21452
|
-
return
|
|
21244
|
+
return parseOpenclawBaseUrl(envOpenclawBaseUrl);
|
|
21453
21245
|
}
|
|
21454
21246
|
const existingConfig = await loadRelayRuntimeConfig(
|
|
21455
21247
|
input.relayRuntimeConfigPath
|
|
@@ -21475,21 +21267,24 @@ function normalizeStringArrayWithValue(value, requiredValue) {
|
|
|
21475
21267
|
normalized.add(requiredValue);
|
|
21476
21268
|
return Array.from(normalized);
|
|
21477
21269
|
}
|
|
21270
|
+
function generateOpenclawHookToken() {
|
|
21271
|
+
return randomBytes3(OPENCLAW_HOOK_TOKEN_BYTES).toString("hex");
|
|
21272
|
+
}
|
|
21478
21273
|
function upsertRelayHookMapping(mappingsValue) {
|
|
21479
|
-
const mappings = Array.isArray(mappingsValue) ? mappingsValue.filter(
|
|
21274
|
+
const mappings = Array.isArray(mappingsValue) ? mappingsValue.filter(isRecord7).map((mapping) => ({ ...mapping })) : [];
|
|
21480
21275
|
const existingIndex = mappings.findIndex((mapping) => {
|
|
21481
21276
|
if (mapping.id === HOOK_MAPPING_ID) {
|
|
21482
21277
|
return true;
|
|
21483
21278
|
}
|
|
21484
|
-
if (!
|
|
21279
|
+
if (!isRecord7(mapping.match)) {
|
|
21485
21280
|
return false;
|
|
21486
21281
|
}
|
|
21487
21282
|
return mapping.match.path === HOOK_PATH_SEND_TO_PEER;
|
|
21488
21283
|
});
|
|
21489
|
-
const baseMapping = existingIndex >= 0 &&
|
|
21490
|
-
const nextMatch =
|
|
21284
|
+
const baseMapping = existingIndex >= 0 && isRecord7(mappings[existingIndex]) ? mappings[existingIndex] : {};
|
|
21285
|
+
const nextMatch = isRecord7(baseMapping.match) ? { ...baseMapping.match } : {};
|
|
21491
21286
|
nextMatch.path = HOOK_PATH_SEND_TO_PEER;
|
|
21492
|
-
const nextTransform =
|
|
21287
|
+
const nextTransform = isRecord7(baseMapping.transform) ? { ...baseMapping.transform } : {};
|
|
21493
21288
|
nextTransform.module = RELAY_MODULE_FILE_NAME;
|
|
21494
21289
|
const relayMapping = {
|
|
21495
21290
|
...baseMapping,
|
|
@@ -21506,7 +21301,7 @@ function upsertRelayHookMapping(mappingsValue) {
|
|
|
21506
21301
|
mappings.push(relayMapping);
|
|
21507
21302
|
return mappings;
|
|
21508
21303
|
}
|
|
21509
|
-
async function patchOpenclawConfig(openclawConfigPath) {
|
|
21304
|
+
async function patchOpenclawConfig(openclawConfigPath, hookToken) {
|
|
21510
21305
|
let config2;
|
|
21511
21306
|
try {
|
|
21512
21307
|
config2 = await readJsonFile(openclawConfigPath);
|
|
@@ -21520,15 +21315,19 @@ async function patchOpenclawConfig(openclawConfigPath) {
|
|
|
21520
21315
|
}
|
|
21521
21316
|
throw error48;
|
|
21522
21317
|
}
|
|
21523
|
-
if (!
|
|
21318
|
+
if (!isRecord7(config2)) {
|
|
21524
21319
|
throw createCliError5(
|
|
21525
21320
|
"CLI_OPENCLAW_INVALID_CONFIG",
|
|
21526
21321
|
"OpenClaw config root must be an object",
|
|
21527
21322
|
{ openclawConfigPath }
|
|
21528
21323
|
);
|
|
21529
21324
|
}
|
|
21530
|
-
const hooks =
|
|
21325
|
+
const hooks = isRecord7(config2.hooks) ? { ...config2.hooks } : {};
|
|
21326
|
+
const existingHookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
21327
|
+
const preferredHookToken = typeof hookToken === "string" && hookToken.trim().length > 0 ? hookToken.trim() : void 0;
|
|
21328
|
+
const resolvedHookToken = existingHookToken ?? preferredHookToken ?? generateOpenclawHookToken();
|
|
21531
21329
|
hooks.enabled = true;
|
|
21330
|
+
hooks.token = resolvedHookToken;
|
|
21532
21331
|
hooks.allowRequestSessionKey = false;
|
|
21533
21332
|
hooks.allowedSessionKeyPrefixes = normalizeStringArrayWithValue(
|
|
21534
21333
|
hooks.allowedSessionKeyPrefixes,
|
|
@@ -21545,6 +21344,9 @@ async function patchOpenclawConfig(openclawConfigPath) {
|
|
|
21545
21344
|
`,
|
|
21546
21345
|
"utf8"
|
|
21547
21346
|
);
|
|
21347
|
+
return {
|
|
21348
|
+
hookToken: resolvedHookToken
|
|
21349
|
+
};
|
|
21548
21350
|
}
|
|
21549
21351
|
function toDoctorCheck(input) {
|
|
21550
21352
|
return input;
|
|
@@ -21557,10 +21359,10 @@ function toDoctorResult(checks) {
|
|
|
21557
21359
|
};
|
|
21558
21360
|
}
|
|
21559
21361
|
function isRelayHookMapping(value) {
|
|
21560
|
-
if (!
|
|
21362
|
+
if (!isRecord7(value)) {
|
|
21561
21363
|
return false;
|
|
21562
21364
|
}
|
|
21563
|
-
if (!
|
|
21365
|
+
if (!isRecord7(value.match) || value.match.path !== HOOK_PATH_SEND_TO_PEER) {
|
|
21564
21366
|
return false;
|
|
21565
21367
|
}
|
|
21566
21368
|
if (typeof value.id === "string" && value.id !== HOOK_MAPPING_ID) {
|
|
@@ -21569,7 +21371,7 @@ function isRelayHookMapping(value) {
|
|
|
21569
21371
|
return true;
|
|
21570
21372
|
}
|
|
21571
21373
|
function hasRelayTransformModule(value) {
|
|
21572
|
-
if (!
|
|
21374
|
+
if (!isRecord7(value) || !isRecord7(value.transform)) {
|
|
21573
21375
|
return false;
|
|
21574
21376
|
}
|
|
21575
21377
|
return value.transform.module === RELAY_MODULE_FILE_NAME;
|
|
@@ -21580,8 +21382,8 @@ function parseDoctorPeerAlias(peerAlias) {
|
|
|
21580
21382
|
}
|
|
21581
21383
|
return parsePeerAlias(peerAlias);
|
|
21582
21384
|
}
|
|
21583
|
-
function resolveHookToken(
|
|
21584
|
-
const trimmedOption = optionValue?.trim();
|
|
21385
|
+
async function resolveHookToken(input) {
|
|
21386
|
+
const trimmedOption = input.optionValue?.trim();
|
|
21585
21387
|
if (trimmedOption !== void 0 && trimmedOption.length > 0) {
|
|
21586
21388
|
return trimmedOption;
|
|
21587
21389
|
}
|
|
@@ -21589,6 +21391,12 @@ function resolveHookToken(optionValue) {
|
|
|
21589
21391
|
if (envValue !== void 0 && envValue.length > 0) {
|
|
21590
21392
|
return envValue;
|
|
21591
21393
|
}
|
|
21394
|
+
const existingConfig = await loadRelayRuntimeConfig(
|
|
21395
|
+
input.relayRuntimeConfigPath
|
|
21396
|
+
);
|
|
21397
|
+
if (existingConfig?.openclawHookToken) {
|
|
21398
|
+
return existingConfig.openclawHookToken;
|
|
21399
|
+
}
|
|
21592
21400
|
return void 0;
|
|
21593
21401
|
}
|
|
21594
21402
|
function resolveProbeMessage(optionValue) {
|
|
@@ -21686,7 +21494,7 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21686
21494
|
const selectedAgentPath = resolveOpenclawAgentNamePath(homeDir);
|
|
21687
21495
|
let selectedAgentName;
|
|
21688
21496
|
try {
|
|
21689
|
-
const selectedAgentRaw = await
|
|
21497
|
+
const selectedAgentRaw = await readFile4(selectedAgentPath, "utf8");
|
|
21690
21498
|
selectedAgentName = assertValidAgentName(selectedAgentRaw.trim());
|
|
21691
21499
|
checks.push(
|
|
21692
21500
|
toDoctorCheck({
|
|
@@ -21807,17 +21615,28 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21807
21615
|
);
|
|
21808
21616
|
}
|
|
21809
21617
|
const transformTargetPath = resolveTransformTargetPath(openclawDir);
|
|
21618
|
+
const relayTransformRuntimePath = resolveTransformRuntimePath(openclawDir);
|
|
21619
|
+
const relayTransformPeersPath = resolveTransformPeersPath(openclawDir);
|
|
21810
21620
|
try {
|
|
21811
|
-
const transformContents = await
|
|
21812
|
-
|
|
21621
|
+
const transformContents = await readFile4(transformTargetPath, "utf8");
|
|
21622
|
+
const runtimeContents = await readFile4(relayTransformRuntimePath, "utf8");
|
|
21623
|
+
const peersSnapshotContents = await readFile4(
|
|
21624
|
+
relayTransformPeersPath,
|
|
21625
|
+
"utf8"
|
|
21626
|
+
);
|
|
21627
|
+
if (transformContents.trim().length === 0 || runtimeContents.trim().length === 0 || peersSnapshotContents.trim().length === 0) {
|
|
21813
21628
|
checks.push(
|
|
21814
21629
|
toDoctorCheck({
|
|
21815
21630
|
id: "state.transform",
|
|
21816
21631
|
label: "Relay transform",
|
|
21817
21632
|
status: "fail",
|
|
21818
|
-
message:
|
|
21633
|
+
message: "relay transform artifacts are missing or empty",
|
|
21819
21634
|
remediationHint: "Run: npm install clawdentity --skill",
|
|
21820
|
-
details: {
|
|
21635
|
+
details: {
|
|
21636
|
+
transformTargetPath,
|
|
21637
|
+
relayTransformRuntimePath,
|
|
21638
|
+
relayTransformPeersPath
|
|
21639
|
+
}
|
|
21821
21640
|
})
|
|
21822
21641
|
);
|
|
21823
21642
|
} else {
|
|
@@ -21826,8 +21645,12 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21826
21645
|
id: "state.transform",
|
|
21827
21646
|
label: "Relay transform",
|
|
21828
21647
|
status: "pass",
|
|
21829
|
-
message: "relay transform
|
|
21830
|
-
details: {
|
|
21648
|
+
message: "relay transform artifacts are present",
|
|
21649
|
+
details: {
|
|
21650
|
+
transformTargetPath,
|
|
21651
|
+
relayTransformRuntimePath,
|
|
21652
|
+
relayTransformPeersPath
|
|
21653
|
+
}
|
|
21831
21654
|
})
|
|
21832
21655
|
);
|
|
21833
21656
|
}
|
|
@@ -21837,20 +21660,26 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21837
21660
|
id: "state.transform",
|
|
21838
21661
|
label: "Relay transform",
|
|
21839
21662
|
status: "fail",
|
|
21840
|
-
message:
|
|
21663
|
+
message: "missing relay transform artifacts",
|
|
21841
21664
|
remediationHint: "Run: npm install clawdentity --skill",
|
|
21842
|
-
details: {
|
|
21665
|
+
details: {
|
|
21666
|
+
transformTargetPath,
|
|
21667
|
+
relayTransformRuntimePath,
|
|
21668
|
+
relayTransformPeersPath
|
|
21669
|
+
}
|
|
21843
21670
|
})
|
|
21844
21671
|
);
|
|
21845
21672
|
}
|
|
21846
|
-
const openclawConfigPath = resolveOpenclawConfigPath(openclawDir);
|
|
21673
|
+
const openclawConfigPath = resolveOpenclawConfigPath(openclawDir, homeDir);
|
|
21847
21674
|
try {
|
|
21848
21675
|
const openclawConfig = await readJsonFile(openclawConfigPath);
|
|
21849
|
-
if (!
|
|
21676
|
+
if (!isRecord7(openclawConfig)) {
|
|
21850
21677
|
throw new Error("root");
|
|
21851
21678
|
}
|
|
21852
|
-
const hooks =
|
|
21853
|
-
const
|
|
21679
|
+
const hooks = isRecord7(openclawConfig.hooks) ? openclawConfig.hooks : {};
|
|
21680
|
+
const hooksEnabled = hooks.enabled === true;
|
|
21681
|
+
const hookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
21682
|
+
const mappings = Array.isArray(hooks.mappings) ? hooks.mappings.filter(isRecord7) : [];
|
|
21854
21683
|
const relayMapping = mappings.find(
|
|
21855
21684
|
(mapping) => isRelayHookMapping(mapping)
|
|
21856
21685
|
);
|
|
@@ -21876,6 +21705,39 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21876
21705
|
})
|
|
21877
21706
|
);
|
|
21878
21707
|
}
|
|
21708
|
+
if (!hooksEnabled) {
|
|
21709
|
+
checks.push(
|
|
21710
|
+
toDoctorCheck({
|
|
21711
|
+
id: "state.hookToken",
|
|
21712
|
+
label: "OpenClaw hook auth",
|
|
21713
|
+
status: "fail",
|
|
21714
|
+
message: `hooks.enabled is not true in ${openclawConfigPath}`,
|
|
21715
|
+
remediationHint: "Run: clawdentity openclaw setup <agentName> --invite-code <code> and restart OpenClaw",
|
|
21716
|
+
details: { openclawConfigPath }
|
|
21717
|
+
})
|
|
21718
|
+
);
|
|
21719
|
+
} else if (hookToken === void 0) {
|
|
21720
|
+
checks.push(
|
|
21721
|
+
toDoctorCheck({
|
|
21722
|
+
id: "state.hookToken",
|
|
21723
|
+
label: "OpenClaw hook auth",
|
|
21724
|
+
status: "fail",
|
|
21725
|
+
message: `hooks.token is missing in ${openclawConfigPath}`,
|
|
21726
|
+
remediationHint: "Run: clawdentity openclaw setup <agentName> --invite-code <code> and restart OpenClaw",
|
|
21727
|
+
details: { openclawConfigPath }
|
|
21728
|
+
})
|
|
21729
|
+
);
|
|
21730
|
+
} else {
|
|
21731
|
+
checks.push(
|
|
21732
|
+
toDoctorCheck({
|
|
21733
|
+
id: "state.hookToken",
|
|
21734
|
+
label: "OpenClaw hook auth",
|
|
21735
|
+
status: "pass",
|
|
21736
|
+
message: "hooks token is configured",
|
|
21737
|
+
details: { openclawConfigPath }
|
|
21738
|
+
})
|
|
21739
|
+
);
|
|
21740
|
+
}
|
|
21879
21741
|
} catch {
|
|
21880
21742
|
checks.push(
|
|
21881
21743
|
toDoctorCheck({
|
|
@@ -21883,14 +21745,24 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21883
21745
|
label: "OpenClaw hook mapping",
|
|
21884
21746
|
status: "fail",
|
|
21885
21747
|
message: `unable to read ${openclawConfigPath}`,
|
|
21886
|
-
remediationHint: "Ensure
|
|
21748
|
+
remediationHint: "Ensure the OpenClaw config file exists (OPENCLAW_CONFIG_PATH/CLAWDBOT_CONFIG_PATH, or state dir) and rerun openclaw setup",
|
|
21749
|
+
details: { openclawConfigPath }
|
|
21750
|
+
})
|
|
21751
|
+
);
|
|
21752
|
+
checks.push(
|
|
21753
|
+
toDoctorCheck({
|
|
21754
|
+
id: "state.hookToken",
|
|
21755
|
+
label: "OpenClaw hook auth",
|
|
21756
|
+
status: "fail",
|
|
21757
|
+
message: `unable to read ${openclawConfigPath}`,
|
|
21758
|
+
remediationHint: "Ensure the OpenClaw config file exists (OPENCLAW_CONFIG_PATH/CLAWDBOT_CONFIG_PATH, or state dir) and rerun openclaw setup",
|
|
21887
21759
|
details: { openclawConfigPath }
|
|
21888
21760
|
})
|
|
21889
21761
|
);
|
|
21890
21762
|
}
|
|
21891
21763
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
21892
21764
|
try {
|
|
21893
|
-
const openclawBaseUrl = await
|
|
21765
|
+
const openclawBaseUrl = await resolveOpenclawBaseUrl2({
|
|
21894
21766
|
relayRuntimeConfigPath
|
|
21895
21767
|
});
|
|
21896
21768
|
checks.push(
|
|
@@ -21927,6 +21799,12 @@ function parseRelayProbeFailure(input) {
|
|
|
21927
21799
|
remediationHint: "Run: clawdentity openclaw setup <agentName> --invite-code <code>"
|
|
21928
21800
|
};
|
|
21929
21801
|
}
|
|
21802
|
+
if (input.status === 405) {
|
|
21803
|
+
return {
|
|
21804
|
+
message: "OpenClaw send-to-peer hook is not enabled for POST requests",
|
|
21805
|
+
remediationHint: "Run: clawdentity openclaw setup <agentName> --invite-code <code>, then restart OpenClaw"
|
|
21806
|
+
};
|
|
21807
|
+
}
|
|
21930
21808
|
if (input.status === 500) {
|
|
21931
21809
|
return {
|
|
21932
21810
|
message: "Relay probe failed inside local relay pipeline",
|
|
@@ -21952,7 +21830,7 @@ async function runOpenclawRelayTest(options) {
|
|
|
21952
21830
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
21953
21831
|
let openclawBaseUrl = DEFAULT_OPENCLAW_BASE_URL2;
|
|
21954
21832
|
try {
|
|
21955
|
-
openclawBaseUrl = await
|
|
21833
|
+
openclawBaseUrl = await resolveOpenclawBaseUrl2({
|
|
21956
21834
|
optionValue: options.openclawBaseUrl,
|
|
21957
21835
|
relayRuntimeConfigPath
|
|
21958
21836
|
});
|
|
@@ -21982,7 +21860,10 @@ async function runOpenclawRelayTest(options) {
|
|
|
21982
21860
|
preflight
|
|
21983
21861
|
};
|
|
21984
21862
|
}
|
|
21985
|
-
const hookToken = resolveHookToken(
|
|
21863
|
+
const hookToken = await resolveHookToken({
|
|
21864
|
+
optionValue: options.hookToken,
|
|
21865
|
+
relayRuntimeConfigPath
|
|
21866
|
+
});
|
|
21986
21867
|
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
21987
21868
|
if (typeof fetchImpl !== "function") {
|
|
21988
21869
|
return {
|
|
@@ -22074,21 +21955,17 @@ async function setupOpenclawRelayFromInvite(agentName, options) {
|
|
|
22074
21955
|
const normalizedAgentName = assertValidAgentName(agentName);
|
|
22075
21956
|
const homeDir = resolveHomeDir(options.homeDir);
|
|
22076
21957
|
const openclawDir = resolveOpenclawDir(options.openclawDir, homeDir);
|
|
22077
|
-
const openclawConfigPath = resolveOpenclawConfigPath(openclawDir);
|
|
21958
|
+
const openclawConfigPath = resolveOpenclawConfigPath(openclawDir, homeDir);
|
|
22078
21959
|
const transformSource = typeof options.transformSource === "string" && options.transformSource.trim().length > 0 ? options.transformSource.trim() : resolveDefaultTransformSource(openclawDir);
|
|
22079
21960
|
const transformTargetPath = resolveTransformTargetPath(openclawDir);
|
|
22080
21961
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
22081
21962
|
const existingRelayRuntimeConfig = await loadRelayRuntimeConfig(
|
|
22082
21963
|
relayRuntimeConfigPath
|
|
22083
21964
|
);
|
|
22084
|
-
const openclawBaseUrl = await
|
|
21965
|
+
const openclawBaseUrl = await resolveOpenclawBaseUrl2({
|
|
22085
21966
|
optionValue: options.openclawBaseUrl,
|
|
22086
21967
|
relayRuntimeConfigPath
|
|
22087
21968
|
});
|
|
22088
|
-
const relayEchoConfig = resolveSetupRelayEchoConfig({
|
|
22089
|
-
existingConfig: existingRelayRuntimeConfig,
|
|
22090
|
-
options
|
|
22091
|
-
});
|
|
22092
21969
|
const invite = decodeInvitePayload(options.inviteCode);
|
|
22093
21970
|
const peerAliasCandidate = options.peerAlias ?? invite.alias;
|
|
22094
21971
|
if (!peerAliasCandidate) {
|
|
@@ -22112,18 +21989,64 @@ async function setupOpenclawRelayFromInvite(agentName, options) {
|
|
|
22112
21989
|
}
|
|
22113
21990
|
throw error48;
|
|
22114
21991
|
}
|
|
22115
|
-
await patchOpenclawConfig(
|
|
21992
|
+
const patchedOpenclawConfig = await patchOpenclawConfig(
|
|
21993
|
+
openclawConfigPath,
|
|
21994
|
+
existingRelayRuntimeConfig?.openclawHookToken
|
|
21995
|
+
);
|
|
22116
21996
|
const peersPath = resolvePeersPath(homeDir);
|
|
22117
21997
|
const peers = await loadPeersConfig(peersPath);
|
|
22118
21998
|
peers.peers[peerAlias] = invite.name === void 0 ? { did: invite.did, proxyUrl: invite.proxyUrl } : { did: invite.did, proxyUrl: invite.proxyUrl, name: invite.name };
|
|
22119
21999
|
await savePeersConfig(peersPath, peers);
|
|
22000
|
+
const relayTransformPeersPath = resolveTransformPeersPath(openclawDir);
|
|
22001
|
+
await writeSecureFile3(
|
|
22002
|
+
relayTransformPeersPath,
|
|
22003
|
+
`${JSON.stringify(peers, null, 2)}
|
|
22004
|
+
`
|
|
22005
|
+
);
|
|
22006
|
+
const connectorAssignmentsPath = resolveConnectorAssignmentsPath(homeDir);
|
|
22007
|
+
const connectorAssignments = await loadConnectorAssignments(
|
|
22008
|
+
connectorAssignmentsPath
|
|
22009
|
+
);
|
|
22010
|
+
const connectorPort = allocateConnectorPort(
|
|
22011
|
+
connectorAssignments,
|
|
22012
|
+
normalizedAgentName
|
|
22013
|
+
);
|
|
22014
|
+
const connectorBaseUrl = buildConnectorBaseUrl(
|
|
22015
|
+
CONNECTOR_HOST_LOOPBACK,
|
|
22016
|
+
connectorPort
|
|
22017
|
+
);
|
|
22018
|
+
connectorAssignments.agents[normalizedAgentName] = {
|
|
22019
|
+
connectorBaseUrl,
|
|
22020
|
+
updatedAt: nowIso()
|
|
22021
|
+
};
|
|
22022
|
+
await saveConnectorAssignments(
|
|
22023
|
+
connectorAssignmentsPath,
|
|
22024
|
+
connectorAssignments
|
|
22025
|
+
);
|
|
22026
|
+
const relayTransformRuntimePath = resolveTransformRuntimePath(openclawDir);
|
|
22027
|
+
await writeSecureFile3(
|
|
22028
|
+
relayTransformRuntimePath,
|
|
22029
|
+
`${JSON.stringify(
|
|
22030
|
+
{
|
|
22031
|
+
version: 1,
|
|
22032
|
+
connectorBaseUrl: buildRelayConnectorBaseUrls(connectorPort)[0],
|
|
22033
|
+
connectorBaseUrls: buildRelayConnectorBaseUrls(connectorPort),
|
|
22034
|
+
connectorPath: DEFAULT_CONNECTOR_OUTBOUND_PATH3,
|
|
22035
|
+
peersConfigPath: RELAY_PEERS_FILE_NAME,
|
|
22036
|
+
updatedAt: nowIso()
|
|
22037
|
+
},
|
|
22038
|
+
null,
|
|
22039
|
+
2
|
|
22040
|
+
)}
|
|
22041
|
+
`
|
|
22042
|
+
);
|
|
22120
22043
|
const agentNamePath = resolveOpenclawAgentNamePath(homeDir);
|
|
22121
22044
|
await writeSecureFile3(agentNamePath, `${normalizedAgentName}
|
|
22122
22045
|
`);
|
|
22123
22046
|
await saveRelayRuntimeConfig(
|
|
22124
22047
|
relayRuntimeConfigPath,
|
|
22125
22048
|
openclawBaseUrl,
|
|
22126
|
-
|
|
22049
|
+
patchedOpenclawConfig.hookToken
|
|
22127
22050
|
);
|
|
22128
22051
|
logger8.info("cli.openclaw_setup_completed", {
|
|
22129
22052
|
agentName: normalizedAgentName,
|
|
@@ -22131,9 +22054,11 @@ async function setupOpenclawRelayFromInvite(agentName, options) {
|
|
|
22131
22054
|
peerDid: invite.did,
|
|
22132
22055
|
openclawConfigPath,
|
|
22133
22056
|
transformTargetPath,
|
|
22057
|
+
relayTransformRuntimePath,
|
|
22058
|
+
relayTransformPeersPath,
|
|
22134
22059
|
openclawBaseUrl,
|
|
22135
|
-
|
|
22136
|
-
|
|
22060
|
+
connectorBaseUrl,
|
|
22061
|
+
relayRuntimeConfigPath
|
|
22137
22062
|
});
|
|
22138
22063
|
return {
|
|
22139
22064
|
peerAlias,
|
|
@@ -22141,9 +22066,11 @@ async function setupOpenclawRelayFromInvite(agentName, options) {
|
|
|
22141
22066
|
peerProxyUrl: invite.proxyUrl,
|
|
22142
22067
|
openclawConfigPath,
|
|
22143
22068
|
transformTargetPath,
|
|
22069
|
+
relayTransformRuntimePath,
|
|
22070
|
+
relayTransformPeersPath,
|
|
22144
22071
|
openclawBaseUrl,
|
|
22145
|
-
|
|
22146
|
-
|
|
22072
|
+
connectorBaseUrl,
|
|
22073
|
+
relayRuntimeConfigPath
|
|
22147
22074
|
};
|
|
22148
22075
|
}
|
|
22149
22076
|
var createOpenclawCommand = () => {
|
|
@@ -22179,20 +22106,6 @@ var createOpenclawCommand = () => {
|
|
|
22179
22106
|
).option(
|
|
22180
22107
|
"--openclaw-base-url <url>",
|
|
22181
22108
|
"Base URL for local OpenClaw hook API (default http://127.0.0.1:18789)"
|
|
22182
|
-
).option(
|
|
22183
|
-
"--echo-enabled <true|false>",
|
|
22184
|
-
"Enable or disable relay echo to the operator chat channel (default true)",
|
|
22185
|
-
parseRelayEchoEnabled
|
|
22186
|
-
).option(
|
|
22187
|
-
"--echo-channel <channel>",
|
|
22188
|
-
"Relay echo delivery channel (default last)"
|
|
22189
|
-
).option(
|
|
22190
|
-
"--echo-to <target>",
|
|
22191
|
-
"Relay echo delivery target id/recipient (optional)"
|
|
22192
|
-
).option(
|
|
22193
|
-
"--echo-max-length <number>",
|
|
22194
|
-
`Relay echo message truncation limit (${MIN_RELAY_ECHO_MAX_LENGTH}-${MAX_RELAY_ECHO_MAX_LENGTH}, default ${DEFAULT_RELAY_ECHO_MAX_LENGTH2})`,
|
|
22195
|
-
parseRelayEchoMaxLength
|
|
22196
22109
|
).action(
|
|
22197
22110
|
withErrorHandling(
|
|
22198
22111
|
"openclaw setup",
|
|
@@ -22205,17 +22118,14 @@ var createOpenclawCommand = () => {
|
|
|
22205
22118
|
`Updated OpenClaw config: ${result.openclawConfigPath}`
|
|
22206
22119
|
);
|
|
22207
22120
|
writeStdoutLine(`Installed transform: ${result.transformTargetPath}`);
|
|
22208
|
-
writeStdoutLine(`OpenClaw base URL: ${result.openclawBaseUrl}`);
|
|
22209
22121
|
writeStdoutLine(
|
|
22210
|
-
`
|
|
22122
|
+
`Transform runtime config: ${result.relayTransformRuntimePath}`
|
|
22211
22123
|
);
|
|
22212
|
-
writeStdoutLine(`Relay echo channel: ${result.relayEcho.channel}`);
|
|
22213
22124
|
writeStdoutLine(
|
|
22214
|
-
`
|
|
22215
|
-
);
|
|
22216
|
-
writeStdoutLine(
|
|
22217
|
-
`Relay echo max length: ${result.relayEcho.maxLength}`
|
|
22125
|
+
`Transform peers snapshot: ${result.relayTransformPeersPath}`
|
|
22218
22126
|
);
|
|
22127
|
+
writeStdoutLine(`Connector base URL: ${result.connectorBaseUrl}`);
|
|
22128
|
+
writeStdoutLine(`OpenClaw base URL: ${result.openclawBaseUrl}`);
|
|
22219
22129
|
writeStdoutLine(
|
|
22220
22130
|
`Relay runtime config: ${result.relayRuntimeConfigPath}`
|
|
22221
22131
|
);
|
|
@@ -22286,9 +22196,9 @@ var createOpenclawCommand = () => {
|
|
|
22286
22196
|
};
|
|
22287
22197
|
|
|
22288
22198
|
// src/commands/pair.ts
|
|
22289
|
-
import { randomBytes as
|
|
22290
|
-
import { mkdir as mkdir6, readdir, readFile as
|
|
22291
|
-
import { dirname as dirname5, join as
|
|
22199
|
+
import { randomBytes as randomBytes4 } from "crypto";
|
|
22200
|
+
import { mkdir as mkdir6, readdir, readFile as readFile5, unlink as unlink2, writeFile as writeFile6 } from "fs/promises";
|
|
22201
|
+
import { dirname as dirname5, join as join7, resolve } from "path";
|
|
22292
22202
|
import { Command as Command8 } from "commander";
|
|
22293
22203
|
import jsQR from "jsqr";
|
|
22294
22204
|
import { PNG } from "pngjs";
|
|
@@ -22305,7 +22215,7 @@ var NONCE_SIZE2 = 24;
|
|
|
22305
22215
|
var PAIRING_TICKET_PREFIX = "clwpair1_";
|
|
22306
22216
|
var PAIRING_QR_MAX_AGE_SECONDS = 900;
|
|
22307
22217
|
var PAIRING_QR_FILENAME_PATTERN = /-pair-(\d+)\.png$/;
|
|
22308
|
-
var
|
|
22218
|
+
var isRecord8 = (value) => {
|
|
22309
22219
|
return typeof value === "object" && value !== null;
|
|
22310
22220
|
};
|
|
22311
22221
|
function createCliError6(code, message2) {
|
|
@@ -22372,7 +22282,7 @@ function toPathWithQuery3(url2) {
|
|
|
22372
22282
|
return `${parsed.pathname}${parsed.search}`;
|
|
22373
22283
|
}
|
|
22374
22284
|
function extractErrorCode(payload) {
|
|
22375
|
-
if (!
|
|
22285
|
+
if (!isRecord8(payload)) {
|
|
22376
22286
|
return void 0;
|
|
22377
22287
|
}
|
|
22378
22288
|
const envelope = payload;
|
|
@@ -22383,7 +22293,7 @@ function extractErrorCode(payload) {
|
|
|
22383
22293
|
return code.length > 0 ? code : void 0;
|
|
22384
22294
|
}
|
|
22385
22295
|
function extractErrorMessage(payload) {
|
|
22386
|
-
if (!
|
|
22296
|
+
if (!isRecord8(payload)) {
|
|
22387
22297
|
return void 0;
|
|
22388
22298
|
}
|
|
22389
22299
|
const envelope = payload;
|
|
@@ -22451,7 +22361,7 @@ function mapConfirmPairError(status, payload) {
|
|
|
22451
22361
|
return `Pair confirm failed (${status})`;
|
|
22452
22362
|
}
|
|
22453
22363
|
function parsePairStartResponse(payload) {
|
|
22454
|
-
if (!
|
|
22364
|
+
if (!isRecord8(payload)) {
|
|
22455
22365
|
throw createCliError6(
|
|
22456
22366
|
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
22457
22367
|
"Pair start response is invalid"
|
|
@@ -22473,7 +22383,7 @@ function parsePairStartResponse(payload) {
|
|
|
22473
22383
|
};
|
|
22474
22384
|
}
|
|
22475
22385
|
function parsePairConfirmResponse(payload) {
|
|
22476
|
-
if (!
|
|
22386
|
+
if (!isRecord8(payload)) {
|
|
22477
22387
|
throw createCliError6(
|
|
22478
22388
|
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
22479
22389
|
"Pair confirm response is invalid"
|
|
@@ -22495,16 +22405,16 @@ function parsePairConfirmResponse(payload) {
|
|
|
22495
22405
|
};
|
|
22496
22406
|
}
|
|
22497
22407
|
async function readAgentProofMaterial(agentName, dependencies) {
|
|
22498
|
-
const readFileImpl = dependencies.readFileImpl ??
|
|
22408
|
+
const readFileImpl = dependencies.readFileImpl ?? readFile5;
|
|
22499
22409
|
const getConfigDirImpl = dependencies.getConfigDirImpl ?? getConfigDir;
|
|
22500
22410
|
const normalizedAgentName = assertValidAgentName(agentName);
|
|
22501
|
-
const agentDir =
|
|
22411
|
+
const agentDir = join7(
|
|
22502
22412
|
getConfigDirImpl(),
|
|
22503
22413
|
AGENTS_DIR_NAME5,
|
|
22504
22414
|
normalizedAgentName
|
|
22505
22415
|
);
|
|
22506
|
-
const aitPath =
|
|
22507
|
-
const secretKeyPath =
|
|
22416
|
+
const aitPath = join7(agentDir, AIT_FILE_NAME4);
|
|
22417
|
+
const secretKeyPath = join7(agentDir, SECRET_KEY_FILE_NAME3);
|
|
22508
22418
|
let ait;
|
|
22509
22419
|
try {
|
|
22510
22420
|
ait = (await readFileImpl(aitPath, "utf-8")).trim();
|
|
@@ -22618,8 +22528,8 @@ async function persistPairingQr(input) {
|
|
|
22618
22528
|
const writeFileImpl = input.dependencies.writeFileImpl ?? writeFile6;
|
|
22619
22529
|
const getConfigDirImpl = input.dependencies.getConfigDirImpl ?? getConfigDir;
|
|
22620
22530
|
const qrEncodeImpl = input.dependencies.qrEncodeImpl ?? encodeTicketQrPng;
|
|
22621
|
-
const baseDir =
|
|
22622
|
-
const outputPath = parseNonEmptyString8(input.qrOutput) ? resolve(input.qrOutput ?? "") :
|
|
22531
|
+
const baseDir = join7(getConfigDirImpl(), PAIRING_QR_DIR_NAME);
|
|
22532
|
+
const outputPath = parseNonEmptyString8(input.qrOutput) ? resolve(input.qrOutput ?? "") : join7(
|
|
22623
22533
|
baseDir,
|
|
22624
22534
|
`${assertValidAgentName(input.agentName)}-pair-${input.nowSeconds}.png`
|
|
22625
22535
|
);
|
|
@@ -22645,7 +22555,7 @@ async function persistPairingQr(input) {
|
|
|
22645
22555
|
if (issuedAtSeconds + PAIRING_QR_MAX_AGE_SECONDS > input.nowSeconds) {
|
|
22646
22556
|
continue;
|
|
22647
22557
|
}
|
|
22648
|
-
const stalePath =
|
|
22558
|
+
const stalePath = join7(baseDir, fileName);
|
|
22649
22559
|
await unlinkImpl(stalePath).catch((error48) => {
|
|
22650
22560
|
const nodeError = error48;
|
|
22651
22561
|
if (nodeError.code === "ENOENT") {
|
|
@@ -22690,7 +22600,7 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
22690
22600
|
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
22691
22601
|
const resolveConfigImpl = dependencies.resolveConfigImpl ?? resolveConfig;
|
|
22692
22602
|
const nowSecondsImpl = dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
22693
|
-
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() =>
|
|
22603
|
+
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
22694
22604
|
const ttlSeconds = parseTtlSeconds(options.ttlSeconds);
|
|
22695
22605
|
const proxyUrl = resolveProxyUrl(options.proxyUrl);
|
|
22696
22606
|
const config2 = await resolveConfigImpl();
|
|
@@ -22757,8 +22667,8 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
22757
22667
|
async function confirmPairing(agentName, options, dependencies = {}) {
|
|
22758
22668
|
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
22759
22669
|
const nowSecondsImpl = dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
22760
|
-
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() =>
|
|
22761
|
-
const readFileImpl = dependencies.readFileImpl ??
|
|
22670
|
+
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
22671
|
+
const readFileImpl = dependencies.readFileImpl ?? readFile5;
|
|
22762
22672
|
const qrDecodeImpl = dependencies.qrDecodeImpl ?? decodeTicketFromPng;
|
|
22763
22673
|
const ticketSource = resolveConfirmTicketSource(options);
|
|
22764
22674
|
const proxyUrl = resolveProxyUrl(options.proxyUrl);
|
|
@@ -22896,7 +22806,7 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
22896
22806
|
};
|
|
22897
22807
|
|
|
22898
22808
|
// src/commands/verify.ts
|
|
22899
|
-
import { readFile as
|
|
22809
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
22900
22810
|
import { Command as Command9 } from "commander";
|
|
22901
22811
|
var logger10 = createLogger({ service: "cli", module: "verify" });
|
|
22902
22812
|
var REGISTRY_KEYS_CACHE_FILE = "registry-keys.json";
|
|
@@ -22909,7 +22819,7 @@ var VerifyCommandError = class extends Error {
|
|
|
22909
22819
|
this.name = "VerifyCommandError";
|
|
22910
22820
|
}
|
|
22911
22821
|
};
|
|
22912
|
-
var
|
|
22822
|
+
var isRecord9 = (value) => {
|
|
22913
22823
|
return typeof value === "object" && value !== null;
|
|
22914
22824
|
};
|
|
22915
22825
|
var normalizeRegistryUrl = (registryUrl) => {
|
|
@@ -22945,7 +22855,7 @@ var resolveToken = async (tokenOrFile) => {
|
|
|
22945
22855
|
throw new VerifyCommandError("invalid token (value is empty)");
|
|
22946
22856
|
}
|
|
22947
22857
|
try {
|
|
22948
|
-
const fileContents = await
|
|
22858
|
+
const fileContents = await readFile6(input, "utf-8");
|
|
22949
22859
|
const token = fileContents.trim();
|
|
22950
22860
|
if (token.length === 0) {
|
|
22951
22861
|
throw new VerifyCommandError(`invalid token (${input} is empty)`);
|
|
@@ -22977,7 +22887,7 @@ var parseResponseJson = async (response) => {
|
|
|
22977
22887
|
}
|
|
22978
22888
|
};
|
|
22979
22889
|
var parseSigningKeys = (payload) => {
|
|
22980
|
-
if (!
|
|
22890
|
+
if (!isRecord9(payload) || !Array.isArray(payload.keys)) {
|
|
22981
22891
|
throw new VerifyCommandError(
|
|
22982
22892
|
"verification keys unavailable (response payload is invalid)"
|
|
22983
22893
|
);
|
|
@@ -22996,7 +22906,7 @@ var parseSigningKeys = (payload) => {
|
|
|
22996
22906
|
};
|
|
22997
22907
|
var parseRegistryKeysCache = (rawCache) => {
|
|
22998
22908
|
const parsed = parseJson(rawCache);
|
|
22999
|
-
if (!
|
|
22909
|
+
if (!isRecord9(parsed)) {
|
|
23000
22910
|
return void 0;
|
|
23001
22911
|
}
|
|
23002
22912
|
const { registryUrl, fetchedAtMs, keys } = parsed;
|
|
@@ -23022,7 +22932,7 @@ var parseRegistryKeysCache = (rawCache) => {
|
|
|
23022
22932
|
};
|
|
23023
22933
|
var parseCrlCache = (rawCache) => {
|
|
23024
22934
|
const parsed = parseJson(rawCache);
|
|
23025
|
-
if (!
|
|
22935
|
+
if (!isRecord9(parsed)) {
|
|
23026
22936
|
return void 0;
|
|
23027
22937
|
}
|
|
23028
22938
|
const { registryUrl, fetchedAtMs, claims } = parsed;
|
|
@@ -23120,7 +23030,7 @@ var fetchCrlClaims = async (input) => {
|
|
|
23120
23030
|
);
|
|
23121
23031
|
}
|
|
23122
23032
|
const payload = await parseResponseJson(response);
|
|
23123
|
-
if (!
|
|
23033
|
+
if (!isRecord9(payload) || typeof payload.crl !== "string") {
|
|
23124
23034
|
throw new VerifyCommandError(
|
|
23125
23035
|
"revocation check unavailable (response payload is invalid)"
|
|
23126
23036
|
);
|
|
@@ -23165,7 +23075,7 @@ var loadCrlClaims = async (input) => {
|
|
|
23165
23075
|
return claims;
|
|
23166
23076
|
};
|
|
23167
23077
|
var toInvalidTokenReason = (error48) => {
|
|
23168
|
-
if (
|
|
23078
|
+
if (isRecord9(error48) && typeof error48.message === "string") {
|
|
23169
23079
|
return `invalid token (${error48.message})`;
|
|
23170
23080
|
}
|
|
23171
23081
|
if (error48 instanceof Error && error48.message.length > 0) {
|