soulhubcli 1.0.15 → 1.0.16
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 +31 -22
- package/dist/index.cjs +83 -102
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SoulHub CLI
|
|
2
2
|
|
|
3
|
-
SoulHub CLI —
|
|
3
|
+
SoulHub CLI — 用于发现、安装和管理 AI Agent 灵魂(Soul)的命令行工具。支持从 SoulHub Registry 或本地目录安装单 Agent 和多 Agent 团队,兼容 OpenClaw 和 LightClaw。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -34,14 +34,14 @@ npx soulhubcli <command>
|
|
|
34
34
|
|
|
35
35
|
| 命令 | 说明 |
|
|
36
36
|
|------|------|
|
|
37
|
-
| `soulhub search <keyword>` |
|
|
38
|
-
| `soulhub info <name>` | 查看 Agent
|
|
39
|
-
| `soulhub install <name>` | 从 Registry 安装 Agent
|
|
37
|
+
| `soulhub search <keyword>` | 搜索 Agent |
|
|
38
|
+
| `soulhub info <name>` | 查看 Agent 详细信息(identity、soul、skills 等) |
|
|
39
|
+
| `soulhub install <name>` | 从 Registry 安装 Agent 或团队(默认为 worker,安装到所有检测到的 claw) |
|
|
40
|
+
| `soulhub install <name> --main` | 安装为主 Agent |
|
|
40
41
|
| `soulhub install --from <source>` | 从本地目录、ZIP 文件或 URL 安装 |
|
|
41
42
|
| `soulhub list` | 列出已安装的 Agent |
|
|
42
43
|
| `soulhub update [name]` | 更新已安装的 Agent |
|
|
43
|
-
| `soulhub
|
|
44
|
-
| `soulhub publish` | 验证并发布你的 Agent |
|
|
44
|
+
| `soulhub rollback` | 回滚到上一次安装状态 |
|
|
45
45
|
|
|
46
46
|
## 使用方法
|
|
47
47
|
|
|
@@ -56,11 +56,16 @@ soulhub search "content writing"
|
|
|
56
56
|
|
|
57
57
|
CLI 会自动识别目标是单 Agent 还是多 Agent 团队,无需手动区分。
|
|
58
58
|
|
|
59
|
+
**默认行为:安装为 Worker Agent,自动安装到所有检测到的 claw 目录。**
|
|
60
|
+
|
|
59
61
|
**从 Registry 安装:**
|
|
60
62
|
|
|
61
63
|
```bash
|
|
62
|
-
# 安装单 Agent
|
|
63
|
-
soulhub install
|
|
64
|
+
# 安装单 Agent(默认为 worker,安装到所有检测到的 claw)
|
|
65
|
+
soulhub install writer-wechat
|
|
66
|
+
|
|
67
|
+
# 安装为主 Agent
|
|
68
|
+
soulhub install writer-wechat --main
|
|
64
69
|
|
|
65
70
|
# 安装多 Agent 团队(调度 Agent + 工作 Agent)
|
|
66
71
|
soulhub install dev-squad
|
|
@@ -82,11 +87,11 @@ soulhub install --from https://example.com/agent-team.zip
|
|
|
82
87
|
**指定目标目录:**
|
|
83
88
|
|
|
84
89
|
```bash
|
|
85
|
-
# 安装到自定义目录(不依赖 OpenClaw 环境)
|
|
86
|
-
soulhub install
|
|
90
|
+
# 安装到自定义目录(不依赖 OpenClaw/LightClaw 环境)
|
|
91
|
+
soulhub install writer-wechat --dir ./my-agents
|
|
87
92
|
|
|
88
|
-
# 指定
|
|
89
|
-
soulhub install
|
|
93
|
+
# 指定 claw 安装目录(只安装到该 claw)
|
|
94
|
+
soulhub install writer-wechat --claw-dir ~/.lightclaw
|
|
90
95
|
```
|
|
91
96
|
|
|
92
97
|
### 列出已安装的 Agent
|
|
@@ -112,9 +117,11 @@ soulhub uninstall ops-assistant
|
|
|
112
117
|
|
|
113
118
|
### 单 Agent 安装
|
|
114
119
|
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
120
|
+
- **默认安装为 Worker Agent**(子 agent),部署到 `workspace-<agentId>/` 目录
|
|
121
|
+
- 使用 `--main` 参数可安装为主 Agent,部署到 `workspace/` 目录
|
|
122
|
+
- **自动安装到所有检测到的 claw 目录**(OpenClaw / LightClaw),使用 `--claw-dir` 可指定单个 claw
|
|
123
|
+
- 如果目标目录已存在,CLI 会**自动备份**(复制到 `agentbackup/`)
|
|
124
|
+
- 仅覆盖 `IDENTITY.md`、`SOUL.md` 等灵魂文件,不影响 workspace 中的其他运行时文件
|
|
118
125
|
- 安装完成后自动重启 OpenClaw Gateway;若重启失败会提示手动重启
|
|
119
126
|
|
|
120
127
|
### 多 Agent 团队安装
|
|
@@ -122,7 +129,7 @@ soulhub uninstall ops-assistant
|
|
|
122
129
|
- **调度 Agent(Dispatcher)** 作为主 Agent 安装到 `workspace/` 目录
|
|
123
130
|
- **工作 Agent(Worker)** 安装到各自的 `workspace-<agentId>/` 目录
|
|
124
131
|
- 自动配置多 Agent 之间的通信
|
|
125
|
-
- Worker Agent
|
|
132
|
+
- Worker Agent 自动注册到 claw 配置中
|
|
126
133
|
- 安装完成后自动重启 OpenClaw Gateway
|
|
127
134
|
|
|
128
135
|
## 配置
|
|
@@ -137,18 +144,20 @@ CLI 将配置存储在 `~/.soulhub/config.json`。
|
|
|
137
144
|
export SOULHUB_REGISTRY_URL=https://your-registry.example.com
|
|
138
145
|
```
|
|
139
146
|
|
|
140
|
-
### OpenClaw 目录
|
|
147
|
+
### OpenClaw / LightClaw 目录
|
|
148
|
+
|
|
149
|
+
CLI 按以下优先级查找 claw 安装目录:
|
|
141
150
|
|
|
142
|
-
|
|
151
|
+
1. `--claw-dir` 命令行参数(指定时只安装到该 claw)
|
|
152
|
+
2. `OPENCLAW_HOME` / `LIGHTCLAW_HOME` 环境变量
|
|
153
|
+
3. 默认路径 `~/.openclaw`、`~/.lightclaw`
|
|
143
154
|
|
|
144
|
-
|
|
145
|
-
2. `OPENCLAW_HOME` 环境变量
|
|
146
|
-
3. 默认路径 `~/.openclaw`
|
|
155
|
+
未指定 `--claw-dir` 时,CLI 会检测所有可用的 claw 目录并全部安装。
|
|
147
156
|
|
|
148
157
|
## 环境要求
|
|
149
158
|
|
|
150
159
|
- Node.js >= 18.0.0
|
|
151
|
-
- OpenClaw(可选,使用 `--dir` 参数时不需要)
|
|
160
|
+
- OpenClaw 或 LightClaw(可选,使用 `--dir` 参数时不需要)
|
|
152
161
|
|
|
153
162
|
## License
|
|
154
163
|
|
package/dist/index.cjs
CHANGED
|
@@ -19725,40 +19725,20 @@ function createSpinner(initialText = "") {
|
|
|
19725
19725
|
// src/commands/install.ts
|
|
19726
19726
|
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
19727
19727
|
var import_node_path12 = __toESM(require("path"), 1);
|
|
19728
|
-
var import_node_readline2 = __toESM(require("readline"), 1);
|
|
19729
19728
|
async function resolveClawDir(clawDir) {
|
|
19730
19729
|
if (clawDir) {
|
|
19731
19730
|
return findOpenClawDir(clawDir);
|
|
19732
19731
|
}
|
|
19733
19732
|
return promptSelectClawDir();
|
|
19734
19733
|
}
|
|
19735
|
-
|
|
19736
|
-
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
console.log();
|
|
19742
|
-
const rl = import_node_readline2.default.createInterface({
|
|
19743
|
-
input: process.stdin,
|
|
19744
|
-
output: process.stdout
|
|
19745
|
-
});
|
|
19746
|
-
return new Promise((resolve) => {
|
|
19747
|
-
rl.question(" Please select (1-2, default: 2): ", (answer) => {
|
|
19748
|
-
rl.close();
|
|
19749
|
-
const trimmed = answer.trim();
|
|
19750
|
-
if (trimmed === "" || trimmed === "2") {
|
|
19751
|
-
resolve(false);
|
|
19752
|
-
} else if (trimmed === "1") {
|
|
19753
|
-
resolve(true);
|
|
19754
|
-
} else {
|
|
19755
|
-
console.log(" Invalid selection, operation cancelled.");
|
|
19756
|
-
resolve(null);
|
|
19757
|
-
}
|
|
19758
|
-
});
|
|
19759
|
-
});
|
|
19734
|
+
function resolveAllClawDirs(clawDir) {
|
|
19735
|
+
if (clawDir) {
|
|
19736
|
+
const resolved = findOpenClawDir(clawDir);
|
|
19737
|
+
return resolved ? [resolved] : [];
|
|
19738
|
+
}
|
|
19739
|
+
return findAllClawDirs();
|
|
19760
19740
|
}
|
|
19761
|
-
var installCommand = new Command("install").description("Install an agent or team from the SoulHub registry (default: as worker)").argument("[name]", "Agent or team name to install").option("--from <source>", "Install from a local directory, ZIP file, or URL").option("--main", "Install as main agent
|
|
19741
|
+
var installCommand = new Command("install").description("Install an agent or team from the SoulHub registry (default: as worker, installs to all detected claws)").argument("[name]", "Agent or team name to install").option("--from <source>", "Install from a local directory, ZIP file, or URL").option("--main", "Install as main agent").option(
|
|
19762
19742
|
"--dir <path>",
|
|
19763
19743
|
"Target directory (defaults to OpenClaw/LightClaw workspace)"
|
|
19764
19744
|
).option(
|
|
@@ -19766,13 +19746,7 @@ var installCommand = new Command("install").description("Install an agent or tea
|
|
|
19766
19746
|
"OpenClaw/LightClaw installation directory (overrides OPENCLAW_HOME/LIGHTCLAW_HOME env var, defaults to ~/.openclaw or ~/.lightclaw)"
|
|
19767
19747
|
).action(async (name, options) => {
|
|
19768
19748
|
try {
|
|
19769
|
-
|
|
19770
|
-
if (options.main && options.worker) {
|
|
19771
|
-
console.error(source_default.red("Error: --main and --worker cannot be used together."));
|
|
19772
|
-
process.exit(1);
|
|
19773
|
-
}
|
|
19774
|
-
if (options.main) asMain = true;
|
|
19775
|
-
if (options.worker) asMain = false;
|
|
19749
|
+
const asMain = !!options.main;
|
|
19776
19750
|
if (options.from) {
|
|
19777
19751
|
await installFromSource(options.from, options.dir, options.clawDir, asMain);
|
|
19778
19752
|
} else if (name) {
|
|
@@ -19780,12 +19754,11 @@ var installCommand = new Command("install").description("Install an agent or tea
|
|
|
19780
19754
|
} else {
|
|
19781
19755
|
console.error(source_default.red("Please specify an agent or team name, or use --from to install from a local source."));
|
|
19782
19756
|
console.log(source_default.dim(" Examples:"));
|
|
19783
|
-
console.log(source_default.dim(" soulhub install writer-wechat #
|
|
19784
|
-
console.log(source_default.dim(" soulhub install writer-wechat --main #
|
|
19785
|
-
console.log(source_default.dim(" soulhub install
|
|
19786
|
-
console.log(source_default.dim(" soulhub install
|
|
19787
|
-
console.log(source_default.dim(" soulhub install --
|
|
19788
|
-
console.log(source_default.dim(" soulhub install writer-wechat --claw-dir ~/.lightclaw # \u975E\u4EA4\u4E92\u5F0F\u6307\u5B9A claw \u76EE\u5F55"));
|
|
19757
|
+
console.log(source_default.dim(" soulhub install writer-wechat # Install as worker to all detected claws"));
|
|
19758
|
+
console.log(source_default.dim(" soulhub install writer-wechat --main # Install as main agent"));
|
|
19759
|
+
console.log(source_default.dim(" soulhub install dev-squad # Install a team from registry"));
|
|
19760
|
+
console.log(source_default.dim(" soulhub install --from ./agent-team/ # Install from local directory"));
|
|
19761
|
+
console.log(source_default.dim(" soulhub install writer-wechat --claw-dir ~/.lightclaw # Install to specific claw"));
|
|
19789
19762
|
process.exit(1);
|
|
19790
19763
|
}
|
|
19791
19764
|
} catch (error) {
|
|
@@ -19804,7 +19777,7 @@ async function installFromRegistry(name, targetDir, clawDir, asMain) {
|
|
|
19804
19777
|
const recipe = index.recipes.find((r) => r.name === name);
|
|
19805
19778
|
if (agent && !recipe) {
|
|
19806
19779
|
spinner.stop();
|
|
19807
|
-
logger.info(`Installing single agent from registry: ${name}, asMain=${asMain
|
|
19780
|
+
logger.info(`Installing single agent from registry: ${name}, asMain=${asMain}`);
|
|
19808
19781
|
await installSingleAgent(name, targetDir, clawDir, asMain);
|
|
19809
19782
|
} else if (recipe) {
|
|
19810
19783
|
spinner.stop();
|
|
@@ -19816,31 +19789,18 @@ async function installFromRegistry(name, targetDir, clawDir, asMain) {
|
|
|
19816
19789
|
console.log(source_default.dim(" Use 'soulhub search' to find available agents and teams."));
|
|
19817
19790
|
}
|
|
19818
19791
|
}
|
|
19819
|
-
async function installSingleAgent(name, targetDir, clawDir, asMain) {
|
|
19820
|
-
|
|
19821
|
-
|
|
19822
|
-
|
|
19823
|
-
spinner.stop();
|
|
19824
|
-
selectedClawDir = await resolveClawDir(clawDir);
|
|
19825
|
-
if (!selectedClawDir) {
|
|
19826
|
-
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
19827
|
-
printOpenClawInstallHelp();
|
|
19828
|
-
return;
|
|
19829
|
-
}
|
|
19830
|
-
const brand = detectClawBrand(selectedClawDir);
|
|
19831
|
-
console.log(source_default.dim(` ${brand} detected: ${selectedClawDir}`));
|
|
19832
|
-
}
|
|
19833
|
-
const agentId = name.toLowerCase().replace(/[\s_]+/g, "-");
|
|
19834
|
-
if (asMain === void 0) {
|
|
19835
|
-
const choice = await promptInstallRole(agentId);
|
|
19836
|
-
if (choice === null) return;
|
|
19837
|
-
asMain = choice;
|
|
19792
|
+
async function installSingleAgent(name, targetDir, clawDir, asMain = false) {
|
|
19793
|
+
if (targetDir) {
|
|
19794
|
+
await installSingleAgentToClaw(name, null, targetDir, asMain);
|
|
19795
|
+
return;
|
|
19838
19796
|
}
|
|
19839
|
-
|
|
19840
|
-
if (
|
|
19841
|
-
|
|
19797
|
+
const allClawDirs = resolveAllClawDirs(clawDir);
|
|
19798
|
+
if (allClawDirs.length === 0) {
|
|
19799
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
19800
|
+
printOpenClawInstallHelp();
|
|
19801
|
+
return;
|
|
19842
19802
|
}
|
|
19843
|
-
spinner
|
|
19803
|
+
const spinner = createSpinner(`Fetching agent ${source_default.cyan(name)}...`).start();
|
|
19844
19804
|
const index = await fetchIndex();
|
|
19845
19805
|
const agent = index.agents.find((a) => a.name === name);
|
|
19846
19806
|
if (!agent) {
|
|
@@ -19848,6 +19808,32 @@ async function installSingleAgent(name, targetDir, clawDir, asMain) {
|
|
|
19848
19808
|
console.log(source_default.dim(" Use 'soulhub search' to find available agents."));
|
|
19849
19809
|
return;
|
|
19850
19810
|
}
|
|
19811
|
+
spinner.text = `Downloading ${source_default.cyan(agent.displayName)} package...`;
|
|
19812
|
+
const pkgDir = await downloadAgentPackage(name, agent.version);
|
|
19813
|
+
spinner.succeed(`Package ${source_default.cyan(agent.displayName)} downloaded.`);
|
|
19814
|
+
for (const selectedClawDir of allClawDirs) {
|
|
19815
|
+
await installSingleAgentToClaw(name, selectedClawDir, void 0, asMain, pkgDir, agent);
|
|
19816
|
+
}
|
|
19817
|
+
import_node_fs9.default.rmSync(pkgDir, { recursive: true, force: true });
|
|
19818
|
+
}
|
|
19819
|
+
async function installSingleAgentToClaw(name, selectedClawDir, targetDir, asMain = false, preDownloadedPkgDir, preLoadedAgent) {
|
|
19820
|
+
const brand = selectedClawDir ? detectClawBrand(selectedClawDir) : null;
|
|
19821
|
+
const clawLabel = brand ? `${brand} (${selectedClawDir})` : targetDir;
|
|
19822
|
+
const spinner = createSpinner(`Installing to ${source_default.dim(clawLabel)}...`).start();
|
|
19823
|
+
const agentId = name.toLowerCase().replace(/[\s_]+/g, "-");
|
|
19824
|
+
logger.info(`Install role resolved: asMain=${asMain}, claw=${selectedClawDir || targetDir}`);
|
|
19825
|
+
let agent = preLoadedAgent;
|
|
19826
|
+
if (!agent) {
|
|
19827
|
+
spinner.text = `Fetching agent ${source_default.cyan(name)}...`;
|
|
19828
|
+
const index = await fetchIndex();
|
|
19829
|
+
const found = index.agents.find((a) => a.name === name);
|
|
19830
|
+
if (!found) {
|
|
19831
|
+
spinner.fail(`Agent "${name}" not found in registry.`);
|
|
19832
|
+
console.log(source_default.dim(" Use 'soulhub search' to find available agents."));
|
|
19833
|
+
return;
|
|
19834
|
+
}
|
|
19835
|
+
agent = found;
|
|
19836
|
+
}
|
|
19851
19837
|
let workspaceDir;
|
|
19852
19838
|
if (targetDir) {
|
|
19853
19839
|
workspaceDir = import_node_path12.default.resolve(targetDir);
|
|
@@ -19860,9 +19846,7 @@ async function installSingleAgent(name, targetDir, clawDir, asMain) {
|
|
|
19860
19846
|
if (!targetDir && asMain) {
|
|
19861
19847
|
const mainCheck = checkMainAgentExists(selectedClawDir);
|
|
19862
19848
|
if (mainCheck.hasContent) {
|
|
19863
|
-
spinner.warn(
|
|
19864
|
-
`Existing main agent detected. Backing up workspace...`
|
|
19865
|
-
);
|
|
19849
|
+
spinner.warn(`Existing main agent detected. Backing up workspace...`);
|
|
19866
19850
|
const backupDir = backupAgentWorkspace(workspaceDir);
|
|
19867
19851
|
if (backupDir) {
|
|
19868
19852
|
console.log(source_default.yellow(` \u26A0 Existing main agent backed up to: ${backupDir}`));
|
|
@@ -19902,21 +19886,23 @@ async function installSingleAgent(name, targetDir, clawDir, asMain) {
|
|
|
19902
19886
|
if (asMain) {
|
|
19903
19887
|
spinner.text = `Registering ${source_default.cyan(agent.displayName)} as main agent...`;
|
|
19904
19888
|
addAgentToOpenClawConfig(selectedClawDir, "main", name, true);
|
|
19905
|
-
spinner.text = source_default.dim(`Main agent registered in config`);
|
|
19906
19889
|
} else {
|
|
19907
19890
|
spinner.text = `Registering ${source_default.cyan(agent.displayName)} as worker agent...`;
|
|
19908
|
-
const regResult = registerAgentToOpenClaw(agentId, workspaceDir
|
|
19891
|
+
const regResult = registerAgentToOpenClaw(agentId, workspaceDir);
|
|
19909
19892
|
if (!regResult.success) {
|
|
19910
19893
|
spinner.fail(`Failed to register ${agentId}: ${regResult.message}`);
|
|
19911
19894
|
return;
|
|
19912
19895
|
}
|
|
19913
|
-
spinner.text = source_default.dim(`Worker agent ${agentId} registered in config`);
|
|
19914
19896
|
}
|
|
19915
19897
|
}
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
19898
|
+
if (preDownloadedPkgDir) {
|
|
19899
|
+
copyAgentFilesFromPackage(preDownloadedPkgDir, workspaceDir);
|
|
19900
|
+
} else {
|
|
19901
|
+
spinner.text = `Downloading ${source_default.cyan(agent.displayName)} package...`;
|
|
19902
|
+
const pkgDir = await downloadAgentPackage(name, agent.version);
|
|
19903
|
+
copyAgentFilesFromPackage(pkgDir, workspaceDir);
|
|
19904
|
+
import_node_fs9.default.rmSync(pkgDir, { recursive: true, force: true });
|
|
19905
|
+
}
|
|
19920
19906
|
recordInstall(name, agent.version, workspaceDir);
|
|
19921
19907
|
if (backupRecord) {
|
|
19922
19908
|
if (asMain) {
|
|
@@ -19930,9 +19916,8 @@ async function installSingleAgent(name, targetDir, clawDir, asMain) {
|
|
|
19930
19916
|
const typeLabel = asMain ? source_default.blue("Single Agent (Main)") : source_default.green("Single Agent (Worker)");
|
|
19931
19917
|
logger.info(`Single agent installed as ${roleLabel}: ${name}`, { version: agent.version, workspace: workspaceDir });
|
|
19932
19918
|
spinner.succeed(
|
|
19933
|
-
`${source_default.cyan.bold(agent.displayName)} installed as ${roleLabel}
|
|
19919
|
+
`${source_default.cyan.bold(agent.displayName)} installed as ${roleLabel} \u2192 ${source_default.dim(clawLabel)}`
|
|
19934
19920
|
);
|
|
19935
|
-
console.log();
|
|
19936
19921
|
console.log(` ${source_default.dim("Location:")} ${workspaceDir}`);
|
|
19937
19922
|
console.log(` ${source_default.dim("Version:")} ${agent.version}`);
|
|
19938
19923
|
console.log(` ${source_default.dim("Type:")} ${typeLabel}`);
|
|
@@ -20099,32 +20084,29 @@ async function installFromSource(source, targetDir, clawDir, asMain) {
|
|
|
20099
20084
|
import_node_fs9.default.rmSync(tempDir, { recursive: true, force: true });
|
|
20100
20085
|
}
|
|
20101
20086
|
}
|
|
20102
|
-
async function installSingleAgentFromDir(packageDir, targetDir, clawDir, asMain) {
|
|
20103
|
-
const spinner = createSpinner("Installing single agent...").start();
|
|
20087
|
+
async function installSingleAgentFromDir(packageDir, targetDir, clawDir, asMain = false) {
|
|
20104
20088
|
const pkg = readSoulHubPackage(packageDir);
|
|
20105
20089
|
const agentName = pkg?.name || import_node_path12.default.basename(packageDir);
|
|
20106
|
-
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
selectedClawDir = await resolveClawDir(clawDir);
|
|
20110
|
-
if (!selectedClawDir) {
|
|
20111
|
-
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
20112
|
-
printOpenClawInstallHelp();
|
|
20113
|
-
return;
|
|
20114
|
-
}
|
|
20115
|
-
const brand = detectClawBrand(selectedClawDir);
|
|
20116
|
-
console.log(source_default.dim(` ${brand} detected: ${selectedClawDir}`));
|
|
20090
|
+
if (targetDir) {
|
|
20091
|
+
await installSingleAgentFromDirToClaw(packageDir, agentName, pkg, null, targetDir, asMain);
|
|
20092
|
+
return;
|
|
20117
20093
|
}
|
|
20118
|
-
const
|
|
20119
|
-
if (
|
|
20120
|
-
|
|
20121
|
-
|
|
20122
|
-
|
|
20094
|
+
const allClawDirs = resolveAllClawDirs(clawDir);
|
|
20095
|
+
if (allClawDirs.length === 0) {
|
|
20096
|
+
console.log(source_default.red("OpenClaw/LightClaw workspace directory not found."));
|
|
20097
|
+
printOpenClawInstallHelp();
|
|
20098
|
+
return;
|
|
20123
20099
|
}
|
|
20124
|
-
|
|
20125
|
-
|
|
20126
|
-
spinner.start();
|
|
20100
|
+
for (const selectedClawDir of allClawDirs) {
|
|
20101
|
+
await installSingleAgentFromDirToClaw(packageDir, agentName, pkg, selectedClawDir, void 0, asMain);
|
|
20127
20102
|
}
|
|
20103
|
+
}
|
|
20104
|
+
async function installSingleAgentFromDirToClaw(packageDir, agentName, pkg, selectedClawDir, targetDir, asMain = false) {
|
|
20105
|
+
const brand = selectedClawDir ? detectClawBrand(selectedClawDir) : null;
|
|
20106
|
+
const clawLabel = brand ? `${brand} (${selectedClawDir})` : targetDir;
|
|
20107
|
+
const spinner = createSpinner(`Installing to ${source_default.dim(clawLabel)}...`).start();
|
|
20108
|
+
const agentId = agentName.toLowerCase().replace(/[\s_]+/g, "-");
|
|
20109
|
+
logger.info(`Install role resolved: asMain=${asMain}, claw=${selectedClawDir || targetDir}`);
|
|
20128
20110
|
let workspaceDir;
|
|
20129
20111
|
if (targetDir) {
|
|
20130
20112
|
workspaceDir = import_node_path12.default.resolve(targetDir);
|
|
@@ -20174,7 +20156,7 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir, asMain)
|
|
|
20174
20156
|
addAgentToOpenClawConfig(selectedClawDir, "main", agentName, true);
|
|
20175
20157
|
} else {
|
|
20176
20158
|
spinner.text = `Registering ${source_default.cyan(agentName)} as worker agent...`;
|
|
20177
|
-
const regResult = registerAgentToOpenClaw(agentId, workspaceDir
|
|
20159
|
+
const regResult = registerAgentToOpenClaw(agentId, workspaceDir);
|
|
20178
20160
|
if (!regResult.success) {
|
|
20179
20161
|
spinner.fail(`Failed to register ${agentId}: ${regResult.message}`);
|
|
20180
20162
|
return;
|
|
@@ -20195,8 +20177,7 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir, asMain)
|
|
|
20195
20177
|
const roleLabel = asMain ? "main agent" : "worker agent";
|
|
20196
20178
|
const typeLabel = asMain ? source_default.blue("Single Agent (Main)") : source_default.green("Single Agent (Worker)");
|
|
20197
20179
|
logger.info(`Single agent installed from dir as ${roleLabel}: ${agentName}`, { source: packageDir, workspace: workspaceDir });
|
|
20198
|
-
spinner.succeed(`${source_default.cyan.bold(agentName)} installed as ${roleLabel}
|
|
20199
|
-
console.log();
|
|
20180
|
+
spinner.succeed(`${source_default.cyan.bold(agentName)} installed as ${roleLabel} \u2192 ${source_default.dim(clawLabel)}`);
|
|
20200
20181
|
console.log(` ${source_default.dim("Location:")} ${workspaceDir}`);
|
|
20201
20182
|
console.log(` ${source_default.dim("Source:")} ${packageDir}`);
|
|
20202
20183
|
console.log(` ${source_default.dim("Type:")} ${typeLabel}`);
|
|
@@ -20702,13 +20683,13 @@ function formatInstallType(type2) {
|
|
|
20702
20683
|
|
|
20703
20684
|
// src/index.ts
|
|
20704
20685
|
var program2 = new Command();
|
|
20705
|
-
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.
|
|
20686
|
+
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.16").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
|
|
20706
20687
|
const opts = program2.opts();
|
|
20707
20688
|
const verbose = opts.verbose || process.env.SOULHUB_DEBUG === "1";
|
|
20708
20689
|
logger.init(verbose);
|
|
20709
20690
|
logger.info("CLI started", {
|
|
20710
20691
|
args: process.argv.slice(2),
|
|
20711
|
-
version: "1.0.
|
|
20692
|
+
version: "1.0.16",
|
|
20712
20693
|
node: process.version
|
|
20713
20694
|
});
|
|
20714
20695
|
});
|