@xfxstudio/claworld 0.1.5 → 0.2.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.
Files changed (54) hide show
  1. package/README.md +12 -29
  2. package/openclaw.plugin.json +5 -29
  3. package/package.json +4 -12
  4. package/skills/claworld-help/SKILL.md +50 -182
  5. package/skills/claworld-join-and-chat/SKILL.md +78 -288
  6. package/skills/claworld-manage-worlds/SKILL.md +71 -288
  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 +18 -9
  11. package/src/openclaw/installer/core.js +12 -6
  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 +118 -623
  15. package/src/openclaw/plugin/config-schema.js +3 -15
  16. package/src/openclaw/plugin/managed-config.js +98 -47
  17. package/src/openclaw/plugin/onboarding.js +7 -3
  18. package/src/openclaw/plugin/register.js +37 -336
  19. package/src/openclaw/plugin/relay-client.js +111 -101
  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 +43 -636
  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 +33 -258
  30. package/src/openclaw/runtime/world-moderation-helper.js +11 -65
  31. package/src/product-shell/catalog/default-world-catalog.js +9 -27
  32. package/src/product-shell/contracts/candidate-feed.js +26 -1
  33. package/src/product-shell/contracts/chat-request-approval-policy.js +4 -4
  34. package/src/product-shell/contracts/world-manifest.js +115 -160
  35. package/src/product-shell/contracts/world-orchestration.js +47 -322
  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 +5 -6
  39. package/src/product-shell/membership/membership-service.js +125 -147
  40. package/src/product-shell/onboarding/onboarding-service.js +2 -2
  41. package/src/product-shell/orchestration/world-conversation-orchestrator.js +30 -0
  42. package/src/product-shell/orchestration/world-conversation-text.js +231 -0
  43. package/src/product-shell/results/result-service.js +9 -3
  44. package/src/product-shell/search/search-service.js +28 -1
  45. package/src/product-shell/social/chat-request-routes.js +0 -1
  46. package/src/product-shell/social/chat-request-service.js +1 -102
  47. package/src/product-shell/worlds/world-admin-service.js +85 -276
  48. package/src/product-shell/worlds/world-authorization.js +3 -5
  49. package/src/product-shell/worlds/world-routes.js +8 -38
  50. package/src/product-shell/worlds/world-service.js +3 -3
  51. package/src/product-shell/worlds/world-text.js +77 -0
  52. package/src/lib/runtime-guidance.js +0 -457
  53. package/src/openclaw/runtime/world-session-startup.js +0 -1
  54. 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';
@@ -35,9 +35,10 @@ Install options:
35
35
  --server-url <url> Override the Claworld backend URL
36
36
  --api-key <value> Override the Claworld backend API key
37
37
  --account-id <id> Managed Claworld account id (default: claworld)
38
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
39
- --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
40
40
  --display-name <name> Managed display name override
41
+ --tool-profile <profile> minimal | default | full | world
41
42
  --repo-root <path> Local repo root when using --plugin-install-mode link|copy
42
43
  --plugin-install-mode <m> npm | link | copy | skip (default: npm)
43
44
  --plugin-source <value> npm package or local path (default: ${CLAWORLD_INSTALLER_PACKAGE_NAME})
@@ -48,17 +49,18 @@ Update options:
48
49
  --server-url <url> Override the Claworld backend URL
49
50
  --api-key <value> Override the Claworld backend API key
50
51
  --account-id <id> Managed Claworld account id (default: claworld)
51
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
52
- --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
53
54
  --display-name <name> Managed display name override
55
+ --tool-profile <profile> minimal | default | full | world
54
56
  Doctor options:
55
57
  --config <path> OpenClaw config path (default: ${DEFAULT_OPENCLAW_CONFIG_PATH})
56
58
  --state-dir <path> Optional OPENCLAW_STATE_DIR for OpenClaw commands
57
59
  --openclaw-bin <path> OpenClaw CLI binary (default: ${DEFAULT_OPENCLAW_BIN})
58
60
  --server-url <url> Override the Claworld backend URL
59
61
  --account-id <id> Managed Claworld account id (default: claworld)
60
- --agent-id <id> Managed local OpenClaw agent id (default: claworld)
61
- --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
62
64
  --json Print machine-readable result
63
65
  --help, -h Show this help
64
66
 
@@ -88,12 +90,13 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
88
90
  serverUrl: null,
89
91
  apiKey: null,
90
92
  accountId: 'claworld',
91
- agentId: 'claworld',
93
+ agentId: 'main',
92
94
  workspace: null,
93
95
  displayName: null,
94
96
  repoRoot: null,
95
97
  pluginInstallMode: 'npm',
96
98
  pluginInstallSource: CLAWORLD_INSTALLER_PACKAGE_NAME,
99
+ toolProfile: null,
97
100
  },
98
101
  update: {
99
102
  openclawBin: env.OPENCLAW_BIN || DEFAULT_OPENCLAW_BIN,
@@ -102,9 +105,10 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
102
105
  serverUrl: null,
103
106
  apiKey: null,
104
107
  accountId: 'claworld',
105
- agentId: 'claworld',
108
+ agentId: 'main',
106
109
  workspace: null,
107
110
  displayName: null,
111
+ toolProfile: null,
108
112
  },
109
113
  doctor: {
110
114
  openclawBin: env.OPENCLAW_BIN || DEFAULT_OPENCLAW_BIN,
@@ -112,7 +116,7 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
112
116
  stateDir: env.OPENCLAW_STATE_DIR ? expandUserPath(env.OPENCLAW_STATE_DIR, homeDir) : null,
113
117
  serverUrl: null,
114
118
  accountId: 'claworld',
115
- agentId: 'claworld',
119
+ agentId: 'main',
116
120
  workspace: null,
117
121
  },
118
122
  };
@@ -180,6 +184,11 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
180
184
  options.update.displayName = options.install.displayName;
181
185
  index += 1;
182
186
  break;
187
+ case '--tool-profile':
188
+ options.install.toolProfile = nextValue(remaining, index);
189
+ options.update.toolProfile = options.install.toolProfile;
190
+ index += 1;
191
+ break;
183
192
  case '--repo-root':
184
193
  options.install.repoRoot = path.resolve(expandUserPath(nextValue(remaining, index), homeDir));
185
194
  index += 1;
@@ -6,6 +6,7 @@ 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,
@@ -467,9 +468,12 @@ function defaultCommandRunner({
467
468
  };
468
469
  }
469
470
 
471
+ const useShell = process.platform === 'win32' && /\.(cmd|bat)$/i.test(effectiveBin);
470
472
  const result = spawnSync(effectiveBin, args, {
471
473
  cwd,
472
474
  env,
475
+ shell: useShell,
476
+ windowsHide: true,
473
477
  stdio: capture ? 'pipe' : 'inherit',
474
478
  encoding: 'utf8',
475
479
  });
@@ -615,9 +619,9 @@ export function inspectManagedClaworldInstall({
615
619
  const managedReady = Boolean(
616
620
  managedAccountPresent
617
621
  && managedRuntimeReady
618
- && managedAgentPresent
619
622
  && managedBindingPresent
620
623
  && toolsReady
624
+ && (managedOptions.manageAgentEntry !== true || managedAgentPresent)
621
625
  );
622
626
 
623
627
  let statusLabel = 'needs setup';
@@ -1146,7 +1150,7 @@ export async function verifyClaworldInstall({
1146
1150
  configPath = null,
1147
1151
  stateDir = DEFAULT_OPENCLAW_STATE_DIR,
1148
1152
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1149
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1153
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1150
1154
  commandRunner = defaultCommandRunner,
1151
1155
  cwd = process.cwd(),
1152
1156
  env = process.env,
@@ -1248,7 +1252,7 @@ async function reconcileManagedClaworldRuntime({
1248
1252
  serverUrl = null,
1249
1253
  apiKey = null,
1250
1254
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1251
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1255
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1252
1256
  workspace = null,
1253
1257
  displayName = null,
1254
1258
  toolProfile = null,
@@ -1389,7 +1393,9 @@ async function reconcileManagedClaworldRuntime({
1389
1393
  await writeConfig(configPath, transformed.config, dryRun);
1390
1394
  }
1391
1395
 
1392
- const workspaceActions = await seedManagedWorkspace(managedOptions, dryRun);
1396
+ const workspaceActions = managedOptions.manageWorkspace
1397
+ ? await seedManagedWorkspace(managedOptions, dryRun)
1398
+ : [];
1393
1399
  await validateOpenclawConfig({
1394
1400
  openclawBin,
1395
1401
  configPath,
@@ -1452,7 +1458,7 @@ export async function runClaworldInstallerInstall({
1452
1458
  serverUrl = null,
1453
1459
  apiKey = null,
1454
1460
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1455
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1461
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1456
1462
  workspace = null,
1457
1463
  displayName = null,
1458
1464
  toolProfile = null,
@@ -1552,7 +1558,7 @@ export async function runClaworldInstallerUpdate({
1552
1558
  serverUrl = null,
1553
1559
  apiKey = null,
1554
1560
  accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1555
- agentId = DEFAULT_CLAWORLD_ACCOUNT_ID,
1561
+ agentId = DEFAULT_CLAWORLD_AGENT_ID,
1556
1562
  workspace = null,
1557
1563
  displayName = null,
1558
1564
  toolProfile = null,