clawdentity 0.0.14 → 0.0.15
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
CHANGED
|
@@ -15643,6 +15643,7 @@ var runtimeEnvironmentValues = [
|
|
|
15643
15643
|
// ../../packages/sdk/src/config.ts
|
|
15644
15644
|
var environmentSchema = external_exports.enum(runtimeEnvironmentValues);
|
|
15645
15645
|
var registrySigningKeyStatusSchema = external_exports.enum(["active", "revoked"]);
|
|
15646
|
+
var registryEventBusBackendSchema = external_exports.enum(["memory", "queue"]);
|
|
15646
15647
|
var ED25519_PUBLIC_KEY_LENGTH2 = 32;
|
|
15647
15648
|
var registrySigningPublicKeySchema = external_exports.object({
|
|
15648
15649
|
kid: external_exports.string().min(1),
|
|
@@ -15712,6 +15713,7 @@ var registryConfigSchema = external_exports.object({
|
|
|
15712
15713
|
ENVIRONMENT: environmentSchema,
|
|
15713
15714
|
APP_VERSION: external_exports.string().min(1).optional(),
|
|
15714
15715
|
PROXY_URL: external_exports.string().url().optional(),
|
|
15716
|
+
EVENT_BUS_BACKEND: registryEventBusBackendSchema.optional(),
|
|
15715
15717
|
BOOTSTRAP_SECRET: external_exports.string().min(1).optional(),
|
|
15716
15718
|
REGISTRY_SIGNING_KEY: external_exports.string().min(1).optional(),
|
|
15717
15719
|
REGISTRY_SIGNING_KEYS: registrySigningKeysEnvSchema.optional()
|
|
@@ -18671,6 +18673,7 @@ var DEFAULT_RECONNECT_BACKOFF_FACTOR = 2;
|
|
|
18671
18673
|
var DEFAULT_RECONNECT_JITTER_RATIO = 0.2;
|
|
18672
18674
|
var DEFAULT_CONNECTOR_BASE_URL = "http://127.0.0.1:19400";
|
|
18673
18675
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH = "/v1/outbound";
|
|
18676
|
+
var DEFAULT_CONNECTOR_STATUS_PATH = "/v1/status";
|
|
18674
18677
|
var DEFAULT_RELAY_DELIVER_TIMEOUT_MS = 15e3;
|
|
18675
18678
|
var DEFAULT_OPENCLAW_DELIVER_RETRY_BUDGET_MS = DEFAULT_RELAY_DELIVER_TIMEOUT_MS - 1e3;
|
|
18676
18679
|
var AGENT_ACCESS_HEADER = "x-claw-agent-access";
|
|
@@ -19598,6 +19601,7 @@ async function startConnectorRuntime(input) {
|
|
|
19598
19601
|
});
|
|
19599
19602
|
const outboundBaseUrl = normalizeOutboundBaseUrl(input.outboundBaseUrl);
|
|
19600
19603
|
const outboundPath = normalizeOutboundPath(input.outboundPath);
|
|
19604
|
+
const statusPath = DEFAULT_CONNECTOR_STATUS_PATH;
|
|
19601
19605
|
const outboundUrl = new URL(outboundPath, outboundBaseUrl).toString();
|
|
19602
19606
|
const relayToPeer = async (request) => {
|
|
19603
19607
|
const peerUrl = new URL(request.peerProxyUrl);
|
|
@@ -19665,6 +19669,21 @@ async function startConnectorRuntime(input) {
|
|
|
19665
19669
|
};
|
|
19666
19670
|
const server = createServer(async (req, res) => {
|
|
19667
19671
|
const requestPath = req.url ? new URL(req.url, outboundBaseUrl).pathname : "/";
|
|
19672
|
+
if (requestPath === statusPath) {
|
|
19673
|
+
if (req.method !== "GET") {
|
|
19674
|
+
res.statusCode = 405;
|
|
19675
|
+
res.setHeader("allow", "GET");
|
|
19676
|
+
writeJson(res, 405, { error: "Method Not Allowed" });
|
|
19677
|
+
return;
|
|
19678
|
+
}
|
|
19679
|
+
writeJson(res, 200, {
|
|
19680
|
+
status: "ok",
|
|
19681
|
+
outboundUrl,
|
|
19682
|
+
websocketUrl: wsUrl,
|
|
19683
|
+
websocketConnected: connectorClient.isConnected()
|
|
19684
|
+
});
|
|
19685
|
+
return;
|
|
19686
|
+
}
|
|
19668
19687
|
if (requestPath !== outboundPath) {
|
|
19669
19688
|
writeJson(res, 404, { error: "Not Found" });
|
|
19670
19689
|
return;
|
|
@@ -20921,11 +20940,13 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20921
20940
|
};
|
|
20922
20941
|
|
|
20923
20942
|
// src/commands/openclaw.ts
|
|
20943
|
+
import { spawn } from "child_process";
|
|
20924
20944
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
20925
20945
|
import { existsSync } from "fs";
|
|
20926
20946
|
import { chmod as chmod3, copyFile, mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
20927
20947
|
import { homedir as homedir3 } from "os";
|
|
20928
20948
|
import { dirname as dirname4, join as join6, resolve as resolvePath } from "path";
|
|
20949
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20929
20950
|
import { Command as Command7 } from "commander";
|
|
20930
20951
|
var logger8 = createLogger({ service: "cli", module: "openclaw" });
|
|
20931
20952
|
var CLAWDENTITY_DIR_NAME = ".clawdentity";
|
|
@@ -20960,10 +20981,13 @@ var DEFAULT_OPENCLAW_MAIN_SESSION_KEY = "main";
|
|
|
20960
20981
|
var DEFAULT_OPENCLAW_AGENT_ID = "main";
|
|
20961
20982
|
var DEFAULT_CONNECTOR_PORT = 19400;
|
|
20962
20983
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH3 = "/v1/outbound";
|
|
20984
|
+
var DEFAULT_CONNECTOR_STATUS_PATH2 = "/v1/status";
|
|
20985
|
+
var DEFAULT_SETUP_WAIT_TIMEOUT_SECONDS = 30;
|
|
20963
20986
|
var CONNECTOR_HOST_LOOPBACK = "127.0.0.1";
|
|
20964
20987
|
var CONNECTOR_HOST_DOCKER = "host.docker.internal";
|
|
20965
20988
|
var CONNECTOR_HOST_DOCKER_GATEWAY = "gateway.docker.internal";
|
|
20966
20989
|
var CONNECTOR_HOST_LINUX_BRIDGE = "172.17.0.1";
|
|
20990
|
+
var CONNECTOR_RUN_DIR_NAME = "run";
|
|
20967
20991
|
var PEER_ALIAS_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
20968
20992
|
var FILE_MODE3 = 384;
|
|
20969
20993
|
var OPENCLAW_HOOK_TOKEN_BYTES = 32;
|
|
@@ -21376,6 +21400,256 @@ function buildRelayConnectorBaseUrls(port) {
|
|
|
21376
21400
|
buildConnectorBaseUrl(CONNECTOR_HOST_LOOPBACK, port)
|
|
21377
21401
|
];
|
|
21378
21402
|
}
|
|
21403
|
+
function parseOpenclawRuntimeMode(value) {
|
|
21404
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
21405
|
+
return "auto";
|
|
21406
|
+
}
|
|
21407
|
+
const normalized = value.trim().toLowerCase();
|
|
21408
|
+
if (normalized === "auto" || normalized === "service" || normalized === "detached") {
|
|
21409
|
+
return normalized;
|
|
21410
|
+
}
|
|
21411
|
+
throw createCliError6(
|
|
21412
|
+
"CLI_OPENCLAW_SETUP_RUNTIME_MODE_INVALID",
|
|
21413
|
+
"runtimeMode must be one of: auto, service, detached"
|
|
21414
|
+
);
|
|
21415
|
+
}
|
|
21416
|
+
function parseWaitTimeoutSeconds(value) {
|
|
21417
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
21418
|
+
return DEFAULT_SETUP_WAIT_TIMEOUT_SECONDS;
|
|
21419
|
+
}
|
|
21420
|
+
const parsed = Number.parseInt(value, 10);
|
|
21421
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
21422
|
+
throw createCliError6(
|
|
21423
|
+
"CLI_OPENCLAW_SETUP_TIMEOUT_INVALID",
|
|
21424
|
+
"waitTimeoutSeconds must be a positive integer"
|
|
21425
|
+
);
|
|
21426
|
+
}
|
|
21427
|
+
return parsed;
|
|
21428
|
+
}
|
|
21429
|
+
function resolveConnectorStatusUrl(connectorBaseUrl) {
|
|
21430
|
+
const normalizedBase = connectorBaseUrl.endsWith("/") ? connectorBaseUrl : `${connectorBaseUrl}/`;
|
|
21431
|
+
return new URL(
|
|
21432
|
+
DEFAULT_CONNECTOR_STATUS_PATH2.slice(1),
|
|
21433
|
+
normalizedBase
|
|
21434
|
+
).toString();
|
|
21435
|
+
}
|
|
21436
|
+
function parseConnectorStatusPayload(payload) {
|
|
21437
|
+
if (!isRecord8(payload) || typeof payload.websocketConnected !== "boolean") {
|
|
21438
|
+
throw createCliError6(
|
|
21439
|
+
"CLI_OPENCLAW_SETUP_CONNECTOR_STATUS_INVALID",
|
|
21440
|
+
"Connector status response is invalid"
|
|
21441
|
+
);
|
|
21442
|
+
}
|
|
21443
|
+
return {
|
|
21444
|
+
websocketConnected: payload.websocketConnected
|
|
21445
|
+
};
|
|
21446
|
+
}
|
|
21447
|
+
async function fetchConnectorHealthStatus(input) {
|
|
21448
|
+
const statusUrl = resolveConnectorStatusUrl(input.connectorBaseUrl);
|
|
21449
|
+
try {
|
|
21450
|
+
const response = await input.fetchImpl(statusUrl, {
|
|
21451
|
+
method: "GET",
|
|
21452
|
+
headers: {
|
|
21453
|
+
accept: "application/json"
|
|
21454
|
+
}
|
|
21455
|
+
});
|
|
21456
|
+
if (!response.ok) {
|
|
21457
|
+
return {
|
|
21458
|
+
connected: false,
|
|
21459
|
+
reachable: false,
|
|
21460
|
+
statusUrl,
|
|
21461
|
+
reason: `HTTP ${response.status}`
|
|
21462
|
+
};
|
|
21463
|
+
}
|
|
21464
|
+
let payload;
|
|
21465
|
+
try {
|
|
21466
|
+
payload = await response.json();
|
|
21467
|
+
} catch {
|
|
21468
|
+
return {
|
|
21469
|
+
connected: false,
|
|
21470
|
+
reachable: false,
|
|
21471
|
+
statusUrl,
|
|
21472
|
+
reason: "invalid JSON payload"
|
|
21473
|
+
};
|
|
21474
|
+
}
|
|
21475
|
+
const parsed = parseConnectorStatusPayload(payload);
|
|
21476
|
+
return {
|
|
21477
|
+
connected: parsed.websocketConnected,
|
|
21478
|
+
reachable: true,
|
|
21479
|
+
statusUrl,
|
|
21480
|
+
reason: parsed.websocketConnected ? void 0 : "connector websocket is disconnected"
|
|
21481
|
+
};
|
|
21482
|
+
} catch {
|
|
21483
|
+
return {
|
|
21484
|
+
connected: false,
|
|
21485
|
+
reachable: false,
|
|
21486
|
+
statusUrl,
|
|
21487
|
+
reason: "connector status endpoint is unreachable"
|
|
21488
|
+
};
|
|
21489
|
+
}
|
|
21490
|
+
}
|
|
21491
|
+
async function waitForConnectorConnected(input) {
|
|
21492
|
+
const deadline = Date.now() + input.waitTimeoutSeconds * 1e3;
|
|
21493
|
+
let latest = await fetchConnectorHealthStatus({
|
|
21494
|
+
connectorBaseUrl: input.connectorBaseUrl,
|
|
21495
|
+
fetchImpl: input.fetchImpl
|
|
21496
|
+
});
|
|
21497
|
+
while (!latest.connected && Date.now() < deadline) {
|
|
21498
|
+
await new Promise((resolve2) => {
|
|
21499
|
+
setTimeout(resolve2, 1e3);
|
|
21500
|
+
});
|
|
21501
|
+
latest = await fetchConnectorHealthStatus({
|
|
21502
|
+
connectorBaseUrl: input.connectorBaseUrl,
|
|
21503
|
+
fetchImpl: input.fetchImpl
|
|
21504
|
+
});
|
|
21505
|
+
}
|
|
21506
|
+
if (!latest.connected) {
|
|
21507
|
+
throw createCliError6(
|
|
21508
|
+
"CLI_OPENCLAW_SETUP_CONNECTOR_NOT_READY",
|
|
21509
|
+
`Connector runtime is not websocket-connected after ${input.waitTimeoutSeconds} seconds`,
|
|
21510
|
+
{
|
|
21511
|
+
connectorBaseUrl: input.connectorBaseUrl,
|
|
21512
|
+
connectorStatusUrl: latest.statusUrl,
|
|
21513
|
+
reason: latest.reason
|
|
21514
|
+
}
|
|
21515
|
+
);
|
|
21516
|
+
}
|
|
21517
|
+
return latest;
|
|
21518
|
+
}
|
|
21519
|
+
function resolveConnectorRunDir(homeDir) {
|
|
21520
|
+
return join6(homeDir, CLAWDENTITY_DIR_NAME, CONNECTOR_RUN_DIR_NAME);
|
|
21521
|
+
}
|
|
21522
|
+
function resolveConnectorPidPath(homeDir, agentName) {
|
|
21523
|
+
return join6(resolveConnectorRunDir(homeDir), `connector-${agentName}.pid`);
|
|
21524
|
+
}
|
|
21525
|
+
async function readConnectorPidFile(pidPath) {
|
|
21526
|
+
try {
|
|
21527
|
+
const raw = (await readFile4(pidPath, "utf8")).trim();
|
|
21528
|
+
if (raw.length === 0) {
|
|
21529
|
+
return void 0;
|
|
21530
|
+
}
|
|
21531
|
+
const parsed = Number.parseInt(raw, 10);
|
|
21532
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
21533
|
+
return void 0;
|
|
21534
|
+
}
|
|
21535
|
+
return parsed;
|
|
21536
|
+
} catch (error48) {
|
|
21537
|
+
if (getErrorCode2(error48) === "ENOENT") {
|
|
21538
|
+
return void 0;
|
|
21539
|
+
}
|
|
21540
|
+
throw error48;
|
|
21541
|
+
}
|
|
21542
|
+
}
|
|
21543
|
+
function isPidRunning(pid) {
|
|
21544
|
+
try {
|
|
21545
|
+
process.kill(pid, 0);
|
|
21546
|
+
return true;
|
|
21547
|
+
} catch {
|
|
21548
|
+
return false;
|
|
21549
|
+
}
|
|
21550
|
+
}
|
|
21551
|
+
async function stopDetachedConnectorIfRunning(input) {
|
|
21552
|
+
const pidPath = resolveConnectorPidPath(input.homeDir, input.agentName);
|
|
21553
|
+
const pid = await readConnectorPidFile(pidPath);
|
|
21554
|
+
if (pid === void 0 || !isPidRunning(pid)) {
|
|
21555
|
+
return;
|
|
21556
|
+
}
|
|
21557
|
+
try {
|
|
21558
|
+
process.kill(pid, "SIGTERM");
|
|
21559
|
+
} catch {
|
|
21560
|
+
}
|
|
21561
|
+
}
|
|
21562
|
+
function resolveCliEntryPathForDetachedStart() {
|
|
21563
|
+
const argvEntry = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
21564
|
+
if (argvEntry.length > 0 && existsSync(argvEntry)) {
|
|
21565
|
+
return argvEntry;
|
|
21566
|
+
}
|
|
21567
|
+
const modulePath = fileURLToPath2(import.meta.url);
|
|
21568
|
+
return join6(dirname4(modulePath), "..", "bin.js");
|
|
21569
|
+
}
|
|
21570
|
+
async function startDetachedConnectorRuntime(input) {
|
|
21571
|
+
await stopDetachedConnectorIfRunning({
|
|
21572
|
+
homeDir: input.homeDir,
|
|
21573
|
+
agentName: input.agentName
|
|
21574
|
+
});
|
|
21575
|
+
const runDir = resolveConnectorRunDir(input.homeDir);
|
|
21576
|
+
await mkdir5(runDir, { recursive: true });
|
|
21577
|
+
const cliEntryPath = resolveCliEntryPathForDetachedStart();
|
|
21578
|
+
const args = [
|
|
21579
|
+
cliEntryPath,
|
|
21580
|
+
"connector",
|
|
21581
|
+
"start",
|
|
21582
|
+
input.agentName,
|
|
21583
|
+
"--openclaw-base-url",
|
|
21584
|
+
input.openclawBaseUrl
|
|
21585
|
+
];
|
|
21586
|
+
const child = spawn(process.execPath, args, {
|
|
21587
|
+
detached: true,
|
|
21588
|
+
stdio: "ignore",
|
|
21589
|
+
env: process.env
|
|
21590
|
+
});
|
|
21591
|
+
child.unref();
|
|
21592
|
+
await writeSecureFile3(
|
|
21593
|
+
resolveConnectorPidPath(input.homeDir, input.agentName),
|
|
21594
|
+
`${child.pid}
|
|
21595
|
+
`
|
|
21596
|
+
);
|
|
21597
|
+
}
|
|
21598
|
+
async function startSetupConnectorRuntime(input) {
|
|
21599
|
+
if (input.mode !== "service") {
|
|
21600
|
+
const existingStatus = await fetchConnectorHealthStatus({
|
|
21601
|
+
connectorBaseUrl: input.connectorBaseUrl,
|
|
21602
|
+
fetchImpl: input.fetchImpl
|
|
21603
|
+
});
|
|
21604
|
+
if (existingStatus.connected) {
|
|
21605
|
+
return {
|
|
21606
|
+
runtimeMode: "existing",
|
|
21607
|
+
runtimeStatus: "running",
|
|
21608
|
+
websocketStatus: "connected",
|
|
21609
|
+
connectorStatusUrl: existingStatus.statusUrl
|
|
21610
|
+
};
|
|
21611
|
+
}
|
|
21612
|
+
}
|
|
21613
|
+
let runtimeMode = "service";
|
|
21614
|
+
if (input.mode === "detached") {
|
|
21615
|
+
runtimeMode = "detached";
|
|
21616
|
+
} else {
|
|
21617
|
+
try {
|
|
21618
|
+
await installConnectorServiceForAgent(input.agentName, {
|
|
21619
|
+
platform: "auto",
|
|
21620
|
+
openclawBaseUrl: input.openclawBaseUrl
|
|
21621
|
+
});
|
|
21622
|
+
runtimeMode = "service";
|
|
21623
|
+
} catch (error48) {
|
|
21624
|
+
if (input.mode === "service") {
|
|
21625
|
+
throw error48;
|
|
21626
|
+
}
|
|
21627
|
+
runtimeMode = "detached";
|
|
21628
|
+
logger8.warn("cli.openclaw.setup.service_fallback_detached", {
|
|
21629
|
+
agentName: input.agentName,
|
|
21630
|
+
reason: error48 instanceof Error ? error48.message : "unknown"
|
|
21631
|
+
});
|
|
21632
|
+
}
|
|
21633
|
+
}
|
|
21634
|
+
if (runtimeMode === "detached") {
|
|
21635
|
+
await startDetachedConnectorRuntime({
|
|
21636
|
+
agentName: input.agentName,
|
|
21637
|
+
homeDir: input.homeDir,
|
|
21638
|
+
openclawBaseUrl: input.openclawBaseUrl
|
|
21639
|
+
});
|
|
21640
|
+
}
|
|
21641
|
+
const connectedStatus = await waitForConnectorConnected({
|
|
21642
|
+
connectorBaseUrl: input.connectorBaseUrl,
|
|
21643
|
+
fetchImpl: input.fetchImpl,
|
|
21644
|
+
waitTimeoutSeconds: input.waitTimeoutSeconds
|
|
21645
|
+
});
|
|
21646
|
+
return {
|
|
21647
|
+
runtimeMode,
|
|
21648
|
+
runtimeStatus: "running",
|
|
21649
|
+
websocketStatus: "connected",
|
|
21650
|
+
connectorStatusUrl: connectedStatus.statusUrl
|
|
21651
|
+
};
|
|
21652
|
+
}
|
|
21379
21653
|
function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
21380
21654
|
if (!isRecord8(value)) {
|
|
21381
21655
|
throw createCliError6(
|
|
@@ -22054,6 +22328,97 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22054
22328
|
})
|
|
22055
22329
|
);
|
|
22056
22330
|
}
|
|
22331
|
+
if (options.includeConnectorRuntimeCheck !== false) {
|
|
22332
|
+
if (selectedAgentName === void 0) {
|
|
22333
|
+
checks.push(
|
|
22334
|
+
toDoctorCheck({
|
|
22335
|
+
id: "state.connectorRuntime",
|
|
22336
|
+
label: "Connector runtime",
|
|
22337
|
+
status: "fail",
|
|
22338
|
+
message: "cannot validate connector runtime without selected agent marker",
|
|
22339
|
+
remediationHint: OPENCLAW_SETUP_COMMAND_HINT
|
|
22340
|
+
})
|
|
22341
|
+
);
|
|
22342
|
+
} else {
|
|
22343
|
+
const connectorAssignmentsPath = resolveConnectorAssignmentsPath(homeDir);
|
|
22344
|
+
try {
|
|
22345
|
+
const connectorAssignments = await loadConnectorAssignments(
|
|
22346
|
+
connectorAssignmentsPath
|
|
22347
|
+
);
|
|
22348
|
+
const assignment = connectorAssignments.agents[selectedAgentName];
|
|
22349
|
+
if (assignment === void 0) {
|
|
22350
|
+
checks.push(
|
|
22351
|
+
toDoctorCheck({
|
|
22352
|
+
id: "state.connectorRuntime",
|
|
22353
|
+
label: "Connector runtime",
|
|
22354
|
+
status: "fail",
|
|
22355
|
+
message: `no connector assignment found for ${selectedAgentName}`,
|
|
22356
|
+
remediationHint: OPENCLAW_SETUP_COMMAND_HINT,
|
|
22357
|
+
details: { connectorAssignmentsPath, selectedAgentName }
|
|
22358
|
+
})
|
|
22359
|
+
);
|
|
22360
|
+
} else {
|
|
22361
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
22362
|
+
if (typeof fetchImpl !== "function") {
|
|
22363
|
+
checks.push(
|
|
22364
|
+
toDoctorCheck({
|
|
22365
|
+
id: "state.connectorRuntime",
|
|
22366
|
+
label: "Connector runtime",
|
|
22367
|
+
status: "fail",
|
|
22368
|
+
message: "fetch implementation is unavailable for connector checks",
|
|
22369
|
+
remediationHint: "Run doctor in a Node runtime with fetch support, or rerun openclaw setup"
|
|
22370
|
+
})
|
|
22371
|
+
);
|
|
22372
|
+
} else {
|
|
22373
|
+
const connectorStatus = await fetchConnectorHealthStatus({
|
|
22374
|
+
connectorBaseUrl: assignment.connectorBaseUrl,
|
|
22375
|
+
fetchImpl
|
|
22376
|
+
});
|
|
22377
|
+
if (connectorStatus.connected) {
|
|
22378
|
+
checks.push(
|
|
22379
|
+
toDoctorCheck({
|
|
22380
|
+
id: "state.connectorRuntime",
|
|
22381
|
+
label: "Connector runtime",
|
|
22382
|
+
status: "pass",
|
|
22383
|
+
message: `connector websocket is connected (${assignment.connectorBaseUrl})`,
|
|
22384
|
+
details: {
|
|
22385
|
+
connectorStatusUrl: connectorStatus.statusUrl,
|
|
22386
|
+
connectorBaseUrl: assignment.connectorBaseUrl
|
|
22387
|
+
}
|
|
22388
|
+
})
|
|
22389
|
+
);
|
|
22390
|
+
} else {
|
|
22391
|
+
const reason = connectorStatus.reason ?? "connector runtime is unavailable";
|
|
22392
|
+
checks.push(
|
|
22393
|
+
toDoctorCheck({
|
|
22394
|
+
id: "state.connectorRuntime",
|
|
22395
|
+
label: "Connector runtime",
|
|
22396
|
+
status: "fail",
|
|
22397
|
+
message: `connector runtime is not ready: ${reason}`,
|
|
22398
|
+
remediationHint: OPENCLAW_SETUP_COMMAND_HINT,
|
|
22399
|
+
details: {
|
|
22400
|
+
connectorStatusUrl: connectorStatus.statusUrl,
|
|
22401
|
+
connectorBaseUrl: assignment.connectorBaseUrl
|
|
22402
|
+
}
|
|
22403
|
+
})
|
|
22404
|
+
);
|
|
22405
|
+
}
|
|
22406
|
+
}
|
|
22407
|
+
}
|
|
22408
|
+
} catch {
|
|
22409
|
+
checks.push(
|
|
22410
|
+
toDoctorCheck({
|
|
22411
|
+
id: "state.connectorRuntime",
|
|
22412
|
+
label: "Connector runtime",
|
|
22413
|
+
status: "fail",
|
|
22414
|
+
message: `unable to read connector assignments at ${connectorAssignmentsPath}`,
|
|
22415
|
+
remediationHint: OPENCLAW_SETUP_COMMAND_HINT,
|
|
22416
|
+
details: { connectorAssignmentsPath }
|
|
22417
|
+
})
|
|
22418
|
+
);
|
|
22419
|
+
}
|
|
22420
|
+
}
|
|
22421
|
+
}
|
|
22057
22422
|
return toDoctorResult(checks);
|
|
22058
22423
|
}
|
|
22059
22424
|
function parseRelayProbeFailure(input) {
|
|
@@ -22135,7 +22500,8 @@ async function runOpenclawRelayTest(options) {
|
|
|
22135
22500
|
homeDir,
|
|
22136
22501
|
openclawDir,
|
|
22137
22502
|
peerAlias,
|
|
22138
|
-
resolveConfigImpl: options.resolveConfigImpl
|
|
22503
|
+
resolveConfigImpl: options.resolveConfigImpl,
|
|
22504
|
+
includeConnectorRuntimeCheck: false
|
|
22139
22505
|
});
|
|
22140
22506
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
22141
22507
|
let openclawBaseUrl = DEFAULT_OPENCLAW_BASE_URL2;
|
|
@@ -22346,6 +22712,42 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
22346
22712
|
relayRuntimeConfigPath
|
|
22347
22713
|
};
|
|
22348
22714
|
}
|
|
22715
|
+
async function setupOpenclawSelfReady(agentName, options) {
|
|
22716
|
+
const setup = await setupOpenclawRelay(agentName, options);
|
|
22717
|
+
if (options.noRuntimeStart === true) {
|
|
22718
|
+
return {
|
|
22719
|
+
...setup,
|
|
22720
|
+
runtimeMode: "none",
|
|
22721
|
+
runtimeStatus: "skipped",
|
|
22722
|
+
websocketStatus: "skipped"
|
|
22723
|
+
};
|
|
22724
|
+
}
|
|
22725
|
+
const fetchImpl = globalThis.fetch;
|
|
22726
|
+
if (typeof fetchImpl !== "function") {
|
|
22727
|
+
throw createCliError6(
|
|
22728
|
+
"CLI_OPENCLAW_SETUP_FETCH_UNAVAILABLE",
|
|
22729
|
+
"Runtime fetch is unavailable for connector readiness checks"
|
|
22730
|
+
);
|
|
22731
|
+
}
|
|
22732
|
+
const resolvedMode = parseOpenclawRuntimeMode(options.runtimeMode);
|
|
22733
|
+
const waitTimeoutSeconds = parseWaitTimeoutSeconds(
|
|
22734
|
+
options.waitTimeoutSeconds
|
|
22735
|
+
);
|
|
22736
|
+
const resolvedHomeDir = resolveHomeDir(options.homeDir);
|
|
22737
|
+
const runtime = await startSetupConnectorRuntime({
|
|
22738
|
+
agentName: assertValidAgentName(agentName),
|
|
22739
|
+
homeDir: resolvedHomeDir,
|
|
22740
|
+
openclawBaseUrl: setup.openclawBaseUrl,
|
|
22741
|
+
connectorBaseUrl: setup.connectorBaseUrl,
|
|
22742
|
+
mode: resolvedMode,
|
|
22743
|
+
waitTimeoutSeconds,
|
|
22744
|
+
fetchImpl
|
|
22745
|
+
});
|
|
22746
|
+
return {
|
|
22747
|
+
...setup,
|
|
22748
|
+
...runtime
|
|
22749
|
+
};
|
|
22750
|
+
}
|
|
22349
22751
|
var createOpenclawCommand = () => {
|
|
22350
22752
|
const openclawCommand = new Command7("openclaw").description(
|
|
22351
22753
|
"Manage OpenClaw relay setup"
|
|
@@ -22359,11 +22761,20 @@ var createOpenclawCommand = () => {
|
|
|
22359
22761
|
).option(
|
|
22360
22762
|
"--openclaw-base-url <url>",
|
|
22361
22763
|
"Base URL for local OpenClaw hook API (default http://127.0.0.1:18789)"
|
|
22764
|
+
).option(
|
|
22765
|
+
"--runtime-mode <mode>",
|
|
22766
|
+
"Connector runtime mode: auto | service | detached (default auto)"
|
|
22767
|
+
).option(
|
|
22768
|
+
"--wait-timeout-seconds <seconds>",
|
|
22769
|
+
"Seconds to wait for connector websocket readiness (default 30)"
|
|
22770
|
+
).option(
|
|
22771
|
+
"--no-runtime-start",
|
|
22772
|
+
"Skip connector runtime startup (advanced/manual mode)"
|
|
22362
22773
|
).action(
|
|
22363
22774
|
withErrorHandling(
|
|
22364
22775
|
"openclaw setup",
|
|
22365
22776
|
async (agentName, options) => {
|
|
22366
|
-
const result = await
|
|
22777
|
+
const result = await setupOpenclawSelfReady(agentName, options);
|
|
22367
22778
|
writeStdoutLine("Self setup complete");
|
|
22368
22779
|
writeStdoutLine(
|
|
22369
22780
|
`Updated OpenClaw config: ${result.openclawConfigPath}`
|
|
@@ -22380,6 +22791,14 @@ var createOpenclawCommand = () => {
|
|
|
22380
22791
|
writeStdoutLine(
|
|
22381
22792
|
`Relay runtime config: ${result.relayRuntimeConfigPath}`
|
|
22382
22793
|
);
|
|
22794
|
+
writeStdoutLine(`Runtime mode: ${result.runtimeMode}`);
|
|
22795
|
+
writeStdoutLine(`Runtime status: ${result.runtimeStatus}`);
|
|
22796
|
+
writeStdoutLine(`WebSocket status: ${result.websocketStatus}`);
|
|
22797
|
+
if (result.connectorStatusUrl) {
|
|
22798
|
+
writeStdoutLine(
|
|
22799
|
+
`Connector status URL: ${result.connectorStatusUrl}`
|
|
22800
|
+
);
|
|
22801
|
+
}
|
|
22383
22802
|
}
|
|
22384
22803
|
)
|
|
22385
22804
|
);
|
|
@@ -22472,7 +22891,6 @@ var PEERS_FILE_NAME2 = "peers.json";
|
|
|
22472
22891
|
var PAIR_START_PATH = "/pair/start";
|
|
22473
22892
|
var PAIR_CONFIRM_PATH = "/pair/confirm";
|
|
22474
22893
|
var PAIR_STATUS_PATH = "/pair/status";
|
|
22475
|
-
var OWNER_PAT_HEADER = "x-claw-owner-pat";
|
|
22476
22894
|
var NONCE_SIZE2 = 24;
|
|
22477
22895
|
var PAIRING_TICKET_PREFIX = "clwpair1_";
|
|
22478
22896
|
var PAIRING_QR_MAX_AGE_SECONDS = 900;
|
|
@@ -22830,11 +23248,8 @@ async function executePairRequest(input) {
|
|
|
22830
23248
|
function mapStartPairError(status, payload) {
|
|
22831
23249
|
const code = extractErrorCode(payload);
|
|
22832
23250
|
const message2 = extractErrorMessage(payload);
|
|
22833
|
-
if (code === "
|
|
22834
|
-
return message2 ? `
|
|
22835
|
-
}
|
|
22836
|
-
if (code === "PROXY_PAIR_OWNER_PAT_FORBIDDEN" || status === 403) {
|
|
22837
|
-
return message2 ? `Owner PAT does not control initiator agent DID (403): ${message2}` : "Owner PAT does not control initiator agent DID (403).";
|
|
23251
|
+
if (code === "PROXY_PAIR_OWNERSHIP_FORBIDDEN" || status === 403) {
|
|
23252
|
+
return message2 ? `Initiator agent ownership check failed (403): ${message2}` : "Initiator agent ownership check failed (403).";
|
|
22838
23253
|
}
|
|
22839
23254
|
if (status === 400) {
|
|
22840
23255
|
return message2 ? `Pair start request is invalid (400): ${message2}` : "Pair start request is invalid (400).";
|
|
@@ -23035,16 +23450,6 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
23035
23450
|
secretKey
|
|
23036
23451
|
};
|
|
23037
23452
|
}
|
|
23038
|
-
function resolveOwnerPat(options) {
|
|
23039
|
-
const ownerPat = parseNonEmptyString9(options.explicitOwnerPat) || parseNonEmptyString9(options.config.apiKey);
|
|
23040
|
-
if (ownerPat.length > 0) {
|
|
23041
|
-
return ownerPat;
|
|
23042
|
-
}
|
|
23043
|
-
throw createCliError7(
|
|
23044
|
-
"CLI_PAIR_START_OWNER_PAT_REQUIRED",
|
|
23045
|
-
"Owner PAT is required. Pass --owner-pat <token> or configure API key with `clawdentity invite redeem` / `clawdentity config set apiKey <token>`."
|
|
23046
|
-
);
|
|
23047
|
-
}
|
|
23048
23453
|
async function buildSignedHeaders(input) {
|
|
23049
23454
|
const signed = await signHttpRequest({
|
|
23050
23455
|
method: input.method,
|
|
@@ -23200,10 +23605,6 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
23200
23605
|
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
23201
23606
|
const ttlSeconds = parseTtlSeconds(options.ttlSeconds);
|
|
23202
23607
|
const config2 = await resolveConfigImpl();
|
|
23203
|
-
const ownerPat = resolveOwnerPat({
|
|
23204
|
-
explicitOwnerPat: options.ownerPat,
|
|
23205
|
-
config: config2
|
|
23206
|
-
});
|
|
23207
23608
|
const proxyUrl = await resolveProxyUrl({
|
|
23208
23609
|
config: config2,
|
|
23209
23610
|
fetchImpl
|
|
@@ -23235,7 +23636,6 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
23235
23636
|
headers: {
|
|
23236
23637
|
authorization: `Claw ${ait}`,
|
|
23237
23638
|
"content-type": "application/json",
|
|
23238
|
-
[OWNER_PAT_HEADER]: ownerPat,
|
|
23239
23639
|
...signedHeaders
|
|
23240
23640
|
},
|
|
23241
23641
|
body: requestBody
|
|
@@ -23479,11 +23879,7 @@ async function getPairingStatus(agentName, options, dependencies = {}) {
|
|
|
23479
23879
|
}
|
|
23480
23880
|
const ticket = parsePairingTicket(ticketRaw);
|
|
23481
23881
|
if (options.wait !== true) {
|
|
23482
|
-
return getPairingStatusOnce(
|
|
23483
|
-
agentName,
|
|
23484
|
-
{ ticket },
|
|
23485
|
-
dependencies
|
|
23486
|
-
);
|
|
23882
|
+
return getPairingStatusOnce(agentName, { ticket }, dependencies);
|
|
23487
23883
|
}
|
|
23488
23884
|
const waitSeconds = parsePositiveIntegerOption({
|
|
23489
23885
|
value: options.waitSeconds,
|
|
@@ -23507,10 +23903,7 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23507
23903
|
const pairCommand = new Command8("pair").description(
|
|
23508
23904
|
"Manage proxy trust pairing between agents"
|
|
23509
23905
|
);
|
|
23510
|
-
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option(
|
|
23511
|
-
"--owner-pat <token>",
|
|
23512
|
-
"Owner PAT override (defaults to configured API key)"
|
|
23513
|
-
).option("--ttl-seconds <seconds>", "Pairing ticket expiry in seconds").option("--qr", "Generate a local QR file for sharing").option("--qr-output <path>", "Write QR PNG to a specific file path").option(
|
|
23906
|
+
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option("--ttl-seconds <seconds>", "Pairing ticket expiry in seconds").option("--qr", "Generate a local QR file for sharing").option("--qr-output <path>", "Write QR PNG to a specific file path").option(
|
|
23514
23907
|
"--wait",
|
|
23515
23908
|
"Wait for responder confirmation and auto-save peer on initiator"
|
|
23516
23909
|
).option(
|
|
@@ -23566,10 +23959,14 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23566
23959
|
writeStdoutLine("Pairing confirmed");
|
|
23567
23960
|
writeStdoutLine(`Status: ${status.status}`);
|
|
23568
23961
|
if (status.initiatorAgentDid) {
|
|
23569
|
-
writeStdoutLine(
|
|
23962
|
+
writeStdoutLine(
|
|
23963
|
+
`Initiator Agent DID: ${status.initiatorAgentDid}`
|
|
23964
|
+
);
|
|
23570
23965
|
}
|
|
23571
23966
|
if (status.responderAgentDid) {
|
|
23572
|
-
writeStdoutLine(
|
|
23967
|
+
writeStdoutLine(
|
|
23968
|
+
`Responder Agent DID: ${status.responderAgentDid}`
|
|
23969
|
+
);
|
|
23573
23970
|
}
|
|
23574
23971
|
if (status.peerAlias) {
|
|
23575
23972
|
writeStdoutLine(`Peer alias saved: ${status.peerAlias}`);
|
|
@@ -23609,7 +24006,11 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23609
24006
|
withErrorHandling(
|
|
23610
24007
|
"pair status",
|
|
23611
24008
|
async (agentName, options) => {
|
|
23612
|
-
const result = await getPairingStatus(
|
|
24009
|
+
const result = await getPairingStatus(
|
|
24010
|
+
agentName,
|
|
24011
|
+
options,
|
|
24012
|
+
dependencies
|
|
24013
|
+
);
|
|
23613
24014
|
logger9.info("cli.pair_status", {
|
|
23614
24015
|
initiatorAgentDid: result.initiatorAgentDid,
|
|
23615
24016
|
responderAgentDid: result.responderAgentDid,
|
|
@@ -23644,7 +24045,7 @@ import { access as access3, copyFile as copyFile2, mkdir as mkdir7, readdir as r
|
|
|
23644
24045
|
import { createRequire } from "module";
|
|
23645
24046
|
import { homedir as homedir4 } from "os";
|
|
23646
24047
|
import { dirname as dirname6, join as join8, relative } from "path";
|
|
23647
|
-
import { fileURLToPath as
|
|
24048
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
23648
24049
|
var OPENCLAW_DIR_NAME2 = ".openclaw";
|
|
23649
24050
|
var SKILL_PACKAGE_NAME = "@clawdentity/openclaw-skill";
|
|
23650
24051
|
var SKILL_DIR_NAME2 = "clawdentity-openclaw-relay";
|
|
@@ -23689,7 +24090,7 @@ function resolveSkillPackageRoot(input) {
|
|
|
23689
24090
|
return overriddenRoot.trim();
|
|
23690
24091
|
}
|
|
23691
24092
|
const bundledSkillRoot = join8(
|
|
23692
|
-
dirname6(
|
|
24093
|
+
dirname6(fileURLToPath3(import.meta.url)),
|
|
23693
24094
|
"..",
|
|
23694
24095
|
"skill-bundle",
|
|
23695
24096
|
"openclaw-skill"
|
|
@@ -23704,7 +24105,7 @@ function resolveSkillPackageRoot(input) {
|
|
|
23704
24105
|
return dirname6(packageJsonPath);
|
|
23705
24106
|
} catch {
|
|
23706
24107
|
const workspaceFallbackRoot = join8(
|
|
23707
|
-
dirname6(
|
|
24108
|
+
dirname6(fileURLToPath3(import.meta.url)),
|
|
23708
24109
|
"..",
|
|
23709
24110
|
"..",
|
|
23710
24111
|
"openclaw-skill"
|
|
@@ -23797,11 +24198,7 @@ async function resolveArtifacts(input) {
|
|
|
23797
24198
|
}
|
|
23798
24199
|
});
|
|
23799
24200
|
}
|
|
23800
|
-
const targetSkillRoot = join8(
|
|
23801
|
-
input.openclawDir,
|
|
23802
|
-
"skills",
|
|
23803
|
-
SKILL_DIR_NAME2
|
|
23804
|
-
);
|
|
24201
|
+
const targetSkillRoot = join8(input.openclawDir, "skills", SKILL_DIR_NAME2);
|
|
23805
24202
|
const artifacts = [
|
|
23806
24203
|
{
|
|
23807
24204
|
sourcePath: skillDocSource,
|