@xfxstudio/claworld 2026.4.14-testing.1 → 2026.4.16-testing.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/openclaw.plugin.json +1 -1
  2. package/package.json +1 -1
  3. package/index.js +0 -50
  4. package/setup-entry.js +0 -6
  5. package/skills/claworld-a2a-channel-agent/SKILL.md +0 -218
  6. package/skills/claworld-help/SKILL.md +0 -304
  7. package/skills/claworld-join-and-chat/SKILL.md +0 -515
  8. package/skills/claworld-manage-worlds/SKILL.md +0 -283
  9. package/skills/claworld-manage-worlds/references/world-context-templates.md +0 -145
  10. package/src/lib/chat-request.js +0 -366
  11. package/src/lib/public-identity.js +0 -175
  12. package/src/lib/relay/agent-readable-markdown.js +0 -385
  13. package/src/lib/relay/kickoff-progress.js +0 -162
  14. package/src/lib/relay/kickoff-text.js +0 -191
  15. package/src/lib/relay/shared.js +0 -30
  16. package/src/lib/runtime-errors.js +0 -149
  17. package/src/openclaw/index.js +0 -51
  18. package/src/openclaw/plugin/account-identity.js +0 -73
  19. package/src/openclaw/plugin/claworld-channel-plugin.js +0 -3483
  20. package/src/openclaw/plugin/config-schema.js +0 -392
  21. package/src/openclaw/plugin/lifecycle.js +0 -114
  22. package/src/openclaw/plugin/managed-config.js +0 -1054
  23. package/src/openclaw/plugin/onboarding.js +0 -312
  24. package/src/openclaw/plugin/register-tooling.js +0 -728
  25. package/src/openclaw/plugin/register.js +0 -1609
  26. package/src/openclaw/plugin/relay-client-shared.js +0 -146
  27. package/src/openclaw/plugin/relay-client.js +0 -1469
  28. package/src/openclaw/plugin/runtime-backup.js +0 -105
  29. package/src/openclaw/plugin/runtime.js +0 -12
  30. package/src/openclaw/plugin-version.js +0 -67
  31. package/src/openclaw/protocol/relay-event-protocol.js +0 -43
  32. package/src/openclaw/runtime/backend-error-context.js +0 -91
  33. package/src/openclaw/runtime/canonical-result-builder.js +0 -126
  34. package/src/openclaw/runtime/demo-session-bootstrap.js +0 -32
  35. package/src/openclaw/runtime/feedback-helper.js +0 -145
  36. package/src/openclaw/runtime/inbound-session-router.js +0 -44
  37. package/src/openclaw/runtime/outbound-session-bridge.js +0 -29
  38. package/src/openclaw/runtime/product-shell-helper.js +0 -931
  39. package/src/openclaw/runtime/runtime-path.js +0 -19
  40. package/src/openclaw/runtime/system-message-orchestrator.js +0 -1
  41. package/src/openclaw/runtime/tool-contracts.js +0 -939
  42. package/src/openclaw/runtime/tool-inventory.js +0 -83
  43. package/src/openclaw/runtime/world-membership-helper.js +0 -320
  44. package/src/openclaw/runtime/world-moderation-helper.js +0 -508
  45. package/src/product-shell/contracts/chat-request-approval-policy.js +0 -93
  46. package/src/product-shell/contracts/world-orchestration.js +0 -734
  47. package/src/product-shell/orchestration/world-conversation-text.js +0 -229
@@ -1,1054 +0,0 @@
1
- import os from 'os';
2
- import path from 'path';
3
- import {
4
- CLAWORLD_MINIMAL_OPENCLAW_TOOL_NAMES,
5
- CLAWORLD_PUBLIC_TOOL_NAMES,
6
- CLAWORLD_READ_ONLY_OPENCLAW_TOOL_NAMES,
7
- CLAWORLD_TOOL_PROFILES,
8
- } from '../runtime/tool-inventory.js';
9
-
10
- export const DEFAULT_CLAWORLD_SERVER_URL = 'https://claworld.love';
11
- export const DEFAULT_CLAWORLD_API_KEY = 'local-test';
12
- export const DEFAULT_CLAWORLD_AGENT_ID = 'main';
13
- export const DEFAULT_CLAWORLD_ACCOUNT_ID = 'claworld';
14
- export const DEFAULT_CLAWORLD_TOOL_PROFILE = 'default';
15
- export const DEFAULT_CLAWORLD_DM_SCOPE = 'per-channel-peer';
16
- export const DEFAULT_CLAWORLD_SESSION_RESET_MODE = 'idle';
17
- export const DEFAULT_CLAWORLD_SESSION_RESET_IDLE_MINUTES = 43200;
18
- export const DEFAULT_CLAWORLD_SESSION_TARGET = 'mainagent';
19
- export const DEFAULT_CLAWORLD_FALLBACK_TARGET = 'mainagent';
20
- export const CLAWORLD_PLUGIN_TOOL_ALLOW_ENTRY = 'claworld';
21
- export const MIN_MANAGED_SESSION_VISIBILITY = 'agent';
22
- export const REQUIRED_SANDBOX_SESSION_TOOLS_VISIBILITY = 'all';
23
- export const CLAWORLD_INSTALLER_STATE_ROOT_KEY = 'claworldInstaller';
24
- export const CLAWORLD_MANAGED_RUNTIME_BACKUP_VERSION = 1;
25
-
26
- export const TOOL_PROFILES = CLAWORLD_TOOL_PROFILES;
27
-
28
- export function normalizeText(value, fallback = null) {
29
- if (value == null) return fallback;
30
- const normalized = String(value).trim();
31
- return normalized || fallback;
32
- }
33
-
34
- export function titleCase(value) {
35
- const normalized = normalizeText(value, '') || '';
36
- if (!normalized) return 'Claworld';
37
- return normalized
38
- .split(/[^A-Za-z0-9]+/)
39
- .filter(Boolean)
40
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
41
- .join(' ');
42
- }
43
-
44
- export function ensureObject(value) {
45
- if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
46
- return value;
47
- }
48
-
49
- function buildDefaultClaworldSessionResetOverride() {
50
- return {
51
- mode: DEFAULT_CLAWORLD_SESSION_RESET_MODE,
52
- idleMinutes: DEFAULT_CLAWORLD_SESSION_RESET_IDLE_MINUTES,
53
- };
54
- }
55
-
56
- function normalizeRegistrationDisplayName(value, fallback = null) {
57
- const normalized = normalizeText(value, fallback);
58
- return normalized || fallback;
59
- }
60
-
61
- export function expandUserPath(input, homeDir = os.homedir()) {
62
- const normalized = normalizeText(input, null);
63
- if (!normalized) return normalized;
64
- if (normalized === '~') return homeDir;
65
- if (normalized.startsWith('~/')) return path.join(homeDir, normalized.slice(2));
66
- return normalized;
67
- }
68
-
69
- function asStringArray(value) {
70
- if (value == null) return [];
71
- if (Array.isArray(value)) {
72
- return value
73
- .map((item) => normalizeText(item, null))
74
- .filter(Boolean);
75
- }
76
- const normalized = normalizeText(value, null);
77
- return normalized ? [normalized] : [];
78
- }
79
-
80
- function uniqueStrings(values = []) {
81
- const seen = new Set();
82
- const result = [];
83
- for (const value of values) {
84
- const normalized = normalizeText(value, null);
85
- if (!normalized || seen.has(normalized)) continue;
86
- seen.add(normalized);
87
- result.push(normalized);
88
- }
89
- return result;
90
- }
91
-
92
- function mergeManagedPluginToolExposure(existingTools = {}) {
93
- const tools = ensureObject(existingTools);
94
- const allow = asStringArray(tools.allow);
95
- const alsoAllow = asStringArray(tools.alsoAllow);
96
-
97
- if (allow.length > 0) {
98
- return {
99
- ...tools,
100
- allow: uniqueStrings([...allow, CLAWORLD_PLUGIN_TOOL_ALLOW_ENTRY]),
101
- };
102
- }
103
-
104
- return {
105
- ...tools,
106
- alsoAllow: uniqueStrings([...alsoAllow, CLAWORLD_PLUGIN_TOOL_ALLOW_ENTRY]),
107
- };
108
- }
109
-
110
- function findAgentIndex(agentList = [], agentId) {
111
- return agentList.findIndex((item) => ensureObject(item).id === agentId);
112
- }
113
-
114
- function findAgentEntry(config = {}, agentId) {
115
- const list = Array.isArray(config?.agents?.list) ? config.agents.list : [];
116
- return list
117
- .map((item) => ensureObject(item))
118
- .find((item) => item.id === agentId) || null;
119
- }
120
-
121
- function findManagedAccountEntry(config = {}, accountId) {
122
- const claworldRoot = ensureObject(config?.channels?.claworld);
123
- const accounts = ensureObject(claworldRoot.accounts);
124
- if (accounts[accountId]) return ensureObject(accounts[accountId]);
125
- if (normalizeText(claworldRoot.accountId, null) === accountId) return claworldRoot;
126
- return {};
127
- }
128
-
129
- function ensureMutableInstallerStateRoot(installerState = {}) {
130
- installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY] = ensureObject(installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY]);
131
- const rootState = ensureObject(installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY]);
132
- rootState.managedRuntime = ensureObject(rootState.managedRuntime);
133
- rootState.managedRuntime.accounts = ensureObject(rootState.managedRuntime.accounts);
134
- installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY] = rootState;
135
- return rootState.managedRuntime.accounts;
136
- }
137
-
138
- function trimInstallerStateRoot(installerState = {}) {
139
- const rootState = ensureObject(installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY]);
140
- const managedRuntime = ensureObject(rootState.managedRuntime);
141
- const accounts = ensureObject(managedRuntime.accounts);
142
- if (Object.keys(accounts).length === 0) {
143
- delete managedRuntime.accounts;
144
- } else {
145
- managedRuntime.accounts = accounts;
146
- }
147
- if (Object.keys(managedRuntime).length === 0) {
148
- delete rootState.managedRuntime;
149
- } else {
150
- rootState.managedRuntime = managedRuntime;
151
- }
152
- if (Object.keys(rootState).length === 0) {
153
- delete installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY];
154
- } else {
155
- installerState[CLAWORLD_INSTALLER_STATE_ROOT_KEY] = rootState;
156
- }
157
- }
158
-
159
- export function findClaworldManagedRuntimeBackup(installerState = {}, accountId = DEFAULT_CLAWORLD_ACCOUNT_ID) {
160
- const normalizedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
161
- const rootState = ensureObject(installerState?.[CLAWORLD_INSTALLER_STATE_ROOT_KEY]);
162
- const managedRuntime = ensureObject(rootState.managedRuntime);
163
- const accounts = ensureObject(managedRuntime.accounts);
164
- return ensureObject(accounts[normalizedAccountId]);
165
- }
166
-
167
- export function setClaworldManagedRuntimeBackupState(
168
- installerState = {},
169
- accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
170
- value = null,
171
- ) {
172
- const normalizedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
173
- const accounts = ensureMutableInstallerStateRoot(installerState);
174
- if (value && typeof value === 'object' && !Array.isArray(value)) {
175
- accounts[normalizedAccountId] = JSON.parse(JSON.stringify(value));
176
- } else {
177
- delete accounts[normalizedAccountId];
178
- }
179
- trimInstallerStateRoot(installerState);
180
- return installerState;
181
- }
182
-
183
- function removeManagedPluginToolExposure(existingTools = {}) {
184
- const tools = ensureObject(existingTools);
185
- const allow = asStringArray(tools.allow).filter((toolName) => toolName !== CLAWORLD_PLUGIN_TOOL_ALLOW_ENTRY);
186
- const alsoAllow = asStringArray(tools.alsoAllow).filter((toolName) => toolName !== CLAWORLD_PLUGIN_TOOL_ALLOW_ENTRY);
187
- const nextTools = { ...tools };
188
- if (allow.length > 0) nextTools.allow = uniqueStrings(allow);
189
- else delete nextTools.allow;
190
- if (alsoAllow.length > 0) nextTools.alsoAllow = uniqueStrings(alsoAllow);
191
- else delete nextTools.alsoAllow;
192
- return Object.keys(nextTools).length > 0 ? nextTools : null;
193
- }
194
-
195
- const SESSION_VISIBILITY_RANK = Object.freeze({
196
- self: 0,
197
- tree: 1,
198
- agent: 2,
199
- all: 3,
200
- });
201
-
202
- const SANDBOX_SESSION_TOOLS_VISIBILITY_RANK = Object.freeze({
203
- spawned: 0,
204
- all: 1,
205
- });
206
-
207
- function normalizeSessionVisibility(value, fallback = null) {
208
- const normalized = normalizeText(value, fallback);
209
- return Object.prototype.hasOwnProperty.call(SESSION_VISIBILITY_RANK, normalized)
210
- ? normalized
211
- : fallback;
212
- }
213
-
214
- function normalizeSandboxSessionToolsVisibility(value, fallback = null) {
215
- const normalized = normalizeText(value, fallback);
216
- return Object.prototype.hasOwnProperty.call(SANDBOX_SESSION_TOOLS_VISIBILITY_RANK, normalized)
217
- ? normalized
218
- : fallback;
219
- }
220
-
221
- function compareRankedSetting(value, target, rankMap) {
222
- const nextValue = normalizeText(value, null);
223
- const nextTarget = normalizeText(target, null);
224
- const valueRank = Object.prototype.hasOwnProperty.call(rankMap, nextValue) ? rankMap[nextValue] : null;
225
- const targetRank = Object.prototype.hasOwnProperty.call(rankMap, nextTarget) ? rankMap[nextTarget] : null;
226
- if (valueRank == null && targetRank == null) return 0;
227
- if (valueRank == null) return -1;
228
- if (targetRank == null) return 1;
229
- return valueRank - targetRank;
230
- }
231
-
232
- export function getEffectiveAgentSandboxMode(config = {}, agentId = DEFAULT_CLAWORLD_AGENT_ID) {
233
- const normalizedAgentId = normalizeText(agentId, DEFAULT_CLAWORLD_AGENT_ID);
234
- const agentEntry = findAgentEntry(config, normalizedAgentId);
235
- const agentSandboxMode = normalizeText(agentEntry?.sandbox?.mode, null);
236
- if (agentSandboxMode) return agentSandboxMode;
237
- return normalizeText(config?.agents?.defaults?.sandbox?.mode, 'off');
238
- }
239
-
240
- export function sandboxModeNeedsSessionToolsVisibility(mode) {
241
- return mode === 'all' || mode === 'non-main';
242
- }
243
-
244
- function ensureManagedSessionRoutingVisibility(config = {}, {
245
- agentId = DEFAULT_CLAWORLD_AGENT_ID,
246
- summary = [],
247
- } = {}) {
248
- config.tools = ensureObject(config.tools);
249
- const existingSessionTools = ensureObject(config.tools.sessions);
250
- const existingVisibility = normalizeSessionVisibility(existingSessionTools.visibility, null);
251
- if (compareRankedSetting(existingVisibility, MIN_MANAGED_SESSION_VISIBILITY, SESSION_VISIBILITY_RANK) < 0) {
252
- config.tools.sessions = {
253
- ...existingSessionTools,
254
- visibility: MIN_MANAGED_SESSION_VISIBILITY,
255
- };
256
- summary.push(
257
- existingVisibility
258
- ? `tools.sessions.visibility raised from ${existingVisibility} to ${MIN_MANAGED_SESSION_VISIBILITY}`
259
- : `tools.sessions.visibility set to ${MIN_MANAGED_SESSION_VISIBILITY}`,
260
- );
261
- } else if (Object.keys(existingSessionTools).length > 0) {
262
- config.tools.sessions = existingSessionTools;
263
- }
264
-
265
- const effectiveSandboxMode = getEffectiveAgentSandboxMode(config, agentId);
266
- if (!sandboxModeNeedsSessionToolsVisibility(effectiveSandboxMode)) {
267
- return;
268
- }
269
-
270
- config.agents = ensureObject(config.agents);
271
- config.agents.defaults = ensureObject(config.agents.defaults);
272
- const existingSandbox = ensureObject(config.agents.defaults.sandbox);
273
- const existingSessionToolsVisibility = normalizeSandboxSessionToolsVisibility(
274
- existingSandbox.sessionToolsVisibility,
275
- null,
276
- );
277
- if (
278
- compareRankedSetting(
279
- existingSessionToolsVisibility,
280
- REQUIRED_SANDBOX_SESSION_TOOLS_VISIBILITY,
281
- SANDBOX_SESSION_TOOLS_VISIBILITY_RANK,
282
- ) < 0
283
- ) {
284
- config.agents.defaults.sandbox = {
285
- ...existingSandbox,
286
- sessionToolsVisibility: REQUIRED_SANDBOX_SESSION_TOOLS_VISIBILITY,
287
- };
288
- summary.push(
289
- existingSessionToolsVisibility
290
- ? `agents.defaults.sandbox.sessionToolsVisibility raised from ${existingSessionToolsVisibility} to ${REQUIRED_SANDBOX_SESSION_TOOLS_VISIBILITY}`
291
- : `agents.defaults.sandbox.sessionToolsVisibility set to ${REQUIRED_SANDBOX_SESSION_TOOLS_VISIBILITY}`,
292
- );
293
- } else if (Object.keys(existingSandbox).length > 0) {
294
- config.agents.defaults.sandbox = existingSandbox;
295
- }
296
- }
297
-
298
- function inferExistingAgentId(config = {}, accountId = DEFAULT_CLAWORLD_ACCOUNT_ID) {
299
- const bindings = Array.isArray(config?.bindings) ? config.bindings : [];
300
- const bindingMatch = bindings
301
- .map((item) => ensureObject(item))
302
- .find((item) => ensureObject(item.match).channel === 'claworld'
303
- && normalizeText(ensureObject(item.match).accountId, null) === accountId
304
- && normalizeText(item.agentId, null));
305
- if (bindingMatch?.agentId) return normalizeText(bindingMatch.agentId, null);
306
-
307
- const agents = Array.isArray(config?.agents?.list) ? config.agents.list : [];
308
- if (agents.some((item) => ensureObject(item).id === DEFAULT_CLAWORLD_AGENT_ID)) {
309
- return DEFAULT_CLAWORLD_AGENT_ID;
310
- }
311
- if (agents.length === 1) {
312
- return normalizeText(ensureObject(agents[0]).id, DEFAULT_CLAWORLD_AGENT_ID);
313
- }
314
- return DEFAULT_CLAWORLD_AGENT_ID;
315
- }
316
-
317
- const MANAGED_LEGACY_BUNDLED_SKILL_NAMES = Object.freeze([
318
- 'claworld-join-and-chat',
319
- 'claworld-manage-worlds',
320
- 'claworld-help',
321
- ]);
322
-
323
- function hasOnlyManagedBundledSkills(value) {
324
- if (!Array.isArray(value) || value.length === 0) return false;
325
- return value.every((skillName) => MANAGED_LEGACY_BUNDLED_SKILL_NAMES.includes(skillName));
326
- }
327
-
328
- function buildManagedAgentEntry(options = {}) {
329
- return {
330
- id: options.agentId,
331
- workspace: options.workspace,
332
- ...(options.agentDirExplicit && options.agentDir ? { agentDir: options.agentDir } : {}),
333
- };
334
- }
335
-
336
- function buildManagedRoutingEntry(options = {}, existingRouting = {}) {
337
- return {
338
- ...ensureObject(existingRouting),
339
- sessionTarget: normalizeText(options.sessionTarget, DEFAULT_CLAWORLD_SESSION_TARGET),
340
- fallbackTarget: normalizeText(options.fallbackTarget, DEFAULT_CLAWORLD_FALLBACK_TARGET),
341
- allowHumanInterrupt: existingRouting?.allowHumanInterrupt !== false,
342
- };
343
- }
344
-
345
- function buildManagedAccountEntry(options = {}) {
346
- const base = {
347
- enabled: true,
348
- serverUrl: options.serverUrl,
349
- apiKey: options.apiKey,
350
- accountId: options.accountId,
351
- name: normalizeText(options.name, normalizeText(options.displayName, null)),
352
- routing: buildManagedRoutingEntry(options),
353
- };
354
-
355
- if (options.appToken) {
356
- base.appToken = options.appToken;
357
- } else if (normalizeText(options.registrationDisplayName, null)) {
358
- base.registration = {
359
- enabled: true,
360
- displayName: normalizeText(options.registrationDisplayName, options.displayName),
361
- };
362
- }
363
-
364
- if (!options.defaultTargetAgentId) {
365
- return base;
366
- }
367
-
368
- return {
369
- ...base,
370
- relay: {
371
- defaultTargetAgentId: options.defaultTargetAgentId,
372
- },
373
- };
374
- }
375
-
376
- function buildMergedAccountEntry(existingAccount = {}, options = {}) {
377
- const existingRelay = ensureObject(existingAccount.relay);
378
- const existingRegistration = ensureObject(existingAccount.registration);
379
- const merged = {
380
- ...existingAccount,
381
- enabled: true,
382
- serverUrl: options.serverUrl,
383
- apiKey: options.apiKey,
384
- accountId: options.accountId,
385
- name: normalizeText(options.name, normalizeText(existingAccount.name, normalizeText(options.displayName, null))),
386
- routing: buildManagedRoutingEntry(options, existingAccount.routing),
387
- ...(options.defaultTargetAgentId
388
- ? {
389
- relay: {
390
- ...existingRelay,
391
- defaultTargetAgentId: options.defaultTargetAgentId,
392
- },
393
- }
394
- : existingAccount.relay
395
- ? { relay: existingRelay }
396
- : {}),
397
- };
398
- delete merged.toolProfile;
399
-
400
- if (options.appToken) {
401
- const withToken = {
402
- ...merged,
403
- appToken: options.appToken,
404
- };
405
- delete withToken.registration;
406
- return withToken;
407
- }
408
-
409
- if (!normalizeText(options.registrationDisplayName, null)) {
410
- const withoutRegistration = { ...merged };
411
- delete withoutRegistration.registration;
412
- return withoutRegistration;
413
- }
414
-
415
- return {
416
- ...merged,
417
- registration: {
418
- ...existingRegistration,
419
- enabled: true,
420
- displayName: normalizeText(options.registrationDisplayName, options.displayName),
421
- },
422
- };
423
- }
424
-
425
- export function normalizeClaworldToolProfile(toolProfile = DEFAULT_CLAWORLD_TOOL_PROFILE) {
426
- const normalized = normalizeText(toolProfile, DEFAULT_CLAWORLD_TOOL_PROFILE);
427
- if (normalized === 'world') return 'default';
428
- return normalized;
429
- }
430
-
431
- export function inferClaworldToolProfile(config = {}) {
432
- const allow = new Set(asStringArray(config?.tools?.allow));
433
- if (allow.has('*')) return 'full';
434
- if (CLAWORLD_READ_ONLY_OPENCLAW_TOOL_NAMES.some((toolName) => allow.has(toolName))) {
435
- return 'default';
436
- }
437
- if (CLAWORLD_PUBLIC_TOOL_NAMES.some((toolName) => allow.has(toolName))) {
438
- return 'minimal';
439
- }
440
- return DEFAULT_CLAWORLD_TOOL_PROFILE;
441
- }
442
-
443
- function resolveStoredClaworldToolProfile(account = {}) {
444
- const persistedToolProfile = normalizeText(account?.toolProfile, null);
445
- return persistedToolProfile
446
- ? normalizeClaworldToolProfile(persistedToolProfile)
447
- : null;
448
- }
449
-
450
- function resolveManagedToolProfile({
451
- cfg = {},
452
- existingAccount = {},
453
- explicitToolProfile = null,
454
- } = {}) {
455
- const normalizedExplicitToolProfile = normalizeText(explicitToolProfile, null);
456
- if (normalizedExplicitToolProfile) {
457
- return normalizeClaworldToolProfile(normalizedExplicitToolProfile);
458
- }
459
-
460
- const persistedToolProfile = resolveStoredClaworldToolProfile(existingAccount);
461
- if (persistedToolProfile) {
462
- return persistedToolProfile;
463
- }
464
-
465
- const inferredToolProfile = inferClaworldToolProfile(cfg);
466
- if (inferredToolProfile === 'minimal') {
467
- const allow = new Set(asStringArray(cfg?.tools?.allow));
468
- const hasMinimalCoreAnchor = CLAWORLD_MINIMAL_OPENCLAW_TOOL_NAMES
469
- .some((toolName) => allow.has(toolName));
470
- if (!hasMinimalCoreAnchor) {
471
- // Legacy managed installs stored only the old public claworld allowlist.
472
- // Treat that shape as the historical default/world profile during refresh.
473
- return DEFAULT_CLAWORLD_TOOL_PROFILE;
474
- }
475
- }
476
- return normalizeClaworldToolProfile(inferredToolProfile);
477
- }
478
-
479
- export function resolveToolNames({ toolProfile = DEFAULT_CLAWORLD_TOOL_PROFILE } = {}) {
480
- const normalizedProfile = normalizeClaworldToolProfile(toolProfile);
481
- const baseProfile = TOOL_PROFILES[normalizedProfile];
482
- if (!baseProfile) {
483
- throw new Error(`Unsupported tool profile: ${toolProfile}`);
484
- }
485
- return [...baseProfile];
486
- }
487
-
488
- const MANAGED_BUNDLED_SKILL_NAMES = Object.freeze([
489
- 'claworld-join-and-chat',
490
- 'claworld-manage-worlds',
491
- 'claworld-help',
492
- ]);
493
-
494
- export function resolveManagedAgentSkills({ toolProfile = DEFAULT_CLAWORLD_TOOL_PROFILE } = {}) {
495
- const normalizedProfile = normalizeClaworldToolProfile(toolProfile);
496
- return normalizedProfile === 'full' ? undefined : [...MANAGED_BUNDLED_SKILL_NAMES];
497
- }
498
-
499
- function describeToolAllowEntries(toolNames = []) {
500
- if (toolNames.length === 1) {
501
- return toolNames[0] === '*' ? '1 entry (includes *)' : '1 entry';
502
- }
503
- return toolNames.includes('*')
504
- ? `${toolNames.length} entries (includes *)`
505
- : `${toolNames.length} entries`;
506
- }
507
-
508
- export function buildWorkspaceAgentsContent({
509
- agentId,
510
- accountId,
511
- registrationDisplayName,
512
- appToken = null,
513
- defaultTargetAgentId = null,
514
- } = {}) {
515
- const identityLine = appToken
516
- ? '- relay binding is resolved from the configured appToken at runtime'
517
- : registrationDisplayName
518
- ? '- relay binding is created during runtime bootstrap and persists as backend-issued credentials'
519
- : '- activation is pending until the user completes Claworld public identity setup';
520
-
521
- return `# Claworld Channel Agent
522
-
523
- This workspace is dedicated to the OpenClaw \`claworld\` channel.
524
-
525
- Routing contract:
526
-
527
- - local OpenClaw agent id: \`${agentId}\`
528
- - claworld account id: \`${accountId}\`
529
- ${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : (appToken ? '- credential mode: appToken/manual binding' : '- credential mode: activation pending')}
530
- ${identityLine}
531
- ${defaultTargetAgentId ? `- default outbound target agentId: \`${defaultTargetAgentId}\`` : '- outbound sends require explicit target agentId inputs'}
532
-
533
- Operating rules:
534
-
535
- - keep this workspace focused on Claworld relay and world interactions
536
- - use explicit \`claworld_*\` tools when they are available
537
- - do not treat this workspace as the user's general-purpose main agent
538
- - do not treat this as a separately bootstrapped OpenClaw persona
539
- `;
540
- }
541
-
542
- function buildBoundAgentEntry(existingAgent = {}, agentId) {
543
- const nextAgent = {
544
- ...ensureObject(existingAgent),
545
- id: agentId,
546
- };
547
- nextAgent.tools = mergeManagedPluginToolExposure(existingAgent.tools);
548
- return nextAgent;
549
- }
550
-
551
- export function buildWorkspaceMemoryContent({
552
- agentId,
553
- accountId,
554
- registrationDisplayName,
555
- appToken = null,
556
- defaultTargetAgentId = null,
557
- } = {}) {
558
- const identityLine = appToken
559
- ? '- relay binding: resolved from appToken at runtime'
560
- : registrationDisplayName
561
- ? '- relay binding: assigned during runtime bootstrap'
562
- : '- relay binding: pending until public identity setup completes';
563
-
564
- return `# Claworld Memory
565
-
566
- - workspace owner: \`${agentId}\`
567
- - claworld account: \`${accountId}\`
568
- ${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : ''}
569
- ${identityLine}
570
- ${defaultTargetAgentId ? `- default outbound target agentId: \`${defaultTargetAgentId}\`` : ''}
571
-
572
- Use this file for durable Claworld-specific notes only.
573
-
574
- - keep world rules, pairing context, and recurring counterpart preferences here when they help future Claworld conversations
575
- - do not duplicate a full standalone OpenClaw bootstrap/persona here
576
- - prefer channel/world-specific memory over general-purpose assistant memory
577
- `;
578
- }
579
-
580
- export function resolveDefaultManagedWorkspace(agentId = DEFAULT_CLAWORLD_AGENT_ID) {
581
- return `~/.openclaw/workspace-${agentId}`;
582
- }
583
-
584
- export function resolveDefaultManagedDisplayName(accountId = DEFAULT_CLAWORLD_ACCOUNT_ID) {
585
- return `${titleCase(accountId)} Channel Agent`;
586
- }
587
-
588
- export function resolveClaworldManagedRuntimeOptions({
589
- cfg = {},
590
- accountId = null,
591
- input = {},
592
- overrides = {},
593
- installerState = null,
594
- } = {}) {
595
- const resolvedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
596
- const attachToExistingAgent = overrides.attachToExistingAgent !== false;
597
- const existingBackup = findClaworldManagedRuntimeBackup(installerState, resolvedAccountId);
598
- const inferredAgentId = inferExistingAgentId(cfg, resolvedAccountId)
599
- || normalizeText(existingBackup.agentId, null);
600
- const agentId = normalizeText(overrides.agentId, inferredAgentId);
601
- const existingAgent = findAgentEntry(cfg, agentId);
602
- const existingAccount = findManagedAccountEntry(cfg, resolvedAccountId);
603
- const replaceManagedRuntime = overrides.replaceManagedRuntime !== false;
604
- const explicitWorkspace = normalizeText(overrides.workspace, null);
605
- const manageAgentEntry = overrides.manageAgentEntry === true
606
- || overrides.agentDirExplicit === true
607
- || attachToExistingAgent !== true;
608
- const manageWorkspace = overrides.manageWorkspace === true
609
- || Boolean(explicitWorkspace)
610
- || attachToExistingAgent !== true;
611
- const defaultWorkspace = manageWorkspace ? resolveDefaultManagedWorkspace(agentId) : null;
612
- const workspace = normalizeText(
613
- explicitWorkspace,
614
- replaceManagedRuntime
615
- ? normalizeText(existingAgent?.workspace, normalizeText(existingBackup.workspace, defaultWorkspace))
616
- : normalizeText(existingAgent?.workspace, normalizeText(existingBackup.workspace, defaultWorkspace)),
617
- );
618
- const serverUrl = normalizeText(
619
- overrides.serverUrl,
620
- normalizeText(input.httpUrl, normalizeText(input.url, normalizeText(existingBackup.serverUrl, DEFAULT_CLAWORLD_SERVER_URL))),
621
- );
622
- const apiKey = normalizeText(overrides.apiKey, normalizeText(existingBackup.apiKey, DEFAULT_CLAWORLD_API_KEY));
623
- const explicitAppToken = normalizeText(
624
- overrides.appToken,
625
- normalizeText(input.appToken, null),
626
- );
627
- const explicitRegistrationDisplayName = normalizeRegistrationDisplayName(
628
- overrides.registrationDisplayName,
629
- normalizeRegistrationDisplayName(input.name, null),
630
- );
631
- const appToken = explicitRegistrationDisplayName && !explicitAppToken
632
- ? null
633
- : normalizeText(
634
- explicitAppToken,
635
- normalizeText(
636
- existingAccount.appToken,
637
- normalizeText(
638
- existingAccount?.relay?.appToken,
639
- normalizeText(existingAccount?.relay?.credentialToken, normalizeText(existingBackup.appToken, null)),
640
- ),
641
- ),
642
- );
643
- const displayName = normalizeText(
644
- overrides.displayName,
645
- normalizeText(input.name, normalizeText(existingBackup.displayName, resolveDefaultManagedDisplayName(resolvedAccountId))),
646
- );
647
- const name = normalizeText(overrides.name, normalizeText(existingBackup.name, displayName));
648
- const existingRegistrationDisplayName = normalizeRegistrationDisplayName(
649
- existingAccount?.registration?.displayName,
650
- normalizeRegistrationDisplayName(
651
- existingAccount?.localAgent?.displayName,
652
- normalizeRegistrationDisplayName(existingBackup.registrationDisplayName, null),
653
- ),
654
- );
655
- const registrationDisplayName = appToken && !explicitRegistrationDisplayName
656
- ? null
657
- : normalizeRegistrationDisplayName(
658
- explicitRegistrationDisplayName,
659
- existingRegistrationDisplayName,
660
- );
661
-
662
- return {
663
- repoRoot: normalizeText(overrides.repoRoot, null),
664
- attachToExistingAgent,
665
- agentId,
666
- accountId: resolvedAccountId,
667
- workspace,
668
- manageAgentEntry,
669
- manageWorkspace,
670
- agentDir: normalizeText(overrides.agentDir, null),
671
- agentDirExplicit: overrides.agentDirExplicit === true,
672
- serverUrl,
673
- apiKey,
674
- appToken,
675
- registrationDisplayName,
676
- displayName,
677
- name,
678
- defaultTargetAgentId: normalizeText(overrides.defaultTargetAgentId, null),
679
- sessionDmScope: normalizeText(
680
- overrides.sessionDmScope,
681
- normalizeText(existingBackup.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE),
682
- ),
683
- replaceManagedRuntime,
684
- preserveDefaultAccount: overrides.preserveDefaultAccount === true,
685
- forceDefaultAccount: overrides.forceDefaultAccount === true,
686
- pluginInstallMode: normalizeText(overrides.pluginInstallMode, 'skip'),
687
- installPlugin: overrides.installPlugin !== false,
688
- sessionTarget: normalizeText(overrides.sessionTarget, DEFAULT_CLAWORLD_SESSION_TARGET),
689
- fallbackTarget: normalizeText(overrides.fallbackTarget, DEFAULT_CLAWORLD_FALLBACK_TARGET),
690
- };
691
- }
692
-
693
- export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}) {
694
- const config = JSON.parse(JSON.stringify(ensureObject(inputConfig)));
695
- const summary = [];
696
- const replaceManagedRuntime = options.replaceManagedRuntime !== false;
697
- const preserveDefaultAccount = options.preserveDefaultAccount === true;
698
- const sessionDmScope = normalizeText(options.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE);
699
- const manageAgentEntry = options.manageAgentEntry === true;
700
-
701
- const removedManagedToolNames = new Set(CLAWORLD_PUBLIC_TOOL_NAMES);
702
- if (inputConfig?.tools && typeof inputConfig.tools === 'object') {
703
- config.tools = ensureObject(config.tools);
704
- const existingAllow = asStringArray(config.tools.allow);
705
- const filteredAllow = existingAllow.filter((toolName) => !removedManagedToolNames.has(toolName));
706
- const removedManagedTools = existingAllow.filter((toolName) => removedManagedToolNames.has(toolName));
707
- if (removedManagedTools.length > 0) {
708
- if (filteredAllow.length > 0) {
709
- config.tools.allow = uniqueStrings(filteredAllow);
710
- } else {
711
- delete config.tools.allow;
712
- }
713
- summary.push(`tools.allow removed managed claworld entries (${removedManagedTools.join(',')})`);
714
- }
715
- if (Object.keys(config.tools).length === 0) {
716
- delete config.tools;
717
- }
718
- }
719
-
720
- config.session = ensureObject(config.session);
721
- if (!Object.prototype.hasOwnProperty.call(config.session, 'dmScope')) {
722
- config.session.dmScope = sessionDmScope;
723
- summary.push(`session.dmScope set to ${sessionDmScope}`);
724
- }
725
- const resetByChannel = ensureObject(config.session.resetByChannel);
726
- if (!Object.prototype.hasOwnProperty.call(resetByChannel, 'claworld')) {
727
- config.session.resetByChannel = {
728
- ...resetByChannel,
729
- claworld: buildDefaultClaworldSessionResetOverride(),
730
- };
731
- summary.push(
732
- `session.resetByChannel.claworld set to ${DEFAULT_CLAWORLD_SESSION_RESET_MODE}/${DEFAULT_CLAWORLD_SESSION_RESET_IDLE_MINUTES}m`,
733
- );
734
- }
735
-
736
- config.agents = ensureObject(config.agents);
737
- const existingAgentList = Array.isArray(config.agents.list) ? [...config.agents.list] : [];
738
- if (manageAgentEntry) {
739
- const managedAgentEntry = buildManagedAgentEntry(options);
740
- if (replaceManagedRuntime) {
741
- const removedAgentEntries = existingAgentList.filter((item) => ensureObject(item).id === options.agentId).length;
742
- config.agents.list = [
743
- ...existingAgentList.filter((item) => ensureObject(item).id !== options.agentId),
744
- {
745
- ...managedAgentEntry,
746
- tools: mergeManagedPluginToolExposure(managedAgentEntry.tools),
747
- },
748
- ];
749
- summary.push(
750
- removedAgentEntries > 0
751
- ? `replaced managed agent entry ${options.agentId}`
752
- : `added workspace-scoped agent entry ${options.agentId}`,
753
- );
754
- } else {
755
- const agentIndex = findAgentIndex(existingAgentList, options.agentId);
756
- if (agentIndex >= 0) {
757
- const existingAgent = ensureObject(existingAgentList[agentIndex]);
758
- const existingAgentDir = normalizeText(existingAgent.agentDir, null);
759
- const keepExistingAgentDir = Boolean(
760
- existingAgentDir
761
- && (
762
- options.agentDirExplicit
763
- || existingAgentDir !== normalizeText(options.agentDir, null)
764
- ),
765
- );
766
- const nextAgentEntry = {
767
- ...existingAgent,
768
- id: options.agentId,
769
- workspace: normalizeText(existingAgent.workspace, options.workspace),
770
- ...(keepExistingAgentDir ? { agentDir: existingAgentDir } : {}),
771
- };
772
- if (!keepExistingAgentDir) {
773
- delete nextAgentEntry.agentDir;
774
- }
775
- if (hasOnlyManagedBundledSkills(existingAgent.skills)) {
776
- delete nextAgentEntry.skills;
777
- }
778
- nextAgentEntry.tools = mergeManagedPluginToolExposure(existingAgent.tools);
779
- existingAgentList[agentIndex] = nextAgentEntry;
780
- summary.push(`updated existing agent entry ${options.agentId}`);
781
- } else {
782
- existingAgentList.push({
783
- ...managedAgentEntry,
784
- tools: mergeManagedPluginToolExposure(managedAgentEntry.tools),
785
- });
786
- summary.push(`added workspace-scoped agent entry ${options.agentId}`);
787
- }
788
- config.agents.list = existingAgentList;
789
- }
790
- } else {
791
- const agentIndex = findAgentIndex(existingAgentList, options.agentId);
792
- if (agentIndex >= 0) {
793
- const existingAgent = ensureObject(existingAgentList[agentIndex]);
794
- existingAgentList[agentIndex] = buildBoundAgentEntry(existingAgent, options.agentId);
795
- config.agents.list = existingAgentList;
796
- summary.push(`updated bound agent tool exposure ${options.agentId}`);
797
- } else {
798
- existingAgentList.push(buildBoundAgentEntry({}, options.agentId));
799
- config.agents.list = existingAgentList;
800
- summary.push(`added bound agent entry ${options.agentId}`);
801
- }
802
- summary.push(`attached claworld account ${options.accountId} to existing local agent ${options.agentId}`);
803
- }
804
-
805
- config.channels = ensureObject(config.channels);
806
- const existingClaworldRoot = ensureObject(config.channels.claworld);
807
- const claworldRoot = replaceManagedRuntime ? {} : { ...existingClaworldRoot };
808
- const existingDefaultAccount = normalizeText(existingClaworldRoot.defaultAccount, null);
809
- const existingAccounts = ensureObject(existingClaworldRoot.accounts);
810
- const targetExistingAccount = ensureObject(existingAccounts[options.accountId]);
811
- const nextAccounts = { ...existingAccounts };
812
- nextAccounts[options.accountId] = replaceManagedRuntime
813
- ? buildManagedAccountEntry(options)
814
- : buildMergedAccountEntry(targetExistingAccount, options);
815
- claworldRoot.accounts = nextAccounts;
816
- const shouldKeepDefaultAccount = preserveDefaultAccount
817
- && existingDefaultAccount
818
- && Object.prototype.hasOwnProperty.call(nextAccounts, existingDefaultAccount);
819
- if (!shouldKeepDefaultAccount || options.forceDefaultAccount) {
820
- claworldRoot.defaultAccount = options.accountId;
821
- summary.push(`channels.claworld.defaultAccount set to ${options.accountId}`);
822
- } else {
823
- claworldRoot.defaultAccount = existingDefaultAccount;
824
- summary.push(`channels.claworld.defaultAccount preserved as ${existingDefaultAccount}`);
825
- }
826
- config.channels.claworld = claworldRoot;
827
- summary.push(
828
- replaceManagedRuntime
829
- ? `replaced managed channels.claworld.accounts.${options.accountId}`
830
- : `configured channels.claworld.accounts.${options.accountId}`,
831
- );
832
-
833
- const existingBindings = Array.isArray(config.bindings) ? [...config.bindings] : [];
834
- const remainingBindings = existingBindings.filter((binding) => {
835
- const candidate = ensureObject(binding);
836
- const match = ensureObject(candidate.match);
837
- const bindingChannel = normalizeText(match.channel, null);
838
- const bindingAccountId = normalizeText(match.accountId, null);
839
- const bindingAgentId = normalizeText(candidate.agentId, null);
840
-
841
- if (bindingChannel === 'claworld' && bindingAccountId === options.accountId) return false;
842
- if (bindingChannel === 'claworld' && bindingAgentId === options.agentId) return false;
843
- return true;
844
- });
845
- remainingBindings.push({
846
- agentId: options.agentId,
847
- match: {
848
- channel: 'claworld',
849
- accountId: options.accountId,
850
- },
851
- });
852
- config.bindings = remainingBindings;
853
- summary.push(
854
- replaceManagedRuntime
855
- ? `replaced claworld binding for ${options.accountId}`
856
- : `reconciled claworld binding for ${options.accountId}`,
857
- );
858
-
859
- ensureManagedSessionRoutingVisibility(config, {
860
- agentId: options.agentId,
861
- summary,
862
- });
863
-
864
- return {
865
- config,
866
- summary,
867
- bootstrapDisplayName: normalizeText(options.registrationDisplayName, null),
868
- };
869
- }
870
-
871
- export function stripClaworldManagedRuntimeConfig(inputConfig = {}, {
872
- accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
873
- agentId = null,
874
- preserveBackup = true,
875
- } = {}) {
876
- const config = JSON.parse(JSON.stringify(ensureObject(inputConfig)));
877
- const summary = [];
878
- const resolvedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
879
- const resolvedAgentId = normalizeText(agentId, inferExistingAgentId(config, resolvedAccountId));
880
- const existingAgent = findAgentEntry(config, resolvedAgentId);
881
- const existingAccount = findManagedAccountEntry(config, resolvedAccountId);
882
- const existingToolProfile = resolveStoredClaworldToolProfile(existingAccount) || inferClaworldToolProfile(config);
883
- const backup = preserveBackup
884
- ? {
885
- version: CLAWORLD_MANAGED_RUNTIME_BACKUP_VERSION,
886
- accountId: resolvedAccountId,
887
- agentId: resolvedAgentId,
888
- workspace: normalizeText(existingAgent?.workspace, null),
889
- serverUrl: normalizeText(existingAccount.serverUrl, null),
890
- apiKey: normalizeText(existingAccount.apiKey, null),
891
- appToken: normalizeText(
892
- existingAccount.appToken,
893
- normalizeText(existingAccount?.relay?.appToken, normalizeText(existingAccount?.relay?.credentialToken, null)),
894
- ),
895
- displayName: normalizeText(existingAccount.name, normalizeText(existingAgent?.name, null)),
896
- name: normalizeText(existingAccount.name, null),
897
- registrationDisplayName: normalizeRegistrationDisplayName(existingAccount?.registration?.displayName, null),
898
- sessionDmScope: normalizeText(config?.session?.dmScope, DEFAULT_CLAWORLD_DM_SCOPE),
899
- toolProfile: existingToolProfile,
900
- preservedAt: new Date().toISOString(),
901
- }
902
- : null;
903
- if (backup) {
904
- summary.push(`prepared managed claworld runtime backup for ${resolvedAccountId}`);
905
- }
906
-
907
- if (resolvedAgentId) {
908
- const agentList = Array.isArray(config?.agents?.list) ? [...config.agents.list] : [];
909
- const agentIndex = findAgentIndex(agentList, resolvedAgentId);
910
- if (agentIndex >= 0) {
911
- const nextAgent = { ...ensureObject(agentList[agentIndex]) };
912
- const nextTools = removeManagedPluginToolExposure(nextAgent.tools);
913
- if (nextTools) nextAgent.tools = nextTools;
914
- else delete nextAgent.tools;
915
- agentList[agentIndex] = nextAgent;
916
- config.agents = ensureObject(config.agents);
917
- config.agents.list = agentList;
918
- summary.push(`removed managed claworld tool exposure from agent ${resolvedAgentId}`);
919
- }
920
- }
921
-
922
- const claworldRoot = ensureObject(config?.channels?.claworld);
923
- const accounts = ensureObject(claworldRoot.accounts);
924
- if (Object.prototype.hasOwnProperty.call(accounts, resolvedAccountId)) {
925
- delete accounts[resolvedAccountId];
926
- summary.push(`removed channels.claworld.accounts.${resolvedAccountId}`);
927
- }
928
- const nextClaworldRoot = { ...claworldRoot };
929
- if (Object.keys(accounts).length > 0) {
930
- nextClaworldRoot.accounts = accounts;
931
- const currentDefaultAccount = normalizeText(nextClaworldRoot.defaultAccount, null);
932
- if (currentDefaultAccount === resolvedAccountId) {
933
- nextClaworldRoot.defaultAccount = Object.keys(accounts)[0];
934
- summary.push(`repointed channels.claworld.defaultAccount to ${nextClaworldRoot.defaultAccount}`);
935
- }
936
- } else {
937
- delete nextClaworldRoot.accounts;
938
- delete nextClaworldRoot.defaultAccount;
939
- }
940
- if (Object.keys(nextClaworldRoot).length > 0) {
941
- config.channels = ensureObject(config.channels);
942
- config.channels.claworld = nextClaworldRoot;
943
- } else if (config.channels && typeof config.channels === 'object' && !Array.isArray(config.channels)) {
944
- delete config.channels.claworld;
945
- if (Object.keys(config.channels).length === 0) {
946
- delete config.channels;
947
- }
948
- summary.push('removed channels.claworld root');
949
- }
950
-
951
- if (Array.isArray(config.bindings)) {
952
- const nextBindings = config.bindings.filter((binding) => {
953
- const candidate = ensureObject(binding);
954
- const match = ensureObject(candidate.match);
955
- const bindingChannel = normalizeText(match.channel, null);
956
- const bindingAccountId = normalizeText(match.accountId, null);
957
- const bindingAgentId = normalizeText(candidate.agentId, null);
958
- if (bindingChannel !== 'claworld') return true;
959
- if (bindingAccountId === resolvedAccountId) return false;
960
- if (!bindingAccountId && resolvedAgentId && bindingAgentId === resolvedAgentId) return false;
961
- return true;
962
- });
963
- if (nextBindings.length !== config.bindings.length) {
964
- config.bindings = nextBindings;
965
- summary.push(`removed claworld bindings for ${resolvedAccountId}`);
966
- }
967
- if (config.bindings.length === 0) {
968
- delete config.bindings;
969
- }
970
- }
971
-
972
- config.plugins = ensureObject(config.plugins);
973
- const nextPluginAllow = asStringArray(config.plugins.allow).filter((pluginId) => pluginId !== 'claworld');
974
- if (nextPluginAllow.length > 0) config.plugins.allow = uniqueStrings(nextPluginAllow);
975
- else delete config.plugins.allow;
976
-
977
- const nextPluginEntries = ensureObject(config.plugins.entries);
978
- if (Object.prototype.hasOwnProperty.call(nextPluginEntries, 'claworld')) {
979
- delete nextPluginEntries.claworld;
980
- summary.push('removed plugins.entries.claworld');
981
- }
982
- if (Object.keys(nextPluginEntries).length > 0) config.plugins.entries = nextPluginEntries;
983
- else delete config.plugins.entries;
984
-
985
- const nextPluginInstalls = ensureObject(config.plugins.installs);
986
- const claworldInstallRecord = ensureObject(nextPluginInstalls.claworld);
987
- if (Object.prototype.hasOwnProperty.call(nextPluginInstalls, 'claworld')) {
988
- delete nextPluginInstalls.claworld;
989
- summary.push('removed plugins.installs.claworld');
990
- }
991
- if (Object.keys(nextPluginInstalls).length > 0) config.plugins.installs = nextPluginInstalls;
992
- else delete config.plugins.installs;
993
-
994
- const nextPluginLoad = ensureObject(config.plugins.load);
995
- const sourcePath = normalizeText(claworldInstallRecord.sourcePath, null);
996
- const filteredLoadPaths = asStringArray(nextPluginLoad.paths).filter((entry) => entry !== sourcePath);
997
- if (sourcePath && filteredLoadPaths.length !== asStringArray(nextPluginLoad.paths).length) {
998
- if (filteredLoadPaths.length > 0) {
999
- nextPluginLoad.paths = uniqueStrings(filteredLoadPaths);
1000
- } else {
1001
- delete nextPluginLoad.paths;
1002
- }
1003
- summary.push('removed plugins.load.paths claworld sourcePath');
1004
- }
1005
- if (Object.keys(nextPluginLoad).length > 0) config.plugins.load = nextPluginLoad;
1006
- else delete config.plugins.load;
1007
-
1008
- const nextPluginSlots = ensureObject(config.plugins.slots);
1009
- if (normalizeText(nextPluginSlots.memory, null) === 'claworld') {
1010
- delete nextPluginSlots.memory;
1011
- summary.push('removed plugins.slots.memory claworld');
1012
- }
1013
- if (Object.keys(nextPluginSlots).length > 0) config.plugins.slots = nextPluginSlots;
1014
- else delete config.plugins.slots;
1015
-
1016
- if (Object.keys(config.plugins).length === 0) {
1017
- delete config.plugins;
1018
- }
1019
-
1020
- return {
1021
- config,
1022
- summary,
1023
- backup,
1024
- };
1025
- }
1026
-
1027
- export function applyClaworldBootstrapConfig(inputConfig = {}, options = {}) {
1028
- const config = JSON.parse(JSON.stringify(ensureObject(inputConfig)));
1029
- const summary = [];
1030
-
1031
- config.plugins = ensureObject(config.plugins);
1032
- config.plugins.allow = uniqueStrings([...asStringArray(config.plugins.allow), 'claworld']);
1033
- config.plugins.entries = ensureObject(config.plugins.entries);
1034
- config.plugins.entries.claworld = {
1035
- ...ensureObject(config.plugins.entries.claworld),
1036
- enabled: true,
1037
- };
1038
- config.plugins.load = ensureObject(config.plugins.load);
1039
- const shouldEnsureLoadPath = options.pluginInstallMode === 'link' || options.installPlugin === false;
1040
- if (shouldEnsureLoadPath) {
1041
- config.plugins.load.paths = uniqueStrings([
1042
- ...asStringArray(config.plugins.load.paths),
1043
- options.repoRoot,
1044
- ]);
1045
- summary.push(`plugins.load.paths includes ${options.repoRoot}`);
1046
- }
1047
- summary.push('plugins.allow includes claworld');
1048
-
1049
- const runtimeResult = applyClaworldManagedRuntimeConfig(config, options);
1050
- return {
1051
- ...runtimeResult,
1052
- summary: [...summary, ...runtimeResult.summary],
1053
- };
1054
- }