@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.
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/claworld-a2a-channel-agent/SKILL.md +3 -6
- package/src/openclaw/plugin/claworld-channel-plugin.js +96 -533
- package/src/openclaw/plugin/register-tooling.js +25 -5
- package/src/openclaw/plugin/register.js +41 -50
- package/src/openclaw/plugin/relay-client-shared.js +96 -50
- package/src/openclaw/plugin/relay-client.js +275 -123
- package/src/openclaw/protocol/relay-event-protocol.js +6 -16
- package/src/openclaw/runtime/session-routing.js +7 -3
- package/src/openclaw/runtime/working-memory.js +54 -877
|
@@ -653,7 +653,19 @@ export function projectToolAccountViewResponse({
|
|
|
653
653
|
identityPayload = null,
|
|
654
654
|
} = {}) {
|
|
655
655
|
const identityReady = identityPayload?.ready === true;
|
|
656
|
-
const
|
|
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:
|
|
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:
|
|
682
|
-
resolved:
|
|
683
|
-
bindingStatus
|
|
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
|
|
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:
|
|
1995
|
-
|
|
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:
|
|
2030
|
+
bindingSource: activationReady
|
|
1999
2031
|
? 'configured_app_token'
|
|
2000
2032
|
: (runtimeConfig.registration?.enabled === true ? 'registration_pending' : 'unbound'),
|
|
2001
|
-
runtimeConfig:
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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:
|
|
74
|
-
deliveryId: data
|
|
75
|
-
sessionKey
|
|
76
|
-
|
|
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
|
|
80
|
-
? { ...data.payload }
|
|
81
|
-
: {},
|
|
127
|
+
payload,
|
|
82
128
|
metadata,
|
|
83
129
|
};
|
|
84
130
|
}
|