soulhubcli 1.0.23 → 1.0.24
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 +7 -7
- package/dist/index.cjs +90 -306
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ npx soulhubcli <command>
|
|
|
42
42
|
| `soulhub info <name> --identity` | 显示 IDENTITY.md 内容 |
|
|
43
43
|
| `soulhub info <name> --soul` | 显示 SOUL.md 内容 |
|
|
44
44
|
| `soulhub info <name> --json` | 以 JSON 格式输出 Agent 详情 |
|
|
45
|
-
| `soulhub install <name>` | 从 Registry 安装 Agent 或团队(交互式:选择角色和目标
|
|
45
|
+
| `soulhub install <name>` | 从 Registry 安装 Agent 或团队(交互式:选择角色和目标 Claw) |
|
|
46
46
|
| `soulhub install <name> --role main` | 安装为主 Agent(跳过角色选择) |
|
|
47
47
|
| `soulhub install <name> --role worker` | 安装为 Worker Agent(跳过角色选择) |
|
|
48
48
|
| `soulhub install <name> --claw-type <type>` | 指定 claw 类型(跳过 claw 选择) |
|
|
@@ -92,7 +92,7 @@ soulhub search writer --json
|
|
|
92
92
|
|
|
93
93
|
CLI 会自动识别目标是单 Agent 还是多 Agent 团队,无需手动区分。
|
|
94
94
|
|
|
95
|
-
**默认行为:交互式安装。** CLI 会提示用户选择安装角色(主 Agent / Worker Agent)以及目标
|
|
95
|
+
**默认行为:交互式安装。** CLI 会提示用户选择安装角色(主 Agent / Worker Agent)以及目标 Claw 目录(单选)。通过命令行参数可跳过交互,实现完全非交互式安装。
|
|
96
96
|
|
|
97
97
|
**从 Registry 安装:**
|
|
98
98
|
|
|
@@ -215,8 +215,8 @@ soulhub rollback --id <record-id>
|
|
|
215
215
|
1. 展示 Agent 基本信息(名称、版本、描述、分类、标签)
|
|
216
216
|
2. 提示选择安装角色:**Main Agent** 或 **Worker Agent**
|
|
217
217
|
3. 安装为 Main Agent 时,警告将覆盖当前 workspace 内容(人格文件会被替换,记忆不受影响),需用户确认(或使用 `-y` 跳过)
|
|
218
|
-
4.
|
|
219
|
-
5.
|
|
218
|
+
4. 提示单选目标 Claw 目录(OpenClaw / LightClaw),一次只安装到一个 Claw
|
|
219
|
+
5. 执行安装、注册,并提示用户重启
|
|
220
220
|
|
|
221
221
|
### 单 Agent 安装
|
|
222
222
|
|
|
@@ -224,7 +224,7 @@ soulhub rollback --id <record-id>
|
|
|
224
224
|
- 安装为 **Main Agent** 时,部署到 `workspace/` 目录,会覆盖已有人格文件
|
|
225
225
|
- 安装前自动备份已有内容到 `~/.soulhub/backups/<claw>/`(按 claw 类型分目录存储)
|
|
226
226
|
- 仅覆盖 `IDENTITY.md`、`SOUL.md` 等灵魂文件,不影响 workspace 中的其他运行时文件
|
|
227
|
-
-
|
|
227
|
+
- 安装完成后提示用户重启 OpenClaw/LightClaw Gateway
|
|
228
228
|
|
|
229
229
|
### 多 Agent 团队安装
|
|
230
230
|
|
|
@@ -233,7 +233,7 @@ soulhub rollback --id <record-id>
|
|
|
233
233
|
- 安装前自动备份存量子 Agent(mv 方式移走已有 worker 目录)
|
|
234
234
|
- 自动配置多 Agent 之间的通信
|
|
235
235
|
- Worker Agent 自动注册到 claw 配置中
|
|
236
|
-
-
|
|
236
|
+
- 安装完成后提示用户重启 OpenClaw/LightClaw Gateway
|
|
237
237
|
|
|
238
238
|
### 备份与回滚
|
|
239
239
|
|
|
@@ -264,7 +264,7 @@ CLI 按以下优先级查找 claw 安装目录:
|
|
|
264
264
|
3. `OPENCLAW_HOME` / `LIGHTCLAW_HOME` 环境变量
|
|
265
265
|
4. 默认路径 `~/.openclaw`、`~/.lightclaw`
|
|
266
266
|
|
|
267
|
-
未指定 `--claw-type` 或 `--dir` 时,CLI 会检测所有可用的
|
|
267
|
+
未指定 `--claw-type` 或 `--dir` 时,CLI 会检测所有可用的 Claw 目录,多个时交互式单选(一次只安装到一个 Claw)。
|
|
268
268
|
|
|
269
269
|
## 环境要求
|
|
270
270
|
|
package/dist/index.cjs
CHANGED
|
@@ -13464,7 +13464,6 @@ var isDownKey = (key, keybindings = []) => (
|
|
|
13464
13464
|
keybindings.includes("vim") && key.name === "j" || // Emacs keybinding: Ctrl+N means "next" in Emacs navigation conventions
|
|
13465
13465
|
keybindings.includes("emacs") && key.ctrl && key.name === "n"
|
|
13466
13466
|
);
|
|
13467
|
-
var isSpaceKey = (key) => key.name === "space";
|
|
13468
13467
|
var isBackspaceKey = (key) => key.name === "backspace";
|
|
13469
13468
|
var isTabKey = (key) => key.name === "tab";
|
|
13470
13469
|
var isNumberKey = (key) => "1234567890".includes(key.name);
|
|
@@ -14941,196 +14940,6 @@ var Separator = class {
|
|
|
14941
14940
|
}
|
|
14942
14941
|
};
|
|
14943
14942
|
|
|
14944
|
-
// node_modules/@inquirer/checkbox/dist/index.js
|
|
14945
|
-
var import_node_util4 = require("util");
|
|
14946
|
-
var checkboxTheme = {
|
|
14947
|
-
icon: {
|
|
14948
|
-
checked: (0, import_node_util4.styleText)("green", dist_default.circleFilled),
|
|
14949
|
-
unchecked: dist_default.circle,
|
|
14950
|
-
cursor: dist_default.pointer,
|
|
14951
|
-
disabledChecked: (0, import_node_util4.styleText)("green", dist_default.circleDouble),
|
|
14952
|
-
disabledUnchecked: "-"
|
|
14953
|
-
},
|
|
14954
|
-
style: {
|
|
14955
|
-
disabled: (text) => (0, import_node_util4.styleText)("dim", text),
|
|
14956
|
-
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
14957
|
-
description: (text) => (0, import_node_util4.styleText)("cyan", text),
|
|
14958
|
-
keysHelpTip: (keys) => keys.map(([key, action]) => `${(0, import_node_util4.styleText)("bold", key)} ${(0, import_node_util4.styleText)("dim", action)}`).join((0, import_node_util4.styleText)("dim", " \u2022 "))
|
|
14959
|
-
},
|
|
14960
|
-
i18n: { disabledError: "This option is disabled and cannot be toggled." },
|
|
14961
|
-
keybindings: []
|
|
14962
|
-
};
|
|
14963
|
-
function isSelectable(item) {
|
|
14964
|
-
return !Separator.isSeparator(item) && !item.disabled;
|
|
14965
|
-
}
|
|
14966
|
-
function isNavigable(item) {
|
|
14967
|
-
return !Separator.isSeparator(item);
|
|
14968
|
-
}
|
|
14969
|
-
function isChecked(item) {
|
|
14970
|
-
return !Separator.isSeparator(item) && item.checked;
|
|
14971
|
-
}
|
|
14972
|
-
function toggle(item) {
|
|
14973
|
-
return isSelectable(item) ? { ...item, checked: !item.checked } : item;
|
|
14974
|
-
}
|
|
14975
|
-
function check(checked) {
|
|
14976
|
-
return function(item) {
|
|
14977
|
-
return isSelectable(item) ? { ...item, checked } : item;
|
|
14978
|
-
};
|
|
14979
|
-
}
|
|
14980
|
-
function normalizeChoices(choices) {
|
|
14981
|
-
return choices.map((choice) => {
|
|
14982
|
-
if (Separator.isSeparator(choice))
|
|
14983
|
-
return choice;
|
|
14984
|
-
if (typeof choice === "string") {
|
|
14985
|
-
return {
|
|
14986
|
-
value: choice,
|
|
14987
|
-
name: choice,
|
|
14988
|
-
short: choice,
|
|
14989
|
-
checkedName: choice,
|
|
14990
|
-
disabled: false,
|
|
14991
|
-
checked: false
|
|
14992
|
-
};
|
|
14993
|
-
}
|
|
14994
|
-
const name = choice.name ?? String(choice.value);
|
|
14995
|
-
const normalizedChoice = {
|
|
14996
|
-
value: choice.value,
|
|
14997
|
-
name,
|
|
14998
|
-
short: choice.short ?? name,
|
|
14999
|
-
checkedName: choice.checkedName ?? name,
|
|
15000
|
-
disabled: choice.disabled ?? false,
|
|
15001
|
-
checked: choice.checked ?? false
|
|
15002
|
-
};
|
|
15003
|
-
if (choice.description) {
|
|
15004
|
-
normalizedChoice.description = choice.description;
|
|
15005
|
-
}
|
|
15006
|
-
return normalizedChoice;
|
|
15007
|
-
});
|
|
15008
|
-
}
|
|
15009
|
-
var dist_default4 = createPrompt((config, done) => {
|
|
15010
|
-
const { pageSize = 7, loop = true, required, validate = () => true } = config;
|
|
15011
|
-
const shortcuts = { all: "a", invert: "i", ...config.shortcuts };
|
|
15012
|
-
const theme = makeTheme(checkboxTheme, config.theme);
|
|
15013
|
-
const { keybindings } = theme;
|
|
15014
|
-
const [status, setStatus] = useState("idle");
|
|
15015
|
-
const prefix = usePrefix({ status, theme });
|
|
15016
|
-
const [items, setItems] = useState(normalizeChoices(config.choices));
|
|
15017
|
-
const bounds = useMemo(() => {
|
|
15018
|
-
const first = items.findIndex(isNavigable);
|
|
15019
|
-
const last = items.findLastIndex(isNavigable);
|
|
15020
|
-
if (first === -1) {
|
|
15021
|
-
throw new ValidationError("[checkbox prompt] No selectable choices. All choices are disabled.");
|
|
15022
|
-
}
|
|
15023
|
-
return { first, last };
|
|
15024
|
-
}, [items]);
|
|
15025
|
-
const [active, setActive] = useState(bounds.first);
|
|
15026
|
-
const [errorMsg, setError] = useState();
|
|
15027
|
-
useKeypress(async (key) => {
|
|
15028
|
-
if (isEnterKey(key)) {
|
|
15029
|
-
const selection = items.filter(isChecked);
|
|
15030
|
-
const isValid = await validate([...selection]);
|
|
15031
|
-
if (required && !selection.length) {
|
|
15032
|
-
setError("At least one choice must be selected");
|
|
15033
|
-
} else if (isValid === true) {
|
|
15034
|
-
setStatus("done");
|
|
15035
|
-
done(selection.map((choice) => choice.value));
|
|
15036
|
-
} else {
|
|
15037
|
-
setError(isValid || "You must select a valid value");
|
|
15038
|
-
}
|
|
15039
|
-
} else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
|
|
15040
|
-
if (errorMsg) {
|
|
15041
|
-
setError(void 0);
|
|
15042
|
-
}
|
|
15043
|
-
if (loop || isUpKey(key, keybindings) && active !== bounds.first || isDownKey(key, keybindings) && active !== bounds.last) {
|
|
15044
|
-
const offset = isUpKey(key, keybindings) ? -1 : 1;
|
|
15045
|
-
let next = active;
|
|
15046
|
-
do {
|
|
15047
|
-
next = (next + offset + items.length) % items.length;
|
|
15048
|
-
} while (!isNavigable(items[next]));
|
|
15049
|
-
setActive(next);
|
|
15050
|
-
}
|
|
15051
|
-
} else if (isSpaceKey(key)) {
|
|
15052
|
-
const activeItem = items[active];
|
|
15053
|
-
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
15054
|
-
if (activeItem.disabled) {
|
|
15055
|
-
setError(theme.i18n.disabledError);
|
|
15056
|
-
} else {
|
|
15057
|
-
setError(void 0);
|
|
15058
|
-
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
15059
|
-
}
|
|
15060
|
-
}
|
|
15061
|
-
} else if (key.name === shortcuts.all) {
|
|
15062
|
-
const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
15063
|
-
setItems(items.map(check(selectAll)));
|
|
15064
|
-
} else if (key.name === shortcuts.invert) {
|
|
15065
|
-
setItems(items.map(toggle));
|
|
15066
|
-
} else if (isNumberKey(key)) {
|
|
15067
|
-
const selectedIndex = Number(key.name) - 1;
|
|
15068
|
-
let selectableIndex = -1;
|
|
15069
|
-
const position = items.findIndex((item) => {
|
|
15070
|
-
if (Separator.isSeparator(item))
|
|
15071
|
-
return false;
|
|
15072
|
-
selectableIndex++;
|
|
15073
|
-
return selectableIndex === selectedIndex;
|
|
15074
|
-
});
|
|
15075
|
-
const selectedItem = items[position];
|
|
15076
|
-
if (selectedItem && isSelectable(selectedItem)) {
|
|
15077
|
-
setActive(position);
|
|
15078
|
-
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
15079
|
-
}
|
|
15080
|
-
}
|
|
15081
|
-
});
|
|
15082
|
-
const message = theme.style.message(config.message, status);
|
|
15083
|
-
let description;
|
|
15084
|
-
const page = usePagination({
|
|
15085
|
-
items,
|
|
15086
|
-
active,
|
|
15087
|
-
renderItem({ item, isActive }) {
|
|
15088
|
-
if (Separator.isSeparator(item)) {
|
|
15089
|
-
return ` ${item.separator}`;
|
|
15090
|
-
}
|
|
15091
|
-
const cursor = isActive ? theme.icon.cursor : " ";
|
|
15092
|
-
if (item.disabled) {
|
|
15093
|
-
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
15094
|
-
const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
15095
|
-
return theme.style.disabled(`${cursor}${checkbox2} ${item.name} ${disabledLabel}`);
|
|
15096
|
-
}
|
|
15097
|
-
if (isActive) {
|
|
15098
|
-
description = item.description;
|
|
15099
|
-
}
|
|
15100
|
-
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
15101
|
-
const name = item.checked ? item.checkedName : item.name;
|
|
15102
|
-
const color = isActive ? theme.style.highlight : (x) => x;
|
|
15103
|
-
return color(`${cursor}${checkbox} ${name}`);
|
|
15104
|
-
},
|
|
15105
|
-
pageSize,
|
|
15106
|
-
loop
|
|
15107
|
-
});
|
|
15108
|
-
if (status === "done") {
|
|
15109
|
-
const selection = items.filter(isChecked);
|
|
15110
|
-
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
15111
|
-
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
15112
|
-
}
|
|
15113
|
-
const keys = [
|
|
15114
|
-
["\u2191\u2193", "navigate"],
|
|
15115
|
-
["space", "select"]
|
|
15116
|
-
];
|
|
15117
|
-
if (shortcuts.all)
|
|
15118
|
-
keys.push([shortcuts.all, "all"]);
|
|
15119
|
-
if (shortcuts.invert)
|
|
15120
|
-
keys.push([shortcuts.invert, "invert"]);
|
|
15121
|
-
keys.push(["\u23CE", "submit"]);
|
|
15122
|
-
const helpLine = theme.style.keysHelpTip(keys);
|
|
15123
|
-
const lines = [
|
|
15124
|
-
[prefix, message].filter(Boolean).join(" "),
|
|
15125
|
-
page,
|
|
15126
|
-
" ",
|
|
15127
|
-
description ? theme.style.description(description) : "",
|
|
15128
|
-
errorMsg ? theme.style.error(errorMsg) : "",
|
|
15129
|
-
helpLine
|
|
15130
|
-
].filter(Boolean).join("\n").trimEnd();
|
|
15131
|
-
return `${lines}${cursorHide}`;
|
|
15132
|
-
});
|
|
15133
|
-
|
|
15134
14943
|
// node_modules/@inquirer/confirm/dist/index.js
|
|
15135
14944
|
function getBooleanValue(value, defaultValue) {
|
|
15136
14945
|
let answer = defaultValue !== false;
|
|
@@ -15143,7 +14952,7 @@ function getBooleanValue(value, defaultValue) {
|
|
|
15143
14952
|
function boolToString(value) {
|
|
15144
14953
|
return value ? "Yes" : "No";
|
|
15145
14954
|
}
|
|
15146
|
-
var
|
|
14955
|
+
var dist_default4 = createPrompt((config, done) => {
|
|
15147
14956
|
const { transformer = boolToString } = config;
|
|
15148
14957
|
const [status, setStatus] = useState("idle");
|
|
15149
14958
|
const [value, setValue] = useState("");
|
|
@@ -15178,25 +14987,25 @@ var dist_default5 = createPrompt((config, done) => {
|
|
|
15178
14987
|
});
|
|
15179
14988
|
|
|
15180
14989
|
// node_modules/@inquirer/select/dist/index.js
|
|
15181
|
-
var
|
|
14990
|
+
var import_node_util4 = require("util");
|
|
15182
14991
|
var selectTheme = {
|
|
15183
14992
|
icon: { cursor: dist_default.pointer },
|
|
15184
14993
|
style: {
|
|
15185
|
-
disabled: (text) => (0,
|
|
15186
|
-
description: (text) => (0,
|
|
15187
|
-
keysHelpTip: (keys) => keys.map(([key, action]) => `${(0,
|
|
14994
|
+
disabled: (text) => (0, import_node_util4.styleText)("dim", text),
|
|
14995
|
+
description: (text) => (0, import_node_util4.styleText)("cyan", text),
|
|
14996
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${(0, import_node_util4.styleText)("bold", key)} ${(0, import_node_util4.styleText)("dim", action)}`).join((0, import_node_util4.styleText)("dim", " \u2022 "))
|
|
15188
14997
|
},
|
|
15189
14998
|
i18n: { disabledError: "This option is disabled and cannot be selected." },
|
|
15190
14999
|
indexMode: "hidden",
|
|
15191
15000
|
keybindings: []
|
|
15192
15001
|
};
|
|
15193
|
-
function
|
|
15002
|
+
function isSelectable(item) {
|
|
15194
15003
|
return !Separator.isSeparator(item) && !item.disabled;
|
|
15195
15004
|
}
|
|
15196
|
-
function
|
|
15005
|
+
function isNavigable(item) {
|
|
15197
15006
|
return !Separator.isSeparator(item);
|
|
15198
15007
|
}
|
|
15199
|
-
function
|
|
15008
|
+
function normalizeChoices(choices) {
|
|
15200
15009
|
return choices.map((choice) => {
|
|
15201
15010
|
if (Separator.isSeparator(choice))
|
|
15202
15011
|
return choice;
|
|
@@ -15222,7 +15031,7 @@ function normalizeChoices2(choices) {
|
|
|
15222
15031
|
return normalizedChoice;
|
|
15223
15032
|
});
|
|
15224
15033
|
}
|
|
15225
|
-
var
|
|
15034
|
+
var dist_default5 = createPrompt((config, done) => {
|
|
15226
15035
|
const { loop = true, pageSize = 7 } = config;
|
|
15227
15036
|
const theme = makeTheme(selectTheme, config.theme);
|
|
15228
15037
|
const { keybindings } = theme;
|
|
@@ -15230,10 +15039,10 @@ var dist_default6 = createPrompt((config, done) => {
|
|
|
15230
15039
|
const prefix = usePrefix({ status, theme });
|
|
15231
15040
|
const searchTimeoutRef = useRef();
|
|
15232
15041
|
const searchEnabled = !keybindings.includes("vim");
|
|
15233
|
-
const items = useMemo(() =>
|
|
15042
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
15234
15043
|
const bounds = useMemo(() => {
|
|
15235
|
-
const first = items.findIndex(
|
|
15236
|
-
const last = items.findLastIndex(
|
|
15044
|
+
const first = items.findIndex(isNavigable);
|
|
15045
|
+
const last = items.findLastIndex(isNavigable);
|
|
15237
15046
|
if (first === -1) {
|
|
15238
15047
|
throw new ValidationError("[select prompt] No selectable choices. All choices are disabled.");
|
|
15239
15048
|
}
|
|
@@ -15242,7 +15051,7 @@ var dist_default6 = createPrompt((config, done) => {
|
|
|
15242
15051
|
const defaultItemIndex = useMemo(() => {
|
|
15243
15052
|
if (!("default" in config))
|
|
15244
15053
|
return -1;
|
|
15245
|
-
return items.findIndex((item) =>
|
|
15054
|
+
return items.findIndex((item) => isSelectable(item) && item.value === config.default);
|
|
15246
15055
|
}, [config.default, items]);
|
|
15247
15056
|
const [active, setActive] = useState(defaultItemIndex === -1 ? bounds.first : defaultItemIndex);
|
|
15248
15057
|
const selectedChoice = items[active];
|
|
@@ -15266,7 +15075,7 @@ var dist_default6 = createPrompt((config, done) => {
|
|
|
15266
15075
|
let next = active;
|
|
15267
15076
|
do {
|
|
15268
15077
|
next = (next + offset + items.length) % items.length;
|
|
15269
|
-
} while (!
|
|
15078
|
+
} while (!isNavigable(items[next]));
|
|
15270
15079
|
setActive(next);
|
|
15271
15080
|
}
|
|
15272
15081
|
} else if (isNumberKey(key) && !Number.isNaN(Number(rl.line))) {
|
|
@@ -15279,7 +15088,7 @@ var dist_default6 = createPrompt((config, done) => {
|
|
|
15279
15088
|
return selectableIndex === selectedIndex;
|
|
15280
15089
|
});
|
|
15281
15090
|
const item = items[position];
|
|
15282
|
-
if (item != null &&
|
|
15091
|
+
if (item != null && isSelectable(item)) {
|
|
15283
15092
|
setActive(position);
|
|
15284
15093
|
}
|
|
15285
15094
|
searchTimeoutRef.current = setTimeout(() => {
|
|
@@ -15290,7 +15099,7 @@ var dist_default6 = createPrompt((config, done) => {
|
|
|
15290
15099
|
} else if (searchEnabled) {
|
|
15291
15100
|
const searchTerm = rl.line.toLowerCase();
|
|
15292
15101
|
const matchIndex = items.findIndex((item) => {
|
|
15293
|
-
if (Separator.isSeparator(item) || !
|
|
15102
|
+
if (Separator.isSeparator(item) || !isSelectable(item))
|
|
15294
15103
|
return false;
|
|
15295
15104
|
return item.name.toLowerCase().startsWith(searchTerm);
|
|
15296
15105
|
});
|
|
@@ -21157,7 +20966,7 @@ async function promptSelectClawDir(customDir) {
|
|
|
21157
20966
|
return dirs[0];
|
|
21158
20967
|
}
|
|
21159
20968
|
try {
|
|
21160
|
-
const selected = await
|
|
20969
|
+
const selected = await dist_default5({
|
|
21161
20970
|
message: "Select target Claw installation:",
|
|
21162
20971
|
choices: dirs.map((dir) => {
|
|
21163
20972
|
const brand = detectClawBrand(dir);
|
|
@@ -21487,7 +21296,7 @@ function commitBackupRecord(record) {
|
|
|
21487
21296
|
}
|
|
21488
21297
|
async function promptSelectRole() {
|
|
21489
21298
|
try {
|
|
21490
|
-
const selected = await
|
|
21299
|
+
const selected = await dist_default5({
|
|
21491
21300
|
message: "Install as:",
|
|
21492
21301
|
choices: [
|
|
21493
21302
|
{ name: "\u{1F477} Worker agent (\u5B50Agent\uFF0C\u5B89\u88C5\u5230 workspace-<name>/ \u76EE\u5F55)", value: "worker" },
|
|
@@ -21512,24 +21321,21 @@ async function promptMultiSelectClawDirs() {
|
|
|
21512
21321
|
return dirs;
|
|
21513
21322
|
}
|
|
21514
21323
|
try {
|
|
21515
|
-
const selected = await
|
|
21516
|
-
message: "Select target Claw
|
|
21324
|
+
const selected = await dist_default5({
|
|
21325
|
+
message: "Select target Claw installation:",
|
|
21517
21326
|
choices: dirs.map((dir) => {
|
|
21518
21327
|
const brand = detectClawBrand(dir);
|
|
21519
|
-
return { name: `${brand} ${dir}`, value: dir
|
|
21328
|
+
return { name: `${brand} ${dir}`, value: dir };
|
|
21520
21329
|
})
|
|
21521
21330
|
});
|
|
21522
|
-
|
|
21523
|
-
console.log(" No claw selected, operation cancelled.");
|
|
21524
|
-
}
|
|
21525
|
-
return selected;
|
|
21331
|
+
return [selected];
|
|
21526
21332
|
} catch {
|
|
21527
21333
|
return [];
|
|
21528
21334
|
}
|
|
21529
21335
|
}
|
|
21530
21336
|
async function promptConfirm(message, defaultYes = true) {
|
|
21531
21337
|
try {
|
|
21532
|
-
return await
|
|
21338
|
+
return await dist_default4({
|
|
21533
21339
|
message,
|
|
21534
21340
|
default: defaultYes
|
|
21535
21341
|
});
|
|
@@ -21619,28 +21425,6 @@ function detectClawCommand(clawDir) {
|
|
|
21619
21425
|
}
|
|
21620
21426
|
return "openclaw";
|
|
21621
21427
|
}
|
|
21622
|
-
function restartOpenClawGateway(clawDir) {
|
|
21623
|
-
const clawCmd = detectClawCommand(clawDir);
|
|
21624
|
-
logger.debug(`Restarting ${clawCmd} Gateway`);
|
|
21625
|
-
try {
|
|
21626
|
-
(0, import_node_child_process.execSync)(`${clawCmd} gateway restart`, {
|
|
21627
|
-
stdio: "pipe",
|
|
21628
|
-
timeout: 3e4
|
|
21629
|
-
// 30 秒超时
|
|
21630
|
-
});
|
|
21631
|
-
return {
|
|
21632
|
-
success: true,
|
|
21633
|
-
message: `${clawCmd} Gateway restarted successfully.`
|
|
21634
|
-
};
|
|
21635
|
-
} catch (error) {
|
|
21636
|
-
const stderr = error && typeof error === "object" && "stderr" in error ? String(error.stderr).trim() : "";
|
|
21637
|
-
const errMsg = stderr || (error instanceof Error ? error.message : String(error));
|
|
21638
|
-
return {
|
|
21639
|
-
success: false,
|
|
21640
|
-
message: errMsg
|
|
21641
|
-
};
|
|
21642
|
-
}
|
|
21643
|
-
}
|
|
21644
21428
|
|
|
21645
21429
|
// src/commands/search.ts
|
|
21646
21430
|
var searchCommand = new Command("search").description("Search for agents in the SoulHub registry").argument("[query]", "Search query (matches name, description, tags)").option("-c, --category <category>", "Filter by category").option("-n, --limit <number>", "Max results to show", "20").option("--json", "Output results in JSON format").action(async (query, options) => {
|
|
@@ -21913,7 +21697,8 @@ function resolveAllClawDirs(clawDir) {
|
|
|
21913
21697
|
const resolved = findOpenClawDir(clawDir);
|
|
21914
21698
|
return resolved ? [resolved] : [];
|
|
21915
21699
|
}
|
|
21916
|
-
|
|
21700
|
+
const all = findAllClawDirs();
|
|
21701
|
+
return all.length > 0 ? [all[0]] : [];
|
|
21917
21702
|
}
|
|
21918
21703
|
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("-r, --role <role>", "Install role: main or worker (skip role selection prompt)").option(
|
|
21919
21704
|
"--dir <path>",
|
|
@@ -22058,14 +21843,13 @@ async function installSingleAgent(name, targetDir, clawDir, asMain = false, preR
|
|
|
22058
21843
|
spinner.text = `Downloading ${source_default.cyan(agent.displayName)} package...`;
|
|
22059
21844
|
const pkgDir = await downloadAgentPackage(name, agent.version);
|
|
22060
21845
|
spinner.succeed(`Package ${source_default.cyan(agent.displayName)} downloaded.`);
|
|
22061
|
-
const
|
|
22062
|
-
|
|
22063
|
-
if (showClawHeader) {
|
|
22064
|
-
const brand = detectClawBrand(selectedClawDir);
|
|
22065
|
-
console.log();
|
|
22066
|
-
console.log(source_default.bold(`\u2500\u2500 ${brand} (${selectedClawDir}) \u2500\u2500`));
|
|
22067
|
-
}
|
|
21846
|
+
const selectedClawDir = allClawDirs[0];
|
|
21847
|
+
try {
|
|
22068
21848
|
await installSingleAgentToClaw(name, selectedClawDir, void 0, asMain, pkgDir, agent);
|
|
21849
|
+
} catch (err) {
|
|
21850
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
21851
|
+
logger.error(`Failed to install to ${selectedClawDir}`, { error: errMsg });
|
|
21852
|
+
console.error(source_default.red(` \u2717 Installation failed for ${selectedClawDir}: ${errMsg}`));
|
|
22069
21853
|
}
|
|
22070
21854
|
import_node_fs9.default.rmSync(pkgDir, { recursive: true, force: true });
|
|
22071
21855
|
}
|
|
@@ -22234,23 +22018,29 @@ async function installRecipeFromRegistry(name, recipe, targetDir, clawDir) {
|
|
|
22234
22018
|
spinner.text = `Installing worker ${source_default.cyan(worker.name)}...`;
|
|
22235
22019
|
const agentName = worker.dir || worker.name;
|
|
22236
22020
|
const agentId = worker.name;
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22021
|
+
try {
|
|
22022
|
+
const workerDir = targetDir ? import_node_path12.default.join(resolvedClawDir, `workspace-${agentId}`) : getWorkspaceDir(resolvedClawDir, agentId);
|
|
22023
|
+
if (!targetDir) {
|
|
22024
|
+
const regResult = registerAgentToOpenClaw(agentId, workerDir, resolvedClawDir);
|
|
22025
|
+
if (!regResult.success) {
|
|
22026
|
+
console.log(source_default.yellow(` \u26A0 Failed to register ${agentId}: ${regResult.message}`));
|
|
22027
|
+
continue;
|
|
22028
|
+
}
|
|
22029
|
+
} else {
|
|
22030
|
+
import_node_fs9.default.mkdirSync(workerDir, { recursive: true });
|
|
22031
|
+
}
|
|
22032
|
+
const agentInfo = index.agents.find((a) => a.name === agentName);
|
|
22033
|
+
const agentVersion = agentInfo?.version || "latest";
|
|
22034
|
+
const pkgDir = await downloadAgentPackage(agentName, agentVersion);
|
|
22035
|
+
copyAgentFilesFromPackage(pkgDir, workerDir);
|
|
22036
|
+
import_node_fs9.default.rmSync(pkgDir, { recursive: true, force: true });
|
|
22037
|
+
recordInstall(agentId, recipe.version || "1.0.0", workerDir);
|
|
22038
|
+
workerIds.push(agentId);
|
|
22039
|
+
} catch (err) {
|
|
22040
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
22041
|
+
logger.error(`Failed to install worker ${agentId}`, { error: errMsg });
|
|
22042
|
+
console.log(source_default.red(` \u2717 Failed to install worker ${agentId}: ${errMsg}`));
|
|
22246
22043
|
}
|
|
22247
|
-
const agentInfo = index.agents.find((a) => a.name === agentName);
|
|
22248
|
-
const agentVersion = agentInfo?.version || "latest";
|
|
22249
|
-
const pkgDir = await downloadAgentPackage(agentName, agentVersion);
|
|
22250
|
-
copyAgentFilesFromPackage(pkgDir, workerDir);
|
|
22251
|
-
import_node_fs9.default.rmSync(pkgDir, { recursive: true, force: true });
|
|
22252
|
-
recordInstall(agentId, recipe.version || "1.0.0", workerDir);
|
|
22253
|
-
workerIds.push(agentId);
|
|
22254
22044
|
}
|
|
22255
22045
|
if (!targetDir) {
|
|
22256
22046
|
spinner.text = "Configuring multi-agent communication...";
|
|
@@ -22367,14 +22157,13 @@ async function installSingleAgentFromDir(packageDir, targetDir, clawDir, asMain
|
|
|
22367
22157
|
printOpenClawInstallHelp();
|
|
22368
22158
|
return;
|
|
22369
22159
|
}
|
|
22370
|
-
const
|
|
22371
|
-
|
|
22372
|
-
if (showClawHeader) {
|
|
22373
|
-
const brand = detectClawBrand(selectedClawDir);
|
|
22374
|
-
console.log();
|
|
22375
|
-
console.log(source_default.bold(`\u2500\u2500 ${brand} (${selectedClawDir}) \u2500\u2500`));
|
|
22376
|
-
}
|
|
22160
|
+
const selectedClawDir = allClawDirs[0];
|
|
22161
|
+
try {
|
|
22377
22162
|
await installSingleAgentFromDirToClaw(packageDir, agentName, pkg, selectedClawDir, void 0, asMain);
|
|
22163
|
+
} catch (err) {
|
|
22164
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
22165
|
+
logger.error(`Failed to install to ${selectedClawDir}`, { error: errMsg });
|
|
22166
|
+
console.error(source_default.red(` \u2717 Installation failed for ${selectedClawDir}: ${errMsg}`));
|
|
22378
22167
|
}
|
|
22379
22168
|
}
|
|
22380
22169
|
async function installSingleAgentFromDirToClaw(packageDir, agentName, pkg, selectedClawDir, targetDir, asMain = false) {
|
|
@@ -22542,22 +22331,28 @@ async function installTeamFromDir(packageDir, targetDir, clawDir) {
|
|
|
22542
22331
|
const agentId = worker.name;
|
|
22543
22332
|
const agentDir = worker.dir || worker.name;
|
|
22544
22333
|
spinner.text = `Installing worker ${source_default.cyan(agentId)}...`;
|
|
22545
|
-
|
|
22546
|
-
|
|
22547
|
-
|
|
22548
|
-
|
|
22549
|
-
|
|
22550
|
-
|
|
22334
|
+
try {
|
|
22335
|
+
const workerWorkspace = targetDir ? import_node_path12.default.join(resolvedClawDir, `workspace-${agentId}`) : getWorkspaceDir(resolvedClawDir, agentId);
|
|
22336
|
+
if (!targetDir) {
|
|
22337
|
+
const regResult = registerAgentToOpenClaw(agentId, workerWorkspace, resolvedClawDir);
|
|
22338
|
+
if (!regResult.success) {
|
|
22339
|
+
console.log(source_default.yellow(` \u26A0 Failed to register ${agentId}: ${regResult.message}`));
|
|
22340
|
+
continue;
|
|
22341
|
+
}
|
|
22342
|
+
} else {
|
|
22343
|
+
import_node_fs9.default.mkdirSync(workerWorkspace, { recursive: true });
|
|
22551
22344
|
}
|
|
22552
|
-
|
|
22553
|
-
import_node_fs9.default.
|
|
22554
|
-
|
|
22555
|
-
|
|
22556
|
-
|
|
22557
|
-
|
|
22345
|
+
const workerSourceDir = import_node_path12.default.join(packageDir, agentDir);
|
|
22346
|
+
if (import_node_fs9.default.existsSync(workerSourceDir)) {
|
|
22347
|
+
copyAgentFilesFromDir(workerSourceDir, workerWorkspace);
|
|
22348
|
+
}
|
|
22349
|
+
recordInstall(agentId, pkg.version || "local", workerWorkspace);
|
|
22350
|
+
workerIds.push(agentId);
|
|
22351
|
+
} catch (err) {
|
|
22352
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
22353
|
+
logger.error(`Failed to install worker ${agentId}`, { error: errMsg });
|
|
22354
|
+
console.log(source_default.red(` \u2717 Failed to install worker ${agentId}: ${errMsg}`));
|
|
22558
22355
|
}
|
|
22559
|
-
recordInstall(agentId, pkg.version || "local", workerWorkspace);
|
|
22560
|
-
workerIds.push(agentId);
|
|
22561
22356
|
}
|
|
22562
22357
|
if (!targetDir && workerIds.length > 0) {
|
|
22563
22358
|
spinner.text = "Configuring multi-agent communication...";
|
|
@@ -22665,13 +22460,9 @@ function printTeamSummary(pkg, workerIds) {
|
|
|
22665
22460
|
async function tryRestartGateway(clawDir) {
|
|
22666
22461
|
const clawCmd = detectClawCommand(clawDir);
|
|
22667
22462
|
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
22668
|
-
|
|
22669
|
-
|
|
22670
|
-
|
|
22671
|
-
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
22672
|
-
} else {
|
|
22673
|
-
restartSpinner.warn(`Failed to restart ${brandName} Gateway. Please restart it manually.`);
|
|
22674
|
-
}
|
|
22463
|
+
console.log();
|
|
22464
|
+
console.log(source_default.yellow(` \u26A0 Please restart ${brandName} Gateway to apply changes:`));
|
|
22465
|
+
console.log(source_default.cyan(` ${clawCmd} gateway restart`));
|
|
22675
22466
|
}
|
|
22676
22467
|
|
|
22677
22468
|
// src/commands/list.ts
|
|
@@ -22956,7 +22747,7 @@ async function interactiveRollback(clawDir) {
|
|
|
22956
22747
|
console.log();
|
|
22957
22748
|
let selected;
|
|
22958
22749
|
try {
|
|
22959
|
-
selected = await
|
|
22750
|
+
selected = await dist_default5({
|
|
22960
22751
|
message: "Select a record to rollback:",
|
|
22961
22752
|
choices: manifest.records.map((record, index) => {
|
|
22962
22753
|
const date = new Date(record.createdAt).toLocaleString();
|
|
@@ -23003,7 +22794,7 @@ async function performRollbackByIndex(n, clawDir, skipConfirm = false) {
|
|
|
23003
22794
|
if (!skipConfirm) {
|
|
23004
22795
|
let confirmed;
|
|
23005
22796
|
try {
|
|
23006
|
-
confirmed = await
|
|
22797
|
+
confirmed = await dist_default4({
|
|
23007
22798
|
message: `${source_default.yellow("\u26A0")} Proceed with rollback?`,
|
|
23008
22799
|
default: true
|
|
23009
22800
|
});
|
|
@@ -23073,7 +22864,7 @@ function printRollbackDetails(record) {
|
|
|
23073
22864
|
}
|
|
23074
22865
|
async function promptConfirmRollback() {
|
|
23075
22866
|
try {
|
|
23076
|
-
return await
|
|
22867
|
+
return await dist_default4({
|
|
23077
22868
|
message: `${source_default.yellow("\u26A0")} Proceed with rollback?`,
|
|
23078
22869
|
default: true
|
|
23079
22870
|
});
|
|
@@ -23170,16 +22961,9 @@ async function executeRollback(record, clawDir) {
|
|
|
23170
22961
|
);
|
|
23171
22962
|
const clawCmd = detectClawCommand(resolvedClawDir);
|
|
23172
22963
|
const brandName = clawCmd === "lightclaw" ? "LightClaw" : "OpenClaw";
|
|
23173
|
-
|
|
23174
|
-
|
|
23175
|
-
|
|
23176
|
-
restartSpinner.succeed(`${brandName} Gateway restarted successfully.`);
|
|
23177
|
-
} else {
|
|
23178
|
-
restartSpinner.warn(`Failed to restart ${brandName} Gateway.`);
|
|
23179
|
-
console.log(source_default.yellow(` Reason: ${result.message}`));
|
|
23180
|
-
console.log(source_default.dim(" Please restart manually:"));
|
|
23181
|
-
console.log(source_default.dim(` ${clawCmd} gateway restart`));
|
|
23182
|
-
}
|
|
22964
|
+
console.log();
|
|
22965
|
+
console.log(source_default.yellow(` \u26A0 Please restart ${brandName} Gateway to apply changes:`));
|
|
22966
|
+
console.log(source_default.cyan(` ${clawCmd} gateway restart`));
|
|
23183
22967
|
console.log();
|
|
23184
22968
|
}
|
|
23185
22969
|
function formatInstallType(type2) {
|
|
@@ -23206,13 +22990,13 @@ function detectClawBrandFromDir(clawDir) {
|
|
|
23206
22990
|
|
|
23207
22991
|
// src/index.ts
|
|
23208
22992
|
var program2 = new Command();
|
|
23209
|
-
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.
|
|
22993
|
+
program2.name("soulhub").description("SoulHub CLI - Discover, install and manage AI agent souls").version("1.0.24").option("--verbose", "Enable verbose debug logging").hook("preAction", () => {
|
|
23210
22994
|
const opts = program2.opts();
|
|
23211
22995
|
const verbose = opts.verbose || process.env.SOULHUB_DEBUG === "1";
|
|
23212
22996
|
logger.init(verbose);
|
|
23213
22997
|
logger.info("CLI started", {
|
|
23214
22998
|
args: process.argv.slice(2),
|
|
23215
|
-
version: "1.0.
|
|
22999
|
+
version: "1.0.24",
|
|
23216
23000
|
node: process.version
|
|
23217
23001
|
});
|
|
23218
23002
|
});
|