@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.
Files changed (55) hide show
  1. package/README.md +12 -29
  2. package/openclaw.plugin.json +9 -33
  3. package/package.json +2 -10
  4. package/skills/claworld-help/SKILL.md +86 -160
  5. package/skills/claworld-join-and-chat/SKILL.md +107 -203
  6. package/skills/claworld-manage-worlds/SKILL.md +75 -392
  7. package/src/lib/chat-request.js +347 -0
  8. package/src/lib/{accepted-chat-kickoff.js → relay/kickoff-text.js} +67 -26
  9. package/src/openclaw/index.js +0 -5
  10. package/src/openclaw/installer/cli.js +14 -16
  11. package/src/openclaw/installer/core.js +13 -14
  12. package/src/openclaw/installer/doctor.js +69 -31
  13. package/src/openclaw/installer/workspace-contract.js +33 -9
  14. package/src/openclaw/plugin/claworld-channel-plugin.js +156 -625
  15. package/src/openclaw/plugin/config-schema.js +4 -16
  16. package/src/openclaw/plugin/managed-config.js +127 -75
  17. package/src/openclaw/plugin/onboarding.js +7 -3
  18. package/src/openclaw/plugin/register.js +40 -339
  19. package/src/openclaw/plugin/relay-client.js +112 -102
  20. package/src/openclaw/protocol/relay-event-protocol.js +34 -22
  21. package/src/openclaw/runtime/canonical-result-builder.js +15 -5
  22. package/src/openclaw/runtime/demo-session-bootstrap.js +0 -4
  23. package/src/openclaw/runtime/feedback-helper.js +3 -2
  24. package/src/openclaw/runtime/inbound-session-router.js +28 -20
  25. package/src/openclaw/runtime/outbound-session-bridge.js +21 -9
  26. package/src/openclaw/runtime/product-shell-helper.js +45 -637
  27. package/src/openclaw/runtime/runtime-path.js +2 -2
  28. package/src/openclaw/runtime/system-message-orchestrator.js +1 -1
  29. package/src/openclaw/runtime/tool-contracts.js +36 -258
  30. package/src/openclaw/runtime/world-moderation-helper.js +11 -65
  31. package/src/product-shell/catalog/default-world-catalog.js +15 -33
  32. package/src/product-shell/contracts/candidate-feed.js +40 -5
  33. package/src/product-shell/contracts/chat-request-approval-policy.js +3 -3
  34. package/src/product-shell/contracts/world-manifest.js +134 -161
  35. package/src/product-shell/contracts/world-orchestration.js +55 -326
  36. package/src/product-shell/feedback/feedback-routes.js +4 -3
  37. package/src/product-shell/feedback/feedback-service.js +11 -8
  38. package/src/product-shell/index.js +6 -7
  39. package/src/product-shell/matching/matchmaking-service.js +39 -5
  40. package/src/product-shell/membership/membership-service.js +125 -147
  41. package/src/product-shell/onboarding/onboarding-service.js +2 -2
  42. package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
  43. package/src/product-shell/orchestration/world-conversation-text.js +231 -0
  44. package/src/product-shell/results/result-service.js +9 -3
  45. package/src/product-shell/search/search-service.js +28 -1
  46. package/src/product-shell/social/chat-request-routes.js +0 -1
  47. package/src/product-shell/social/chat-request-service.js +1 -102
  48. package/src/product-shell/worlds/world-admin-service.js +86 -277
  49. package/src/product-shell/worlds/world-authorization.js +3 -5
  50. package/src/product-shell/worlds/world-routes.js +8 -38
  51. package/src/product-shell/worlds/world-service.js +3 -3
  52. package/src/product-shell/worlds/world-text.js +77 -0
  53. package/src/lib/runtime-guidance.js +0 -457
  54. package/src/openclaw/runtime/world-session-startup.js +0 -1
  55. package/src/product-shell/orchestration/session-orchestrator.js +0 -38
@@ -0,0 +1,77 @@
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 normalizeStringList(values = []) {
8
+ if (!Array.isArray(values)) return [];
9
+ return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
10
+ }
11
+
12
+ function formatProfileValue(value) {
13
+ if (value == null) return null;
14
+ if (typeof value === 'string') return normalizeText(value, null);
15
+ if (typeof value === 'number' || typeof value === 'boolean') return String(value);
16
+ if (Array.isArray(value)) {
17
+ const normalized = normalizeStringList(value);
18
+ return normalized.length > 0 ? normalized.join(', ') : null;
19
+ }
20
+ return null;
21
+ }
22
+
23
+ export function buildWorldContextText({
24
+ worldId = null,
25
+ displayName = null,
26
+ summary = null,
27
+ worldContextText = null,
28
+ interactionRules = null,
29
+ prohibitedRules = null,
30
+ ratingRules = null,
31
+ } = {}) {
32
+ const explicitWorldContextText = normalizeText(worldContextText, null);
33
+ if (explicitWorldContextText) return explicitWorldContextText;
34
+
35
+ const normalizedWorldId = normalizeText(worldId, null);
36
+ const normalizedDisplayName = normalizeText(displayName, normalizedWorldId);
37
+ const lines = [
38
+ normalizedDisplayName
39
+ ? `世界:${normalizedDisplayName}${normalizedWorldId ? ` [${normalizedWorldId}]` : ''}`
40
+ : (normalizedWorldId ? `世界:${normalizedWorldId}` : null),
41
+ normalizeText(summary, null) ? `简介:${normalizeText(summary, null)}` : null,
42
+ normalizeText(interactionRules, null) ? `互动规则:${normalizeText(interactionRules, null)}` : null,
43
+ normalizeText(prohibitedRules, null) ? `禁止事项:${normalizeText(prohibitedRules, null)}` : null,
44
+ normalizeText(ratingRules, null) ? `结果要求:${normalizeText(ratingRules, null)}` : null,
45
+ ].filter(Boolean);
46
+
47
+ return lines.length > 0 ? lines.join('\n') : null;
48
+ }
49
+
50
+ export function buildParticipantContextText({
51
+ world = null,
52
+ agent = null,
53
+ participantContextText = null,
54
+ profileSnapshot = null,
55
+ } = {}) {
56
+ const explicitParticipantContextText = normalizeText(participantContextText, null);
57
+ if (explicitParticipantContextText) return explicitParticipantContextText;
58
+
59
+ const normalizedProfileSnapshot = profileSnapshot && typeof profileSnapshot === 'object' && !Array.isArray(profileSnapshot)
60
+ ? profileSnapshot
61
+ : {};
62
+ const normalizedProfileText = normalizeText(normalizedProfileSnapshot.participantContextText, null);
63
+ if (normalizedProfileText) return normalizedProfileText;
64
+
65
+ const lines = [
66
+ normalizeText(agent?.displayName, null) ? `名称:${normalizeText(agent.displayName, null)}` : null,
67
+ normalizeText(normalizedProfileSnapshot.headline, null) ? `简介:${normalizeText(normalizedProfileSnapshot.headline, null)}` : null,
68
+ ...Object.entries(normalizedProfileSnapshot).map(([fieldId, rawValue]) => {
69
+ if (fieldId === 'headline' || fieldId === 'participantContextText') return null;
70
+ const value = formatProfileValue(rawValue);
71
+ if (!value) return null;
72
+ return `${fieldId}:${value}`;
73
+ }),
74
+ ].filter(Boolean);
75
+
76
+ return lines.length > 0 ? lines.join('\n') : null;
77
+ }
@@ -1,457 +0,0 @@
1
- const DEFAULT_TEMPLATE_REFS = {
2
- opening: 'world.session.opening',
3
- convergence: 'world.session.convergence',
4
- stateChanged: 'world.session.state_changed',
5
- };
6
-
7
- const CLAWORLD_RAISE_HAND_DIRECTIVE = '[[CLAWORLD_RAISE_HAND]]';
8
-
9
- function normalizeText(value, fallback = null) {
10
- if (value == null) return fallback;
11
- const normalized = String(value).trim();
12
- return normalized || fallback;
13
- }
14
-
15
- function normalizeInteger(value, fallback = null) {
16
- const normalized = Number(value);
17
- if (!Number.isFinite(normalized)) return fallback;
18
- return Math.trunc(normalized);
19
- }
20
-
21
- function normalizePositiveInteger(value, fallback = null) {
22
- const normalized = normalizeInteger(value, fallback);
23
- if (normalized == null || normalized <= 0) return fallback;
24
- return normalized;
25
- }
26
-
27
- function normalizeTurnRule(rule = {}, index = 0) {
28
- return {
29
- id: rule.id || `turn_rule_${index + 1}`,
30
- trigger: rule.trigger || 'turn_threshold',
31
- atTurn: Number.isFinite(Number(rule.atTurn)) ? Math.max(0, Number(rule.atTurn)) : null,
32
- visibility: rule.visibility || 'both',
33
- role: rule.role || 'system',
34
- templateRef: rule.templateRef || `world.turn.rule.${index + 1}`,
35
- text: rule.text || null,
36
- once: rule.once !== false,
37
- };
38
- }
39
-
40
- function buildMessage({
41
- sessionId,
42
- trigger,
43
- role = 'system',
44
- visibility = 'both',
45
- templateRef = null,
46
- text = null,
47
- metadata = {},
48
- }) {
49
- return {
50
- sessionId,
51
- trigger,
52
- role,
53
- visibility,
54
- templateRef,
55
- text,
56
- metadata,
57
- };
58
- }
59
-
60
- function buildGuidanceMessage({
61
- kind,
62
- contextKey,
63
- text,
64
- templateRef = null,
65
- metadata = {},
66
- }) {
67
- const normalizedText = normalizeText(text, null);
68
- const normalizedContextKey = normalizeText(contextKey, null);
69
- if (!normalizedText || !normalizedContextKey) return null;
70
- return {
71
- kind,
72
- contextKey: normalizedContextKey,
73
- text: normalizedText,
74
- ...(templateRef ? { templateRef } : {}),
75
- metadata: metadata && typeof metadata === 'object' && !Array.isArray(metadata) ? metadata : {},
76
- };
77
- }
78
-
79
- function finalizeGuidancePayload(messages = []) {
80
- const normalizedMessages = messages.filter(Boolean);
81
- if (normalizedMessages.length === 0) return null;
82
- return {
83
- owner: 'backend',
84
- messages: normalizedMessages,
85
- };
86
- }
87
-
88
- function formatSessionOverview(detail = {}) {
89
- const sessionOverview = detail.sessionOverview && typeof detail.sessionOverview === 'object'
90
- ? detail.sessionOverview
91
- : {};
92
- const mode = normalizeText(detail.sessionMode || sessionOverview.mode, null);
93
- const maxTurns = normalizeInteger(sessionOverview.maxTurns, null);
94
- const parts = [];
95
-
96
- if (mode) parts.push(`${mode} mode`);
97
- if (maxTurns != null) parts.push(`max ${maxTurns} turns`);
98
-
99
- return parts.length > 0 ? parts.join(', ') : null;
100
- }
101
-
102
- export function buildRaiseHandGuidance(raiseHandPolicy = {}) {
103
- const mode = normalizeText(raiseHandPolicy?.mode, null);
104
- if (mode === 'dual_raise_hand') {
105
- return `When you are ready to conclude, include ${CLAWORLD_RAISE_HAND_DIRECTIVE} in your reply. The round closes once both agents raise hand.`;
106
- }
107
- if (mode === 'single_raise_hand' || mode === 'either_raise_hand') {
108
- return `When you are ready to conclude, include ${CLAWORLD_RAISE_HAND_DIRECTIVE} in your reply to close the round.`;
109
- }
110
- return null;
111
- }
112
-
113
- export function buildFinalReplyWindowSystemText() {
114
- return 'This is the final reply window for the current round. Reply to the peer and conclude this round in this message.';
115
- }
116
-
117
- export function buildInterventionMessageText(message = {}, { roundBudget = {} } = {}) {
118
- const explicitText = normalizeText(message.text, null);
119
- const templateRef = normalizeText(message.templateRef, null);
120
-
121
- if (templateRef === DEFAULT_TEMPLATE_REFS.convergence) {
122
- const baseText = explicitText || 'You are near the end of this round. Focus on unresolved blockers and prepare to conclude soon.';
123
- return roundBudget.finalReplyWindow
124
- ? `${baseText} ${buildFinalReplyWindowSystemText()}`
125
- : baseText;
126
- }
127
- if (explicitText) return explicitText;
128
- if (templateRef === 'world.turn.nudge') {
129
- return 'Stay concise. Ask only the next most useful question and move toward a decision.';
130
- }
131
- if (templateRef === DEFAULT_TEMPLATE_REFS.stateChanged) {
132
- return 'Round state changed. Update your working state before sending anything else.';
133
- }
134
-
135
- return null;
136
- }
137
-
138
- export function buildRoundClosingSystemText({ continuation = {}, raiseHandPolicy = null } = {}) {
139
- if (continuation?.allowed !== false) return null;
140
- const reason = normalizeText(continuation.reason, null);
141
- const baseText = reason === 'max_turns_reached'
142
- ? 'This round closes now because the configured max-turn limit has been reached.'
143
- : reason === 'dual_raise_hand'
144
- ? 'This round closes now because both agents raised hand.'
145
- : reason === 'raise_hand'
146
- ? 'This round closes now because a completion signal was received.'
147
- : 'This round closes now.';
148
- const raiseHandDirective = buildRaiseHandGuidance(raiseHandPolicy);
149
- return [
150
- baseText,
151
- 'Read the message above, update your state, and do not send another relay turn.',
152
- raiseHandDirective && reason !== 'dual_raise_hand' ? raiseHandDirective : null,
153
- ].filter(Boolean).join(' ');
154
- }
155
-
156
- export function buildWorldSessionStartupEvent(detail = {}) {
157
- const worldId = normalizeText(detail.worldId || detail.worldId, null);
158
- if (!worldId) return null;
159
- const startupText = normalizeText(detail.runtimeStartupContext?.text, null);
160
- if (startupText) return startupText;
161
-
162
- const displayName = normalizeText(detail.displayName || detail.worldDisplayName, worldId);
163
- const summary = normalizeText(detail.summary, null);
164
- const sessionSummary = formatSessionOverview(detail);
165
- const sessionOverview = detail.sessionOverview && typeof detail.sessionOverview === 'object'
166
- ? detail.sessionOverview
167
- : {};
168
- const raiseHandSummary = normalizeText(sessionOverview.raiseHandPolicy?.summary, null);
169
- const openingText = normalizeText(sessionOverview.openingText, null);
170
- const convergenceText = normalizeText(sessionOverview.convergence?.text, null);
171
- const raiseHandDirective = buildRaiseHandGuidance(sessionOverview.raiseHandPolicy);
172
- const interactionRules = normalizeText(detail.interactionRules, null);
173
- const prohibitedRules = normalizeText(detail.prohibitedRules, null);
174
- const ratingRules = normalizeText(detail.ratingRules, null);
175
-
176
- const lines = [
177
- 'Internal Claworld world context for this session.',
178
- 'Do not acknowledge, paraphrase, or announce this setup to the peer unless it is directly relevant to their message.',
179
- `World: ${displayName} [${worldId}]`,
180
- summary ? `Summary: ${summary}` : null,
181
- sessionSummary ? `Session overview: ${sessionSummary}` : null,
182
- raiseHandSummary ? `Completion rule: ${raiseHandSummary}` : null,
183
- 'Interruption handling: prefer reconnect/resume. Temporary silence or reconnect churn is not the normal way to close a round.',
184
- openingText ? `Opening focus: ${openingText}` : null,
185
- interactionRules ? `Interaction rules: ${interactionRules}` : null,
186
- prohibitedRules ? `Prohibited rules: ${prohibitedRules}` : null,
187
- ratingRules ? `Rating rules: ${ratingRules}` : null,
188
- convergenceText ? `Convergence rule: ${convergenceText}` : null,
189
- raiseHandDirective ? `Completion signal: ${raiseHandDirective}` : null,
190
- 'Apply these world rules symmetrically when responding in this session.',
191
- ].filter(Boolean);
192
-
193
- return lines.join('\n');
194
- }
195
-
196
- export function createSystemMessageOrchestrator({ templateRefs = DEFAULT_TEMPLATE_REFS } = {}) {
197
- return {
198
- supportedTriggers: ['session_started', 'turn_threshold', 'convergence', 'state_changed'],
199
- describeRuleShape() {
200
- return {
201
- opening_system_message: 'optional text/template ref',
202
- turn_message_rules: [
203
- {
204
- id: 'turn_nudge_2',
205
- trigger: 'turn_threshold',
206
- atTurn: 2,
207
- visibility: 'both',
208
- role: 'system',
209
- templateRef: 'world.turn.nudge',
210
- once: true,
211
- },
212
- ],
213
- convergence_message: {
214
- whenRemainingTurnsLTE: 1,
215
- templateRef: templateRefs.convergence,
216
- },
217
- state_change_messages: {
218
- active_to_review: templateRefs.stateChanged,
219
- },
220
- };
221
- },
222
- planMessages({
223
- sessionId,
224
- trigger = 'session_started',
225
- turnIndex = 0,
226
- remainingTurns = null,
227
- worldRules = {},
228
- previousState = null,
229
- nextState = null,
230
- emittedRuleIds = [],
231
- } = {}) {
232
- const messages = [];
233
- const emitted = new Set(emittedRuleIds);
234
-
235
- if (trigger === 'session_started' && worldRules.openingSystemMessage !== false) {
236
- messages.push(
237
- buildMessage({
238
- sessionId,
239
- trigger,
240
- templateRef: worldRules.openingTemplateRef || templateRefs.opening,
241
- text: worldRules.openingText || null,
242
- metadata: { phase: 'opening' },
243
- }),
244
- );
245
- }
246
-
247
- const rules = Array.isArray(worldRules.turnMessageRules)
248
- ? worldRules.turnMessageRules.map((rule, index) => normalizeTurnRule(rule, index))
249
- : [];
250
- if (trigger === 'turn_threshold') {
251
- for (const rule of rules) {
252
- if (rule.trigger !== 'turn_threshold') continue;
253
- if (rule.atTurn == null || turnIndex < rule.atTurn) continue;
254
- if (rule.once && emitted.has(rule.id)) continue;
255
- messages.push(
256
- buildMessage({
257
- sessionId,
258
- trigger,
259
- role: rule.role,
260
- visibility: rule.visibility,
261
- templateRef: rule.templateRef,
262
- text: rule.text,
263
- metadata: { ruleId: rule.id, atTurn: rule.atTurn },
264
- }),
265
- );
266
- emitted.add(rule.id);
267
- }
268
- }
269
-
270
- const convergenceThreshold = Number.isFinite(Number(worldRules.convergence?.whenRemainingTurnsLTE))
271
- ? Number(worldRules.convergence.whenRemainingTurnsLTE)
272
- : 1;
273
- if (
274
- trigger === 'convergence' &&
275
- remainingTurns != null &&
276
- Number(remainingTurns) <= convergenceThreshold
277
- ) {
278
- messages.push(
279
- buildMessage({
280
- sessionId,
281
- trigger,
282
- templateRef: worldRules.convergence?.templateRef || templateRefs.convergence,
283
- text: worldRules.convergence?.text || null,
284
- metadata: { remainingTurns: Number(remainingTurns) },
285
- }),
286
- );
287
- }
288
-
289
- if (trigger === 'state_changed' && previousState !== nextState && nextState) {
290
- const stateKey = `${previousState || 'unknown'}_to_${nextState}`;
291
- messages.push(
292
- buildMessage({
293
- sessionId,
294
- trigger,
295
- templateRef:
296
- worldRules.stateChangeMessages?.[stateKey]?.templateRef || templateRefs.stateChanged,
297
- text: worldRules.stateChangeMessages?.[stateKey]?.text || null,
298
- metadata: {
299
- previousState,
300
- nextState,
301
- stateKey,
302
- },
303
- }),
304
- );
305
- }
306
-
307
- return {
308
- sessionId,
309
- turnIndex,
310
- trigger,
311
- emittedRuleIds: [...emitted],
312
- messages,
313
- status: messages.length > 0 ? 'planned' : 'noop',
314
- };
315
- },
316
- };
317
- }
318
-
319
- export function buildSessionGuidancePayload({ session = {} } = {}) {
320
- const worldContext = session?.metadata?.worldContext;
321
- if (!worldContext || typeof worldContext !== 'object' || Array.isArray(worldContext)) return null;
322
-
323
- const worldId = normalizeText(worldContext.worldId, null);
324
- const startupText = buildWorldSessionStartupEvent(worldContext);
325
- return finalizeGuidancePayload([
326
- buildGuidanceMessage({
327
- kind: 'world_session_startup',
328
- contextKey: `claworld:world-startup:${normalizeText(session.sessionId, 'session')}:${worldId || 'world'}`,
329
- text: startupText,
330
- templateRef: DEFAULT_TEMPLATE_REFS.opening,
331
- metadata: {
332
- worldId,
333
- sessionId: normalizeText(session.sessionId, null),
334
- },
335
- }),
336
- ]);
337
- }
338
-
339
- export function buildTurnGuidancePayload({
340
- session = {},
341
- round = {},
342
- turn = {},
343
- roundBudget = {},
344
- continuation = {},
345
- } = {}) {
346
- const sessionId = normalizeText(session.sessionId, null);
347
- const turnId = normalizeText(turn.turnId, 'turn');
348
- const roundId = normalizeText(round.roundId || turn.roundId, 'roundless');
349
- if (!sessionId) return null;
350
-
351
- const messages = [];
352
- const worldContext = session?.metadata?.worldContext;
353
- const sessionOverview = worldContext?.sessionOverview && typeof worldContext.sessionOverview === 'object'
354
- ? worldContext.sessionOverview
355
- : {};
356
- const turnRules = Array.isArray(sessionOverview.turnMessageRules)
357
- ? sessionOverview.turnMessageRules.map((rule, index) => normalizeTurnRule(rule, index))
358
- : [];
359
- const roundTurnIndex = normalizePositiveInteger(roundBudget.roundTurnIndex, 0);
360
-
361
- for (const rule of turnRules) {
362
- if (rule.trigger !== 'turn_threshold') continue;
363
- if (rule.atTurn == null || roundTurnIndex !== rule.atTurn) continue;
364
- const text = buildInterventionMessageText(rule, { roundBudget });
365
- messages.push(
366
- buildGuidanceMessage({
367
- kind: 'world_turn_threshold',
368
- contextKey: `claworld:turn-guidance:${sessionId}:${turnId}:${rule.id}`,
369
- text,
370
- templateRef: rule.templateRef,
371
- metadata: {
372
- ruleId: rule.id,
373
- atTurn: rule.atTurn,
374
- roundId,
375
- },
376
- }),
377
- );
378
- }
379
-
380
- const remainingTurns = normalizeInteger(roundBudget.remainingTurns, null);
381
- const convergenceThreshold = normalizePositiveInteger(sessionOverview.convergence?.whenRemainingTurnsLTE, 1);
382
- if (remainingTurns != null && remainingTurns <= convergenceThreshold && worldContext) {
383
- const templateRef = normalizeText(sessionOverview.convergence?.templateRef, DEFAULT_TEMPLATE_REFS.convergence);
384
- const text = buildInterventionMessageText(
385
- {
386
- templateRef,
387
- text: sessionOverview.convergence?.text || null,
388
- },
389
- { roundBudget },
390
- );
391
- messages.push(
392
- buildGuidanceMessage({
393
- kind: 'world_convergence',
394
- contextKey: `claworld:turn-guidance:${sessionId}:${turnId}:${templateRef}`,
395
- text,
396
- templateRef,
397
- metadata: {
398
- remainingTurns,
399
- roundId,
400
- },
401
- }),
402
- );
403
- }
404
-
405
- if (
406
- continuation?.allowed !== false
407
- && roundBudget?.hasExplicitBudget === true
408
- && roundBudget?.finalReplyWindow === true
409
- && messages.length === 0
410
- ) {
411
- messages.push(
412
- buildGuidanceMessage({
413
- kind: 'final_reply_window',
414
- contextKey: `claworld:final-reply:${sessionId}:${turnId}`,
415
- text: buildFinalReplyWindowSystemText(),
416
- metadata: {
417
- roundId,
418
- },
419
- }),
420
- );
421
- }
422
-
423
- if (
424
- !worldContext
425
- && continuation?.allowed !== false
426
- && roundTurnIndex === 1
427
- && roundBudget?.raiseHandPolicy
428
- ) {
429
- messages.push(
430
- buildGuidanceMessage({
431
- kind: 'direct_round_opening',
432
- contextKey: `claworld:direct-round-guidance:${sessionId}:${roundId}`,
433
- text: buildRaiseHandGuidance(roundBudget.raiseHandPolicy),
434
- metadata: {
435
- roundId,
436
- },
437
- }),
438
- );
439
- }
440
-
441
- messages.push(
442
- buildGuidanceMessage({
443
- kind: 'round_closure',
444
- contextKey: `claworld:round-closure:${sessionId}:${turnId}:${normalizeText(continuation?.reason, 'complete')}`,
445
- text: buildRoundClosingSystemText({
446
- continuation,
447
- raiseHandPolicy: roundBudget?.raiseHandPolicy || sessionOverview.raiseHandPolicy || null,
448
- }),
449
- metadata: {
450
- reason: normalizeText(continuation?.reason, null),
451
- roundId,
452
- },
453
- }),
454
- );
455
-
456
- return finalizeGuidancePayload(messages);
457
- }
@@ -1 +0,0 @@
1
- export { buildWorldSessionStartupEvent } from '../../lib/runtime-guidance.js';
@@ -1,38 +0,0 @@
1
- import { createSystemMessageOrchestrator } from '../../lib/runtime-guidance.js';
2
-
3
- export function createSessionOrchestrator({
4
- worldService,
5
- resultService,
6
- systemMessages = createSystemMessageOrchestrator(),
7
- } = {}) {
8
- return {
9
- previewSession({ worldId, sessionId = 'ses_preview' } = {}) {
10
- const world = worldService.requireWorld(worldId);
11
- const openingPlan = systemMessages.planMessages({
12
- sessionId,
13
- trigger: 'session_started',
14
- worldRules: world.sessionTemplate.worldRules,
15
- });
16
- const convergencePlan = systemMessages.planMessages({
17
- sessionId,
18
- trigger: 'convergence',
19
- remainingTurns: Math.max(world.sessionTemplate.maxTurns - 1, 0),
20
- worldRules: world.sessionTemplate.worldRules,
21
- });
22
-
23
- return {
24
- worldId: world.worldId,
25
- sessionTemplate: {
26
- mode: world.sessionTemplate.mode,
27
- maxTurns: world.sessionTemplate.maxTurns,
28
- turnTimeoutMs: world.sessionTemplate.turnTimeoutMs,
29
- raiseHandPolicy: world.sessionTemplate.raiseHandPolicy,
30
- },
31
- openingPlan,
32
- convergencePlan,
33
- resultPreview: resultService.preview({ world, sessionId }),
34
- status: 'preview_ready',
35
- };
36
- },
37
- };
38
- }