soulhubcli 1.0.19 → 1.0.21
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 +5 -5
- package/dist/index.cjs +58 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,8 +90,8 @@ soulhub install --from https://example.com/agent-team.zip
|
|
|
90
90
|
# 安装到自定义目录(不依赖 OpenClaw/LightClaw 环境)
|
|
91
91
|
soulhub install writer-wechat --dir ./my-agents
|
|
92
92
|
|
|
93
|
-
# 指定 claw
|
|
94
|
-
soulhub install writer-wechat --
|
|
93
|
+
# 指定 claw 类型(只安装到该 claw)
|
|
94
|
+
soulhub install writer-wechat --clawtype LightClaw
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
### 列出已安装的 Agent
|
|
@@ -119,7 +119,7 @@ soulhub uninstall ops-assistant
|
|
|
119
119
|
|
|
120
120
|
- **默认安装为 Worker Agent**(子 agent),部署到 `workspace-<agentId>/` 目录
|
|
121
121
|
- 使用 `--main` 参数可安装为主 Agent,部署到 `workspace/` 目录
|
|
122
|
-
- **自动安装到所有检测到的 claw 目录**(OpenClaw / LightClaw),使用 `--
|
|
122
|
+
- **自动安装到所有检测到的 claw 目录**(OpenClaw / LightClaw),使用 `--clawtype` 可指定单个 claw
|
|
123
123
|
- 如果目标目录已存在,CLI 会**自动备份**(复制到 `agentbackup/`)
|
|
124
124
|
- 仅覆盖 `IDENTITY.md`、`SOUL.md` 等灵魂文件,不影响 workspace 中的其他运行时文件
|
|
125
125
|
- 安装完成后自动重启 OpenClaw Gateway;若重启失败会提示手动重启
|
|
@@ -148,11 +148,11 @@ export SOULHUB_REGISTRY_URL=https://your-registry.example.com
|
|
|
148
148
|
|
|
149
149
|
CLI 按以下优先级查找 claw 安装目录:
|
|
150
150
|
|
|
151
|
-
1. `--
|
|
151
|
+
1. `--clawtype` 命令行参数(指定时只安装到该 claw)
|
|
152
152
|
2. `OPENCLAW_HOME` / `LIGHTCLAW_HOME` 环境变量
|
|
153
153
|
3. 默认路径 `~/.openclaw`、`~/.lightclaw`
|
|
154
154
|
|
|
155
|
-
未指定 `--
|
|
155
|
+
未指定 `--clawtype` 时,CLI 会检测所有可用的 claw 目录并全部安装。
|
|
156
156
|
|
|
157
157
|
## 环境要求
|
|
158
158
|
|
package/dist/index.cjs
CHANGED
|
@@ -19033,11 +19033,15 @@ function copyAgentFilesFromPackage(packageDir, targetDir) {
|
|
|
19033
19033
|
}
|
|
19034
19034
|
function findOpenClawDir(customDir) {
|
|
19035
19035
|
if (customDir) {
|
|
19036
|
-
const
|
|
19037
|
-
|
|
19038
|
-
|
|
19036
|
+
const home2 = import_node_os2.default.homedir();
|
|
19037
|
+
const lower = customDir.toLowerCase();
|
|
19038
|
+
if (lower === "openclaw") {
|
|
19039
|
+
return import_node_path11.default.join(home2, ".openclaw");
|
|
19039
19040
|
}
|
|
19040
|
-
|
|
19041
|
+
if (lower === "lightclaw") {
|
|
19042
|
+
return import_node_path11.default.join(home2, ".lightclaw");
|
|
19043
|
+
}
|
|
19044
|
+
throw new Error(`Unsupported claw type: "${customDir}". Only "OpenClaw" or "LightClaw" is supported (case-insensitive).`);
|
|
19041
19045
|
}
|
|
19042
19046
|
const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
|
|
19043
19047
|
if (envHome) {
|
|
@@ -19063,8 +19067,15 @@ function findOpenClawDir(customDir) {
|
|
|
19063
19067
|
}
|
|
19064
19068
|
function findAllClawDirs(customDir) {
|
|
19065
19069
|
if (customDir) {
|
|
19066
|
-
const
|
|
19067
|
-
|
|
19070
|
+
const home2 = import_node_os2.default.homedir();
|
|
19071
|
+
const lower = customDir.toLowerCase();
|
|
19072
|
+
if (lower === "openclaw") {
|
|
19073
|
+
return [import_node_path11.default.join(home2, ".openclaw")];
|
|
19074
|
+
}
|
|
19075
|
+
if (lower === "lightclaw") {
|
|
19076
|
+
return [import_node_path11.default.join(home2, ".lightclaw")];
|
|
19077
|
+
}
|
|
19078
|
+
throw new Error(`Unsupported claw type: "${customDir}". Only "OpenClaw" or "LightClaw" is supported (case-insensitive).`);
|
|
19068
19079
|
}
|
|
19069
19080
|
const envHome = process.env.OPENCLAW_HOME || process.env.LIGHTCLAW_HOME;
|
|
19070
19081
|
if (envHome) {
|
|
@@ -19207,9 +19218,10 @@ function writeOpenClawConfig(clawDir, config) {
|
|
|
19207
19218
|
import_node_fs8.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
19208
19219
|
}
|
|
19209
19220
|
function updateOpenClawConfig(clawDir, updater) {
|
|
19210
|
-
|
|
19221
|
+
let config = readOpenClawConfig(clawDir);
|
|
19211
19222
|
if (!config) {
|
|
19212
|
-
|
|
19223
|
+
logger.info(`Config file not found in ${clawDir}, creating default config.`);
|
|
19224
|
+
config = { agents: { list: [] } };
|
|
19213
19225
|
}
|
|
19214
19226
|
const updated = updater(config);
|
|
19215
19227
|
writeOpenClawConfig(clawDir, updated);
|
|
@@ -19428,11 +19440,12 @@ var CATEGORY_LABELS = {
|
|
|
19428
19440
|
education: "Education",
|
|
19429
19441
|
dispatcher: "Dispatcher"
|
|
19430
19442
|
};
|
|
19431
|
-
function registerAgentToOpenClaw(agentName, workspaceDir,
|
|
19443
|
+
function registerAgentToOpenClaw(agentName, workspaceDir, clawDir) {
|
|
19432
19444
|
const agentId = agentName.toLowerCase().replace(/[\s_]+/g, "-");
|
|
19433
|
-
|
|
19445
|
+
const brandName = clawDir ? detectClawBrand(clawDir) : "OpenClaw/LightClaw";
|
|
19446
|
+
logger.debug(`Registering agent to ${brandName}`, { agentId, workspaceDir });
|
|
19434
19447
|
try {
|
|
19435
|
-
const clawCmd = detectClawCommand();
|
|
19448
|
+
const clawCmd = detectClawCommand(clawDir);
|
|
19436
19449
|
(0, import_node_child_process.execSync)(
|
|
19437
19450
|
`${clawCmd} agents add "${agentId}" --workspace "${workspaceDir}" --non-interactive --json`,
|
|
19438
19451
|
{ stdio: "pipe", timeout: 15e3 }
|
|
@@ -19446,8 +19459,8 @@ function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
|
|
|
19446
19459
|
if (stderr.includes("already exists")) {
|
|
19447
19460
|
logger.info(`Agent "${agentId}" already exists in CLI, updating config...`);
|
|
19448
19461
|
try {
|
|
19449
|
-
const
|
|
19450
|
-
addAgentToOpenClawConfig(
|
|
19462
|
+
const resolvedClawDir = clawDir || import_node_path11.default.dirname(workspaceDir);
|
|
19463
|
+
addAgentToOpenClawConfig(resolvedClawDir, agentId, agentName, false);
|
|
19451
19464
|
} catch {
|
|
19452
19465
|
logger.warn(`Failed to update config for existing agent "${agentId}", skipping.`);
|
|
19453
19466
|
}
|
|
@@ -19459,8 +19472,8 @@ function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
|
|
|
19459
19472
|
const errMsg = cliError instanceof Error ? cliError.message : String(cliError);
|
|
19460
19473
|
logger.warn(`CLI agents add failed, falling back to config file modification`, { agentId, stderr, error: errMsg });
|
|
19461
19474
|
try {
|
|
19462
|
-
const
|
|
19463
|
-
const configUpdated = addAgentToOpenClawConfig(
|
|
19475
|
+
const resolvedClawDir = clawDir || import_node_path11.default.dirname(workspaceDir);
|
|
19476
|
+
const configUpdated = addAgentToOpenClawConfig(resolvedClawDir, agentId, agentName, false);
|
|
19464
19477
|
if (configUpdated) {
|
|
19465
19478
|
logger.info(`Agent "${agentId}" registered via config file fallback.`);
|
|
19466
19479
|
return {
|
|
@@ -19484,7 +19497,11 @@ function registerAgentToOpenClaw(agentName, workspaceDir, _clawDir) {
|
|
|
19484
19497
|
}
|
|
19485
19498
|
}
|
|
19486
19499
|
}
|
|
19487
|
-
function detectClawCommand() {
|
|
19500
|
+
function detectClawCommand(clawDir) {
|
|
19501
|
+
if (clawDir) {
|
|
19502
|
+
const brand = detectClawBrand(clawDir);
|
|
19503
|
+
return brand === "LightClaw" ? "lightclaw" : "openclaw";
|
|
19504
|
+
}
|
|
19488
19505
|
try {
|
|
19489
19506
|
(0, import_node_child_process.execSync)("which lightclaw 2>/dev/null || where lightclaw 2>nul", { stdio: "pipe" });
|
|
19490
19507
|
return "lightclaw";
|
|
@@ -19497,8 +19514,8 @@ function detectClawCommand() {
|
|
|
19497
19514
|
}
|
|
19498
19515
|
return "openclaw";
|
|
19499
19516
|
}
|
|
19500
|
-
function restartOpenClawGateway() {
|
|
19501
|
-
const clawCmd = detectClawCommand();
|
|
19517
|
+
function restartOpenClawGateway(clawDir) {
|
|
19518
|
+
const clawCmd = detectClawCommand(clawDir);
|
|
19502
19519
|
logger.debug(`Restarting ${clawCmd} Gateway`);
|
|
19503
19520
|
try {
|
|
19504
19521
|
(0, import_node_child_process.execSync)(`${clawCmd} gateway restart`, {
|
|
@@ -19765,15 +19782,15 @@ var installCommand = new Command("install").description("Install an agent or tea
|
|
|
19765
19782
|
"--dir <path>",
|
|
19766
19783
|
"Target directory (defaults to OpenClaw/LightClaw workspace)"
|
|
19767
19784
|
).option(
|
|
19768
|
-
"--
|
|
19769
|
-
"
|
|
19785
|
+
"--clawtype <type>",
|
|
19786
|
+
"Specify claw type: OpenClaw or LightClaw (case-insensitive)"
|
|
19770
19787
|
).action(async (name, options) => {
|
|
19771
19788
|
try {
|
|
19772
19789
|
const asMain = !!options.main;
|
|
19773
19790
|
if (options.from) {
|
|
19774
|
-
await installFromSource(options.from, options.dir, options.
|
|
19791
|
+
await installFromSource(options.from, options.dir, options.clawtype, asMain);
|
|
19775
19792
|
} else if (name) {
|
|
19776
|
-
await installFromRegistry(name, options.dir, options.
|
|
19793
|
+
await installFromRegistry(name, options.dir, options.clawtype, asMain);
|
|
19777
19794
|
} else {
|
|
19778
19795
|
console.error(source_default.red("Please specify an agent or team name, or use --from to install from a local source."));
|
|
19779
19796
|
console.log(source_default.dim(" Examples:"));
|
|
@@ -19781,7 +19798,7 @@ var installCommand = new Command("install").description("Install an agent or tea
|
|
|
19781
19798
|
console.log(source_default.dim(" soulhub install writer-wechat --main # Install as main agent"));
|
|
19782
19799
|
console.log(source_default.dim(" soulhub install dev-squad # Install a team from registry"));
|
|
19783
19800
|
console.log(source_default.dim(" soulhub install --from ./agent-team/ # Install from local directory"));
|
|
19784
|
-
console.log(source_default.dim(" soulhub install writer-wechat --
|
|
19801
|
+
console.log(source_default.dim(" soulhub install writer-wechat --clawtype LightClaw # Install to specific claw"));
|
|
19785
19802
|
process.exit(1);
|
|
19786
19803
|
}
|
|
19787
19804
|
} catch (error) {
|
|
@@ -19951,7 +19968,7 @@ async function installSingleAgentToClaw(name, selectedClawDir, targetDir, asMain
|
|
|
19951
19968
|
console.log(` ${source_default.dim("Version:")} ${agent.version}`);
|
|
19952
19969
|
console.log(` ${source_default.dim("Type:")} ${typeLabel}`);
|
|
19953
19970
|
if (!targetDir) {
|
|
19954
|
-
await tryRestartGateway();
|
|
19971
|
+
await tryRestartGateway(selectedClawDir || void 0);
|
|
19955
19972
|
}
|
|
19956
19973
|
console.log();
|
|
19957
19974
|
}
|
|
@@ -20012,7 +20029,7 @@ async function installRecipeFromRegistry(name, recipe, targetDir, clawDir) {
|
|
|
20012
20029
|
const agentId = worker.name;
|
|
20013
20030
|
const workerDir = targetDir ? import_node_path12.default.join(resolvedClawDir, `workspace-${agentId}`) : getWorkspaceDir(resolvedClawDir, agentId);
|
|
20014
20031
|
if (!targetDir) {
|
|
20015
|
-
const regResult = registerAgentToOpenClaw(agentId, workerDir,
|
|
20032
|
+
const regResult = registerAgentToOpenClaw(agentId, workerDir, resolvedClawDir);
|
|
20016
20033
|
if (!regResult.success) {
|
|
20017
20034
|
console.log(source_default.yellow(` \u26A0 Failed to register ${agentId}: ${regResult.message}`));
|
|
20018
20035
|
continue;
|
|
@@ -20044,7 +20061,7 @@ async function installRecipeFromRegistry(name, recipe, targetDir, clawDir) {
|
|
|
20044
20061
|
);
|
|
20045
20062
|
printTeamSummary(pkg, workerIds);
|
|
20046
20063
|
if (!targetDir) {
|
|
20047
|
-
await tryRestartGateway();
|
|
20064
|
+
await tryRestartGateway(resolvedClawDir);
|
|
20048
20065
|
}
|
|
20049
20066
|
}
|
|
20050
20067
|
async function installFromSource(source, targetDir, clawDir, asMain) {
|
|
@@ -20217,7 +20234,7 @@ async function installSingleAgentFromDirToClaw(packageDir, agentName, pkg, selec
|
|
|
20217
20234
|
console.log(` ${source_default.dim("Source:")} ${packageDir}`);
|
|
20218
20235
|
console.log(` ${source_default.dim("Type:")} ${typeLabel}`);
|
|
20219
20236
|
if (!targetDir) {
|
|
20220
|
-
await tryRestartGateway();
|
|
20237
|
+
await tryRestartGateway(selectedClawDir || void 0);
|
|
20221
20238
|
}
|
|
20222
20239
|
console.log();
|
|
20223
20240
|
}
|
|
@@ -20303,7 +20320,7 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
|
|
|
20303
20320
|
spinner.text = `Installing worker ${source_default.cyan(agentId)}...`;
|
|
20304
20321
|
const workerWorkspace = targetDir ? import_node_path12.default.join(resolvedClawDir, `workspace-${agentId}`) : getWorkspaceDir(resolvedClawDir, agentId);
|
|
20305
20322
|
if (!targetDir) {
|
|
20306
|
-
const regResult = registerAgentToOpenClaw(agentId, workerWorkspace,
|
|
20323
|
+
const regResult = registerAgentToOpenClaw(agentId, workerWorkspace, resolvedClawDir);
|
|
20307
20324
|
if (!regResult.success) {
|
|
20308
20325
|
console.log(source_default.yellow(` \u26A0 Failed to register ${agentId}: ${regResult.message}`));
|
|
20309
20326
|
continue;
|
|
@@ -20333,7 +20350,7 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
|
|
|
20333
20350
|
);
|
|
20334
20351
|
printTeamSummary(pkg, workerIds);
|
|
20335
20352
|
if (!targetDir) {
|
|
20336
|
-
await tryRestartGateway();
|
|
20353
|
+
await tryRestartGateway(resolvedClawDir);
|
|
20337
20354
|
}
|
|
20338
20355
|
}
|
|
20339
20356
|
function copyAgentFilesFromDir(sourceDir, targetDir) {
|
|
@@ -20401,7 +20418,7 @@ async function extractZipToDir(zip, targetDir) {
|
|
|
20401
20418
|
}
|
|
20402
20419
|
function printOpenClawInstallHelp() {
|
|
20403
20420
|
console.log(source_default.dim(" Please install OpenClaw or LightClaw first, or use one of the following options:"));
|
|
20404
|
-
console.log(source_default.dim(" --
|
|
20421
|
+
console.log(source_default.dim(" --clawtype <type> Specify claw type: OpenClaw or LightClaw"));
|
|
20405
20422
|
console.log(source_default.dim(" --dir <path> Specify agent target directory directly"));
|
|
20406
20423
|
console.log(source_default.dim(" OPENCLAW_HOME=<path> Set environment variable (for OpenClaw)"));
|
|
20407
20424
|
console.log(source_default.dim(" LIGHTCLAW_HOME=<path> Set environment variable (for LightClaw)"));
|
|
@@ -20421,11 +20438,11 @@ function printTeamSummary(pkg, workerIds) {
|
|
|
20421
20438
|
}
|
|
20422
20439
|
console.log();
|
|
20423
20440
|
}
|
|
20424
|
-
async function tryRestartGateway() {
|
|
20425
|
-
const clawCmd = detectClawCommand();
|
|
20441
|
+
async function tryRestartGateway(clawDir) {
|
|
20442
|
+
const clawCmd = detectClawCommand(clawDir);
|
|
20426
20443
|
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
20427
20444
|
const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
|
|
20428
|
-
const result = restartOpenClawGateway();
|
|
20445
|
+
const result = restartOpenClawGateway(clawDir);
|
|
20429
20446
|
if (result.success) {
|
|
20430
20447
|
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
20431
20448
|
} else {
|
|
@@ -20534,16 +20551,16 @@ var updateCommand = new Command("update").description("Update installed agents t
|
|
|
20534
20551
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
20535
20552
|
var import_node_path13 = __toESM(require("path"), 1);
|
|
20536
20553
|
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(
|
|
20537
|
-
"--
|
|
20538
|
-
"
|
|
20554
|
+
"--clawtype <type>",
|
|
20555
|
+
"Specify claw type: OpenClaw or LightClaw (case-insensitive)"
|
|
20539
20556
|
).action(async (options) => {
|
|
20540
20557
|
try {
|
|
20541
20558
|
if (options.list) {
|
|
20542
20559
|
listBackupRecords();
|
|
20543
20560
|
} else if (options.id) {
|
|
20544
|
-
await performRollback(options.id, options.
|
|
20561
|
+
await performRollback(options.id, options.clawtype);
|
|
20545
20562
|
} else {
|
|
20546
|
-
await performRollback(void 0, options.
|
|
20563
|
+
await performRollback(void 0, options.clawtype);
|
|
20547
20564
|
}
|
|
20548
20565
|
} catch (error) {
|
|
20549
20566
|
logger.errorObj("Rollback command failed", error);
|
|
@@ -20684,10 +20701,10 @@ async function performRollback(recordId, clawDir) {
|
|
|
20684
20701
|
spinner.succeed(
|
|
20685
20702
|
`Rolled back ${source_default.cyan.bold(record.packageName)} successfully! (${restoredCount} item(s) restored)`
|
|
20686
20703
|
);
|
|
20687
|
-
const clawCmd = detectClawCommand();
|
|
20704
|
+
const clawCmd = detectClawCommand(resolvedClawDir);
|
|
20688
20705
|
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
20689
20706
|
const restartSpinner = createSpinner(`Restarting ${brandName} Gateway...`).start();
|
|
20690
|
-
const result = restartOpenClawGateway();
|
|
20707
|
+
const result = restartOpenClawGateway(resolvedClawDir);
|
|
20691
20708
|
if (result.success) {
|
|
20692
20709
|
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
20693
20710
|
} else {
|
|
@@ -20715,13 +20732,13 @@ function formatInstallType(type2) {
|
|
|
20715
20732
|
|
|
20716
20733
|
// src/index.ts
|
|
20717
20734
|
var program2 = new Command();
|
|
20718
|
-
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.
|
|
20735
|
+
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.21").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
|
|
20719
20736
|
const opts = program2.opts();
|
|
20720
20737
|
const verbose = opts.verbose || process.env.SOULHUB_DEBUG === "1";
|
|
20721
20738
|
logger.init(verbose);
|
|
20722
20739
|
logger.info("CLI started", {
|
|
20723
20740
|
args: process.argv.slice(2),
|
|
20724
|
-
version: "1.0.
|
|
20741
|
+
version: "1.0.21",
|
|
20725
20742
|
node: process.version
|
|
20726
20743
|
});
|
|
20727
20744
|
});
|