@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.
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/index.js +0 -50
- package/setup-entry.js +0 -6
- package/skills/claworld-a2a-channel-agent/SKILL.md +0 -218
- package/skills/claworld-help/SKILL.md +0 -304
- package/skills/claworld-join-and-chat/SKILL.md +0 -515
- package/skills/claworld-manage-worlds/SKILL.md +0 -283
- package/skills/claworld-manage-worlds/references/world-context-templates.md +0 -145
- package/src/lib/chat-request.js +0 -366
- package/src/lib/public-identity.js +0 -175
- package/src/lib/relay/agent-readable-markdown.js +0 -385
- package/src/lib/relay/kickoff-progress.js +0 -162
- package/src/lib/relay/kickoff-text.js +0 -191
- package/src/lib/relay/shared.js +0 -30
- package/src/lib/runtime-errors.js +0 -149
- package/src/openclaw/index.js +0 -51
- package/src/openclaw/plugin/account-identity.js +0 -73
- package/src/openclaw/plugin/claworld-channel-plugin.js +0 -3483
- package/src/openclaw/plugin/config-schema.js +0 -392
- package/src/openclaw/plugin/lifecycle.js +0 -114
- package/src/openclaw/plugin/managed-config.js +0 -1054
- package/src/openclaw/plugin/onboarding.js +0 -312
- package/src/openclaw/plugin/register-tooling.js +0 -728
- package/src/openclaw/plugin/register.js +0 -1609
- package/src/openclaw/plugin/relay-client-shared.js +0 -146
- package/src/openclaw/plugin/relay-client.js +0 -1469
- package/src/openclaw/plugin/runtime-backup.js +0 -105
- package/src/openclaw/plugin/runtime.js +0 -12
- package/src/openclaw/plugin-version.js +0 -67
- package/src/openclaw/protocol/relay-event-protocol.js +0 -43
- package/src/openclaw/runtime/backend-error-context.js +0 -91
- package/src/openclaw/runtime/canonical-result-builder.js +0 -126
- package/src/openclaw/runtime/demo-session-bootstrap.js +0 -32
- package/src/openclaw/runtime/feedback-helper.js +0 -145
- package/src/openclaw/runtime/inbound-session-router.js +0 -44
- package/src/openclaw/runtime/outbound-session-bridge.js +0 -29
- package/src/openclaw/runtime/product-shell-helper.js +0 -931
- package/src/openclaw/runtime/runtime-path.js +0 -19
- package/src/openclaw/runtime/system-message-orchestrator.js +0 -1
- package/src/openclaw/runtime/tool-contracts.js +0 -939
- package/src/openclaw/runtime/tool-inventory.js +0 -83
- package/src/openclaw/runtime/world-membership-helper.js +0 -320
- package/src/openclaw/runtime/world-moderation-helper.js +0 -508
- package/src/product-shell/contracts/chat-request-approval-policy.js +0 -93
- package/src/product-shell/contracts/world-orchestration.js +0 -734
- 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
|
-
}
|