@xfxstudio/claworld 0.2.10-beta.0 → 0.2.10-beta.1
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/openclaw/installer/cli.js +2 -3
- package/src/openclaw/installer/core.js +14 -69
- package/src/openclaw/installer/doctor.js +29 -15
- package/src/openclaw/plugin/claworld-channel-plugin.js +223 -48
- package/src/openclaw/plugin/managed-config.js +18 -13
- package/src/openclaw/plugin/onboarding.js +21 -9
- package/src/openclaw/plugin/register.js +25 -13
- package/src/product-shell/onboarding/onboarding-service.js +6 -5
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -296,10 +296,9 @@ function printInstallSummary(result) {
|
|
|
296
296
|
console.log('Claworld installer complete');
|
|
297
297
|
console.log('===========================');
|
|
298
298
|
console.log(`Managed account: ${result.transformed?.config?.channels?.claworld?.defaultAccount || 'claworld'}`);
|
|
299
|
-
console.log(`Canonical agentId: ${result.activation?.agentId || '(unknown)'}`);
|
|
300
299
|
console.log(`OpenClaw version: ${result.host?.version || '(unknown)'}`);
|
|
301
300
|
console.log(`Plugin action: ${result.plugin?.action || 'unknown'}`);
|
|
302
|
-
console.log(`Activation
|
|
301
|
+
console.log(`Activation: ${result.activationStatus === 'ready' ? 'ready' : 'pending via claworld_update_public_identity'}`);
|
|
303
302
|
console.log(`Runtime refresh: ${result.runtimeRefresh?.action || 'unknown'}`);
|
|
304
303
|
console.log(`Config path: ${result.configPath}`);
|
|
305
304
|
console.log(`Backup path: ${result.backupPath || '(unchanged or new file)'}`);
|
|
@@ -315,10 +314,10 @@ function printUpdateSummary(result, doctorResult) {
|
|
|
315
314
|
console.log('Claworld update complete');
|
|
316
315
|
console.log('========================');
|
|
317
316
|
console.log(`Managed account: ${result.managedOptions?.accountId || 'claworld'}`);
|
|
318
|
-
console.log(`Canonical agentId: ${result.activation?.agentId || '(unknown)'}`);
|
|
319
317
|
console.log(`OpenClaw version: ${result.host?.version || '(unknown)'}`);
|
|
320
318
|
console.log(`Plugin action: ${result.plugin?.action || 'unknown'}`);
|
|
321
319
|
console.log(`Tracked install: ${trackedSummary}`);
|
|
320
|
+
console.log(`Activation: ${result.activationStatus === 'ready' ? 'ready' : 'pending via claworld_update_public_identity'}`);
|
|
322
321
|
console.log(`Runtime refresh: ${result.runtimeRefresh?.action || 'unknown'}`);
|
|
323
322
|
console.log(`Doctor status: ${doctorResult?.status || 'unknown'}`);
|
|
324
323
|
console.log(`Config path: ${result.configPath}`);
|
|
@@ -143,13 +143,7 @@ export function isManagedToolAllowlistReady(config = {}, options = {}) {
|
|
|
143
143
|
export function isRelayBootstrapReady(account = {}) {
|
|
144
144
|
return Boolean(
|
|
145
145
|
account?.configured
|
|
146
|
-
&& (
|
|
147
|
-
normalizeText(account?.appToken, null)
|
|
148
|
-
|| (
|
|
149
|
-
account?.registration?.enabled === true
|
|
150
|
-
&& normalizeText(account?.registration?.displayName, null)
|
|
151
|
-
)
|
|
152
|
-
),
|
|
146
|
+
&& normalizeText(account?.appToken, null),
|
|
153
147
|
);
|
|
154
148
|
}
|
|
155
149
|
|
|
@@ -756,8 +750,8 @@ export function inspectManagedClaworldInstall({
|
|
|
756
750
|
statusLabel = managedReady ? 'configured' : 'configured (managed refresh recommended)';
|
|
757
751
|
selectionHint = managedReady ? 'configured · managed runtime' : 'configured · managed refresh';
|
|
758
752
|
} else if (hasAnyConfig) {
|
|
759
|
-
statusLabel = '
|
|
760
|
-
selectionHint = '
|
|
753
|
+
statusLabel = 'configured (activation pending)';
|
|
754
|
+
selectionHint = 'configured · activation pending';
|
|
761
755
|
}
|
|
762
756
|
|
|
763
757
|
return {
|
|
@@ -1288,6 +1282,7 @@ export async function verifyClaworldInstall({
|
|
|
1288
1282
|
attempts = DEFAULT_VERIFICATION_ATTEMPTS,
|
|
1289
1283
|
delayMs = DEFAULT_VERIFICATION_DELAY_MS,
|
|
1290
1284
|
requireGatewayRunning = resolveRequireGatewayRunning(env),
|
|
1285
|
+
requireChannelToken = true,
|
|
1291
1286
|
} = {}) {
|
|
1292
1287
|
let lastResult = null;
|
|
1293
1288
|
|
|
@@ -1341,7 +1336,10 @@ export async function verifyClaworldInstall({
|
|
|
1341
1336
|
channelAccount
|
|
1342
1337
|
&& channelAccount.configured === true
|
|
1343
1338
|
&& channelAccount.enabled !== false
|
|
1344
|
-
&&
|
|
1339
|
+
&& (
|
|
1340
|
+
requireChannelToken !== true
|
|
1341
|
+
|| channelAccount.tokenStatus === 'available'
|
|
1342
|
+
)
|
|
1345
1343
|
);
|
|
1346
1344
|
const pluginReady = Boolean(plugin.installed);
|
|
1347
1345
|
const bindingReady = Boolean(bindingLine);
|
|
@@ -1358,6 +1356,7 @@ export async function verifyClaworldInstall({
|
|
|
1358
1356
|
channelReady,
|
|
1359
1357
|
bindingReady,
|
|
1360
1358
|
requireGatewayRunning,
|
|
1359
|
+
requireChannelToken,
|
|
1361
1360
|
};
|
|
1362
1361
|
|
|
1363
1362
|
if (lastResult.ok) {
|
|
@@ -1419,30 +1418,13 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1419
1418
|
normalizeText(existingInstall.accountStatus?.serverUrl, DEFAULT_CLAWORLD_SERVER_URL),
|
|
1420
1419
|
);
|
|
1421
1420
|
|
|
1422
|
-
const manifest = await fetchInstallManifest({
|
|
1423
|
-
serverUrl: effectiveServerUrl,
|
|
1424
|
-
apiKey,
|
|
1425
|
-
fetchImpl,
|
|
1426
|
-
});
|
|
1427
|
-
const manifestMinHostVersion = normalizeText(
|
|
1428
|
-
manifest?.installer?.minHostVersion,
|
|
1429
|
-
normalizeText(manifest?.plugin?.minHostVersion, CLAWORLD_OPENCLAW_MIN_HOST_VERSION),
|
|
1430
|
-
);
|
|
1431
|
-
if (host && compareVersionParts(host.version, manifestMinHostVersion) < 0) {
|
|
1432
|
-
throw createInstallerError(
|
|
1433
|
-
'openclaw_version_too_old',
|
|
1434
|
-
`OpenClaw ${host.version} is below the required minimum ${manifestMinHostVersion}.`,
|
|
1435
|
-
{ hostVersion: host.version, minHostVersion: manifestMinHostVersion },
|
|
1436
|
-
);
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
1421
|
const installAccountId = normalizeText(
|
|
1440
1422
|
accountId,
|
|
1441
|
-
|
|
1423
|
+
DEFAULT_CLAWORLD_ACCOUNT_ID,
|
|
1442
1424
|
);
|
|
1443
1425
|
const installAgentId = normalizeText(
|
|
1444
1426
|
agentId,
|
|
1445
|
-
|
|
1427
|
+
installAccountId,
|
|
1446
1428
|
);
|
|
1447
1429
|
|
|
1448
1430
|
const preflight = inspectManagedClaworldInstall({
|
|
@@ -1465,51 +1447,15 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1465
1447
|
normalizeText(preflight.managedOptions.displayName, null),
|
|
1466
1448
|
);
|
|
1467
1449
|
|
|
1468
|
-
let activation = null;
|
|
1469
|
-
let activationMode = 'new_activation';
|
|
1470
|
-
const existingAppToken = normalizeText(preflight.reusableAppToken, null);
|
|
1471
|
-
if (existingAppToken) {
|
|
1472
|
-
try {
|
|
1473
|
-
activation = await activateInstall({
|
|
1474
|
-
serverUrl: effectiveServerUrl,
|
|
1475
|
-
apiKey,
|
|
1476
|
-
appToken: existingAppToken,
|
|
1477
|
-
displayName: desiredDisplayName,
|
|
1478
|
-
fetchImpl,
|
|
1479
|
-
});
|
|
1480
|
-
activationMode = 'reused_existing_token';
|
|
1481
|
-
} catch (error) {
|
|
1482
|
-
const status = error?.context?.response?.status;
|
|
1483
|
-
if (status !== 401 && status !== 403) {
|
|
1484
|
-
throw error;
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
if (!activation) {
|
|
1489
|
-
activation = await activateInstall({
|
|
1490
|
-
serverUrl: effectiveServerUrl,
|
|
1491
|
-
apiKey,
|
|
1492
|
-
displayName: desiredDisplayName,
|
|
1493
|
-
fetchImpl,
|
|
1494
|
-
});
|
|
1495
|
-
activationMode = 'created_new_activation';
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
1450
|
const managedOptions = resolveClaworldManagedRuntimeOptions({
|
|
1499
1451
|
cfg: currentConfig,
|
|
1500
1452
|
installerState: currentInstallerState,
|
|
1501
1453
|
accountId: installAccountId,
|
|
1502
|
-
input: {
|
|
1503
|
-
name: desiredDisplayName,
|
|
1504
|
-
appToken: activation.appToken,
|
|
1505
|
-
toolProfile,
|
|
1506
|
-
},
|
|
1507
1454
|
overrides: {
|
|
1508
1455
|
agentId: installAgentId,
|
|
1509
1456
|
workspace,
|
|
1510
1457
|
serverUrl: effectiveServerUrl,
|
|
1511
1458
|
apiKey,
|
|
1512
|
-
appToken: activation.appToken,
|
|
1513
1459
|
displayName: desiredDisplayName,
|
|
1514
1460
|
toolProfile,
|
|
1515
1461
|
approvalMode,
|
|
@@ -1562,11 +1508,12 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1562
1508
|
env,
|
|
1563
1509
|
dryRun,
|
|
1564
1510
|
delayMs: Math.min(timeoutMs, DEFAULT_VERIFICATION_DELAY_MS),
|
|
1511
|
+
requireChannelToken: Boolean(managedOptions.appToken),
|
|
1565
1512
|
});
|
|
1566
1513
|
if (!verification.ok) {
|
|
1567
1514
|
throw createInstallerError(
|
|
1568
1515
|
'claworld_install_verification_failed',
|
|
1569
|
-
'Claworld install verification did not confirm the managed
|
|
1516
|
+
'Claworld install verification did not confirm the managed channel runtime shape.',
|
|
1570
1517
|
{ verification },
|
|
1571
1518
|
);
|
|
1572
1519
|
}
|
|
@@ -1585,10 +1532,8 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1585
1532
|
backupPath,
|
|
1586
1533
|
existingInstall,
|
|
1587
1534
|
effectiveServerUrl,
|
|
1588
|
-
manifest,
|
|
1589
1535
|
preflight,
|
|
1590
|
-
|
|
1591
|
-
activation,
|
|
1536
|
+
activationStatus: managedOptions.appToken ? 'ready' : 'pending',
|
|
1592
1537
|
managedOptions,
|
|
1593
1538
|
transformed,
|
|
1594
1539
|
configChanged,
|
|
@@ -522,11 +522,13 @@ export async function runClaworldDoctor({
|
|
|
522
522
|
id: 'app-token',
|
|
523
523
|
category: 'Credentials and runtime',
|
|
524
524
|
label: 'Managed appToken',
|
|
525
|
-
status: configuredAccount.tokenStatus === 'available' ? 'pass' : '
|
|
525
|
+
status: configuredAccount.tokenStatus === 'available' ? 'pass' : 'warn',
|
|
526
526
|
summary: configuredAccount.tokenStatus === 'available'
|
|
527
527
|
? 'Managed account has an available appToken.'
|
|
528
|
-
: `Managed account token status is ${configuredAccount.tokenStatus}.`,
|
|
529
|
-
action:
|
|
528
|
+
: `Managed account token status is ${configuredAccount.tokenStatus}; activation is still pending.`,
|
|
529
|
+
action: configuredAccount.tokenStatus === 'available'
|
|
530
|
+
? null
|
|
531
|
+
: 'Open a live OpenClaw session, run `claworld_pair_agent`, and then complete `claworld_update_public_identity` when prompted.',
|
|
530
532
|
details: { tokenSource: configuredAccount.tokenSource, tokenStatus: configuredAccount.tokenStatus },
|
|
531
533
|
}));
|
|
532
534
|
|
|
@@ -549,9 +551,9 @@ export async function runClaworldDoctor({
|
|
|
549
551
|
id: 'backend-reachable',
|
|
550
552
|
category: 'Credentials and runtime',
|
|
551
553
|
label: 'Claworld backend reachability',
|
|
552
|
-
status: '
|
|
553
|
-
summary: `Unable to
|
|
554
|
-
action: '
|
|
554
|
+
status: 'warn',
|
|
555
|
+
summary: `Unable to reach the Claworld backend at ${effectiveServerUrl}.`,
|
|
556
|
+
action: 'Restore backend reachability before pairing or live Claworld use, then rerun doctor.',
|
|
555
557
|
details: { serverUrl: effectiveServerUrl, message: error?.message || String(error) },
|
|
556
558
|
}));
|
|
557
559
|
}
|
|
@@ -580,7 +582,7 @@ export async function runClaworldDoctor({
|
|
|
580
582
|
label: 'Stable relay binding',
|
|
581
583
|
status: 'fail',
|
|
582
584
|
summary: 'Managed appToken could not be resolved into a healthy backend binding.',
|
|
583
|
-
action: `
|
|
585
|
+
action: 'Run `claworld_pair_agent` in a live OpenClaw session to refresh the managed relay binding.',
|
|
584
586
|
details: { message: error?.message || String(error) },
|
|
585
587
|
}));
|
|
586
588
|
}
|
|
@@ -589,17 +591,17 @@ export async function runClaworldDoctor({
|
|
|
589
591
|
id: 'stable-agent-binding',
|
|
590
592
|
category: 'Credentials and runtime',
|
|
591
593
|
label: 'Stable relay binding',
|
|
592
|
-
status: '
|
|
593
|
-
summary: 'Doctor could not verify the managed relay binding because
|
|
594
|
-
action:
|
|
594
|
+
status: 'warn',
|
|
595
|
+
summary: 'Doctor could not verify the managed relay binding because activation is still pending.',
|
|
596
|
+
action: 'Open a live OpenClaw session, run `claworld_pair_agent`, and then complete `claworld_update_public_identity` when prompted.',
|
|
595
597
|
}));
|
|
596
598
|
} else {
|
|
597
599
|
checks.push(createCheck({
|
|
598
600
|
id: 'stable-agent-binding',
|
|
599
601
|
category: 'Credentials and runtime',
|
|
600
602
|
label: 'Stable relay binding',
|
|
601
|
-
status: '
|
|
602
|
-
summary: 'Doctor could not verify the managed relay binding because the backend
|
|
603
|
+
status: 'warn',
|
|
604
|
+
summary: 'Doctor could not verify the managed relay binding because the backend was not reachable.',
|
|
603
605
|
action: 'Restore backend reachability, then rerun doctor to verify the managed relay binding.',
|
|
604
606
|
}));
|
|
605
607
|
}
|
|
@@ -655,15 +657,27 @@ export async function runClaworldDoctor({
|
|
|
655
657
|
&& channelAccount.enabled !== false
|
|
656
658
|
&& channelAccount.tokenStatus === 'available'
|
|
657
659
|
);
|
|
660
|
+
const channelPendingActivation = Boolean(
|
|
661
|
+
channelAccount
|
|
662
|
+
&& channelAccount.configured === true
|
|
663
|
+
&& channelAccount.enabled !== false
|
|
664
|
+
&& channelAccount.tokenStatus !== 'available'
|
|
665
|
+
);
|
|
658
666
|
checks.push(createCheck({
|
|
659
667
|
id: 'channel-runtime',
|
|
660
668
|
category: 'Credentials and runtime',
|
|
661
669
|
label: 'Claworld channel runtime account',
|
|
662
|
-
status: channelHealthy ? 'pass' : 'fail',
|
|
670
|
+
status: channelHealthy ? 'pass' : channelPendingActivation ? 'warn' : 'fail',
|
|
663
671
|
summary: channelHealthy
|
|
664
672
|
? `channels status reports managed account \`${configuredAccount.accountId}\` as configured with an available token.`
|
|
665
|
-
:
|
|
666
|
-
|
|
673
|
+
: channelPendingActivation
|
|
674
|
+
? `channels status reports managed account \`${configuredAccount.accountId}\` as configured, but activation is still pending (${channelAccount.tokenStatus}).`
|
|
675
|
+
: `channels status does not report a healthy managed account for \`${configuredAccount.accountId}\`.`,
|
|
676
|
+
action: channelHealthy
|
|
677
|
+
? null
|
|
678
|
+
: channelPendingActivation
|
|
679
|
+
? 'Open a live OpenClaw session, run `claworld_pair_agent`, and then complete `claworld_update_public_identity` when prompted.'
|
|
680
|
+
: `Rerun \`${CLAWORLD_INSTALLER_COMMAND}\` or restart the gateway to recover the managed account runtime.`,
|
|
667
681
|
details: { channelAccount },
|
|
668
682
|
}));
|
|
669
683
|
} catch (error) {
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
normalizeRuntimeBoundaryError,
|
|
53
53
|
serializeRuntimeBoundaryError,
|
|
54
54
|
} from '../../lib/runtime-errors.js';
|
|
55
|
+
import { PUBLIC_IDENTITY_STATUS } from '../../lib/public-identity.js';
|
|
55
56
|
import { v4 as uuidv4 } from 'uuid';
|
|
56
57
|
|
|
57
58
|
function normalizeRelayHttpBaseUrl(serverUrl) {
|
|
@@ -909,6 +910,48 @@ async function fetchPublicIdentity({
|
|
|
909
910
|
agentId = null,
|
|
910
911
|
fetchImpl,
|
|
911
912
|
}) {
|
|
913
|
+
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
914
|
+
const recommendedDisplayName = normalizeClaworldText(
|
|
915
|
+
runtimeConfig?.name,
|
|
916
|
+
normalizeClaworldText(runtimeConfig?.registration?.displayName, null),
|
|
917
|
+
);
|
|
918
|
+
return {
|
|
919
|
+
status: 'pending',
|
|
920
|
+
agentId: normalizeClaworldText(agentId, null),
|
|
921
|
+
ready: false,
|
|
922
|
+
publicIdentity: {
|
|
923
|
+
status: PUBLIC_IDENTITY_STATUS.PENDING,
|
|
924
|
+
displayName: null,
|
|
925
|
+
code: null,
|
|
926
|
+
displayIdentity: null,
|
|
927
|
+
confirmedAt: null,
|
|
928
|
+
updatedAt: null,
|
|
929
|
+
},
|
|
930
|
+
recommendedDisplayName,
|
|
931
|
+
nextAction: 'set_public_identity',
|
|
932
|
+
requiredAction: 'set_public_identity',
|
|
933
|
+
nextTool: 'claworld_update_public_identity',
|
|
934
|
+
missingFields: [
|
|
935
|
+
{
|
|
936
|
+
fieldId: 'displayName',
|
|
937
|
+
label: 'Public Name',
|
|
938
|
+
description: 'A public display name used in Claworld identity surfaces.',
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
fieldId: 'code',
|
|
942
|
+
label: 'Public Code',
|
|
943
|
+
description: 'A system-generated unique suffix used in the public identity.',
|
|
944
|
+
},
|
|
945
|
+
],
|
|
946
|
+
feedbackSummary: {
|
|
947
|
+
totalLikesReceived: 0,
|
|
948
|
+
totalDislikesReceived: 0,
|
|
949
|
+
totalLikesGiven: 0,
|
|
950
|
+
totalDislikesGiven: 0,
|
|
951
|
+
},
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
|
|
912
955
|
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
913
956
|
const path = buildRelayJsonPath('/v1/profile/public-identity', {
|
|
914
957
|
agentId,
|
|
@@ -950,31 +993,85 @@ async function updatePublicIdentity({
|
|
|
950
993
|
context: { field: 'displayName' },
|
|
951
994
|
});
|
|
952
995
|
}
|
|
996
|
+
let resolvedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
|
|
997
|
+
let resolvedAgentId = normalizeClaworldText(agentId, normalizeClaworldText(resolvedRuntimeConfig?.relay?.agentId, null));
|
|
998
|
+
|
|
999
|
+
if (!resolveRuntimeAppToken(resolvedRuntimeConfig)) {
|
|
1000
|
+
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
1001
|
+
const activationResult = await fetchJson(fetchImpl, `${baseUrl}/v1/onboarding/activate`, {
|
|
1002
|
+
method: 'POST',
|
|
1003
|
+
headers: {
|
|
1004
|
+
'content-type': 'application/json',
|
|
1005
|
+
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
1006
|
+
...buildRuntimeAuthHeaders(resolvedRuntimeConfig),
|
|
1007
|
+
},
|
|
1008
|
+
body: JSON.stringify({
|
|
1009
|
+
displayName: normalizedDisplayName,
|
|
1010
|
+
}),
|
|
1011
|
+
});
|
|
1012
|
+
if (!activationResult.ok) {
|
|
1013
|
+
createRelayRouteError({
|
|
1014
|
+
result: activationResult,
|
|
1015
|
+
runtimeConfig: resolvedRuntimeConfig,
|
|
1016
|
+
code: 'claworld_activation_failed',
|
|
1017
|
+
publicMessage: 'failed to activate Claworld account',
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
const activatedToken = normalizeClaworldText(activationResult.body?.appToken, null);
|
|
1021
|
+
const activatedAgentId = normalizeClaworldText(activationResult.body?.agentId, null);
|
|
1022
|
+
if (!activatedToken || !activatedAgentId) {
|
|
1023
|
+
throw createRuntimeBoundaryError({
|
|
1024
|
+
code: 'claworld_activation_failed',
|
|
1025
|
+
category: 'runtime',
|
|
1026
|
+
status: 502,
|
|
1027
|
+
message: 'claworld activation did not return appToken and agentId',
|
|
1028
|
+
publicMessage: 'failed to activate Claworld account',
|
|
1029
|
+
recoverable: true,
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
resolvedRuntimeConfig = applyRuntimeIdentity(resolvedRuntimeConfig, {
|
|
1033
|
+
appToken: activatedToken,
|
|
1034
|
+
relay: {
|
|
1035
|
+
...(resolvedRuntimeConfig?.relay && typeof resolvedRuntimeConfig.relay === 'object' ? resolvedRuntimeConfig.relay : {}),
|
|
1036
|
+
agentId: activatedAgentId,
|
|
1037
|
+
},
|
|
1038
|
+
});
|
|
1039
|
+
resolvedAgentId = activatedAgentId;
|
|
1040
|
+
}
|
|
953
1041
|
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
954
1042
|
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/profile/public-identity`, {
|
|
955
1043
|
method: 'PUT',
|
|
956
1044
|
headers: {
|
|
957
1045
|
'content-type': 'application/json',
|
|
958
|
-
...(
|
|
959
|
-
...buildRuntimeAuthHeaders(
|
|
1046
|
+
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
1047
|
+
...buildRuntimeAuthHeaders(resolvedRuntimeConfig),
|
|
960
1048
|
},
|
|
961
1049
|
body: JSON.stringify({
|
|
962
|
-
...(
|
|
1050
|
+
...(resolvedAgentId ? { agentId: resolvedAgentId } : {}),
|
|
963
1051
|
displayName: normalizedDisplayName,
|
|
964
1052
|
}),
|
|
965
1053
|
});
|
|
966
1054
|
if (!result.ok) {
|
|
967
1055
|
createRelayRouteError({
|
|
968
1056
|
result,
|
|
969
|
-
runtimeConfig,
|
|
1057
|
+
runtimeConfig: resolvedRuntimeConfig,
|
|
970
1058
|
code: 'public_identity_update_failed',
|
|
971
1059
|
publicMessage: 'failed to update public identity',
|
|
972
1060
|
context: {
|
|
973
|
-
agentId:
|
|
1061
|
+
agentId: resolvedAgentId,
|
|
974
1062
|
},
|
|
975
1063
|
});
|
|
976
1064
|
}
|
|
977
|
-
return
|
|
1065
|
+
return {
|
|
1066
|
+
...(result.body || {}),
|
|
1067
|
+
runtimeActivation: !resolveRuntimeAppToken(runtimeConfig)
|
|
1068
|
+
? {
|
|
1069
|
+
status: 'activated',
|
|
1070
|
+
agentId: resolvedAgentId,
|
|
1071
|
+
}
|
|
1072
|
+
: null,
|
|
1073
|
+
runtimeConfig: resolvedRuntimeConfig,
|
|
1074
|
+
};
|
|
978
1075
|
}
|
|
979
1076
|
|
|
980
1077
|
async function registerRelayBinding({ runtimeConfig, fetchImpl, logger }) {
|
|
@@ -1890,6 +1987,18 @@ export function createClaworldChannelPlugin({
|
|
|
1890
1987
|
});
|
|
1891
1988
|
}
|
|
1892
1989
|
|
|
1990
|
+
function rememberAccountBinding({ runtimeConfig, accountId = null, bindingSource = 'binding_cache', relayAgent = null }) {
|
|
1991
|
+
const normalizedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
|
|
1992
|
+
const accountKey = resolveAccountBindingKey(normalizedRuntimeConfig, accountId || null);
|
|
1993
|
+
accountBindingStates.set(accountKey, {
|
|
1994
|
+
binding: {
|
|
1995
|
+
runtimeConfig: normalizedRuntimeConfig,
|
|
1996
|
+
bindingSource,
|
|
1997
|
+
...(relayAgent ? { relayAgent } : {}),
|
|
1998
|
+
},
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
|
|
1893
2002
|
async function ensureAccountRelayBinding({ runtimeConfig, accountId = null }) {
|
|
1894
2003
|
const normalizedRuntimeConfig = applyRuntimeIdentity(runtimeConfig);
|
|
1895
2004
|
const accountKey = resolveAccountBindingKey(normalizedRuntimeConfig, accountId || null);
|
|
@@ -1937,7 +2046,7 @@ export function createClaworldChannelPlugin({
|
|
|
1937
2046
|
return promise;
|
|
1938
2047
|
}
|
|
1939
2048
|
|
|
1940
|
-
async function persistRuntimeAppToken({ runtime, accountId, appToken }) {
|
|
2049
|
+
async function persistRuntimeAppToken({ runtime, accountId, appToken, relayAgentId = null }) {
|
|
1941
2050
|
if (!runtime?.config?.loadConfig || !runtime?.config?.writeConfigFile) {
|
|
1942
2051
|
return { skipped: true, reason: 'missing_runtime_config_io' };
|
|
1943
2052
|
}
|
|
@@ -1960,43 +2069,67 @@ export function createClaworldChannelPlugin({
|
|
|
1960
2069
|
? accounts[accountId]
|
|
1961
2070
|
: {};
|
|
1962
2071
|
|
|
1963
|
-
|
|
2072
|
+
const normalizedRelayAgentId = normalizeClaworldText(relayAgentId, normalizeClaworldText(account?.relay?.agentId, null));
|
|
2073
|
+
const currentAppToken = normalizeClaworldText(account.appToken, null);
|
|
2074
|
+
const currentRelayAgentId = normalizeClaworldText(account?.relay?.agentId, null);
|
|
2075
|
+
if (currentAppToken === appToken && currentRelayAgentId === normalizedRelayAgentId) {
|
|
1964
2076
|
return { skipped: true, reason: 'already_persisted' };
|
|
1965
2077
|
}
|
|
1966
2078
|
|
|
1967
2079
|
accounts[accountId] = {
|
|
1968
2080
|
...account,
|
|
1969
2081
|
appToken,
|
|
2082
|
+
relay: {
|
|
2083
|
+
...(account?.relay && typeof account.relay === 'object' && !Array.isArray(account.relay) ? account.relay : {}),
|
|
2084
|
+
...(normalizedRelayAgentId ? { agentId: normalizedRelayAgentId } : {}),
|
|
2085
|
+
},
|
|
1970
2086
|
};
|
|
2087
|
+
delete accounts[accountId].registration;
|
|
1971
2088
|
claworldRoot.accounts = accounts;
|
|
1972
2089
|
nextCfg.channels.claworld = claworldRoot;
|
|
1973
2090
|
await runtime.config.writeConfigFile(nextCfg);
|
|
1974
2091
|
return { skipped: false, ok: true };
|
|
1975
2092
|
}
|
|
1976
2093
|
|
|
1977
|
-
|
|
2094
|
+
function resolveConfiguredRuntimeContext(context = {}) {
|
|
1978
2095
|
const cfg = context.cfg || {};
|
|
1979
2096
|
const accountId = context.accountId || null;
|
|
1980
2097
|
const runtimeContext = accountRuntimeContexts.get(accountId || 'default') || null;
|
|
1981
|
-
|
|
2098
|
+
const runtimeConfig = runtimeContext?.runtimeConfig || context.runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
2099
|
+
return {
|
|
2100
|
+
...context,
|
|
2101
|
+
cfg: runtimeContext?.cfg || cfg,
|
|
2102
|
+
accountId: runtimeConfig.accountId || accountId || null,
|
|
2103
|
+
runtimeConfig,
|
|
2104
|
+
agentId: context.agentId || runtimeConfig.relay?.agentId || null,
|
|
2105
|
+
bindingSource: runtimeContext?.deferredFailure ? 'runtime_context_deferred' : 'runtime_context',
|
|
2106
|
+
};
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
async function resolveBoundRuntimeContext(context = {}) {
|
|
2110
|
+
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
2111
|
+
const cfg = configuredContext.cfg || {};
|
|
2112
|
+
const accountId = configuredContext.accountId || null;
|
|
2113
|
+
let runtimeConfig = configuredContext.runtimeConfig;
|
|
2114
|
+
const runtimeContext = accountRuntimeContexts.get(accountId || 'default') || null;
|
|
1982
2115
|
if (runtimeContext?.runtimeConfig && !runtimeContext?.deferredFailure) {
|
|
1983
2116
|
return {
|
|
1984
|
-
...
|
|
2117
|
+
...configuredContext,
|
|
1985
2118
|
cfg: runtimeContext.cfg || cfg,
|
|
1986
2119
|
accountId: runtimeConfig.accountId || accountId || null,
|
|
1987
2120
|
runtimeConfig,
|
|
1988
|
-
agentId:
|
|
2121
|
+
agentId: configuredContext.agentId || runtimeConfig.relay?.agentId || null,
|
|
1989
2122
|
bindingSource: 'runtime_context',
|
|
1990
2123
|
};
|
|
1991
2124
|
}
|
|
1992
2125
|
const binding = await ensureAccountRelayBinding({ runtimeConfig, accountId });
|
|
1993
2126
|
runtimeConfig = binding.runtimeConfig;
|
|
1994
2127
|
return {
|
|
1995
|
-
...
|
|
2128
|
+
...configuredContext,
|
|
1996
2129
|
cfg,
|
|
1997
2130
|
accountId: runtimeConfig.accountId || accountId || null,
|
|
1998
2131
|
runtimeConfig,
|
|
1999
|
-
agentId:
|
|
2132
|
+
agentId: configuredContext.agentId || runtimeConfig.relay?.agentId || null,
|
|
2000
2133
|
bindingSource: binding.bindingSource,
|
|
2001
2134
|
};
|
|
2002
2135
|
}
|
|
@@ -2117,6 +2250,7 @@ export function createClaworldChannelPlugin({
|
|
|
2117
2250
|
runtime: pluginRuntime,
|
|
2118
2251
|
accountId: runtimeConfig.accountId,
|
|
2119
2252
|
appToken: resolveRuntimeAppToken(runtimeConfig),
|
|
2253
|
+
relayAgentId: runtimeConfig.relay?.agentId || null,
|
|
2120
2254
|
});
|
|
2121
2255
|
if (!persisted.skipped) {
|
|
2122
2256
|
logger.info?.(`[claworld:${runtimeAccountId}] persisted runtime appToken`, {
|
|
@@ -2304,6 +2438,77 @@ export function createClaworldChannelPlugin({
|
|
|
2304
2438
|
};
|
|
2305
2439
|
}
|
|
2306
2440
|
|
|
2441
|
+
async function getRuntimePublicIdentity(context = {}) {
|
|
2442
|
+
const resolvedContext = resolveConfiguredRuntimeContext(context);
|
|
2443
|
+
return fetchPublicIdentity({
|
|
2444
|
+
runtimeConfig: resolvedContext.runtimeConfig,
|
|
2445
|
+
agentId: resolvedContext.agentId || null,
|
|
2446
|
+
fetchImpl,
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
async function updateRuntimePublicIdentity(context = {}) {
|
|
2451
|
+
const resolvedContext = resolveConfiguredRuntimeContext(context);
|
|
2452
|
+
const updateResult = await updatePublicIdentity({
|
|
2453
|
+
runtimeConfig: resolvedContext.runtimeConfig,
|
|
2454
|
+
agentId: resolvedContext.agentId || null,
|
|
2455
|
+
displayName: context.displayName || null,
|
|
2456
|
+
fetchImpl,
|
|
2457
|
+
});
|
|
2458
|
+
|
|
2459
|
+
const runtimeActivation = updateResult?.runtimeActivation && typeof updateResult.runtimeActivation === 'object'
|
|
2460
|
+
? updateResult.runtimeActivation
|
|
2461
|
+
: null;
|
|
2462
|
+
const nextRuntimeConfig = updateResult?.runtimeConfig && typeof updateResult.runtimeConfig === 'object'
|
|
2463
|
+
? updateResult.runtimeConfig
|
|
2464
|
+
: resolvedContext.runtimeConfig;
|
|
2465
|
+
const nextAgentId = normalizeClaworldText(
|
|
2466
|
+
runtimeActivation?.agentId,
|
|
2467
|
+
normalizeClaworldText(resolvedContext.agentId, normalizeClaworldText(nextRuntimeConfig?.relay?.agentId, null)),
|
|
2468
|
+
);
|
|
2469
|
+
|
|
2470
|
+
if (runtimeActivation && resolveRuntimeAppToken(nextRuntimeConfig)) {
|
|
2471
|
+
const runtimeResolution = resolvePluginRuntimeCandidate(context.runtime || null);
|
|
2472
|
+
try {
|
|
2473
|
+
await persistRuntimeAppToken({
|
|
2474
|
+
runtime: runtimeResolution.runtime,
|
|
2475
|
+
accountId: resolvedContext.accountId || nextRuntimeConfig.accountId || null,
|
|
2476
|
+
appToken: resolveRuntimeAppToken(nextRuntimeConfig),
|
|
2477
|
+
relayAgentId: nextAgentId,
|
|
2478
|
+
});
|
|
2479
|
+
} catch (error) {
|
|
2480
|
+
logger.warn?.('[claworld:profile] failed to persist activated runtime binding', {
|
|
2481
|
+
accountId: resolvedContext.accountId || nextRuntimeConfig.accountId || null,
|
|
2482
|
+
error: error?.message || String(error),
|
|
2483
|
+
});
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
rememberAccountBinding({
|
|
2487
|
+
runtimeConfig: nextRuntimeConfig,
|
|
2488
|
+
accountId: resolvedContext.accountId || nextRuntimeConfig.accountId || null,
|
|
2489
|
+
bindingSource: 'activated_app_token',
|
|
2490
|
+
});
|
|
2491
|
+
|
|
2492
|
+
const accountKey = resolveAccountBindingKey(nextRuntimeConfig, resolvedContext.accountId || null);
|
|
2493
|
+
const currentRuntimeContext = accountRuntimeContexts.get(accountKey) || null;
|
|
2494
|
+
if (currentRuntimeContext) {
|
|
2495
|
+
accountRuntimeContexts.set(accountKey, {
|
|
2496
|
+
...currentRuntimeContext,
|
|
2497
|
+
runtimeConfig: nextRuntimeConfig,
|
|
2498
|
+
deferredFailure: null,
|
|
2499
|
+
deferredErrorMessage: null,
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
const payload = updateResult && typeof updateResult === 'object' && !Array.isArray(updateResult)
|
|
2505
|
+
? { ...updateResult }
|
|
2506
|
+
: {};
|
|
2507
|
+
delete payload.runtimeActivation;
|
|
2508
|
+
delete payload.runtimeConfig;
|
|
2509
|
+
return payload;
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2307
2512
|
return {
|
|
2308
2513
|
id: 'claworld',
|
|
2309
2514
|
meta: {
|
|
@@ -2556,23 +2761,8 @@ export function createClaworldChannelPlugin({
|
|
|
2556
2761
|
},
|
|
2557
2762
|
},
|
|
2558
2763
|
profile: {
|
|
2559
|
-
getPublicIdentity:
|
|
2560
|
-
|
|
2561
|
-
return fetchPublicIdentity({
|
|
2562
|
-
runtimeConfig: resolvedContext.runtimeConfig,
|
|
2563
|
-
agentId: resolvedContext.agentId || null,
|
|
2564
|
-
fetchImpl,
|
|
2565
|
-
});
|
|
2566
|
-
},
|
|
2567
|
-
updatePublicIdentity: async (context = {}) => {
|
|
2568
|
-
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
2569
|
-
return updatePublicIdentity({
|
|
2570
|
-
runtimeConfig: resolvedContext.runtimeConfig,
|
|
2571
|
-
agentId: resolvedContext.agentId || null,
|
|
2572
|
-
displayName: context.displayName || null,
|
|
2573
|
-
fetchImpl,
|
|
2574
|
-
});
|
|
2575
|
-
},
|
|
2764
|
+
getPublicIdentity: getRuntimePublicIdentity,
|
|
2765
|
+
updatePublicIdentity: updateRuntimePublicIdentity,
|
|
2576
2766
|
},
|
|
2577
2767
|
postSetup: {
|
|
2578
2768
|
fetchWorldDirectory: async (context = {}) => {
|
|
@@ -2725,23 +2915,8 @@ export function createClaworldChannelPlugin({
|
|
|
2725
2915
|
demo,
|
|
2726
2916
|
productShell: {
|
|
2727
2917
|
profile: {
|
|
2728
|
-
getPublicIdentity:
|
|
2729
|
-
|
|
2730
|
-
return fetchPublicIdentity({
|
|
2731
|
-
runtimeConfig: resolvedContext.runtimeConfig || null,
|
|
2732
|
-
agentId: resolvedContext.agentId || null,
|
|
2733
|
-
fetchImpl,
|
|
2734
|
-
});
|
|
2735
|
-
},
|
|
2736
|
-
updatePublicIdentity: async (context = {}) => {
|
|
2737
|
-
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
2738
|
-
return updatePublicIdentity({
|
|
2739
|
-
runtimeConfig: resolvedContext.runtimeConfig || null,
|
|
2740
|
-
agentId: resolvedContext.agentId || null,
|
|
2741
|
-
displayName: context.displayName || null,
|
|
2742
|
-
fetchImpl,
|
|
2743
|
-
});
|
|
2744
|
-
},
|
|
2918
|
+
getPublicIdentity: getRuntimePublicIdentity,
|
|
2919
|
+
updatePublicIdentity: updateRuntimePublicIdentity,
|
|
2745
2920
|
},
|
|
2746
2921
|
fetchWorldDirectory: async (context = {}) => {
|
|
2747
2922
|
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
@@ -355,7 +355,7 @@ function buildManagedAccountEntry(options = {}) {
|
|
|
355
355
|
|
|
356
356
|
if (options.appToken) {
|
|
357
357
|
base.appToken = options.appToken;
|
|
358
|
-
} else {
|
|
358
|
+
} else if (normalizeText(options.registrationDisplayName, null)) {
|
|
359
359
|
base.registration = {
|
|
360
360
|
enabled: true,
|
|
361
361
|
displayName: normalizeText(options.registrationDisplayName, options.displayName),
|
|
@@ -404,10 +404,18 @@ function buildMergedAccountEntry(existingAccount = {}, options = {}) {
|
|
|
404
404
|
delete merged.toolProfile;
|
|
405
405
|
|
|
406
406
|
if (options.appToken) {
|
|
407
|
-
|
|
407
|
+
const withToken = {
|
|
408
408
|
...merged,
|
|
409
409
|
appToken: options.appToken,
|
|
410
410
|
};
|
|
411
|
+
delete withToken.registration;
|
|
412
|
+
return withToken;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (!normalizeText(options.registrationDisplayName, null)) {
|
|
416
|
+
const withoutRegistration = { ...merged };
|
|
417
|
+
delete withoutRegistration.registration;
|
|
418
|
+
return withoutRegistration;
|
|
411
419
|
}
|
|
412
420
|
|
|
413
421
|
return {
|
|
@@ -512,7 +520,9 @@ export function buildWorkspaceAgentsContent({
|
|
|
512
520
|
} = {}) {
|
|
513
521
|
const identityLine = appToken
|
|
514
522
|
? '- relay binding is resolved from the configured appToken at runtime'
|
|
515
|
-
:
|
|
523
|
+
: registrationDisplayName
|
|
524
|
+
? '- relay binding is created during runtime bootstrap and persists as backend-issued credentials'
|
|
525
|
+
: '- activation is pending until the user completes Claworld public identity setup';
|
|
516
526
|
|
|
517
527
|
return `# Claworld Channel Agent
|
|
518
528
|
|
|
@@ -522,7 +532,7 @@ Routing contract:
|
|
|
522
532
|
|
|
523
533
|
- local OpenClaw agent id: \`${agentId}\`
|
|
524
534
|
- claworld account id: \`${accountId}\`
|
|
525
|
-
${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : '- credential mode: appToken/manual binding'}
|
|
535
|
+
${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : (appToken ? '- credential mode: appToken/manual binding' : '- credential mode: activation pending')}
|
|
526
536
|
${identityLine}
|
|
527
537
|
${defaultTargetAgentId ? `- default outbound target agentId: \`${defaultTargetAgentId}\`` : '- outbound sends require explicit target agentId inputs'}
|
|
528
538
|
|
|
@@ -553,7 +563,9 @@ export function buildWorkspaceMemoryContent({
|
|
|
553
563
|
} = {}) {
|
|
554
564
|
const identityLine = appToken
|
|
555
565
|
? '- relay binding: resolved from appToken at runtime'
|
|
556
|
-
:
|
|
566
|
+
: registrationDisplayName
|
|
567
|
+
? '- relay binding: assigned during runtime bootstrap'
|
|
568
|
+
: '- relay binding: pending until public identity setup completes';
|
|
557
569
|
|
|
558
570
|
return `# Claworld Memory
|
|
559
571
|
|
|
@@ -661,10 +673,7 @@ export function resolveClaworldManagedRuntimeOptions({
|
|
|
661
673
|
? null
|
|
662
674
|
: normalizeRegistrationDisplayName(
|
|
663
675
|
explicitRegistrationDisplayName,
|
|
664
|
-
|
|
665
|
-
existingRegistrationDisplayName,
|
|
666
|
-
displayName,
|
|
667
|
-
),
|
|
676
|
+
existingRegistrationDisplayName,
|
|
668
677
|
);
|
|
669
678
|
const approvalMode = normalizeChatRequestApprovalMode(
|
|
670
679
|
normalizeText(overrides.approvalMode, null),
|
|
@@ -716,10 +725,6 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
|
|
|
716
725
|
const sessionDmScope = normalizeText(options.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE);
|
|
717
726
|
const manageAgentEntry = options.manageAgentEntry === true;
|
|
718
727
|
|
|
719
|
-
if (!options.appToken && !normalizeText(options.registrationDisplayName, null)) {
|
|
720
|
-
throw new Error('claworld registration displayName is required when appToken is absent');
|
|
721
|
-
}
|
|
722
|
-
|
|
723
728
|
const removedManagedToolNames = new Set([
|
|
724
729
|
...CLAWORLD_PUBLIC_TOOL_NAMES,
|
|
725
730
|
...CLAWORLD_COMPATIBILITY_TOOL_NAMES,
|
|
@@ -84,8 +84,11 @@ function validateClaworldSetupInput({ cfg = {}, accountId = null, input = {} } =
|
|
|
84
84
|
const registrationDisplayName = normalizeText(
|
|
85
85
|
input.name,
|
|
86
86
|
normalizeText(
|
|
87
|
-
inspected?.
|
|
88
|
-
normalizeText(
|
|
87
|
+
inspected?.name,
|
|
88
|
+
normalizeText(
|
|
89
|
+
inspected?.registration?.displayName,
|
|
90
|
+
normalizeText(inspected?.localAgent?.displayName, null),
|
|
91
|
+
),
|
|
89
92
|
),
|
|
90
93
|
);
|
|
91
94
|
if (!appToken && !registrationDisplayName) {
|
|
@@ -105,8 +108,11 @@ function currentManagedIdentityInput({ cfg = {}, accountId = null } = {}) {
|
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
const currentDisplayName = normalizeText(
|
|
108
|
-
inspected?.
|
|
109
|
-
normalizeText(
|
|
111
|
+
inspected?.name,
|
|
112
|
+
normalizeText(
|
|
113
|
+
inspected?.registration?.displayName,
|
|
114
|
+
normalizeText(inspected?.localAgent?.displayName, null),
|
|
115
|
+
),
|
|
110
116
|
);
|
|
111
117
|
return currentDisplayName
|
|
112
118
|
? { name: currentDisplayName }
|
|
@@ -163,11 +169,17 @@ function applyManagedAccountName({ cfg = {}, accountId, name } = {}) {
|
|
|
163
169
|
}
|
|
164
170
|
|
|
165
171
|
function resolveManagedOptionsFromContext({ cfg = {}, accountId = null, input = {}, overrides = {} } = {}) {
|
|
172
|
+
const normalizedInput = ensureObject(input);
|
|
173
|
+
const resolvedInput = { ...normalizedInput };
|
|
174
|
+
delete resolvedInput.name;
|
|
166
175
|
return resolveClaworldManagedRuntimeOptions({
|
|
167
176
|
cfg,
|
|
168
177
|
accountId: normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID),
|
|
169
|
-
input,
|
|
170
|
-
overrides
|
|
178
|
+
input: resolvedInput,
|
|
179
|
+
overrides: {
|
|
180
|
+
...overrides,
|
|
181
|
+
...(normalizeText(normalizedInput.name, null) ? { displayName: normalizedInput.name } : {}),
|
|
182
|
+
},
|
|
171
183
|
});
|
|
172
184
|
}
|
|
173
185
|
|
|
@@ -187,9 +199,9 @@ async function applyManagedOnboardingConfig({
|
|
|
187
199
|
const noteLines = [
|
|
188
200
|
`Bound local agent/account: ${managedOptions.agentId}`,
|
|
189
201
|
`Remote backend: ${managedOptions.serverUrl}`,
|
|
190
|
-
managedOptions.
|
|
191
|
-
?
|
|
192
|
-
: '
|
|
202
|
+
managedOptions.appToken
|
|
203
|
+
? 'Activation state: ready via configured appToken'
|
|
204
|
+
: 'Activation state: pending until claworld_update_public_identity runs',
|
|
193
205
|
managedOptions.manageWorkspace
|
|
194
206
|
? 'This flow refreshes plugin-side config and the dedicated claworld workspace contract. It does not start a backend service.'
|
|
195
207
|
: 'This flow refreshes plugin-side config and binds claworld onto the existing local agent. It does not start a backend service.',
|
|
@@ -178,12 +178,12 @@ function withToolErrorBoundary(toolName, execute) {
|
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
async function resolveToolContext(api, plugin, params = {}) {
|
|
181
|
+
async function resolveToolContext(api, plugin, params = {}, { bindRuntime = true } = {}) {
|
|
182
182
|
const cfg = await loadCurrentConfig(api);
|
|
183
183
|
const accountId = normalizeText(params.accountId, plugin.config.defaultAccountId(cfg) || null);
|
|
184
184
|
const runtimeConfig = plugin.config.resolveRuntimeConfig(cfg, accountId);
|
|
185
185
|
|
|
186
|
-
if (typeof plugin.helpers?.resolveToolRuntimeContext === 'function') {
|
|
186
|
+
if (bindRuntime && typeof plugin.helpers?.resolveToolRuntimeContext === 'function') {
|
|
187
187
|
return await plugin.helpers.resolveToolRuntimeContext({
|
|
188
188
|
cfg,
|
|
189
189
|
accountId,
|
|
@@ -1128,19 +1128,30 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1128
1128
|
runtimeConfig,
|
|
1129
1129
|
});
|
|
1130
1130
|
const pairedAgentId = payload.runtimeConfig?.relay?.agentId || payload.relayAgent?.agentId || null;
|
|
1131
|
-
const publicIdentity =
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1131
|
+
const publicIdentity = await plugin.runtime.productShell.profile.getPublicIdentity({
|
|
1132
|
+
cfg,
|
|
1133
|
+
accountId,
|
|
1134
|
+
runtimeConfig: payload.runtimeConfig || runtimeConfig,
|
|
1135
|
+
agentId: pairedAgentId,
|
|
1136
|
+
});
|
|
1137
|
+
const ready = payload.status === 'paired' && publicIdentity?.ready === true;
|
|
1138
|
+
const readiness = payload.status === 'paired'
|
|
1139
|
+
? (publicIdentity?.ready === true ? 'paired_and_ready' : 'paired_but_identity_pending')
|
|
1140
|
+
: 'installed_unactivated';
|
|
1139
1141
|
return buildToolResult({
|
|
1140
|
-
status:
|
|
1142
|
+
status: ready ? 'ready' : 'pending',
|
|
1143
|
+
ready,
|
|
1144
|
+
readiness,
|
|
1141
1145
|
reason: payload.reason || null,
|
|
1146
|
+
requiredAction: publicIdentity?.requiredAction || (ready ? null : 'set_public_identity'),
|
|
1147
|
+
nextAction: publicIdentity?.nextAction || (ready ? 'continue_claworld_flow' : 'set_public_identity'),
|
|
1148
|
+
nextTool: publicIdentity?.nextTool || (ready ? null : 'claworld_update_public_identity'),
|
|
1149
|
+
missingFields: Array.isArray(publicIdentity?.missingFields) ? publicIdentity.missingFields : [],
|
|
1142
1150
|
accountId: payload.runtimeConfig?.accountId || accountId,
|
|
1143
1151
|
bindingSource: payload.bindingSource || null,
|
|
1152
|
+
activation: {
|
|
1153
|
+
status: payload.status === 'paired' ? 'ready' : 'pending',
|
|
1154
|
+
},
|
|
1144
1155
|
relay: {
|
|
1145
1156
|
agentId: payload.runtimeConfig?.relay?.agentId || payload.relayAgent?.agentId || null,
|
|
1146
1157
|
displayName: payload.relayAgent?.displayName || null,
|
|
@@ -1148,6 +1159,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1148
1159
|
contactable: payload.relayAgent?.contactable ?? null,
|
|
1149
1160
|
online: payload.relayAgent?.online ?? null,
|
|
1150
1161
|
resolved: payload.relayAgent?.resolved ?? null,
|
|
1162
|
+
bindingStatus: payload.status === 'paired' ? 'bound' : 'unactivated',
|
|
1151
1163
|
},
|
|
1152
1164
|
publicIdentity: publicIdentity
|
|
1153
1165
|
? {
|
|
@@ -1192,7 +1204,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1192
1204
|
},
|
|
1193
1205
|
}),
|
|
1194
1206
|
async execute(_toolCallId, params = {}) {
|
|
1195
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
1207
|
+
const context = await resolveToolContext(api, plugin, params, { bindRuntime: false });
|
|
1196
1208
|
const payload = await plugin.runtime.productShell.profile.getPublicIdentity(context);
|
|
1197
1209
|
return buildToolResult(payload);
|
|
1198
1210
|
},
|
|
@@ -1221,7 +1233,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1221
1233
|
},
|
|
1222
1234
|
}),
|
|
1223
1235
|
async execute(_toolCallId, params = {}) {
|
|
1224
|
-
const context = await resolveToolContext(api, plugin, params);
|
|
1236
|
+
const context = await resolveToolContext(api, plugin, params, { bindRuntime: false });
|
|
1225
1237
|
const payload = await plugin.runtime.productShell.profile.updatePublicIdentity({
|
|
1226
1238
|
...context,
|
|
1227
1239
|
displayName: params.displayName,
|
|
@@ -164,9 +164,9 @@ export function createOnboardingService({ worldService, store = null } = {}) {
|
|
|
164
164
|
'installer validates OpenClaw availability and minimum host version',
|
|
165
165
|
'installer verifies or installs the claworld OpenClaw plugin package',
|
|
166
166
|
'installer writes or refreshes the managed claworld channel config and binds it to the local main agent by default',
|
|
167
|
-
'installer
|
|
168
|
-
'
|
|
169
|
-
'
|
|
167
|
+
'installer reloads or starts the runtime and verifies the managed channel shape without requiring backend activation',
|
|
168
|
+
'first-run readiness goes through claworld_pair_agent and then claworld_update_public_identity',
|
|
169
|
+
'claworld_update_public_identity performs activation when needed and completes the public displayName#code identity',
|
|
170
170
|
`ongoing lifecycle uses ${CLAWORLD_UPDATE_COMMAND} for tracked package updates plus managed repair, then ${CLAWORLD_DOCTOR_COMMAND} for health confirmation`,
|
|
171
171
|
],
|
|
172
172
|
recommendedWorlds,
|
|
@@ -182,8 +182,9 @@ export function createOnboardingService({ worldService, store = null } = {}) {
|
|
|
182
182
|
selectedWorld: selectedWorld ? { worldId: selectedWorld.worldId, displayName: selectedWorld.displayName } : null,
|
|
183
183
|
actions: [
|
|
184
184
|
'install the claworld plugin and write the managed config shape',
|
|
185
|
-
'
|
|
186
|
-
'
|
|
185
|
+
'run claworld_pair_agent to confirm readiness after install',
|
|
186
|
+
'if public identity is pending, call claworld_update_public_identity',
|
|
187
|
+
'claworld_update_public_identity activates the backend binding when needed and persists the returned appToken',
|
|
187
188
|
'collect required world profile fields',
|
|
188
189
|
'validate world membership eligibility',
|
|
189
190
|
'start the first A2A loop or deliver world content',
|