@xfxstudio/claworld 2026.4.30-testing.1 → 2026.4.30-testing.2
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 +6 -3
- package/src/openclaw/plugin/claworld-channel-plugin.js +494 -3
- package/src/openclaw/plugin/register-tooling.js +5 -25
- package/src/openclaw/plugin/register.js +50 -41
- package/src/openclaw/plugin/relay-client-shared.js +43 -1
- package/src/openclaw/protocol/relay-event-protocol.js +16 -6
- package/src/openclaw/runtime/working-memory.js +877 -54
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -31,9 +31,12 @@ description: |
|
|
|
31
31
|
- That document is internal. It is for you only. Do not quote it, paraphrase
|
|
32
32
|
it, summarize it to the peer, or mention its section names.
|
|
33
33
|
- If workspace-local Claworld working memory is available and the current
|
|
34
|
-
intent needs prior Claworld progress,
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
intent needs prior Claworld progress, prefer direct reads from
|
|
35
|
+
`.claworld/context/NOW.md`, `.claworld/context/MEMORY.md`,
|
|
36
|
+
`.claworld/context/PROFILE.md`, `.claworld/journal/`, `.claworld/reports/`,
|
|
37
|
+
and `.claworld/sessions/index.json`. Use the session directory before
|
|
38
|
+
searching raw local session files. Prefer summarized `NOW`, `MEMORY`,
|
|
39
|
+
`PROFILE`, journal, and report content over raw transcripts.
|
|
37
40
|
- Do not write `.claworld/` content into global `MEMORY.md`, and do not load
|
|
38
41
|
raw Claworld transcripts by default.
|
|
39
42
|
- A single local session transcript may contain multiple accepted-chat intents
|
|
@@ -32,6 +32,11 @@ import { createInboundSessionRouter } from '../runtime/inbound-session-router.js
|
|
|
32
32
|
import { createOutboundSessionBridge } from '../runtime/outbound-session-bridge.js';
|
|
33
33
|
import { createCanonicalResultBuilder } from '../runtime/canonical-result-builder.js';
|
|
34
34
|
import { createDemoSessionBootstrap } from '../runtime/demo-session-bootstrap.js';
|
|
35
|
+
import {
|
|
36
|
+
appendClaworldJournalEvent,
|
|
37
|
+
buildClaworldRuntimeMaintenanceEvent,
|
|
38
|
+
} from '../runtime/working-memory.js';
|
|
39
|
+
import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
|
|
35
40
|
import {
|
|
36
41
|
broadcastModeratedWorld,
|
|
37
42
|
createModeratedWorld,
|
|
@@ -1807,6 +1812,230 @@ function buildDeliveryInboundEnvelope({
|
|
|
1807
1812
|
};
|
|
1808
1813
|
}
|
|
1809
1814
|
|
|
1815
|
+
function resolveRuntimeManagementEnvelope(event = {}) {
|
|
1816
|
+
const envelope = event?.delivery && typeof event.delivery === 'object' && !Array.isArray(event.delivery)
|
|
1817
|
+
? event.delivery
|
|
1818
|
+
: {};
|
|
1819
|
+
const payload = envelope.payload && typeof envelope.payload === 'object' && !Array.isArray(envelope.payload)
|
|
1820
|
+
? envelope.payload
|
|
1821
|
+
: {};
|
|
1822
|
+
const notification = payload.notification && typeof payload.notification === 'object' && !Array.isArray(payload.notification)
|
|
1823
|
+
? payload.notification
|
|
1824
|
+
: {};
|
|
1825
|
+
return {
|
|
1826
|
+
envelope,
|
|
1827
|
+
payload,
|
|
1828
|
+
notification,
|
|
1829
|
+
eventType: resolveNormalizedText(envelope.eventType || payload.eventType || event.eventType, null),
|
|
1830
|
+
eventName: resolveNormalizedText(envelope.eventName || payload.eventName || notification.notificationType, null),
|
|
1831
|
+
eventId: resolveNormalizedText(
|
|
1832
|
+
envelope.eventId,
|
|
1833
|
+
resolveNormalizedText(payload.inboxItemId, resolveNormalizedText(notification.notificationId, null)),
|
|
1834
|
+
),
|
|
1835
|
+
sessionKey: resolveNormalizedText(envelope.sessionKey, resolveNormalizedText(payload.sessionKey, null)),
|
|
1836
|
+
targetAgentId: resolveNormalizedText(
|
|
1837
|
+
envelope.targetAgentId,
|
|
1838
|
+
resolveNormalizedText(payload.targetAgentId, resolveNormalizedText(notification.targetAgentId, null)),
|
|
1839
|
+
),
|
|
1840
|
+
worldId: resolveNormalizedText(envelope.worldId, resolveNormalizedText(payload.worldId, resolveNormalizedText(notification.relatedObjects?.worldId, null))),
|
|
1841
|
+
conversationKey: resolveNormalizedText(
|
|
1842
|
+
envelope.conversationKey,
|
|
1843
|
+
resolveNormalizedText(payload.conversationKey, resolveNormalizedText(notification.relatedObjects?.conversationKey, null)),
|
|
1844
|
+
),
|
|
1845
|
+
createdAt: envelope.createdAt || payload.createdAt || notification.createdAt || null,
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
function stableJsonPreview(value = null, maxChars = 1200) {
|
|
1850
|
+
if (!value || typeof value !== 'object') return null;
|
|
1851
|
+
let json;
|
|
1852
|
+
try {
|
|
1853
|
+
json = JSON.stringify(value, null, 2);
|
|
1854
|
+
} catch {
|
|
1855
|
+
return null;
|
|
1856
|
+
}
|
|
1857
|
+
if (json.length <= maxChars) return json;
|
|
1858
|
+
return `${json.slice(0, Math.max(0, maxChars - 3))}...`;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
function buildManagementRuntimeEventBody(details = {}, { localSessionKey = null } = {}) {
|
|
1862
|
+
const notification = details.notification || {};
|
|
1863
|
+
const relatedObjects = notification.relatedObjects || details.payload?.relatedObjects || null;
|
|
1864
|
+
const nextActions = notification.nextActions || details.payload?.nextActions || null;
|
|
1865
|
+
const lines = [
|
|
1866
|
+
'Claworld management event received.',
|
|
1867
|
+
'',
|
|
1868
|
+
`Event type: ${details.eventType || 'unknown'}`,
|
|
1869
|
+
`Event name: ${details.eventName || details.eventType || 'unknown'}`,
|
|
1870
|
+
details.eventId ? `Event id: ${details.eventId}` : null,
|
|
1871
|
+
`Management session: ${localSessionKey || details.sessionKey || 'unknown'}`,
|
|
1872
|
+
details.targetAgentId ? `Target agent: ${details.targetAgentId}` : null,
|
|
1873
|
+
details.worldId ? `World: ${details.worldId}` : null,
|
|
1874
|
+
details.conversationKey ? `Conversation: ${details.conversationKey}` : null,
|
|
1875
|
+
'',
|
|
1876
|
+
notification.notificationType ? `Notification type: ${notification.notificationType}` : null,
|
|
1877
|
+
notification.title ? `Title: ${notification.title}` : null,
|
|
1878
|
+
notification.body ? `Body: ${notification.body}` : null,
|
|
1879
|
+
notification.whyReceived ? `Why received: ${notification.whyReceived}` : null,
|
|
1880
|
+
relatedObjects ? 'Related objects:' : null,
|
|
1881
|
+
relatedObjects ? stableJsonPreview(relatedObjects, 900) : null,
|
|
1882
|
+
Array.isArray(nextActions) && nextActions.length > 0 ? 'Next actions:' : null,
|
|
1883
|
+
Array.isArray(nextActions) && nextActions.length > 0 ? stableJsonPreview(nextActions, 900) : null,
|
|
1884
|
+
'',
|
|
1885
|
+
'Handle this as a Claworld Management Session input: decide whether to record, digest, act, report, or ask the user according to the current Claworld working memory and proactivity settings.',
|
|
1886
|
+
].filter((line) => line != null && line !== '');
|
|
1887
|
+
return lines.join('\n');
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
function resolveSessionRecordArtifacts(record = null, fallbackStorePath = null) {
|
|
1891
|
+
const normalizedRecord = record && typeof record === 'object' && !Array.isArray(record) ? record : {};
|
|
1892
|
+
const nestedSession = normalizedRecord.session && typeof normalizedRecord.session === 'object' && !Array.isArray(normalizedRecord.session)
|
|
1893
|
+
? normalizedRecord.session
|
|
1894
|
+
: {};
|
|
1895
|
+
return {
|
|
1896
|
+
sessionId: resolveNormalizedText(
|
|
1897
|
+
normalizedRecord.sessionId,
|
|
1898
|
+
resolveNormalizedText(nestedSession.sessionId, resolveNormalizedText(normalizedRecord.id, null)),
|
|
1899
|
+
),
|
|
1900
|
+
sessionFile: resolveNormalizedText(
|
|
1901
|
+
normalizedRecord.sessionFile,
|
|
1902
|
+
resolveNormalizedText(
|
|
1903
|
+
normalizedRecord.sessionPath,
|
|
1904
|
+
resolveNormalizedText(
|
|
1905
|
+
normalizedRecord.filePath,
|
|
1906
|
+
resolveNormalizedText(normalizedRecord.path, resolveNormalizedText(nestedSession.filePath, null)),
|
|
1907
|
+
),
|
|
1908
|
+
),
|
|
1909
|
+
),
|
|
1910
|
+
sessionStorePath: resolveNormalizedText(
|
|
1911
|
+
normalizedRecord.storePath,
|
|
1912
|
+
resolveNormalizedText(normalizedRecord.sessionStorePath, fallbackStorePath),
|
|
1913
|
+
),
|
|
1914
|
+
transcriptPath: resolveNormalizedText(
|
|
1915
|
+
normalizedRecord.transcriptPath,
|
|
1916
|
+
resolveNormalizedText(nestedSession.transcriptPath, null),
|
|
1917
|
+
),
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
function buildDeliveryRuntimeMaintenanceEvent({
|
|
1922
|
+
delivery = {},
|
|
1923
|
+
metadata = {},
|
|
1924
|
+
payload = {},
|
|
1925
|
+
localSessionKey = null,
|
|
1926
|
+
localAgentId = null,
|
|
1927
|
+
sessionArtifacts = {},
|
|
1928
|
+
workspaceRoot = null,
|
|
1929
|
+
} = {}) {
|
|
1930
|
+
const deliveryId = resolveNormalizedText(delivery.deliveryId, null);
|
|
1931
|
+
const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
|
|
1932
|
+
const requestId = resolveNormalizedText(
|
|
1933
|
+
metadata.kickoffRequestId,
|
|
1934
|
+
resolveNormalizedText(metadata.requestId, resolveNormalizedText(metadata.chatRequestId, null)),
|
|
1935
|
+
);
|
|
1936
|
+
const worldId = resolveNormalizedText(
|
|
1937
|
+
metadata.worldId,
|
|
1938
|
+
resolveNormalizedText(delivery.worldId, null),
|
|
1939
|
+
);
|
|
1940
|
+
const conversationKey = resolveNormalizedText(metadata.conversationKey, resolveNormalizedText(delivery.conversationKey, null));
|
|
1941
|
+
const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
|
|
1942
|
+
const summary = [
|
|
1943
|
+
'Inbound Claworld delivery joined local session',
|
|
1944
|
+
requestId ? `for request ${requestId}` : null,
|
|
1945
|
+
fromAgentId ? `from ${fromAgentId}` : null,
|
|
1946
|
+
].filter(Boolean).join(' ');
|
|
1947
|
+
return buildClaworldRuntimeMaintenanceEvent({
|
|
1948
|
+
id: deliveryId ? `runtime:delivery:${deliveryId}` : null,
|
|
1949
|
+
timestamp: delivery.createdAt || metadata.createdAt || payload.createdAt || null,
|
|
1950
|
+
kind: metadata.deliveryType ? `delivery.${metadata.deliveryType}` : 'delivery',
|
|
1951
|
+
eventType: 'delivery',
|
|
1952
|
+
scope: 'conversation',
|
|
1953
|
+
summary,
|
|
1954
|
+
excerpt: payload.contextText
|
|
1955
|
+
? 'Inbound delivery included contextText; raw dialogue is kept in the OpenClaw session transcript.'
|
|
1956
|
+
: 'Inbound delivery routed into an OpenClaw conversation session; raw dialogue is kept in the session transcript.',
|
|
1957
|
+
refs: {
|
|
1958
|
+
deliveryId,
|
|
1959
|
+
requestId,
|
|
1960
|
+
chatRequestId: requestId,
|
|
1961
|
+
worldId,
|
|
1962
|
+
conversationKey,
|
|
1963
|
+
fromAgentId,
|
|
1964
|
+
sessionKey: localSessionKey || sessionKey,
|
|
1965
|
+
relaySessionKey: sessionKey,
|
|
1966
|
+
},
|
|
1967
|
+
relations: {
|
|
1968
|
+
deliveryId,
|
|
1969
|
+
requestId,
|
|
1970
|
+
chatRequestId: requestId,
|
|
1971
|
+
worldId,
|
|
1972
|
+
conversationKey,
|
|
1973
|
+
fromAgentId,
|
|
1974
|
+
localAgentId,
|
|
1975
|
+
localSessionKey,
|
|
1976
|
+
relaySessionKey: sessionKey,
|
|
1977
|
+
sessionKey: localSessionKey || sessionKey,
|
|
1978
|
+
sessionId: sessionArtifacts.sessionId,
|
|
1979
|
+
sessionFile: sessionArtifacts.sessionFile,
|
|
1980
|
+
sessionStorePath: sessionArtifacts.sessionStorePath,
|
|
1981
|
+
transcriptPath: sessionArtifacts.transcriptPath,
|
|
1982
|
+
},
|
|
1983
|
+
artifacts: {
|
|
1984
|
+
workspaceRoot,
|
|
1985
|
+
...sessionArtifacts,
|
|
1986
|
+
},
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
function buildManagementRuntimeMaintenanceEvent(details = {}, {
|
|
1991
|
+
localSessionKey = null,
|
|
1992
|
+
localAgentId = null,
|
|
1993
|
+
sessionArtifacts = {},
|
|
1994
|
+
workspaceRoot = null,
|
|
1995
|
+
} = {}) {
|
|
1996
|
+
const notification = details.notification || {};
|
|
1997
|
+
const refs = {
|
|
1998
|
+
inboxItemId: details.payload?.inboxItemId || details.eventId,
|
|
1999
|
+
notificationId: notification.notificationId,
|
|
2000
|
+
notificationType: notification.notificationType || details.payload?.notificationType,
|
|
2001
|
+
worldId: details.worldId,
|
|
2002
|
+
conversationKey: details.conversationKey,
|
|
2003
|
+
targetAgentId: details.targetAgentId,
|
|
2004
|
+
sessionKey: localSessionKey || details.sessionKey,
|
|
2005
|
+
relaySessionKey: details.sessionKey,
|
|
2006
|
+
};
|
|
2007
|
+
return buildClaworldRuntimeMaintenanceEvent({
|
|
2008
|
+
id: details.eventId ? `runtime:${details.eventType}:${details.eventId}` : null,
|
|
2009
|
+
timestamp: details.createdAt || notification.createdAt || null,
|
|
2010
|
+
kind: details.eventName || details.eventType || 'runtime_event',
|
|
2011
|
+
eventType: details.eventType || 'runtime_event',
|
|
2012
|
+
scope: 'management',
|
|
2013
|
+
summary: notification.title || notification.body || `${details.eventType || 'runtime'} event received.`,
|
|
2014
|
+
excerpt: buildManagementRuntimeEventBody(details),
|
|
2015
|
+
refs,
|
|
2016
|
+
relations: {
|
|
2017
|
+
inboxItemId: refs.inboxItemId,
|
|
2018
|
+
notificationId: refs.notificationId,
|
|
2019
|
+
notificationType: refs.notificationType,
|
|
2020
|
+
worldId: details.worldId,
|
|
2021
|
+
conversationKey: details.conversationKey,
|
|
2022
|
+
targetAgentId: details.targetAgentId,
|
|
2023
|
+
localAgentId,
|
|
2024
|
+
localSessionKey,
|
|
2025
|
+
relaySessionKey: details.sessionKey,
|
|
2026
|
+
sessionKey: localSessionKey || details.sessionKey,
|
|
2027
|
+
sessionId: sessionArtifacts.sessionId,
|
|
2028
|
+
sessionFile: sessionArtifacts.sessionFile,
|
|
2029
|
+
sessionStorePath: sessionArtifacts.sessionStorePath,
|
|
2030
|
+
transcriptPath: sessionArtifacts.transcriptPath,
|
|
2031
|
+
},
|
|
2032
|
+
artifacts: {
|
|
2033
|
+
workspaceRoot,
|
|
2034
|
+
...sessionArtifacts,
|
|
2035
|
+
},
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
|
|
1810
2039
|
function createDeliveryReplyDispatcher({
|
|
1811
2040
|
runtime,
|
|
1812
2041
|
currentCfg,
|
|
@@ -2298,12 +2527,15 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2298
2527
|
UntrustedContext,
|
|
2299
2528
|
});
|
|
2300
2529
|
|
|
2530
|
+
let sessionStorePath = null;
|
|
2531
|
+
let sessionRecord = null;
|
|
2532
|
+
let sessionArtifacts = {};
|
|
2301
2533
|
if (runtime?.channel?.session?.recordInboundSession && runtime?.channel?.session?.resolveStorePath && localAgentId) {
|
|
2302
|
-
|
|
2534
|
+
sessionStorePath = runtime.channel.session.resolveStorePath(currentCfg.session?.store, {
|
|
2303
2535
|
agentId: localAgentId,
|
|
2304
2536
|
});
|
|
2305
|
-
await runtime.channel.session.recordInboundSession({
|
|
2306
|
-
storePath,
|
|
2537
|
+
sessionRecord = await runtime.channel.session.recordInboundSession({
|
|
2538
|
+
storePath: sessionStorePath,
|
|
2307
2539
|
sessionKey: inboundCtx.SessionKey || sessionKey,
|
|
2308
2540
|
ctx: inboundCtx,
|
|
2309
2541
|
onRecordError: (error) => {
|
|
@@ -2316,6 +2548,46 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2316
2548
|
});
|
|
2317
2549
|
},
|
|
2318
2550
|
});
|
|
2551
|
+
sessionArtifacts = resolveSessionRecordArtifacts(sessionRecord, sessionStorePath);
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
const workspaceRoot = resolveOpenClawWorkspaceRoot({
|
|
2555
|
+
sources: [
|
|
2556
|
+
{ agentId: localAgentId, localAgentId },
|
|
2557
|
+
currentCfg,
|
|
2558
|
+
runtimeConfig,
|
|
2559
|
+
],
|
|
2560
|
+
config: currentCfg,
|
|
2561
|
+
agentId: localAgentId,
|
|
2562
|
+
});
|
|
2563
|
+
let journalResult = null;
|
|
2564
|
+
if (workspaceRoot) {
|
|
2565
|
+
try {
|
|
2566
|
+
journalResult = await appendClaworldJournalEvent(
|
|
2567
|
+
workspaceRoot,
|
|
2568
|
+
buildDeliveryRuntimeMaintenanceEvent({
|
|
2569
|
+
delivery,
|
|
2570
|
+
metadata,
|
|
2571
|
+
payload,
|
|
2572
|
+
localSessionKey,
|
|
2573
|
+
localAgentId,
|
|
2574
|
+
sessionArtifacts,
|
|
2575
|
+
workspaceRoot,
|
|
2576
|
+
}),
|
|
2577
|
+
{
|
|
2578
|
+
trigger: 'delivery',
|
|
2579
|
+
rule: 'runtime_delivery_joined_session',
|
|
2580
|
+
},
|
|
2581
|
+
);
|
|
2582
|
+
} catch (error) {
|
|
2583
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] delivery journal append failed`, {
|
|
2584
|
+
deliveryId,
|
|
2585
|
+
sessionKey,
|
|
2586
|
+
localSessionKey,
|
|
2587
|
+
localAgentId,
|
|
2588
|
+
error: error?.message || String(error),
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2319
2591
|
}
|
|
2320
2592
|
|
|
2321
2593
|
logger.info?.(`[claworld:${runtimeAccountId}] routing delivery into runtime session`, {
|
|
@@ -2323,12 +2595,15 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2323
2595
|
sessionKey,
|
|
2324
2596
|
localSessionKey,
|
|
2325
2597
|
localAgentId,
|
|
2598
|
+
sessionId: sessionArtifacts.sessionId || null,
|
|
2599
|
+
sessionFile: sessionArtifacts.sessionFile || null,
|
|
2326
2600
|
remoteIdentity,
|
|
2327
2601
|
routeStatus: routed?.status || null,
|
|
2328
2602
|
bodyPreview: String(Body || '').slice(0, 240),
|
|
2329
2603
|
rawBodyPreview: String(RawBody || '').slice(0, 240),
|
|
2330
2604
|
allowReply: metadata.allowReply !== false,
|
|
2331
2605
|
commandAuthorized,
|
|
2606
|
+
journal: journalResult?.ok === true,
|
|
2332
2607
|
});
|
|
2333
2608
|
|
|
2334
2609
|
try {
|
|
@@ -2437,6 +2712,206 @@ async function maybeBridgeRuntimeDelivery({
|
|
|
2437
2712
|
};
|
|
2438
2713
|
}
|
|
2439
2714
|
|
|
2715
|
+
async function maybeBridgeRuntimeManagementEvent({
|
|
2716
|
+
runtimeConfig,
|
|
2717
|
+
runtimeAccountId,
|
|
2718
|
+
event,
|
|
2719
|
+
logger,
|
|
2720
|
+
runtime,
|
|
2721
|
+
cfg,
|
|
2722
|
+
inbound,
|
|
2723
|
+
}) {
|
|
2724
|
+
const details = resolveRuntimeManagementEnvelope(event);
|
|
2725
|
+
const route = event?.route || inbound?.routeInboundEvent?.(details.envelope, {
|
|
2726
|
+
sessionTarget: runtimeConfig.routing?.sessionTarget,
|
|
2727
|
+
fallbackTarget: runtimeConfig.routing?.fallbackTarget,
|
|
2728
|
+
}) || null;
|
|
2729
|
+
const sessionKey = resolveNormalizedText(details.sessionKey, resolveNormalizedText(route?.sessionKey, null));
|
|
2730
|
+
const eventId = resolveNormalizedText(details.eventId, `${details.eventType || 'runtime_event'}:${Date.now()}`);
|
|
2731
|
+
|
|
2732
|
+
if (
|
|
2733
|
+
!runtime?.channel?.reply?.finalizeInboundContext
|
|
2734
|
+
|| !runtime?.channel?.reply?.dispatchReplyFromConfig
|
|
2735
|
+
|| !runtime?.channel?.reply?.createReplyDispatcherWithTyping
|
|
2736
|
+
) {
|
|
2737
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] skipping management event bridge: missing runtime bridge hooks`, {
|
|
2738
|
+
eventType: details.eventType,
|
|
2739
|
+
eventName: details.eventName,
|
|
2740
|
+
sessionKey,
|
|
2741
|
+
});
|
|
2742
|
+
return { skipped: true, reason: 'missing_runtime_bridge_hooks' };
|
|
2743
|
+
}
|
|
2744
|
+
if (!details.eventType || !sessionKey || route?.status === 'invalid') {
|
|
2745
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] skipping management event bridge: missing runtime event payload`, {
|
|
2746
|
+
eventType: details.eventType,
|
|
2747
|
+
eventName: details.eventName,
|
|
2748
|
+
sessionKey,
|
|
2749
|
+
routeStatus: route?.status || null,
|
|
2750
|
+
});
|
|
2751
|
+
return { skipped: true, reason: 'missing_management_event_payload' };
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
const loadedCfg = await runtime.config?.loadConfig?.() || {};
|
|
2755
|
+
const currentCfg = {
|
|
2756
|
+
...(loadedCfg && typeof loadedCfg === 'object' && !Array.isArray(loadedCfg) ? loadedCfg : {}),
|
|
2757
|
+
...(cfg && typeof cfg === 'object' && !Array.isArray(cfg) ? cfg : {}),
|
|
2758
|
+
agents: cfg?.agents || loadedCfg?.agents,
|
|
2759
|
+
bindings: cfg?.bindings || loadedCfg?.bindings,
|
|
2760
|
+
channels: cfg?.channels || loadedCfg?.channels,
|
|
2761
|
+
session: cfg?.session || loadedCfg?.session,
|
|
2762
|
+
};
|
|
2763
|
+
const localAgentId = resolveBoundLocalAgentId({
|
|
2764
|
+
cfg: currentCfg,
|
|
2765
|
+
runtimeConfig,
|
|
2766
|
+
});
|
|
2767
|
+
const localSessionKey = buildAgentScopedLocalSessionKey({
|
|
2768
|
+
sessionKey,
|
|
2769
|
+
localAgentId,
|
|
2770
|
+
});
|
|
2771
|
+
const body = buildManagementRuntimeEventBody(details, { localSessionKey });
|
|
2772
|
+
const timestamp = Date.parse(details.createdAt || '');
|
|
2773
|
+
const inboundTimestamp = Number.isFinite(timestamp) ? timestamp : Date.now();
|
|
2774
|
+
const localIdentity = normalizeClaworldText(runtimeConfig.relay?.agentId, runtimeConfig.accountId);
|
|
2775
|
+
const inboundCtx = runtime.channel.reply.finalizeInboundContext({
|
|
2776
|
+
Body: body,
|
|
2777
|
+
RawBody: body,
|
|
2778
|
+
CommandBody: body,
|
|
2779
|
+
BodyForAgent: body,
|
|
2780
|
+
BodyForCommands: body,
|
|
2781
|
+
From: 'claworld:management',
|
|
2782
|
+
To: `claworld:${localIdentity}`,
|
|
2783
|
+
SessionKey: localSessionKey || sessionKey,
|
|
2784
|
+
RelaySessionKey: sessionKey,
|
|
2785
|
+
AccountId: runtimeConfig.accountId,
|
|
2786
|
+
OriginatingChannel: 'claworld',
|
|
2787
|
+
OriginatingFrom: 'management',
|
|
2788
|
+
OriginatingTo: localIdentity,
|
|
2789
|
+
ChatType: 'management',
|
|
2790
|
+
SessionType: 'management',
|
|
2791
|
+
sessionType: 'management',
|
|
2792
|
+
sessionKind: 'management',
|
|
2793
|
+
SenderName: 'Claworld Management',
|
|
2794
|
+
SenderId: 'claworld-management',
|
|
2795
|
+
MessageId: eventId,
|
|
2796
|
+
Provider: 'claworld',
|
|
2797
|
+
Surface: 'claworld',
|
|
2798
|
+
ConversationLabel: 'Claworld Management',
|
|
2799
|
+
Timestamp: inboundTimestamp,
|
|
2800
|
+
MessageSid: eventId,
|
|
2801
|
+
WasMentioned: false,
|
|
2802
|
+
CommandAuthorized: false,
|
|
2803
|
+
RelayEventId: eventId,
|
|
2804
|
+
RelayEventType: details.eventType,
|
|
2805
|
+
RelayEventName: details.eventName,
|
|
2806
|
+
RelayTargetAgentId: details.targetAgentId,
|
|
2807
|
+
});
|
|
2808
|
+
|
|
2809
|
+
let sessionStorePath = null;
|
|
2810
|
+
let sessionRecord = null;
|
|
2811
|
+
let sessionArtifacts = {};
|
|
2812
|
+
if (runtime?.channel?.session?.recordInboundSession && runtime?.channel?.session?.resolveStorePath && localAgentId) {
|
|
2813
|
+
sessionStorePath = runtime.channel.session.resolveStorePath(currentCfg.session?.store, {
|
|
2814
|
+
agentId: localAgentId,
|
|
2815
|
+
});
|
|
2816
|
+
sessionRecord = await runtime.channel.session.recordInboundSession({
|
|
2817
|
+
storePath: sessionStorePath,
|
|
2818
|
+
sessionKey: inboundCtx.SessionKey || sessionKey,
|
|
2819
|
+
ctx: inboundCtx,
|
|
2820
|
+
onRecordError: (error) => {
|
|
2821
|
+
logger.error?.(`[claworld:${runtimeAccountId}] failed to record management inbound session`, {
|
|
2822
|
+
eventType: details.eventType,
|
|
2823
|
+
eventName: details.eventName,
|
|
2824
|
+
sessionKey,
|
|
2825
|
+
localSessionKey,
|
|
2826
|
+
localAgentId,
|
|
2827
|
+
error: error?.message || String(error),
|
|
2828
|
+
});
|
|
2829
|
+
},
|
|
2830
|
+
});
|
|
2831
|
+
sessionArtifacts = resolveSessionRecordArtifacts(sessionRecord, sessionStorePath);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
const workspaceRoot = resolveOpenClawWorkspaceRoot({
|
|
2835
|
+
sources: [
|
|
2836
|
+
{ agentId: localAgentId, localAgentId },
|
|
2837
|
+
currentCfg,
|
|
2838
|
+
runtimeConfig,
|
|
2839
|
+
],
|
|
2840
|
+
config: currentCfg,
|
|
2841
|
+
agentId: localAgentId,
|
|
2842
|
+
});
|
|
2843
|
+
let journalResult = null;
|
|
2844
|
+
if (workspaceRoot) {
|
|
2845
|
+
try {
|
|
2846
|
+
journalResult = await appendClaworldJournalEvent(
|
|
2847
|
+
workspaceRoot,
|
|
2848
|
+
buildManagementRuntimeMaintenanceEvent(details, {
|
|
2849
|
+
localSessionKey,
|
|
2850
|
+
localAgentId,
|
|
2851
|
+
sessionArtifacts,
|
|
2852
|
+
workspaceRoot,
|
|
2853
|
+
}),
|
|
2854
|
+
);
|
|
2855
|
+
} catch (error) {
|
|
2856
|
+
logger.warn?.(`[claworld:${runtimeAccountId}] management event journal append failed`, {
|
|
2857
|
+
eventType: details.eventType,
|
|
2858
|
+
eventName: details.eventName,
|
|
2859
|
+
sessionKey,
|
|
2860
|
+
error: error?.message || String(error),
|
|
2861
|
+
});
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
logger.info?.(`[claworld:${runtimeAccountId}] routing management event into runtime session`, {
|
|
2866
|
+
eventType: details.eventType,
|
|
2867
|
+
eventName: details.eventName,
|
|
2868
|
+
eventId,
|
|
2869
|
+
sessionKey,
|
|
2870
|
+
localSessionKey,
|
|
2871
|
+
localAgentId,
|
|
2872
|
+
sessionId: sessionArtifacts.sessionId || null,
|
|
2873
|
+
sessionFile: sessionArtifacts.sessionFile || null,
|
|
2874
|
+
routeStatus: route?.status || null,
|
|
2875
|
+
journal: journalResult?.ok === true,
|
|
2876
|
+
});
|
|
2877
|
+
|
|
2878
|
+
const {
|
|
2879
|
+
dispatchResult,
|
|
2880
|
+
runtimeOutputSummary,
|
|
2881
|
+
} = await runDeliveryReplyDispatch({
|
|
2882
|
+
runtime,
|
|
2883
|
+
currentCfg,
|
|
2884
|
+
relayClient: null,
|
|
2885
|
+
deliveryId: eventId,
|
|
2886
|
+
sessionKey,
|
|
2887
|
+
localAgentId,
|
|
2888
|
+
allowReply: false,
|
|
2889
|
+
logger,
|
|
2890
|
+
runtimeAccountId,
|
|
2891
|
+
inboundCtx,
|
|
2892
|
+
});
|
|
2893
|
+
|
|
2894
|
+
logger.info?.(`[claworld:${runtimeAccountId}] management event bridge completed`, {
|
|
2895
|
+
eventType: details.eventType,
|
|
2896
|
+
eventName: details.eventName,
|
|
2897
|
+
eventId,
|
|
2898
|
+
sessionKey,
|
|
2899
|
+
localSessionKey,
|
|
2900
|
+
queuedFinal: Boolean(dispatchResult?.queuedFinal),
|
|
2901
|
+
routeStatus: route?.status || null,
|
|
2902
|
+
runtimeOutputSummary,
|
|
2903
|
+
});
|
|
2904
|
+
|
|
2905
|
+
return {
|
|
2906
|
+
skipped: false,
|
|
2907
|
+
ok: true,
|
|
2908
|
+
queuedFinal: Boolean(dispatchResult?.queuedFinal),
|
|
2909
|
+
sessionKey,
|
|
2910
|
+
localSessionKey,
|
|
2911
|
+
routeStatus: route?.status || null,
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2440
2915
|
export function createClaworldChannelPlugin({
|
|
2441
2916
|
logger = console,
|
|
2442
2917
|
relayClientFactory = createClaworldRelayClient,
|
|
@@ -2871,6 +3346,7 @@ export function createClaworldChannelPlugin({
|
|
|
2871
3346
|
eventType: event?.eventType || null,
|
|
2872
3347
|
target: event?.route?.target || null,
|
|
2873
3348
|
deliveryId: event?.delivery?.deliveryId || null,
|
|
3349
|
+
eventId: event?.delivery?.eventId || null,
|
|
2874
3350
|
sessionKey: event?.delivery?.sessionKey || null,
|
|
2875
3351
|
});
|
|
2876
3352
|
|
|
@@ -2890,6 +3366,21 @@ export function createClaworldChannelPlugin({
|
|
|
2890
3366
|
error: error?.message || String(error),
|
|
2891
3367
|
});
|
|
2892
3368
|
});
|
|
3369
|
+
} else if (event?.route?.sessionKind === 'management' || event?.delivery?.sessionKey?.startsWith?.('management:')) {
|
|
3370
|
+
const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
|
|
3371
|
+
maybeBridgeRuntimeManagementEvent({
|
|
3372
|
+
runtimeConfig,
|
|
3373
|
+
runtimeAccountId,
|
|
3374
|
+
event,
|
|
3375
|
+
logger,
|
|
3376
|
+
runtime: runtimeContext.runtime,
|
|
3377
|
+
cfg: runtimeContext.cfg,
|
|
3378
|
+
inbound,
|
|
3379
|
+
}).catch((error) => {
|
|
3380
|
+
logger.error?.(`[claworld:${runtimeAccountId}] management event bridge exception`, {
|
|
3381
|
+
error: error?.message || String(error),
|
|
3382
|
+
});
|
|
3383
|
+
});
|
|
2893
3384
|
}
|
|
2894
3385
|
});
|
|
2895
3386
|
|
|
@@ -653,19 +653,7 @@ export function projectToolAccountViewResponse({
|
|
|
653
653
|
identityPayload = null,
|
|
654
654
|
} = {}) {
|
|
655
655
|
const identityReady = identityPayload?.ready === true;
|
|
656
|
-
const
|
|
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;
|
|
656
|
+
const ready = pairingPayload?.status === 'paired' && identityReady;
|
|
669
657
|
const resolvedShareCard = identityPayload && Object.prototype.hasOwnProperty.call(identityPayload, 'shareCard')
|
|
670
658
|
? projectToolShareCard(identityPayload.shareCard)
|
|
671
659
|
: undefined;
|
|
@@ -680,15 +668,7 @@ export function projectToolAccountViewResponse({
|
|
|
680
668
|
reason: normalizeText(pairingPayload?.reason, null),
|
|
681
669
|
bindingSource: normalizeText(pairingPayload?.bindingSource, null),
|
|
682
670
|
activation: {
|
|
683
|
-
status:
|
|
684
|
-
},
|
|
685
|
-
diagnostics: {
|
|
686
|
-
toolReachable: true,
|
|
687
|
-
bindingReady,
|
|
688
|
-
bindingStatus,
|
|
689
|
-
publicIdentityReady: identityReady,
|
|
690
|
-
relayPresenceResolved: relayResolved,
|
|
691
|
-
relayOnline,
|
|
671
|
+
status: pairingPayload?.status === 'paired' ? 'ready' : 'pending',
|
|
692
672
|
},
|
|
693
673
|
relay: {
|
|
694
674
|
agentId: normalizeText(
|
|
@@ -698,9 +678,9 @@ export function projectToolAccountViewResponse({
|
|
|
698
678
|
displayName: normalizeText(pairingPayload?.relayAgent?.displayName, null),
|
|
699
679
|
discoverable: pairingPayload?.relayAgent?.discoverable ?? null,
|
|
700
680
|
contactable: pairingPayload?.relayAgent?.contactable ?? null,
|
|
701
|
-
online:
|
|
702
|
-
resolved:
|
|
703
|
-
bindingStatus,
|
|
681
|
+
online: pairingPayload?.relayAgent?.online ?? null,
|
|
682
|
+
resolved: pairingPayload?.relayAgent?.resolved ?? null,
|
|
683
|
+
bindingStatus: pairingPayload?.status === 'paired' ? 'bound' : 'unactivated',
|
|
704
684
|
},
|
|
705
685
|
profile: projectToolAccountProfile(identityPayload),
|
|
706
686
|
...projectToolAccountIdentityFields(identityPayload),
|