clawdentity 0.0.11 → 0.0.12
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 +609 -346
- package/dist/index.js +609 -346
- package/package.json +1 -1
- package/skill-bundle/openclaw-skill/skill/SKILL.md +4 -7
package/dist/bin.js
CHANGED
|
@@ -14355,6 +14355,8 @@ var AGENT_AUTH_REFRESH_PATH = "/v1/agents/auth/refresh";
|
|
|
14355
14355
|
var INVITES_PATH = "/v1/invites";
|
|
14356
14356
|
var INVITES_REDEEM_PATH = "/v1/invites/redeem";
|
|
14357
14357
|
var ME_API_KEYS_PATH = "/v1/me/api-keys";
|
|
14358
|
+
var REGISTRY_METADATA_PATH = "/v1/metadata";
|
|
14359
|
+
var RELAY_CONNECT_PATH = "/v1/relay/connect";
|
|
14358
14360
|
var RELAY_RECIPIENT_AGENT_DID_HEADER = "x-claw-recipient-agent-did";
|
|
14359
14361
|
|
|
14360
14362
|
// ../../packages/protocol/src/http-signing.ts
|
|
@@ -18395,6 +18397,139 @@ var createApiKeyCommand = (dependencies = {}) => {
|
|
|
18395
18397
|
// src/commands/config.ts
|
|
18396
18398
|
import { access as access2 } from "fs/promises";
|
|
18397
18399
|
import { Command as Command4 } from "commander";
|
|
18400
|
+
|
|
18401
|
+
// src/config/registry-metadata.ts
|
|
18402
|
+
function isRecord4(value) {
|
|
18403
|
+
return typeof value === "object" && value !== null;
|
|
18404
|
+
}
|
|
18405
|
+
function parseNonEmptyString5(value) {
|
|
18406
|
+
if (typeof value !== "string") {
|
|
18407
|
+
return "";
|
|
18408
|
+
}
|
|
18409
|
+
return value.trim();
|
|
18410
|
+
}
|
|
18411
|
+
function createCliError3(code, message2) {
|
|
18412
|
+
return new AppError({
|
|
18413
|
+
code,
|
|
18414
|
+
message: message2,
|
|
18415
|
+
status: 400
|
|
18416
|
+
});
|
|
18417
|
+
}
|
|
18418
|
+
function parseUrl(candidate, label) {
|
|
18419
|
+
let parsed;
|
|
18420
|
+
try {
|
|
18421
|
+
parsed = new URL(candidate);
|
|
18422
|
+
} catch {
|
|
18423
|
+
throw createCliError3("CLI_REGISTRY_URL_INVALID", `${label} is invalid`);
|
|
18424
|
+
}
|
|
18425
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
18426
|
+
throw createCliError3("CLI_REGISTRY_URL_INVALID", `${label} is invalid`);
|
|
18427
|
+
}
|
|
18428
|
+
return parsed;
|
|
18429
|
+
}
|
|
18430
|
+
function normalizeRegistryUrl(registryUrl) {
|
|
18431
|
+
return parseUrl(registryUrl, "Registry URL").toString();
|
|
18432
|
+
}
|
|
18433
|
+
function toRegistryRequestUrl(registryUrl, path) {
|
|
18434
|
+
const normalizedRegistryUrl = normalizeRegistryUrl(registryUrl);
|
|
18435
|
+
const base = normalizedRegistryUrl.endsWith("/") ? normalizedRegistryUrl : `${normalizedRegistryUrl}/`;
|
|
18436
|
+
return new URL(path.slice(1), base).toString();
|
|
18437
|
+
}
|
|
18438
|
+
function extractRegistryErrorMessage3(payload) {
|
|
18439
|
+
if (!isRecord4(payload)) {
|
|
18440
|
+
return void 0;
|
|
18441
|
+
}
|
|
18442
|
+
const envelope = payload;
|
|
18443
|
+
if (!envelope.error || typeof envelope.error.message !== "string") {
|
|
18444
|
+
return void 0;
|
|
18445
|
+
}
|
|
18446
|
+
const trimmed = envelope.error.message.trim();
|
|
18447
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
18448
|
+
}
|
|
18449
|
+
async function parseJsonResponse4(response) {
|
|
18450
|
+
try {
|
|
18451
|
+
return await response.json();
|
|
18452
|
+
} catch {
|
|
18453
|
+
return void 0;
|
|
18454
|
+
}
|
|
18455
|
+
}
|
|
18456
|
+
function parseMetadataPayload(payload, fallbackRegistryUrl) {
|
|
18457
|
+
if (!isRecord4(payload)) {
|
|
18458
|
+
throw createCliError3(
|
|
18459
|
+
"CLI_REGISTRY_METADATA_INVALID_RESPONSE",
|
|
18460
|
+
"Registry metadata response is invalid"
|
|
18461
|
+
);
|
|
18462
|
+
}
|
|
18463
|
+
const proxyUrlRaw = parseNonEmptyString5(payload.proxyUrl);
|
|
18464
|
+
if (proxyUrlRaw.length === 0) {
|
|
18465
|
+
throw createCliError3(
|
|
18466
|
+
"CLI_REGISTRY_METADATA_INVALID_RESPONSE",
|
|
18467
|
+
"Registry metadata response is invalid"
|
|
18468
|
+
);
|
|
18469
|
+
}
|
|
18470
|
+
const proxyUrl = parseUrl(proxyUrlRaw, "Proxy URL").toString();
|
|
18471
|
+
const registryUrlRaw = parseNonEmptyString5(payload.registryUrl);
|
|
18472
|
+
const registryUrl = registryUrlRaw.length > 0 ? parseUrl(registryUrlRaw, "Registry URL").toString() : normalizeRegistryUrl(fallbackRegistryUrl);
|
|
18473
|
+
const environment = parseNonEmptyString5(payload.environment);
|
|
18474
|
+
const version2 = parseNonEmptyString5(payload.version);
|
|
18475
|
+
return {
|
|
18476
|
+
proxyUrl,
|
|
18477
|
+
registryUrl,
|
|
18478
|
+
environment: environment.length > 0 ? environment : void 0,
|
|
18479
|
+
version: version2.length > 0 ? version2 : void 0
|
|
18480
|
+
};
|
|
18481
|
+
}
|
|
18482
|
+
function mapMetadataError(status, payload) {
|
|
18483
|
+
const registryMessage = extractRegistryErrorMessage3(payload);
|
|
18484
|
+
if (status === 404) {
|
|
18485
|
+
return "Registry metadata endpoint is unavailable (404).";
|
|
18486
|
+
}
|
|
18487
|
+
if (status >= 500) {
|
|
18488
|
+
return `Registry metadata request failed (${status}). Try again later.`;
|
|
18489
|
+
}
|
|
18490
|
+
if (registryMessage) {
|
|
18491
|
+
return `Registry metadata request failed (${status}): ${registryMessage}`;
|
|
18492
|
+
}
|
|
18493
|
+
return `Registry metadata request failed (${status}).`;
|
|
18494
|
+
}
|
|
18495
|
+
async function fetchRegistryMetadata(registryUrl, dependencies = {}) {
|
|
18496
|
+
const fetchImpl = dependencies.fetchImpl ?? globalThis.fetch;
|
|
18497
|
+
if (typeof fetchImpl !== "function") {
|
|
18498
|
+
throw createCliError3(
|
|
18499
|
+
"CLI_REGISTRY_METADATA_FETCH_UNAVAILABLE",
|
|
18500
|
+
"Runtime fetch is unavailable for registry metadata lookup"
|
|
18501
|
+
);
|
|
18502
|
+
}
|
|
18503
|
+
const normalizedRegistryUrl = normalizeRegistryUrl(registryUrl);
|
|
18504
|
+
const requestUrl = toRegistryRequestUrl(
|
|
18505
|
+
normalizedRegistryUrl,
|
|
18506
|
+
REGISTRY_METADATA_PATH
|
|
18507
|
+
);
|
|
18508
|
+
let response;
|
|
18509
|
+
try {
|
|
18510
|
+
response = await fetchImpl(requestUrl, {
|
|
18511
|
+
method: "GET",
|
|
18512
|
+
headers: {
|
|
18513
|
+
accept: "application/json"
|
|
18514
|
+
}
|
|
18515
|
+
});
|
|
18516
|
+
} catch {
|
|
18517
|
+
throw createCliError3(
|
|
18518
|
+
"CLI_REGISTRY_METADATA_REQUEST_FAILED",
|
|
18519
|
+
"Unable to reach registry metadata endpoint. Check registryUrl and network access."
|
|
18520
|
+
);
|
|
18521
|
+
}
|
|
18522
|
+
const payload = await parseJsonResponse4(response);
|
|
18523
|
+
if (!response.ok) {
|
|
18524
|
+
throw createCliError3(
|
|
18525
|
+
"CLI_REGISTRY_METADATA_FETCH_FAILED",
|
|
18526
|
+
mapMetadataError(response.status, payload)
|
|
18527
|
+
);
|
|
18528
|
+
}
|
|
18529
|
+
return parseMetadataPayload(payload, normalizedRegistryUrl);
|
|
18530
|
+
}
|
|
18531
|
+
|
|
18532
|
+
// src/commands/config.ts
|
|
18398
18533
|
var logger5 = createLogger({ service: "cli", module: "config" });
|
|
18399
18534
|
var VALID_KEYS = [
|
|
18400
18535
|
"registryUrl",
|
|
@@ -18437,7 +18572,7 @@ var getEnvRegistryUrlOverride = () => {
|
|
|
18437
18572
|
return typeof value === "string" && value.length > 0;
|
|
18438
18573
|
});
|
|
18439
18574
|
};
|
|
18440
|
-
var createConfigCommand = () => {
|
|
18575
|
+
var createConfigCommand = (dependencies = {}) => {
|
|
18441
18576
|
const configCommand = new Command4("config").description(
|
|
18442
18577
|
"Manage local CLI configuration"
|
|
18443
18578
|
);
|
|
@@ -18454,14 +18589,27 @@ var createConfigCommand = () => {
|
|
|
18454
18589
|
}
|
|
18455
18590
|
}
|
|
18456
18591
|
const config2 = await readConfig();
|
|
18457
|
-
const
|
|
18592
|
+
const requestedRegistryUrl = options.registryUrl ?? getEnvRegistryUrlOverride() ?? config2.registryUrl;
|
|
18593
|
+
const normalizedRegistryUrl = normalizeRegistryUrl(requestedRegistryUrl);
|
|
18594
|
+
const metadata = await fetchRegistryMetadata(normalizedRegistryUrl, {
|
|
18595
|
+
fetchImpl: dependencies.fetchImpl
|
|
18596
|
+
});
|
|
18458
18597
|
await writeConfig({
|
|
18459
18598
|
...config2,
|
|
18460
|
-
registryUrl
|
|
18599
|
+
registryUrl: metadata.registryUrl,
|
|
18600
|
+
proxyUrl: metadata.proxyUrl
|
|
18461
18601
|
});
|
|
18462
18602
|
writeStdoutLine(`Initialized config at ${configFilePath}`);
|
|
18463
18603
|
writeStdoutLine(
|
|
18464
|
-
JSON.stringify(
|
|
18604
|
+
JSON.stringify(
|
|
18605
|
+
maskApiKey({
|
|
18606
|
+
...config2,
|
|
18607
|
+
registryUrl: metadata.registryUrl,
|
|
18608
|
+
proxyUrl: metadata.proxyUrl
|
|
18609
|
+
}),
|
|
18610
|
+
null,
|
|
18611
|
+
2
|
|
18612
|
+
)
|
|
18465
18613
|
);
|
|
18466
18614
|
})
|
|
18467
18615
|
);
|
|
@@ -18768,6 +18916,7 @@ function normalizeConnectionHeaders(headers) {
|
|
|
18768
18916
|
var ConnectorClient = class {
|
|
18769
18917
|
connectorUrl;
|
|
18770
18918
|
connectionHeaders;
|
|
18919
|
+
connectionHeadersProvider;
|
|
18771
18920
|
openclawHookUrl;
|
|
18772
18921
|
openclawHookToken;
|
|
18773
18922
|
heartbeatIntervalMs;
|
|
@@ -18799,6 +18948,7 @@ var ConnectorClient = class {
|
|
|
18799
18948
|
this.connectionHeaders = normalizeConnectionHeaders(
|
|
18800
18949
|
options.connectionHeaders
|
|
18801
18950
|
);
|
|
18951
|
+
this.connectionHeadersProvider = options.connectionHeadersProvider;
|
|
18802
18952
|
this.openclawHookToken = options.openclawHookToken;
|
|
18803
18953
|
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
|
|
18804
18954
|
this.reconnectMinDelayMs = options.reconnectMinDelayMs ?? DEFAULT_RECONNECT_MIN_DELAY_MS;
|
|
@@ -18851,7 +19001,7 @@ var ConnectorClient = class {
|
|
|
18851
19001
|
return;
|
|
18852
19002
|
}
|
|
18853
19003
|
this.started = true;
|
|
18854
|
-
this.connectSocket();
|
|
19004
|
+
void this.connectSocket();
|
|
18855
19005
|
}
|
|
18856
19006
|
disconnect() {
|
|
18857
19007
|
this.started = false;
|
|
@@ -18884,13 +19034,27 @@ var ConnectorClient = class {
|
|
|
18884
19034
|
this.flushOutboundQueue();
|
|
18885
19035
|
return frame;
|
|
18886
19036
|
}
|
|
18887
|
-
connectSocket() {
|
|
19037
|
+
async connectSocket() {
|
|
18888
19038
|
this.clearReconnectTimeout();
|
|
19039
|
+
let connectionHeaders = this.connectionHeaders;
|
|
19040
|
+
if (this.connectionHeadersProvider) {
|
|
19041
|
+
try {
|
|
19042
|
+
connectionHeaders = normalizeConnectionHeaders(
|
|
19043
|
+
await this.connectionHeadersProvider()
|
|
19044
|
+
);
|
|
19045
|
+
} catch (error48) {
|
|
19046
|
+
this.logger.warn("connector.websocket.create_failed", {
|
|
19047
|
+
reason: sanitizeErrorReason(error48)
|
|
19048
|
+
});
|
|
19049
|
+
this.scheduleReconnect();
|
|
19050
|
+
return;
|
|
19051
|
+
}
|
|
19052
|
+
}
|
|
19053
|
+
if (!this.started) {
|
|
19054
|
+
return;
|
|
19055
|
+
}
|
|
18889
19056
|
try {
|
|
18890
|
-
this.socket = this.webSocketFactory(
|
|
18891
|
-
this.connectorUrl,
|
|
18892
|
-
this.connectionHeaders
|
|
18893
|
-
);
|
|
19057
|
+
this.socket = this.webSocketFactory(this.connectorUrl, connectionHeaders);
|
|
18894
19058
|
} catch (error48) {
|
|
18895
19059
|
this.logger.warn("connector.websocket.create_failed", {
|
|
18896
19060
|
reason: sanitizeErrorReason(error48)
|
|
@@ -18945,7 +19109,7 @@ var ConnectorClient = class {
|
|
|
18945
19109
|
const delayMs = Math.max(0, Math.floor(boundedDelay + jitterOffset));
|
|
18946
19110
|
this.reconnectAttempt += 1;
|
|
18947
19111
|
this.reconnectTimeout = setTimeout(() => {
|
|
18948
|
-
this.connectSocket();
|
|
19112
|
+
void this.connectSocket();
|
|
18949
19113
|
}, delayMs);
|
|
18950
19114
|
}
|
|
18951
19115
|
clearReconnectTimeout() {
|
|
@@ -19165,7 +19329,7 @@ var REFRESH_SINGLE_FLIGHT_PREFIX = "connector-runtime";
|
|
|
19165
19329
|
var NONCE_SIZE = 16;
|
|
19166
19330
|
var MAX_OUTBOUND_BODY_BYTES = 1024 * 1024;
|
|
19167
19331
|
var ACCESS_TOKEN_REFRESH_SKEW_MS = 3e4;
|
|
19168
|
-
function
|
|
19332
|
+
function isRecord5(value) {
|
|
19169
19333
|
return typeof value === "object" && value !== null;
|
|
19170
19334
|
}
|
|
19171
19335
|
function toPathWithQuery2(url2) {
|
|
@@ -19213,6 +19377,9 @@ function normalizeWebSocketUrl(urlInput) {
|
|
|
19213
19377
|
if (parsed.protocol !== "wss:" && parsed.protocol !== "ws:") {
|
|
19214
19378
|
throw new Error("Proxy websocket URL must use ws:// or wss://");
|
|
19215
19379
|
}
|
|
19380
|
+
if (parsed.pathname === "/") {
|
|
19381
|
+
parsed.pathname = RELAY_CONNECT_PATH;
|
|
19382
|
+
}
|
|
19216
19383
|
return parsed.toString();
|
|
19217
19384
|
}
|
|
19218
19385
|
function resolveOpenclawBaseUrl(input) {
|
|
@@ -19257,7 +19424,7 @@ function shouldRefreshAccessToken(auth, nowMs) {
|
|
|
19257
19424
|
return expiresAtMs <= nowMs + ACCESS_TOKEN_REFRESH_SKEW_MS;
|
|
19258
19425
|
}
|
|
19259
19426
|
function parseOutboundRelayRequest(payload) {
|
|
19260
|
-
if (!
|
|
19427
|
+
if (!isRecord5(payload)) {
|
|
19261
19428
|
throw new AppError({
|
|
19262
19429
|
code: "CONNECTOR_OUTBOUND_INVALID_REQUEST",
|
|
19263
19430
|
message: "Outbound relay request must be an object",
|
|
@@ -19390,7 +19557,10 @@ async function startConnectorRuntime(input) {
|
|
|
19390
19557
|
parseRequiredString(input.credentials.secretKey, "secretKey")
|
|
19391
19558
|
);
|
|
19392
19559
|
let currentAuth = toInitialAuthBundle(input.credentials);
|
|
19393
|
-
|
|
19560
|
+
const refreshCurrentAuthIfNeeded = async () => {
|
|
19561
|
+
if (!shouldRefreshAccessToken(currentAuth, Date.now())) {
|
|
19562
|
+
return;
|
|
19563
|
+
}
|
|
19394
19564
|
currentAuth = await refreshAgentAuthWithClawProof({
|
|
19395
19565
|
registryUrl: input.registryUrl,
|
|
19396
19566
|
ait: input.credentials.ait,
|
|
@@ -19403,18 +19573,22 @@ async function startConnectorRuntime(input) {
|
|
|
19403
19573
|
agentName: input.agentName,
|
|
19404
19574
|
auth: currentAuth
|
|
19405
19575
|
});
|
|
19406
|
-
}
|
|
19576
|
+
};
|
|
19577
|
+
await refreshCurrentAuthIfNeeded();
|
|
19407
19578
|
const wsUrl = normalizeWebSocketUrl(input.proxyWebsocketUrl);
|
|
19408
19579
|
const wsParsed = new URL(wsUrl);
|
|
19409
|
-
const
|
|
19410
|
-
|
|
19411
|
-
|
|
19412
|
-
|
|
19413
|
-
|
|
19414
|
-
|
|
19580
|
+
const resolveUpgradeHeaders = async () => {
|
|
19581
|
+
await refreshCurrentAuthIfNeeded();
|
|
19582
|
+
return buildUpgradeHeaders({
|
|
19583
|
+
wsUrl: wsParsed,
|
|
19584
|
+
ait: input.credentials.ait,
|
|
19585
|
+
accessToken: currentAuth.accessToken,
|
|
19586
|
+
secretKey
|
|
19587
|
+
});
|
|
19588
|
+
};
|
|
19415
19589
|
const connectorClient = new ConnectorClient({
|
|
19416
19590
|
connectorUrl: wsParsed.toString(),
|
|
19417
|
-
|
|
19591
|
+
connectionHeadersProvider: resolveUpgradeHeaders,
|
|
19418
19592
|
openclawBaseUrl: resolveOpenclawBaseUrl(input.openclawBaseUrl),
|
|
19419
19593
|
openclawHookPath: resolveOpenclawHookPath(input.openclawHookPath),
|
|
19420
19594
|
openclawHookToken: resolveOpenclawHookToken(input.openclawHookToken),
|
|
@@ -19588,16 +19762,16 @@ var OPENCLAW_CONNECTORS_FILE_NAME = "openclaw-connectors.json";
|
|
|
19588
19762
|
var SERVICE_LOG_DIR_NAME = "logs";
|
|
19589
19763
|
var DEFAULT_CONNECTOR_BASE_URL2 = "http://127.0.0.1:19400";
|
|
19590
19764
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH2 = "/v1/outbound";
|
|
19591
|
-
function
|
|
19765
|
+
function isRecord6(value) {
|
|
19592
19766
|
return typeof value === "object" && value !== null;
|
|
19593
19767
|
}
|
|
19594
19768
|
function getErrorCode(error48) {
|
|
19595
|
-
if (!
|
|
19769
|
+
if (!isRecord6(error48)) {
|
|
19596
19770
|
return void 0;
|
|
19597
19771
|
}
|
|
19598
19772
|
return typeof error48.code === "string" ? error48.code : void 0;
|
|
19599
19773
|
}
|
|
19600
|
-
function
|
|
19774
|
+
function createCliError4(code, message2, details) {
|
|
19601
19775
|
return new AppError({
|
|
19602
19776
|
code,
|
|
19603
19777
|
message: message2,
|
|
@@ -19605,9 +19779,9 @@ function createCliError3(code, message2, details) {
|
|
|
19605
19779
|
details
|
|
19606
19780
|
});
|
|
19607
19781
|
}
|
|
19608
|
-
function
|
|
19782
|
+
function parseNonEmptyString6(value, label) {
|
|
19609
19783
|
if (typeof value !== "string") {
|
|
19610
|
-
throw
|
|
19784
|
+
throw createCliError4(
|
|
19611
19785
|
"CLI_CONNECTOR_INVALID_INPUT",
|
|
19612
19786
|
"Connector input is invalid",
|
|
19613
19787
|
{
|
|
@@ -19617,7 +19791,7 @@ function parseNonEmptyString5(value, label) {
|
|
|
19617
19791
|
}
|
|
19618
19792
|
const trimmed = value.trim();
|
|
19619
19793
|
if (trimmed.length === 0) {
|
|
19620
|
-
throw
|
|
19794
|
+
throw createCliError4(
|
|
19621
19795
|
"CLI_CONNECTOR_INVALID_INPUT",
|
|
19622
19796
|
"Connector input is invalid",
|
|
19623
19797
|
{
|
|
@@ -19628,9 +19802,9 @@ function parseNonEmptyString5(value, label) {
|
|
|
19628
19802
|
return trimmed;
|
|
19629
19803
|
}
|
|
19630
19804
|
function parseAgentDid(value) {
|
|
19631
|
-
const did =
|
|
19805
|
+
const did = parseNonEmptyString6(value, "agent did");
|
|
19632
19806
|
if (!did.startsWith("did:claw:agent:")) {
|
|
19633
|
-
throw
|
|
19807
|
+
throw createCliError4(
|
|
19634
19808
|
"CLI_CONNECTOR_INVALID_AGENT_IDENTITY",
|
|
19635
19809
|
"Agent identity is invalid for connector startup"
|
|
19636
19810
|
);
|
|
@@ -19642,13 +19816,13 @@ function parseConnectorBaseUrl(value) {
|
|
|
19642
19816
|
try {
|
|
19643
19817
|
parsed = new URL(value);
|
|
19644
19818
|
} catch {
|
|
19645
|
-
throw
|
|
19819
|
+
throw createCliError4(
|
|
19646
19820
|
"CLI_CONNECTOR_INVALID_BASE_URL",
|
|
19647
19821
|
"Connector base URL is invalid"
|
|
19648
19822
|
);
|
|
19649
19823
|
}
|
|
19650
19824
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
19651
|
-
throw
|
|
19825
|
+
throw createCliError4(
|
|
19652
19826
|
"CLI_CONNECTOR_INVALID_BASE_URL",
|
|
19653
19827
|
"Connector base URL is invalid"
|
|
19654
19828
|
);
|
|
@@ -19658,10 +19832,65 @@ function parseConnectorBaseUrl(value) {
|
|
|
19658
19832
|
}
|
|
19659
19833
|
return parsed.toString();
|
|
19660
19834
|
}
|
|
19835
|
+
function parseProxyWebsocketUrl(value) {
|
|
19836
|
+
let parsed;
|
|
19837
|
+
try {
|
|
19838
|
+
parsed = new URL(value);
|
|
19839
|
+
} catch {
|
|
19840
|
+
throw createCliError4(
|
|
19841
|
+
"CLI_CONNECTOR_INVALID_PROXY_URL",
|
|
19842
|
+
"Proxy websocket URL is invalid"
|
|
19843
|
+
);
|
|
19844
|
+
}
|
|
19845
|
+
if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:" && parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
19846
|
+
throw createCliError4(
|
|
19847
|
+
"CLI_CONNECTOR_INVALID_PROXY_URL",
|
|
19848
|
+
"Proxy websocket URL is invalid"
|
|
19849
|
+
);
|
|
19850
|
+
}
|
|
19851
|
+
return parsed.toString();
|
|
19852
|
+
}
|
|
19853
|
+
function resolveProxyWebsocketUrlFromEnv() {
|
|
19854
|
+
const explicitProxyWsUrl = process.env.CLAWDENTITY_PROXY_WS_URL;
|
|
19855
|
+
if (typeof explicitProxyWsUrl === "string" && explicitProxyWsUrl.trim().length > 0) {
|
|
19856
|
+
return parseProxyWebsocketUrl(explicitProxyWsUrl.trim());
|
|
19857
|
+
}
|
|
19858
|
+
const proxyUrl = process.env.CLAWDENTITY_PROXY_URL;
|
|
19859
|
+
if (typeof proxyUrl === "string" && proxyUrl.trim().length > 0) {
|
|
19860
|
+
return parseProxyWebsocketUrl(proxyUrl.trim());
|
|
19861
|
+
}
|
|
19862
|
+
return void 0;
|
|
19863
|
+
}
|
|
19864
|
+
async function resolveProxyWebsocketUrl(input) {
|
|
19865
|
+
if (typeof input.explicitProxyWsUrl === "string" && input.explicitProxyWsUrl.trim().length > 0) {
|
|
19866
|
+
return parseProxyWebsocketUrl(input.explicitProxyWsUrl.trim());
|
|
19867
|
+
}
|
|
19868
|
+
const fromEnv = resolveProxyWebsocketUrlFromEnv();
|
|
19869
|
+
if (fromEnv !== void 0) {
|
|
19870
|
+
return fromEnv;
|
|
19871
|
+
}
|
|
19872
|
+
if (typeof input.configProxyUrl === "string" && input.configProxyUrl.trim().length > 0) {
|
|
19873
|
+
return parseProxyWebsocketUrl(input.configProxyUrl.trim());
|
|
19874
|
+
}
|
|
19875
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
19876
|
+
if (typeof fetchImpl === "function") {
|
|
19877
|
+
try {
|
|
19878
|
+
const metadata = await fetchRegistryMetadata(input.registryUrl, {
|
|
19879
|
+
fetchImpl
|
|
19880
|
+
});
|
|
19881
|
+
return parseProxyWebsocketUrl(metadata.proxyUrl);
|
|
19882
|
+
} catch {
|
|
19883
|
+
}
|
|
19884
|
+
}
|
|
19885
|
+
throw createCliError4(
|
|
19886
|
+
"CLI_CONNECTOR_PROXY_URL_REQUIRED",
|
|
19887
|
+
"Proxy URL is required for connector startup. Run `clawdentity invite redeem <clw_inv_...>` or set CLAWDENTITY_PROXY_URL / CLAWDENTITY_PROXY_WS_URL."
|
|
19888
|
+
);
|
|
19889
|
+
}
|
|
19661
19890
|
function normalizeOutboundPath2(pathValue) {
|
|
19662
19891
|
const trimmed = pathValue.trim();
|
|
19663
19892
|
if (trimmed.length === 0) {
|
|
19664
|
-
throw
|
|
19893
|
+
throw createCliError4(
|
|
19665
19894
|
"CLI_CONNECTOR_INVALID_OUTBOUND_PATH",
|
|
19666
19895
|
"Connector outbound path is invalid"
|
|
19667
19896
|
);
|
|
@@ -19690,17 +19919,17 @@ async function readConnectorAssignedBaseUrl(configDir, agentName, readFileImpl)
|
|
|
19690
19919
|
try {
|
|
19691
19920
|
parsed = JSON.parse(raw);
|
|
19692
19921
|
} catch {
|
|
19693
|
-
throw
|
|
19922
|
+
throw createCliError4(
|
|
19694
19923
|
"CLI_CONNECTOR_INVALID_ASSIGNMENTS",
|
|
19695
19924
|
"Connector assignments config is invalid JSON",
|
|
19696
19925
|
{ assignmentsPath }
|
|
19697
19926
|
);
|
|
19698
19927
|
}
|
|
19699
|
-
if (!
|
|
19928
|
+
if (!isRecord6(parsed) || !isRecord6(parsed.agents)) {
|
|
19700
19929
|
return void 0;
|
|
19701
19930
|
}
|
|
19702
19931
|
const entry = parsed.agents[agentName];
|
|
19703
|
-
if (!
|
|
19932
|
+
if (!isRecord6(entry) || typeof entry.connectorBaseUrl !== "string") {
|
|
19704
19933
|
return void 0;
|
|
19705
19934
|
}
|
|
19706
19935
|
return parseConnectorBaseUrl(entry.connectorBaseUrl);
|
|
@@ -19721,7 +19950,7 @@ async function readRequiredTrimmedFile(filePath, label, readFileImpl) {
|
|
|
19721
19950
|
raw = await readFileImpl(filePath, "utf8");
|
|
19722
19951
|
} catch (error48) {
|
|
19723
19952
|
if (getErrorCode(error48) === "ENOENT") {
|
|
19724
|
-
throw
|
|
19953
|
+
throw createCliError4(
|
|
19725
19954
|
"CLI_CONNECTOR_MISSING_AGENT_MATERIAL",
|
|
19726
19955
|
"Local agent credentials are missing for connector startup",
|
|
19727
19956
|
{ label }
|
|
@@ -19731,7 +19960,7 @@ async function readRequiredTrimmedFile(filePath, label, readFileImpl) {
|
|
|
19731
19960
|
}
|
|
19732
19961
|
const trimmed = raw.trim();
|
|
19733
19962
|
if (trimmed.length === 0) {
|
|
19734
|
-
throw
|
|
19963
|
+
throw createCliError4(
|
|
19735
19964
|
"CLI_CONNECTOR_MISSING_AGENT_MATERIAL",
|
|
19736
19965
|
"Local agent credentials are missing for connector startup",
|
|
19737
19966
|
{ label }
|
|
@@ -19756,7 +19985,7 @@ async function readRelayRuntimeConfig(configDir, readFileImpl) {
|
|
|
19756
19985
|
} catch {
|
|
19757
19986
|
return void 0;
|
|
19758
19987
|
}
|
|
19759
|
-
if (!
|
|
19988
|
+
if (!isRecord6(parsed)) {
|
|
19760
19989
|
return void 0;
|
|
19761
19990
|
}
|
|
19762
19991
|
const openclawHookToken = typeof parsed.openclawHookToken === "string" && parsed.openclawHookToken.trim().length > 0 ? parsed.openclawHookToken.trim() : void 0;
|
|
@@ -19772,10 +20001,10 @@ function parseJsonRecord(value, code, message2) {
|
|
|
19772
20001
|
try {
|
|
19773
20002
|
parsed = JSON.parse(value);
|
|
19774
20003
|
} catch {
|
|
19775
|
-
throw
|
|
20004
|
+
throw createCliError4(code, message2);
|
|
19776
20005
|
}
|
|
19777
|
-
if (!
|
|
19778
|
-
throw
|
|
20006
|
+
if (!isRecord6(parsed)) {
|
|
20007
|
+
throw createCliError4(code, message2);
|
|
19779
20008
|
}
|
|
19780
20009
|
return parsed;
|
|
19781
20010
|
}
|
|
@@ -19785,7 +20014,7 @@ function parseRegistryAuth(rawRegistryAuth) {
|
|
|
19785
20014
|
"CLI_CONNECTOR_INVALID_REGISTRY_AUTH",
|
|
19786
20015
|
"Agent registry auth is invalid for connector startup"
|
|
19787
20016
|
);
|
|
19788
|
-
const refreshToken =
|
|
20017
|
+
const refreshToken = parseNonEmptyString6(parsed.refreshToken, "refreshToken");
|
|
19789
20018
|
const accessToken = typeof parsed.accessToken === "string" && parsed.accessToken.trim().length > 0 ? parsed.accessToken.trim() : void 0;
|
|
19790
20019
|
const accessExpiresAt = typeof parsed.accessExpiresAt === "string" && parsed.accessExpiresAt.trim().length > 0 ? parsed.accessExpiresAt.trim() : void 0;
|
|
19791
20020
|
const refreshExpiresAt = typeof parsed.refreshExpiresAt === "string" && parsed.refreshExpiresAt.trim().length > 0 ? parsed.refreshExpiresAt.trim() : void 0;
|
|
@@ -19814,7 +20043,7 @@ async function loadDefaultConnectorModule() {
|
|
|
19814
20043
|
};
|
|
19815
20044
|
}
|
|
19816
20045
|
function resolveWaitPromise(runtime) {
|
|
19817
|
-
if (!runtime || !
|
|
20046
|
+
if (!runtime || !isRecord6(runtime)) {
|
|
19818
20047
|
return void 0;
|
|
19819
20048
|
}
|
|
19820
20049
|
if (typeof runtime.waitUntilStopped === "function") {
|
|
@@ -19838,7 +20067,7 @@ function parseConnectorServicePlatformOption(value) {
|
|
|
19838
20067
|
if (value === "auto" || value === "launchd" || value === "systemd") {
|
|
19839
20068
|
return value;
|
|
19840
20069
|
}
|
|
19841
|
-
throw
|
|
20070
|
+
throw createCliError4(
|
|
19842
20071
|
"CLI_CONNECTOR_SERVICE_PLATFORM_INVALID",
|
|
19843
20072
|
"Connector service platform must be one of: auto, launchd, systemd"
|
|
19844
20073
|
);
|
|
@@ -19853,7 +20082,7 @@ function resolveConnectorServicePlatform(inputPlatform, currentPlatform) {
|
|
|
19853
20082
|
if (currentPlatform === "linux") {
|
|
19854
20083
|
return "systemd";
|
|
19855
20084
|
}
|
|
19856
|
-
throw
|
|
20085
|
+
throw createCliError4(
|
|
19857
20086
|
"CLI_CONNECTOR_SERVICE_PLATFORM_UNSUPPORTED",
|
|
19858
20087
|
"Connector service install is supported only on macOS (launchd) and Linux (systemd)",
|
|
19859
20088
|
{
|
|
@@ -19955,7 +20184,7 @@ function resolveServiceDependencies(dependencies) {
|
|
|
19955
20184
|
resolveCurrentPlatformImpl: dependencies.resolveCurrentPlatformImpl ?? (() => process.platform),
|
|
19956
20185
|
resolveCurrentUidImpl: dependencies.resolveCurrentUidImpl ?? (() => {
|
|
19957
20186
|
if (typeof process.getuid !== "function") {
|
|
19958
|
-
throw
|
|
20187
|
+
throw createCliError4(
|
|
19959
20188
|
"CLI_CONNECTOR_SERVICE_UID_UNAVAILABLE",
|
|
19960
20189
|
"Current user id is unavailable in this runtime"
|
|
19961
20190
|
);
|
|
@@ -20017,7 +20246,7 @@ async function installConnectorServiceForAgent(agentName, commandOptions = {}, d
|
|
|
20017
20246
|
`${serviceName}.service`
|
|
20018
20247
|
]);
|
|
20019
20248
|
} catch (error48) {
|
|
20020
|
-
throw
|
|
20249
|
+
throw createCliError4(
|
|
20021
20250
|
"CLI_CONNECTOR_SERVICE_INSTALL_FAILED",
|
|
20022
20251
|
"Failed to install systemd connector service",
|
|
20023
20252
|
{
|
|
@@ -20064,7 +20293,7 @@ async function installConnectorServiceForAgent(agentName, commandOptions = {}, d
|
|
|
20064
20293
|
serviceFilePath
|
|
20065
20294
|
]);
|
|
20066
20295
|
} catch (error48) {
|
|
20067
|
-
throw
|
|
20296
|
+
throw createCliError4(
|
|
20068
20297
|
"CLI_CONNECTOR_SERVICE_INSTALL_FAILED",
|
|
20069
20298
|
"Failed to install launchd connector service",
|
|
20070
20299
|
{
|
|
@@ -20148,6 +20377,7 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20148
20377
|
const resolveConfigImpl = dependencies.resolveConfigImpl ?? resolveConfig;
|
|
20149
20378
|
const getConfigDirImpl = dependencies.getConfigDirImpl ?? getConfigDir;
|
|
20150
20379
|
const readFileImpl = dependencies.readFileImpl ?? ((path, encoding) => readFile3(path, encoding));
|
|
20380
|
+
const fetchImpl = dependencies.fetchImpl ?? globalThis.fetch;
|
|
20151
20381
|
const loadConnectorModule = dependencies.loadConnectorModule ?? loadDefaultConnectorModule;
|
|
20152
20382
|
const configDir = getConfigDirImpl();
|
|
20153
20383
|
const agentDirectory = join5(configDir, AGENTS_DIR_NAME3, agentName);
|
|
@@ -20187,13 +20417,19 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20187
20417
|
loadConnectorModule()
|
|
20188
20418
|
]);
|
|
20189
20419
|
if (typeof connectorModule.startConnectorRuntime !== "function") {
|
|
20190
|
-
throw
|
|
20420
|
+
throw createCliError4(
|
|
20191
20421
|
"CLI_CONNECTOR_INVALID_PACKAGE_API",
|
|
20192
20422
|
"Connector package does not expose startConnectorRuntime"
|
|
20193
20423
|
);
|
|
20194
20424
|
}
|
|
20195
20425
|
const identity = parseAgentIdentity(rawIdentity);
|
|
20196
20426
|
const registryAuth = parseRegistryAuth(rawRegistryAuth);
|
|
20427
|
+
const resolvedProxyWebsocketUrl = await resolveProxyWebsocketUrl({
|
|
20428
|
+
explicitProxyWsUrl: commandOptions.proxyWsUrl,
|
|
20429
|
+
configProxyUrl: config2.proxyUrl,
|
|
20430
|
+
registryUrl: config2.registryUrl,
|
|
20431
|
+
fetchImpl
|
|
20432
|
+
});
|
|
20197
20433
|
const openclawHookToken = commandOptions.openclawHookToken ?? relayRuntimeConfig?.openclawHookToken;
|
|
20198
20434
|
const outboundBaseUrl = resolveConnectorBaseUrlFromEnv() ?? assignedConnectorBaseUrl ?? DEFAULT_CONNECTOR_BASE_URL2;
|
|
20199
20435
|
const outboundPath = resolveConnectorOutboundPath();
|
|
@@ -20203,7 +20439,7 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20203
20439
|
registryUrl: config2.registryUrl,
|
|
20204
20440
|
outboundBaseUrl,
|
|
20205
20441
|
outboundPath,
|
|
20206
|
-
proxyWebsocketUrl:
|
|
20442
|
+
proxyWebsocketUrl: resolvedProxyWebsocketUrl,
|
|
20207
20443
|
openclawBaseUrl: commandOptions.openclawBaseUrl,
|
|
20208
20444
|
openclawHookPath: commandOptions.openclawHookPath,
|
|
20209
20445
|
openclawHookToken,
|
|
@@ -20218,8 +20454,8 @@ async function startConnectorForAgent(agentName, commandOptions = {}, dependenci
|
|
|
20218
20454
|
tokenType: registryAuth.tokenType
|
|
20219
20455
|
}
|
|
20220
20456
|
});
|
|
20221
|
-
const outboundUrl = runtime &&
|
|
20222
|
-
const proxyWebsocketUrl = runtime &&
|
|
20457
|
+
const outboundUrl = runtime && isRecord6(runtime) && typeof runtime.outboundUrl === "string" ? runtime.outboundUrl : resolveOutboundUrl(outboundBaseUrl, outboundPath);
|
|
20458
|
+
const proxyWebsocketUrl = runtime && isRecord6(runtime) ? typeof runtime.websocketUrl === "string" ? runtime.websocketUrl : typeof runtime.proxyWebsocketUrl === "string" ? runtime.proxyWebsocketUrl : resolvedProxyWebsocketUrl : void 0;
|
|
20223
20459
|
return {
|
|
20224
20460
|
outboundUrl,
|
|
20225
20461
|
proxyWebsocketUrl,
|
|
@@ -20349,107 +20585,52 @@ function createConnectorCommand(dependencies = {}) {
|
|
|
20349
20585
|
|
|
20350
20586
|
// src/commands/invite.ts
|
|
20351
20587
|
import { Command as Command6 } from "commander";
|
|
20352
|
-
|
|
20353
|
-
// src/config/endpoints.ts
|
|
20354
|
-
var PRODUCTION_REGISTRY_HOST = "registry.clawdentity.com";
|
|
20355
|
-
var DEVELOPMENT_REGISTRY_HOST = "dev.registry.clawdentity.com";
|
|
20356
|
-
var PRODUCTION_PROXY_HOST = "proxy.clawdentity.com";
|
|
20357
|
-
var DEVELOPMENT_PROXY_HOST = "dev.proxy.clawdentity.com";
|
|
20358
|
-
var LOCAL_REGISTRY_PORT = "8788";
|
|
20359
|
-
var LOCAL_PROXY_PORT = "8787";
|
|
20360
|
-
var LOCAL_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
20361
|
-
"localhost",
|
|
20362
|
-
"127.0.0.1",
|
|
20363
|
-
"host.docker.internal",
|
|
20364
|
-
"gateway.docker.internal"
|
|
20365
|
-
]);
|
|
20366
|
-
var normalizeUrl = (candidate) => {
|
|
20367
|
-
try {
|
|
20368
|
-
const parsed = new URL(candidate);
|
|
20369
|
-
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
20370
|
-
return void 0;
|
|
20371
|
-
}
|
|
20372
|
-
return parsed;
|
|
20373
|
-
} catch {
|
|
20374
|
-
return void 0;
|
|
20375
|
-
}
|
|
20376
|
-
};
|
|
20377
|
-
var toProxyHostname = (registryHostname) => {
|
|
20378
|
-
if (registryHostname === PRODUCTION_REGISTRY_HOST) {
|
|
20379
|
-
return PRODUCTION_PROXY_HOST;
|
|
20380
|
-
}
|
|
20381
|
-
if (registryHostname === DEVELOPMENT_REGISTRY_HOST) {
|
|
20382
|
-
return DEVELOPMENT_PROXY_HOST;
|
|
20383
|
-
}
|
|
20384
|
-
if (registryHostname.startsWith("dev.registry.")) {
|
|
20385
|
-
return `dev.proxy.${registryHostname.slice("dev.registry.".length)}`;
|
|
20386
|
-
}
|
|
20387
|
-
if (registryHostname.startsWith("registry.")) {
|
|
20388
|
-
return `proxy.${registryHostname.slice("registry.".length)}`;
|
|
20389
|
-
}
|
|
20390
|
-
return void 0;
|
|
20391
|
-
};
|
|
20392
|
-
var deriveProxyUrlFromRegistryUrl = (registryUrl) => {
|
|
20393
|
-
const parsedRegistryUrl = normalizeUrl(registryUrl);
|
|
20394
|
-
if (!parsedRegistryUrl) {
|
|
20395
|
-
return void 0;
|
|
20396
|
-
}
|
|
20397
|
-
const hostname3 = parsedRegistryUrl.hostname.toLowerCase();
|
|
20398
|
-
if (LOCAL_HOSTNAMES.has(hostname3) && parsedRegistryUrl.port === LOCAL_REGISTRY_PORT) {
|
|
20399
|
-
return `${parsedRegistryUrl.protocol}//${hostname3}:${LOCAL_PROXY_PORT}/`;
|
|
20400
|
-
}
|
|
20401
|
-
const mappedHostname = toProxyHostname(hostname3);
|
|
20402
|
-
if (!mappedHostname) {
|
|
20403
|
-
return void 0;
|
|
20404
|
-
}
|
|
20405
|
-
const port = parsedRegistryUrl.port.length > 0 ? `:${parsedRegistryUrl.port}` : "";
|
|
20406
|
-
return `${parsedRegistryUrl.protocol}//${mappedHostname}${port}/`;
|
|
20407
|
-
};
|
|
20408
|
-
|
|
20409
|
-
// src/commands/invite.ts
|
|
20410
20588
|
var logger7 = createLogger({ service: "cli", module: "invite" });
|
|
20411
|
-
var
|
|
20589
|
+
var isRecord7 = (value) => {
|
|
20412
20590
|
return typeof value === "object" && value !== null;
|
|
20413
20591
|
};
|
|
20414
|
-
function
|
|
20592
|
+
function parseNonEmptyString7(value) {
|
|
20415
20593
|
if (typeof value !== "string") {
|
|
20416
20594
|
return "";
|
|
20417
20595
|
}
|
|
20418
20596
|
return value.trim();
|
|
20419
20597
|
}
|
|
20420
|
-
function
|
|
20598
|
+
function createCliError5(code, message2) {
|
|
20421
20599
|
return new AppError({
|
|
20422
20600
|
code,
|
|
20423
20601
|
message: message2,
|
|
20424
20602
|
status: 400
|
|
20425
20603
|
});
|
|
20426
20604
|
}
|
|
20427
|
-
function
|
|
20428
|
-
const candidate = parseNonEmptyString6(input.overrideRegistryUrl) || input.configRegistryUrl;
|
|
20605
|
+
function normalizeProxyUrl(value) {
|
|
20429
20606
|
try {
|
|
20430
|
-
|
|
20607
|
+
const parsed = new URL(value);
|
|
20608
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
20609
|
+
throw new Error("invalid protocol");
|
|
20610
|
+
}
|
|
20611
|
+
return parsed.toString();
|
|
20431
20612
|
} catch {
|
|
20432
|
-
throw
|
|
20433
|
-
"
|
|
20434
|
-
"
|
|
20613
|
+
throw createCliError5(
|
|
20614
|
+
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20615
|
+
"Invite redeem response is invalid"
|
|
20435
20616
|
);
|
|
20436
20617
|
}
|
|
20437
20618
|
}
|
|
20619
|
+
function resolveRegistryUrl2(input) {
|
|
20620
|
+
const candidate = parseNonEmptyString7(input.overrideRegistryUrl) || input.configRegistryUrl;
|
|
20621
|
+
return normalizeRegistryUrl(candidate);
|
|
20622
|
+
}
|
|
20438
20623
|
function requireApiKey2(config2) {
|
|
20439
20624
|
if (typeof config2.apiKey === "string" && config2.apiKey.trim().length > 0) {
|
|
20440
20625
|
return config2.apiKey;
|
|
20441
20626
|
}
|
|
20442
|
-
throw
|
|
20627
|
+
throw createCliError5(
|
|
20443
20628
|
"CLI_INVITE_MISSING_LOCAL_CREDENTIALS",
|
|
20444
20629
|
"API key is not configured. Run `clawdentity config set apiKey <token>` or set CLAWDENTITY_API_KEY."
|
|
20445
20630
|
);
|
|
20446
20631
|
}
|
|
20447
|
-
function toRegistryRequestUrl(registryUrl, path) {
|
|
20448
|
-
const normalizedBaseUrl = registryUrl.endsWith("/") ? registryUrl : `${registryUrl}/`;
|
|
20449
|
-
return new URL(path.slice(1), normalizedBaseUrl).toString();
|
|
20450
|
-
}
|
|
20451
20632
|
function extractRegistryErrorCode(payload) {
|
|
20452
|
-
if (!
|
|
20633
|
+
if (!isRecord7(payload)) {
|
|
20453
20634
|
return void 0;
|
|
20454
20635
|
}
|
|
20455
20636
|
const envelope = payload;
|
|
@@ -20459,8 +20640,8 @@ function extractRegistryErrorCode(payload) {
|
|
|
20459
20640
|
const trimmed = envelope.error.code.trim();
|
|
20460
20641
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
20461
20642
|
}
|
|
20462
|
-
function
|
|
20463
|
-
if (!
|
|
20643
|
+
function extractRegistryErrorMessage4(payload) {
|
|
20644
|
+
if (!isRecord7(payload)) {
|
|
20464
20645
|
return void 0;
|
|
20465
20646
|
}
|
|
20466
20647
|
const envelope = payload;
|
|
@@ -20470,7 +20651,7 @@ function extractRegistryErrorMessage3(payload) {
|
|
|
20470
20651
|
const trimmed = envelope.error.message.trim();
|
|
20471
20652
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
20472
20653
|
}
|
|
20473
|
-
async function
|
|
20654
|
+
async function parseJsonResponse5(response) {
|
|
20474
20655
|
try {
|
|
20475
20656
|
return await response.json();
|
|
20476
20657
|
} catch {
|
|
@@ -20481,7 +20662,7 @@ async function executeInviteRequest(input) {
|
|
|
20481
20662
|
try {
|
|
20482
20663
|
return await input.fetchImpl(input.url, input.init);
|
|
20483
20664
|
} catch {
|
|
20484
|
-
throw
|
|
20665
|
+
throw createCliError5(
|
|
20485
20666
|
"CLI_INVITE_REQUEST_FAILED",
|
|
20486
20667
|
"Unable to connect to the registry. Check network access and registryUrl."
|
|
20487
20668
|
);
|
|
@@ -20489,7 +20670,7 @@ async function executeInviteRequest(input) {
|
|
|
20489
20670
|
}
|
|
20490
20671
|
function mapCreateInviteError(status, payload) {
|
|
20491
20672
|
const errorCode = extractRegistryErrorCode(payload);
|
|
20492
|
-
const registryMessage =
|
|
20673
|
+
const registryMessage = extractRegistryErrorMessage4(payload);
|
|
20493
20674
|
if (status === 401) {
|
|
20494
20675
|
return registryMessage ? `Registry authentication failed (401): ${registryMessage}` : "Registry authentication failed (401). Check your API key.";
|
|
20495
20676
|
}
|
|
@@ -20512,7 +20693,7 @@ function mapCreateInviteError(status, payload) {
|
|
|
20512
20693
|
}
|
|
20513
20694
|
function mapRedeemInviteError(status, payload) {
|
|
20514
20695
|
const errorCode = extractRegistryErrorCode(payload);
|
|
20515
|
-
const registryMessage =
|
|
20696
|
+
const registryMessage = extractRegistryErrorMessage4(payload);
|
|
20516
20697
|
if (errorCode === "INVITE_REDEEM_ALREADY_USED" || errorCode === "INVITE_REDEEM_ALREADY_REDEEMED") {
|
|
20517
20698
|
return "Invite code has already been redeemed";
|
|
20518
20699
|
}
|
|
@@ -20534,16 +20715,16 @@ function mapRedeemInviteError(status, payload) {
|
|
|
20534
20715
|
return `Invite redeem failed (${status})`;
|
|
20535
20716
|
}
|
|
20536
20717
|
function parseInviteRecord(payload) {
|
|
20537
|
-
if (!
|
|
20538
|
-
throw
|
|
20718
|
+
if (!isRecord7(payload)) {
|
|
20719
|
+
throw createCliError5(
|
|
20539
20720
|
"CLI_INVITE_CREATE_INVALID_RESPONSE",
|
|
20540
20721
|
"Invite response is invalid"
|
|
20541
20722
|
);
|
|
20542
20723
|
}
|
|
20543
|
-
const source =
|
|
20544
|
-
const code =
|
|
20724
|
+
const source = isRecord7(payload.invite) ? payload.invite : payload;
|
|
20725
|
+
const code = parseNonEmptyString7(source.code);
|
|
20545
20726
|
if (code.length === 0) {
|
|
20546
|
-
throw
|
|
20727
|
+
throw createCliError5(
|
|
20547
20728
|
"CLI_INVITE_CREATE_INVALID_RESPONSE",
|
|
20548
20729
|
"Invite response is invalid"
|
|
20549
20730
|
);
|
|
@@ -20551,11 +20732,11 @@ function parseInviteRecord(payload) {
|
|
|
20551
20732
|
const invite = {
|
|
20552
20733
|
code
|
|
20553
20734
|
};
|
|
20554
|
-
const id =
|
|
20735
|
+
const id = parseNonEmptyString7(source.id);
|
|
20555
20736
|
if (id.length > 0) {
|
|
20556
20737
|
invite.id = id;
|
|
20557
20738
|
}
|
|
20558
|
-
const createdAt =
|
|
20739
|
+
const createdAt = parseNonEmptyString7(source.createdAt);
|
|
20559
20740
|
if (createdAt.length > 0) {
|
|
20560
20741
|
invite.createdAt = createdAt;
|
|
20561
20742
|
}
|
|
@@ -20565,36 +20746,25 @@ function parseInviteRecord(payload) {
|
|
|
20565
20746
|
return invite;
|
|
20566
20747
|
}
|
|
20567
20748
|
function parseInviteRedeemResponse(payload) {
|
|
20568
|
-
if (!
|
|
20569
|
-
throw
|
|
20749
|
+
if (!isRecord7(payload)) {
|
|
20750
|
+
throw createCliError5(
|
|
20570
20751
|
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20571
20752
|
"Invite redeem response is invalid"
|
|
20572
20753
|
);
|
|
20573
20754
|
}
|
|
20574
|
-
const apiKeySource =
|
|
20575
|
-
const apiKeyToken =
|
|
20576
|
-
|
|
20755
|
+
const apiKeySource = isRecord7(payload.apiKey) ? payload.apiKey : payload;
|
|
20756
|
+
const apiKeyToken = parseNonEmptyString7(
|
|
20757
|
+
isRecord7(payload.apiKey) ? payload.apiKey.token : payload.token
|
|
20577
20758
|
);
|
|
20578
20759
|
if (apiKeyToken.length === 0) {
|
|
20579
|
-
throw
|
|
20760
|
+
throw createCliError5(
|
|
20580
20761
|
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20581
20762
|
"Invite redeem response is invalid"
|
|
20582
20763
|
);
|
|
20583
20764
|
}
|
|
20584
|
-
const apiKeyId =
|
|
20585
|
-
const apiKeyName =
|
|
20586
|
-
const
|
|
20587
|
-
let proxyUrl;
|
|
20588
|
-
if (proxyUrlCandidate.length > 0) {
|
|
20589
|
-
try {
|
|
20590
|
-
const parsed = new URL(proxyUrlCandidate);
|
|
20591
|
-
if (parsed.protocol === "https:" || parsed.protocol === "http:") {
|
|
20592
|
-
proxyUrl = parsed.toString();
|
|
20593
|
-
}
|
|
20594
|
-
} catch {
|
|
20595
|
-
proxyUrl = void 0;
|
|
20596
|
-
}
|
|
20597
|
-
}
|
|
20765
|
+
const apiKeyId = parseNonEmptyString7(apiKeySource.id);
|
|
20766
|
+
const apiKeyName = parseNonEmptyString7(apiKeySource.name);
|
|
20767
|
+
const proxyUrl = parseNonEmptyString7(payload.proxyUrl);
|
|
20598
20768
|
return {
|
|
20599
20769
|
apiKeyToken,
|
|
20600
20770
|
apiKeyId: apiKeyId.length > 0 ? apiKeyId : void 0,
|
|
@@ -20629,13 +20799,13 @@ async function createInvite(options, dependencies = {}) {
|
|
|
20629
20799
|
"content-type": "application/json"
|
|
20630
20800
|
},
|
|
20631
20801
|
body: JSON.stringify({
|
|
20632
|
-
expiresAt:
|
|
20802
|
+
expiresAt: parseNonEmptyString7(options.expiresAt) || void 0
|
|
20633
20803
|
})
|
|
20634
20804
|
}
|
|
20635
20805
|
});
|
|
20636
|
-
const responseBody = await
|
|
20806
|
+
const responseBody = await parseJsonResponse5(response);
|
|
20637
20807
|
if (!response.ok) {
|
|
20638
|
-
throw
|
|
20808
|
+
throw createCliError5(
|
|
20639
20809
|
"CLI_INVITE_CREATE_FAILED",
|
|
20640
20810
|
mapCreateInviteError(response.status, responseBody)
|
|
20641
20811
|
);
|
|
@@ -20646,9 +20816,9 @@ async function createInvite(options, dependencies = {}) {
|
|
|
20646
20816
|
};
|
|
20647
20817
|
}
|
|
20648
20818
|
async function redeemInvite(code, options, dependencies = {}) {
|
|
20649
|
-
const inviteCode =
|
|
20819
|
+
const inviteCode = parseNonEmptyString7(code);
|
|
20650
20820
|
if (inviteCode.length === 0) {
|
|
20651
|
-
throw
|
|
20821
|
+
throw createCliError5(
|
|
20652
20822
|
"CLI_INVITE_REDEEM_CODE_REQUIRED",
|
|
20653
20823
|
"Invite code is required"
|
|
20654
20824
|
);
|
|
@@ -20665,36 +20835,34 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20665
20835
|
body: JSON.stringify({ code: inviteCode })
|
|
20666
20836
|
}
|
|
20667
20837
|
});
|
|
20668
|
-
const responseBody = await
|
|
20838
|
+
const responseBody = await parseJsonResponse5(response);
|
|
20669
20839
|
if (!response.ok) {
|
|
20670
|
-
throw
|
|
20840
|
+
throw createCliError5(
|
|
20671
20841
|
"CLI_INVITE_REDEEM_FAILED",
|
|
20672
20842
|
mapRedeemInviteError(response.status, responseBody)
|
|
20673
20843
|
);
|
|
20674
20844
|
}
|
|
20845
|
+
const parsedRedeem = parseInviteRedeemResponse(responseBody);
|
|
20846
|
+
const proxyUrl = parsedRedeem.proxyUrl.length > 0 ? parsedRedeem.proxyUrl : (await fetchRegistryMetadata(runtime.registryUrl, {
|
|
20847
|
+
fetchImpl: runtime.fetchImpl
|
|
20848
|
+
})).proxyUrl;
|
|
20675
20849
|
return {
|
|
20676
|
-
...
|
|
20850
|
+
...parsedRedeem,
|
|
20851
|
+
proxyUrl: normalizeProxyUrl(proxyUrl),
|
|
20677
20852
|
registryUrl: runtime.registryUrl
|
|
20678
20853
|
};
|
|
20679
20854
|
}
|
|
20680
|
-
async function persistRedeemConfig(
|
|
20855
|
+
async function persistRedeemConfig(registryUrl, apiKeyToken, proxyUrl, dependencies = {}) {
|
|
20681
20856
|
const setConfigValueImpl = dependencies.setConfigValueImpl ?? setConfigValue;
|
|
20682
20857
|
try {
|
|
20683
|
-
await setConfigValueImpl("registryUrl",
|
|
20684
|
-
await setConfigValueImpl("apiKey",
|
|
20685
|
-
|
|
20686
|
-
if (!resolvedProxyUrl) {
|
|
20687
|
-
throw createCliError4(
|
|
20688
|
-
"CLI_INVITE_REDEEM_PROXY_URL_MISSING",
|
|
20689
|
-
"Proxy URL is missing from onboarding response and could not be derived from registry URL."
|
|
20690
|
-
);
|
|
20691
|
-
}
|
|
20692
|
-
await setConfigValueImpl("proxyUrl", resolvedProxyUrl);
|
|
20858
|
+
await setConfigValueImpl("registryUrl", registryUrl);
|
|
20859
|
+
await setConfigValueImpl("apiKey", apiKeyToken);
|
|
20860
|
+
await setConfigValueImpl("proxyUrl", proxyUrl);
|
|
20693
20861
|
} catch (error48) {
|
|
20694
20862
|
logger7.warn("cli.invite_redeem_config_persist_failed", {
|
|
20695
20863
|
errorName: error48 instanceof Error ? error48.name : "unknown"
|
|
20696
20864
|
});
|
|
20697
|
-
throw
|
|
20865
|
+
throw createCliError5(
|
|
20698
20866
|
"CLI_INVITE_REDEEM_CONFIG_PERSISTENCE_FAILED",
|
|
20699
20867
|
"Failed to save redeemed API key locally"
|
|
20700
20868
|
);
|
|
@@ -20702,7 +20870,7 @@ async function persistRedeemConfig(input, dependencies = {}) {
|
|
|
20702
20870
|
}
|
|
20703
20871
|
var createInviteCommand = (dependencies = {}) => {
|
|
20704
20872
|
const inviteCommand = new Command6("invite").description(
|
|
20705
|
-
"Manage registry onboarding invites"
|
|
20873
|
+
"Manage registry onboarding invites (not OpenClaw peer relay invites)"
|
|
20706
20874
|
);
|
|
20707
20875
|
inviteCommand.command("create").description("Create a registry invite code (admin only)").option("--expires-at <timestamp>", "Optional invite expiry (ISO-8601)").option("--registry-url <url>", "Override registry URL").action(
|
|
20708
20876
|
withErrorHandling(
|
|
@@ -20740,15 +20908,12 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20740
20908
|
writeStdoutLine("API key token (shown once):");
|
|
20741
20909
|
writeStdoutLine(result.apiKeyToken);
|
|
20742
20910
|
await persistRedeemConfig(
|
|
20743
|
-
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
proxyUrl: result.proxyUrl
|
|
20747
|
-
},
|
|
20911
|
+
result.registryUrl,
|
|
20912
|
+
result.apiKeyToken,
|
|
20913
|
+
result.proxyUrl,
|
|
20748
20914
|
dependencies
|
|
20749
20915
|
);
|
|
20750
20916
|
writeStdoutLine("API key saved to local config");
|
|
20751
|
-
writeStdoutLine("Onboarding auth complete");
|
|
20752
20917
|
}
|
|
20753
20918
|
)
|
|
20754
20919
|
);
|
|
@@ -20770,8 +20935,16 @@ var SECRET_KEY_FILE_NAME2 = "secret.key";
|
|
|
20770
20935
|
var PEERS_FILE_NAME = "peers.json";
|
|
20771
20936
|
var OPENCLAW_DIR_NAME = ".openclaw";
|
|
20772
20937
|
var OPENCLAW_CONFIG_FILE_NAME = "openclaw.json";
|
|
20773
|
-
var LEGACY_OPENCLAW_STATE_DIR_NAMES = [
|
|
20774
|
-
|
|
20938
|
+
var LEGACY_OPENCLAW_STATE_DIR_NAMES = [
|
|
20939
|
+
".clawdbot",
|
|
20940
|
+
".moldbot",
|
|
20941
|
+
".moltbot"
|
|
20942
|
+
];
|
|
20943
|
+
var LEGACY_OPENCLAW_CONFIG_FILE_NAMES = [
|
|
20944
|
+
"clawdbot.json",
|
|
20945
|
+
"moldbot.json",
|
|
20946
|
+
"moltbot.json"
|
|
20947
|
+
];
|
|
20775
20948
|
var OPENCLAW_AGENT_FILE_NAME = "openclaw-agent-name";
|
|
20776
20949
|
var OPENCLAW_RELAY_RUNTIME_FILE_NAME2 = "openclaw-relay.json";
|
|
20777
20950
|
var OPENCLAW_CONNECTORS_FILE_NAME2 = "openclaw-connectors.json";
|
|
@@ -20783,6 +20956,8 @@ var HOOK_MAPPING_ID = "clawdentity-send-to-peer";
|
|
|
20783
20956
|
var HOOK_PATH_SEND_TO_PEER = "send-to-peer";
|
|
20784
20957
|
var OPENCLAW_SEND_TO_PEER_HOOK_PATH = "hooks/send-to-peer";
|
|
20785
20958
|
var DEFAULT_OPENCLAW_BASE_URL2 = "http://127.0.0.1:18789";
|
|
20959
|
+
var DEFAULT_OPENCLAW_MAIN_SESSION_KEY = "main";
|
|
20960
|
+
var DEFAULT_OPENCLAW_AGENT_ID = "main";
|
|
20786
20961
|
var DEFAULT_CONNECTOR_PORT = 19400;
|
|
20787
20962
|
var DEFAULT_CONNECTOR_OUTBOUND_PATH3 = "/v1/outbound";
|
|
20788
20963
|
var CONNECTOR_HOST_LOOPBACK = "127.0.0.1";
|
|
@@ -20798,10 +20973,10 @@ var OPENCLAW_SETUP_WITH_BASE_URL_HINT = `${OPENCLAW_SETUP_COMMAND_HINT} --opencl
|
|
|
20798
20973
|
var OPENCLAW_PAIRING_COMMAND_HINT = "Run QR pairing first: clawdentity pair start <agentName> --qr and clawdentity pair confirm <agentName> --qr-file <path>";
|
|
20799
20974
|
var textEncoder2 = new TextEncoder();
|
|
20800
20975
|
var textDecoder = new TextDecoder();
|
|
20801
|
-
function
|
|
20976
|
+
function isRecord8(value) {
|
|
20802
20977
|
return typeof value === "object" && value !== null;
|
|
20803
20978
|
}
|
|
20804
|
-
function
|
|
20979
|
+
function createCliError6(code, message2, details) {
|
|
20805
20980
|
return new AppError({
|
|
20806
20981
|
code,
|
|
20807
20982
|
message: message2,
|
|
@@ -20810,14 +20985,14 @@ function createCliError5(code, message2, details) {
|
|
|
20810
20985
|
});
|
|
20811
20986
|
}
|
|
20812
20987
|
function getErrorCode2(error48) {
|
|
20813
|
-
if (!
|
|
20988
|
+
if (!isRecord8(error48)) {
|
|
20814
20989
|
return void 0;
|
|
20815
20990
|
}
|
|
20816
20991
|
return typeof error48.code === "string" ? error48.code : void 0;
|
|
20817
20992
|
}
|
|
20818
|
-
function
|
|
20993
|
+
function parseNonEmptyString8(value, label) {
|
|
20819
20994
|
if (typeof value !== "string") {
|
|
20820
|
-
throw
|
|
20995
|
+
throw createCliError6(
|
|
20821
20996
|
"CLI_OPENCLAW_INVALID_INPUT",
|
|
20822
20997
|
"Input must be a string",
|
|
20823
20998
|
{
|
|
@@ -20827,7 +21002,7 @@ function parseNonEmptyString7(value, label) {
|
|
|
20827
21002
|
}
|
|
20828
21003
|
const trimmed = value.trim();
|
|
20829
21004
|
if (trimmed.length === 0) {
|
|
20830
|
-
throw
|
|
21005
|
+
throw createCliError6(
|
|
20831
21006
|
"CLI_OPENCLAW_INVALID_INPUT",
|
|
20832
21007
|
"Input must not be empty",
|
|
20833
21008
|
{ label }
|
|
@@ -20839,18 +21014,18 @@ function parseOptionalName(value) {
|
|
|
20839
21014
|
if (value === void 0) {
|
|
20840
21015
|
return void 0;
|
|
20841
21016
|
}
|
|
20842
|
-
return
|
|
21017
|
+
return parseNonEmptyString8(value, "name");
|
|
20843
21018
|
}
|
|
20844
21019
|
function parsePeerAlias(value) {
|
|
20845
|
-
const alias =
|
|
21020
|
+
const alias = parseNonEmptyString8(value, "peer alias");
|
|
20846
21021
|
if (alias.length > 128) {
|
|
20847
|
-
throw
|
|
21022
|
+
throw createCliError6(
|
|
20848
21023
|
"CLI_OPENCLAW_INVALID_PEER_ALIAS",
|
|
20849
21024
|
"peer alias must be at most 128 characters"
|
|
20850
21025
|
);
|
|
20851
21026
|
}
|
|
20852
21027
|
if (!PEER_ALIAS_PATTERN.test(alias)) {
|
|
20853
|
-
throw
|
|
21028
|
+
throw createCliError6(
|
|
20854
21029
|
"CLI_OPENCLAW_INVALID_PEER_ALIAS",
|
|
20855
21030
|
"peer alias must use only letters, numbers, dot, underscore, or hyphen"
|
|
20856
21031
|
);
|
|
@@ -20865,15 +21040,15 @@ function parseProxyUrl(value) {
|
|
|
20865
21040
|
});
|
|
20866
21041
|
}
|
|
20867
21042
|
function parseHttpUrl(value, input) {
|
|
20868
|
-
const candidate =
|
|
21043
|
+
const candidate = parseNonEmptyString8(value, input.label);
|
|
20869
21044
|
let parsedUrl;
|
|
20870
21045
|
try {
|
|
20871
21046
|
parsedUrl = new URL(candidate);
|
|
20872
21047
|
} catch {
|
|
20873
|
-
throw
|
|
21048
|
+
throw createCliError6(input.code, input.message);
|
|
20874
21049
|
}
|
|
20875
21050
|
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
20876
|
-
throw
|
|
21051
|
+
throw createCliError6(input.code, `${input.label} must use http or https`);
|
|
20877
21052
|
}
|
|
20878
21053
|
if (parsedUrl.pathname === "/" && parsedUrl.search.length === 0 && parsedUrl.hash.length === 0) {
|
|
20879
21054
|
return parsedUrl.origin;
|
|
@@ -20888,17 +21063,17 @@ function parseOpenclawBaseUrl(value) {
|
|
|
20888
21063
|
});
|
|
20889
21064
|
}
|
|
20890
21065
|
function parseAgentDid2(value, label) {
|
|
20891
|
-
const did =
|
|
21066
|
+
const did = parseNonEmptyString8(value, label);
|
|
20892
21067
|
try {
|
|
20893
21068
|
const parsed = parseDid(did);
|
|
20894
21069
|
if (parsed.kind !== "agent") {
|
|
20895
|
-
throw
|
|
21070
|
+
throw createCliError6(
|
|
20896
21071
|
"CLI_OPENCLAW_INVALID_DID",
|
|
20897
21072
|
"DID is not an agent DID"
|
|
20898
21073
|
);
|
|
20899
21074
|
}
|
|
20900
21075
|
} catch {
|
|
20901
|
-
throw
|
|
21076
|
+
throw createCliError6("CLI_OPENCLAW_INVALID_DID", "Agent DID is invalid", {
|
|
20902
21077
|
label
|
|
20903
21078
|
});
|
|
20904
21079
|
}
|
|
@@ -20924,7 +21099,10 @@ function readNonEmptyEnvPath(value, homeDir) {
|
|
|
20924
21099
|
return resolveHomePrefixedPath(value, homeDir);
|
|
20925
21100
|
}
|
|
20926
21101
|
function resolveOpenclawHomeDir(homeDir) {
|
|
20927
|
-
const envOpenclawHome = readNonEmptyEnvPath(
|
|
21102
|
+
const envOpenclawHome = readNonEmptyEnvPath(
|
|
21103
|
+
process.env.OPENCLAW_HOME,
|
|
21104
|
+
homeDir
|
|
21105
|
+
);
|
|
20928
21106
|
return envOpenclawHome ?? homeDir;
|
|
20929
21107
|
}
|
|
20930
21108
|
function resolveDefaultOpenclawStateDir(openclawHomeDir) {
|
|
@@ -21020,7 +21198,7 @@ async function readJsonFile(filePath) {
|
|
|
21020
21198
|
try {
|
|
21021
21199
|
return JSON.parse(raw);
|
|
21022
21200
|
} catch {
|
|
21023
|
-
throw
|
|
21201
|
+
throw createCliError6("CLI_OPENCLAW_INVALID_JSON", "JSON file is invalid", {
|
|
21024
21202
|
filePath
|
|
21025
21203
|
});
|
|
21026
21204
|
}
|
|
@@ -21037,7 +21215,7 @@ async function ensureLocalAgentCredentials(homeDir, agentName) {
|
|
|
21037
21215
|
content = await readFile4(filePath, "utf8");
|
|
21038
21216
|
} catch (error48) {
|
|
21039
21217
|
if (getErrorCode2(error48) === "ENOENT") {
|
|
21040
|
-
throw
|
|
21218
|
+
throw createCliError6(
|
|
21041
21219
|
"CLI_OPENCLAW_MISSING_AGENT_CREDENTIALS",
|
|
21042
21220
|
"Local agent credentials are missing",
|
|
21043
21221
|
{ agentName, filePath }
|
|
@@ -21046,7 +21224,7 @@ async function ensureLocalAgentCredentials(homeDir, agentName) {
|
|
|
21046
21224
|
throw error48;
|
|
21047
21225
|
}
|
|
21048
21226
|
if (content.trim().length === 0) {
|
|
21049
|
-
throw
|
|
21227
|
+
throw createCliError6(
|
|
21050
21228
|
"CLI_OPENCLAW_EMPTY_AGENT_CREDENTIALS",
|
|
21051
21229
|
"Agent credential file is empty",
|
|
21052
21230
|
{ filePath }
|
|
@@ -21069,8 +21247,8 @@ async function loadPeersConfig(peersPath) {
|
|
|
21069
21247
|
}
|
|
21070
21248
|
throw error48;
|
|
21071
21249
|
}
|
|
21072
|
-
if (!
|
|
21073
|
-
throw
|
|
21250
|
+
if (!isRecord8(parsed)) {
|
|
21251
|
+
throw createCliError6(
|
|
21074
21252
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21075
21253
|
"Peer config root must be a JSON object",
|
|
21076
21254
|
{ peersPath }
|
|
@@ -21080,8 +21258,8 @@ async function loadPeersConfig(peersPath) {
|
|
|
21080
21258
|
if (peersValue === void 0) {
|
|
21081
21259
|
return { peers: {} };
|
|
21082
21260
|
}
|
|
21083
|
-
if (!
|
|
21084
|
-
throw
|
|
21261
|
+
if (!isRecord8(peersValue)) {
|
|
21262
|
+
throw createCliError6(
|
|
21085
21263
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21086
21264
|
"Peer config peers field must be an object",
|
|
21087
21265
|
{ peersPath }
|
|
@@ -21090,8 +21268,8 @@ async function loadPeersConfig(peersPath) {
|
|
|
21090
21268
|
const peers = {};
|
|
21091
21269
|
for (const [alias, value] of Object.entries(peersValue)) {
|
|
21092
21270
|
const normalizedAlias = parsePeerAlias(alias);
|
|
21093
|
-
if (!
|
|
21094
|
-
throw
|
|
21271
|
+
if (!isRecord8(value)) {
|
|
21272
|
+
throw createCliError6(
|
|
21095
21273
|
"CLI_OPENCLAW_INVALID_PEERS_CONFIG",
|
|
21096
21274
|
"Peer entry must be an object",
|
|
21097
21275
|
{ alias: normalizedAlias }
|
|
@@ -21120,21 +21298,21 @@ function parseConnectorBaseUrlForAssignment(value, label) {
|
|
|
21120
21298
|
});
|
|
21121
21299
|
}
|
|
21122
21300
|
function parseConnectorAssignments(value, connectorAssignmentsPath) {
|
|
21123
|
-
if (!
|
|
21124
|
-
throw
|
|
21301
|
+
if (!isRecord8(value)) {
|
|
21302
|
+
throw createCliError6(
|
|
21125
21303
|
"CLI_OPENCLAW_INVALID_CONNECTOR_ASSIGNMENTS",
|
|
21126
21304
|
"Connector assignments config must be an object",
|
|
21127
21305
|
{ connectorAssignmentsPath }
|
|
21128
21306
|
);
|
|
21129
21307
|
}
|
|
21130
21308
|
const agentsRaw = value.agents;
|
|
21131
|
-
if (!
|
|
21309
|
+
if (!isRecord8(agentsRaw)) {
|
|
21132
21310
|
return { agents: {} };
|
|
21133
21311
|
}
|
|
21134
21312
|
const agents = {};
|
|
21135
21313
|
for (const [agentName, entryValue] of Object.entries(agentsRaw)) {
|
|
21136
|
-
if (!
|
|
21137
|
-
throw
|
|
21314
|
+
if (!isRecord8(entryValue)) {
|
|
21315
|
+
throw createCliError6(
|
|
21138
21316
|
"CLI_OPENCLAW_INVALID_CONNECTOR_ASSIGNMENTS",
|
|
21139
21317
|
"Connector assignment entry must be an object",
|
|
21140
21318
|
{ connectorAssignmentsPath, agentName }
|
|
@@ -21205,8 +21383,8 @@ function buildRelayConnectorBaseUrls(port) {
|
|
|
21205
21383
|
];
|
|
21206
21384
|
}
|
|
21207
21385
|
function parseRelayRuntimeConfig(value, relayRuntimeConfigPath) {
|
|
21208
|
-
if (!
|
|
21209
|
-
throw
|
|
21386
|
+
if (!isRecord8(value)) {
|
|
21387
|
+
throw createCliError6(
|
|
21210
21388
|
"CLI_OPENCLAW_INVALID_RELAY_RUNTIME_CONFIG",
|
|
21211
21389
|
"Relay runtime config must be an object",
|
|
21212
21390
|
{ relayRuntimeConfigPath }
|
|
@@ -21260,7 +21438,7 @@ async function resolveOpenclawBaseUrl2(input) {
|
|
|
21260
21438
|
}
|
|
21261
21439
|
return DEFAULT_OPENCLAW_BASE_URL2;
|
|
21262
21440
|
}
|
|
21263
|
-
function
|
|
21441
|
+
function normalizeStringArrayWithValues(value, requiredValues) {
|
|
21264
21442
|
const normalized = /* @__PURE__ */ new Set();
|
|
21265
21443
|
if (Array.isArray(value)) {
|
|
21266
21444
|
for (const item of value) {
|
|
@@ -21273,27 +21451,61 @@ function normalizeStringArrayWithValue(value, requiredValue) {
|
|
|
21273
21451
|
}
|
|
21274
21452
|
}
|
|
21275
21453
|
}
|
|
21276
|
-
|
|
21454
|
+
for (const requiredValue of requiredValues) {
|
|
21455
|
+
const trimmed = requiredValue.trim();
|
|
21456
|
+
if (trimmed.length > 0) {
|
|
21457
|
+
normalized.add(trimmed);
|
|
21458
|
+
}
|
|
21459
|
+
}
|
|
21277
21460
|
return Array.from(normalized);
|
|
21278
21461
|
}
|
|
21462
|
+
function resolveHookDefaultSessionKey(config2, hooks) {
|
|
21463
|
+
if (typeof hooks.defaultSessionKey === "string" && hooks.defaultSessionKey.trim().length > 0) {
|
|
21464
|
+
return hooks.defaultSessionKey.trim();
|
|
21465
|
+
}
|
|
21466
|
+
const session = isRecord8(config2.session) ? config2.session : {};
|
|
21467
|
+
const scope = typeof session.scope === "string" ? session.scope.trim().toLowerCase() : "";
|
|
21468
|
+
if (scope === "global") {
|
|
21469
|
+
return "global";
|
|
21470
|
+
}
|
|
21471
|
+
const agents = isRecord8(config2.agents) ? config2.agents : {};
|
|
21472
|
+
const agentList = Array.isArray(agents.list) ? agents.list : [];
|
|
21473
|
+
const defaultAgentId = resolveDefaultOpenclawAgentId(agentList);
|
|
21474
|
+
return `agent:${defaultAgentId}:${DEFAULT_OPENCLAW_MAIN_SESSION_KEY}`;
|
|
21475
|
+
}
|
|
21476
|
+
function resolveDefaultOpenclawAgentId(agentList) {
|
|
21477
|
+
const preferred = agentList.find(
|
|
21478
|
+
(agent) => isRecord8(agent) && agent.default === true && typeof agent.id === "string" && agent.id.trim().length > 0
|
|
21479
|
+
) ?? agentList.find(
|
|
21480
|
+
(agent) => isRecord8(agent) && typeof agent.id === "string" && agent.id.trim().length > 0
|
|
21481
|
+
);
|
|
21482
|
+
if (isRecord8(preferred) && typeof preferred.id === "string" && preferred.id.trim().length > 0) {
|
|
21483
|
+
return normalizeOpenclawIdToken(preferred.id, DEFAULT_OPENCLAW_AGENT_ID);
|
|
21484
|
+
}
|
|
21485
|
+
return DEFAULT_OPENCLAW_AGENT_ID;
|
|
21486
|
+
}
|
|
21487
|
+
function normalizeOpenclawIdToken(value, fallback) {
|
|
21488
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+/g, "").replace(/-+$/g, "").slice(0, 64);
|
|
21489
|
+
return normalized.length > 0 ? normalized : fallback;
|
|
21490
|
+
}
|
|
21279
21491
|
function generateOpenclawHookToken() {
|
|
21280
21492
|
return randomBytes3(OPENCLAW_HOOK_TOKEN_BYTES).toString("hex");
|
|
21281
21493
|
}
|
|
21282
21494
|
function upsertRelayHookMapping(mappingsValue) {
|
|
21283
|
-
const mappings = Array.isArray(mappingsValue) ? mappingsValue.filter(
|
|
21495
|
+
const mappings = Array.isArray(mappingsValue) ? mappingsValue.filter(isRecord8).map((mapping) => ({ ...mapping })) : [];
|
|
21284
21496
|
const existingIndex = mappings.findIndex((mapping) => {
|
|
21285
21497
|
if (mapping.id === HOOK_MAPPING_ID) {
|
|
21286
21498
|
return true;
|
|
21287
21499
|
}
|
|
21288
|
-
if (!
|
|
21500
|
+
if (!isRecord8(mapping.match)) {
|
|
21289
21501
|
return false;
|
|
21290
21502
|
}
|
|
21291
21503
|
return mapping.match.path === HOOK_PATH_SEND_TO_PEER;
|
|
21292
21504
|
});
|
|
21293
|
-
const baseMapping = existingIndex >= 0 &&
|
|
21294
|
-
const nextMatch =
|
|
21505
|
+
const baseMapping = existingIndex >= 0 && isRecord8(mappings[existingIndex]) ? mappings[existingIndex] : {};
|
|
21506
|
+
const nextMatch = isRecord8(baseMapping.match) ? { ...baseMapping.match } : {};
|
|
21295
21507
|
nextMatch.path = HOOK_PATH_SEND_TO_PEER;
|
|
21296
|
-
const nextTransform =
|
|
21508
|
+
const nextTransform = isRecord8(baseMapping.transform) ? { ...baseMapping.transform } : {};
|
|
21297
21509
|
nextTransform.module = RELAY_MODULE_FILE_NAME;
|
|
21298
21510
|
const relayMapping = {
|
|
21299
21511
|
...baseMapping,
|
|
@@ -21316,7 +21528,7 @@ async function patchOpenclawConfig(openclawConfigPath, hookToken) {
|
|
|
21316
21528
|
config2 = await readJsonFile(openclawConfigPath);
|
|
21317
21529
|
} catch (error48) {
|
|
21318
21530
|
if (getErrorCode2(error48) === "ENOENT") {
|
|
21319
|
-
throw
|
|
21531
|
+
throw createCliError6(
|
|
21320
21532
|
"CLI_OPENCLAW_CONFIG_NOT_FOUND",
|
|
21321
21533
|
"OpenClaw config file was not found",
|
|
21322
21534
|
{ openclawConfigPath }
|
|
@@ -21324,23 +21536,25 @@ async function patchOpenclawConfig(openclawConfigPath, hookToken) {
|
|
|
21324
21536
|
}
|
|
21325
21537
|
throw error48;
|
|
21326
21538
|
}
|
|
21327
|
-
if (!
|
|
21328
|
-
throw
|
|
21539
|
+
if (!isRecord8(config2)) {
|
|
21540
|
+
throw createCliError6(
|
|
21329
21541
|
"CLI_OPENCLAW_INVALID_CONFIG",
|
|
21330
21542
|
"OpenClaw config root must be an object",
|
|
21331
21543
|
{ openclawConfigPath }
|
|
21332
21544
|
);
|
|
21333
21545
|
}
|
|
21334
|
-
const hooks =
|
|
21546
|
+
const hooks = isRecord8(config2.hooks) ? { ...config2.hooks } : {};
|
|
21335
21547
|
const existingHookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
21336
21548
|
const preferredHookToken = typeof hookToken === "string" && hookToken.trim().length > 0 ? hookToken.trim() : void 0;
|
|
21337
21549
|
const resolvedHookToken = existingHookToken ?? preferredHookToken ?? generateOpenclawHookToken();
|
|
21550
|
+
const defaultSessionKey = resolveHookDefaultSessionKey(config2, hooks);
|
|
21338
21551
|
hooks.enabled = true;
|
|
21339
21552
|
hooks.token = resolvedHookToken;
|
|
21553
|
+
hooks.defaultSessionKey = defaultSessionKey;
|
|
21340
21554
|
hooks.allowRequestSessionKey = false;
|
|
21341
|
-
hooks.allowedSessionKeyPrefixes =
|
|
21555
|
+
hooks.allowedSessionKeyPrefixes = normalizeStringArrayWithValues(
|
|
21342
21556
|
hooks.allowedSessionKeyPrefixes,
|
|
21343
|
-
"hook:"
|
|
21557
|
+
["hook:", defaultSessionKey]
|
|
21344
21558
|
);
|
|
21345
21559
|
hooks.mappings = upsertRelayHookMapping(hooks.mappings);
|
|
21346
21560
|
const nextConfig = {
|
|
@@ -21368,10 +21582,10 @@ function toDoctorResult(checks) {
|
|
|
21368
21582
|
};
|
|
21369
21583
|
}
|
|
21370
21584
|
function isRelayHookMapping(value) {
|
|
21371
|
-
if (!
|
|
21585
|
+
if (!isRecord8(value)) {
|
|
21372
21586
|
return false;
|
|
21373
21587
|
}
|
|
21374
|
-
if (!
|
|
21588
|
+
if (!isRecord8(value.match) || value.match.path !== HOOK_PATH_SEND_TO_PEER) {
|
|
21375
21589
|
return false;
|
|
21376
21590
|
}
|
|
21377
21591
|
if (typeof value.id === "string" && value.id !== HOOK_MAPPING_ID) {
|
|
@@ -21380,7 +21594,7 @@ function isRelayHookMapping(value) {
|
|
|
21380
21594
|
return true;
|
|
21381
21595
|
}
|
|
21382
21596
|
function hasRelayTransformModule(value) {
|
|
21383
|
-
if (!
|
|
21597
|
+
if (!isRecord8(value) || !isRecord8(value.transform)) {
|
|
21384
21598
|
return false;
|
|
21385
21599
|
}
|
|
21386
21600
|
return value.transform.module === RELAY_MODULE_FILE_NAME;
|
|
@@ -21459,6 +21673,7 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21459
21673
|
const resolveConfigImpl = options.resolveConfigImpl ?? resolveConfig;
|
|
21460
21674
|
try {
|
|
21461
21675
|
const resolvedConfig = await resolveConfigImpl();
|
|
21676
|
+
const envProxyUrl = typeof process.env.CLAWDENTITY_PROXY_URL === "string" ? process.env.CLAWDENTITY_PROXY_URL.trim() : "";
|
|
21462
21677
|
if (typeof resolvedConfig.registryUrl !== "string" || resolvedConfig.registryUrl.trim().length === 0) {
|
|
21463
21678
|
checks.push(
|
|
21464
21679
|
toDoctorCheck({
|
|
@@ -21479,15 +21694,68 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21479
21694
|
remediationHint: "Run: clawdentity config set apiKey <API_KEY>"
|
|
21480
21695
|
})
|
|
21481
21696
|
);
|
|
21482
|
-
} else {
|
|
21697
|
+
} else if (envProxyUrl.length > 0) {
|
|
21698
|
+
let hasValidEnvProxyUrl = true;
|
|
21699
|
+
try {
|
|
21700
|
+
parseProxyUrl(envProxyUrl);
|
|
21701
|
+
} catch {
|
|
21702
|
+
hasValidEnvProxyUrl = false;
|
|
21703
|
+
checks.push(
|
|
21704
|
+
toDoctorCheck({
|
|
21705
|
+
id: "config.registry",
|
|
21706
|
+
label: "CLI config",
|
|
21707
|
+
status: "fail",
|
|
21708
|
+
message: "CLAWDENTITY_PROXY_URL is invalid",
|
|
21709
|
+
remediationHint: "Set CLAWDENTITY_PROXY_URL to a valid http(s) URL or unset it"
|
|
21710
|
+
})
|
|
21711
|
+
);
|
|
21712
|
+
}
|
|
21713
|
+
if (hasValidEnvProxyUrl) {
|
|
21714
|
+
checks.push(
|
|
21715
|
+
toDoctorCheck({
|
|
21716
|
+
id: "config.registry",
|
|
21717
|
+
label: "CLI config",
|
|
21718
|
+
status: "pass",
|
|
21719
|
+
message: "registryUrl and apiKey are configured (proxy URL override is active via CLAWDENTITY_PROXY_URL)"
|
|
21720
|
+
})
|
|
21721
|
+
);
|
|
21722
|
+
}
|
|
21723
|
+
} else if (typeof resolvedConfig.proxyUrl !== "string" || resolvedConfig.proxyUrl.trim().length === 0) {
|
|
21483
21724
|
checks.push(
|
|
21484
21725
|
toDoctorCheck({
|
|
21485
21726
|
id: "config.registry",
|
|
21486
21727
|
label: "CLI config",
|
|
21487
|
-
status: "
|
|
21488
|
-
message: "
|
|
21728
|
+
status: "fail",
|
|
21729
|
+
message: "proxyUrl is missing",
|
|
21730
|
+
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
21489
21731
|
})
|
|
21490
21732
|
);
|
|
21733
|
+
} else {
|
|
21734
|
+
let hasValidConfigProxyUrl = true;
|
|
21735
|
+
try {
|
|
21736
|
+
parseProxyUrl(resolvedConfig.proxyUrl);
|
|
21737
|
+
} catch {
|
|
21738
|
+
hasValidConfigProxyUrl = false;
|
|
21739
|
+
checks.push(
|
|
21740
|
+
toDoctorCheck({
|
|
21741
|
+
id: "config.registry",
|
|
21742
|
+
label: "CLI config",
|
|
21743
|
+
status: "fail",
|
|
21744
|
+
message: "proxyUrl is invalid",
|
|
21745
|
+
remediationHint: "Run: clawdentity invite redeem <clw_inv_...> or clawdentity config init"
|
|
21746
|
+
})
|
|
21747
|
+
);
|
|
21748
|
+
}
|
|
21749
|
+
if (hasValidConfigProxyUrl) {
|
|
21750
|
+
checks.push(
|
|
21751
|
+
toDoctorCheck({
|
|
21752
|
+
id: "config.registry",
|
|
21753
|
+
label: "CLI config",
|
|
21754
|
+
status: "pass",
|
|
21755
|
+
message: "registryUrl, apiKey, and proxyUrl are configured"
|
|
21756
|
+
})
|
|
21757
|
+
);
|
|
21758
|
+
}
|
|
21491
21759
|
}
|
|
21492
21760
|
} catch {
|
|
21493
21761
|
checks.push(
|
|
@@ -21681,13 +21949,13 @@ async function runOpenclawDoctor(options = {}) {
|
|
|
21681
21949
|
const openclawConfigPath = resolveOpenclawConfigPath(openclawDir, homeDir);
|
|
21682
21950
|
try {
|
|
21683
21951
|
const openclawConfig = await readJsonFile(openclawConfigPath);
|
|
21684
|
-
if (!
|
|
21952
|
+
if (!isRecord8(openclawConfig)) {
|
|
21685
21953
|
throw new Error("root");
|
|
21686
21954
|
}
|
|
21687
|
-
const hooks =
|
|
21955
|
+
const hooks = isRecord8(openclawConfig.hooks) ? openclawConfig.hooks : {};
|
|
21688
21956
|
const hooksEnabled = hooks.enabled === true;
|
|
21689
21957
|
const hookToken = typeof hooks.token === "string" && hooks.token.trim().length > 0 ? hooks.token.trim() : void 0;
|
|
21690
|
-
const mappings = Array.isArray(hooks.mappings) ? hooks.mappings.filter(
|
|
21958
|
+
const mappings = Array.isArray(hooks.mappings) ? hooks.mappings.filter(isRecord8) : [];
|
|
21691
21959
|
const relayMapping = mappings.find(
|
|
21692
21960
|
(mapping) => isRelayHookMapping(mapping)
|
|
21693
21961
|
);
|
|
@@ -21835,13 +22103,13 @@ async function resolveRelayProbePeerAlias(input) {
|
|
|
21835
22103
|
return peerAliases[0];
|
|
21836
22104
|
}
|
|
21837
22105
|
if (peerAliases.length === 0) {
|
|
21838
|
-
throw
|
|
22106
|
+
throw createCliError6(
|
|
21839
22107
|
"CLI_OPENCLAW_RELAY_TEST_PEER_REQUIRED",
|
|
21840
22108
|
"No paired peer is configured yet. Complete QR pairing first.",
|
|
21841
22109
|
{ peersPath }
|
|
21842
22110
|
);
|
|
21843
22111
|
}
|
|
21844
|
-
throw
|
|
22112
|
+
throw createCliError6(
|
|
21845
22113
|
"CLI_OPENCLAW_RELAY_TEST_PEER_REQUIRED",
|
|
21846
22114
|
"Multiple peers are configured. Pass --peer <alias> to choose one.",
|
|
21847
22115
|
{ peersPath, peerAliases }
|
|
@@ -21998,7 +22266,7 @@ async function setupOpenclawRelay(agentName, options) {
|
|
|
21998
22266
|
await copyFile(transformSource, transformTargetPath);
|
|
21999
22267
|
} catch (error48) {
|
|
22000
22268
|
if (getErrorCode2(error48) === "ENOENT") {
|
|
22001
|
-
throw
|
|
22269
|
+
throw createCliError6(
|
|
22002
22270
|
"CLI_OPENCLAW_TRANSFORM_NOT_FOUND",
|
|
22003
22271
|
"Relay transform source file was not found",
|
|
22004
22272
|
{ transformSource }
|
|
@@ -22216,26 +22484,26 @@ var PAIRING_QR_MAX_AGE_SECONDS = 900;
|
|
|
22216
22484
|
var PAIRING_QR_FILENAME_PATTERN = /-pair-(\d+)\.png$/;
|
|
22217
22485
|
var FILE_MODE4 = 384;
|
|
22218
22486
|
var PEER_ALIAS_PATTERN2 = /^[a-zA-Z0-9._-]+$/;
|
|
22219
|
-
var
|
|
22487
|
+
var isRecord9 = (value) => {
|
|
22220
22488
|
return typeof value === "object" && value !== null;
|
|
22221
22489
|
};
|
|
22222
|
-
function
|
|
22490
|
+
function createCliError7(code, message2) {
|
|
22223
22491
|
return new AppError({
|
|
22224
22492
|
code,
|
|
22225
22493
|
message: message2,
|
|
22226
22494
|
status: 400
|
|
22227
22495
|
});
|
|
22228
22496
|
}
|
|
22229
|
-
function
|
|
22497
|
+
function parseNonEmptyString9(value) {
|
|
22230
22498
|
if (typeof value !== "string") {
|
|
22231
22499
|
return "";
|
|
22232
22500
|
}
|
|
22233
22501
|
return value.trim();
|
|
22234
22502
|
}
|
|
22235
22503
|
function parsePairingTicket(value) {
|
|
22236
|
-
const ticket =
|
|
22504
|
+
const ticket = parseNonEmptyString9(value);
|
|
22237
22505
|
if (!ticket.startsWith(PAIRING_TICKET_PREFIX)) {
|
|
22238
|
-
throw
|
|
22506
|
+
throw createCliError7(
|
|
22239
22507
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22240
22508
|
"Pairing ticket is invalid"
|
|
22241
22509
|
);
|
|
@@ -22245,7 +22513,7 @@ function parsePairingTicket(value) {
|
|
|
22245
22513
|
function parsePairingTicketIssuerOrigin(ticket) {
|
|
22246
22514
|
const encodedPayload = ticket.slice(PAIRING_TICKET_PREFIX.length);
|
|
22247
22515
|
if (encodedPayload.length === 0) {
|
|
22248
|
-
throw
|
|
22516
|
+
throw createCliError7(
|
|
22249
22517
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22250
22518
|
"Pairing ticket is invalid"
|
|
22251
22519
|
);
|
|
@@ -22254,7 +22522,7 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22254
22522
|
try {
|
|
22255
22523
|
payloadRaw = new TextDecoder().decode(decodeBase64url(encodedPayload));
|
|
22256
22524
|
} catch {
|
|
22257
|
-
throw
|
|
22525
|
+
throw createCliError7(
|
|
22258
22526
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22259
22527
|
"Pairing ticket is invalid"
|
|
22260
22528
|
);
|
|
@@ -22263,13 +22531,13 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22263
22531
|
try {
|
|
22264
22532
|
payload = JSON.parse(payloadRaw);
|
|
22265
22533
|
} catch {
|
|
22266
|
-
throw
|
|
22534
|
+
throw createCliError7(
|
|
22267
22535
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22268
22536
|
"Pairing ticket is invalid"
|
|
22269
22537
|
);
|
|
22270
22538
|
}
|
|
22271
|
-
if (!
|
|
22272
|
-
throw
|
|
22539
|
+
if (!isRecord9(payload) || typeof payload.iss !== "string") {
|
|
22540
|
+
throw createCliError7(
|
|
22273
22541
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22274
22542
|
"Pairing ticket is invalid"
|
|
22275
22543
|
);
|
|
@@ -22278,13 +22546,13 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22278
22546
|
try {
|
|
22279
22547
|
issuerUrl = new URL(payload.iss);
|
|
22280
22548
|
} catch {
|
|
22281
|
-
throw
|
|
22549
|
+
throw createCliError7(
|
|
22282
22550
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22283
22551
|
"Pairing ticket is invalid"
|
|
22284
22552
|
);
|
|
22285
22553
|
}
|
|
22286
22554
|
if (issuerUrl.protocol !== "https:" && issuerUrl.protocol !== "http:") {
|
|
22287
|
-
throw
|
|
22555
|
+
throw createCliError7(
|
|
22288
22556
|
"CLI_PAIR_CONFIRM_TICKET_INVALID",
|
|
22289
22557
|
"Pairing ticket is invalid"
|
|
22290
22558
|
);
|
|
@@ -22293,13 +22561,13 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22293
22561
|
}
|
|
22294
22562
|
function parsePeerAlias2(value) {
|
|
22295
22563
|
if (value.length === 0 || value.length > 128) {
|
|
22296
|
-
throw
|
|
22564
|
+
throw createCliError7(
|
|
22297
22565
|
"CLI_PAIR_PEER_ALIAS_INVALID",
|
|
22298
22566
|
"Generated peer alias is invalid"
|
|
22299
22567
|
);
|
|
22300
22568
|
}
|
|
22301
22569
|
if (!PEER_ALIAS_PATTERN2.test(value)) {
|
|
22302
|
-
throw
|
|
22570
|
+
throw createCliError7(
|
|
22303
22571
|
"CLI_PAIR_PEER_ALIAS_INVALID",
|
|
22304
22572
|
"Generated peer alias is invalid"
|
|
22305
22573
|
);
|
|
@@ -22336,16 +22604,16 @@ function resolvePeersConfigPath(getConfigDirImpl) {
|
|
|
22336
22604
|
return join7(getConfigDirImpl(), PEERS_FILE_NAME2);
|
|
22337
22605
|
}
|
|
22338
22606
|
function parsePeerEntry(value) {
|
|
22339
|
-
if (!
|
|
22340
|
-
throw
|
|
22607
|
+
if (!isRecord9(value)) {
|
|
22608
|
+
throw createCliError7(
|
|
22341
22609
|
"CLI_PAIR_PEERS_CONFIG_INVALID",
|
|
22342
22610
|
"Peer entry must be an object"
|
|
22343
22611
|
);
|
|
22344
22612
|
}
|
|
22345
|
-
const did =
|
|
22346
|
-
const proxyUrl =
|
|
22613
|
+
const did = parseNonEmptyString9(value.did);
|
|
22614
|
+
const proxyUrl = parseNonEmptyString9(value.proxyUrl);
|
|
22347
22615
|
if (did.length === 0 || proxyUrl.length === 0) {
|
|
22348
|
-
throw
|
|
22616
|
+
throw createCliError7(
|
|
22349
22617
|
"CLI_PAIR_PEERS_CONFIG_INVALID",
|
|
22350
22618
|
"Peer entry is invalid"
|
|
22351
22619
|
);
|
|
@@ -22371,13 +22639,13 @@ async function loadPeersConfig2(input) {
|
|
|
22371
22639
|
try {
|
|
22372
22640
|
parsed = JSON.parse(raw);
|
|
22373
22641
|
} catch {
|
|
22374
|
-
throw
|
|
22642
|
+
throw createCliError7(
|
|
22375
22643
|
"CLI_PAIR_PEERS_CONFIG_INVALID",
|
|
22376
22644
|
"Peer config is not valid JSON"
|
|
22377
22645
|
);
|
|
22378
22646
|
}
|
|
22379
|
-
if (!
|
|
22380
|
-
throw
|
|
22647
|
+
if (!isRecord9(parsed)) {
|
|
22648
|
+
throw createCliError7(
|
|
22381
22649
|
"CLI_PAIR_PEERS_CONFIG_INVALID",
|
|
22382
22650
|
"Peer config must be a JSON object"
|
|
22383
22651
|
);
|
|
@@ -22385,8 +22653,8 @@ async function loadPeersConfig2(input) {
|
|
|
22385
22653
|
if (parsed.peers === void 0) {
|
|
22386
22654
|
return { peers: {} };
|
|
22387
22655
|
}
|
|
22388
|
-
if (!
|
|
22389
|
-
throw
|
|
22656
|
+
if (!isRecord9(parsed.peers)) {
|
|
22657
|
+
throw createCliError7(
|
|
22390
22658
|
"CLI_PAIR_PEERS_CONFIG_INVALID",
|
|
22391
22659
|
"Peer config peers field must be an object"
|
|
22392
22660
|
);
|
|
@@ -22409,13 +22677,13 @@ async function savePeersConfig2(input) {
|
|
|
22409
22677
|
await input.chmodImpl(peersPath, FILE_MODE4);
|
|
22410
22678
|
}
|
|
22411
22679
|
function parseTtlSeconds(value) {
|
|
22412
|
-
const raw =
|
|
22680
|
+
const raw = parseNonEmptyString9(value);
|
|
22413
22681
|
if (raw.length === 0) {
|
|
22414
22682
|
return void 0;
|
|
22415
22683
|
}
|
|
22416
22684
|
const parsed = Number.parseInt(raw, 10);
|
|
22417
22685
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
22418
|
-
throw
|
|
22686
|
+
throw createCliError7(
|
|
22419
22687
|
"CLI_PAIR_START_INVALID_TTL",
|
|
22420
22688
|
"ttlSeconds must be a positive integer"
|
|
22421
22689
|
);
|
|
@@ -22430,36 +22698,31 @@ function parseProxyUrl2(candidate) {
|
|
|
22430
22698
|
}
|
|
22431
22699
|
return parsed.toString();
|
|
22432
22700
|
} catch {
|
|
22433
|
-
throw
|
|
22701
|
+
throw createCliError7("CLI_PAIR_INVALID_PROXY_URL", "Proxy URL is invalid");
|
|
22434
22702
|
}
|
|
22435
22703
|
}
|
|
22436
|
-
function
|
|
22437
|
-
const
|
|
22438
|
-
if (explicit.length > 0) {
|
|
22439
|
-
return [parseProxyUrl2(explicit)];
|
|
22440
|
-
}
|
|
22441
|
-
const fromEnv = parseNonEmptyString8(process.env.CLAWDENTITY_PROXY_URL);
|
|
22704
|
+
async function resolveProxyUrl(input) {
|
|
22705
|
+
const fromEnv = parseNonEmptyString9(process.env.CLAWDENTITY_PROXY_URL);
|
|
22442
22706
|
if (fromEnv.length > 0) {
|
|
22443
|
-
return
|
|
22707
|
+
return parseProxyUrl2(fromEnv);
|
|
22444
22708
|
}
|
|
22445
|
-
const
|
|
22446
|
-
|
|
22447
|
-
|
|
22709
|
+
const metadata = await fetchRegistryMetadata(input.config.registryUrl, {
|
|
22710
|
+
fetchImpl: input.fetchImpl
|
|
22711
|
+
});
|
|
22712
|
+
const metadataProxyUrl = parseProxyUrl2(metadata.proxyUrl);
|
|
22713
|
+
const configuredProxyUrl = parseNonEmptyString9(input.config.proxyUrl);
|
|
22714
|
+
if (configuredProxyUrl.length === 0) {
|
|
22715
|
+
return metadataProxyUrl;
|
|
22448
22716
|
}
|
|
22449
|
-
const
|
|
22450
|
-
|
|
22451
|
-
|
|
22452
|
-
if (typeof derivedFromRegistry === "string" && derivedFromRegistry.length > 0) {
|
|
22453
|
-
return [parseProxyUrl2(derivedFromRegistry)];
|
|
22717
|
+
const normalizedConfiguredProxyUrl = parseProxyUrl2(configuredProxyUrl);
|
|
22718
|
+
if (normalizedConfiguredProxyUrl === metadataProxyUrl) {
|
|
22719
|
+
return metadataProxyUrl;
|
|
22454
22720
|
}
|
|
22455
|
-
throw
|
|
22456
|
-
"
|
|
22457
|
-
|
|
22721
|
+
throw createCliError7(
|
|
22722
|
+
"CLI_PAIR_PROXY_URL_MISMATCH",
|
|
22723
|
+
`Configured proxy URL does not match registry metadata. config=${normalizedConfiguredProxyUrl} metadata=${metadataProxyUrl}. Rerun onboarding invite redeem to refresh config.`
|
|
22458
22724
|
);
|
|
22459
22725
|
}
|
|
22460
|
-
function resolveProxyUrl(input) {
|
|
22461
|
-
return resolveProxyUrlCandidates(input)[0];
|
|
22462
|
-
}
|
|
22463
22726
|
function toProxyRequestUrl(proxyUrl, path) {
|
|
22464
22727
|
const normalizedBase = proxyUrl.endsWith("/") ? proxyUrl : `${proxyUrl}/`;
|
|
22465
22728
|
return new URL(path.slice(1), normalizedBase).toString();
|
|
@@ -22469,7 +22732,7 @@ function toPathWithQuery3(url2) {
|
|
|
22469
22732
|
return `${parsed.pathname}${parsed.search}`;
|
|
22470
22733
|
}
|
|
22471
22734
|
function extractErrorCode(payload) {
|
|
22472
|
-
if (!
|
|
22735
|
+
if (!isRecord9(payload)) {
|
|
22473
22736
|
return void 0;
|
|
22474
22737
|
}
|
|
22475
22738
|
const envelope = payload;
|
|
@@ -22480,7 +22743,7 @@ function extractErrorCode(payload) {
|
|
|
22480
22743
|
return code.length > 0 ? code : void 0;
|
|
22481
22744
|
}
|
|
22482
22745
|
function extractErrorMessage(payload) {
|
|
22483
|
-
if (!
|
|
22746
|
+
if (!isRecord9(payload)) {
|
|
22484
22747
|
return void 0;
|
|
22485
22748
|
}
|
|
22486
22749
|
const envelope = payload;
|
|
@@ -22490,7 +22753,7 @@ function extractErrorMessage(payload) {
|
|
|
22490
22753
|
const message2 = envelope.error.message.trim();
|
|
22491
22754
|
return message2.length > 0 ? message2 : void 0;
|
|
22492
22755
|
}
|
|
22493
|
-
async function
|
|
22756
|
+
async function parseJsonResponse6(response) {
|
|
22494
22757
|
try {
|
|
22495
22758
|
return await response.json();
|
|
22496
22759
|
} catch {
|
|
@@ -22501,7 +22764,7 @@ async function executePairRequest(input) {
|
|
|
22501
22764
|
try {
|
|
22502
22765
|
return await input.fetchImpl(input.url, input.init);
|
|
22503
22766
|
} catch {
|
|
22504
|
-
throw
|
|
22767
|
+
throw createCliError7(
|
|
22505
22768
|
"CLI_PAIR_REQUEST_FAILED",
|
|
22506
22769
|
"Unable to connect to proxy URL. Check network access and proxyUrl."
|
|
22507
22770
|
);
|
|
@@ -22548,17 +22811,17 @@ function mapConfirmPairError(status, payload) {
|
|
|
22548
22811
|
return `Pair confirm failed (${status})`;
|
|
22549
22812
|
}
|
|
22550
22813
|
function parsePairStartResponse(payload) {
|
|
22551
|
-
if (!
|
|
22552
|
-
throw
|
|
22814
|
+
if (!isRecord9(payload)) {
|
|
22815
|
+
throw createCliError7(
|
|
22553
22816
|
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
22554
22817
|
"Pair start response is invalid"
|
|
22555
22818
|
);
|
|
22556
22819
|
}
|
|
22557
22820
|
const ticket = parsePairingTicket(payload.ticket);
|
|
22558
|
-
const initiatorAgentDid =
|
|
22559
|
-
const expiresAt =
|
|
22821
|
+
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
22822
|
+
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
22560
22823
|
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
22561
|
-
throw
|
|
22824
|
+
throw createCliError7(
|
|
22562
22825
|
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
22563
22826
|
"Pair start response is invalid"
|
|
22564
22827
|
);
|
|
@@ -22570,17 +22833,17 @@ function parsePairStartResponse(payload) {
|
|
|
22570
22833
|
};
|
|
22571
22834
|
}
|
|
22572
22835
|
function parsePairConfirmResponse(payload) {
|
|
22573
|
-
if (!
|
|
22574
|
-
throw
|
|
22836
|
+
if (!isRecord9(payload)) {
|
|
22837
|
+
throw createCliError7(
|
|
22575
22838
|
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
22576
22839
|
"Pair confirm response is invalid"
|
|
22577
22840
|
);
|
|
22578
22841
|
}
|
|
22579
22842
|
const paired = payload.paired === true;
|
|
22580
|
-
const initiatorAgentDid =
|
|
22581
|
-
const responderAgentDid =
|
|
22843
|
+
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
22844
|
+
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
22582
22845
|
if (!paired || initiatorAgentDid.length === 0 || responderAgentDid.length === 0) {
|
|
22583
|
-
throw
|
|
22846
|
+
throw createCliError7(
|
|
22584
22847
|
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
22585
22848
|
"Pair confirm response is invalid"
|
|
22586
22849
|
);
|
|
@@ -22608,7 +22871,7 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22608
22871
|
} catch (error48) {
|
|
22609
22872
|
const nodeError = error48;
|
|
22610
22873
|
if (nodeError.code === "ENOENT") {
|
|
22611
|
-
throw
|
|
22874
|
+
throw createCliError7(
|
|
22612
22875
|
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22613
22876
|
`Agent "${normalizedAgentName}" is missing ${AIT_FILE_NAME4}. Run agent create first.`
|
|
22614
22877
|
);
|
|
@@ -22616,7 +22879,7 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22616
22879
|
throw error48;
|
|
22617
22880
|
}
|
|
22618
22881
|
if (ait.length === 0) {
|
|
22619
|
-
throw
|
|
22882
|
+
throw createCliError7(
|
|
22620
22883
|
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22621
22884
|
`Agent "${normalizedAgentName}" has an empty ${AIT_FILE_NAME4}`
|
|
22622
22885
|
);
|
|
@@ -22627,7 +22890,7 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22627
22890
|
} catch (error48) {
|
|
22628
22891
|
const nodeError = error48;
|
|
22629
22892
|
if (nodeError.code === "ENOENT") {
|
|
22630
|
-
throw
|
|
22893
|
+
throw createCliError7(
|
|
22631
22894
|
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22632
22895
|
`Agent "${normalizedAgentName}" is missing ${SECRET_KEY_FILE_NAME3}. Run agent create first.`
|
|
22633
22896
|
);
|
|
@@ -22635,7 +22898,7 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22635
22898
|
throw error48;
|
|
22636
22899
|
}
|
|
22637
22900
|
if (encodedSecretKey.length === 0) {
|
|
22638
|
-
throw
|
|
22901
|
+
throw createCliError7(
|
|
22639
22902
|
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22640
22903
|
`Agent "${normalizedAgentName}" has an empty ${SECRET_KEY_FILE_NAME3}`
|
|
22641
22904
|
);
|
|
@@ -22644,7 +22907,7 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22644
22907
|
try {
|
|
22645
22908
|
secretKey = decodeBase64url(encodedSecretKey);
|
|
22646
22909
|
} catch {
|
|
22647
|
-
throw
|
|
22910
|
+
throw createCliError7(
|
|
22648
22911
|
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22649
22912
|
`Agent "${normalizedAgentName}" has invalid ${SECRET_KEY_FILE_NAME3}`
|
|
22650
22913
|
);
|
|
@@ -22655,11 +22918,11 @@ async function readAgentProofMaterial(agentName, dependencies) {
|
|
|
22655
22918
|
};
|
|
22656
22919
|
}
|
|
22657
22920
|
function resolveOwnerPat(options) {
|
|
22658
|
-
const ownerPat =
|
|
22921
|
+
const ownerPat = parseNonEmptyString9(options.explicitOwnerPat) || parseNonEmptyString9(options.config.apiKey);
|
|
22659
22922
|
if (ownerPat.length > 0) {
|
|
22660
22923
|
return ownerPat;
|
|
22661
22924
|
}
|
|
22662
|
-
throw
|
|
22925
|
+
throw createCliError7(
|
|
22663
22926
|
"CLI_PAIR_START_OWNER_PAT_REQUIRED",
|
|
22664
22927
|
"Owner PAT is required. Pass --owner-pat <token> or configure API key with `clawdentity invite redeem` / `clawdentity config set apiKey <token>`."
|
|
22665
22928
|
);
|
|
@@ -22689,7 +22952,7 @@ function decodeTicketFromPng(imageBytes) {
|
|
|
22689
22952
|
try {
|
|
22690
22953
|
decodedPng = PNG.sync.read(Buffer.from(imageBytes));
|
|
22691
22954
|
} catch {
|
|
22692
|
-
throw
|
|
22955
|
+
throw createCliError7(
|
|
22693
22956
|
"CLI_PAIR_CONFIRM_QR_FILE_INVALID",
|
|
22694
22957
|
"QR image file is invalid or unsupported"
|
|
22695
22958
|
);
|
|
@@ -22700,8 +22963,8 @@ function decodeTicketFromPng(imageBytes) {
|
|
|
22700
22963
|
decodedPng.data.byteLength
|
|
22701
22964
|
);
|
|
22702
22965
|
const decoded = jsQR(imageData, decodedPng.width, decodedPng.height);
|
|
22703
|
-
if (!decoded ||
|
|
22704
|
-
throw
|
|
22966
|
+
if (!decoded || parseNonEmptyString9(decoded.data).length === 0) {
|
|
22967
|
+
throw createCliError7(
|
|
22705
22968
|
"CLI_PAIR_CONFIRM_QR_NOT_FOUND",
|
|
22706
22969
|
"No pairing QR code was found in the image"
|
|
22707
22970
|
);
|
|
@@ -22716,7 +22979,7 @@ async function persistPairingQr(input) {
|
|
|
22716
22979
|
const getConfigDirImpl = input.dependencies.getConfigDirImpl ?? getConfigDir;
|
|
22717
22980
|
const qrEncodeImpl = input.dependencies.qrEncodeImpl ?? encodeTicketQrPng;
|
|
22718
22981
|
const baseDir = join7(getConfigDirImpl(), PAIRING_QR_DIR_NAME);
|
|
22719
|
-
const outputPath =
|
|
22982
|
+
const outputPath = parseNonEmptyString9(input.qrOutput) ? resolve(input.qrOutput ?? "") : join7(
|
|
22720
22983
|
baseDir,
|
|
22721
22984
|
`${assertValidAgentName(input.agentName)}-pair-${input.nowSeconds}.png`
|
|
22722
22985
|
);
|
|
@@ -22757,10 +23020,10 @@ async function persistPairingQr(input) {
|
|
|
22757
23020
|
return outputPath;
|
|
22758
23021
|
}
|
|
22759
23022
|
function resolveConfirmTicketSource(options) {
|
|
22760
|
-
const inlineTicket =
|
|
22761
|
-
const qrFile =
|
|
23023
|
+
const inlineTicket = parseNonEmptyString9(options.ticket);
|
|
23024
|
+
const qrFile = parseNonEmptyString9(options.qrFile);
|
|
22762
23025
|
if (inlineTicket.length > 0 && qrFile.length > 0) {
|
|
22763
|
-
throw
|
|
23026
|
+
throw createCliError7(
|
|
22764
23027
|
"CLI_PAIR_CONFIRM_INPUT_CONFLICT",
|
|
22765
23028
|
"Provide either --ticket or --qr-file, not both"
|
|
22766
23029
|
);
|
|
@@ -22778,7 +23041,7 @@ function resolveConfirmTicketSource(options) {
|
|
|
22778
23041
|
qrFilePath: resolve(qrFile)
|
|
22779
23042
|
};
|
|
22780
23043
|
}
|
|
22781
|
-
throw
|
|
23044
|
+
throw createCliError7(
|
|
22782
23045
|
"CLI_PAIR_CONFIRM_TICKET_REQUIRED",
|
|
22783
23046
|
"Pairing ticket is required. Pass --ticket <clwpair1_...> or --qr-file <path>."
|
|
22784
23047
|
);
|
|
@@ -22819,14 +23082,14 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
22819
23082
|
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
22820
23083
|
const ttlSeconds = parseTtlSeconds(options.ttlSeconds);
|
|
22821
23084
|
const config2 = await resolveConfigImpl();
|
|
22822
|
-
const proxyUrl = resolveProxyUrl({
|
|
22823
|
-
overrideProxyUrl: options.proxyUrl,
|
|
22824
|
-
config: config2
|
|
22825
|
-
});
|
|
22826
23085
|
const ownerPat = resolveOwnerPat({
|
|
22827
23086
|
explicitOwnerPat: options.ownerPat,
|
|
22828
23087
|
config: config2
|
|
22829
23088
|
});
|
|
23089
|
+
const proxyUrl = await resolveProxyUrl({
|
|
23090
|
+
config: config2,
|
|
23091
|
+
fetchImpl
|
|
23092
|
+
});
|
|
22830
23093
|
const { ait, secretKey } = await readAgentProofMaterial(
|
|
22831
23094
|
agentName,
|
|
22832
23095
|
dependencies
|
|
@@ -22860,9 +23123,9 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
22860
23123
|
body: requestBody
|
|
22861
23124
|
}
|
|
22862
23125
|
});
|
|
22863
|
-
const responseBody = await
|
|
23126
|
+
const responseBody = await parseJsonResponse6(response);
|
|
22864
23127
|
if (!response.ok) {
|
|
22865
|
-
throw
|
|
23128
|
+
throw createCliError7(
|
|
22866
23129
|
"CLI_PAIR_START_FAILED",
|
|
22867
23130
|
mapStartPairError(response.status, responseBody)
|
|
22868
23131
|
);
|
|
@@ -22892,14 +23155,14 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
22892
23155
|
const qrDecodeImpl = dependencies.qrDecodeImpl ?? decodeTicketFromPng;
|
|
22893
23156
|
const config2 = await resolveConfigImpl();
|
|
22894
23157
|
const ticketSource = resolveConfirmTicketSource(options);
|
|
22895
|
-
const proxyUrl = resolveProxyUrl({
|
|
22896
|
-
|
|
22897
|
-
|
|
23158
|
+
const proxyUrl = await resolveProxyUrl({
|
|
23159
|
+
config: config2,
|
|
23160
|
+
fetchImpl
|
|
22898
23161
|
});
|
|
22899
23162
|
let ticket = ticketSource.ticket;
|
|
22900
23163
|
if (ticketSource.source === "qr-file") {
|
|
22901
23164
|
if (!ticketSource.qrFilePath) {
|
|
22902
|
-
throw
|
|
23165
|
+
throw createCliError7(
|
|
22903
23166
|
"CLI_PAIR_CONFIRM_QR_FILE_REQUIRED",
|
|
22904
23167
|
"QR file path is required"
|
|
22905
23168
|
);
|
|
@@ -22910,7 +23173,7 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
22910
23173
|
} catch (error48) {
|
|
22911
23174
|
const nodeError = error48;
|
|
22912
23175
|
if (nodeError.code === "ENOENT") {
|
|
22913
|
-
throw
|
|
23176
|
+
throw createCliError7(
|
|
22914
23177
|
"CLI_PAIR_CONFIRM_QR_FILE_NOT_FOUND",
|
|
22915
23178
|
`QR file not found: ${ticketSource.qrFilePath}`
|
|
22916
23179
|
);
|
|
@@ -22949,9 +23212,9 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
22949
23212
|
body: requestBody
|
|
22950
23213
|
}
|
|
22951
23214
|
});
|
|
22952
|
-
const responseBody = await
|
|
23215
|
+
const responseBody = await parseJsonResponse6(response);
|
|
22953
23216
|
if (!response.ok) {
|
|
22954
|
-
throw
|
|
23217
|
+
throw createCliError7(
|
|
22955
23218
|
"CLI_PAIR_CONFIRM_FAILED",
|
|
22956
23219
|
mapConfirmPairError(response.status, responseBody)
|
|
22957
23220
|
);
|
|
@@ -22985,7 +23248,7 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
22985
23248
|
const pairCommand = new Command8("pair").description(
|
|
22986
23249
|
"Manage proxy trust pairing between agents"
|
|
22987
23250
|
);
|
|
22988
|
-
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option(
|
|
23251
|
+
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option(
|
|
22989
23252
|
"--owner-pat <token>",
|
|
22990
23253
|
"Owner PAT override (defaults to configured API key)"
|
|
22991
23254
|
).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").action(
|
|
@@ -23009,7 +23272,7 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23009
23272
|
}
|
|
23010
23273
|
)
|
|
23011
23274
|
);
|
|
23012
|
-
pairCommand.command("confirm <agentName>").description("Confirm pairing using one-time pairing ticket").option("--ticket <ticket>", "One-time pairing ticket (clwpair1_...)").option("--qr-file <path>", "Path to pairing QR PNG file").
|
|
23275
|
+
pairCommand.command("confirm <agentName>").description("Confirm pairing using one-time pairing ticket").option("--ticket <ticket>", "One-time pairing ticket (clwpair1_...)").option("--qr-file <path>", "Path to pairing QR PNG file").action(
|
|
23013
23276
|
withErrorHandling(
|
|
23014
23277
|
"pair confirm",
|
|
23015
23278
|
async (agentName, options) => {
|
|
@@ -23047,10 +23310,10 @@ var VerifyCommandError = class extends Error {
|
|
|
23047
23310
|
this.name = "VerifyCommandError";
|
|
23048
23311
|
}
|
|
23049
23312
|
};
|
|
23050
|
-
var
|
|
23313
|
+
var isRecord10 = (value) => {
|
|
23051
23314
|
return typeof value === "object" && value !== null;
|
|
23052
23315
|
};
|
|
23053
|
-
var
|
|
23316
|
+
var normalizeRegistryUrl2 = (registryUrl) => {
|
|
23054
23317
|
try {
|
|
23055
23318
|
return new URL(registryUrl).toString();
|
|
23056
23319
|
} catch {
|
|
@@ -23115,7 +23378,7 @@ var parseResponseJson = async (response) => {
|
|
|
23115
23378
|
}
|
|
23116
23379
|
};
|
|
23117
23380
|
var parseSigningKeys = (payload) => {
|
|
23118
|
-
if (!
|
|
23381
|
+
if (!isRecord10(payload) || !Array.isArray(payload.keys)) {
|
|
23119
23382
|
throw new VerifyCommandError(
|
|
23120
23383
|
"verification keys unavailable (response payload is invalid)"
|
|
23121
23384
|
);
|
|
@@ -23134,7 +23397,7 @@ var parseSigningKeys = (payload) => {
|
|
|
23134
23397
|
};
|
|
23135
23398
|
var parseRegistryKeysCache = (rawCache) => {
|
|
23136
23399
|
const parsed = parseJson(rawCache);
|
|
23137
|
-
if (!
|
|
23400
|
+
if (!isRecord10(parsed)) {
|
|
23138
23401
|
return void 0;
|
|
23139
23402
|
}
|
|
23140
23403
|
const { registryUrl, fetchedAtMs, keys } = parsed;
|
|
@@ -23160,7 +23423,7 @@ var parseRegistryKeysCache = (rawCache) => {
|
|
|
23160
23423
|
};
|
|
23161
23424
|
var parseCrlCache = (rawCache) => {
|
|
23162
23425
|
const parsed = parseJson(rawCache);
|
|
23163
|
-
if (!
|
|
23426
|
+
if (!isRecord10(parsed)) {
|
|
23164
23427
|
return void 0;
|
|
23165
23428
|
}
|
|
23166
23429
|
const { registryUrl, fetchedAtMs, claims } = parsed;
|
|
@@ -23258,7 +23521,7 @@ var fetchCrlClaims = async (input) => {
|
|
|
23258
23521
|
);
|
|
23259
23522
|
}
|
|
23260
23523
|
const payload = await parseResponseJson(response);
|
|
23261
|
-
if (!
|
|
23524
|
+
if (!isRecord10(payload) || typeof payload.crl !== "string") {
|
|
23262
23525
|
throw new VerifyCommandError(
|
|
23263
23526
|
"revocation check unavailable (response payload is invalid)"
|
|
23264
23527
|
);
|
|
@@ -23303,7 +23566,7 @@ var loadCrlClaims = async (input) => {
|
|
|
23303
23566
|
return claims;
|
|
23304
23567
|
};
|
|
23305
23568
|
var toInvalidTokenReason = (error48) => {
|
|
23306
|
-
if (
|
|
23569
|
+
if (isRecord10(error48) && typeof error48.message === "string") {
|
|
23307
23570
|
return `invalid token (${error48.message})`;
|
|
23308
23571
|
}
|
|
23309
23572
|
if (error48 instanceof Error && error48.message.length > 0) {
|
|
@@ -23321,7 +23584,7 @@ var printResult = (passed, reason) => {
|
|
|
23321
23584
|
};
|
|
23322
23585
|
var runVerify = async (tokenOrFile) => {
|
|
23323
23586
|
const config2 = await resolveConfig();
|
|
23324
|
-
const registryUrl =
|
|
23587
|
+
const registryUrl = normalizeRegistryUrl2(config2.registryUrl);
|
|
23325
23588
|
const expectedIssuer = toExpectedIssuer(registryUrl);
|
|
23326
23589
|
const token = await resolveToken(tokenOrFile);
|
|
23327
23590
|
let keys;
|