@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,347 @@
1
+ import { createKickoffBrief } from './relay/kickoff-text.js';
2
+
3
+ function normalizeText(value, fallback = null) {
4
+ if (value == null) return fallback;
5
+ const normalized = String(value).trim();
6
+ return normalized || fallback;
7
+ }
8
+
9
+ function cloneJsonObject(value) {
10
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
11
+ try {
12
+ const cloned = JSON.parse(JSON.stringify(value));
13
+ if (!cloned || typeof cloned !== 'object' || Array.isArray(cloned)) return null;
14
+ return cloned;
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+
20
+ export function normalizeChatRequestConversation(input = {}) {
21
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return {};
22
+ const conversation = {
23
+ ...(normalizeText(input.worldId, null) ? { worldId: normalizeText(input.worldId, null) } : {}),
24
+ ...(normalizeText(input.scope, null)
25
+ ? { scope: normalizeText(input.scope, null) }
26
+ : {}),
27
+ ...(normalizeText(input.conversationId, null) ? { conversationId: normalizeText(input.conversationId, null) } : {}),
28
+ ...(normalizeText(input.threadId, null) ? { threadId: normalizeText(input.threadId, null) } : {}),
29
+ ...(normalizeText(input.conversationKey, null) ? { conversationKey: normalizeText(input.conversationKey, null) } : {}),
30
+ ...(normalizeText(input.sessionKey, null) ? { sessionKey: normalizeText(input.sessionKey, null) } : {}),
31
+ };
32
+
33
+ const episode = cloneJsonObject(input.episode);
34
+ if (episode) {
35
+ conversation.episode = episode;
36
+ }
37
+ const worldContextText = normalizeText(
38
+ input.worldContextText,
39
+ normalizeText(input.worldContext?.worldContextText, normalizeText(input.worldContext?.text, null)),
40
+ );
41
+ if (worldContextText) {
42
+ conversation.worldContextText = worldContextText;
43
+ }
44
+
45
+ return conversation;
46
+ }
47
+
48
+ export function normalizeChatRequestOrigin(origin = {}, { fallbackType = null } = {}) {
49
+ if (!origin || typeof origin !== 'object' || Array.isArray(origin)) {
50
+ const type = normalizeText(fallbackType, null);
51
+ return type ? { type } : null;
52
+ }
53
+
54
+ const normalized = {
55
+ ...(normalizeText(origin.type, normalizeText(fallbackType, null))
56
+ ? { type: normalizeText(origin.type, normalizeText(fallbackType, null)) }
57
+ : {}),
58
+ ...(normalizeText(origin.broadcastId, null) ? { broadcastId: normalizeText(origin.broadcastId, null) } : {}),
59
+ };
60
+
61
+ return Object.keys(normalized).length > 0 ? normalized : null;
62
+ }
63
+
64
+ export function normalizeChatRequestBroadcast(input = {}) {
65
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
66
+ const normalized = {
67
+ ...(normalizeText(input.broadcastId, null) ? { broadcastId: normalizeText(input.broadcastId, null) } : {}),
68
+ ...(normalizeText(input.worldId, null) ? { worldId: normalizeText(input.worldId, null) } : {}),
69
+ ...(normalizeText(input.audience, null) ? { audience: normalizeText(input.audience, null) } : {}),
70
+ ...(normalizeText(input.senderRole, null) ? { senderRole: normalizeText(input.senderRole, null) } : {}),
71
+ ...(normalizeText(input.eligibility, null) ? { eligibility: normalizeText(input.eligibility, null) } : {}),
72
+ ...(typeof input.excludeSelf === 'boolean' ? { excludeSelf: input.excludeSelf } : {}),
73
+ };
74
+ return Object.keys(normalized).length > 0 ? normalized : null;
75
+ }
76
+
77
+ export function normalizeChatRequestOpeningPayload(input = null) {
78
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
79
+ const payload = cloneJsonObject(input);
80
+ if (!payload) return null;
81
+ if (typeof payload.text === 'string') {
82
+ payload.text = payload.text.trim();
83
+ if (!payload.text) delete payload.text;
84
+ }
85
+ if (typeof payload.source === 'string') {
86
+ payload.source = payload.source.trim() || undefined;
87
+ }
88
+ return Object.keys(payload).length > 0 ? payload : null;
89
+ }
90
+
91
+ export function resolveChatRequestOpeningMessage({
92
+ openingMessage = null,
93
+ openingPayload = null,
94
+ requestContext = null,
95
+ } = {}) {
96
+ return normalizeText(
97
+ openingMessage,
98
+ normalizeText(openingPayload?.text, normalizeText(requestContext?.message, null)),
99
+ );
100
+ }
101
+
102
+ function resolveKickoffBriefSource({
103
+ kickoffBrief = null,
104
+ openingPayload = null,
105
+ requestContext = null,
106
+ source = null,
107
+ } = {}) {
108
+ const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
109
+ ? requestContext
110
+ : {};
111
+ const explicitKickoffBrief = kickoffBrief && typeof kickoffBrief === 'object' && !Array.isArray(kickoffBrief)
112
+ ? kickoffBrief
113
+ : null;
114
+ const contextKickoffBrief = normalizedContext.kickoffBrief && typeof normalizedContext.kickoffBrief === 'object' && !Array.isArray(normalizedContext.kickoffBrief)
115
+ ? normalizedContext.kickoffBrief
116
+ : null;
117
+ const fallbackSource = normalizeText(source, null) === 'world_broadcast'
118
+ ? 'world_broadcast_brief'
119
+ : 'chat_request_brief';
120
+ return normalizeText(
121
+ explicitKickoffBrief?.source,
122
+ normalizeText(
123
+ contextKickoffBrief?.source,
124
+ normalizeText(
125
+ openingPayload?.source,
126
+ normalizeText(normalizedContext.openingPayload?.source, fallbackSource),
127
+ ),
128
+ ),
129
+ );
130
+ }
131
+
132
+ function resolveChatRequestKickoffBrief({
133
+ kickoffBrief = null,
134
+ openingMessage = null,
135
+ openingPayload = null,
136
+ requestContext = null,
137
+ source = null,
138
+ } = {}) {
139
+ const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
140
+ ? requestContext
141
+ : {};
142
+ const explicitKickoffBrief = kickoffBrief && typeof kickoffBrief === 'object' && !Array.isArray(kickoffBrief)
143
+ ? kickoffBrief
144
+ : null;
145
+ const contextKickoffBrief = normalizedContext.kickoffBrief && typeof normalizedContext.kickoffBrief === 'object' && !Array.isArray(normalizedContext.kickoffBrief)
146
+ ? normalizedContext.kickoffBrief
147
+ : null;
148
+ const normalizedOpeningPayload = normalizeChatRequestOpeningPayload(
149
+ explicitKickoffBrief?.payload
150
+ ?? contextKickoffBrief?.payload
151
+ ?? openingPayload
152
+ ?? normalizedContext.openingPayload,
153
+ );
154
+ const normalizedOpeningMessage = resolveChatRequestOpeningMessage({
155
+ openingMessage:
156
+ explicitKickoffBrief?.text
157
+ ?? contextKickoffBrief?.text
158
+ ?? openingMessage,
159
+ openingPayload: normalizedOpeningPayload,
160
+ requestContext: normalizedContext,
161
+ });
162
+ return createKickoffBrief({
163
+ text: normalizedOpeningMessage,
164
+ payload: explicitKickoffBrief?.payload ?? contextKickoffBrief?.payload ?? normalizedOpeningPayload,
165
+ source: resolveKickoffBriefSource({
166
+ kickoffBrief: explicitKickoffBrief ?? contextKickoffBrief,
167
+ openingPayload: normalizedOpeningPayload,
168
+ requestContext: normalizedContext,
169
+ source,
170
+ }),
171
+ });
172
+ }
173
+
174
+ export function normalizeChatRequestInput({ requestContext = {}, source = null } = {}) {
175
+ const normalizedContext = requestContext && typeof requestContext === 'object' && !Array.isArray(requestContext)
176
+ ? requestContext
177
+ : {};
178
+ const conversationSource = normalizedContext.conversation && typeof normalizedContext.conversation === 'object' && !Array.isArray(normalizedContext.conversation)
179
+ ? normalizedContext.conversation
180
+ : {};
181
+ const conversation = normalizeChatRequestConversation({
182
+ ...conversationSource,
183
+ conversationKey: normalizedContext.conversationKey ?? conversationSource.conversationKey,
184
+ sessionKey: normalizedContext.sessionKey ?? conversationSource.sessionKey,
185
+ });
186
+ const kickoffBrief = resolveChatRequestKickoffBrief({
187
+ requestContext: normalizedContext,
188
+ source,
189
+ });
190
+ const openingPayload = normalizeChatRequestOpeningPayload(kickoffBrief?.payload ?? normalizedContext.openingPayload);
191
+ const broadcast = normalizeChatRequestBroadcast(normalizedContext.broadcast);
192
+ let origin = normalizeChatRequestOrigin(normalizedContext.origin, {
193
+ fallbackType: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request',
194
+ });
195
+
196
+ if (broadcast?.broadcastId && !origin?.broadcastId) {
197
+ origin = {
198
+ ...(origin || { type: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request' }),
199
+ broadcastId: broadcast.broadcastId,
200
+ };
201
+ }
202
+
203
+ return {
204
+ kickoffBrief,
205
+ openingMessage: resolveChatRequestOpeningMessage({
206
+ openingMessage: kickoffBrief?.text ?? null,
207
+ openingPayload: kickoffBrief?.payload ?? openingPayload,
208
+ requestContext: normalizedContext,
209
+ }),
210
+ openingPayload: kickoffBrief?.payload ?? openingPayload,
211
+ conversation,
212
+ origin,
213
+ broadcast,
214
+ };
215
+ }
216
+
217
+ export function buildChatRequestContext({
218
+ kickoffBrief = null,
219
+ openingMessage = null,
220
+ openingPayload = null,
221
+ conversation = {},
222
+ origin = null,
223
+ broadcast = null,
224
+ source = 'chat_request',
225
+ } = {}) {
226
+ const normalizedConversation = normalizeChatRequestConversation(conversation);
227
+ const normalizedKickoffBrief = resolveChatRequestKickoffBrief({
228
+ kickoffBrief,
229
+ openingMessage,
230
+ openingPayload,
231
+ source,
232
+ });
233
+ const normalizedOpeningPayload = normalizeChatRequestOpeningPayload(
234
+ normalizedKickoffBrief?.payload ?? openingPayload,
235
+ );
236
+ const normalizedMessage = resolveChatRequestOpeningMessage({
237
+ openingMessage: normalizedKickoffBrief?.text ?? openingMessage,
238
+ openingPayload: normalizedOpeningPayload,
239
+ });
240
+ let normalizedOrigin = normalizeChatRequestOrigin(origin, {
241
+ fallbackType: normalizeText(source, null) === 'world_broadcast' ? 'world_broadcast' : 'chat_request',
242
+ });
243
+ let normalizedBroadcast = normalizeChatRequestBroadcast(broadcast);
244
+
245
+ if (normalizedOrigin?.broadcastId && !normalizedBroadcast?.broadcastId) {
246
+ normalizedBroadcast = {
247
+ ...(normalizedBroadcast || {}),
248
+ broadcastId: normalizedOrigin.broadcastId,
249
+ };
250
+ }
251
+
252
+ const requestContext = {
253
+ type: 'chat_request',
254
+ ...(normalizedKickoffBrief ? { kickoffBrief: normalizedKickoffBrief } : {}),
255
+ ...(normalizedMessage ? { message: normalizedMessage } : {}),
256
+ ...(normalizedOpeningPayload ? { openingPayload: normalizedOpeningPayload } : {}),
257
+ ...(Object.keys(normalizedConversation).length > 0 ? { conversation: normalizedConversation } : {}),
258
+ ...(normalizedOrigin ? { origin: normalizedOrigin } : {}),
259
+ ...(normalizedBroadcast ? { broadcast: normalizedBroadcast } : {}),
260
+ };
261
+
262
+ return requestContext;
263
+ }
264
+
265
+ export function normalizeStoredChatRequest(input = {}, { defaultSource = 'chat_request' } = {}) {
266
+ const normalizedSource = normalizeText(input.source, defaultSource);
267
+ const normalizedRequest = normalizeChatRequestInput({
268
+ requestContext: input.requestContext,
269
+ source: normalizedSource,
270
+ });
271
+ const kickoffBrief = resolveChatRequestKickoffBrief({
272
+ kickoffBrief: input.kickoffBrief,
273
+ openingMessage: input.openingMessage,
274
+ openingPayload: input.openingPayload ?? normalizedRequest.openingPayload,
275
+ requestContext: input.requestContext,
276
+ source: normalizedSource,
277
+ });
278
+ const openingPayload = normalizeChatRequestOpeningPayload(
279
+ input.openingPayload ?? kickoffBrief?.payload ?? normalizedRequest.openingPayload,
280
+ );
281
+ const openingMessage = resolveChatRequestOpeningMessage({
282
+ openingMessage: kickoffBrief?.text ?? input.openingMessage,
283
+ openingPayload,
284
+ requestContext: input.requestContext,
285
+ });
286
+ const conversation = normalizeChatRequestConversation(
287
+ input.conversation && typeof input.conversation === 'object' && !Array.isArray(input.conversation)
288
+ ? input.conversation
289
+ : normalizedRequest.conversation,
290
+ );
291
+ const broadcast = normalizeChatRequestBroadcast(
292
+ input.broadcast && typeof input.broadcast === 'object' && !Array.isArray(input.broadcast)
293
+ ? input.broadcast
294
+ : normalizedRequest.broadcast,
295
+ );
296
+ let origin = normalizeChatRequestOrigin(
297
+ input.origin && typeof input.origin === 'object' && !Array.isArray(input.origin)
298
+ ? input.origin
299
+ : normalizedRequest.origin,
300
+ { fallbackType: normalizedSource === 'world_broadcast' ? 'world_broadcast' : 'chat_request' },
301
+ );
302
+
303
+ if (broadcast?.broadcastId && !origin?.broadcastId) {
304
+ origin = {
305
+ ...(origin || { type: normalizedSource === 'world_broadcast' ? 'world_broadcast' : 'chat_request' }),
306
+ broadcastId: broadcast.broadcastId,
307
+ };
308
+ }
309
+
310
+ const chatRequestId = normalizeText(input.chatRequestId, normalizeText(input.requestId, null));
311
+ const normalized = {
312
+ chatRequestId,
313
+ requestId: chatRequestId,
314
+ fromAgentId: normalizeText(input.fromAgentId, null),
315
+ toAgentId: normalizeText(input.toAgentId, null),
316
+ toAddress: normalizeText(input.toAddress, null),
317
+ openingMessage,
318
+ ...(kickoffBrief ? { kickoffBrief } : {}),
319
+ ...(openingPayload ? { openingPayload } : {}),
320
+ conversation,
321
+ ...(origin ? { origin } : {}),
322
+ ...(broadcast ? { broadcast } : {}),
323
+ requestContext: buildChatRequestContext({
324
+ kickoffBrief,
325
+ openingMessage,
326
+ openingPayload,
327
+ conversation,
328
+ origin,
329
+ broadcast,
330
+ source: normalizedSource,
331
+ }),
332
+ status: normalizeText(input.status, 'pending'),
333
+ createdAt: normalizeText(input.createdAt, null),
334
+ respondedAt: normalizeText(input.respondedAt, null),
335
+ expiresAt: normalizeText(input.expiresAt, null),
336
+ source: normalizedSource,
337
+ };
338
+
339
+ const acceptedByAgentId = normalizeText(input.acceptedByAgentId, null);
340
+ if (acceptedByAgentId) normalized.acceptedByAgentId = acceptedByAgentId;
341
+ const approvalGrantId = normalizeText(input.approvalGrantId, null);
342
+ if (approvalGrantId) normalized.approvalGrantId = approvalGrantId;
343
+ const kickoff = cloneJsonObject(input.kickoff);
344
+ if (kickoff) normalized.kickoff = kickoff;
345
+
346
+ return normalized;
347
+ }
@@ -21,6 +21,43 @@ function normalizeKickoffPayload(input) {
21
21
  return cloneJsonObject(input);
22
22
  }
23
23
 
24
+ function formatScalar(value) {
25
+ if (value == null) return null;
26
+ if (typeof value === 'string') return normalizeText(value, null);
27
+ if (typeof value === 'number' || typeof value === 'boolean') return String(value);
28
+ return null;
29
+ }
30
+
31
+ function formatStructuredValue(value, indent = '') {
32
+ const scalar = formatScalar(value);
33
+ if (scalar != null) return scalar;
34
+ if (Array.isArray(value)) {
35
+ const items = value
36
+ .map((item) => formatStructuredValue(item, `${indent} `))
37
+ .filter(Boolean);
38
+ if (items.length === 0) return null;
39
+ return items.map((item) => `${indent}- ${String(item).replace(/\n/g, `\n${indent} `)}`).join('\n');
40
+ }
41
+ if (!value || typeof value !== 'object') return null;
42
+ const entries = Object.entries(value)
43
+ .map(([key, entryValue]) => {
44
+ const formatted = formatStructuredValue(entryValue, `${indent} `);
45
+ if (!formatted) return null;
46
+ if (formatted.includes('\n')) {
47
+ return `${indent}${key}:\n${formatted}`;
48
+ }
49
+ return `${indent}${key}: ${formatted}`;
50
+ })
51
+ .filter(Boolean);
52
+ return entries.length > 0 ? entries.join('\n') : null;
53
+ }
54
+
55
+ function formatStructuredSection(title, value) {
56
+ const formatted = formatStructuredValue(value);
57
+ if (!formatted) return null;
58
+ return `${title}:\n${formatted}`;
59
+ }
60
+
24
61
  function normalizeKickoffSource(value, fallback = 'chat_request_brief') {
25
62
  return normalizeText(value, fallback);
26
63
  }
@@ -63,7 +100,7 @@ export function resolveStoredKickoffBrief(requestContext = {}) {
63
100
  return createKickoffBrief({
64
101
  text: normalizeText(requestContext.openingPayload?.text, normalizeText(requestContext.message, null)),
65
102
  payload: requestContext.openingPayload,
66
- source: requestContext.openingPayload?.source || 'legacy_chat_request_opening',
103
+ source: requestContext.openingPayload?.source || 'chat_request_opening',
67
104
  });
68
105
  }
69
106
 
@@ -151,16 +188,28 @@ export function createAcceptedChatKickoffRuntimeContextForAgent(bundle = {}, {
151
188
 
152
189
  export function formatAcceptedChatKickoffMessage(bundle = {}, { viewer = 'recipient' } = {}) {
153
190
  const normalizedViewer = viewer === 'sender' ? 'sender' : 'recipient';
154
- const request = bundle.request && typeof bundle.request === 'object' ? bundle.request : {};
155
- const conversation = bundle.conversation && typeof bundle.conversation === 'object' ? bundle.conversation : {};
156
- const participants = bundle.participants && typeof bundle.participants === 'object' ? bundle.participants : {};
157
- const sender = participants.sender && typeof participants.sender === 'object' ? participants.sender : {};
158
- const recipient = participants.recipient && typeof participants.recipient === 'object' ? participants.recipient : {};
159
- const world = bundle.world && typeof bundle.world === 'object' ? bundle.world : null;
160
- const policy = bundle.policy && typeof bundle.policy === 'object' ? bundle.policy : {};
161
- const brief = request.brief && typeof request.brief === 'object' ? request.brief : {};
162
-
163
- const worldLabel = normalizeText(world?.displayName, normalizeText(world?.worldId, null));
191
+ const requestContext = bundle.requestContext && typeof bundle.requestContext === 'object' && !Array.isArray(bundle.requestContext)
192
+ ? bundle.requestContext
193
+ : {};
194
+ const worldInfo = bundle.worldInfo && typeof bundle.worldInfo === 'object' && !Array.isArray(bundle.worldInfo)
195
+ ? bundle.worldInfo
196
+ : null;
197
+ const senderInfo = bundle.senderInfo && typeof bundle.senderInfo === 'object' && !Array.isArray(bundle.senderInfo)
198
+ ? bundle.senderInfo
199
+ : (
200
+ bundle.selfInfo && typeof bundle.selfInfo === 'object' && !Array.isArray(bundle.selfInfo)
201
+ ? bundle.selfInfo
202
+ : null
203
+ );
204
+ const recipientInfo = bundle.recipientInfo && typeof bundle.recipientInfo === 'object' && !Array.isArray(bundle.recipientInfo)
205
+ ? bundle.recipientInfo
206
+ : (
207
+ bundle.peerInfo && typeof bundle.peerInfo === 'object' && !Array.isArray(bundle.peerInfo)
208
+ ? bundle.peerInfo
209
+ : null
210
+ );
211
+ const selfInfo = normalizedViewer === 'sender' ? senderInfo : recipientInfo;
212
+ const peerInfo = normalizedViewer === 'sender' ? recipientInfo : senderInfo;
164
213
  const viewerInstruction = normalizedViewer === 'recipient'
165
214
  ? 'Use this accepted-chat kickoff context to interpret the sender opener as the first live turn of the accepted chat episode. Decide whether and how to reply. Do not echo the bundle verbatim to the peer.'
166
215
  : 'Use this accepted-chat kickoff bundle to craft the first live opener to the recipient. Do not echo the bundle verbatim to the peer.';
@@ -171,21 +220,13 @@ export function formatAcceptedChatKickoffMessage(bundle = {}, { viewer = 'recipi
171
220
  : 'Internal Claworld accepted-chat kickoff bundle for the sender runtime.',
172
221
  viewerInstruction,
173
222
  normalizeText(bundle.requestId, null) ? `Accepted episode: ${bundle.requestId}` : null,
174
- normalizeText(conversation.mode, null) ? `Conversation mode: ${conversation.mode}` : null,
175
- worldLabel ? `World: ${worldLabel}${world?.worldId ? ` [${world.worldId}]` : ''}` : null,
176
- brief.text ? `Sender brief: ${brief.text}` : null,
177
- sender.displayName || sender.agentId
178
- ? `Sender: ${normalizeText(sender.displayName, sender.agentId)}${sender.agentId ? ` [${sender.agentId}]` : ''}`
179
- : null,
180
- recipient.displayName || recipient.agentId
181
- ? `Recipient: ${normalizeText(recipient.displayName, recipient.agentId)}${recipient.agentId ? ` [${recipient.agentId}]` : ''}`
182
- : null,
183
- world?.summary ? `World summary: ${world.summary}` : null,
184
- world?.sessionContext ? `World session context:\n${JSON.stringify(world.sessionContext, null, 2)}` : null,
185
- participants.sender?.worldProfile ? `Sender world profile:\n${JSON.stringify(participants.sender.worldProfile, null, 2)}` : null,
186
- participants.recipient?.worldProfile ? `Recipient world profile:\n${JSON.stringify(participants.recipient.worldProfile, null, 2)}` : null,
187
- Object.keys(policy).length > 0 ? `Accepted episode policy:\n${JSON.stringify(policy, null, 2)}` : null,
188
- brief.payload ? `Structured brief payload:\n${JSON.stringify(brief.payload, null, 2)}` : null,
223
+ formatStructuredSection('主人想让你做的事情 / 请求上下文', requestContext),
224
+ formatStructuredSection('世界信息', worldInfo),
225
+ formatStructuredSection('我方信息', selfInfo),
226
+ formatStructuredSection('对方信息', peerInfo),
227
+ normalizedViewer === 'sender'
228
+ ? '请你现在直接输出一条自然的开场白。不要解释规则,不要复述这些说明。'
229
+ : '请把对方刚发来的 opener 视为这段对话的第一条 live turn,并决定是否以及如何直接回复。不要解释规则,不要复述这些说明。',
189
230
  ].filter(Boolean);
190
231
 
191
232
  return blocks.join('\n\n');
@@ -37,17 +37,12 @@ export {
37
37
  buildWorldSelectionPrompt,
38
38
  resolveWorldSelection,
39
39
  fetchWorldDetail,
40
- fetchWorldJoinCheck,
41
40
  joinWorld,
42
- submitWorldJoin,
43
41
  fetchWorldSearch,
44
42
  submitWorldSearch,
45
43
  broadcastWorld,
46
44
  fetchWorldCandidateFeed,
47
45
  buildCandidateDeliverySummary,
48
- buildRequiredFieldExplanation,
49
- resolveWorldProfileCollectionFlow,
50
46
  resolveWorldSelectionFlow,
51
- resolveWorldJoinFlow,
52
47
  } from './runtime/product-shell-helper.js';
53
48
  export { submitFeedbackReport } from './runtime/feedback-helper.js';
@@ -1,9 +1,7 @@
1
1
  import os from 'os';
2
2
  import path from 'path';
3
3
  import {
4
- DEFAULT_CLAWORLD_TOOL_PROFILE,
5
4
  expandUserPath,
6
- normalizeClaworldToolProfile,
7
5
  } from '../plugin/managed-config.js';
8
6
  import {
9
7
  CLAWORLD_DOCTOR_COMMAND,
@@ -37,10 +35,10 @@ Install options:
37
35
  --server-url <url> Override the Claworld backend URL
38
36
  --api-key <value> Override the Claworld backend API key
39
37
  --account-id <id> Managed Claworld account id (default: claworld)
40
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
41
- --workspace <path> Managed agent workspace path
38
+ --agent-id <id> Local OpenClaw agent id to bind claworld onto (default: main)
39
+ --workspace <path> Optional dedicated workspace path for claworld-specific bootstrap files
42
40
  --display-name <name> Managed display name override
43
- --tool-profile <name> minimal | default | full (default: ${DEFAULT_CLAWORLD_TOOL_PROFILE})
41
+ --tool-profile <profile> minimal | default | full | world
44
42
  --repo-root <path> Local repo root when using --plugin-install-mode link|copy
45
43
  --plugin-install-mode <m> npm | link | copy | skip (default: npm)
46
44
  --plugin-source <value> npm package or local path (default: ${CLAWORLD_INSTALLER_PACKAGE_NAME})
@@ -51,18 +49,18 @@ Update options:
51
49
  --server-url <url> Override the Claworld backend URL
52
50
  --api-key <value> Override the Claworld backend API key
53
51
  --account-id <id> Managed Claworld account id (default: claworld)
54
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
55
- --workspace <path> Managed agent workspace path
52
+ --agent-id <id> Local OpenClaw agent id bound to claworld (default: main)
53
+ --workspace <path> Optional dedicated workspace path for claworld-specific bootstrap files
56
54
  --display-name <name> Managed display name override
57
- --tool-profile <name> minimal | default | full (default: ${DEFAULT_CLAWORLD_TOOL_PROFILE})
55
+ --tool-profile <profile> minimal | default | full | world
58
56
  Doctor options:
59
57
  --config <path> OpenClaw config path (default: ${DEFAULT_OPENCLAW_CONFIG_PATH})
60
58
  --state-dir <path> Optional OPENCLAW_STATE_DIR for OpenClaw commands
61
59
  --openclaw-bin <path> OpenClaw CLI binary (default: ${DEFAULT_OPENCLAW_BIN})
62
60
  --server-url <url> Override the Claworld backend URL
63
61
  --account-id <id> Managed Claworld account id (default: claworld)
64
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
65
- --workspace <path> Managed workspace path override
62
+ --agent-id <id> Local OpenClaw agent id bound to claworld (default: main)
63
+ --workspace <path> Optional dedicated workspace path override
66
64
  --json Print machine-readable result
67
65
  --help, -h Show this help
68
66
 
@@ -92,13 +90,13 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
92
90
  serverUrl: null,
93
91
  apiKey: null,
94
92
  accountId: 'claworld',
95
- agentId: 'claworld',
93
+ agentId: 'main',
96
94
  workspace: null,
97
95
  displayName: null,
98
- toolProfile: DEFAULT_CLAWORLD_TOOL_PROFILE,
99
96
  repoRoot: null,
100
97
  pluginInstallMode: 'npm',
101
98
  pluginInstallSource: CLAWORLD_INSTALLER_PACKAGE_NAME,
99
+ toolProfile: null,
102
100
  },
103
101
  update: {
104
102
  openclawBin: env.OPENCLAW_BIN || DEFAULT_OPENCLAW_BIN,
@@ -107,10 +105,10 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
107
105
  serverUrl: null,
108
106
  apiKey: null,
109
107
  accountId: 'claworld',
110
- agentId: 'claworld',
108
+ agentId: 'main',
111
109
  workspace: null,
112
110
  displayName: null,
113
- toolProfile: DEFAULT_CLAWORLD_TOOL_PROFILE,
111
+ toolProfile: null,
114
112
  },
115
113
  doctor: {
116
114
  openclawBin: env.OPENCLAW_BIN || DEFAULT_OPENCLAW_BIN,
@@ -118,7 +116,7 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
118
116
  stateDir: env.OPENCLAW_STATE_DIR ? expandUserPath(env.OPENCLAW_STATE_DIR, homeDir) : null,
119
117
  serverUrl: null,
120
118
  accountId: 'claworld',
121
- agentId: 'claworld',
119
+ agentId: 'main',
122
120
  workspace: null,
123
121
  },
124
122
  };
@@ -187,7 +185,7 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
187
185
  index += 1;
188
186
  break;
189
187
  case '--tool-profile':
190
- options.install.toolProfile = normalizeClaworldToolProfile(nextValue(remaining, index));
188
+ options.install.toolProfile = nextValue(remaining, index);
191
189
  options.update.toolProfile = options.install.toolProfile;
192
190
  index += 1;
193
191
  break;
@@ -6,13 +6,13 @@ import { spawnSync } from 'child_process';
6
6
  import vm from 'vm';
7
7
  import {
8
8
  DEFAULT_CLAWORLD_ACCOUNT_ID,
9
+ DEFAULT_CLAWORLD_AGENT_ID,
9
10
  DEFAULT_CLAWORLD_SERVER_URL,
10
11
  applyClaworldManagedRuntimeConfig,
11
12
  ensureObject,
12
13
  expandUserPath,
13
14
  normalizeText,
14
15
  resolveClaworldManagedRuntimeOptions,
15
- resolveToolNames,
16
16
  } from '../plugin/managed-config.js';
17
17
  import {
18
18
  defaultClaworldAccountId,
@@ -58,13 +58,7 @@ export function hasManagedBinding(config = {}, { agentId, accountId } = {}) {
58
58
  }
59
59
 
60
60
  export function isManagedToolAllowlistReady(config = {}, options = {}) {
61
- const allow = new Set(
62
- (Array.isArray(config?.tools?.allow) ? config.tools.allow : [])
63
- .map((item) => normalizeText(item, null))
64
- .filter(Boolean),
65
- );
66
- if (allow.has('*')) return true;
67
- return resolveToolNames(options).every((toolName) => allow.has(toolName));
61
+ return true;
68
62
  }
69
63
 
70
64
  export function isRelayBootstrapReady(account = {}) {
@@ -474,9 +468,12 @@ function defaultCommandRunner({
474
468
  };
475
469
  }
476
470
 
471
+ const useShell = process.platform === 'win32' && /\.(cmd|bat)$/i.test(effectiveBin);
477
472
  const result = spawnSync(effectiveBin, args, {
478
473
  cwd,
479
474
  env,
475
+ shell: useShell,
476
+ windowsHide: true,
480
477
  stdio: capture ? 'pipe' : 'inherit',
481
478
  encoding: 'utf8',
482
479
  });
@@ -622,9 +619,9 @@ export function inspectManagedClaworldInstall({
622
619
  const managedReady = Boolean(
623
620
  managedAccountPresent
624
621
  && managedRuntimeReady
625
- && managedAgentPresent
626
622
  && managedBindingPresent
627
623
  && toolsReady
624
+ && (managedOptions.manageAgentEntry !== true || managedAgentPresent)
628
625
  );
629
626
 
630
627
  let statusLabel = 'needs setup';
@@ -1153,7 +1150,7 @@ export async function verifyClaworldInstall({
1153
1150
  configPath = null,
1154
1151
  stateDir = DEFAULT_OPENCLAW_STATE_DIR,
1155
1152
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1156
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1153
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1157
1154
  commandRunner = defaultCommandRunner,
1158
1155
  cwd = process.cwd(),
1159
1156
  env = process.env,
@@ -1255,7 +1252,7 @@ async function reconcileManagedClaworldRuntime({
1255
1252
  serverUrl = null,
1256
1253
  apiKey = null,
1257
1254
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1258
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1255
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1259
1256
  workspace = null,
1260
1257
  displayName = null,
1261
1258
  toolProfile = null,
@@ -1396,7 +1393,9 @@ async function reconcileManagedClaworldRuntime({
1396
1393
  await writeConfig(configPath, transformed.config, dryRun);
1397
1394
  }
1398
1395
 
1399
- const workspaceActions = await seedManagedWorkspace(managedOptions, dryRun);
1396
+ const workspaceActions = managedOptions.manageWorkspace
1397
+ ? await seedManagedWorkspace(managedOptions, dryRun)
1398
+ : [];
1400
1399
  await validateOpenclawConfig({
1401
1400
  openclawBin,
1402
1401
  configPath,
@@ -1459,7 +1458,7 @@ export async function runClaworldInstallerInstall({
1459
1458
  serverUrl = null,
1460
1459
  apiKey = null,
1461
1460
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1462
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1461
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1463
1462
  workspace = null,
1464
1463
  displayName = null,
1465
1464
  toolProfile = null,
@@ -1559,7 +1558,7 @@ export async function runClaworldInstallerUpdate({
1559
1558
  serverUrl = null,
1560
1559
  apiKey = null,
1561
1560
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1562
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1561
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1563
1562
  workspace = null,
1564
1563
  displayName = null,
1565
1564
  toolProfile = null,