soulhubcli 1.0.9 → 1.0.10
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/dist/index.cjs +165 -137
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -966,7 +966,7 @@ var require_command = __commonJS({
|
|
|
966
966
|
var EventEmitter = require("events").EventEmitter;
|
|
967
967
|
var childProcess = require("child_process");
|
|
968
968
|
var path6 = require("path");
|
|
969
|
-
var
|
|
969
|
+
var fs6 = require("fs");
|
|
970
970
|
var process3 = require("process");
|
|
971
971
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
972
972
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1899,10 +1899,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1899
1899
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1900
1900
|
function findFile(baseDir, baseName) {
|
|
1901
1901
|
const localBin = path6.resolve(baseDir, baseName);
|
|
1902
|
-
if (
|
|
1902
|
+
if (fs6.existsSync(localBin)) return localBin;
|
|
1903
1903
|
if (sourceExt.includes(path6.extname(baseName))) return void 0;
|
|
1904
1904
|
const foundExt = sourceExt.find(
|
|
1905
|
-
(ext) =>
|
|
1905
|
+
(ext) => fs6.existsSync(`${localBin}${ext}`)
|
|
1906
1906
|
);
|
|
1907
1907
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1908
1908
|
return void 0;
|
|
@@ -1914,7 +1914,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1914
1914
|
if (this._scriptPath) {
|
|
1915
1915
|
let resolvedScriptPath;
|
|
1916
1916
|
try {
|
|
1917
|
-
resolvedScriptPath =
|
|
1917
|
+
resolvedScriptPath = fs6.realpathSync(this._scriptPath);
|
|
1918
1918
|
} catch (err) {
|
|
1919
1919
|
resolvedScriptPath = this._scriptPath;
|
|
1920
1920
|
}
|
|
@@ -16134,11 +16134,6 @@ function recordInstall(name, version, workspace) {
|
|
|
16134
16134
|
saveConfig(config);
|
|
16135
16135
|
logger.debug(`Recorded install`, { name, version, workspace });
|
|
16136
16136
|
}
|
|
16137
|
-
function removeInstallRecord(name) {
|
|
16138
|
-
const config = loadConfig();
|
|
16139
|
-
config.installed = config.installed.filter((a) => a.name !== name);
|
|
16140
|
-
saveConfig(config);
|
|
16141
|
-
}
|
|
16142
16137
|
function getWorkspaceDir(clawDir, agentName) {
|
|
16143
16138
|
return import_node_path2.default.join(clawDir, `workspace-${agentName}`);
|
|
16144
16139
|
}
|
|
@@ -17397,43 +17392,23 @@ var updateCommand = new Command("update").description("Update installed agent te
|
|
|
17397
17392
|
}
|
|
17398
17393
|
});
|
|
17399
17394
|
|
|
17400
|
-
// src/commands/
|
|
17395
|
+
// src/commands/rollback.ts
|
|
17401
17396
|
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
17402
|
-
var
|
|
17397
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
17398
|
+
var rollbackCommand = new Command("rollback").description("Rollback to a previous agent installation state").option("--list", "List available rollback records").option("--id <id>", "Rollback to a specific backup record by ID").option(
|
|
17399
|
+
"--claw-dir <path>",
|
|
17400
|
+
"OpenClaw installation directory (overrides OPENCLAW_HOME env var)"
|
|
17401
|
+
).action(async (options) => {
|
|
17403
17402
|
try {
|
|
17404
|
-
|
|
17405
|
-
|
|
17406
|
-
if (
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17410
|
-
`)
|
|
17411
|
-
);
|
|
17412
|
-
console.log(
|
|
17413
|
-
source_default.dim(" Use 'soulhub list' to see installed agents.")
|
|
17414
|
-
);
|
|
17415
|
-
process.exit(1);
|
|
17416
|
-
}
|
|
17417
|
-
const spinner = createSpinner(
|
|
17418
|
-
`Uninstalling ${source_default.cyan(name)}...`
|
|
17419
|
-
).start();
|
|
17420
|
-
if (!options.keepFiles && import_node_fs5.default.existsSync(installed.workspace)) {
|
|
17421
|
-
import_node_fs5.default.rmSync(installed.workspace, { recursive: true, force: true });
|
|
17422
|
-
spinner.text = `Removed workspace: ${installed.workspace}`;
|
|
17423
|
-
}
|
|
17424
|
-
removeInstallRecord(name);
|
|
17425
|
-
logger.info(`Agent uninstalled: ${name}`, { workspace: installed.workspace, keepFiles: !!options.keepFiles });
|
|
17426
|
-
spinner.succeed(
|
|
17427
|
-
`${source_default.cyan.bold(name)} uninstalled.`
|
|
17428
|
-
);
|
|
17429
|
-
if (options.keepFiles) {
|
|
17430
|
-
console.log(
|
|
17431
|
-
source_default.dim(` Files kept at: ${installed.workspace}`)
|
|
17432
|
-
);
|
|
17403
|
+
if (options.list) {
|
|
17404
|
+
listBackupRecords();
|
|
17405
|
+
} else if (options.id) {
|
|
17406
|
+
await performRollback(options.id, options.clawDir);
|
|
17407
|
+
} else {
|
|
17408
|
+
await performRollback(void 0, options.clawDir);
|
|
17433
17409
|
}
|
|
17434
|
-
console.log();
|
|
17435
17410
|
} catch (error) {
|
|
17436
|
-
logger.errorObj("
|
|
17411
|
+
logger.errorObj("Rollback command failed", error);
|
|
17437
17412
|
console.error(
|
|
17438
17413
|
source_default.red(`Error: ${error instanceof Error ? error.message : error}`)
|
|
17439
17414
|
);
|
|
@@ -17441,107 +17416,161 @@ var uninstallCommand = new Command("uninstall").description("Uninstall an agent
|
|
|
17441
17416
|
process.exit(1);
|
|
17442
17417
|
}
|
|
17443
17418
|
});
|
|
17444
|
-
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
}
|
|
17464
|
-
console.log();
|
|
17465
|
-
console.log(source_default.dim(" Required files: manifest.yaml, IDENTITY.md, SOUL.md"));
|
|
17466
|
-
console.log(
|
|
17467
|
-
source_default.dim(
|
|
17468
|
-
" See: https://soulhub.dev/docs/contributing"
|
|
17469
|
-
)
|
|
17470
|
-
);
|
|
17471
|
-
return;
|
|
17472
|
-
}
|
|
17473
|
-
const manifestContent = import_node_fs6.default.readFileSync(
|
|
17474
|
-
import_node_path5.default.join(dir, "manifest.yaml"),
|
|
17475
|
-
"utf-8"
|
|
17476
|
-
);
|
|
17477
|
-
const manifest = jsYaml.load(manifestContent);
|
|
17478
|
-
const requiredFields = [
|
|
17479
|
-
"name",
|
|
17480
|
-
"displayName",
|
|
17481
|
-
"description",
|
|
17482
|
-
"category",
|
|
17483
|
-
"version",
|
|
17484
|
-
"author"
|
|
17485
|
-
];
|
|
17486
|
-
const missingFields = requiredFields.filter(
|
|
17487
|
-
(f) => !manifest[f]
|
|
17419
|
+
function listBackupRecords() {
|
|
17420
|
+
const manifest = loadBackupManifest();
|
|
17421
|
+
if (manifest.records.length === 0) {
|
|
17422
|
+
console.log(source_default.yellow("No backup records found."));
|
|
17423
|
+
console.log(source_default.dim(" Backup records are created automatically when you install agents."));
|
|
17424
|
+
return;
|
|
17425
|
+
}
|
|
17426
|
+
console.log(source_default.bold("\nAvailable rollback records:\n"));
|
|
17427
|
+
console.log(
|
|
17428
|
+
source_default.dim(
|
|
17429
|
+
` ${"ID".padEnd(20)} ${"Type".padEnd(20)} ${"Package".padEnd(20)} ${"Date".padEnd(22)} Items`
|
|
17430
|
+
)
|
|
17431
|
+
);
|
|
17432
|
+
console.log(source_default.dim(" " + "\u2500".repeat(90)));
|
|
17433
|
+
for (const record of manifest.records) {
|
|
17434
|
+
const date = new Date(record.createdAt).toLocaleString();
|
|
17435
|
+
const typeLabel = formatInstallType(record.installType);
|
|
17436
|
+
const itemCount = record.items.length;
|
|
17437
|
+
console.log(
|
|
17438
|
+
` ${source_default.cyan(record.id.padEnd(20))} ${typeLabel.padEnd(20)} ${source_default.white(record.packageName.padEnd(20))} ${source_default.dim(date.padEnd(22))} ${itemCount} backup(s)`
|
|
17488
17439
|
);
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
|
|
17503
|
-
|
|
17504
|
-
|
|
17505
|
-
|
|
17506
|
-
|
|
17507
|
-
);
|
|
17440
|
+
}
|
|
17441
|
+
console.log();
|
|
17442
|
+
console.log(source_default.dim(" Usage:"));
|
|
17443
|
+
console.log(source_default.dim(" soulhub rollback # Rollback last installation"));
|
|
17444
|
+
console.log(source_default.dim(" soulhub rollback --id <id> # Rollback to a specific record"));
|
|
17445
|
+
console.log();
|
|
17446
|
+
}
|
|
17447
|
+
async function performRollback(recordId, clawDir) {
|
|
17448
|
+
const manifest = loadBackupManifest();
|
|
17449
|
+
if (manifest.records.length === 0) {
|
|
17450
|
+
console.log(source_default.yellow("No backup records found. Nothing to rollback."));
|
|
17451
|
+
return;
|
|
17452
|
+
}
|
|
17453
|
+
let record;
|
|
17454
|
+
if (recordId) {
|
|
17455
|
+
record = manifest.records.find((r) => r.id === recordId);
|
|
17456
|
+
if (!record) {
|
|
17457
|
+
console.error(source_default.red(`Backup record "${recordId}" not found.`));
|
|
17458
|
+
console.log(source_default.dim(" Use 'soulhub rollback --list' to see available records."));
|
|
17508
17459
|
return;
|
|
17509
17460
|
}
|
|
17510
|
-
|
|
17511
|
-
|
|
17512
|
-
console.log(source_default.bold(` ${manifest.displayName}`));
|
|
17513
|
-
console.log(
|
|
17514
|
-
source_default.dim(` ${manifest.name} v${manifest.version}`)
|
|
17515
|
-
);
|
|
17516
|
-
console.log(` ${manifest.description}`);
|
|
17517
|
-
console.log();
|
|
17518
|
-
console.log(source_default.bold(" Next steps to publish:"));
|
|
17519
|
-
console.log();
|
|
17520
|
-
console.log(
|
|
17521
|
-
` 1. Fork ${source_default.cyan("github.com/soulhub-community/soulhub")}`
|
|
17522
|
-
);
|
|
17523
|
-
console.log(
|
|
17524
|
-
` 2. Copy your agent directory to ${source_default.cyan(`registry/agents/${manifest.name}/`)}`
|
|
17525
|
-
);
|
|
17526
|
-
console.log(
|
|
17527
|
-
` 3. Submit a Pull Request`
|
|
17528
|
-
);
|
|
17529
|
-
console.log();
|
|
17461
|
+
} else {
|
|
17462
|
+
record = manifest.records[0];
|
|
17530
17463
|
console.log(
|
|
17531
17464
|
source_default.dim(
|
|
17532
|
-
|
|
17465
|
+
`Rolling back last installation: ${source_default.cyan(record.id)} (${record.packageName})`
|
|
17533
17466
|
)
|
|
17534
17467
|
);
|
|
17535
|
-
console.log();
|
|
17536
|
-
} catch (error) {
|
|
17537
|
-
logger.errorObj("Publish command failed", error);
|
|
17538
|
-
console.error(
|
|
17539
|
-
source_default.red(`Error: ${error instanceof Error ? error.message : error}`)
|
|
17540
|
-
);
|
|
17541
|
-
console.error(source_default.dim(` See logs: ${logger.getTodayLogFile()}`));
|
|
17542
|
-
process.exit(1);
|
|
17543
17468
|
}
|
|
17544
|
-
|
|
17469
|
+
const spinner = createSpinner(
|
|
17470
|
+
`Rolling back ${source_default.cyan(record.packageName)}...`
|
|
17471
|
+
).start();
|
|
17472
|
+
const resolvedClawDir = findOpenClawDir(clawDir) || record.clawDir;
|
|
17473
|
+
if (!resolvedClawDir || !import_node_fs5.default.existsSync(resolvedClawDir)) {
|
|
17474
|
+
spinner.fail(`OpenClaw directory not found: ${record.clawDir}`);
|
|
17475
|
+
return;
|
|
17476
|
+
}
|
|
17477
|
+
if (record.openclawJsonSnapshot) {
|
|
17478
|
+
spinner.text = "Restoring openclaw.json...";
|
|
17479
|
+
try {
|
|
17480
|
+
const configObj = JSON.parse(record.openclawJsonSnapshot);
|
|
17481
|
+
writeOpenClawConfig(resolvedClawDir, configObj);
|
|
17482
|
+
logger.info("openclaw.json restored from snapshot", { recordId: record.id });
|
|
17483
|
+
} catch (err) {
|
|
17484
|
+
logger.error("Failed to restore openclaw.json", { error: err });
|
|
17485
|
+
console.log(source_default.yellow(" \u26A0 Failed to restore openclaw.json, skipping..."));
|
|
17486
|
+
}
|
|
17487
|
+
}
|
|
17488
|
+
if (record.installedWorkerIds.length > 0) {
|
|
17489
|
+
spinner.text = "Removing installed workers...";
|
|
17490
|
+
for (const workerId of record.installedWorkerIds) {
|
|
17491
|
+
const workerDir = getWorkspaceDir(resolvedClawDir, workerId);
|
|
17492
|
+
if (import_node_fs5.default.existsSync(workerDir)) {
|
|
17493
|
+
import_node_fs5.default.rmSync(workerDir, { recursive: true, force: true });
|
|
17494
|
+
logger.info(`Removed installed worker directory`, { workerId, dir: workerDir });
|
|
17495
|
+
}
|
|
17496
|
+
const agentConfigDir = import_node_path5.default.join(resolvedClawDir, "agents", workerId);
|
|
17497
|
+
if (import_node_fs5.default.existsSync(agentConfigDir)) {
|
|
17498
|
+
import_node_fs5.default.rmSync(agentConfigDir, { recursive: true, force: true });
|
|
17499
|
+
}
|
|
17500
|
+
}
|
|
17501
|
+
}
|
|
17502
|
+
if (record.installedMainAgent) {
|
|
17503
|
+
const mainWorkspace = getMainWorkspaceDir(resolvedClawDir);
|
|
17504
|
+
const hasMainBackup = record.items.some((item) => item.role === "main");
|
|
17505
|
+
if (hasMainBackup && import_node_fs5.default.existsSync(mainWorkspace)) {
|
|
17506
|
+
spinner.text = "Cleaning current main workspace...";
|
|
17507
|
+
const entries = import_node_fs5.default.readdirSync(mainWorkspace);
|
|
17508
|
+
for (const entry of entries) {
|
|
17509
|
+
import_node_fs5.default.rmSync(import_node_path5.default.join(mainWorkspace, entry), { recursive: true, force: true });
|
|
17510
|
+
}
|
|
17511
|
+
}
|
|
17512
|
+
}
|
|
17513
|
+
let restoredCount = 0;
|
|
17514
|
+
for (const item of record.items) {
|
|
17515
|
+
if (!import_node_fs5.default.existsSync(item.backupPath)) {
|
|
17516
|
+
logger.warn(`Backup path not found, skipping`, { backupPath: item.backupPath });
|
|
17517
|
+
console.log(source_default.yellow(` \u26A0 Backup not found: ${item.backupPath}, skipping...`));
|
|
17518
|
+
continue;
|
|
17519
|
+
}
|
|
17520
|
+
spinner.text = `Restoring ${source_default.cyan(item.agentId)} (${item.role})...`;
|
|
17521
|
+
if (item.method === "mv") {
|
|
17522
|
+
if (import_node_fs5.default.existsSync(item.originalPath)) {
|
|
17523
|
+
import_node_fs5.default.rmSync(item.originalPath, { recursive: true, force: true });
|
|
17524
|
+
}
|
|
17525
|
+
import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(item.originalPath), { recursive: true });
|
|
17526
|
+
import_node_fs5.default.renameSync(item.backupPath, item.originalPath);
|
|
17527
|
+
logger.info(`Restored (mv back)`, { from: item.backupPath, to: item.originalPath });
|
|
17528
|
+
} else {
|
|
17529
|
+
if (import_node_fs5.default.existsSync(item.originalPath)) {
|
|
17530
|
+
const entries = import_node_fs5.default.readdirSync(item.originalPath);
|
|
17531
|
+
for (const entry of entries) {
|
|
17532
|
+
import_node_fs5.default.rmSync(import_node_path5.default.join(item.originalPath, entry), { recursive: true, force: true });
|
|
17533
|
+
}
|
|
17534
|
+
} else {
|
|
17535
|
+
import_node_fs5.default.mkdirSync(item.originalPath, { recursive: true });
|
|
17536
|
+
}
|
|
17537
|
+
import_node_fs5.default.cpSync(item.backupPath, item.originalPath, { recursive: true });
|
|
17538
|
+
import_node_fs5.default.rmSync(item.backupPath, { recursive: true, force: true });
|
|
17539
|
+
logger.info(`Restored (cp back)`, { from: item.backupPath, to: item.originalPath });
|
|
17540
|
+
}
|
|
17541
|
+
restoredCount++;
|
|
17542
|
+
}
|
|
17543
|
+
manifest.records = manifest.records.filter((r) => r.id !== record.id);
|
|
17544
|
+
saveBackupManifest(manifest);
|
|
17545
|
+
spinner.succeed(
|
|
17546
|
+
`Rolled back ${source_default.cyan.bold(record.packageName)} successfully! (${restoredCount} item(s) restored)`
|
|
17547
|
+
);
|
|
17548
|
+
const restartSpinner = createSpinner("Restarting OpenClaw Gateway...").start();
|
|
17549
|
+
const result = restartOpenClawGateway();
|
|
17550
|
+
if (result.success) {
|
|
17551
|
+
restartSpinner.succeed("OpenClaw Gateway restarted successfully.");
|
|
17552
|
+
} else {
|
|
17553
|
+
restartSpinner.warn("Failed to restart OpenClaw Gateway.");
|
|
17554
|
+
console.log(source_default.yellow(` Reason: ${result.message}`));
|
|
17555
|
+
console.log(source_default.dim(" Please restart manually:"));
|
|
17556
|
+
console.log(source_default.dim(" openclaw gateway restart"));
|
|
17557
|
+
}
|
|
17558
|
+
console.log();
|
|
17559
|
+
}
|
|
17560
|
+
function formatInstallType(type2) {
|
|
17561
|
+
switch (type2) {
|
|
17562
|
+
case "single-agent":
|
|
17563
|
+
return source_default.blue("Single Agent");
|
|
17564
|
+
case "team-registry":
|
|
17565
|
+
return source_default.magenta("Team (Registry)");
|
|
17566
|
+
case "team-local":
|
|
17567
|
+
return source_default.magenta("Team (Local)");
|
|
17568
|
+
case "single-agent-local":
|
|
17569
|
+
return source_default.blue("Agent (Local)");
|
|
17570
|
+
default:
|
|
17571
|
+
return type2;
|
|
17572
|
+
}
|
|
17573
|
+
}
|
|
17545
17574
|
|
|
17546
17575
|
// src/index.ts
|
|
17547
17576
|
var program2 = new Command();
|
|
@@ -17560,8 +17589,7 @@ program2.addCommand(infoCommand);
|
|
|
17560
17589
|
program2.addCommand(installCommand);
|
|
17561
17590
|
program2.addCommand(listCommand);
|
|
17562
17591
|
program2.addCommand(updateCommand);
|
|
17563
|
-
program2.addCommand(
|
|
17564
|
-
program2.addCommand(publishCommand);
|
|
17592
|
+
program2.addCommand(rollbackCommand);
|
|
17565
17593
|
program2.parse();
|
|
17566
17594
|
/*! Bundled license information:
|
|
17567
17595
|
|