@xfxstudio/claworld 0.1.5 → 0.2.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.
Files changed (54) hide show
  1. package/README.md +12 -29
  2. package/openclaw.plugin.json +5 -29
  3. package/package.json +4 -12
  4. package/skills/claworld-help/SKILL.md +50 -182
  5. package/skills/claworld-join-and-chat/SKILL.md +78 -288
  6. package/skills/claworld-manage-worlds/SKILL.md +71 -288
  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 +18 -9
  11. package/src/openclaw/installer/core.js +12 -6
  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 +118 -623
  15. package/src/openclaw/plugin/config-schema.js +3 -15
  16. package/src/openclaw/plugin/managed-config.js +98 -47
  17. package/src/openclaw/plugin/onboarding.js +7 -3
  18. package/src/openclaw/plugin/register.js +37 -336
  19. package/src/openclaw/plugin/relay-client.js +111 -101
  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 +43 -636
  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 +33 -258
  30. package/src/openclaw/runtime/world-moderation-helper.js +11 -65
  31. package/src/product-shell/catalog/default-world-catalog.js +9 -27
  32. package/src/product-shell/contracts/candidate-feed.js +26 -1
  33. package/src/product-shell/contracts/chat-request-approval-policy.js +4 -4
  34. package/src/product-shell/contracts/world-manifest.js +115 -160
  35. package/src/product-shell/contracts/world-orchestration.js +47 -322
  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 +5 -6
  39. package/src/product-shell/membership/membership-service.js +125 -147
  40. package/src/product-shell/onboarding/onboarding-service.js +2 -2
  41. package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
  42. package/src/product-shell/orchestration/world-conversation-text.js +231 -0
  43. package/src/product-shell/results/result-service.js +9 -3
  44. package/src/product-shell/search/search-service.js +28 -1
  45. package/src/product-shell/social/chat-request-routes.js +0 -1
  46. package/src/product-shell/social/chat-request-service.js +1 -102
  47. package/src/product-shell/worlds/world-admin-service.js +85 -276
  48. package/src/product-shell/worlds/world-authorization.js +3 -5
  49. package/src/product-shell/worlds/world-routes.js +8 -38
  50. package/src/product-shell/worlds/world-service.js +3 -3
  51. package/src/product-shell/worlds/world-text.js +77 -0
  52. package/src/lib/runtime-guidance.js +0 -457
  53. package/src/openclaw/runtime/world-session-startup.js +0 -1
  54. package/src/product-shell/orchestration/session-orchestrator.js +0 -38
@@ -8,9 +8,9 @@ export const OPENCLAW_RUNTIME_PATH = [
8
8
  'gateway(channel)',
9
9
  ];
10
10
 
11
- export function createRuntimePathTrace({ sessionId = null, eventId = null, direction = 'inbound' } = {}) {
11
+ export function createRuntimePathTrace({ sessionKey = null, eventId = null, direction = 'inbound' } = {}) {
12
12
  return {
13
- sessionId,
13
+ sessionKey: sessionKey || null,
14
14
  eventId,
15
15
  direction,
16
16
  path: [...OPENCLAW_RUNTIME_PATH],
@@ -1 +1 @@
1
- export { createSystemMessageOrchestrator } from '../../lib/runtime-guidance.js';
1
+ export { createSystemMessageOrchestrator } from '../../product-shell/orchestration/world-conversation-text.js';
@@ -52,34 +52,6 @@ function summarizeProfileSnippet(profileSummary = {}) {
52
52
  return allFields[0] || null;
53
53
  }
54
54
 
55
- function projectEntryProfileFields(worldDetail = {}) {
56
- const requiredFields = Array.isArray(worldDetail.requiredFields) ? worldDetail.requiredFields : [];
57
- const optionalFields = Array.isArray(worldDetail.optionalFields) ? worldDetail.optionalFields : [];
58
- const searchableFieldIds = new Set(
59
- Array.isArray(worldDetail.searchSchema?.inputFieldIds) ? worldDetail.searchSchema.inputFieldIds : [],
60
- );
61
-
62
- return [...requiredFields, ...optionalFields].map((field) => ({
63
- fieldId: field.fieldId,
64
- label: field.label,
65
- required: field.required === true,
66
- searchable: searchableFieldIds.has(field.fieldId),
67
- description: field.description || null,
68
- examples: normalizeStringList(field.examples),
69
- }));
70
- }
71
-
72
- function projectProfileField(field = {}) {
73
- return {
74
- fieldId: normalizeText(field.fieldId, null),
75
- label: normalizeText(field.label, normalizeText(field.fieldId, 'Field')),
76
- required: field.required === true,
77
- description: normalizeText(field.description, null),
78
- examples: normalizeStringList(field.examples),
79
- constraints: field.constraints && typeof field.constraints === 'object' ? field.constraints : null,
80
- };
81
- }
82
-
83
55
  function projectSearchMatchReasons(item = {}) {
84
56
  if (Array.isArray(item.matchedFields) && item.matchedFields.length > 0) {
85
57
  return item.matchedFields.map((field) => {
@@ -93,47 +65,12 @@ function projectSearchMatchReasons(item = {}) {
93
65
  return [normalizeText(item.reasonSummary, 'Recently active online world member.')];
94
66
  }
95
67
 
96
- function projectModerationEntryProfileSchema(schema = null) {
97
- if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return null;
68
+ function projectParticipantContextField(field = null) {
69
+ if (!field || typeof field !== 'object' || Array.isArray(field)) return null;
98
70
  return {
99
- fields: Array.isArray(schema.fields)
100
- ? schema.fields.map((field) => ({
101
- fieldId: field.fieldId,
102
- label: field.label,
103
- type: field.type,
104
- required: typeof field.required === 'boolean' ? field.required : null,
105
- searchable: typeof field.searchable === 'boolean' ? field.searchable : null,
106
- description: field.description || null,
107
- examples: normalizeStringList(field.examples),
108
- }))
109
- : [],
110
- };
111
- }
112
-
113
- function projectModerationSessionTemplate(sessionTemplate = null) {
114
- if (!sessionTemplate || typeof sessionTemplate !== 'object' || Array.isArray(sessionTemplate)) return null;
115
-
116
- return {
117
- mode: normalizeText(sessionTemplate.mode, null),
118
- maxTurns: normalizePositiveInteger(sessionTemplate.maxTurns, null),
119
- turnTimeoutMs: normalizePositiveInteger(sessionTemplate.turnTimeoutMs, null),
120
- raiseHandPolicy: sessionTemplate.raiseHandPolicy && typeof sessionTemplate.raiseHandPolicy === 'object'
121
- ? {
122
- mode: normalizeText(sessionTemplate.raiseHandPolicy.mode, null),
123
- summary: normalizeText(sessionTemplate.raiseHandPolicy.summary, null),
124
- }
125
- : null,
126
- };
127
- }
128
-
129
- function projectModerationBroadcastConfig(broadcast = null) {
130
- if (!broadcast || typeof broadcast !== 'object' || Array.isArray(broadcast)) return null;
131
-
132
- return {
133
- enabled: normalizeOptionalBoolean(broadcast.enabled, null),
134
- audience: normalizeText(broadcast.audience, null),
135
- replyPolicy: normalizeText(broadcast.replyPolicy, null),
136
- excludeSelf: typeof broadcast.excludeSelf === 'boolean' ? broadcast.excludeSelf : null,
71
+ fieldId: normalizeText(field.fieldId, null),
72
+ label: normalizeText(field.label, normalizeText(field.fieldId, 'Entry Profile')),
73
+ description: normalizeText(field.description, null),
137
74
  };
138
75
  }
139
76
 
@@ -269,7 +206,7 @@ export function projectToolWorldList(worldDirectory = {}) {
269
206
  .map((world) => ({
270
207
  worldId: world.worldId,
271
208
  displayName: world.displayName,
272
- summary: world.summary,
209
+ worldContextText: normalizeText(world.worldContextText, null),
273
210
  hotness: normalizeInteger(world.hotness, 0),
274
211
  }))
275
212
  .sort((left, right) => right.hotness - left.hotness || left.displayName.localeCompare(right.displayName))
@@ -294,87 +231,15 @@ export function projectToolWorldList(worldDirectory = {}) {
294
231
  export function projectToolWorldDetail(worldDetail = {}) {
295
232
  return {
296
233
  worldId: worldDetail.worldId,
297
- displayName: worldDetail.displayName,
298
- description: normalizeText(worldDetail.description, worldDetail.summary || ''),
299
- entryProfileSchema: {
300
- fields: projectEntryProfileFields(worldDetail),
301
- },
302
- interactionRules: normalizeText(worldDetail.interactionRules, ''),
303
- prohibitedRules: normalizeText(worldDetail.prohibitedRules, ''),
304
- ratingRules: normalizeText(worldDetail.ratingRules, ''),
305
- adminAgentIds: Array.isArray(worldDetail.adminAgentIds) ? worldDetail.adminAgentIds : [],
306
- eligibility: normalizeText(worldDetail.eligibility, null),
307
- broadcast: projectModerationBroadcastConfig(worldDetail.broadcast),
308
- };
309
- }
310
-
311
- export function projectToolWorldProfileCollectionResponse(
312
- flow = {},
313
- {
314
- accountId = null,
315
- continueToolName = null,
316
- joinToolName = null,
317
- } = {},
318
- ) {
319
- const profileDraft = flow.profile && typeof flow.profile === 'object' ? flow.profile : {};
320
- const missingRequiredFields = Array.isArray(flow.joinCheck?.missingFields)
321
- ? flow.joinCheck.missingFields.map((field) => projectProfileField(field))
322
- : [];
323
- const promptFields = Array.isArray(flow.promptFields)
324
- ? flow.promptFields.map((field) => projectProfileField(field))
325
- : [];
326
- const nextMissingField = flow.joinCheck?.nextMissingField
327
- ? projectProfileField(flow.joinCheck.nextMissingField)
328
- : (promptFields[0] || null);
329
- const normalizedAccountId = normalizeText(accountId, null);
330
- const normalizedWorldId = normalizeText(flow.worldId, null);
331
- const readyToJoin = flow.accepted === true;
332
-
333
- return {
334
- status: readyToJoin ? 'ready_to_join' : 'needs_profile',
335
- worldId: normalizedWorldId,
336
- accountId: normalizedAccountId,
337
- profileDraft,
338
- providedRequiredFieldIds: normalizeStringList(flow.providedRequiredFieldIds),
339
- missingRequiredFields,
340
- nextMissingField,
341
- promptFields,
342
- remainingRequiredFieldCount: normalizeInteger(
343
- flow.remainingRequiredFieldCount,
344
- missingRequiredFields.length,
234
+ displayName: normalizeText(worldDetail.world?.displayName, worldDetail.displayName || ''),
235
+ worldContextText: normalizeText(
236
+ worldDetail.world?.worldContextText,
237
+ worldDetail.worldContextText || '',
345
238
  ),
346
- revalidationCheckpoint: flow.revalidationCheckpoint && typeof flow.revalidationCheckpoint === 'object'
347
- ? {
348
- mode: normalizeText(
349
- flow.revalidationCheckpoint.mode,
350
- readyToJoin ? 'complete' : 'after_each_reply',
351
- ),
352
- promptFieldIds: normalizeStringList(flow.revalidationCheckpoint.promptFieldIds),
353
- }
354
- : {
355
- mode: readyToJoin ? 'complete' : 'after_each_reply',
356
- promptFieldIds: promptFields.map((field) => field.fieldId).filter(Boolean),
357
- },
358
- nextAction: readyToJoin
359
- ? 'call_join_world'
360
- : 'retry_join_world_after_profile_update',
361
- nextTool: readyToJoin ? normalizeText(joinToolName, null) : normalizeText(continueToolName, null),
362
- continueTool: normalizeText(continueToolName, null),
363
- joinTool: normalizeText(joinToolName, null),
364
- joinPayload: readyToJoin && normalizedWorldId
365
- ? {
366
- accountId: normalizedAccountId,
367
- worldId: normalizedWorldId,
368
- profileSnapshot: profileDraft,
369
- }
370
- : null,
371
- orchestration: projectOrchestration(flow.orchestration),
372
- guidance: flow.orchestration && typeof flow.orchestration === 'object'
373
- ? {
374
- user: normalizeText(flow.orchestration.user, null),
375
- followUp: normalizeText(flow.orchestration.followUp, null),
376
- }
377
- : null,
239
+ ownerAgentId: normalizeText(worldDetail.management?.ownerAgentId, null),
240
+ enabled: normalizeOptionalBoolean(worldDetail.management?.enabled, null),
241
+ status: normalizeText(worldDetail.management?.status, null),
242
+ participantContextField: projectParticipantContextField(worldDetail.participantContextField),
378
243
  };
379
244
  }
380
245
 
@@ -436,94 +301,27 @@ function projectToolCandidateFeed(joinResult = {}) {
436
301
 
437
302
  export function projectToolJoinWorldResponse(
438
303
  joinResult = {},
439
- {
440
- accountId = null,
441
- continueToolName = 'claworld_prepare_world_join',
442
- joinToolName = 'claworld_join_world',
443
- } = {},
304
+ { accountId = null } = {},
444
305
  ) {
445
- if (joinResult.status === 'needs_profile') {
446
- if (joinResult.profileCollectionFlow && typeof joinResult.profileCollectionFlow === 'object') {
447
- const profileCollectionResponse = projectToolWorldProfileCollectionResponse(joinResult.profileCollectionFlow, {
448
- accountId,
449
- continueToolName,
450
- joinToolName,
451
- });
452
- const normalizedProfile = joinResult.normalizedProfile && typeof joinResult.normalizedProfile === 'object'
453
- ? joinResult.normalizedProfile
454
- : profileCollectionResponse.profileDraft;
455
- const missingFields = Array.isArray(joinResult.missingFields)
456
- ? joinResult.missingFields
457
- : (Array.isArray(joinResult.missingRequiredFields) ? joinResult.missingRequiredFields : []);
458
-
459
- return {
460
- ...profileCollectionResponse,
461
- membershipStatus: joinResult.membershipStatus || 'inactive',
462
- normalizedProfile,
463
- profileDraft: normalizedProfile,
464
- missingFields,
465
- missingRequiredFields: missingFields,
466
- nextAction: normalizeText(joinResult.nextAction, profileCollectionResponse.nextAction),
467
- missingFieldGuidance: joinResult.missingFieldGuidance && typeof joinResult.missingFieldGuidance === 'object'
468
- ? joinResult.missingFieldGuidance
469
- : null,
470
- };
471
- }
472
-
473
- const normalizedProfile = joinResult.normalizedProfile && typeof joinResult.normalizedProfile === 'object'
474
- ? joinResult.normalizedProfile
475
- : {};
476
- const missingFields = Array.isArray(joinResult.missingFields)
477
- ? joinResult.missingFields
478
- : (Array.isArray(joinResult.missingRequiredFields) ? joinResult.missingRequiredFields : []);
479
-
480
- return {
481
- status: 'needs_profile',
482
- worldId: joinResult.worldId,
483
- accountId: normalizeText(accountId, null),
484
- membershipStatus: joinResult.membershipStatus || 'inactive',
485
- normalizedProfile,
486
- profileDraft: normalizedProfile,
487
- missingFields,
488
- missingRequiredFields: missingFields,
489
- nextMissingField: joinResult.nextMissingField || null,
490
- nextAction: normalizeText(joinResult.nextAction, 'retry_join_world_after_profile_update'),
491
- nextTool: normalizeText(joinToolName, null),
492
- continueTool: normalizeText(joinToolName, null),
493
- joinTool: normalizeText(joinToolName, null),
494
- missingFieldGuidance: joinResult.missingFieldGuidance && typeof joinResult.missingFieldGuidance === 'object'
495
- ? joinResult.missingFieldGuidance
496
- : null,
497
- orchestration: projectOrchestration(joinResult.orchestration),
498
- guidance: joinResult.orchestration && typeof joinResult.orchestration === 'object'
499
- ? {
500
- user: normalizeText(joinResult.orchestration.user, null),
501
- followUp: normalizeText(joinResult.orchestration.followUp, null),
502
- }
503
- : null,
504
- };
505
- }
506
-
306
+ const normalizedProfile = joinResult.normalizedProfile && typeof joinResult.normalizedProfile === 'object'
307
+ ? joinResult.normalizedProfile
308
+ : {};
507
309
  return {
508
310
  status: joinResult.membershipStatus === 'active' ? 'joined' : 'accepted',
509
311
  worldId: joinResult.worldId,
510
312
  accountId: normalizeText(accountId, null),
511
313
  membershipStatus: joinResult.membershipStatus || 'unknown',
512
- normalizedProfile: joinResult.normalizedProfile && typeof joinResult.normalizedProfile === 'object'
513
- ? joinResult.normalizedProfile
514
- : {},
314
+ participantContextText: normalizeText(
315
+ joinResult.participantContextText,
316
+ normalizedProfile.participantContextText || joinResult.membership?.participantContextText || null,
317
+ ),
318
+ normalizedProfile,
515
319
  nextAction: normalizeText(joinResult.nextAction, 'review_candidate_feed'),
516
320
  candidateFeed: projectToolCandidateFeed(joinResult),
517
321
  requestChatTool: 'claworld_request_chat',
518
322
  candidateDelivery: projectToolCandidateDeliverySummary(joinResult.candidateDelivery, { accountId }),
519
323
  requestChatAction: projectRequestChatAction(joinResult.requestChatAction, { accountId }),
520
324
  orchestration: projectOrchestration(joinResult.orchestration),
521
- guidance: joinResult.orchestration && typeof joinResult.orchestration === 'object'
522
- ? {
523
- user: normalizeText(joinResult.orchestration.user, null),
524
- followUp: normalizeText(joinResult.orchestration.followUp, null),
525
- }
526
- : null,
527
325
  };
528
326
  }
529
327
 
@@ -576,15 +374,15 @@ export function projectToolCreateWorldResponse(world = {}, { accountId = null }
576
374
  return {
577
375
  worldId: world.worldId,
578
376
  accountId: normalizeText(accountId, null),
377
+ displayName: normalizeText(world.displayName, null),
378
+ worldContextText: normalizeText(world.worldContextText, null),
379
+ participantContextField: projectParticipantContextField(world.participantContextField),
380
+ ownerAgentId: normalizeText(world.ownerAgentId, null),
579
381
  status: normalizeText(world.status, null),
580
382
  enabled: normalizeOptionalBoolean(world.enabled, null),
581
383
  worldRole: projectWorldRole(world.worldRole, null),
582
384
  schemaVersion: normalizeOptionalInteger(world.schemaVersion, null),
583
385
  createdAt: normalizeText(world.createdAt, null),
584
- adminAgentIds: Array.isArray(world.adminAgentIds) ? world.adminAgentIds : [],
585
- eligibility: normalizeText(world.eligibility, null),
586
- broadcast: projectModerationBroadcastConfig(world.broadcast),
587
- sessionTemplate: projectModerationSessionTemplate(world.sessionTemplate),
588
386
  };
589
387
  }
590
388
 
@@ -614,22 +412,15 @@ export function projectToolManagedWorldResponse(world = {}, { accountId = null }
614
412
  worldId: world.worldId,
615
413
  accountId: normalizeText(accountId, null),
616
414
  displayName: world.displayName,
617
- summary: world.summary,
618
- description: world.description,
415
+ worldContextText: normalizeText(world.worldContextText, null),
416
+ ownerAgentId: normalizeText(world.ownerAgentId, null),
619
417
  enabled: normalizeOptionalBoolean(world.enabled, null),
620
418
  status: normalizeText(world.status, null),
621
419
  worldRole: projectWorldRole(world.worldRole, null),
622
420
  schemaVersion: normalizeOptionalInteger(world.schemaVersion, null),
623
421
  createdAt: normalizeText(world.createdAt, null),
624
422
  updatedAt: normalizeText(world.updatedAt, null),
625
- adminAgentIds: Array.isArray(world.adminAgentIds) ? world.adminAgentIds : [],
626
- eligibility: normalizeText(world.eligibility, null),
627
- broadcast: projectModerationBroadcastConfig(world.broadcast),
628
- entryProfileSchema: projectModerationEntryProfileSchema(world.entryProfileSchema),
629
- interactionRules: normalizeText(world.interactionRules, null),
630
- prohibitedRules: normalizeText(world.prohibitedRules, null),
631
- ratingRules: normalizeText(world.ratingRules, null),
632
- sessionTemplate: projectModerationSessionTemplate(world.sessionTemplate),
423
+ participantContextField: projectParticipantContextField(world.participantContextField),
633
424
  stats: projectWorldStats(world.stats),
634
425
  };
635
426
  }
@@ -693,7 +484,9 @@ export function projectToolFeedbackSubmissionResponse(result = {}) {
693
484
  reporterAgentId: normalizeText(reporter.agentId, null),
694
485
  reporterAgentCode: normalizeText(reporter.agentCode, null),
695
486
  worldId: normalizeText(context.worldId, null),
696
- sessionId: normalizeText(context.sessionId, null),
487
+ conversationKey: normalizeText(context.conversationKey, null),
488
+ turnId: normalizeText(context.turnId, null),
489
+ deliveryId: normalizeText(context.deliveryId, null),
697
490
  tags: normalizeStringList(context.tags),
698
491
  createdAt: normalizeText(feedback.createdAt, null),
699
492
  runtime: {
@@ -744,26 +537,10 @@ function projectToolWorldSummary(world = {}) {
744
537
  function normalizeConversationScopeDetails(input = {}) {
745
538
  const conversation = input && typeof input === 'object' && !Array.isArray(input) ? input : {};
746
539
  const worldId = normalizeText(conversation.worldId, null);
747
- const maxTurns = normalizePositiveInteger(conversation.maxTurns, null);
748
- const turnTimeoutMs = normalizePositiveInteger(conversation.turnTimeoutMs, null);
749
- const raiseHandPolicy = conversation.raiseHandPolicy && typeof conversation.raiseHandPolicy === 'object' && !Array.isArray(conversation.raiseHandPolicy)
750
- ? {
751
- mode: normalizeText(conversation.raiseHandPolicy.mode, null),
752
- summary: normalizeText(conversation.raiseHandPolicy.summary, null),
753
- }
754
- : null;
755
- const episodePolicy = maxTurns != null || turnTimeoutMs != null || raiseHandPolicy
756
- ? {
757
- ...(maxTurns != null ? { maxTurns } : {}),
758
- ...(turnTimeoutMs != null ? { turnTimeoutMs } : {}),
759
- ...(raiseHandPolicy ? { raiseHandPolicy } : {}),
760
- }
761
- : null;
762
540
  return {
763
541
  mode: worldId ? 'world' : 'direct',
764
542
  worldId,
765
543
  world: projectToolWorldSummary(conversation.world),
766
- ...(episodePolicy ? { episodePolicy } : {}),
767
544
  };
768
545
  }
769
546
 
@@ -786,8 +563,6 @@ function projectChatRequestKickoff(kickoff = {}) {
786
563
  return {
787
564
  status: normalizeText(kickoff.status, 'skipped'),
788
565
  deliveredAt: normalizeText(kickoff.deliveredAt, null),
789
- relaySessionPreparedAt: normalizeText(kickoff.relaySessionPreparedAt, null),
790
- acceptedRoundPreparedAt: normalizeText(kickoff.acceptedRoundPreparedAt, null),
791
566
  senderKickoffDeliveredAt: normalizeText(kickoff.senderKickoffDeliveredAt, normalizeText(kickoff.deliveredAt, null)),
792
567
  openerAcceptedAt: normalizeText(kickoff.openerAcceptedAt, null),
793
568
  openerDeliveredAt: normalizeText(kickoff.openerDeliveredAt, null),
@@ -48,7 +48,7 @@ function normalizeFieldError(fieldError = {}) {
48
48
  };
49
49
  }
50
50
 
51
- function normalizeProfileField(field = {}, index = 0) {
51
+ function normalizeParticipantContextField(field = {}, index = 0) {
52
52
  return {
53
53
  fieldId: normalizeText(field.fieldId, `field_${index + 1}`),
54
54
  label: normalizeText(field.label, `Field ${index + 1}`),
@@ -60,12 +60,9 @@ function normalizeProfileField(field = {}, index = 0) {
60
60
  };
61
61
  }
62
62
 
63
- function normalizeEntryProfileSchema(schema = null) {
64
- if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return null;
65
- const rawFields = Array.isArray(schema?.fields) ? schema.fields : [];
66
- return {
67
- fields: rawFields.map((field, index) => normalizeProfileField(field, index)),
68
- };
63
+ function normalizeParticipantContextFieldPayload(field = null) {
64
+ if (!field || typeof field !== 'object' || Array.isArray(field)) return null;
65
+ return normalizeParticipantContextField(field);
69
66
  }
70
67
 
71
68
  function normalizeWorldStats(stats = null) {
@@ -77,33 +74,6 @@ function normalizeWorldStats(stats = null) {
77
74
  };
78
75
  }
79
76
 
80
- function normalizeManagedSessionTemplate(sessionTemplate = null) {
81
- if (!sessionTemplate || typeof sessionTemplate !== 'object' || Array.isArray(sessionTemplate)) return null;
82
-
83
- return {
84
- mode: normalizeText(sessionTemplate.mode, null),
85
- maxTurns: normalizePositiveInteger(sessionTemplate.maxTurns, null),
86
- turnTimeoutMs: normalizePositiveInteger(sessionTemplate.turnTimeoutMs, null),
87
- raiseHandPolicy: sessionTemplate.raiseHandPolicy && typeof sessionTemplate.raiseHandPolicy === 'object'
88
- ? {
89
- mode: normalizeText(sessionTemplate.raiseHandPolicy.mode, null),
90
- summary: normalizeText(sessionTemplate.raiseHandPolicy.summary, null),
91
- }
92
- : null,
93
- };
94
- }
95
-
96
- function normalizeManagedBroadcastConfig(broadcast = null) {
97
- if (!broadcast || typeof broadcast !== 'object' || Array.isArray(broadcast)) return null;
98
-
99
- return {
100
- enabled: normalizeOptionalBoolean(broadcast.enabled, null),
101
- audience: normalizeText(broadcast.audience, null),
102
- replyPolicy: normalizeText(broadcast.replyPolicy, null),
103
- excludeSelf: typeof broadcast.excludeSelf === 'boolean' ? broadcast.excludeSelf : null,
104
- };
105
- }
106
-
107
77
  function normalizeWorldRole(worldRole, fallback = null) {
108
78
  const normalized = normalizeText(worldRole, fallback);
109
79
  return ['owner', 'admin', 'member'].includes(normalized) ? normalized : fallback;
@@ -113,22 +83,15 @@ function normalizeManagedWorld(payload = {}) {
113
83
  return {
114
84
  worldId: normalizeText(payload.worldId, null),
115
85
  displayName: normalizeText(payload.displayName, null),
116
- summary: normalizeText(payload.summary, null),
117
- description: normalizeText(payload.description, null),
86
+ worldContextText: normalizeText(payload.worldContextText, null),
87
+ ownerAgentId: normalizeText(payload.ownerAgentId, null),
118
88
  enabled: normalizeOptionalBoolean(payload.enabled, null),
119
89
  status: normalizeText(payload.status, null),
120
90
  worldRole: normalizeWorldRole(payload.worldRole, null),
121
91
  schemaVersion: normalizeOptionalInteger(payload.schemaVersion, null),
122
92
  createdAt: normalizeText(payload.createdAt, null),
123
93
  updatedAt: normalizeText(payload.updatedAt, null),
124
- adminAgentIds: normalizeStringList(payload.adminAgentIds),
125
- eligibility: normalizeText(payload.eligibility, null),
126
- broadcast: normalizeManagedBroadcastConfig(payload.broadcast),
127
- entryProfileSchema: normalizeEntryProfileSchema(payload.entryProfileSchema),
128
- interactionRules: normalizeText(payload.interactionRules, null),
129
- prohibitedRules: normalizeText(payload.prohibitedRules, null),
130
- ratingRules: normalizeText(payload.ratingRules, null),
131
- sessionTemplate: normalizeManagedSessionTemplate(payload.sessionTemplate),
94
+ participantContextField: normalizeParticipantContextFieldPayload(payload.participantContextField),
132
95
  stats: normalizeWorldStats(payload.stats),
133
96
  };
134
97
  }
@@ -137,7 +100,8 @@ function normalizeOwnedWorldSummary(payload = {}) {
137
100
  return {
138
101
  worldId: normalizeText(payload.worldId, null),
139
102
  displayName: normalizeText(payload.displayName, null),
140
- summary: normalizeText(payload.summary, null),
103
+ worldContextText: normalizeText(payload.worldContextText, null),
104
+ ownerAgentId: normalizeText(payload.ownerAgentId, null),
141
105
  enabled: normalizeOptionalBoolean(payload.enabled, null),
142
106
  status: normalizeText(payload.status, null),
143
107
  worldRole: normalizeWorldRole(payload.worldRole, null),
@@ -224,17 +188,8 @@ export async function createModeratedWorld({
224
188
  accountId = null,
225
189
  runtimeConfig = null,
226
190
  agentId = null,
227
- adminAgentIds = [],
228
- eligibility = 'active',
229
- broadcast = undefined,
230
191
  displayName = null,
231
- summary = null,
232
- description = null,
233
- entryProfileSchema = {},
234
- interactionRules = null,
235
- prohibitedRules = null,
236
- ratingRules = null,
237
- sessionTemplate = null,
192
+ worldContextText = null,
238
193
  enabled = false,
239
194
  fetchImpl,
240
195
  logger = console,
@@ -260,17 +215,8 @@ export async function createModeratedWorld({
260
215
  },
261
216
  body: JSON.stringify({
262
217
  agentId: resolvedAgentId,
263
- adminAgentIds,
264
- eligibility,
265
- ...(broadcast === undefined ? {} : { broadcast }),
266
218
  displayName,
267
- summary,
268
- description,
269
- entryProfileSchema,
270
- interactionRules,
271
- prohibitedRules,
272
- ratingRules,
273
- sessionTemplate,
219
+ worldContextText,
274
220
  enabled,
275
221
  }),
276
222
  });
@@ -86,32 +86,26 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
86
86
  'Score active online memberships by intent, location, and interests, deliver candidate summaries first, and route live contact through request_chat after review.',
87
87
  candidateSources: ['active_memberships_online'],
88
88
  },
89
- sessionTemplate: {
89
+ conversationTemplate: {
90
90
  mode: 'a2a',
91
- maxTurns: 6,
92
- turnTimeoutMs: 45_000,
93
- raiseHandPolicy: {
94
- mode: 'dual_raise_hand',
95
- summary: 'Conversation closes when both sides declare they are done asking new questions.',
96
- },
97
91
  worldRules: {
98
92
  openingText: 'You are in the dating demo world. Clarify fit quickly and stop once both sides can decide whether to continue.',
99
93
  turnMessageRules: [{ id: 'nudge-2', atTurn: 2, templateRef: 'world.turn.nudge' }],
100
94
  convergence: {
101
95
  whenRemainingTurnsLTE: 1,
102
- text: 'Focus on unresolved blockers and whether to raise hand.',
96
+ text: 'Focus on unresolved blockers and whether both sides have enough information to decide next steps.',
103
97
  },
104
98
  },
105
99
  },
106
100
  resultContract: {
107
101
  schemaId: 'dating-demo-world.result.v1',
108
102
  outputs: ['match_score', 'recommendation', 'risks', 'evidence'],
109
- successCriteria: ['both agents can summarize fit', 'raise hand state is explicit'],
103
+ successCriteria: ['both agents can summarize fit', 'next step is explicit'],
110
104
  exampleSignals: {
111
105
  intentSignals: [{ id: 'intent-1', type: 'intent_match', score: 0.8, summary: 'Stated intent aligns.' }],
112
106
  conversationSignals: [
113
- { id: 'conv-1', type: 'raise_hand', score: 0.7, summary: 'One side is ready to stop and move forward.' },
114
- { id: 'conv-2', type: 'raise_hand', score: 0.7, summary: 'The other side is also ready to stop.' },
107
+ { id: 'conv-1', type: 'next_step_ready', score: 0.7, summary: 'One side is ready to stop and move forward.' },
108
+ { id: 'conv-2', type: 'next_step_ready', score: 0.7, summary: 'The other side is also ready to stop.' },
115
109
  ],
116
110
  agentSignals: [{ id: 'agent-1', type: 'safety', risk: 0.1, summary: 'No major risk surfaced.' }],
117
111
  },
@@ -182,14 +176,8 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
182
176
  'Filter active online world members by capability overlap, deliver candidate summaries first, and let members request_chat before negotiating fit in a short session.',
183
177
  candidateSources: ['active_memberships_online'],
184
178
  },
185
- sessionTemplate: {
179
+ conversationTemplate: {
186
180
  mode: 'a2a',
187
- maxTurns: 5,
188
- turnTimeoutMs: 60_000,
189
- raiseHandPolicy: {
190
- mode: 'dual_raise_hand',
191
- summary: 'End once both agents agree the human owners should talk directly.',
192
- },
193
181
  worldRules: {
194
182
  openingText: 'Clarify scope, constraints, and whether a human handoff is justified.',
195
183
  },
@@ -200,7 +188,7 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
200
188
  successCriteria: ['scope is summarized', 'handoff recommendation is explicit'],
201
189
  exampleSignals: {
202
190
  intentSignals: [{ id: 'intent-1', type: 'intent_match', score: 0.65, summary: 'Capabilities appear relevant.' }],
203
- conversationSignals: [{ id: 'conv-1', type: 'raise_hand', score: 0.6, summary: 'Seller is ready for human handoff.' }],
191
+ conversationSignals: [{ id: 'conv-1', type: 'human_handoff_ready', score: 0.6, summary: 'Seller is ready for human handoff.' }],
204
192
  agentSignals: [{ id: 'agent-1', type: 'scope_risk', risk: 0.2, summary: 'A few requirements remain vague.' }],
205
193
  },
206
194
  },
@@ -276,14 +264,8 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
276
264
  'Use active online memberships plus target role, experience summary, and location/work mode as the first-pass scoring surface, deliver candidate summaries, and route contact through request_chat after review.',
277
265
  candidateSources: ['active_memberships_online'],
278
266
  },
279
- sessionTemplate: {
267
+ conversationTemplate: {
280
268
  mode: 'a2a',
281
- maxTurns: 6,
282
- turnTimeoutMs: 60_000,
283
- raiseHandPolicy: {
284
- mode: 'dual_raise_hand',
285
- summary: 'Close once role fit and next action are explicit.',
286
- },
287
269
  worldRules: {
288
270
  openingText: 'Focus on role fit, constraints, and whether both sides should move to a human conversation.',
289
271
  },
@@ -294,7 +276,7 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
294
276
  successCriteria: ['role fit is explicit', 'human next step is explicit'],
295
277
  exampleSignals: {
296
278
  intentSignals: [{ id: 'intent-1', type: 'role_fit', score: 0.7, summary: 'Role expectations line up.' }],
297
- conversationSignals: [{ id: 'conv-1', type: 'raise_hand', score: 0.55, summary: 'Both sides are ready to stop and proceed.' }],
279
+ conversationSignals: [{ id: 'conv-1', type: 'next_step_ready', score: 0.55, summary: 'Both sides are ready to stop and proceed.' }],
298
280
  agentSignals: [{ id: 'agent-1', type: 'timeline_risk', risk: 0.15, summary: 'Availability still needs confirmation.' }],
299
281
  },
300
282
  },
@@ -101,6 +101,16 @@ function normalizeComparableText(value) {
101
101
  return normalizeText(value, null)?.toLowerCase() || null;
102
102
  }
103
103
 
104
+ function tokenizeText(value) {
105
+ return [...new Set(
106
+ String(value || '')
107
+ .toLowerCase()
108
+ .split(/[^a-z0-9\u4e00-\u9fff]+/i)
109
+ .map((entry) => entry.trim())
110
+ .filter((entry) => entry.length >= 2),
111
+ )];
112
+ }
113
+
104
114
  function projectSummaryField(field = {}, profile = {}) {
105
115
  const normalizedValue = normalizeValue(profile[field.fieldId], field);
106
116
  if (normalizedValue == null) return null;
@@ -116,7 +126,7 @@ function projectSummaryField(field = {}, profile = {}) {
116
126
  function projectProfileSummary(world, profile = {}, agent = null) {
117
127
  return {
118
128
  displayName: normalizeText(agent?.displayName, null),
119
- headline: normalizeText(profile.headline, null),
129
+ headline: normalizeText(profile.participantContextText, normalizeText(profile.headline, null)),
120
130
  requiredFields: world.joinSchema.requiredFields
121
131
  .map((field) => projectSummaryField(field, profile))
122
132
  .filter(Boolean),
@@ -137,6 +147,21 @@ function createCompatibilitySignal({ sourceMembershipId, type, fieldIds, score,
137
147
  }
138
148
 
139
149
  function compareFieldValues(field, viewerValue, candidateValue, sourceMembershipId) {
150
+ if (field.fieldId === 'participantContextText') {
151
+ const viewerTokens = tokenizeText(viewerValue);
152
+ const candidateTokens = tokenizeText(candidateValue);
153
+ const sharedItems = viewerTokens.filter((item) => candidateTokens.includes(item));
154
+ if (sharedItems.length === 0) return null;
155
+
156
+ return createCompatibilitySignal({
157
+ sourceMembershipId,
158
+ type: 'field_overlap',
159
+ fieldIds: [field.fieldId],
160
+ score: Math.min(sharedItems.length * 0.08, 0.48),
161
+ summary: `Shared context: ${sharedItems.slice(0, 6).join(', ')}.`,
162
+ });
163
+ }
164
+
140
165
  if (field.type === 'string[]') {
141
166
  const viewerItems = normalizeComparableArray(viewerValue);
142
167
  const candidateItems = normalizeComparableArray(candidateValue);