@xfxstudio/claworld 2026.6.10-testing.5 → 2026.6.26-testing.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/README.md +16 -9
- package/openclaw.plugin.json +1 -1
- package/package.json +6 -3
- package/skills/claworld-help/SKILL.md +2 -1
- package/skills/claworld-main-session/SKILL.md +0 -2
- package/skills/claworld-manage-worlds/SKILL.md +72 -38
- package/skills/claworld-management-session/SKILL.md +0 -1
- package/src/openclaw/plugin/claworld-channel-plugin.js +323 -62
- package/src/openclaw/plugin/managed-config.js +30 -206
- package/src/openclaw/plugin/onboarding.js +169 -15
- package/src/openclaw/plugin/register-tooling.js +70 -37
- package/src/openclaw/plugin/register.js +95 -92
- package/src/openclaw/runtime/tool-contracts.js +0 -40
- package/src/product-shell/contracts/search-item.js +2 -1
- package/src/openclaw/plugin/conversation-viewer-env.js +0 -67
- package/src/openclaw/plugin/conversation-viewer.js +0 -1547
|
@@ -1303,6 +1303,7 @@ async function fetchPublicIdentity({
|
|
|
1303
1303
|
agentId = null,
|
|
1304
1304
|
generateShareCard = false,
|
|
1305
1305
|
expiresInSeconds = null,
|
|
1306
|
+
shareCardVariant = null,
|
|
1306
1307
|
fetchImpl,
|
|
1307
1308
|
}) {
|
|
1308
1309
|
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
@@ -1361,6 +1362,7 @@ async function fetchPublicIdentity({
|
|
|
1361
1362
|
...(agentId ? { agentId } : {}),
|
|
1362
1363
|
action: 'view',
|
|
1363
1364
|
...(generateShareCard === true ? { generateShareCard: true } : {}),
|
|
1365
|
+
...(normalizeClaworldText(shareCardVariant, null) ? { shareCardVariant: normalizeClaworldText(shareCardVariant, null) } : {}),
|
|
1364
1366
|
...(normalizeClaworldInteger(expiresInSeconds, null) > 0
|
|
1365
1367
|
? { expiresInSeconds: normalizeClaworldInteger(expiresInSeconds, null) }
|
|
1366
1368
|
: {}),
|
|
@@ -1384,6 +1386,7 @@ async function updatePublicIdentity({
|
|
|
1384
1386
|
displayName = null,
|
|
1385
1387
|
generateShareCard = true,
|
|
1386
1388
|
expiresInSeconds = null,
|
|
1389
|
+
shareCardVariant = null,
|
|
1387
1390
|
fetchImpl,
|
|
1388
1391
|
}) {
|
|
1389
1392
|
const normalizedDisplayName = normalizeClaworldText(displayName, null);
|
|
@@ -1402,46 +1405,17 @@ async function updatePublicIdentity({
|
|
|
1402
1405
|
let resolvedAgentId = normalizeClaworldText(agentId, normalizeClaworldText(resolvedRuntimeConfig?.relay?.agentId, null));
|
|
1403
1406
|
|
|
1404
1407
|
if (!resolveRuntimeAppToken(resolvedRuntimeConfig)) {
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
displayName: normalizedDisplayName,
|
|
1415
|
-
}),
|
|
1416
|
-
});
|
|
1417
|
-
if (!activationResult.ok) {
|
|
1418
|
-
createRelayRouteError({
|
|
1419
|
-
result: activationResult,
|
|
1420
|
-
runtimeConfig: resolvedRuntimeConfig,
|
|
1421
|
-
code: 'claworld_activation_failed',
|
|
1422
|
-
publicMessage: 'failed to activate Claworld account',
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
const activatedToken = normalizeClaworldText(activationResult.body?.appToken, null);
|
|
1426
|
-
const activatedAgentId = normalizeClaworldText(activationResult.body?.agentId, null);
|
|
1427
|
-
if (!activatedToken || !activatedAgentId) {
|
|
1428
|
-
throw createRuntimeBoundaryError({
|
|
1429
|
-
code: 'claworld_activation_failed',
|
|
1430
|
-
category: 'runtime',
|
|
1431
|
-
status: 502,
|
|
1432
|
-
message: 'claworld activation did not return appToken and agentId',
|
|
1433
|
-
publicMessage: 'failed to activate Claworld account',
|
|
1434
|
-
recoverable: true,
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
resolvedRuntimeConfig = applyRuntimeIdentity(resolvedRuntimeConfig, {
|
|
1438
|
-
appToken: activatedToken,
|
|
1439
|
-
relay: {
|
|
1440
|
-
...(resolvedRuntimeConfig?.relay && typeof resolvedRuntimeConfig.relay === 'object' ? resolvedRuntimeConfig.relay : {}),
|
|
1441
|
-
agentId: activatedAgentId,
|
|
1408
|
+
throw createRuntimeBoundaryError({
|
|
1409
|
+
code: 'email_verification_required',
|
|
1410
|
+
category: 'auth',
|
|
1411
|
+
status: 401,
|
|
1412
|
+
message: 'claworld email verification is required before updating public identity',
|
|
1413
|
+
publicMessage: 'complete Claworld email verification before updating public identity',
|
|
1414
|
+
recoverable: true,
|
|
1415
|
+
context: {
|
|
1416
|
+
requiredActions: ['start_email_verification', 'complete_email_verification'],
|
|
1442
1417
|
},
|
|
1443
1418
|
});
|
|
1444
|
-
resolvedAgentId = activatedAgentId;
|
|
1445
1419
|
}
|
|
1446
1420
|
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
1447
1421
|
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/profile`, {
|
|
@@ -1457,6 +1431,7 @@ async function updatePublicIdentity({
|
|
|
1457
1431
|
action: 'update_identity',
|
|
1458
1432
|
displayName: normalizedDisplayName,
|
|
1459
1433
|
...(generateShareCard === true ? { generateShareCard: true } : {}),
|
|
1434
|
+
...(normalizeClaworldText(shareCardVariant, null) ? { shareCardVariant: normalizeClaworldText(shareCardVariant, null) } : {}),
|
|
1460
1435
|
...(normalizeClaworldInteger(expiresInSeconds, null) > 0
|
|
1461
1436
|
? { expiresInSeconds: normalizeClaworldInteger(expiresInSeconds, null) }
|
|
1462
1437
|
: {}),
|
|
@@ -1475,9 +1450,9 @@ async function updatePublicIdentity({
|
|
|
1475
1450
|
}
|
|
1476
1451
|
return {
|
|
1477
1452
|
...(result.body || {}),
|
|
1478
|
-
|
|
1453
|
+
runtimeIdentity: !resolveRuntimeAppToken(runtimeConfig)
|
|
1479
1454
|
? {
|
|
1480
|
-
status: '
|
|
1455
|
+
status: 'verified',
|
|
1481
1456
|
agentId: resolvedAgentId,
|
|
1482
1457
|
}
|
|
1483
1458
|
: null,
|
|
@@ -1485,6 +1460,106 @@ async function updatePublicIdentity({
|
|
|
1485
1460
|
};
|
|
1486
1461
|
}
|
|
1487
1462
|
|
|
1463
|
+
async function startEmailVerification({
|
|
1464
|
+
runtimeConfig,
|
|
1465
|
+
email = null,
|
|
1466
|
+
displayName = null,
|
|
1467
|
+
fetchImpl,
|
|
1468
|
+
}) {
|
|
1469
|
+
const normalizedEmail = normalizeClaworldText(email, null);
|
|
1470
|
+
if (!normalizedEmail) {
|
|
1471
|
+
throw createRuntimeBoundaryError({
|
|
1472
|
+
code: 'tool_input_invalid',
|
|
1473
|
+
category: 'input',
|
|
1474
|
+
status: 400,
|
|
1475
|
+
message: 'claworld email verification requires email',
|
|
1476
|
+
publicMessage: 'claworld email verification requires email',
|
|
1477
|
+
recoverable: true,
|
|
1478
|
+
context: { field: 'email' },
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
1482
|
+
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/identity/email/start`, {
|
|
1483
|
+
method: 'POST',
|
|
1484
|
+
headers: {
|
|
1485
|
+
'content-type': 'application/json',
|
|
1486
|
+
...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
|
|
1487
|
+
},
|
|
1488
|
+
body: JSON.stringify({
|
|
1489
|
+
email: normalizedEmail,
|
|
1490
|
+
...(normalizeClaworldText(displayName, null) ? { displayName: normalizeClaworldText(displayName, null) } : {}),
|
|
1491
|
+
}),
|
|
1492
|
+
});
|
|
1493
|
+
if (!result.ok) {
|
|
1494
|
+
createRelayRouteError({
|
|
1495
|
+
result,
|
|
1496
|
+
runtimeConfig,
|
|
1497
|
+
code: 'email_verification_start_failed',
|
|
1498
|
+
publicMessage: 'failed to start Claworld email verification',
|
|
1499
|
+
context: { email: normalizedEmail },
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
const payload = result.body && typeof result.body === 'object' && !Array.isArray(result.body)
|
|
1503
|
+
? { ...result.body }
|
|
1504
|
+
: {};
|
|
1505
|
+
delete payload.verificationId;
|
|
1506
|
+
return payload;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
async function completeEmailVerification({
|
|
1510
|
+
runtimeConfig,
|
|
1511
|
+
email = null,
|
|
1512
|
+
code = null,
|
|
1513
|
+
fetchImpl,
|
|
1514
|
+
}) {
|
|
1515
|
+
const normalizedEmail = normalizeClaworldText(email, null);
|
|
1516
|
+
const normalizedCode = normalizeClaworldText(code, null);
|
|
1517
|
+
if (!normalizedEmail) {
|
|
1518
|
+
throw createRuntimeBoundaryError({
|
|
1519
|
+
code: 'tool_input_invalid',
|
|
1520
|
+
category: 'input',
|
|
1521
|
+
status: 400,
|
|
1522
|
+
message: 'claworld email verification requires email',
|
|
1523
|
+
publicMessage: 'claworld email verification requires email',
|
|
1524
|
+
recoverable: true,
|
|
1525
|
+
context: { field: 'email' },
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
if (!normalizedCode) {
|
|
1529
|
+
throw createRuntimeBoundaryError({
|
|
1530
|
+
code: 'tool_input_invalid',
|
|
1531
|
+
category: 'input',
|
|
1532
|
+
status: 400,
|
|
1533
|
+
message: 'claworld email verification requires code',
|
|
1534
|
+
publicMessage: 'claworld email verification requires code',
|
|
1535
|
+
recoverable: true,
|
|
1536
|
+
context: { field: 'code' },
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
1540
|
+
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/identity/email/verify`, {
|
|
1541
|
+
method: 'POST',
|
|
1542
|
+
headers: {
|
|
1543
|
+
'content-type': 'application/json',
|
|
1544
|
+
...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
|
|
1545
|
+
},
|
|
1546
|
+
body: JSON.stringify({
|
|
1547
|
+
email: normalizedEmail,
|
|
1548
|
+
code: normalizedCode,
|
|
1549
|
+
}),
|
|
1550
|
+
});
|
|
1551
|
+
if (!result.ok) {
|
|
1552
|
+
createRelayRouteError({
|
|
1553
|
+
result,
|
|
1554
|
+
runtimeConfig,
|
|
1555
|
+
code: 'email_verification_complete_failed',
|
|
1556
|
+
publicMessage: 'failed to complete Claworld email verification',
|
|
1557
|
+
context: { email: normalizedEmail },
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
return result.body || {};
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1488
1563
|
async function updateChatRequestApprovalPolicy({
|
|
1489
1564
|
runtimeConfig,
|
|
1490
1565
|
agentId = null,
|
|
@@ -1493,11 +1568,11 @@ async function updateChatRequestApprovalPolicy({
|
|
|
1493
1568
|
}) {
|
|
1494
1569
|
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
1495
1570
|
throw createRuntimeBoundaryError({
|
|
1496
|
-
code: '
|
|
1571
|
+
code: 'claworld_identity_unverified',
|
|
1497
1572
|
category: 'conflict',
|
|
1498
1573
|
status: 409,
|
|
1499
|
-
message: 'claworld
|
|
1500
|
-
publicMessage: '
|
|
1574
|
+
message: 'claworld email verification must be completed before updating chat policy',
|
|
1575
|
+
publicMessage: 'complete Claworld email verification before changing chat policy',
|
|
1501
1576
|
recoverable: true,
|
|
1502
1577
|
});
|
|
1503
1578
|
}
|
|
@@ -1540,11 +1615,11 @@ async function updateGlobalProfile({
|
|
|
1540
1615
|
}) {
|
|
1541
1616
|
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
1542
1617
|
throw createRuntimeBoundaryError({
|
|
1543
|
-
code: '
|
|
1618
|
+
code: 'claworld_identity_unverified',
|
|
1544
1619
|
category: 'conflict',
|
|
1545
1620
|
status: 409,
|
|
1546
|
-
message: 'claworld
|
|
1547
|
-
publicMessage: '
|
|
1621
|
+
message: 'claworld email verification must be completed before updating profile',
|
|
1622
|
+
publicMessage: 'complete Claworld email verification before updating profile',
|
|
1548
1623
|
recoverable: true,
|
|
1549
1624
|
});
|
|
1550
1625
|
}
|
|
@@ -1689,15 +1764,16 @@ async function executeRuntimeAccountAction({
|
|
|
1689
1764
|
proactivitySettings = undefined,
|
|
1690
1765
|
generateShareCard = false,
|
|
1691
1766
|
expiresInSeconds = null,
|
|
1767
|
+
shareCardVariant = null,
|
|
1692
1768
|
fetchImpl,
|
|
1693
1769
|
}) {
|
|
1694
1770
|
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
1695
1771
|
throw createRuntimeBoundaryError({
|
|
1696
|
-
code: '
|
|
1772
|
+
code: 'claworld_identity_unverified',
|
|
1697
1773
|
category: 'conflict',
|
|
1698
1774
|
status: 409,
|
|
1699
|
-
message: 'claworld
|
|
1700
|
-
publicMessage: '
|
|
1775
|
+
message: 'claworld email verification must be completed before managing account settings',
|
|
1776
|
+
publicMessage: 'complete Claworld email verification before changing account settings',
|
|
1701
1777
|
recoverable: true,
|
|
1702
1778
|
});
|
|
1703
1779
|
}
|
|
@@ -1723,6 +1799,7 @@ async function executeRuntimeAccountAction({
|
|
|
1723
1799
|
...(chatRequestApprovalPolicy ? { chatRequestApprovalPolicy } : {}),
|
|
1724
1800
|
...(proactivitySettings !== undefined ? { proactivitySettings } : {}),
|
|
1725
1801
|
...(generateShareCard === true ? { generateShareCard: true } : {}),
|
|
1802
|
+
...(normalizeClaworldText(shareCardVariant, null) ? { shareCardVariant: normalizeClaworldText(shareCardVariant, null) } : {}),
|
|
1726
1803
|
...(normalizeClaworldInteger(expiresInSeconds, null) > 0
|
|
1727
1804
|
? { expiresInSeconds: normalizeClaworldInteger(expiresInSeconds, null) }
|
|
1728
1805
|
: {}),
|
|
@@ -3242,14 +3319,27 @@ export function createClaworldChannelPlugin({
|
|
|
3242
3319
|
}
|
|
3243
3320
|
|
|
3244
3321
|
function mergeBoundRuntimeConfig(currentRuntimeConfig = {}, boundRuntimeConfig = {}) {
|
|
3322
|
+
const currentRelay = currentRuntimeConfig?.relay && typeof currentRuntimeConfig.relay === 'object'
|
|
3323
|
+
? currentRuntimeConfig.relay
|
|
3324
|
+
: {};
|
|
3325
|
+
const boundRelay = boundRuntimeConfig?.relay && typeof boundRuntimeConfig.relay === 'object'
|
|
3326
|
+
? boundRuntimeConfig.relay
|
|
3327
|
+
: {};
|
|
3328
|
+
const appToken = resolveRuntimeAppToken(currentRuntimeConfig) || resolveRuntimeAppToken(boundRuntimeConfig);
|
|
3329
|
+
const agentId = normalizeClaworldText(currentRelay.agentId, normalizeClaworldText(boundRelay.agentId, null));
|
|
3330
|
+
|
|
3245
3331
|
return applyRuntimeIdentity({
|
|
3246
|
-
...currentRuntimeConfig,
|
|
3247
3332
|
...boundRuntimeConfig,
|
|
3333
|
+
...currentRuntimeConfig,
|
|
3334
|
+
appToken,
|
|
3248
3335
|
relay: {
|
|
3249
|
-
...
|
|
3250
|
-
...
|
|
3336
|
+
...boundRelay,
|
|
3337
|
+
...currentRelay,
|
|
3338
|
+
appToken,
|
|
3339
|
+
credentialToken: appToken,
|
|
3340
|
+
agentId,
|
|
3251
3341
|
},
|
|
3252
|
-
});
|
|
3342
|
+
}, { appToken, agentId });
|
|
3253
3343
|
}
|
|
3254
3344
|
|
|
3255
3345
|
function rememberAccountBinding({ runtimeConfig, accountId = null, bindingSource = 'binding_cache', relayAgent = null }) {
|
|
@@ -3270,10 +3360,14 @@ export function createClaworldChannelPlugin({
|
|
|
3270
3360
|
const cachedState = accountBindingStates.get(accountKey) || null;
|
|
3271
3361
|
const cachedBinding = cachedState?.binding || null;
|
|
3272
3362
|
|
|
3363
|
+
const normalizedAppToken = resolveRuntimeAppToken(normalizedRuntimeConfig);
|
|
3364
|
+
const cachedAppToken = resolveRuntimeAppToken(cachedBinding?.runtimeConfig || {});
|
|
3365
|
+
|
|
3273
3366
|
if (
|
|
3274
3367
|
cachedBinding
|
|
3275
3368
|
&& cachedBinding.runtimeConfig?.serverUrl
|
|
3276
3369
|
&& cachedBinding.runtimeConfig.serverUrl === normalizedRuntimeConfig.serverUrl
|
|
3370
|
+
&& (!normalizedAppToken || cachedAppToken === normalizedAppToken)
|
|
3277
3371
|
) {
|
|
3278
3372
|
return {
|
|
3279
3373
|
...cachedBinding,
|
|
@@ -3488,7 +3582,7 @@ export function createClaworldChannelPlugin({
|
|
|
3488
3582
|
method: 'loadConfig_writeConfigFile',
|
|
3489
3583
|
};
|
|
3490
3584
|
if (!mutationOutcome.skipped) {
|
|
3491
|
-
await runtime.config.writeConfigFile(nextCfg);
|
|
3585
|
+
await runtime.config.writeConfigFile(nextCfg, { afterWrite: { mode: 'auto' } });
|
|
3492
3586
|
}
|
|
3493
3587
|
}
|
|
3494
3588
|
} catch (error) {
|
|
@@ -3972,11 +4066,12 @@ export function createClaworldChannelPlugin({
|
|
|
3972
4066
|
agentId: resolvedContext.agentId || null,
|
|
3973
4067
|
generateShareCard: context.generateShareCard === true,
|
|
3974
4068
|
expiresInSeconds: context.expiresInSeconds ?? null,
|
|
4069
|
+
shareCardVariant: context.shareCardVariant ?? null,
|
|
3975
4070
|
fetchImpl,
|
|
3976
4071
|
});
|
|
3977
4072
|
}
|
|
3978
4073
|
|
|
3979
|
-
async function updateRuntimePublicIdentity(context = {}) {
|
|
4074
|
+
async function updateRuntimePublicIdentity(context = {}) {
|
|
3980
4075
|
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
3981
4076
|
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
3982
4077
|
const updateResult = await updatePublicIdentity({
|
|
@@ -3985,17 +4080,18 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
3985
4080
|
displayName: context.displayName || null,
|
|
3986
4081
|
generateShareCard: context.generateShareCard !== false,
|
|
3987
4082
|
expiresInSeconds: context.expiresInSeconds ?? null,
|
|
4083
|
+
shareCardVariant: context.shareCardVariant ?? null,
|
|
3988
4084
|
fetchImpl,
|
|
3989
4085
|
});
|
|
3990
4086
|
|
|
3991
|
-
const
|
|
3992
|
-
? updateResult.
|
|
4087
|
+
const runtimeIdentity = updateResult?.runtimeIdentity && typeof updateResult.runtimeIdentity === 'object'
|
|
4088
|
+
? updateResult.runtimeIdentity
|
|
3993
4089
|
: null;
|
|
3994
4090
|
const nextRuntimeConfig = updateResult?.runtimeConfig && typeof updateResult.runtimeConfig === 'object'
|
|
3995
4091
|
? updateResult.runtimeConfig
|
|
3996
4092
|
: resolvedContext.runtimeConfig;
|
|
3997
4093
|
const nextAgentId = normalizeClaworldText(
|
|
3998
|
-
|
|
4094
|
+
runtimeIdentity?.agentId,
|
|
3999
4095
|
normalizeClaworldText(
|
|
4000
4096
|
updateResult?.agentId,
|
|
4001
4097
|
null,
|
|
@@ -4018,7 +4114,7 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
4018
4114
|
nextAppToken
|
|
4019
4115
|
&& nextAgentId
|
|
4020
4116
|
&& (
|
|
4021
|
-
|
|
4117
|
+
runtimeIdentity
|
|
4022
4118
|
|| configuredAppToken !== nextAppToken
|
|
4023
4119
|
|| previousAgentId !== nextAgentId
|
|
4024
4120
|
),
|
|
@@ -4035,7 +4131,7 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
4035
4131
|
runtimeConfig: boundRuntimeConfig,
|
|
4036
4132
|
});
|
|
4037
4133
|
} catch (error) {
|
|
4038
|
-
logger.warn?.('[claworld:profile] failed to persist
|
|
4134
|
+
logger.warn?.('[claworld:profile] failed to persist verified runtime binding', {
|
|
4039
4135
|
accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
|
|
4040
4136
|
error: error?.message || String(error),
|
|
4041
4137
|
});
|
|
@@ -4044,8 +4140,8 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
4044
4140
|
rememberAccountBinding({
|
|
4045
4141
|
runtimeConfig: boundRuntimeConfig,
|
|
4046
4142
|
accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
|
|
4047
|
-
bindingSource:
|
|
4048
|
-
? '
|
|
4143
|
+
bindingSource: runtimeIdentity
|
|
4144
|
+
? 'verified_app_token'
|
|
4049
4145
|
: (resolvedContext.bindingSource || 'configured_app_token'),
|
|
4050
4146
|
});
|
|
4051
4147
|
|
|
@@ -4068,6 +4164,158 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
4068
4164
|
return payload;
|
|
4069
4165
|
}
|
|
4070
4166
|
|
|
4167
|
+
async function startRuntimeEmailVerification(context = {}) {
|
|
4168
|
+
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
4169
|
+
return startEmailVerification({
|
|
4170
|
+
runtimeConfig: configuredContext.runtimeConfig,
|
|
4171
|
+
email: context.email || null,
|
|
4172
|
+
displayName: context.displayName || null,
|
|
4173
|
+
fetchImpl,
|
|
4174
|
+
});
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
function projectRuntimeCredentialPersistence(persistence = {}) {
|
|
4178
|
+
if (!persistence || typeof persistence !== 'object' || Array.isArray(persistence)) {
|
|
4179
|
+
return { status: 'unknown' };
|
|
4180
|
+
}
|
|
4181
|
+
const skipped = persistence?.skipped === true;
|
|
4182
|
+
return {
|
|
4183
|
+
status: skipped ? 'best_effort' : 'saved',
|
|
4184
|
+
method: normalizeClaworldText(persistence?.method, null),
|
|
4185
|
+
reason: skipped ? normalizeClaworldText(persistence?.reason, null) : null,
|
|
4186
|
+
backupStatus: persistence?.backup?.skipped === true
|
|
4187
|
+
? 'best_effort'
|
|
4188
|
+
: (persistence?.backup?.ok === true ? 'saved' : null),
|
|
4189
|
+
restartRequired: false,
|
|
4190
|
+
reloadRequired: !skipped,
|
|
4191
|
+
reloadMode: skipped ? null : 'openclaw_channel_hot_reload',
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4195
|
+
async function completeRuntimeEmailVerification(context = {}) {
|
|
4196
|
+
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
4197
|
+
const verification = await completeEmailVerification({
|
|
4198
|
+
runtimeConfig: configuredContext.runtimeConfig,
|
|
4199
|
+
email: context.email || null,
|
|
4200
|
+
code: context.code || null,
|
|
4201
|
+
fetchImpl,
|
|
4202
|
+
});
|
|
4203
|
+
const appToken = normalizeClaworldText(verification?.appToken, null);
|
|
4204
|
+
const agentId = normalizeClaworldText(verification?.agentId, null);
|
|
4205
|
+
if (!appToken || !agentId) {
|
|
4206
|
+
throw createRuntimeBoundaryError({
|
|
4207
|
+
code: 'email_verification_complete_failed',
|
|
4208
|
+
category: 'runtime',
|
|
4209
|
+
status: 502,
|
|
4210
|
+
message: 'claworld email verification did not return appToken and agentId',
|
|
4211
|
+
publicMessage: 'failed to complete Claworld email verification',
|
|
4212
|
+
recoverable: true,
|
|
4213
|
+
});
|
|
4214
|
+
}
|
|
4215
|
+
|
|
4216
|
+
const boundRuntimeConfig = applyRuntimeIdentity(configuredContext.runtimeConfig, {
|
|
4217
|
+
appToken,
|
|
4218
|
+
agentId,
|
|
4219
|
+
});
|
|
4220
|
+
const accountId = configuredContext.accountId || boundRuntimeConfig.accountId || null;
|
|
4221
|
+
const runtimeResolution = resolvePluginRuntimeCandidate(context.runtime || null);
|
|
4222
|
+
let persistence = null;
|
|
4223
|
+
try {
|
|
4224
|
+
persistence = await persistRuntimeAppToken({
|
|
4225
|
+
runtime: runtimeResolution.runtime,
|
|
4226
|
+
accountId,
|
|
4227
|
+
appToken,
|
|
4228
|
+
relayAgentId: agentId,
|
|
4229
|
+
runtimeConfig: boundRuntimeConfig,
|
|
4230
|
+
});
|
|
4231
|
+
} catch (error) {
|
|
4232
|
+
persistence = {
|
|
4233
|
+
skipped: true,
|
|
4234
|
+
reason: 'persist_runtime_binding_failed',
|
|
4235
|
+
error: error?.message || String(error),
|
|
4236
|
+
};
|
|
4237
|
+
logger.warn?.('[claworld:identity] failed to persist email verification runtime binding', {
|
|
4238
|
+
accountId,
|
|
4239
|
+
error: persistence.error,
|
|
4240
|
+
});
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
rememberAccountBinding({
|
|
4244
|
+
runtimeConfig: boundRuntimeConfig,
|
|
4245
|
+
accountId,
|
|
4246
|
+
bindingSource: 'email_verification',
|
|
4247
|
+
});
|
|
4248
|
+
|
|
4249
|
+
const accountKey = resolveAccountBindingKey(boundRuntimeConfig, accountId);
|
|
4250
|
+
const currentRuntimeContext = accountRuntimeContexts.get(accountKey) || null;
|
|
4251
|
+
if (currentRuntimeContext) {
|
|
4252
|
+
accountRuntimeContexts.set(accountKey, {
|
|
4253
|
+
...currentRuntimeContext,
|
|
4254
|
+
runtimeConfig: boundRuntimeConfig,
|
|
4255
|
+
deferredFailure: null,
|
|
4256
|
+
deferredErrorMessage: null,
|
|
4257
|
+
});
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
const payload = verification && typeof verification === 'object' && !Array.isArray(verification)
|
|
4261
|
+
? { ...verification }
|
|
4262
|
+
: {};
|
|
4263
|
+
delete payload.appToken;
|
|
4264
|
+
delete payload.credential;
|
|
4265
|
+
const credentialPersistence = projectRuntimeCredentialPersistence(persistence);
|
|
4266
|
+
return {
|
|
4267
|
+
...payload,
|
|
4268
|
+
credentialPersistence,
|
|
4269
|
+
runtimeIdentity: {
|
|
4270
|
+
status: 'verified',
|
|
4271
|
+
agentId,
|
|
4272
|
+
created: verification?.created === true,
|
|
4273
|
+
recovered: verification?.recovered === true,
|
|
4274
|
+
bindingSource: 'email_verification',
|
|
4275
|
+
},
|
|
4276
|
+
runtimeBinding: {
|
|
4277
|
+
status: 'bound',
|
|
4278
|
+
accountId,
|
|
4279
|
+
agentId,
|
|
4280
|
+
bindingSource: 'email_verification',
|
|
4281
|
+
credentialPersistence,
|
|
4282
|
+
},
|
|
4283
|
+
};
|
|
4284
|
+
}
|
|
4285
|
+
|
|
4286
|
+
async function getRuntimeIdentityStatus(context = {}) {
|
|
4287
|
+
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
4288
|
+
const runtimeConfig = applyRuntimeIdentity(configuredContext.runtimeConfig);
|
|
4289
|
+
const agentId = normalizeClaworldText(
|
|
4290
|
+
context.agentId,
|
|
4291
|
+
normalizeClaworldText(runtimeConfig?.relay?.agentId, null),
|
|
4292
|
+
);
|
|
4293
|
+
if (!resolveRuntimeAppToken(runtimeConfig)) {
|
|
4294
|
+
return { emailVerified: false, reason: 'missing_app_token' };
|
|
4295
|
+
}
|
|
4296
|
+
if (!agentId) {
|
|
4297
|
+
return { emailVerified: false, reason: 'agent_id_required' };
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4300
|
+
const accountView = await executeRuntimeAccountAction({
|
|
4301
|
+
runtimeConfig,
|
|
4302
|
+
agentId,
|
|
4303
|
+
action: 'view_account',
|
|
4304
|
+
generateShareCard: false,
|
|
4305
|
+
fetchImpl,
|
|
4306
|
+
});
|
|
4307
|
+
const account = accountView?.account && typeof accountView.account === 'object' && !Array.isArray(accountView.account)
|
|
4308
|
+
? accountView.account
|
|
4309
|
+
: {};
|
|
4310
|
+
const emailVerified = account.emailVerified === true;
|
|
4311
|
+
return {
|
|
4312
|
+
emailVerified,
|
|
4313
|
+
email: normalizeClaworldText(account.email, null),
|
|
4314
|
+
verifiedAt: normalizeClaworldText(account.verifiedAt, null),
|
|
4315
|
+
reason: emailVerified ? null : 'no_email_identity',
|
|
4316
|
+
};
|
|
4317
|
+
}
|
|
4318
|
+
|
|
4071
4319
|
async function updateRuntimeChatRequestApprovalPolicy(context = {}) {
|
|
4072
4320
|
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
4073
4321
|
return updateChatRequestApprovalPolicy({
|
|
@@ -4097,6 +4345,7 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
4097
4345
|
agentId: context.agentId || resolvedContext.agentId || null,
|
|
4098
4346
|
generateShareCard: true,
|
|
4099
4347
|
expiresInSeconds: context.expiresInSeconds ?? null,
|
|
4348
|
+
shareCardVariant: context.shareCardVariant ?? null,
|
|
4100
4349
|
fetchImpl,
|
|
4101
4350
|
});
|
|
4102
4351
|
return result?.shareCard || {};
|
|
@@ -4369,6 +4618,7 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
4369
4618
|
proactivitySettings: Object.prototype.hasOwnProperty.call(context, 'proactivitySettings') ? context.proactivitySettings : undefined,
|
|
4370
4619
|
generateShareCard: context.generateShareCard === true,
|
|
4371
4620
|
expiresInSeconds: context.expiresInSeconds ?? null,
|
|
4621
|
+
shareCardVariant: context.shareCardVariant ?? null,
|
|
4372
4622
|
fetchImpl,
|
|
4373
4623
|
});
|
|
4374
4624
|
},
|
|
@@ -4377,6 +4627,11 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
4377
4627
|
updateChatRequestApprovalPolicy: updateRuntimeChatRequestApprovalPolicy,
|
|
4378
4628
|
generateShareCard: generateRuntimeProfileCard,
|
|
4379
4629
|
},
|
|
4630
|
+
identity: {
|
|
4631
|
+
startEmailVerification: startRuntimeEmailVerification,
|
|
4632
|
+
completeEmailVerification: completeRuntimeEmailVerification,
|
|
4633
|
+
getIdentityStatus: getRuntimeIdentityStatus,
|
|
4634
|
+
},
|
|
4380
4635
|
postSetup: {
|
|
4381
4636
|
fetchWorldDirectory: async (context = {}) => {
|
|
4382
4637
|
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
@@ -4752,6 +5007,7 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
4752
5007
|
proactivitySettings: Object.prototype.hasOwnProperty.call(context, 'proactivitySettings') ? context.proactivitySettings : undefined,
|
|
4753
5008
|
generateShareCard: context.generateShareCard === true,
|
|
4754
5009
|
expiresInSeconds: context.expiresInSeconds ?? null,
|
|
5010
|
+
shareCardVariant: context.shareCardVariant ?? null,
|
|
4755
5011
|
fetchImpl,
|
|
4756
5012
|
});
|
|
4757
5013
|
},
|
|
@@ -4760,6 +5016,11 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
4760
5016
|
updateChatRequestApprovalPolicy: updateRuntimeChatRequestApprovalPolicy,
|
|
4761
5017
|
generateShareCard: generateRuntimeProfileCard,
|
|
4762
5018
|
},
|
|
5019
|
+
identity: {
|
|
5020
|
+
startEmailVerification: startRuntimeEmailVerification,
|
|
5021
|
+
completeEmailVerification: completeRuntimeEmailVerification,
|
|
5022
|
+
getIdentityStatus: getRuntimeIdentityStatus,
|
|
5023
|
+
},
|
|
4763
5024
|
fetchWorldDirectory: async (context = {}) => {
|
|
4764
5025
|
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
4765
5026
|
return fetchPostSetupWorldDirectory({
|