clawdentity 0.0.13 → 0.0.14
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 +346 -1
- package/dist/index.js +346 -1
- package/dist/postinstall.js +0 -0
- package/package.json +17 -16
package/dist/bin.js
CHANGED
|
@@ -22471,6 +22471,7 @@ var PAIRING_QR_DIR_NAME = "pairing";
|
|
|
22471
22471
|
var PEERS_FILE_NAME2 = "peers.json";
|
|
22472
22472
|
var PAIR_START_PATH = "/pair/start";
|
|
22473
22473
|
var PAIR_CONFIRM_PATH = "/pair/confirm";
|
|
22474
|
+
var PAIR_STATUS_PATH = "/pair/status";
|
|
22474
22475
|
var OWNER_PAT_HEADER = "x-claw-owner-pat";
|
|
22475
22476
|
var NONCE_SIZE2 = 24;
|
|
22476
22477
|
var PAIRING_TICKET_PREFIX = "clwpair1_";
|
|
@@ -22478,6 +22479,8 @@ var PAIRING_QR_MAX_AGE_SECONDS = 900;
|
|
|
22478
22479
|
var PAIRING_QR_FILENAME_PATTERN = /-pair-(\d+)\.png$/;
|
|
22479
22480
|
var FILE_MODE4 = 384;
|
|
22480
22481
|
var PEER_ALIAS_PATTERN2 = /^[a-zA-Z0-9._-]+$/;
|
|
22482
|
+
var DEFAULT_STATUS_WAIT_SECONDS = 300;
|
|
22483
|
+
var DEFAULT_STATUS_POLL_INTERVAL_SECONDS = 3;
|
|
22481
22484
|
var isRecord9 = (value) => {
|
|
22482
22485
|
return typeof value === "object" && value !== null;
|
|
22483
22486
|
};
|
|
@@ -22553,6 +22556,52 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22553
22556
|
}
|
|
22554
22557
|
return issuerUrl.origin;
|
|
22555
22558
|
}
|
|
22559
|
+
function parseAitAgentDid(ait) {
|
|
22560
|
+
const parts = ait.split(".");
|
|
22561
|
+
if (parts.length < 2) {
|
|
22562
|
+
throw createCliError7(
|
|
22563
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22564
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22565
|
+
);
|
|
22566
|
+
}
|
|
22567
|
+
let payloadRaw;
|
|
22568
|
+
try {
|
|
22569
|
+
payloadRaw = new TextDecoder().decode(decodeBase64url(parts[1] ?? ""));
|
|
22570
|
+
} catch {
|
|
22571
|
+
throw createCliError7(
|
|
22572
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22573
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22574
|
+
);
|
|
22575
|
+
}
|
|
22576
|
+
let payload;
|
|
22577
|
+
try {
|
|
22578
|
+
payload = JSON.parse(payloadRaw);
|
|
22579
|
+
} catch {
|
|
22580
|
+
throw createCliError7(
|
|
22581
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22582
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22583
|
+
);
|
|
22584
|
+
}
|
|
22585
|
+
if (!isRecord9(payload) || typeof payload.sub !== "string") {
|
|
22586
|
+
throw createCliError7(
|
|
22587
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22588
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22589
|
+
);
|
|
22590
|
+
}
|
|
22591
|
+
const candidate = payload.sub.trim();
|
|
22592
|
+
try {
|
|
22593
|
+
const parsed = parseDid(candidate);
|
|
22594
|
+
if (parsed.kind !== "agent") {
|
|
22595
|
+
throw new Error("invalid kind");
|
|
22596
|
+
}
|
|
22597
|
+
} catch {
|
|
22598
|
+
throw createCliError7(
|
|
22599
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22600
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22601
|
+
);
|
|
22602
|
+
}
|
|
22603
|
+
return candidate;
|
|
22604
|
+
}
|
|
22556
22605
|
function parsePeerAlias2(value) {
|
|
22557
22606
|
if (value.length === 0 || value.length > 128) {
|
|
22558
22607
|
throw createCliError7(
|
|
@@ -22684,6 +22733,20 @@ function parseTtlSeconds(value) {
|
|
|
22684
22733
|
}
|
|
22685
22734
|
return parsed;
|
|
22686
22735
|
}
|
|
22736
|
+
function parsePositiveIntegerOption(input) {
|
|
22737
|
+
const raw = parseNonEmptyString9(input.value);
|
|
22738
|
+
if (raw.length === 0) {
|
|
22739
|
+
return input.defaultValue;
|
|
22740
|
+
}
|
|
22741
|
+
const parsed = Number.parseInt(raw, 10);
|
|
22742
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
22743
|
+
throw createCliError7(
|
|
22744
|
+
"CLI_PAIR_STATUS_WAIT_INVALID",
|
|
22745
|
+
`${input.optionName} must be a positive integer`
|
|
22746
|
+
);
|
|
22747
|
+
}
|
|
22748
|
+
return parsed;
|
|
22749
|
+
}
|
|
22687
22750
|
function parseProxyUrl2(candidate) {
|
|
22688
22751
|
try {
|
|
22689
22752
|
const parsed = new URL(candidate);
|
|
@@ -22804,6 +22867,29 @@ function mapConfirmPairError(status, payload) {
|
|
|
22804
22867
|
}
|
|
22805
22868
|
return `Pair confirm failed (${status})`;
|
|
22806
22869
|
}
|
|
22870
|
+
function mapStatusPairError(status, payload) {
|
|
22871
|
+
const code = extractErrorCode(payload);
|
|
22872
|
+
const message2 = extractErrorMessage(payload);
|
|
22873
|
+
if (code === "PROXY_PAIR_TICKET_NOT_FOUND" || status === 404) {
|
|
22874
|
+
return "Pairing ticket not found";
|
|
22875
|
+
}
|
|
22876
|
+
if (code === "PROXY_PAIR_TICKET_EXPIRED" || status === 410) {
|
|
22877
|
+
return "Pairing ticket has expired";
|
|
22878
|
+
}
|
|
22879
|
+
if (code === "PROXY_PAIR_STATUS_FORBIDDEN" || status === 403) {
|
|
22880
|
+
return message2 ? `Pair status request is forbidden (403): ${message2}` : "Pair status request is forbidden (403).";
|
|
22881
|
+
}
|
|
22882
|
+
if (status === 400) {
|
|
22883
|
+
return message2 ? `Pair status request is invalid (400): ${message2}` : "Pair status request is invalid (400).";
|
|
22884
|
+
}
|
|
22885
|
+
if (status >= 500) {
|
|
22886
|
+
return `Proxy pairing service is unavailable (${status}).`;
|
|
22887
|
+
}
|
|
22888
|
+
if (message2) {
|
|
22889
|
+
return `Pair status failed (${status}): ${message2}`;
|
|
22890
|
+
}
|
|
22891
|
+
return `Pair status failed (${status})`;
|
|
22892
|
+
}
|
|
22807
22893
|
function parsePairStartResponse(payload) {
|
|
22808
22894
|
if (!isRecord9(payload)) {
|
|
22809
22895
|
throw createCliError7(
|
|
@@ -22848,6 +22934,44 @@ function parsePairConfirmResponse(payload) {
|
|
|
22848
22934
|
responderAgentDid
|
|
22849
22935
|
};
|
|
22850
22936
|
}
|
|
22937
|
+
function parsePairStatusResponse(payload) {
|
|
22938
|
+
if (!isRecord9(payload)) {
|
|
22939
|
+
throw createCliError7(
|
|
22940
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22941
|
+
"Pair status response is invalid"
|
|
22942
|
+
);
|
|
22943
|
+
}
|
|
22944
|
+
const statusRaw = parseNonEmptyString9(payload.status);
|
|
22945
|
+
if (statusRaw !== "pending" && statusRaw !== "confirmed") {
|
|
22946
|
+
throw createCliError7(
|
|
22947
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22948
|
+
"Pair status response is invalid"
|
|
22949
|
+
);
|
|
22950
|
+
}
|
|
22951
|
+
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
22952
|
+
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
22953
|
+
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
22954
|
+
const confirmedAt = parseNonEmptyString9(payload.confirmedAt);
|
|
22955
|
+
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
22956
|
+
throw createCliError7(
|
|
22957
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22958
|
+
"Pair status response is invalid"
|
|
22959
|
+
);
|
|
22960
|
+
}
|
|
22961
|
+
if (statusRaw === "confirmed" && responderAgentDid.length === 0) {
|
|
22962
|
+
throw createCliError7(
|
|
22963
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22964
|
+
"Pair status response is invalid"
|
|
22965
|
+
);
|
|
22966
|
+
}
|
|
22967
|
+
return {
|
|
22968
|
+
status: statusRaw,
|
|
22969
|
+
initiatorAgentDid,
|
|
22970
|
+
responderAgentDid: responderAgentDid.length > 0 ? responderAgentDid : void 0,
|
|
22971
|
+
expiresAt,
|
|
22972
|
+
confirmedAt: confirmedAt.length > 0 ? confirmedAt : void 0
|
|
22973
|
+
};
|
|
22974
|
+
}
|
|
22851
22975
|
async function readAgentProofMaterial(agentName, dependencies) {
|
|
22852
22976
|
const readFileImpl = dependencies.readFileImpl ?? readFile5;
|
|
22853
22977
|
const getConfigDirImpl = dependencies.getConfigDirImpl ?? getConfigDir;
|
|
@@ -23238,6 +23362,147 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23238
23362
|
peerAlias
|
|
23239
23363
|
};
|
|
23240
23364
|
}
|
|
23365
|
+
async function getPairingStatusOnce(agentName, options, dependencies = {}) {
|
|
23366
|
+
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
23367
|
+
const resolveConfigImpl = dependencies.resolveConfigImpl ?? resolveConfig;
|
|
23368
|
+
const nowSecondsImpl = dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
23369
|
+
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
23370
|
+
const config2 = await resolveConfigImpl();
|
|
23371
|
+
const proxyUrl = await resolveProxyUrl({
|
|
23372
|
+
config: config2,
|
|
23373
|
+
fetchImpl
|
|
23374
|
+
});
|
|
23375
|
+
const ticket = parsePairingTicket(options.ticket);
|
|
23376
|
+
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23377
|
+
agentName,
|
|
23378
|
+
dependencies
|
|
23379
|
+
);
|
|
23380
|
+
const callerAgentDid = parseAitAgentDid(ait);
|
|
23381
|
+
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_STATUS_PATH);
|
|
23382
|
+
const requestBody = JSON.stringify({ ticket });
|
|
23383
|
+
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23384
|
+
const timestampSeconds = nowSecondsImpl();
|
|
23385
|
+
const nonce = nonceFactoryImpl();
|
|
23386
|
+
const signedHeaders = await buildSignedHeaders({
|
|
23387
|
+
method: "POST",
|
|
23388
|
+
requestUrl,
|
|
23389
|
+
bodyBytes,
|
|
23390
|
+
secretKey,
|
|
23391
|
+
timestampSeconds,
|
|
23392
|
+
nonce
|
|
23393
|
+
});
|
|
23394
|
+
const response = await executePairRequest({
|
|
23395
|
+
fetchImpl,
|
|
23396
|
+
url: requestUrl,
|
|
23397
|
+
init: {
|
|
23398
|
+
method: "POST",
|
|
23399
|
+
headers: {
|
|
23400
|
+
authorization: `Claw ${ait}`,
|
|
23401
|
+
"content-type": "application/json",
|
|
23402
|
+
...signedHeaders
|
|
23403
|
+
},
|
|
23404
|
+
body: requestBody
|
|
23405
|
+
}
|
|
23406
|
+
});
|
|
23407
|
+
const responseBody = await parseJsonResponse6(response);
|
|
23408
|
+
if (!response.ok) {
|
|
23409
|
+
throw createCliError7(
|
|
23410
|
+
"CLI_PAIR_STATUS_FAILED",
|
|
23411
|
+
mapStatusPairError(response.status, responseBody)
|
|
23412
|
+
);
|
|
23413
|
+
}
|
|
23414
|
+
const parsed = parsePairStatusResponse(responseBody);
|
|
23415
|
+
let peerAlias;
|
|
23416
|
+
if (parsed.status === "confirmed") {
|
|
23417
|
+
const responderAgentDid = parsed.responderAgentDid;
|
|
23418
|
+
if (!responderAgentDid) {
|
|
23419
|
+
throw createCliError7(
|
|
23420
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23421
|
+
"Pair status response is invalid"
|
|
23422
|
+
);
|
|
23423
|
+
}
|
|
23424
|
+
const peerDid = callerAgentDid === parsed.initiatorAgentDid ? responderAgentDid : callerAgentDid === responderAgentDid ? parsed.initiatorAgentDid : void 0;
|
|
23425
|
+
if (!peerDid) {
|
|
23426
|
+
throw createCliError7(
|
|
23427
|
+
"CLI_PAIR_STATUS_FORBIDDEN",
|
|
23428
|
+
"Local agent is not a participant in the pairing ticket"
|
|
23429
|
+
);
|
|
23430
|
+
}
|
|
23431
|
+
peerAlias = await persistPairedPeer({
|
|
23432
|
+
ticket,
|
|
23433
|
+
peerDid,
|
|
23434
|
+
dependencies
|
|
23435
|
+
});
|
|
23436
|
+
}
|
|
23437
|
+
return {
|
|
23438
|
+
...parsed,
|
|
23439
|
+
proxyUrl,
|
|
23440
|
+
peerAlias
|
|
23441
|
+
};
|
|
23442
|
+
}
|
|
23443
|
+
async function waitForPairingStatus(input) {
|
|
23444
|
+
const nowSecondsImpl = input.dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
23445
|
+
const sleepImpl = input.dependencies.sleepImpl ?? (async (ms) => {
|
|
23446
|
+
await new Promise((resolve2) => {
|
|
23447
|
+
setTimeout(resolve2, ms);
|
|
23448
|
+
});
|
|
23449
|
+
});
|
|
23450
|
+
const deadlineSeconds = nowSecondsImpl() + input.waitSeconds;
|
|
23451
|
+
while (true) {
|
|
23452
|
+
const status = await getPairingStatusOnce(
|
|
23453
|
+
input.agentName,
|
|
23454
|
+
{ ticket: input.ticket },
|
|
23455
|
+
input.dependencies
|
|
23456
|
+
);
|
|
23457
|
+
if (status.status === "confirmed") {
|
|
23458
|
+
return status;
|
|
23459
|
+
}
|
|
23460
|
+
const nowSeconds = nowSecondsImpl();
|
|
23461
|
+
if (nowSeconds >= deadlineSeconds) {
|
|
23462
|
+
throw createCliError7(
|
|
23463
|
+
"CLI_PAIR_STATUS_WAIT_TIMEOUT",
|
|
23464
|
+
`Pairing is still pending after ${input.waitSeconds} seconds`
|
|
23465
|
+
);
|
|
23466
|
+
}
|
|
23467
|
+
const remainingSeconds = Math.max(0, deadlineSeconds - nowSeconds);
|
|
23468
|
+
const sleepSeconds = Math.min(input.pollIntervalSeconds, remainingSeconds);
|
|
23469
|
+
await sleepImpl(sleepSeconds * 1e3);
|
|
23470
|
+
}
|
|
23471
|
+
}
|
|
23472
|
+
async function getPairingStatus(agentName, options, dependencies = {}) {
|
|
23473
|
+
const ticketRaw = parseNonEmptyString9(options.ticket);
|
|
23474
|
+
if (ticketRaw.length === 0) {
|
|
23475
|
+
throw createCliError7(
|
|
23476
|
+
"CLI_PAIR_STATUS_TICKET_REQUIRED",
|
|
23477
|
+
"Pair status requires --ticket <clwpair1_...>"
|
|
23478
|
+
);
|
|
23479
|
+
}
|
|
23480
|
+
const ticket = parsePairingTicket(ticketRaw);
|
|
23481
|
+
if (options.wait !== true) {
|
|
23482
|
+
return getPairingStatusOnce(
|
|
23483
|
+
agentName,
|
|
23484
|
+
{ ticket },
|
|
23485
|
+
dependencies
|
|
23486
|
+
);
|
|
23487
|
+
}
|
|
23488
|
+
const waitSeconds = parsePositiveIntegerOption({
|
|
23489
|
+
value: options.waitSeconds,
|
|
23490
|
+
optionName: "waitSeconds",
|
|
23491
|
+
defaultValue: DEFAULT_STATUS_WAIT_SECONDS
|
|
23492
|
+
});
|
|
23493
|
+
const pollIntervalSeconds = parsePositiveIntegerOption({
|
|
23494
|
+
value: options.pollIntervalSeconds,
|
|
23495
|
+
optionName: "pollIntervalSeconds",
|
|
23496
|
+
defaultValue: DEFAULT_STATUS_POLL_INTERVAL_SECONDS
|
|
23497
|
+
});
|
|
23498
|
+
return waitForPairingStatus({
|
|
23499
|
+
agentName,
|
|
23500
|
+
ticket,
|
|
23501
|
+
waitSeconds,
|
|
23502
|
+
pollIntervalSeconds,
|
|
23503
|
+
dependencies
|
|
23504
|
+
});
|
|
23505
|
+
}
|
|
23241
23506
|
var createPairCommand = (dependencies = {}) => {
|
|
23242
23507
|
const pairCommand = new Command8("pair").description(
|
|
23243
23508
|
"Manage proxy trust pairing between agents"
|
|
@@ -23245,7 +23510,16 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23245
23510
|
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option(
|
|
23246
23511
|
"--owner-pat <token>",
|
|
23247
23512
|
"Owner PAT override (defaults to configured API key)"
|
|
23248
|
-
).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").
|
|
23513
|
+
).option("--ttl-seconds <seconds>", "Pairing ticket expiry in seconds").option("--qr", "Generate a local QR file for sharing").option("--qr-output <path>", "Write QR PNG to a specific file path").option(
|
|
23514
|
+
"--wait",
|
|
23515
|
+
"Wait for responder confirmation and auto-save peer on initiator"
|
|
23516
|
+
).option(
|
|
23517
|
+
"--wait-seconds <seconds>",
|
|
23518
|
+
"Max seconds to poll for confirmation (default: 300)"
|
|
23519
|
+
).option(
|
|
23520
|
+
"--poll-interval-seconds <seconds>",
|
|
23521
|
+
"Polling interval in seconds while waiting (default: 3)"
|
|
23522
|
+
).action(
|
|
23249
23523
|
withErrorHandling(
|
|
23250
23524
|
"pair start",
|
|
23251
23525
|
async (agentName, options) => {
|
|
@@ -23263,6 +23537,44 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23263
23537
|
if (result.qrPath) {
|
|
23264
23538
|
writeStdoutLine(`QR File: ${result.qrPath}`);
|
|
23265
23539
|
}
|
|
23540
|
+
if (options.wait === true) {
|
|
23541
|
+
const waitSeconds = parsePositiveIntegerOption({
|
|
23542
|
+
value: options.waitSeconds,
|
|
23543
|
+
optionName: "waitSeconds",
|
|
23544
|
+
defaultValue: DEFAULT_STATUS_WAIT_SECONDS
|
|
23545
|
+
});
|
|
23546
|
+
const pollIntervalSeconds = parsePositiveIntegerOption({
|
|
23547
|
+
value: options.pollIntervalSeconds,
|
|
23548
|
+
optionName: "pollIntervalSeconds",
|
|
23549
|
+
defaultValue: DEFAULT_STATUS_POLL_INTERVAL_SECONDS
|
|
23550
|
+
});
|
|
23551
|
+
writeStdoutLine(
|
|
23552
|
+
`Waiting for confirmation (timeout=${waitSeconds}s, interval=${pollIntervalSeconds}s) ...`
|
|
23553
|
+
);
|
|
23554
|
+
const status = await waitForPairingStatus({
|
|
23555
|
+
agentName,
|
|
23556
|
+
ticket: result.ticket,
|
|
23557
|
+
waitSeconds,
|
|
23558
|
+
pollIntervalSeconds,
|
|
23559
|
+
dependencies
|
|
23560
|
+
});
|
|
23561
|
+
logger9.info("cli.pair_status_confirmed_after_start", {
|
|
23562
|
+
initiatorAgentDid: status.initiatorAgentDid,
|
|
23563
|
+
responderAgentDid: status.responderAgentDid,
|
|
23564
|
+
peerAlias: status.peerAlias
|
|
23565
|
+
});
|
|
23566
|
+
writeStdoutLine("Pairing confirmed");
|
|
23567
|
+
writeStdoutLine(`Status: ${status.status}`);
|
|
23568
|
+
if (status.initiatorAgentDid) {
|
|
23569
|
+
writeStdoutLine(`Initiator Agent DID: ${status.initiatorAgentDid}`);
|
|
23570
|
+
}
|
|
23571
|
+
if (status.responderAgentDid) {
|
|
23572
|
+
writeStdoutLine(`Responder Agent DID: ${status.responderAgentDid}`);
|
|
23573
|
+
}
|
|
23574
|
+
if (status.peerAlias) {
|
|
23575
|
+
writeStdoutLine(`Peer alias saved: ${status.peerAlias}`);
|
|
23576
|
+
}
|
|
23577
|
+
}
|
|
23266
23578
|
}
|
|
23267
23579
|
)
|
|
23268
23580
|
);
|
|
@@ -23287,6 +23599,39 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23287
23599
|
}
|
|
23288
23600
|
)
|
|
23289
23601
|
);
|
|
23602
|
+
pairCommand.command("status <agentName>").description("Check pairing ticket status and sync local peer on confirm").option("--ticket <ticket>", "One-time pairing ticket (clwpair1_...)").option("--wait", "Poll until ticket is confirmed or timeout is reached").option(
|
|
23603
|
+
"--wait-seconds <seconds>",
|
|
23604
|
+
"Max seconds to poll for confirmation (default: 300)"
|
|
23605
|
+
).option(
|
|
23606
|
+
"--poll-interval-seconds <seconds>",
|
|
23607
|
+
"Polling interval in seconds while waiting (default: 3)"
|
|
23608
|
+
).action(
|
|
23609
|
+
withErrorHandling(
|
|
23610
|
+
"pair status",
|
|
23611
|
+
async (agentName, options) => {
|
|
23612
|
+
const result = await getPairingStatus(agentName, options, dependencies);
|
|
23613
|
+
logger9.info("cli.pair_status", {
|
|
23614
|
+
initiatorAgentDid: result.initiatorAgentDid,
|
|
23615
|
+
responderAgentDid: result.responderAgentDid,
|
|
23616
|
+
status: result.status,
|
|
23617
|
+
proxyUrl: result.proxyUrl,
|
|
23618
|
+
peerAlias: result.peerAlias
|
|
23619
|
+
});
|
|
23620
|
+
writeStdoutLine(`Status: ${result.status}`);
|
|
23621
|
+
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
23622
|
+
if (result.responderAgentDid) {
|
|
23623
|
+
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
23624
|
+
}
|
|
23625
|
+
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
23626
|
+
if (result.confirmedAt) {
|
|
23627
|
+
writeStdoutLine(`Confirmed At: ${result.confirmedAt}`);
|
|
23628
|
+
}
|
|
23629
|
+
if (result.peerAlias) {
|
|
23630
|
+
writeStdoutLine(`Peer alias saved: ${result.peerAlias}`);
|
|
23631
|
+
}
|
|
23632
|
+
}
|
|
23633
|
+
)
|
|
23634
|
+
);
|
|
23290
23635
|
return pairCommand;
|
|
23291
23636
|
};
|
|
23292
23637
|
|
package/dist/index.js
CHANGED
|
@@ -22471,6 +22471,7 @@ var PAIRING_QR_DIR_NAME = "pairing";
|
|
|
22471
22471
|
var PEERS_FILE_NAME2 = "peers.json";
|
|
22472
22472
|
var PAIR_START_PATH = "/pair/start";
|
|
22473
22473
|
var PAIR_CONFIRM_PATH = "/pair/confirm";
|
|
22474
|
+
var PAIR_STATUS_PATH = "/pair/status";
|
|
22474
22475
|
var OWNER_PAT_HEADER = "x-claw-owner-pat";
|
|
22475
22476
|
var NONCE_SIZE2 = 24;
|
|
22476
22477
|
var PAIRING_TICKET_PREFIX = "clwpair1_";
|
|
@@ -22478,6 +22479,8 @@ var PAIRING_QR_MAX_AGE_SECONDS = 900;
|
|
|
22478
22479
|
var PAIRING_QR_FILENAME_PATTERN = /-pair-(\d+)\.png$/;
|
|
22479
22480
|
var FILE_MODE4 = 384;
|
|
22480
22481
|
var PEER_ALIAS_PATTERN2 = /^[a-zA-Z0-9._-]+$/;
|
|
22482
|
+
var DEFAULT_STATUS_WAIT_SECONDS = 300;
|
|
22483
|
+
var DEFAULT_STATUS_POLL_INTERVAL_SECONDS = 3;
|
|
22481
22484
|
var isRecord9 = (value) => {
|
|
22482
22485
|
return typeof value === "object" && value !== null;
|
|
22483
22486
|
};
|
|
@@ -22553,6 +22556,52 @@ function parsePairingTicketIssuerOrigin(ticket) {
|
|
|
22553
22556
|
}
|
|
22554
22557
|
return issuerUrl.origin;
|
|
22555
22558
|
}
|
|
22559
|
+
function parseAitAgentDid(ait) {
|
|
22560
|
+
const parts = ait.split(".");
|
|
22561
|
+
if (parts.length < 2) {
|
|
22562
|
+
throw createCliError7(
|
|
22563
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22564
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22565
|
+
);
|
|
22566
|
+
}
|
|
22567
|
+
let payloadRaw;
|
|
22568
|
+
try {
|
|
22569
|
+
payloadRaw = new TextDecoder().decode(decodeBase64url(parts[1] ?? ""));
|
|
22570
|
+
} catch {
|
|
22571
|
+
throw createCliError7(
|
|
22572
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22573
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22574
|
+
);
|
|
22575
|
+
}
|
|
22576
|
+
let payload;
|
|
22577
|
+
try {
|
|
22578
|
+
payload = JSON.parse(payloadRaw);
|
|
22579
|
+
} catch {
|
|
22580
|
+
throw createCliError7(
|
|
22581
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22582
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22583
|
+
);
|
|
22584
|
+
}
|
|
22585
|
+
if (!isRecord9(payload) || typeof payload.sub !== "string") {
|
|
22586
|
+
throw createCliError7(
|
|
22587
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22588
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22589
|
+
);
|
|
22590
|
+
}
|
|
22591
|
+
const candidate = payload.sub.trim();
|
|
22592
|
+
try {
|
|
22593
|
+
const parsed = parseDid(candidate);
|
|
22594
|
+
if (parsed.kind !== "agent") {
|
|
22595
|
+
throw new Error("invalid kind");
|
|
22596
|
+
}
|
|
22597
|
+
} catch {
|
|
22598
|
+
throw createCliError7(
|
|
22599
|
+
"CLI_PAIR_AGENT_NOT_FOUND",
|
|
22600
|
+
"Agent AIT is invalid. Recreate the agent before pairing."
|
|
22601
|
+
);
|
|
22602
|
+
}
|
|
22603
|
+
return candidate;
|
|
22604
|
+
}
|
|
22556
22605
|
function parsePeerAlias2(value) {
|
|
22557
22606
|
if (value.length === 0 || value.length > 128) {
|
|
22558
22607
|
throw createCliError7(
|
|
@@ -22684,6 +22733,20 @@ function parseTtlSeconds(value) {
|
|
|
22684
22733
|
}
|
|
22685
22734
|
return parsed;
|
|
22686
22735
|
}
|
|
22736
|
+
function parsePositiveIntegerOption(input) {
|
|
22737
|
+
const raw = parseNonEmptyString9(input.value);
|
|
22738
|
+
if (raw.length === 0) {
|
|
22739
|
+
return input.defaultValue;
|
|
22740
|
+
}
|
|
22741
|
+
const parsed = Number.parseInt(raw, 10);
|
|
22742
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
22743
|
+
throw createCliError7(
|
|
22744
|
+
"CLI_PAIR_STATUS_WAIT_INVALID",
|
|
22745
|
+
`${input.optionName} must be a positive integer`
|
|
22746
|
+
);
|
|
22747
|
+
}
|
|
22748
|
+
return parsed;
|
|
22749
|
+
}
|
|
22687
22750
|
function parseProxyUrl2(candidate) {
|
|
22688
22751
|
try {
|
|
22689
22752
|
const parsed = new URL(candidate);
|
|
@@ -22804,6 +22867,29 @@ function mapConfirmPairError(status, payload) {
|
|
|
22804
22867
|
}
|
|
22805
22868
|
return `Pair confirm failed (${status})`;
|
|
22806
22869
|
}
|
|
22870
|
+
function mapStatusPairError(status, payload) {
|
|
22871
|
+
const code = extractErrorCode(payload);
|
|
22872
|
+
const message2 = extractErrorMessage(payload);
|
|
22873
|
+
if (code === "PROXY_PAIR_TICKET_NOT_FOUND" || status === 404) {
|
|
22874
|
+
return "Pairing ticket not found";
|
|
22875
|
+
}
|
|
22876
|
+
if (code === "PROXY_PAIR_TICKET_EXPIRED" || status === 410) {
|
|
22877
|
+
return "Pairing ticket has expired";
|
|
22878
|
+
}
|
|
22879
|
+
if (code === "PROXY_PAIR_STATUS_FORBIDDEN" || status === 403) {
|
|
22880
|
+
return message2 ? `Pair status request is forbidden (403): ${message2}` : "Pair status request is forbidden (403).";
|
|
22881
|
+
}
|
|
22882
|
+
if (status === 400) {
|
|
22883
|
+
return message2 ? `Pair status request is invalid (400): ${message2}` : "Pair status request is invalid (400).";
|
|
22884
|
+
}
|
|
22885
|
+
if (status >= 500) {
|
|
22886
|
+
return `Proxy pairing service is unavailable (${status}).`;
|
|
22887
|
+
}
|
|
22888
|
+
if (message2) {
|
|
22889
|
+
return `Pair status failed (${status}): ${message2}`;
|
|
22890
|
+
}
|
|
22891
|
+
return `Pair status failed (${status})`;
|
|
22892
|
+
}
|
|
22807
22893
|
function parsePairStartResponse(payload) {
|
|
22808
22894
|
if (!isRecord9(payload)) {
|
|
22809
22895
|
throw createCliError7(
|
|
@@ -22848,6 +22934,44 @@ function parsePairConfirmResponse(payload) {
|
|
|
22848
22934
|
responderAgentDid
|
|
22849
22935
|
};
|
|
22850
22936
|
}
|
|
22937
|
+
function parsePairStatusResponse(payload) {
|
|
22938
|
+
if (!isRecord9(payload)) {
|
|
22939
|
+
throw createCliError7(
|
|
22940
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22941
|
+
"Pair status response is invalid"
|
|
22942
|
+
);
|
|
22943
|
+
}
|
|
22944
|
+
const statusRaw = parseNonEmptyString9(payload.status);
|
|
22945
|
+
if (statusRaw !== "pending" && statusRaw !== "confirmed") {
|
|
22946
|
+
throw createCliError7(
|
|
22947
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22948
|
+
"Pair status response is invalid"
|
|
22949
|
+
);
|
|
22950
|
+
}
|
|
22951
|
+
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
22952
|
+
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
22953
|
+
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
22954
|
+
const confirmedAt = parseNonEmptyString9(payload.confirmedAt);
|
|
22955
|
+
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
22956
|
+
throw createCliError7(
|
|
22957
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22958
|
+
"Pair status response is invalid"
|
|
22959
|
+
);
|
|
22960
|
+
}
|
|
22961
|
+
if (statusRaw === "confirmed" && responderAgentDid.length === 0) {
|
|
22962
|
+
throw createCliError7(
|
|
22963
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
22964
|
+
"Pair status response is invalid"
|
|
22965
|
+
);
|
|
22966
|
+
}
|
|
22967
|
+
return {
|
|
22968
|
+
status: statusRaw,
|
|
22969
|
+
initiatorAgentDid,
|
|
22970
|
+
responderAgentDid: responderAgentDid.length > 0 ? responderAgentDid : void 0,
|
|
22971
|
+
expiresAt,
|
|
22972
|
+
confirmedAt: confirmedAt.length > 0 ? confirmedAt : void 0
|
|
22973
|
+
};
|
|
22974
|
+
}
|
|
22851
22975
|
async function readAgentProofMaterial(agentName, dependencies) {
|
|
22852
22976
|
const readFileImpl = dependencies.readFileImpl ?? readFile5;
|
|
22853
22977
|
const getConfigDirImpl = dependencies.getConfigDirImpl ?? getConfigDir;
|
|
@@ -23238,6 +23362,147 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23238
23362
|
peerAlias
|
|
23239
23363
|
};
|
|
23240
23364
|
}
|
|
23365
|
+
async function getPairingStatusOnce(agentName, options, dependencies = {}) {
|
|
23366
|
+
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
23367
|
+
const resolveConfigImpl = dependencies.resolveConfigImpl ?? resolveConfig;
|
|
23368
|
+
const nowSecondsImpl = dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
23369
|
+
const nonceFactoryImpl = dependencies.nonceFactoryImpl ?? (() => randomBytes4(NONCE_SIZE2).toString("base64url"));
|
|
23370
|
+
const config2 = await resolveConfigImpl();
|
|
23371
|
+
const proxyUrl = await resolveProxyUrl({
|
|
23372
|
+
config: config2,
|
|
23373
|
+
fetchImpl
|
|
23374
|
+
});
|
|
23375
|
+
const ticket = parsePairingTicket(options.ticket);
|
|
23376
|
+
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23377
|
+
agentName,
|
|
23378
|
+
dependencies
|
|
23379
|
+
);
|
|
23380
|
+
const callerAgentDid = parseAitAgentDid(ait);
|
|
23381
|
+
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_STATUS_PATH);
|
|
23382
|
+
const requestBody = JSON.stringify({ ticket });
|
|
23383
|
+
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23384
|
+
const timestampSeconds = nowSecondsImpl();
|
|
23385
|
+
const nonce = nonceFactoryImpl();
|
|
23386
|
+
const signedHeaders = await buildSignedHeaders({
|
|
23387
|
+
method: "POST",
|
|
23388
|
+
requestUrl,
|
|
23389
|
+
bodyBytes,
|
|
23390
|
+
secretKey,
|
|
23391
|
+
timestampSeconds,
|
|
23392
|
+
nonce
|
|
23393
|
+
});
|
|
23394
|
+
const response = await executePairRequest({
|
|
23395
|
+
fetchImpl,
|
|
23396
|
+
url: requestUrl,
|
|
23397
|
+
init: {
|
|
23398
|
+
method: "POST",
|
|
23399
|
+
headers: {
|
|
23400
|
+
authorization: `Claw ${ait}`,
|
|
23401
|
+
"content-type": "application/json",
|
|
23402
|
+
...signedHeaders
|
|
23403
|
+
},
|
|
23404
|
+
body: requestBody
|
|
23405
|
+
}
|
|
23406
|
+
});
|
|
23407
|
+
const responseBody = await parseJsonResponse6(response);
|
|
23408
|
+
if (!response.ok) {
|
|
23409
|
+
throw createCliError7(
|
|
23410
|
+
"CLI_PAIR_STATUS_FAILED",
|
|
23411
|
+
mapStatusPairError(response.status, responseBody)
|
|
23412
|
+
);
|
|
23413
|
+
}
|
|
23414
|
+
const parsed = parsePairStatusResponse(responseBody);
|
|
23415
|
+
let peerAlias;
|
|
23416
|
+
if (parsed.status === "confirmed") {
|
|
23417
|
+
const responderAgentDid = parsed.responderAgentDid;
|
|
23418
|
+
if (!responderAgentDid) {
|
|
23419
|
+
throw createCliError7(
|
|
23420
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23421
|
+
"Pair status response is invalid"
|
|
23422
|
+
);
|
|
23423
|
+
}
|
|
23424
|
+
const peerDid = callerAgentDid === parsed.initiatorAgentDid ? responderAgentDid : callerAgentDid === responderAgentDid ? parsed.initiatorAgentDid : void 0;
|
|
23425
|
+
if (!peerDid) {
|
|
23426
|
+
throw createCliError7(
|
|
23427
|
+
"CLI_PAIR_STATUS_FORBIDDEN",
|
|
23428
|
+
"Local agent is not a participant in the pairing ticket"
|
|
23429
|
+
);
|
|
23430
|
+
}
|
|
23431
|
+
peerAlias = await persistPairedPeer({
|
|
23432
|
+
ticket,
|
|
23433
|
+
peerDid,
|
|
23434
|
+
dependencies
|
|
23435
|
+
});
|
|
23436
|
+
}
|
|
23437
|
+
return {
|
|
23438
|
+
...parsed,
|
|
23439
|
+
proxyUrl,
|
|
23440
|
+
peerAlias
|
|
23441
|
+
};
|
|
23442
|
+
}
|
|
23443
|
+
async function waitForPairingStatus(input) {
|
|
23444
|
+
const nowSecondsImpl = input.dependencies.nowSecondsImpl ?? (() => Math.floor(Date.now() / 1e3));
|
|
23445
|
+
const sleepImpl = input.dependencies.sleepImpl ?? (async (ms) => {
|
|
23446
|
+
await new Promise((resolve2) => {
|
|
23447
|
+
setTimeout(resolve2, ms);
|
|
23448
|
+
});
|
|
23449
|
+
});
|
|
23450
|
+
const deadlineSeconds = nowSecondsImpl() + input.waitSeconds;
|
|
23451
|
+
while (true) {
|
|
23452
|
+
const status = await getPairingStatusOnce(
|
|
23453
|
+
input.agentName,
|
|
23454
|
+
{ ticket: input.ticket },
|
|
23455
|
+
input.dependencies
|
|
23456
|
+
);
|
|
23457
|
+
if (status.status === "confirmed") {
|
|
23458
|
+
return status;
|
|
23459
|
+
}
|
|
23460
|
+
const nowSeconds = nowSecondsImpl();
|
|
23461
|
+
if (nowSeconds >= deadlineSeconds) {
|
|
23462
|
+
throw createCliError7(
|
|
23463
|
+
"CLI_PAIR_STATUS_WAIT_TIMEOUT",
|
|
23464
|
+
`Pairing is still pending after ${input.waitSeconds} seconds`
|
|
23465
|
+
);
|
|
23466
|
+
}
|
|
23467
|
+
const remainingSeconds = Math.max(0, deadlineSeconds - nowSeconds);
|
|
23468
|
+
const sleepSeconds = Math.min(input.pollIntervalSeconds, remainingSeconds);
|
|
23469
|
+
await sleepImpl(sleepSeconds * 1e3);
|
|
23470
|
+
}
|
|
23471
|
+
}
|
|
23472
|
+
async function getPairingStatus(agentName, options, dependencies = {}) {
|
|
23473
|
+
const ticketRaw = parseNonEmptyString9(options.ticket);
|
|
23474
|
+
if (ticketRaw.length === 0) {
|
|
23475
|
+
throw createCliError7(
|
|
23476
|
+
"CLI_PAIR_STATUS_TICKET_REQUIRED",
|
|
23477
|
+
"Pair status requires --ticket <clwpair1_...>"
|
|
23478
|
+
);
|
|
23479
|
+
}
|
|
23480
|
+
const ticket = parsePairingTicket(ticketRaw);
|
|
23481
|
+
if (options.wait !== true) {
|
|
23482
|
+
return getPairingStatusOnce(
|
|
23483
|
+
agentName,
|
|
23484
|
+
{ ticket },
|
|
23485
|
+
dependencies
|
|
23486
|
+
);
|
|
23487
|
+
}
|
|
23488
|
+
const waitSeconds = parsePositiveIntegerOption({
|
|
23489
|
+
value: options.waitSeconds,
|
|
23490
|
+
optionName: "waitSeconds",
|
|
23491
|
+
defaultValue: DEFAULT_STATUS_WAIT_SECONDS
|
|
23492
|
+
});
|
|
23493
|
+
const pollIntervalSeconds = parsePositiveIntegerOption({
|
|
23494
|
+
value: options.pollIntervalSeconds,
|
|
23495
|
+
optionName: "pollIntervalSeconds",
|
|
23496
|
+
defaultValue: DEFAULT_STATUS_POLL_INTERVAL_SECONDS
|
|
23497
|
+
});
|
|
23498
|
+
return waitForPairingStatus({
|
|
23499
|
+
agentName,
|
|
23500
|
+
ticket,
|
|
23501
|
+
waitSeconds,
|
|
23502
|
+
pollIntervalSeconds,
|
|
23503
|
+
dependencies
|
|
23504
|
+
});
|
|
23505
|
+
}
|
|
23241
23506
|
var createPairCommand = (dependencies = {}) => {
|
|
23242
23507
|
const pairCommand = new Command8("pair").description(
|
|
23243
23508
|
"Manage proxy trust pairing between agents"
|
|
@@ -23245,7 +23510,16 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23245
23510
|
pairCommand.command("start <agentName>").description("Start pairing and issue one-time pairing ticket").option(
|
|
23246
23511
|
"--owner-pat <token>",
|
|
23247
23512
|
"Owner PAT override (defaults to configured API key)"
|
|
23248
|
-
).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").
|
|
23513
|
+
).option("--ttl-seconds <seconds>", "Pairing ticket expiry in seconds").option("--qr", "Generate a local QR file for sharing").option("--qr-output <path>", "Write QR PNG to a specific file path").option(
|
|
23514
|
+
"--wait",
|
|
23515
|
+
"Wait for responder confirmation and auto-save peer on initiator"
|
|
23516
|
+
).option(
|
|
23517
|
+
"--wait-seconds <seconds>",
|
|
23518
|
+
"Max seconds to poll for confirmation (default: 300)"
|
|
23519
|
+
).option(
|
|
23520
|
+
"--poll-interval-seconds <seconds>",
|
|
23521
|
+
"Polling interval in seconds while waiting (default: 3)"
|
|
23522
|
+
).action(
|
|
23249
23523
|
withErrorHandling(
|
|
23250
23524
|
"pair start",
|
|
23251
23525
|
async (agentName, options) => {
|
|
@@ -23263,6 +23537,44 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23263
23537
|
if (result.qrPath) {
|
|
23264
23538
|
writeStdoutLine(`QR File: ${result.qrPath}`);
|
|
23265
23539
|
}
|
|
23540
|
+
if (options.wait === true) {
|
|
23541
|
+
const waitSeconds = parsePositiveIntegerOption({
|
|
23542
|
+
value: options.waitSeconds,
|
|
23543
|
+
optionName: "waitSeconds",
|
|
23544
|
+
defaultValue: DEFAULT_STATUS_WAIT_SECONDS
|
|
23545
|
+
});
|
|
23546
|
+
const pollIntervalSeconds = parsePositiveIntegerOption({
|
|
23547
|
+
value: options.pollIntervalSeconds,
|
|
23548
|
+
optionName: "pollIntervalSeconds",
|
|
23549
|
+
defaultValue: DEFAULT_STATUS_POLL_INTERVAL_SECONDS
|
|
23550
|
+
});
|
|
23551
|
+
writeStdoutLine(
|
|
23552
|
+
`Waiting for confirmation (timeout=${waitSeconds}s, interval=${pollIntervalSeconds}s) ...`
|
|
23553
|
+
);
|
|
23554
|
+
const status = await waitForPairingStatus({
|
|
23555
|
+
agentName,
|
|
23556
|
+
ticket: result.ticket,
|
|
23557
|
+
waitSeconds,
|
|
23558
|
+
pollIntervalSeconds,
|
|
23559
|
+
dependencies
|
|
23560
|
+
});
|
|
23561
|
+
logger9.info("cli.pair_status_confirmed_after_start", {
|
|
23562
|
+
initiatorAgentDid: status.initiatorAgentDid,
|
|
23563
|
+
responderAgentDid: status.responderAgentDid,
|
|
23564
|
+
peerAlias: status.peerAlias
|
|
23565
|
+
});
|
|
23566
|
+
writeStdoutLine("Pairing confirmed");
|
|
23567
|
+
writeStdoutLine(`Status: ${status.status}`);
|
|
23568
|
+
if (status.initiatorAgentDid) {
|
|
23569
|
+
writeStdoutLine(`Initiator Agent DID: ${status.initiatorAgentDid}`);
|
|
23570
|
+
}
|
|
23571
|
+
if (status.responderAgentDid) {
|
|
23572
|
+
writeStdoutLine(`Responder Agent DID: ${status.responderAgentDid}`);
|
|
23573
|
+
}
|
|
23574
|
+
if (status.peerAlias) {
|
|
23575
|
+
writeStdoutLine(`Peer alias saved: ${status.peerAlias}`);
|
|
23576
|
+
}
|
|
23577
|
+
}
|
|
23266
23578
|
}
|
|
23267
23579
|
)
|
|
23268
23580
|
);
|
|
@@ -23287,6 +23599,39 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
23287
23599
|
}
|
|
23288
23600
|
)
|
|
23289
23601
|
);
|
|
23602
|
+
pairCommand.command("status <agentName>").description("Check pairing ticket status and sync local peer on confirm").option("--ticket <ticket>", "One-time pairing ticket (clwpair1_...)").option("--wait", "Poll until ticket is confirmed or timeout is reached").option(
|
|
23603
|
+
"--wait-seconds <seconds>",
|
|
23604
|
+
"Max seconds to poll for confirmation (default: 300)"
|
|
23605
|
+
).option(
|
|
23606
|
+
"--poll-interval-seconds <seconds>",
|
|
23607
|
+
"Polling interval in seconds while waiting (default: 3)"
|
|
23608
|
+
).action(
|
|
23609
|
+
withErrorHandling(
|
|
23610
|
+
"pair status",
|
|
23611
|
+
async (agentName, options) => {
|
|
23612
|
+
const result = await getPairingStatus(agentName, options, dependencies);
|
|
23613
|
+
logger9.info("cli.pair_status", {
|
|
23614
|
+
initiatorAgentDid: result.initiatorAgentDid,
|
|
23615
|
+
responderAgentDid: result.responderAgentDid,
|
|
23616
|
+
status: result.status,
|
|
23617
|
+
proxyUrl: result.proxyUrl,
|
|
23618
|
+
peerAlias: result.peerAlias
|
|
23619
|
+
});
|
|
23620
|
+
writeStdoutLine(`Status: ${result.status}`);
|
|
23621
|
+
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
23622
|
+
if (result.responderAgentDid) {
|
|
23623
|
+
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
23624
|
+
}
|
|
23625
|
+
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
23626
|
+
if (result.confirmedAt) {
|
|
23627
|
+
writeStdoutLine(`Confirmed At: ${result.confirmedAt}`);
|
|
23628
|
+
}
|
|
23629
|
+
if (result.peerAlias) {
|
|
23630
|
+
writeStdoutLine(`Peer alias saved: ${result.peerAlias}`);
|
|
23631
|
+
}
|
|
23632
|
+
}
|
|
23633
|
+
)
|
|
23634
|
+
);
|
|
23290
23635
|
return pairCommand;
|
|
23291
23636
|
};
|
|
23292
23637
|
|
package/dist/postinstall.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawdentity",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -21,6 +21,17 @@
|
|
|
21
21
|
"postinstall.mjs",
|
|
22
22
|
"skill-bundle"
|
|
23
23
|
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "pnpm -F @clawdentity/openclaw-skill build && pnpm run sync:skill-bundle && pnpm run verify:skill-bundle && tsup",
|
|
26
|
+
"format": "biome format .",
|
|
27
|
+
"lint": "biome lint .",
|
|
28
|
+
"prepack": "pnpm run build",
|
|
29
|
+
"postinstall": "node ./postinstall.mjs",
|
|
30
|
+
"sync:skill-bundle": "node ./scripts/sync-skill-bundle.mjs",
|
|
31
|
+
"verify:skill-bundle": "node ./scripts/verify-skill-bundle.mjs",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"typecheck": "tsc --noEmit"
|
|
34
|
+
},
|
|
24
35
|
"dependencies": {
|
|
25
36
|
"commander": "^13.1.0",
|
|
26
37
|
"jsqr": "^1.4.0",
|
|
@@ -29,21 +40,11 @@
|
|
|
29
40
|
"ws": "^8.19.0"
|
|
30
41
|
},
|
|
31
42
|
"devDependencies": {
|
|
43
|
+
"@clawdentity/connector": "workspace:*",
|
|
44
|
+
"@clawdentity/protocol": "workspace:*",
|
|
45
|
+
"@clawdentity/sdk": "workspace:*",
|
|
32
46
|
"@types/node": "^22.18.11",
|
|
33
47
|
"@types/pngjs": "^6.0.5",
|
|
34
|
-
"@types/qrcode": "^1.5.6"
|
|
35
|
-
"@clawdentity/connector": "0.0.0",
|
|
36
|
-
"@clawdentity/protocol": "0.0.0",
|
|
37
|
-
"@clawdentity/sdk": "0.0.0"
|
|
38
|
-
},
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "pnpm -F @clawdentity/openclaw-skill build && pnpm run sync:skill-bundle && pnpm run verify:skill-bundle && tsup",
|
|
41
|
-
"format": "biome format .",
|
|
42
|
-
"lint": "biome lint .",
|
|
43
|
-
"postinstall": "node ./postinstall.mjs",
|
|
44
|
-
"sync:skill-bundle": "node ./scripts/sync-skill-bundle.mjs",
|
|
45
|
-
"verify:skill-bundle": "node ./scripts/verify-skill-bundle.mjs",
|
|
46
|
-
"test": "vitest run",
|
|
47
|
-
"typecheck": "tsc --noEmit"
|
|
48
|
+
"@types/qrcode": "^1.5.6"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|