@xfxstudio/claworld 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -29
- package/openclaw.plugin.json +9 -33
- package/package.json +2 -10
- package/skills/claworld-help/SKILL.md +86 -160
- package/skills/claworld-join-and-chat/SKILL.md +107 -203
- package/skills/claworld-manage-worlds/SKILL.md +75 -392
- package/src/lib/chat-request.js +347 -0
- package/src/lib/{accepted-chat-kickoff.js → relay/kickoff-text.js} +67 -26
- package/src/openclaw/index.js +0 -5
- package/src/openclaw/installer/cli.js +14 -16
- package/src/openclaw/installer/core.js +13 -14
- package/src/openclaw/installer/doctor.js +69 -31
- package/src/openclaw/installer/workspace-contract.js +33 -9
- package/src/openclaw/plugin/claworld-channel-plugin.js +156 -625
- package/src/openclaw/plugin/config-schema.js +4 -16
- package/src/openclaw/plugin/managed-config.js +127 -75
- package/src/openclaw/plugin/onboarding.js +7 -3
- package/src/openclaw/plugin/register.js +40 -339
- package/src/openclaw/plugin/relay-client.js +112 -102
- package/src/openclaw/protocol/relay-event-protocol.js +34 -22
- package/src/openclaw/runtime/canonical-result-builder.js +15 -5
- package/src/openclaw/runtime/demo-session-bootstrap.js +0 -4
- package/src/openclaw/runtime/feedback-helper.js +3 -2
- package/src/openclaw/runtime/inbound-session-router.js +28 -20
- package/src/openclaw/runtime/outbound-session-bridge.js +21 -9
- package/src/openclaw/runtime/product-shell-helper.js +45 -637
- package/src/openclaw/runtime/runtime-path.js +2 -2
- package/src/openclaw/runtime/system-message-orchestrator.js +1 -1
- package/src/openclaw/runtime/tool-contracts.js +36 -258
- package/src/openclaw/runtime/world-moderation-helper.js +11 -65
- package/src/product-shell/catalog/default-world-catalog.js +15 -33
- package/src/product-shell/contracts/candidate-feed.js +40 -5
- package/src/product-shell/contracts/chat-request-approval-policy.js +3 -3
- package/src/product-shell/contracts/world-manifest.js +134 -161
- package/src/product-shell/contracts/world-orchestration.js +55 -326
- package/src/product-shell/feedback/feedback-routes.js +4 -3
- package/src/product-shell/feedback/feedback-service.js +11 -8
- package/src/product-shell/index.js +6 -7
- package/src/product-shell/matching/matchmaking-service.js +39 -5
- package/src/product-shell/membership/membership-service.js +125 -147
- package/src/product-shell/onboarding/onboarding-service.js +2 -2
- package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
- package/src/product-shell/orchestration/world-conversation-text.js +231 -0
- package/src/product-shell/results/result-service.js +9 -3
- package/src/product-shell/search/search-service.js +28 -1
- package/src/product-shell/social/chat-request-routes.js +0 -1
- package/src/product-shell/social/chat-request-service.js +1 -102
- package/src/product-shell/worlds/world-admin-service.js +86 -277
- package/src/product-shell/worlds/world-authorization.js +3 -5
- package/src/product-shell/worlds/world-routes.js +8 -38
- package/src/product-shell/worlds/world-service.js +3 -3
- package/src/product-shell/worlds/world-text.js +77 -0
- package/src/lib/runtime-guidance.js +0 -457
- package/src/openclaw/runtime/world-session-startup.js +0 -1
- package/src/product-shell/orchestration/session-orchestrator.js +0 -38
|
@@ -10,7 +10,7 @@ import { createMembershipService } from './membership/membership-service.js';
|
|
|
10
10
|
import { createMatchmakingService } from './matching/matchmaking-service.js';
|
|
11
11
|
import { createWorldSearchService } from './search/search-service.js';
|
|
12
12
|
import { createResultService } from './results/result-service.js';
|
|
13
|
-
import {
|
|
13
|
+
import { createWorldConversationOrchestrator } from './orchestration/world-conversation-orchestrator.js';
|
|
14
14
|
import { createSocialService } from './social/social-service.js';
|
|
15
15
|
import { registerSocialRoutes } from './social/social-routes.js';
|
|
16
16
|
import { createFriendService } from './social/friend-service.js';
|
|
@@ -33,7 +33,7 @@ export function createClaworldProductShell({
|
|
|
33
33
|
worldService,
|
|
34
34
|
membershipService,
|
|
35
35
|
});
|
|
36
|
-
const matchmakingService = createMatchmakingService({ worldService, worldAuthorizationService, store });
|
|
36
|
+
const matchmakingService = createMatchmakingService({ worldService, worldAuthorizationService, store, presence });
|
|
37
37
|
const searchService = createWorldSearchService({ worldService, worldAuthorizationService, store, presence });
|
|
38
38
|
const worldAdminService = createWorldAdminService({ worldService, worldAuthorizationService, store });
|
|
39
39
|
const chatRequestService = createChatRequestService({
|
|
@@ -60,7 +60,7 @@ export function createClaworldProductShell({
|
|
|
60
60
|
return socialLookupService.lookupAgentByCode(input);
|
|
61
61
|
},
|
|
62
62
|
};
|
|
63
|
-
const
|
|
63
|
+
const worldConversationOrchestrator = createWorldConversationOrchestrator({
|
|
64
64
|
worldService,
|
|
65
65
|
resultService,
|
|
66
66
|
});
|
|
@@ -79,7 +79,7 @@ export function createClaworldProductShell({
|
|
|
79
79
|
moderation: worldAdminService,
|
|
80
80
|
feedback: feedbackService,
|
|
81
81
|
results: resultService,
|
|
82
|
-
orchestration:
|
|
82
|
+
orchestration: worldConversationOrchestrator,
|
|
83
83
|
},
|
|
84
84
|
registerRoutes(app) {
|
|
85
85
|
registerOnboardingRoutes(app, { onboardingService, store });
|
|
@@ -94,7 +94,7 @@ export function createClaworldProductShell({
|
|
|
94
94
|
searchService,
|
|
95
95
|
worldBroadcastService,
|
|
96
96
|
worldAdminService,
|
|
97
|
-
|
|
97
|
+
worldConversationOrchestrator,
|
|
98
98
|
});
|
|
99
99
|
registerSocialRoutes(app, { socialService: socialLookupService });
|
|
100
100
|
registerFeedbackRoutes(app, { store, feedbackService });
|
|
@@ -138,11 +138,10 @@ export function createClaworldProductShell({
|
|
|
138
138
|
'POST /v1/worlds/:worldId/search',
|
|
139
139
|
'POST /v1/worlds/:worldId/broadcast',
|
|
140
140
|
'GET /v1/worlds/:worldId/candidates',
|
|
141
|
-
'POST /v1/worlds/:worldId/join-check',
|
|
142
141
|
'POST /v1/worlds/:worldId/join',
|
|
143
142
|
'GET /v1/worlds/:worldId/memberships',
|
|
144
143
|
'POST /v1/worlds/:worldId/memberships',
|
|
145
|
-
'POST /v1/worlds/:worldId/
|
|
144
|
+
'POST /v1/worlds/:worldId/conversation-preview',
|
|
146
145
|
'GET /v1/social/agents/lookup',
|
|
147
146
|
'POST /v1/feedback',
|
|
148
147
|
'GET /v1/moderation/worlds',
|
|
@@ -217,7 +217,14 @@ function buildViewerContext({ world, membershipStore, normalizedAgentId, worldAu
|
|
|
217
217
|
};
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
function buildBaseFeed({
|
|
220
|
+
function buildBaseFeed({
|
|
221
|
+
world,
|
|
222
|
+
membershipStore,
|
|
223
|
+
normalizedAgentId,
|
|
224
|
+
limit,
|
|
225
|
+
worldAuthorizationService,
|
|
226
|
+
resolvePresence,
|
|
227
|
+
}) {
|
|
221
228
|
const { viewerAgent, viewerMembership } = buildViewerContext({
|
|
222
229
|
world,
|
|
223
230
|
membershipStore,
|
|
@@ -236,6 +243,7 @@ function buildBaseFeed({ world, membershipStore, normalizedAgentId, limit, world
|
|
|
236
243
|
viewerAgent,
|
|
237
244
|
candidateMemberships: activeMemberships,
|
|
238
245
|
getAgent: (candidateAgentId) => membershipStore.getAgent(candidateAgentId),
|
|
246
|
+
getPresence: (candidateAgentId) => resolvePresence(candidateAgentId),
|
|
239
247
|
nowMs,
|
|
240
248
|
limit: activeMemberships.length,
|
|
241
249
|
});
|
|
@@ -248,13 +256,21 @@ function buildBaseFeed({ world, membershipStore, normalizedAgentId, limit, world
|
|
|
248
256
|
};
|
|
249
257
|
}
|
|
250
258
|
|
|
251
|
-
function buildDatingDemoFeed({
|
|
259
|
+
function buildDatingDemoFeed({
|
|
260
|
+
world,
|
|
261
|
+
membershipStore,
|
|
262
|
+
normalizedAgentId,
|
|
263
|
+
limit,
|
|
264
|
+
worldAuthorizationService,
|
|
265
|
+
resolvePresence,
|
|
266
|
+
}) {
|
|
252
267
|
const { viewerMembership, activeMemberships, normalizedLimit, baseFeed } = buildBaseFeed({
|
|
253
268
|
world,
|
|
254
269
|
membershipStore,
|
|
255
270
|
normalizedAgentId,
|
|
256
271
|
limit,
|
|
257
272
|
worldAuthorizationService,
|
|
273
|
+
resolvePresence,
|
|
258
274
|
});
|
|
259
275
|
const membershipById = new Map(activeMemberships.map((membership) => [membership.membershipId, membership]));
|
|
260
276
|
const rankedCandidates = baseFeed.candidates
|
|
@@ -278,19 +294,35 @@ function buildDatingDemoFeed({ world, membershipStore, normalizedAgentId, limit,
|
|
|
278
294
|
...baseFeed,
|
|
279
295
|
agentId: normalizedAgentId,
|
|
280
296
|
limit: normalizedLimit,
|
|
281
|
-
candidateSource: '
|
|
297
|
+
candidateSource: 'active_memberships_online',
|
|
282
298
|
strategy: buildStrategy(world),
|
|
283
299
|
totalCandidates: rankedCandidates.length,
|
|
284
300
|
candidates,
|
|
285
301
|
};
|
|
286
302
|
}
|
|
287
303
|
|
|
288
|
-
export function createMatchmakingService({
|
|
304
|
+
export function createMatchmakingService({
|
|
305
|
+
worldService,
|
|
306
|
+
worldAuthorizationService,
|
|
307
|
+
store = null,
|
|
308
|
+
presence = null,
|
|
309
|
+
} = {}) {
|
|
289
310
|
function assertStore() {
|
|
290
311
|
if (!store) throw createConfigurationError();
|
|
291
312
|
return store;
|
|
292
313
|
}
|
|
293
314
|
|
|
315
|
+
function resolvePresence(agentId) {
|
|
316
|
+
if (!presence) {
|
|
317
|
+
return {
|
|
318
|
+
online: true,
|
|
319
|
+
connectedAt: null,
|
|
320
|
+
lastHeartbeatAt: null,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return presence.getPresence(agentId);
|
|
324
|
+
}
|
|
325
|
+
|
|
294
326
|
return {
|
|
295
327
|
describeStrategy(worldId) {
|
|
296
328
|
const world = worldService.requireWorld(worldId);
|
|
@@ -312,6 +344,7 @@ export function createMatchmakingService({ worldService, worldAuthorizationServi
|
|
|
312
344
|
normalizedAgentId,
|
|
313
345
|
limit,
|
|
314
346
|
worldAuthorizationService,
|
|
347
|
+
resolvePresence,
|
|
315
348
|
});
|
|
316
349
|
}
|
|
317
350
|
|
|
@@ -321,13 +354,14 @@ export function createMatchmakingService({ worldService, worldAuthorizationServi
|
|
|
321
354
|
normalizedAgentId,
|
|
322
355
|
limit,
|
|
323
356
|
worldAuthorizationService,
|
|
357
|
+
resolvePresence,
|
|
324
358
|
});
|
|
325
359
|
|
|
326
360
|
return {
|
|
327
361
|
...baseFeed,
|
|
328
362
|
agentId: normalizedAgentId,
|
|
329
363
|
limit: normalizedLimit,
|
|
330
|
-
candidateSource: '
|
|
364
|
+
candidateSource: 'active_memberships_online',
|
|
331
365
|
strategy: buildStrategy(world),
|
|
332
366
|
totalCandidates: baseFeed.candidates.length,
|
|
333
367
|
candidates: baseFeed.candidates.slice(0, normalizedLimit),
|
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
buildWorldProfileCollectionFlow,
|
|
4
|
-
} from '../contracts/world-orchestration.js';
|
|
1
|
+
import { buildResolvedWorldJoinOrchestration } from '../contracts/world-orchestration.js';
|
|
2
|
+
import { buildParticipantContextText } from '../worlds/world-text.js';
|
|
5
3
|
|
|
6
|
-
function
|
|
7
|
-
if (value == null) return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function projectMissingField(field = {}) {
|
|
14
|
-
return {
|
|
15
|
-
fieldId: field.fieldId,
|
|
16
|
-
label: field.label,
|
|
17
|
-
description: field.description,
|
|
18
|
-
};
|
|
4
|
+
function normalizeText(value, fallback = null) {
|
|
5
|
+
if (value == null) return fallback;
|
|
6
|
+
const normalized = String(value).trim();
|
|
7
|
+
return normalized || fallback;
|
|
19
8
|
}
|
|
20
9
|
|
|
21
10
|
function createConfigurationError() {
|
|
@@ -49,67 +38,30 @@ function createInvalidJoinRequestError(fieldId, message = `${fieldId} is require
|
|
|
49
38
|
return error;
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
function createMembershipNotEligibleError(joinCheck) {
|
|
53
|
-
const error = new Error('membership_not_eligible');
|
|
54
|
-
error.code = 'membership_not_eligible';
|
|
55
|
-
error.status = 422;
|
|
56
|
-
error.responseBody = {
|
|
57
|
-
error: error.code,
|
|
58
|
-
message: 'profile does not satisfy world join requirements',
|
|
59
|
-
joinCheck,
|
|
60
|
-
profileCollectionFlow: joinCheck.profileCollectionFlow || null,
|
|
61
|
-
};
|
|
62
|
-
return error;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function createJoinNotEligibleError(joinCheck) {
|
|
66
|
-
const error = new Error('world_join_not_eligible');
|
|
67
|
-
error.code = 'world_join_not_eligible';
|
|
68
|
-
error.status = 422;
|
|
69
|
-
error.responseBody = {
|
|
70
|
-
error: error.code,
|
|
71
|
-
message: 'profile does not satisfy world join requirements',
|
|
72
|
-
status: 'needs_profile',
|
|
73
|
-
membershipStatus: 'inactive',
|
|
74
|
-
worldId: joinCheck.worldId,
|
|
75
|
-
normalizedProfile: joinCheck.normalizedProfile,
|
|
76
|
-
missingFields: joinCheck.missingFields,
|
|
77
|
-
nextMissingField: joinCheck.nextMissingField,
|
|
78
|
-
missingFieldGuidance: joinCheck.missingFieldGuidance,
|
|
79
|
-
nextAction: 'retry_join_world_after_profile_update',
|
|
80
|
-
};
|
|
81
|
-
return error;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
41
|
function normalizeAgentId(agentId) {
|
|
85
42
|
const normalized = String(agentId || '').trim();
|
|
86
43
|
return normalized || null;
|
|
87
44
|
}
|
|
88
45
|
|
|
89
|
-
function normalizeProfileSnapshot(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
46
|
+
function normalizeProfileSnapshot(profileSnapshot = null, participantContextText = null) {
|
|
47
|
+
const base = profileSnapshot && typeof profileSnapshot === 'object' && !Array.isArray(profileSnapshot)
|
|
48
|
+
? { ...profileSnapshot }
|
|
49
|
+
: {};
|
|
50
|
+
const normalizedParticipantContextText = normalizeText(
|
|
51
|
+
participantContextText,
|
|
52
|
+
normalizeText(base.participantContextText, null),
|
|
53
|
+
);
|
|
54
|
+
if (normalizedParticipantContextText) {
|
|
55
|
+
base.participantContextText = normalizedParticipantContextText;
|
|
94
56
|
}
|
|
95
|
-
return
|
|
57
|
+
return base;
|
|
96
58
|
}
|
|
97
59
|
|
|
98
|
-
function buildNextStageSummary(
|
|
99
|
-
const matchingSummary = world.matching.strategySummary
|
|
100
|
-
|| `The world uses ${world.matching.mode} matching to deliver candidate summaries before request_chat.`;
|
|
101
|
-
const reviewSummary =
|
|
102
|
-
'Review the backend-authored candidate feed, choose a candidate, and create a world-scoped chat request.';
|
|
103
|
-
const sessionSummary = `Matched agents then enter a ${world.sessionTemplate.mode} session with up to ${world.sessionTemplate.maxTurns} turns.`;
|
|
104
|
-
|
|
60
|
+
function buildNextStageSummary() {
|
|
105
61
|
return {
|
|
106
|
-
stage: '
|
|
107
|
-
summary:
|
|
108
|
-
|
|
109
|
-
matchingCadence: world.matching.cadence,
|
|
110
|
-
sessionMode: world.sessionTemplate.mode,
|
|
111
|
-
maxTurns: world.sessionTemplate.maxTurns,
|
|
112
|
-
turnTimeoutMs: world.sessionTemplate.turnTimeoutMs,
|
|
62
|
+
stage: 'candidate_review',
|
|
63
|
+
summary:
|
|
64
|
+
'Review the backend-authored candidate feed or use world search, then choose one target agent and create a world-scoped chat request.',
|
|
113
65
|
};
|
|
114
66
|
}
|
|
115
67
|
|
|
@@ -119,67 +71,86 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
119
71
|
return store;
|
|
120
72
|
}
|
|
121
73
|
|
|
74
|
+
function resolveNormalizedParticipantContextText({ participantContextText = null, profileSnapshot = null, agent = null, world = null } = {}) {
|
|
75
|
+
return buildParticipantContextText({
|
|
76
|
+
world,
|
|
77
|
+
agent,
|
|
78
|
+
participantContextText,
|
|
79
|
+
profileSnapshot,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
122
83
|
return {
|
|
123
|
-
evaluateJoin({ worldId,
|
|
84
|
+
evaluateJoin({ worldId, participantContextText = null } = {}) {
|
|
124
85
|
const world = worldService.requireWorld(worldId);
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
isEmptyValue(normalizedProfile[field.fieldId]),
|
|
128
|
-
);
|
|
129
|
-
const missingFields = orderedMissingFields.map((field) => projectMissingField(field));
|
|
130
|
-
const nextMissingField = missingFields[0] || null;
|
|
86
|
+
const normalizedParticipantContextText = normalizeText(participantContextText, null);
|
|
87
|
+
const accepted = Boolean(normalizedParticipantContextText);
|
|
131
88
|
|
|
132
|
-
|
|
89
|
+
return {
|
|
133
90
|
worldId: world.worldId,
|
|
134
|
-
accepted
|
|
135
|
-
status:
|
|
136
|
-
|
|
137
|
-
|
|
91
|
+
accepted,
|
|
92
|
+
status: accepted ? 'eligible' : 'needs_profile',
|
|
93
|
+
participantContextText: normalizedParticipantContextText,
|
|
94
|
+
missingFields: accepted
|
|
95
|
+
? []
|
|
96
|
+
: [
|
|
97
|
+
{
|
|
98
|
+
fieldId: 'participantContextText',
|
|
99
|
+
label: 'Entry Profile',
|
|
100
|
+
description: 'A short text describing who you are in this world and what context you bring into it.',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
nextMissingField: accepted
|
|
104
|
+
? null
|
|
105
|
+
: {
|
|
106
|
+
fieldId: 'participantContextText',
|
|
107
|
+
label: 'Entry Profile',
|
|
108
|
+
description: 'A short text describing who you are in this world and what context you bring into it.',
|
|
109
|
+
},
|
|
138
110
|
missingFieldGuidance: {
|
|
139
|
-
mode:
|
|
140
|
-
orderedMissingFields:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
111
|
+
mode: accepted ? 'complete' : 'single_text_field',
|
|
112
|
+
orderedMissingFields: accepted
|
|
113
|
+
? []
|
|
114
|
+
: [
|
|
115
|
+
{
|
|
116
|
+
fieldId: 'participantContextText',
|
|
117
|
+
label: 'Entry Profile',
|
|
118
|
+
description: 'A short text describing who you are in this world and what context you bring into it.',
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
orderedMissingFieldIds: accepted ? [] : ['participantContextText'],
|
|
122
|
+
nextMissingField: accepted
|
|
123
|
+
? null
|
|
124
|
+
: {
|
|
125
|
+
fieldId: 'participantContextText',
|
|
126
|
+
label: 'Entry Profile',
|
|
127
|
+
description: 'A short text describing who you are in this world and what context you bring into it.',
|
|
128
|
+
},
|
|
129
|
+
remainingRequiredFieldCount: accepted ? 0 : 1,
|
|
144
130
|
},
|
|
145
|
-
|
|
146
|
-
nextAction:
|
|
147
|
-
missingFields.length === 0 ? 'call_join_world' : 'retry_join_world_after_profile_update',
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const worldDetail = worldService.describeWorldDetail(world.worldId);
|
|
151
|
-
return {
|
|
152
|
-
...joinCheck,
|
|
153
|
-
profileCollectionFlow: buildWorldProfileCollectionFlow({
|
|
154
|
-
worldDetail,
|
|
155
|
-
joinCheck,
|
|
156
|
-
profile: normalizedProfile,
|
|
157
|
-
maxFieldsPerStep,
|
|
158
|
-
}),
|
|
131
|
+
nextAction: accepted ? 'call_join_world' : 'retry_join_world_after_profile_update',
|
|
159
132
|
};
|
|
160
133
|
},
|
|
161
|
-
|
|
162
|
-
|
|
134
|
+
|
|
135
|
+
async createMembership({ worldId, agentId, participantContextText } = {}) {
|
|
136
|
+
const world = worldService.requireWorld(worldId);
|
|
163
137
|
const membershipStore = assertStore();
|
|
164
138
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
165
|
-
if (!normalizedAgentId)
|
|
166
|
-
throw createInvalidJoinRequestError('agentId');
|
|
167
|
-
}
|
|
139
|
+
if (!normalizedAgentId) throw createInvalidJoinRequestError('agentId');
|
|
168
140
|
|
|
169
141
|
const agent = membershipStore.getAgent(normalizedAgentId);
|
|
142
|
+
if (!agent) throw createAgentNotFoundError(normalizedAgentId);
|
|
170
143
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const normalizedProfileSnapshot = normalizeProfileSnapshot(profileSnapshot, agent.profile);
|
|
176
|
-
const joinCheck = this.evaluateJoin({
|
|
177
|
-
worldId,
|
|
178
|
-
profile: normalizedProfileSnapshot,
|
|
144
|
+
const normalizedParticipantContextText = resolveNormalizedParticipantContextText({
|
|
145
|
+
world,
|
|
146
|
+
agent,
|
|
147
|
+
participantContextText,
|
|
179
148
|
});
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
149
|
+
if (!normalizedParticipantContextText) {
|
|
150
|
+
throw createInvalidJoinRequestError(
|
|
151
|
+
'participantContextText',
|
|
152
|
+
'participantContextText is required',
|
|
153
|
+
);
|
|
183
154
|
}
|
|
184
155
|
|
|
185
156
|
const existingMembership = membershipStore.listMemberships({
|
|
@@ -195,34 +166,37 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
195
166
|
worldId,
|
|
196
167
|
agentId: normalizedAgentId,
|
|
197
168
|
status: 'joined',
|
|
198
|
-
profileSnapshot:
|
|
169
|
+
profileSnapshot: normalizeProfileSnapshot(null, normalizedParticipantContextText),
|
|
170
|
+
participantContextText: normalizedParticipantContextText,
|
|
199
171
|
});
|
|
200
172
|
|
|
201
173
|
return { membership, created: true };
|
|
202
174
|
},
|
|
203
|
-
|
|
175
|
+
|
|
176
|
+
async joinWorld({
|
|
177
|
+
worldId,
|
|
178
|
+
agentId,
|
|
179
|
+
participantContextText,
|
|
180
|
+
} = {}) {
|
|
204
181
|
const world = worldService.requireWorld(worldId);
|
|
205
182
|
const membershipStore = assertStore();
|
|
206
183
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
207
184
|
|
|
208
|
-
if (!normalizedAgentId)
|
|
209
|
-
throw createInvalidJoinRequestError('agentId');
|
|
210
|
-
}
|
|
185
|
+
if (!normalizedAgentId) throw createInvalidJoinRequestError('agentId');
|
|
211
186
|
|
|
212
187
|
const agent = membershipStore.getAgent(normalizedAgentId);
|
|
213
|
-
if (!agent)
|
|
214
|
-
throw createAgentNotFoundError(normalizedAgentId);
|
|
215
|
-
}
|
|
188
|
+
if (!agent) throw createAgentNotFoundError(normalizedAgentId);
|
|
216
189
|
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
maxFieldsPerStep,
|
|
190
|
+
const normalizedParticipantContextText = resolveNormalizedParticipantContextText({
|
|
191
|
+
world,
|
|
192
|
+
agent,
|
|
193
|
+
participantContextText,
|
|
222
194
|
});
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
195
|
+
if (!normalizedParticipantContextText) {
|
|
196
|
+
throw createInvalidJoinRequestError(
|
|
197
|
+
'participantContextText',
|
|
198
|
+
'participantContextText is required',
|
|
199
|
+
);
|
|
226
200
|
}
|
|
227
201
|
|
|
228
202
|
const existingMembership = membershipStore.listMemberships({
|
|
@@ -233,49 +207,53 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
233
207
|
const membership = existingMembership
|
|
234
208
|
? await membershipStore.updateMembership(existingMembership.membershipId, {
|
|
235
209
|
status: 'active',
|
|
236
|
-
profileSnapshot:
|
|
210
|
+
profileSnapshot: normalizeProfileSnapshot(existingMembership.profileSnapshot, normalizedParticipantContextText),
|
|
211
|
+
participantContextText: normalizedParticipantContextText,
|
|
237
212
|
})
|
|
238
213
|
: await membershipStore.createMembership({
|
|
239
214
|
worldId: world.worldId,
|
|
240
215
|
agentId: normalizedAgentId,
|
|
241
216
|
status: 'active',
|
|
242
|
-
profileSnapshot:
|
|
217
|
+
profileSnapshot: normalizeProfileSnapshot(null, normalizedParticipantContextText),
|
|
218
|
+
participantContextText: normalizedParticipantContextText,
|
|
243
219
|
});
|
|
244
220
|
|
|
245
|
-
|
|
221
|
+
const joinResult = {
|
|
246
222
|
status: 'joined',
|
|
247
223
|
worldId: world.worldId,
|
|
248
224
|
membership,
|
|
249
225
|
membershipStatus: membership.status,
|
|
250
226
|
created: !existingMembership,
|
|
251
|
-
|
|
227
|
+
participantContextText: normalizedParticipantContextText,
|
|
252
228
|
nextAction: 'review_candidate_feed',
|
|
253
|
-
nextStageSummary: buildNextStageSummary(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
},
|
|
263
|
-
}),
|
|
229
|
+
nextStageSummary: buildNextStageSummary(),
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
...joinResult,
|
|
234
|
+
orchestration: buildResolvedWorldJoinOrchestration({
|
|
235
|
+
joinResult,
|
|
236
|
+
candidateDelivery: null,
|
|
237
|
+
}) || null,
|
|
264
238
|
};
|
|
265
239
|
},
|
|
240
|
+
|
|
266
241
|
getMembership({ worldId, agentId, includeDisabled = false } = {}) {
|
|
267
242
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
268
243
|
if (!normalizedAgentId) return null;
|
|
269
244
|
worldService.requireWorld(worldId, { includeDisabled });
|
|
270
245
|
return assertStore().listMemberships({ worldId, agentId: normalizedAgentId })[0] || null;
|
|
271
246
|
},
|
|
247
|
+
|
|
272
248
|
listMemberships({ worldId, agentId = null, status = null, includeDisabled = false } = {}) {
|
|
273
249
|
worldService.requireWorld(worldId, { includeDisabled });
|
|
274
250
|
return assertStore().listMemberships({ worldId, agentId, status });
|
|
275
251
|
},
|
|
252
|
+
|
|
276
253
|
listMembershipsAcrossWorlds({ agentId = null, status = null } = {}) {
|
|
277
254
|
return assertStore().listMemberships({ agentId, status });
|
|
278
255
|
},
|
|
256
|
+
|
|
279
257
|
countMemberships({ worldId, agentId = null, status = null, includeDisabled = false } = {}) {
|
|
280
258
|
worldService.requireWorld(worldId, { includeDisabled });
|
|
281
259
|
return assertStore().countMemberships({ worldId, agentId, status });
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
const DEFAULT_INSTALL_CHANNEL_ID = 'claworld';
|
|
11
11
|
const DEFAULT_INSTALL_ACCOUNT_ID = 'claworld';
|
|
12
|
-
const DEFAULT_INSTALL_LOCAL_AGENT_ID = '
|
|
12
|
+
const DEFAULT_INSTALL_LOCAL_AGENT_ID = 'main';
|
|
13
13
|
const DEFAULT_ACTIVATION_DISPLAY_NAME = 'Claworld Agent';
|
|
14
14
|
|
|
15
15
|
function normalizeText(value, fallback = null) {
|
|
@@ -174,7 +174,7 @@ export function createOnboardingService({ worldService, store = null } = {}) {
|
|
|
174
174
|
`run ${CLAWORLD_INSTALLER_COMMAND}`,
|
|
175
175
|
'installer validates OpenClaw availability and minimum host version',
|
|
176
176
|
'installer verifies or installs the claworld OpenClaw plugin package',
|
|
177
|
-
'installer writes or refreshes the managed claworld channel config',
|
|
177
|
+
'installer writes or refreshes the managed claworld channel config and binds it to the local main agent by default',
|
|
178
178
|
'installer calls POST /v1/onboarding/activate to obtain agentId and appToken when reuse is not possible',
|
|
179
179
|
'installer persists the returned appToken into the managed claworld account config',
|
|
180
180
|
'installer reloads or starts the runtime and verifies the relay binding',
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createSystemMessageOrchestrator } from './world-conversation-text.js';
|
|
2
|
+
|
|
3
|
+
export function createWorldConversationOrchestrator({
|
|
4
|
+
worldService,
|
|
5
|
+
resultService,
|
|
6
|
+
systemMessages = createSystemMessageOrchestrator(),
|
|
7
|
+
} = {}) {
|
|
8
|
+
return {
|
|
9
|
+
previewConversation({ worldId, conversationKey = 'cnv_preview' } = {}) {
|
|
10
|
+
const world = worldService.requireWorld(worldId);
|
|
11
|
+
const openingPlan = systemMessages.planMessages({
|
|
12
|
+
conversationId: conversationKey,
|
|
13
|
+
trigger: 'conversation_started',
|
|
14
|
+
worldRules: world.conversationTemplate.worldRules,
|
|
15
|
+
});
|
|
16
|
+
const convergencePlan = [];
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
worldId: world.worldId,
|
|
20
|
+
conversationTemplate: {
|
|
21
|
+
mode: world.conversationTemplate.mode,
|
|
22
|
+
},
|
|
23
|
+
openingPlan,
|
|
24
|
+
convergencePlan,
|
|
25
|
+
resultPreview: resultService.previewConversation({ world, conversationKey }),
|
|
26
|
+
status: 'preview_ready',
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|