@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.
@@ -20,7 +20,6 @@ import {
20
20
  } from '../runtime/backend-error-context.js';
21
21
 
22
22
  export const INTERNAL_REQUESTER_SESSION_KEY_PARAM = '__claworldRequesterSessionKey';
23
- export const INTERNAL_WORKSPACE_ROOT_PARAM = '__claworldWorkspaceRoot';
24
23
 
25
24
  export function normalizeText(value, fallback = null) {
26
25
  if (value == null) return fallback;
@@ -159,12 +158,6 @@ export function buildPublicToolErrorExtras(error) {
159
158
  }
160
159
 
161
160
  export async function loadCurrentConfig(api) {
162
- if (api?.config && typeof api.config.current === 'function') {
163
- return api.config.current();
164
- }
165
- if (api?.runtime?.config && typeof api.runtime.config.current === 'function') {
166
- return api.runtime.config.current();
167
- }
168
161
  if (api?.config && typeof api.config.loadConfig === 'function') {
169
162
  return await api.config.loadConfig();
170
163
  }
@@ -247,10 +240,9 @@ export async function resolveToolContext(
247
240
  runtime: api?.runtime || null,
248
241
  accountId,
249
242
  runtimeConfig,
250
- agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
251
- requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
252
- workspaceRoot: normalizeText(params[INTERNAL_WORKSPACE_ROOT_PARAM], null),
253
- });
243
+ agentId: normalizeText(params.agentId, runtimeConfig.relay?.agentId || null),
244
+ requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
245
+ });
254
246
  if (
255
247
  requiredPublicIdentityCapability
256
248
  && (
@@ -290,7 +282,6 @@ export async function resolveToolContext(
290
282
  runtimeConfig,
291
283
  agentId,
292
284
  requesterSessionKey: normalizeText(params[INTERNAL_REQUESTER_SESSION_KEY_PARAM], null),
293
- workspaceRoot: normalizeText(params[INTERNAL_WORKSPACE_ROOT_PARAM], null),
294
285
  };
295
286
  }
296
287
 
@@ -557,11 +548,12 @@ function projectToolShareCard(payload = null) {
557
548
  const imageUrl = normalizeText(payload?.imageUrl, null);
558
549
  const downloadUrl = normalizeText(payload?.downloadUrl, imageUrl);
559
550
  const templateId = normalizeText(payload?.templateId, null);
551
+ const variant = normalizeText(payload?.variant, null);
560
552
  const imageFormat = normalizeText(payload?.imageFormat, null);
561
553
  const mimeType = normalizeText(payload?.mimeType, null);
562
554
  const expiresAt = normalizeText(payload?.expiresAt, null);
563
555
  const description = normalizeText(payload?.description, null);
564
- if (!imageUrl && !downloadUrl && !templateId && !imageFormat && !mimeType && !expiresAt && !description) {
556
+ if (!imageUrl && !downloadUrl && !templateId && !variant && !imageFormat && !mimeType && !expiresAt && !description) {
565
557
  return {
566
558
  status: normalizeText(payload?.status, 'unavailable'),
567
559
  reason: normalizeText(payload?.reason, null),
@@ -573,6 +565,7 @@ function projectToolShareCard(payload = null) {
573
565
  imageUrl,
574
566
  downloadUrl,
575
567
  templateId,
568
+ variant,
576
569
  imageFormat,
577
570
  mimeType,
578
571
  expiresAt,
@@ -695,20 +688,29 @@ export function projectToolAccountViewResponse({
695
688
  } = {}) {
696
689
  const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
697
690
  const accountProfile = projectToolAccountProfileState(identityPayload);
698
- const identityReady = identityPayload?.ready === true;
691
+ const publicIdentityReady = identityPayload?.ready === true;
699
692
  const accountProfileReady = accountProfile.ready === true;
700
- const activationReady = pairingPayload?.status === 'paired';
693
+ const emailVerified = pairingPayload?.emailVerified === true;
694
+ const runtimePaired = pairingPayload?.status === 'paired';
701
695
  const bindingReady = typeof pairingPayload?.bindingReady === 'boolean'
702
696
  ? pairingPayload.bindingReady
703
- : activationReady;
697
+ : runtimePaired;
704
698
  const bindingStatus = normalizeText(
705
699
  pairingPayload?.bindingStatus,
706
- activationReady
700
+ runtimePaired
707
701
  ? (bindingReady ? 'bound' : 'identity_unresolved')
708
- : 'unactivated',
702
+ : 'unbound',
709
703
  );
710
- const ready = activationReady && identityReady && accountProfileReady;
711
- const blockedAction = !identityReady
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
712
714
  ? {
713
715
  requiredAction: publicIdentityState.requiredAction,
714
716
  nextAction: publicIdentityState.nextAction,
@@ -740,22 +742,28 @@ export function projectToolAccountViewResponse({
740
742
  action: 'view',
741
743
  status: ready ? 'ready' : 'pending',
742
744
  ready,
743
- readiness: pairingPayload?.status === 'paired'
744
- ? (identityReady
745
- ? (accountProfileReady ? 'paired_and_ready' : 'paired_but_account_profile_incomplete')
746
- : 'paired_but_identity_pending')
747
- : 'installed_unactivated',
745
+ readiness: !emailVerified
746
+ ? 'email_verification_required'
747
+ : !publicIdentityReady
748
+ ? 'public_identity_incomplete'
749
+ : accountProfileReady
750
+ ? 'ready'
751
+ : 'account_profile_incomplete',
748
752
  accountId: normalizeText(pairingPayload?.runtimeConfig?.accountId, normalizeText(accountId, null)),
749
- reason: normalizeText(pairingPayload?.reason, blockedAction.reason),
753
+ reason: blockedAction.reason,
754
+ bindingReason: normalizeText(pairingPayload?.reason, null),
750
755
  bindingSource: normalizeText(pairingPayload?.bindingSource, null),
751
- activation: {
752
- status: activationReady ? 'ready' : 'pending',
756
+ emailVerification: {
757
+ status: emailVerified ? 'verified' : 'pending',
758
+ email: normalizeText(pairingPayload?.email, null),
759
+ verifiedAt: normalizeText(pairingPayload?.verifiedAt, null),
753
760
  },
754
761
  diagnostics: {
755
762
  toolReachable: true,
763
+ emailVerified,
756
764
  bindingReady,
757
765
  bindingStatus,
758
- publicIdentityReady: identityReady,
766
+ publicIdentityReady,
759
767
  accountProfileReady,
760
768
  relayPresenceResolved: relayResolved,
761
769
  relayOnline,
@@ -790,7 +798,7 @@ export function projectToolAccountMutationResponse({
790
798
  accountId = null,
791
799
  identityPayload = null,
792
800
  shareCard = undefined,
793
- runtimeActivation = null,
801
+ runtimeIdentity = null,
794
802
  } = {}) {
795
803
  const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
796
804
  const accountProfile = projectToolAccountProfileState(identityPayload);
@@ -799,10 +807,21 @@ export function projectToolAccountMutationResponse({
799
807
  : (identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
800
808
  ? projectToolShareCard(identityPayload.shareCard)
801
809
  : undefined);
802
- const identityReady = identityPayload?.ready === true;
810
+ const publicIdentityReady = identityPayload?.ready === true;
803
811
  const accountProfileReady = accountProfile.ready === true;
804
- const ready = identityReady && accountProfileReady;
805
- const blockedAction = !identityReady
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
806
825
  ? {
807
826
  requiredAction: publicIdentityState.requiredAction,
808
827
  nextAction: publicIdentityState.nextAction,
@@ -829,10 +848,24 @@ export function projectToolAccountMutationResponse({
829
848
  action,
830
849
  status: ready ? 'ready' : 'pending',
831
850
  ready,
832
- readiness: identityReady
833
- ? (accountProfileReady ? 'ready' : 'account_profile_incomplete')
834
- : 'public_identity_incomplete',
851
+ readiness: !emailVerified
852
+ ? 'email_verification_required'
853
+ : !publicIdentityReady
854
+ ? 'public_identity_incomplete'
855
+ : accountProfileReady
856
+ ? 'ready'
857
+ : 'account_profile_incomplete',
835
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
+ },
836
869
  profile: accountProfile.profile,
837
870
  ...publicIdentityState,
838
871
  accountProfile,
@@ -844,7 +877,7 @@ export function projectToolAccountMutationResponse({
844
877
  pluginVersionStatus: projectToolPluginVersionStatus(identityPayload?.pluginVersionStatus),
845
878
  chatRequestApprovalPolicy: projectToolChatRequestApprovalPolicy(identityPayload?.chatRequestApprovalPolicy),
846
879
  ...(resolvedShareCard !== undefined ? { shareCard: resolvedShareCard } : {}),
847
- ...(runtimeActivation ? { runtimeActivation } : {}),
880
+ ...(runtimeIdentity ? { runtimeIdentity } : {}),
848
881
  ...(action === 'update_identity'
849
882
  ? {
850
883
  updated: resolvedShareCard && resolvedShareCard.status === 'ready'
@@ -2,10 +2,6 @@ import {
2
2
  createClaworldChannelPlugin,
3
3
  recordClaworldRuntimeAssistantOutput,
4
4
  } from './claworld-channel-plugin.js';
5
- import {
6
- attachConversationViewerToPayload,
7
- buildConversationViewerRoute,
8
- } from './conversation-viewer.js';
9
5
  import {
10
6
  projectToolChatRequestMutationResponse,
11
7
  projectToolCreateWorldResponse,
@@ -45,7 +41,6 @@ import {
45
41
  inferChatInboxAction,
46
42
  inferManageWorldAction,
47
43
  INTERNAL_REQUESTER_SESSION_KEY_PARAM,
48
- INTERNAL_WORKSPACE_ROOT_PARAM,
49
44
  integerParam,
50
45
  loadCurrentConfig,
51
46
  MANAGE_WORLD_ACTIONS,
@@ -186,7 +181,6 @@ const TERMINAL_CONVERSATION_ACTIONS = PUBLIC_TOOL_ACTION_CATALOG.claworld_manage
186
181
 
187
182
  const ACCOUNT_IMPLEMENTATION_ACTIONS = Object.freeze({
188
183
  view_account: 'view',
189
- activate_account: 'update_identity',
190
184
  });
191
185
 
192
186
  const WORLD_IMPLEMENTATION_ACTIONS = Object.freeze({
@@ -272,24 +266,6 @@ function buildTerminalActionResult({ tool, action, payload = {}, status = null }
272
266
  });
273
267
  }
274
268
 
275
- async function attachLocalConversationViewer(payload, {
276
- context = {},
277
- params = {},
278
- role = null,
279
- source = null,
280
- logger = console,
281
- } = {}) {
282
- return await attachConversationViewerToPayload(payload, {
283
- accountId: context.accountId || null,
284
- viewerAgentId: context.agentId || null,
285
- role,
286
- source,
287
- cfg: context.cfg || {},
288
- workspaceRoot: context.workspaceRoot || params[INTERNAL_WORKSPACE_ROOT_PARAM] || null,
289
- logger,
290
- });
291
- }
292
-
293
269
  function normalizeChatInboxListFiltersInput(params = {}) {
294
270
  const source = normalizeObject(params.filters, {}) || {};
295
271
  const normalized = {
@@ -452,6 +428,11 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
452
428
  minLength: 1,
453
429
  examples: ['claworld'],
454
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
+ });
455
436
  const worldIdProperty = stringParam({
456
437
  description: 'Canonical world id.',
457
438
  minLength: 1,
@@ -467,12 +448,13 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
467
448
  {
468
449
  name: accountTool,
469
450
  label: 'Claworld Manage Account',
470
- description: 'Terminal account surface for readiness, public identity, global profile, share-card generation, and account-level chat policy.',
451
+ description: 'Terminal account surface for readiness, public identity, global profile, share-card generation, account-level chat policy, and email-based identity verification.',
471
452
  metadata: buildToolMetadata({
472
453
  category: 'account',
473
454
  usageNotes: [
474
- 'Use this owner-facing account surface for activation, profile, policy, and subscription decisions.',
455
+ 'Use this human-facing account surface for identity verification, profile, policy, and subscription decisions.',
475
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.',
476
458
  'Use subscribe_person or unsubscribe_person when a search/profile result exposes a person subscription target.',
477
459
  ],
478
460
  }),
@@ -484,10 +466,10 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
484
466
  action: stringParam({
485
467
  description: 'Account action.',
486
468
  enumValues: TERMINAL_ACCOUNT_ACTIONS,
487
- examples: ['view_account', 'update_display_name', 'set_chat_policy'],
469
+ examples: ['view_account', 'start_email_verification', 'update_display_name', 'set_chat_policy'],
488
470
  }),
489
471
  displayName: stringParam({
490
- description: 'Public-facing display name for activate_account or update_display_name.',
472
+ description: 'Public-facing display name for update_display_name or start_email_verification.',
491
473
  minLength: 1,
492
474
  examples: ['Moza', '小发发'],
493
475
  }),
@@ -496,7 +478,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
496
478
  examples: ['喜欢慢节奏介绍,也愿意先让 agent 做初步认识。🙂'],
497
479
  }),
498
480
  humanProfile: stringParam({
499
- description: 'Owner-facing human profile text for update_human_profile.',
481
+ description: 'Human-facing profile text for update_human_profile.',
500
482
  examples: ['周末在上海,喜欢网球和安静咖啡馆。'],
501
483
  }),
502
484
  agentProfile: stringParam({
@@ -530,11 +512,22 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
530
512
  generateShareCard: booleanParam({
531
513
  description: 'When true, include a temporary public identity card when supported.',
532
514
  }),
515
+ shareCardVariant: shareCardVariantProperty,
533
516
  expiresInSeconds: integerParam({
534
517
  description: 'Optional temporary share-card TTL in seconds.',
535
518
  minimum: 1,
536
519
  examples: [7200],
537
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
+ }),
538
531
  },
539
532
  }),
540
533
  async execute(toolCallId, params = {}) {
@@ -565,6 +558,34 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
565
558
  return buildTerminalActionResult({ tool: accountTool, action, payload });
566
559
  }
567
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
+
568
589
  const implementationAction = ACCOUNT_IMPLEMENTATION_ACTIONS[action] || null;
569
590
  if (implementationAction) {
570
591
  const implementationParams = {
@@ -586,7 +607,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
586
607
  requireManageWorldField('action', `action=${action} requires the account management runtime adapter`);
587
608
  }
588
609
  const context = await resolveToolContext(api, plugin, params, {
589
- requiredPublicIdentityCapability: action === 'activate_account' ? null : 'manage account',
610
+ requiredPublicIdentityCapability: action === 'view_account' ? null : 'manage account',
590
611
  });
591
612
  const generateShareCard = typeof params.generateShareCard === 'boolean'
592
613
  ? params.generateShareCard
@@ -603,6 +624,7 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
603
624
  chatRequestApprovalPolicy: params.chatRequestApprovalPolicy || null,
604
625
  proactivitySettings: params.proactivitySettings,
605
626
  generateShareCard,
627
+ shareCardVariant: params.shareCardVariant ?? null,
606
628
  expiresInSeconds: params.expiresInSeconds ?? null,
607
629
  });
608
630
  return buildTerminalActionResult({ tool: accountTool, action, payload });
@@ -763,14 +785,6 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
763
785
  minLength: 1,
764
786
  examples: ['Runtime Peer'],
765
787
  }),
766
- generateShareCard: booleanParam({
767
- description: 'When true, include the current account share-card when available.',
768
- }),
769
- expiresInSeconds: integerParam({
770
- description: 'Optional temporary share-card TTL in seconds.',
771
- minimum: 1,
772
- examples: [7200],
773
- }),
774
788
  },
775
789
  }),
776
790
  async execute(toolCallId, params = {}) {
@@ -1116,17 +1130,10 @@ function createTerminalToolAdapters(api, plugin, internalTools) {
1116
1130
  conversationKey,
1117
1131
  localSessionKey,
1118
1132
  });
1119
- const payloadWithViewer = await attachLocalConversationViewer(payload, {
1120
- context,
1121
- params,
1122
- role: 'participant',
1123
- source: 'close_conversation',
1124
- logger: getHookLogger(api),
1125
- });
1126
1133
  return buildTerminalActionResult({
1127
1134
  tool: manageConversationsTool,
1128
1135
  action,
1129
- payload: payloadWithViewer,
1136
+ payload,
1130
1137
  });
1131
1138
  }
1132
1139
  requireManageWorldField('action', `action must be one of ${TERMINAL_CONVERSATION_ACTIONS.join(', ')}`);
@@ -1142,6 +1149,11 @@ function buildRegisteredTools(api, plugin) {
1142
1149
  minLength: 1,
1143
1150
  examples: ['claworld'],
1144
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
+ });
1145
1157
  const chatRequestApprovalPolicyProperty = objectParam({
1146
1158
  description: 'Backend-managed inbound chat-request policy for this account.',
1147
1159
  required: ['mode'],
@@ -1721,7 +1733,6 @@ function buildRegisteredTools(api, plugin) {
1721
1733
  'Do not use this tool for replying inside an already-open Claworld chat or for runtime live turns.',
1722
1734
  'After creation, use claworld_chat_inbox to inspect pending, expired, rejected, opening, ending, active, silent, or ended status, or wait for the peer to accept.',
1723
1735
  'Once accepted, the runtime owns the live conversation loop.',
1724
- 'If the result includes conversationViewer.url, include that local viewer link in the owner-facing response so the human can watch the chat live.',
1725
1736
  ],
1726
1737
  examples: [
1727
1738
  {
@@ -1790,14 +1801,7 @@ function buildRegisteredTools(api, plugin) {
1790
1801
  openingMessage: params.openingMessage || null,
1791
1802
  worldId: params.worldId || null,
1792
1803
  });
1793
- const payloadWithViewer = await attachLocalConversationViewer(payload, {
1794
- context,
1795
- params,
1796
- role: 'requester',
1797
- source: 'request_chat',
1798
- logger: getHookLogger(api),
1799
- });
1800
- return buildToolResult(projectToolChatRequestMutationResponse(payloadWithViewer, { accountId: context.accountId }));
1804
+ return buildToolResult(projectToolChatRequestMutationResponse(payload, { accountId: context.accountId }));
1801
1805
  },
1802
1806
  },
1803
1807
  {
@@ -1816,7 +1820,6 @@ function buildRegisteredTools(api, plugin) {
1816
1820
  'For user requests to contact, PK, continue, or re-engage a Claworld peer, use claworld_manage_conversations(action=request) with the intended direct or world scope.',
1817
1821
  'Peer-facing opener/reply/final content is delivered by the Conversation Session and backend conversation runtime. Main Session must not use sessions_send to write peer-facing content into a local conversation session.',
1818
1822
  'Prefer Claworld conversation state, reports, and concise summaries before inspecting raw local transcript details.',
1819
- 'If an accept result includes conversationViewer.url, include that local viewer link in the owner-facing response or report.',
1820
1823
  'Global counts stay visible even when filters are applied; filtered counts describe the current narrowed result set.',
1821
1824
  'After action=accept or action=reject, call action=list again to refresh the inbox view.',
1822
1825
  ],
@@ -1907,16 +1910,7 @@ function buildRegisteredTools(api, plugin) {
1907
1910
  ...context,
1908
1911
  chatRequestId,
1909
1912
  });
1910
- const payloadWithViewer = action === 'accept'
1911
- ? await attachLocalConversationViewer(payload, {
1912
- context,
1913
- params,
1914
- role: 'recipient',
1915
- source: 'accept_chat_request',
1916
- logger: getHookLogger(api),
1917
- })
1918
- : payload;
1919
- return buildToolResult(projectToolChatInboxActionResponse(payloadWithViewer, {
1913
+ return buildToolResult(projectToolChatInboxActionResponse(payload, {
1920
1914
  accountId: context.accountId,
1921
1915
  action,
1922
1916
  }));
@@ -2011,6 +2005,7 @@ function buildRegisteredTools(api, plugin) {
2011
2005
  generateShareCard: booleanParam({
2012
2006
  description: 'When true, return a temporary public identity card URL. Defaults to false for view and true for update_identity.',
2013
2007
  }),
2008
+ shareCardVariant: shareCardVariantProperty,
2014
2009
  expiresInSeconds: integerParam({
2015
2010
  description: 'Optional temporary share-card TTL in seconds.',
2016
2011
  minimum: 1,
@@ -2027,6 +2022,7 @@ function buildRegisteredTools(api, plugin) {
2027
2022
  action: 'update_identity',
2028
2023
  displayName: '小发发',
2029
2024
  generateShareCard: true,
2025
+ shareCardVariant: 'zh',
2030
2026
  },
2031
2027
  {
2032
2028
  accountId: 'claworld',
@@ -2058,13 +2054,14 @@ function buildRegisteredTools(api, plugin) {
2058
2054
  ...context,
2059
2055
  displayName,
2060
2056
  generateShareCard,
2057
+ shareCardVariant: params.shareCardVariant ?? null,
2061
2058
  expiresInSeconds: params.expiresInSeconds ?? null,
2062
2059
  });
2063
2060
  return buildToolResult(projectToolAccountMutationResponse({
2064
2061
  action,
2065
2062
  accountId: context.accountId,
2066
2063
  identityPayload: payload,
2067
- runtimeActivation: payload?.runtimeActivation || null,
2064
+ runtimeIdentity: payload?.runtimeIdentity || null,
2068
2065
  }));
2069
2066
  }
2070
2067
 
@@ -2115,6 +2112,7 @@ function buildRegisteredTools(api, plugin) {
2115
2112
  runtimeConfig,
2116
2113
  agentId: context.agentId || runtimeConfig.relay?.agentId || null,
2117
2114
  generateShareCard,
2115
+ shareCardVariant: params.shareCardVariant ?? null,
2118
2116
  expiresInSeconds: params.expiresInSeconds ?? null,
2119
2117
  });
2120
2118
  const pairedAgentId = identityPayload?.agentId || runtimeConfig.relay?.agentId || null;
@@ -2148,11 +2146,19 @@ function buildRegisteredTools(api, plugin) {
2148
2146
  || runtimeConfig.relay?.appToken
2149
2147
  || runtimeConfig.relay?.credentialToken,
2150
2148
  );
2151
- const activationReady = hasConfiguredAppToken;
2152
- const bindingReady = activationReady && Boolean(pairedAgentId);
2153
- const bindingStatus = activationReady
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
2154
2160
  ? (bindingReady ? 'bound' : 'identity_unresolved')
2155
- : 'unactivated';
2161
+ : 'unbound';
2156
2162
  let relayAgent = relayAgentFallback;
2157
2163
  if (hasConfiguredAppToken && pairedAgentId && typeof plugin.helpers?.pairing?.resolveAgentIdentity === 'function') {
2158
2164
  const resolvedRelayAgent = await plugin.helpers.pairing.resolveAgentIdentity({
@@ -2171,13 +2177,16 @@ function buildRegisteredTools(api, plugin) {
2171
2177
  }
2172
2178
  }
2173
2179
  const pairingPayload = {
2174
- status: activationReady ? 'paired' : 'unpaired',
2180
+ status: hasConfiguredAppToken ? 'paired' : 'unpaired',
2175
2181
  bindingReady,
2176
2182
  bindingStatus,
2177
- reason: activationReady
2183
+ emailVerified,
2184
+ email: identityStatus?.email || null,
2185
+ verifiedAt: identityStatus?.verifiedAt || null,
2186
+ reason: hasConfiguredAppToken
2178
2187
  ? (pairedAgentId ? null : 'missing_agent_id')
2179
2188
  : 'missing_app_token',
2180
- bindingSource: activationReady
2189
+ bindingSource: hasConfiguredAppToken
2181
2190
  ? 'configured_app_token'
2182
2191
  : (runtimeConfig.registration?.enabled === true ? 'registration_pending' : 'unbound'),
2183
2192
  runtimeConfig: pairedRuntimeConfig,
@@ -2196,7 +2205,7 @@ function buildRegisteredTools(api, plugin) {
2196
2205
  }));
2197
2206
  }
2198
2207
 
2199
- export function registerClaworldPluginFull(api, plugin, { fetchImpl = globalThis.fetch } = {}) {
2208
+ export function registerClaworldPluginFull(api, plugin) {
2200
2209
  if (!plugin) {
2201
2210
  throw new Error('registerClaworldPluginFull requires a plugin instance');
2202
2211
  }
@@ -2265,16 +2274,17 @@ export function registerClaworldPluginFull(api, plugin, { fetchImpl = globalThis
2265
2274
  ? event.params
2266
2275
  : {};
2267
2276
  const requesterSessionKey = normalizeText(ctx?.sessionKey, null);
2268
- if (toolName !== 'claworld_manage_conversations') return;
2277
+ if (
2278
+ toolName !== 'claworld_manage_conversations'
2279
+ || normalizeTerminalConversationAction(params.action, null) !== 'request'
2280
+ || !requesterSessionKey
2281
+ ) {
2282
+ return;
2283
+ }
2269
2284
  const logger = getHookLogger(api);
2270
- let workspaceRoot = null;
2271
2285
  try {
2272
- workspaceRoot = await resolveHookWorkspaceRoot(api, event, ctx);
2273
- if (
2274
- workspaceRoot
2275
- && requesterSessionKey
2276
- && normalizeTerminalConversationAction(params.action, null) === 'request'
2277
- ) {
2286
+ const workspaceRoot = await resolveHookWorkspaceRoot(api, event, ctx);
2287
+ if (workspaceRoot) {
2278
2288
  await updateClaworldSessionDirectory(
2279
2289
  workspaceRoot,
2280
2290
  {
@@ -2295,12 +2305,10 @@ export function registerClaworldPluginFull(api, plugin, { fetchImpl = globalThis
2295
2305
  } catch (error) {
2296
2306
  logger?.warn?.('[claworld:working-memory] unable to update requester session directory', error);
2297
2307
  }
2298
- if (!requesterSessionKey && !workspaceRoot) return;
2299
2308
  return {
2300
2309
  params: {
2301
2310
  ...params,
2302
- ...(requesterSessionKey ? { [INTERNAL_REQUESTER_SESSION_KEY_PARAM]: requesterSessionKey } : {}),
2303
- ...(workspaceRoot ? { [INTERNAL_WORKSPACE_ROOT_PARAM]: workspaceRoot } : {}),
2311
+ [INTERNAL_REQUESTER_SESSION_KEY_PARAM]: requesterSessionKey,
2304
2312
  },
2305
2313
  };
2306
2314
  });
@@ -2329,11 +2337,6 @@ export function registerClaworldPluginFull(api, plugin, { fetchImpl = globalThis
2329
2337
  }
2330
2338
  if (typeof api.registerHttpRoute === 'function') {
2331
2339
  api.registerHttpRoute(buildClaworldStatusRoute(plugin));
2332
- api.registerHttpRoute(buildConversationViewerRoute(plugin, {
2333
- api,
2334
- fetchImpl,
2335
- logger: getHookLogger(api),
2336
- }));
2337
2340
  }
2338
2341
  if (typeof api.registerTool === 'function') {
2339
2342
  const internalTools = new Map(
@@ -2364,7 +2367,7 @@ export function registerClaworldPlugin(api, options = {}) {
2364
2367
  } = options;
2365
2368
  const plugin = existingPlugin || createClaworldChannelPlugin(pluginOptions);
2366
2369
  api.registerChannel({ plugin });
2367
- registerClaworldPluginFull(api, plugin, pluginOptions);
2370
+ registerClaworldPluginFull(api, plugin);
2368
2371
  return plugin;
2369
2372
  }
2370
2373