soulhubcli 1.0.11 → 1.0.13
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 +190 -115
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -13284,6 +13284,7 @@ var import_node_fs8 = __toESM(require("fs"), 1);
|
|
|
13284
13284
|
var import_node_path11 = __toESM(require("path"), 1);
|
|
13285
13285
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
13286
13286
|
var import_node_child_process = require("child_process");
|
|
13287
|
+
var import_node_readline = __toESM(require("readline"), 1);
|
|
13287
13288
|
|
|
13288
13289
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
13289
13290
|
function isNothing(subject) {
|
|
@@ -19023,6 +19024,12 @@ function copyAgentFilesFromPackage(packageDir, targetDir) {
|
|
|
19023
19024
|
import_node_fs8.default.copyFileSync(sourcePath, import_node_path11.default.join(targetDir, destName));
|
|
19024
19025
|
}
|
|
19025
19026
|
}
|
|
19027
|
+
const skillsSource = import_node_path11.default.join(packageDir, "skills");
|
|
19028
|
+
if (import_node_fs8.default.existsSync(skillsSource) && import_node_fs8.default.statSync(skillsSource).isDirectory()) {
|
|
19029
|
+
const skillsTarget = import_node_path11.default.join(targetDir, "skills");
|
|
19030
|
+
import_node_fs8.default.cpSync(skillsSource, skillsTarget, { recursive: true });
|
|
19031
|
+
logger.debug(`Skills directory copied`, { from: skillsSource, to: skillsTarget });
|
|
19032
|
+
}
|
|
19026
19033
|
}
|
|
19027
19034
|
function findOpenClawDir(customDir) {
|
|
19028
19035
|
if (customDir) {
|
|
@@ -19032,7 +19039,7 @@ function findOpenClawDir(customDir) {
|
|
|
19032
19039
|
}
|
|
19033
19040
|
return resolved;
|
|
19034
19041
|
}
|
|
19035
|
-
const envHome = process.env.OPENCLAW_HOME;
|
|
19042
|
+
const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
|
|
19036
19043
|
if (envHome) {
|
|
19037
19044
|
const resolved = import_node_path11.default.resolve(envHome);
|
|
19038
19045
|
if (import_node_fs8.default.existsSync(resolved)) {
|
|
@@ -19040,9 +19047,12 @@ function findOpenClawDir(customDir) {
|
|
|
19040
19047
|
}
|
|
19041
19048
|
return resolved;
|
|
19042
19049
|
}
|
|
19050
|
+
const home = process.env.HOME || "~";
|
|
19043
19051
|
const candidates = [
|
|
19044
|
-
import_node_path11.default.join(
|
|
19045
|
-
import_node_path11.default.join(
|
|
19052
|
+
import_node_path11.default.join(home, ".openclaw"),
|
|
19053
|
+
import_node_path11.default.join(home, ".lightclaw"),
|
|
19054
|
+
import_node_path11.default.join(process.cwd(), ".openclaw"),
|
|
19055
|
+
import_node_path11.default.join(process.cwd(), ".lightclaw")
|
|
19046
19056
|
];
|
|
19047
19057
|
for (const candidate of candidates) {
|
|
19048
19058
|
if (import_node_fs8.default.existsSync(candidate)) {
|
|
@@ -19051,6 +19061,58 @@ function findOpenClawDir(customDir) {
|
|
|
19051
19061
|
}
|
|
19052
19062
|
return null;
|
|
19053
19063
|
}
|
|
19064
|
+
function findAllClawDirs(customDir) {
|
|
19065
|
+
if (customDir) {
|
|
19066
|
+
const resolved = import_node_path11.default.resolve(customDir);
|
|
19067
|
+
return import_node_fs8.default.existsSync(resolved) ? [resolved] : [resolved];
|
|
19068
|
+
}
|
|
19069
|
+
const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
|
|
19070
|
+
if (envHome) {
|
|
19071
|
+
const resolved = import_node_path11.default.resolve(envHome);
|
|
19072
|
+
return [resolved];
|
|
19073
|
+
}
|
|
19074
|
+
const home = process.env.HOME || "~";
|
|
19075
|
+
const candidates = [
|
|
19076
|
+
import_node_path11.default.join(home, ".openclaw"),
|
|
19077
|
+
import_node_path11.default.join(home, ".lightclaw"),
|
|
19078
|
+
import_node_path11.default.join(process.cwd(), ".openclaw"),
|
|
19079
|
+
import_node_path11.default.join(process.cwd(), ".lightclaw")
|
|
19080
|
+
];
|
|
19081
|
+
return candidates.filter((c) => import_node_fs8.default.existsSync(c));
|
|
19082
|
+
}
|
|
19083
|
+
async function promptSelectClawDir(customDir) {
|
|
19084
|
+
const dirs = findAllClawDirs(customDir);
|
|
19085
|
+
if (dirs.length === 0) {
|
|
19086
|
+
return null;
|
|
19087
|
+
}
|
|
19088
|
+
if (dirs.length === 1) {
|
|
19089
|
+
return dirs[0];
|
|
19090
|
+
}
|
|
19091
|
+
console.log();
|
|
19092
|
+
console.log(" Detected multiple Claw installations:");
|
|
19093
|
+
console.log();
|
|
19094
|
+
dirs.forEach((dir, index) => {
|
|
19095
|
+
const brand = detectClawBrand(dir);
|
|
19096
|
+
console.log(` ${index + 1}) ${brand} ${dir}`);
|
|
19097
|
+
});
|
|
19098
|
+
console.log();
|
|
19099
|
+
const rl = import_node_readline.default.createInterface({
|
|
19100
|
+
input: process.stdin,
|
|
19101
|
+
output: process.stdout
|
|
19102
|
+
});
|
|
19103
|
+
return new Promise((resolve) => {
|
|
19104
|
+
rl.question(` Please select target (1-${dirs.length}): `, (answer) => {
|
|
19105
|
+
rl.close();
|
|
19106
|
+
const idx = parseInt(answer.trim(), 10);
|
|
19107
|
+
if (idx >= 1 && idx <= dirs.length) {
|
|
19108
|
+
resolve(dirs[idx - 1]);
|
|
19109
|
+
} else {
|
|
19110
|
+
console.log(" Invalid selection, operation cancelled.");
|
|
19111
|
+
resolve(null);
|
|
19112
|
+
}
|
|
19113
|
+
});
|
|
19114
|
+
});
|
|
19115
|
+
}
|
|
19054
19116
|
function getConfigPath() {
|
|
19055
19117
|
const home = process.env.HOME || "~";
|
|
19056
19118
|
return import_node_path11.default.join(home, ".soulhub", "config.json");
|
|
@@ -19105,8 +19167,22 @@ function checkMainAgentExists(clawDir) {
|
|
|
19105
19167
|
workspaceDir
|
|
19106
19168
|
};
|
|
19107
19169
|
}
|
|
19170
|
+
function detectClawBrand(clawDir) {
|
|
19171
|
+
const dirName = import_node_path11.default.basename(clawDir).toLowerCase();
|
|
19172
|
+
if (dirName.includes("lightclaw")) {
|
|
19173
|
+
return "LightClaw";
|
|
19174
|
+
}
|
|
19175
|
+
if (import_node_fs8.default.existsSync(import_node_path11.default.join(clawDir, "lightclaw.json"))) {
|
|
19176
|
+
return "LightClaw";
|
|
19177
|
+
}
|
|
19178
|
+
return "OpenClaw";
|
|
19179
|
+
}
|
|
19180
|
+
function getClawConfigFileName(clawDir) {
|
|
19181
|
+
const brand = detectClawBrand(clawDir);
|
|
19182
|
+
return brand === "LightClaw" ? "lightclaw.json" : "openclaw.json";
|
|
19183
|
+
}
|
|
19108
19184
|
function getOpenClawConfigPath(clawDir) {
|
|
19109
|
-
return import_node_path11.default.join(clawDir,
|
|
19185
|
+
return import_node_path11.default.join(clawDir, getClawConfigFileName(clawDir));
|
|
19110
19186
|
}
|
|
19111
19187
|
function readOpenClawConfig(clawDir) {
|
|
19112
19188
|
const configPath = getOpenClawConfigPath(clawDir);
|
|
@@ -19202,32 +19278,6 @@ function detectPackageKind(dir) {
|
|
|
19202
19278
|
}
|
|
19203
19279
|
return "unknown";
|
|
19204
19280
|
}
|
|
19205
|
-
function checkOpenClawInstalled(customDir) {
|
|
19206
|
-
const clawDir = findOpenClawDir(customDir);
|
|
19207
|
-
if (clawDir) {
|
|
19208
|
-
return {
|
|
19209
|
-
installed: true,
|
|
19210
|
-
clawDir,
|
|
19211
|
-
message: `OpenClaw detected at: ${clawDir}`
|
|
19212
|
-
};
|
|
19213
|
-
}
|
|
19214
|
-
try {
|
|
19215
|
-
(0, import_node_child_process.execSync)("which openclaw 2>/dev/null || where openclaw 2>nul", {
|
|
19216
|
-
stdio: "pipe"
|
|
19217
|
-
});
|
|
19218
|
-
return {
|
|
19219
|
-
installed: true,
|
|
19220
|
-
clawDir: null,
|
|
19221
|
-
message: "OpenClaw command found in PATH, but workspace directory not detected."
|
|
19222
|
-
};
|
|
19223
|
-
} catch {
|
|
19224
|
-
}
|
|
19225
|
-
return {
|
|
19226
|
-
installed: false,
|
|
19227
|
-
clawDir: null,
|
|
19228
|
-
message: "OpenClaw is not installed. Please install OpenClaw first, use --claw-dir to specify OpenClaw directory, or set OPENCLAW_HOME environment variable."
|
|
19229
|
-
};
|
|
19230
|
-
}
|
|
19231
19281
|
function backupAgentWorkspace(workspaceDir) {
|
|
19232
19282
|
if (!import_node_fs8.default.existsSync(workspaceDir)) {
|
|
19233
19283
|
return null;
|
|
@@ -19327,7 +19377,7 @@ function generateBackupId() {
|
|
|
19327
19377
|
}
|
|
19328
19378
|
function createBackupRecord(installType, packageName, clawDir) {
|
|
19329
19379
|
let openclawJsonSnapshot = null;
|
|
19330
|
-
const configPath =
|
|
19380
|
+
const configPath = getOpenClawConfigPath(clawDir);
|
|
19331
19381
|
if (import_node_fs8.default.existsSync(configPath)) {
|
|
19332
19382
|
try {
|
|
19333
19383
|
openclawJsonSnapshot = import_node_fs8.default.readFileSync(configPath, "utf-8");
|
|
@@ -19369,30 +19419,31 @@ var CATEGORY_LABELS = {
|
|
|
19369
19419
|
};
|
|
19370
19420
|
function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
|
|
19371
19421
|
const agentId = agentName.toLowerCase().replace(/[\s_]+/g, "-");
|
|
19372
|
-
logger.debug(`Registering agent to OpenClaw`, { agentId, workspaceDir });
|
|
19422
|
+
logger.debug(`Registering agent to OpenClaw/LightClaw`, { agentId, workspaceDir });
|
|
19373
19423
|
try {
|
|
19424
|
+
const clawCmd = detectClawCommand();
|
|
19374
19425
|
(0, import_node_child_process.execSync)(
|
|
19375
|
-
|
|
19426
|
+
`${clawCmd} agents add "${agentId}" --workspace "${workspaceDir}" --non-interactive --json`,
|
|
19376
19427
|
{ stdio: "pipe", timeout: 15e3 }
|
|
19377
19428
|
);
|
|
19378
19429
|
return {
|
|
19379
19430
|
success: true,
|
|
19380
|
-
message: `Agent "${agentId}" registered via
|
|
19431
|
+
message: `Agent "${agentId}" registered via CLI.`
|
|
19381
19432
|
};
|
|
19382
19433
|
} catch (cliError) {
|
|
19383
19434
|
const stderr = cliError && typeof cliError === "object" && "stderr" in cliError ? String(cliError.stderr) : "";
|
|
19384
19435
|
if (stderr.includes("already exists")) {
|
|
19385
19436
|
return {
|
|
19386
19437
|
success: true,
|
|
19387
|
-
message: `Agent "${agentId}" already registered
|
|
19438
|
+
message: `Agent "${agentId}" already registered.`
|
|
19388
19439
|
};
|
|
19389
19440
|
}
|
|
19390
19441
|
const isCommandNotFound = cliError && typeof cliError === "object" && "code" in cliError && cliError.code === "ENOENT" || stderr.includes("not found") || stderr.includes("not recognized");
|
|
19391
19442
|
if (isCommandNotFound) {
|
|
19392
|
-
logger.error(`OpenClaw CLI not found`);
|
|
19443
|
+
logger.error(`OpenClaw/LightClaw CLI not found`);
|
|
19393
19444
|
return {
|
|
19394
19445
|
success: false,
|
|
19395
|
-
message: "OpenClaw CLI not found. Please install
|
|
19446
|
+
message: "OpenClaw/LightClaw CLI not found. Please install first."
|
|
19396
19447
|
};
|
|
19397
19448
|
}
|
|
19398
19449
|
const errMsg = cliError instanceof Error ? cliError.message : String(cliError);
|
|
@@ -19403,17 +19454,31 @@ function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
|
|
|
19403
19454
|
};
|
|
19404
19455
|
}
|
|
19405
19456
|
}
|
|
19457
|
+
function detectClawCommand() {
|
|
19458
|
+
try {
|
|
19459
|
+
(0, import_node_child_process.execSync)("which lightclaw 2>/dev/null || where lightclaw 2>nul", { stdio: "pipe" });
|
|
19460
|
+
return "lightclaw";
|
|
19461
|
+
} catch {
|
|
19462
|
+
}
|
|
19463
|
+
try {
|
|
19464
|
+
(0, import_node_child_process.execSync)("which openclaw 2>/dev/null || where openclaw 2>nul", { stdio: "pipe" });
|
|
19465
|
+
return "openclaw";
|
|
19466
|
+
} catch {
|
|
19467
|
+
}
|
|
19468
|
+
return "openclaw";
|
|
19469
|
+
}
|
|
19406
19470
|
function restartOpenClawGateway() {
|
|
19407
|
-
|
|
19471
|
+
const clawCmd = detectClawCommand();
|
|
19472
|
+
logger.debug(`Restarting ${clawCmd} Gateway`);
|
|
19408
19473
|
try {
|
|
19409
|
-
(0, import_node_child_process.execSync)(
|
|
19474
|
+
(0, import_node_child_process.execSync)(`${clawCmd} gateway restart`, {
|
|
19410
19475
|
stdio: "pipe",
|
|
19411
19476
|
timeout: 3e4
|
|
19412
19477
|
// 30 秒超时
|
|
19413
19478
|
});
|
|
19414
19479
|
return {
|
|
19415
19480
|
success: true,
|
|
19416
|
-
message:
|
|
19481
|
+
message: `${clawCmd} Gateway restarted successfully.`
|
|
19417
19482
|
};
|
|
19418
19483
|
} catch (error) {
|
|
19419
19484
|
const stderr = error && typeof error === "object" && "stderr" in error ? String(error.stderr).trim() : "";
|
|
@@ -19653,12 +19718,18 @@ function createSpinner(initialText = "") {
|
|
|
19653
19718
|
// src/commands/install.ts
|
|
19654
19719
|
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
19655
19720
|
var import_node_path12 = __toESM(require("path"), 1);
|
|
19721
|
+
async function resolveClawDir(clawDir) {
|
|
19722
|
+
if (clawDir) {
|
|
19723
|
+
return findOpenClawDir(clawDir);
|
|
19724
|
+
}
|
|
19725
|
+
return promptSelectClawDir();
|
|
19726
|
+
}
|
|
19656
19727
|
var installCommand = new Command("install").description("Install an agent or team from the SoulHub registry").argument("[name]", "Agent or team name to install").option("--from <source>", "Install from a local directory, ZIP file, or URL").option(
|
|
19657
19728
|
"--dir <path>",
|
|
19658
|
-
"Target directory (defaults to OpenClaw workspace)"
|
|
19729
|
+
"Target directory (defaults to OpenClaw/LightClaw workspace)"
|
|
19659
19730
|
).option(
|
|
19660
19731
|
"--claw-dir <path>",
|
|
19661
|
-
"OpenClaw installation directory (overrides OPENCLAW_HOME env var, defaults to ~/.openclaw)"
|
|
19732
|
+
"OpenClaw/LightClaw installation directory (overrides OPENCLAW_HOME/LIGHTCLAW_HOME env var, defaults to ~/.openclaw or ~/.lightclaw)"
|
|
19662
19733
|
).action(async (name, options) => {
|
|
19663
19734
|
try {
|
|
19664
19735
|
if (options.from) {
|
|
@@ -19703,14 +19774,18 @@ async function installFromRegistry(name, targetDir, clawDir) {
|
|
|
19703
19774
|
}
|
|
19704
19775
|
async function installSingleAgent(name, targetDir, clawDir) {
|
|
19705
19776
|
const spinner = createSpinner(`Checking environment...`).start();
|
|
19777
|
+
let selectedClawDir = null;
|
|
19706
19778
|
if (!targetDir) {
|
|
19707
|
-
|
|
19708
|
-
|
|
19709
|
-
|
|
19779
|
+
spinner.stop();
|
|
19780
|
+
selectedClawDir = await resolveClawDir(clawDir);
|
|
19781
|
+
if (!selectedClawDir) {
|
|
19782
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
19710
19783
|
printOpenClawInstallHelp();
|
|
19711
19784
|
return;
|
|
19712
19785
|
}
|
|
19713
|
-
spinner.
|
|
19786
|
+
spinner.start();
|
|
19787
|
+
const brand = detectClawBrand(selectedClawDir);
|
|
19788
|
+
spinner.text = source_default.dim(`${brand} detected: ${selectedClawDir}`);
|
|
19714
19789
|
}
|
|
19715
19790
|
spinner.text = `Fetching agent ${source_default.cyan(name)}...`;
|
|
19716
19791
|
const index = await fetchIndex();
|
|
@@ -19724,18 +19799,11 @@ async function installSingleAgent(name, targetDir, clawDir) {
|
|
|
19724
19799
|
if (targetDir) {
|
|
19725
19800
|
workspaceDir = import_node_path12.default.resolve(targetDir);
|
|
19726
19801
|
} else {
|
|
19727
|
-
|
|
19728
|
-
if (!resolvedClawDir) {
|
|
19729
|
-
spinner.fail("OpenClaw workspace directory not found.");
|
|
19730
|
-
printOpenClawInstallHelp();
|
|
19731
|
-
return;
|
|
19732
|
-
}
|
|
19733
|
-
workspaceDir = getMainWorkspaceDir(resolvedClawDir);
|
|
19802
|
+
workspaceDir = getMainWorkspaceDir(selectedClawDir);
|
|
19734
19803
|
}
|
|
19735
|
-
const
|
|
19736
|
-
const backupRecord = !targetDir ? createBackupRecord("single-agent", name, resolvedClawDirForBackup) : null;
|
|
19804
|
+
const backupRecord = !targetDir ? createBackupRecord("single-agent", name, selectedClawDir) : null;
|
|
19737
19805
|
if (!targetDir) {
|
|
19738
|
-
const mainCheck = checkMainAgentExists(
|
|
19806
|
+
const mainCheck = checkMainAgentExists(selectedClawDir);
|
|
19739
19807
|
if (mainCheck.hasContent) {
|
|
19740
19808
|
spinner.warn(
|
|
19741
19809
|
`Existing main agent detected. Backing up workspace...`
|
|
@@ -19763,9 +19831,8 @@ async function installSingleAgent(name, targetDir, clawDir) {
|
|
|
19763
19831
|
}
|
|
19764
19832
|
if (!targetDir) {
|
|
19765
19833
|
spinner.text = `Registering ${source_default.cyan(agent.displayName)} as main agent...`;
|
|
19766
|
-
|
|
19767
|
-
|
|
19768
|
-
spinner.text = source_default.dim(`Main agent registered in openclaw.json`);
|
|
19834
|
+
addAgentToOpenClawConfig(selectedClawDir, "main", name, true);
|
|
19835
|
+
spinner.text = source_default.dim(`Main agent registered in config`);
|
|
19769
19836
|
}
|
|
19770
19837
|
spinner.text = `Downloading ${source_default.cyan(agent.displayName)} package...`;
|
|
19771
19838
|
const pkgDir = await downloadAgentPackage(name, agent.version);
|
|
@@ -19791,19 +19858,19 @@ async function installSingleAgent(name, targetDir, clawDir) {
|
|
|
19791
19858
|
}
|
|
19792
19859
|
async function installRecipeFromRegistry(name, recipe, targetDir, clawDir) {
|
|
19793
19860
|
const spinner = createSpinner(`Installing team ${source_default.cyan(recipe.displayName)}...`).start();
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19861
|
+
let resolvedClawDir;
|
|
19862
|
+
if (targetDir) {
|
|
19863
|
+
resolvedClawDir = import_node_path12.default.resolve(targetDir);
|
|
19864
|
+
} else {
|
|
19865
|
+
spinner.stop();
|
|
19866
|
+
const selected = await resolveClawDir(clawDir);
|
|
19867
|
+
if (!selected) {
|
|
19868
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
19798
19869
|
printOpenClawInstallHelp();
|
|
19799
19870
|
return;
|
|
19800
19871
|
}
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
if (!resolvedClawDir) {
|
|
19804
|
-
spinner.fail("OpenClaw workspace directory not found.");
|
|
19805
|
-
printOpenClawInstallHelp();
|
|
19806
|
-
return;
|
|
19872
|
+
resolvedClawDir = selected;
|
|
19873
|
+
spinner.start();
|
|
19807
19874
|
}
|
|
19808
19875
|
spinner.text = `Fetching team configuration...`;
|
|
19809
19876
|
let pkg;
|
|
@@ -19951,29 +20018,26 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir) {
|
|
|
19951
20018
|
const spinner = createSpinner("Installing single agent...").start();
|
|
19952
20019
|
const pkg = readSoulHubPackage(packageDir);
|
|
19953
20020
|
const agentName = pkg?.name || import_node_path12.default.basename(packageDir);
|
|
20021
|
+
let selectedClawDir = null;
|
|
19954
20022
|
if (!targetDir) {
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
20023
|
+
spinner.stop();
|
|
20024
|
+
selectedClawDir = await resolveClawDir(clawDir);
|
|
20025
|
+
if (!selectedClawDir) {
|
|
20026
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
19958
20027
|
printOpenClawInstallHelp();
|
|
19959
20028
|
return;
|
|
19960
20029
|
}
|
|
20030
|
+
spinner.start();
|
|
19961
20031
|
}
|
|
19962
20032
|
let workspaceDir;
|
|
19963
20033
|
if (targetDir) {
|
|
19964
20034
|
workspaceDir = import_node_path12.default.resolve(targetDir);
|
|
19965
20035
|
} else {
|
|
19966
|
-
|
|
19967
|
-
if (!resolvedClawDir) {
|
|
19968
|
-
spinner.fail("OpenClaw workspace directory not found.");
|
|
19969
|
-
return;
|
|
19970
|
-
}
|
|
19971
|
-
workspaceDir = getMainWorkspaceDir(resolvedClawDir);
|
|
20036
|
+
workspaceDir = getMainWorkspaceDir(selectedClawDir);
|
|
19972
20037
|
}
|
|
19973
|
-
const localBackupRecord = !targetDir ? createBackupRecord("single-agent-local", agentName,
|
|
20038
|
+
const localBackupRecord = !targetDir ? createBackupRecord("single-agent-local", agentName, selectedClawDir) : null;
|
|
19974
20039
|
if (!targetDir) {
|
|
19975
|
-
const
|
|
19976
|
-
const mainCheck = checkMainAgentExists(resolvedClawDir);
|
|
20040
|
+
const mainCheck = checkMainAgentExists(selectedClawDir);
|
|
19977
20041
|
if (mainCheck.hasContent) {
|
|
19978
20042
|
spinner.warn("Existing main agent detected. Backing up...");
|
|
19979
20043
|
const backupDir = backupAgentWorkspace(workspaceDir);
|
|
@@ -19994,8 +20058,7 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir) {
|
|
|
19994
20058
|
}
|
|
19995
20059
|
if (!targetDir) {
|
|
19996
20060
|
spinner.text = `Registering ${source_default.cyan(agentName)} as main agent...`;
|
|
19997
|
-
|
|
19998
|
-
addAgentToOpenClawConfig(resolvedClawDir, "main", agentName, true);
|
|
20061
|
+
addAgentToOpenClawConfig(selectedClawDir, "main", agentName, true);
|
|
19999
20062
|
}
|
|
20000
20063
|
spinner.text = `Copying soul files...`;
|
|
20001
20064
|
copyAgentFilesFromDir(packageDir, workspaceDir);
|
|
@@ -20022,18 +20085,19 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
|
|
|
20022
20085
|
spinner.fail("Invalid team package. Missing soulhub.yaml.");
|
|
20023
20086
|
return;
|
|
20024
20087
|
}
|
|
20025
|
-
|
|
20026
|
-
|
|
20027
|
-
|
|
20028
|
-
|
|
20088
|
+
let resolvedClawDir;
|
|
20089
|
+
if (targetDir) {
|
|
20090
|
+
resolvedClawDir = import_node_path12.default.resolve(targetDir);
|
|
20091
|
+
} else {
|
|
20092
|
+
spinner.stop();
|
|
20093
|
+
const selected = await resolveClawDir(clawDir);
|
|
20094
|
+
if (!selected) {
|
|
20095
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
20029
20096
|
printOpenClawInstallHelp();
|
|
20030
20097
|
return;
|
|
20031
20098
|
}
|
|
20032
|
-
|
|
20033
|
-
|
|
20034
|
-
if (!resolvedClawDir) {
|
|
20035
|
-
spinner.fail("OpenClaw workspace directory not found.");
|
|
20036
|
-
return;
|
|
20099
|
+
resolvedClawDir = selected;
|
|
20100
|
+
spinner.start();
|
|
20037
20101
|
}
|
|
20038
20102
|
const teamBackupRecord = !targetDir ? createBackupRecord("team-local", pkg.name, resolvedClawDir) : null;
|
|
20039
20103
|
if (!targetDir) {
|
|
@@ -20131,13 +20195,19 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
|
|
|
20131
20195
|
}
|
|
20132
20196
|
function copyAgentFilesFromDir(sourceDir, targetDir) {
|
|
20133
20197
|
const filesToCopy = ["IDENTITY.md", "SOUL.md", "USER.md", "TOOLS.md", "AGENTS.md", "HEARTBEAT.md"];
|
|
20198
|
+
import_node_fs9.default.mkdirSync(targetDir, { recursive: true });
|
|
20134
20199
|
for (const fileName of filesToCopy) {
|
|
20135
20200
|
const sourcePath = import_node_path12.default.join(sourceDir, fileName);
|
|
20136
20201
|
if (import_node_fs9.default.existsSync(sourcePath)) {
|
|
20137
|
-
import_node_fs9.default.mkdirSync(targetDir, { recursive: true });
|
|
20138
20202
|
import_node_fs9.default.copyFileSync(sourcePath, import_node_path12.default.join(targetDir, fileName));
|
|
20139
20203
|
}
|
|
20140
20204
|
}
|
|
20205
|
+
const skillsSource = import_node_path12.default.join(sourceDir, "skills");
|
|
20206
|
+
if (import_node_fs9.default.existsSync(skillsSource) && import_node_fs9.default.statSync(skillsSource).isDirectory()) {
|
|
20207
|
+
const skillsTarget = import_node_path12.default.join(targetDir, "skills");
|
|
20208
|
+
import_node_fs9.default.cpSync(skillsSource, skillsTarget, { recursive: true });
|
|
20209
|
+
logger.debug(`Skills directory copied`, { from: skillsSource, to: skillsTarget });
|
|
20210
|
+
}
|
|
20141
20211
|
}
|
|
20142
20212
|
async function installDispatcher(dispatcher, resolvedClawDir, clawDir, targetDir, spinner, backupRecord) {
|
|
20143
20213
|
const mainWorkspace = targetDir ? import_node_path12.default.join(resolvedClawDir, "workspace") : getMainWorkspaceDir(resolvedClawDir);
|
|
@@ -20187,11 +20257,11 @@ async function extractZipToDir(zip, targetDir) {
|
|
|
20187
20257
|
}
|
|
20188
20258
|
}
|
|
20189
20259
|
function printOpenClawInstallHelp() {
|
|
20190
|
-
console.log(source_default.dim(" Please install OpenClaw first, or use one of the following options:"));
|
|
20191
|
-
console.log(source_default.dim(" --claw-dir <path>
|
|
20192
|
-
console.log(source_default.dim(" --dir <path>
|
|
20193
|
-
console.log(source_default.dim(" OPENCLAW_HOME=<path>
|
|
20194
|
-
console.log(source_default.dim("
|
|
20260
|
+
console.log(source_default.dim(" Please install OpenClaw or LightClaw first, or use one of the following options:"));
|
|
20261
|
+
console.log(source_default.dim(" --claw-dir <path> Specify OpenClaw/LightClaw installation directory"));
|
|
20262
|
+
console.log(source_default.dim(" --dir <path> Specify agent target directory directly"));
|
|
20263
|
+
console.log(source_default.dim(" OPENCLAW_HOME=<path> Set environment variable (for OpenClaw)"));
|
|
20264
|
+
console.log(source_default.dim(" LIGHTCLAW_HOME=<path> Set environment variable (for LightClaw)"));
|
|
20195
20265
|
}
|
|
20196
20266
|
function printTeamSummary(pkg, workerIds) {
|
|
20197
20267
|
console.log();
|
|
@@ -20209,15 +20279,17 @@ function printTeamSummary(pkg, workerIds) {
|
|
|
20209
20279
|
console.log();
|
|
20210
20280
|
}
|
|
20211
20281
|
async function tryRestartGateway() {
|
|
20212
|
-
const
|
|
20282
|
+
const clawCmd = detectClawCommand();
|
|
20283
|
+
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
20284
|
+
const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
|
|
20213
20285
|
const result = restartOpenClawGateway();
|
|
20214
20286
|
if (result.success) {
|
|
20215
|
-
restartSpinner.succeed(
|
|
20287
|
+
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
20216
20288
|
} else {
|
|
20217
|
-
restartSpinner.warn(
|
|
20289
|
+
restartSpinner.warn(`Failed to restart ${brandName} Gateway.`);
|
|
20218
20290
|
console.log(source_default.yellow(` Reason: ${result.message}`));
|
|
20219
20291
|
console.log(source_default.dim(" Please restart manually:"));
|
|
20220
|
-
console.log(source_default.dim(
|
|
20292
|
+
console.log(source_default.dim(` ${clawCmd} gateway restart`));
|
|
20221
20293
|
}
|
|
20222
20294
|
}
|
|
20223
20295
|
|
|
@@ -20323,7 +20395,7 @@ var import_node_fs11 = __toESM(require("fs"), 1);
|
|
|
20323
20395
|
var import_node_path13 = __toESM(require("path"), 1);
|
|
20324
20396
|
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(
|
|
20325
20397
|
"--claw-dir <path>",
|
|
20326
|
-
"OpenClaw installation directory (overrides OPENCLAW_HOME env var)"
|
|
20398
|
+
"OpenClaw/LightClaw installation directory (overrides OPENCLAW_HOME/LIGHTCLAW_HOME env var)"
|
|
20327
20399
|
).action(async (options) => {
|
|
20328
20400
|
try {
|
|
20329
20401
|
if (options.list) {
|
|
@@ -20395,20 +20467,21 @@ async function performRollback(recordId, clawDir) {
|
|
|
20395
20467
|
const spinner = createSpinner(
|
|
20396
20468
|
`Rolling back ${source_default.cyan(record.packageName)}...`
|
|
20397
20469
|
).start();
|
|
20398
|
-
const resolvedClawDir = findOpenClawDir(clawDir) || record.clawDir;
|
|
20470
|
+
const resolvedClawDir = clawDir ? findOpenClawDir(clawDir) || record.clawDir : await promptSelectClawDir() || record.clawDir;
|
|
20399
20471
|
if (!resolvedClawDir || !import_node_fs11.default.existsSync(resolvedClawDir)) {
|
|
20400
|
-
spinner.fail(`OpenClaw directory not found: ${record.clawDir}`);
|
|
20472
|
+
spinner.fail(`OpenClaw/LightClaw directory not found: ${record.clawDir}`);
|
|
20401
20473
|
return;
|
|
20402
20474
|
}
|
|
20475
|
+
const brand = detectClawBrand(resolvedClawDir);
|
|
20403
20476
|
if (record.openclawJsonSnapshot) {
|
|
20404
|
-
spinner.text =
|
|
20477
|
+
spinner.text = `Restoring ${brand.toLowerCase()}.json...`;
|
|
20405
20478
|
try {
|
|
20406
20479
|
const configObj = JSON.parse(record.openclawJsonSnapshot);
|
|
20407
20480
|
writeOpenClawConfig(resolvedClawDir, configObj);
|
|
20408
|
-
logger.info(
|
|
20481
|
+
logger.info(`${brand.toLowerCase()}.json restored from snapshot`, { recordId: record.id });
|
|
20409
20482
|
} catch (err) {
|
|
20410
|
-
logger.error(
|
|
20411
|
-
console.log(source_default.yellow(
|
|
20483
|
+
logger.error(`Failed to restore ${brand.toLowerCase()}.json`, { error: err });
|
|
20484
|
+
console.log(source_default.yellow(` \u26A0 Failed to restore ${brand.toLowerCase()}.json, skipping...`));
|
|
20412
20485
|
}
|
|
20413
20486
|
}
|
|
20414
20487
|
if (record.installedWorkerIds.length > 0) {
|
|
@@ -20471,15 +20544,17 @@ async function performRollback(recordId, clawDir) {
|
|
|
20471
20544
|
spinner.succeed(
|
|
20472
20545
|
`Rolled back ${source_default.cyan.bold(record.packageName)} successfully! (${restoredCount} item(s) restored)`
|
|
20473
20546
|
);
|
|
20474
|
-
const
|
|
20547
|
+
const clawCmd = detectClawCommand();
|
|
20548
|
+
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
20549
|
+
const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
|
|
20475
20550
|
const result = restartOpenClawGateway();
|
|
20476
20551
|
if (result.success) {
|
|
20477
|
-
restartSpinner.succeed(
|
|
20552
|
+
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
20478
20553
|
} else {
|
|
20479
|
-
restartSpinner.warn(
|
|
20554
|
+
restartSpinner.warn(`Failed to restart ${brandName} Gateway.`);
|
|
20480
20555
|
console.log(source_default.yellow(` Reason: ${result.message}`));
|
|
20481
20556
|
console.log(source_default.dim(" Please restart manually:"));
|
|
20482
|
-
console.log(source_default.dim(
|
|
20557
|
+
console.log(source_default.dim(` ${clawCmd} gateway restart`));
|
|
20483
20558
|
}
|
|
20484
20559
|
console.log();
|
|
20485
20560
|
}
|
|
@@ -20500,13 +20575,13 @@ function formatInstallType(type2) {
|
|
|
20500
20575
|
|
|
20501
20576
|
// src/index.ts
|
|
20502
20577
|
var program2 = new Command();
|
|
20503
|
-
program2.name("soulhub").description("SoulHub CLI - Install and manage AI agent persona templates").version("1.0.
|
|
20578
|
+
program2.name("soulhub").description("SoulHub CLI - Install and manage AI agent persona templates").version("1.0.13").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
|
|
20504
20579
|
const opts = program2.opts();
|
|
20505
20580
|
const verbose = opts.verbose || process.env.SOULHUB_DEBUG === "1";
|
|
20506
20581
|
logger.init(verbose);
|
|
20507
20582
|
logger.info("CLI started", {
|
|
20508
20583
|
args: process.argv.slice(2),
|
|
20509
|
-
version: "1.0.
|
|
20584
|
+
version: "1.0.13",
|
|
20510
20585
|
node: process.version
|
|
20511
20586
|
});
|
|
20512
20587
|
});
|