@xfxstudio/claworld 0.1.4 → 0.2.0

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.
Files changed (55) hide show
  1. package/README.md +12 -29
  2. package/openclaw.plugin.json +9 -33
  3. package/package.json +2 -10
  4. package/skills/claworld-help/SKILL.md +86 -160
  5. package/skills/claworld-join-and-chat/SKILL.md +107 -203
  6. package/skills/claworld-manage-worlds/SKILL.md +75 -392
  7. package/src/lib/chat-request.js +347 -0
  8. package/src/lib/{accepted-chat-kickoff.js → relay/kickoff-text.js} +67 -26
  9. package/src/openclaw/index.js +0 -5
  10. package/src/openclaw/installer/cli.js +14 -16
  11. package/src/openclaw/installer/core.js +13 -14
  12. package/src/openclaw/installer/doctor.js +69 -31
  13. package/src/openclaw/installer/workspace-contract.js +33 -9
  14. package/src/openclaw/plugin/claworld-channel-plugin.js +156 -625
  15. package/src/openclaw/plugin/config-schema.js +4 -16
  16. package/src/openclaw/plugin/managed-config.js +127 -75
  17. package/src/openclaw/plugin/onboarding.js +7 -3
  18. package/src/openclaw/plugin/register.js +40 -339
  19. package/src/openclaw/plugin/relay-client.js +112 -102
  20. package/src/openclaw/protocol/relay-event-protocol.js +34 -22
  21. package/src/openclaw/runtime/canonical-result-builder.js +15 -5
  22. package/src/openclaw/runtime/demo-session-bootstrap.js +0 -4
  23. package/src/openclaw/runtime/feedback-helper.js +3 -2
  24. package/src/openclaw/runtime/inbound-session-router.js +28 -20
  25. package/src/openclaw/runtime/outbound-session-bridge.js +21 -9
  26. package/src/openclaw/runtime/product-shell-helper.js +45 -637
  27. package/src/openclaw/runtime/runtime-path.js +2 -2
  28. package/src/openclaw/runtime/system-message-orchestrator.js +1 -1
  29. package/src/openclaw/runtime/tool-contracts.js +36 -258
  30. package/src/openclaw/runtime/world-moderation-helper.js +11 -65
  31. package/src/product-shell/catalog/default-world-catalog.js +15 -33
  32. package/src/product-shell/contracts/candidate-feed.js +40 -5
  33. package/src/product-shell/contracts/chat-request-approval-policy.js +3 -3
  34. package/src/product-shell/contracts/world-manifest.js +134 -161
  35. package/src/product-shell/contracts/world-orchestration.js +55 -326
  36. package/src/product-shell/feedback/feedback-routes.js +4 -3
  37. package/src/product-shell/feedback/feedback-service.js +11 -8
  38. package/src/product-shell/index.js +6 -7
  39. package/src/product-shell/matching/matchmaking-service.js +39 -5
  40. package/src/product-shell/membership/membership-service.js +125 -147
  41. package/src/product-shell/onboarding/onboarding-service.js +2 -2
  42. package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
  43. package/src/product-shell/orchestration/world-conversation-text.js +231 -0
  44. package/src/product-shell/results/result-service.js +9 -3
  45. package/src/product-shell/search/search-service.js +28 -1
  46. package/src/product-shell/social/chat-request-routes.js +0 -1
  47. package/src/product-shell/social/chat-request-service.js +1 -102
  48. package/src/product-shell/worlds/world-admin-service.js +86 -277
  49. package/src/product-shell/worlds/world-authorization.js +3 -5
  50. package/src/product-shell/worlds/world-routes.js +8 -38
  51. package/src/product-shell/worlds/world-service.js +3 -3
  52. package/src/product-shell/worlds/world-text.js +77 -0
  53. package/src/lib/runtime-guidance.js +0 -457
  54. package/src/openclaw/runtime/world-session-startup.js +0 -1
  55. package/src/product-shell/orchestration/session-orchestrator.js +0 -38
@@ -35,18 +35,13 @@ import {
35
35
  buildWorldSelectionPrompt,
36
36
  buildCandidateDeliverySummary,
37
37
  buildPostSetupWorldDirectory,
38
- buildRequiredFieldExplanation,
39
38
  broadcastWorld,
40
39
  fetchWorldSearch,
41
40
  fetchWorldCandidateFeed,
42
- fetchWorldJoinCheck,
43
41
  fetchWorldDetail,
44
42
  joinWorld,
45
- submitWorldJoin,
46
43
  submitWorldSearch,
47
- resolveWorldJoinFlow,
48
44
  resolveWorldSelection,
49
- resolveWorldProfileCollectionFlow,
50
45
  resolveWorldSelectionFlow,
51
46
  } from '../runtime/product-shell-helper.js';
52
47
  import { getClaworldRuntime } from './runtime.js';
@@ -55,11 +50,6 @@ import {
55
50
  normalizeRuntimeBoundaryError,
56
51
  serializeRuntimeBoundaryError,
57
52
  } from '../../lib/runtime-errors.js';
58
- import {
59
- ACCEPTED_CHAT_KICKOFF_PAYLOAD_KIND,
60
- readAcceptedChatKickoffRuntimeContext,
61
- resolveAcceptedChatKickoffViewer,
62
- } from '../../lib/accepted-chat-kickoff.js';
63
53
 
64
54
  function normalizeRelayHttpBaseUrl(serverUrl) {
65
55
  const parsed = new URL(serverUrl);
@@ -212,13 +202,10 @@ function normalizeClaworldInteger(value, fallback = null) {
212
202
  return Math.trunc(normalized);
213
203
  }
214
204
 
215
- function shouldAuthorizeBridgedCommand({ runtimeConfig = {}, relayEvent, incomingText }) {
205
+ function shouldAuthorizeBridgedCommand({ runtimeConfig = {}, incomingText }) {
216
206
  if (runtimeConfig.testing?.allowBridgedCommandDispatch !== true) {
217
207
  return false;
218
208
  }
219
- if (relayEvent !== 'turn.deliver') {
220
- return false;
221
- }
222
209
  return typeof incomingText === 'string' && incomingText.trim().startsWith('/');
223
210
  }
224
211
 
@@ -227,6 +214,7 @@ const CLAWORLD_RELAY_OPERATIONAL_NOTICE_PATTERNS = [
227
214
  /^🧹\s*Auto-compaction complete(?:\s*\(count \d+\))?\.$/i,
228
215
  /^↪️\s*Model Fallback:/i,
229
216
  /^↪️\s*Model Fallback cleared:/i,
217
+ /^⚠️\s*Agent failed before reply:/i,
230
218
  ];
231
219
 
232
220
  const CLAWORLD_RELAY_OPERATIONAL_SUFFIX_PATTERNS = [
@@ -290,7 +278,23 @@ function appendRuntimeOutputPreview(previews, text) {
290
278
  previews.push(preview);
291
279
  }
292
280
 
293
- function buildRelayContinuationText({ finalTexts = [], blockTexts = [] } = {}) {
281
+ function appendPartialContinuationChunk(currentText, chunk) {
282
+ const nextChunk = typeof chunk === 'string' ? chunk : '';
283
+ if (!nextChunk) return currentText;
284
+ const existing = typeof currentText === 'string' ? currentText : '';
285
+ if (!existing) return nextChunk;
286
+ if (nextChunk === existing) return existing;
287
+ if (nextChunk.startsWith(existing)) return nextChunk;
288
+ if (existing.endsWith(nextChunk)) return existing;
289
+ return `${existing}${nextChunk}`;
290
+ }
291
+
292
+ function buildRelayContinuationText({
293
+ finalTexts = [],
294
+ blockTexts = [],
295
+ partialText = '',
296
+ allowPartialFallback = false,
297
+ } = {}) {
294
298
  const sanitizedFinalTexts = finalTexts
295
299
  .map((entry) => sanitizeRelayContinuationText(entry))
296
300
  .filter(Boolean);
@@ -309,6 +313,15 @@ function buildRelayContinuationText({ finalTexts = [], blockTexts = [] } = {}) {
309
313
  source: 'block',
310
314
  };
311
315
  }
316
+ const sanitizedPartialText = allowPartialFallback
317
+ ? sanitizeRelayContinuationText(partialText)
318
+ : '';
319
+ if (sanitizedPartialText) {
320
+ return {
321
+ text: sanitizedPartialText,
322
+ source: 'partial',
323
+ };
324
+ }
312
325
  return {
313
326
  text: '',
314
327
  source: 'none',
@@ -327,52 +340,6 @@ function resolveContinuationState(turnData = {}) {
327
340
  };
328
341
  }
329
342
 
330
- function resolveBackendGuidanceMessages(payload = {}) {
331
- const guidance = payload?.guidance;
332
- if (!guidance || typeof guidance !== 'object' || Array.isArray(guidance)) return [];
333
- const messages = Array.isArray(guidance.messages) ? guidance.messages : [];
334
- return messages
335
- .map((message, index) => {
336
- const text = normalizeClaworldText(message?.text, null);
337
- if (!text) return null;
338
- return {
339
- text,
340
- contextKey:
341
- normalizeClaworldText(message?.contextKey, null)
342
- || `claworld:backend-guidance:${normalizeClaworldText(message?.kind, 'message')}:${index}`,
343
- };
344
- })
345
- .filter(Boolean);
346
- }
347
-
348
- function enqueueBackendGuidance({
349
- runtime,
350
- sessionKey,
351
- payload,
352
- } = {}) {
353
- if (!runtime?.system?.enqueueSystemEvent || !sessionKey) {
354
- return { skipped: true, reason: 'missing_runtime_or_session', count: 0 };
355
- }
356
-
357
- const messages = resolveBackendGuidanceMessages(payload);
358
- if (messages.length === 0) {
359
- return { skipped: true, reason: 'no_backend_guidance', count: 0 };
360
- }
361
-
362
- for (const message of messages) {
363
- runtime.system.enqueueSystemEvent(message.text, {
364
- sessionKey,
365
- contextKey: message.contextKey,
366
- });
367
- }
368
-
369
- return {
370
- skipped: false,
371
- reason: null,
372
- count: messages.length,
373
- };
374
- }
375
-
376
343
  function buildClaworldDirectoryEntries(config = {}, accountId = null) {
377
344
  const accountIds = listClaworldAccountIds(config);
378
345
  const currentAccountId = String(accountId || '').trim();
@@ -440,7 +407,7 @@ async function deliverRelayMessage({ runtimeConfig, to, text, fetchImpl, logger,
440
407
  conversation: {
441
408
  conversationKey: outboundContext.conversationKey || outboundContext.metadata?.conversationKey || null,
442
409
  worldId: outboundContext.worldId || outboundContext.metadata?.worldId || null,
443
- scope: outboundContext.scope || outboundContext.sessionScope || outboundContext.metadata?.scope || null,
410
+ scope: outboundContext.scope || outboundContext.metadata?.scope || null,
444
411
  conversationId: outboundContext.conversationId || outboundContext.metadata?.conversationId || null,
445
412
  threadId: outboundContext.threadId || outboundContext.metadata?.threadId || null,
446
413
  sessionKey: outboundContext.sessionKey || outboundContext.SessionKey || null,
@@ -449,7 +416,7 @@ async function deliverRelayMessage({ runtimeConfig, to, text, fetchImpl, logger,
449
416
  });
450
417
 
451
418
  if (!result.ok) {
452
- logger.error?.('[claworld:outbound] session request failed', { status: result.status, body: result.body });
419
+ logger.error?.('[claworld:outbound] message delivery failed', { status: result.status, body: result.body });
453
420
  throw createRuntimeBoundaryError({
454
421
  code: 'relay_message_delivery_failed',
455
422
  category: 'transport',
@@ -472,7 +439,7 @@ async function deliverRelayMessage({ runtimeConfig, to, text, fetchImpl, logger,
472
439
  chatId: toAddress,
473
440
  timestamp: Date.now(),
474
441
  meta: {
475
- sessionId: result.body?.session?.sessionId || null,
442
+ sessionKey: result.body?.delivery?.sessionKey || outboundContext.sessionKey || outboundContext.SessionKey || null,
476
443
  turnId: result.body?.turn?.turnId || null,
477
444
  conversationKey: result.body?.conversationKey || null,
478
445
  toAddress,
@@ -644,7 +611,6 @@ async function createChatRequest({
644
611
  targetAgentId,
645
612
  openingMessage = null,
646
613
  worldId = null,
647
- episodePolicy = null,
648
614
  fetchImpl,
649
615
  }) {
650
616
  const normalizedTargetAgentId = normalizeClaworldText(targetAgentId, null);
@@ -672,9 +638,6 @@ async function createChatRequest({
672
638
  targetAgentId: normalizedTargetAgentId,
673
639
  openingMessage: normalizeClaworldText(openingMessage, null),
674
640
  ...(normalizeClaworldText(worldId, null) ? { worldId: normalizeClaworldText(worldId, null) } : {}),
675
- ...(episodePolicy && typeof episodePolicy === 'object' && !Array.isArray(episodePolicy)
676
- ? { episodePolicy }
677
- : {}),
678
641
  }),
679
642
  });
680
643
  if (!result.ok) {
@@ -1258,187 +1221,22 @@ async function ensureRelayBinding({ runtimeConfig, fetchImpl, logger }) {
1258
1221
  });
1259
1222
  }
1260
1223
 
1261
- function resolveSessionCreatedWorldId(event = {}) {
1262
- const session = event?.raw?.data && typeof event.raw.data === 'object' ? event.raw.data : {};
1263
- const metadata = session.metadata && typeof session.metadata === 'object' ? session.metadata : {};
1264
- const candidateWorldId = [
1265
- metadata.worldId,
1266
- metadata.worldContext?.worldId,
1267
- session.worldContext?.worldId,
1268
- session.worldId,
1269
- session.session?.metadata?.worldId,
1270
- session.session?.metadata?.worldContext?.worldId,
1271
- session.session?.worldContext?.worldId,
1272
- session.session?.worldId,
1273
- event?.inboundEnvelope?.metadata?.worldId,
1274
- event?.inboundEnvelope?.metadata?.worldContext?.worldId,
1275
- event?.inboundEnvelope?.metadata?.session?.worldId,
1276
- event?.inboundEnvelope?.metadata?.session?.metadata?.worldId,
1277
- event?.inboundEnvelope?.metadata?.session?.metadata?.worldContext?.worldId,
1278
- ].map((value) => resolveNormalizedText(value, null)).find(Boolean);
1279
- return candidateWorldId || null;
1280
- }
1281
-
1282
- function resolveTurnWorldId(event = {}) {
1283
- const turnData = event?.raw?.data && typeof event.raw.data === 'object' ? event.raw.data : {};
1284
- const metadata = turnData.metadata && typeof turnData.metadata === 'object' ? turnData.metadata : {};
1285
- const candidateWorldId = [
1286
- metadata.worldId,
1287
- metadata.worldContext?.worldId,
1288
- turnData.worldContext?.worldId,
1289
- turnData.worldId,
1290
- turnData.session?.metadata?.worldId,
1291
- turnData.session?.metadata?.worldContext?.worldId,
1292
- turnData.session?.worldContext?.worldId,
1293
- turnData.session?.worldId,
1294
- event?.inboundEnvelope?.metadata?.worldId,
1295
- event?.inboundEnvelope?.metadata?.worldContext?.worldId,
1296
- event?.inboundEnvelope?.metadata?.session?.worldId,
1297
- event?.inboundEnvelope?.metadata?.session?.metadata?.worldId,
1298
- event?.inboundEnvelope?.metadata?.session?.metadata?.worldContext?.worldId,
1299
- ].map((value) => resolveNormalizedText(value, null)).find(Boolean);
1300
- return candidateWorldId || null;
1301
- }
1302
-
1303
- function resolveAcceptedChatKickoffBundle(event = {}) {
1304
- const turnData = event?.raw?.data && typeof event.raw.data === 'object' ? event.raw.data : {};
1305
- if (turnData.acceptedChatKickoff && typeof turnData.acceptedChatKickoff === 'object' && !Array.isArray(turnData.acceptedChatKickoff)) {
1306
- return turnData.acceptedChatKickoff;
1307
- }
1308
- const payload = turnData.payload && typeof turnData.payload === 'object' && !Array.isArray(turnData.payload)
1309
- ? turnData.payload
1224
+ function resolveDeliveryWorldId(delivery = {}) {
1225
+ const metadata = delivery?.metadata && typeof delivery.metadata === 'object' && !Array.isArray(delivery.metadata)
1226
+ ? delivery.metadata
1310
1227
  : {};
1311
- if (payload.kickoffBundle && typeof payload.kickoffBundle === 'object' && !Array.isArray(payload.kickoffBundle)) {
1312
- return payload.kickoffBundle;
1313
- }
1314
- return null;
1315
- }
1316
-
1317
- function resolveAcceptedChatKickoffRuntimeContext(event = {}, { bundle = null, localAgentId = null, fallback = 'recipient' } = {}) {
1318
- const turnData = event?.raw?.data && typeof event.raw.data === 'object' ? event.raw.data : {};
1319
- if (
1320
- turnData.acceptedChatKickoffRuntimeContext
1321
- && typeof turnData.acceptedChatKickoffRuntimeContext === 'object'
1322
- && !Array.isArray(turnData.acceptedChatKickoffRuntimeContext)
1323
- ) {
1324
- return turnData.acceptedChatKickoffRuntimeContext;
1325
- }
1326
- const payload = turnData.payload && typeof turnData.payload === 'object' && !Array.isArray(turnData.payload)
1327
- ? turnData.payload
1328
- : {};
1329
- if (
1330
- payload.acceptedChatKickoffRuntimeContext
1331
- && typeof payload.acceptedChatKickoffRuntimeContext === 'object'
1332
- && !Array.isArray(payload.acceptedChatKickoffRuntimeContext)
1333
- ) {
1334
- return payload.acceptedChatKickoffRuntimeContext;
1335
- }
1336
- if (!bundle) return null;
1337
- return readAcceptedChatKickoffRuntimeContext(bundle, {
1338
- viewer: resolveAcceptedChatKickoffViewer(bundle, {
1339
- localAgentId,
1340
- fallback,
1341
- }),
1342
- });
1343
- }
1344
-
1345
- function buildWorldAwareSessionKey(sessionKey, worldId = null) {
1346
- if (!worldId) return sessionKey;
1347
- return `${sessionKey}:world:${worldId}`;
1348
- }
1349
-
1350
- function buildSessionWorldCacheKey(runtimeAccountId, sessionId) {
1351
- const accountId = resolveNormalizedText(runtimeAccountId, 'default');
1352
- if (!sessionId || !accountId) return null;
1353
- return `${accountId}:${sessionId}`;
1354
- }
1355
-
1356
- function resolveSessionCreatedPeerAgentId(session = {}, localRelayAgentId = null) {
1357
- const agentAId = normalizeClaworldText(session.agentAId, null);
1358
- const agentBId = normalizeClaworldText(session.agentBId, null);
1359
- const localAgentId = normalizeClaworldText(localRelayAgentId, null);
1360
-
1361
- if (localAgentId && agentAId === localAgentId) return agentBId;
1362
- if (localAgentId && agentBId === localAgentId) return agentAId;
1363
- return agentAId || agentBId || null;
1364
- }
1365
-
1366
- async function maybeInjectWorldSessionStartupContext({
1367
- runtime,
1368
- cfg,
1369
- runtimeConfig,
1370
- runtimeAccountId,
1371
- event,
1372
- logger,
1373
- sessionIdToWorldId,
1374
- } = {}) {
1375
- const worldCache = sessionIdToWorldId || null;
1376
- if (!runtime?.system?.enqueueSystemEvent || !runtime?.channel?.routing?.resolveAgentRoute) {
1377
- return { skipped: true, reason: 'missing_runtime_system_or_routing' };
1378
- }
1379
-
1380
- const session = event?.raw?.data && typeof event.raw.data === 'object' ? event.raw.data : {};
1381
- const worldId = resolveSessionCreatedWorldId(event);
1382
- if (!worldId) {
1383
- return { skipped: true, reason: 'not_world_scoped' };
1384
- }
1385
- const sessionLookupKey = buildSessionWorldCacheKey(runtimeAccountId, session.sessionId);
1386
- if (sessionLookupKey && worldCache) {
1387
- worldCache.set(sessionLookupKey, worldId);
1388
- }
1389
-
1390
- const peerAgentId = resolveSessionCreatedPeerAgentId(session, runtimeConfig?.relay?.agentId || null);
1391
- if (!peerAgentId) {
1392
- return { skipped: true, reason: 'peer_agent_unresolved' };
1393
- }
1394
-
1395
- const currentCfg = cfg || await runtime.config?.loadConfig?.() || {};
1396
- const routePeerId = resolveRelayAddress(peerAgentId, runtimeConfig);
1397
- const route = runtime.channel.routing.resolveAgentRoute({
1398
- cfg: currentCfg,
1399
- channel: 'claworld',
1400
- accountId: runtimeConfig.accountId,
1401
- peer: { kind: 'direct', id: routePeerId || peerAgentId },
1402
- }) || {};
1403
- const sessionKey = route.sessionKey || `agent:${route.agentId || runtimeConfig.accountId}:main`;
1404
- const worldSessionKey = buildWorldAwareSessionKey(sessionKey, worldId);
1405
- const enqueueResult = enqueueBackendGuidance({
1406
- runtime,
1407
- sessionKey: worldSessionKey,
1408
- payload: session,
1409
- });
1410
- if (enqueueResult.skipped) {
1411
- return { skipped: true, reason: enqueueResult.reason, worldId, sessionKey: worldSessionKey };
1412
- }
1413
-
1414
- logger.info?.(`[claworld:${runtimeAccountId}] injected backend-authored world startup guidance`, {
1415
- worldId,
1416
- sessionId: session.sessionId || null,
1417
- sessionKey: worldSessionKey,
1418
- routePeerId: routePeerId || peerAgentId,
1419
- guidanceCount: enqueueResult.count,
1420
- });
1421
-
1422
- return {
1423
- skipped: false,
1424
- ok: true,
1425
- worldId,
1426
- sessionKey: worldSessionKey,
1427
- };
1228
+ return resolveNormalizedText(metadata.worldId, null) || null;
1428
1229
  }
1429
1230
 
1430
- function buildRelayInboundEnvelope({
1231
+ function buildDeliveryInboundEnvelope({
1431
1232
  runtime,
1432
1233
  currentCfg,
1433
- runtimeAccountId,
1434
1234
  remoteIdentity,
1435
1235
  incomingText,
1436
1236
  contextText = null,
1437
1237
  commandText = null,
1438
- sessionId,
1439
- turnId,
1440
- relayEvent,
1441
- mode = 'direct',
1238
+ deliveryId,
1239
+ sessionKey,
1442
1240
  worldId = null,
1443
1241
  conversationKey = null,
1444
1242
  }) {
@@ -1452,12 +1250,10 @@ function buildRelayInboundEnvelope({
1452
1250
  const remoteLabel = String(remoteIdentity || 'unknown-peer').trim() || 'unknown-peer';
1453
1251
  const systemLines = [
1454
1252
  `[claworld peer ${remoteLabel}]`,
1455
- `[claworld mode ${mode}]`,
1456
1253
  ...(worldId ? [`[claworld world ${worldId}]`] : []),
1457
1254
  ...(conversationKey ? [`[claworld conversation ${conversationKey}]`] : []),
1458
- `[claworld session ${sessionId}]`,
1459
- `[claworld turn ${turnId}]`,
1460
- `[relay event ${relayEvent}]`,
1255
+ `[claworld session ${sessionKey}]`,
1256
+ `[claworld delivery ${deliveryId}]`,
1461
1257
  ];
1462
1258
  const rawBody = `${bodyText}\n\n${systemLines.join('\n')}`;
1463
1259
  const normalizedCommandText = String(commandText || '').trim();
@@ -1486,30 +1282,29 @@ function buildRelayInboundEnvelope({
1486
1282
  };
1487
1283
  }
1488
1284
 
1489
- function createRelayReplyDispatcher({
1285
+ function createDeliveryReplyDispatcher({
1490
1286
  runtime,
1491
1287
  currentCfg,
1492
- route,
1493
1288
  relayClient,
1494
- sessionId,
1495
- turnId,
1496
- relayEvent,
1497
- localRelayAgentId,
1498
- allowRelayContinuation = true,
1289
+ deliveryId,
1290
+ sessionKey,
1291
+ localAgentId = null,
1292
+ allowReply = true,
1499
1293
  logger,
1500
1294
  runtimeAccountId,
1501
1295
  }) {
1502
1296
  const prefixContext = runtime?.channel?.reply?.createReplyPrefixContext
1503
- ? runtime.channel.reply.createReplyPrefixContext({ cfg: currentCfg, agentId: route.agentId })
1297
+ ? runtime.channel.reply.createReplyPrefixContext({ cfg: currentCfg, agentId: localAgentId || runtimeAccountId })
1504
1298
  : { responsePrefix: '', responsePrefixContextProvider: () => ({}) };
1505
1299
  const humanDelay = runtime?.channel?.reply?.resolveHumanDelayConfig
1506
- ? runtime.channel.reply.resolveHumanDelayConfig(currentCfg, route.agentId)
1300
+ ? runtime.channel.reply.resolveHumanDelayConfig(currentCfg, localAgentId || runtimeAccountId)
1507
1301
  : undefined;
1508
1302
 
1509
1303
  let replied = false;
1510
1304
  let suppressed = false;
1511
1305
  const finalTexts = [];
1512
1306
  const blockTexts = [];
1307
+ let partialContinuationText = '';
1513
1308
  const runtimeOutputSummary = {
1514
1309
  counts: {
1515
1310
  final: 0,
@@ -1584,33 +1379,16 @@ function createRelayReplyDispatcher({
1584
1379
  const flushReply = async (text) => {
1585
1380
  const normalized = String(text || '').trim();
1586
1381
  if (!normalized || replied || suppressed) return false;
1587
- if (allowRelayContinuation === false) {
1382
+ if (allowReply === false) {
1588
1383
  suppressed = true;
1589
1384
  return false;
1590
1385
  }
1591
- if (relayEvent === 'turn.reply') {
1592
- if (!localRelayAgentId) {
1593
- throw new Error('missing local relay agent id for relay continuation');
1594
- }
1595
- const result = await relayClient.createTurn({
1596
- sessionId,
1597
- fromAgentId: localRelayAgentId,
1598
- payload: {
1599
- text: normalized,
1600
- source: 'openclaw-autochain',
1601
- },
1602
- });
1603
- if (result.status !== 201) {
1604
- throw new Error(`failed to create follow-up relay turn: ${result.status}`);
1605
- }
1606
- } else {
1607
- relayClient.sendTurnReply({
1608
- sessionId,
1609
- messageId: turnId,
1610
- replyText: normalized,
1611
- source: 'openclaw-autochain',
1612
- });
1613
- }
1386
+ relayClient.sendReply({
1387
+ deliveryId,
1388
+ sessionKey,
1389
+ replyText: normalized,
1390
+ source: 'openclaw-autochain',
1391
+ });
1614
1392
  replied = true;
1615
1393
  return true;
1616
1394
  };
@@ -1633,9 +1411,9 @@ function createRelayReplyDispatcher({
1633
1411
  }
1634
1412
  },
1635
1413
  onError: (error, info) => {
1636
- logger.error?.(`[claworld:${runtimeAccountId}] turn bridge dispatch error`, {
1637
- sessionId,
1638
- turnId,
1414
+ logger.error?.(`[claworld:${runtimeAccountId}] delivery bridge dispatch error`, {
1415
+ deliveryId,
1416
+ sessionKey,
1639
1417
  kind: info?.kind || null,
1640
1418
  error: error?.message || String(error),
1641
1419
  });
@@ -1644,14 +1422,19 @@ function createRelayReplyDispatcher({
1644
1422
 
1645
1423
  const markDispatchIdle = async () => {
1646
1424
  if (!replied && !suppressed) {
1647
- const continuation = buildRelayContinuationText({ finalTexts, blockTexts });
1425
+ const continuation = buildRelayContinuationText({
1426
+ finalTexts,
1427
+ blockTexts,
1428
+ partialText: partialContinuationText,
1429
+ allowPartialFallback:
1430
+ runtimeOutputSummary.counts.final > 0 && finalTexts.length === 0 && blockTexts.length === 0,
1431
+ });
1648
1432
  runtimeOutputSummary.relayContinuationSource = continuation.source;
1649
1433
  runtimeOutputSummary.relayContinuationPreview = continuation.text
1650
1434
  ? previewRuntimeOutputText(continuation.text)
1651
1435
  : null;
1652
- const continuationText = continuation.text;
1653
- if (continuationText) {
1654
- await flushReply(continuationText);
1436
+ if (continuation.text) {
1437
+ await flushReply(continuation.text);
1655
1438
  }
1656
1439
  }
1657
1440
  await dispatchApi.markDispatchIdle?.();
@@ -1662,6 +1445,10 @@ function createRelayReplyDispatcher({
1662
1445
  replyOptions: {
1663
1446
  ...dispatchApi.replyOptions,
1664
1447
  onPartialReply: async (payload = {}) => {
1448
+ partialContinuationText = appendPartialContinuationChunk(
1449
+ partialContinuationText,
1450
+ typeof payload?.text === 'string' ? payload.text : '',
1451
+ );
1665
1452
  recordRuntimeTextEvent('partial', payload?.text);
1666
1453
  },
1667
1454
  onReasoningStream: async (payload = {}) => {
@@ -1701,7 +1488,7 @@ function createRelayReplyDispatcher({
1701
1488
  };
1702
1489
  }
1703
1490
 
1704
- async function maybeBridgeDeliveredTurn({
1491
+ async function maybeBridgeRuntimeDelivery({
1705
1492
  relayClient,
1706
1493
  runtimeConfig,
1707
1494
  runtimeAccountId,
@@ -1710,175 +1497,119 @@ async function maybeBridgeDeliveredTurn({
1710
1497
  runtime,
1711
1498
  cfg,
1712
1499
  inbound,
1713
- sessionIdToWorldId,
1714
1500
  }) {
1715
- const worldCache = sessionIdToWorldId || null;
1716
- const relayEvent = event?.relayEvent || 'turn.deliver';
1717
- const turnData = event?.raw?.data || {};
1718
- const sessionId = turnData.sessionId || event?.inboundEnvelope?.session_id || null;
1719
- const turnId = turnData.turnId || event?.inboundEnvelope?.event_id || null;
1720
- const kickoffBundle = resolveAcceptedChatKickoffBundle(event);
1721
- const payload = turnData.payload && typeof turnData.payload === 'object' && !Array.isArray(turnData.payload)
1722
- ? turnData.payload
1501
+ const delivery = event?.delivery && typeof event.delivery === 'object' && !Array.isArray(event.delivery)
1502
+ ? event.delivery
1723
1503
  : {};
1724
- const localRelayAgentId = runtimeConfig.relay?.agentId || relayClient?.boundAgentId || null;
1725
- const kickoffRuntimeContext = resolveAcceptedChatKickoffRuntimeContext(event, {
1726
- bundle: kickoffBundle,
1727
- localAgentId: localRelayAgentId,
1728
- fallback: relayEvent === 'turn.deliver' ? 'sender' : 'recipient',
1729
- });
1730
- const incomingText = turnData.payload?.text
1731
- || event?.inboundEnvelope?.payload?.text
1732
- || (
1733
- payload.kind === ACCEPTED_CHAT_KICKOFF_PAYLOAD_KIND
1734
- ? kickoffRuntimeContext?.text || ''
1735
- : ''
1736
- );
1737
- const fromAgentId = turnData.fromAgentId || event?.inboundEnvelope?.from_agent_id || null;
1738
- const conversationKey = turnData.conversationKey || null;
1739
- const bridgedCommandText = payload.kind === ACCEPTED_CHAT_KICKOFF_PAYLOAD_KIND
1740
- ? kickoffRuntimeContext?.briefText || kickoffBundle?.request?.brief?.text || incomingText
1741
- : incomingText;
1742
- const kickoffContextText = relayEvent === 'turn.reply'
1743
- && kickoffBundle?.kickoffTurnId
1744
- && kickoffBundle.kickoffTurnId === turnId
1745
- ? kickoffRuntimeContext?.text || null
1746
- : null;
1747
- const senderId = fromAgentId || 'unknown-peer';
1504
+ const metadata = delivery.metadata && typeof delivery.metadata === 'object' && !Array.isArray(delivery.metadata)
1505
+ ? delivery.metadata
1506
+ : {};
1507
+ const payload = delivery.payload && typeof delivery.payload === 'object' && !Array.isArray(delivery.payload)
1508
+ ? delivery.payload
1509
+ : {};
1510
+ const deliveryId = resolveNormalizedText(delivery.deliveryId, null);
1511
+ const sessionKey = resolveNormalizedText(delivery.sessionKey, null);
1512
+ const incomingText = resolveNormalizedText(payload.text, null);
1513
+ const contextText = null;
1514
+ const fromAgentId = resolveNormalizedText(metadata.fromAgentId, null);
1515
+ const remoteAddress = resolveNormalizedText(metadata.fromAddress, null)
1516
+ || resolveRelayAddress(fromAgentId || '', runtimeConfig)
1517
+ || fromAgentId
1518
+ || 'unknown-peer';
1519
+ const remoteRouteIdentity = resolveRelayAddress(fromAgentId || '', runtimeConfig)
1520
+ || remoteAddress;
1521
+
1748
1522
  if (
1749
- !runtime?.channel?.routing?.resolveAgentRoute
1750
- || !runtime?.channel?.reply?.finalizeInboundContext
1523
+ !runtime?.channel?.reply?.finalizeInboundContext
1751
1524
  || !runtime?.channel?.reply?.dispatchReplyFromConfig
1752
1525
  || !runtime?.channel?.reply?.createReplyDispatcherWithTyping
1753
1526
  ) {
1754
- logger.warn?.(`[claworld:${runtimeAccountId}] skipping relay bridge: missing runtime bridge hooks`, {
1755
- relayEvent,
1756
- sessionId,
1757
- turnId,
1527
+ logger.warn?.(`[claworld:${runtimeAccountId}] skipping delivery bridge: missing runtime bridge hooks`, {
1528
+ deliveryId,
1529
+ sessionKey,
1758
1530
  });
1759
1531
  return { skipped: true, reason: 'missing_runtime_bridge_hooks' };
1760
1532
  }
1761
- if (!sessionId || !turnId || !incomingText) {
1762
- logger.warn?.(`[claworld:${runtimeAccountId}] skipping relay bridge: missing turn payload`, {
1763
- relayEvent,
1764
- sessionId,
1765
- turnId,
1533
+ if (!deliveryId || !sessionKey || !incomingText) {
1534
+ logger.warn?.(`[claworld:${runtimeAccountId}] skipping delivery bridge: missing delivery payload`, {
1535
+ deliveryId,
1536
+ sessionKey,
1766
1537
  hasIncomingText: Boolean(incomingText),
1767
1538
  });
1768
- return { skipped: true, reason: 'missing_turn_payload' };
1539
+ return { skipped: true, reason: 'missing_delivery_payload' };
1769
1540
  }
1770
1541
 
1771
1542
  const currentCfg = cfg || await runtime.config?.loadConfig?.() || {};
1772
- const localAddress = resolveRelayAddress(runtimeConfig.accountId || '', runtimeConfig);
1773
- const remoteAddress = resolveRelayAddress(senderId, runtimeConfig);
1774
- const routePeerId = remoteAddress || senderId;
1775
- const worldId = resolveTurnWorldId(event);
1776
- const sessionLookupKey = buildSessionWorldCacheKey(runtimeAccountId, sessionId);
1777
- const resolvedWorldId = worldId || (sessionLookupKey ? worldCache?.get(sessionLookupKey) : null);
1778
- if (sessionLookupKey && resolvedWorldId && worldCache) {
1779
- worldCache.set(sessionLookupKey, resolvedWorldId);
1780
- }
1781
- // Gateway reply dispatch stays on the dedicated `claworld` channel surface.
1782
- // Accept may have been reviewed from another main-agent channel, but live
1783
- // continuation/generation cannot hop across channels mid-session.
1784
- const route = runtime.channel.routing.resolveAgentRoute({
1785
- cfg: currentCfg,
1786
- channel: 'claworld',
1787
- accountId: runtimeConfig.accountId,
1788
- peer: { kind: 'direct', id: routePeerId },
1789
- }) || {};
1790
- const routed = inbound?.routeInboundEvent?.(event?.inboundEnvelope || {}, {
1543
+ const routed = inbound?.routeInboundEvent?.(delivery, {
1791
1544
  sessionTarget: runtimeConfig.routing?.sessionTarget,
1792
1545
  fallbackTarget: runtimeConfig.routing?.fallbackTarget,
1793
- route,
1794
1546
  }) || null;
1795
-
1796
- const sessionKey = route.sessionKey || `agent:${route.agentId || runtimeConfig.accountId}:main`;
1797
- const worldSessionKey = buildWorldAwareSessionKey(sessionKey, resolvedWorldId);
1547
+ const worldId = resolveDeliveryWorldId(delivery);
1798
1548
  const commandAuthorized = shouldAuthorizeBridgedCommand({
1799
1549
  runtimeConfig,
1800
- relayEvent,
1801
- incomingText: bridgedCommandText,
1550
+ incomingText,
1802
1551
  });
1803
- const { Body, RawBody, CommandBody, ContextLines } = buildRelayInboundEnvelope({
1552
+ const { Body, RawBody, CommandBody, ContextLines } = buildDeliveryInboundEnvelope({
1804
1553
  runtime,
1805
1554
  currentCfg,
1806
- runtimeAccountId,
1807
- remoteIdentity: routePeerId,
1555
+ remoteIdentity: remoteAddress,
1808
1556
  incomingText,
1809
- contextText: kickoffContextText,
1810
- commandText: bridgedCommandText,
1811
- sessionId,
1812
- turnId,
1813
- relayEvent,
1814
- mode: resolvedWorldId ? 'world' : 'direct',
1815
- worldId: resolvedWorldId,
1816
- conversationKey,
1557
+ contextText,
1558
+ commandText: incomingText,
1559
+ deliveryId,
1560
+ sessionKey,
1561
+ worldId,
1562
+ conversationKey: metadata.conversationKey || null,
1817
1563
  });
1564
+ const localAddress = resolveRelayAddress(runtimeConfig.accountId || '', runtimeConfig);
1818
1565
  const inboundCtx = runtime.channel.reply.finalizeInboundContext({
1819
1566
  Body,
1820
1567
  RawBody,
1821
1568
  CommandBody,
1822
1569
  BodyForAgent: RawBody,
1823
1570
  BodyForCommands: CommandBody,
1824
- From: routePeerId ? `claworld:${routePeerId}` : `claworld:${senderId}`,
1571
+ From: `claworld:${remoteRouteIdentity}`,
1825
1572
  To: localAddress ? `claworld:${localAddress}` : `claworld:${runtimeConfig.accountId}`,
1826
- SessionKey: worldSessionKey,
1573
+ SessionKey: sessionKey,
1827
1574
  AccountId: runtimeConfig.accountId,
1828
1575
  OriginatingChannel: 'claworld',
1829
- OriginatingFrom: routePeerId || senderId,
1830
- // Match OpenClaw DM channel semantics: `To` is the local account surface,
1831
- // while `OriginatingTo` is the remote peer to reply back to.
1832
- OriginatingTo: routePeerId || localAddress || runtimeConfig.accountId,
1576
+ OriginatingFrom: remoteRouteIdentity,
1577
+ OriginatingTo: remoteRouteIdentity,
1833
1578
  ChatType: 'direct',
1834
- SenderName: routePeerId || senderId,
1835
- SenderId: routePeerId || senderId,
1836
- MessageId: turnId,
1579
+ SenderName: remoteAddress,
1580
+ SenderId: remoteRouteIdentity,
1581
+ MessageId: deliveryId,
1837
1582
  Provider: 'claworld',
1838
1583
  Surface: 'claworld',
1839
- ConversationLabel: routePeerId || senderId,
1584
+ ConversationLabel: remoteAddress,
1840
1585
  Timestamp: Date.now(),
1841
- MessageSid: turnId,
1586
+ MessageSid: deliveryId,
1842
1587
  WasMentioned: false,
1843
1588
  CommandAuthorized: commandAuthorized,
1844
- RelaySessionId: sessionId,
1845
- RelayTurnId: turnId,
1589
+ RelayDeliveryId: deliveryId,
1846
1590
  RelayFromAgentId: fromAgentId,
1847
1591
  UntrustedContext: ContextLines,
1848
1592
  });
1849
1593
 
1850
- enqueueBackendGuidance({
1851
- runtime,
1852
- sessionKey: worldSessionKey,
1853
- payload: turnData,
1854
- });
1855
-
1856
- logger.info?.(`[claworld:${runtimeAccountId}] bridging ${relayEvent} into agent session`, {
1857
- sessionId,
1858
- turnId,
1859
- routePeerId,
1860
- routeSessionKey: worldSessionKey,
1594
+ logger.info?.(`[claworld:${runtimeAccountId}] routing delivery into runtime session`, {
1595
+ deliveryId,
1596
+ sessionKey,
1597
+ remoteIdentity: remoteAddress,
1861
1598
  routeStatus: routed?.status || null,
1862
1599
  bodyPreview: String(Body || '').slice(0, 240),
1863
1600
  rawBodyPreview: String(RawBody || '').slice(0, 240),
1864
- inboundAccountId: inboundCtx?.AccountId || null,
1865
- inboundTo: inboundCtx?.To || null,
1866
- inboundFrom: inboundCtx?.From || null,
1867
- originatingTo: inboundCtx?.OriginatingTo || null,
1868
- originatingFrom: inboundCtx?.OriginatingFrom || null,
1601
+ allowReply: metadata.allowReply !== false,
1869
1602
  commandAuthorized,
1870
1603
  });
1871
1604
 
1872
- const { dispatcher, replyOptions, markDispatchIdle, didReply, getRuntimeOutputSummary } = createRelayReplyDispatcher({
1605
+ const { dispatcher, replyOptions, markDispatchIdle, didReply, getRuntimeOutputSummary } = createDeliveryReplyDispatcher({
1873
1606
  runtime,
1874
1607
  currentCfg,
1875
- route,
1876
1608
  relayClient,
1877
- sessionId,
1878
- turnId,
1879
- relayEvent,
1880
- localRelayAgentId,
1881
- allowRelayContinuation: resolveContinuationState(turnData).allowed !== false,
1609
+ deliveryId,
1610
+ sessionKey,
1611
+ localAgentId: runtimeConfig.relay?.agentId || relayClient?.boundAgentId || null,
1612
+ allowReply: metadata.allowReply !== false,
1882
1613
  logger,
1883
1614
  runtimeAccountId,
1884
1615
  });
@@ -1892,13 +1623,11 @@ async function maybeBridgeDeliveredTurn({
1892
1623
  const replied = didReply();
1893
1624
  const runtimeOutputSummary = getRuntimeOutputSummary();
1894
1625
 
1895
- logger.info?.(`[claworld:${runtimeAccountId}] relay message bridge completed`, {
1896
- sessionId,
1897
- turnId,
1898
- relayEvent,
1626
+ logger.info?.(`[claworld:${runtimeAccountId}] delivery bridge completed`, {
1627
+ deliveryId,
1628
+ sessionKey,
1899
1629
  queuedFinal: Boolean(dispatchResult?.queuedFinal),
1900
1630
  replied,
1901
- routeSessionKey: worldSessionKey,
1902
1631
  routeStatus: routed?.status || null,
1903
1632
  runtimeOutputSummary,
1904
1633
  });
@@ -1908,7 +1637,7 @@ async function maybeBridgeDeliveredTurn({
1908
1637
  ok: true,
1909
1638
  replied,
1910
1639
  queuedFinal: Boolean(dispatchResult?.queuedFinal),
1911
- routeSessionKey: worldSessionKey,
1640
+ sessionKey,
1912
1641
  routeStatus: routed?.status || null,
1913
1642
  };
1914
1643
  }
@@ -1926,7 +1655,6 @@ export function createClaworldChannelPlugin({
1926
1655
  const relayClients = new Map();
1927
1656
  const lifecycles = new Map();
1928
1657
  const accountRuntimeContexts = new Map();
1929
- const sessionIdToWorldId = new Map();
1930
1658
 
1931
1659
  async function persistRuntimeAppToken({ runtime, accountId, appToken }) {
1932
1660
  if (!runtime?.config?.loadConfig || !runtime?.config?.writeConfigFile) {
@@ -1992,16 +1720,6 @@ export function createClaworldChannelPlugin({
1992
1720
  };
1993
1721
  }
1994
1722
 
1995
- function clearSessionWorldCache(runtimeAccountId = 'default') {
1996
- const accountId = resolveNormalizedText(runtimeAccountId, 'default');
1997
- const prefix = `${accountId}:`;
1998
- Array.from(sessionIdToWorldId.keys()).forEach((cacheKey) => {
1999
- if (cacheKey.startsWith(prefix)) {
2000
- sessionIdToWorldId.delete(cacheKey);
2001
- }
2002
- });
2003
- }
2004
-
2005
1723
  function getAccountLifecycle(accountKey = 'default') {
2006
1724
  if (lifecycles.has(accountKey)) return lifecycles.get(accountKey);
2007
1725
 
@@ -2153,50 +1871,15 @@ export function createClaworldChannelPlugin({
2153
1871
  });
2154
1872
  relayClient.on?.('runtime_event', (event) => {
2155
1873
  logger.debug?.(`[claworld:${runtimeAccountId}] inbound relay event`, {
2156
- relayEvent: event?.relayEvent,
1874
+ eventType: event?.eventType || null,
2157
1875
  target: event?.route?.target || null,
2158
- sessionId: event?.inboundEnvelope?.session_id || null,
1876
+ deliveryId: event?.delivery?.deliveryId || null,
1877
+ sessionKey: event?.delivery?.sessionKey || null,
2159
1878
  });
2160
1879
 
2161
- if (event?.relayEvent === 'session.created') {
2162
- const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
2163
- maybeInjectWorldSessionStartupContext({
2164
- runtime: runtimeContext.runtime,
2165
- cfg: runtimeContext.cfg,
2166
- runtimeConfig,
2167
- runtimeAccountId,
2168
- event,
2169
- logger,
2170
- sessionIdToWorldId,
2171
- }).catch((error) => {
2172
- logger.error?.(`[claworld:${runtimeAccountId}] world startup injection exception`, {
2173
- error: error?.message || String(error),
2174
- });
2175
- });
2176
- }
2177
-
2178
- if (event?.relayEvent === 'turn.deliver') {
2179
- const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
2180
- maybeBridgeDeliveredTurn({
2181
- relayClient,
2182
- runtimeConfig,
2183
- runtimeAccountId,
2184
- event,
2185
- logger,
2186
- runtime: runtimeContext.runtime,
2187
- cfg: runtimeContext.cfg,
2188
- inbound,
2189
- sessionIdToWorldId,
2190
- }).catch((error) => {
2191
- logger.error?.(`[claworld:${runtimeAccountId}] turn bridge exception`, {
2192
- error: error?.message || String(error),
2193
- });
2194
- });
2195
- }
2196
-
2197
- if (event?.relayEvent === 'turn.reply') {
1880
+ if (event?.eventType === 'delivery') {
2198
1881
  const runtimeContext = accountRuntimeContexts.get(accountKey) || {};
2199
- maybeBridgeDeliveredTurn({
1882
+ maybeBridgeRuntimeDelivery({
2200
1883
  relayClient,
2201
1884
  runtimeConfig,
2202
1885
  runtimeAccountId,
@@ -2205,9 +1888,8 @@ export function createClaworldChannelPlugin({
2205
1888
  runtime: runtimeContext.runtime,
2206
1889
  cfg: runtimeContext.cfg,
2207
1890
  inbound,
2208
- sessionIdToWorldId,
2209
1891
  }).catch((error) => {
2210
- logger.error?.(`[claworld:${runtimeAccountId}] reply bridge exception`, {
1892
+ logger.error?.(`[claworld:${runtimeAccountId}] delivery bridge exception`, {
2211
1893
  error: error?.message || String(error),
2212
1894
  });
2213
1895
  });
@@ -2238,7 +1920,6 @@ export function createClaworldChannelPlugin({
2238
1920
  relayClients.delete(accountKey);
2239
1921
  }
2240
1922
  accountRuntimeContexts.delete(accountKey);
2241
- clearSessionWorldCache(accountKey);
2242
1923
  },
2243
1924
  });
2244
1925
 
@@ -2456,14 +2137,13 @@ export function createClaworldChannelPlugin({
2456
2137
  },
2457
2138
  inbound: {
2458
2139
  routeRelayEvent: (event = {}, options = {}) => {
2459
- const envelope = {
2460
- session_id: event.session_id || event.sessionId || null,
2461
- event_id: event.event_id || event.eventId || null,
2462
- from_agent_id: event.from_agent_id || event.fromAgentId || null,
2463
- type: event.type || 'message',
2140
+ return inbound.routeInboundEvent({
2141
+ eventType: event.eventType || event.type || 'delivery',
2142
+ deliveryId: event.deliveryId || event.event_id || event.eventId || null,
2143
+ sessionKey: event.sessionKey || null,
2464
2144
  payload: event.payload || {},
2465
- };
2466
- return inbound.routeInboundEvent(envelope, options);
2145
+ metadata: event.metadata || {},
2146
+ }, options);
2467
2147
  },
2468
2148
  },
2469
2149
  outbound: {
@@ -2547,7 +2227,6 @@ export function createClaworldChannelPlugin({
2547
2227
  targetAgentId: context.targetAgentId || null,
2548
2228
  openingMessage: context.openingMessage || context.message || context.text || null,
2549
2229
  worldId: context.worldId || null,
2550
- episodePolicy: context.episodePolicy || null,
2551
2230
  fetchImpl,
2552
2231
  });
2553
2232
  },
@@ -2595,19 +2274,6 @@ export function createClaworldChannelPlugin({
2595
2274
  logger,
2596
2275
  });
2597
2276
  },
2598
- fetchWorldJoinCheck: async (context = {}) => {
2599
- const resolvedContext = await resolveBoundRuntimeContext(context);
2600
- return fetchWorldJoinCheck({
2601
- cfg: resolvedContext.cfg || {},
2602
- accountId: resolvedContext.accountId || null,
2603
- runtimeConfig: resolvedContext.runtimeConfig || null,
2604
- worldId: context.worldId || null,
2605
- profile: context.profile || {},
2606
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? null,
2607
- fetchImpl,
2608
- logger,
2609
- });
2610
- },
2611
2277
  joinWorld: async (context = {}) => {
2612
2278
  const resolvedContext = await resolveBoundRuntimeContext(context);
2613
2279
  return joinWorld({
@@ -2616,25 +2282,7 @@ export function createClaworldChannelPlugin({
2616
2282
  runtimeConfig: resolvedContext.runtimeConfig || null,
2617
2283
  worldId: context.worldId || null,
2618
2284
  agentId: resolvedContext.agentId || null,
2619
- profile: context.profile || {},
2620
- profileSnapshot: context.profileSnapshot ?? null,
2621
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? null,
2622
- fetchImpl,
2623
- logger,
2624
- });
2625
- },
2626
- submitWorldJoin: async (context = {}) => {
2627
- const resolvedContext = await resolveBoundRuntimeContext(context);
2628
- return submitWorldJoin({
2629
- cfg: resolvedContext.cfg || {},
2630
- accountId: resolvedContext.accountId || null,
2631
- runtimeConfig: resolvedContext.runtimeConfig || null,
2632
- worldId: context.worldId || null,
2633
- agentId: resolvedContext.agentId || null,
2634
- profile: context.profile || {},
2635
- profileSnapshot: context.profileSnapshot ?? null,
2636
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2637
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2285
+ participantContextText: context.participantContextText || null,
2638
2286
  fetchImpl,
2639
2287
  logger,
2640
2288
  });
@@ -2685,39 +2333,6 @@ export function createClaworldChannelPlugin({
2685
2333
  context.selection ?? context.userChoice ?? null,
2686
2334
  ),
2687
2335
  buildCandidateDeliverySummary,
2688
- buildRequiredFieldExplanation,
2689
- resolveWorldProfileCollectionFlow: async (context = {}) => {
2690
- const resolvedContext = await resolveBoundRuntimeContext(context);
2691
- return resolveWorldProfileCollectionFlow({
2692
- cfg: resolvedContext.cfg || {},
2693
- accountId: resolvedContext.accountId || null,
2694
- runtimeConfig: resolvedContext.runtimeConfig || null,
2695
- worldId: context.worldId || null,
2696
- worldDetail: context.worldDetail || null,
2697
- profile: context.profile || {},
2698
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2699
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2700
- fetchImpl,
2701
- logger,
2702
- });
2703
- },
2704
- resolveWorldJoinFlow: async (context = {}) => {
2705
- const resolvedContext = await resolveBoundRuntimeContext(context);
2706
- return resolveWorldJoinFlow({
2707
- cfg: resolvedContext.cfg || {},
2708
- accountId: resolvedContext.accountId || null,
2709
- runtimeConfig: resolvedContext.runtimeConfig || null,
2710
- worldId: context.worldId || null,
2711
- worldDetail: context.worldDetail || null,
2712
- agentId: resolvedContext.agentId || null,
2713
- profile: context.profile || {},
2714
- profileSnapshot: context.profileSnapshot ?? null,
2715
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2716
- limit: context.limit ?? context.candidateLimit ?? null,
2717
- fetchImpl,
2718
- logger,
2719
- });
2720
- },
2721
2336
  resolveWorldSelectionFlow: async (context = {}) => {
2722
2337
  const resolvedContext = await resolveBoundRuntimeContext(context);
2723
2338
  return resolveWorldSelectionFlow({
@@ -2727,7 +2342,6 @@ export function createClaworldChannelPlugin({
2727
2342
  worldDirectory: context.worldDirectory || null,
2728
2343
  selection: context.selection ?? context.userChoice ?? null,
2729
2344
  profile: context.profile || {},
2730
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2731
2345
  fetchImpl,
2732
2346
  logger,
2733
2347
  });
@@ -2741,17 +2355,8 @@ export function createClaworldChannelPlugin({
2741
2355
  accountId: resolvedContext.accountId || null,
2742
2356
  runtimeConfig: resolvedContext.runtimeConfig || null,
2743
2357
  agentId: resolvedContext.agentId || null,
2744
- adminAgentIds: context.adminAgentIds || [],
2745
- eligibility: context.eligibility || 'active',
2746
- ...(Object.prototype.hasOwnProperty.call(context, 'broadcast') ? { broadcast: context.broadcast } : {}),
2747
2358
  displayName: context.displayName || null,
2748
- summary: context.summary || null,
2749
- description: context.description || null,
2750
- entryProfileSchema: context.entryProfileSchema || {},
2751
- sessionTemplate: context.sessionTemplate || null,
2752
- interactionRules: context.interactionRules || null,
2753
- prohibitedRules: context.prohibitedRules || null,
2754
- ratingRules: context.ratingRules || null,
2359
+ worldContextText: context.worldContextText || null,
2755
2360
  enabled: context.enabled === true,
2756
2361
  fetchImpl,
2757
2362
  logger,
@@ -2818,19 +2423,6 @@ export function createClaworldChannelPlugin({
2818
2423
  logger,
2819
2424
  });
2820
2425
  },
2821
- fetchWorldJoinCheck: async (context = {}) => {
2822
- const resolvedContext = await resolveBoundRuntimeContext(context);
2823
- return fetchWorldJoinCheck({
2824
- cfg: resolvedContext.cfg || {},
2825
- accountId: resolvedContext.accountId || null,
2826
- runtimeConfig: resolvedContext.runtimeConfig || null,
2827
- worldId: context.worldId || null,
2828
- profile: context.profile || {},
2829
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? null,
2830
- fetchImpl,
2831
- logger,
2832
- });
2833
- },
2834
2426
  joinWorld: async (context = {}) => {
2835
2427
  const resolvedContext = await resolveBoundRuntimeContext(context);
2836
2428
  return joinWorld({
@@ -2839,25 +2431,7 @@ export function createClaworldChannelPlugin({
2839
2431
  runtimeConfig: resolvedContext.runtimeConfig || null,
2840
2432
  worldId: context.worldId || null,
2841
2433
  agentId: resolvedContext.agentId || null,
2842
- profile: context.profile || {},
2843
- profileSnapshot: context.profileSnapshot ?? null,
2844
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? null,
2845
- fetchImpl,
2846
- logger,
2847
- });
2848
- },
2849
- submitWorldJoin: async (context = {}) => {
2850
- const resolvedContext = await resolveBoundRuntimeContext(context);
2851
- return submitWorldJoin({
2852
- cfg: resolvedContext.cfg || {},
2853
- accountId: resolvedContext.accountId || null,
2854
- runtimeConfig: resolvedContext.runtimeConfig || null,
2855
- worldId: context.worldId || null,
2856
- agentId: resolvedContext.agentId || null,
2857
- profile: context.profile || {},
2858
- profileSnapshot: context.profileSnapshot ?? null,
2859
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2860
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2434
+ participantContextText: context.participantContextText || null,
2861
2435
  fetchImpl,
2862
2436
  logger,
2863
2437
  });
@@ -2923,39 +2497,6 @@ export function createClaworldChannelPlugin({
2923
2497
  },
2924
2498
  resolveWorldSelection,
2925
2499
  buildCandidateDeliverySummary,
2926
- buildRequiredFieldExplanation,
2927
- resolveWorldProfileCollectionFlow: async (context = {}) => {
2928
- const resolvedContext = await resolveBoundRuntimeContext(context);
2929
- return resolveWorldProfileCollectionFlow({
2930
- cfg: resolvedContext.cfg || {},
2931
- accountId: resolvedContext.accountId || null,
2932
- runtimeConfig: resolvedContext.runtimeConfig || null,
2933
- worldId: context.worldId || null,
2934
- worldDetail: context.worldDetail || null,
2935
- profile: context.profile || {},
2936
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2937
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2938
- fetchImpl,
2939
- logger,
2940
- });
2941
- },
2942
- resolveWorldJoinFlow: async (context = {}) => {
2943
- const resolvedContext = await resolveBoundRuntimeContext(context);
2944
- return resolveWorldJoinFlow({
2945
- cfg: resolvedContext.cfg || {},
2946
- accountId: resolvedContext.accountId || null,
2947
- runtimeConfig: resolvedContext.runtimeConfig || null,
2948
- worldId: context.worldId || null,
2949
- worldDetail: context.worldDetail || null,
2950
- agentId: resolvedContext.agentId || null,
2951
- profile: context.profile || {},
2952
- profileSnapshot: context.profileSnapshot ?? null,
2953
- profileUpdate: context.profileUpdate ?? context.profilePatch ?? null,
2954
- limit: context.limit ?? context.candidateLimit ?? null,
2955
- fetchImpl,
2956
- logger,
2957
- });
2958
- },
2959
2500
  resolveWorldSelectionFlow: async (context = {}) => {
2960
2501
  const resolvedContext = await resolveBoundRuntimeContext(context);
2961
2502
  return resolveWorldSelectionFlow({
@@ -2965,7 +2506,6 @@ export function createClaworldChannelPlugin({
2965
2506
  worldDirectory: context.worldDirectory || null,
2966
2507
  selection: context.selection ?? context.userChoice ?? null,
2967
2508
  profile: context.profile || {},
2968
- maxFieldsPerStep: context.maxFieldsPerStep ?? context.maxPromptFields ?? 1,
2969
2509
  fetchImpl,
2970
2510
  logger,
2971
2511
  });
@@ -2998,23 +2538,14 @@ export function createClaworldChannelPlugin({
2998
2538
  moderation: {
2999
2539
  createWorld: async (context = {}) => {
3000
2540
  const resolvedContext = await resolveBoundRuntimeContext(context);
3001
- return createModeratedWorld({
2541
+ return createModeratedWorld({
3002
2542
  cfg: resolvedContext.cfg || {},
3003
2543
  accountId: resolvedContext.accountId || null,
3004
2544
  runtimeConfig: resolvedContext.runtimeConfig || null,
3005
2545
  agentId: resolvedContext.agentId || null,
3006
- adminAgentIds: context.adminAgentIds || [],
3007
- eligibility: context.eligibility || 'active',
3008
- ...(Object.prototype.hasOwnProperty.call(context, 'broadcast') ? { broadcast: context.broadcast } : {}),
3009
2546
  displayName: context.displayName || null,
3010
- summary: context.summary || null,
3011
- description: context.description || null,
3012
- entryProfileSchema: context.entryProfileSchema || {},
3013
- sessionTemplate: context.sessionTemplate || null,
3014
- interactionRules: context.interactionRules || null,
3015
- prohibitedRules: context.prohibitedRules || null,
3016
- ratingRules: context.ratingRules || null,
3017
- enabled: context.enabled === true,
2547
+ worldContextText: context.worldContextText || null,
2548
+ enabled: context.enabled === true,
3018
2549
  fetchImpl,
3019
2550
  logger,
3020
2551
  });
@@ -3084,7 +2615,7 @@ export function createClaworldChannelPlugin({
3084
2615
  'native channel setup/onboarding',
3085
2616
  'relay websocket adapter tests',
3086
2617
  'manual relay-agent binding',
3087
- 'minimal outbound session-request send',
2618
+ 'minimal outbound conversation send',
3088
2619
  ],
3089
2620
  notImplemented: [
3090
2621
  '真实 OpenClaw sdk import/types 对齐',