@xfxstudio/claworld 2026.4.27-testing.1 → 2026.4.28-testing
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.
- package/openclaw.plugin.json +245 -234
- package/package.json +1 -1
- package/skills/claworld-help/SKILL.md +3 -3
- package/src/openclaw/index.js +3 -0
- package/src/openclaw/plugin/claworld-channel-plugin.js +30 -90
- package/src/openclaw/plugin/config-schema.js +6 -0
- package/src/openclaw/plugin/register-tooling.js +0 -4
- package/src/openclaw/plugin/register.js +394 -118
- package/src/openclaw/runtime/feedback-helper.js +2 -2
- package/src/openclaw/runtime/product-shell-helper.js +213 -139
- package/src/openclaw/runtime/tool-contracts.js +195 -6
- package/src/openclaw/runtime/tool-inventory.js +15 -0
- package/src/openclaw/runtime/working-memory.js +2 -0
- package/src/openclaw/runtime/world-moderation-helper.js +0 -16
- package/src/product-shell/contracts/world-orchestration.js +270 -1
|
@@ -125,6 +125,14 @@ 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
|
+
}
|
|
128
136
|
return {
|
|
129
137
|
tool,
|
|
130
138
|
summary: normalizeText(action.summary, null),
|
|
@@ -193,6 +201,55 @@ function projectRequestChatAction(
|
|
|
193
201
|
};
|
|
194
202
|
}
|
|
195
203
|
|
|
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
|
+
|
|
196
253
|
export function projectToolWorldList(worldDirectory = {}) {
|
|
197
254
|
const worlds = Array.isArray(worldDirectory.items)
|
|
198
255
|
? worldDirectory.items.map((world) => ({
|
|
@@ -302,7 +359,23 @@ export function projectToolWorldDetail(worldDetail = {}, { accountId = null } =
|
|
|
302
359
|
};
|
|
303
360
|
}
|
|
304
361
|
|
|
305
|
-
function
|
|
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 = {}) {
|
|
306
379
|
return {
|
|
307
380
|
displayName: normalizeText(summary.displayName, null),
|
|
308
381
|
headline: normalizeText(summary.headline, null),
|
|
@@ -323,6 +396,123 @@ function projectMemberProfileSummary(summary = {}) {
|
|
|
323
396
|
};
|
|
324
397
|
}
|
|
325
398
|
|
|
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
|
+
|
|
326
516
|
function projectToolJoinAction(action = null, { accountId = null, requestToolName = null } = {}) {
|
|
327
517
|
if (!action || typeof action !== 'object' || Array.isArray(action)) return null;
|
|
328
518
|
const normalizedAccountId = normalizeText(accountId, null);
|
|
@@ -516,22 +706,21 @@ export function projectToolWorldMemberSearchResponse(payload = {}, { accountId =
|
|
|
516
706
|
status: normalizeText(payload.status, 'no_matches'),
|
|
517
707
|
worldId: normalizeText(payload.worldId, null),
|
|
518
708
|
query: normalizeText(payload.query, null),
|
|
519
|
-
sort: normalizeText(payload.sort, '
|
|
709
|
+
sort: normalizeText(payload.sort, 'match'),
|
|
520
710
|
limit: normalizeInteger(payload.limit, 0),
|
|
521
711
|
totalMatches: normalizeInteger(payload.totalMatches, Array.isArray(payload.items) ? payload.items.length : 0),
|
|
522
712
|
nextAction: normalizeText(payload.nextAction, null),
|
|
523
713
|
members: Array.isArray(payload.items)
|
|
524
714
|
? payload.items.map((item, index) => ({
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
displayName: normalizeText(item.displayName, `Member ${index + 1}`),
|
|
715
|
+
candidateId: normalizeText(item.membershipId, `candidate_${index + 1}`),
|
|
716
|
+
displayName: normalizeText(item.displayName, `Candidate ${index + 1}`),
|
|
528
717
|
agentCode: normalizeText(item.agentCode, null)?.toUpperCase() || null,
|
|
529
718
|
headline: normalizeText(item.headline, null),
|
|
530
719
|
online: item.online === true,
|
|
531
720
|
score: normalizeInteger(item.score, 0),
|
|
532
721
|
matchedFieldIds: normalizeStringList(item.matchedFieldIds),
|
|
533
722
|
reasonSummary: normalizeText(item.reasonSummary, null),
|
|
534
|
-
profileSummary:
|
|
723
|
+
profileSummary: projectCandidateProfileSummary(item.profileSummary || {}),
|
|
535
724
|
worldFeedbackSummary: projectWorldFeedbackSummary(item.worldFeedbackSummary),
|
|
536
725
|
requestChat: projectRequestChatPayload(item.requestChat, { accountId }),
|
|
537
726
|
}))
|
|
@@ -17,12 +17,16 @@ 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
|
+
]);
|
|
20
23
|
|
|
21
24
|
export const CLAWORLD_REGISTERED_TOOL_NAMES = Object.freeze([
|
|
22
25
|
...CLAWORLD_ACCOUNT_TOOL_NAMES,
|
|
23
26
|
...CLAWORLD_SEARCH_TOOL_NAMES,
|
|
24
27
|
...CLAWORLD_WORLD_TOOL_NAMES,
|
|
25
28
|
...CLAWORLD_CONVERSATION_TOOL_NAMES,
|
|
29
|
+
...CLAWORLD_FEEDBACK_TOOL_NAMES,
|
|
26
30
|
]);
|
|
27
31
|
|
|
28
32
|
export const CLAWORLD_PUBLIC_TOOL_NAMES = Object.freeze([
|
|
@@ -30,6 +34,17 @@ export const CLAWORLD_PUBLIC_TOOL_NAMES = Object.freeze([
|
|
|
30
34
|
]);
|
|
31
35
|
|
|
32
36
|
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',
|
|
33
48
|
]);
|
|
34
49
|
|
|
35
50
|
export const CLAWORLD_MINIMAL_OPENCLAW_TOOL_NAMES = Object.freeze([
|
|
@@ -602,6 +602,7 @@ function compactResultPayload(payload = {}) {
|
|
|
602
602
|
'displayName',
|
|
603
603
|
'chatRequestId',
|
|
604
604
|
'conversationKey',
|
|
605
|
+
'candidateId',
|
|
605
606
|
'feedbackId',
|
|
606
607
|
'nextAction',
|
|
607
608
|
'requiredAction',
|
|
@@ -631,6 +632,7 @@ export function buildClaworldToolMaintenanceEvent({
|
|
|
631
632
|
worldId: params.worldId || payload.worldId,
|
|
632
633
|
chatRequestId: params.chatRequestId || payload.chatRequestId,
|
|
633
634
|
conversationKey: params.conversationKey || payload.conversationKey,
|
|
635
|
+
candidateId: params.candidateId || payload.candidateId,
|
|
634
636
|
agentCode: params.agentCode || payload.agentCode,
|
|
635
637
|
};
|
|
636
638
|
return buildClaworldMaintenanceEvent({
|
|
@@ -101,10 +101,6 @@ 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'),
|
|
108
104
|
schemaVersion: normalizeOptionalInteger(payload.schemaVersion, null),
|
|
109
105
|
createdAt: normalizeText(payload.createdAt, null),
|
|
110
106
|
updatedAt: normalizeText(payload.updatedAt, null),
|
|
@@ -137,10 +133,6 @@ function normalizeOwnedWorldSummary(payload = {}) {
|
|
|
137
133
|
enabled: normalizeOptionalBoolean(payload.enabled, null),
|
|
138
134
|
status: normalizeText(payload.status, null),
|
|
139
135
|
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'),
|
|
144
136
|
createdAt: normalizeText(payload.createdAt, null),
|
|
145
137
|
updatedAt: normalizeText(payload.updatedAt, null),
|
|
146
138
|
broadcast: normalizeWorldBroadcastConfig(payload.broadcast),
|
|
@@ -281,10 +273,6 @@ export async function createModeratedWorld({
|
|
|
281
273
|
worldContextText = null,
|
|
282
274
|
participantContextText = null,
|
|
283
275
|
enabled = true,
|
|
284
|
-
visibility = null,
|
|
285
|
-
identityMode = null,
|
|
286
|
-
joinPolicy = null,
|
|
287
|
-
approvalPolicy = null,
|
|
288
276
|
fetchImpl,
|
|
289
277
|
logger = console,
|
|
290
278
|
} = {}) {
|
|
@@ -312,10 +300,6 @@ export async function createModeratedWorld({
|
|
|
312
300
|
worldContextText,
|
|
313
301
|
participantContextText: normalizeText(participantContextText, null),
|
|
314
302
|
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) } : {}),
|
|
319
303
|
}),
|
|
320
304
|
});
|
|
321
305
|
|
|
@@ -10,6 +10,12 @@ 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
|
+
|
|
13
19
|
function normalizeStringList(values = []) {
|
|
14
20
|
if (!Array.isArray(values)) return [];
|
|
15
21
|
return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
|
|
@@ -208,6 +214,147 @@ function normalizeWorldDetail(payload = {}) {
|
|
|
208
214
|
};
|
|
209
215
|
}
|
|
210
216
|
|
|
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
|
+
|
|
211
358
|
function formatConversationOverview(detail = {}) {
|
|
212
359
|
const conversationOverview = detail.conversationOverview && typeof detail.conversationOverview === 'object'
|
|
213
360
|
? detail.conversationOverview
|
|
@@ -458,11 +605,133 @@ export function buildRequiredFieldExplanation(worldDetail = {}) {
|
|
|
458
605
|
};
|
|
459
606
|
}
|
|
460
607
|
|
|
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
|
+
|
|
461
708
|
export function buildResolvedWorldJoinOrchestration({
|
|
462
709
|
joinResult = null,
|
|
710
|
+
candidateDelivery = null,
|
|
463
711
|
} = {}) {
|
|
464
712
|
const joinOrchestration = joinResult?.orchestration && typeof joinResult.orchestration === 'object' && !Array.isArray(joinResult.orchestration)
|
|
465
713
|
? joinResult.orchestration
|
|
466
714
|
: null;
|
|
467
|
-
|
|
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
|
+
};
|
|
468
737
|
}
|