@xfxstudio/claworld 0.2.9 → 0.2.10-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/openclaw.plugin.json +7 -63
- package/package.json +6 -2
- package/skills/claworld-help/SKILL.md +5 -1
- package/skills/claworld-join-and-chat/SKILL.md +21 -1
- package/skills/claworld-manage-worlds/SKILL.md +81 -10
- package/src/lib/agent-profile.js +8 -3
- package/src/lib/chat-request.js +0 -1
- package/src/lib/policy.js +2 -6
- package/src/lib/public-identity.js +175 -0
- package/src/lib/relay/kickoff-text.js +1 -0
- package/src/openclaw/installer/cli.js +46 -1
- package/src/openclaw/installer/constants.js +1 -0
- package/src/openclaw/installer/core.js +234 -3
- package/src/openclaw/installer/doctor.js +2 -2
- package/src/openclaw/plugin/account-identity.js +1 -2
- package/src/openclaw/plugin/claworld-channel-plugin.js +270 -255
- package/src/openclaw/plugin/config-schema.js +9 -23
- package/src/openclaw/plugin/managed-config.js +284 -79
- package/src/openclaw/plugin/onboarding.js +22 -42
- package/src/openclaw/plugin/register.js +109 -10
- package/src/openclaw/plugin/relay-client.js +233 -17
- package/src/openclaw/runtime/backend-error-context.js +91 -0
- package/src/openclaw/runtime/feedback-helper.js +1 -2
- package/src/openclaw/runtime/product-shell-helper.js +43 -9
- package/src/openclaw/runtime/tool-contracts.js +26 -3
- package/src/openclaw/runtime/tool-inventory.js +7 -0
- package/src/openclaw/runtime/world-moderation-helper.js +3 -19
- package/src/product-shell/contracts/candidate-feed.js +7 -0
- package/src/product-shell/contracts/world-manifest.js +0 -1
- package/src/product-shell/contracts/world-orchestration.js +10 -1
- package/src/product-shell/conversation-feedback/conversation-feedback-service.js +261 -0
- package/src/product-shell/feedback/feedback-routes.js +0 -1
- package/src/product-shell/feedback/feedback-service.js +4 -9
- package/src/product-shell/index.js +40 -7
- package/src/product-shell/matching/matchmaking-service.js +22 -1
- package/src/product-shell/membership/membership-service.js +5 -1
- package/src/product-shell/onboarding/onboarding-service.js +10 -21
- package/src/product-shell/profile/public-identity-routes.js +60 -0
- package/src/product-shell/profile/public-identity-service.js +190 -0
- package/src/product-shell/search/search-service.js +9 -2
- package/src/product-shell/social/chat-request-service.js +22 -7
- package/src/product-shell/social/friend-routes.js +1 -1
- package/src/product-shell/social/friend-service.js +16 -19
- package/src/product-shell/social/social-routes.js +2 -2
- package/src/product-shell/social/social-service.js +31 -35
- package/src/product-shell/worlds/world-admin-service.js +31 -10
- package/src/product-shell/worlds/world-broadcast-service.js +2 -2
- package/src/lib/agent-address.js +0 -46
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
CLAWORLD_INSTALLER_BIN_NAME,
|
|
9
9
|
CLAWORLD_INSTALLER_COMMAND,
|
|
10
10
|
CLAWORLD_INSTALLER_PACKAGE_NAME,
|
|
11
|
+
CLAWORLD_UNINSTALL_COMMAND,
|
|
11
12
|
CLAWORLD_UPDATE_COMMAND,
|
|
12
13
|
} from './constants.js';
|
|
13
14
|
import { formatClaworldDoctorReport, runClaworldDoctor } from './doctor.js';
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
DEFAULT_OPENCLAW_BIN,
|
|
16
17
|
DEFAULT_OPENCLAW_CONFIG_PATH,
|
|
17
18
|
runClaworldInstallerInstall,
|
|
19
|
+
runClaworldInstallerUninstall,
|
|
18
20
|
runClaworldInstallerUpdate,
|
|
19
21
|
} from './core.js';
|
|
20
22
|
|
|
@@ -38,6 +40,7 @@ Commands:
|
|
|
38
40
|
install Run the installer-first Claworld setup flow
|
|
39
41
|
doctor Validate the managed Claworld install health
|
|
40
42
|
update Update the tracked Claworld plugin, refresh managed state, and run doctor
|
|
43
|
+
uninstall Safely remove the managed Claworld runtime and uninstall the plugin
|
|
41
44
|
upgrade Alias for update
|
|
42
45
|
help Show this help
|
|
43
46
|
|
|
@@ -74,6 +77,12 @@ Doctor options:
|
|
|
74
77
|
--account-id <id> Managed Claworld account id (default: claworld)
|
|
75
78
|
--agent-id <id> Local OpenClaw agent id bound to claworld (default: main)
|
|
76
79
|
--workspace <path> Optional dedicated workspace path override
|
|
80
|
+
Uninstall options:
|
|
81
|
+
--config <path> OpenClaw config path (default: ${DEFAULT_OPENCLAW_CONFIG_PATH})
|
|
82
|
+
--state-dir <path> Optional OPENCLAW_STATE_DIR for OpenClaw commands
|
|
83
|
+
--openclaw-bin <path> OpenClaw CLI binary (default: ${DEFAULT_OPENCLAW_BIN})
|
|
84
|
+
--account-id <id> Managed Claworld account id (default: claworld)
|
|
85
|
+
--agent-id <id> Local OpenClaw agent id bound to claworld (default: main)
|
|
77
86
|
--json Print machine-readable result
|
|
78
87
|
--help, -h Show this help
|
|
79
88
|
|
|
@@ -81,6 +90,7 @@ Canonical commands:
|
|
|
81
90
|
${CLAWORLD_INSTALLER_COMMAND}
|
|
82
91
|
${CLAWORLD_DOCTOR_COMMAND}
|
|
83
92
|
${CLAWORLD_UPDATE_COMMAND}
|
|
93
|
+
${CLAWORLD_UNINSTALL_COMMAND}
|
|
84
94
|
`);
|
|
85
95
|
}
|
|
86
96
|
|
|
@@ -132,6 +142,13 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
|
|
|
132
142
|
agentId: 'main',
|
|
133
143
|
workspace: null,
|
|
134
144
|
},
|
|
145
|
+
uninstall: {
|
|
146
|
+
openclawBin: env.OPENCLAW_BIN || DEFAULT_OPENCLAW_BIN,
|
|
147
|
+
configPath: expandUserPath(env.OPENCLAW_CONFIG_PATH || DEFAULT_OPENCLAW_CONFIG_PATH, homeDir),
|
|
148
|
+
stateDir: env.OPENCLAW_STATE_DIR ? expandUserPath(env.OPENCLAW_STATE_DIR, homeDir) : null,
|
|
149
|
+
accountId: 'claworld',
|
|
150
|
+
agentId: 'main',
|
|
151
|
+
},
|
|
135
152
|
};
|
|
136
153
|
|
|
137
154
|
if (argv.length === 0) {
|
|
@@ -149,18 +166,21 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
|
|
|
149
166
|
options.install.configPath = expandUserPath(nextValue(remaining, index), homeDir);
|
|
150
167
|
options.update.configPath = options.install.configPath;
|
|
151
168
|
options.doctor.configPath = options.install.configPath;
|
|
169
|
+
options.uninstall.configPath = options.install.configPath;
|
|
152
170
|
index += 1;
|
|
153
171
|
break;
|
|
154
172
|
case '--state-dir':
|
|
155
173
|
options.install.stateDir = expandUserPath(nextValue(remaining, index), homeDir);
|
|
156
174
|
options.update.stateDir = options.install.stateDir;
|
|
157
175
|
options.doctor.stateDir = options.install.stateDir;
|
|
176
|
+
options.uninstall.stateDir = options.install.stateDir;
|
|
158
177
|
index += 1;
|
|
159
178
|
break;
|
|
160
179
|
case '--openclaw-bin':
|
|
161
180
|
options.install.openclawBin = nextValue(remaining, index);
|
|
162
181
|
options.update.openclawBin = options.install.openclawBin;
|
|
163
182
|
options.doctor.openclawBin = options.install.openclawBin;
|
|
183
|
+
options.uninstall.openclawBin = options.install.openclawBin;
|
|
164
184
|
index += 1;
|
|
165
185
|
break;
|
|
166
186
|
case '--server-url':
|
|
@@ -178,12 +198,14 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
|
|
|
178
198
|
options.install.accountId = nextValue(remaining, index);
|
|
179
199
|
options.update.accountId = options.install.accountId;
|
|
180
200
|
options.doctor.accountId = options.install.accountId;
|
|
201
|
+
options.uninstall.accountId = options.install.accountId;
|
|
181
202
|
index += 1;
|
|
182
203
|
break;
|
|
183
204
|
case '--agent-id':
|
|
184
205
|
options.install.agentId = nextValue(remaining, index);
|
|
185
206
|
options.update.agentId = options.install.agentId;
|
|
186
207
|
options.doctor.agentId = options.install.agentId;
|
|
208
|
+
options.uninstall.agentId = options.install.agentId;
|
|
187
209
|
index += 1;
|
|
188
210
|
break;
|
|
189
211
|
case '--workspace':
|
|
@@ -226,7 +248,7 @@ export function parseInstallerCliArgs(argv = process.argv.slice(2), env = proces
|
|
|
226
248
|
}
|
|
227
249
|
}
|
|
228
250
|
|
|
229
|
-
if (!['install', 'update', 'doctor', 'help'].includes(options.command)) {
|
|
251
|
+
if (!['install', 'update', 'uninstall', 'doctor', 'help'].includes(options.command)) {
|
|
230
252
|
throw new Error(`Unknown command: ${options.command}`);
|
|
231
253
|
}
|
|
232
254
|
if (options.command === 'install' && !['npm', 'link', 'copy', 'skip'].includes(options.install.pluginInstallMode)) {
|
|
@@ -304,6 +326,19 @@ function printUpdateSummary(result, doctorResult) {
|
|
|
304
326
|
console.log('');
|
|
305
327
|
}
|
|
306
328
|
|
|
329
|
+
function printUninstallSummary(result) {
|
|
330
|
+
console.log('');
|
|
331
|
+
console.log('Claworld uninstall complete');
|
|
332
|
+
console.log('===========================');
|
|
333
|
+
console.log(`Managed account: ${result.transformed?.backup?.accountId || 'claworld'}`);
|
|
334
|
+
console.log(`OpenClaw version: ${result.host?.version || '(unknown)'}`);
|
|
335
|
+
console.log(`Plugin action: ${result.plugin?.action || 'unknown'}`);
|
|
336
|
+
console.log(`Runtime refresh: ${result.runtimeRefresh?.action || 'unknown'}`);
|
|
337
|
+
console.log(`Config path: ${result.configPath}`);
|
|
338
|
+
console.log(`Backup path: ${result.backupPath || '(unchanged or new file)'}`);
|
|
339
|
+
console.log('');
|
|
340
|
+
}
|
|
341
|
+
|
|
307
342
|
export async function runInstallerCli(argv = process.argv.slice(2), env = process.env) {
|
|
308
343
|
const parsed = parseInstallerCliArgs(argv, env);
|
|
309
344
|
if (parsed.command === 'help') {
|
|
@@ -347,6 +382,16 @@ export async function runInstallerCli(argv = process.argv.slice(2), env = proces
|
|
|
347
382
|
};
|
|
348
383
|
}
|
|
349
384
|
|
|
385
|
+
if (parsed.command === 'uninstall') {
|
|
386
|
+
const result = await runClaworldInstallerUninstall(parsed.uninstall);
|
|
387
|
+
if (parsed.json) {
|
|
388
|
+
console.log(JSON.stringify(result, null, 2));
|
|
389
|
+
} else {
|
|
390
|
+
printUninstallSummary(result);
|
|
391
|
+
}
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
|
|
350
395
|
const result = await runClaworldDoctor(parsed.doctor);
|
|
351
396
|
if (parsed.json) {
|
|
352
397
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -3,4 +3,5 @@ export const CLAWORLD_INSTALLER_PACKAGE_NAME = '@xfxstudio/claworld';
|
|
|
3
3
|
export const CLAWORLD_INSTALLER_COMMAND = 'npx -y @xfxstudio/claworld install';
|
|
4
4
|
export const CLAWORLD_DOCTOR_COMMAND = 'npx -y @xfxstudio/claworld doctor';
|
|
5
5
|
export const CLAWORLD_UPDATE_COMMAND = 'npx -y @xfxstudio/claworld update';
|
|
6
|
+
export const CLAWORLD_UNINSTALL_COMMAND = 'npx -y @xfxstudio/claworld uninstall';
|
|
6
7
|
export const CLAWORLD_OPENCLAW_MIN_HOST_VERSION = '>=2026.3.22';
|
|
@@ -11,8 +11,11 @@ import {
|
|
|
11
11
|
applyClaworldManagedRuntimeConfig,
|
|
12
12
|
ensureObject,
|
|
13
13
|
expandUserPath,
|
|
14
|
+
findClaworldManagedRuntimeBackup,
|
|
14
15
|
normalizeText,
|
|
15
16
|
resolveClaworldManagedRuntimeOptions,
|
|
17
|
+
setClaworldManagedRuntimeBackupState,
|
|
18
|
+
stripClaworldManagedRuntimeConfig,
|
|
16
19
|
} from '../plugin/managed-config.js';
|
|
17
20
|
import {
|
|
18
21
|
defaultClaworldAccountId,
|
|
@@ -23,6 +26,7 @@ import {
|
|
|
23
26
|
CLAWORLD_INSTALLER_COMMAND,
|
|
24
27
|
CLAWORLD_INSTALLER_PACKAGE_NAME,
|
|
25
28
|
CLAWORLD_OPENCLAW_MIN_HOST_VERSION,
|
|
29
|
+
CLAWORLD_UNINSTALL_COMMAND,
|
|
26
30
|
CLAWORLD_UPDATE_COMMAND,
|
|
27
31
|
} from './constants.js';
|
|
28
32
|
import { seedManagedWorkspaceContract } from './workspace-contract.js';
|
|
@@ -143,7 +147,7 @@ export function isRelayBootstrapReady(account = {}) {
|
|
|
143
147
|
normalizeText(account?.appToken, null)
|
|
144
148
|
|| (
|
|
145
149
|
account?.registration?.enabled === true
|
|
146
|
-
&& normalizeText(account?.registration?.
|
|
150
|
+
&& normalizeText(account?.registration?.displayName, null)
|
|
147
151
|
)
|
|
148
152
|
),
|
|
149
153
|
);
|
|
@@ -658,6 +662,23 @@ export async function loadConfigFromDisk(configPath) {
|
|
|
658
662
|
}
|
|
659
663
|
}
|
|
660
664
|
|
|
665
|
+
export function resolveClaworldInstallerStatePath(configPath) {
|
|
666
|
+
const resolvedConfigPath = path.resolve(String(configPath || DEFAULT_OPENCLAW_CONFIG_PATH));
|
|
667
|
+
return path.join(path.dirname(resolvedConfigPath), '.claworld-installer-state.json');
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export async function loadInstallerStateFromDisk(installerStatePath) {
|
|
671
|
+
try {
|
|
672
|
+
const raw = await fs.readFile(installerStatePath, 'utf8');
|
|
673
|
+
return { existed: true, state: parseConfigObject(raw, installerStatePath) };
|
|
674
|
+
} catch (error) {
|
|
675
|
+
if (error && error.code === 'ENOENT') {
|
|
676
|
+
return { existed: false, state: {} };
|
|
677
|
+
}
|
|
678
|
+
throw error;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
661
682
|
export async function backupConfigIfPresent(configPath, existed, dryRun = false) {
|
|
662
683
|
if (!existed) return null;
|
|
663
684
|
const stamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\..+$/, '').replace('T', '-');
|
|
@@ -675,6 +696,20 @@ export async function writeConfig(configPath, config, dryRun = false) {
|
|
|
675
696
|
return rendered;
|
|
676
697
|
}
|
|
677
698
|
|
|
699
|
+
export async function writeInstallerState(installerStatePath, installerState, dryRun = false) {
|
|
700
|
+
const renderedState = ensureObject(installerState);
|
|
701
|
+
if (Object.keys(renderedState).length === 0) {
|
|
702
|
+
if (dryRun) return '';
|
|
703
|
+
await fs.rm(installerStatePath, { force: true });
|
|
704
|
+
return '';
|
|
705
|
+
}
|
|
706
|
+
const rendered = `${JSON.stringify(renderedState, null, 2)}\n`;
|
|
707
|
+
if (dryRun) return rendered;
|
|
708
|
+
await fs.mkdir(path.dirname(installerStatePath), { recursive: true });
|
|
709
|
+
await fs.writeFile(installerStatePath, rendered, 'utf8');
|
|
710
|
+
return rendered;
|
|
711
|
+
}
|
|
712
|
+
|
|
678
713
|
export function buildOpenclawCommandEnv({ configPath, stateDir = null, env = process.env } = {}) {
|
|
679
714
|
return {
|
|
680
715
|
...env,
|
|
@@ -688,6 +723,7 @@ export function inspectManagedClaworldInstall({
|
|
|
688
723
|
accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
|
|
689
724
|
input = {},
|
|
690
725
|
overrides = {},
|
|
726
|
+
installerState = {},
|
|
691
727
|
} = {}) {
|
|
692
728
|
const configuredAccountIds = listClaworldAccountIds(cfg);
|
|
693
729
|
const hasAnyConfig = configuredAccountIds.length > 0 || cfg?.channels?.claworld != null;
|
|
@@ -696,6 +732,7 @@ export function inspectManagedClaworldInstall({
|
|
|
696
732
|
accountId,
|
|
697
733
|
input,
|
|
698
734
|
overrides,
|
|
735
|
+
installerState,
|
|
699
736
|
});
|
|
700
737
|
const managedAgentPresent = Boolean(findAgentEntry(cfg, managedOptions.agentId));
|
|
701
738
|
const managedBindingPresent = hasManagedBinding(cfg, managedOptions);
|
|
@@ -735,7 +772,10 @@ export function inspectManagedClaworldInstall({
|
|
|
735
772
|
accountStatus,
|
|
736
773
|
managedRuntimeReady,
|
|
737
774
|
managedReady,
|
|
738
|
-
reusableAppToken: normalizeText(
|
|
775
|
+
reusableAppToken: normalizeText(
|
|
776
|
+
managedOptions.appToken,
|
|
777
|
+
normalizeText(accountStatus?.appToken, null),
|
|
778
|
+
),
|
|
739
779
|
statusLabel,
|
|
740
780
|
selectionHint,
|
|
741
781
|
quickstartScore: managedRuntimeReady ? 2 : 5,
|
|
@@ -879,7 +919,7 @@ export async function ensureClaworldPluginInstalled({
|
|
|
879
919
|
});
|
|
880
920
|
}
|
|
881
921
|
|
|
882
|
-
const args = ['plugins', 'install'];
|
|
922
|
+
const args = ['plugins', 'install', '--dangerously-force-unsafe-install'];
|
|
883
923
|
if (installMode === 'link') args.push('--link');
|
|
884
924
|
args.push(installSource);
|
|
885
925
|
await executeCommand({
|
|
@@ -1337,8 +1377,10 @@ export async function verifyClaworldInstall({
|
|
|
1337
1377
|
async function reconcileManagedClaworldRuntime({
|
|
1338
1378
|
openclawBin = DEFAULT_OPENCLAW_BIN,
|
|
1339
1379
|
configPath = DEFAULT_OPENCLAW_CONFIG_PATH,
|
|
1380
|
+
installerStatePath = null,
|
|
1340
1381
|
stateDir = DEFAULT_OPENCLAW_STATE_DIR,
|
|
1341
1382
|
currentConfigState = { existed: false, config: {} },
|
|
1383
|
+
currentInstallerState = {},
|
|
1342
1384
|
currentConfig = {},
|
|
1343
1385
|
host = null,
|
|
1344
1386
|
serverUrl = null,
|
|
@@ -1361,6 +1403,7 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1361
1403
|
const existingInstall = inspectManagedClaworldInstall({
|
|
1362
1404
|
cfg: currentConfig,
|
|
1363
1405
|
accountId,
|
|
1406
|
+
installerState: currentInstallerState,
|
|
1364
1407
|
overrides: {
|
|
1365
1408
|
agentId,
|
|
1366
1409
|
workspace,
|
|
@@ -1405,6 +1448,7 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1405
1448
|
const preflight = inspectManagedClaworldInstall({
|
|
1406
1449
|
cfg: currentConfig,
|
|
1407
1450
|
accountId: installAccountId,
|
|
1451
|
+
installerState: currentInstallerState,
|
|
1408
1452
|
overrides: {
|
|
1409
1453
|
agentId: installAgentId,
|
|
1410
1454
|
workspace,
|
|
@@ -1453,6 +1497,7 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1453
1497
|
|
|
1454
1498
|
const managedOptions = resolveClaworldManagedRuntimeOptions({
|
|
1455
1499
|
cfg: currentConfig,
|
|
1500
|
+
installerState: currentInstallerState,
|
|
1456
1501
|
accountId: installAccountId,
|
|
1457
1502
|
input: {
|
|
1458
1503
|
name: desiredDisplayName,
|
|
@@ -1526,6 +1571,16 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1526
1571
|
);
|
|
1527
1572
|
}
|
|
1528
1573
|
|
|
1574
|
+
let installerStateChanged = false;
|
|
1575
|
+
if (installerStatePath && installAccountId) {
|
|
1576
|
+
const nextInstallerState = JSON.parse(JSON.stringify(ensureObject(currentInstallerState)));
|
|
1577
|
+
setClaworldManagedRuntimeBackupState(nextInstallerState, installAccountId, null);
|
|
1578
|
+
installerStateChanged = JSON.stringify(currentInstallerState) !== JSON.stringify(nextInstallerState);
|
|
1579
|
+
if (installerStateChanged) {
|
|
1580
|
+
await writeInstallerState(installerStatePath, nextInstallerState, dryRun);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1529
1584
|
return {
|
|
1530
1585
|
backupPath,
|
|
1531
1586
|
existingInstall,
|
|
@@ -1540,6 +1595,8 @@ async function reconcileManagedClaworldRuntime({
|
|
|
1540
1595
|
workspaceActions,
|
|
1541
1596
|
runtimeRefresh,
|
|
1542
1597
|
verification,
|
|
1598
|
+
installerStatePath,
|
|
1599
|
+
installerStateChanged,
|
|
1543
1600
|
};
|
|
1544
1601
|
}
|
|
1545
1602
|
|
|
@@ -1567,6 +1624,7 @@ export async function runClaworldInstallerInstall({
|
|
|
1567
1624
|
timeoutMs = DEFAULT_INSTALL_TIMEOUT_MS,
|
|
1568
1625
|
} = {}) {
|
|
1569
1626
|
const resolvedConfigPath = path.resolve(expandUserPath(configPath, os.homedir()));
|
|
1627
|
+
const installerStatePath = resolveClaworldInstallerStatePath(resolvedConfigPath);
|
|
1570
1628
|
const resolvedStateDir = stateDir ? path.resolve(expandUserPath(stateDir, os.homedir())) : null;
|
|
1571
1629
|
const commandEnv = buildOpenclawCommandEnv({
|
|
1572
1630
|
configPath: resolvedConfigPath,
|
|
@@ -1574,6 +1632,7 @@ export async function runClaworldInstallerInstall({
|
|
|
1574
1632
|
env,
|
|
1575
1633
|
});
|
|
1576
1634
|
const currentConfigState = await loadConfigFromDisk(resolvedConfigPath);
|
|
1635
|
+
const currentInstallerState = (await loadInstallerStateFromDisk(installerStatePath)).state;
|
|
1577
1636
|
const currentConfigBeforePluginInstall = currentConfigState.config;
|
|
1578
1637
|
const host = await detectOpenclawHost({
|
|
1579
1638
|
openclawBin,
|
|
@@ -1620,8 +1679,10 @@ export async function runClaworldInstallerInstall({
|
|
|
1620
1679
|
const lifecycle = await reconcileManagedClaworldRuntime({
|
|
1621
1680
|
openclawBin,
|
|
1622
1681
|
configPath: resolvedConfigPath,
|
|
1682
|
+
installerStatePath,
|
|
1623
1683
|
stateDir: resolvedStateDir,
|
|
1624
1684
|
currentConfigState,
|
|
1685
|
+
currentInstallerState,
|
|
1625
1686
|
currentConfig,
|
|
1626
1687
|
host,
|
|
1627
1688
|
serverUrl,
|
|
@@ -1646,6 +1707,7 @@ export async function runClaworldInstallerInstall({
|
|
|
1646
1707
|
ok: true,
|
|
1647
1708
|
command: CLAWORLD_INSTALLER_COMMAND,
|
|
1648
1709
|
configPath: resolvedConfigPath,
|
|
1710
|
+
installerStatePath,
|
|
1649
1711
|
stateDir: resolvedStateDir,
|
|
1650
1712
|
host,
|
|
1651
1713
|
plugin,
|
|
@@ -1674,6 +1736,7 @@ export async function runClaworldInstallerUpdate({
|
|
|
1674
1736
|
timeoutMs = DEFAULT_INSTALL_TIMEOUT_MS,
|
|
1675
1737
|
} = {}) {
|
|
1676
1738
|
const resolvedConfigPath = path.resolve(expandUserPath(configPath, os.homedir()));
|
|
1739
|
+
const installerStatePath = resolveClaworldInstallerStatePath(resolvedConfigPath);
|
|
1677
1740
|
const resolvedStateDir = stateDir ? path.resolve(expandUserPath(stateDir, os.homedir())) : null;
|
|
1678
1741
|
const commandEnv = buildOpenclawCommandEnv({
|
|
1679
1742
|
configPath: resolvedConfigPath,
|
|
@@ -1681,6 +1744,7 @@ export async function runClaworldInstallerUpdate({
|
|
|
1681
1744
|
env,
|
|
1682
1745
|
});
|
|
1683
1746
|
const currentConfigState = await loadConfigFromDisk(resolvedConfigPath);
|
|
1747
|
+
const currentInstallerState = (await loadInstallerStateFromDisk(installerStatePath)).state;
|
|
1684
1748
|
const host = await detectOpenclawHost({
|
|
1685
1749
|
openclawBin,
|
|
1686
1750
|
commandRunner,
|
|
@@ -1712,8 +1776,10 @@ export async function runClaworldInstallerUpdate({
|
|
|
1712
1776
|
const lifecycle = await reconcileManagedClaworldRuntime({
|
|
1713
1777
|
openclawBin,
|
|
1714
1778
|
configPath: resolvedConfigPath,
|
|
1779
|
+
installerStatePath,
|
|
1715
1780
|
stateDir: resolvedStateDir,
|
|
1716
1781
|
currentConfigState: refreshedConfigState,
|
|
1782
|
+
currentInstallerState,
|
|
1717
1783
|
currentConfig,
|
|
1718
1784
|
host,
|
|
1719
1785
|
serverUrl,
|
|
@@ -1737,6 +1803,7 @@ export async function runClaworldInstallerUpdate({
|
|
|
1737
1803
|
ok: true,
|
|
1738
1804
|
command: CLAWORLD_UPDATE_COMMAND,
|
|
1739
1805
|
configPath: resolvedConfigPath,
|
|
1806
|
+
installerStatePath,
|
|
1740
1807
|
stateDir: resolvedStateDir,
|
|
1741
1808
|
host,
|
|
1742
1809
|
plugin,
|
|
@@ -1744,6 +1811,170 @@ export async function runClaworldInstallerUpdate({
|
|
|
1744
1811
|
};
|
|
1745
1812
|
}
|
|
1746
1813
|
|
|
1814
|
+
export async function runClaworldInstallerUninstall({
|
|
1815
|
+
openclawBin = DEFAULT_OPENCLAW_BIN,
|
|
1816
|
+
configPath = DEFAULT_OPENCLAW_CONFIG_PATH,
|
|
1817
|
+
stateDir = DEFAULT_OPENCLAW_STATE_DIR,
|
|
1818
|
+
accountId = DEFAULT_CLAWORLD_ACCOUNT_ID,
|
|
1819
|
+
agentId = DEFAULT_CLAWORLD_AGENT_ID,
|
|
1820
|
+
commandRunner = defaultCommandRunner,
|
|
1821
|
+
cwd = process.cwd(),
|
|
1822
|
+
env = process.env,
|
|
1823
|
+
dryRun = false,
|
|
1824
|
+
} = {}) {
|
|
1825
|
+
const resolvedConfigPath = path.resolve(expandUserPath(configPath, os.homedir()));
|
|
1826
|
+
const installerStatePath = resolveClaworldInstallerStatePath(resolvedConfigPath);
|
|
1827
|
+
const resolvedStateDir = stateDir ? path.resolve(expandUserPath(stateDir, os.homedir())) : null;
|
|
1828
|
+
const commandEnv = buildOpenclawCommandEnv({
|
|
1829
|
+
configPath: resolvedConfigPath,
|
|
1830
|
+
stateDir: resolvedStateDir,
|
|
1831
|
+
env,
|
|
1832
|
+
});
|
|
1833
|
+
const currentConfigState = await loadConfigFromDisk(resolvedConfigPath);
|
|
1834
|
+
const currentInstallerState = (await loadInstallerStateFromDisk(installerStatePath)).state;
|
|
1835
|
+
const currentConfig = currentConfigState.config;
|
|
1836
|
+
const host = await detectOpenclawHost({
|
|
1837
|
+
openclawBin,
|
|
1838
|
+
commandRunner,
|
|
1839
|
+
cwd,
|
|
1840
|
+
env: commandEnv,
|
|
1841
|
+
dryRun,
|
|
1842
|
+
});
|
|
1843
|
+
if (compareVersionParts(host.version, CLAWORLD_OPENCLAW_MIN_HOST_VERSION) < 0) {
|
|
1844
|
+
throw createInstallerError(
|
|
1845
|
+
'openclaw_version_too_old',
|
|
1846
|
+
`OpenClaw ${host.version} is below the required minimum ${CLAWORLD_OPENCLAW_MIN_HOST_VERSION}.`,
|
|
1847
|
+
{ hostVersion: host.version, minHostVersion: CLAWORLD_OPENCLAW_MIN_HOST_VERSION },
|
|
1848
|
+
);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
const pluginBefore = await inspectClaworldPluginInstall({
|
|
1852
|
+
openclawBin,
|
|
1853
|
+
configPath: resolvedConfigPath,
|
|
1854
|
+
stateDir: resolvedStateDir,
|
|
1855
|
+
commandRunner,
|
|
1856
|
+
cwd,
|
|
1857
|
+
env,
|
|
1858
|
+
dryRun,
|
|
1859
|
+
});
|
|
1860
|
+
const transformed = stripClaworldManagedRuntimeConfig(currentConfig, {
|
|
1861
|
+
accountId,
|
|
1862
|
+
agentId,
|
|
1863
|
+
preserveBackup: true,
|
|
1864
|
+
});
|
|
1865
|
+
const configChanged = JSON.stringify(currentConfig) !== JSON.stringify(transformed.config);
|
|
1866
|
+
const backupPath = configChanged
|
|
1867
|
+
? await backupConfigIfPresent(resolvedConfigPath, currentConfigState.existed, dryRun)
|
|
1868
|
+
: null;
|
|
1869
|
+
if (configChanged) {
|
|
1870
|
+
await writeConfig(resolvedConfigPath, transformed.config, dryRun);
|
|
1871
|
+
}
|
|
1872
|
+
const nextInstallerState = JSON.parse(JSON.stringify(ensureObject(currentInstallerState)));
|
|
1873
|
+
setClaworldManagedRuntimeBackupState(nextInstallerState, accountId, transformed.backup);
|
|
1874
|
+
const installerStateChanged = JSON.stringify(currentInstallerState) !== JSON.stringify(nextInstallerState);
|
|
1875
|
+
if (installerStateChanged) {
|
|
1876
|
+
await writeInstallerState(installerStatePath, nextInstallerState, dryRun);
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
await validateOpenclawConfig({
|
|
1880
|
+
openclawBin,
|
|
1881
|
+
configPath: resolvedConfigPath,
|
|
1882
|
+
stateDir: resolvedStateDir,
|
|
1883
|
+
commandRunner,
|
|
1884
|
+
cwd,
|
|
1885
|
+
env,
|
|
1886
|
+
dryRun,
|
|
1887
|
+
});
|
|
1888
|
+
|
|
1889
|
+
const uninstallBootstrap = pluginBefore.installed
|
|
1890
|
+
? await preparePluginBootstrapConfig({
|
|
1891
|
+
configPath: resolvedConfigPath,
|
|
1892
|
+
config: currentConfig,
|
|
1893
|
+
dryRun,
|
|
1894
|
+
})
|
|
1895
|
+
: null;
|
|
1896
|
+
|
|
1897
|
+
let pluginAction = 'plugin_already_absent';
|
|
1898
|
+
try {
|
|
1899
|
+
if (pluginBefore.installed) {
|
|
1900
|
+
await executeCommand({
|
|
1901
|
+
commandRunner,
|
|
1902
|
+
bin: openclawBin,
|
|
1903
|
+
args: ['plugins', 'uninstall', 'claworld', '--force'],
|
|
1904
|
+
cwd,
|
|
1905
|
+
env: buildOpenclawCommandEnv({
|
|
1906
|
+
configPath: uninstallBootstrap?.configPath || resolvedConfigPath,
|
|
1907
|
+
stateDir: resolvedStateDir,
|
|
1908
|
+
env,
|
|
1909
|
+
}),
|
|
1910
|
+
dryRun,
|
|
1911
|
+
capture: false,
|
|
1912
|
+
});
|
|
1913
|
+
pluginAction = 'uninstalled_plugin';
|
|
1914
|
+
}
|
|
1915
|
+
} finally {
|
|
1916
|
+
if (uninstallBootstrap) {
|
|
1917
|
+
await uninstallBootstrap.cleanup();
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
const runtimeRefresh = await refreshOpenclawRuntime({
|
|
1922
|
+
openclawBin,
|
|
1923
|
+
configPath: resolvedConfigPath,
|
|
1924
|
+
stateDir: resolvedStateDir,
|
|
1925
|
+
commandRunner,
|
|
1926
|
+
cwd,
|
|
1927
|
+
env,
|
|
1928
|
+
dryRun,
|
|
1929
|
+
});
|
|
1930
|
+
const pluginAfter = await inspectClaworldPluginInstall({
|
|
1931
|
+
openclawBin,
|
|
1932
|
+
configPath: resolvedConfigPath,
|
|
1933
|
+
stateDir: resolvedStateDir,
|
|
1934
|
+
commandRunner,
|
|
1935
|
+
cwd,
|
|
1936
|
+
env,
|
|
1937
|
+
dryRun,
|
|
1938
|
+
});
|
|
1939
|
+
if (pluginBefore.installed && pluginAfter.installed) {
|
|
1940
|
+
throw createInstallerError(
|
|
1941
|
+
'claworld_plugin_uninstall_failed',
|
|
1942
|
+
'OpenClaw still reports the claworld plugin as installed after uninstall.',
|
|
1943
|
+
{ before: pluginBefore, after: pluginAfter },
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
const gatewayStatus = await readGatewayStatus({
|
|
1948
|
+
openclawBin,
|
|
1949
|
+
configPath: resolvedConfigPath,
|
|
1950
|
+
stateDir: resolvedStateDir,
|
|
1951
|
+
commandRunner,
|
|
1952
|
+
cwd,
|
|
1953
|
+
env,
|
|
1954
|
+
dryRun,
|
|
1955
|
+
});
|
|
1956
|
+
|
|
1957
|
+
return {
|
|
1958
|
+
ok: true,
|
|
1959
|
+
command: CLAWORLD_UNINSTALL_COMMAND,
|
|
1960
|
+
configPath: resolvedConfigPath,
|
|
1961
|
+
installerStatePath,
|
|
1962
|
+
stateDir: resolvedStateDir,
|
|
1963
|
+
host,
|
|
1964
|
+
backupPath,
|
|
1965
|
+
transformed,
|
|
1966
|
+
configChanged,
|
|
1967
|
+
installerStateChanged,
|
|
1968
|
+
plugin: {
|
|
1969
|
+
action: pluginAction,
|
|
1970
|
+
before: pluginBefore,
|
|
1971
|
+
after: pluginAfter,
|
|
1972
|
+
},
|
|
1973
|
+
runtimeRefresh,
|
|
1974
|
+
gatewayStatus,
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1747
1978
|
export {
|
|
1748
1979
|
compareVersionParts,
|
|
1749
1980
|
defaultCommandRunner,
|
|
@@ -249,8 +249,8 @@ export async function runClaworldDoctor({
|
|
|
249
249
|
workspace: resolvedWorkspace,
|
|
250
250
|
serverUrl: effectiveServerUrl,
|
|
251
251
|
appToken: configuredAccount.appToken,
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
registrationDisplayName: configuredAccount.registration?.displayName || null,
|
|
253
|
+
defaultTargetAgentId: configuredAccount.relay?.defaultTargetAgentId || null,
|
|
254
254
|
})
|
|
255
255
|
: {
|
|
256
256
|
ok: true,
|
|
@@ -17,7 +17,6 @@ export function normalizeRuntimeRegistration(candidate = {}) {
|
|
|
17
17
|
|
|
18
18
|
return {
|
|
19
19
|
enabled: true,
|
|
20
|
-
agentCode: normalizeText(registration.agentCode, normalizeText(legacyLocalAgent.agentCode, null)),
|
|
21
20
|
displayName: normalizeText(registration.displayName, normalizeText(legacyLocalAgent.displayName, null)),
|
|
22
21
|
};
|
|
23
22
|
}
|
|
@@ -49,7 +48,7 @@ export function applyRuntimeIdentity(runtimeConfig = {}, { agentId = null, appTo
|
|
|
49
48
|
agentId: normalizeText(agentId, normalizeText(relay.agentId, null)),
|
|
50
49
|
appToken: resolvedAppToken,
|
|
51
50
|
credentialToken: resolvedAppToken,
|
|
52
|
-
|
|
51
|
+
defaultTargetAgentId: normalizeText(relay.defaultTargetAgentId, null),
|
|
53
52
|
},
|
|
54
53
|
};
|
|
55
54
|
}
|