@xfxstudio/claworld 2026.5.10-testing.1 → 2026.5.11-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/src/openclaw/plugin/claworld-channel-plugin.js +362 -27
- package/src/openclaw/plugin/register.js +35 -3
- package/src/openclaw/plugin/relay-client-shared.js +38 -6
- package/src/openclaw/protocol/relay-event-protocol.js +4 -3
- package/src/openclaw/runtime/inbound-session-router.js +0 -1
- package/src/openclaw/runtime/session-routing.js +19 -11
- package/src/openclaw/runtime/working-memory.js +1037 -56
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -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,
|
|
@@ -32,6 +33,10 @@ import { createInboundSessionRouter } from '../runtime/inbound-session-router.js
|
|
|
32
33
|
import { createOutboundSessionBridge } from '../runtime/outbound-session-bridge.js';
|
|
33
34
|
import { createCanonicalResultBuilder } from '../runtime/canonical-result-builder.js';
|
|
34
35
|
import { createDemoSessionBootstrap } from '../runtime/demo-session-bootstrap.js';
|
|
36
|
+
import {
|
|
37
|
+
appendClaworldJournalEvent,
|
|
38
|
+
buildClaworldRuntimeMaintenanceEvent,
|
|
39
|
+
} from '../runtime/working-memory.js';
|
|
35
40
|
import {
|
|
36
41
|
broadcastModeratedWorld,
|
|
37
42
|
createModeratedWorld,
|
|
@@ -62,6 +67,7 @@ import {
|
|
|
62
67
|
resolveWorldSelectionFlow,
|
|
63
68
|
} from '../runtime/product-shell-helper.js';
|
|
64
69
|
import { extractBackendErrorContext } from '../runtime/backend-error-context.js';
|
|
70
|
+
import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
|
|
65
71
|
import { getClaworldRuntime } from './runtime.js';
|
|
66
72
|
import {
|
|
67
73
|
CLAWORLD_PLUGIN_CURRENT_VERSION,
|
|
@@ -1841,6 +1847,297 @@ function buildDeliveryInboundEnvelope({
|
|
|
1841
1847
|
};
|
|
1842
1848
|
}
|
|
1843
1849
|
|
|
1850
|
+
function normalizeSessionStoreKey(value) {
|
|
1851
|
+
return resolveNormalizedText(value, '').toLowerCase();
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
function resolveSessionStoreEntry(store = null, sessionKey = null) {
|
|
1855
|
+
if (!store || typeof store !== 'object' || Array.isArray(store)) return null;
|
|
1856
|
+
const normalizedSessionKey = resolveNormalizedText(sessionKey, null);
|
|
1857
|
+
if (!normalizedSessionKey) return null;
|
|
1858
|
+
if (store[normalizedSessionKey] && typeof store[normalizedSessionKey] === 'object') {
|
|
1859
|
+
return store[normalizedSessionKey];
|
|
1860
|
+
}
|
|
1861
|
+
const lowerSessionKey = normalizeSessionStoreKey(normalizedSessionKey);
|
|
1862
|
+
if (store[lowerSessionKey] && typeof store[lowerSessionKey] === 'object') {
|
|
1863
|
+
return store[lowerSessionKey];
|
|
1864
|
+
}
|
|
1865
|
+
const match = Object.entries(store).find(([key, value]) => (
|
|
1866
|
+
normalizeSessionStoreKey(key) === lowerSessionKey
|
|
1867
|
+
&& value
|
|
1868
|
+
&& typeof value === 'object'
|
|
1869
|
+
&& !Array.isArray(value)
|
|
1870
|
+
));
|
|
1871
|
+
return match ? match[1] : null;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
function readRuntimeSessionStoreEntry({ runtime = null, sessionStorePath = null, sessionKey = null } = {}) {
|
|
1875
|
+
if (!runtime?.agent?.session?.loadSessionStore || !sessionStorePath || !sessionKey) return null;
|
|
1876
|
+
try {
|
|
1877
|
+
return resolveSessionStoreEntry(
|
|
1878
|
+
runtime.agent.session.loadSessionStore(sessionStorePath),
|
|
1879
|
+
sessionKey,
|
|
1880
|
+
);
|
|
1881
|
+
} catch {
|
|
1882
|
+
return null;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
function resolveSessionFilePathFromRuntime({
|
|
1887
|
+
runtime = null,
|
|
1888
|
+
sessionId = null,
|
|
1889
|
+
record = {},
|
|
1890
|
+
sessionStorePath = null,
|
|
1891
|
+
localAgentId = null,
|
|
1892
|
+
} = {}) {
|
|
1893
|
+
const normalizedSessionId = resolveNormalizedText(sessionId, null);
|
|
1894
|
+
if (!normalizedSessionId) return null;
|
|
1895
|
+
|
|
1896
|
+
const sessionsDir = sessionStorePath
|
|
1897
|
+
? path.dirname(path.resolve(sessionStorePath))
|
|
1898
|
+
: null;
|
|
1899
|
+
if (typeof runtime?.agent?.session?.resolveSessionFilePath === 'function') {
|
|
1900
|
+
try {
|
|
1901
|
+
const resolved = runtime.agent.session.resolveSessionFilePath(
|
|
1902
|
+
normalizedSessionId,
|
|
1903
|
+
record,
|
|
1904
|
+
{
|
|
1905
|
+
...(sessionsDir ? { sessionsDir } : {}),
|
|
1906
|
+
...(localAgentId ? { agentId: localAgentId } : {}),
|
|
1907
|
+
},
|
|
1908
|
+
);
|
|
1909
|
+
const normalized = resolveNormalizedText(resolved, null);
|
|
1910
|
+
if (normalized) return normalized;
|
|
1911
|
+
} catch {
|
|
1912
|
+
// Fall through to the local derivation below.
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
const candidate = resolveNormalizedText(record?.sessionFile, null);
|
|
1917
|
+
if (candidate) {
|
|
1918
|
+
if (path.isAbsolute(candidate) || !sessionsDir) return candidate;
|
|
1919
|
+
return path.resolve(sessionsDir, candidate);
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
if (sessionsDir) {
|
|
1923
|
+
return path.join(sessionsDir, `${normalizedSessionId}.jsonl`);
|
|
1924
|
+
}
|
|
1925
|
+
return null;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
function resolveSessionRecordArtifacts(record = null, fallbackStorePath = null, options = {}) {
|
|
1929
|
+
const normalizedRecord = record && typeof record === 'object' && !Array.isArray(record) ? record : {};
|
|
1930
|
+
const nestedSession = normalizedRecord.session && typeof normalizedRecord.session === 'object' && !Array.isArray(normalizedRecord.session)
|
|
1931
|
+
? normalizedRecord.session
|
|
1932
|
+
: {};
|
|
1933
|
+
const sessionId = resolveNormalizedText(
|
|
1934
|
+
normalizedRecord.sessionId,
|
|
1935
|
+
resolveNormalizedText(nestedSession.sessionId, resolveNormalizedText(normalizedRecord.id, null)),
|
|
1936
|
+
);
|
|
1937
|
+
const sessionStorePath = resolveNormalizedText(
|
|
1938
|
+
normalizedRecord.storePath,
|
|
1939
|
+
resolveNormalizedText(normalizedRecord.sessionStorePath, fallbackStorePath),
|
|
1940
|
+
);
|
|
1941
|
+
const directSessionFile = resolveNormalizedText(
|
|
1942
|
+
normalizedRecord.sessionFile,
|
|
1943
|
+
resolveNormalizedText(
|
|
1944
|
+
normalizedRecord.sessionPath,
|
|
1945
|
+
resolveNormalizedText(
|
|
1946
|
+
normalizedRecord.filePath,
|
|
1947
|
+
resolveNormalizedText(normalizedRecord.path, resolveNormalizedText(nestedSession.filePath, null)),
|
|
1948
|
+
),
|
|
1949
|
+
),
|
|
1950
|
+
);
|
|
1951
|
+
const sessionFile = directSessionFile || resolveSessionFilePathFromRuntime({
|
|
1952
|
+
runtime: options.runtime,
|
|
1953
|
+
sessionId,
|
|
1954
|
+
record: normalizedRecord,
|
|
1955
|
+
sessionStorePath,
|
|
1956
|
+
localAgentId: options.localAgentId,
|
|
1957
|
+
});
|
|
1958
|
+
const transcriptPath = resolveNormalizedText(
|
|
1959
|
+
normalizedRecord.transcriptPath,
|
|
1960
|
+
resolveNormalizedText(nestedSession.transcriptPath, sessionFile),
|
|
1961
|
+
);
|
|
1962
|
+
return {
|
|
1963
|
+
sessionId,
|
|
1964
|
+
sessionFile,
|
|
1965
|
+
sessionStorePath,
|
|
1966
|
+
transcriptPath,
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
async function recordRuntimeInboundSessionArtifacts({
|
|
1971
|
+
runtime = null,
|
|
1972
|
+
currentCfg = {},
|
|
1973
|
+
localAgentId = null,
|
|
1974
|
+
sessionKey = null,
|
|
1975
|
+
ctx = {},
|
|
1976
|
+
logger = console,
|
|
1977
|
+
runtimeAccountId = null,
|
|
1978
|
+
logLabel = 'inbound',
|
|
1979
|
+
logContext = {},
|
|
1980
|
+
} = {}) {
|
|
1981
|
+
let sessionStorePath = null;
|
|
1982
|
+
let sessionRecord = null;
|
|
1983
|
+
const sessionApi = runtime?.channel?.session || {};
|
|
1984
|
+
const localSessionKey = resolveNormalizedText(ctx?.SessionKey, sessionKey);
|
|
1985
|
+
|
|
1986
|
+
if (sessionApi.resolveStorePath && localAgentId) {
|
|
1987
|
+
sessionStorePath = sessionApi.resolveStorePath(currentCfg.session?.store, {
|
|
1988
|
+
agentId: localAgentId,
|
|
1989
|
+
});
|
|
1990
|
+
const onRecordError = (error) => {
|
|
1991
|
+
logger.error?.(`[claworld:${runtimeAccountId}] failed to record ${logLabel} inbound session`, {
|
|
1992
|
+
...logContext,
|
|
1993
|
+
sessionKey,
|
|
1994
|
+
localSessionKey,
|
|
1995
|
+
localAgentId,
|
|
1996
|
+
error: error?.message || String(error),
|
|
1997
|
+
});
|
|
1998
|
+
};
|
|
1999
|
+
try {
|
|
2000
|
+
if (typeof sessionApi.recordSessionMetaFromInbound === 'function') {
|
|
2001
|
+
sessionRecord = await sessionApi.recordSessionMetaFromInbound({
|
|
2002
|
+
storePath: sessionStorePath,
|
|
2003
|
+
sessionKey: localSessionKey,
|
|
2004
|
+
ctx,
|
|
2005
|
+
});
|
|
2006
|
+
} else if (typeof sessionApi.recordInboundSession === 'function') {
|
|
2007
|
+
sessionRecord = await sessionApi.recordInboundSession({
|
|
2008
|
+
storePath: sessionStorePath,
|
|
2009
|
+
sessionKey: localSessionKey,
|
|
2010
|
+
ctx,
|
|
2011
|
+
onRecordError,
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
} catch (error) {
|
|
2015
|
+
onRecordError(error);
|
|
2016
|
+
}
|
|
2017
|
+
if (!sessionRecord) {
|
|
2018
|
+
sessionRecord = readRuntimeSessionStoreEntry({
|
|
2019
|
+
runtime,
|
|
2020
|
+
sessionStorePath,
|
|
2021
|
+
sessionKey: localSessionKey,
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
return {
|
|
2027
|
+
sessionStorePath,
|
|
2028
|
+
sessionRecord,
|
|
2029
|
+
sessionArtifacts: resolveSessionRecordArtifacts(sessionRecord, sessionStorePath, {
|
|
2030
|
+
runtime,
|
|
2031
|
+
localAgentId,
|
|
2032
|
+
}),
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
function buildInboundRuntimeMaintenanceEvent({
|
|
2037
|
+
delivery = {},
|
|
2038
|
+
metadata = {},
|
|
2039
|
+
payload = {},
|
|
2040
|
+
messageId = null,
|
|
2041
|
+
eventType = 'delivery',
|
|
2042
|
+
sessionKind = null,
|
|
2043
|
+
localSessionKey = null,
|
|
2044
|
+
localAgentId = null,
|
|
2045
|
+
sessionArtifacts = {},
|
|
2046
|
+
workspaceRoot = null,
|
|
2047
|
+
} = {}) {
|
|
2048
|
+
const normalizedEventType = resolveNormalizedText(eventType, 'delivery');
|
|
2049
|
+
const isRelayDelivery = normalizedEventType === 'delivery';
|
|
2050
|
+
const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
|
|
2051
|
+
const requestId = resolveNormalizedText(
|
|
2052
|
+
metadata.kickoffRequestId,
|
|
2053
|
+
resolveNormalizedText(metadata.requestId, resolveNormalizedText(metadata.chatRequestId, null)),
|
|
2054
|
+
);
|
|
2055
|
+
const worldId = resolveNormalizedText(
|
|
2056
|
+
metadata.worldId,
|
|
2057
|
+
resolveNormalizedText(delivery.worldId, resolveNormalizedText(payload.worldId, null)),
|
|
2058
|
+
);
|
|
2059
|
+
const conversationKey = resolveNormalizedText(
|
|
2060
|
+
metadata.conversationKey,
|
|
2061
|
+
resolveNormalizedText(delivery.conversationKey, resolveNormalizedText(payload.conversationKey, null)),
|
|
2062
|
+
);
|
|
2063
|
+
const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
|
|
2064
|
+
const targetAgentId = resolveNormalizedText(
|
|
2065
|
+
delivery.targetAgentId,
|
|
2066
|
+
resolveNormalizedText(payload.targetAgentId, resolveNormalizedText(metadata.targetAgentId, null)),
|
|
2067
|
+
);
|
|
2068
|
+
const notificationId = resolveNormalizedText(
|
|
2069
|
+
metadata.notificationId,
|
|
2070
|
+
resolveNormalizedText(payload.notificationId, null),
|
|
2071
|
+
);
|
|
2072
|
+
const inboxItemId = resolveNormalizedText(
|
|
2073
|
+
metadata.inboxItemId,
|
|
2074
|
+
resolveNormalizedText(payload.inboxItemId, null),
|
|
2075
|
+
);
|
|
2076
|
+
const scope = sessionKind === 'management' ? 'management' : 'conversation';
|
|
2077
|
+
const summary = [
|
|
2078
|
+
isRelayDelivery
|
|
2079
|
+
? 'Inbound Claworld delivery joined local session'
|
|
2080
|
+
: 'Inbound Claworld runtime input joined local session',
|
|
2081
|
+
requestId ? `for request ${requestId}` : null,
|
|
2082
|
+
fromAgentId ? `from ${fromAgentId}` : null,
|
|
2083
|
+
].filter(Boolean).join(' ');
|
|
2084
|
+
return buildClaworldRuntimeMaintenanceEvent({
|
|
2085
|
+
id: messageId ? `runtime:${normalizedEventType}:${messageId}` : null,
|
|
2086
|
+
timestamp: delivery.createdAt || metadata.createdAt || payload.createdAt || null,
|
|
2087
|
+
kind: isRelayDelivery
|
|
2088
|
+
? (metadata.deliveryType ? `delivery.${metadata.deliveryType}` : 'delivery')
|
|
2089
|
+
: 'runtime_event',
|
|
2090
|
+
eventType: normalizedEventType,
|
|
2091
|
+
scope,
|
|
2092
|
+
summary,
|
|
2093
|
+
excerpt: isRelayDelivery
|
|
2094
|
+
? (
|
|
2095
|
+
payload.contextText
|
|
2096
|
+
? 'Inbound delivery included contextText; raw dialogue is kept in the OpenClaw session transcript.'
|
|
2097
|
+
: 'Inbound delivery routed into an OpenClaw session after backend session resolution.'
|
|
2098
|
+
)
|
|
2099
|
+
: 'Inbound runtime input routed into an OpenClaw session after backend session resolution.',
|
|
2100
|
+
refs: {
|
|
2101
|
+
deliveryId: isRelayDelivery ? messageId : null,
|
|
2102
|
+
eventId: messageId,
|
|
2103
|
+
requestId,
|
|
2104
|
+
chatRequestId: requestId,
|
|
2105
|
+
worldId,
|
|
2106
|
+
conversationKey,
|
|
2107
|
+
fromAgentId,
|
|
2108
|
+
targetAgentId,
|
|
2109
|
+
notificationId,
|
|
2110
|
+
inboxItemId,
|
|
2111
|
+
sessionKey: localSessionKey || sessionKey,
|
|
2112
|
+
relaySessionKey: sessionKey,
|
|
2113
|
+
},
|
|
2114
|
+
relations: {
|
|
2115
|
+
deliveryId: isRelayDelivery ? messageId : null,
|
|
2116
|
+
eventId: messageId,
|
|
2117
|
+
requestId,
|
|
2118
|
+
chatRequestId: requestId,
|
|
2119
|
+
worldId,
|
|
2120
|
+
conversationKey,
|
|
2121
|
+
fromAgentId,
|
|
2122
|
+
targetAgentId,
|
|
2123
|
+
notificationId,
|
|
2124
|
+
inboxItemId,
|
|
2125
|
+
localAgentId,
|
|
2126
|
+
localSessionKey,
|
|
2127
|
+
relaySessionKey: sessionKey,
|
|
2128
|
+
sessionKey: localSessionKey || sessionKey,
|
|
2129
|
+
sessionId: sessionArtifacts.sessionId,
|
|
2130
|
+
sessionFile: sessionArtifacts.sessionFile,
|
|
2131
|
+
sessionStorePath: sessionArtifacts.sessionStorePath,
|
|
2132
|
+
transcriptPath: sessionArtifacts.transcriptPath,
|
|
2133
|
+
},
|
|
2134
|
+
artifacts: {
|
|
2135
|
+
workspaceRoot,
|
|
2136
|
+
...sessionArtifacts,
|
|
2137
|
+
},
|
|
2138
|
+
});
|
|
2139
|
+
}
|
|
2140
|
+
|
|
1844
2141
|
function createDeliveryReplyDispatcher({
|
|
1845
2142
|
runtime,
|
|
1846
2143
|
currentCfg,
|
|
@@ -2232,18 +2529,14 @@ async function maybeBridgeRuntimeInboundEvent({
|
|
|
2232
2529
|
const contextText = resolveNormalizedText(payload.contextText, null);
|
|
2233
2530
|
const incomingText = resolveNormalizedText(
|
|
2234
2531
|
payload.commandText,
|
|
2235
|
-
contextText
|
|
2532
|
+
contextText
|
|
2533
|
+
? null
|
|
2534
|
+
: resolveNormalizedText(payload.text, resolveNormalizedText(payload.body, null)),
|
|
2236
2535
|
);
|
|
2237
2536
|
const commandText = resolveNormalizedText(payload.commandText, incomingText);
|
|
2238
2537
|
const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
|
|
2239
|
-
const routeSessionKind = resolveNormalizedText(
|
|
2240
|
-
event?.route?.sessionKind,
|
|
2241
|
-
resolveNormalizedText(delivery.sessionKind, resolveNormalizedText(payload.sessionKind, null)),
|
|
2242
|
-
);
|
|
2243
2538
|
const isRelayDelivery = eventType === 'delivery';
|
|
2244
2539
|
const allowReply = metadata.allowReply === true || (isRelayDelivery && metadata.allowReply !== false);
|
|
2245
|
-
const remoteIdentity = fromAgentId
|
|
2246
|
-
|| resolveNormalizedText(metadata.source, routeSessionKind === 'management' ? 'claworld-management' : 'unknown-peer');
|
|
2247
2540
|
|
|
2248
2541
|
if (
|
|
2249
2542
|
!runtime?.channel?.reply?.finalizeInboundContext
|
|
@@ -2290,6 +2583,12 @@ async function maybeBridgeRuntimeInboundEvent({
|
|
|
2290
2583
|
sessionTarget: runtimeConfig.routing?.sessionTarget,
|
|
2291
2584
|
fallbackTarget: runtimeConfig.routing?.fallbackTarget,
|
|
2292
2585
|
}) || null;
|
|
2586
|
+
const routeSessionKind = resolveNormalizedText(
|
|
2587
|
+
event?.route?.sessionKind,
|
|
2588
|
+
resolveNormalizedText(routed?.sessionKind, null),
|
|
2589
|
+
);
|
|
2590
|
+
const remoteIdentity = fromAgentId
|
|
2591
|
+
|| resolveNormalizedText(metadata.source, routeSessionKind === 'management' ? 'claworld-management' : 'unknown-peer');
|
|
2293
2592
|
const worldId = resolveDeliveryWorldId(delivery);
|
|
2294
2593
|
const commandAuthorized = isRelayDelivery && shouldAuthorizeBridgedCommand({
|
|
2295
2594
|
runtimeConfig,
|
|
@@ -2331,6 +2630,9 @@ async function maybeBridgeRuntimeInboundEvent({
|
|
|
2331
2630
|
OriginatingFrom: remoteIdentity,
|
|
2332
2631
|
OriginatingTo: remoteIdentity,
|
|
2333
2632
|
ChatType: isManagementSession ? 'management' : 'direct',
|
|
2633
|
+
SessionType: isManagementSession ? 'management' : 'direct',
|
|
2634
|
+
sessionType: isManagementSession ? 'management' : 'direct',
|
|
2635
|
+
sessionKind: isManagementSession ? 'management' : 'conversation',
|
|
2334
2636
|
SenderName: senderName,
|
|
2335
2637
|
SenderId: remoteIdentity,
|
|
2336
2638
|
MessageId: deliveryId,
|
|
@@ -2346,26 +2648,21 @@ async function maybeBridgeRuntimeInboundEvent({
|
|
|
2346
2648
|
UntrustedContext,
|
|
2347
2649
|
});
|
|
2348
2650
|
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
error: error?.message || String(error),
|
|
2365
|
-
});
|
|
2366
|
-
},
|
|
2367
|
-
});
|
|
2368
|
-
}
|
|
2651
|
+
const {
|
|
2652
|
+
sessionArtifacts,
|
|
2653
|
+
} = await recordRuntimeInboundSessionArtifacts({
|
|
2654
|
+
runtime,
|
|
2655
|
+
currentCfg,
|
|
2656
|
+
localAgentId,
|
|
2657
|
+
sessionKey,
|
|
2658
|
+
ctx: inboundCtx,
|
|
2659
|
+
logger,
|
|
2660
|
+
runtimeAccountId,
|
|
2661
|
+
logContext: {
|
|
2662
|
+
eventType,
|
|
2663
|
+
deliveryId,
|
|
2664
|
+
},
|
|
2665
|
+
});
|
|
2369
2666
|
|
|
2370
2667
|
logger.info?.(`[claworld:${runtimeAccountId}] ${isRelayDelivery ? 'routing delivery into runtime session' : 'routing inbound event into runtime session'}`, {
|
|
2371
2668
|
eventType,
|
|
@@ -2467,16 +2764,54 @@ async function maybeBridgeRuntimeInboundEvent({
|
|
|
2467
2764
|
}));
|
|
2468
2765
|
}
|
|
2469
2766
|
|
|
2767
|
+
let journalResult = null;
|
|
2768
|
+
const workspaceRoot = resolveOpenClawWorkspaceRoot({
|
|
2769
|
+
sources: [
|
|
2770
|
+
{ agentId: localAgentId, localAgentId },
|
|
2771
|
+
currentCfg,
|
|
2772
|
+
runtimeConfig,
|
|
2773
|
+
],
|
|
2774
|
+
config: currentCfg,
|
|
2775
|
+
agentId: localAgentId,
|
|
2776
|
+
});
|
|
2777
|
+
if (workspaceRoot) {
|
|
2778
|
+
try {
|
|
2779
|
+
const maintenanceEvent = buildInboundRuntimeMaintenanceEvent({
|
|
2780
|
+
delivery,
|
|
2781
|
+
metadata,
|
|
2782
|
+
payload,
|
|
2783
|
+
messageId: deliveryId,
|
|
2784
|
+
eventType,
|
|
2785
|
+
sessionKind: routeSessionKind,
|
|
2786
|
+
localSessionKey,
|
|
2787
|
+
localAgentId,
|
|
2788
|
+
sessionArtifacts,
|
|
2789
|
+
workspaceRoot,
|
|
2790
|
+
});
|
|
2791
|
+
journalResult = await appendClaworldJournalEvent(workspaceRoot, maintenanceEvent);
|
|
2792
|
+
} catch (error) {
|
|
2793
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] inbound journal append failed`, {
|
|
2794
|
+
eventType,
|
|
2795
|
+
deliveryId,
|
|
2796
|
+
sessionKey,
|
|
2797
|
+
error: error?.message || String(error),
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2470
2802
|
logger.info?.(`[claworld:${runtimeAccountId}] ${isRelayDelivery ? 'delivery bridge completed' : 'inbound bridge completed'}`, {
|
|
2471
2803
|
eventType,
|
|
2472
2804
|
deliveryId,
|
|
2473
2805
|
sessionKey,
|
|
2474
2806
|
localSessionKey,
|
|
2807
|
+
sessionId: sessionArtifacts.sessionId || null,
|
|
2808
|
+
sessionFile: sessionArtifacts.sessionFile || null,
|
|
2475
2809
|
queuedFinal: Boolean(dispatchResult?.queuedFinal),
|
|
2476
2810
|
replied,
|
|
2477
2811
|
keptSilent,
|
|
2478
2812
|
routeStatus: routed?.status || null,
|
|
2479
2813
|
runtimeOutputSummary,
|
|
2814
|
+
journal: journalResult?.ok === true,
|
|
2480
2815
|
});
|
|
2481
2816
|
|
|
2482
2817
|
return {
|
|
@@ -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
|
-
|
|
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 (
|
|
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(
|
|
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(
|
|
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
|
-
|
|
139
|
+
eventName,
|
|
140
|
+
eventId: deliveryId,
|
|
141
|
+
deliveryId,
|
|
122
142
|
sessionKey,
|
|
123
143
|
targetAgentId,
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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,
|