@xfxstudio/claworld 2026.4.30-testing.2 → 2026.5.3-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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/claworld-a2a-channel-agent/SKILL.md +3 -46
- package/skills/claworld-join-and-chat/SKILL.md +1 -14
- package/src/lib/relay/agent-readable-markdown.js +1 -24
- package/src/openclaw/plugin/claworld-channel-plugin.js +337 -121
- package/src/openclaw/plugin/register-tooling.js +25 -5
- package/src/openclaw/plugin/register.js +212 -58
- package/src/openclaw/plugin/relay-client-shared.js +132 -51
- package/src/openclaw/plugin/relay-client.js +275 -123
- package/src/openclaw/runtime/session-routing.js +7 -3
- package/src/openclaw/runtime/working-memory.js +86 -37
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
applyRuntimeIdentity,
|
|
@@ -137,6 +138,35 @@ function resolveNormalizedText(value, fallback = null) {
|
|
|
137
138
|
return normalizeClaworldText(value, fallback);
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
function resolveInboundMessageId({ delivery = {}, payload = {}, metadata = {} } = {}) {
|
|
142
|
+
const notification = payload.notification && typeof payload.notification === 'object' && !Array.isArray(payload.notification)
|
|
143
|
+
? payload.notification
|
|
144
|
+
: delivery.notification && typeof delivery.notification === 'object' && !Array.isArray(delivery.notification)
|
|
145
|
+
? delivery.notification
|
|
146
|
+
: {};
|
|
147
|
+
const candidates = [
|
|
148
|
+
delivery.deliveryId,
|
|
149
|
+
delivery.inboxItemId,
|
|
150
|
+
delivery.messageId,
|
|
151
|
+
delivery.eventId,
|
|
152
|
+
delivery.notificationId,
|
|
153
|
+
payload.deliveryId,
|
|
154
|
+
payload.inboxItemId,
|
|
155
|
+
payload.messageId,
|
|
156
|
+
payload.eventId,
|
|
157
|
+
payload.notificationId,
|
|
158
|
+
metadata.messageId,
|
|
159
|
+
metadata.eventId,
|
|
160
|
+
metadata.notificationId,
|
|
161
|
+
notification.notificationId,
|
|
162
|
+
];
|
|
163
|
+
for (const candidate of candidates) {
|
|
164
|
+
const normalized = resolveNormalizedText(candidate, null);
|
|
165
|
+
if (normalized) return normalized;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
140
170
|
function isAgentScopedSessionKey(sessionKey) {
|
|
141
171
|
return /^agent:[^:]+:/i.test(String(sessionKey || ''));
|
|
142
172
|
}
|
|
@@ -279,6 +309,7 @@ function parseBridgeTimestampMs(value) {
|
|
|
279
309
|
|
|
280
310
|
function resolveBridgeDeliveryTimestampMs({ delivery = {}, metadata = {} } = {}) {
|
|
281
311
|
return parseBridgeTimestampMs(delivery?.createdAt)
|
|
312
|
+
|| parseBridgeTimestampMs(delivery?.availableAt)
|
|
282
313
|
|| parseBridgeTimestampMs(delivery?.turnCreatedAt)
|
|
283
314
|
|| parseBridgeTimestampMs(metadata?.createdAt)
|
|
284
315
|
|| Date.now();
|
|
@@ -1757,6 +1788,7 @@ function buildDeliveryInboundEnvelope({
|
|
|
1757
1788
|
commandText = null,
|
|
1758
1789
|
timestamp = null,
|
|
1759
1790
|
deliveryId,
|
|
1791
|
+
eventType = 'delivery',
|
|
1760
1792
|
sessionKey,
|
|
1761
1793
|
localSessionKey = null,
|
|
1762
1794
|
worldId = null,
|
|
@@ -1775,13 +1807,16 @@ function buildDeliveryInboundEnvelope({
|
|
|
1775
1807
|
const normalizedCommandText = String(commandText || '').trim();
|
|
1776
1808
|
const commandBody = normalizedCommandText || rawBody;
|
|
1777
1809
|
const bodyForAgent = bodyText || rawBody;
|
|
1810
|
+
const eventLabel = normalizePluginOptionalText(eventType) === 'delivery'
|
|
1811
|
+
? 'delivery'
|
|
1812
|
+
: `event ${normalizePluginOptionalText(eventType)}`;
|
|
1778
1813
|
const contextLines = mergeUntrustedContextLines([
|
|
1779
1814
|
`[claworld peer ${remoteLabel}]`,
|
|
1780
1815
|
...(worldId ? [`[claworld world ${worldId}]`] : []),
|
|
1781
1816
|
...(conversationKey ? [`[claworld conversation ${conversationKey}]`] : []),
|
|
1782
1817
|
...(localSessionKey && localSessionKey !== sessionKey ? [`[claworld local session ${localSessionKey}]`] : []),
|
|
1783
1818
|
`[claworld relay session ${sessionKey}]`,
|
|
1784
|
-
`[claworld
|
|
1819
|
+
`[claworld ${eventLabel} ${deliveryId}]`,
|
|
1785
1820
|
], untrustedContext);
|
|
1786
1821
|
const envelopeTimestamp = Number.isFinite(timestamp) ? new Date(timestamp) : new Date();
|
|
1787
1822
|
|
|
@@ -1887,34 +1922,189 @@ function buildManagementRuntimeEventBody(details = {}, { localSessionKey = null
|
|
|
1887
1922
|
return lines.join('\n');
|
|
1888
1923
|
}
|
|
1889
1924
|
|
|
1890
|
-
function
|
|
1925
|
+
function normalizeSessionStoreKey(value) {
|
|
1926
|
+
return resolveNormalizedText(value, '').toLowerCase();
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
function resolveSessionStoreEntry(store = null, sessionKey = null) {
|
|
1930
|
+
if (!store || typeof store !== 'object' || Array.isArray(store)) return null;
|
|
1931
|
+
const normalizedSessionKey = resolveNormalizedText(sessionKey, null);
|
|
1932
|
+
if (!normalizedSessionKey) return null;
|
|
1933
|
+
if (store[normalizedSessionKey] && typeof store[normalizedSessionKey] === 'object') {
|
|
1934
|
+
return store[normalizedSessionKey];
|
|
1935
|
+
}
|
|
1936
|
+
const lowerSessionKey = normalizeSessionStoreKey(normalizedSessionKey);
|
|
1937
|
+
if (store[lowerSessionKey] && typeof store[lowerSessionKey] === 'object') {
|
|
1938
|
+
return store[lowerSessionKey];
|
|
1939
|
+
}
|
|
1940
|
+
const match = Object.entries(store).find(([key, value]) => (
|
|
1941
|
+
normalizeSessionStoreKey(key) === lowerSessionKey
|
|
1942
|
+
&& value
|
|
1943
|
+
&& typeof value === 'object'
|
|
1944
|
+
&& !Array.isArray(value)
|
|
1945
|
+
));
|
|
1946
|
+
return match ? match[1] : null;
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
function readRuntimeSessionStoreEntry({ runtime = null, sessionStorePath = null, sessionKey = null } = {}) {
|
|
1950
|
+
if (!runtime?.agent?.session?.loadSessionStore || !sessionStorePath || !sessionKey) return null;
|
|
1951
|
+
try {
|
|
1952
|
+
return resolveSessionStoreEntry(
|
|
1953
|
+
runtime.agent.session.loadSessionStore(sessionStorePath),
|
|
1954
|
+
sessionKey,
|
|
1955
|
+
);
|
|
1956
|
+
} catch {
|
|
1957
|
+
return null;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
function resolveSessionFilePathFromRuntime({
|
|
1962
|
+
runtime = null,
|
|
1963
|
+
sessionId = null,
|
|
1964
|
+
record = {},
|
|
1965
|
+
sessionStorePath = null,
|
|
1966
|
+
localAgentId = null,
|
|
1967
|
+
} = {}) {
|
|
1968
|
+
const normalizedSessionId = resolveNormalizedText(sessionId, null);
|
|
1969
|
+
if (!normalizedSessionId) return null;
|
|
1970
|
+
|
|
1971
|
+
const sessionsDir = sessionStorePath
|
|
1972
|
+
? path.dirname(path.resolve(sessionStorePath))
|
|
1973
|
+
: null;
|
|
1974
|
+
if (typeof runtime?.agent?.session?.resolveSessionFilePath === 'function') {
|
|
1975
|
+
try {
|
|
1976
|
+
const resolved = runtime.agent.session.resolveSessionFilePath(
|
|
1977
|
+
normalizedSessionId,
|
|
1978
|
+
record,
|
|
1979
|
+
{
|
|
1980
|
+
...(sessionsDir ? { sessionsDir } : {}),
|
|
1981
|
+
...(localAgentId ? { agentId: localAgentId } : {}),
|
|
1982
|
+
},
|
|
1983
|
+
);
|
|
1984
|
+
const normalized = resolveNormalizedText(resolved, null);
|
|
1985
|
+
if (normalized) return normalized;
|
|
1986
|
+
} catch {
|
|
1987
|
+
// Fall through to the local derivation below.
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
const candidate = resolveNormalizedText(record?.sessionFile, null);
|
|
1992
|
+
if (candidate) {
|
|
1993
|
+
if (path.isAbsolute(candidate) || !sessionsDir) return candidate;
|
|
1994
|
+
return path.resolve(sessionsDir, candidate);
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
if (sessionsDir) {
|
|
1998
|
+
return path.join(sessionsDir, `${normalizedSessionId}.jsonl`);
|
|
1999
|
+
}
|
|
2000
|
+
return null;
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
function resolveSessionRecordArtifacts(record = null, fallbackStorePath = null, options = {}) {
|
|
1891
2004
|
const normalizedRecord = record && typeof record === 'object' && !Array.isArray(record) ? record : {};
|
|
1892
2005
|
const nestedSession = normalizedRecord.session && typeof normalizedRecord.session === 'object' && !Array.isArray(normalizedRecord.session)
|
|
1893
2006
|
? normalizedRecord.session
|
|
1894
2007
|
: {};
|
|
1895
|
-
|
|
1896
|
-
sessionId
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
2008
|
+
const sessionId = resolveNormalizedText(
|
|
2009
|
+
normalizedRecord.sessionId,
|
|
2010
|
+
resolveNormalizedText(nestedSession.sessionId, resolveNormalizedText(normalizedRecord.id, null)),
|
|
2011
|
+
);
|
|
2012
|
+
const sessionStorePath = resolveNormalizedText(
|
|
2013
|
+
normalizedRecord.storePath,
|
|
2014
|
+
resolveNormalizedText(normalizedRecord.sessionStorePath, fallbackStorePath),
|
|
2015
|
+
);
|
|
2016
|
+
const directSessionFile = resolveNormalizedText(
|
|
2017
|
+
normalizedRecord.sessionFile,
|
|
2018
|
+
resolveNormalizedText(
|
|
2019
|
+
normalizedRecord.sessionPath,
|
|
1902
2020
|
resolveNormalizedText(
|
|
1903
|
-
normalizedRecord.
|
|
1904
|
-
resolveNormalizedText(
|
|
1905
|
-
normalizedRecord.filePath,
|
|
1906
|
-
resolveNormalizedText(normalizedRecord.path, resolveNormalizedText(nestedSession.filePath, null)),
|
|
1907
|
-
),
|
|
2021
|
+
normalizedRecord.filePath,
|
|
2022
|
+
resolveNormalizedText(normalizedRecord.path, resolveNormalizedText(nestedSession.filePath, null)),
|
|
1908
2023
|
),
|
|
1909
2024
|
),
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
2025
|
+
);
|
|
2026
|
+
const sessionFile = directSessionFile || resolveSessionFilePathFromRuntime({
|
|
2027
|
+
runtime: options.runtime,
|
|
2028
|
+
sessionId,
|
|
2029
|
+
record: normalizedRecord,
|
|
2030
|
+
sessionStorePath,
|
|
2031
|
+
localAgentId: options.localAgentId,
|
|
2032
|
+
});
|
|
2033
|
+
const transcriptPath = resolveNormalizedText(
|
|
2034
|
+
normalizedRecord.transcriptPath,
|
|
2035
|
+
resolveNormalizedText(nestedSession.transcriptPath, sessionFile),
|
|
2036
|
+
);
|
|
2037
|
+
return {
|
|
2038
|
+
sessionId,
|
|
2039
|
+
sessionFile,
|
|
2040
|
+
sessionStorePath,
|
|
2041
|
+
transcriptPath,
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
async function recordRuntimeInboundSessionArtifacts({
|
|
2046
|
+
runtime = null,
|
|
2047
|
+
currentCfg = {},
|
|
2048
|
+
localAgentId = null,
|
|
2049
|
+
sessionKey = null,
|
|
2050
|
+
ctx = {},
|
|
2051
|
+
logger = console,
|
|
2052
|
+
runtimeAccountId = null,
|
|
2053
|
+
logLabel = 'inbound',
|
|
2054
|
+
logContext = {},
|
|
2055
|
+
} = {}) {
|
|
2056
|
+
let sessionStorePath = null;
|
|
2057
|
+
let sessionRecord = null;
|
|
2058
|
+
const sessionApi = runtime?.channel?.session || {};
|
|
2059
|
+
const localSessionKey = resolveNormalizedText(ctx?.SessionKey, sessionKey);
|
|
2060
|
+
|
|
2061
|
+
if (sessionApi.resolveStorePath && localAgentId) {
|
|
2062
|
+
sessionStorePath = sessionApi.resolveStorePath(currentCfg.session?.store, {
|
|
2063
|
+
agentId: localAgentId,
|
|
2064
|
+
});
|
|
2065
|
+
const onRecordError = (error) => {
|
|
2066
|
+
logger.error?.(`[claworld:${runtimeAccountId}] failed to record ${logLabel} inbound session`, {
|
|
2067
|
+
...logContext,
|
|
2068
|
+
sessionKey,
|
|
2069
|
+
localSessionKey,
|
|
2070
|
+
localAgentId,
|
|
2071
|
+
error: error?.message || String(error),
|
|
2072
|
+
});
|
|
2073
|
+
};
|
|
2074
|
+
try {
|
|
2075
|
+
if (typeof sessionApi.recordSessionMetaFromInbound === 'function') {
|
|
2076
|
+
sessionRecord = await sessionApi.recordSessionMetaFromInbound({
|
|
2077
|
+
storePath: sessionStorePath,
|
|
2078
|
+
sessionKey: localSessionKey,
|
|
2079
|
+
ctx,
|
|
2080
|
+
});
|
|
2081
|
+
} else if (typeof sessionApi.recordInboundSession === 'function') {
|
|
2082
|
+
sessionRecord = await sessionApi.recordInboundSession({
|
|
2083
|
+
storePath: sessionStorePath,
|
|
2084
|
+
sessionKey: localSessionKey,
|
|
2085
|
+
ctx,
|
|
2086
|
+
onRecordError,
|
|
2087
|
+
});
|
|
2088
|
+
}
|
|
2089
|
+
} catch (error) {
|
|
2090
|
+
onRecordError(error);
|
|
2091
|
+
}
|
|
2092
|
+
if (!sessionRecord) {
|
|
2093
|
+
sessionRecord = readRuntimeSessionStoreEntry({
|
|
2094
|
+
runtime,
|
|
2095
|
+
sessionStorePath,
|
|
2096
|
+
sessionKey: localSessionKey,
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
return {
|
|
2102
|
+
sessionStorePath,
|
|
2103
|
+
sessionRecord,
|
|
2104
|
+
sessionArtifacts: resolveSessionRecordArtifacts(sessionRecord, sessionStorePath, {
|
|
2105
|
+
runtime,
|
|
2106
|
+
localAgentId,
|
|
2107
|
+
}),
|
|
1918
2108
|
};
|
|
1919
2109
|
}
|
|
1920
2110
|
|
|
@@ -2402,7 +2592,7 @@ function resolveBoundLocalAgentId({ cfg = {}, runtimeConfig = {}, relayClient }
|
|
|
2402
2592
|
|| 'main';
|
|
2403
2593
|
}
|
|
2404
2594
|
|
|
2405
|
-
async function
|
|
2595
|
+
async function maybeBridgeRuntimeInboundEvent({
|
|
2406
2596
|
relayClient,
|
|
2407
2597
|
runtimeConfig,
|
|
2408
2598
|
runtimeAccountId,
|
|
@@ -2421,36 +2611,49 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2421
2611
|
const payload = delivery.payload && typeof delivery.payload === 'object' && !Array.isArray(delivery.payload)
|
|
2422
2612
|
? delivery.payload
|
|
2423
2613
|
: {};
|
|
2424
|
-
const
|
|
2614
|
+
const eventType = resolveNormalizedText(delivery.eventType, resolveNormalizedText(event?.eventType, 'delivery'));
|
|
2615
|
+
const deliveryId = resolveInboundMessageId({ delivery, payload, metadata });
|
|
2425
2616
|
const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
|
|
2617
|
+
const fallbackRuntimeEventText = eventType !== 'delivery'
|
|
2618
|
+
? buildManagementRuntimeEventBody(resolveRuntimeManagementEnvelope(event))
|
|
2619
|
+
: null;
|
|
2426
2620
|
const contextText = resolveNormalizedText(payload.contextText, null);
|
|
2427
2621
|
const incomingText = resolveNormalizedText(
|
|
2428
2622
|
payload.commandText,
|
|
2429
|
-
contextText ? null : resolveNormalizedText(payload.text,
|
|
2623
|
+
contextText ? null : resolveNormalizedText(payload.text, resolveNormalizedText(payload.body, fallbackRuntimeEventText)),
|
|
2430
2624
|
);
|
|
2431
2625
|
const commandText = resolveNormalizedText(payload.commandText, incomingText);
|
|
2432
2626
|
const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
|
|
2433
|
-
const
|
|
2627
|
+
const routeSessionKind = resolveNormalizedText(
|
|
2628
|
+
event?.route?.sessionKind,
|
|
2629
|
+
resolveNormalizedText(delivery.sessionKind, resolveNormalizedText(payload.sessionKind, null)),
|
|
2630
|
+
);
|
|
2631
|
+
const isRelayDelivery = eventType === 'delivery';
|
|
2632
|
+
const allowReply = metadata.allowReply === true || (isRelayDelivery && metadata.allowReply !== false);
|
|
2633
|
+
const remoteIdentity = fromAgentId
|
|
2634
|
+
|| resolveNormalizedText(metadata.source, routeSessionKind === 'management' ? 'claworld-management' : 'unknown-peer');
|
|
2434
2635
|
|
|
2435
2636
|
if (
|
|
2436
2637
|
!runtime?.channel?.reply?.finalizeInboundContext
|
|
2437
2638
|
|| !runtime?.channel?.reply?.dispatchReplyFromConfig
|
|
2438
2639
|
|| !runtime?.channel?.reply?.createReplyDispatcherWithTyping
|
|
2439
2640
|
) {
|
|
2440
|
-
logger.warn?.(`[claworld:${runtimeAccountId}] skipping
|
|
2641
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] skipping inbound bridge: missing runtime bridge hooks`, {
|
|
2642
|
+
eventType,
|
|
2441
2643
|
deliveryId,
|
|
2442
2644
|
sessionKey,
|
|
2443
2645
|
});
|
|
2444
2646
|
return { skipped: true, reason: 'missing_runtime_bridge_hooks' };
|
|
2445
2647
|
}
|
|
2446
2648
|
if (!deliveryId || !sessionKey || (!incomingText && !contextText)) {
|
|
2447
|
-
logger.warn?.(`[claworld:${runtimeAccountId}] skipping
|
|
2649
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] skipping inbound bridge: missing payload`, {
|
|
2650
|
+
eventType,
|
|
2448
2651
|
deliveryId,
|
|
2449
2652
|
sessionKey,
|
|
2450
2653
|
hasIncomingText: Boolean(incomingText),
|
|
2451
2654
|
hasContextText: Boolean(contextText),
|
|
2452
2655
|
});
|
|
2453
|
-
return { skipped: true, reason: '
|
|
2656
|
+
return { skipped: true, reason: 'missing_inbound_payload' };
|
|
2454
2657
|
}
|
|
2455
2658
|
|
|
2456
2659
|
const loadedCfg = await runtime.config?.loadConfig?.() || {};
|
|
@@ -2476,7 +2679,7 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2476
2679
|
fallbackTarget: runtimeConfig.routing?.fallbackTarget,
|
|
2477
2680
|
}) || null;
|
|
2478
2681
|
const worldId = resolveDeliveryWorldId(delivery);
|
|
2479
|
-
const commandAuthorized = shouldAuthorizeBridgedCommand({
|
|
2682
|
+
const commandAuthorized = isRelayDelivery && shouldAuthorizeBridgedCommand({
|
|
2480
2683
|
runtimeConfig,
|
|
2481
2684
|
incomingText: commandText || incomingText,
|
|
2482
2685
|
});
|
|
@@ -2490,6 +2693,7 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2490
2693
|
commandText,
|
|
2491
2694
|
timestamp: inboundTimestamp,
|
|
2492
2695
|
deliveryId,
|
|
2696
|
+
eventType,
|
|
2493
2697
|
sessionKey,
|
|
2494
2698
|
localSessionKey,
|
|
2495
2699
|
worldId,
|
|
@@ -2497,6 +2701,9 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2497
2701
|
untrustedContext: payload.untrustedContext,
|
|
2498
2702
|
});
|
|
2499
2703
|
const localIdentity = normalizeClaworldText(runtimeConfig.relay?.agentId, runtimeConfig.accountId);
|
|
2704
|
+
const isManagementSession = routeSessionKind === 'management';
|
|
2705
|
+
const senderName = isManagementSession ? 'Claworld' : remoteIdentity;
|
|
2706
|
+
const conversationLabel = isManagementSession ? 'Claworld management' : remoteIdentity;
|
|
2500
2707
|
const inboundCtx = runtime.channel.reply.finalizeInboundContext({
|
|
2501
2708
|
Body,
|
|
2502
2709
|
RawBody,
|
|
@@ -2511,45 +2718,38 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2511
2718
|
OriginatingChannel: 'claworld',
|
|
2512
2719
|
OriginatingFrom: remoteIdentity,
|
|
2513
2720
|
OriginatingTo: remoteIdentity,
|
|
2514
|
-
ChatType: 'direct',
|
|
2515
|
-
|
|
2721
|
+
ChatType: isManagementSession ? 'management' : 'direct',
|
|
2722
|
+
SessionType: isManagementSession ? 'management' : 'direct',
|
|
2723
|
+
sessionType: isManagementSession ? 'management' : 'direct',
|
|
2724
|
+
sessionKind: isManagementSession ? 'management' : 'conversation',
|
|
2725
|
+
SenderName: senderName,
|
|
2516
2726
|
SenderId: remoteIdentity,
|
|
2517
2727
|
MessageId: deliveryId,
|
|
2518
2728
|
Provider: 'claworld',
|
|
2519
2729
|
Surface: 'claworld',
|
|
2520
|
-
ConversationLabel:
|
|
2730
|
+
ConversationLabel: conversationLabel,
|
|
2521
2731
|
Timestamp: inboundTimestamp,
|
|
2522
2732
|
MessageSid: deliveryId,
|
|
2523
2733
|
WasMentioned: false,
|
|
2524
2734
|
CommandAuthorized: commandAuthorized,
|
|
2525
|
-
RelayDeliveryId: deliveryId,
|
|
2735
|
+
RelayDeliveryId: isRelayDelivery ? deliveryId : null,
|
|
2526
2736
|
RelayFromAgentId: fromAgentId,
|
|
2527
2737
|
UntrustedContext,
|
|
2528
2738
|
});
|
|
2529
2739
|
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
deliveryId,
|
|
2544
|
-
sessionKey,
|
|
2545
|
-
localSessionKey,
|
|
2546
|
-
localAgentId,
|
|
2547
|
-
error: error?.message || String(error),
|
|
2548
|
-
});
|
|
2549
|
-
},
|
|
2550
|
-
});
|
|
2551
|
-
sessionArtifacts = resolveSessionRecordArtifacts(sessionRecord, sessionStorePath);
|
|
2552
|
-
}
|
|
2740
|
+
const {
|
|
2741
|
+
sessionArtifacts,
|
|
2742
|
+
} = await recordRuntimeInboundSessionArtifacts({
|
|
2743
|
+
runtime,
|
|
2744
|
+
currentCfg,
|
|
2745
|
+
localAgentId,
|
|
2746
|
+
sessionKey,
|
|
2747
|
+
ctx: inboundCtx,
|
|
2748
|
+
logger,
|
|
2749
|
+
runtimeAccountId,
|
|
2750
|
+
logLabel: isRelayDelivery ? 'delivery' : 'inbound',
|
|
2751
|
+
logContext: { eventType, deliveryId },
|
|
2752
|
+
});
|
|
2553
2753
|
|
|
2554
2754
|
const workspaceRoot = resolveOpenClawWorkspaceRoot({
|
|
2555
2755
|
sources: [
|
|
@@ -2563,9 +2763,8 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2563
2763
|
let journalResult = null;
|
|
2564
2764
|
if (workspaceRoot) {
|
|
2565
2765
|
try {
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
buildDeliveryRuntimeMaintenanceEvent({
|
|
2766
|
+
const maintenanceEvent = isRelayDelivery
|
|
2767
|
+
? buildDeliveryRuntimeMaintenanceEvent({
|
|
2569
2768
|
delivery,
|
|
2570
2769
|
metadata,
|
|
2571
2770
|
payload,
|
|
@@ -2573,14 +2772,24 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2573
2772
|
localAgentId,
|
|
2574
2773
|
sessionArtifacts,
|
|
2575
2774
|
workspaceRoot,
|
|
2576
|
-
})
|
|
2775
|
+
})
|
|
2776
|
+
: buildManagementRuntimeMaintenanceEvent(resolveRuntimeManagementEnvelope(event), {
|
|
2777
|
+
localSessionKey,
|
|
2778
|
+
localAgentId,
|
|
2779
|
+
sessionArtifacts,
|
|
2780
|
+
workspaceRoot,
|
|
2781
|
+
});
|
|
2782
|
+
journalResult = await appendClaworldJournalEvent(
|
|
2783
|
+
workspaceRoot,
|
|
2784
|
+
maintenanceEvent,
|
|
2577
2785
|
{
|
|
2578
|
-
trigger: 'delivery',
|
|
2579
|
-
rule: 'runtime_delivery_joined_session',
|
|
2786
|
+
trigger: isRelayDelivery ? 'delivery' : 'runtime_event',
|
|
2787
|
+
rule: isRelayDelivery ? 'runtime_delivery_joined_session' : 'runtime_event_joined_session',
|
|
2580
2788
|
},
|
|
2581
2789
|
);
|
|
2582
2790
|
} catch (error) {
|
|
2583
|
-
logger.warn?.(`[claworld:${runtimeAccountId}]
|
|
2791
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] inbound journal append failed`, {
|
|
2792
|
+
eventType,
|
|
2584
2793
|
deliveryId,
|
|
2585
2794
|
sessionKey,
|
|
2586
2795
|
localSessionKey,
|
|
@@ -2590,7 +2799,8 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2590
2799
|
}
|
|
2591
2800
|
}
|
|
2592
2801
|
|
|
2593
|
-
logger.info?.(`[claworld:${runtimeAccountId}] routing delivery into runtime session`, {
|
|
2802
|
+
logger.info?.(`[claworld:${runtimeAccountId}] ${isRelayDelivery ? 'routing delivery into runtime session' : 'routing inbound event into runtime session'}`, {
|
|
2803
|
+
eventType,
|
|
2594
2804
|
deliveryId,
|
|
2595
2805
|
sessionKey,
|
|
2596
2806
|
localSessionKey,
|
|
@@ -2601,28 +2811,30 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2601
2811
|
routeStatus: routed?.status || null,
|
|
2602
2812
|
bodyPreview: String(Body || '').slice(0, 240),
|
|
2603
2813
|
rawBodyPreview: String(RawBody || '').slice(0, 240),
|
|
2604
|
-
allowReply
|
|
2814
|
+
allowReply,
|
|
2605
2815
|
commandAuthorized,
|
|
2606
2816
|
journal: journalResult?.ok === true,
|
|
2607
2817
|
});
|
|
2608
2818
|
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2819
|
+
if (isRelayDelivery && metadata.acceptanceRequired !== false) {
|
|
2820
|
+
try {
|
|
2821
|
+
const acceptedResult = await relayClient.acceptDeliveryHttp({
|
|
2822
|
+
deliveryId,
|
|
2823
|
+
sessionKey,
|
|
2824
|
+
source: 'runtime_dispatch',
|
|
2825
|
+
});
|
|
2826
|
+
if (acceptedResult.status < 200 || acceptedResult.status >= 300) {
|
|
2827
|
+
throw new Error(`failed to submit relay delivery acceptance: ${acceptedResult.status}`);
|
|
2828
|
+
}
|
|
2829
|
+
} catch (error) {
|
|
2830
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] delivery acceptance acknowledgement failed`, {
|
|
2831
|
+
deliveryId,
|
|
2832
|
+
sessionKey,
|
|
2833
|
+
localSessionKey,
|
|
2834
|
+
localAgentId,
|
|
2835
|
+
error: error?.message || String(error),
|
|
2836
|
+
});
|
|
2617
2837
|
}
|
|
2618
|
-
} catch (error) {
|
|
2619
|
-
logger.warn?.(`[claworld:${runtimeAccountId}] delivery acceptance acknowledgement failed`, {
|
|
2620
|
-
deliveryId,
|
|
2621
|
-
sessionKey,
|
|
2622
|
-
localSessionKey,
|
|
2623
|
-
localAgentId,
|
|
2624
|
-
error: error?.message || String(error),
|
|
2625
|
-
});
|
|
2626
2838
|
}
|
|
2627
2839
|
|
|
2628
2840
|
let {
|
|
@@ -2637,15 +2849,16 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2637
2849
|
deliveryId,
|
|
2638
2850
|
sessionKey,
|
|
2639
2851
|
localAgentId,
|
|
2640
|
-
allowReply
|
|
2852
|
+
allowReply,
|
|
2641
2853
|
logger,
|
|
2642
2854
|
runtimeAccountId,
|
|
2643
2855
|
inboundCtx,
|
|
2644
2856
|
});
|
|
2645
2857
|
|
|
2646
2858
|
const shouldRetryKickoffDispatch = (
|
|
2647
|
-
|
|
2648
|
-
&& metadata.
|
|
2859
|
+
isRelayDelivery
|
|
2860
|
+
&& metadata.deliveryType === 'kickoff'
|
|
2861
|
+
&& allowReply
|
|
2649
2862
|
&& replied !== true
|
|
2650
2863
|
&& runtimeOutputSummary.counts.final > 0
|
|
2651
2864
|
&& runtimeOutputSummary.counts.nonRenderableFinal > 0
|
|
@@ -2682,14 +2895,15 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2682
2895
|
deliveryId,
|
|
2683
2896
|
sessionKey,
|
|
2684
2897
|
localAgentId,
|
|
2685
|
-
allowReply
|
|
2898
|
+
allowReply,
|
|
2686
2899
|
logger,
|
|
2687
2900
|
runtimeAccountId,
|
|
2688
2901
|
inboundCtx,
|
|
2689
2902
|
}));
|
|
2690
2903
|
}
|
|
2691
2904
|
|
|
2692
|
-
logger.info?.(`[claworld:${runtimeAccountId}] delivery bridge completed`, {
|
|
2905
|
+
logger.info?.(`[claworld:${runtimeAccountId}] ${isRelayDelivery ? 'delivery bridge completed' : 'inbound bridge completed'}`, {
|
|
2906
|
+
eventType,
|
|
2693
2907
|
deliveryId,
|
|
2694
2908
|
sessionKey,
|
|
2695
2909
|
localSessionKey,
|
|
@@ -2806,30 +3020,23 @@ async function maybeBridgeRuntimeManagementEvent({
|
|
|
2806
3020
|
RelayTargetAgentId: details.targetAgentId,
|
|
2807
3021
|
});
|
|
2808
3022
|
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
localAgentId,
|
|
2827
|
-
error: error?.message || String(error),
|
|
2828
|
-
});
|
|
2829
|
-
},
|
|
2830
|
-
});
|
|
2831
|
-
sessionArtifacts = resolveSessionRecordArtifacts(sessionRecord, sessionStorePath);
|
|
2832
|
-
}
|
|
3023
|
+
const {
|
|
3024
|
+
sessionStorePath,
|
|
3025
|
+
sessionArtifacts,
|
|
3026
|
+
} = await recordRuntimeInboundSessionArtifacts({
|
|
3027
|
+
runtime,
|
|
3028
|
+
currentCfg,
|
|
3029
|
+
localAgentId,
|
|
3030
|
+
sessionKey,
|
|
3031
|
+
ctx: inboundCtx,
|
|
3032
|
+
logger,
|
|
3033
|
+
runtimeAccountId,
|
|
3034
|
+
logLabel: 'management',
|
|
3035
|
+
logContext: {
|
|
3036
|
+
eventType: details.eventType,
|
|
3037
|
+
eventName: details.eventName,
|
|
3038
|
+
},
|
|
3039
|
+
});
|
|
2833
3040
|
|
|
2834
3041
|
const workspaceRoot = resolveOpenClawWorkspaceRoot({
|
|
2835
3042
|
sources: [
|
|
@@ -3350,9 +3557,9 @@ export function createClaworldChannelPlugin({
|
|
|
3350
3557
|
sessionKey: event?.delivery?.sessionKey || null,
|
|
3351
3558
|
});
|
|
3352
3559
|
|
|
3353
|
-
if (event?.
|
|
3560
|
+
if (event?.delivery?.sessionKey) {
|
|
3354
3561
|
const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
|
|
3355
|
-
|
|
3562
|
+
maybeBridgeRuntimeInboundEvent({
|
|
3356
3563
|
relayClient,
|
|
3357
3564
|
runtimeConfig,
|
|
3358
3565
|
runtimeAccountId,
|
|
@@ -3362,7 +3569,7 @@ export function createClaworldChannelPlugin({
|
|
|
3362
3569
|
cfg: runtimeContext.cfg,
|
|
3363
3570
|
inbound,
|
|
3364
3571
|
}).catch((error) => {
|
|
3365
|
-
logger.error?.(`[claworld:${runtimeAccountId}]
|
|
3572
|
+
logger.error?.(`[claworld:${runtimeAccountId}] inbound bridge exception`, {
|
|
3366
3573
|
error: error?.message || String(error),
|
|
3367
3574
|
});
|
|
3368
3575
|
});
|
|
@@ -3523,7 +3730,8 @@ export function createClaworldChannelPlugin({
|
|
|
3523
3730
|
}
|
|
3524
3731
|
|
|
3525
3732
|
async function updateRuntimePublicIdentity(context = {}) {
|
|
3526
|
-
const
|
|
3733
|
+
const configuredContext = resolveConfiguredRuntimeContext(context);
|
|
3734
|
+
const resolvedContext = await resolveBoundRuntimeContext(context);
|
|
3527
3735
|
const updateResult = await updatePublicIdentity({
|
|
3528
3736
|
runtimeConfig: resolvedContext.runtimeConfig,
|
|
3529
3737
|
agentId: resolvedContext.agentId || null,
|
|
@@ -3553,14 +3761,20 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
3553
3761
|
? applyRuntimeIdentity(nextRuntimeConfig, { agentId: nextAgentId })
|
|
3554
3762
|
: nextRuntimeConfig;
|
|
3555
3763
|
|
|
3764
|
+
const configuredAppToken = resolveRuntimeAppToken(configuredContext.runtimeConfig);
|
|
3556
3765
|
const previousAgentId = normalizeClaworldText(
|
|
3557
|
-
|
|
3558
|
-
normalizeClaworldText(
|
|
3766
|
+
configuredContext.runtimeConfig?.relay?.agentId,
|
|
3767
|
+
normalizeClaworldText(configuredContext.agentId, null),
|
|
3559
3768
|
);
|
|
3769
|
+
const nextAppToken = resolveRuntimeAppToken(boundRuntimeConfig);
|
|
3560
3770
|
const shouldPersistRuntimeBinding = Boolean(
|
|
3561
|
-
|
|
3771
|
+
nextAppToken
|
|
3562
3772
|
&& nextAgentId
|
|
3563
|
-
&& (
|
|
3773
|
+
&& (
|
|
3774
|
+
runtimeActivation
|
|
3775
|
+
|| configuredAppToken !== nextAppToken
|
|
3776
|
+
|| previousAgentId !== nextAgentId
|
|
3777
|
+
),
|
|
3564
3778
|
);
|
|
3565
3779
|
|
|
3566
3780
|
if (shouldPersistRuntimeBinding) {
|
|
@@ -3569,7 +3783,7 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
3569
3783
|
await persistRuntimeAppToken({
|
|
3570
3784
|
runtime: runtimeResolution.runtime,
|
|
3571
3785
|
accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
|
|
3572
|
-
appToken:
|
|
3786
|
+
appToken: nextAppToken,
|
|
3573
3787
|
relayAgentId: nextAgentId,
|
|
3574
3788
|
});
|
|
3575
3789
|
} catch (error) {
|
|
@@ -3582,7 +3796,9 @@ async function updateRuntimePublicIdentity(context = {}) {
|
|
|
3582
3796
|
rememberAccountBinding({
|
|
3583
3797
|
runtimeConfig: boundRuntimeConfig,
|
|
3584
3798
|
accountId: resolvedContext.accountId || boundRuntimeConfig.accountId || null,
|
|
3585
|
-
bindingSource: runtimeActivation
|
|
3799
|
+
bindingSource: runtimeActivation
|
|
3800
|
+
? 'activated_app_token'
|
|
3801
|
+
: (resolvedContext.bindingSource || 'configured_app_token'),
|
|
3586
3802
|
});
|
|
3587
3803
|
|
|
3588
3804
|
const accountKey = resolveAccountBindingKey(boundRuntimeConfig, resolvedContext.accountId || null);
|