claw-control-center 0.1.11 → 0.1.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 +91 -118
- package/dist/install-qclaw.cjs +91 -118
- package/dist/install-qclaw.d.cts +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -16403,7 +16403,7 @@ var isDownKey = (key, keybindings2 = []) => (
|
|
|
16403
16403
|
keybindings2.includes("vim") && key.name === "j" || // Emacs keybinding: Ctrl+N means "next" in Emacs navigation conventions
|
|
16404
16404
|
keybindings2.includes("emacs") && key.ctrl && key.name === "n"
|
|
16405
16405
|
);
|
|
16406
|
-
var
|
|
16406
|
+
var isBackspaceKey = (key) => key.name === "backspace";
|
|
16407
16407
|
var isNumberKey = (key) => "1234567890".includes(key.name);
|
|
16408
16408
|
var isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
16409
16409
|
|
|
@@ -17906,23 +17906,17 @@ var Separator = class {
|
|
|
17906
17906
|
}
|
|
17907
17907
|
};
|
|
17908
17908
|
|
|
17909
|
-
// ../node_modules/.pnpm/@inquirer+
|
|
17909
|
+
// ../node_modules/.pnpm/@inquirer+select@5.2.1_@types+node@24.12.4/node_modules/@inquirer/select/dist/index.js
|
|
17910
17910
|
var import_node_util4 = require("util");
|
|
17911
|
-
var
|
|
17912
|
-
icon: {
|
|
17913
|
-
checked: (0, import_node_util4.styleText)("green", dist_default.circleFilled),
|
|
17914
|
-
unchecked: dist_default.circle,
|
|
17915
|
-
cursor: dist_default.pointer,
|
|
17916
|
-
disabledChecked: (0, import_node_util4.styleText)("green", dist_default.circleDouble),
|
|
17917
|
-
disabledUnchecked: "-"
|
|
17918
|
-
},
|
|
17911
|
+
var selectTheme = {
|
|
17912
|
+
icon: { cursor: dist_default.pointer },
|
|
17919
17913
|
style: {
|
|
17920
17914
|
disabled: (text) => (0, import_node_util4.styleText)("dim", text),
|
|
17921
|
-
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
17922
17915
|
description: (text) => (0, import_node_util4.styleText)("cyan", text),
|
|
17923
17916
|
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 "))
|
|
17924
17917
|
},
|
|
17925
|
-
i18n: { disabledError: "This option is disabled and cannot be
|
|
17918
|
+
i18n: { disabledError: "This option is disabled and cannot be selected." },
|
|
17919
|
+
indexMode: "hidden"
|
|
17926
17920
|
};
|
|
17927
17921
|
function isSelectable(item) {
|
|
17928
17922
|
return !Separator.isSeparator(item) && !item.disabled;
|
|
@@ -17930,17 +17924,6 @@ function isSelectable(item) {
|
|
|
17930
17924
|
function isNavigable(item) {
|
|
17931
17925
|
return !Separator.isSeparator(item);
|
|
17932
17926
|
}
|
|
17933
|
-
function isChecked(item) {
|
|
17934
|
-
return !Separator.isSeparator(item) && item.checked;
|
|
17935
|
-
}
|
|
17936
|
-
function toggle(item) {
|
|
17937
|
-
return isSelectable(item) ? { ...item, checked: !item.checked } : item;
|
|
17938
|
-
}
|
|
17939
|
-
function check(checked) {
|
|
17940
|
-
return function(item) {
|
|
17941
|
-
return isSelectable(item) ? { ...item, checked } : item;
|
|
17942
|
-
};
|
|
17943
|
-
}
|
|
17944
17927
|
function normalizeChoices(choices) {
|
|
17945
17928
|
return choices.map((choice) => {
|
|
17946
17929
|
if (Separator.isSeparator(choice))
|
|
@@ -17951,9 +17934,7 @@ function normalizeChoices(choices) {
|
|
|
17951
17934
|
value: choice,
|
|
17952
17935
|
name: name2,
|
|
17953
17936
|
short: name2,
|
|
17954
|
-
|
|
17955
|
-
disabled: false,
|
|
17956
|
-
checked: false
|
|
17937
|
+
disabled: false
|
|
17957
17938
|
};
|
|
17958
17939
|
}
|
|
17959
17940
|
const name = choice.name ?? String(choice.value);
|
|
@@ -17961,9 +17942,7 @@ function normalizeChoices(choices) {
|
|
|
17961
17942
|
value: choice.value,
|
|
17962
17943
|
name,
|
|
17963
17944
|
short: choice.short ?? name,
|
|
17964
|
-
|
|
17965
|
-
disabled: choice.disabled ?? false,
|
|
17966
|
-
checked: choice.checked ?? false
|
|
17945
|
+
disabled: choice.disabled ?? false
|
|
17967
17946
|
};
|
|
17968
17947
|
if (choice.description) {
|
|
17969
17948
|
normalizedChoice.description = choice.description;
|
|
@@ -17972,39 +17951,47 @@ function normalizeChoices(choices) {
|
|
|
17972
17951
|
});
|
|
17973
17952
|
}
|
|
17974
17953
|
var dist_default4 = createPrompt((config, done) => {
|
|
17975
|
-
const {
|
|
17976
|
-
const
|
|
17977
|
-
const theme = makeTheme(checkboxTheme, config.theme);
|
|
17954
|
+
const { loop = true, pageSize = 7 } = config;
|
|
17955
|
+
const theme = makeTheme(selectTheme, config.theme);
|
|
17978
17956
|
const { keybindings: keybindings2 } = theme;
|
|
17979
17957
|
const [status, setStatus] = useState("idle");
|
|
17980
17958
|
const prefix = usePrefix({ status, theme });
|
|
17981
|
-
const
|
|
17959
|
+
const searchTimeoutRef = useRef();
|
|
17960
|
+
const searchEnabled = !keybindings2.includes("vim");
|
|
17961
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
17982
17962
|
const bounds = useMemo(() => {
|
|
17983
17963
|
const first = items.findIndex(isNavigable);
|
|
17984
17964
|
const last = items.findLastIndex(isNavigable);
|
|
17985
17965
|
if (first === -1) {
|
|
17986
|
-
throw new ValidationError("[
|
|
17966
|
+
throw new ValidationError("[select prompt] No selectable choices. All choices are disabled.");
|
|
17987
17967
|
}
|
|
17988
17968
|
return { first, last };
|
|
17989
17969
|
}, [items]);
|
|
17990
|
-
const
|
|
17970
|
+
const defaultItemIndex = useMemo(() => {
|
|
17971
|
+
if (!("default" in config))
|
|
17972
|
+
return -1;
|
|
17973
|
+
return items.findIndex((item) => isSelectable(item) && item.value === config.default);
|
|
17974
|
+
}, [config.default, items]);
|
|
17975
|
+
const [active, setActive] = useState(defaultItemIndex === -1 ? bounds.first : defaultItemIndex);
|
|
17976
|
+
const selectedChoice = items[active];
|
|
17977
|
+
if (selectedChoice == null || Separator.isSeparator(selectedChoice)) {
|
|
17978
|
+
throw new Error("Active index does not point to a choice");
|
|
17979
|
+
}
|
|
17991
17980
|
const [errorMsg, setError] = useState();
|
|
17992
|
-
useKeypress(
|
|
17981
|
+
useKeypress((key, rl) => {
|
|
17982
|
+
clearTimeout(searchTimeoutRef.current);
|
|
17983
|
+
if (errorMsg) {
|
|
17984
|
+
setError(void 0);
|
|
17985
|
+
}
|
|
17993
17986
|
if (isEnterKey(key)) {
|
|
17994
|
-
|
|
17995
|
-
|
|
17996
|
-
if (required && !selection.length) {
|
|
17997
|
-
setError("At least one choice must be selected");
|
|
17998
|
-
} else if (isValid === true) {
|
|
17999
|
-
setStatus("done");
|
|
18000
|
-
done(selection.map((choice) => choice.value));
|
|
17987
|
+
if (selectedChoice.disabled) {
|
|
17988
|
+
setError(theme.i18n.disabledError);
|
|
18001
17989
|
} else {
|
|
18002
|
-
|
|
17990
|
+
setStatus("done");
|
|
17991
|
+
done(selectedChoice.value);
|
|
18003
17992
|
}
|
|
18004
17993
|
} else if (isUpKey(key, keybindings2) || isDownKey(key, keybindings2)) {
|
|
18005
|
-
|
|
18006
|
-
setError(void 0);
|
|
18007
|
-
}
|
|
17994
|
+
rl.clearLine(0);
|
|
18008
17995
|
if (loop || isUpKey(key, keybindings2) && active !== bounds.first || isDownKey(key, keybindings2) && active !== bounds.last) {
|
|
18009
17996
|
const offset = isUpKey(key, keybindings2) ? -1 : 1;
|
|
18010
17997
|
let next = active;
|
|
@@ -18013,78 +18000,73 @@ var dist_default4 = createPrompt((config, done) => {
|
|
|
18013
18000
|
} while (!isNavigable(items[next]));
|
|
18014
18001
|
setActive(next);
|
|
18015
18002
|
}
|
|
18016
|
-
} else if (
|
|
18017
|
-
const
|
|
18018
|
-
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
18019
|
-
if (activeItem.disabled) {
|
|
18020
|
-
setError(theme.i18n.disabledError);
|
|
18021
|
-
} else {
|
|
18022
|
-
setError(void 0);
|
|
18023
|
-
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
18024
|
-
}
|
|
18025
|
-
}
|
|
18026
|
-
} else if (key.name === shortcuts.all) {
|
|
18027
|
-
const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
18028
|
-
setItems(items.map(check(selectAll)));
|
|
18029
|
-
} else if (key.name === shortcuts.invert) {
|
|
18030
|
-
setItems(items.map(toggle));
|
|
18031
|
-
} else if (isNumberKey(key)) {
|
|
18032
|
-
const selectedIndex = Number(key.name) - 1;
|
|
18003
|
+
} else if (isNumberKey(key) && !Number.isNaN(Number(rl.line))) {
|
|
18004
|
+
const selectedIndex = Number(rl.line) - 1;
|
|
18033
18005
|
let selectableIndex = -1;
|
|
18034
|
-
const position = items.findIndex((
|
|
18035
|
-
if (Separator.isSeparator(
|
|
18006
|
+
const position = items.findIndex((item2) => {
|
|
18007
|
+
if (Separator.isSeparator(item2))
|
|
18036
18008
|
return false;
|
|
18037
18009
|
selectableIndex++;
|
|
18038
18010
|
return selectableIndex === selectedIndex;
|
|
18039
18011
|
});
|
|
18040
|
-
const
|
|
18041
|
-
if (
|
|
18012
|
+
const item = items[position];
|
|
18013
|
+
if (item != null && isSelectable(item)) {
|
|
18042
18014
|
setActive(position);
|
|
18043
|
-
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
18044
18015
|
}
|
|
18016
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
18017
|
+
rl.clearLine(0);
|
|
18018
|
+
}, 700);
|
|
18019
|
+
} else if (isBackspaceKey(key)) {
|
|
18020
|
+
rl.clearLine(0);
|
|
18021
|
+
} else if (searchEnabled) {
|
|
18022
|
+
const searchTerm = rl.line.toLowerCase();
|
|
18023
|
+
const matchIndex = items.findIndex((item) => {
|
|
18024
|
+
if (Separator.isSeparator(item) || !isSelectable(item))
|
|
18025
|
+
return false;
|
|
18026
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
18027
|
+
});
|
|
18028
|
+
if (matchIndex !== -1) {
|
|
18029
|
+
setActive(matchIndex);
|
|
18030
|
+
}
|
|
18031
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
18032
|
+
rl.clearLine(0);
|
|
18033
|
+
}, 700);
|
|
18045
18034
|
}
|
|
18046
18035
|
});
|
|
18036
|
+
useEffect(() => () => {
|
|
18037
|
+
clearTimeout(searchTimeoutRef.current);
|
|
18038
|
+
}, []);
|
|
18047
18039
|
const message = theme.style.message(config.message, status);
|
|
18048
|
-
|
|
18040
|
+
const helpLine = theme.style.keysHelpTip([
|
|
18041
|
+
["\u2191\u2193", "navigate"],
|
|
18042
|
+
["\u23CE", "select"]
|
|
18043
|
+
]);
|
|
18044
|
+
let separatorCount = 0;
|
|
18049
18045
|
const page = usePagination({
|
|
18050
18046
|
items,
|
|
18051
18047
|
active,
|
|
18052
|
-
renderItem({ item, isActive }) {
|
|
18048
|
+
renderItem({ item, isActive, index }) {
|
|
18053
18049
|
if (Separator.isSeparator(item)) {
|
|
18050
|
+
separatorCount++;
|
|
18054
18051
|
return ` ${item.separator}`;
|
|
18055
18052
|
}
|
|
18056
18053
|
const cursor = isActive ? theme.icon.cursor : " ";
|
|
18054
|
+
const indexLabel = theme.indexMode === "number" ? `${index + 1 - separatorCount}. ` : "";
|
|
18057
18055
|
if (item.disabled) {
|
|
18058
18056
|
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
18059
|
-
const
|
|
18060
|
-
return theme.style.disabled(`${
|
|
18057
|
+
const disabledCursor = isActive ? theme.icon.cursor : "-";
|
|
18058
|
+
return theme.style.disabled(`${disabledCursor} ${indexLabel}${item.name} ${disabledLabel}`);
|
|
18061
18059
|
}
|
|
18062
|
-
if (isActive) {
|
|
18063
|
-
description = item.description;
|
|
18064
|
-
}
|
|
18065
|
-
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
18066
|
-
const name = item.checked ? item.checkedName : item.name;
|
|
18067
18060
|
const color = isActive ? theme.style.highlight : (x) => x;
|
|
18068
|
-
return color(`${cursor}${
|
|
18061
|
+
return color(`${cursor} ${indexLabel}${item.name}`);
|
|
18069
18062
|
},
|
|
18070
18063
|
pageSize,
|
|
18071
18064
|
loop
|
|
18072
18065
|
});
|
|
18073
18066
|
if (status === "done") {
|
|
18074
|
-
|
|
18075
|
-
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
18076
|
-
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
18067
|
+
return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ");
|
|
18077
18068
|
}
|
|
18078
|
-
const
|
|
18079
|
-
["\u2191\u2193", "navigate"],
|
|
18080
|
-
["space", "select"]
|
|
18081
|
-
];
|
|
18082
|
-
if (shortcuts.all)
|
|
18083
|
-
keys.push([shortcuts.all, "all"]);
|
|
18084
|
-
if (shortcuts.invert)
|
|
18085
|
-
keys.push([shortcuts.invert, "invert"]);
|
|
18086
|
-
keys.push(["\u23CE", "submit"]);
|
|
18087
|
-
const helpLine = theme.style.keysHelpTip(keys);
|
|
18069
|
+
const { description } = selectedChoice;
|
|
18088
18070
|
const lines = [
|
|
18089
18071
|
[prefix, message].filter(Boolean).join(" "),
|
|
18090
18072
|
page,
|
|
@@ -18275,7 +18257,7 @@ async function runInstallCommand(input) {
|
|
|
18275
18257
|
hostDefinitions: input.hostDefinitions,
|
|
18276
18258
|
selectHosts: input.selectHosts,
|
|
18277
18259
|
selectHost: input.selectHost,
|
|
18278
|
-
|
|
18260
|
+
promptSelectHost: input.promptSelectHost,
|
|
18279
18261
|
ttyPath: input.ttyPath
|
|
18280
18262
|
});
|
|
18281
18263
|
for (const destination of destinations) {
|
|
@@ -18327,12 +18309,9 @@ async function resolveInstallDestinations(args, options = {}) {
|
|
|
18327
18309
|
const detected = detectInstallHosts(options.hostDefinitions ?? getDefaultHostDefinitions());
|
|
18328
18310
|
const compatible = detected;
|
|
18329
18311
|
const incompatible = [];
|
|
18330
|
-
if (compatible.length
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
if (compatible.length > 1) {
|
|
18334
|
-
const selected = options.selectHosts ? await options.selectHosts(compatible, incompatible) : options.selectHost ? [await options.selectHost(compatible)] : await (options.promptSelectHosts ?? promptForInstallHosts)(compatible, incompatible);
|
|
18335
|
-
return validateSelectedHosts(selected, compatible).map(toInstallDestination);
|
|
18312
|
+
if (compatible.length > 0) {
|
|
18313
|
+
const selected = options.selectHosts ? validateSingleSelectedHost(await options.selectHosts(compatible, incompatible), compatible) : options.selectHost ? validateSingleSelectedHost(await options.selectHost(compatible), compatible) : validateSingleSelectedHost(await (options.promptSelectHost ?? promptForInstallHost)(compatible, incompatible), compatible);
|
|
18314
|
+
return [toInstallDestination(selected)];
|
|
18336
18315
|
}
|
|
18337
18316
|
throw new Error(
|
|
18338
18317
|
[
|
|
@@ -18382,7 +18361,7 @@ function detectInstallHosts(hosts) {
|
|
|
18382
18361
|
return true;
|
|
18383
18362
|
});
|
|
18384
18363
|
}
|
|
18385
|
-
async function
|
|
18364
|
+
async function promptForInstallHost(hosts, incompatibleHosts) {
|
|
18386
18365
|
try {
|
|
18387
18366
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
18388
18367
|
throw new Error("interactive terminal is required");
|
|
@@ -18405,14 +18384,10 @@ Extensions: ${host.extensionsDir}`
|
|
|
18405
18384
|
}))
|
|
18406
18385
|
];
|
|
18407
18386
|
return await dist_default4({
|
|
18408
|
-
message: "Choose
|
|
18387
|
+
message: "Choose the Claw installation to connect with this 53AIHub agent:",
|
|
18409
18388
|
choices,
|
|
18410
18389
|
pageSize: Math.min(Math.max(choices.length, 5), 12),
|
|
18411
|
-
|
|
18412
|
-
shortcuts: {
|
|
18413
|
-
all: "a",
|
|
18414
|
-
invert: "i"
|
|
18415
|
-
}
|
|
18390
|
+
loop: true
|
|
18416
18391
|
});
|
|
18417
18392
|
} catch (error) {
|
|
18418
18393
|
throw new Error(
|
|
@@ -18435,20 +18410,18 @@ function toInstallDestination(host) {
|
|
|
18435
18410
|
installKind: host.installKind ?? "openclaw"
|
|
18436
18411
|
};
|
|
18437
18412
|
}
|
|
18438
|
-
function
|
|
18413
|
+
function validateSingleSelectedHost(selected, compatible) {
|
|
18414
|
+
if (Array.isArray(selected)) {
|
|
18415
|
+
if (selected.length !== 1) {
|
|
18416
|
+
throw new Error("select exactly one Claw host for this 53AIHub agent");
|
|
18417
|
+
}
|
|
18418
|
+
return validateSingleSelectedHost(selected[0], compatible);
|
|
18419
|
+
}
|
|
18439
18420
|
const compatibleIds = new Set(compatible.map((host) => host.id));
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
throw new Error(`selected host is not installable: ${invalid.label}`);
|
|
18421
|
+
if (!compatibleIds.has(selected.id)) {
|
|
18422
|
+
throw new Error(`selected host is not installable: ${selected.label}`);
|
|
18443
18423
|
}
|
|
18444
|
-
|
|
18445
|
-
return selected.filter((host) => {
|
|
18446
|
-
if (seen.has(host.id)) {
|
|
18447
|
-
return false;
|
|
18448
|
-
}
|
|
18449
|
-
seen.add(host.id);
|
|
18450
|
-
return true;
|
|
18451
|
-
});
|
|
18424
|
+
return selected;
|
|
18452
18425
|
}
|
|
18453
18426
|
function formatHostList(hosts) {
|
|
18454
18427
|
return hosts.flatMap((host) => [
|
package/dist/install-qclaw.cjs
CHANGED
|
@@ -7562,7 +7562,7 @@ var isDownKey = (key, keybindings2 = []) => (
|
|
|
7562
7562
|
keybindings2.includes("vim") && key.name === "j" || // Emacs keybinding: Ctrl+N means "next" in Emacs navigation conventions
|
|
7563
7563
|
keybindings2.includes("emacs") && key.ctrl && key.name === "n"
|
|
7564
7564
|
);
|
|
7565
|
-
var
|
|
7565
|
+
var isBackspaceKey = (key) => key.name === "backspace";
|
|
7566
7566
|
var isNumberKey = (key) => "1234567890".includes(key.name);
|
|
7567
7567
|
var isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
7568
7568
|
|
|
@@ -9065,23 +9065,17 @@ var Separator = class {
|
|
|
9065
9065
|
}
|
|
9066
9066
|
};
|
|
9067
9067
|
|
|
9068
|
-
// ../node_modules/.pnpm/@inquirer+
|
|
9068
|
+
// ../node_modules/.pnpm/@inquirer+select@5.2.1_@types+node@24.12.4/node_modules/@inquirer/select/dist/index.js
|
|
9069
9069
|
var import_node_util4 = require("util");
|
|
9070
|
-
var
|
|
9071
|
-
icon: {
|
|
9072
|
-
checked: (0, import_node_util4.styleText)("green", dist_default.circleFilled),
|
|
9073
|
-
unchecked: dist_default.circle,
|
|
9074
|
-
cursor: dist_default.pointer,
|
|
9075
|
-
disabledChecked: (0, import_node_util4.styleText)("green", dist_default.circleDouble),
|
|
9076
|
-
disabledUnchecked: "-"
|
|
9077
|
-
},
|
|
9070
|
+
var selectTheme = {
|
|
9071
|
+
icon: { cursor: dist_default.pointer },
|
|
9078
9072
|
style: {
|
|
9079
9073
|
disabled: (text) => (0, import_node_util4.styleText)("dim", text),
|
|
9080
|
-
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
9081
9074
|
description: (text) => (0, import_node_util4.styleText)("cyan", text),
|
|
9082
9075
|
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 "))
|
|
9083
9076
|
},
|
|
9084
|
-
i18n: { disabledError: "This option is disabled and cannot be
|
|
9077
|
+
i18n: { disabledError: "This option is disabled and cannot be selected." },
|
|
9078
|
+
indexMode: "hidden"
|
|
9085
9079
|
};
|
|
9086
9080
|
function isSelectable(item) {
|
|
9087
9081
|
return !Separator.isSeparator(item) && !item.disabled;
|
|
@@ -9089,17 +9083,6 @@ function isSelectable(item) {
|
|
|
9089
9083
|
function isNavigable(item) {
|
|
9090
9084
|
return !Separator.isSeparator(item);
|
|
9091
9085
|
}
|
|
9092
|
-
function isChecked(item) {
|
|
9093
|
-
return !Separator.isSeparator(item) && item.checked;
|
|
9094
|
-
}
|
|
9095
|
-
function toggle(item) {
|
|
9096
|
-
return isSelectable(item) ? { ...item, checked: !item.checked } : item;
|
|
9097
|
-
}
|
|
9098
|
-
function check(checked) {
|
|
9099
|
-
return function(item) {
|
|
9100
|
-
return isSelectable(item) ? { ...item, checked } : item;
|
|
9101
|
-
};
|
|
9102
|
-
}
|
|
9103
9086
|
function normalizeChoices(choices) {
|
|
9104
9087
|
return choices.map((choice) => {
|
|
9105
9088
|
if (Separator.isSeparator(choice))
|
|
@@ -9110,9 +9093,7 @@ function normalizeChoices(choices) {
|
|
|
9110
9093
|
value: choice,
|
|
9111
9094
|
name: name2,
|
|
9112
9095
|
short: name2,
|
|
9113
|
-
|
|
9114
|
-
disabled: false,
|
|
9115
|
-
checked: false
|
|
9096
|
+
disabled: false
|
|
9116
9097
|
};
|
|
9117
9098
|
}
|
|
9118
9099
|
const name = choice.name ?? String(choice.value);
|
|
@@ -9120,9 +9101,7 @@ function normalizeChoices(choices) {
|
|
|
9120
9101
|
value: choice.value,
|
|
9121
9102
|
name,
|
|
9122
9103
|
short: choice.short ?? name,
|
|
9123
|
-
|
|
9124
|
-
disabled: choice.disabled ?? false,
|
|
9125
|
-
checked: choice.checked ?? false
|
|
9104
|
+
disabled: choice.disabled ?? false
|
|
9126
9105
|
};
|
|
9127
9106
|
if (choice.description) {
|
|
9128
9107
|
normalizedChoice.description = choice.description;
|
|
@@ -9131,39 +9110,47 @@ function normalizeChoices(choices) {
|
|
|
9131
9110
|
});
|
|
9132
9111
|
}
|
|
9133
9112
|
var dist_default4 = createPrompt((config, done) => {
|
|
9134
|
-
const {
|
|
9135
|
-
const
|
|
9136
|
-
const theme = makeTheme(checkboxTheme, config.theme);
|
|
9113
|
+
const { loop = true, pageSize = 7 } = config;
|
|
9114
|
+
const theme = makeTheme(selectTheme, config.theme);
|
|
9137
9115
|
const { keybindings: keybindings2 } = theme;
|
|
9138
9116
|
const [status, setStatus] = useState("idle");
|
|
9139
9117
|
const prefix = usePrefix({ status, theme });
|
|
9140
|
-
const
|
|
9118
|
+
const searchTimeoutRef = useRef();
|
|
9119
|
+
const searchEnabled = !keybindings2.includes("vim");
|
|
9120
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
9141
9121
|
const bounds = useMemo(() => {
|
|
9142
9122
|
const first = items.findIndex(isNavigable);
|
|
9143
9123
|
const last = items.findLastIndex(isNavigable);
|
|
9144
9124
|
if (first === -1) {
|
|
9145
|
-
throw new ValidationError("[
|
|
9125
|
+
throw new ValidationError("[select prompt] No selectable choices. All choices are disabled.");
|
|
9146
9126
|
}
|
|
9147
9127
|
return { first, last };
|
|
9148
9128
|
}, [items]);
|
|
9149
|
-
const
|
|
9129
|
+
const defaultItemIndex = useMemo(() => {
|
|
9130
|
+
if (!("default" in config))
|
|
9131
|
+
return -1;
|
|
9132
|
+
return items.findIndex((item) => isSelectable(item) && item.value === config.default);
|
|
9133
|
+
}, [config.default, items]);
|
|
9134
|
+
const [active, setActive] = useState(defaultItemIndex === -1 ? bounds.first : defaultItemIndex);
|
|
9135
|
+
const selectedChoice = items[active];
|
|
9136
|
+
if (selectedChoice == null || Separator.isSeparator(selectedChoice)) {
|
|
9137
|
+
throw new Error("Active index does not point to a choice");
|
|
9138
|
+
}
|
|
9150
9139
|
const [errorMsg, setError] = useState();
|
|
9151
|
-
useKeypress(
|
|
9140
|
+
useKeypress((key, rl) => {
|
|
9141
|
+
clearTimeout(searchTimeoutRef.current);
|
|
9142
|
+
if (errorMsg) {
|
|
9143
|
+
setError(void 0);
|
|
9144
|
+
}
|
|
9152
9145
|
if (isEnterKey(key)) {
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
if (required && !selection.length) {
|
|
9156
|
-
setError("At least one choice must be selected");
|
|
9157
|
-
} else if (isValid === true) {
|
|
9158
|
-
setStatus("done");
|
|
9159
|
-
done(selection.map((choice) => choice.value));
|
|
9146
|
+
if (selectedChoice.disabled) {
|
|
9147
|
+
setError(theme.i18n.disabledError);
|
|
9160
9148
|
} else {
|
|
9161
|
-
|
|
9149
|
+
setStatus("done");
|
|
9150
|
+
done(selectedChoice.value);
|
|
9162
9151
|
}
|
|
9163
9152
|
} else if (isUpKey(key, keybindings2) || isDownKey(key, keybindings2)) {
|
|
9164
|
-
|
|
9165
|
-
setError(void 0);
|
|
9166
|
-
}
|
|
9153
|
+
rl.clearLine(0);
|
|
9167
9154
|
if (loop || isUpKey(key, keybindings2) && active !== bounds.first || isDownKey(key, keybindings2) && active !== bounds.last) {
|
|
9168
9155
|
const offset = isUpKey(key, keybindings2) ? -1 : 1;
|
|
9169
9156
|
let next = active;
|
|
@@ -9172,78 +9159,73 @@ var dist_default4 = createPrompt((config, done) => {
|
|
|
9172
9159
|
} while (!isNavigable(items[next]));
|
|
9173
9160
|
setActive(next);
|
|
9174
9161
|
}
|
|
9175
|
-
} else if (
|
|
9176
|
-
const
|
|
9177
|
-
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
9178
|
-
if (activeItem.disabled) {
|
|
9179
|
-
setError(theme.i18n.disabledError);
|
|
9180
|
-
} else {
|
|
9181
|
-
setError(void 0);
|
|
9182
|
-
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
9183
|
-
}
|
|
9184
|
-
}
|
|
9185
|
-
} else if (key.name === shortcuts.all) {
|
|
9186
|
-
const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
9187
|
-
setItems(items.map(check(selectAll)));
|
|
9188
|
-
} else if (key.name === shortcuts.invert) {
|
|
9189
|
-
setItems(items.map(toggle));
|
|
9190
|
-
} else if (isNumberKey(key)) {
|
|
9191
|
-
const selectedIndex = Number(key.name) - 1;
|
|
9162
|
+
} else if (isNumberKey(key) && !Number.isNaN(Number(rl.line))) {
|
|
9163
|
+
const selectedIndex = Number(rl.line) - 1;
|
|
9192
9164
|
let selectableIndex = -1;
|
|
9193
|
-
const position = items.findIndex((
|
|
9194
|
-
if (Separator.isSeparator(
|
|
9165
|
+
const position = items.findIndex((item2) => {
|
|
9166
|
+
if (Separator.isSeparator(item2))
|
|
9195
9167
|
return false;
|
|
9196
9168
|
selectableIndex++;
|
|
9197
9169
|
return selectableIndex === selectedIndex;
|
|
9198
9170
|
});
|
|
9199
|
-
const
|
|
9200
|
-
if (
|
|
9171
|
+
const item = items[position];
|
|
9172
|
+
if (item != null && isSelectable(item)) {
|
|
9201
9173
|
setActive(position);
|
|
9202
|
-
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
9203
9174
|
}
|
|
9175
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
9176
|
+
rl.clearLine(0);
|
|
9177
|
+
}, 700);
|
|
9178
|
+
} else if (isBackspaceKey(key)) {
|
|
9179
|
+
rl.clearLine(0);
|
|
9180
|
+
} else if (searchEnabled) {
|
|
9181
|
+
const searchTerm = rl.line.toLowerCase();
|
|
9182
|
+
const matchIndex = items.findIndex((item) => {
|
|
9183
|
+
if (Separator.isSeparator(item) || !isSelectable(item))
|
|
9184
|
+
return false;
|
|
9185
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
9186
|
+
});
|
|
9187
|
+
if (matchIndex !== -1) {
|
|
9188
|
+
setActive(matchIndex);
|
|
9189
|
+
}
|
|
9190
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
9191
|
+
rl.clearLine(0);
|
|
9192
|
+
}, 700);
|
|
9204
9193
|
}
|
|
9205
9194
|
});
|
|
9195
|
+
useEffect(() => () => {
|
|
9196
|
+
clearTimeout(searchTimeoutRef.current);
|
|
9197
|
+
}, []);
|
|
9206
9198
|
const message = theme.style.message(config.message, status);
|
|
9207
|
-
|
|
9199
|
+
const helpLine = theme.style.keysHelpTip([
|
|
9200
|
+
["\u2191\u2193", "navigate"],
|
|
9201
|
+
["\u23CE", "select"]
|
|
9202
|
+
]);
|
|
9203
|
+
let separatorCount = 0;
|
|
9208
9204
|
const page = usePagination({
|
|
9209
9205
|
items,
|
|
9210
9206
|
active,
|
|
9211
|
-
renderItem({ item, isActive }) {
|
|
9207
|
+
renderItem({ item, isActive, index }) {
|
|
9212
9208
|
if (Separator.isSeparator(item)) {
|
|
9209
|
+
separatorCount++;
|
|
9213
9210
|
return ` ${item.separator}`;
|
|
9214
9211
|
}
|
|
9215
9212
|
const cursor = isActive ? theme.icon.cursor : " ";
|
|
9213
|
+
const indexLabel = theme.indexMode === "number" ? `${index + 1 - separatorCount}. ` : "";
|
|
9216
9214
|
if (item.disabled) {
|
|
9217
9215
|
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
9218
|
-
const
|
|
9219
|
-
return theme.style.disabled(`${
|
|
9216
|
+
const disabledCursor = isActive ? theme.icon.cursor : "-";
|
|
9217
|
+
return theme.style.disabled(`${disabledCursor} ${indexLabel}${item.name} ${disabledLabel}`);
|
|
9220
9218
|
}
|
|
9221
|
-
if (isActive) {
|
|
9222
|
-
description = item.description;
|
|
9223
|
-
}
|
|
9224
|
-
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
9225
|
-
const name = item.checked ? item.checkedName : item.name;
|
|
9226
9219
|
const color = isActive ? theme.style.highlight : (x) => x;
|
|
9227
|
-
return color(`${cursor}${
|
|
9220
|
+
return color(`${cursor} ${indexLabel}${item.name}`);
|
|
9228
9221
|
},
|
|
9229
9222
|
pageSize,
|
|
9230
9223
|
loop
|
|
9231
9224
|
});
|
|
9232
9225
|
if (status === "done") {
|
|
9233
|
-
|
|
9234
|
-
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
9235
|
-
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
9226
|
+
return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ");
|
|
9236
9227
|
}
|
|
9237
|
-
const
|
|
9238
|
-
["\u2191\u2193", "navigate"],
|
|
9239
|
-
["space", "select"]
|
|
9240
|
-
];
|
|
9241
|
-
if (shortcuts.all)
|
|
9242
|
-
keys.push([shortcuts.all, "all"]);
|
|
9243
|
-
if (shortcuts.invert)
|
|
9244
|
-
keys.push([shortcuts.invert, "invert"]);
|
|
9245
|
-
keys.push(["\u23CE", "submit"]);
|
|
9246
|
-
const helpLine = theme.style.keysHelpTip(keys);
|
|
9228
|
+
const { description } = selectedChoice;
|
|
9247
9229
|
const lines = [
|
|
9248
9230
|
[prefix, message].filter(Boolean).join(" "),
|
|
9249
9231
|
page,
|
|
@@ -9434,7 +9416,7 @@ async function runInstallCommand(input) {
|
|
|
9434
9416
|
hostDefinitions: input.hostDefinitions,
|
|
9435
9417
|
selectHosts: input.selectHosts,
|
|
9436
9418
|
selectHost: input.selectHost,
|
|
9437
|
-
|
|
9419
|
+
promptSelectHost: input.promptSelectHost,
|
|
9438
9420
|
ttyPath: input.ttyPath
|
|
9439
9421
|
});
|
|
9440
9422
|
for (const destination of destinations) {
|
|
@@ -9486,12 +9468,9 @@ async function resolveInstallDestinations(args, options = {}) {
|
|
|
9486
9468
|
const detected = detectInstallHosts(options.hostDefinitions ?? getDefaultHostDefinitions());
|
|
9487
9469
|
const compatible = detected;
|
|
9488
9470
|
const incompatible = [];
|
|
9489
|
-
if (compatible.length
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
if (compatible.length > 1) {
|
|
9493
|
-
const selected = options.selectHosts ? await options.selectHosts(compatible, incompatible) : options.selectHost ? [await options.selectHost(compatible)] : await (options.promptSelectHosts ?? promptForInstallHosts)(compatible, incompatible);
|
|
9494
|
-
return validateSelectedHosts(selected, compatible).map(toInstallDestination);
|
|
9471
|
+
if (compatible.length > 0) {
|
|
9472
|
+
const selected = options.selectHosts ? validateSingleSelectedHost(await options.selectHosts(compatible, incompatible), compatible) : options.selectHost ? validateSingleSelectedHost(await options.selectHost(compatible), compatible) : validateSingleSelectedHost(await (options.promptSelectHost ?? promptForInstallHost)(compatible, incompatible), compatible);
|
|
9473
|
+
return [toInstallDestination(selected)];
|
|
9495
9474
|
}
|
|
9496
9475
|
throw new Error(
|
|
9497
9476
|
[
|
|
@@ -9541,7 +9520,7 @@ function detectInstallHosts(hosts) {
|
|
|
9541
9520
|
return true;
|
|
9542
9521
|
});
|
|
9543
9522
|
}
|
|
9544
|
-
async function
|
|
9523
|
+
async function promptForInstallHost(hosts, incompatibleHosts) {
|
|
9545
9524
|
try {
|
|
9546
9525
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
9547
9526
|
throw new Error("interactive terminal is required");
|
|
@@ -9564,14 +9543,10 @@ Extensions: ${host.extensionsDir}`
|
|
|
9564
9543
|
}))
|
|
9565
9544
|
];
|
|
9566
9545
|
return await dist_default4({
|
|
9567
|
-
message: "Choose
|
|
9546
|
+
message: "Choose the Claw installation to connect with this 53AIHub agent:",
|
|
9568
9547
|
choices,
|
|
9569
9548
|
pageSize: Math.min(Math.max(choices.length, 5), 12),
|
|
9570
|
-
|
|
9571
|
-
shortcuts: {
|
|
9572
|
-
all: "a",
|
|
9573
|
-
invert: "i"
|
|
9574
|
-
}
|
|
9549
|
+
loop: true
|
|
9575
9550
|
});
|
|
9576
9551
|
} catch (error) {
|
|
9577
9552
|
throw new Error(
|
|
@@ -9594,20 +9569,18 @@ function toInstallDestination(host) {
|
|
|
9594
9569
|
installKind: host.installKind ?? "openclaw"
|
|
9595
9570
|
};
|
|
9596
9571
|
}
|
|
9597
|
-
function
|
|
9572
|
+
function validateSingleSelectedHost(selected, compatible) {
|
|
9573
|
+
if (Array.isArray(selected)) {
|
|
9574
|
+
if (selected.length !== 1) {
|
|
9575
|
+
throw new Error("select exactly one Claw host for this 53AIHub agent");
|
|
9576
|
+
}
|
|
9577
|
+
return validateSingleSelectedHost(selected[0], compatible);
|
|
9578
|
+
}
|
|
9598
9579
|
const compatibleIds = new Set(compatible.map((host) => host.id));
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
throw new Error(`selected host is not installable: ${invalid.label}`);
|
|
9580
|
+
if (!compatibleIds.has(selected.id)) {
|
|
9581
|
+
throw new Error(`selected host is not installable: ${selected.label}`);
|
|
9602
9582
|
}
|
|
9603
|
-
|
|
9604
|
-
return selected.filter((host) => {
|
|
9605
|
-
if (seen.has(host.id)) {
|
|
9606
|
-
return false;
|
|
9607
|
-
}
|
|
9608
|
-
seen.add(host.id);
|
|
9609
|
-
return true;
|
|
9610
|
-
});
|
|
9583
|
+
return selected;
|
|
9611
9584
|
}
|
|
9612
9585
|
function formatHostList(hosts) {
|
|
9613
9586
|
return hosts.flatMap((host) => [
|
package/dist/install-qclaw.d.cts
CHANGED
|
@@ -22,7 +22,7 @@ type HostDefinition = {
|
|
|
22
22
|
installKind?: "openclaw" | "hermes";
|
|
23
23
|
incompatibilityReason?: string;
|
|
24
24
|
};
|
|
25
|
-
type
|
|
25
|
+
type PromptSelectHost = (hosts: HostDefinition[], incompatibleHosts: HostDefinition[]) => Promise<HostDefinition>;
|
|
26
26
|
declare function installIntoQClaw(input: InstallInput): Promise<{
|
|
27
27
|
configPath: string;
|
|
28
28
|
extensionsDir: string;
|
|
@@ -52,8 +52,8 @@ declare function runInstallCommand(input: {
|
|
|
52
52
|
hostDefinitions?: HostDefinition[];
|
|
53
53
|
selectHosts?: (hosts: HostDefinition[], incompatibleHosts: HostDefinition[]) => Promise<HostDefinition[]>;
|
|
54
54
|
selectHost?: (hosts: HostDefinition[]) => Promise<HostDefinition>;
|
|
55
|
-
|
|
55
|
+
promptSelectHost?: PromptSelectHost;
|
|
56
56
|
ttyPath?: string;
|
|
57
57
|
}): Promise<void>;
|
|
58
58
|
|
|
59
|
-
export { type HostDefinition, type
|
|
59
|
+
export { type HostDefinition, type PromptSelectHost, installIntoHermes, installIntoOpenClaw, installIntoQClaw, runInstallCommand };
|