@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
@@ -1,4 +1,5 @@
1
1
  import { WORLD_ACTIONS, WORLD_ROLES } from './world-authorization.js';
2
+ import { buildWorldContextText } from './world-text.js';
2
3
 
3
4
  function normalizeText(value, fallback = null) {
4
5
  if (value == null) return fallback;
@@ -41,6 +42,16 @@ function normalizeBroadcastReplyPolicy(value, fallback = 'zero') {
41
42
  return 'zero';
42
43
  }
43
44
 
45
+ function summarizeWorldContextText(worldContextText, fallback = null) {
46
+ const normalized = normalizeText(worldContextText, null);
47
+ if (!normalized) return fallback;
48
+ const firstLine = normalized
49
+ .split('\n')
50
+ .map((line) => line.trim())
51
+ .find(Boolean);
52
+ return firstLine || fallback;
53
+ }
54
+
44
55
  function slugify(value, fallback = 'world') {
45
56
  const normalized = normalizeText(value, fallback)
46
57
  .toLowerCase()
@@ -117,175 +128,49 @@ function normalizeWorldRole(worldRole, fallback = null) {
117
128
  return [WORLD_ROLES.OWNER, WORLD_ROLES.ADMIN, WORLD_ROLES.MEMBER].includes(normalized) ? normalized : fallback;
118
129
  }
119
130
 
120
- function normalizeFieldType(type) {
121
- const normalized = normalizeText(type, 'string');
122
- if (['string', 'string[]', 'number', 'boolean'].includes(normalized)) return normalized;
123
- throw createInvalidWorldRequestError('entryProfileSchema.fields.type', `unsupported field type: ${normalized}`);
124
- }
125
-
126
- function normalizeEntryProfileField(field = {}, index = 0) {
127
- const label = normalizeText(field.label, null);
128
- const fieldId = normalizeText(field.fieldId, label ? slugify(label, `field-${index + 1}`) : `field_${index + 1}`);
129
- if (!fieldId) {
130
- throw createInvalidWorldRequestError('entryProfileSchema.fields.fieldId');
131
- }
132
-
131
+ function buildDefaultEntryProfileField() {
133
132
  return {
134
- fieldId,
135
- label: label || fieldId,
136
- type: normalizeFieldType(field.type),
137
- required: field.required !== false,
138
- searchable: field.searchable === true,
139
- description: normalizeText(field.description, null),
140
- examples: normalizeStringList(field.examples),
133
+ fieldId: 'participantContextText',
134
+ label: 'Entry Profile',
135
+ type: 'string',
136
+ required: true,
137
+ searchable: true,
138
+ description: 'Free-form participant profile/context text used for world join, search, and candidate review.',
139
+ examples: [],
141
140
  };
142
141
  }
143
142
 
144
- function normalizeEntryProfileSchema(input = {}) {
145
- const rawFields = Array.isArray(input?.fields) ? input.fields : (Array.isArray(input) ? input : []);
146
- if (rawFields.length === 0) {
147
- throw createInvalidWorldRequestError('entryProfileSchema.fields', 'at least one profile field is required');
148
- }
149
-
150
- const fields = rawFields.map((field, index) => normalizeEntryProfileField(field, index));
151
- const fieldIds = new Set();
152
- for (const field of fields) {
153
- if (fieldIds.has(field.fieldId)) {
154
- throw createInvalidWorldRequestError('entryProfileSchema.fields.fieldId', `duplicate fieldId: ${field.fieldId}`);
155
- }
156
- fieldIds.add(field.fieldId);
157
- }
158
-
159
- const requiredFields = fields.filter((field) => field.required);
160
- if (requiredFields.length === 0) {
161
- throw createInvalidWorldRequestError('entryProfileSchema.fields.required', 'at least one required profile field is required');
162
- }
163
-
164
- const searchableFields = fields.filter((field) => field.searchable);
165
- if (searchableFields.length === 0) {
166
- throw createInvalidWorldRequestError('entryProfileSchema.fields.searchable', 'at least one searchable field is required');
167
- }
168
-
169
- return {
170
- fields,
171
- requiredFields,
172
- optionalFields: fields.filter((field) => !field.required),
173
- searchableFieldIds: searchableFields.map((field) => field.fieldId),
174
- };
175
- }
176
-
177
- function normalizeAdminAgentIds(adminAgentIds, { creatorAgentId = null, store = null } = {}) {
178
- if (adminAgentIds == null) return [];
179
- if (!Array.isArray(adminAgentIds)) {
180
- throw createInvalidWorldRequestError('adminAgentIds', 'adminAgentIds must be an array of agent ids');
181
- }
182
-
183
- const normalizedCreatorAgentId = normalizeAgentId(creatorAgentId);
184
- const uniqueAgentIds = [];
185
- const seen = new Set();
186
-
187
- for (const rawAgentId of adminAgentIds) {
188
- const agentId = normalizeAgentId(rawAgentId);
189
- if (!agentId || seen.has(agentId) || agentId === normalizedCreatorAgentId) continue;
190
- if (store && !store.getAgent(agentId)) {
191
- throw createInvalidWorldRequestError('adminAgentIds', `unknown admin agent: ${agentId}`);
192
- }
193
- seen.add(agentId);
194
- uniqueAgentIds.push(agentId);
195
- }
196
-
197
- return uniqueAgentIds;
198
- }
199
-
200
- function normalizeBroadcastConfig(broadcast, { existingBroadcast = null } = {}) {
201
- if (broadcast !== undefined && (broadcast == null || typeof broadcast !== 'object' || Array.isArray(broadcast))) {
202
- throw createInvalidWorldRequestError('broadcast', 'broadcast must be an object');
203
- }
204
-
205
- const source = broadcast === undefined ? existingBroadcast : broadcast;
206
- const normalized = source && typeof source === 'object' && !Array.isArray(source)
207
- ? source
208
- : {};
209
-
210
- return {
211
- enabled: normalized.enabled === true,
212
- audience: normalizeBroadcastAudience(
213
- normalized.audience,
214
- normalizeBroadcastAudience(existingBroadcast?.audience, 'members'),
215
- ),
216
- replyPolicy: normalizeBroadcastReplyPolicy(
217
- normalized.replyPolicy,
218
- normalizeBroadcastReplyPolicy(existingBroadcast?.replyPolicy, 'zero'),
219
- ),
220
- excludeSelf: normalized.excludeSelf === undefined
221
- ? existingBroadcast?.excludeSelf !== false
222
- : normalized.excludeSelf !== false,
223
- };
224
- }
225
-
226
- function buildSearchSchema(entryProfileSchema) {
143
+ function buildSearchSchema() {
227
144
  return {
228
145
  mode: 'profile_overlap_search',
229
- inputFieldIds: entryProfileSchema.searchableFieldIds,
146
+ inputFieldIds: ['participantContextText'],
230
147
  summary:
231
- 'Compatibility-only manual search over active online members. Candidate feed review is the canonical path before request_chat.',
148
+ 'Manual world search over active online members using participantContextText. Candidate feed review is the canonical path before request_chat.',
232
149
  onlineOnly: true,
233
150
  defaultLimit: 10,
234
151
  };
235
152
  }
236
153
 
237
- function buildMatchingStrategy(entryProfileSchema) {
154
+ function buildMatchingStrategy() {
238
155
  return {
239
156
  mode: 'profile_overlap',
240
157
  cadence: 'on_demand',
241
158
  strategySummary:
242
- `Rank world members by overlap on ${entryProfileSchema.searchableFieldIds.join(', ')}, deliver candidate summaries first, and let members request_chat after review.`,
243
- candidateSources: ['active_memberships'],
159
+ 'Rank active online world members by overlap on participantContextText, deliver candidate summaries first, and let members request_chat after review.',
160
+ candidateSources: ['active_memberships_online'],
244
161
  };
245
162
  }
246
163
 
247
- function resolveWorldMaxTurns(sessionTemplate, { existingSessionTemplate = null, required = false } = {}) {
248
- const sessionTemplateProvided = sessionTemplate !== undefined;
249
- if (sessionTemplateProvided) {
250
- if (!sessionTemplate || typeof sessionTemplate !== 'object' || Array.isArray(sessionTemplate)) {
251
- throw createInvalidWorldRequestError(
252
- 'sessionTemplate.maxTurns',
253
- 'sessionTemplate.maxTurns is required',
254
- );
255
- }
256
-
257
- const explicitMaxTurns = normalizePositiveInteger(sessionTemplate.maxTurns, null);
258
- if (explicitMaxTurns == null) {
259
- throw createInvalidWorldRequestError(
260
- 'sessionTemplate.maxTurns',
261
- 'sessionTemplate.maxTurns must be a positive integer',
262
- );
263
- }
264
- return explicitMaxTurns;
265
- }
266
-
267
- const existingMaxTurns = normalizePositiveInteger(existingSessionTemplate?.maxTurns, null);
268
- if (existingMaxTurns != null) return existingMaxTurns;
269
- if (required) throw createInvalidWorldRequestError('sessionTemplate.maxTurns');
270
- return null;
271
- }
272
-
273
- function buildSessionTemplate(interactionRules, prohibitedRules, { maxTurns, existingSessionTemplate = null } = {}) {
164
+ function buildConversationTemplate(interactionRules, prohibitedRules, { existingConversationTemplate = null } = {}) {
274
165
  return {
275
- mode: normalizeText(existingSessionTemplate?.mode, 'a2a'),
276
- maxTurns,
277
- turnTimeoutMs: normalizePositiveInteger(existingSessionTemplate?.turnTimeoutMs, 60_000),
278
- raiseHandPolicy: {
279
- mode: normalizeText(existingSessionTemplate?.raiseHandPolicy?.mode, 'dual_raise_hand'),
280
- summary: prohibitedRules || 'Both agents should stop once neither side has useful new questions.',
281
- },
166
+ mode: normalizeText(existingConversationTemplate?.mode, 'a2a'),
282
167
  worldRules: {
283
168
  openingText: interactionRules,
284
- turnMessageRules: Array.isArray(existingSessionTemplate?.worldRules?.turnMessageRules)
285
- ? existingSessionTemplate.worldRules.turnMessageRules
169
+ turnMessageRules: Array.isArray(existingConversationTemplate?.worldRules?.turnMessageRules)
170
+ ? existingConversationTemplate.worldRules.turnMessageRules
286
171
  : [],
287
- convergence: existingSessionTemplate?.worldRules?.convergence || {},
288
- stateChangeMessages: existingSessionTemplate?.worldRules?.stateChangeMessages || {},
172
+ convergence: existingConversationTemplate?.worldRules?.convergence || {},
173
+ stateChangeMessages: existingConversationTemplate?.worldRules?.stateChangeMessages || {},
289
174
  },
290
175
  };
291
176
  }
@@ -306,31 +191,20 @@ function buildResultContract(worldId, ratingRules) {
306
191
  function buildWorldRecord({
307
192
  worldId,
308
193
  creatorAgentId,
309
- adminAgentIds = [],
310
- eligibility = 'active',
311
- broadcast = undefined,
312
194
  displayName,
313
195
  summary,
314
196
  description,
315
197
  interactionRules,
316
198
  prohibitedRules,
317
199
  ratingRules,
318
- entryProfileSchema,
200
+ worldContextText = null,
319
201
  enabled = false,
320
202
  status = null,
321
203
  schemaVersion = 1,
322
204
  existingMetrics = null,
323
- sessionTemplate = undefined,
324
- existingSessionTemplate = null,
325
- existingBroadcast = null,
326
205
  } = {}) {
327
206
  const resolvedStatus = status || (enabled ? 'enabled' : 'draft');
328
- const resolvedMaxTurns = resolveWorldMaxTurns(sessionTemplate, {
329
- existingSessionTemplate,
330
- required: existingSessionTemplate == null,
331
- });
332
- const resolvedEligibility = normalizeWorldEligibility(eligibility, 'active');
333
- const resolvedBroadcast = normalizeBroadcastConfig(broadcast, { existingBroadcast });
207
+ const participantContextField = buildDefaultEntryProfileField();
334
208
 
335
209
  return {
336
210
  worldId,
@@ -344,17 +218,25 @@ function buildWorldRecord({
344
218
  interactionRules,
345
219
  prohibitedRules,
346
220
  ratingRules,
221
+ worldContextText: buildWorldContextText({
222
+ worldId,
223
+ displayName,
224
+ summary,
225
+ worldContextText,
226
+ interactionRules,
227
+ prohibitedRules,
228
+ ratingRules,
229
+ }),
347
230
  roles: [],
348
231
  joinSchema: {
349
- requiredFields: entryProfileSchema.requiredFields,
350
- optionalFields: entryProfileSchema.optionalFields,
232
+ requiredFields: [participantContextField],
233
+ optionalFields: [],
351
234
  hints: [],
352
235
  },
353
- searchSchema: buildSearchSchema(entryProfileSchema),
354
- matching: buildMatchingStrategy(entryProfileSchema),
355
- sessionTemplate: buildSessionTemplate(interactionRules, prohibitedRules, {
356
- maxTurns: resolvedMaxTurns,
357
- existingSessionTemplate,
236
+ searchSchema: buildSearchSchema(),
237
+ matching: buildMatchingStrategy(),
238
+ conversationTemplate: buildConversationTemplate(interactionRules, prohibitedRules, {
239
+ existingConversationTemplate,
358
240
  }),
359
241
  resultContract: buildResultContract(worldId, ratingRules),
360
242
  meta: {
@@ -362,9 +244,14 @@ function buildWorldRecord({
362
244
  persistence: 'store',
363
245
  },
364
246
  creatorAgentId,
365
- adminAgentIds,
366
- eligibility: resolvedEligibility,
367
- broadcast: resolvedBroadcast,
247
+ adminAgentIds: [],
248
+ eligibility: 'active',
249
+ broadcast: {
250
+ enabled: false,
251
+ audience: 'members',
252
+ replyPolicy: 'zero',
253
+ excludeSelf: true,
254
+ },
368
255
  status: resolvedStatus,
369
256
  enabled,
370
257
  schemaVersion,
@@ -374,21 +261,13 @@ function buildWorldRecord({
374
261
  };
375
262
  }
376
263
 
377
- function projectEntryProfileSchema(world = {}) {
264
+ function projectParticipantContextField(world = {}) {
378
265
  const requiredFields = Array.isArray(world.joinSchema?.requiredFields) ? world.joinSchema.requiredFields : [];
379
- const optionalFields = Array.isArray(world.joinSchema?.optionalFields) ? world.joinSchema.optionalFields : [];
380
- const searchableFieldIds = new Set(Array.isArray(world.searchSchema?.inputFieldIds) ? world.searchSchema.inputFieldIds : []);
381
-
266
+ const field = requiredFields[0] || buildDefaultEntryProfileField();
382
267
  return {
383
- fields: [...requiredFields, ...optionalFields].map((field) => ({
384
- fieldId: field.fieldId,
385
- label: field.label,
386
- type: field.type,
387
- required: field.required === true,
388
- searchable: searchableFieldIds.has(field.fieldId),
389
- description: field.description || null,
390
- examples: normalizeStringList(field.examples),
391
- })),
268
+ fieldId: field.fieldId,
269
+ label: field.label,
270
+ description: field.description || null,
392
271
  };
393
272
  }
394
273
 
@@ -406,7 +285,8 @@ function projectManagedWorldSummary(store, world = {}, { worldRole = null } = {}
406
285
  return {
407
286
  worldId: world.worldId,
408
287
  displayName: world.displayName,
409
- summary: world.summary,
288
+ worldContextText: world.worldContextText || '',
289
+ ownerAgentId: world.creatorAgentId || null,
410
290
  enabled: world.enabled === true,
411
291
  status: world.status || 'draft',
412
292
  worldRole: normalizeWorldRole(worldRole, null),
@@ -420,24 +300,15 @@ function projectManagedWorld(store, world = {}, { worldRole = null } = {}) {
420
300
  return {
421
301
  worldId: world.worldId,
422
302
  displayName: world.displayName,
423
- summary: world.summary,
424
- description: world.description,
303
+ worldContextText: world.worldContextText || '',
304
+ ownerAgentId: world.creatorAgentId || null,
425
305
  enabled: world.enabled === true,
426
306
  status: world.status || 'draft',
427
307
  worldRole: normalizeWorldRole(worldRole, null),
428
308
  schemaVersion: Number(world.schemaVersion || 1),
429
309
  createdAt: world.createdAt || null,
430
310
  updatedAt: world.updatedAt || null,
431
- adminAgentIds: Array.isArray(world.adminAgentIds) ? world.adminAgentIds : [],
432
- eligibility: normalizeWorldEligibility(world.eligibility, 'active'),
433
- broadcast: normalizeBroadcastConfig(world.broadcast, {
434
- existingBroadcast: world.broadcast || null,
435
- }),
436
- entryProfileSchema: projectEntryProfileSchema(world),
437
- interactionRules: world.interactionRules || '',
438
- prohibitedRules: world.prohibitedRules || '',
439
- ratingRules: world.ratingRules || '',
440
- sessionTemplate: world.sessionTemplate || null,
311
+ participantContextField: projectParticipantContextField(world),
441
312
  stats: projectWorldStats(store, world),
442
313
  };
443
314
  }
@@ -499,60 +370,35 @@ export function createWorldAdminService({ worldService, worldAuthorizationServic
499
370
 
500
371
  function hasManageWorldChanges(changes = null) {
501
372
  if (!changes || typeof changes !== 'object' || Array.isArray(changes)) return false;
502
- return Object.keys(changes).some((fieldId) => fieldId !== 'adminAgentIds');
373
+ return Object.keys(changes).length > 0;
503
374
  }
504
375
 
505
376
  return {
506
377
  async createWorld({
507
378
  ownerAgentId,
508
379
  creatorAgentId,
509
- adminAgentIds = [],
510
- eligibility = 'active',
511
- broadcast = undefined,
512
380
  displayName,
513
- summary,
514
- description,
515
- entryProfileSchema,
516
- interactionRules,
517
- prohibitedRules,
518
- ratingRules,
519
- sessionTemplate,
381
+ worldContextText,
520
382
  enabled = false,
521
383
  } = {}) {
522
384
  const storeBacked = assertStore();
523
385
  const resolvedOwnerAgentId = assertActorAgent(ownerAgentId || creatorAgentId);
524
386
  const resolvedDisplayName = normalizeText(displayName, null);
525
387
  if (!resolvedDisplayName) throw createInvalidWorldRequestError('displayName');
526
- const resolvedSummary = normalizeText(summary, null);
527
- if (!resolvedSummary) throw createInvalidWorldRequestError('summary');
528
- const resolvedDescription = normalizeText(description, resolvedSummary);
529
- const resolvedInteractionRules = normalizeText(interactionRules, null);
530
- if (!resolvedInteractionRules) throw createInvalidWorldRequestError('interactionRules');
531
- const resolvedProhibitedRules = normalizeText(prohibitedRules, null);
532
- if (!resolvedProhibitedRules) throw createInvalidWorldRequestError('prohibitedRules');
533
- const resolvedRatingRules = normalizeText(ratingRules, null);
534
- if (!resolvedRatingRules) throw createInvalidWorldRequestError('ratingRules');
535
-
536
- const normalizedEntryProfileSchema = normalizeEntryProfileSchema(entryProfileSchema);
537
- const normalizedAdminAgentIds = normalizeAdminAgentIds(adminAgentIds, {
538
- creatorAgentId: resolvedOwnerAgentId,
539
- store: storeBacked,
540
- });
388
+ const resolvedWorldContextText = normalizeText(worldContextText, null);
389
+ if (!resolvedWorldContextText) throw createInvalidWorldRequestError('worldContextText');
390
+
541
391
  const worldId = buildWorldId(resolvedDisplayName, worldService.listWorldIds());
542
392
  const worldRecord = buildWorldRecord({
543
393
  worldId,
544
394
  creatorAgentId: resolvedOwnerAgentId,
545
- adminAgentIds: normalizedAdminAgentIds,
546
- eligibility,
547
- broadcast,
548
395
  displayName: resolvedDisplayName,
549
- summary: resolvedSummary,
550
- description: resolvedDescription,
551
- interactionRules: resolvedInteractionRules,
552
- prohibitedRules: resolvedProhibitedRules,
553
- ratingRules: resolvedRatingRules,
554
- entryProfileSchema: normalizedEntryProfileSchema,
555
- sessionTemplate,
396
+ summary: summarizeWorldContextText(resolvedWorldContextText, resolvedDisplayName),
397
+ description: resolvedWorldContextText,
398
+ interactionRules: null,
399
+ prohibitedRules: null,
400
+ ratingRules: null,
401
+ worldContextText: resolvedWorldContextText,
556
402
  enabled: normalizeBoolean(enabled, false),
557
403
  });
558
404
 
@@ -604,13 +450,6 @@ export function createWorldAdminService({ worldService, worldAuthorizationServic
604
450
  action: WORLD_ACTIONS.MANAGE_WORLD,
605
451
  });
606
452
  }
607
- if (hasChanges && Object.prototype.hasOwnProperty.call(changes, 'adminAgentIds')) {
608
- authorization = requireWorldAction({
609
- worldId,
610
- actorAgentId: resolvedActorAgentId,
611
- action: WORLD_ACTIONS.MANAGE_WORLD_ROLES,
612
- });
613
- }
614
453
  if (enabled != null) {
615
454
  authorization = requireWorldAction({
616
455
  worldId,
@@ -631,49 +470,19 @@ export function createWorldAdminService({ worldService, worldAuthorizationServic
631
470
 
632
471
  if (hasChanges) {
633
472
  const nextDisplayName = normalizeText(changes.displayName, existingWorld.displayName);
634
- const nextSummary = normalizeText(changes.summary, existingWorld.summary);
635
- const nextDescription = normalizeText(changes.description, existingWorld.description);
636
- const nextInteractionRules = normalizeText(changes.interactionRules, existingWorld.interactionRules);
637
- const nextProhibitedRules = normalizeText(changes.prohibitedRules, existingWorld.prohibitedRules);
638
- const nextRatingRules = normalizeText(changes.ratingRules, existingWorld.ratingRules);
639
- const nextSessionTemplate = Object.prototype.hasOwnProperty.call(changes, 'sessionTemplate')
640
- ? changes.sessionTemplate
641
- : undefined;
642
- const nextAdminAgentIds = Object.prototype.hasOwnProperty.call(changes, 'adminAgentIds')
643
- ? normalizeAdminAgentIds(changes.adminAgentIds, {
644
- creatorAgentId: existingWorld.creatorAgentId,
645
- store: storeBacked,
646
- })
647
- : (Array.isArray(existingWorld.adminAgentIds) ? existingWorld.adminAgentIds : []);
648
- const nextEligibility = Object.prototype.hasOwnProperty.call(changes, 'eligibility')
649
- ? normalizeWorldEligibility(changes.eligibility, existingWorld.eligibility || 'active')
650
- : normalizeWorldEligibility(existingWorld.eligibility, 'active');
651
- const nextBroadcast = Object.prototype.hasOwnProperty.call(changes, 'broadcast')
652
- ? changes.broadcast
653
- : undefined;
654
- let entryProfileSchema = null;
655
-
656
- if (Object.prototype.hasOwnProperty.call(changes, 'entryProfileSchema')) {
657
- entryProfileSchema = normalizeEntryProfileSchema(changes.entryProfileSchema);
658
- nextSchemaVersion += 1;
659
- }
660
-
473
+ const nextWorldContextText = Object.prototype.hasOwnProperty.call(changes, 'worldContextText')
474
+ ? normalizeText(changes.worldContextText, null)
475
+ : existingWorld.worldContextText;
661
476
  nextRecord = buildWorldRecord({
662
477
  worldId: existingWorld.worldId,
663
478
  creatorAgentId: existingWorld.creatorAgentId,
664
- adminAgentIds: nextAdminAgentIds,
665
- eligibility: nextEligibility,
666
- broadcast: nextBroadcast,
667
479
  displayName: nextDisplayName,
668
- summary: nextSummary,
669
- description: nextDescription,
670
- interactionRules: nextInteractionRules,
671
- prohibitedRules: nextProhibitedRules,
672
- ratingRules: nextRatingRules,
673
- entryProfileSchema: entryProfileSchema || normalizeEntryProfileSchema(projectEntryProfileSchema(existingWorld)),
674
- sessionTemplate: nextSessionTemplate,
675
- existingSessionTemplate: existingWorld.sessionTemplate || null,
676
- existingBroadcast: existingWorld.broadcast || null,
480
+ summary: summarizeWorldContextText(nextWorldContextText, nextDisplayName),
481
+ description: nextWorldContextText,
482
+ interactionRules: null,
483
+ prohibitedRules: null,
484
+ ratingRules: null,
485
+ worldContextText: nextWorldContextText,
677
486
  enabled: enabled == null ? existingWorld.enabled === true : normalizeBoolean(enabled, false),
678
487
  status: enabled == null
679
488
  ? existingWorld.status
@@ -6,7 +6,6 @@ function normalizeText(value, fallback = null) {
6
6
 
7
7
  export const WORLD_ROLES = Object.freeze({
8
8
  OWNER: 'owner',
9
- ADMIN: 'admin',
10
9
  MEMBER: 'member',
11
10
  NONE: 'none',
12
11
  });
@@ -24,7 +23,6 @@ export const WORLD_ACTIONS = Object.freeze({
24
23
 
25
24
  function resolveWorldRole({ isOwner = false, isAdmin = false, isMember = false } = {}) {
26
25
  if (isOwner) return WORLD_ROLES.OWNER;
27
- if (isAdmin) return WORLD_ROLES.ADMIN;
28
26
  if (isMember) return WORLD_ROLES.MEMBER;
29
27
  return WORLD_ROLES.NONE;
30
28
  }
@@ -34,12 +32,12 @@ function resolveActionRequirement(action) {
34
32
  case WORLD_ACTIONS.VIEW_MANAGEMENT:
35
33
  case WORLD_ACTIONS.MANAGE_WORLD:
36
34
  case WORLD_ACTIONS.BROADCAST:
35
+ case WORLD_ACTIONS.CHANGE_ENABLED_STATE:
37
36
  return {
38
- allowedRoles: [WORLD_ROLES.OWNER, WORLD_ROLES.ADMIN],
39
- reason: 'management_role_required',
37
+ allowedRoles: [WORLD_ROLES.OWNER],
38
+ reason: 'owner_role_required',
40
39
  };
41
40
  case WORLD_ACTIONS.MANAGE_WORLD_ROLES:
42
- case WORLD_ACTIONS.CHANGE_ENABLED_STATE:
43
41
  return {
44
42
  allowedRoles: [WORLD_ROLES.OWNER],
45
43
  reason: 'owner_role_required',
@@ -1,7 +1,6 @@
1
1
  import { authenticateAppTokenRequest, resolveAuthenticatedAgentId } from '../../lib/http-auth.js';
2
2
  import {
3
3
  buildCandidateDeliverySummary,
4
- buildRequiredFieldExplanation,
5
4
  buildResolvedWorldJoinOrchestration,
6
5
  buildWorldSelectionPrompt,
7
6
  } from '../contracts/world-orchestration.js';
@@ -103,7 +102,7 @@ export function registerWorldRoutes(
103
102
  searchService,
104
103
  worldBroadcastService,
105
104
  worldAdminService,
106
- sessionOrchestrator,
105
+ worldConversationOrchestrator,
107
106
  },
108
107
  ) {
109
108
  function resolveAgentIdentity(req, res, { providedAgentId = null, fieldName = 'agentId', required = true } = {}) {
@@ -175,17 +174,8 @@ export function registerWorldRoutes(
175
174
  try {
176
175
  const result = await worldAdminService.createWorld({
177
176
  ownerAgentId,
178
- adminAgentIds: req.body?.adminAgentIds,
179
- eligibility: req.body?.eligibility,
180
- broadcast: req.body?.broadcast,
181
177
  displayName: req.body?.displayName,
182
- summary: req.body?.summary,
183
- description: req.body?.description,
184
- entryProfileSchema: req.body?.entryProfileSchema,
185
- interactionRules: req.body?.interactionRules,
186
- prohibitedRules: req.body?.prohibitedRules,
187
- ratingRules: req.body?.ratingRules,
188
- sessionTemplate: req.body?.sessionTemplate,
178
+ worldContextText: req.body?.worldContextText,
189
179
  enabled: req.body?.enabled,
190
180
  });
191
181
  res.status(201).json(result);
@@ -197,12 +187,7 @@ export function registerWorldRoutes(
197
187
  app.get('/v1/worlds/:worldId', (req, res) => {
198
188
  try {
199
189
  const detail = worldService.describeWorldDetail(req.params.worldId);
200
- const world = detail.world;
201
- res.json({
202
- ...detail,
203
- matching: matchmakingService.describeStrategy(world.worldId),
204
- requiredFieldExplanation: buildRequiredFieldExplanation(detail),
205
- });
190
+ res.json(detail);
206
191
  } catch (error) {
207
192
  sendWorldError(res, error);
208
193
  }
@@ -269,19 +254,6 @@ export function registerWorldRoutes(
269
254
  }
270
255
  });
271
256
 
272
- app.post('/v1/worlds/:worldId/join-check', (req, res) => {
273
- try {
274
- const result = membershipService.evaluateJoin({
275
- worldId: req.params.worldId,
276
- profile: req.body?.profile,
277
- maxFieldsPerStep: req.body?.maxFieldsPerStep,
278
- });
279
- res.status(result.accepted ? 200 : 422).json(result);
280
- } catch (error) {
281
- sendWorldError(res, error);
282
- }
283
- });
284
-
285
257
  app.post('/v1/worlds/:worldId/join', async (req, res) => {
286
258
  const agentId = resolveAgentIdentity(req, res, {
287
259
  providedAgentId: req.body?.agentId,
@@ -292,9 +264,7 @@ export function registerWorldRoutes(
292
264
  const result = await membershipService.joinWorld({
293
265
  worldId: req.params.worldId,
294
266
  agentId,
295
- profile: req.body?.profile,
296
- profileSnapshot: req.body?.profileSnapshot,
297
- maxFieldsPerStep: req.body?.maxFieldsPerStep,
267
+ participantContextText: req.body?.participantContextText,
298
268
  });
299
269
  const worldDetail = worldService.describeWorldDetail(req.params.worldId);
300
270
  const candidateFeed = matchmakingService.listCandidateFeed({
@@ -357,7 +327,7 @@ export function registerWorldRoutes(
357
327
  const result = await membershipService.createMembership({
358
328
  worldId: req.params.worldId,
359
329
  agentId,
360
- profileSnapshot: req.body?.profileSnapshot,
330
+ participantContextText: req.body?.participantContextText,
361
331
  });
362
332
  res.status(result.created ? 201 : 200).json(result.membership);
363
333
  } catch (error) {
@@ -365,11 +335,11 @@ export function registerWorldRoutes(
365
335
  }
366
336
  });
367
337
 
368
- app.post('/v1/worlds/:worldId/session-preview', (req, res) => {
338
+ app.post('/v1/worlds/:worldId/conversation-preview', (req, res) => {
369
339
  try {
370
- const result = sessionOrchestrator.previewSession({
340
+ const result = worldConversationOrchestrator.previewConversation({
371
341
  worldId: req.params.worldId,
372
- sessionId: req.body?.sessionId,
342
+ conversationKey: req.body?.conversationKey,
373
343
  });
374
344
  res.json(result);
375
345
  } catch (error) {
@@ -3,7 +3,7 @@ import {
3
3
  projectWorldCard,
4
4
  projectWorldDetail,
5
5
  projectJoinPlan,
6
- projectSessionStartupContext,
6
+ projectConversationWorldContext,
7
7
  } from '../contracts/world-manifest.js';
8
8
  import { DEFAULT_WORLD_MANIFESTS } from '../catalog/default-world-catalog.js';
9
9
 
@@ -75,8 +75,8 @@ export function createWorldService({ worldCatalog = DEFAULT_WORLD_MANIFESTS, sto
75
75
  buildJoinPlan(worldId) {
76
76
  return projectJoinPlan(this.requireWorld(worldId));
77
77
  },
78
- describeSessionStartupContext(worldId) {
79
- return projectSessionStartupContext(this.requireWorld(worldId));
78
+ describeConversationWorldContext(worldId) {
79
+ return projectConversationWorldContext(this.requireWorld(worldId));
80
80
  },
81
81
  describeCatalog() {
82
82
  return {