@xfxstudio/claworld 2026.4.22-testing.7 → 2026.4.27-testing.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -125,14 +125,6 @@ function projectToolAction(action = null) {
125
125
  payloadTemplate: { ...payloadTemplate, action: 'get_world' },
126
126
  };
127
127
  }
128
- if (tool === 'claworld_search_world_members') {
129
- return {
130
- tool: 'claworld_search',
131
- summary: normalizeText(action.summary, null),
132
- payload: { ...payload, scope: 'world_members' },
133
- payloadTemplate: { ...payloadTemplate, scope: 'world_members' },
134
- };
135
- }
136
128
  return {
137
129
  tool,
138
130
  summary: normalizeText(action.summary, null),
@@ -201,55 +193,6 @@ function projectRequestChatAction(
201
193
  };
202
194
  }
203
195
 
204
- function projectToolCandidateDeliverySummary(
205
- candidateDelivery = {},
206
- {
207
- accountId = null,
208
- requestToolName = 'claworld_manage_conversations',
209
- } = {},
210
- ) {
211
- if (!candidateDelivery || typeof candidateDelivery !== 'object' || Array.isArray(candidateDelivery)) return null;
212
-
213
- const candidateSummaries = Array.isArray(candidateDelivery.candidateSummaries)
214
- ? candidateDelivery.candidateSummaries.map((summary) => ({
215
- candidateId: normalizeText(summary.candidateId, null),
216
- sourceMembershipId: normalizeText(summary.sourceMembershipId, null),
217
- displayName: normalizeText(summary.displayName, null),
218
- worldRole: projectWorldRole(summary.worldRole, null),
219
- headline: normalizeText(summary.headline, null),
220
- online: summary.online === true,
221
- rank: normalizeOptionalInteger(summary.rank, null),
222
- score: normalizeOptionalInteger(summary.score, null),
223
- agentCode: normalizeText(summary.agentCode, summary.requestChat?.agentCode || null)?.toUpperCase() || null,
224
- requestChat: projectRequestChatPayload(summary.requestChat, {
225
- accountId,
226
- requestToolName,
227
- }),
228
- requiredFieldSummary: normalizeStringList(summary.requiredFieldSummary),
229
- optionalFieldSummary: normalizeStringList(summary.optionalFieldSummary),
230
- compatibilitySummary: normalizeStringList(summary.compatibilitySummary),
231
- deliveryReasonSummary: normalizeText(summary.deliveryReasonSummary, null),
232
- expiresAt: normalizeText(summary.expiresAt, null),
233
- summary: normalizeText(summary.summary, null),
234
- }))
235
- : [];
236
-
237
- return {
238
- status: normalizeText(candidateDelivery.status, null),
239
- worldId: normalizeText(candidateDelivery.worldId, null),
240
- deliveredCandidateCount: normalizeInteger(candidateDelivery.deliveredCandidateCount, candidateSummaries.length),
241
- totalCandidateCount: normalizeInteger(candidateDelivery.totalCandidateCount, candidateSummaries.length),
242
- remainingCandidateCount: normalizeInteger(candidateDelivery.remainingCandidateCount, 0),
243
- nextAction: normalizeText(candidateDelivery.nextAction, null),
244
- requestChatAction: projectRequestChatAction(candidateDelivery.requestChatAction, {
245
- accountId,
246
- requestToolName,
247
- }),
248
- candidateSummaries,
249
- orchestration: projectOrchestration(candidateDelivery.orchestration),
250
- };
251
- }
252
-
253
196
  export function projectToolWorldList(worldDirectory = {}) {
254
197
  const worlds = Array.isArray(worldDirectory.items)
255
198
  ? worldDirectory.items.map((world) => ({
@@ -359,23 +302,7 @@ export function projectToolWorldDetail(worldDetail = {}, { accountId = null } =
359
302
  };
360
303
  }
361
304
 
362
- function projectToolCandidateSummary(summary = {}, index = 0) {
363
- return {
364
- candidateId: normalizeText(summary.candidateId, `candidate_${index + 1}`),
365
- displayName: normalizeText(summary.displayName, `Candidate ${index + 1}`),
366
- agentCode: normalizeText(summary.agentCode, null)?.toUpperCase() || null,
367
- worldRole: projectWorldRole(summary.worldRole, null),
368
- headline: normalizeText(summary.headline, null),
369
- online: summary.online === true,
370
- rank: normalizeInteger(summary.rank, 0) || null,
371
- score: normalizeInteger(summary.score, 0) || null,
372
- summary: normalizeText(summary.summary, null),
373
- expiresAt: normalizeText(summary.expiresAt, null),
374
- worldFeedbackSummary: projectWorldFeedbackSummary(summary.worldFeedbackSummary),
375
- };
376
- }
377
-
378
- function projectCandidateProfileSummary(summary = {}) {
305
+ function projectMemberProfileSummary(summary = {}) {
379
306
  return {
380
307
  displayName: normalizeText(summary.displayName, null),
381
308
  headline: normalizeText(summary.headline, null),
@@ -396,123 +323,6 @@ function projectCandidateProfileSummary(summary = {}) {
396
323
  };
397
324
  }
398
325
 
399
- function resolveCandidateProjectionPayload(payload = {}) {
400
- if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
401
- return {
402
- worldId: null,
403
- nextAction: null,
404
- candidateFeed: null,
405
- candidateDelivery: null,
406
- requestChatAction: null,
407
- };
408
- }
409
-
410
- const candidateFeed = payload.candidateFeed && typeof payload.candidateFeed === 'object' && !Array.isArray(payload.candidateFeed)
411
- ? payload.candidateFeed
412
- : Array.isArray(payload.candidates)
413
- ? payload
414
- : null;
415
- const candidateDelivery = payload.candidateDelivery && typeof payload.candidateDelivery === 'object' && !Array.isArray(payload.candidateDelivery)
416
- ? payload.candidateDelivery
417
- : candidateFeed?.candidateDelivery && typeof candidateFeed.candidateDelivery === 'object' && !Array.isArray(candidateFeed.candidateDelivery)
418
- ? candidateFeed.candidateDelivery
419
- : null;
420
- const candidateModelRequestChatAction = candidateFeed?.candidateModel && typeof candidateFeed.candidateModel === 'object' && !Array.isArray(candidateFeed.candidateModel)
421
- ? candidateFeed.candidateModel.requestChatAction
422
- : null;
423
-
424
- return {
425
- worldId: normalizeText(payload.worldId, normalizeText(candidateFeed?.worldId, normalizeText(candidateDelivery?.worldId, null))),
426
- nextAction: normalizeText(payload.nextAction, normalizeText(candidateFeed?.nextAction, normalizeText(candidateDelivery?.nextAction, null))),
427
- candidateFeed,
428
- candidateDelivery,
429
- requestChatAction: payload.requestChatAction && typeof payload.requestChatAction === 'object' && !Array.isArray(payload.requestChatAction)
430
- ? payload.requestChatAction
431
- : candidateDelivery?.requestChatAction && typeof candidateDelivery.requestChatAction === 'object' && !Array.isArray(candidateDelivery.requestChatAction)
432
- ? candidateDelivery.requestChatAction
433
- : candidateModelRequestChatAction && typeof candidateModelRequestChatAction === 'object' && !Array.isArray(candidateModelRequestChatAction)
434
- ? candidateModelRequestChatAction
435
- : null,
436
- };
437
- }
438
-
439
- function projectToolCandidateFeed(payload = {}) {
440
- const { candidateFeed, candidateDelivery } = resolveCandidateProjectionPayload(payload);
441
- const candidateSummaries = Array.isArray(candidateDelivery?.candidateSummaries)
442
- ? candidateDelivery.candidateSummaries.map((summary, index) => projectToolCandidateSummary(summary, index))
443
- : Array.isArray(candidateFeed?.candidates)
444
- ? candidateFeed.candidates.map((candidate, index) => projectToolCandidateSummary({
445
- candidateId: candidate.candidateId,
446
- displayName: candidate.profileSummary?.displayName,
447
- agentCode: normalizeText(candidate.agentCode, candidate.requestChat?.agentCode || null),
448
- worldRole: candidate.worldRole,
449
- headline: candidate.profileSummary?.headline,
450
- online: candidate.online === true,
451
- rank: candidate.rank,
452
- score: candidate.score,
453
- summary: normalizeText(candidate.deliveryReason?.summary, null),
454
- expiresAt: candidate.expiresAt,
455
- worldFeedbackSummary: candidate.worldFeedbackSummary,
456
- }, index))
457
- : [];
458
-
459
- return {
460
- status: normalizeText(
461
- candidateDelivery?.status,
462
- normalizeText(candidateFeed?.status, candidateSummaries.length > 0 ? 'candidate_summary_ready' : 'candidate_summary_pending'),
463
- ),
464
- nextAction: normalizeText(
465
- candidateDelivery?.nextAction,
466
- normalizeText(candidateFeed?.nextAction, candidateSummaries.length > 0 ? 'review_candidates_then_request_chat' : 'wait_for_more_candidates'),
467
- ),
468
- deliveredCandidateCount: normalizeInteger(candidateDelivery?.deliveredCandidateCount, candidateSummaries.length),
469
- totalCandidateCount: normalizeInteger(
470
- candidateDelivery?.totalCandidateCount,
471
- normalizeInteger(candidateFeed?.totalCandidates, candidateSummaries.length),
472
- ),
473
- remainingCandidateCount: normalizeInteger(candidateDelivery?.remainingCandidateCount, 0),
474
- candidates: candidateSummaries,
475
- };
476
- }
477
-
478
- function projectToolCandidateFlowResponse(payload = {}, { accountId = null } = {}) {
479
- const {
480
- worldId,
481
- nextAction,
482
- candidateFeed,
483
- candidateDelivery,
484
- requestChatAction,
485
- } = resolveCandidateProjectionPayload(payload);
486
- const projectedFeed = projectToolCandidateFeed({ candidateFeed, candidateDelivery });
487
- const projectedDelivery = projectToolCandidateDeliverySummary(candidateDelivery, { accountId });
488
- const projectedRequestChatAction = projectRequestChatAction(requestChatAction, { accountId });
489
-
490
- return {
491
- worldId: normalizeText(worldId, normalizeText(projectedDelivery?.worldId, null)),
492
- nextAction: normalizeText(nextAction, normalizeText(projectedFeed?.nextAction, normalizeText(projectedDelivery?.nextAction, null))),
493
- candidateFeed: projectedFeed,
494
- requestChatTool: 'claworld_manage_conversations',
495
- candidateDelivery: projectedDelivery,
496
- requestChatAction: projectedRequestChatAction,
497
- };
498
- }
499
-
500
- export function projectToolCandidateFeedResponse(candidateFeedPayload = {}, { accountId = null } = {}) {
501
- const candidateFlow = projectToolCandidateFlowResponse(candidateFeedPayload, { accountId });
502
-
503
- return {
504
- status: normalizeText(candidateFeedPayload.status, normalizeText(candidateFlow.candidateFeed?.status, 'no_candidates_ready')),
505
- worldId: candidateFlow.worldId,
506
- accountId: normalizeText(accountId, null),
507
- nextAction: candidateFlow.nextAction,
508
- candidateFeed: candidateFlow.candidateFeed,
509
- requestChatTool: candidateFlow.requestChatTool,
510
- candidateDelivery: candidateFlow.candidateDelivery,
511
- requestChatAction: candidateFlow.requestChatAction,
512
- };
513
- }
514
-
515
-
516
326
  function projectToolJoinAction(action = null, { accountId = null, requestToolName = null } = {}) {
517
327
  if (!action || typeof action !== 'object' || Array.isArray(action)) return null;
518
328
  const normalizedAccountId = normalizeText(accountId, null);
@@ -706,21 +516,22 @@ export function projectToolWorldMemberSearchResponse(payload = {}, { accountId =
706
516
  status: normalizeText(payload.status, 'no_matches'),
707
517
  worldId: normalizeText(payload.worldId, null),
708
518
  query: normalizeText(payload.query, null),
709
- sort: normalizeText(payload.sort, 'match'),
519
+ sort: normalizeText(payload.sort, 'relevance'),
710
520
  limit: normalizeInteger(payload.limit, 0),
711
521
  totalMatches: normalizeInteger(payload.totalMatches, Array.isArray(payload.items) ? payload.items.length : 0),
712
522
  nextAction: normalizeText(payload.nextAction, null),
713
523
  members: Array.isArray(payload.items)
714
524
  ? payload.items.map((item, index) => ({
715
- candidateId: normalizeText(item.membershipId, `candidate_${index + 1}`),
716
- displayName: normalizeText(item.displayName, `Candidate ${index + 1}`),
525
+ memberId: normalizeText(item.membershipId, `member_${index + 1}`),
526
+ membershipId: normalizeText(item.membershipId, null),
527
+ displayName: normalizeText(item.displayName, `Member ${index + 1}`),
717
528
  agentCode: normalizeText(item.agentCode, null)?.toUpperCase() || null,
718
529
  headline: normalizeText(item.headline, null),
719
530
  online: item.online === true,
720
531
  score: normalizeInteger(item.score, 0),
721
532
  matchedFieldIds: normalizeStringList(item.matchedFieldIds),
722
533
  reasonSummary: normalizeText(item.reasonSummary, null),
723
- profileSummary: projectCandidateProfileSummary(item.profileSummary || {}),
534
+ profileSummary: projectMemberProfileSummary(item.profileSummary || {}),
724
535
  worldFeedbackSummary: projectWorldFeedbackSummary(item.worldFeedbackSummary),
725
536
  requestChat: projectRequestChatPayload(item.requestChat, { accountId }),
726
537
  }))
@@ -17,16 +17,12 @@ export const CLAWORLD_CONVERSATION_TOOL_NAMES = Object.freeze([
17
17
  'claworld_manage_conversations',
18
18
  ]);
19
19
 
20
- export const CLAWORLD_FEEDBACK_TOOL_NAMES = Object.freeze([
21
- 'claworld_submit_feedback',
22
- ]);
23
20
 
24
21
  export const CLAWORLD_REGISTERED_TOOL_NAMES = Object.freeze([
25
22
  ...CLAWORLD_ACCOUNT_TOOL_NAMES,
26
23
  ...CLAWORLD_SEARCH_TOOL_NAMES,
27
24
  ...CLAWORLD_WORLD_TOOL_NAMES,
28
25
  ...CLAWORLD_CONVERSATION_TOOL_NAMES,
29
- ...CLAWORLD_FEEDBACK_TOOL_NAMES,
30
26
  ]);
31
27
 
32
28
  export const CLAWORLD_PUBLIC_TOOL_NAMES = Object.freeze([
@@ -34,17 +30,6 @@ export const CLAWORLD_PUBLIC_TOOL_NAMES = Object.freeze([
34
30
  ]);
35
31
 
36
32
  export const CLAWORLD_RETIRED_PUBLIC_TOOL_NAMES = Object.freeze([
37
- 'claworld_account',
38
- 'claworld_search_worlds',
39
- 'claworld_list_worlds',
40
- 'claworld_get_world_detail',
41
- 'claworld_join_world',
42
- 'claworld_search_world_members',
43
- 'claworld_get_candidate_feed',
44
- 'claworld_create_world',
45
- 'claworld_manage_world',
46
- 'claworld_request_chat',
47
- 'claworld_chat_inbox',
48
33
  ]);
49
34
 
50
35
  export const CLAWORLD_MINIMAL_OPENCLAW_TOOL_NAMES = Object.freeze([
@@ -602,7 +602,6 @@ function compactResultPayload(payload = {}) {
602
602
  'displayName',
603
603
  'chatRequestId',
604
604
  'conversationKey',
605
- 'candidateId',
606
605
  'feedbackId',
607
606
  'nextAction',
608
607
  'requiredAction',
@@ -632,7 +631,6 @@ export function buildClaworldToolMaintenanceEvent({
632
631
  worldId: params.worldId || payload.worldId,
633
632
  chatRequestId: params.chatRequestId || payload.chatRequestId,
634
633
  conversationKey: params.conversationKey || payload.conversationKey,
635
- candidateId: params.candidateId || payload.candidateId,
636
634
  agentCode: params.agentCode || payload.agentCode,
637
635
  };
638
636
  return buildClaworldMaintenanceEvent({
@@ -101,6 +101,10 @@ function normalizeManagedWorld(payload = {}) {
101
101
  enabled: normalizeOptionalBoolean(payload.enabled, null),
102
102
  status: normalizeText(payload.status, null),
103
103
  worldRole: normalizeWorldRole(payload.worldRole, null),
104
+ visibility: normalizeText(payload.visibility, 'public'),
105
+ identityMode: normalizeText(payload.identityMode, 'imaginary'),
106
+ joinPolicy: normalizeText(payload.joinPolicy, 'open'),
107
+ approvalPolicy: normalizeText(payload.approvalPolicy, 'auto'),
104
108
  schemaVersion: normalizeOptionalInteger(payload.schemaVersion, null),
105
109
  createdAt: normalizeText(payload.createdAt, null),
106
110
  updatedAt: normalizeText(payload.updatedAt, null),
@@ -133,6 +137,10 @@ function normalizeOwnedWorldSummary(payload = {}) {
133
137
  enabled: normalizeOptionalBoolean(payload.enabled, null),
134
138
  status: normalizeText(payload.status, null),
135
139
  worldRole: normalizeWorldRole(payload.worldRole, null),
140
+ visibility: normalizeText(payload.visibility, 'public'),
141
+ identityMode: normalizeText(payload.identityMode, 'imaginary'),
142
+ joinPolicy: normalizeText(payload.joinPolicy, 'open'),
143
+ approvalPolicy: normalizeText(payload.approvalPolicy, 'auto'),
136
144
  createdAt: normalizeText(payload.createdAt, null),
137
145
  updatedAt: normalizeText(payload.updatedAt, null),
138
146
  broadcast: normalizeWorldBroadcastConfig(payload.broadcast),
@@ -273,6 +281,10 @@ export async function createModeratedWorld({
273
281
  worldContextText = null,
274
282
  participantContextText = null,
275
283
  enabled = true,
284
+ visibility = null,
285
+ identityMode = null,
286
+ joinPolicy = null,
287
+ approvalPolicy = null,
276
288
  fetchImpl,
277
289
  logger = console,
278
290
  } = {}) {
@@ -300,6 +312,10 @@ export async function createModeratedWorld({
300
312
  worldContextText,
301
313
  participantContextText: normalizeText(participantContextText, null),
302
314
  enabled,
315
+ ...(normalizeText(visibility, null) ? { visibility: normalizeText(visibility, null) } : {}),
316
+ ...(normalizeText(identityMode, null) ? { identityMode: normalizeText(identityMode, null) } : {}),
317
+ ...(normalizeText(joinPolicy, null) ? { joinPolicy: normalizeText(joinPolicy, null) } : {}),
318
+ ...(normalizeText(approvalPolicy, null) ? { approvalPolicy: normalizeText(approvalPolicy, null) } : {}),
303
319
  }),
304
320
  });
305
321
 
@@ -10,12 +10,6 @@ function normalizeInteger(value, fallback = 0) {
10
10
  return Math.max(0, Math.trunc(parsed));
11
11
  }
12
12
 
13
- function normalizeNumber(value, fallback = null) {
14
- const parsed = Number(value);
15
- if (!Number.isFinite(parsed)) return fallback;
16
- return parsed;
17
- }
18
-
19
13
  function normalizeStringList(values = []) {
20
14
  if (!Array.isArray(values)) return [];
21
15
  return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
@@ -214,147 +208,6 @@ function normalizeWorldDetail(payload = {}) {
214
208
  };
215
209
  }
216
210
 
217
- function normalizeProfileSummaryField(field = {}, index = 0) {
218
- const fieldId = normalizeText(field.fieldId || field.id, `field_${index + 1}`);
219
- const value = Array.isArray(field.value)
220
- ? normalizeStringList(field.value)
221
- : normalizeText(field.value, null);
222
-
223
- if (value == null || (Array.isArray(value) && value.length === 0)) {
224
- return null;
225
- }
226
-
227
- return {
228
- fieldId,
229
- label: normalizeText(field.label, fieldId),
230
- value,
231
- };
232
- }
233
-
234
- function normalizeCandidateProfileSummary(summary = {}) {
235
- return {
236
- displayName: normalizeText(summary.displayName, null),
237
- headline: normalizeText(summary.headline, null),
238
- requiredFields: Array.isArray(summary.requiredFields)
239
- ? summary.requiredFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
240
- : [],
241
- optionalFields: Array.isArray(summary.optionalFields)
242
- ? summary.optionalFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
243
- : [],
244
- };
245
- }
246
-
247
- function normalizeCompatibilitySignal(signal = {}, index = 0) {
248
- return {
249
- signalId: normalizeText(signal.signalId, `signal_${index + 1}`),
250
- type: normalizeText(signal.type, 'world_ready'),
251
- fieldIds: normalizeStringList(signal.fieldIds),
252
- score: normalizeNumber(signal.score, 0),
253
- summary: normalizeText(signal.summary, ''),
254
- };
255
- }
256
-
257
- function normalizeDeliveryReason(reason = {}) {
258
- return {
259
- code: normalizeText(reason.code, null),
260
- matchedFieldIds: normalizeStringList(reason.matchedFieldIds),
261
- summary: normalizeText(reason.summary, ''),
262
- };
263
- }
264
-
265
- function normalizeWorldRole(worldRole, fallback = null) {
266
- const normalized = normalizeText(worldRole, fallback);
267
- return ['owner', 'member'].includes(normalized) ? normalized : fallback;
268
- }
269
-
270
- function normalizeCandidate(candidate = {}, index = 0) {
271
- const normalizedRank = normalizeNumber(candidate.rank, null);
272
- const displayName = normalizeText(
273
- candidate.displayName || candidate.profileSummary?.displayName || candidate.requestChat?.displayName,
274
- null,
275
- );
276
- const agentCode = normalizeText(
277
- candidate.agentCode || candidate.requestChat?.agentCode,
278
- null,
279
- )?.toUpperCase() || null;
280
- const requestChat = displayName && agentCode
281
- ? {
282
- worldId: normalizeText(candidate.requestChat?.worldId, normalizeText(candidate.worldId, 'unknown-world')),
283
- displayName,
284
- agentCode,
285
- }
286
- : null;
287
-
288
- return {
289
- candidateId: normalizeText(candidate.candidateId, `candidate_${index + 1}`),
290
- worldId: normalizeText(candidate.worldId, 'unknown-world'),
291
- worldRole: normalizeWorldRole(candidate.worldRole, null),
292
- sourceMembershipId: normalizeText(candidate.sourceMembershipId, null),
293
- online: candidate.online === true,
294
- displayName,
295
- agentCode,
296
- requestChat,
297
- profileSummary: normalizeCandidateProfileSummary(candidate.profileSummary),
298
- compatibilitySignals: Array.isArray(candidate.compatibilitySignals)
299
- ? candidate.compatibilitySignals.map((signal, signalIndex) => normalizeCompatibilitySignal(signal, signalIndex))
300
- : [],
301
- deliveryReason: normalizeDeliveryReason(candidate.deliveryReason),
302
- expiresAt: normalizeText(candidate.expiresAt, null),
303
- joinedAt: normalizeText(candidate.joinedAt, null),
304
- rank: normalizedRank == null ? null : Math.max(1, Math.trunc(normalizedRank)),
305
- score: normalizeNumber(candidate.score, null),
306
- };
307
- }
308
-
309
- function normalizeCandidateFeedResponse(payload = {}, { worldId = null } = {}) {
310
- const candidates = Array.isArray(payload.candidates)
311
- ? payload.candidates.map((candidate, index) => normalizeCandidate(candidate, index))
312
- : [];
313
-
314
- return {
315
- worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
316
- viewerMembershipId: normalizeText(payload.viewerMembershipId, null),
317
- generatedAt: normalizeText(payload.generatedAt, null),
318
- expiresAt: normalizeText(payload.expiresAt, null),
319
- deliveryMode: normalizeText(payload.deliveryMode, 'agent_review_before_live_session'),
320
- nextAction: normalizeText(
321
- payload.nextAction,
322
- candidates.length > 0 ? 'review_candidates_then_request_chat' : 'wait_for_more_candidates',
323
- ),
324
- candidateSource: normalizeText(payload.candidateSource, 'active_memberships_online'),
325
- candidateModel: payload.candidateModel && typeof payload.candidateModel === 'object' ? payload.candidateModel : {},
326
- strategy: payload.strategy && typeof payload.strategy === 'object' ? payload.strategy : {},
327
- limit: normalizeInteger(payload.limit, candidates.length),
328
- totalCandidates: normalizeInteger(payload.totalCandidates, candidates.length),
329
- status: normalizeText(payload.status, candidates.length > 0 ? 'feed_ready' : 'no_candidates_ready'),
330
- candidates,
331
- };
332
- }
333
-
334
- function summarizeProfileValue(value) {
335
- if (Array.isArray(value)) return joinAsNaturalLanguage(value.map((entry) => String(entry).trim()).filter(Boolean));
336
- return normalizeText(value, '');
337
- }
338
-
339
- function summarizeProfileFields(fields = []) {
340
- return fields
341
- .map((field) => {
342
- const value = summarizeProfileValue(field.value);
343
- if (!value) return null;
344
- return `${field.label}: ${value}`;
345
- })
346
- .filter(Boolean);
347
- }
348
-
349
- function buildCandidateDeliverySummaryLine(candidateSummary = {}, index = 0) {
350
- const likesReceived = Number(candidateSummary.worldFeedbackSummary?.likesReceived || 0);
351
- const dislikesReceived = Number(candidateSummary.worldFeedbackSummary?.dislikesReceived || 0);
352
- const feedbackLine = likesReceived > 0 || dislikesReceived > 0
353
- ? ` World feedback in this world: ${likesReceived} like${likesReceived === 1 ? '' : 's'}, ${dislikesReceived} dislike${dislikesReceived === 1 ? '' : 's'}.`
354
- : '';
355
- return `${index + 1}. ${candidateSummary.summary}${feedbackLine}`;
356
- }
357
-
358
211
  function formatConversationOverview(detail = {}) {
359
212
  const conversationOverview = detail.conversationOverview && typeof detail.conversationOverview === 'object'
360
213
  ? detail.conversationOverview
@@ -605,133 +458,11 @@ export function buildRequiredFieldExplanation(worldDetail = {}) {
605
458
  };
606
459
  }
607
460
 
608
- export function buildCandidateDeliverySummary(candidateFeed = {}, { worldDetail = null, limit = null } = {}) {
609
- const detail = worldDetail ? normalizeWorldDetail(worldDetail) : null;
610
- const normalizedFeed = normalizeCandidateFeedResponse(candidateFeed, {
611
- worldId: detail?.worldId || candidateFeed.worldId || null,
612
- });
613
- const summaryLimit = Math.max(
614
- 1,
615
- normalizeInteger(limit, normalizedFeed.candidates.length || normalizedFeed.totalCandidates || 1),
616
- );
617
- const displayName = detail?.displayName || normalizedFeed.worldId || 'the selected world';
618
- const requestChatAction = {
619
- action: 'request_chat',
620
- worldId: normalizedFeed.worldId,
621
- requiredFields: ['worldId', 'displayName', 'agentCode', 'openingMessage'],
622
- summary:
623
- 'After the user chooses a candidate, request_chat with this worldId, displayName, agentCode, and a non-blank openingMessage.',
624
- };
625
- const candidateSummaries = normalizedFeed.candidates.slice(0, summaryLimit).map((candidate, index) => {
626
- const name = candidate.profileSummary.displayName || `Candidate ${index + 1}`;
627
- const requiredFieldSummary = summarizeProfileFields(candidate.profileSummary.requiredFields);
628
- const optionalFieldSummary = summarizeProfileFields(candidate.profileSummary.optionalFields);
629
- const compatibilitySummary = candidate.compatibilitySignals
630
- .map((signal) => sentenceCase(signal.summary, ''))
631
- .filter(Boolean);
632
- const deliveryReasonSummary = sentenceCase(candidate.deliveryReason.summary, '');
633
- const availabilitySummary = candidate.online === true ? 'Online now.' : 'Currently offline.';
634
- const roleSummary = candidate.worldRole ? `World role: ${candidate.worldRole}.` : null;
635
- const scoreSummary = candidate.score == null
636
- ? null
637
- : `Score ${candidate.score}${candidate.rank == null ? '' : `, rank ${candidate.rank}`}.`;
638
- const summary = [
639
- candidate.profileSummary.headline ? `${name}: ${candidate.profileSummary.headline}.` : `${name}.`,
640
- requiredFieldSummary.length > 0 ? `Required profile fields: ${requiredFieldSummary.join('; ')}.` : null,
641
- optionalFieldSummary.length > 0 ? `Optional context: ${optionalFieldSummary.join('; ')}.` : null,
642
- compatibilitySummary.length > 0 ? compatibilitySummary.join(' ') : null,
643
- deliveryReasonSummary || null,
644
- roleSummary,
645
- availabilitySummary,
646
- scoreSummary,
647
- ].filter(Boolean).join(' ');
648
-
649
- return {
650
- candidateId: candidate.candidateId,
651
- sourceMembershipId: candidate.sourceMembershipId,
652
- online: candidate.online === true,
653
- worldRole: candidate.worldRole,
654
- agentCode: candidate.agentCode,
655
- requestChat: candidate.requestChat,
656
- displayName: name,
657
- headline: candidate.profileSummary.headline,
658
- rank: candidate.rank,
659
- score: candidate.score,
660
- requiredFieldSummary,
661
- optionalFieldSummary,
662
- compatibilitySummary,
663
- deliveryReasonSummary: deliveryReasonSummary || null,
664
- worldFeedbackSummary: candidate.worldFeedbackSummary || {
665
- likesReceived: 0,
666
- dislikesReceived: 0,
667
- },
668
- expiresAt: candidate.expiresAt,
669
- summary,
670
- };
671
- });
672
- const deliveredCandidateCount = candidateSummaries.length;
673
- const totalCandidateCount = Math.max(normalizedFeed.totalCandidates, deliveredCandidateCount);
674
- const remainingCandidateCount = Math.max(totalCandidateCount - deliveredCandidateCount, 0);
675
- const heading = deliveredCandidateCount > 0
676
- ? `${displayName} has ${deliveredCandidateCount} online candidate profile ${deliveredCandidateCount === 1 ? 'summary' : 'summaries'} ready for review now.`
677
- : `No online candidate profile summaries are ready for review in ${displayName} yet.`;
678
- const promptBody = deliveredCandidateCount > 0
679
- ? candidateSummaries.map((summary, index) => buildCandidateDeliverySummaryLine(summary, index)).join('\n\n')
680
- : 'No online candidates are currently available from the active-membership feed.';
681
-
682
- return {
683
- worldId: normalizedFeed.worldId,
684
- status: deliveredCandidateCount > 0 ? 'candidate_summary_ready' : 'candidate_summary_pending',
685
- deliveredCandidateCount,
686
- totalCandidateCount,
687
- remainingCandidateCount,
688
- requestChatAction,
689
- candidateSummaries,
690
- nextAction: deliveredCandidateCount > 0
691
- ? normalizedFeed.nextAction
692
- : 'wait_for_more_candidates',
693
- orchestration: {
694
- stage: 'post_join_candidate_delivery',
695
- system:
696
- 'Use the backend-authored candidate summaries already attached to this payload. Candidate requestChat payloads are the canonical follow-up inputs for world-scoped contact establishment.',
697
- confirmation: `Candidate review payload for ${displayName} [${normalizedFeed.worldId}].`,
698
- user: [heading, promptBody].filter(Boolean).join('\n\n'),
699
- followUp: deliveredCandidateCount > 0
700
- ? (remainingCandidateCount > 0
701
- ? `Share these ${deliveredCandidateCount} candidate summaries first. If the user chooses someone now, continue with request_chat using that candidate's {worldId, displayName, agentCode} plus a non-blank openingMessage from the user. If they want more options first, continue with the remaining ${remainingCandidateCount} candidate${remainingCandidateCount === 1 ? '' : 's'} from the same feed.`
702
- : 'Share these candidate summaries and, if the user chooses one, continue with request_chat using the attached {worldId, displayName, agentCode} payload plus a non-blank openingMessage from the user.')
703
- : 'Tell the user candidate delivery can be retried later through the same backend-authored world flow.',
704
- },
705
- };
706
- }
707
-
708
461
  export function buildResolvedWorldJoinOrchestration({
709
462
  joinResult = null,
710
- candidateDelivery = null,
711
463
  } = {}) {
712
464
  const joinOrchestration = joinResult?.orchestration && typeof joinResult.orchestration === 'object' && !Array.isArray(joinResult.orchestration)
713
465
  ? joinResult.orchestration
714
466
  : null;
715
- const candidateOrchestration = candidateDelivery?.orchestration && typeof candidateDelivery.orchestration === 'object' && !Array.isArray(candidateDelivery.orchestration)
716
- ? candidateDelivery.orchestration
717
- : null;
718
-
719
- if (!candidateOrchestration) return joinOrchestration;
720
-
721
- return {
722
- stage: normalizeText(candidateOrchestration.stage, normalizeText(joinOrchestration?.stage, null)),
723
- system: normalizeText(candidateOrchestration.system, normalizeText(joinOrchestration?.system, null)),
724
- confirmation: normalizeText(
725
- joinOrchestration?.confirmation,
726
- normalizeText(candidateOrchestration.confirmation, null),
727
- ),
728
- user: [
729
- normalizeText(joinOrchestration?.user, normalizeText(joinOrchestration?.confirmation, null)),
730
- normalizeText(candidateOrchestration.user, null),
731
- ].filter(Boolean).join('\n\n'),
732
- followUp: normalizeText(
733
- candidateOrchestration.followUp,
734
- normalizeText(joinOrchestration?.followUp, null),
735
- ),
736
- };
467
+ return joinOrchestration;
737
468
  }