@xfxstudio/claworld 2026.5.10-testing.1 → 2026.5.14-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.
@@ -595,6 +595,34 @@ function projectToolAccountProfile(identityPayload = null) {
595
595
  return normalizeText(identityPayload?.profile, null);
596
596
  }
597
597
 
598
+ function projectToolAccountProfileState(identityPayload = null) {
599
+ const profilePayload = normalizeObject(identityPayload?.accountProfile, null);
600
+ const profile = normalizeText(profilePayload?.profile, projectToolAccountProfile(identityPayload));
601
+ const ready = profilePayload
602
+ ? profilePayload.ready === true
603
+ : Boolean(profile);
604
+ return {
605
+ status: normalizeText(profilePayload?.status, ready ? 'ready' : 'pending'),
606
+ ready,
607
+ profile,
608
+ reason: normalizeText(profilePayload?.reason, ready ? null : 'account_profile_missing'),
609
+ requiredAction: normalizeText(profilePayload?.requiredAction, ready ? null : 'update_agent_profile'),
610
+ nextAction: normalizeText(profilePayload?.nextAction, ready ? null : 'update_agent_profile'),
611
+ nextTool: normalizeText(profilePayload?.nextTool, ready ? null : 'claworld_manage_account'),
612
+ missingFields: Array.isArray(profilePayload?.missingFields)
613
+ ? profilePayload.missingFields
614
+ : (ready
615
+ ? []
616
+ : [
617
+ {
618
+ fieldId: 'profile',
619
+ label: 'Account Profile',
620
+ description: 'A non-empty global Claworld account profile used when other agents need to know who you are.',
621
+ },
622
+ ]),
623
+ };
624
+ }
625
+
598
626
  function projectToolChatRequestApprovalPolicy(payload = null) {
599
627
  const policy = normalizeObject(payload, null);
600
628
  if (!policy) return null;
@@ -652,7 +680,10 @@ export function projectToolAccountViewResponse({
652
680
  pairingPayload = null,
653
681
  identityPayload = null,
654
682
  } = {}) {
683
+ const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
684
+ const accountProfile = projectToolAccountProfileState(identityPayload);
655
685
  const identityReady = identityPayload?.ready === true;
686
+ const accountProfileReady = accountProfile.ready === true;
656
687
  const activationReady = pairingPayload?.status === 'paired';
657
688
  const bindingReady = typeof pairingPayload?.bindingReady === 'boolean'
658
689
  ? pairingPayload.bindingReady
@@ -663,7 +694,30 @@ export function projectToolAccountViewResponse({
663
694
  ? (bindingReady ? 'bound' : 'identity_unresolved')
664
695
  : 'unactivated',
665
696
  );
666
- const ready = activationReady && identityReady;
697
+ const ready = activationReady && identityReady && accountProfileReady;
698
+ const blockedAction = !identityReady
699
+ ? {
700
+ requiredAction: publicIdentityState.requiredAction,
701
+ nextAction: publicIdentityState.nextAction,
702
+ nextTool: publicIdentityState.nextTool,
703
+ missingFields: publicIdentityState.missingFields,
704
+ reason: 'public_identity_incomplete',
705
+ }
706
+ : !accountProfileReady
707
+ ? {
708
+ requiredAction: accountProfile.requiredAction,
709
+ nextAction: accountProfile.nextAction,
710
+ nextTool: accountProfile.nextTool,
711
+ missingFields: accountProfile.missingFields,
712
+ reason: accountProfile.reason,
713
+ }
714
+ : {
715
+ requiredAction: null,
716
+ nextAction: null,
717
+ nextTool: null,
718
+ missingFields: [],
719
+ reason: null,
720
+ };
667
721
  const relayResolved = pairingPayload?.relayAgent?.resolved ?? null;
668
722
  const relayOnline = pairingPayload?.relayAgent?.online ?? null;
669
723
  const resolvedShareCard = identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
@@ -674,10 +728,12 @@ export function projectToolAccountViewResponse({
674
728
  status: ready ? 'ready' : 'pending',
675
729
  ready,
676
730
  readiness: pairingPayload?.status === 'paired'
677
- ? (identityReady ? 'paired_and_ready' : 'paired_but_identity_pending')
731
+ ? (identityReady
732
+ ? (accountProfileReady ? 'paired_and_ready' : 'paired_but_account_profile_incomplete')
733
+ : 'paired_but_identity_pending')
678
734
  : 'installed_unactivated',
679
735
  accountId: normalizeText(pairingPayload?.runtimeConfig?.accountId, normalizeText(accountId, null)),
680
- reason: normalizeText(pairingPayload?.reason, null),
736
+ reason: normalizeText(pairingPayload?.reason, blockedAction.reason),
681
737
  bindingSource: normalizeText(pairingPayload?.bindingSource, null),
682
738
  activation: {
683
739
  status: activationReady ? 'ready' : 'pending',
@@ -687,6 +743,7 @@ export function projectToolAccountViewResponse({
687
743
  bindingReady,
688
744
  bindingStatus,
689
745
  publicIdentityReady: identityReady,
746
+ accountProfileReady,
690
747
  relayPresenceResolved: relayResolved,
691
748
  relayOnline,
692
749
  },
@@ -702,8 +759,13 @@ export function projectToolAccountViewResponse({
702
759
  resolved: relayResolved,
703
760
  bindingStatus,
704
761
  },
705
- profile: projectToolAccountProfile(identityPayload),
706
- ...projectToolAccountIdentityFields(identityPayload),
762
+ profile: accountProfile.profile,
763
+ ...publicIdentityState,
764
+ accountProfile,
765
+ requiredAction: blockedAction.requiredAction,
766
+ nextAction: blockedAction.nextAction,
767
+ nextTool: blockedAction.nextTool,
768
+ missingFields: blockedAction.missingFields,
707
769
  pluginVersionStatus: projectToolPluginVersionStatus(identityPayload?.pluginVersionStatus),
708
770
  chatRequestApprovalPolicy: projectToolChatRequestApprovalPolicy(identityPayload?.chatRequestApprovalPolicy),
709
771
  ...(resolvedShareCard !== undefined ? { shareCard: resolvedShareCard } : {}),
@@ -717,19 +779,55 @@ export function projectToolAccountMutationResponse({
717
779
  shareCard = undefined,
718
780
  runtimeActivation = null,
719
781
  } = {}) {
782
+ const publicIdentityState = projectToolAccountIdentityFields(identityPayload);
783
+ const accountProfile = projectToolAccountProfileState(identityPayload);
720
784
  const resolvedShareCard = shareCard !== undefined
721
785
  ? shareCard
722
786
  : (identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
723
787
  ? projectToolShareCard(identityPayload.shareCard)
724
788
  : undefined);
725
- const ready = identityPayload?.ready === true;
789
+ const identityReady = identityPayload?.ready === true;
790
+ const accountProfileReady = accountProfile.ready === true;
791
+ const ready = identityReady && accountProfileReady;
792
+ const blockedAction = !identityReady
793
+ ? {
794
+ requiredAction: publicIdentityState.requiredAction,
795
+ nextAction: publicIdentityState.nextAction,
796
+ nextTool: publicIdentityState.nextTool,
797
+ missingFields: publicIdentityState.missingFields,
798
+ reason: 'public_identity_incomplete',
799
+ }
800
+ : !accountProfileReady
801
+ ? {
802
+ requiredAction: accountProfile.requiredAction,
803
+ nextAction: accountProfile.nextAction,
804
+ nextTool: accountProfile.nextTool,
805
+ missingFields: accountProfile.missingFields,
806
+ reason: accountProfile.reason,
807
+ }
808
+ : {
809
+ requiredAction: null,
810
+ nextAction: null,
811
+ nextTool: null,
812
+ missingFields: [],
813
+ reason: null,
814
+ };
726
815
  return {
727
816
  action,
728
817
  status: ready ? 'ready' : 'pending',
729
818
  ready,
819
+ readiness: identityReady
820
+ ? (accountProfileReady ? 'ready' : 'account_profile_incomplete')
821
+ : 'public_identity_incomplete',
730
822
  accountId: normalizeText(accountId, null),
731
- profile: projectToolAccountProfile(identityPayload),
732
- ...projectToolAccountIdentityFields(identityPayload),
823
+ profile: accountProfile.profile,
824
+ ...publicIdentityState,
825
+ accountProfile,
826
+ requiredAction: blockedAction.requiredAction,
827
+ nextAction: blockedAction.nextAction,
828
+ nextTool: blockedAction.nextTool,
829
+ missingFields: blockedAction.missingFields,
830
+ reason: blockedAction.reason,
733
831
  pluginVersionStatus: projectToolPluginVersionStatus(identityPayload?.pluginVersionStatus),
734
832
  chatRequestApprovalPolicy: projectToolChatRequestApprovalPolicy(identityPayload?.chatRequestApprovalPolicy),
735
833
  ...(resolvedShareCard !== undefined ? { shareCard: resolvedShareCard } : {}),
@@ -18,6 +18,7 @@ import {
18
18
  buildClaworldToolMaintenanceEvent,
19
19
  ensureClaworldWorkingMemory,
20
20
  resolveClaworldBootstrapTarget,
21
+ updateClaworldSessionDirectory,
21
22
  } from '../runtime/working-memory.js';
22
23
  import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
23
24
  import { setClaworldRuntime } from './runtime.js';
@@ -2224,13 +2225,43 @@ export function registerClaworldPluginFull(api, plugin) {
2224
2225
  });
2225
2226
 
2226
2227
  api.on('before_tool_call', async (event, ctx) => {
2227
- if (event?.toolName !== 'claworld_manage_conversations') return;
2228
+ const toolName = normalizeText(event?.toolName, null);
2229
+ if (!toolName || !toolName.startsWith('claworld_')) return;
2228
2230
  const params = event?.params && typeof event.params === 'object' && !Array.isArray(event.params)
2229
2231
  ? event.params
2230
2232
  : {};
2231
- if (normalizeTerminalConversationAction(params.action, null) !== 'request') return;
2232
2233
  const requesterSessionKey = normalizeText(ctx?.sessionKey, null);
2233
- if (!requesterSessionKey) return;
2234
+ if (
2235
+ toolName !== 'claworld_manage_conversations'
2236
+ || normalizeTerminalConversationAction(params.action, null) !== 'request'
2237
+ || !requesterSessionKey
2238
+ ) {
2239
+ return;
2240
+ }
2241
+ const logger = getHookLogger(api);
2242
+ try {
2243
+ const workspaceRoot = await resolveHookWorkspaceRoot(api, event, ctx);
2244
+ if (workspaceRoot) {
2245
+ await updateClaworldSessionDirectory(
2246
+ workspaceRoot,
2247
+ {
2248
+ timestamp: event?.timestamp || ctx?.timestamp || null,
2249
+ source: 'claworld_hook',
2250
+ eventType: 'before_tool_call',
2251
+ kind: toolName,
2252
+ toolName,
2253
+ relations: {
2254
+ localSessionKey: requesterSessionKey,
2255
+ sessionKey: requesterSessionKey,
2256
+ localAgentId: normalizeText(ctx?.agentId ?? ctx?.AgentId, null),
2257
+ },
2258
+ context: ctx || {},
2259
+ },
2260
+ );
2261
+ }
2262
+ } catch (error) {
2263
+ logger?.warn?.('[claworld:working-memory] unable to update requester session directory', error);
2264
+ }
2234
2265
  return {
2235
2266
  params: {
2236
2267
  ...params,
@@ -2252,6 +2283,7 @@ export function registerClaworldPluginFull(api, plugin) {
2252
2283
  params: event?.params || {},
2253
2284
  result: hookToolResult(event),
2254
2285
  timestamp: event?.timestamp || ctx?.timestamp || null,
2286
+ context: ctx || {},
2255
2287
  });
2256
2288
  if (!maintenanceEvent) return;
2257
2289
  await appendClaworldJournalEvent(workspaceRoot, maintenanceEvent);
@@ -95,13 +95,23 @@ export function buildInboundEnvelope(message = {}) {
95
95
  'text',
96
96
  'body',
97
97
  'notification',
98
+ 'conversationKey',
99
+ 'worldId',
98
100
  ]) {
99
101
  if (payload[key] == null && data[key] != null) payload[key] = data[key];
100
102
  }
101
103
  }
104
+ const notification = payload.notification && typeof payload.notification === 'object' && !Array.isArray(payload.notification)
105
+ ? payload.notification
106
+ : data.notification && typeof data.notification === 'object' && !Array.isArray(data.notification)
107
+ ? data.notification
108
+ : {};
102
109
  const targetAgentId = normalizeEnvelopeText(
103
110
  data.targetAgentId,
104
- normalizeEnvelopeText(payload.targetAgentId, null),
111
+ normalizeEnvelopeText(
112
+ payload.targetAgentId,
113
+ normalizeEnvelopeText(notification.targetAgentId, normalizeEnvelopeText(metadata.targetAgentId, null)),
114
+ ),
105
115
  );
106
116
  const sessionKey = normalizeEnvelopeText(
107
117
  data.sessionKey,
@@ -109,23 +119,45 @@ export function buildInboundEnvelope(message = {}) {
109
119
  payload.sessionKey,
110
120
  normalizeEnvelopeText(
111
121
  data.targetSessionKey,
112
- normalizeEnvelopeText(payload.targetSessionKey, null),
122
+ normalizeEnvelopeText(
123
+ payload.targetSessionKey,
124
+ normalizeEnvelopeText(notification.targetSessionKey, normalizeEnvelopeText(metadata.sessionKey, null)),
125
+ ),
113
126
  ),
114
127
  ),
115
128
  );
116
129
  const isDeliveryEvent = message.event === 'delivery';
117
130
  const isRoutableEvent = Boolean(eventType && sessionKey);
118
131
  if (!isDeliveryEvent && !isRoutableEvent) return null;
132
+ const deliveryId = resolveEnvelopeMessageId(data, payload);
133
+ const eventName = normalizeEnvelopeText(
134
+ data.eventName,
135
+ normalizeEnvelopeText(payload.eventName, isDeliveryEvent ? null : normalizeEnvelopeText(message.event, null)),
136
+ );
119
137
  return {
120
138
  eventType: eventType || 'delivery',
121
- deliveryId: resolveEnvelopeMessageId(data, payload),
139
+ eventName,
140
+ eventId: deliveryId,
141
+ deliveryId,
122
142
  sessionKey,
123
143
  targetAgentId,
124
- createdAt: data.createdAt || data.availableAt || null,
125
- updatedAt: data.updatedAt || null,
144
+ conversationKey: normalizeEnvelopeText(
145
+ data.conversationKey,
146
+ normalizeEnvelopeText(payload.conversationKey, normalizeEnvelopeText(notification.relatedObjects?.conversationKey, null)),
147
+ ),
148
+ worldId: normalizeEnvelopeText(
149
+ data.worldId,
150
+ normalizeEnvelopeText(payload.worldId, normalizeEnvelopeText(notification.relatedObjects?.worldId, null)),
151
+ ),
152
+ createdAt: data.createdAt || payload.createdAt || data.availableAt || payload.availableAt || notification.createdAt || null,
153
+ updatedAt: data.updatedAt || payload.updatedAt || notification.updatedAt || null,
126
154
  turnCreatedAt: data.turnCreatedAt || null,
127
155
  payload,
128
- metadata,
156
+ metadata: {
157
+ ...metadata,
158
+ relayEvent: normalizeEnvelopeText(message.event, null),
159
+ inboxItemId: normalizeEnvelopeText(data.inboxItemId, normalizeEnvelopeText(payload.inboxItemId, null)),
160
+ },
129
161
  };
130
162
  }
131
163
 
@@ -21,16 +21,17 @@ export function createRelayEventProtocol() {
21
21
  describeEvent(event = {}) {
22
22
  const payload = normalizePayload(event.payload);
23
23
  const missing = [];
24
- if (normalizeText(event.eventType, null) !== DELIVERY_EVENT_TYPE) {
24
+ const eventType = normalizeText(event.eventType, null);
25
+ if (eventType !== DELIVERY_EVENT_TYPE) {
25
26
  missing.push('eventType');
26
27
  }
27
- if (!normalizeText(event.deliveryId, null)) {
28
+ if (eventType === DELIVERY_EVENT_TYPE && !normalizeText(event.deliveryId, null)) {
28
29
  missing.push('deliveryId');
29
30
  }
30
31
  if (!normalizeText(event.sessionKey, null)) {
31
32
  missing.push('sessionKey');
32
33
  }
33
- if (!normalizeText(payload.text, null)) {
34
+ if (eventType === DELIVERY_EVENT_TYPE && !normalizeText(payload.text, null)) {
34
35
  missing.push('payload.text');
35
36
  }
36
37
  return {
@@ -22,7 +22,6 @@ export function createInboundSessionRouter() {
22
22
  const target = resolveRuntimeSessionTarget(event, options);
23
23
  const sessionKey = target.sessionKey;
24
24
  return {
25
- action: target.sessionKind === 'management' ? 'route_management_input' : 'route_delivery',
26
25
  target: target.target,
27
26
  fallbackTarget: normalizeText(options.fallbackTarget, 'mainagent'),
28
27
  sessionKind: target.sessionKind,
@@ -44,13 +44,18 @@ export function buildConversationSessionKey(conversationKey = null, fallbackSess
44
44
  return normalizeText(fallbackSessionKey, null);
45
45
  }
46
46
 
47
+ function resolveSessionKindFromSessionKey(sessionKey = null) {
48
+ const normalizedSessionKey = normalizeText(sessionKey, null);
49
+ if (!normalizedSessionKey) return null;
50
+ const lowerSessionKey = normalizedSessionKey.toLowerCase();
51
+ if (lowerSessionKey.startsWith('management:') || lowerSessionKey.includes(':management:')) {
52
+ return CLAWORLD_SESSION_KINDS.management;
53
+ }
54
+ return CLAWORLD_SESSION_KINDS.conversation;
55
+ }
56
+
47
57
  export function resolveRuntimeSessionTarget(event = {}, options = {}) {
48
58
  const payload = normalizePayload(event.payload);
49
- const eventType = normalizeText(event.eventType || event.type || payload.eventType, null);
50
- const providedSessionKind = normalizeText(
51
- event.sessionKind,
52
- normalizeText(payload.sessionKind, normalizeText(options.sessionKind, null)),
53
- );
54
59
  const targetAgentId = normalizeText(
55
60
  event.targetAgentId,
56
61
  normalizeText(payload.targetAgentId, normalizeText(options.targetAgentId, null)),
@@ -63,16 +68,17 @@ export function resolveRuntimeSessionTarget(event = {}, options = {}) {
63
68
  event.sessionKey,
64
69
  normalizeText(payload.sessionKey, normalizeText(options.sessionKey, null)),
65
70
  );
71
+ const sessionKind = resolveSessionKindFromSessionKey(providedSessionKey);
66
72
 
67
- if (providedSessionKind === CLAWORLD_SESSION_KINDS.management || CLAWORLD_MANAGEMENT_EVENT_TYPES.includes(eventType)) {
68
- const managementSessionKey = normalizeText(
73
+ if (sessionKind === CLAWORLD_SESSION_KINDS.management) {
74
+ const managementSessionKey = normalizeText(providedSessionKey, normalizeText(
69
75
  options.managementSessionKey,
70
- normalizeText(providedSessionKey, buildManagementSessionKey(targetAgentId)),
71
- );
76
+ buildManagementSessionKey(targetAgentId),
77
+ ));
72
78
  return {
73
79
  sessionKind: CLAWORLD_SESSION_KINDS.management,
74
80
  target: normalizeText(options.managementTarget, 'management_session'),
75
- sessionKey: providedSessionKey || managementSessionKey,
81
+ sessionKey: providedSessionKey,
76
82
  managementSessionKey: managementSessionKey || null,
77
83
  conversationSessionKey: conversationKey ? buildConversationSessionKey(conversationKey) : null,
78
84
  targetAgentId,
@@ -85,7 +91,9 @@ export function resolveRuntimeSessionTarget(event = {}, options = {}) {
85
91
  sessionKind: CLAWORLD_SESSION_KINDS.conversation,
86
92
  target: normalizeText(options.sessionTarget, 'conversation_session'),
87
93
  sessionKey: conversationSessionKey,
88
- managementSessionKey: targetAgentId ? buildManagementSessionKey(targetAgentId) : null,
94
+ managementSessionKey: conversationSessionKey && targetAgentId
95
+ ? buildManagementSessionKey(targetAgentId)
96
+ : null,
89
97
  conversationSessionKey,
90
98
  targetAgentId,
91
99
  conversationKey,