@xfxstudio/claworld 2026.4.30-testing.2 → 2026.4.30-testing.3

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.
@@ -653,7 +653,19 @@ export function projectToolAccountViewResponse({
653
653
  identityPayload = null,
654
654
  } = {}) {
655
655
  const identityReady = identityPayload?.ready === true;
656
- const ready = pairingPayload?.status === 'paired' && identityReady;
656
+ const activationReady = pairingPayload?.status === 'paired';
657
+ const bindingReady = typeof pairingPayload?.bindingReady === 'boolean'
658
+ ? pairingPayload.bindingReady
659
+ : activationReady;
660
+ const bindingStatus = normalizeText(
661
+ pairingPayload?.bindingStatus,
662
+ activationReady
663
+ ? (bindingReady ? 'bound' : 'identity_unresolved')
664
+ : 'unactivated',
665
+ );
666
+ const ready = activationReady && identityReady;
667
+ const relayResolved = pairingPayload?.relayAgent?.resolved ?? null;
668
+ const relayOnline = pairingPayload?.relayAgent?.online ?? null;
657
669
  const resolvedShareCard = identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
658
670
  ? projectToolShareCard(identityPayload.shareCard)
659
671
  : undefined;
@@ -668,7 +680,15 @@ export function projectToolAccountViewResponse({
668
680
  reason: normalizeText(pairingPayload?.reason, null),
669
681
  bindingSource: normalizeText(pairingPayload?.bindingSource, null),
670
682
  activation: {
671
- status: pairingPayload?.status === 'paired' ? 'ready' : 'pending',
683
+ status: activationReady ? 'ready' : 'pending',
684
+ },
685
+ diagnostics: {
686
+ toolReachable: true,
687
+ bindingReady,
688
+ bindingStatus,
689
+ publicIdentityReady: identityReady,
690
+ relayPresenceResolved: relayResolved,
691
+ relayOnline,
672
692
  },
673
693
  relay: {
674
694
  agentId: normalizeText(
@@ -678,9 +698,9 @@ export function projectToolAccountViewResponse({
678
698
  displayName: normalizeText(pairingPayload?.relayAgent?.displayName, null),
679
699
  discoverable: pairingPayload?.relayAgent?.discoverable ?? null,
680
700
  contactable: pairingPayload?.relayAgent?.contactable ?? null,
681
- online: pairingPayload?.relayAgent?.online ?? null,
682
- resolved: pairingPayload?.relayAgent?.resolved ?? null,
683
- bindingStatus: pairingPayload?.status === 'paired' ? 'bound' : 'unactivated',
701
+ online: relayOnline,
702
+ resolved: relayResolved,
703
+ bindingStatus,
684
704
  },
685
705
  profile: projectToolAccountProfile(identityPayload),
686
706
  ...projectToolAccountIdentityFields(identityPayload),
@@ -18,7 +18,6 @@ import {
18
18
  buildClaworldToolMaintenanceEvent,
19
19
  ensureClaworldWorkingMemory,
20
20
  resolveClaworldBootstrapTarget,
21
- updateClaworldSessionDirectory,
22
21
  } from '../runtime/working-memory.js';
23
22
  import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
24
23
  import { setClaworldRuntime } from './runtime.js';
@@ -1969,7 +1968,16 @@ function buildRegisteredTools(api, plugin) {
1969
1968
  expiresInSeconds: params.expiresInSeconds ?? null,
1970
1969
  });
1971
1970
  const pairedAgentId = identityPayload?.agentId || runtimeConfig.relay?.agentId || null;
1972
- const relayAgent = pairedAgentId
1971
+ const pairedRuntimeConfig = pairedAgentId
1972
+ ? {
1973
+ ...runtimeConfig,
1974
+ relay: {
1975
+ ...(runtimeConfig.relay && typeof runtimeConfig.relay === 'object' ? runtimeConfig.relay : {}),
1976
+ agentId: pairedAgentId,
1977
+ },
1978
+ }
1979
+ : runtimeConfig;
1980
+ const relayAgentFallback = pairedAgentId
1973
1981
  ? {
1974
1982
  agentId: pairedAgentId,
1975
1983
  displayName: normalizeText(
@@ -1990,23 +1998,39 @@ function buildRegisteredTools(api, plugin) {
1990
1998
  || runtimeConfig.relay?.appToken
1991
1999
  || runtimeConfig.relay?.credentialToken,
1992
2000
  );
2001
+ const activationReady = hasConfiguredAppToken;
2002
+ const bindingReady = activationReady && Boolean(pairedAgentId);
2003
+ const bindingStatus = activationReady
2004
+ ? (bindingReady ? 'bound' : 'identity_unresolved')
2005
+ : 'unactivated';
2006
+ let relayAgent = relayAgentFallback;
2007
+ if (hasConfiguredAppToken && pairedAgentId && typeof plugin.helpers?.pairing?.resolveAgentIdentity === 'function') {
2008
+ const resolvedRelayAgent = await plugin.helpers.pairing.resolveAgentIdentity({
2009
+ cfg,
2010
+ accountId,
2011
+ runtimeConfig: pairedRuntimeConfig,
2012
+ agentId: pairedAgentId,
2013
+ });
2014
+ if (resolvedRelayAgent && typeof resolvedRelayAgent === 'object') {
2015
+ relayAgent = {
2016
+ ...relayAgentFallback,
2017
+ ...resolvedRelayAgent,
2018
+ agentId: normalizeText(resolvedRelayAgent.agentId, pairedAgentId),
2019
+ displayName: normalizeText(resolvedRelayAgent.displayName, relayAgentFallback?.displayName ?? null),
2020
+ };
2021
+ }
2022
+ }
1993
2023
  const pairingPayload = {
1994
- status: hasConfiguredAppToken ? 'paired' : 'unpaired',
1995
- reason: hasConfiguredAppToken
2024
+ status: activationReady ? 'paired' : 'unpaired',
2025
+ bindingReady,
2026
+ bindingStatus,
2027
+ reason: activationReady
1996
2028
  ? (pairedAgentId ? null : 'missing_agent_id')
1997
2029
  : 'missing_app_token',
1998
- bindingSource: hasConfiguredAppToken
2030
+ bindingSource: activationReady
1999
2031
  ? 'configured_app_token'
2000
2032
  : (runtimeConfig.registration?.enabled === true ? 'registration_pending' : 'unbound'),
2001
- runtimeConfig: pairedAgentId
2002
- ? {
2003
- ...runtimeConfig,
2004
- relay: {
2005
- ...(runtimeConfig.relay && typeof runtimeConfig.relay === 'object' ? runtimeConfig.relay : {}),
2006
- agentId: pairedAgentId,
2007
- },
2008
- }
2009
- : runtimeConfig,
2033
+ runtimeConfig: pairedRuntimeConfig,
2010
2034
  relayAgent,
2011
2035
  };
2012
2036
  return buildToolResult(projectToolAccountViewResponse({
@@ -2071,45 +2095,13 @@ export function registerClaworldPluginFull(api, plugin) {
2071
2095
  });
2072
2096
 
2073
2097
  api.on('before_tool_call', async (event, ctx) => {
2074
- const toolName = normalizeText(event?.toolName, null);
2075
- if (!toolName || !toolName.startsWith('claworld_')) return;
2098
+ if (event?.toolName !== 'claworld_manage_conversations') return;
2076
2099
  const params = event?.params && typeof event.params === 'object' && !Array.isArray(event.params)
2077
2100
  ? event.params
2078
2101
  : {};
2102
+ if (normalizeTerminalConversationAction(params.action, null) !== 'request') return;
2079
2103
  const requesterSessionKey = normalizeText(ctx?.sessionKey, null);
2080
- if (requesterSessionKey) {
2081
- const logger = getHookLogger(api);
2082
- try {
2083
- const workspaceRoot = await resolveHookWorkspaceRoot(api, event, ctx);
2084
- if (workspaceRoot) {
2085
- await updateClaworldSessionDirectory(
2086
- workspaceRoot,
2087
- {
2088
- timestamp: event?.timestamp || ctx?.timestamp || null,
2089
- source: 'claworld_hook',
2090
- eventType: 'before_tool_call',
2091
- kind: toolName,
2092
- toolName,
2093
- relations: {
2094
- localSessionKey: requesterSessionKey,
2095
- sessionKey: requesterSessionKey,
2096
- localAgentId: normalizeText(ctx?.agentId ?? ctx?.AgentId, null),
2097
- },
2098
- context: ctx || {},
2099
- },
2100
- );
2101
- }
2102
- } catch (error) {
2103
- logger?.warn?.('[claworld:working-memory] unable to update session directory before tool call', error);
2104
- }
2105
- }
2106
- if (
2107
- toolName !== 'claworld_manage_conversations'
2108
- || normalizeTerminalConversationAction(params.action, null) !== 'request'
2109
- || !requesterSessionKey
2110
- ) {
2111
- return;
2112
- }
2104
+ if (!requesterSessionKey) return;
2113
2105
  return {
2114
2106
  params: {
2115
2107
  ...params,
@@ -2131,7 +2123,6 @@ export function registerClaworldPluginFull(api, plugin) {
2131
2123
  params: event?.params || {},
2132
2124
  result: hookToolResult(event),
2133
2125
  timestamp: event?.timestamp || ctx?.timestamp || null,
2134
- context: ctx || {},
2135
2126
  });
2136
2127
  if (!maintenanceEvent) return;
2137
2128
  await appendClaworldJournalEvent(workspaceRoot, maintenanceEvent);
@@ -5,6 +5,51 @@ export const STALE_CONNECTION_CLOSE_CODE = 4002;
5
5
  export const TERMINAL_CLOSE_REASONS = new Set(['duplicate_connection_replaced', 'stale_connection']);
6
6
  export const DEFAULT_REPLY_ACK_TIMEOUT_MS = 5000;
7
7
 
8
+ function cloneObject(value, fallback = {}) {
9
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return { ...fallback };
10
+ return { ...value };
11
+ }
12
+
13
+ function normalizeEnvelopeText(value, fallback = null) {
14
+ if (value == null) return fallback;
15
+ const normalized = String(value).trim();
16
+ return normalized || fallback;
17
+ }
18
+
19
+ function resolveEnvelopeMessageId(data = {}, payload = {}) {
20
+ const notification = payload.notification && typeof payload.notification === 'object' && !Array.isArray(payload.notification)
21
+ ? payload.notification
22
+ : data.notification && typeof data.notification === 'object' && !Array.isArray(data.notification)
23
+ ? data.notification
24
+ : {};
25
+ const metadata = data.metadata && typeof data.metadata === 'object' && !Array.isArray(data.metadata)
26
+ ? data.metadata
27
+ : payload.metadata && typeof payload.metadata === 'object' && !Array.isArray(payload.metadata)
28
+ ? payload.metadata
29
+ : {};
30
+ const candidates = [
31
+ data.deliveryId,
32
+ data.inboxItemId,
33
+ data.messageId,
34
+ data.eventId,
35
+ data.notificationId,
36
+ payload.deliveryId,
37
+ payload.inboxItemId,
38
+ payload.messageId,
39
+ payload.eventId,
40
+ payload.notificationId,
41
+ metadata.messageId,
42
+ metadata.eventId,
43
+ metadata.notificationId,
44
+ notification.notificationId,
45
+ ];
46
+ for (const candidate of candidates) {
47
+ const normalized = normalizeEnvelopeText(candidate, null);
48
+ if (normalized) return normalized;
49
+ }
50
+ return null;
51
+ }
52
+
8
53
  export function normalizeRelayWebSocketUrl(serverUrl) {
9
54
  const parsed = new URL(serverUrl);
10
55
  if (parsed.protocol === 'http:') parsed.protocol = 'ws:';
@@ -23,62 +68,63 @@ export function normalizeRelayWebSocketUrl(serverUrl) {
23
68
 
24
69
  export function buildInboundEnvelope(message = {}) {
25
70
  const data = message.data || {};
71
+ const directPayload = data.payload && typeof data.payload === 'object' && !Array.isArray(data.payload)
72
+ ? { ...data.payload }
73
+ : {};
26
74
  const metadata = data.metadata && typeof data.metadata === 'object' && !Array.isArray(data.metadata)
27
75
  ? { ...data.metadata }
28
- : {};
29
- if (message.event !== 'delivery') {
30
- const eventType = normalizeOptionalText(data.eventType) || normalizeOptionalText(message.event);
31
- const notification = data.notification && typeof data.notification === 'object' && !Array.isArray(data.notification)
32
- ? data.notification
33
- : {};
34
- const targetAgentId = normalizeOptionalText(
35
- data.targetAgentId
36
- || notification.targetAgentId
37
- || metadata.targetAgentId,
38
- );
39
- const sessionKey = normalizeOptionalText(
40
- data.sessionKey
41
- || notification.targetSessionKey
42
- || metadata.sessionKey,
43
- ) || (targetAgentId ? `management:${targetAgentId}` : null);
44
- if (!eventType || !sessionKey) return null;
45
- return {
46
- eventType,
47
- eventName: normalizeOptionalText(data.eventName) || normalizeOptionalText(message.event),
48
- eventId: normalizeOptionalText(data.eventId)
49
- || normalizeOptionalText(data.inboxItemId)
50
- || normalizeOptionalText(notification.notificationId)
51
- || null,
52
- sessionKey,
53
- targetAgentId,
54
- conversationKey: normalizeOptionalText(data.conversationKey)
55
- || normalizeOptionalText(notification.relatedObjects?.conversationKey)
56
- || null,
57
- worldId: normalizeOptionalText(data.worldId)
58
- || normalizeOptionalText(notification.relatedObjects?.worldId)
59
- || null,
60
- createdAt: data.createdAt || notification.createdAt || null,
61
- updatedAt: data.updatedAt || notification.updatedAt || null,
62
- payload: data && typeof data === 'object' && !Array.isArray(data)
63
- ? { ...data }
64
- : {},
65
- metadata: {
66
- ...metadata,
67
- relayEvent: normalizeOptionalText(message.event),
68
- inboxItemId: normalizeOptionalText(data.inboxItemId) || null,
69
- },
70
- };
76
+ : directPayload.metadata && typeof directPayload.metadata === 'object' && !Array.isArray(directPayload.metadata)
77
+ ? { ...directPayload.metadata }
78
+ : cloneObject(data.meta, {});
79
+ const payloadEventType = normalizeEnvelopeText(directPayload.eventType, null);
80
+ const dataEventType = normalizeEnvelopeText(data.eventType, null);
81
+ const eventType = dataEventType
82
+ || payloadEventType
83
+ || (message.event === 'delivery' ? 'delivery' : normalizeEnvelopeText(message.event, null));
84
+ const payload = Object.keys(directPayload).length > 0
85
+ ? { ...directPayload }
86
+ : cloneObject(data, {});
87
+ if (Object.keys(directPayload).length > 0) {
88
+ for (const key of [
89
+ 'eventType',
90
+ 'eventName',
91
+ 'sessionKind',
92
+ 'sessionKey',
93
+ 'targetSessionKey',
94
+ 'targetAgentId',
95
+ 'text',
96
+ 'body',
97
+ 'notification',
98
+ ]) {
99
+ if (payload[key] == null && data[key] != null) payload[key] = data[key];
100
+ }
71
101
  }
102
+ const targetAgentId = normalizeEnvelopeText(
103
+ data.targetAgentId,
104
+ normalizeEnvelopeText(payload.targetAgentId, null),
105
+ );
106
+ const sessionKey = normalizeEnvelopeText(
107
+ data.sessionKey,
108
+ normalizeEnvelopeText(
109
+ payload.sessionKey,
110
+ normalizeEnvelopeText(
111
+ data.targetSessionKey,
112
+ normalizeEnvelopeText(payload.targetSessionKey, null),
113
+ ),
114
+ ),
115
+ );
116
+ const isDeliveryEvent = message.event === 'delivery';
117
+ const isRoutableEvent = Boolean(eventType && sessionKey);
118
+ if (!isDeliveryEvent && !isRoutableEvent) return null;
72
119
  return {
73
- eventType: data.eventType || 'delivery',
74
- deliveryId: data.deliveryId || null,
75
- sessionKey: data.sessionKey || null,
76
- createdAt: data.createdAt || null,
120
+ eventType: eventType || 'delivery',
121
+ deliveryId: resolveEnvelopeMessageId(data, payload),
122
+ sessionKey,
123
+ targetAgentId,
124
+ createdAt: data.createdAt || data.availableAt || null,
77
125
  updatedAt: data.updatedAt || null,
78
126
  turnCreatedAt: data.turnCreatedAt || null,
79
- payload: data.payload && typeof data.payload === 'object' && !Array.isArray(data.payload)
80
- ? { ...data.payload }
81
- : {},
127
+ payload,
82
128
  metadata,
83
129
  };
84
130
  }