@cannbot-ai/install-helper 1.1.6-beta.6 → 1.1.6-beta.7

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.js CHANGED
@@ -849,6 +849,7 @@ var init_zh_CN = __esm({
849
849
  uninstall_type_skill: "\u5378\u8F7D Skills",
850
850
  uninstall_type_plugin: "\u5378\u8F7D Plugins",
851
851
  uninstall_checkbox_hint: "\u52FE\u9009=\u4FDD\u7559\uFF0C\u53D6\u6D88\u52FE\u9009=\u5378\u8F7D",
852
+ uninstall_checkbox_hint_select: "\u52FE\u9009\u8981\u5378\u8F7D\u7684\u9879\uFF0C\u4E0D\u9009\u6309\u56DE\u8F66\u53EF\u8FD4\u56DE",
852
853
  uninstall_uncheck_all: "\u5378\u8F7D\u5168\u90E8",
853
854
  uninstall_confirm_count: "\u786E\u8BA4\u5378\u8F7D\uFF08{count} \u4E2A\u5C06\u5378\u8F7D\uFF09",
854
855
  uninstall_no_installed: "\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684 Skills \u6216 Plugins",
@@ -1071,6 +1072,7 @@ var init_en_US = __esm({
1071
1072
  uninstall_type_skill: "Uninstall Skills",
1072
1073
  uninstall_type_plugin: "Uninstall Plugins",
1073
1074
  uninstall_checkbox_hint: "Checked = keep, unchecked = uninstall",
1075
+ uninstall_checkbox_hint_select: "Check items to uninstall, press enter without selection to go back",
1074
1076
  uninstall_uncheck_all: "Uninstall all",
1075
1077
  uninstall_confirm_count: "Confirm uninstall ({count} will be removed)",
1076
1078
  uninstall_no_installed: "No installed Skills or Plugins",
@@ -3841,6 +3843,55 @@ async function interactiveSkillUnselect(tool, level) {
3841
3843
  logger.warn(t("uninstall_no_installed_skills"));
3842
3844
  return "back";
3843
3845
  }
3846
+ if (installedSkills.length <= 15) {
3847
+ return await flatSkillUnselect(installedSkills);
3848
+ }
3849
+ return await categorySkillUnselect(installedSkills);
3850
+ }
3851
+ async function flatSkillUnselect(installedSkills) {
3852
+ const categories = getAllCategories();
3853
+ const installedSet = new Set(installedSkills);
3854
+ const skillChoices = [
3855
+ ...installedSkills.map((skillId) => {
3856
+ const skill = findSkill(skillId);
3857
+ const cat = categories.find((c) => c.skills.some((s) => s.id === skillId));
3858
+ const catName = cat ? cat.name : "";
3859
+ const desc = skill?.description || "";
3860
+ return {
3861
+ name: `${chalk5.cyan(skillId)}${catName ? chalk5.dim(` [${catName}]`) : ""}`,
3862
+ value: skillId,
3863
+ checked: false,
3864
+ description: desc
3865
+ };
3866
+ })
3867
+ ];
3868
+ printBoxTitle(t("uninstall_interactive_title"));
3869
+ logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint_select")}`));
3870
+ logger.blank();
3871
+ showOperationHints(true);
3872
+ const selected = await checkbox({
3873
+ message: t("uninstall_select_items"),
3874
+ choices: skillChoices,
3875
+ loop: false,
3876
+ instructions: false,
3877
+ theme: checkboxTheme,
3878
+ pageSize: 20
3879
+ });
3880
+ if (selected.length === 0) {
3881
+ logger.info(t("uninstall_nothing_to_uninstall"));
3882
+ return "back";
3883
+ }
3884
+ const confirmed = await confirm({
3885
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(selected.length))),
3886
+ default: false
3887
+ });
3888
+ if (!confirmed) return "cancel";
3889
+ return {
3890
+ toUninstall: selected,
3891
+ toKeep: installedSkills.filter((id) => !selected.includes(id))
3892
+ };
3893
+ }
3894
+ async function categorySkillUnselect(installedSkills) {
3844
3895
  const allCategories = getAllCategories();
3845
3896
  const installedSet = new Set(installedSkills);
3846
3897
  const categoriesWithInstalled = allCategories.map((cat) => ({
@@ -3857,14 +3908,13 @@ async function interactiveSkillUnselect(tool, level) {
3857
3908
  skills: uncategorized.map((id) => ({ id, description: "", source: "", filePath: "" }))
3858
3909
  });
3859
3910
  }
3860
- let keptSet = new Set(installedSkills);
3911
+ const uninstallSet = /* @__PURE__ */ new Set();
3861
3912
  let step = 0;
3862
3913
  let selectedCategoryId = "";
3863
3914
  while (true) {
3864
3915
  switch (step) {
3865
3916
  case 0: {
3866
- const toUninstallCount = installedSkills.length - keptSet.size;
3867
- const titleSuffix = toUninstallCount > 0 ? `${t("wizard_step_3_skill_title")}\uFF08${t("uninstall_marked_count").replace("{count}", String(toUninstallCount))}\uFF09` : t("wizard_step_3_skill_title");
3917
+ const titleSuffix = uninstallSet.size > 0 ? `${t("wizard_step_3_skill_title")}\uFF08${t("uninstall_marked_count").replace("{count}", String(uninstallSet.size))}\uFF09` : t("wizard_step_3_skill_title");
3868
3918
  printBoxTitle(titleSuffix);
3869
3919
  const categoryChoices = [
3870
3920
  {
@@ -3873,16 +3923,15 @@ async function interactiveSkillUnselect(tool, level) {
3873
3923
  },
3874
3924
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
3875
3925
  ...categoriesWithInstalled.map((cat) => {
3876
- const catKeptCount = cat.skills.filter((s) => keptSet.has(s.id)).length;
3877
- const catUninstallCount = cat.skills.length - catKeptCount;
3878
- const suffix = catUninstallCount > 0 ? chalk5.yellow(` (${catUninstallCount} to uninstall)`) : "";
3926
+ const catSelectedCount = cat.skills.filter((s) => uninstallSet.has(s.id)).length;
3927
+ const suffix = catSelectedCount > 0 ? chalk5.yellow(` (${catSelectedCount} selected)`) : "";
3879
3928
  return {
3880
3929
  name: `> ${cat.name} (${cat.skills.length} skills)${suffix}`,
3881
3930
  value: cat.id
3882
3931
  };
3883
3932
  }),
3884
3933
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
3885
- ...toUninstallCount > 0 ? [{ name: `>> ${t("uninstall_confirm_count").replace("{count}", String(toUninstallCount))}`, value: "uninstall" }] : [],
3934
+ ...uninstallSet.size > 0 ? [{ name: `>> ${t("uninstall_confirm_count").replace("{count}", String(uninstallSet.size))}`, value: "uninstall" }] : [],
3886
3935
  { name: "<- " + t("wizard_back"), value: BACK },
3887
3936
  { name: "x " + t("wizard_cancel"), value: CANCEL }
3888
3937
  ];
@@ -3897,27 +3946,27 @@ async function interactiveSkillUnselect(tool, level) {
3897
3946
  if (selectedCategoryId === BACK) return "back";
3898
3947
  if (selectedCategoryId === CANCEL) return "cancel";
3899
3948
  if (selectedCategoryId === UNSELECT_ALL) {
3900
- keptSet = /* @__PURE__ */ new Set();
3901
- const toUninstall = [...installedSkills];
3949
+ for (const id of installedSkills) {
3950
+ uninstallSet.add(id);
3951
+ }
3902
3952
  const confirmed = await confirm({
3903
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
3953
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(installedSkills.length))),
3904
3954
  default: false
3905
3955
  });
3906
3956
  if (!confirmed) return "cancel";
3907
- return { toUninstall, toKeep: [] };
3957
+ return { toUninstall: [...uninstallSet], toKeep: [] };
3908
3958
  }
3909
3959
  if (selectedCategoryId === "uninstall") {
3910
- const toUninstall = installedSkills.filter((id) => !keptSet.has(id));
3911
- if (toUninstall.length === 0) {
3960
+ if (uninstallSet.size === 0) {
3912
3961
  logger.info(t("uninstall_nothing_to_uninstall"));
3913
3962
  return "back";
3914
3963
  }
3915
3964
  const confirmed = await confirm({
3916
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
3965
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(uninstallSet.size))),
3917
3966
  default: false
3918
3967
  });
3919
3968
  if (!confirmed) return "cancel";
3920
- return { toUninstall, toKeep: [...keptSet] };
3969
+ return { toUninstall: [...uninstallSet], toKeep: installedSkills.filter((id) => !uninstallSet.has(id)) };
3921
3970
  }
3922
3971
  step = 1;
3923
3972
  break;
@@ -3927,26 +3976,26 @@ async function interactiveSkillUnselect(tool, level) {
3927
3976
  if (!category) return "back";
3928
3977
  printBoxTitle(t("wizard_step_4_skill_title").replace("{category}", category.name));
3929
3978
  const categorySkillIds = new Set(category.skills.map((s) => s.id));
3930
- const keptInCategory = new Set([...keptSet].filter((id) => categorySkillIds.has(id)));
3979
+ const selectedInCategory = new Set([...uninstallSet].filter((id) => categorySkillIds.has(id)));
3931
3980
  const skillChoices = [
3932
3981
  {
3933
3982
  name: `>> ${t("uninstall_uncheck_all_category")}`,
3934
3983
  value: SELECT_ALL_CATEGORY,
3935
- checked: keptInCategory.size === 0,
3984
+ checked: selectedInCategory.size === category.skills.length,
3936
3985
  description: t("uninstall_uncheck_all_category")
3937
3986
  },
3938
3987
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
3939
3988
  ...category.skills.map((skill) => {
3940
- const isKept = keptInCategory.has(skill.id);
3989
+ const isSelected = selectedInCategory.has(skill.id);
3941
3990
  return {
3942
3991
  name: `${chalk5.cyan(skill.id)}`,
3943
3992
  value: skill.id,
3944
- checked: isKept,
3993
+ checked: isSelected,
3945
3994
  description: skill.description || ""
3946
3995
  };
3947
3996
  })
3948
3997
  ];
3949
- logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint")}`));
3998
+ logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint_select")}`));
3950
3999
  logger.blank();
3951
4000
  showOperationHints(true);
3952
4001
  const selectedSkills = await checkbox({
@@ -3957,20 +4006,20 @@ async function interactiveSkillUnselect(tool, level) {
3957
4006
  theme: checkboxTheme,
3958
4007
  pageSize: 15
3959
4008
  });
3960
- let keptInCat;
4009
+ let selectedInCat;
3961
4010
  if (selectedSkills.includes(SELECT_ALL_CATEGORY)) {
3962
- keptInCat = [];
4011
+ selectedInCat = category.skills.map((s) => s.id);
3963
4012
  } else {
3964
- keptInCat = selectedSkills.filter((id) => id !== SELECT_ALL_CATEGORY);
4013
+ selectedInCat = selectedSkills.filter((id) => id !== SELECT_ALL_CATEGORY);
3965
4014
  }
3966
4015
  for (const id of categorySkillIds) {
3967
- if (keptInCat.includes(id)) {
3968
- keptSet.add(id);
4016
+ if (selectedInCat.includes(id)) {
4017
+ uninstallSet.add(id);
3969
4018
  } else {
3970
- keptSet.delete(id);
4019
+ uninstallSet.delete(id);
3971
4020
  }
3972
4021
  }
3973
- const toUninstallCount = installedSkills.length - keptSet.size;
4022
+ const toUninstallCount = uninstallSet.size;
3974
4023
  const action = await select3({
3975
4024
  message: toUninstallCount > 0 ? t("uninstall_continue_or_confirm").replace("{count}", String(toUninstallCount)) : t("wizard_no_selection"),
3976
4025
  choices: toUninstallCount > 0 ? [
@@ -3988,17 +4037,16 @@ async function interactiveSkillUnselect(tool, level) {
3988
4037
  theme: selectTheme
3989
4038
  });
3990
4039
  if (action === "uninstall") {
3991
- const toUninstall = installedSkills.filter((id) => !keptSet.has(id));
3992
- if (toUninstall.length === 0) {
4040
+ if (uninstallSet.size === 0) {
3993
4041
  logger.info(t("uninstall_nothing_to_uninstall"));
3994
4042
  return "back";
3995
4043
  }
3996
4044
  const confirmed = await confirm({
3997
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
4045
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(uninstallSet.size))),
3998
4046
  default: false
3999
4047
  });
4000
4048
  if (!confirmed) return "cancel";
4001
- return { toUninstall, toKeep: [...keptSet] };
4049
+ return { toUninstall: [...uninstallSet], toKeep: installedSkills.filter((id) => !uninstallSet.has(id)) };
4002
4050
  }
4003
4051
  if (action === CONTINUE_SELECT) {
4004
4052
  step = 0;
@@ -5051,24 +5099,64 @@ async function uninstallRecent(tool, level, yes) {
5051
5099
  async function uninstallInteractive(defaultTool, defaultLevel) {
5052
5100
  let tool = defaultTool;
5053
5101
  let level = defaultLevel;
5054
- const typeChoices = [
5055
- { name: `> ${t("uninstall_type_skill")}`, value: "skill" },
5056
- { name: `> ${t("uninstall_type_plugin")}`, value: "plugin" },
5057
- new Separator4("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
5058
- { name: "x " + t("wizard_cancel"), value: "cancel" }
5059
- ];
5060
- showOperationHints();
5061
- const uninstallType = await select5({
5062
- message: t("uninstall_select_type"),
5063
- choices: typeChoices,
5064
- loop: false,
5065
- theme: selectTheme
5066
- });
5067
- if (uninstallType === "cancel") {
5068
- logger.info(t("init_cancelled"));
5102
+ const allInstalledPlugins = scanInstalled();
5103
+ const toolsWithPlugins = new Set(allInstalledPlugins.map((p) => `${p.tool}:${p.level}`));
5104
+ const toolsWithSkills = /* @__PURE__ */ new Set();
5105
+ for (const t2 of ["opencode", "claude", "trae", "cursor", "copilot", "codearts"]) {
5106
+ for (const l of ["project", "global"]) {
5107
+ const ip = l === "project" ? process.cwd() : getConfigRoot(t2, l);
5108
+ const skills = getInstalledSkills(t2, l, ip);
5109
+ if (skills.length > 0) {
5110
+ toolsWithSkills.add(`${t2}:${l}`);
5111
+ }
5112
+ }
5113
+ }
5114
+ const hasSkills = toolsWithSkills.size > 0;
5115
+ const hasPlugins = toolsWithPlugins.size > 0;
5116
+ if (!hasSkills && !hasPlugins) {
5117
+ logger.warn(t("uninstall_no_installed"));
5069
5118
  return;
5070
5119
  }
5071
- if (!process.env.INSTALL_HELPER_TOOL) {
5120
+ let uninstallType;
5121
+ if (hasSkills && hasPlugins) {
5122
+ printBoxTitle(t("uninstall_interactive_title"));
5123
+ const skillCount = [...toolsWithSkills].reduce((sum, key) => {
5124
+ const [t2, l] = key.split(":");
5125
+ const ip = l === "project" ? process.cwd() : getConfigRoot(t2, l);
5126
+ return sum + getInstalledSkills(t2, l, ip).length;
5127
+ }, 0);
5128
+ const pluginCount = allInstalledPlugins.length;
5129
+ const typeChoices = [
5130
+ { name: `> ${t("uninstall_type_skill")} (${skillCount})`, value: "skill" },
5131
+ { name: `> ${t("uninstall_type_plugin")} (${pluginCount})`, value: "plugin" },
5132
+ new Separator4("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
5133
+ { name: "x " + t("wizard_cancel"), value: "cancel" }
5134
+ ];
5135
+ showOperationHints();
5136
+ const choice = await select5({
5137
+ message: t("uninstall_select_type"),
5138
+ choices: typeChoices,
5139
+ loop: false,
5140
+ theme: selectTheme
5141
+ });
5142
+ if (choice === "cancel") {
5143
+ logger.info(t("init_cancelled"));
5144
+ return;
5145
+ }
5146
+ uninstallType = choice;
5147
+ } else if (hasSkills) {
5148
+ uninstallType = "skill";
5149
+ } else {
5150
+ uninstallType = "plugin";
5151
+ }
5152
+ const relevantKeys = uninstallType === "skill" ? toolsWithSkills : toolsWithPlugins;
5153
+ const toolsWithContent = /* @__PURE__ */ new Set();
5154
+ for (const key of relevantKeys) {
5155
+ toolsWithContent.add(key.split(":")[0]);
5156
+ }
5157
+ if (toolsWithContent.size === 1) {
5158
+ tool = [...toolsWithContent][0];
5159
+ } else if (!process.env.INSTALL_HELPER_TOOL) {
5072
5160
  const detected = await selectToolWithDetection();
5073
5161
  if (detected === "back" || detected === "cancel") {
5074
5162
  logger.info(t("init_cancelled"));
@@ -5076,7 +5164,16 @@ async function uninstallInteractive(defaultTool, defaultLevel) {
5076
5164
  }
5077
5165
  tool = detected;
5078
5166
  }
5079
- if (!process.env.INSTALL_HELPER_LEVEL) {
5167
+ const levelsWithContent = /* @__PURE__ */ new Set();
5168
+ for (const key of relevantKeys) {
5169
+ const [t2, l] = key.split(":");
5170
+ if (t2 === tool) {
5171
+ levelsWithContent.add(l);
5172
+ }
5173
+ }
5174
+ if (levelsWithContent.size === 1) {
5175
+ level = [...levelsWithContent][0];
5176
+ } else if (!process.env.INSTALL_HELPER_LEVEL) {
5080
5177
  const { stepLevel: stepLevel2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
5081
5178
  const levelResult = await stepLevel2();
5082
5179
  if (levelResult === "__back__" || levelResult === "__cancel__") {
@@ -5114,12 +5211,12 @@ async function interactivePluginUninstall(tool, level) {
5114
5211
  ...installed.map((inst) => ({
5115
5212
  name: `${chalk11.cyan(inst.displayName)} ${chalk11.dim(`(${inst.id})`)}`,
5116
5213
  value: inst.id,
5117
- checked: true,
5214
+ checked: false,
5118
5215
  description: `${inst.skillsCount} skills, ${inst.agentsCount} agents`
5119
5216
  }))
5120
5217
  ];
5121
5218
  printBoxTitle(t("uninstall_interactive_title"));
5122
- logger.info(chalk11.dim(` ${t("uninstall_checkbox_hint")}`));
5219
+ logger.info(chalk11.dim(` ${t("uninstall_checkbox_hint_select")}`));
5123
5220
  logger.blank();
5124
5221
  showOperationHints(true);
5125
5222
  const selected = await checkbox2({
@@ -5130,13 +5227,13 @@ async function interactivePluginUninstall(tool, level) {
5130
5227
  theme: checkboxTheme,
5131
5228
  pageSize: 15
5132
5229
  });
5133
- const toUninstall = installed.filter((inst) => !selected.includes(inst.id));
5230
+ const toUninstall = installed.filter((inst) => selected.includes(inst.id));
5134
5231
  if (toUninstall.length === 0) {
5135
5232
  logger.info(t("uninstall_nothing_to_uninstall"));
5136
5233
  return;
5137
5234
  }
5138
5235
  const confirmed = await confirm3({
5139
- message: t("uninstall_confirm_count").replace("{count}", chalk11.bold(String(toUninstall.length))),
5236
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk11.bold(String(toUninstall.length))),
5140
5237
  default: false
5141
5238
  });
5142
5239
  if (!confirmed) {