@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,931 +0,0 @@
|
|
|
1
|
-
import { resolveClaworldRuntimeConfig } from '../plugin/config-schema.js';
|
|
2
|
-
import { buildRuntimeAuthHeaders } from '../plugin/account-identity.js';
|
|
3
|
-
import { createRuntimeBoundaryError } from '../../lib/runtime-errors.js';
|
|
4
|
-
import { extractBackendErrorContext } from './backend-error-context.js';
|
|
5
|
-
import {
|
|
6
|
-
buildCandidateDeliverySummary as buildBackendCandidateDeliverySummary,
|
|
7
|
-
resolveWorldSelection as resolveBackendWorldSelection,
|
|
8
|
-
} from '../../product-shell/contracts/world-orchestration.js';
|
|
9
|
-
|
|
10
|
-
function normalizeText(value, fallback = null) {
|
|
11
|
-
if (value == null) return fallback;
|
|
12
|
-
const normalized = String(value).trim();
|
|
13
|
-
return normalized || fallback;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function normalizeInteger(value, fallback = 0) {
|
|
17
|
-
const parsed = Number(value);
|
|
18
|
-
if (!Number.isFinite(parsed)) return fallback;
|
|
19
|
-
return Math.max(0, Math.trunc(parsed));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function normalizeStringList(values = []) {
|
|
23
|
-
if (!Array.isArray(values)) return [];
|
|
24
|
-
return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function normalizeWorldRole(worldRole, fallback = null) {
|
|
28
|
-
const normalized = normalizeText(worldRole, fallback);
|
|
29
|
-
return ['owner', 'member'].includes(normalized) ? normalized : fallback;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function sentenceCase(value, fallback = '') {
|
|
33
|
-
const normalized = normalizeText(value, fallback);
|
|
34
|
-
if (!normalized) return fallback;
|
|
35
|
-
return /[.!?]$/.test(normalized) ? normalized : `${normalized}.`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function quoteExample(example) {
|
|
39
|
-
return `"${String(example).trim()}"`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function joinAsNaturalLanguage(values = []) {
|
|
43
|
-
const items = values.filter(Boolean);
|
|
44
|
-
if (items.length === 0) return '';
|
|
45
|
-
if (items.length === 1) return items[0];
|
|
46
|
-
if (items.length === 2) return `${items[0]} and ${items[1]}`;
|
|
47
|
-
return `${items.slice(0, -1).join(', ')}, and ${items.at(-1)}`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function normalizeWorldSummary(world = {}) {
|
|
51
|
-
const summary = world.agentSummary && typeof world.agentSummary === 'object' ? world.agentSummary : world;
|
|
52
|
-
const rawWorldId = world.worldId || summary.worldId;
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
worldId: normalizeText(rawWorldId, 'unknown-world'),
|
|
56
|
-
displayName: normalizeText(summary.displayName || world.displayName, normalizeText(rawWorldId, 'Unknown World')),
|
|
57
|
-
summary: normalizeText(summary.summary || world.summary, null),
|
|
58
|
-
worldContextText: normalizeText(summary.worldContextText || world.worldContextText, ''),
|
|
59
|
-
hotness: normalizeInteger(summary.hotness || world.hotness || world.activatedMemberCount, 0),
|
|
60
|
-
activatedMemberCount: normalizeInteger(summary.activatedMemberCount || world.activatedMemberCount || summary.hotness || world.hotness, 0),
|
|
61
|
-
tags: normalizeStringList(summary.tags || world.tags),
|
|
62
|
-
matchScore: normalizeInteger(summary.matchScore || world.matchScore, 0),
|
|
63
|
-
matchedFieldIds: normalizeStringList(summary.matchedFieldIds || world.matchedFieldIds),
|
|
64
|
-
matchedTerms: normalizeStringList(summary.matchedTerms || world.matchedTerms),
|
|
65
|
-
reasonSummary: normalizeText(summary.reasonSummary || world.reasonSummary, null),
|
|
66
|
-
requiredFieldCount: normalizeInteger(summary.requiredFieldCount || world.requiredFieldCount, 0),
|
|
67
|
-
detailAction: world.detailAction && typeof world.detailAction === 'object' ? world.detailAction : null,
|
|
68
|
-
joinAction: world.joinAction && typeof world.joinAction === 'object' ? world.joinAction : null,
|
|
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 buildParticipantContextField(field = null) {
|
|
87
|
-
if (field && typeof field === 'object' && !Array.isArray(field)) {
|
|
88
|
-
return normalizeField(field, 0, { required: true });
|
|
89
|
-
}
|
|
90
|
-
return normalizeField({
|
|
91
|
-
fieldId: 'participantContextText',
|
|
92
|
-
label: 'Entry Profile',
|
|
93
|
-
type: 'string',
|
|
94
|
-
source: 'membership',
|
|
95
|
-
required: true,
|
|
96
|
-
description: 'A short text describing who you are in this world and what context you bring into it.',
|
|
97
|
-
examples: [],
|
|
98
|
-
constraints: {},
|
|
99
|
-
}, 0, { required: true });
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function normalizeSearchSchema(payload = {}, { worldId = null, fallbackFields = [] } = {}) {
|
|
103
|
-
const rawInputFields = Array.isArray(payload.inputFields) && payload.inputFields.length > 0
|
|
104
|
-
? payload.inputFields
|
|
105
|
-
: fallbackFields;
|
|
106
|
-
const inputFields = rawInputFields.map((field, index) => normalizeField(field, index, { required: false }));
|
|
107
|
-
const inputFieldIds = normalizeStringList(
|
|
108
|
-
Array.isArray(payload.inputFieldIds)
|
|
109
|
-
? payload.inputFieldIds
|
|
110
|
-
: inputFields.map((field) => field.fieldId),
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
modelId: normalizeText(payload.modelId, worldId ? `${worldId}.search.v1` : 'world.search.v1'),
|
|
115
|
-
worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
|
|
116
|
-
mode: normalizeText(payload.mode, 'membership_profile_search'),
|
|
117
|
-
previewRoute: normalizeText(payload.previewRoute, worldId ? `/v1/worlds/${worldId}/search` : '/v1/worlds/:worldId/search'),
|
|
118
|
-
inputFieldIds,
|
|
119
|
-
inputFields,
|
|
120
|
-
resultFields: normalizeStringList(payload.resultFields),
|
|
121
|
-
viewerRequirement: normalizeText(payload.viewerRequirement, 'active_membership'),
|
|
122
|
-
onlineOnly: payload.onlineOnly !== false,
|
|
123
|
-
defaultLimit: normalizeInteger(payload.defaultLimit, 10),
|
|
124
|
-
summary: normalizeText(payload.summary, ''),
|
|
125
|
-
hints: normalizeStringList(payload.hints),
|
|
126
|
-
status: normalizeText(payload.status, 'phase1_world_search'),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function normalizeWorldDetail(payload = {}) {
|
|
131
|
-
if (Array.isArray(payload.requiredFields) || Array.isArray(payload.optionalFields)) {
|
|
132
|
-
const requiredFields = Array.isArray(payload.requiredFields)
|
|
133
|
-
? payload.requiredFields.map((field, index) => normalizeField(field, index, { required: true }))
|
|
134
|
-
: [];
|
|
135
|
-
const optionalFields = Array.isArray(payload.optionalFields)
|
|
136
|
-
? payload.optionalFields.map((field, index) => normalizeField(field, index, { required: false }))
|
|
137
|
-
: [];
|
|
138
|
-
const normalizedWorldId = normalizeText(payload.worldId, 'unknown-world');
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
status: normalizeText(payload.status, 'ready'),
|
|
142
|
-
source: normalizeText(payload.source, 'product_shell'),
|
|
143
|
-
worldId: normalizedWorldId,
|
|
144
|
-
displayName: normalizeText(payload.displayName, normalizedWorldId),
|
|
145
|
-
worldContextText: normalizeText(payload.worldContextText, ''),
|
|
146
|
-
ownerAgentId: normalizeText(payload.ownerAgentId, null),
|
|
147
|
-
worldRole: normalizeWorldRole(payload.worldRole, null),
|
|
148
|
-
enabled: typeof payload.enabled === 'boolean' ? payload.enabled : null,
|
|
149
|
-
requiredFieldCount: normalizeInteger(payload.requiredFieldCount, requiredFields.length) || requiredFields.length,
|
|
150
|
-
optionalFieldCount: normalizeInteger(payload.optionalFieldCount, optionalFields.length) || optionalFields.length,
|
|
151
|
-
requiredFields,
|
|
152
|
-
optionalFields,
|
|
153
|
-
hints: normalizeStringList(payload.hints),
|
|
154
|
-
nextAction: normalizeText(payload.nextAction, 'call_join_world'),
|
|
155
|
-
searchSchema: normalizeSearchSchema(payload.searchSchema || {}, {
|
|
156
|
-
worldId: normalizedWorldId,
|
|
157
|
-
fallbackFields: requiredFields,
|
|
158
|
-
}),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const world = payload.world && typeof payload.world === 'object' ? payload.world : {};
|
|
163
|
-
const management = payload.management && typeof payload.management === 'object' ? payload.management : {};
|
|
164
|
-
const joinSchema = payload.joinSchema && typeof payload.joinSchema === 'object' ? payload.joinSchema : {};
|
|
165
|
-
const fieldGuide = payload.fieldGuide && typeof payload.fieldGuide === 'object' ? payload.fieldGuide : {};
|
|
166
|
-
const searchOverview = payload.searchSchema && typeof payload.searchSchema === 'object'
|
|
167
|
-
? payload.searchSchema
|
|
168
|
-
: {};
|
|
169
|
-
const participantContextField = buildParticipantContextField(
|
|
170
|
-
payload.participantContextField
|
|
171
|
-
|| (Array.isArray(fieldGuide.required) ? fieldGuide.required[0] : null)
|
|
172
|
-
|| (Array.isArray(joinSchema.requiredFields) ? joinSchema.requiredFields[0] : null),
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
const requiredFields = [participantContextField];
|
|
176
|
-
const optionalFields = [];
|
|
177
|
-
const worldId = normalizeText(world.worldId || joinSchema.worldId, 'unknown-world');
|
|
178
|
-
const displayName = normalizeText(world.displayName, worldId);
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
status: 'ready',
|
|
182
|
-
source: 'product_shell',
|
|
183
|
-
worldId,
|
|
184
|
-
displayName,
|
|
185
|
-
worldContextText: normalizeText(world.worldContextText || payload.worldContextText, ''),
|
|
186
|
-
ownerAgentId: normalizeText(management.ownerAgentId, null),
|
|
187
|
-
worldRole: normalizeWorldRole(payload.worldRole, null),
|
|
188
|
-
enabled: typeof management.enabled === 'boolean' ? management.enabled : null,
|
|
189
|
-
statusLabel: normalizeText(management.status, null),
|
|
190
|
-
requiredFieldCount: 1,
|
|
191
|
-
optionalFieldCount: 0,
|
|
192
|
-
requiredFields,
|
|
193
|
-
optionalFields,
|
|
194
|
-
participantContextField,
|
|
195
|
-
hints: [],
|
|
196
|
-
nextAction: normalizeText(joinSchema.nextAction, 'call_join_world'),
|
|
197
|
-
searchSchema: normalizeSearchSchema(searchOverview, {
|
|
198
|
-
worldId,
|
|
199
|
-
fallbackFields: [...requiredFields, ...optionalFields],
|
|
200
|
-
}),
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function normalizeNumber(value, fallback = null) {
|
|
205
|
-
const parsed = Number(value);
|
|
206
|
-
if (!Number.isFinite(parsed)) return fallback;
|
|
207
|
-
return parsed;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function normalizeProfileSummaryField(field = {}, index = 0) {
|
|
211
|
-
const fieldId = normalizeText(field.fieldId || field.id, `field_${index + 1}`);
|
|
212
|
-
const value = Array.isArray(field.value)
|
|
213
|
-
? normalizeStringList(field.value)
|
|
214
|
-
: normalizeText(field.value, null);
|
|
215
|
-
|
|
216
|
-
if (value == null || (Array.isArray(value) && value.length === 0)) {
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
fieldId,
|
|
222
|
-
label: normalizeText(field.label, fieldId),
|
|
223
|
-
value,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function normalizeCandidateProfileSummary(summary = {}) {
|
|
228
|
-
return {
|
|
229
|
-
displayName: normalizeText(summary.displayName, null),
|
|
230
|
-
headline: normalizeText(summary.headline, null),
|
|
231
|
-
requiredFields: Array.isArray(summary.requiredFields)
|
|
232
|
-
? summary.requiredFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
|
|
233
|
-
: [],
|
|
234
|
-
optionalFields: Array.isArray(summary.optionalFields)
|
|
235
|
-
? summary.optionalFields.map((field, index) => normalizeProfileSummaryField(field, index)).filter(Boolean)
|
|
236
|
-
: [],
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function normalizeSearchAction(action = null) {
|
|
241
|
-
if (!action || typeof action !== 'object' || Array.isArray(action)) return null;
|
|
242
|
-
const payload = action.payload && typeof action.payload === 'object' && !Array.isArray(action.payload)
|
|
243
|
-
? action.payload
|
|
244
|
-
: {};
|
|
245
|
-
const payloadTemplate = action.payloadTemplate && typeof action.payloadTemplate === 'object' && !Array.isArray(action.payloadTemplate)
|
|
246
|
-
? action.payloadTemplate
|
|
247
|
-
: {};
|
|
248
|
-
return {
|
|
249
|
-
tool: normalizeText(action.tool, null),
|
|
250
|
-
summary: normalizeText(action.summary, null),
|
|
251
|
-
payload,
|
|
252
|
-
payloadTemplate,
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function normalizeCompatibilitySignal(signal = {}, index = 0) {
|
|
257
|
-
return {
|
|
258
|
-
signalId: normalizeText(signal.signalId, `signal_${index + 1}`),
|
|
259
|
-
type: normalizeText(signal.type, 'world_ready'),
|
|
260
|
-
fieldIds: normalizeStringList(signal.fieldIds),
|
|
261
|
-
score: normalizeNumber(signal.score, 0),
|
|
262
|
-
summary: normalizeText(signal.summary, ''),
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function normalizeDeliveryReason(reason = {}) {
|
|
267
|
-
return {
|
|
268
|
-
code: normalizeText(reason.code, null),
|
|
269
|
-
matchedFieldIds: normalizeStringList(reason.matchedFieldIds),
|
|
270
|
-
summary: normalizeText(reason.summary, ''),
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function normalizeCandidate(candidate = {}, index = 0) {
|
|
275
|
-
const normalizedRank = normalizeNumber(candidate.rank, null);
|
|
276
|
-
const displayName = normalizeText(
|
|
277
|
-
candidate.displayName || candidate.profileSummary?.displayName || candidate.requestChat?.displayName,
|
|
278
|
-
null,
|
|
279
|
-
);
|
|
280
|
-
const agentCode = normalizeText(
|
|
281
|
-
candidate.agentCode || candidate.requestChat?.agentCode,
|
|
282
|
-
null,
|
|
283
|
-
)?.toUpperCase() || null;
|
|
284
|
-
const requestChat = displayName && agentCode
|
|
285
|
-
? {
|
|
286
|
-
worldId: normalizeText(candidate.requestChat?.worldId, normalizeText(candidate.worldId, 'unknown-world')),
|
|
287
|
-
displayName,
|
|
288
|
-
agentCode,
|
|
289
|
-
}
|
|
290
|
-
: null;
|
|
291
|
-
|
|
292
|
-
return {
|
|
293
|
-
candidateId: normalizeText(candidate.candidateId, `candidate_${index + 1}`),
|
|
294
|
-
worldId: normalizeText(candidate.worldId, 'unknown-world'),
|
|
295
|
-
worldRole: normalizeWorldRole(candidate.worldRole, null),
|
|
296
|
-
sourceMembershipId: normalizeText(candidate.sourceMembershipId, null),
|
|
297
|
-
online: candidate.online === true,
|
|
298
|
-
displayName,
|
|
299
|
-
agentCode,
|
|
300
|
-
requestChat,
|
|
301
|
-
profileSummary: normalizeCandidateProfileSummary(candidate.profileSummary),
|
|
302
|
-
compatibilitySignals: Array.isArray(candidate.compatibilitySignals)
|
|
303
|
-
? candidate.compatibilitySignals.map((signal, signalIndex) => normalizeCompatibilitySignal(signal, signalIndex))
|
|
304
|
-
: [],
|
|
305
|
-
deliveryReason: normalizeDeliveryReason(candidate.deliveryReason),
|
|
306
|
-
worldFeedbackSummary: candidate.worldFeedbackSummary && typeof candidate.worldFeedbackSummary === 'object'
|
|
307
|
-
? {
|
|
308
|
-
likesReceived: normalizeInteger(candidate.worldFeedbackSummary.likesReceived, 0),
|
|
309
|
-
dislikesReceived: normalizeInteger(candidate.worldFeedbackSummary.dislikesReceived, 0),
|
|
310
|
-
}
|
|
311
|
-
: {
|
|
312
|
-
likesReceived: 0,
|
|
313
|
-
dislikesReceived: 0,
|
|
314
|
-
},
|
|
315
|
-
expiresAt: normalizeText(candidate.expiresAt, null),
|
|
316
|
-
joinedAt: normalizeText(candidate.joinedAt, null),
|
|
317
|
-
rank: normalizedRank == null ? null : Math.max(1, Math.trunc(normalizedRank)),
|
|
318
|
-
score: normalizeNumber(candidate.score, null),
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
function normalizeCandidateFeedResponse(payload = {}, { worldId = null, agentId = null } = {}) {
|
|
323
|
-
const candidates = Array.isArray(payload.candidates)
|
|
324
|
-
? payload.candidates.map((candidate, index) => normalizeCandidate(candidate, index))
|
|
325
|
-
: [];
|
|
326
|
-
|
|
327
|
-
return {
|
|
328
|
-
worldId: normalizeText(payload.worldId, worldId || 'unknown-world'),
|
|
329
|
-
agentId: normalizeText(payload.agentId, agentId || null),
|
|
330
|
-
viewerMembershipId: normalizeText(payload.viewerMembershipId, null),
|
|
331
|
-
generatedAt: normalizeText(payload.generatedAt, null),
|
|
332
|
-
expiresAt: normalizeText(payload.expiresAt, null),
|
|
333
|
-
deliveryMode: normalizeText(payload.deliveryMode, 'agent_review_before_live_session'),
|
|
334
|
-
nextAction: normalizeText(
|
|
335
|
-
payload.nextAction,
|
|
336
|
-
candidates.length > 0 ? 'review_candidates_then_request_chat' : 'wait_for_more_candidates',
|
|
337
|
-
),
|
|
338
|
-
candidateDelivery: payload.candidateDelivery && typeof payload.candidateDelivery === 'object'
|
|
339
|
-
? payload.candidateDelivery
|
|
340
|
-
: null,
|
|
341
|
-
candidateSource: normalizeText(payload.candidateSource, 'active_memberships_online'),
|
|
342
|
-
candidateModel: payload.candidateModel && typeof payload.candidateModel === 'object' ? payload.candidateModel : {},
|
|
343
|
-
strategy: payload.strategy && typeof payload.strategy === 'object' ? payload.strategy : {},
|
|
344
|
-
limit: normalizeInteger(payload.limit, candidates.length),
|
|
345
|
-
totalCandidates: normalizeInteger(payload.totalCandidates, candidates.length),
|
|
346
|
-
status: normalizeText(payload.status, candidates.length > 0 ? 'feed_ready' : 'no_candidates_ready'),
|
|
347
|
-
candidates,
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function normalizeWorldJoinResponse(payload = {}, { worldId = null, agentId = null } = {}) {
|
|
352
|
-
const membership = payload.membership && typeof payload.membership === 'object' ? payload.membership : null;
|
|
353
|
-
const normalizedWorldId = normalizeText(payload.worldId, worldId || 'unknown-world');
|
|
354
|
-
const normalizedAgentId = normalizeText(payload.agentId || membership?.agentId, agentId || null);
|
|
355
|
-
const membershipStatus = normalizeText(payload.membershipStatus || membership?.status, 'unknown');
|
|
356
|
-
const candidateFeed = payload.candidateFeed && typeof payload.candidateFeed === 'object'
|
|
357
|
-
? normalizeCandidateFeedResponse(payload.candidateFeed, {
|
|
358
|
-
worldId: normalizedWorldId,
|
|
359
|
-
agentId: normalizedAgentId,
|
|
360
|
-
})
|
|
361
|
-
: null;
|
|
362
|
-
|
|
363
|
-
return {
|
|
364
|
-
status: normalizeText(payload.status, membershipStatus === 'active' ? 'joined' : 'accepted'),
|
|
365
|
-
worldId: normalizedWorldId,
|
|
366
|
-
agentId: normalizedAgentId,
|
|
367
|
-
worldRole: normalizeWorldRole(payload.worldRole, null),
|
|
368
|
-
membershipStatus,
|
|
369
|
-
participantContextText: normalizeText(
|
|
370
|
-
payload.participantContextText,
|
|
371
|
-
membership?.participantContextText || null,
|
|
372
|
-
),
|
|
373
|
-
membership,
|
|
374
|
-
nextAction: normalizeText(
|
|
375
|
-
payload.nextAction,
|
|
376
|
-
membershipStatus === 'active' ? 'review_candidate_feed' : null,
|
|
377
|
-
),
|
|
378
|
-
nextStageSummary: payload.nextStageSummary && typeof payload.nextStageSummary === 'object'
|
|
379
|
-
? payload.nextStageSummary
|
|
380
|
-
: {},
|
|
381
|
-
candidateFeed,
|
|
382
|
-
candidateDelivery: payload.candidateDelivery && typeof payload.candidateDelivery === 'object'
|
|
383
|
-
? payload.candidateDelivery
|
|
384
|
-
: null,
|
|
385
|
-
orchestration: payload.orchestration && typeof payload.orchestration === 'object'
|
|
386
|
-
? payload.orchestration
|
|
387
|
-
: null,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function summarizeProfileValue(value) {
|
|
392
|
-
if (Array.isArray(value)) return joinAsNaturalLanguage(value.map((entry) => String(entry).trim()).filter(Boolean));
|
|
393
|
-
return normalizeText(value, '');
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function summarizeProfileFields(fields = []) {
|
|
397
|
-
return fields
|
|
398
|
-
.map((field) => {
|
|
399
|
-
const value = summarizeProfileValue(field.value);
|
|
400
|
-
if (!value) return null;
|
|
401
|
-
return `${field.label}: ${value}`;
|
|
402
|
-
})
|
|
403
|
-
.filter(Boolean);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function buildCandidateDeliverySummaryLine(candidateSummary = {}, index = 0) {
|
|
407
|
-
return `${index + 1}. ${candidateSummary.summary}`;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
export function buildCandidateDeliverySummary(candidateFeed = {}, { worldDetail = null, limit = null } = {}) {
|
|
411
|
-
if (candidateFeed?.candidateDelivery && typeof candidateFeed.candidateDelivery === 'object') {
|
|
412
|
-
return candidateFeed.candidateDelivery;
|
|
413
|
-
}
|
|
414
|
-
if (worldDetail?.candidateDelivery && typeof worldDetail.candidateDelivery === 'object') {
|
|
415
|
-
return worldDetail.candidateDelivery;
|
|
416
|
-
}
|
|
417
|
-
return buildBackendCandidateDeliverySummary(candidateFeed, { worldDetail, limit });
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
export function buildWorldSelectionPrompt(worldDirectory = {}) {
|
|
421
|
-
return worldDirectory?.orchestration && typeof worldDirectory.orchestration === 'object'
|
|
422
|
-
? worldDirectory.orchestration
|
|
423
|
-
: null;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
export function buildPostSetupWorldDirectory(payload = {}, {
|
|
427
|
-
accountId = null,
|
|
428
|
-
statusMode = 'directory',
|
|
429
|
-
} = {}) {
|
|
430
|
-
const items = Array.isArray(payload.items) ? payload.items.map((world) => normalizeWorldSummary(world)) : [];
|
|
431
|
-
const recommendedWorldId = items[0]?.worldId || null;
|
|
432
|
-
const pagination = payload.pagination && typeof payload.pagination === 'object'
|
|
433
|
-
? {
|
|
434
|
-
page: normalizeInteger(payload.pagination.page, 1) || 1,
|
|
435
|
-
totalPages: normalizeInteger(payload.pagination.totalPages, 0),
|
|
436
|
-
totalCount: normalizeInteger(payload.pagination.totalCount, items.length),
|
|
437
|
-
}
|
|
438
|
-
: {
|
|
439
|
-
page: 1,
|
|
440
|
-
totalPages: items.length > 0 ? 1 : 0,
|
|
441
|
-
totalCount: items.length,
|
|
442
|
-
};
|
|
443
|
-
const mode = normalizeText(payload.mode, 'browse');
|
|
444
|
-
const sort = normalizeText(payload.sort, 'hot');
|
|
445
|
-
const statusFallback = items.length > 0
|
|
446
|
-
? (statusMode === 'search' ? 'search_ready' : 'ready')
|
|
447
|
-
: 'no_matches';
|
|
448
|
-
const normalizedStatus = normalizeText(
|
|
449
|
-
statusMode === 'directory' && mode === 'browse' && payload.status === 'search_ready'
|
|
450
|
-
? 'ready'
|
|
451
|
-
: payload.status,
|
|
452
|
-
statusFallback,
|
|
453
|
-
);
|
|
454
|
-
|
|
455
|
-
return {
|
|
456
|
-
status: normalizedStatus,
|
|
457
|
-
source: 'product_shell',
|
|
458
|
-
accountId: normalizeText(accountId, null),
|
|
459
|
-
mode,
|
|
460
|
-
query: normalizeText(payload.query, null),
|
|
461
|
-
worldCount: pagination.totalCount,
|
|
462
|
-
recommendedWorldId,
|
|
463
|
-
items,
|
|
464
|
-
pagination,
|
|
465
|
-
sort,
|
|
466
|
-
nextAction: normalizeText(payload.nextAction, items.length > 0 ? 'inspect_world_detail_or_join_world' : 'broaden_world_search'),
|
|
467
|
-
orchestration: payload.orchestration && typeof payload.orchestration === 'object'
|
|
468
|
-
? payload.orchestration
|
|
469
|
-
: null,
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function normalizeWorldMemberSearchItem(item = {}) {
|
|
474
|
-
return {
|
|
475
|
-
membershipId: normalizeText(item.membershipId, null),
|
|
476
|
-
worldId: normalizeText(item.worldId, null),
|
|
477
|
-
displayName: normalizeText(item.displayName, null),
|
|
478
|
-
agentCode: normalizeText(item.agentCode, null)?.toUpperCase() || null,
|
|
479
|
-
requestChat: item.requestChat && typeof item.requestChat === 'object' && !Array.isArray(item.requestChat)
|
|
480
|
-
? item.requestChat
|
|
481
|
-
: null,
|
|
482
|
-
headline: normalizeText(item.headline, null),
|
|
483
|
-
online: item.online === true,
|
|
484
|
-
score: normalizeInteger(item.score, 0),
|
|
485
|
-
matchedFieldIds: normalizeStringList(item.matchedFieldIds),
|
|
486
|
-
reasonSummary: normalizeText(item.reasonSummary, null),
|
|
487
|
-
joinedAt: normalizeText(item.joinedAt, null),
|
|
488
|
-
profileSummary: normalizeCandidateProfileSummary(item.profileSummary || {}),
|
|
489
|
-
worldFeedbackSummary: item.worldFeedbackSummary && typeof item.worldFeedbackSummary === 'object' && !Array.isArray(item.worldFeedbackSummary)
|
|
490
|
-
? {
|
|
491
|
-
likesReceived: normalizeInteger(item.worldFeedbackSummary.likesReceived, 0),
|
|
492
|
-
dislikesReceived: normalizeInteger(item.worldFeedbackSummary.dislikesReceived, 0),
|
|
493
|
-
}
|
|
494
|
-
: {
|
|
495
|
-
likesReceived: 0,
|
|
496
|
-
dislikesReceived: 0,
|
|
497
|
-
},
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
export function normalizeWorldMemberSearchResponse(payload = {}, { accountId = null } = {}) {
|
|
502
|
-
const items = Array.isArray(payload.items)
|
|
503
|
-
? payload.items.map((item) => normalizeWorldMemberSearchItem(item))
|
|
504
|
-
: [];
|
|
505
|
-
|
|
506
|
-
return {
|
|
507
|
-
status: normalizeText(payload.status, items.length > 0 ? 'search_ready' : 'no_matches'),
|
|
508
|
-
source: 'product_shell',
|
|
509
|
-
accountId: normalizeText(accountId, null),
|
|
510
|
-
worldId: normalizeText(payload.worldId, null),
|
|
511
|
-
query: normalizeText(payload.query, null),
|
|
512
|
-
sort: normalizeText(payload.sort, 'match'),
|
|
513
|
-
limit: normalizeInteger(payload.limit, items.length),
|
|
514
|
-
totalMatches: normalizeInteger(payload.totalMatches, items.length),
|
|
515
|
-
nextAction: normalizeText(payload.nextAction, items.length > 0 ? 'request_chat_with_selected_candidate' : 'broaden_search_or_refresh_candidate_feed'),
|
|
516
|
-
items,
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
export function resolveWorldSelection(worldDirectory = {}, selection = null) {
|
|
521
|
-
return resolveBackendWorldSelection(worldDirectory, selection);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
async function fetchJson(fetchImpl, url, init = {}) {
|
|
525
|
-
let response;
|
|
526
|
-
try {
|
|
527
|
-
response = await fetchImpl(url, init);
|
|
528
|
-
} catch (error) {
|
|
529
|
-
throw createRuntimeBoundaryError({
|
|
530
|
-
code: 'relay_fetch_failed',
|
|
531
|
-
category: 'transport',
|
|
532
|
-
status: 502,
|
|
533
|
-
message: `fetch failed: ${error?.message || String(error)}`,
|
|
534
|
-
publicMessage: 'relay fetch failed',
|
|
535
|
-
recoverable: true,
|
|
536
|
-
context: {
|
|
537
|
-
fetchUrl: url,
|
|
538
|
-
fetchMethod: init?.method || 'GET',
|
|
539
|
-
},
|
|
540
|
-
cause: error,
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
let body = null;
|
|
544
|
-
|
|
545
|
-
try {
|
|
546
|
-
body = await response.json();
|
|
547
|
-
} catch {
|
|
548
|
-
body = null;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
return { ok: response.ok, status: response.status, body };
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
function normalizeRelayHttpBaseUrl(serverUrl) {
|
|
555
|
-
const parsed = new URL(serverUrl);
|
|
556
|
-
if (parsed.protocol === 'ws:') parsed.protocol = 'http:';
|
|
557
|
-
if (parsed.protocol === 'wss:') parsed.protocol = 'https:';
|
|
558
|
-
parsed.pathname = '';
|
|
559
|
-
parsed.search = '';
|
|
560
|
-
parsed.hash = '';
|
|
561
|
-
return parsed.toString().replace(/\/$/, '');
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
function inferHttpErrorCategory(status) {
|
|
565
|
-
if (status === 401) return 'auth';
|
|
566
|
-
if (status === 403) return 'policy';
|
|
567
|
-
if (status === 409) return 'conflict';
|
|
568
|
-
if (status >= 400 && status < 500) return 'input';
|
|
569
|
-
return 'runtime';
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
function createProductShellHttpError(action, response, { accountId = null, worldId = null } = {}) {
|
|
573
|
-
const backendCode = normalizeText(response?.body?.error, null);
|
|
574
|
-
const backendMessage = normalizeText(response?.body?.message, `claworld product-shell ${action} failed`);
|
|
575
|
-
|
|
576
|
-
return createRuntimeBoundaryError({
|
|
577
|
-
code: backendCode || `claworld_product_shell_${action}_failed`,
|
|
578
|
-
category: inferHttpErrorCategory(response?.status),
|
|
579
|
-
status: response?.status ?? 500,
|
|
580
|
-
message: `claworld product-shell ${action} failed: ${response?.status ?? 500}`,
|
|
581
|
-
publicMessage: backendMessage,
|
|
582
|
-
recoverable: Number(response?.status) >= 400 && Number(response?.status) < 500,
|
|
583
|
-
context: {
|
|
584
|
-
action,
|
|
585
|
-
accountId,
|
|
586
|
-
...(worldId ? { worldId } : {}),
|
|
587
|
-
httpStatus: response?.status ?? 500,
|
|
588
|
-
...extractBackendErrorContext(response?.body),
|
|
589
|
-
},
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
export async function fetchWorldDetail({
|
|
594
|
-
cfg = {},
|
|
595
|
-
accountId = null,
|
|
596
|
-
runtimeConfig = null,
|
|
597
|
-
worldId = null,
|
|
598
|
-
fetchImpl,
|
|
599
|
-
logger = console,
|
|
600
|
-
} = {}) {
|
|
601
|
-
if (typeof fetchImpl !== 'function') {
|
|
602
|
-
throw new Error('fetch is unavailable for claworld product-shell detail helper');
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
const resolvedWorldId = normalizeText(worldId, null);
|
|
606
|
-
if (!resolvedWorldId) {
|
|
607
|
-
throw new Error('claworld product-shell detail helper requires worldId');
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
611
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
612
|
-
const detail = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}`, {
|
|
613
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
614
|
-
accept: 'application/json',
|
|
615
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
616
|
-
}),
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
if (!detail.ok) {
|
|
620
|
-
logger.error?.('[claworld:product-shell] world detail fetch failed', {
|
|
621
|
-
status: detail.status,
|
|
622
|
-
worldId: resolvedWorldId,
|
|
623
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
624
|
-
body: detail.body,
|
|
625
|
-
});
|
|
626
|
-
throw createProductShellHttpError('world_detail', detail, {
|
|
627
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
628
|
-
worldId: resolvedWorldId,
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
return normalizeWorldDetail(detail.body);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
export async function searchWorlds({
|
|
636
|
-
cfg = {},
|
|
637
|
-
accountId = null,
|
|
638
|
-
runtimeConfig = null,
|
|
639
|
-
query = null,
|
|
640
|
-
limit = null,
|
|
641
|
-
sort = null,
|
|
642
|
-
page = null,
|
|
643
|
-
fetchImpl,
|
|
644
|
-
logger = console,
|
|
645
|
-
} = {}) {
|
|
646
|
-
if (typeof fetchImpl !== 'function') {
|
|
647
|
-
throw new Error('fetch is unavailable for claworld product-shell world search helper');
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
651
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
652
|
-
const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/search`, {
|
|
653
|
-
method: 'POST',
|
|
654
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
655
|
-
accept: 'application/json',
|
|
656
|
-
'content-type': 'application/json',
|
|
657
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
658
|
-
}),
|
|
659
|
-
body: JSON.stringify({
|
|
660
|
-
query: normalizeText(query, null),
|
|
661
|
-
sort: normalizeText(sort, null),
|
|
662
|
-
limit: limit == null ? null : normalizeInteger(limit, 0),
|
|
663
|
-
page: page == null ? null : normalizeInteger(page, 0),
|
|
664
|
-
}),
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
if (!searchResult.ok) {
|
|
668
|
-
logger.error?.('[claworld:product-shell] world search failed', {
|
|
669
|
-
status: searchResult.status,
|
|
670
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
671
|
-
body: searchResult.body,
|
|
672
|
-
});
|
|
673
|
-
throw createProductShellHttpError('world_search', searchResult, {
|
|
674
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
return buildPostSetupWorldDirectory(searchResult.body, {
|
|
679
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
680
|
-
statusMode: 'search',
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
export async function joinWorld({
|
|
685
|
-
cfg = {},
|
|
686
|
-
accountId = null,
|
|
687
|
-
runtimeConfig = null,
|
|
688
|
-
worldId = null,
|
|
689
|
-
agentId = null,
|
|
690
|
-
participantContextText = null,
|
|
691
|
-
fetchImpl,
|
|
692
|
-
logger = console,
|
|
693
|
-
} = {}) {
|
|
694
|
-
if (typeof fetchImpl !== 'function') {
|
|
695
|
-
throw new Error('fetch is unavailable for claworld product-shell join helper');
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
const resolvedWorldId = normalizeText(worldId, null);
|
|
699
|
-
if (!resolvedWorldId) {
|
|
700
|
-
throw new Error('claworld product-shell join helper requires worldId');
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
const resolvedAgentId = normalizeText(agentId, null);
|
|
704
|
-
if (!resolvedAgentId) {
|
|
705
|
-
throw new Error('claworld product-shell join helper requires agentId');
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
709
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
710
|
-
const joinResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/join`, {
|
|
711
|
-
method: 'POST',
|
|
712
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
713
|
-
accept: 'application/json',
|
|
714
|
-
'content-type': 'application/json',
|
|
715
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
716
|
-
}),
|
|
717
|
-
body: JSON.stringify({
|
|
718
|
-
agentId: resolvedAgentId,
|
|
719
|
-
participantContextText: normalizeText(participantContextText, null),
|
|
720
|
-
}),
|
|
721
|
-
});
|
|
722
|
-
|
|
723
|
-
if (!joinResult.ok) {
|
|
724
|
-
logger.error?.('[claworld:product-shell] world join failed', {
|
|
725
|
-
status: joinResult.status,
|
|
726
|
-
worldId: resolvedWorldId,
|
|
727
|
-
agentId: resolvedAgentId,
|
|
728
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
729
|
-
body: joinResult.body,
|
|
730
|
-
});
|
|
731
|
-
throw createProductShellHttpError('world_join', joinResult, {
|
|
732
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
733
|
-
worldId: resolvedWorldId,
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
return normalizeWorldJoinResponse(joinResult.body, {
|
|
738
|
-
worldId: resolvedWorldId,
|
|
739
|
-
agentId: resolvedAgentId,
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
export async function searchWorldMembers({
|
|
744
|
-
cfg = {},
|
|
745
|
-
accountId = null,
|
|
746
|
-
runtimeConfig = null,
|
|
747
|
-
worldId = null,
|
|
748
|
-
agentId = null,
|
|
749
|
-
query = null,
|
|
750
|
-
sort = null,
|
|
751
|
-
limit = null,
|
|
752
|
-
fetchImpl,
|
|
753
|
-
logger = console,
|
|
754
|
-
} = {}) {
|
|
755
|
-
if (typeof fetchImpl !== 'function') {
|
|
756
|
-
throw new Error('fetch is unavailable for claworld product-shell member search helper');
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
const resolvedWorldId = normalizeText(worldId, null);
|
|
760
|
-
if (!resolvedWorldId) {
|
|
761
|
-
throw new Error('claworld product-shell member search helper requires worldId');
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
const resolvedAgentId = normalizeText(agentId, null);
|
|
765
|
-
if (!resolvedAgentId) {
|
|
766
|
-
throw new Error('claworld product-shell member search helper requires agentId');
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
770
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
771
|
-
const searchResult = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/search`, {
|
|
772
|
-
method: 'POST',
|
|
773
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
774
|
-
accept: 'application/json',
|
|
775
|
-
'content-type': 'application/json',
|
|
776
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
777
|
-
}),
|
|
778
|
-
body: JSON.stringify({
|
|
779
|
-
agentId: resolvedAgentId,
|
|
780
|
-
query: normalizeText(query, null),
|
|
781
|
-
sort: normalizeText(sort, null),
|
|
782
|
-
limit: limit == null ? null : normalizeInteger(limit, 0),
|
|
783
|
-
}),
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
if (!searchResult.ok) {
|
|
787
|
-
logger.error?.('[claworld:product-shell] world member search failed', {
|
|
788
|
-
status: searchResult.status,
|
|
789
|
-
worldId: resolvedWorldId,
|
|
790
|
-
agentId: resolvedAgentId,
|
|
791
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
792
|
-
body: searchResult.body,
|
|
793
|
-
});
|
|
794
|
-
throw createProductShellHttpError('world_member_search', searchResult, {
|
|
795
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
796
|
-
worldId: resolvedWorldId,
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
return normalizeWorldMemberSearchResponse(searchResult.body, {
|
|
801
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
export async function fetchWorldCandidateFeed({
|
|
806
|
-
cfg = {},
|
|
807
|
-
accountId = null,
|
|
808
|
-
runtimeConfig = null,
|
|
809
|
-
worldId = null,
|
|
810
|
-
agentId = null,
|
|
811
|
-
limit = null,
|
|
812
|
-
fetchImpl,
|
|
813
|
-
logger = console,
|
|
814
|
-
} = {}) {
|
|
815
|
-
if (typeof fetchImpl !== 'function') {
|
|
816
|
-
throw new Error('fetch is unavailable for claworld product-shell candidate feed helper');
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
const resolvedWorldId = normalizeText(worldId, null);
|
|
820
|
-
if (!resolvedWorldId) {
|
|
821
|
-
throw new Error('claworld product-shell candidate feed helper requires worldId');
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
const resolvedAgentId = normalizeText(agentId, null);
|
|
825
|
-
if (!resolvedAgentId) {
|
|
826
|
-
throw new Error('claworld product-shell candidate feed helper requires agentId');
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
830
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
831
|
-
const requestUrl = new URL(`${baseUrl}/v1/worlds/${encodeURIComponent(resolvedWorldId)}/candidates`);
|
|
832
|
-
requestUrl.searchParams.set('agentId', resolvedAgentId);
|
|
833
|
-
const normalizedLimit = normalizeInteger(limit, 0);
|
|
834
|
-
if (normalizedLimit > 0) {
|
|
835
|
-
requestUrl.searchParams.set('limit', String(normalizedLimit));
|
|
836
|
-
}
|
|
837
|
-
const candidateFeed = await fetchJson(fetchImpl, requestUrl.toString(), {
|
|
838
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
839
|
-
accept: 'application/json',
|
|
840
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
841
|
-
}),
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
if (!candidateFeed.ok) {
|
|
845
|
-
logger.error?.('[claworld:product-shell] candidate feed fetch failed', {
|
|
846
|
-
status: candidateFeed.status,
|
|
847
|
-
worldId: resolvedWorldId,
|
|
848
|
-
agentId: resolvedAgentId,
|
|
849
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
850
|
-
body: candidateFeed.body,
|
|
851
|
-
});
|
|
852
|
-
throw createProductShellHttpError('world_candidate_feed', candidateFeed, {
|
|
853
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
854
|
-
worldId: resolvedWorldId,
|
|
855
|
-
});
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
return normalizeCandidateFeedResponse(candidateFeed.body, {
|
|
859
|
-
worldId: resolvedWorldId,
|
|
860
|
-
agentId: resolvedAgentId,
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
export async function resolveWorldSelectionFlow({
|
|
865
|
-
cfg = {},
|
|
866
|
-
accountId = null,
|
|
867
|
-
runtimeConfig = null,
|
|
868
|
-
worldDirectory = null,
|
|
869
|
-
selection = null,
|
|
870
|
-
profile = {},
|
|
871
|
-
fetchImpl,
|
|
872
|
-
logger = console,
|
|
873
|
-
} = {}) {
|
|
874
|
-
const directory = worldDirectory && Array.isArray(worldDirectory.items)
|
|
875
|
-
? buildPostSetupWorldDirectory(worldDirectory, { accountId })
|
|
876
|
-
: await (async () => {
|
|
877
|
-
if (typeof fetchImpl !== 'function') {
|
|
878
|
-
throw new Error('fetch is unavailable for claworld product-shell world flow');
|
|
879
|
-
}
|
|
880
|
-
const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
|
|
881
|
-
const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
|
|
882
|
-
const worlds = await fetchJson(fetchImpl, `${baseUrl}/v1/worlds`, {
|
|
883
|
-
headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
|
|
884
|
-
accept: 'application/json',
|
|
885
|
-
...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
|
|
886
|
-
}),
|
|
887
|
-
});
|
|
888
|
-
|
|
889
|
-
if (!worlds.ok) {
|
|
890
|
-
logger.error?.('[claworld:product-shell] world directory fetch failed during selection flow', {
|
|
891
|
-
status: worlds.status,
|
|
892
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
893
|
-
body: worlds.body,
|
|
894
|
-
});
|
|
895
|
-
throw createProductShellHttpError('world_directory', worlds, {
|
|
896
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
897
|
-
});
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
return buildPostSetupWorldDirectory(worlds.body, {
|
|
901
|
-
accountId: resolvedRuntimeConfig.accountId || accountId || null,
|
|
902
|
-
});
|
|
903
|
-
})();
|
|
904
|
-
|
|
905
|
-
const resolvedSelection = resolveWorldSelection(directory, selection);
|
|
906
|
-
if (resolvedSelection.status !== 'selected') {
|
|
907
|
-
return {
|
|
908
|
-
...resolvedSelection,
|
|
909
|
-
worldDirectory: directory,
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
const worldDetail = await fetchWorldDetail({
|
|
914
|
-
cfg,
|
|
915
|
-
accountId,
|
|
916
|
-
runtimeConfig,
|
|
917
|
-
worldId: resolvedSelection.selectedWorld.worldId,
|
|
918
|
-
fetchImpl,
|
|
919
|
-
logger,
|
|
920
|
-
});
|
|
921
|
-
return {
|
|
922
|
-
status: 'selected',
|
|
923
|
-
source: 'product_shell',
|
|
924
|
-
worldDirectory: directory,
|
|
925
|
-
selection: resolvedSelection.selection,
|
|
926
|
-
selectedWorld: resolvedSelection.selectedWorld,
|
|
927
|
-
worldDetail,
|
|
928
|
-
participantContextField: worldDetail.participantContextField || null,
|
|
929
|
-
orchestration: resolvedSelection.orchestration || null,
|
|
930
|
-
};
|
|
931
|
-
}
|