clawdentity 0.0.18 → 0.0.19
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 +364 -98
- package/dist/index.js +364 -98
- package/dist/postinstall.js +0 -0
- package/package.json +17 -16
- package/skill-bundle/openclaw-skill/skill/SKILL.md +3 -0
package/dist/bin.js
CHANGED
|
@@ -21090,7 +21090,6 @@ var HOOK_PATH_SEND_TO_PEER = "send-to-peer";
|
|
|
21090
21090
|
var OPENCLAW_SEND_TO_PEER_HOOK_PATH = "hooks/send-to-peer";
|
|
21091
21091
|
var DEFAULT_OPENCLAW_BASE_URL2 = "http://127.0.0.1:18789";
|
|
21092
21092
|
var DEFAULT_OPENCLAW_MAIN_SESSION_KEY = "main";
|
|
21093
|
-
var DEFAULT_OPENCLAW_AGENT_ID = "main";
|
|
21094
21093
|
var DEFAULT_CONNECTOR_PORT = 19400;
|
|
21095
21094
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH3 = "/v1/outbound";
|
|
21096
21095
|
var DEFAULT_CONNECTOR_STATUS_PATH2 = "/v1/status";
|
|
@@ -21107,6 +21106,7 @@ var OPENCLAW_SETUP_COMMAND_HINT = "Run: clawdentity openclaw setup <agentName>";
|
|
|
21107
21106
|
var OPENCLAW_SETUP_RESTART_COMMAND_HINT = `${OPENCLAW_SETUP_COMMAND_HINT} and restart OpenClaw`;
|
|
21108
21107
|
var OPENCLAW_SETUP_WITH_BASE_URL_HINT = `${OPENCLAW_SETUP_COMMAND_HINT} --openclaw-base-url <url>`;
|
|
21109
21108
|
var OPENCLAW_PAIRING_COMMAND_HINT = "Run QR pairing first: clawdentity pair start <agentName> --qr and clawdentity pair confirm <agentName> --qr-file <path>";
|
|
21109
|
+
var OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT = "Run: openclaw devices list and openclaw devices approve <requestId>";
|
|
21110
21110
|
var textEncoder2 = new TextEncoder();
|
|
21111
21111
|
var textDecoder = new TextDecoder();
|
|
21112
21112
|
function isRecord8(value) {
|
|
@@ -21773,9 +21773,11 @@ function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
|
21773
21773
|
}
|
|
21774
21774
|
const updatedAt = typeof value.updatedAt === "string" && value.updatedAt.trim().length > 0 ? value.updatedAt.trim() : void 0;
|
|
21775
21775
|
const openclawHookToken = typeof value.openclawHookToken === "string" && value.openclawHookToken.trim().length > 0 ? value.openclawHookToken.trim() : void 0;
|
|
21776
|
+
const relayTransformPeersPath = typeof value.relayTransformPeersPath === "string" && value.relayTransformPeersPath.trim().length > 0 ? value.relayTransformPeersPath.trim() : void 0;
|
|
21776
21777
|
return {
|
|
21777
21778
|
openclawBaseUrl: parseOpenclawBaseUrl(value.openclawBaseUrl),
|
|
21778
21779
|
openclawHookToken,
|
|
21780
|
+
relayTransformPeersPath,
|
|
21779
21781
|
updatedAt
|
|
21780
21782
|
};
|
|
21781
21783
|
}
|
|
@@ -21791,10 +21793,11 @@ async function loadRelayRuntimeConfig(relayRuntimeConfigPath) {
|
|
|
21791
21793
|
}
|
|
21792
21794
|
return parseRelayRuntimeConfig(parsed, relayRuntimeConfigPath);
|
|
21793
21795
|
}
|
|
21794
|
-
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, openclawHookToken) {
|
|
21796
|
+
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, openclawHookToken, relayTransformPeersPath) {
|
|
21795
21797
|
const config2 = {
|
|
21796
21798
|
openclawBaseUrl,
|
|
21797
21799
|
...openclawHookToken ? { openclawHookToken } : {},
|
|
21800
|
+
...relayTransformPeersPath ? { relayTransformPeersPath } : {},
|
|
21798
21801
|
updatedAt: nowIso()
|
|
21799
21802
|
};
|
|
21800
21803
|
await writeSecureFile3(
|
|
@@ -21841,33 +21844,40 @@ function normalizeStringArrayWithValues(value, requiredValues) {
|
|
|
21841
21844
|
return Array.from(normalized);
|
|
21842
21845
|
}
|
|
21843
21846
|
function resolveHookDefaultSessionKey(config2, hooks) {
|
|
21844
|
-
if (typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0) {
|
|
21845
|
-
return hooks.defaultSessionKey.trim();
|
|
21846
|
-
}
|
|
21847
21847
|
const session = isRecord8(config2.session) ? config2.session : {};
|
|
21848
21848
|
const scope = typeof session.scope === "string" ? session.scope.trim().toLowerCase() : "";
|
|
21849
|
+
const configuredMainSessionKey = resolveConfiguredOpenclawMainSessionKey(session);
|
|
21850
|
+
if (typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0) {
|
|
21851
|
+
return normalizeLegacyHookDefaultSessionKey(
|
|
21852
|
+
hooks.defaultSessionKey,
|
|
21853
|
+
configuredMainSessionKey
|
|
21854
|
+
);
|
|
21855
|
+
}
|
|
21849
21856
|
if (scope === "global") {
|
|
21850
21857
|
return "global";
|
|
21851
21858
|
}
|
|
21852
|
-
|
|
21853
|
-
const agentList = Array.isArray(agents.list) ? agents.list : [];
|
|
21854
|
-
const defaultAgentId = resolveDefaultOpenclawAgentId(agentList);
|
|
21855
|
-
return `agent:${defaultAgentId}:${DEFAULT_OPENCLAW_MAIN_SESSION_KEY}`;
|
|
21859
|
+
return configuredMainSessionKey;
|
|
21856
21860
|
}
|
|
21857
|
-
function
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
) ?? agentList.find(
|
|
21861
|
-
(agent) => isRecord8(agent) && typeof agent.id === "string" && agent.id.trim().length > 0
|
|
21862
|
-
);
|
|
21863
|
-
if (isRecord8(preferred) && typeof preferred.id === "string" && preferred.id.trim().length > 0) {
|
|
21864
|
-
return normalizeOpenclawIdToken(preferred.id, DEFAULT_OPENCLAW_AGENT_ID);
|
|
21861
|
+
function resolveConfiguredOpenclawMainSessionKey(session) {
|
|
21862
|
+
if (typeof session.mainKey === "string" && session.mainKey.trim().length > 0) {
|
|
21863
|
+
return session.mainKey.trim();
|
|
21865
21864
|
}
|
|
21866
|
-
return
|
|
21865
|
+
return DEFAULT_OPENCLAW_MAIN_SESSION_KEY;
|
|
21867
21866
|
}
|
|
21868
|
-
function
|
|
21869
|
-
const
|
|
21870
|
-
|
|
21867
|
+
function normalizeLegacyHookDefaultSessionKey(value, fallbackSessionKey) {
|
|
21868
|
+
const trimmed = value.trim();
|
|
21869
|
+
const legacyMatch = /^agent:[^:]+:(.+)$/i.exec(trimmed);
|
|
21870
|
+
if (!legacyMatch) {
|
|
21871
|
+
return trimmed;
|
|
21872
|
+
}
|
|
21873
|
+
const routedSessionKey = legacyMatch[1]?.trim();
|
|
21874
|
+
if (typeof routedSessionKey === "string" && routedSessionKey.length > 0) {
|
|
21875
|
+
return routedSessionKey;
|
|
21876
|
+
}
|
|
21877
|
+
return fallbackSessionKey;
|
|
21878
|
+
}
|
|
21879
|
+
function isCanonicalAgentSessionKey(value) {
|
|
21880
|
+
return /^agent:[^:]+:.+/i.test(value.trim());
|
|
21871
21881
|
}
|
|
21872
21882
|
function generateOpenclawHookToken() {
|
|
21873
21883
|
return randomBytes3(OPENCLAW_HOOK_TOKEN_BYTES).toString("hex");
|
|
@@ -22051,103 +22061,105 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22051
22061
|
const openclawDir = resolveOpenclawDir(options.openclawDir, homeDir);
|
|
22052
22062
|
const peerAlias = parseDoctorPeerAlias(options.peerAlias);
|
|
22053
22063
|
const checks = [];
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
toDoctorCheck({
|
|
22061
|
-
id: "config.registry",
|
|
22062
|
-
label: "CLI config",
|
|
22063
|
-
status: "fail",
|
|
22064
|
-
message: "registryUrl is missing",
|
|
22065
|
-
remediationHint: "Run: clawdentity config set registryUrl <REGISTRY_URL>"
|
|
22066
|
-
})
|
|
22067
|
-
);
|
|
22068
|
-
} else if (typeof resolvedConfig.apiKey !== "string" || resolvedConfig.apiKey.trim().length === 0) {
|
|
22069
|
-
checks.push(
|
|
22070
|
-
toDoctorCheck({
|
|
22071
|
-
id: "config.registry",
|
|
22072
|
-
label: "CLI config",
|
|
22073
|
-
status: "fail",
|
|
22074
|
-
message: "apiKey is missing",
|
|
22075
|
-
remediationHint: "Run: clawdentity config set apiKey <API_KEY>"
|
|
22076
|
-
})
|
|
22077
|
-
);
|
|
22078
|
-
} else if (envProxyUrl.length > 0) {
|
|
22079
|
-
let hasValidEnvProxyUrl = true;
|
|
22080
|
-
try {
|
|
22081
|
-
parseProxyUrl(envProxyUrl);
|
|
22082
|
-
} catch {
|
|
22083
|
-
hasValidEnvProxyUrl = false;
|
|
22064
|
+
if (options.includeConfigCheck !== false) {
|
|
22065
|
+
const resolveConfigImpl = options.resolveConfigImpl ?? resolveConfig;
|
|
22066
|
+
try {
|
|
22067
|
+
const resolvedConfig = await resolveConfigImpl();
|
|
22068
|
+
const envProxyUrl = typeof process.env.CLAWDENTITY_PROXY_URL === "string" ? process.env.CLAWDENTITY_PROXY_URL.trim() : "";
|
|
22069
|
+
if (typeof resolvedConfig.registryUrl !== "string" || resolvedConfig.registryUrl.trim().length === 0) {
|
|
22084
22070
|
checks.push(
|
|
22085
22071
|
toDoctorCheck({
|
|
22086
22072
|
id: "config.registry",
|
|
22087
22073
|
label: "CLI config",
|
|
22088
22074
|
status: "fail",
|
|
22089
|
-
message: "
|
|
22090
|
-
remediationHint: "
|
|
22075
|
+
message: "registryUrl is missing",
|
|
22076
|
+
remediationHint: "Run: clawdentity config set registryUrl <REGISTRY_URL>"
|
|
22091
22077
|
})
|
|
22092
22078
|
);
|
|
22093
|
-
}
|
|
22094
|
-
if (hasValidEnvProxyUrl) {
|
|
22079
|
+
} else if (typeof resolvedConfig.apiKey !== "string" || resolvedConfig.apiKey.trim().length === 0) {
|
|
22095
22080
|
checks.push(
|
|
22096
22081
|
toDoctorCheck({
|
|
22097
22082
|
id: "config.registry",
|
|
22098
22083
|
label: "CLI config",
|
|
22099
|
-
status: "
|
|
22100
|
-
message: "
|
|
22084
|
+
status: "fail",
|
|
22085
|
+
message: "apiKey is missing",
|
|
22086
|
+
remediationHint: "Run: clawdentity config set apiKey <API_KEY>"
|
|
22101
22087
|
})
|
|
22102
22088
|
);
|
|
22103
|
-
}
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
|
|
22111
|
-
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22089
|
+
} else if (envProxyUrl.length > 0) {
|
|
22090
|
+
let hasValidEnvProxyUrl = true;
|
|
22091
|
+
try {
|
|
22092
|
+
parseProxyUrl(envProxyUrl);
|
|
22093
|
+
} catch {
|
|
22094
|
+
hasValidEnvProxyUrl = false;
|
|
22095
|
+
checks.push(
|
|
22096
|
+
toDoctorCheck({
|
|
22097
|
+
id: "config.registry",
|
|
22098
|
+
label: "CLI config",
|
|
22099
|
+
status: "fail",
|
|
22100
|
+
message: "CLAWDENTITY_PROXY_URL is invalid",
|
|
22101
|
+
remediationHint: "Set CLAWDENTITY_PROXY_URL to a valid http(s) URL or unset it"
|
|
22102
|
+
})
|
|
22103
|
+
);
|
|
22104
|
+
}
|
|
22105
|
+
if (hasValidEnvProxyUrl) {
|
|
22106
|
+
checks.push(
|
|
22107
|
+
toDoctorCheck({
|
|
22108
|
+
id: "config.registry",
|
|
22109
|
+
label: "CLI config",
|
|
22110
|
+
status: "pass",
|
|
22111
|
+
message: "registryUrl and apiKey are configured (proxy URL override is active via CLAWDENTITY_PROXY_URL)"
|
|
22112
|
+
})
|
|
22113
|
+
);
|
|
22114
|
+
}
|
|
22115
|
+
} else if (typeof resolvedConfig.proxyUrl !== "string" || resolvedConfig.proxyUrl.trim().length === 0) {
|
|
22120
22116
|
checks.push(
|
|
22121
22117
|
toDoctorCheck({
|
|
22122
22118
|
id: "config.registry",
|
|
22123
22119
|
label: "CLI config",
|
|
22124
22120
|
status: "fail",
|
|
22125
|
-
message: "proxyUrl is
|
|
22121
|
+
message: "proxyUrl is missing",
|
|
22126
22122
|
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
22127
22123
|
})
|
|
22128
22124
|
);
|
|
22125
|
+
} else {
|
|
22126
|
+
let hasValidConfigProxyUrl = true;
|
|
22127
|
+
try {
|
|
22128
|
+
parseProxyUrl(resolvedConfig.proxyUrl);
|
|
22129
|
+
} catch {
|
|
22130
|
+
hasValidConfigProxyUrl = false;
|
|
22131
|
+
checks.push(
|
|
22132
|
+
toDoctorCheck({
|
|
22133
|
+
id: "config.registry",
|
|
22134
|
+
label: "CLI config",
|
|
22135
|
+
status: "fail",
|
|
22136
|
+
message: "proxyUrl is invalid",
|
|
22137
|
+
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
22138
|
+
})
|
|
22139
|
+
);
|
|
22140
|
+
}
|
|
22141
|
+
if (hasValidConfigProxyUrl) {
|
|
22142
|
+
checks.push(
|
|
22143
|
+
toDoctorCheck({
|
|
22144
|
+
id: "config.registry",
|
|
22145
|
+
label: "CLI config",
|
|
22146
|
+
status: "pass",
|
|
22147
|
+
message: "registryUrl, apiKey, and proxyUrl are configured"
|
|
22148
|
+
})
|
|
22149
|
+
);
|
|
22150
|
+
}
|
|
22129
22151
|
}
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
)
|
|
22139
|
-
|
|
22152
|
+
} catch {
|
|
22153
|
+
checks.push(
|
|
22154
|
+
toDoctorCheck({
|
|
22155
|
+
id: "config.registry",
|
|
22156
|
+
label: "CLI config",
|
|
22157
|
+
status: "fail",
|
|
22158
|
+
message: "unable to resolve CLI config",
|
|
22159
|
+
remediationHint: "Fix ~/.clawdentity/config.json or rerun: clawdentity config init"
|
|
22160
|
+
})
|
|
22161
|
+
);
|
|
22140
22162
|
}
|
|
22141
|
-
} catch {
|
|
22142
|
-
checks.push(
|
|
22143
|
-
toDoctorCheck({
|
|
22144
|
-
id: "config.registry",
|
|
22145
|
-
label: "CLI config",
|
|
22146
|
-
status: "fail",
|
|
22147
|
-
message: "unable to resolve CLI config",
|
|
22148
|
-
remediationHint: "Fix ~/.clawdentity/config.json or rerun: clawdentity config init"
|
|
22149
|
-
})
|
|
22150
|
-
);
|
|
22151
22163
|
}
|
|
22152
22164
|
const selectedAgentPath = resolveOpenclawAgentNamePath(homeDir);
|
|
22153
22165
|
let selectedAgentName;
|
|
@@ -22336,6 +22348,15 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22336
22348
|
const hooks = isRecord8(openclawConfig.hooks) ? openclawConfig.hooks : {};
|
|
22337
22349
|
const hooksEnabled = hooks.enabled === true;
|
|
22338
22350
|
const hookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
22351
|
+
const defaultSessionKey = typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0 ? hooks.defaultSessionKey.trim() : void 0;
|
|
22352
|
+
const allowRequestSessionKey = hooks.allowRequestSessionKey === false;
|
|
22353
|
+
const allowedSessionKeyPrefixes = normalizeStringArrayWithValues(
|
|
22354
|
+
hooks.allowedSessionKeyPrefixes,
|
|
22355
|
+
[]
|
|
22356
|
+
);
|
|
22357
|
+
const missingRequiredSessionPrefixes = defaultSessionKey === void 0 ? ["hook:"] : ["hook:", defaultSessionKey].filter(
|
|
22358
|
+
(prefix) => !allowedSessionKeyPrefixes.includes(prefix)
|
|
22359
|
+
);
|
|
22339
22360
|
const mappings = Array.isArray(hooks.mappings) ? hooks.mappings.filter(isRecord8) : [];
|
|
22340
22361
|
const relayMapping = mappings.find(
|
|
22341
22362
|
(mapping) => isRelayHookMapping(mapping)
|
|
@@ -22395,6 +22416,45 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22395
22416
|
})
|
|
22396
22417
|
);
|
|
22397
22418
|
}
|
|
22419
|
+
const sessionRoutingIssues = [];
|
|
22420
|
+
if (defaultSessionKey === void 0) {
|
|
22421
|
+
sessionRoutingIssues.push("hooks.defaultSessionKey is missing");
|
|
22422
|
+
}
|
|
22423
|
+
if (!allowRequestSessionKey) {
|
|
22424
|
+
sessionRoutingIssues.push("hooks.allowRequestSessionKey is not false");
|
|
22425
|
+
}
|
|
22426
|
+
if (missingRequiredSessionPrefixes.length > 0) {
|
|
22427
|
+
sessionRoutingIssues.push(
|
|
22428
|
+
`hooks.allowedSessionKeyPrefixes is missing: ${missingRequiredSessionPrefixes.join(", ")}`
|
|
22429
|
+
);
|
|
22430
|
+
}
|
|
22431
|
+
if (defaultSessionKey !== void 0 && isCanonicalAgentSessionKey(defaultSessionKey)) {
|
|
22432
|
+
sessionRoutingIssues.push(
|
|
22433
|
+
"hooks.defaultSessionKey uses canonical agent format (agent:<id>:...); use OpenClaw request session keys like main, global, or subagent:*"
|
|
22434
|
+
);
|
|
22435
|
+
}
|
|
22436
|
+
if (sessionRoutingIssues.length > 0) {
|
|
22437
|
+
checks.push(
|
|
22438
|
+
toDoctorCheck({
|
|
22439
|
+
id: "state.hookSessionRouting",
|
|
22440
|
+
label: "OpenClaw hook session routing",
|
|
22441
|
+
status: "fail",
|
|
22442
|
+
message: sessionRoutingIssues.join("; "),
|
|
22443
|
+
remediationHint: OPENCLAW_SETUP_RESTART_COMMAND_HINT,
|
|
22444
|
+
details: { openclawConfigPath }
|
|
22445
|
+
})
|
|
22446
|
+
);
|
|
22447
|
+
} else {
|
|
22448
|
+
checks.push(
|
|
22449
|
+
toDoctorCheck({
|
|
22450
|
+
id: "state.hookSessionRouting",
|
|
22451
|
+
label: "OpenClaw hook session routing",
|
|
22452
|
+
status: "pass",
|
|
22453
|
+
message: "hooks default session and allowed session prefixes are configured",
|
|
22454
|
+
details: { openclawConfigPath }
|
|
22455
|
+
})
|
|
22456
|
+
);
|
|
22457
|
+
}
|
|
22398
22458
|
} catch {
|
|
22399
22459
|
checks.push(
|
|
22400
22460
|
toDoctorCheck({
|
|
@@ -22416,6 +22476,16 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22416
22476
|
details: { openclawConfigPath }
|
|
22417
22477
|
})
|
|
22418
22478
|
);
|
|
22479
|
+
checks.push(
|
|
22480
|
+
toDoctorCheck({
|
|
22481
|
+
id: "state.hookSessionRouting",
|
|
22482
|
+
label: "OpenClaw hook session routing",
|
|
22483
|
+
status: "fail",
|
|
22484
|
+
message: `unable to read ${openclawConfigPath}`,
|
|
22485
|
+
remediationHint: "Ensure the OpenClaw config file exists (OPENCLAW_CONFIG_PATH/CLAWDBOT_CONFIG_PATH, or state dir) and rerun openclaw setup",
|
|
22486
|
+
details: { openclawConfigPath }
|
|
22487
|
+
})
|
|
22488
|
+
);
|
|
22419
22489
|
}
|
|
22420
22490
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
22421
22491
|
try {
|
|
@@ -22441,6 +22511,72 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22441
22511
|
})
|
|
22442
22512
|
);
|
|
22443
22513
|
}
|
|
22514
|
+
const gatewayDevicePendingPath = join6(openclawDir, "devices", "pending.json");
|
|
22515
|
+
try {
|
|
22516
|
+
const pendingPayload = await readJsonFile(gatewayDevicePendingPath);
|
|
22517
|
+
if (!isRecord8(pendingPayload)) {
|
|
22518
|
+
checks.push(
|
|
22519
|
+
toDoctorCheck({
|
|
22520
|
+
id: "state.gatewayDevicePairing",
|
|
22521
|
+
label: "OpenClaw gateway device pairing",
|
|
22522
|
+
status: "fail",
|
|
22523
|
+
message: `invalid pending device approvals file: ${gatewayDevicePendingPath}`,
|
|
22524
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22525
|
+
details: { gatewayDevicePendingPath }
|
|
22526
|
+
})
|
|
22527
|
+
);
|
|
22528
|
+
} else {
|
|
22529
|
+
const pendingRequestIds = Object.keys(pendingPayload);
|
|
22530
|
+
if (pendingRequestIds.length === 0) {
|
|
22531
|
+
checks.push(
|
|
22532
|
+
toDoctorCheck({
|
|
22533
|
+
id: "state.gatewayDevicePairing",
|
|
22534
|
+
label: "OpenClaw gateway device pairing",
|
|
22535
|
+
status: "pass",
|
|
22536
|
+
message: "no pending gateway device approvals",
|
|
22537
|
+
details: { gatewayDevicePendingPath }
|
|
22538
|
+
})
|
|
22539
|
+
);
|
|
22540
|
+
} else {
|
|
22541
|
+
checks.push(
|
|
22542
|
+
toDoctorCheck({
|
|
22543
|
+
id: "state.gatewayDevicePairing",
|
|
22544
|
+
label: "OpenClaw gateway device pairing",
|
|
22545
|
+
status: "fail",
|
|
22546
|
+
message: `pending gateway device approvals: ${pendingRequestIds.length}`,
|
|
22547
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22548
|
+
details: {
|
|
22549
|
+
gatewayDevicePendingPath,
|
|
22550
|
+
pendingRequestIds
|
|
22551
|
+
}
|
|
22552
|
+
})
|
|
22553
|
+
);
|
|
22554
|
+
}
|
|
22555
|
+
}
|
|
22556
|
+
} catch (error48) {
|
|
22557
|
+
if (getErrorCode2(error48) === "ENOENT") {
|
|
22558
|
+
checks.push(
|
|
22559
|
+
toDoctorCheck({
|
|
22560
|
+
id: "state.gatewayDevicePairing",
|
|
22561
|
+
label: "OpenClaw gateway device pairing",
|
|
22562
|
+
status: "pass",
|
|
22563
|
+
message: "no pending gateway device approvals file was found",
|
|
22564
|
+
details: { gatewayDevicePendingPath }
|
|
22565
|
+
})
|
|
22566
|
+
);
|
|
22567
|
+
} else {
|
|
22568
|
+
checks.push(
|
|
22569
|
+
toDoctorCheck({
|
|
22570
|
+
id: "state.gatewayDevicePairing",
|
|
22571
|
+
label: "OpenClaw gateway device pairing",
|
|
22572
|
+
status: "fail",
|
|
22573
|
+
message: `unable to read pending device approvals at ${gatewayDevicePendingPath}`,
|
|
22574
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22575
|
+
details: { gatewayDevicePendingPath }
|
|
22576
|
+
})
|
|
22577
|
+
);
|
|
22578
|
+
}
|
|
22579
|
+
}
|
|
22444
22580
|
if (options.includeConnectorRuntimeCheck !== false) {
|
|
22445
22581
|
if (selectedAgentName === void 0) {
|
|
22446
22582
|
checks.push(
|
|
@@ -22803,7 +22939,8 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
22803
22939
|
await saveRelayRuntimeConfig(
|
|
22804
22940
|
relayRuntimeConfigPath,
|
|
22805
22941
|
openclawBaseUrl,
|
|
22806
|
-
patchedOpenclawConfig.hookToken
|
|
22942
|
+
patchedOpenclawConfig.hookToken,
|
|
22943
|
+
relayTransformPeersPath
|
|
22807
22944
|
);
|
|
22808
22945
|
logger8.info("cli.openclaw_setup_completed", {
|
|
22809
22946
|
agentName: normalizedAgentName,
|
|
@@ -22825,9 +22962,45 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
22825
22962
|
relayRuntimeConfigPath
|
|
22826
22963
|
};
|
|
22827
22964
|
}
|
|
22965
|
+
async function assertSetupChecklistHealthy(input) {
|
|
22966
|
+
const checklist = await runOpenclawDoctor({
|
|
22967
|
+
homeDir: input.homeDir,
|
|
22968
|
+
openclawDir: input.openclawDir,
|
|
22969
|
+
includeConfigCheck: false,
|
|
22970
|
+
includeConnectorRuntimeCheck: input.includeConnectorRuntimeCheck
|
|
22971
|
+
});
|
|
22972
|
+
if (checklist.status === "healthy") {
|
|
22973
|
+
return;
|
|
22974
|
+
}
|
|
22975
|
+
const firstFailure = checklist.checks.find((check2) => check2.status === "fail");
|
|
22976
|
+
throw createCliError6(
|
|
22977
|
+
"CLI_OPENCLAW_SETUP_CHECKLIST_FAILED",
|
|
22978
|
+
"OpenClaw setup checklist failed",
|
|
22979
|
+
{
|
|
22980
|
+
firstFailedCheckId: firstFailure?.id,
|
|
22981
|
+
firstFailedCheckMessage: firstFailure?.message,
|
|
22982
|
+
remediationHint: firstFailure?.remediationHint,
|
|
22983
|
+
checks: checklist.checks
|
|
22984
|
+
}
|
|
22985
|
+
);
|
|
22986
|
+
}
|
|
22828
22987
|
async function setupOpenclawSelfReady(agentName, options) {
|
|
22829
|
-
const
|
|
22988
|
+
const resolvedHomeDir = resolveHomeDir(options.homeDir);
|
|
22989
|
+
const resolvedOpenclawDir = resolveOpenclawDir(
|
|
22990
|
+
options.openclawDir,
|
|
22991
|
+
resolvedHomeDir
|
|
22992
|
+
);
|
|
22993
|
+
const setup = await setupOpenclawRelay(agentName, {
|
|
22994
|
+
...options,
|
|
22995
|
+
homeDir: resolvedHomeDir,
|
|
22996
|
+
openclawDir: resolvedOpenclawDir
|
|
22997
|
+
});
|
|
22830
22998
|
if (options.noRuntimeStart === true) {
|
|
22999
|
+
await assertSetupChecklistHealthy({
|
|
23000
|
+
homeDir: resolvedHomeDir,
|
|
23001
|
+
openclawDir: resolvedOpenclawDir,
|
|
23002
|
+
includeConnectorRuntimeCheck: false
|
|
23003
|
+
});
|
|
22831
23004
|
return {
|
|
22832
23005
|
...setup,
|
|
22833
23006
|
runtimeMode: "none",
|
|
@@ -22846,7 +23019,6 @@ async function setupOpenclawSelfReady(agentName, options) {
|
|
|
22846
23019
|
const waitTimeoutSeconds = parseWaitTimeoutSeconds(
|
|
22847
23020
|
options.waitTimeoutSeconds
|
|
22848
23021
|
);
|
|
22849
|
-
const resolvedHomeDir = resolveHomeDir(options.homeDir);
|
|
22850
23022
|
const runtime = await startSetupConnectorRuntime({
|
|
22851
23023
|
agentName: assertValidAgentName(agentName),
|
|
22852
23024
|
homeDir: resolvedHomeDir,
|
|
@@ -22856,6 +23028,11 @@ async function setupOpenclawSelfReady(agentName, options) {
|
|
|
22856
23028
|
waitTimeoutSeconds,
|
|
22857
23029
|
fetchImpl
|
|
22858
23030
|
});
|
|
23031
|
+
await assertSetupChecklistHealthy({
|
|
23032
|
+
homeDir: resolvedHomeDir,
|
|
23033
|
+
openclawDir: resolvedOpenclawDir,
|
|
23034
|
+
includeConnectorRuntimeCheck: true
|
|
23035
|
+
});
|
|
22859
23036
|
return {
|
|
22860
23037
|
...setup,
|
|
22861
23038
|
...runtime
|
|
@@ -23001,6 +23178,7 @@ var AIT_FILE_NAME4 = "ait.jwt";
|
|
|
23001
23178
|
var SECRET_KEY_FILE_NAME3 = "secret.key";
|
|
23002
23179
|
var PAIRING_QR_DIR_NAME = "pairing";
|
|
23003
23180
|
var PEERS_FILE_NAME2 = "peers.json";
|
|
23181
|
+
var OPENCLAW_RELAY_RUNTIME_FILE_NAME3 = "openclaw-relay.json";
|
|
23004
23182
|
var PAIR_START_PATH = "/pair/start";
|
|
23005
23183
|
var PAIR_CONFIRM_PATH = "/pair/confirm";
|
|
23006
23184
|
var PAIR_STATUS_PATH = "/pair/status";
|
|
@@ -23303,6 +23481,86 @@ async function savePeersConfig2(input) {
|
|
|
23303
23481
|
);
|
|
23304
23482
|
await input.chmodImpl(peersPath, FILE_MODE4);
|
|
23305
23483
|
}
|
|
23484
|
+
function resolveRelayRuntimeConfigPath2(getConfigDirImpl) {
|
|
23485
|
+
return join7(getConfigDirImpl(), OPENCLAW_RELAY_RUNTIME_FILE_NAME3);
|
|
23486
|
+
}
|
|
23487
|
+
async function loadRelayTransformPeersPath(input) {
|
|
23488
|
+
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath2(
|
|
23489
|
+
input.getConfigDirImpl
|
|
23490
|
+
);
|
|
23491
|
+
let raw;
|
|
23492
|
+
try {
|
|
23493
|
+
raw = await input.readFileImpl(relayRuntimeConfigPath, "utf8");
|
|
23494
|
+
} catch (error48) {
|
|
23495
|
+
const nodeError = error48;
|
|
23496
|
+
if (nodeError.code === "ENOENT") {
|
|
23497
|
+
return void 0;
|
|
23498
|
+
}
|
|
23499
|
+
logger9.warn("cli.pair.relay_runtime_read_failed", {
|
|
23500
|
+
relayRuntimeConfigPath,
|
|
23501
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23502
|
+
});
|
|
23503
|
+
return void 0;
|
|
23504
|
+
}
|
|
23505
|
+
let parsed;
|
|
23506
|
+
try {
|
|
23507
|
+
parsed = JSON.parse(raw);
|
|
23508
|
+
} catch {
|
|
23509
|
+
logger9.warn("cli.pair.relay_runtime_invalid_json", {
|
|
23510
|
+
relayRuntimeConfigPath
|
|
23511
|
+
});
|
|
23512
|
+
return void 0;
|
|
23513
|
+
}
|
|
23514
|
+
if (!isRecord9(parsed)) {
|
|
23515
|
+
return void 0;
|
|
23516
|
+
}
|
|
23517
|
+
const relayTransformPeersPath = parseNonEmptyString9(
|
|
23518
|
+
parsed.relayTransformPeersPath
|
|
23519
|
+
);
|
|
23520
|
+
if (relayTransformPeersPath.length === 0) {
|
|
23521
|
+
return void 0;
|
|
23522
|
+
}
|
|
23523
|
+
return resolve(relayTransformPeersPath);
|
|
23524
|
+
}
|
|
23525
|
+
async function syncOpenclawRelayPeersSnapshot(input) {
|
|
23526
|
+
const relayTransformPeersPath = await loadRelayTransformPeersPath({
|
|
23527
|
+
getConfigDirImpl: input.getConfigDirImpl,
|
|
23528
|
+
readFileImpl: input.readFileImpl
|
|
23529
|
+
});
|
|
23530
|
+
if (relayTransformPeersPath === void 0) {
|
|
23531
|
+
return;
|
|
23532
|
+
}
|
|
23533
|
+
try {
|
|
23534
|
+
await input.readFileImpl(relayTransformPeersPath, "utf8");
|
|
23535
|
+
} catch (error48) {
|
|
23536
|
+
const nodeError = error48;
|
|
23537
|
+
if (nodeError.code === "ENOENT") {
|
|
23538
|
+
return;
|
|
23539
|
+
}
|
|
23540
|
+
logger9.warn("cli.pair.relay_peers_snapshot_probe_failed", {
|
|
23541
|
+
relayTransformPeersPath,
|
|
23542
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23543
|
+
});
|
|
23544
|
+
return;
|
|
23545
|
+
}
|
|
23546
|
+
try {
|
|
23547
|
+
await input.mkdirImpl(dirname5(relayTransformPeersPath), {
|
|
23548
|
+
recursive: true
|
|
23549
|
+
});
|
|
23550
|
+
await input.writeFileImpl(
|
|
23551
|
+
relayTransformPeersPath,
|
|
23552
|
+
`${JSON.stringify(input.config, null, 2)}
|
|
23553
|
+
`,
|
|
23554
|
+
"utf8"
|
|
23555
|
+
);
|
|
23556
|
+
await input.chmodImpl(relayTransformPeersPath, FILE_MODE4);
|
|
23557
|
+
} catch (error48) {
|
|
23558
|
+
logger9.warn("cli.pair.relay_peers_snapshot_write_failed", {
|
|
23559
|
+
relayTransformPeersPath,
|
|
23560
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23561
|
+
});
|
|
23562
|
+
}
|
|
23563
|
+
}
|
|
23306
23564
|
function parseTtlSeconds(value) {
|
|
23307
23565
|
const raw = parseNonEmptyString9(value);
|
|
23308
23566
|
if (raw.length === 0) {
|
|
@@ -23828,6 +24086,14 @@ async function persistPairedPeer(input) {
|
|
|
23828
24086
|
writeFileImpl,
|
|
23829
24087
|
chmodImpl
|
|
23830
24088
|
});
|
|
24089
|
+
await syncOpenclawRelayPeersSnapshot({
|
|
24090
|
+
config: peersConfig,
|
|
24091
|
+
getConfigDirImpl,
|
|
24092
|
+
readFileImpl,
|
|
24093
|
+
mkdirImpl,
|
|
24094
|
+
writeFileImpl,
|
|
24095
|
+
chmodImpl
|
|
24096
|
+
});
|
|
23831
24097
|
return alias;
|
|
23832
24098
|
}
|
|
23833
24099
|
async function startPairing(agentName, options, dependencies = {}) {
|
package/dist/index.js
CHANGED
|
@@ -21090,7 +21090,6 @@ var HOOK_PATH_SEND_TO_PEER = "send-to-peer";
|
|
|
21090
21090
|
var OPENCLAW_SEND_TO_PEER_HOOK_PATH = "hooks/send-to-peer";
|
|
21091
21091
|
var DEFAULT_OPENCLAW_BASE_URL2 = "http://127.0.0.1:18789";
|
|
21092
21092
|
var DEFAULT_OPENCLAW_MAIN_SESSION_KEY = "main";
|
|
21093
|
-
var DEFAULT_OPENCLAW_AGENT_ID = "main";
|
|
21094
21093
|
var DEFAULT_CONNECTOR_PORT = 19400;
|
|
21095
21094
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH3 = "/v1/outbound";
|
|
21096
21095
|
var DEFAULT_CONNECTOR_STATUS_PATH2 = "/v1/status";
|
|
@@ -21107,6 +21106,7 @@ var OPENCLAW_SETUP_COMMAND_HINT = "Run: clawdentity openclaw setup <agentName>";
|
|
|
21107
21106
|
var OPENCLAW_SETUP_RESTART_COMMAND_HINT = `${OPENCLAW_SETUP_COMMAND_HINT} and restart OpenClaw`;
|
|
21108
21107
|
var OPENCLAW_SETUP_WITH_BASE_URL_HINT = `${OPENCLAW_SETUP_COMMAND_HINT} --openclaw-base-url <url>`;
|
|
21109
21108
|
var OPENCLAW_PAIRING_COMMAND_HINT = "Run QR pairing first: clawdentity pair start <agentName> --qr and clawdentity pair confirm <agentName> --qr-file <path>";
|
|
21109
|
+
var OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT = "Run: openclaw devices list and openclaw devices approve <requestId>";
|
|
21110
21110
|
var textEncoder2 = new TextEncoder();
|
|
21111
21111
|
var textDecoder = new TextDecoder();
|
|
21112
21112
|
function isRecord8(value) {
|
|
@@ -21773,9 +21773,11 @@ function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
|
21773
21773
|
}
|
|
21774
21774
|
const updatedAt = typeof value.updatedAt === "string" && value.updatedAt.trim().length > 0 ? value.updatedAt.trim() : void 0;
|
|
21775
21775
|
const openclawHookToken = typeof value.openclawHookToken === "string" && value.openclawHookToken.trim().length > 0 ? value.openclawHookToken.trim() : void 0;
|
|
21776
|
+
const relayTransformPeersPath = typeof value.relayTransformPeersPath === "string" && value.relayTransformPeersPath.trim().length > 0 ? value.relayTransformPeersPath.trim() : void 0;
|
|
21776
21777
|
return {
|
|
21777
21778
|
openclawBaseUrl: parseOpenclawBaseUrl(value.openclawBaseUrl),
|
|
21778
21779
|
openclawHookToken,
|
|
21780
|
+
relayTransformPeersPath,
|
|
21779
21781
|
updatedAt
|
|
21780
21782
|
};
|
|
21781
21783
|
}
|
|
@@ -21791,10 +21793,11 @@ async function loadRelayRuntimeConfig(relayRuntimeConfigPath) {
|
|
|
21791
21793
|
}
|
|
21792
21794
|
return parseRelayRuntimeConfig(parsed, relayRuntimeConfigPath);
|
|
21793
21795
|
}
|
|
21794
|
-
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, openclawHookToken) {
|
|
21796
|
+
async function saveRelayRuntimeConfig(relayRuntimeConfigPath, openclawBaseUrl, openclawHookToken, relayTransformPeersPath) {
|
|
21795
21797
|
const config2 = {
|
|
21796
21798
|
openclawBaseUrl,
|
|
21797
21799
|
...openclawHookToken ? { openclawHookToken } : {},
|
|
21800
|
+
...relayTransformPeersPath ? { relayTransformPeersPath } : {},
|
|
21798
21801
|
updatedAt: nowIso()
|
|
21799
21802
|
};
|
|
21800
21803
|
await writeSecureFile3(
|
|
@@ -21841,33 +21844,40 @@ function normalizeStringArrayWithValues(value, requiredValues) {
|
|
|
21841
21844
|
return Array.from(normalized);
|
|
21842
21845
|
}
|
|
21843
21846
|
function resolveHookDefaultSessionKey(config2, hooks) {
|
|
21844
|
-
if (typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0) {
|
|
21845
|
-
return hooks.defaultSessionKey.trim();
|
|
21846
|
-
}
|
|
21847
21847
|
const session = isRecord8(config2.session) ? config2.session : {};
|
|
21848
21848
|
const scope = typeof session.scope === "string" ? session.scope.trim().toLowerCase() : "";
|
|
21849
|
+
const configuredMainSessionKey = resolveConfiguredOpenclawMainSessionKey(session);
|
|
21850
|
+
if (typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0) {
|
|
21851
|
+
return normalizeLegacyHookDefaultSessionKey(
|
|
21852
|
+
hooks.defaultSessionKey,
|
|
21853
|
+
configuredMainSessionKey
|
|
21854
|
+
);
|
|
21855
|
+
}
|
|
21849
21856
|
if (scope === "global") {
|
|
21850
21857
|
return "global";
|
|
21851
21858
|
}
|
|
21852
|
-
|
|
21853
|
-
const agentList = Array.isArray(agents.list) ? agents.list : [];
|
|
21854
|
-
const defaultAgentId = resolveDefaultOpenclawAgentId(agentList);
|
|
21855
|
-
return `agent:${defaultAgentId}:${DEFAULT_OPENCLAW_MAIN_SESSION_KEY}`;
|
|
21859
|
+
return configuredMainSessionKey;
|
|
21856
21860
|
}
|
|
21857
|
-
function
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
) ?? agentList.find(
|
|
21861
|
-
(agent) => isRecord8(agent) && typeof agent.id === "string" && agent.id.trim().length > 0
|
|
21862
|
-
);
|
|
21863
|
-
if (isRecord8(preferred) && typeof preferred.id === "string" && preferred.id.trim().length > 0) {
|
|
21864
|
-
return normalizeOpenclawIdToken(preferred.id, DEFAULT_OPENCLAW_AGENT_ID);
|
|
21861
|
+
function resolveConfiguredOpenclawMainSessionKey(session) {
|
|
21862
|
+
if (typeof session.mainKey === "string" && session.mainKey.trim().length > 0) {
|
|
21863
|
+
return session.mainKey.trim();
|
|
21865
21864
|
}
|
|
21866
|
-
return
|
|
21865
|
+
return DEFAULT_OPENCLAW_MAIN_SESSION_KEY;
|
|
21867
21866
|
}
|
|
21868
|
-
function
|
|
21869
|
-
const
|
|
21870
|
-
|
|
21867
|
+
function normalizeLegacyHookDefaultSessionKey(value, fallbackSessionKey) {
|
|
21868
|
+
const trimmed = value.trim();
|
|
21869
|
+
const legacyMatch = /^agent:[^:]+:(.+)$/i.exec(trimmed);
|
|
21870
|
+
if (!legacyMatch) {
|
|
21871
|
+
return trimmed;
|
|
21872
|
+
}
|
|
21873
|
+
const routedSessionKey = legacyMatch[1]?.trim();
|
|
21874
|
+
if (typeof routedSessionKey === "string" && routedSessionKey.length > 0) {
|
|
21875
|
+
return routedSessionKey;
|
|
21876
|
+
}
|
|
21877
|
+
return fallbackSessionKey;
|
|
21878
|
+
}
|
|
21879
|
+
function isCanonicalAgentSessionKey(value) {
|
|
21880
|
+
return /^agent:[^:]+:.+/i.test(value.trim());
|
|
21871
21881
|
}
|
|
21872
21882
|
function generateOpenclawHookToken() {
|
|
21873
21883
|
return randomBytes3(OPENCLAW_HOOK_TOKEN_BYTES).toString("hex");
|
|
@@ -22051,103 +22061,105 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22051
22061
|
const openclawDir = resolveOpenclawDir(options.openclawDir, homeDir);
|
|
22052
22062
|
const peerAlias = parseDoctorPeerAlias(options.peerAlias);
|
|
22053
22063
|
const checks = [];
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
toDoctorCheck({
|
|
22061
|
-
id: "config.registry",
|
|
22062
|
-
label: "CLI config",
|
|
22063
|
-
status: "fail",
|
|
22064
|
-
message: "registryUrl is missing",
|
|
22065
|
-
remediationHint: "Run: clawdentity config set registryUrl <REGISTRY_URL>"
|
|
22066
|
-
})
|
|
22067
|
-
);
|
|
22068
|
-
} else if (typeof resolvedConfig.apiKey !== "string" || resolvedConfig.apiKey.trim().length === 0) {
|
|
22069
|
-
checks.push(
|
|
22070
|
-
toDoctorCheck({
|
|
22071
|
-
id: "config.registry",
|
|
22072
|
-
label: "CLI config",
|
|
22073
|
-
status: "fail",
|
|
22074
|
-
message: "apiKey is missing",
|
|
22075
|
-
remediationHint: "Run: clawdentity config set apiKey <API_KEY>"
|
|
22076
|
-
})
|
|
22077
|
-
);
|
|
22078
|
-
} else if (envProxyUrl.length > 0) {
|
|
22079
|
-
let hasValidEnvProxyUrl = true;
|
|
22080
|
-
try {
|
|
22081
|
-
parseProxyUrl(envProxyUrl);
|
|
22082
|
-
} catch {
|
|
22083
|
-
hasValidEnvProxyUrl = false;
|
|
22064
|
+
if (options.includeConfigCheck !== false) {
|
|
22065
|
+
const resolveConfigImpl = options.resolveConfigImpl ?? resolveConfig;
|
|
22066
|
+
try {
|
|
22067
|
+
const resolvedConfig = await resolveConfigImpl();
|
|
22068
|
+
const envProxyUrl = typeof process.env.CLAWDENTITY_PROXY_URL === "string" ? process.env.CLAWDENTITY_PROXY_URL.trim() : "";
|
|
22069
|
+
if (typeof resolvedConfig.registryUrl !== "string" || resolvedConfig.registryUrl.trim().length === 0) {
|
|
22084
22070
|
checks.push(
|
|
22085
22071
|
toDoctorCheck({
|
|
22086
22072
|
id: "config.registry",
|
|
22087
22073
|
label: "CLI config",
|
|
22088
22074
|
status: "fail",
|
|
22089
|
-
message: "
|
|
22090
|
-
remediationHint: "
|
|
22075
|
+
message: "registryUrl is missing",
|
|
22076
|
+
remediationHint: "Run: clawdentity config set registryUrl <REGISTRY_URL>"
|
|
22091
22077
|
})
|
|
22092
22078
|
);
|
|
22093
|
-
}
|
|
22094
|
-
if (hasValidEnvProxyUrl) {
|
|
22079
|
+
} else if (typeof resolvedConfig.apiKey !== "string" || resolvedConfig.apiKey.trim().length === 0) {
|
|
22095
22080
|
checks.push(
|
|
22096
22081
|
toDoctorCheck({
|
|
22097
22082
|
id: "config.registry",
|
|
22098
22083
|
label: "CLI config",
|
|
22099
|
-
status: "
|
|
22100
|
-
message: "
|
|
22084
|
+
status: "fail",
|
|
22085
|
+
message: "apiKey is missing",
|
|
22086
|
+
remediationHint: "Run: clawdentity config set apiKey <API_KEY>"
|
|
22101
22087
|
})
|
|
22102
22088
|
);
|
|
22103
|
-
}
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
|
|
22111
|
-
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22089
|
+
} else if (envProxyUrl.length > 0) {
|
|
22090
|
+
let hasValidEnvProxyUrl = true;
|
|
22091
|
+
try {
|
|
22092
|
+
parseProxyUrl(envProxyUrl);
|
|
22093
|
+
} catch {
|
|
22094
|
+
hasValidEnvProxyUrl = false;
|
|
22095
|
+
checks.push(
|
|
22096
|
+
toDoctorCheck({
|
|
22097
|
+
id: "config.registry",
|
|
22098
|
+
label: "CLI config",
|
|
22099
|
+
status: "fail",
|
|
22100
|
+
message: "CLAWDENTITY_PROXY_URL is invalid",
|
|
22101
|
+
remediationHint: "Set CLAWDENTITY_PROXY_URL to a valid http(s) URL or unset it"
|
|
22102
|
+
})
|
|
22103
|
+
);
|
|
22104
|
+
}
|
|
22105
|
+
if (hasValidEnvProxyUrl) {
|
|
22106
|
+
checks.push(
|
|
22107
|
+
toDoctorCheck({
|
|
22108
|
+
id: "config.registry",
|
|
22109
|
+
label: "CLI config",
|
|
22110
|
+
status: "pass",
|
|
22111
|
+
message: "registryUrl and apiKey are configured (proxy URL override is active via CLAWDENTITY_PROXY_URL)"
|
|
22112
|
+
})
|
|
22113
|
+
);
|
|
22114
|
+
}
|
|
22115
|
+
} else if (typeof resolvedConfig.proxyUrl !== "string" || resolvedConfig.proxyUrl.trim().length === 0) {
|
|
22120
22116
|
checks.push(
|
|
22121
22117
|
toDoctorCheck({
|
|
22122
22118
|
id: "config.registry",
|
|
22123
22119
|
label: "CLI config",
|
|
22124
22120
|
status: "fail",
|
|
22125
|
-
message: "proxyUrl is
|
|
22121
|
+
message: "proxyUrl is missing",
|
|
22126
22122
|
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
22127
22123
|
})
|
|
22128
22124
|
);
|
|
22125
|
+
} else {
|
|
22126
|
+
let hasValidConfigProxyUrl = true;
|
|
22127
|
+
try {
|
|
22128
|
+
parseProxyUrl(resolvedConfig.proxyUrl);
|
|
22129
|
+
} catch {
|
|
22130
|
+
hasValidConfigProxyUrl = false;
|
|
22131
|
+
checks.push(
|
|
22132
|
+
toDoctorCheck({
|
|
22133
|
+
id: "config.registry",
|
|
22134
|
+
label: "CLI config",
|
|
22135
|
+
status: "fail",
|
|
22136
|
+
message: "proxyUrl is invalid",
|
|
22137
|
+
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
22138
|
+
})
|
|
22139
|
+
);
|
|
22140
|
+
}
|
|
22141
|
+
if (hasValidConfigProxyUrl) {
|
|
22142
|
+
checks.push(
|
|
22143
|
+
toDoctorCheck({
|
|
22144
|
+
id: "config.registry",
|
|
22145
|
+
label: "CLI config",
|
|
22146
|
+
status: "pass",
|
|
22147
|
+
message: "registryUrl, apiKey, and proxyUrl are configured"
|
|
22148
|
+
})
|
|
22149
|
+
);
|
|
22150
|
+
}
|
|
22129
22151
|
}
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
)
|
|
22139
|
-
|
|
22152
|
+
} catch {
|
|
22153
|
+
checks.push(
|
|
22154
|
+
toDoctorCheck({
|
|
22155
|
+
id: "config.registry",
|
|
22156
|
+
label: "CLI config",
|
|
22157
|
+
status: "fail",
|
|
22158
|
+
message: "unable to resolve CLI config",
|
|
22159
|
+
remediationHint: "Fix ~/.clawdentity/config.json or rerun: clawdentity config init"
|
|
22160
|
+
})
|
|
22161
|
+
);
|
|
22140
22162
|
}
|
|
22141
|
-
} catch {
|
|
22142
|
-
checks.push(
|
|
22143
|
-
toDoctorCheck({
|
|
22144
|
-
id: "config.registry",
|
|
22145
|
-
label: "CLI config",
|
|
22146
|
-
status: "fail",
|
|
22147
|
-
message: "unable to resolve CLI config",
|
|
22148
|
-
remediationHint: "Fix ~/.clawdentity/config.json or rerun: clawdentity config init"
|
|
22149
|
-
})
|
|
22150
|
-
);
|
|
22151
22163
|
}
|
|
22152
22164
|
const selectedAgentPath = resolveOpenclawAgentNamePath(homeDir);
|
|
22153
22165
|
let selectedAgentName;
|
|
@@ -22336,6 +22348,15 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22336
22348
|
const hooks = isRecord8(openclawConfig.hooks) ? openclawConfig.hooks : {};
|
|
22337
22349
|
const hooksEnabled = hooks.enabled === true;
|
|
22338
22350
|
const hookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
22351
|
+
const defaultSessionKey = typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0 ? hooks.defaultSessionKey.trim() : void 0;
|
|
22352
|
+
const allowRequestSessionKey = hooks.allowRequestSessionKey === false;
|
|
22353
|
+
const allowedSessionKeyPrefixes = normalizeStringArrayWithValues(
|
|
22354
|
+
hooks.allowedSessionKeyPrefixes,
|
|
22355
|
+
[]
|
|
22356
|
+
);
|
|
22357
|
+
const missingRequiredSessionPrefixes = defaultSessionKey === void 0 ? ["hook:"] : ["hook:", defaultSessionKey].filter(
|
|
22358
|
+
(prefix) => !allowedSessionKeyPrefixes.includes(prefix)
|
|
22359
|
+
);
|
|
22339
22360
|
const mappings = Array.isArray(hooks.mappings) ? hooks.mappings.filter(isRecord8) : [];
|
|
22340
22361
|
const relayMapping = mappings.find(
|
|
22341
22362
|
(mapping) => isRelayHookMapping(mapping)
|
|
@@ -22395,6 +22416,45 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22395
22416
|
})
|
|
22396
22417
|
);
|
|
22397
22418
|
}
|
|
22419
|
+
const sessionRoutingIssues = [];
|
|
22420
|
+
if (defaultSessionKey === void 0) {
|
|
22421
|
+
sessionRoutingIssues.push("hooks.defaultSessionKey is missing");
|
|
22422
|
+
}
|
|
22423
|
+
if (!allowRequestSessionKey) {
|
|
22424
|
+
sessionRoutingIssues.push("hooks.allowRequestSessionKey is not false");
|
|
22425
|
+
}
|
|
22426
|
+
if (missingRequiredSessionPrefixes.length > 0) {
|
|
22427
|
+
sessionRoutingIssues.push(
|
|
22428
|
+
`hooks.allowedSessionKeyPrefixes is missing: ${missingRequiredSessionPrefixes.join(", ")}`
|
|
22429
|
+
);
|
|
22430
|
+
}
|
|
22431
|
+
if (defaultSessionKey !== void 0 && isCanonicalAgentSessionKey(defaultSessionKey)) {
|
|
22432
|
+
sessionRoutingIssues.push(
|
|
22433
|
+
"hooks.defaultSessionKey uses canonical agent format (agent:<id>:...); use OpenClaw request session keys like main, global, or subagent:*"
|
|
22434
|
+
);
|
|
22435
|
+
}
|
|
22436
|
+
if (sessionRoutingIssues.length > 0) {
|
|
22437
|
+
checks.push(
|
|
22438
|
+
toDoctorCheck({
|
|
22439
|
+
id: "state.hookSessionRouting",
|
|
22440
|
+
label: "OpenClaw hook session routing",
|
|
22441
|
+
status: "fail",
|
|
22442
|
+
message: sessionRoutingIssues.join("; "),
|
|
22443
|
+
remediationHint: OPENCLAW_SETUP_RESTART_COMMAND_HINT,
|
|
22444
|
+
details: { openclawConfigPath }
|
|
22445
|
+
})
|
|
22446
|
+
);
|
|
22447
|
+
} else {
|
|
22448
|
+
checks.push(
|
|
22449
|
+
toDoctorCheck({
|
|
22450
|
+
id: "state.hookSessionRouting",
|
|
22451
|
+
label: "OpenClaw hook session routing",
|
|
22452
|
+
status: "pass",
|
|
22453
|
+
message: "hooks default session and allowed session prefixes are configured",
|
|
22454
|
+
details: { openclawConfigPath }
|
|
22455
|
+
})
|
|
22456
|
+
);
|
|
22457
|
+
}
|
|
22398
22458
|
} catch {
|
|
22399
22459
|
checks.push(
|
|
22400
22460
|
toDoctorCheck({
|
|
@@ -22416,6 +22476,16 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22416
22476
|
details: { openclawConfigPath }
|
|
22417
22477
|
})
|
|
22418
22478
|
);
|
|
22479
|
+
checks.push(
|
|
22480
|
+
toDoctorCheck({
|
|
22481
|
+
id: "state.hookSessionRouting",
|
|
22482
|
+
label: "OpenClaw hook session routing",
|
|
22483
|
+
status: "fail",
|
|
22484
|
+
message: `unable to read ${openclawConfigPath}`,
|
|
22485
|
+
remediationHint: "Ensure the OpenClaw config file exists (OPENCLAW_CONFIG_PATH/CLAWDBOT_CONFIG_PATH, or state dir) and rerun openclaw setup",
|
|
22486
|
+
details: { openclawConfigPath }
|
|
22487
|
+
})
|
|
22488
|
+
);
|
|
22419
22489
|
}
|
|
22420
22490
|
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath(homeDir);
|
|
22421
22491
|
try {
|
|
@@ -22441,6 +22511,72 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
22441
22511
|
})
|
|
22442
22512
|
);
|
|
22443
22513
|
}
|
|
22514
|
+
const gatewayDevicePendingPath = join6(openclawDir, "devices", "pending.json");
|
|
22515
|
+
try {
|
|
22516
|
+
const pendingPayload = await readJsonFile(gatewayDevicePendingPath);
|
|
22517
|
+
if (!isRecord8(pendingPayload)) {
|
|
22518
|
+
checks.push(
|
|
22519
|
+
toDoctorCheck({
|
|
22520
|
+
id: "state.gatewayDevicePairing",
|
|
22521
|
+
label: "OpenClaw gateway device pairing",
|
|
22522
|
+
status: "fail",
|
|
22523
|
+
message: `invalid pending device approvals file: ${gatewayDevicePendingPath}`,
|
|
22524
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22525
|
+
details: { gatewayDevicePendingPath }
|
|
22526
|
+
})
|
|
22527
|
+
);
|
|
22528
|
+
} else {
|
|
22529
|
+
const pendingRequestIds = Object.keys(pendingPayload);
|
|
22530
|
+
if (pendingRequestIds.length === 0) {
|
|
22531
|
+
checks.push(
|
|
22532
|
+
toDoctorCheck({
|
|
22533
|
+
id: "state.gatewayDevicePairing",
|
|
22534
|
+
label: "OpenClaw gateway device pairing",
|
|
22535
|
+
status: "pass",
|
|
22536
|
+
message: "no pending gateway device approvals",
|
|
22537
|
+
details: { gatewayDevicePendingPath }
|
|
22538
|
+
})
|
|
22539
|
+
);
|
|
22540
|
+
} else {
|
|
22541
|
+
checks.push(
|
|
22542
|
+
toDoctorCheck({
|
|
22543
|
+
id: "state.gatewayDevicePairing",
|
|
22544
|
+
label: "OpenClaw gateway device pairing",
|
|
22545
|
+
status: "fail",
|
|
22546
|
+
message: `pending gateway device approvals: ${pendingRequestIds.length}`,
|
|
22547
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22548
|
+
details: {
|
|
22549
|
+
gatewayDevicePendingPath,
|
|
22550
|
+
pendingRequestIds
|
|
22551
|
+
}
|
|
22552
|
+
})
|
|
22553
|
+
);
|
|
22554
|
+
}
|
|
22555
|
+
}
|
|
22556
|
+
} catch (error48) {
|
|
22557
|
+
if (getErrorCode2(error48) === "ENOENT") {
|
|
22558
|
+
checks.push(
|
|
22559
|
+
toDoctorCheck({
|
|
22560
|
+
id: "state.gatewayDevicePairing",
|
|
22561
|
+
label: "OpenClaw gateway device pairing",
|
|
22562
|
+
status: "pass",
|
|
22563
|
+
message: "no pending gateway device approvals file was found",
|
|
22564
|
+
details: { gatewayDevicePendingPath }
|
|
22565
|
+
})
|
|
22566
|
+
);
|
|
22567
|
+
} else {
|
|
22568
|
+
checks.push(
|
|
22569
|
+
toDoctorCheck({
|
|
22570
|
+
id: "state.gatewayDevicePairing",
|
|
22571
|
+
label: "OpenClaw gateway device pairing",
|
|
22572
|
+
status: "fail",
|
|
22573
|
+
message: `unable to read pending device approvals at ${gatewayDevicePendingPath}`,
|
|
22574
|
+
remediationHint: OPENCLAW_DEVICE_APPROVAL_COMMAND_HINT,
|
|
22575
|
+
details: { gatewayDevicePendingPath }
|
|
22576
|
+
})
|
|
22577
|
+
);
|
|
22578
|
+
}
|
|
22579
|
+
}
|
|
22444
22580
|
if (options.includeConnectorRuntimeCheck !== false) {
|
|
22445
22581
|
if (selectedAgentName === void 0) {
|
|
22446
22582
|
checks.push(
|
|
@@ -22803,7 +22939,8 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
22803
22939
|
await saveRelayRuntimeConfig(
|
|
22804
22940
|
relayRuntimeConfigPath,
|
|
22805
22941
|
openclawBaseUrl,
|
|
22806
|
-
patchedOpenclawConfig.hookToken
|
|
22942
|
+
patchedOpenclawConfig.hookToken,
|
|
22943
|
+
relayTransformPeersPath
|
|
22807
22944
|
);
|
|
22808
22945
|
logger8.info("cli.openclaw_setup_completed", {
|
|
22809
22946
|
agentName: normalizedAgentName,
|
|
@@ -22825,9 +22962,45 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
22825
22962
|
relayRuntimeConfigPath
|
|
22826
22963
|
};
|
|
22827
22964
|
}
|
|
22965
|
+
async function assertSetupChecklistHealthy(input) {
|
|
22966
|
+
const checklist = await runOpenclawDoctor({
|
|
22967
|
+
homeDir: input.homeDir,
|
|
22968
|
+
openclawDir: input.openclawDir,
|
|
22969
|
+
includeConfigCheck: false,
|
|
22970
|
+
includeConnectorRuntimeCheck: input.includeConnectorRuntimeCheck
|
|
22971
|
+
});
|
|
22972
|
+
if (checklist.status === "healthy") {
|
|
22973
|
+
return;
|
|
22974
|
+
}
|
|
22975
|
+
const firstFailure = checklist.checks.find((check2) => check2.status === "fail");
|
|
22976
|
+
throw createCliError6(
|
|
22977
|
+
"CLI_OPENCLAW_SETUP_CHECKLIST_FAILED",
|
|
22978
|
+
"OpenClaw setup checklist failed",
|
|
22979
|
+
{
|
|
22980
|
+
firstFailedCheckId: firstFailure?.id,
|
|
22981
|
+
firstFailedCheckMessage: firstFailure?.message,
|
|
22982
|
+
remediationHint: firstFailure?.remediationHint,
|
|
22983
|
+
checks: checklist.checks
|
|
22984
|
+
}
|
|
22985
|
+
);
|
|
22986
|
+
}
|
|
22828
22987
|
async function setupOpenclawSelfReady(agentName, options) {
|
|
22829
|
-
const
|
|
22988
|
+
const resolvedHomeDir = resolveHomeDir(options.homeDir);
|
|
22989
|
+
const resolvedOpenclawDir = resolveOpenclawDir(
|
|
22990
|
+
options.openclawDir,
|
|
22991
|
+
resolvedHomeDir
|
|
22992
|
+
);
|
|
22993
|
+
const setup = await setupOpenclawRelay(agentName, {
|
|
22994
|
+
...options,
|
|
22995
|
+
homeDir: resolvedHomeDir,
|
|
22996
|
+
openclawDir: resolvedOpenclawDir
|
|
22997
|
+
});
|
|
22830
22998
|
if (options.noRuntimeStart === true) {
|
|
22999
|
+
await assertSetupChecklistHealthy({
|
|
23000
|
+
homeDir: resolvedHomeDir,
|
|
23001
|
+
openclawDir: resolvedOpenclawDir,
|
|
23002
|
+
includeConnectorRuntimeCheck: false
|
|
23003
|
+
});
|
|
22831
23004
|
return {
|
|
22832
23005
|
...setup,
|
|
22833
23006
|
runtimeMode: "none",
|
|
@@ -22846,7 +23019,6 @@ async function setupOpenclawSelfReady(agentName, options) {
|
|
|
22846
23019
|
const waitTimeoutSeconds = parseWaitTimeoutSeconds(
|
|
22847
23020
|
options.waitTimeoutSeconds
|
|
22848
23021
|
);
|
|
22849
|
-
const resolvedHomeDir = resolveHomeDir(options.homeDir);
|
|
22850
23022
|
const runtime = await startSetupConnectorRuntime({
|
|
22851
23023
|
agentName: assertValidAgentName(agentName),
|
|
22852
23024
|
homeDir: resolvedHomeDir,
|
|
@@ -22856,6 +23028,11 @@ async function setupOpenclawSelfReady(agentName, options) {
|
|
|
22856
23028
|
waitTimeoutSeconds,
|
|
22857
23029
|
fetchImpl
|
|
22858
23030
|
});
|
|
23031
|
+
await assertSetupChecklistHealthy({
|
|
23032
|
+
homeDir: resolvedHomeDir,
|
|
23033
|
+
openclawDir: resolvedOpenclawDir,
|
|
23034
|
+
includeConnectorRuntimeCheck: true
|
|
23035
|
+
});
|
|
22859
23036
|
return {
|
|
22860
23037
|
...setup,
|
|
22861
23038
|
...runtime
|
|
@@ -23001,6 +23178,7 @@ var AIT_FILE_NAME4 = "ait.jwt";
|
|
|
23001
23178
|
var SECRET_KEY_FILE_NAME3 = "secret.key";
|
|
23002
23179
|
var PAIRING_QR_DIR_NAME = "pairing";
|
|
23003
23180
|
var PEERS_FILE_NAME2 = "peers.json";
|
|
23181
|
+
var OPENCLAW_RELAY_RUNTIME_FILE_NAME3 = "openclaw-relay.json";
|
|
23004
23182
|
var PAIR_START_PATH = "/pair/start";
|
|
23005
23183
|
var PAIR_CONFIRM_PATH = "/pair/confirm";
|
|
23006
23184
|
var PAIR_STATUS_PATH = "/pair/status";
|
|
@@ -23303,6 +23481,86 @@ async function savePeersConfig2(input) {
|
|
|
23303
23481
|
);
|
|
23304
23482
|
await input.chmodImpl(peersPath, FILE_MODE4);
|
|
23305
23483
|
}
|
|
23484
|
+
function resolveRelayRuntimeConfigPath2(getConfigDirImpl) {
|
|
23485
|
+
return join7(getConfigDirImpl(), OPENCLAW_RELAY_RUNTIME_FILE_NAME3);
|
|
23486
|
+
}
|
|
23487
|
+
async function loadRelayTransformPeersPath(input) {
|
|
23488
|
+
const relayRuntimeConfigPath = resolveRelayRuntimeConfigPath2(
|
|
23489
|
+
input.getConfigDirImpl
|
|
23490
|
+
);
|
|
23491
|
+
let raw;
|
|
23492
|
+
try {
|
|
23493
|
+
raw = await input.readFileImpl(relayRuntimeConfigPath, "utf8");
|
|
23494
|
+
} catch (error48) {
|
|
23495
|
+
const nodeError = error48;
|
|
23496
|
+
if (nodeError.code === "ENOENT") {
|
|
23497
|
+
return void 0;
|
|
23498
|
+
}
|
|
23499
|
+
logger9.warn("cli.pair.relay_runtime_read_failed", {
|
|
23500
|
+
relayRuntimeConfigPath,
|
|
23501
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23502
|
+
});
|
|
23503
|
+
return void 0;
|
|
23504
|
+
}
|
|
23505
|
+
let parsed;
|
|
23506
|
+
try {
|
|
23507
|
+
parsed = JSON.parse(raw);
|
|
23508
|
+
} catch {
|
|
23509
|
+
logger9.warn("cli.pair.relay_runtime_invalid_json", {
|
|
23510
|
+
relayRuntimeConfigPath
|
|
23511
|
+
});
|
|
23512
|
+
return void 0;
|
|
23513
|
+
}
|
|
23514
|
+
if (!isRecord9(parsed)) {
|
|
23515
|
+
return void 0;
|
|
23516
|
+
}
|
|
23517
|
+
const relayTransformPeersPath = parseNonEmptyString9(
|
|
23518
|
+
parsed.relayTransformPeersPath
|
|
23519
|
+
);
|
|
23520
|
+
if (relayTransformPeersPath.length === 0) {
|
|
23521
|
+
return void 0;
|
|
23522
|
+
}
|
|
23523
|
+
return resolve(relayTransformPeersPath);
|
|
23524
|
+
}
|
|
23525
|
+
async function syncOpenclawRelayPeersSnapshot(input) {
|
|
23526
|
+
const relayTransformPeersPath = await loadRelayTransformPeersPath({
|
|
23527
|
+
getConfigDirImpl: input.getConfigDirImpl,
|
|
23528
|
+
readFileImpl: input.readFileImpl
|
|
23529
|
+
});
|
|
23530
|
+
if (relayTransformPeersPath === void 0) {
|
|
23531
|
+
return;
|
|
23532
|
+
}
|
|
23533
|
+
try {
|
|
23534
|
+
await input.readFileImpl(relayTransformPeersPath, "utf8");
|
|
23535
|
+
} catch (error48) {
|
|
23536
|
+
const nodeError = error48;
|
|
23537
|
+
if (nodeError.code === "ENOENT") {
|
|
23538
|
+
return;
|
|
23539
|
+
}
|
|
23540
|
+
logger9.warn("cli.pair.relay_peers_snapshot_probe_failed", {
|
|
23541
|
+
relayTransformPeersPath,
|
|
23542
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23543
|
+
});
|
|
23544
|
+
return;
|
|
23545
|
+
}
|
|
23546
|
+
try {
|
|
23547
|
+
await input.mkdirImpl(dirname5(relayTransformPeersPath), {
|
|
23548
|
+
recursive: true
|
|
23549
|
+
});
|
|
23550
|
+
await input.writeFileImpl(
|
|
23551
|
+
relayTransformPeersPath,
|
|
23552
|
+
`${JSON.stringify(input.config, null, 2)}
|
|
23553
|
+
`,
|
|
23554
|
+
"utf8"
|
|
23555
|
+
);
|
|
23556
|
+
await input.chmodImpl(relayTransformPeersPath, FILE_MODE4);
|
|
23557
|
+
} catch (error48) {
|
|
23558
|
+
logger9.warn("cli.pair.relay_peers_snapshot_write_failed", {
|
|
23559
|
+
relayTransformPeersPath,
|
|
23560
|
+
reason: error48 instanceof Error && error48.message.length > 0 ? error48.message : "unknown"
|
|
23561
|
+
});
|
|
23562
|
+
}
|
|
23563
|
+
}
|
|
23306
23564
|
function parseTtlSeconds(value) {
|
|
23307
23565
|
const raw = parseNonEmptyString9(value);
|
|
23308
23566
|
if (raw.length === 0) {
|
|
@@ -23828,6 +24086,14 @@ async function persistPairedPeer(input) {
|
|
|
23828
24086
|
writeFileImpl,
|
|
23829
24087
|
chmodImpl
|
|
23830
24088
|
});
|
|
24089
|
+
await syncOpenclawRelayPeersSnapshot({
|
|
24090
|
+
config: peersConfig,
|
|
24091
|
+
getConfigDirImpl,
|
|
24092
|
+
readFileImpl,
|
|
24093
|
+
mkdirImpl,
|
|
24094
|
+
writeFileImpl,
|
|
24095
|
+
chmodImpl
|
|
24096
|
+
});
|
|
23831
24097
|
return alias;
|
|
23832
24098
|
}
|
|
23833
24099
|
async function startPairing(agentName, options, dependencies = {}) {
|
package/dist/postinstall.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawdentity",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -21,6 +21,17 @@
|
|
|
21
21
|
"postinstall.mjs",
|
|
22
22
|
"skill-bundle"
|
|
23
23
|
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "pnpm -F @clawdentity/openclaw-skill build && pnpm run sync:skill-bundle && pnpm run verify:skill-bundle && tsup",
|
|
26
|
+
"format": "biome format .",
|
|
27
|
+
"lint": "biome lint .",
|
|
28
|
+
"prepack": "pnpm run build",
|
|
29
|
+
"postinstall": "node ./postinstall.mjs",
|
|
30
|
+
"sync:skill-bundle": "node ./scripts/sync-skill-bundle.mjs",
|
|
31
|
+
"verify:skill-bundle": "node ./scripts/verify-skill-bundle.mjs",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"typecheck": "tsc --noEmit"
|
|
34
|
+
},
|
|
24
35
|
"dependencies": {
|
|
25
36
|
"commander": "^13.1.0",
|
|
26
37
|
"jsqr": "^1.4.0",
|
|
@@ -29,21 +40,11 @@
|
|
|
29
40
|
"ws": "^8.19.0"
|
|
30
41
|
},
|
|
31
42
|
"devDependencies": {
|
|
43
|
+
"@clawdentity/connector": "workspace:*",
|
|
44
|
+
"@clawdentity/protocol": "workspace:*",
|
|
45
|
+
"@clawdentity/sdk": "workspace:*",
|
|
32
46
|
"@types/node": "^22.18.11",
|
|
33
47
|
"@types/pngjs": "^6.0.5",
|
|
34
|
-
"@types/qrcode": "^1.5.6"
|
|
35
|
-
"@clawdentity/connector": "0.0.0",
|
|
36
|
-
"@clawdentity/protocol": "0.0.0",
|
|
37
|
-
"@clawdentity/sdk": "0.0.0"
|
|
38
|
-
},
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "pnpm -F @clawdentity/openclaw-skill build && pnpm run sync:skill-bundle && pnpm run verify:skill-bundle && tsup",
|
|
41
|
-
"format": "biome format .",
|
|
42
|
-
"lint": "biome lint .",
|
|
43
|
-
"postinstall": "node ./postinstall.mjs",
|
|
44
|
-
"sync:skill-bundle": "node ./scripts/sync-skill-bundle.mjs",
|
|
45
|
-
"verify:skill-bundle": "node ./scripts/verify-skill-bundle.mjs",
|
|
46
|
-
"test": "vitest run",
|
|
47
|
-
"typecheck": "tsc --noEmit"
|
|
48
|
+
"@types/qrcode": "^1.5.6"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|
|
@@ -196,6 +196,7 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
196
196
|
- OpenClaw config path and relay runtime path
|
|
197
197
|
- runtime mode/status
|
|
198
198
|
- websocket status `connected`
|
|
199
|
+
- setup checklist is healthy (fails fast when hook/device/runtime prerequisites drift)
|
|
199
200
|
|
|
200
201
|
7. Validate readiness.
|
|
201
202
|
- Run `clawdentity openclaw doctor`.
|
|
@@ -212,6 +213,8 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
212
213
|
| `state.transform` | Relay transform artifacts in OpenClaw hooks dir | Reinstall skill package or `openclaw setup <agent-name>` |
|
|
213
214
|
| `state.hookMapping` | `send-to-peer` hook mapping in OpenClaw config | `clawdentity openclaw setup <agent-name>` |
|
|
214
215
|
| `state.hookToken` | Hooks enabled with token in OpenClaw config | `clawdentity openclaw setup <agent-name>` then restart OpenClaw |
|
|
216
|
+
| `state.hookSessionRouting` | `hooks.defaultSessionKey`, `hooks.allowRequestSessionKey=false`, and required prefixes (`hook:`, default session key) | `clawdentity openclaw setup <agent-name>` then restart OpenClaw |
|
|
217
|
+
| `state.gatewayDevicePairing` | Pending OpenClaw device approvals (prevents `pairing required` websocket errors) | `openclaw devices list` then `openclaw devices approve <requestId>` |
|
|
215
218
|
| `state.openclawBaseUrl` | OpenClaw base URL resolvable | `clawdentity openclaw setup <agent-name> --openclaw-base-url <url>` |
|
|
216
219
|
| `state.connectorRuntime` | Local connector runtime reachable and websocket-connected | `clawdentity openclaw setup <agent-name>` |
|
|
217
220
|
|