clawdentity 0.0.17 → 0.0.18
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 +233 -17
- package/dist/index.js +233 -17
- package/dist/postinstall.js +0 -0
- package/package.json +16 -17
- package/skill-bundle/openclaw-skill/dist/relay-to-peer.mjs +6 -5
- package/skill-bundle/openclaw-skill/skill/SKILL.md +16 -3
- package/skill-bundle/openclaw-skill/skill/references/clawdentity-protocol.md +17 -6
package/dist/bin.js
CHANGED
|
@@ -17084,7 +17084,8 @@ var FILE_MODE = 384;
|
|
|
17084
17084
|
var ENV_KEY_MAP = {
|
|
17085
17085
|
registryUrl: "CLAWDENTITY_REGISTRY_URL",
|
|
17086
17086
|
proxyUrl: "CLAWDENTITY_PROXY_URL",
|
|
17087
|
-
apiKey: "CLAWDENTITY_API_KEY"
|
|
17087
|
+
apiKey: "CLAWDENTITY_API_KEY",
|
|
17088
|
+
humanName: "CLAWDENTITY_HUMAN_NAME"
|
|
17088
17089
|
};
|
|
17089
17090
|
var LEGACY_ENV_KEY_MAP = {
|
|
17090
17091
|
registryUrl: ["CLAWDENTITY_REGISTRY"]
|
|
@@ -17111,6 +17112,9 @@ var normalizeConfig = (raw) => {
|
|
|
17111
17112
|
if (typeof raw.apiKey === "string" && raw.apiKey.length > 0) {
|
|
17112
17113
|
config2.apiKey = raw.apiKey;
|
|
17113
17114
|
}
|
|
17115
|
+
if (typeof raw.humanName === "string" && raw.humanName.length > 0) {
|
|
17116
|
+
config2.humanName = raw.humanName;
|
|
17117
|
+
}
|
|
17114
17118
|
return config2;
|
|
17115
17119
|
};
|
|
17116
17120
|
var getConfigDir = () => join2(homedir(), CONFIG_DIR);
|
|
@@ -18536,7 +18540,8 @@ var logger5 = createLogger({ service: "cli", module: "config" });
|
|
|
18536
18540
|
var VALID_KEYS = [
|
|
18537
18541
|
"registryUrl",
|
|
18538
18542
|
"proxyUrl",
|
|
18539
|
-
"apiKey"
|
|
18543
|
+
"apiKey",
|
|
18544
|
+
"humanName"
|
|
18540
18545
|
];
|
|
18541
18546
|
var isValidConfigKey = (value) => {
|
|
18542
18547
|
return VALID_KEYS.includes(value);
|
|
@@ -20862,11 +20867,20 @@ function parseInviteRedeemResponse(payload) {
|
|
|
20862
20867
|
}
|
|
20863
20868
|
const apiKeyId = parseNonEmptyString7(apiKeySource.id);
|
|
20864
20869
|
const apiKeyName = parseNonEmptyString7(apiKeySource.name);
|
|
20870
|
+
const humanSource = isRecord7(payload.human) ? payload.human : void 0;
|
|
20871
|
+
const humanName = parseNonEmptyString7(humanSource?.displayName);
|
|
20865
20872
|
const proxyUrl = parseNonEmptyString7(payload.proxyUrl);
|
|
20873
|
+
if (humanName.length === 0) {
|
|
20874
|
+
throw createCliError5(
|
|
20875
|
+
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20876
|
+
"Invite redeem response is invalid"
|
|
20877
|
+
);
|
|
20878
|
+
}
|
|
20866
20879
|
return {
|
|
20867
20880
|
apiKeyToken,
|
|
20868
20881
|
apiKeyId: apiKeyId.length > 0 ? apiKeyId : void 0,
|
|
20869
20882
|
apiKeyName: apiKeyName.length > 0 ? apiKeyName : void 0,
|
|
20883
|
+
humanName,
|
|
20870
20884
|
proxyUrl
|
|
20871
20885
|
};
|
|
20872
20886
|
}
|
|
@@ -20921,6 +20935,14 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20921
20935
|
"Invite code is required"
|
|
20922
20936
|
);
|
|
20923
20937
|
}
|
|
20938
|
+
const displayName = parseNonEmptyString7(options.displayName);
|
|
20939
|
+
if (displayName.length === 0) {
|
|
20940
|
+
throw createCliError5(
|
|
20941
|
+
"CLI_INVITE_REDEEM_DISPLAY_NAME_REQUIRED",
|
|
20942
|
+
"Display name is required. Pass --display-name <name>."
|
|
20943
|
+
);
|
|
20944
|
+
}
|
|
20945
|
+
const apiKeyName = parseNonEmptyString7(options.apiKeyName);
|
|
20924
20946
|
const runtime = await resolveInviteRuntime(options.registryUrl, dependencies);
|
|
20925
20947
|
const response = await executeInviteRequest({
|
|
20926
20948
|
fetchImpl: runtime.fetchImpl,
|
|
@@ -20930,7 +20952,11 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20930
20952
|
headers: {
|
|
20931
20953
|
"content-type": "application/json"
|
|
20932
20954
|
},
|
|
20933
|
-
body: JSON.stringify({
|
|
20955
|
+
body: JSON.stringify({
|
|
20956
|
+
code: inviteCode,
|
|
20957
|
+
displayName,
|
|
20958
|
+
apiKeyName: apiKeyName.length > 0 ? apiKeyName : void 0
|
|
20959
|
+
})
|
|
20934
20960
|
}
|
|
20935
20961
|
});
|
|
20936
20962
|
const responseBody = await parseJsonResponse5(response);
|
|
@@ -20950,12 +20976,13 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20950
20976
|
registryUrl: runtime.registryUrl
|
|
20951
20977
|
};
|
|
20952
20978
|
}
|
|
20953
|
-
async function persistRedeemConfig(registryUrl, apiKeyToken, proxyUrl, dependencies = {}) {
|
|
20979
|
+
async function persistRedeemConfig(registryUrl, apiKeyToken, proxyUrl, humanName, dependencies = {}) {
|
|
20954
20980
|
const setConfigValueImpl = dependencies.setConfigValueImpl ?? setConfigValue;
|
|
20955
20981
|
try {
|
|
20956
20982
|
await setConfigValueImpl("registryUrl", registryUrl);
|
|
20957
20983
|
await setConfigValueImpl("apiKey", apiKeyToken);
|
|
20958
20984
|
await setConfigValueImpl("proxyUrl", proxyUrl);
|
|
20985
|
+
await setConfigValueImpl("humanName", humanName);
|
|
20959
20986
|
} catch (error48) {
|
|
20960
20987
|
logger7.warn("cli.invite_redeem_config_persist_failed", {
|
|
20961
20988
|
errorName: error48 instanceof Error ? error48.name : "unknown"
|
|
@@ -20989,7 +21016,10 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20989
21016
|
}
|
|
20990
21017
|
)
|
|
20991
21018
|
);
|
|
20992
|
-
inviteCommand.command("redeem <code>").description("Redeem a registry invite code and store PAT locally").
|
|
21019
|
+
inviteCommand.command("redeem <code>").description("Redeem a registry invite code and store PAT locally").requiredOption(
|
|
21020
|
+
"--display-name <name>",
|
|
21021
|
+
"Human display name used for onboarding"
|
|
21022
|
+
).option("--api-key-name <name>", "Optional API key label").option("--registry-url <url>", "Override registry URL").action(
|
|
20993
21023
|
withErrorHandling(
|
|
20994
21024
|
"invite redeem",
|
|
20995
21025
|
async (code, options) => {
|
|
@@ -20997,9 +21027,11 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20997
21027
|
logger7.info("cli.invite_redeemed", {
|
|
20998
21028
|
apiKeyId: result.apiKeyId,
|
|
20999
21029
|
apiKeyName: result.apiKeyName,
|
|
21030
|
+
humanName: result.humanName,
|
|
21000
21031
|
registryUrl: result.registryUrl
|
|
21001
21032
|
});
|
|
21002
21033
|
writeStdoutLine("Invite redeemed");
|
|
21034
|
+
writeStdoutLine(`Human name: ${result.humanName}`);
|
|
21003
21035
|
if (result.apiKeyName) {
|
|
21004
21036
|
writeStdoutLine(`API key name: ${result.apiKeyName}`);
|
|
21005
21037
|
}
|
|
@@ -21009,6 +21041,7 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
21009
21041
|
result.registryUrl,
|
|
21010
21042
|
result.apiKeyToken,
|
|
21011
21043
|
result.proxyUrl,
|
|
21044
|
+
result.humanName,
|
|
21012
21045
|
dependencies
|
|
21013
21046
|
);
|
|
21014
21047
|
writeStdoutLine("API key saved to local config");
|
|
@@ -21113,11 +21146,11 @@ function parseNonEmptyString8(value, label) {
|
|
|
21113
21146
|
}
|
|
21114
21147
|
return trimmed;
|
|
21115
21148
|
}
|
|
21116
|
-
function
|
|
21149
|
+
function parseOptionalProfileName(value, label) {
|
|
21117
21150
|
if (value === void 0) {
|
|
21118
21151
|
return void 0;
|
|
21119
21152
|
}
|
|
21120
|
-
return parseNonEmptyString8(value,
|
|
21153
|
+
return parseNonEmptyString8(value, label);
|
|
21121
21154
|
}
|
|
21122
21155
|
function parsePeerAlias(value) {
|
|
21123
21156
|
const alias = parseNonEmptyString8(value, "peer alias");
|
|
@@ -21374,12 +21407,13 @@ async function loadPeersConfig(peersPath) {
|
|
|
21374
21407
|
}
|
|
21375
21408
|
const did = parseAgentDid2(value.did, `Peer ${normalizedAlias} did`);
|
|
21376
21409
|
const proxyUrl = parseProxyUrl(value.proxyUrl);
|
|
21377
|
-
const
|
|
21378
|
-
|
|
21410
|
+
const agentName = parseOptionalProfileName(value.agentName, "agentName");
|
|
21411
|
+
const humanName = parseOptionalProfileName(value.humanName, "humanName");
|
|
21412
|
+
if (agentName === void 0 && humanName === void 0) {
|
|
21379
21413
|
peers[normalizedAlias] = { did, proxyUrl };
|
|
21380
21414
|
continue;
|
|
21381
21415
|
}
|
|
21382
|
-
peers[normalizedAlias] = { did, proxyUrl,
|
|
21416
|
+
peers[normalizedAlias] = { did, proxyUrl, agentName, humanName };
|
|
21383
21417
|
}
|
|
21384
21418
|
return { peers };
|
|
21385
21419
|
}
|
|
@@ -22978,6 +23012,7 @@ var FILE_MODE4 = 384;
|
|
|
22978
23012
|
var PEER_ALIAS_PATTERN2 = /^[a-zA-Z0-9._-]+$/;
|
|
22979
23013
|
var DEFAULT_STATUS_WAIT_SECONDS = 300;
|
|
22980
23014
|
var DEFAULT_STATUS_POLL_INTERVAL_SECONDS = 3;
|
|
23015
|
+
var MAX_PROFILE_NAME_LENGTH = 64;
|
|
22981
23016
|
var isRecord9 = (value) => {
|
|
22982
23017
|
return typeof value === "object" && value !== null;
|
|
22983
23018
|
};
|
|
@@ -22994,6 +23029,49 @@ function parseNonEmptyString9(value) {
|
|
|
22994
23029
|
}
|
|
22995
23030
|
return value.trim();
|
|
22996
23031
|
}
|
|
23032
|
+
function hasControlChars2(value) {
|
|
23033
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
23034
|
+
const code = value.charCodeAt(index);
|
|
23035
|
+
if (code <= 31 || code === 127) {
|
|
23036
|
+
return true;
|
|
23037
|
+
}
|
|
23038
|
+
}
|
|
23039
|
+
return false;
|
|
23040
|
+
}
|
|
23041
|
+
function parseProfileName(value, label) {
|
|
23042
|
+
const candidate = parseNonEmptyString9(value);
|
|
23043
|
+
if (candidate.length === 0) {
|
|
23044
|
+
throw createCliError7(
|
|
23045
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23046
|
+
`${label} is required for pairing`
|
|
23047
|
+
);
|
|
23048
|
+
}
|
|
23049
|
+
if (candidate.length > MAX_PROFILE_NAME_LENGTH) {
|
|
23050
|
+
throw createCliError7(
|
|
23051
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23052
|
+
`${label} must be at most ${MAX_PROFILE_NAME_LENGTH} characters`
|
|
23053
|
+
);
|
|
23054
|
+
}
|
|
23055
|
+
if (hasControlChars2(candidate)) {
|
|
23056
|
+
throw createCliError7(
|
|
23057
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23058
|
+
`${label} contains control characters`
|
|
23059
|
+
);
|
|
23060
|
+
}
|
|
23061
|
+
return candidate;
|
|
23062
|
+
}
|
|
23063
|
+
function parsePeerProfile(payload) {
|
|
23064
|
+
if (!isRecord9(payload)) {
|
|
23065
|
+
throw createCliError7(
|
|
23066
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23067
|
+
"Pair profile must be an object"
|
|
23068
|
+
);
|
|
23069
|
+
}
|
|
23070
|
+
return {
|
|
23071
|
+
agentName: parseProfileName(payload.agentName, "agentName"),
|
|
23072
|
+
humanName: parseProfileName(payload.humanName, "humanName")
|
|
23073
|
+
};
|
|
23074
|
+
}
|
|
22997
23075
|
function parsePairingTicket(value) {
|
|
22998
23076
|
const ticket = parseNonEmptyString9(value);
|
|
22999
23077
|
if (!ticket.startsWith(PAIRING_TICKET_PREFIX)) {
|
|
@@ -23158,10 +23236,19 @@ function parsePeerEntry(value) {
|
|
|
23158
23236
|
"Peer entry is invalid"
|
|
23159
23237
|
);
|
|
23160
23238
|
}
|
|
23161
|
-
|
|
23239
|
+
const agentNameRaw = parseNonEmptyString9(value.agentName);
|
|
23240
|
+
const humanNameRaw = parseNonEmptyString9(value.humanName);
|
|
23241
|
+
const entry = {
|
|
23162
23242
|
did,
|
|
23163
23243
|
proxyUrl
|
|
23164
23244
|
};
|
|
23245
|
+
if (agentNameRaw.length > 0) {
|
|
23246
|
+
entry.agentName = parseProfileName(agentNameRaw, "agentName");
|
|
23247
|
+
}
|
|
23248
|
+
if (humanNameRaw.length > 0) {
|
|
23249
|
+
entry.humanName = parseProfileName(humanNameRaw, "humanName");
|
|
23250
|
+
}
|
|
23251
|
+
return entry;
|
|
23165
23252
|
}
|
|
23166
23253
|
async function loadPeersConfig2(input) {
|
|
23167
23254
|
const peersPath = resolvePeersConfigPath(input.getConfigDirImpl);
|
|
@@ -23244,6 +23331,19 @@ function parsePositiveIntegerOption(input) {
|
|
|
23244
23331
|
}
|
|
23245
23332
|
return parsed;
|
|
23246
23333
|
}
|
|
23334
|
+
function resolveLocalPairProfile(input) {
|
|
23335
|
+
const humanName = parseNonEmptyString9(input.config.humanName);
|
|
23336
|
+
if (humanName.length === 0) {
|
|
23337
|
+
throw createCliError7(
|
|
23338
|
+
"CLI_PAIR_HUMAN_NAME_MISSING",
|
|
23339
|
+
"Human name is missing. Run `clawdentity invite redeem <clw_inv_...> --display-name <name>` or `clawdentity config set humanName <name>`."
|
|
23340
|
+
);
|
|
23341
|
+
}
|
|
23342
|
+
return {
|
|
23343
|
+
agentName: parseProfileName(input.agentName, "agentName"),
|
|
23344
|
+
humanName: parseProfileName(humanName, "humanName")
|
|
23345
|
+
};
|
|
23346
|
+
}
|
|
23247
23347
|
function parseProxyUrl2(candidate) {
|
|
23248
23348
|
try {
|
|
23249
23349
|
const parsed = new URL(candidate);
|
|
@@ -23394,15 +23494,25 @@ function parsePairStartResponse(payload) {
|
|
|
23394
23494
|
const ticket = parsePairingTicket(payload.ticket);
|
|
23395
23495
|
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
23396
23496
|
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
23497
|
+
let initiatorProfile;
|
|
23397
23498
|
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
23398
23499
|
throw createCliError7(
|
|
23399
23500
|
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
23400
23501
|
"Pair start response is invalid"
|
|
23401
23502
|
);
|
|
23402
23503
|
}
|
|
23504
|
+
try {
|
|
23505
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23506
|
+
} catch {
|
|
23507
|
+
throw createCliError7(
|
|
23508
|
+
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
23509
|
+
"Pair start response is invalid"
|
|
23510
|
+
);
|
|
23511
|
+
}
|
|
23403
23512
|
return {
|
|
23404
23513
|
ticket,
|
|
23405
23514
|
initiatorAgentDid,
|
|
23515
|
+
initiatorProfile,
|
|
23406
23516
|
expiresAt
|
|
23407
23517
|
};
|
|
23408
23518
|
}
|
|
@@ -23416,16 +23526,29 @@ function parsePairConfirmResponse(payload) {
|
|
|
23416
23526
|
const paired = payload.paired === true;
|
|
23417
23527
|
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
23418
23528
|
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
23529
|
+
let initiatorProfile;
|
|
23530
|
+
let responderProfile;
|
|
23419
23531
|
if (!paired || initiatorAgentDid.length === 0 || responderAgentDid.length === 0) {
|
|
23420
23532
|
throw createCliError7(
|
|
23421
23533
|
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
23422
23534
|
"Pair confirm response is invalid"
|
|
23423
23535
|
);
|
|
23424
23536
|
}
|
|
23537
|
+
try {
|
|
23538
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23539
|
+
responderProfile = parsePeerProfile(payload.responderProfile);
|
|
23540
|
+
} catch {
|
|
23541
|
+
throw createCliError7(
|
|
23542
|
+
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
23543
|
+
"Pair confirm response is invalid"
|
|
23544
|
+
);
|
|
23545
|
+
}
|
|
23425
23546
|
return {
|
|
23426
23547
|
paired,
|
|
23427
23548
|
initiatorAgentDid,
|
|
23428
|
-
responderAgentDid
|
|
23549
|
+
responderAgentDid,
|
|
23550
|
+
initiatorProfile,
|
|
23551
|
+
responderProfile
|
|
23429
23552
|
};
|
|
23430
23553
|
}
|
|
23431
23554
|
function parsePairStatusResponse(payload) {
|
|
@@ -23446,6 +23569,7 @@ function parsePairStatusResponse(payload) {
|
|
|
23446
23569
|
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
23447
23570
|
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
23448
23571
|
const confirmedAt = parseNonEmptyString9(payload.confirmedAt);
|
|
23572
|
+
let initiatorProfile;
|
|
23449
23573
|
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
23450
23574
|
throw createCliError7(
|
|
23451
23575
|
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
@@ -23458,10 +23582,37 @@ function parsePairStatusResponse(payload) {
|
|
|
23458
23582
|
"Pair status response is invalid"
|
|
23459
23583
|
);
|
|
23460
23584
|
}
|
|
23585
|
+
try {
|
|
23586
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23587
|
+
} catch {
|
|
23588
|
+
throw createCliError7(
|
|
23589
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23590
|
+
"Pair status response is invalid"
|
|
23591
|
+
);
|
|
23592
|
+
}
|
|
23593
|
+
let responderProfile;
|
|
23594
|
+
if (payload.responderProfile !== void 0) {
|
|
23595
|
+
try {
|
|
23596
|
+
responderProfile = parsePeerProfile(payload.responderProfile);
|
|
23597
|
+
} catch {
|
|
23598
|
+
throw createCliError7(
|
|
23599
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23600
|
+
"Pair status response is invalid"
|
|
23601
|
+
);
|
|
23602
|
+
}
|
|
23603
|
+
}
|
|
23604
|
+
if (statusRaw === "confirmed" && responderProfile === void 0) {
|
|
23605
|
+
throw createCliError7(
|
|
23606
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23607
|
+
"Pair status response is invalid"
|
|
23608
|
+
);
|
|
23609
|
+
}
|
|
23461
23610
|
return {
|
|
23462
23611
|
status: statusRaw,
|
|
23463
23612
|
initiatorAgentDid,
|
|
23613
|
+
initiatorProfile,
|
|
23464
23614
|
responderAgentDid: responderAgentDid.length > 0 ? responderAgentDid : void 0,
|
|
23615
|
+
responderProfile,
|
|
23465
23616
|
expiresAt,
|
|
23466
23617
|
confirmedAt: confirmedAt.length > 0 ? confirmedAt : void 0
|
|
23467
23618
|
};
|
|
@@ -23666,7 +23817,9 @@ async function persistPairedPeer(input) {
|
|
|
23666
23817
|
});
|
|
23667
23818
|
peersConfig.peers[alias] = {
|
|
23668
23819
|
did: input.peerDid,
|
|
23669
|
-
proxyUrl: peerProxyUrl
|
|
23820
|
+
proxyUrl: peerProxyUrl,
|
|
23821
|
+
agentName: input.peerProfile.agentName,
|
|
23822
|
+
humanName: input.peerProfile.humanName
|
|
23670
23823
|
};
|
|
23671
23824
|
await savePeersConfig2({
|
|
23672
23825
|
config: peersConfig,
|
|
@@ -23688,13 +23841,19 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
23688
23841
|
config: config2,
|
|
23689
23842
|
fetchImpl
|
|
23690
23843
|
});
|
|
23844
|
+
const normalizedAgentName = assertValidAgentName(agentName);
|
|
23845
|
+
const initiatorProfile = resolveLocalPairProfile({
|
|
23846
|
+
config: config2,
|
|
23847
|
+
agentName: normalizedAgentName
|
|
23848
|
+
});
|
|
23691
23849
|
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23692
|
-
|
|
23850
|
+
normalizedAgentName,
|
|
23693
23851
|
dependencies
|
|
23694
23852
|
);
|
|
23695
23853
|
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_START_PATH);
|
|
23696
23854
|
const requestBody = JSON.stringify({
|
|
23697
|
-
ttlSeconds
|
|
23855
|
+
ttlSeconds,
|
|
23856
|
+
initiatorProfile
|
|
23698
23857
|
});
|
|
23699
23858
|
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23700
23859
|
const timestampSeconds = nowSecondsImpl();
|
|
@@ -23751,6 +23910,11 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23751
23910
|
const readFileImpl = dependencies.readFileImpl ?? readFile6;
|
|
23752
23911
|
const qrDecodeImpl = dependencies.qrDecodeImpl ?? decodeTicketFromPng;
|
|
23753
23912
|
const config2 = await resolveConfigImpl();
|
|
23913
|
+
const normalizedAgentName = assertValidAgentName(agentName);
|
|
23914
|
+
const responderProfile = resolveLocalPairProfile({
|
|
23915
|
+
config: config2,
|
|
23916
|
+
agentName: normalizedAgentName
|
|
23917
|
+
});
|
|
23754
23918
|
const ticketSource = resolveConfirmTicketSource(options);
|
|
23755
23919
|
const proxyUrl = await resolveProxyUrl({
|
|
23756
23920
|
config: config2,
|
|
@@ -23780,11 +23944,14 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23780
23944
|
ticket = parsePairingTicket(qrDecodeImpl(new Uint8Array(imageBytes)));
|
|
23781
23945
|
}
|
|
23782
23946
|
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23783
|
-
|
|
23947
|
+
normalizedAgentName,
|
|
23784
23948
|
dependencies
|
|
23785
23949
|
);
|
|
23786
23950
|
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_CONFIRM_PATH);
|
|
23787
|
-
const requestBody = JSON.stringify({
|
|
23951
|
+
const requestBody = JSON.stringify({
|
|
23952
|
+
ticket,
|
|
23953
|
+
responderProfile
|
|
23954
|
+
});
|
|
23788
23955
|
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23789
23956
|
const timestampSeconds = nowSecondsImpl();
|
|
23790
23957
|
const nonce = nonceFactoryImpl();
|
|
@@ -23820,6 +23987,7 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23820
23987
|
const peerAlias = await persistPairedPeer({
|
|
23821
23988
|
ticket,
|
|
23822
23989
|
peerDid: parsed.initiatorAgentDid,
|
|
23990
|
+
peerProfile: parsed.initiatorProfile,
|
|
23823
23991
|
dependencies
|
|
23824
23992
|
});
|
|
23825
23993
|
if (ticketSource.source === "qr-file" && ticketSource.qrFilePath) {
|
|
@@ -23901,15 +24069,23 @@ async function getPairingStatusOnce(agentName, options, dependencies = {}) {
|
|
|
23901
24069
|
);
|
|
23902
24070
|
}
|
|
23903
24071
|
const peerDid = callerAgentDid === parsed.initiatorAgentDid ? responderAgentDid : callerAgentDid === responderAgentDid ? parsed.initiatorAgentDid : void 0;
|
|
24072
|
+
const peerProfile = callerAgentDid === parsed.initiatorAgentDid ? parsed.responderProfile : callerAgentDid === responderAgentDid ? parsed.initiatorProfile : void 0;
|
|
23904
24073
|
if (!peerDid) {
|
|
23905
24074
|
throw createCliError7(
|
|
23906
24075
|
"CLI_PAIR_STATUS_FORBIDDEN",
|
|
23907
24076
|
"Local agent is not a participant in the pairing ticket"
|
|
23908
24077
|
);
|
|
23909
24078
|
}
|
|
24079
|
+
if (!peerProfile) {
|
|
24080
|
+
throw createCliError7(
|
|
24081
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
24082
|
+
"Pair status response is invalid"
|
|
24083
|
+
);
|
|
24084
|
+
}
|
|
23910
24085
|
peerAlias = await persistPairedPeer({
|
|
23911
24086
|
ticket,
|
|
23912
24087
|
peerDid,
|
|
24088
|
+
peerProfile,
|
|
23913
24089
|
dependencies
|
|
23914
24090
|
});
|
|
23915
24091
|
}
|
|
@@ -24005,6 +24181,12 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24005
24181
|
writeStdoutLine("Pairing ticket created");
|
|
24006
24182
|
writeStdoutLine(`Ticket: ${result.ticket}`);
|
|
24007
24183
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24184
|
+
writeStdoutLine(
|
|
24185
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24186
|
+
);
|
|
24187
|
+
writeStdoutLine(
|
|
24188
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24189
|
+
);
|
|
24008
24190
|
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
24009
24191
|
if (result.qrPath) {
|
|
24010
24192
|
writeStdoutLine(`QR File: ${result.qrPath}`);
|
|
@@ -24047,6 +24229,14 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24047
24229
|
`Responder Agent DID: ${status.responderAgentDid}`
|
|
24048
24230
|
);
|
|
24049
24231
|
}
|
|
24232
|
+
if (status.responderProfile) {
|
|
24233
|
+
writeStdoutLine(
|
|
24234
|
+
`Responder Agent Name: ${status.responderProfile.agentName}`
|
|
24235
|
+
);
|
|
24236
|
+
writeStdoutLine(
|
|
24237
|
+
`Responder Human Name: ${status.responderProfile.humanName}`
|
|
24238
|
+
);
|
|
24239
|
+
}
|
|
24050
24240
|
if (status.peerAlias) {
|
|
24051
24241
|
writeStdoutLine(`Peer alias saved: ${status.peerAlias}`);
|
|
24052
24242
|
}
|
|
@@ -24067,7 +24257,19 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24067
24257
|
});
|
|
24068
24258
|
writeStdoutLine("Pairing confirmed");
|
|
24069
24259
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24260
|
+
writeStdoutLine(
|
|
24261
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24262
|
+
);
|
|
24263
|
+
writeStdoutLine(
|
|
24264
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24265
|
+
);
|
|
24070
24266
|
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
24267
|
+
writeStdoutLine(
|
|
24268
|
+
`Responder Agent Name: ${result.responderProfile.agentName}`
|
|
24269
|
+
);
|
|
24270
|
+
writeStdoutLine(
|
|
24271
|
+
`Responder Human Name: ${result.responderProfile.humanName}`
|
|
24272
|
+
);
|
|
24071
24273
|
writeStdoutLine(`Paired: ${result.paired ? "true" : "false"}`);
|
|
24072
24274
|
if (result.peerAlias) {
|
|
24073
24275
|
writeStdoutLine(`Peer alias saved: ${result.peerAlias}`);
|
|
@@ -24099,9 +24301,23 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24099
24301
|
});
|
|
24100
24302
|
writeStdoutLine(`Status: ${result.status}`);
|
|
24101
24303
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24304
|
+
writeStdoutLine(
|
|
24305
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24306
|
+
);
|
|
24307
|
+
writeStdoutLine(
|
|
24308
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24309
|
+
);
|
|
24102
24310
|
if (result.responderAgentDid) {
|
|
24103
24311
|
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
24104
24312
|
}
|
|
24313
|
+
if (result.responderProfile) {
|
|
24314
|
+
writeStdoutLine(
|
|
24315
|
+
`Responder Agent Name: ${result.responderProfile.agentName}`
|
|
24316
|
+
);
|
|
24317
|
+
writeStdoutLine(
|
|
24318
|
+
`Responder Human Name: ${result.responderProfile.humanName}`
|
|
24319
|
+
);
|
|
24320
|
+
}
|
|
24105
24321
|
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
24106
24322
|
if (result.confirmedAt) {
|
|
24107
24323
|
writeStdoutLine(`Confirmed At: ${result.confirmedAt}`);
|
package/dist/index.js
CHANGED
|
@@ -17084,7 +17084,8 @@ var FILE_MODE = 384;
|
|
|
17084
17084
|
var ENV_KEY_MAP = {
|
|
17085
17085
|
registryUrl: "CLAWDENTITY_REGISTRY_URL",
|
|
17086
17086
|
proxyUrl: "CLAWDENTITY_PROXY_URL",
|
|
17087
|
-
apiKey: "CLAWDENTITY_API_KEY"
|
|
17087
|
+
apiKey: "CLAWDENTITY_API_KEY",
|
|
17088
|
+
humanName: "CLAWDENTITY_HUMAN_NAME"
|
|
17088
17089
|
};
|
|
17089
17090
|
var LEGACY_ENV_KEY_MAP = {
|
|
17090
17091
|
registryUrl: ["CLAWDENTITY_REGISTRY"]
|
|
@@ -17111,6 +17112,9 @@ var normalizeConfig = (raw) => {
|
|
|
17111
17112
|
if (typeof raw.apiKey === "string" && raw.apiKey.length > 0) {
|
|
17112
17113
|
config2.apiKey = raw.apiKey;
|
|
17113
17114
|
}
|
|
17115
|
+
if (typeof raw.humanName === "string" && raw.humanName.length > 0) {
|
|
17116
|
+
config2.humanName = raw.humanName;
|
|
17117
|
+
}
|
|
17114
17118
|
return config2;
|
|
17115
17119
|
};
|
|
17116
17120
|
var getConfigDir = () => join2(homedir(), CONFIG_DIR);
|
|
@@ -18536,7 +18540,8 @@ var logger5 = createLogger({ service: "cli", module: "config" });
|
|
|
18536
18540
|
var VALID_KEYS = [
|
|
18537
18541
|
"registryUrl",
|
|
18538
18542
|
"proxyUrl",
|
|
18539
|
-
"apiKey"
|
|
18543
|
+
"apiKey",
|
|
18544
|
+
"humanName"
|
|
18540
18545
|
];
|
|
18541
18546
|
var isValidConfigKey = (value) => {
|
|
18542
18547
|
return VALID_KEYS.includes(value);
|
|
@@ -20862,11 +20867,20 @@ function parseInviteRedeemResponse(payload) {
|
|
|
20862
20867
|
}
|
|
20863
20868
|
const apiKeyId = parseNonEmptyString7(apiKeySource.id);
|
|
20864
20869
|
const apiKeyName = parseNonEmptyString7(apiKeySource.name);
|
|
20870
|
+
const humanSource = isRecord7(payload.human) ? payload.human : void 0;
|
|
20871
|
+
const humanName = parseNonEmptyString7(humanSource?.displayName);
|
|
20865
20872
|
const proxyUrl = parseNonEmptyString7(payload.proxyUrl);
|
|
20873
|
+
if (humanName.length === 0) {
|
|
20874
|
+
throw createCliError5(
|
|
20875
|
+
"CLI_INVITE_REDEEM_INVALID_RESPONSE",
|
|
20876
|
+
"Invite redeem response is invalid"
|
|
20877
|
+
);
|
|
20878
|
+
}
|
|
20866
20879
|
return {
|
|
20867
20880
|
apiKeyToken,
|
|
20868
20881
|
apiKeyId: apiKeyId.length > 0 ? apiKeyId : void 0,
|
|
20869
20882
|
apiKeyName: apiKeyName.length > 0 ? apiKeyName : void 0,
|
|
20883
|
+
humanName,
|
|
20870
20884
|
proxyUrl
|
|
20871
20885
|
};
|
|
20872
20886
|
}
|
|
@@ -20921,6 +20935,14 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20921
20935
|
"Invite code is required"
|
|
20922
20936
|
);
|
|
20923
20937
|
}
|
|
20938
|
+
const displayName = parseNonEmptyString7(options.displayName);
|
|
20939
|
+
if (displayName.length === 0) {
|
|
20940
|
+
throw createCliError5(
|
|
20941
|
+
"CLI_INVITE_REDEEM_DISPLAY_NAME_REQUIRED",
|
|
20942
|
+
"Display name is required. Pass --display-name <name>."
|
|
20943
|
+
);
|
|
20944
|
+
}
|
|
20945
|
+
const apiKeyName = parseNonEmptyString7(options.apiKeyName);
|
|
20924
20946
|
const runtime = await resolveInviteRuntime(options.registryUrl, dependencies);
|
|
20925
20947
|
const response = await executeInviteRequest({
|
|
20926
20948
|
fetchImpl: runtime.fetchImpl,
|
|
@@ -20930,7 +20952,11 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20930
20952
|
headers: {
|
|
20931
20953
|
"content-type": "application/json"
|
|
20932
20954
|
},
|
|
20933
|
-
body: JSON.stringify({
|
|
20955
|
+
body: JSON.stringify({
|
|
20956
|
+
code: inviteCode,
|
|
20957
|
+
displayName,
|
|
20958
|
+
apiKeyName: apiKeyName.length > 0 ? apiKeyName : void 0
|
|
20959
|
+
})
|
|
20934
20960
|
}
|
|
20935
20961
|
});
|
|
20936
20962
|
const responseBody = await parseJsonResponse5(response);
|
|
@@ -20950,12 +20976,13 @@ async function redeemInvite(code, options, dependencies = {}) {
|
|
|
20950
20976
|
registryUrl: runtime.registryUrl
|
|
20951
20977
|
};
|
|
20952
20978
|
}
|
|
20953
|
-
async function persistRedeemConfig(registryUrl, apiKeyToken, proxyUrl, dependencies = {}) {
|
|
20979
|
+
async function persistRedeemConfig(registryUrl, apiKeyToken, proxyUrl, humanName, dependencies = {}) {
|
|
20954
20980
|
const setConfigValueImpl = dependencies.setConfigValueImpl ?? setConfigValue;
|
|
20955
20981
|
try {
|
|
20956
20982
|
await setConfigValueImpl("registryUrl", registryUrl);
|
|
20957
20983
|
await setConfigValueImpl("apiKey", apiKeyToken);
|
|
20958
20984
|
await setConfigValueImpl("proxyUrl", proxyUrl);
|
|
20985
|
+
await setConfigValueImpl("humanName", humanName);
|
|
20959
20986
|
} catch (error48) {
|
|
20960
20987
|
logger7.warn("cli.invite_redeem_config_persist_failed", {
|
|
20961
20988
|
errorName: error48 instanceof Error ? error48.name : "unknown"
|
|
@@ -20989,7 +21016,10 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20989
21016
|
}
|
|
20990
21017
|
)
|
|
20991
21018
|
);
|
|
20992
|
-
inviteCommand.command("redeem <code>").description("Redeem a registry invite code and store PAT locally").
|
|
21019
|
+
inviteCommand.command("redeem <code>").description("Redeem a registry invite code and store PAT locally").requiredOption(
|
|
21020
|
+
"--display-name <name>",
|
|
21021
|
+
"Human display name used for onboarding"
|
|
21022
|
+
).option("--api-key-name <name>", "Optional API key label").option("--registry-url <url>", "Override registry URL").action(
|
|
20993
21023
|
withErrorHandling(
|
|
20994
21024
|
"invite redeem",
|
|
20995
21025
|
async (code, options) => {
|
|
@@ -20997,9 +21027,11 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
20997
21027
|
logger7.info("cli.invite_redeemed", {
|
|
20998
21028
|
apiKeyId: result.apiKeyId,
|
|
20999
21029
|
apiKeyName: result.apiKeyName,
|
|
21030
|
+
humanName: result.humanName,
|
|
21000
21031
|
registryUrl: result.registryUrl
|
|
21001
21032
|
});
|
|
21002
21033
|
writeStdoutLine("Invite redeemed");
|
|
21034
|
+
writeStdoutLine(`Human name: ${result.humanName}`);
|
|
21003
21035
|
if (result.apiKeyName) {
|
|
21004
21036
|
writeStdoutLine(`API key name: ${result.apiKeyName}`);
|
|
21005
21037
|
}
|
|
@@ -21009,6 +21041,7 @@ var createInviteCommand = (dependencies = {}) => {
|
|
|
21009
21041
|
result.registryUrl,
|
|
21010
21042
|
result.apiKeyToken,
|
|
21011
21043
|
result.proxyUrl,
|
|
21044
|
+
result.humanName,
|
|
21012
21045
|
dependencies
|
|
21013
21046
|
);
|
|
21014
21047
|
writeStdoutLine("API key saved to local config");
|
|
@@ -21113,11 +21146,11 @@ function parseNonEmptyString8(value, label) {
|
|
|
21113
21146
|
}
|
|
21114
21147
|
return trimmed;
|
|
21115
21148
|
}
|
|
21116
|
-
function
|
|
21149
|
+
function parseOptionalProfileName(value, label) {
|
|
21117
21150
|
if (value === void 0) {
|
|
21118
21151
|
return void 0;
|
|
21119
21152
|
}
|
|
21120
|
-
return parseNonEmptyString8(value,
|
|
21153
|
+
return parseNonEmptyString8(value, label);
|
|
21121
21154
|
}
|
|
21122
21155
|
function parsePeerAlias(value) {
|
|
21123
21156
|
const alias = parseNonEmptyString8(value, "peer alias");
|
|
@@ -21374,12 +21407,13 @@ async function loadPeersConfig(peersPath) {
|
|
|
21374
21407
|
}
|
|
21375
21408
|
const did = parseAgentDid2(value.did, `Peer ${normalizedAlias} did`);
|
|
21376
21409
|
const proxyUrl = parseProxyUrl(value.proxyUrl);
|
|
21377
|
-
const
|
|
21378
|
-
|
|
21410
|
+
const agentName = parseOptionalProfileName(value.agentName, "agentName");
|
|
21411
|
+
const humanName = parseOptionalProfileName(value.humanName, "humanName");
|
|
21412
|
+
if (agentName === void 0 && humanName === void 0) {
|
|
21379
21413
|
peers[normalizedAlias] = { did, proxyUrl };
|
|
21380
21414
|
continue;
|
|
21381
21415
|
}
|
|
21382
|
-
peers[normalizedAlias] = { did, proxyUrl,
|
|
21416
|
+
peers[normalizedAlias] = { did, proxyUrl, agentName, humanName };
|
|
21383
21417
|
}
|
|
21384
21418
|
return { peers };
|
|
21385
21419
|
}
|
|
@@ -22978,6 +23012,7 @@ var FILE_MODE4 = 384;
|
|
|
22978
23012
|
var PEER_ALIAS_PATTERN2 = /^[a-zA-Z0-9._-]+$/;
|
|
22979
23013
|
var DEFAULT_STATUS_WAIT_SECONDS = 300;
|
|
22980
23014
|
var DEFAULT_STATUS_POLL_INTERVAL_SECONDS = 3;
|
|
23015
|
+
var MAX_PROFILE_NAME_LENGTH = 64;
|
|
22981
23016
|
var isRecord9 = (value) => {
|
|
22982
23017
|
return typeof value === "object" && value !== null;
|
|
22983
23018
|
};
|
|
@@ -22994,6 +23029,49 @@ function parseNonEmptyString9(value) {
|
|
|
22994
23029
|
}
|
|
22995
23030
|
return value.trim();
|
|
22996
23031
|
}
|
|
23032
|
+
function hasControlChars2(value) {
|
|
23033
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
23034
|
+
const code = value.charCodeAt(index);
|
|
23035
|
+
if (code <= 31 || code === 127) {
|
|
23036
|
+
return true;
|
|
23037
|
+
}
|
|
23038
|
+
}
|
|
23039
|
+
return false;
|
|
23040
|
+
}
|
|
23041
|
+
function parseProfileName(value, label) {
|
|
23042
|
+
const candidate = parseNonEmptyString9(value);
|
|
23043
|
+
if (candidate.length === 0) {
|
|
23044
|
+
throw createCliError7(
|
|
23045
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23046
|
+
`${label} is required for pairing`
|
|
23047
|
+
);
|
|
23048
|
+
}
|
|
23049
|
+
if (candidate.length > MAX_PROFILE_NAME_LENGTH) {
|
|
23050
|
+
throw createCliError7(
|
|
23051
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23052
|
+
`${label} must be at most ${MAX_PROFILE_NAME_LENGTH} characters`
|
|
23053
|
+
);
|
|
23054
|
+
}
|
|
23055
|
+
if (hasControlChars2(candidate)) {
|
|
23056
|
+
throw createCliError7(
|
|
23057
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23058
|
+
`${label} contains control characters`
|
|
23059
|
+
);
|
|
23060
|
+
}
|
|
23061
|
+
return candidate;
|
|
23062
|
+
}
|
|
23063
|
+
function parsePeerProfile(payload) {
|
|
23064
|
+
if (!isRecord9(payload)) {
|
|
23065
|
+
throw createCliError7(
|
|
23066
|
+
"CLI_PAIR_PROFILE_INVALID",
|
|
23067
|
+
"Pair profile must be an object"
|
|
23068
|
+
);
|
|
23069
|
+
}
|
|
23070
|
+
return {
|
|
23071
|
+
agentName: parseProfileName(payload.agentName, "agentName"),
|
|
23072
|
+
humanName: parseProfileName(payload.humanName, "humanName")
|
|
23073
|
+
};
|
|
23074
|
+
}
|
|
22997
23075
|
function parsePairingTicket(value) {
|
|
22998
23076
|
const ticket = parseNonEmptyString9(value);
|
|
22999
23077
|
if (!ticket.startsWith(PAIRING_TICKET_PREFIX)) {
|
|
@@ -23158,10 +23236,19 @@ function parsePeerEntry(value) {
|
|
|
23158
23236
|
"Peer entry is invalid"
|
|
23159
23237
|
);
|
|
23160
23238
|
}
|
|
23161
|
-
|
|
23239
|
+
const agentNameRaw = parseNonEmptyString9(value.agentName);
|
|
23240
|
+
const humanNameRaw = parseNonEmptyString9(value.humanName);
|
|
23241
|
+
const entry = {
|
|
23162
23242
|
did,
|
|
23163
23243
|
proxyUrl
|
|
23164
23244
|
};
|
|
23245
|
+
if (agentNameRaw.length > 0) {
|
|
23246
|
+
entry.agentName = parseProfileName(agentNameRaw, "agentName");
|
|
23247
|
+
}
|
|
23248
|
+
if (humanNameRaw.length > 0) {
|
|
23249
|
+
entry.humanName = parseProfileName(humanNameRaw, "humanName");
|
|
23250
|
+
}
|
|
23251
|
+
return entry;
|
|
23165
23252
|
}
|
|
23166
23253
|
async function loadPeersConfig2(input) {
|
|
23167
23254
|
const peersPath = resolvePeersConfigPath(input.getConfigDirImpl);
|
|
@@ -23244,6 +23331,19 @@ function parsePositiveIntegerOption(input) {
|
|
|
23244
23331
|
}
|
|
23245
23332
|
return parsed;
|
|
23246
23333
|
}
|
|
23334
|
+
function resolveLocalPairProfile(input) {
|
|
23335
|
+
const humanName = parseNonEmptyString9(input.config.humanName);
|
|
23336
|
+
if (humanName.length === 0) {
|
|
23337
|
+
throw createCliError7(
|
|
23338
|
+
"CLI_PAIR_HUMAN_NAME_MISSING",
|
|
23339
|
+
"Human name is missing. Run `clawdentity invite redeem <clw_inv_...> --display-name <name>` or `clawdentity config set humanName <name>`."
|
|
23340
|
+
);
|
|
23341
|
+
}
|
|
23342
|
+
return {
|
|
23343
|
+
agentName: parseProfileName(input.agentName, "agentName"),
|
|
23344
|
+
humanName: parseProfileName(humanName, "humanName")
|
|
23345
|
+
};
|
|
23346
|
+
}
|
|
23247
23347
|
function parseProxyUrl2(candidate) {
|
|
23248
23348
|
try {
|
|
23249
23349
|
const parsed = new URL(candidate);
|
|
@@ -23394,15 +23494,25 @@ function parsePairStartResponse(payload) {
|
|
|
23394
23494
|
const ticket = parsePairingTicket(payload.ticket);
|
|
23395
23495
|
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
23396
23496
|
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
23497
|
+
let initiatorProfile;
|
|
23397
23498
|
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
23398
23499
|
throw createCliError7(
|
|
23399
23500
|
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
23400
23501
|
"Pair start response is invalid"
|
|
23401
23502
|
);
|
|
23402
23503
|
}
|
|
23504
|
+
try {
|
|
23505
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23506
|
+
} catch {
|
|
23507
|
+
throw createCliError7(
|
|
23508
|
+
"CLI_PAIR_START_INVALID_RESPONSE",
|
|
23509
|
+
"Pair start response is invalid"
|
|
23510
|
+
);
|
|
23511
|
+
}
|
|
23403
23512
|
return {
|
|
23404
23513
|
ticket,
|
|
23405
23514
|
initiatorAgentDid,
|
|
23515
|
+
initiatorProfile,
|
|
23406
23516
|
expiresAt
|
|
23407
23517
|
};
|
|
23408
23518
|
}
|
|
@@ -23416,16 +23526,29 @@ function parsePairConfirmResponse(payload) {
|
|
|
23416
23526
|
const paired = payload.paired === true;
|
|
23417
23527
|
const initiatorAgentDid = parseNonEmptyString9(payload.initiatorAgentDid);
|
|
23418
23528
|
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
23529
|
+
let initiatorProfile;
|
|
23530
|
+
let responderProfile;
|
|
23419
23531
|
if (!paired || initiatorAgentDid.length === 0 || responderAgentDid.length === 0) {
|
|
23420
23532
|
throw createCliError7(
|
|
23421
23533
|
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
23422
23534
|
"Pair confirm response is invalid"
|
|
23423
23535
|
);
|
|
23424
23536
|
}
|
|
23537
|
+
try {
|
|
23538
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23539
|
+
responderProfile = parsePeerProfile(payload.responderProfile);
|
|
23540
|
+
} catch {
|
|
23541
|
+
throw createCliError7(
|
|
23542
|
+
"CLI_PAIR_CONFIRM_INVALID_RESPONSE",
|
|
23543
|
+
"Pair confirm response is invalid"
|
|
23544
|
+
);
|
|
23545
|
+
}
|
|
23425
23546
|
return {
|
|
23426
23547
|
paired,
|
|
23427
23548
|
initiatorAgentDid,
|
|
23428
|
-
responderAgentDid
|
|
23549
|
+
responderAgentDid,
|
|
23550
|
+
initiatorProfile,
|
|
23551
|
+
responderProfile
|
|
23429
23552
|
};
|
|
23430
23553
|
}
|
|
23431
23554
|
function parsePairStatusResponse(payload) {
|
|
@@ -23446,6 +23569,7 @@ function parsePairStatusResponse(payload) {
|
|
|
23446
23569
|
const responderAgentDid = parseNonEmptyString9(payload.responderAgentDid);
|
|
23447
23570
|
const expiresAt = parseNonEmptyString9(payload.expiresAt);
|
|
23448
23571
|
const confirmedAt = parseNonEmptyString9(payload.confirmedAt);
|
|
23572
|
+
let initiatorProfile;
|
|
23449
23573
|
if (initiatorAgentDid.length === 0 || expiresAt.length === 0) {
|
|
23450
23574
|
throw createCliError7(
|
|
23451
23575
|
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
@@ -23458,10 +23582,37 @@ function parsePairStatusResponse(payload) {
|
|
|
23458
23582
|
"Pair status response is invalid"
|
|
23459
23583
|
);
|
|
23460
23584
|
}
|
|
23585
|
+
try {
|
|
23586
|
+
initiatorProfile = parsePeerProfile(payload.initiatorProfile);
|
|
23587
|
+
} catch {
|
|
23588
|
+
throw createCliError7(
|
|
23589
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23590
|
+
"Pair status response is invalid"
|
|
23591
|
+
);
|
|
23592
|
+
}
|
|
23593
|
+
let responderProfile;
|
|
23594
|
+
if (payload.responderProfile !== void 0) {
|
|
23595
|
+
try {
|
|
23596
|
+
responderProfile = parsePeerProfile(payload.responderProfile);
|
|
23597
|
+
} catch {
|
|
23598
|
+
throw createCliError7(
|
|
23599
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23600
|
+
"Pair status response is invalid"
|
|
23601
|
+
);
|
|
23602
|
+
}
|
|
23603
|
+
}
|
|
23604
|
+
if (statusRaw === "confirmed" && responderProfile === void 0) {
|
|
23605
|
+
throw createCliError7(
|
|
23606
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
23607
|
+
"Pair status response is invalid"
|
|
23608
|
+
);
|
|
23609
|
+
}
|
|
23461
23610
|
return {
|
|
23462
23611
|
status: statusRaw,
|
|
23463
23612
|
initiatorAgentDid,
|
|
23613
|
+
initiatorProfile,
|
|
23464
23614
|
responderAgentDid: responderAgentDid.length > 0 ? responderAgentDid : void 0,
|
|
23615
|
+
responderProfile,
|
|
23465
23616
|
expiresAt,
|
|
23466
23617
|
confirmedAt: confirmedAt.length > 0 ? confirmedAt : void 0
|
|
23467
23618
|
};
|
|
@@ -23666,7 +23817,9 @@ async function persistPairedPeer(input) {
|
|
|
23666
23817
|
});
|
|
23667
23818
|
peersConfig.peers[alias] = {
|
|
23668
23819
|
did: input.peerDid,
|
|
23669
|
-
proxyUrl: peerProxyUrl
|
|
23820
|
+
proxyUrl: peerProxyUrl,
|
|
23821
|
+
agentName: input.peerProfile.agentName,
|
|
23822
|
+
humanName: input.peerProfile.humanName
|
|
23670
23823
|
};
|
|
23671
23824
|
await savePeersConfig2({
|
|
23672
23825
|
config: peersConfig,
|
|
@@ -23688,13 +23841,19 @@ async function startPairing(agentName, options, dependencies = {}) {
|
|
|
23688
23841
|
config: config2,
|
|
23689
23842
|
fetchImpl
|
|
23690
23843
|
});
|
|
23844
|
+
const normalizedAgentName = assertValidAgentName(agentName);
|
|
23845
|
+
const initiatorProfile = resolveLocalPairProfile({
|
|
23846
|
+
config: config2,
|
|
23847
|
+
agentName: normalizedAgentName
|
|
23848
|
+
});
|
|
23691
23849
|
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23692
|
-
|
|
23850
|
+
normalizedAgentName,
|
|
23693
23851
|
dependencies
|
|
23694
23852
|
);
|
|
23695
23853
|
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_START_PATH);
|
|
23696
23854
|
const requestBody = JSON.stringify({
|
|
23697
|
-
ttlSeconds
|
|
23855
|
+
ttlSeconds,
|
|
23856
|
+
initiatorProfile
|
|
23698
23857
|
});
|
|
23699
23858
|
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23700
23859
|
const timestampSeconds = nowSecondsImpl();
|
|
@@ -23751,6 +23910,11 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23751
23910
|
const readFileImpl = dependencies.readFileImpl ?? readFile6;
|
|
23752
23911
|
const qrDecodeImpl = dependencies.qrDecodeImpl ?? decodeTicketFromPng;
|
|
23753
23912
|
const config2 = await resolveConfigImpl();
|
|
23913
|
+
const normalizedAgentName = assertValidAgentName(agentName);
|
|
23914
|
+
const responderProfile = resolveLocalPairProfile({
|
|
23915
|
+
config: config2,
|
|
23916
|
+
agentName: normalizedAgentName
|
|
23917
|
+
});
|
|
23754
23918
|
const ticketSource = resolveConfirmTicketSource(options);
|
|
23755
23919
|
const proxyUrl = await resolveProxyUrl({
|
|
23756
23920
|
config: config2,
|
|
@@ -23780,11 +23944,14 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23780
23944
|
ticket = parsePairingTicket(qrDecodeImpl(new Uint8Array(imageBytes)));
|
|
23781
23945
|
}
|
|
23782
23946
|
const { ait, secretKey } = await readAgentProofMaterial(
|
|
23783
|
-
|
|
23947
|
+
normalizedAgentName,
|
|
23784
23948
|
dependencies
|
|
23785
23949
|
);
|
|
23786
23950
|
const requestUrl = toProxyRequestUrl(proxyUrl, PAIR_CONFIRM_PATH);
|
|
23787
|
-
const requestBody = JSON.stringify({
|
|
23951
|
+
const requestBody = JSON.stringify({
|
|
23952
|
+
ticket,
|
|
23953
|
+
responderProfile
|
|
23954
|
+
});
|
|
23788
23955
|
const bodyBytes = new TextEncoder().encode(requestBody);
|
|
23789
23956
|
const timestampSeconds = nowSecondsImpl();
|
|
23790
23957
|
const nonce = nonceFactoryImpl();
|
|
@@ -23820,6 +23987,7 @@ async function confirmPairing(agentName, options, dependencies = {}) {
|
|
|
23820
23987
|
const peerAlias = await persistPairedPeer({
|
|
23821
23988
|
ticket,
|
|
23822
23989
|
peerDid: parsed.initiatorAgentDid,
|
|
23990
|
+
peerProfile: parsed.initiatorProfile,
|
|
23823
23991
|
dependencies
|
|
23824
23992
|
});
|
|
23825
23993
|
if (ticketSource.source === "qr-file" && ticketSource.qrFilePath) {
|
|
@@ -23901,15 +24069,23 @@ async function getPairingStatusOnce(agentName, options, dependencies = {}) {
|
|
|
23901
24069
|
);
|
|
23902
24070
|
}
|
|
23903
24071
|
const peerDid = callerAgentDid === parsed.initiatorAgentDid ? responderAgentDid : callerAgentDid === responderAgentDid ? parsed.initiatorAgentDid : void 0;
|
|
24072
|
+
const peerProfile = callerAgentDid === parsed.initiatorAgentDid ? parsed.responderProfile : callerAgentDid === responderAgentDid ? parsed.initiatorProfile : void 0;
|
|
23904
24073
|
if (!peerDid) {
|
|
23905
24074
|
throw createCliError7(
|
|
23906
24075
|
"CLI_PAIR_STATUS_FORBIDDEN",
|
|
23907
24076
|
"Local agent is not a participant in the pairing ticket"
|
|
23908
24077
|
);
|
|
23909
24078
|
}
|
|
24079
|
+
if (!peerProfile) {
|
|
24080
|
+
throw createCliError7(
|
|
24081
|
+
"CLI_PAIR_STATUS_INVALID_RESPONSE",
|
|
24082
|
+
"Pair status response is invalid"
|
|
24083
|
+
);
|
|
24084
|
+
}
|
|
23910
24085
|
peerAlias = await persistPairedPeer({
|
|
23911
24086
|
ticket,
|
|
23912
24087
|
peerDid,
|
|
24088
|
+
peerProfile,
|
|
23913
24089
|
dependencies
|
|
23914
24090
|
});
|
|
23915
24091
|
}
|
|
@@ -24005,6 +24181,12 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24005
24181
|
writeStdoutLine("Pairing ticket created");
|
|
24006
24182
|
writeStdoutLine(`Ticket: ${result.ticket}`);
|
|
24007
24183
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24184
|
+
writeStdoutLine(
|
|
24185
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24186
|
+
);
|
|
24187
|
+
writeStdoutLine(
|
|
24188
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24189
|
+
);
|
|
24008
24190
|
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
24009
24191
|
if (result.qrPath) {
|
|
24010
24192
|
writeStdoutLine(`QR File: ${result.qrPath}`);
|
|
@@ -24047,6 +24229,14 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24047
24229
|
`Responder Agent DID: ${status.responderAgentDid}`
|
|
24048
24230
|
);
|
|
24049
24231
|
}
|
|
24232
|
+
if (status.responderProfile) {
|
|
24233
|
+
writeStdoutLine(
|
|
24234
|
+
`Responder Agent Name: ${status.responderProfile.agentName}`
|
|
24235
|
+
);
|
|
24236
|
+
writeStdoutLine(
|
|
24237
|
+
`Responder Human Name: ${status.responderProfile.humanName}`
|
|
24238
|
+
);
|
|
24239
|
+
}
|
|
24050
24240
|
if (status.peerAlias) {
|
|
24051
24241
|
writeStdoutLine(`Peer alias saved: ${status.peerAlias}`);
|
|
24052
24242
|
}
|
|
@@ -24067,7 +24257,19 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24067
24257
|
});
|
|
24068
24258
|
writeStdoutLine("Pairing confirmed");
|
|
24069
24259
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24260
|
+
writeStdoutLine(
|
|
24261
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24262
|
+
);
|
|
24263
|
+
writeStdoutLine(
|
|
24264
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24265
|
+
);
|
|
24070
24266
|
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
24267
|
+
writeStdoutLine(
|
|
24268
|
+
`Responder Agent Name: ${result.responderProfile.agentName}`
|
|
24269
|
+
);
|
|
24270
|
+
writeStdoutLine(
|
|
24271
|
+
`Responder Human Name: ${result.responderProfile.humanName}`
|
|
24272
|
+
);
|
|
24071
24273
|
writeStdoutLine(`Paired: ${result.paired ? "true" : "false"}`);
|
|
24072
24274
|
if (result.peerAlias) {
|
|
24073
24275
|
writeStdoutLine(`Peer alias saved: ${result.peerAlias}`);
|
|
@@ -24099,9 +24301,23 @@ var createPairCommand = (dependencies = {}) => {
|
|
|
24099
24301
|
});
|
|
24100
24302
|
writeStdoutLine(`Status: ${result.status}`);
|
|
24101
24303
|
writeStdoutLine(`Initiator Agent DID: ${result.initiatorAgentDid}`);
|
|
24304
|
+
writeStdoutLine(
|
|
24305
|
+
`Initiator Agent Name: ${result.initiatorProfile.agentName}`
|
|
24306
|
+
);
|
|
24307
|
+
writeStdoutLine(
|
|
24308
|
+
`Initiator Human Name: ${result.initiatorProfile.humanName}`
|
|
24309
|
+
);
|
|
24102
24310
|
if (result.responderAgentDid) {
|
|
24103
24311
|
writeStdoutLine(`Responder Agent DID: ${result.responderAgentDid}`);
|
|
24104
24312
|
}
|
|
24313
|
+
if (result.responderProfile) {
|
|
24314
|
+
writeStdoutLine(
|
|
24315
|
+
`Responder Agent Name: ${result.responderProfile.agentName}`
|
|
24316
|
+
);
|
|
24317
|
+
writeStdoutLine(
|
|
24318
|
+
`Responder Human Name: ${result.responderProfile.humanName}`
|
|
24319
|
+
);
|
|
24320
|
+
}
|
|
24105
24321
|
writeStdoutLine(`Expires At: ${result.expiresAt}`);
|
|
24106
24322
|
if (result.confirmedAt) {
|
|
24107
24323
|
writeStdoutLine(`Confirmed At: ${result.confirmedAt}`);
|
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.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -21,17 +21,6 @@
|
|
|
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
|
-
},
|
|
35
24
|
"dependencies": {
|
|
36
25
|
"commander": "^13.1.0",
|
|
37
26
|
"jsqr": "^1.4.0",
|
|
@@ -40,11 +29,21 @@
|
|
|
40
29
|
"ws": "^8.19.0"
|
|
41
30
|
},
|
|
42
31
|
"devDependencies": {
|
|
43
|
-
"@clawdentity/connector": "workspace:*",
|
|
44
|
-
"@clawdentity/protocol": "workspace:*",
|
|
45
|
-
"@clawdentity/sdk": "workspace:*",
|
|
46
32
|
"@types/node": "^22.18.11",
|
|
47
33
|
"@types/pngjs": "^6.0.5",
|
|
48
|
-
"@types/qrcode": "^1.5.6"
|
|
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"
|
|
49
48
|
}
|
|
50
|
-
}
|
|
49
|
+
}
|
|
@@ -56,11 +56,11 @@ function parseProxyUrl(value) {
|
|
|
56
56
|
throw new Error("proxyUrl must be a valid URL");
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
function
|
|
59
|
+
function parseProfileName(value, label) {
|
|
60
60
|
if (value === void 0) {
|
|
61
61
|
return void 0;
|
|
62
62
|
}
|
|
63
|
-
return parseNonEmptyString(value,
|
|
63
|
+
return parseNonEmptyString(value, label);
|
|
64
64
|
}
|
|
65
65
|
function parsePeerEntry(value) {
|
|
66
66
|
if (!isRecord(value)) {
|
|
@@ -68,11 +68,12 @@ function parsePeerEntry(value) {
|
|
|
68
68
|
}
|
|
69
69
|
const did = parseDid(value.did);
|
|
70
70
|
const proxyUrl = parseProxyUrl(value.proxyUrl);
|
|
71
|
-
const
|
|
72
|
-
|
|
71
|
+
const agentName = parseProfileName(value.agentName, "agentName");
|
|
72
|
+
const humanName = parseProfileName(value.humanName, "humanName");
|
|
73
|
+
if (agentName === void 0 && humanName === void 0) {
|
|
73
74
|
return { did, proxyUrl };
|
|
74
75
|
}
|
|
75
|
-
return { did, proxyUrl,
|
|
76
|
+
return { did, proxyUrl, agentName, humanName };
|
|
76
77
|
}
|
|
77
78
|
function parsePeersConfig(value, source) {
|
|
78
79
|
if (!isRecord(value)) {
|
|
@@ -57,6 +57,7 @@ Relay invite codes are not part of this flow.
|
|
|
57
57
|
Required for onboarding:
|
|
58
58
|
- Registry onboarding invite code: `clw_inv_...` (default onboarding path)
|
|
59
59
|
- Local agent name
|
|
60
|
+
- Human display name (used by invite redeem and pairing profile metadata)
|
|
60
61
|
|
|
61
62
|
Optional only for recovery/advanced operator flows:
|
|
62
63
|
- Existing API key (only when user explicitly says no invite is available)
|
|
@@ -84,8 +85,8 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
84
85
|
- `clawdentity config show`
|
|
85
86
|
|
|
86
87
|
### Invite management
|
|
87
|
-
- `clawdentity invite redeem <registry-invite-code>`
|
|
88
|
-
- `clawdentity invite redeem <registry-invite-code> --registry-url <registry-url>`
|
|
88
|
+
- `clawdentity invite redeem <registry-invite-code> --display-name <human-name>`
|
|
89
|
+
- `clawdentity invite redeem <registry-invite-code> --display-name <human-name> --registry-url <registry-url>`
|
|
89
90
|
- `clawdentity invite create` (admin only, see registry reference)
|
|
90
91
|
- `clawdentity invite create --expires-at <iso-8601>` (admin only)
|
|
91
92
|
|
|
@@ -152,6 +153,7 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
152
153
|
- If `--invite-code` appears, treat CLI as outdated and upgrade before continuing:
|
|
153
154
|
- `npm install -g clawdentity@latest`
|
|
154
155
|
- Confirm local agent name.
|
|
156
|
+
- Confirm local human display name for onboarding.
|
|
155
157
|
- Check local API key status with `clawdentity config get apiKey`.
|
|
156
158
|
- If API key is missing, ask for onboarding invite `clw_inv_...` and continue with invite redeem.
|
|
157
159
|
- Do not ask for raw API key unless the user explicitly says invite is unavailable.
|
|
@@ -167,13 +169,14 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
167
169
|
- If needed, run with `--registry-url`.
|
|
168
170
|
|
|
169
171
|
4. Finish onboarding and generate API key.
|
|
170
|
-
- Preferred path: run `clawdentity invite redeem <clw_inv_
|
|
172
|
+
- Preferred path: run `clawdentity invite redeem <clw_inv_...> --display-name <human-name>`.
|
|
171
173
|
- If local API key already exists and user explicitly wants to reuse it, continue without redeem.
|
|
172
174
|
- Use `config set apiKey` only as a manual recovery path when user cannot provide invite.
|
|
173
175
|
- Confirm output shows:
|
|
174
176
|
- `Invite redeemed`
|
|
175
177
|
- API key token printed once
|
|
176
178
|
- `API key saved to local config`
|
|
179
|
+
- `Human name: <human-name>`
|
|
177
180
|
- Stop and fix if this step fails. Do not proceed to pairing.
|
|
178
181
|
|
|
179
182
|
5. Create local OpenClaw agent identity.
|
|
@@ -226,6 +229,14 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
226
229
|
- Inline ticket path: `clawdentity pair confirm <agent-name> --ticket <clwpair1_...>`
|
|
227
230
|
- Cannot provide both `--qr-file` and `--ticket` simultaneously.
|
|
228
231
|
- Pair confirm auto-saves peer DID/proxy mapping locally from QR ticket metadata.
|
|
232
|
+
- Pair start/confirm/status exchange profile metadata:
|
|
233
|
+
- `initiatorProfile = { agentName, humanName }`
|
|
234
|
+
- `responderProfile = { agentName, humanName }`
|
|
235
|
+
- Local peer entries in `~/.clawdentity/peers.json` should include:
|
|
236
|
+
- `did`
|
|
237
|
+
- `proxyUrl`
|
|
238
|
+
- `agentName`
|
|
239
|
+
- `humanName`
|
|
229
240
|
- If initiator started without `--wait`, initiator must run:
|
|
230
241
|
- `clawdentity pair status <agent-name> --ticket <clwpair1_...> --wait`
|
|
231
242
|
- This persists the peer on initiator after responder confirmation.
|
|
@@ -236,6 +247,8 @@ Note: Registry operators must run `admin bootstrap` before creating invites. See
|
|
|
236
247
|
- Verify output shows token status, expiry, and no revocation.
|
|
237
248
|
- Run `clawdentity openclaw doctor --peer <alias>` to confirm the new peer is visible.
|
|
238
249
|
- Run `clawdentity openclaw relay test` to confirm end-to-end message delivery.
|
|
250
|
+
- Relay delivery is asynchronous: proxy accepts deliveries with `202`, and `state=queued` is expected when the recipient connector is temporarily offline.
|
|
251
|
+
- `state=queued` is not a pairing failure. The proxy retries delivery automatically while the message is within queue TTL/retry limits.
|
|
239
252
|
- Note: `relay test` runs preflight doctor checks before sending the probe.
|
|
240
253
|
|
|
241
254
|
## Lifecycle Management
|
|
@@ -51,7 +51,8 @@ Rules:
|
|
|
51
51
|
"beta": {
|
|
52
52
|
"did": "did:claw:agent:01H...",
|
|
53
53
|
"proxyUrl": "https://beta-proxy.example.com/hooks/agent",
|
|
54
|
-
"
|
|
54
|
+
"agentName": "beta",
|
|
55
|
+
"humanName": "Ira"
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
}
|
|
@@ -61,7 +62,8 @@ Rules:
|
|
|
61
62
|
- peer alias key uses `[a-zA-Z0-9._-]`
|
|
62
63
|
- `did` required and must begin with `did:`
|
|
63
64
|
- `proxyUrl` required and must be a valid absolute URL
|
|
64
|
-
- `
|
|
65
|
+
- `agentName` optional
|
|
66
|
+
- `humanName` optional
|
|
65
67
|
|
|
66
68
|
## Proxy Pairing Prerequisite
|
|
67
69
|
|
|
@@ -75,11 +77,15 @@ Current pairing contract is ticket-based with CLI support:
|
|
|
75
77
|
- headers:
|
|
76
78
|
- `Authorization: Claw <AIT>`
|
|
77
79
|
- ownership validation is handled internally by proxy-to-registry service auth
|
|
78
|
-
- body
|
|
80
|
+
- body:
|
|
79
81
|
|
|
80
82
|
```json
|
|
81
83
|
{
|
|
82
|
-
"ttlSeconds": 300
|
|
84
|
+
"ttlSeconds": 300,
|
|
85
|
+
"initiatorProfile": {
|
|
86
|
+
"agentName": "alpha",
|
|
87
|
+
"humanName": "Ravi"
|
|
88
|
+
}
|
|
83
89
|
}
|
|
84
90
|
```
|
|
85
91
|
|
|
@@ -92,7 +98,11 @@ Current pairing contract is ticket-based with CLI support:
|
|
|
92
98
|
|
|
93
99
|
```json
|
|
94
100
|
{
|
|
95
|
-
"ticket": "clwpair1_..."
|
|
101
|
+
"ticket": "clwpair1_...",
|
|
102
|
+
"responderProfile": {
|
|
103
|
+
"agentName": "beta",
|
|
104
|
+
"humanName": "Ira"
|
|
105
|
+
}
|
|
96
106
|
}
|
|
97
107
|
```
|
|
98
108
|
|
|
@@ -202,7 +212,7 @@ Known defaults:
|
|
|
202
212
|
| `https://registry.clawdentity.com` | `https://proxy.clawdentity.com` |
|
|
203
213
|
| `https://dev.registry.clawdentity.com` | `https://dev.proxy.clawdentity.com` |
|
|
204
214
|
|
|
205
|
-
Recovery: rerun onboarding (`clawdentity invite redeem <clw_inv_
|
|
215
|
+
Recovery: rerun onboarding (`clawdentity invite redeem <clw_inv_...> --display-name <human-name>`) so local config aligns to registry metadata.
|
|
206
216
|
|
|
207
217
|
## Pairing Error Codes
|
|
208
218
|
|
|
@@ -213,6 +223,7 @@ Recovery: rerun onboarding (`clawdentity invite redeem <clw_inv_...>`) so local
|
|
|
213
223
|
| 403 | `PROXY_PAIR_OWNERSHIP_FORBIDDEN` | Initiator ownership check failed |
|
|
214
224
|
| 503 | `PROXY_PAIR_OWNERSHIP_UNAVAILABLE` | Registry ownership lookup unavailable |
|
|
215
225
|
| — | `CLI_PAIR_AGENT_NOT_FOUND` | Agent ait.jwt or secret.key missing/empty |
|
|
226
|
+
| — | `CLI_PAIR_HUMAN_NAME_MISSING` | Local config is missing `humanName`; set via invite redeem or config |
|
|
216
227
|
| — | `CLI_PAIR_PROXY_URL_REQUIRED` | Proxy URL could not be resolved |
|
|
217
228
|
| — | `CLI_PAIR_START_INVALID_TTL` | ttlSeconds must be a positive integer |
|
|
218
229
|
| — | `CLI_PAIR_INVALID_PROXY_URL` | Proxy URL is invalid |
|