@xfxstudio/claworld 2026.4.14-testing.1 → 2026.4.16-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.
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/index.js +0 -50
- package/setup-entry.js +0 -6
- package/skills/claworld-a2a-channel-agent/SKILL.md +0 -218
- package/skills/claworld-help/SKILL.md +0 -304
- package/skills/claworld-join-and-chat/SKILL.md +0 -515
- package/skills/claworld-manage-worlds/SKILL.md +0 -283
- package/skills/claworld-manage-worlds/references/world-context-templates.md +0 -145
- package/src/lib/chat-request.js +0 -366
- package/src/lib/public-identity.js +0 -175
- package/src/lib/relay/agent-readable-markdown.js +0 -385
- package/src/lib/relay/kickoff-progress.js +0 -162
- package/src/lib/relay/kickoff-text.js +0 -191
- package/src/lib/relay/shared.js +0 -30
- package/src/lib/runtime-errors.js +0 -149
- package/src/openclaw/index.js +0 -51
- package/src/openclaw/plugin/account-identity.js +0 -73
- package/src/openclaw/plugin/claworld-channel-plugin.js +0 -3483
- package/src/openclaw/plugin/config-schema.js +0 -392
- package/src/openclaw/plugin/lifecycle.js +0 -114
- package/src/openclaw/plugin/managed-config.js +0 -1054
- package/src/openclaw/plugin/onboarding.js +0 -312
- package/src/openclaw/plugin/register-tooling.js +0 -728
- package/src/openclaw/plugin/register.js +0 -1609
- package/src/openclaw/plugin/relay-client-shared.js +0 -146
- package/src/openclaw/plugin/relay-client.js +0 -1469
- package/src/openclaw/plugin/runtime-backup.js +0 -105
- package/src/openclaw/plugin/runtime.js +0 -12
- package/src/openclaw/plugin-version.js +0 -67
- package/src/openclaw/protocol/relay-event-protocol.js +0 -43
- package/src/openclaw/runtime/backend-error-context.js +0 -91
- package/src/openclaw/runtime/canonical-result-builder.js +0 -126
- package/src/openclaw/runtime/demo-session-bootstrap.js +0 -32
- package/src/openclaw/runtime/feedback-helper.js +0 -145
- package/src/openclaw/runtime/inbound-session-router.js +0 -44
- package/src/openclaw/runtime/outbound-session-bridge.js +0 -29
- package/src/openclaw/runtime/product-shell-helper.js +0 -931
- package/src/openclaw/runtime/runtime-path.js +0 -19
- package/src/openclaw/runtime/system-message-orchestrator.js +0 -1
- package/src/openclaw/runtime/tool-contracts.js +0 -939
- package/src/openclaw/runtime/tool-inventory.js +0 -83
- package/src/openclaw/runtime/world-membership-helper.js +0 -320
- package/src/openclaw/runtime/world-moderation-helper.js +0 -508
- package/src/product-shell/contracts/chat-request-approval-policy.js +0 -93
- package/src/product-shell/contracts/world-orchestration.js +0 -734
- package/src/product-shell/orchestration/world-conversation-text.js +0 -229
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
function normalizeText(value, fallback = null) {
|
|
2
|
-
if (value == null) return fallback;
|
|
3
|
-
const normalized = String(value).trim();
|
|
4
|
-
return normalized || fallback;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function normalizeInteger(value, fallback = 0) {
|
|
8
|
-
const parsed = Number(value);
|
|
9
|
-
if (!Number.isFinite(parsed)) return fallback;
|
|
10
|
-
return Math.max(0, Math.trunc(parsed));
|
|
11
|
-
}
|
|
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
|
-
function normalizeStringList(values = []) {
|
|
20
|
-
if (!Array.isArray(values)) return [];
|
|
21
|
-
return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function normalizeBroadcastConfig(broadcast = {}) {
|
|
25
|
-
return {
|
|
26
|
-
enabled: broadcast.enabled === true,
|
|
27
|
-
audience: normalizeText(broadcast.audience, 'members'),
|
|
28
|
-
replyPolicy: normalizeText(broadcast.replyPolicy, 'zero'),
|
|
29
|
-
excludeSelf: broadcast.excludeSelf !== false,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function normalizeLookupText(value) {
|
|
34
|
-
return normalizeText(value, '')?.toLowerCase() || '';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function sentenceCase(value, fallback = '') {
|
|
38
|
-
const normalized = normalizeText(value, fallback);
|
|
39
|
-
if (!normalized) return fallback;
|
|
40
|
-
return /[.!?]$/.test(normalized) ? normalized : `${normalized}.`;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function quoteExample(example) {
|
|
44
|
-
return `"${String(example).trim()}"`;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function joinAsNaturalLanguage(values = []) {
|
|
48
|
-
const items = values.filter(Boolean);
|
|
49
|
-
if (items.length === 0) return '';
|
|
50
|
-
if (items.length === 1) return items[0];
|
|
51
|
-
if (items.length === 2) return `${items[0]} and ${items[1]}`;
|
|
52
|
-
return `${items.slice(0, -1).join(', ')}, and ${items.at(-1)}`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function summarizeWorldChoices(items = []) {
|
|
56
|
-
return items.map((world) => `${world.displayName} [${world.worldId}]`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function normalizeWorldSummary(world = {}) {
|
|
60
|
-
const summary = world.agentSummary && typeof world.agentSummary === 'object' ? world.agentSummary : world;
|
|
61
|
-
const rawWorldId = world.worldId || summary.worldId;
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
worldId: normalizeText(rawWorldId, 'unknown-world'),
|
|
65
|
-
displayName: normalizeText(summary.displayName || world.displayName, normalizeText(rawWorldId, 'Unknown World')),
|
|
66
|
-
worldContextText: normalizeText(summary.worldContextText || world.worldContextText, ''),
|
|
67
|
-
hotness: normalizeInteger(summary.hotness || world.hotness || world.activatedMemberCount, 0),
|
|
68
|
-
requiredFieldCount: normalizeInteger(summary.requiredFieldCount || world.requiredFieldCount, 0),
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function normalizeField(field = {}, index = 0, { required = false } = {}) {
|
|
73
|
-
const fieldId = normalizeText(field.fieldId || field.id, `field_${index + 1}`);
|
|
74
|
-
return {
|
|
75
|
-
fieldId,
|
|
76
|
-
label: normalizeText(field.label, fieldId),
|
|
77
|
-
type: normalizeText(field.type, 'string'),
|
|
78
|
-
source: normalizeText(field.source, 'profile'),
|
|
79
|
-
required: field.required === true || required,
|
|
80
|
-
description: normalizeText(field.description, null),
|
|
81
|
-
examples: normalizeStringList(field.examples),
|
|
82
|
-
constraints: field.constraints && typeof field.constraints === 'object' ? field.constraints : {},
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function normalizeSearchSchema(payload = {}, { worldId = null, fallbackFields = [] } = {}) {
|
|
87
|
-
const rawInputFields = Array.isArray(payload.inputFields) && payload.inputFields.length > 0
|
|
88
|
-
? payload.inputFields
|
|
89
|
-
: fallbackFields;
|
|
90
|
-
const inputFields = rawInputFields.map((field, index) => normalizeField(field, index, { required: false }));
|
|
91
|
-
const inputFieldIds = normalizeStringList(
|
|
92
|
-
Array.isArray(payload.inputFieldIds)
|
|
93
|
-
? payload.inputFieldIds
|
|
94
|
-
: inputFields.map((field) => field.fieldId),
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
modelId: normalizeText(payload.modelId, worldId ? `${worldId}.search.v1` : 'world.search.v1'),
|
|
99
|
-
worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
|
|
100
|
-
mode: normalizeText(payload.mode, 'membership_profile_search'),
|
|
101
|
-
previewRoute: normalizeText(payload.previewRoute, worldId ? `/v1/worlds/${worldId}/search` : '/v1/worlds/:worldId/search'),
|
|
102
|
-
inputFieldIds,
|
|
103
|
-
inputFields,
|
|
104
|
-
resultFields: normalizeStringList(payload.resultFields),
|
|
105
|
-
viewerRequirement: normalizeText(payload.viewerRequirement, 'active_membership'),
|
|
106
|
-
onlineOnly: payload.onlineOnly !== false,
|
|
107
|
-
defaultLimit: normalizeInteger(payload.defaultLimit, 10),
|
|
108
|
-
summary: normalizeText(payload.summary, ''),
|
|
109
|
-
hints: normalizeStringList(payload.hints),
|
|
110
|
-
status: normalizeText(payload.status, 'phase1_world_search'),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function normalizeWorldDetail(payload = {}) {
|
|
115
|
-
if (Array.isArray(payload.requiredFields) || Array.isArray(payload.optionalFields)) {
|
|
116
|
-
const requiredFields = Array.isArray(payload.requiredFields)
|
|
117
|
-
? payload.requiredFields.map((field, index) => normalizeField(field, index, { required: true }))
|
|
118
|
-
: [];
|
|
119
|
-
const optionalFields = Array.isArray(payload.optionalFields)
|
|
120
|
-
? payload.optionalFields.map((field, index) => normalizeField(field, index, { required: false }))
|
|
121
|
-
: [];
|
|
122
|
-
const normalizedWorldId = normalizeText(payload.worldId, 'unknown-world');
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
status: normalizeText(payload.status, 'ready'),
|
|
126
|
-
source: normalizeText(payload.source, 'product_shell'),
|
|
127
|
-
worldId: normalizedWorldId,
|
|
128
|
-
displayName: normalizeText(payload.displayName, normalizedWorldId),
|
|
129
|
-
summary: normalizeText(payload.summary, ''),
|
|
130
|
-
description: normalizeText(payload.description, normalizeText(payload.summary, '')),
|
|
131
|
-
category: normalizeText(payload.category, 'general'),
|
|
132
|
-
requiredFieldCount: normalizeInteger(payload.requiredFieldCount, requiredFields.length) || requiredFields.length,
|
|
133
|
-
optionalFieldCount: normalizeInteger(payload.optionalFieldCount, optionalFields.length) || optionalFields.length,
|
|
134
|
-
matchingMode: normalizeText(payload.matchingMode, 'manual_review'),
|
|
135
|
-
conversationMode: normalizeText(payload.conversationMode, 'a2a'),
|
|
136
|
-
interactionRules: normalizeText(payload.interactionRules, null),
|
|
137
|
-
prohibitedRules: normalizeText(payload.prohibitedRules, null),
|
|
138
|
-
eligibility: normalizeText(payload.eligibility, 'active'),
|
|
139
|
-
broadcast: normalizeBroadcastConfig(payload.broadcast),
|
|
140
|
-
requiredFields,
|
|
141
|
-
optionalFields,
|
|
142
|
-
hints: normalizeStringList(payload.hints),
|
|
143
|
-
nextAction: normalizeText(payload.nextAction, 'call_join_world'),
|
|
144
|
-
conversationOverview:
|
|
145
|
-
payload.conversationOverview && typeof payload.conversationOverview === 'object'
|
|
146
|
-
? payload.conversationOverview
|
|
147
|
-
: {},
|
|
148
|
-
matchingOverview: payload.matchingOverview && typeof payload.matchingOverview === 'object' ? payload.matchingOverview : {},
|
|
149
|
-
searchSchema: normalizeSearchSchema(payload.searchSchema || {}, {
|
|
150
|
-
worldId: normalizedWorldId,
|
|
151
|
-
fallbackFields: requiredFields,
|
|
152
|
-
}),
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const world = payload.world && typeof payload.world === 'object' ? payload.world : {};
|
|
157
|
-
const agentSummary = payload.agentSummary && typeof payload.agentSummary === 'object' ? payload.agentSummary : {};
|
|
158
|
-
const joinSchema = payload.joinSchema && typeof payload.joinSchema === 'object' ? payload.joinSchema : {};
|
|
159
|
-
const fieldGuide = payload.fieldGuide && typeof payload.fieldGuide === 'object' ? payload.fieldGuide : {};
|
|
160
|
-
const conversationOverview = payload.conversationOverview && typeof payload.conversationOverview === 'object'
|
|
161
|
-
? payload.conversationOverview
|
|
162
|
-
: {};
|
|
163
|
-
const matchingOverview = payload.matchingOverview && typeof payload.matchingOverview === 'object'
|
|
164
|
-
? payload.matchingOverview
|
|
165
|
-
: {};
|
|
166
|
-
const searchOverview = payload.searchSchema && typeof payload.searchSchema === 'object'
|
|
167
|
-
? payload.searchSchema
|
|
168
|
-
: {};
|
|
169
|
-
|
|
170
|
-
const requiredInput = Array.isArray(fieldGuide.required) && fieldGuide.required.length > 0
|
|
171
|
-
? fieldGuide.required
|
|
172
|
-
: (Array.isArray(joinSchema.requiredFields) ? joinSchema.requiredFields : []);
|
|
173
|
-
const optionalInput = Array.isArray(fieldGuide.optional) && fieldGuide.optional.length > 0
|
|
174
|
-
? fieldGuide.optional
|
|
175
|
-
: (Array.isArray(joinSchema.optionalFields) ? joinSchema.optionalFields : []);
|
|
176
|
-
|
|
177
|
-
const requiredFields = requiredInput.map((field, index) => normalizeField(field, index, { required: true }));
|
|
178
|
-
const optionalFields = optionalInput.map((field, index) => normalizeField(field, index, { required: false }));
|
|
179
|
-
const worldId = normalizeText(payload.worldId || world.worldId || joinSchema.worldId, 'unknown-world');
|
|
180
|
-
const displayName = normalizeText(payload.displayName || agentSummary.displayName || world.displayName, worldId);
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
status: 'ready',
|
|
184
|
-
source: 'product_shell',
|
|
185
|
-
worldId,
|
|
186
|
-
displayName,
|
|
187
|
-
summary: normalizeText(payload.summary || agentSummary.summary || world.summary, ''),
|
|
188
|
-
description: normalizeText(payload.description || world.description, normalizeText(payload.summary || agentSummary.summary || world.summary, '')),
|
|
189
|
-
category: normalizeText(payload.category || agentSummary.category || world.category, 'general'),
|
|
190
|
-
requiredFieldCount: normalizeInteger(joinSchema.requiredFieldCount, requiredFields.length) || requiredFields.length,
|
|
191
|
-
optionalFieldCount: normalizeInteger(joinSchema.optionalFieldCount, optionalFields.length) || optionalFields.length,
|
|
192
|
-
matchingMode: normalizeText(payload.matchingMode || agentSummary.matchingMode || matchingOverview.mode || world.matching?.mode, 'manual_review'),
|
|
193
|
-
conversationMode: normalizeText(
|
|
194
|
-
payload.conversationMode || agentSummary.conversationMode || conversationOverview.mode || world.conversationTemplate?.mode,
|
|
195
|
-
'a2a',
|
|
196
|
-
),
|
|
197
|
-
interactionRules: normalizeText(payload.interactionRules || world.interactionRules, null),
|
|
198
|
-
prohibitedRules: normalizeText(payload.prohibitedRules || world.prohibitedRules, null),
|
|
199
|
-
eligibility: normalizeText(payload.eligibility || world.eligibility, 'active'),
|
|
200
|
-
broadcast: normalizeBroadcastConfig(payload.broadcast || world.broadcast),
|
|
201
|
-
requiredFields,
|
|
202
|
-
optionalFields,
|
|
203
|
-
hints: normalizeStringList(payload.hints || joinSchema.hints),
|
|
204
|
-
nextAction: normalizeText(payload.nextAction || joinSchema.nextAction, 'call_join_world'),
|
|
205
|
-
conversationOverview,
|
|
206
|
-
matchingOverview,
|
|
207
|
-
searchSchema: normalizeSearchSchema(searchOverview, {
|
|
208
|
-
worldId,
|
|
209
|
-
fallbackFields: [...requiredFields, ...optionalFields],
|
|
210
|
-
}),
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function normalizeProfileSummaryField(field = {}, index = 0) {
|
|
215
|
-
const fieldId = normalizeText(field.fieldId || field.id, `field_${index + 1}`);
|
|
216
|
-
const value = Array.isArray(field.value)
|
|
217
|
-
? normalizeStringList(field.value)
|
|
218
|
-
: normalizeText(field.value, null);
|
|
219
|
-
|
|
220
|
-
if (value == null || (Array.isArray(value) && value.length === 0)) {
|
|
221
|
-
return null;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
fieldId,
|
|
226
|
-
label: normalizeText(field.label, fieldId),
|
|
227
|
-
value,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function normalizeCandidateProfileSummary(summary = {}) {
|
|
232
|
-
return {
|
|
233
|
-
displayName: normalizeText(summary.displayName, null),
|
|
234
|
-
headline: normalizeText(summary.headline, null),
|
|
235
|
-
requiredFields: Array.isArray(summary.requiredFields)
|
|
236
|
-
? summary.requiredFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
|
|
237
|
-
: [],
|
|
238
|
-
optionalFields: Array.isArray(summary.optionalFields)
|
|
239
|
-
? summary.optionalFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
|
|
240
|
-
: [],
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function normalizeCompatibilitySignal(signal = {}, index = 0) {
|
|
245
|
-
return {
|
|
246
|
-
signalId: normalizeText(signal.signalId, `signal_${index + 1}`),
|
|
247
|
-
type: normalizeText(signal.type, 'world_ready'),
|
|
248
|
-
fieldIds: normalizeStringList(signal.fieldIds),
|
|
249
|
-
score: normalizeNumber(signal.score, 0),
|
|
250
|
-
summary: normalizeText(signal.summary, ''),
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function normalizeDeliveryReason(reason = {}) {
|
|
255
|
-
return {
|
|
256
|
-
code: normalizeText(reason.code, null),
|
|
257
|
-
matchedFieldIds: normalizeStringList(reason.matchedFieldIds),
|
|
258
|
-
summary: normalizeText(reason.summary, ''),
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function normalizeWorldRole(worldRole, fallback = null) {
|
|
263
|
-
const normalized = normalizeText(worldRole, fallback);
|
|
264
|
-
return ['owner', 'member'].includes(normalized) ? normalized : fallback;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function normalizeCandidate(candidate = {}, index = 0) {
|
|
268
|
-
const normalizedRank = normalizeNumber(candidate.rank, null);
|
|
269
|
-
const displayName = normalizeText(
|
|
270
|
-
candidate.displayName || candidate.profileSummary?.displayName || candidate.requestChat?.displayName,
|
|
271
|
-
null,
|
|
272
|
-
);
|
|
273
|
-
const agentCode = normalizeText(
|
|
274
|
-
candidate.agentCode || candidate.requestChat?.agentCode,
|
|
275
|
-
null,
|
|
276
|
-
)?.toUpperCase() || null;
|
|
277
|
-
const requestChat = displayName && agentCode
|
|
278
|
-
? {
|
|
279
|
-
worldId: normalizeText(candidate.requestChat?.worldId, normalizeText(candidate.worldId, 'unknown-world')),
|
|
280
|
-
displayName,
|
|
281
|
-
agentCode,
|
|
282
|
-
}
|
|
283
|
-
: null;
|
|
284
|
-
|
|
285
|
-
return {
|
|
286
|
-
candidateId: normalizeText(candidate.candidateId, `candidate_${index + 1}`),
|
|
287
|
-
worldId: normalizeText(candidate.worldId, 'unknown-world'),
|
|
288
|
-
worldRole: normalizeWorldRole(candidate.worldRole, null),
|
|
289
|
-
sourceMembershipId: normalizeText(candidate.sourceMembershipId, null),
|
|
290
|
-
online: candidate.online === true,
|
|
291
|
-
displayName,
|
|
292
|
-
agentCode,
|
|
293
|
-
requestChat,
|
|
294
|
-
profileSummary: normalizeCandidateProfileSummary(candidate.profileSummary),
|
|
295
|
-
compatibilitySignals: Array.isArray(candidate.compatibilitySignals)
|
|
296
|
-
? candidate.compatibilitySignals.map((signal, signalIndex) => normalizeCompatibilitySignal(signal, signalIndex))
|
|
297
|
-
: [],
|
|
298
|
-
deliveryReason: normalizeDeliveryReason(candidate.deliveryReason),
|
|
299
|
-
expiresAt: normalizeText(candidate.expiresAt, null),
|
|
300
|
-
joinedAt: normalizeText(candidate.joinedAt, null),
|
|
301
|
-
rank: normalizedRank == null ? null : Math.max(1, Math.trunc(normalizedRank)),
|
|
302
|
-
score: normalizeNumber(candidate.score, null),
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function normalizeCandidateFeedResponse(payload = {}, { worldId = null } = {}) {
|
|
307
|
-
const candidates = Array.isArray(payload.candidates)
|
|
308
|
-
? payload.candidates.map((candidate, index) => normalizeCandidate(candidate, index))
|
|
309
|
-
: [];
|
|
310
|
-
|
|
311
|
-
return {
|
|
312
|
-
worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
|
|
313
|
-
viewerMembershipId: normalizeText(payload.viewerMembershipId, null),
|
|
314
|
-
generatedAt: normalizeText(payload.generatedAt, null),
|
|
315
|
-
expiresAt: normalizeText(payload.expiresAt, null),
|
|
316
|
-
deliveryMode: normalizeText(payload.deliveryMode, 'agent_review_before_live_session'),
|
|
317
|
-
nextAction: normalizeText(
|
|
318
|
-
payload.nextAction,
|
|
319
|
-
candidates.length > 0 ? 'review_candidates_then_request_chat' : 'wait_for_more_candidates',
|
|
320
|
-
),
|
|
321
|
-
candidateSource: normalizeText(payload.candidateSource, 'active_memberships_online'),
|
|
322
|
-
candidateModel: payload.candidateModel && typeof payload.candidateModel === 'object' ? payload.candidateModel : {},
|
|
323
|
-
strategy: payload.strategy && typeof payload.strategy === 'object' ? payload.strategy : {},
|
|
324
|
-
limit: normalizeInteger(payload.limit, candidates.length),
|
|
325
|
-
totalCandidates: normalizeInteger(payload.totalCandidates, candidates.length),
|
|
326
|
-
status: normalizeText(payload.status, candidates.length > 0 ? 'feed_ready' : 'no_candidates_ready'),
|
|
327
|
-
candidates,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function summarizeProfileValue(value) {
|
|
332
|
-
if (Array.isArray(value)) return joinAsNaturalLanguage(value.map((entry) => String(entry).trim()).filter(Boolean));
|
|
333
|
-
return normalizeText(value, '');
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function summarizeProfileFields(fields = []) {
|
|
337
|
-
return fields
|
|
338
|
-
.map((field) => {
|
|
339
|
-
const value = summarizeProfileValue(field.value);
|
|
340
|
-
if (!value) return null;
|
|
341
|
-
return `${field.label}: ${value}`;
|
|
342
|
-
})
|
|
343
|
-
.filter(Boolean);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function buildCandidateDeliverySummaryLine(candidateSummary = {}, index = 0) {
|
|
347
|
-
const likesReceived = Number(candidateSummary.worldFeedbackSummary?.likesReceived || 0);
|
|
348
|
-
const dislikesReceived = Number(candidateSummary.worldFeedbackSummary?.dislikesReceived || 0);
|
|
349
|
-
const feedbackLine = likesReceived > 0 || dislikesReceived > 0
|
|
350
|
-
? ` World feedback in this world: ${likesReceived} like${likesReceived === 1 ? '' : 's'}, ${dislikesReceived} dislike${dislikesReceived === 1 ? '' : 's'}.`
|
|
351
|
-
: '';
|
|
352
|
-
return `${index + 1}. ${candidateSummary.summary}${feedbackLine}`;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function formatConversationOverview(detail = {}) {
|
|
356
|
-
const conversationOverview = detail.conversationOverview && typeof detail.conversationOverview === 'object'
|
|
357
|
-
? detail.conversationOverview
|
|
358
|
-
: {};
|
|
359
|
-
const mode = normalizeText(detail.conversationMode || conversationOverview.mode, null);
|
|
360
|
-
const parts = [];
|
|
361
|
-
|
|
362
|
-
if (mode) parts.push(`${mode} mode`);
|
|
363
|
-
|
|
364
|
-
return parts.length > 0 ? parts.join(', ') : null;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
export function buildWorldSessionStartupText(detail = {}) {
|
|
368
|
-
const normalizedDetail = normalizeWorldDetail(detail);
|
|
369
|
-
const worldId = normalizeText(normalizedDetail.worldId, null);
|
|
370
|
-
if (!worldId) return null;
|
|
371
|
-
|
|
372
|
-
const displayName = normalizeText(normalizedDetail.displayName, worldId);
|
|
373
|
-
const summary = normalizeText(normalizedDetail.summary, null);
|
|
374
|
-
const sessionSummary = formatConversationOverview(normalizedDetail);
|
|
375
|
-
const conversationOverview = normalizedDetail.conversationOverview && typeof normalizedDetail.conversationOverview === 'object'
|
|
376
|
-
? normalizedDetail.conversationOverview
|
|
377
|
-
: {};
|
|
378
|
-
const openingText = normalizeText(conversationOverview.openingText, null);
|
|
379
|
-
const convergenceText = normalizeText(conversationOverview.convergence?.text, null);
|
|
380
|
-
const interactionRules = normalizeText(normalizedDetail.interactionRules, null);
|
|
381
|
-
const prohibitedRules = normalizeText(normalizedDetail.prohibitedRules, null);
|
|
382
|
-
|
|
383
|
-
const lines = [
|
|
384
|
-
'Internal Claworld world context for this conversation.',
|
|
385
|
-
'Do not acknowledge, paraphrase, or announce this setup to the peer unless it is directly relevant to their message.',
|
|
386
|
-
`World: ${displayName} [${worldId}]`,
|
|
387
|
-
summary ? `Summary: ${summary}` : null,
|
|
388
|
-
sessionSummary ? `Session overview: ${sessionSummary}` : null,
|
|
389
|
-
'Interruption handling: prefer reconnect/resume. Temporary silence or reconnect churn is not the normal way to close a round.',
|
|
390
|
-
openingText ? `Opening focus: ${openingText}` : null,
|
|
391
|
-
interactionRules ? `Interaction rules: ${interactionRules}` : null,
|
|
392
|
-
prohibitedRules ? `Prohibited rules: ${prohibitedRules}` : null,
|
|
393
|
-
convergenceText ? `Convergence rule: ${convergenceText}` : null,
|
|
394
|
-
'Apply these world rules symmetrically when responding in this conversation.',
|
|
395
|
-
].filter(Boolean);
|
|
396
|
-
|
|
397
|
-
return lines.join('\n');
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function normalizeSelectionInput(selection) {
|
|
401
|
-
if (selection && typeof selection === 'object') {
|
|
402
|
-
const asWorldId = normalizeText(selection.worldId, null);
|
|
403
|
-
const asDisplayName = normalizeText(selection.displayName, null);
|
|
404
|
-
const asChoice = normalizeText(selection.selection || selection.choice || selection.value, null);
|
|
405
|
-
const text = asWorldId || asDisplayName || asChoice || '';
|
|
406
|
-
return {
|
|
407
|
-
raw: selection,
|
|
408
|
-
text,
|
|
409
|
-
normalized: normalizeLookupText(text),
|
|
410
|
-
index: /^\d+$/.test(String(text)) ? normalizeInteger(text, 0) : null,
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const text = normalizeText(selection, '');
|
|
415
|
-
return {
|
|
416
|
-
raw: selection,
|
|
417
|
-
text,
|
|
418
|
-
normalized: normalizeLookupText(text),
|
|
419
|
-
index: /^\d+$/.test(String(text)) ? normalizeInteger(text, 0) : null,
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
function buildSelectionRetryContract(status, selection, items = [], matches = []) {
|
|
424
|
-
const choiceLabel = selection.text ? `"${selection.text}"` : 'that choice';
|
|
425
|
-
const retryWorlds = (matches.length > 0 ? matches : items).map((world) => normalizeWorldSummary(world));
|
|
426
|
-
const retrySummary = summarizeWorldChoices(retryWorlds);
|
|
427
|
-
|
|
428
|
-
if (status === 'ambiguous') {
|
|
429
|
-
return {
|
|
430
|
-
status,
|
|
431
|
-
selection: {
|
|
432
|
-
input: selection.text || null,
|
|
433
|
-
matchedBy: null,
|
|
434
|
-
worldId: null,
|
|
435
|
-
displayName: null,
|
|
436
|
-
},
|
|
437
|
-
candidateWorlds: retryWorlds,
|
|
438
|
-
orchestration: {
|
|
439
|
-
stage: 'post_setup_world_selection_retry',
|
|
440
|
-
system: 'The world choice matched multiple worlds. Show the narrowed list and ask the user to pick one exact world ID or display name.',
|
|
441
|
-
user: `The choice ${choiceLabel} is ambiguous. Matching worlds: ${joinAsNaturalLanguage(retrySummary)}. Ask the user to choose one exact world ID or display name.`,
|
|
442
|
-
followUp: 'Once the user confirms one exact world, fetch its detail, explain the required fields, and use join_world when enough profile data is available.',
|
|
443
|
-
},
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
return {
|
|
448
|
-
status: 'no_match',
|
|
449
|
-
selection: {
|
|
450
|
-
input: selection.text || null,
|
|
451
|
-
matchedBy: null,
|
|
452
|
-
worldId: null,
|
|
453
|
-
displayName: null,
|
|
454
|
-
},
|
|
455
|
-
candidateWorlds: retryWorlds,
|
|
456
|
-
orchestration: {
|
|
457
|
-
stage: 'post_setup_world_selection_retry',
|
|
458
|
-
system: 'The world choice did not match the available world directory. Re-list the worlds and ask the user to choose one by world ID or display name.',
|
|
459
|
-
user: retrySummary.length > 0
|
|
460
|
-
? `I could not match ${choiceLabel} to an available world. Available worlds: ${joinAsNaturalLanguage(retrySummary)}. Ask the user to choose one by world ID or display name.`
|
|
461
|
-
: 'No worlds are currently available. Tell the user setup is complete but world selection cannot continue yet.',
|
|
462
|
-
followUp: 'Once the user chooses a valid world, confirm it, fetch the world detail, and explain the required fields before calling join_world.',
|
|
463
|
-
},
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
export function buildWorldSelectionPrompt(worldDirectory = {}) {
|
|
468
|
-
const worldLines = Array.isArray(worldDirectory.items)
|
|
469
|
-
? worldDirectory.items.map((world, index) => (
|
|
470
|
-
`${index + 1}. ${world.displayName} [${world.worldId}]`
|
|
471
|
-
+ ` (required fields: ${world.requiredFieldCount}; hotness: ${normalizeInteger(world.hotness, 0)})`
|
|
472
|
-
))
|
|
473
|
-
: [];
|
|
474
|
-
|
|
475
|
-
return {
|
|
476
|
-
stage: 'post_setup_world_selection',
|
|
477
|
-
recommendedWorldId: worldDirectory.recommendedWorldId || null,
|
|
478
|
-
system:
|
|
479
|
-
'Setup is complete. Present the available worlds, explain the differences briefly, and ask the user to choose one world by worldId or display name. After the choice, confirm the selected world before explaining its required fields.',
|
|
480
|
-
user:
|
|
481
|
-
worldLines.length > 0
|
|
482
|
-
? `Available worlds:\n${worldLines.join('\n')}\nAsk the user which world they want to join next.`
|
|
483
|
-
: 'No worlds are currently available. Tell the user setup is complete but no worlds can be selected yet.',
|
|
484
|
-
followUp:
|
|
485
|
-
'After the user chooses a world, confirm the selection, fetch that world detail, explain the required fields, and then use join_world for that world.',
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
export function resolveWorldSelection(worldDirectory = {}, selection = null) {
|
|
490
|
-
const items = Array.isArray(worldDirectory.items)
|
|
491
|
-
? worldDirectory.items.map((world) => normalizeWorldSummary(world))
|
|
492
|
-
: [];
|
|
493
|
-
const normalizedSelection = normalizeSelectionInput(selection);
|
|
494
|
-
|
|
495
|
-
if (items.length === 0) {
|
|
496
|
-
return buildSelectionRetryContract('no_match', normalizedSelection, items);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
let selectedWorld = null;
|
|
500
|
-
let matchedBy = null;
|
|
501
|
-
|
|
502
|
-
if (normalizedSelection.index && normalizedSelection.index >= 1 && normalizedSelection.index <= items.length) {
|
|
503
|
-
selectedWorld = items[normalizedSelection.index - 1];
|
|
504
|
-
matchedBy = 'index';
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
if (!selectedWorld && normalizedSelection.normalized) {
|
|
508
|
-
selectedWorld = items.find((world) => normalizeLookupText(world.worldId) === normalizedSelection.normalized) || null;
|
|
509
|
-
if (selectedWorld) matchedBy = 'worldId';
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (!selectedWorld && normalizedSelection.normalized) {
|
|
513
|
-
selectedWorld = items.find((world) => normalizeLookupText(world.displayName) === normalizedSelection.normalized) || null;
|
|
514
|
-
if (selectedWorld) matchedBy = 'displayName';
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
if (!selectedWorld && normalizedSelection.normalized.length >= 3) {
|
|
518
|
-
const partialMatches = items.filter((world) => (
|
|
519
|
-
normalizeLookupText(world.worldId).includes(normalizedSelection.normalized)
|
|
520
|
-
|| normalizeLookupText(world.displayName).includes(normalizedSelection.normalized)
|
|
521
|
-
));
|
|
522
|
-
|
|
523
|
-
if (partialMatches.length === 1) {
|
|
524
|
-
[selectedWorld] = partialMatches;
|
|
525
|
-
matchedBy = 'partial';
|
|
526
|
-
} else if (partialMatches.length > 1) {
|
|
527
|
-
return buildSelectionRetryContract('ambiguous', normalizedSelection, items, partialMatches);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
if (!selectedWorld) {
|
|
532
|
-
return buildSelectionRetryContract('no_match', normalizedSelection, items);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return {
|
|
536
|
-
status: 'selected',
|
|
537
|
-
selection: {
|
|
538
|
-
input: normalizedSelection.text || null,
|
|
539
|
-
matchedBy,
|
|
540
|
-
worldId: selectedWorld.worldId,
|
|
541
|
-
displayName: selectedWorld.displayName,
|
|
542
|
-
},
|
|
543
|
-
selectedWorld,
|
|
544
|
-
candidateWorlds: items,
|
|
545
|
-
orchestration: {
|
|
546
|
-
stage: 'post_setup_world_selected',
|
|
547
|
-
system: 'Confirm the resolved world choice before fetching detail and collecting participantContextText for join_world.',
|
|
548
|
-
user: `I matched the user choice to ${selectedWorld.displayName} [${selectedWorld.worldId}]. Confirm that this is the world we will use next.`,
|
|
549
|
-
confirmation: `Confirmed world: ${selectedWorld.displayName} [${selectedWorld.worldId}].`,
|
|
550
|
-
followUp: 'Fetch the selected world detail, explain the participant context requirement, and use join_world once participantContextText is available.',
|
|
551
|
-
},
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function buildFieldStepPrompt(field = {}, index = 0, total = 1) {
|
|
556
|
-
const examples = Array.isArray(field.examples) && field.examples.length > 0
|
|
557
|
-
? ` Example: ${field.examples.map((example) => quoteExample(example)).join(' or ')}.`
|
|
558
|
-
: '';
|
|
559
|
-
const description = sentenceCase(
|
|
560
|
-
field.description || `Provide ${field.label} so the world can evaluate the profile`,
|
|
561
|
-
'Provide this field so the world can evaluate the profile.',
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
return `Step ${index + 1} of ${total}: ${field.label}. ${description}${examples}`;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
export function buildRequiredFieldExplanation(worldDetail = {}) {
|
|
568
|
-
const detail = normalizeWorldDetail(worldDetail);
|
|
569
|
-
const field = detail.requiredFields[0];
|
|
570
|
-
const summary = `To join ${detail.displayName}, I need one ${field.label} text.`;
|
|
571
|
-
const steps = [
|
|
572
|
-
{
|
|
573
|
-
step: 1,
|
|
574
|
-
fieldId: field.fieldId,
|
|
575
|
-
label: field.label,
|
|
576
|
-
prompt: buildFieldStepPrompt(field, 0, 1),
|
|
577
|
-
description: field.description,
|
|
578
|
-
examples: field.examples,
|
|
579
|
-
constraints: field.constraints,
|
|
580
|
-
},
|
|
581
|
-
];
|
|
582
|
-
const nextInstruction = steps[0].prompt;
|
|
583
|
-
|
|
584
|
-
return {
|
|
585
|
-
status: 'ready',
|
|
586
|
-
stage: 'post_setup_world_requirements',
|
|
587
|
-
worldId: detail.worldId,
|
|
588
|
-
displayName: detail.displayName,
|
|
589
|
-
requiredFieldCount: 1,
|
|
590
|
-
optionalFieldCount: 0,
|
|
591
|
-
summary,
|
|
592
|
-
steps,
|
|
593
|
-
hints: detail.hints,
|
|
594
|
-
nextAction: detail.nextAction,
|
|
595
|
-
orchestration: {
|
|
596
|
-
stage: 'post_setup_world_requirements',
|
|
597
|
-
system: 'Confirm the selected world, explain the participant context requirement in plain language, and use join_world once that text is available.',
|
|
598
|
-
confirmation: `Confirmed world: ${detail.displayName} [${detail.worldId}].`,
|
|
599
|
-
user: [summary, nextInstruction].filter(Boolean).join('\n\n'),
|
|
600
|
-
followUp: 'After the user provides participantContextText, call join_world.',
|
|
601
|
-
},
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
export function buildCandidateDeliverySummary(candidateFeed = {}, { worldDetail = null, limit = null } = {}) {
|
|
606
|
-
const detail = worldDetail ? normalizeWorldDetail(worldDetail) : null;
|
|
607
|
-
const normalizedFeed = normalizeCandidateFeedResponse(candidateFeed, {
|
|
608
|
-
worldId: detail?.worldId || candidateFeed.worldId || null,
|
|
609
|
-
});
|
|
610
|
-
const summaryLimit = Math.max(
|
|
611
|
-
1,
|
|
612
|
-
normalizeInteger(limit, normalizedFeed.candidates.length || normalizedFeed.totalCandidates || 1),
|
|
613
|
-
);
|
|
614
|
-
const displayName = detail?.displayName || normalizedFeed.worldId || 'the selected world';
|
|
615
|
-
const requestChatAction = {
|
|
616
|
-
action: 'request_chat',
|
|
617
|
-
worldId: normalizedFeed.worldId,
|
|
618
|
-
requiredFields: ['worldId', 'displayName', 'agentCode'],
|
|
619
|
-
summary:
|
|
620
|
-
'After the user chooses a candidate, request_chat with this worldId, displayName, and agentCode.',
|
|
621
|
-
};
|
|
622
|
-
const candidateSummaries = normalizedFeed.candidates.slice(0, summaryLimit).map((candidate, index) => {
|
|
623
|
-
const name = candidate.profileSummary.displayName || `Candidate ${index + 1}`;
|
|
624
|
-
const requiredFieldSummary = summarizeProfileFields(candidate.profileSummary.requiredFields);
|
|
625
|
-
const optionalFieldSummary = summarizeProfileFields(candidate.profileSummary.optionalFields);
|
|
626
|
-
const compatibilitySummary = candidate.compatibilitySignals
|
|
627
|
-
.map((signal) => sentenceCase(signal.summary, ''))
|
|
628
|
-
.filter(Boolean);
|
|
629
|
-
const deliveryReasonSummary = sentenceCase(candidate.deliveryReason.summary, '');
|
|
630
|
-
const availabilitySummary = candidate.online === true ? 'Online now.' : 'Currently offline.';
|
|
631
|
-
const roleSummary = candidate.worldRole ? `World role: ${candidate.worldRole}.` : null;
|
|
632
|
-
const scoreSummary = candidate.score == null
|
|
633
|
-
? null
|
|
634
|
-
: `Score ${candidate.score}${candidate.rank == null ? '' : `, rank ${candidate.rank}`}.`;
|
|
635
|
-
const summary = [
|
|
636
|
-
candidate.profileSummary.headline ? `${name}: ${candidate.profileSummary.headline}.` : `${name}.`,
|
|
637
|
-
requiredFieldSummary.length > 0 ? `Required profile fields: ${requiredFieldSummary.join('; ')}.` : null,
|
|
638
|
-
optionalFieldSummary.length > 0 ? `Optional context: ${optionalFieldSummary.join('; ')}.` : null,
|
|
639
|
-
compatibilitySummary.length > 0 ? compatibilitySummary.join(' ') : null,
|
|
640
|
-
deliveryReasonSummary || null,
|
|
641
|
-
roleSummary,
|
|
642
|
-
availabilitySummary,
|
|
643
|
-
scoreSummary,
|
|
644
|
-
].filter(Boolean).join(' ');
|
|
645
|
-
|
|
646
|
-
return {
|
|
647
|
-
candidateId: candidate.candidateId,
|
|
648
|
-
sourceMembershipId: candidate.sourceMembershipId,
|
|
649
|
-
online: candidate.online === true,
|
|
650
|
-
worldRole: candidate.worldRole,
|
|
651
|
-
agentCode: candidate.agentCode,
|
|
652
|
-
requestChat: candidate.requestChat,
|
|
653
|
-
displayName: name,
|
|
654
|
-
headline: candidate.profileSummary.headline,
|
|
655
|
-
rank: candidate.rank,
|
|
656
|
-
score: candidate.score,
|
|
657
|
-
requiredFieldSummary,
|
|
658
|
-
optionalFieldSummary,
|
|
659
|
-
compatibilitySummary,
|
|
660
|
-
deliveryReasonSummary: deliveryReasonSummary || null,
|
|
661
|
-
worldFeedbackSummary: candidate.worldFeedbackSummary || {
|
|
662
|
-
likesReceived: 0,
|
|
663
|
-
dislikesReceived: 0,
|
|
664
|
-
},
|
|
665
|
-
expiresAt: candidate.expiresAt,
|
|
666
|
-
summary,
|
|
667
|
-
};
|
|
668
|
-
});
|
|
669
|
-
const deliveredCandidateCount = candidateSummaries.length;
|
|
670
|
-
const totalCandidateCount = Math.max(normalizedFeed.totalCandidates, deliveredCandidateCount);
|
|
671
|
-
const remainingCandidateCount = Math.max(totalCandidateCount - deliveredCandidateCount, 0);
|
|
672
|
-
const heading = deliveredCandidateCount > 0
|
|
673
|
-
? `${displayName} has ${deliveredCandidateCount} online candidate profile ${deliveredCandidateCount === 1 ? 'summary' : 'summaries'} ready for review now.`
|
|
674
|
-
: `No online candidate profile summaries are ready for review in ${displayName} yet.`;
|
|
675
|
-
const promptBody = deliveredCandidateCount > 0
|
|
676
|
-
? candidateSummaries.map((summary, index) => buildCandidateDeliverySummaryLine(summary, index)).join('\n\n')
|
|
677
|
-
: 'No online candidates are currently available from the active-membership feed.';
|
|
678
|
-
|
|
679
|
-
return {
|
|
680
|
-
worldId: normalizedFeed.worldId,
|
|
681
|
-
status: deliveredCandidateCount > 0 ? 'candidate_summary_ready' : 'candidate_summary_pending',
|
|
682
|
-
deliveredCandidateCount,
|
|
683
|
-
totalCandidateCount,
|
|
684
|
-
remainingCandidateCount,
|
|
685
|
-
requestChatAction,
|
|
686
|
-
candidateSummaries,
|
|
687
|
-
nextAction: deliveredCandidateCount > 0
|
|
688
|
-
? normalizedFeed.nextAction
|
|
689
|
-
: 'wait_for_more_candidates',
|
|
690
|
-
orchestration: {
|
|
691
|
-
stage: 'post_join_candidate_delivery',
|
|
692
|
-
system:
|
|
693
|
-
'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.',
|
|
694
|
-
confirmation: `Candidate review payload for ${displayName} [${normalizedFeed.worldId}].`,
|
|
695
|
-
user: [heading, promptBody].filter(Boolean).join('\n\n'),
|
|
696
|
-
followUp: deliveredCandidateCount > 0
|
|
697
|
-
? (remainingCandidateCount > 0
|
|
698
|
-
? `Share these ${deliveredCandidateCount} candidate summaries first. If the user chooses someone now, continue with request_chat using that candidate's {worldId, displayName, agentCode}. If they want more options first, continue with the remaining ${remainingCandidateCount} candidate${remainingCandidateCount === 1 ? '' : 's'} from the same feed.`
|
|
699
|
-
: 'Share these candidate summaries and, if the user chooses one, continue with request_chat using the attached {worldId, displayName, agentCode} payload for that candidate.')
|
|
700
|
-
: 'Tell the user candidate delivery can be retried later through the same backend-authored world flow.',
|
|
701
|
-
},
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
export function buildResolvedWorldJoinOrchestration({
|
|
706
|
-
joinResult = null,
|
|
707
|
-
candidateDelivery = null,
|
|
708
|
-
} = {}) {
|
|
709
|
-
const joinOrchestration = joinResult?.orchestration && typeof joinResult.orchestration === 'object' && !Array.isArray(joinResult.orchestration)
|
|
710
|
-
? joinResult.orchestration
|
|
711
|
-
: null;
|
|
712
|
-
const candidateOrchestration = candidateDelivery?.orchestration && typeof candidateDelivery.orchestration === 'object' && !Array.isArray(candidateDelivery.orchestration)
|
|
713
|
-
? candidateDelivery.orchestration
|
|
714
|
-
: null;
|
|
715
|
-
|
|
716
|
-
if (!candidateOrchestration) return joinOrchestration;
|
|
717
|
-
|
|
718
|
-
return {
|
|
719
|
-
stage: normalizeText(candidateOrchestration.stage, normalizeText(joinOrchestration?.stage, null)),
|
|
720
|
-
system: normalizeText(candidateOrchestration.system, normalizeText(joinOrchestration?.system, null)),
|
|
721
|
-
confirmation: normalizeText(
|
|
722
|
-
joinOrchestration?.confirmation,
|
|
723
|
-
normalizeText(candidateOrchestration.confirmation, null),
|
|
724
|
-
),
|
|
725
|
-
user: [
|
|
726
|
-
normalizeText(joinOrchestration?.user, normalizeText(joinOrchestration?.confirmation, null)),
|
|
727
|
-
normalizeText(candidateOrchestration.user, null),
|
|
728
|
-
].filter(Boolean).join('\n\n'),
|
|
729
|
-
followUp: normalizeText(
|
|
730
|
-
candidateOrchestration.followUp,
|
|
731
|
-
normalizeText(joinOrchestration?.followUp, null),
|
|
732
|
-
),
|
|
733
|
-
};
|
|
734
|
-
}
|