@xfxstudio/claworld 2026.5.3-testing.1 → 2026.5.6-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.
@@ -1,5 +1,4 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import path from 'node:path';
3
2
 
4
3
  import {
5
4
  applyRuntimeIdentity,
@@ -33,11 +32,6 @@ import { createInboundSessionRouter } from '../runtime/inbound-session-router.js
33
32
  import { createOutboundSessionBridge } from '../runtime/outbound-session-bridge.js';
34
33
  import { createCanonicalResultBuilder } from '../runtime/canonical-result-builder.js';
35
34
  import { createDemoSessionBootstrap } from '../runtime/demo-session-bootstrap.js';
36
- import {
37
- appendClaworldJournalEvent,
38
- buildClaworldRuntimeMaintenanceEvent,
39
- } from '../runtime/working-memory.js';
40
- import { resolveOpenClawWorkspaceRoot } from '../runtime/workspace-resolver.js';
41
35
  import {
42
36
  broadcastModeratedWorld,
43
37
  createModeratedWorld,
@@ -588,19 +582,17 @@ async function deliverRelayMessage({ runtimeConfig, to, text, fetchImpl, logger,
588
582
 
589
583
  if (!result.ok) {
590
584
  logger.error?.('[claworld:outbound] message delivery failed', { status: result.status, body: result.body });
591
- throw createRuntimeBoundaryError({
585
+ createRelayRouteError({
586
+ result,
587
+ runtimeConfig,
592
588
  code: 'relay_message_delivery_failed',
593
- category: 'transport',
594
- status: result.status >= 500 ? 502 : result.status,
595
- message: `claworld outbound failed: ${result.status}`,
596
589
  publicMessage: 'claworld outbound message delivery failed',
597
- recoverable: true,
590
+ message: `claworld outbound failed: ${result.status}`,
598
591
  context: {
599
- accountId: runtimeConfig.accountId || null,
600
592
  fromAgentId,
601
593
  targetAgentId,
602
- status: result.status,
603
594
  },
595
+ passThroughBackendConflict: true,
604
596
  });
605
597
  }
606
598
 
@@ -636,13 +628,23 @@ function createRelayRouteError({
636
628
  publicMessage,
637
629
  message,
638
630
  context = {},
631
+ passThroughBackendConflict = false,
639
632
  }) {
633
+ const backendCode = resolveNormalizedText(result?.body?.error, null);
634
+ const backendMessage = resolveNormalizedText(result?.body?.message, null);
635
+ const shouldPassThroughConflict = passThroughBackendConflict === true
636
+ && Number(result?.status) === 409
637
+ && backendCode;
640
638
  throw createRuntimeBoundaryError({
641
- code,
642
- category: 'transport',
639
+ code: shouldPassThroughConflict ? backendCode : code,
640
+ category: shouldPassThroughConflict ? 'conflict' : 'transport',
643
641
  status: result?.status >= 500 ? 502 : result?.status || 502,
644
- message: message || publicMessage,
645
- publicMessage,
642
+ message: shouldPassThroughConflict
643
+ ? (backendMessage || message || publicMessage)
644
+ : (message || publicMessage),
645
+ publicMessage: shouldPassThroughConflict
646
+ ? (backendMessage || publicMessage)
647
+ : publicMessage,
646
648
  recoverable: true,
647
649
  context: {
648
650
  accountId: runtimeConfig.accountId || null,
@@ -733,6 +735,7 @@ async function createChatRequest({
733
735
  displayName: normalizedDisplayName,
734
736
  agentCode: normalizedAgentCode,
735
737
  },
738
+ passThroughBackendConflict: true,
736
739
  });
737
740
  }
738
741
  return result.body || {};
@@ -815,6 +818,7 @@ async function acceptChatRequest({
815
818
  code: 'chat_request_accept_failed',
816
819
  publicMessage: 'failed to accept chat request',
817
820
  context: { actorAgentId, chatRequestId },
821
+ passThroughBackendConflict: true,
818
822
  });
819
823
  }
820
824
  return normalizeChatInboxPayloadSessionKeys(result.body || {}, { localAgentId });
@@ -843,6 +847,7 @@ async function rejectChatRequest({
843
847
  code: 'chat_request_reject_failed',
844
848
  publicMessage: 'failed to reject chat request',
845
849
  context: { actorAgentId, chatRequestId },
850
+ passThroughBackendConflict: true,
846
851
  });
847
852
  }
848
853
  return result.body || {};
@@ -1847,385 +1852,6 @@ function buildDeliveryInboundEnvelope({
1847
1852
  };
1848
1853
  }
1849
1854
 
1850
- function resolveRuntimeManagementEnvelope(event = {}) {
1851
- const envelope = event?.delivery && typeof event.delivery === 'object' && !Array.isArray(event.delivery)
1852
- ? event.delivery
1853
- : {};
1854
- const payload = envelope.payload && typeof envelope.payload === 'object' && !Array.isArray(envelope.payload)
1855
- ? envelope.payload
1856
- : {};
1857
- const notification = payload.notification && typeof payload.notification === 'object' && !Array.isArray(payload.notification)
1858
- ? payload.notification
1859
- : {};
1860
- return {
1861
- envelope,
1862
- payload,
1863
- notification,
1864
- eventType: resolveNormalizedText(envelope.eventType || payload.eventType || event.eventType, null),
1865
- eventName: resolveNormalizedText(envelope.eventName || payload.eventName || notification.notificationType, null),
1866
- eventId: resolveNormalizedText(
1867
- envelope.eventId,
1868
- resolveNormalizedText(payload.inboxItemId, resolveNormalizedText(notification.notificationId, null)),
1869
- ),
1870
- sessionKey: resolveNormalizedText(envelope.sessionKey, resolveNormalizedText(payload.sessionKey, null)),
1871
- targetAgentId: resolveNormalizedText(
1872
- envelope.targetAgentId,
1873
- resolveNormalizedText(payload.targetAgentId, resolveNormalizedText(notification.targetAgentId, null)),
1874
- ),
1875
- worldId: resolveNormalizedText(envelope.worldId, resolveNormalizedText(payload.worldId, resolveNormalizedText(notification.relatedObjects?.worldId, null))),
1876
- conversationKey: resolveNormalizedText(
1877
- envelope.conversationKey,
1878
- resolveNormalizedText(payload.conversationKey, resolveNormalizedText(notification.relatedObjects?.conversationKey, null)),
1879
- ),
1880
- createdAt: envelope.createdAt || payload.createdAt || notification.createdAt || null,
1881
- };
1882
- }
1883
-
1884
- function stableJsonPreview(value = null, maxChars = 1200) {
1885
- if (!value || typeof value !== 'object') return null;
1886
- let json;
1887
- try {
1888
- json = JSON.stringify(value, null, 2);
1889
- } catch {
1890
- return null;
1891
- }
1892
- if (json.length <= maxChars) return json;
1893
- return `${json.slice(0, Math.max(0, maxChars - 3))}...`;
1894
- }
1895
-
1896
- function buildManagementRuntimeEventBody(details = {}, { localSessionKey = null } = {}) {
1897
- const notification = details.notification || {};
1898
- const relatedObjects = notification.relatedObjects || details.payload?.relatedObjects || null;
1899
- const nextActions = notification.nextActions || details.payload?.nextActions || null;
1900
- const lines = [
1901
- 'Claworld management event received.',
1902
- '',
1903
- `Event type: ${details.eventType || 'unknown'}`,
1904
- `Event name: ${details.eventName || details.eventType || 'unknown'}`,
1905
- details.eventId ? `Event id: ${details.eventId}` : null,
1906
- `Management session: ${localSessionKey || details.sessionKey || 'unknown'}`,
1907
- details.targetAgentId ? `Target agent: ${details.targetAgentId}` : null,
1908
- details.worldId ? `World: ${details.worldId}` : null,
1909
- details.conversationKey ? `Conversation: ${details.conversationKey}` : null,
1910
- '',
1911
- notification.notificationType ? `Notification type: ${notification.notificationType}` : null,
1912
- notification.title ? `Title: ${notification.title}` : null,
1913
- notification.body ? `Body: ${notification.body}` : null,
1914
- notification.whyReceived ? `Why received: ${notification.whyReceived}` : null,
1915
- relatedObjects ? 'Related objects:' : null,
1916
- relatedObjects ? stableJsonPreview(relatedObjects, 900) : null,
1917
- Array.isArray(nextActions) && nextActions.length > 0 ? 'Next actions:' : null,
1918
- Array.isArray(nextActions) && nextActions.length > 0 ? stableJsonPreview(nextActions, 900) : null,
1919
- '',
1920
- '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.',
1921
- ].filter((line) => line != null && line !== '');
1922
- return lines.join('\n');
1923
- }
1924
-
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 = {}) {
2004
- const normalizedRecord = record && typeof record === 'object' && !Array.isArray(record) ? record : {};
2005
- const nestedSession = normalizedRecord.session && typeof normalizedRecord.session === 'object' && !Array.isArray(normalizedRecord.session)
2006
- ? normalizedRecord.session
2007
- : {};
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,
2020
- resolveNormalizedText(
2021
- normalizedRecord.filePath,
2022
- resolveNormalizedText(normalizedRecord.path, resolveNormalizedText(nestedSession.filePath, null)),
2023
- ),
2024
- ),
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
- }),
2108
- };
2109
- }
2110
-
2111
- function buildDeliveryRuntimeMaintenanceEvent({
2112
- delivery = {},
2113
- metadata = {},
2114
- payload = {},
2115
- localSessionKey = null,
2116
- localAgentId = null,
2117
- sessionArtifacts = {},
2118
- workspaceRoot = null,
2119
- } = {}) {
2120
- const deliveryId = resolveNormalizedText(delivery.deliveryId, null);
2121
- const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
2122
- const requestId = resolveNormalizedText(
2123
- metadata.kickoffRequestId,
2124
- resolveNormalizedText(metadata.requestId, resolveNormalizedText(metadata.chatRequestId, null)),
2125
- );
2126
- const worldId = resolveNormalizedText(
2127
- metadata.worldId,
2128
- resolveNormalizedText(delivery.worldId, null),
2129
- );
2130
- const conversationKey = resolveNormalizedText(metadata.conversationKey, resolveNormalizedText(delivery.conversationKey, null));
2131
- const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
2132
- const summary = [
2133
- 'Inbound Claworld delivery joined local session',
2134
- requestId ? `for request ${requestId}` : null,
2135
- fromAgentId ? `from ${fromAgentId}` : null,
2136
- ].filter(Boolean).join(' ');
2137
- return buildClaworldRuntimeMaintenanceEvent({
2138
- id: deliveryId ? `runtime:delivery:${deliveryId}` : null,
2139
- timestamp: delivery.createdAt || metadata.createdAt || payload.createdAt || null,
2140
- kind: metadata.deliveryType ? `delivery.${metadata.deliveryType}` : 'delivery',
2141
- eventType: 'delivery',
2142
- scope: 'conversation',
2143
- summary,
2144
- excerpt: payload.contextText
2145
- ? 'Inbound delivery included contextText; raw dialogue is kept in the OpenClaw session transcript.'
2146
- : 'Inbound delivery routed into an OpenClaw conversation session; raw dialogue is kept in the session transcript.',
2147
- refs: {
2148
- deliveryId,
2149
- requestId,
2150
- chatRequestId: requestId,
2151
- worldId,
2152
- conversationKey,
2153
- fromAgentId,
2154
- sessionKey: localSessionKey || sessionKey,
2155
- relaySessionKey: sessionKey,
2156
- },
2157
- relations: {
2158
- deliveryId,
2159
- requestId,
2160
- chatRequestId: requestId,
2161
- worldId,
2162
- conversationKey,
2163
- fromAgentId,
2164
- localAgentId,
2165
- localSessionKey,
2166
- relaySessionKey: sessionKey,
2167
- sessionKey: localSessionKey || sessionKey,
2168
- sessionId: sessionArtifacts.sessionId,
2169
- sessionFile: sessionArtifacts.sessionFile,
2170
- sessionStorePath: sessionArtifacts.sessionStorePath,
2171
- transcriptPath: sessionArtifacts.transcriptPath,
2172
- },
2173
- artifacts: {
2174
- workspaceRoot,
2175
- ...sessionArtifacts,
2176
- },
2177
- });
2178
- }
2179
-
2180
- function buildManagementRuntimeMaintenanceEvent(details = {}, {
2181
- localSessionKey = null,
2182
- localAgentId = null,
2183
- sessionArtifacts = {},
2184
- workspaceRoot = null,
2185
- } = {}) {
2186
- const notification = details.notification || {};
2187
- const refs = {
2188
- inboxItemId: details.payload?.inboxItemId || details.eventId,
2189
- notificationId: notification.notificationId,
2190
- notificationType: notification.notificationType || details.payload?.notificationType,
2191
- worldId: details.worldId,
2192
- conversationKey: details.conversationKey,
2193
- targetAgentId: details.targetAgentId,
2194
- sessionKey: localSessionKey || details.sessionKey,
2195
- relaySessionKey: details.sessionKey,
2196
- };
2197
- return buildClaworldRuntimeMaintenanceEvent({
2198
- id: details.eventId ? `runtime:${details.eventType}:${details.eventId}` : null,
2199
- timestamp: details.createdAt || notification.createdAt || null,
2200
- kind: details.eventName || details.eventType || 'runtime_event',
2201
- eventType: details.eventType || 'runtime_event',
2202
- scope: 'management',
2203
- summary: notification.title || notification.body || `${details.eventType || 'runtime'} event received.`,
2204
- excerpt: buildManagementRuntimeEventBody(details),
2205
- refs,
2206
- relations: {
2207
- inboxItemId: refs.inboxItemId,
2208
- notificationId: refs.notificationId,
2209
- notificationType: refs.notificationType,
2210
- worldId: details.worldId,
2211
- conversationKey: details.conversationKey,
2212
- targetAgentId: details.targetAgentId,
2213
- localAgentId,
2214
- localSessionKey,
2215
- relaySessionKey: details.sessionKey,
2216
- sessionKey: localSessionKey || details.sessionKey,
2217
- sessionId: sessionArtifacts.sessionId,
2218
- sessionFile: sessionArtifacts.sessionFile,
2219
- sessionStorePath: sessionArtifacts.sessionStorePath,
2220
- transcriptPath: sessionArtifacts.transcriptPath,
2221
- },
2222
- artifacts: {
2223
- workspaceRoot,
2224
- ...sessionArtifacts,
2225
- },
2226
- });
2227
- }
2228
-
2229
1855
  function createDeliveryReplyDispatcher({
2230
1856
  runtime,
2231
1857
  currentCfg,
@@ -2614,13 +2240,10 @@ async function maybeBridgeRuntimeInboundEvent({
2614
2240
  const eventType = resolveNormalizedText(delivery.eventType, resolveNormalizedText(event?.eventType, 'delivery'));
2615
2241
  const deliveryId = resolveInboundMessageId({ delivery, payload, metadata });
2616
2242
  const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
2617
- const fallbackRuntimeEventText = eventType !== 'delivery'
2618
- ? buildManagementRuntimeEventBody(resolveRuntimeManagementEnvelope(event))
2619
- : null;
2620
2243
  const contextText = resolveNormalizedText(payload.contextText, null);
2621
2244
  const incomingText = resolveNormalizedText(
2622
2245
  payload.commandText,
2623
- contextText ? null : resolveNormalizedText(payload.text, resolveNormalizedText(payload.body, fallbackRuntimeEventText)),
2246
+ contextText ? null : resolveNormalizedText(payload.text, resolveNormalizedText(payload.body, null)),
2624
2247
  );
2625
2248
  const commandText = resolveNormalizedText(payload.commandText, incomingText);
2626
2249
  const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
@@ -2719,9 +2342,6 @@ async function maybeBridgeRuntimeInboundEvent({
2719
2342
  OriginatingFrom: remoteIdentity,
2720
2343
  OriginatingTo: remoteIdentity,
2721
2344
  ChatType: isManagementSession ? 'management' : 'direct',
2722
- SessionType: isManagementSession ? 'management' : 'direct',
2723
- sessionType: isManagementSession ? 'management' : 'direct',
2724
- sessionKind: isManagementSession ? 'management' : 'conversation',
2725
2345
  SenderName: senderName,
2726
2346
  SenderId: remoteIdentity,
2727
2347
  MessageId: deliveryId,
@@ -2737,66 +2357,25 @@ async function maybeBridgeRuntimeInboundEvent({
2737
2357
  UntrustedContext,
2738
2358
  });
2739
2359
 
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
- });
2753
-
2754
- const workspaceRoot = resolveOpenClawWorkspaceRoot({
2755
- sources: [
2756
- { agentId: localAgentId, localAgentId },
2757
- currentCfg,
2758
- runtimeConfig,
2759
- ],
2760
- config: currentCfg,
2761
- agentId: localAgentId,
2762
- });
2763
- let journalResult = null;
2764
- if (workspaceRoot) {
2765
- try {
2766
- const maintenanceEvent = isRelayDelivery
2767
- ? buildDeliveryRuntimeMaintenanceEvent({
2768
- delivery,
2769
- metadata,
2770
- payload,
2771
- localSessionKey,
2772
- localAgentId,
2773
- sessionArtifacts,
2774
- workspaceRoot,
2775
- })
2776
- : buildManagementRuntimeMaintenanceEvent(resolveRuntimeManagementEnvelope(event), {
2360
+ if (runtime?.channel?.session?.recordInboundSession && runtime?.channel?.session?.resolveStorePath && localAgentId) {
2361
+ const storePath = runtime.channel.session.resolveStorePath(currentCfg.session?.store, {
2362
+ agentId: localAgentId,
2363
+ });
2364
+ await runtime.channel.session.recordInboundSession({
2365
+ storePath,
2366
+ sessionKey: inboundCtx.SessionKey || sessionKey,
2367
+ ctx: inboundCtx,
2368
+ onRecordError: (error) => {
2369
+ logger.error?.(`[claworld:${runtimeAccountId}] failed to record inbound session`, {
2370
+ eventType,
2371
+ deliveryId,
2372
+ sessionKey,
2777
2373
  localSessionKey,
2778
2374
  localAgentId,
2779
- sessionArtifacts,
2780
- workspaceRoot,
2375
+ error: error?.message || String(error),
2781
2376
  });
2782
- journalResult = await appendClaworldJournalEvent(
2783
- workspaceRoot,
2784
- maintenanceEvent,
2785
- {
2786
- trigger: isRelayDelivery ? 'delivery' : 'runtime_event',
2787
- rule: isRelayDelivery ? 'runtime_delivery_joined_session' : 'runtime_event_joined_session',
2788
- },
2789
- );
2790
- } catch (error) {
2791
- logger.warn?.(`[claworld:${runtimeAccountId}] inbound journal append failed`, {
2792
- eventType,
2793
- deliveryId,
2794
- sessionKey,
2795
- localSessionKey,
2796
- localAgentId,
2797
- error: error?.message || String(error),
2798
- });
2799
- }
2377
+ },
2378
+ });
2800
2379
  }
2801
2380
 
2802
2381
  logger.info?.(`[claworld:${runtimeAccountId}] ${isRelayDelivery ? 'routing delivery into runtime session' : 'routing inbound event into runtime session'}`, {
@@ -2805,15 +2384,12 @@ async function maybeBridgeRuntimeInboundEvent({
2805
2384
  sessionKey,
2806
2385
  localSessionKey,
2807
2386
  localAgentId,
2808
- sessionId: sessionArtifacts.sessionId || null,
2809
- sessionFile: sessionArtifacts.sessionFile || null,
2810
2387
  remoteIdentity,
2811
2388
  routeStatus: routed?.status || null,
2812
2389
  bodyPreview: String(Body || '').slice(0, 240),
2813
2390
  rawBodyPreview: String(RawBody || '').slice(0, 240),
2814
2391
  allowReply,
2815
2392
  commandAuthorized,
2816
- journal: journalResult?.ok === true,
2817
2393
  });
2818
2394
 
2819
2395
  if (isRelayDelivery && metadata.acceptanceRequired !== false) {
@@ -2926,199 +2502,6 @@ async function maybeBridgeRuntimeInboundEvent({
2926
2502
  };
2927
2503
  }
2928
2504
 
2929
- async function maybeBridgeRuntimeManagementEvent({
2930
- runtimeConfig,
2931
- runtimeAccountId,
2932
- event,
2933
- logger,
2934
- runtime,
2935
- cfg,
2936
- inbound,
2937
- }) {
2938
- const details = resolveRuntimeManagementEnvelope(event);
2939
- const route = event?.route || inbound?.routeInboundEvent?.(details.envelope, {
2940
- sessionTarget: runtimeConfig.routing?.sessionTarget,
2941
- fallbackTarget: runtimeConfig.routing?.fallbackTarget,
2942
- }) || null;
2943
- const sessionKey = resolveNormalizedText(details.sessionKey, resolveNormalizedText(route?.sessionKey, null));
2944
- const eventId = resolveNormalizedText(details.eventId, `${details.eventType || 'runtime_event'}:${Date.now()}`);
2945
-
2946
- if (
2947
- !runtime?.channel?.reply?.finalizeInboundContext
2948
- || !runtime?.channel?.reply?.dispatchReplyFromConfig
2949
- || !runtime?.channel?.reply?.createReplyDispatcherWithTyping
2950
- ) {
2951
- logger.warn?.(`[claworld:${runtimeAccountId}] skipping management event bridge: missing runtime bridge hooks`, {
2952
- eventType: details.eventType,
2953
- eventName: details.eventName,
2954
- sessionKey,
2955
- });
2956
- return { skipped: true, reason: 'missing_runtime_bridge_hooks' };
2957
- }
2958
- if (!details.eventType || !sessionKey || route?.status === 'invalid') {
2959
- logger.warn?.(`[claworld:${runtimeAccountId}] skipping management event bridge: missing runtime event payload`, {
2960
- eventType: details.eventType,
2961
- eventName: details.eventName,
2962
- sessionKey,
2963
- routeStatus: route?.status || null,
2964
- });
2965
- return { skipped: true, reason: 'missing_management_event_payload' };
2966
- }
2967
-
2968
- const loadedCfg = await runtime.config?.loadConfig?.() || {};
2969
- const currentCfg = {
2970
- ...(loadedCfg && typeof loadedCfg === 'object' && !Array.isArray(loadedCfg) ? loadedCfg : {}),
2971
- ...(cfg && typeof cfg === 'object' && !Array.isArray(cfg) ? cfg : {}),
2972
- agents: cfg?.agents || loadedCfg?.agents,
2973
- bindings: cfg?.bindings || loadedCfg?.bindings,
2974
- channels: cfg?.channels || loadedCfg?.channels,
2975
- session: cfg?.session || loadedCfg?.session,
2976
- };
2977
- const localAgentId = resolveBoundLocalAgentId({
2978
- cfg: currentCfg,
2979
- runtimeConfig,
2980
- });
2981
- const localSessionKey = buildAgentScopedLocalSessionKey({
2982
- sessionKey,
2983
- localAgentId,
2984
- });
2985
- const body = buildManagementRuntimeEventBody(details, { localSessionKey });
2986
- const timestamp = Date.parse(details.createdAt || '');
2987
- const inboundTimestamp = Number.isFinite(timestamp) ? timestamp : Date.now();
2988
- const localIdentity = normalizeClaworldText(runtimeConfig.relay?.agentId, runtimeConfig.accountId);
2989
- const inboundCtx = runtime.channel.reply.finalizeInboundContext({
2990
- Body: body,
2991
- RawBody: body,
2992
- CommandBody: body,
2993
- BodyForAgent: body,
2994
- BodyForCommands: body,
2995
- From: 'claworld:management',
2996
- To: `claworld:${localIdentity}`,
2997
- SessionKey: localSessionKey || sessionKey,
2998
- RelaySessionKey: sessionKey,
2999
- AccountId: runtimeConfig.accountId,
3000
- OriginatingChannel: 'claworld',
3001
- OriginatingFrom: 'management',
3002
- OriginatingTo: localIdentity,
3003
- ChatType: 'management',
3004
- SessionType: 'management',
3005
- sessionType: 'management',
3006
- sessionKind: 'management',
3007
- SenderName: 'Claworld Management',
3008
- SenderId: 'claworld-management',
3009
- MessageId: eventId,
3010
- Provider: 'claworld',
3011
- Surface: 'claworld',
3012
- ConversationLabel: 'Claworld Management',
3013
- Timestamp: inboundTimestamp,
3014
- MessageSid: eventId,
3015
- WasMentioned: false,
3016
- CommandAuthorized: false,
3017
- RelayEventId: eventId,
3018
- RelayEventType: details.eventType,
3019
- RelayEventName: details.eventName,
3020
- RelayTargetAgentId: details.targetAgentId,
3021
- });
3022
-
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
- });
3040
-
3041
- const workspaceRoot = resolveOpenClawWorkspaceRoot({
3042
- sources: [
3043
- { agentId: localAgentId, localAgentId },
3044
- currentCfg,
3045
- runtimeConfig,
3046
- ],
3047
- config: currentCfg,
3048
- agentId: localAgentId,
3049
- });
3050
- let journalResult = null;
3051
- if (workspaceRoot) {
3052
- try {
3053
- journalResult = await appendClaworldJournalEvent(
3054
- workspaceRoot,
3055
- buildManagementRuntimeMaintenanceEvent(details, {
3056
- localSessionKey,
3057
- localAgentId,
3058
- sessionArtifacts,
3059
- workspaceRoot,
3060
- }),
3061
- );
3062
- } catch (error) {
3063
- logger.warn?.(`[claworld:${runtimeAccountId}] management event journal append failed`, {
3064
- eventType: details.eventType,
3065
- eventName: details.eventName,
3066
- sessionKey,
3067
- error: error?.message || String(error),
3068
- });
3069
- }
3070
- }
3071
-
3072
- logger.info?.(`[claworld:${runtimeAccountId}] routing management event into runtime session`, {
3073
- eventType: details.eventType,
3074
- eventName: details.eventName,
3075
- eventId,
3076
- sessionKey,
3077
- localSessionKey,
3078
- localAgentId,
3079
- sessionId: sessionArtifacts.sessionId || null,
3080
- sessionFile: sessionArtifacts.sessionFile || null,
3081
- routeStatus: route?.status || null,
3082
- journal: journalResult?.ok === true,
3083
- });
3084
-
3085
- const {
3086
- dispatchResult,
3087
- runtimeOutputSummary,
3088
- } = await runDeliveryReplyDispatch({
3089
- runtime,
3090
- currentCfg,
3091
- relayClient: null,
3092
- deliveryId: eventId,
3093
- sessionKey,
3094
- localAgentId,
3095
- allowReply: false,
3096
- logger,
3097
- runtimeAccountId,
3098
- inboundCtx,
3099
- });
3100
-
3101
- logger.info?.(`[claworld:${runtimeAccountId}] management event bridge completed`, {
3102
- eventType: details.eventType,
3103
- eventName: details.eventName,
3104
- eventId,
3105
- sessionKey,
3106
- localSessionKey,
3107
- queuedFinal: Boolean(dispatchResult?.queuedFinal),
3108
- routeStatus: route?.status || null,
3109
- runtimeOutputSummary,
3110
- });
3111
-
3112
- return {
3113
- skipped: false,
3114
- ok: true,
3115
- queuedFinal: Boolean(dispatchResult?.queuedFinal),
3116
- sessionKey,
3117
- localSessionKey,
3118
- routeStatus: route?.status || null,
3119
- };
3120
- }
3121
-
3122
2505
  export function createClaworldChannelPlugin({
3123
2506
  logger = console,
3124
2507
  relayClientFactory = createClaworldRelayClient,
@@ -3553,7 +2936,6 @@ export function createClaworldChannelPlugin({
3553
2936
  eventType: event?.eventType || null,
3554
2937
  target: event?.route?.target || null,
3555
2938
  deliveryId: event?.delivery?.deliveryId || null,
3556
- eventId: event?.delivery?.eventId || null,
3557
2939
  sessionKey: event?.delivery?.sessionKey || null,
3558
2940
  });
3559
2941
 
@@ -3573,21 +2955,6 @@ export function createClaworldChannelPlugin({
3573
2955
  error: error?.message || String(error),
3574
2956
  });
3575
2957
  });
3576
- } else if (event?.route?.sessionKind === 'management' || event?.delivery?.sessionKey?.startsWith?.('management:')) {
3577
- const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
3578
- maybeBridgeRuntimeManagementEvent({
3579
- runtimeConfig,
3580
- runtimeAccountId,
3581
- event,
3582
- logger,
3583
- runtime: runtimeContext.runtime,
3584
- cfg: runtimeContext.cfg,
3585
- inbound,
3586
- }).catch((error) => {
3587
- logger.error?.(`[claworld:${runtimeAccountId}] management event bridge exception`, {
3588
- error: error?.message || String(error),
3589
- });
3590
- });
3591
2958
  }
3592
2959
  });
3593
2960