@xfxstudio/claworld 2026.6.10 → 2026.6.29-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 +13 -9
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/claworld-help/SKILL.md +5 -4
- package/skills/claworld-manage-worlds/SKILL.md +72 -38
- package/src/openclaw/plugin/claworld-channel-plugin.js +302 -55
- package/src/openclaw/plugin/managed-config.js +19 -15
- package/src/openclaw/plugin/onboarding.js +167 -14
- package/src/openclaw/plugin/register-tooling.js +67 -25
- package/src/openclaw/plugin/register.js +80 -23
- package/src/product-shell/contracts/search-item.js +2 -1
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
inspectClaworldChannelAccount,
|
|
11
11
|
listClaworldAccountIds,
|
|
12
12
|
} from './config-schema.js';
|
|
13
|
+
import {
|
|
14
|
+
fetchJson,
|
|
15
|
+
normalizeRelayHttpBaseUrl,
|
|
16
|
+
} from '../runtime/http-boundary.js';
|
|
13
17
|
|
|
14
18
|
function collectUnsupportedSetupFlags(input = {}) {
|
|
15
19
|
const unsupported = [];
|
|
@@ -102,7 +106,7 @@ function hasClaworldBinding(config = {}, { agentId, accountId } = {}) {
|
|
|
102
106
|
});
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
function
|
|
109
|
+
function hasRuntimeCredential(account = {}) {
|
|
106
110
|
return Boolean(
|
|
107
111
|
account?.configured
|
|
108
112
|
&& normalizeText(account?.appToken, null),
|
|
@@ -129,7 +133,7 @@ export function inspectManagedClaworldInstall({
|
|
|
129
133
|
const accountStatus = managedAccountPresent
|
|
130
134
|
? inspectClaworldChannelAccount(cfg, managedOptions.accountId)
|
|
131
135
|
: inspectClaworldChannelAccount({}, managedOptions.accountId);
|
|
132
|
-
const
|
|
136
|
+
const runtimeCredentialReady = hasRuntimeCredential(accountStatus);
|
|
133
137
|
const setupReady = Boolean(
|
|
134
138
|
managedAccountPresent
|
|
135
139
|
&& managedBindingPresent
|
|
@@ -139,13 +143,13 @@ export function inspectManagedClaworldInstall({
|
|
|
139
143
|
let selectionHint = 'remote relay world channel';
|
|
140
144
|
let quickstartScore = 5;
|
|
141
145
|
|
|
142
|
-
if (setupReady &&
|
|
146
|
+
if (setupReady && runtimeCredentialReady) {
|
|
143
147
|
statusLabel = 'configured';
|
|
144
148
|
selectionHint = 'configured · ready';
|
|
145
149
|
quickstartScore = 2;
|
|
146
150
|
} else if (setupReady) {
|
|
147
|
-
statusLabel = 'configured (
|
|
148
|
-
selectionHint = 'configured ·
|
|
151
|
+
statusLabel = 'configured (email verification pending)';
|
|
152
|
+
selectionHint = 'configured · email verification pending';
|
|
149
153
|
quickstartScore = 3;
|
|
150
154
|
} else if (managedAccountPresent && !managedBindingPresent) {
|
|
151
155
|
statusLabel = 'configured (binding pending)';
|
|
@@ -166,7 +170,7 @@ export function inspectManagedClaworldInstall({
|
|
|
166
170
|
managedAgentPresent,
|
|
167
171
|
managedBindingPresent,
|
|
168
172
|
accountStatus,
|
|
169
|
-
|
|
173
|
+
runtimeCredentialReady,
|
|
170
174
|
setupReady,
|
|
171
175
|
statusLabel,
|
|
172
176
|
selectionHint,
|
|
@@ -184,7 +188,7 @@ export function buildClaworldOnboardingStatus({
|
|
|
184
188
|
statusLines: [`Claworld: ${inspection.statusLabel}`],
|
|
185
189
|
selectionHint: inspection.selectionHint,
|
|
186
190
|
quickstartScore: inspection.quickstartScore,
|
|
187
|
-
|
|
191
|
+
runtimeCredentialReady: inspection.runtimeCredentialReady,
|
|
188
192
|
};
|
|
189
193
|
}
|
|
190
194
|
|
|
@@ -231,25 +235,172 @@ function resolveManagedOptionsFromContext({ cfg = {}, accountId = null, input =
|
|
|
231
235
|
});
|
|
232
236
|
}
|
|
233
237
|
|
|
238
|
+
function resolveSetupFetchImpl(runtime = {}) {
|
|
239
|
+
const candidate = runtime?.fetchImpl
|
|
240
|
+
|| runtime?.fetch
|
|
241
|
+
|| (typeof globalThis.fetch === 'function' ? globalThis.fetch : null);
|
|
242
|
+
if (typeof candidate !== 'function') {
|
|
243
|
+
throw new Error('Claworld setup requires fetch support to complete email verification.');
|
|
244
|
+
}
|
|
245
|
+
return (url, init) => candidate(url, init);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function validateSetupEmail(value) {
|
|
249
|
+
const normalized = normalizeText(value, null);
|
|
250
|
+
if (!normalized) return 'Email is required.';
|
|
251
|
+
if (!normalized.includes('@')) return 'Enter a valid email address.';
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function validateSetupVerificationCode(value) {
|
|
256
|
+
return normalizeText(value, null) ? null : 'Verification code is required.';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function formatSetupApiError(result, fallbackMessage) {
|
|
260
|
+
const body = ensureObject(result?.body);
|
|
261
|
+
const detail = normalizeText(
|
|
262
|
+
body.publicMessage,
|
|
263
|
+
normalizeText(body.error, normalizeText(body.message, null)),
|
|
264
|
+
);
|
|
265
|
+
return detail ? `${fallbackMessage}: ${detail}` : fallbackMessage;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function startSetupEmailVerification({
|
|
269
|
+
runtimeConfig,
|
|
270
|
+
email,
|
|
271
|
+
displayName = null,
|
|
272
|
+
fetchImpl,
|
|
273
|
+
} = {}) {
|
|
274
|
+
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
275
|
+
const normalizedEmail = normalizeText(email, null);
|
|
276
|
+
const normalizedDisplayName = normalizeText(displayName, null);
|
|
277
|
+
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/identity/email/start`, {
|
|
278
|
+
method: 'POST',
|
|
279
|
+
headers: {
|
|
280
|
+
'content-type': 'application/json',
|
|
281
|
+
...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
|
|
282
|
+
},
|
|
283
|
+
body: JSON.stringify({
|
|
284
|
+
email: normalizedEmail,
|
|
285
|
+
...(normalizedDisplayName ? { displayName: normalizedDisplayName } : {}),
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
if (!result.ok) {
|
|
289
|
+
throw new Error(formatSetupApiError(result, 'Failed to start Claworld email verification'));
|
|
290
|
+
}
|
|
291
|
+
return ensureObject(result.body);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function completeSetupEmailVerification({
|
|
295
|
+
runtimeConfig,
|
|
296
|
+
email,
|
|
297
|
+
code,
|
|
298
|
+
fetchImpl,
|
|
299
|
+
} = {}) {
|
|
300
|
+
const baseUrl = normalizeRelayHttpBaseUrl(runtimeConfig.serverUrl);
|
|
301
|
+
const result = await fetchJson(fetchImpl, `${baseUrl}/v1/identity/email/verify`, {
|
|
302
|
+
method: 'POST',
|
|
303
|
+
headers: {
|
|
304
|
+
'content-type': 'application/json',
|
|
305
|
+
...(runtimeConfig.apiKey ? { 'x-api-key': runtimeConfig.apiKey } : {}),
|
|
306
|
+
},
|
|
307
|
+
body: JSON.stringify({
|
|
308
|
+
email: normalizeText(email, null),
|
|
309
|
+
code: normalizeText(code, null),
|
|
310
|
+
}),
|
|
311
|
+
});
|
|
312
|
+
if (!result.ok) {
|
|
313
|
+
throw new Error(formatSetupApiError(result, 'Failed to complete Claworld email verification'));
|
|
314
|
+
}
|
|
315
|
+
return ensureObject(result.body);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function resolveSetupCredential({
|
|
319
|
+
managedOptions,
|
|
320
|
+
prompter,
|
|
321
|
+
runtime = {},
|
|
322
|
+
input = {},
|
|
323
|
+
} = {}) {
|
|
324
|
+
if (managedOptions.appToken) return null;
|
|
325
|
+
|
|
326
|
+
const fetchImpl = resolveSetupFetchImpl(runtime);
|
|
327
|
+
const email = normalizeText(await prompter.text({
|
|
328
|
+
message: 'Claworld account email',
|
|
329
|
+
placeholder: 'you@example.com',
|
|
330
|
+
validate: validateSetupEmail,
|
|
331
|
+
}), null);
|
|
332
|
+
|
|
333
|
+
await startSetupEmailVerification({
|
|
334
|
+
runtimeConfig: managedOptions,
|
|
335
|
+
email,
|
|
336
|
+
displayName: normalizeText(input?.name, null),
|
|
337
|
+
fetchImpl,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const code = normalizeText(await prompter.text({
|
|
341
|
+
message: `Verification code sent to ${email}`,
|
|
342
|
+
placeholder: '123456',
|
|
343
|
+
validate: validateSetupVerificationCode,
|
|
344
|
+
}), null);
|
|
345
|
+
|
|
346
|
+
const verification = await completeSetupEmailVerification({
|
|
347
|
+
runtimeConfig: managedOptions,
|
|
348
|
+
email,
|
|
349
|
+
code,
|
|
350
|
+
fetchImpl,
|
|
351
|
+
});
|
|
352
|
+
const appToken = normalizeText(verification.appToken, null);
|
|
353
|
+
const relayAgentId = normalizeText(verification.agentId, null);
|
|
354
|
+
if (!appToken || !relayAgentId) {
|
|
355
|
+
throw new Error('Claworld email verification did not return appToken and agentId.');
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
email,
|
|
359
|
+
appToken,
|
|
360
|
+
relayAgentId,
|
|
361
|
+
created: verification.created === true,
|
|
362
|
+
recovered: verification.recovered === true,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
234
366
|
async function applyManagedOnboardingConfig({
|
|
235
367
|
cfg = {},
|
|
368
|
+
runtime = {},
|
|
236
369
|
prompter,
|
|
237
370
|
accountId = null,
|
|
238
371
|
phase = 'setup',
|
|
239
372
|
input = {},
|
|
240
373
|
} = {}) {
|
|
241
|
-
const
|
|
374
|
+
const initialManagedOptions = resolveManagedOptionsFromContext({ cfg, accountId, input });
|
|
375
|
+
const setupCredential = await resolveSetupCredential({
|
|
376
|
+
managedOptions: initialManagedOptions,
|
|
377
|
+
prompter,
|
|
378
|
+
runtime,
|
|
379
|
+
input,
|
|
380
|
+
});
|
|
381
|
+
const managedOptions = setupCredential
|
|
382
|
+
? {
|
|
383
|
+
...initialManagedOptions,
|
|
384
|
+
appToken: setupCredential.appToken,
|
|
385
|
+
relayAgentId: setupCredential.relayAgentId,
|
|
386
|
+
}
|
|
387
|
+
: initialManagedOptions;
|
|
242
388
|
const next = applyClaworldManagedRuntimeConfig(cfg, managedOptions);
|
|
243
389
|
|
|
244
390
|
const noteLines = [
|
|
245
391
|
`Bound local agent/account: ${managedOptions.agentId}`,
|
|
246
392
|
`Remote backend: ${managedOptions.serverUrl}`,
|
|
247
|
-
|
|
248
|
-
?
|
|
249
|
-
:
|
|
393
|
+
setupCredential
|
|
394
|
+
? `Email verification: completed for ${setupCredential.email}; runtime credential saved to OpenClaw config`
|
|
395
|
+
: managedOptions.appToken
|
|
396
|
+
? 'Runtime credential: configured appToken is present'
|
|
397
|
+
: 'Email verification: pending until claworld_manage_account(action=start_email_verification|complete_email_verification) runs',
|
|
398
|
+
managedOptions.relayAgentId
|
|
399
|
+
? `Remote agent identity: ${managedOptions.relayAgentId}`
|
|
400
|
+
: 'Remote agent identity: pending',
|
|
250
401
|
'Workspace memory: runtime prompt bootstrap maintains .claworld/ in the active host workspace',
|
|
251
402
|
'This flow refreshes plugin-side config and binds claworld onto the selected local agent.',
|
|
252
|
-
'Setup lifecycle: OpenClaw host-native setup.',
|
|
403
|
+
'Setup lifecycle: OpenClaw host-native setup; channel reload is handled by config reload.',
|
|
253
404
|
];
|
|
254
405
|
await prompter.note(
|
|
255
406
|
noteLines.join('\n'),
|
|
@@ -294,17 +445,19 @@ export const claworldOnboardingAdapter = {
|
|
|
294
445
|
}),
|
|
295
446
|
};
|
|
296
447
|
},
|
|
297
|
-
configure: async ({ cfg, prompter, accountOverrides }) =>
|
|
448
|
+
configure: async ({ cfg, runtime, prompter, accountOverrides }) =>
|
|
298
449
|
applyManagedOnboardingConfig({
|
|
299
450
|
cfg,
|
|
451
|
+
runtime,
|
|
300
452
|
prompter,
|
|
301
453
|
accountId: accountOverrides?.claworld,
|
|
302
454
|
phase: 'setup',
|
|
303
455
|
input: {},
|
|
304
456
|
}),
|
|
305
|
-
configureWhenConfigured: async ({ cfg, prompter, accountOverrides }) =>
|
|
457
|
+
configureWhenConfigured: async ({ cfg, runtime, prompter, accountOverrides }) =>
|
|
306
458
|
applyManagedOnboardingConfig({
|
|
307
459
|
cfg,
|
|
460
|
+
runtime,
|
|
308
461
|
prompter,
|
|
309
462
|
accountId: accountOverrides?.claworld,
|
|
310
463
|
phase: 'refresh',
|
|
@@ -548,11 +548,12 @@ function projectToolShareCard(payload = null) {
|
|
|
548
548
|
const imageUrl = normalizeText(payload?.imageUrl, null);
|
|
549
549
|
const downloadUrl = normalizeText(payload?.downloadUrl, imageUrl);
|
|
550
550
|
const templateId = normalizeText(payload?.templateId, null);
|
|
551
|
+
const variant = normalizeText(payload?.variant, null);
|
|
551
552
|
const imageFormat = normalizeText(payload?.imageFormat, null);
|
|
552
553
|
const mimeType = normalizeText(payload?.mimeType, null);
|
|
553
554
|
const expiresAt = normalizeText(payload?.expiresAt, null);
|
|
554
555
|
const description = normalizeText(payload?.description, null);
|
|
555
|
-
if (!imageUrl && !downloadUrl && !templateId && !imageFormat && !mimeType && !expiresAt && !description) {
|
|
556
|
+
if (!imageUrl && !downloadUrl && !templateId && !variant && !imageFormat && !mimeType && !expiresAt && !description) {
|
|
556
557
|
return {
|
|
557
558
|
status: normalizeText(payload?.status, 'unavailable'),
|
|
558
559
|
reason: normalizeText(payload?.reason, null),
|
|
@@ -564,6 +565,7 @@ function projectToolShareCard(payload = null) {
|
|
|
564
565
|
imageUrl,
|
|
565
566
|
downloadUrl,
|
|
566
567
|
templateId,
|
|
568
|
+
variant,
|
|
567
569
|
imageFormat,
|
|
568
570
|
mimeType,
|
|
569
571
|
expiresAt,
|
|
@@ -686,20 +688,29 @@ export function projectToolAccountViewResponse({
|
|
|
686
688
|
} = {}) {
|
|
687
689
|
const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
|
|
688
690
|
const accountProfile = projectToolAccountProfileState(identityPayload);
|
|
689
|
-
const
|
|
691
|
+
const publicIdentityReady = identityPayload?.ready === true;
|
|
690
692
|
const accountProfileReady = accountProfile.ready === true;
|
|
691
|
-
const
|
|
693
|
+
const emailVerified = pairingPayload?.emailVerified === true;
|
|
694
|
+
const runtimePaired = pairingPayload?.status === 'paired';
|
|
692
695
|
const bindingReady = typeof pairingPayload?.bindingReady === 'boolean'
|
|
693
696
|
? pairingPayload.bindingReady
|
|
694
|
-
:
|
|
697
|
+
: runtimePaired;
|
|
695
698
|
const bindingStatus = normalizeText(
|
|
696
699
|
pairingPayload?.bindingStatus,
|
|
697
|
-
|
|
700
|
+
runtimePaired
|
|
698
701
|
? (bindingReady ? 'bound' : 'identity_unresolved')
|
|
699
|
-
: '
|
|
702
|
+
: 'unbound',
|
|
700
703
|
);
|
|
701
|
-
const ready =
|
|
702
|
-
const blockedAction = !
|
|
704
|
+
const ready = emailVerified && publicIdentityReady && accountProfileReady;
|
|
705
|
+
const blockedAction = !emailVerified
|
|
706
|
+
? {
|
|
707
|
+
requiredAction: 'start_email_verification',
|
|
708
|
+
nextAction: 'start_email_verification',
|
|
709
|
+
nextTool: 'claworld_manage_account',
|
|
710
|
+
missingFields: [{ fieldId: 'email', label: 'Identity Email', description: 'Email-based identity verification is required before using other account features.' }],
|
|
711
|
+
reason: 'email_verification_required',
|
|
712
|
+
}
|
|
713
|
+
: !publicIdentityReady
|
|
703
714
|
? {
|
|
704
715
|
requiredAction: publicIdentityState.requiredAction,
|
|
705
716
|
nextAction: publicIdentityState.nextAction,
|
|
@@ -731,22 +742,28 @@ export function projectToolAccountViewResponse({
|
|
|
731
742
|
action: 'view',
|
|
732
743
|
status: ready ? 'ready' : 'pending',
|
|
733
744
|
ready,
|
|
734
|
-
readiness:
|
|
735
|
-
?
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
745
|
+
readiness: !emailVerified
|
|
746
|
+
? 'email_verification_required'
|
|
747
|
+
: !publicIdentityReady
|
|
748
|
+
? 'public_identity_incomplete'
|
|
749
|
+
: accountProfileReady
|
|
750
|
+
? 'ready'
|
|
751
|
+
: 'account_profile_incomplete',
|
|
739
752
|
accountId: normalizeText(pairingPayload?.runtimeConfig?.accountId, normalizeText(accountId, null)),
|
|
740
|
-
reason:
|
|
753
|
+
reason: blockedAction.reason,
|
|
754
|
+
bindingReason: normalizeText(pairingPayload?.reason, null),
|
|
741
755
|
bindingSource: normalizeText(pairingPayload?.bindingSource, null),
|
|
742
|
-
|
|
743
|
-
status:
|
|
756
|
+
emailVerification: {
|
|
757
|
+
status: emailVerified ? 'verified' : 'pending',
|
|
758
|
+
email: normalizeText(pairingPayload?.email, null),
|
|
759
|
+
verifiedAt: normalizeText(pairingPayload?.verifiedAt, null),
|
|
744
760
|
},
|
|
745
761
|
diagnostics: {
|
|
746
762
|
toolReachable: true,
|
|
763
|
+
emailVerified,
|
|
747
764
|
bindingReady,
|
|
748
765
|
bindingStatus,
|
|
749
|
-
publicIdentityReady
|
|
766
|
+
publicIdentityReady,
|
|
750
767
|
accountProfileReady,
|
|
751
768
|
relayPresenceResolved: relayResolved,
|
|
752
769
|
relayOnline,
|
|
@@ -781,7 +798,7 @@ export function projectToolAccountMutationResponse({
|
|
|
781
798
|
accountId = null,
|
|
782
799
|
identityPayload = null,
|
|
783
800
|
shareCard = undefined,
|
|
784
|
-
|
|
801
|
+
runtimeIdentity = null,
|
|
785
802
|
} = {}) {
|
|
786
803
|
const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
|
|
787
804
|
const accountProfile = projectToolAccountProfileState(identityPayload);
|
|
@@ -790,10 +807,21 @@ export function projectToolAccountMutationResponse({
|
|
|
790
807
|
: (identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
|
|
791
808
|
? projectToolShareCard(identityPayload.shareCard)
|
|
792
809
|
: undefined);
|
|
793
|
-
const
|
|
810
|
+
const publicIdentityReady = identityPayload?.ready === true;
|
|
794
811
|
const accountProfileReady = accountProfile.ready === true;
|
|
795
|
-
const
|
|
796
|
-
const
|
|
812
|
+
const emailVerificationPayload = normalizeObject(identityPayload?.emailVerification, null);
|
|
813
|
+
const emailVerified = identityPayload?.emailVerified === true
|
|
814
|
+
|| normalizeText(emailVerificationPayload?.status, null) === 'verified';
|
|
815
|
+
const ready = emailVerified && publicIdentityReady && accountProfileReady;
|
|
816
|
+
const blockedAction = !emailVerified
|
|
817
|
+
? {
|
|
818
|
+
requiredAction: 'start_email_verification',
|
|
819
|
+
nextAction: 'start_email_verification',
|
|
820
|
+
nextTool: 'claworld_manage_account',
|
|
821
|
+
missingFields: [{ fieldId: 'email', label: 'Identity Email', description: 'Email-based identity verification is required before using other account features.' }],
|
|
822
|
+
reason: 'email_verification_required',
|
|
823
|
+
}
|
|
824
|
+
: !publicIdentityReady
|
|
797
825
|
? {
|
|
798
826
|
requiredAction: publicIdentityState.requiredAction,
|
|
799
827
|
nextAction: publicIdentityState.nextAction,
|
|
@@ -820,10 +848,24 @@ export function projectToolAccountMutationResponse({
|
|
|
820
848
|
action,
|
|
821
849
|
status: ready ? 'ready' : 'pending',
|
|
822
850
|
ready,
|
|
823
|
-
readiness:
|
|
824
|
-
?
|
|
825
|
-
:
|
|
851
|
+
readiness: !emailVerified
|
|
852
|
+
? 'email_verification_required'
|
|
853
|
+
: !publicIdentityReady
|
|
854
|
+
? 'public_identity_incomplete'
|
|
855
|
+
: accountProfileReady
|
|
856
|
+
? 'ready'
|
|
857
|
+
: 'account_profile_incomplete',
|
|
826
858
|
accountId: normalizeText(accountId, null),
|
|
859
|
+
emailVerification: {
|
|
860
|
+
status: emailVerified ? 'verified' : 'pending',
|
|
861
|
+
email: normalizeText(emailVerificationPayload?.email, null),
|
|
862
|
+
verifiedAt: normalizeText(emailVerificationPayload?.verifiedAt, null),
|
|
863
|
+
},
|
|
864
|
+
diagnostics: {
|
|
865
|
+
emailVerified,
|
|
866
|
+
publicIdentityReady,
|
|
867
|
+
accountProfileReady,
|
|
868
|
+
},
|
|
827
869
|
profile: accountProfile.profile,
|
|
828
870
|
...publicIdentityState,
|
|
829
871
|
accountProfile,
|
|
@@ -835,7 +877,7 @@ export function projectToolAccountMutationResponse({
|
|
|
835
877
|
pluginVersionStatus: projectToolPluginVersionStatus(identityPayload?.pluginVersionStatus),
|
|
836
878
|
chatRequestApprovalPolicy: projectToolChatRequestApprovalPolicy(identityPayload?.chatRequestApprovalPolicy),
|
|
837
879
|
...(resolvedShareCard !== undefined ? { shareCard: resolvedShareCard } : {}),
|
|
838
|
-
...(
|
|
880
|
+
...(runtimeIdentity ? { runtimeIdentity } : {}),
|
|
839
881
|
...(action === 'update_identity'
|
|
840
882
|
? {
|
|
841
883
|
updated: resolvedShareCard && resolvedShareCard.status === 'ready'
|
|
@@ -181,7 +181,6 @@ const TERMINAL_CONVERSATION_ACTIONS = PUBLIC_TOOL_ACTION_CATALOG.claworld_manage
|
|
|
181
181
|
|
|
182
182
|
const ACCOUNT_IMPLEMENTATION_ACTIONS = Object.freeze({
|
|
183
183
|
view_account: 'view',
|
|
184
|
-
activate_account: 'update_identity',
|
|
185
184
|
});
|
|
186
185
|
|
|
187
186
|
const WORLD_IMPLEMENTATION_ACTIONS = Object.freeze({
|
|
@@ -429,6 +428,11 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
429
428
|
minLength: 1,
|
|
430
429
|
examples: ['claworld'],
|
|
431
430
|
});
|
|
431
|
+
const shareCardVariantProperty = stringParam({
|
|
432
|
+
description: 'Optional share-card version. Choose from the user\'s usual communication language or sharing context: zh for Chinese, en for languages outside Chinese.',
|
|
433
|
+
enumValues: ['en', 'zh'],
|
|
434
|
+
examples: ['en', 'zh'],
|
|
435
|
+
});
|
|
432
436
|
const worldIdProperty = stringParam({
|
|
433
437
|
description: 'Canonical world id.',
|
|
434
438
|
minLength: 1,
|
|
@@ -444,12 +448,13 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
444
448
|
{
|
|
445
449
|
name: accountTool,
|
|
446
450
|
label: 'Claworld Manage Account',
|
|
447
|
-
description: 'Terminal account surface for readiness, public identity, global profile, share-card generation,
|
|
451
|
+
description: 'Terminal account surface for readiness, public identity, global profile, share-card generation, account-level chat policy, and email-based identity verification.',
|
|
448
452
|
metadata: buildToolMetadata({
|
|
449
453
|
category: 'account',
|
|
450
454
|
usageNotes: [
|
|
451
|
-
'Use this
|
|
455
|
+
'Use this human-facing account surface for identity verification, profile, policy, and subscription decisions.',
|
|
452
456
|
'Use action=view_account for readiness; update_display_name, update_agent_profile, or set_chat_policy for common account mutations.',
|
|
457
|
+
'Use start_email_verification with email + optional displayName to start email-based identity verification, then complete_email_verification with email + code to finish.',
|
|
453
458
|
'Use subscribe_person or unsubscribe_person when a search/profile result exposes a person subscription target.',
|
|
454
459
|
],
|
|
455
460
|
}),
|
|
@@ -461,10 +466,10 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
461
466
|
action: stringParam({
|
|
462
467
|
description: 'Account action.',
|
|
463
468
|
enumValues: TERMINAL_ACCOUNT_ACTIONS,
|
|
464
|
-
examples: ['view_account', 'update_display_name', 'set_chat_policy'],
|
|
469
|
+
examples: ['view_account', 'start_email_verification', 'update_display_name', 'set_chat_policy'],
|
|
465
470
|
}),
|
|
466
471
|
displayName: stringParam({
|
|
467
|
-
description: 'Public-facing display name for
|
|
472
|
+
description: 'Public-facing display name for update_display_name or start_email_verification.',
|
|
468
473
|
minLength: 1,
|
|
469
474
|
examples: ['Moza', '小发发'],
|
|
470
475
|
}),
|
|
@@ -473,7 +478,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
473
478
|
examples: ['喜欢慢节奏介绍,也愿意先让 agent 做初步认识。🙂'],
|
|
474
479
|
}),
|
|
475
480
|
humanProfile: stringParam({
|
|
476
|
-
description: '
|
|
481
|
+
description: 'Human-facing profile text for update_human_profile.',
|
|
477
482
|
examples: ['周末在上海,喜欢网球和安静咖啡馆。'],
|
|
478
483
|
}),
|
|
479
484
|
agentProfile: stringParam({
|
|
@@ -507,11 +512,22 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
507
512
|
generateShareCard: booleanParam({
|
|
508
513
|
description: 'When true, include a temporary public identity card when supported.',
|
|
509
514
|
}),
|
|
515
|
+
shareCardVariant: shareCardVariantProperty,
|
|
510
516
|
expiresInSeconds: integerParam({
|
|
511
517
|
description: 'Optional temporary share-card TTL in seconds.',
|
|
512
518
|
minimum: 1,
|
|
513
519
|
examples: [7200],
|
|
514
520
|
}),
|
|
521
|
+
email: stringParam({
|
|
522
|
+
description: 'Email address for start_email_verification or complete_email_verification.',
|
|
523
|
+
minLength: 1,
|
|
524
|
+
examples: ['agent@example.com'],
|
|
525
|
+
}),
|
|
526
|
+
code: stringParam({
|
|
527
|
+
description: 'Verification code from email for complete_email_verification.',
|
|
528
|
+
minLength: 1,
|
|
529
|
+
examples: ['123456'],
|
|
530
|
+
}),
|
|
515
531
|
},
|
|
516
532
|
}),
|
|
517
533
|
async execute(toolCallId, params = {}) {
|
|
@@ -542,6 +558,34 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
542
558
|
return buildTerminalActionResult({ tool: accountTool, action, payload });
|
|
543
559
|
}
|
|
544
560
|
|
|
561
|
+
if (action === 'start_email_verification') {
|
|
562
|
+
const email = normalizeText(params.email, null);
|
|
563
|
+
if (!email) requireManageWorldField('email', 'email is required for action=start_email_verification');
|
|
564
|
+
const context = await resolveToolContext(api, plugin, params, { bindRuntime: false });
|
|
565
|
+
const payload = await plugin.runtime.productShell.identity.startEmailVerification({
|
|
566
|
+
...context,
|
|
567
|
+
runtime: api?.runtime || null,
|
|
568
|
+
email,
|
|
569
|
+
displayName: params.displayName || null,
|
|
570
|
+
});
|
|
571
|
+
return buildTerminalActionResult({ tool: accountTool, action, payload });
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (action === 'complete_email_verification') {
|
|
575
|
+
const email = normalizeText(params.email, null);
|
|
576
|
+
const code = normalizeText(params.code, null);
|
|
577
|
+
if (!email) requireManageWorldField('email', 'email is required for action=complete_email_verification');
|
|
578
|
+
if (!code) requireManageWorldField('code', 'code is required for action=complete_email_verification');
|
|
579
|
+
const context = await resolveToolContext(api, plugin, params, { bindRuntime: false });
|
|
580
|
+
const payload = await plugin.runtime.productShell.identity.completeEmailVerification({
|
|
581
|
+
...context,
|
|
582
|
+
runtime: api?.runtime || null,
|
|
583
|
+
email,
|
|
584
|
+
code,
|
|
585
|
+
});
|
|
586
|
+
return buildTerminalActionResult({ tool: accountTool, action, payload });
|
|
587
|
+
}
|
|
588
|
+
|
|
545
589
|
const implementationAction = ACCOUNT_IMPLEMENTATION_ACTIONS[action] || null;
|
|
546
590
|
if (implementationAction) {
|
|
547
591
|
const implementationParams = {
|
|
@@ -563,7 +607,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
563
607
|
requireManageWorldField('action', `action=${action} requires the account management runtime adapter`);
|
|
564
608
|
}
|
|
565
609
|
const context = await resolveToolContext(api, plugin, params, {
|
|
566
|
-
requiredPublicIdentityCapability: action === '
|
|
610
|
+
requiredPublicIdentityCapability: action === 'view_account' ? null : 'manage account',
|
|
567
611
|
});
|
|
568
612
|
const generateShareCard = typeof params.generateShareCard === 'boolean'
|
|
569
613
|
? params.generateShareCard
|
|
@@ -580,6 +624,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
580
624
|
chatRequestApprovalPolicy: params.chatRequestApprovalPolicy || null,
|
|
581
625
|
proactivitySettings: params.proactivitySettings,
|
|
582
626
|
generateShareCard,
|
|
627
|
+
shareCardVariant: params.shareCardVariant ?? null,
|
|
583
628
|
expiresInSeconds: params.expiresInSeconds ?? null,
|
|
584
629
|
});
|
|
585
630
|
return buildTerminalActionResult({ tool: accountTool, action, payload });
|
|
@@ -740,14 +785,6 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
|
|
|
740
785
|
minLength: 1,
|
|
741
786
|
examples: ['Runtime Peer'],
|
|
742
787
|
}),
|
|
743
|
-
generateShareCard: booleanParam({
|
|
744
|
-
description: 'When true, include the current account share-card when available.',
|
|
745
|
-
}),
|
|
746
|
-
expiresInSeconds: integerParam({
|
|
747
|
-
description: 'Optional temporary share-card TTL in seconds.',
|
|
748
|
-
minimum: 1,
|
|
749
|
-
examples: [7200],
|
|
750
|
-
}),
|
|
751
788
|
},
|
|
752
789
|
}),
|
|
753
790
|
async execute(toolCallId, params = {}) {
|
|
@@ -1112,6 +1149,11 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1112
1149
|
minLength: 1,
|
|
1113
1150
|
examples: ['claworld'],
|
|
1114
1151
|
});
|
|
1152
|
+
const shareCardVariantProperty = stringParam({
|
|
1153
|
+
description: 'Optional share-card version. Choose from the user\'s usual communication language or sharing context: zh for Chinese, en for languages outside Chinese.',
|
|
1154
|
+
enumValues: ['en', 'zh'],
|
|
1155
|
+
examples: ['en', 'zh'],
|
|
1156
|
+
});
|
|
1115
1157
|
const chatRequestApprovalPolicyProperty = objectParam({
|
|
1116
1158
|
description: 'Backend-managed inbound chat-request policy for this account.',
|
|
1117
1159
|
required: ['mode'],
|
|
@@ -1963,6 +2005,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1963
2005
|
generateShareCard: booleanParam({
|
|
1964
2006
|
description: 'When true, return a temporary public identity card URL. Defaults to false for view and true for update_identity.',
|
|
1965
2007
|
}),
|
|
2008
|
+
shareCardVariant: shareCardVariantProperty,
|
|
1966
2009
|
expiresInSeconds: integerParam({
|
|
1967
2010
|
description: 'Optional temporary share-card TTL in seconds.',
|
|
1968
2011
|
minimum: 1,
|
|
@@ -1979,6 +2022,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
1979
2022
|
action: 'update_identity',
|
|
1980
2023
|
displayName: '小发发',
|
|
1981
2024
|
generateShareCard: true,
|
|
2025
|
+
shareCardVariant: 'zh',
|
|
1982
2026
|
},
|
|
1983
2027
|
{
|
|
1984
2028
|
accountId: 'claworld',
|
|
@@ -2010,13 +2054,14 @@ function buildRegisteredTools(api, plugin) {
|
|
|
2010
2054
|
...context,
|
|
2011
2055
|
displayName,
|
|
2012
2056
|
generateShareCard,
|
|
2057
|
+
shareCardVariant: params.shareCardVariant ?? null,
|
|
2013
2058
|
expiresInSeconds: params.expiresInSeconds ?? null,
|
|
2014
2059
|
});
|
|
2015
2060
|
return buildToolResult(projectToolAccountMutationResponse({
|
|
2016
2061
|
action,
|
|
2017
2062
|
accountId: context.accountId,
|
|
2018
2063
|
identityPayload: payload,
|
|
2019
|
-
|
|
2064
|
+
runtimeIdentity: payload?.runtimeIdentity || null,
|
|
2020
2065
|
}));
|
|
2021
2066
|
}
|
|
2022
2067
|
|
|
@@ -2067,6 +2112,7 @@ function buildRegisteredTools(api, plugin) {
|
|
|
2067
2112
|
runtimeConfig,
|
|
2068
2113
|
agentId: context.agentId || runtimeConfig.relay?.agentId || null,
|
|
2069
2114
|
generateShareCard,
|
|
2115
|
+
shareCardVariant: params.shareCardVariant ?? null,
|
|
2070
2116
|
expiresInSeconds: params.expiresInSeconds ?? null,
|
|
2071
2117
|
});
|
|
2072
2118
|
const pairedAgentId = identityPayload?.agentId || runtimeConfig.relay?.agentId || null;
|
|
@@ -2100,11 +2146,19 @@ function buildRegisteredTools(api, plugin) {
|
|
|
2100
2146
|
|| runtimeConfig.relay?.appToken
|
|
2101
2147
|
|| runtimeConfig.relay?.credentialToken,
|
|
2102
2148
|
);
|
|
2103
|
-
const
|
|
2104
|
-
|
|
2105
|
-
|
|
2149
|
+
const identityStatus = pairedAgentId && typeof plugin.runtime?.productShell?.identity?.getIdentityStatus === 'function'
|
|
2150
|
+
? await plugin.runtime.productShell.identity.getIdentityStatus({
|
|
2151
|
+
cfg,
|
|
2152
|
+
accountId,
|
|
2153
|
+
runtimeConfig: pairedRuntimeConfig,
|
|
2154
|
+
agentId: pairedAgentId,
|
|
2155
|
+
})
|
|
2156
|
+
: null;
|
|
2157
|
+
const emailVerified = identityStatus?.emailVerified === true;
|
|
2158
|
+
const bindingReady = hasConfiguredAppToken && Boolean(pairedAgentId);
|
|
2159
|
+
const bindingStatus = hasConfiguredAppToken
|
|
2106
2160
|
? (bindingReady ? 'bound' : 'identity_unresolved')
|
|
2107
|
-
: '
|
|
2161
|
+
: 'unbound';
|
|
2108
2162
|
let relayAgent = relayAgentFallback;
|
|
2109
2163
|
if (hasConfiguredAppToken && pairedAgentId && typeof plugin.helpers?.pairing?.resolveAgentIdentity === 'function') {
|
|
2110
2164
|
const resolvedRelayAgent = await plugin.helpers.pairing.resolveAgentIdentity({
|
|
@@ -2123,13 +2177,16 @@ function buildRegisteredTools(api, plugin) {
|
|
|
2123
2177
|
}
|
|
2124
2178
|
}
|
|
2125
2179
|
const pairingPayload = {
|
|
2126
|
-
status:
|
|
2180
|
+
status: hasConfiguredAppToken ? 'paired' : 'unpaired',
|
|
2127
2181
|
bindingReady,
|
|
2128
2182
|
bindingStatus,
|
|
2129
|
-
|
|
2183
|
+
emailVerified,
|
|
2184
|
+
email: identityStatus?.email || null,
|
|
2185
|
+
verifiedAt: identityStatus?.verifiedAt || null,
|
|
2186
|
+
reason: hasConfiguredAppToken
|
|
2130
2187
|
? (pairedAgentId ? null : 'missing_agent_id')
|
|
2131
2188
|
: 'missing_app_token',
|
|
2132
|
-
bindingSource:
|
|
2189
|
+
bindingSource: hasConfiguredAppToken
|
|
2133
2190
|
? 'configured_app_token'
|
|
2134
2191
|
: (runtimeConfig.registration?.enabled === true ? 'registration_pending' : 'unbound'),
|
|
2135
2192
|
runtimeConfig: pairedRuntimeConfig,
|
|
@@ -32,7 +32,8 @@ export const PUBLIC_TOOL_ACTION_CATALOG = Object.freeze({
|
|
|
32
32
|
]),
|
|
33
33
|
claworld_manage_account: Object.freeze([
|
|
34
34
|
'view_account',
|
|
35
|
-
'
|
|
35
|
+
'start_email_verification',
|
|
36
|
+
'complete_email_verification',
|
|
36
37
|
'update_display_name',
|
|
37
38
|
'update_human_profile',
|
|
38
39
|
'update_agent_profile',
|