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

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
@@ -844,11 +844,12 @@ var init_zh_CN = __esm({
844
844
  doctor_result_without_fix: "{warnings} \u4E2A\u8B66\u544A",
845
845
  count_suffix: "\u4E2A",
846
846
  try_prompt: "\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50",
847
- uninstall_interactive_title: "\u7BA1\u7406\u5DF2\u5B89\u88C5\u7684\u5185\u5BB9 \u2014 \u53D6\u6D88\u52FE\u9009\u8981\u5378\u8F7D\u7684\u9879",
847
+ uninstall_interactive_title: "\u7BA1\u7406\u5DF2\u5B89\u88C5\u7684\u5185\u5BB9 \u2014 \u52FE\u9009\u8981\u5378\u8F7D\u7684\u9879",
848
848
  uninstall_select_type: "\u9009\u62E9\u8981\u5378\u8F7D\u7684\u7C7B\u578B",
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",
@@ -1066,11 +1067,12 @@ var init_en_US = __esm({
1066
1067
  doctor_result_without_fix: "{warnings} warnings",
1067
1068
  count_suffix: "",
1068
1069
  try_prompt: "help me develop an Abs operator",
1069
- uninstall_interactive_title: "Manage installed items \u2014 uncheck to uninstall",
1070
+ uninstall_interactive_title: "Manage installed items \u2014 check to uninstall",
1070
1071
  uninstall_select_type: "Select type to uninstall",
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",
@@ -1461,24 +1463,27 @@ function scanInstalled() {
1461
1463
  function verifyPluginFilesExist(configRoot, manifest, tool, level) {
1462
1464
  const skillsDir = join5(configRoot, "skills");
1463
1465
  const agentsDir = join5(configRoot, "agents");
1466
+ let hasAnyComponent = false;
1464
1467
  if (manifest.installed_skills && manifest.installed_skills.length > 0) {
1465
1468
  const hasAnySkill = manifest.installed_skills.some((skillId) => {
1466
1469
  const skillPath = join5(skillsDir, skillId);
1467
1470
  return existsSync5(skillPath);
1468
1471
  });
1469
- if (!hasAnySkill) return false;
1472
+ if (hasAnySkill) hasAnyComponent = true;
1470
1473
  }
1471
1474
  if (manifest.installed_agents && manifest.installed_agents.length > 0) {
1472
1475
  const hasAnyAgent = manifest.installed_agents.some((agentId) => {
1473
1476
  const agentPath = join5(agentsDir, agentId);
1474
1477
  return existsSync5(agentPath);
1475
1478
  });
1476
- if (!hasAnyAgent) return false;
1479
+ if (hasAnyAgent) hasAnyComponent = true;
1477
1480
  }
1478
1481
  const agentsFileName = getAgentsFileName(tool);
1479
1482
  const configFilePath = level === "project" ? join5(configRoot, "..", agentsFileName) : join5(configRoot, agentsFileName);
1480
- if (!existsSync5(configFilePath)) return false;
1481
- return true;
1483
+ if (existsSync5(configFilePath)) hasAnyComponent = true;
1484
+ const pluginManifestPath = join5(configRoot, `${manifest.team}-manifest.json`);
1485
+ if (existsSync5(pluginManifestPath)) hasAnyComponent = true;
1486
+ return hasAnyComponent;
1482
1487
  }
1483
1488
  var init_manifest = __esm({
1484
1489
  "src/core/manifest.ts"() {
@@ -3841,6 +3846,55 @@ async function interactiveSkillUnselect(tool, level) {
3841
3846
  logger.warn(t("uninstall_no_installed_skills"));
3842
3847
  return "back";
3843
3848
  }
3849
+ if (installedSkills.length <= 15) {
3850
+ return await flatSkillUnselect(installedSkills);
3851
+ }
3852
+ return await categorySkillUnselect(installedSkills);
3853
+ }
3854
+ async function flatSkillUnselect(installedSkills) {
3855
+ const categories = getAllCategories();
3856
+ const installedSet = new Set(installedSkills);
3857
+ const skillChoices = [
3858
+ ...installedSkills.map((skillId) => {
3859
+ const skill = findSkill(skillId);
3860
+ const cat = categories.find((c) => c.skills.some((s) => s.id === skillId));
3861
+ const catName = cat ? cat.name : "";
3862
+ const desc = skill?.description || "";
3863
+ return {
3864
+ name: `${chalk5.cyan(skillId)}${catName ? chalk5.dim(` [${catName}]`) : ""}`,
3865
+ value: skillId,
3866
+ checked: false,
3867
+ description: desc
3868
+ };
3869
+ })
3870
+ ];
3871
+ printBoxTitle(t("uninstall_interactive_title"));
3872
+ logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint_select")}`));
3873
+ logger.blank();
3874
+ showOperationHints(true);
3875
+ const selected = await checkbox({
3876
+ message: t("uninstall_select_items"),
3877
+ choices: skillChoices,
3878
+ loop: false,
3879
+ instructions: false,
3880
+ theme: checkboxTheme,
3881
+ pageSize: 20
3882
+ });
3883
+ if (selected.length === 0) {
3884
+ logger.info(t("uninstall_nothing_to_uninstall"));
3885
+ return "back";
3886
+ }
3887
+ const confirmed = await confirm({
3888
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(selected.length))),
3889
+ default: false
3890
+ });
3891
+ if (!confirmed) return "cancel";
3892
+ return {
3893
+ toUninstall: selected,
3894
+ toKeep: installedSkills.filter((id) => !selected.includes(id))
3895
+ };
3896
+ }
3897
+ async function categorySkillUnselect(installedSkills) {
3844
3898
  const allCategories = getAllCategories();
3845
3899
  const installedSet = new Set(installedSkills);
3846
3900
  const categoriesWithInstalled = allCategories.map((cat) => ({
@@ -3857,14 +3911,13 @@ async function interactiveSkillUnselect(tool, level) {
3857
3911
  skills: uncategorized.map((id) => ({ id, description: "", source: "", filePath: "" }))
3858
3912
  });
3859
3913
  }
3860
- let keptSet = new Set(installedSkills);
3914
+ const uninstallSet = /* @__PURE__ */ new Set();
3861
3915
  let step = 0;
3862
3916
  let selectedCategoryId = "";
3863
3917
  while (true) {
3864
3918
  switch (step) {
3865
3919
  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");
3920
+ 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
3921
  printBoxTitle(titleSuffix);
3869
3922
  const categoryChoices = [
3870
3923
  {
@@ -3873,16 +3926,15 @@ async function interactiveSkillUnselect(tool, level) {
3873
3926
  },
3874
3927
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
3875
3928
  ...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)`) : "";
3929
+ const catSelectedCount = cat.skills.filter((s) => uninstallSet.has(s.id)).length;
3930
+ const suffix = catSelectedCount > 0 ? chalk5.yellow(` (${catSelectedCount} selected)`) : "";
3879
3931
  return {
3880
3932
  name: `> ${cat.name} (${cat.skills.length} skills)${suffix}`,
3881
3933
  value: cat.id
3882
3934
  };
3883
3935
  }),
3884
3936
  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" }] : [],
3937
+ ...uninstallSet.size > 0 ? [{ name: `>> ${t("uninstall_confirm_count").replace("{count}", String(uninstallSet.size))}`, value: "uninstall" }] : [],
3886
3938
  { name: "<- " + t("wizard_back"), value: BACK },
3887
3939
  { name: "x " + t("wizard_cancel"), value: CANCEL }
3888
3940
  ];
@@ -3897,27 +3949,27 @@ async function interactiveSkillUnselect(tool, level) {
3897
3949
  if (selectedCategoryId === BACK) return "back";
3898
3950
  if (selectedCategoryId === CANCEL) return "cancel";
3899
3951
  if (selectedCategoryId === UNSELECT_ALL) {
3900
- keptSet = /* @__PURE__ */ new Set();
3901
- const toUninstall = [...installedSkills];
3952
+ for (const id of installedSkills) {
3953
+ uninstallSet.add(id);
3954
+ }
3902
3955
  const confirmed = await confirm({
3903
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
3956
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(installedSkills.length))),
3904
3957
  default: false
3905
3958
  });
3906
3959
  if (!confirmed) return "cancel";
3907
- return { toUninstall, toKeep: [] };
3960
+ return { toUninstall: [...uninstallSet], toKeep: [] };
3908
3961
  }
3909
3962
  if (selectedCategoryId === "uninstall") {
3910
- const toUninstall = installedSkills.filter((id) => !keptSet.has(id));
3911
- if (toUninstall.length === 0) {
3963
+ if (uninstallSet.size === 0) {
3912
3964
  logger.info(t("uninstall_nothing_to_uninstall"));
3913
3965
  return "back";
3914
3966
  }
3915
3967
  const confirmed = await confirm({
3916
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
3968
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(uninstallSet.size))),
3917
3969
  default: false
3918
3970
  });
3919
3971
  if (!confirmed) return "cancel";
3920
- return { toUninstall, toKeep: [...keptSet] };
3972
+ return { toUninstall: [...uninstallSet], toKeep: installedSkills.filter((id) => !uninstallSet.has(id)) };
3921
3973
  }
3922
3974
  step = 1;
3923
3975
  break;
@@ -3927,26 +3979,26 @@ async function interactiveSkillUnselect(tool, level) {
3927
3979
  if (!category) return "back";
3928
3980
  printBoxTitle(t("wizard_step_4_skill_title").replace("{category}", category.name));
3929
3981
  const categorySkillIds = new Set(category.skills.map((s) => s.id));
3930
- const keptInCategory = new Set([...keptSet].filter((id) => categorySkillIds.has(id)));
3982
+ const selectedInCategory = new Set([...uninstallSet].filter((id) => categorySkillIds.has(id)));
3931
3983
  const skillChoices = [
3932
3984
  {
3933
3985
  name: `>> ${t("uninstall_uncheck_all_category")}`,
3934
3986
  value: SELECT_ALL_CATEGORY,
3935
- checked: keptInCategory.size === 0,
3987
+ checked: selectedInCategory.size === category.skills.length,
3936
3988
  description: t("uninstall_uncheck_all_category")
3937
3989
  },
3938
3990
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
3939
3991
  ...category.skills.map((skill) => {
3940
- const isKept = keptInCategory.has(skill.id);
3992
+ const isSelected = selectedInCategory.has(skill.id);
3941
3993
  return {
3942
3994
  name: `${chalk5.cyan(skill.id)}`,
3943
3995
  value: skill.id,
3944
- checked: isKept,
3996
+ checked: isSelected,
3945
3997
  description: skill.description || ""
3946
3998
  };
3947
3999
  })
3948
4000
  ];
3949
- logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint")}`));
4001
+ logger.info(chalk5.dim(` ${t("uninstall_checkbox_hint_select")}`));
3950
4002
  logger.blank();
3951
4003
  showOperationHints(true);
3952
4004
  const selectedSkills = await checkbox({
@@ -3957,20 +4009,20 @@ async function interactiveSkillUnselect(tool, level) {
3957
4009
  theme: checkboxTheme,
3958
4010
  pageSize: 15
3959
4011
  });
3960
- let keptInCat;
4012
+ let selectedInCat;
3961
4013
  if (selectedSkills.includes(SELECT_ALL_CATEGORY)) {
3962
- keptInCat = [];
4014
+ selectedInCat = category.skills.map((s) => s.id);
3963
4015
  } else {
3964
- keptInCat = selectedSkills.filter((id) => id !== SELECT_ALL_CATEGORY);
4016
+ selectedInCat = selectedSkills.filter((id) => id !== SELECT_ALL_CATEGORY);
3965
4017
  }
3966
4018
  for (const id of categorySkillIds) {
3967
- if (keptInCat.includes(id)) {
3968
- keptSet.add(id);
4019
+ if (selectedInCat.includes(id)) {
4020
+ uninstallSet.add(id);
3969
4021
  } else {
3970
- keptSet.delete(id);
4022
+ uninstallSet.delete(id);
3971
4023
  }
3972
4024
  }
3973
- const toUninstallCount = installedSkills.length - keptSet.size;
4025
+ const toUninstallCount = uninstallSet.size;
3974
4026
  const action = await select3({
3975
4027
  message: toUninstallCount > 0 ? t("uninstall_continue_or_confirm").replace("{count}", String(toUninstallCount)) : t("wizard_no_selection"),
3976
4028
  choices: toUninstallCount > 0 ? [
@@ -3988,17 +4040,16 @@ async function interactiveSkillUnselect(tool, level) {
3988
4040
  theme: selectTheme
3989
4041
  });
3990
4042
  if (action === "uninstall") {
3991
- const toUninstall = installedSkills.filter((id) => !keptSet.has(id));
3992
- if (toUninstall.length === 0) {
4043
+ if (uninstallSet.size === 0) {
3993
4044
  logger.info(t("uninstall_nothing_to_uninstall"));
3994
4045
  return "back";
3995
4046
  }
3996
4047
  const confirmed = await confirm({
3997
- message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(toUninstall.length))),
4048
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk5.bold(String(uninstallSet.size))),
3998
4049
  default: false
3999
4050
  });
4000
4051
  if (!confirmed) return "cancel";
4001
- return { toUninstall, toKeep: [...keptSet] };
4052
+ return { toUninstall: [...uninstallSet], toKeep: installedSkills.filter((id) => !uninstallSet.has(id)) };
4002
4053
  }
4003
4054
  if (action === CONTINUE_SELECT) {
4004
4055
  step = 0;
@@ -5051,24 +5102,64 @@ async function uninstallRecent(tool, level, yes) {
5051
5102
  async function uninstallInteractive(defaultTool, defaultLevel) {
5052
5103
  let tool = defaultTool;
5053
5104
  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"));
5105
+ const allInstalledPlugins = scanInstalled();
5106
+ const toolsWithPlugins = new Set(allInstalledPlugins.map((p) => `${p.tool}:${p.level}`));
5107
+ const toolsWithSkills = /* @__PURE__ */ new Set();
5108
+ for (const t2 of ["opencode", "claude", "trae", "cursor", "copilot", "codearts"]) {
5109
+ for (const l of ["project", "global"]) {
5110
+ const ip = l === "project" ? process.cwd() : getConfigRoot(t2, l);
5111
+ const skills = getInstalledSkills(t2, l, ip);
5112
+ if (skills.length > 0) {
5113
+ toolsWithSkills.add(`${t2}:${l}`);
5114
+ }
5115
+ }
5116
+ }
5117
+ const hasSkills = toolsWithSkills.size > 0;
5118
+ const hasPlugins = toolsWithPlugins.size > 0;
5119
+ if (!hasSkills && !hasPlugins) {
5120
+ logger.warn(t("uninstall_no_installed"));
5069
5121
  return;
5070
5122
  }
5071
- if (!process.env.INSTALL_HELPER_TOOL) {
5123
+ let uninstallType;
5124
+ if (hasSkills && hasPlugins) {
5125
+ printBoxTitle(t("uninstall_interactive_title"));
5126
+ const skillCount = [...toolsWithSkills].reduce((sum, key) => {
5127
+ const [t2, l] = key.split(":");
5128
+ const ip = l === "project" ? process.cwd() : getConfigRoot(t2, l);
5129
+ return sum + getInstalledSkills(t2, l, ip).length;
5130
+ }, 0);
5131
+ const pluginCount = allInstalledPlugins.length;
5132
+ const typeChoices = [
5133
+ { name: `> ${t("uninstall_type_skill")} (${skillCount})`, value: "skill" },
5134
+ { name: `> ${t("uninstall_type_plugin")} (${pluginCount})`, value: "plugin" },
5135
+ new Separator4("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
5136
+ { name: "x " + t("wizard_cancel"), value: "cancel" }
5137
+ ];
5138
+ showOperationHints();
5139
+ const choice = await select5({
5140
+ message: t("uninstall_select_type"),
5141
+ choices: typeChoices,
5142
+ loop: false,
5143
+ theme: selectTheme
5144
+ });
5145
+ if (choice === "cancel") {
5146
+ logger.info(t("init_cancelled"));
5147
+ return;
5148
+ }
5149
+ uninstallType = choice;
5150
+ } else if (hasSkills) {
5151
+ uninstallType = "skill";
5152
+ } else {
5153
+ uninstallType = "plugin";
5154
+ }
5155
+ const relevantKeys = uninstallType === "skill" ? toolsWithSkills : toolsWithPlugins;
5156
+ const toolsWithContent = /* @__PURE__ */ new Set();
5157
+ for (const key of relevantKeys) {
5158
+ toolsWithContent.add(key.split(":")[0]);
5159
+ }
5160
+ if (toolsWithContent.size === 1) {
5161
+ tool = [...toolsWithContent][0];
5162
+ } else if (!process.env.INSTALL_HELPER_TOOL) {
5072
5163
  const detected = await selectToolWithDetection();
5073
5164
  if (detected === "back" || detected === "cancel") {
5074
5165
  logger.info(t("init_cancelled"));
@@ -5076,7 +5167,16 @@ async function uninstallInteractive(defaultTool, defaultLevel) {
5076
5167
  }
5077
5168
  tool = detected;
5078
5169
  }
5079
- if (!process.env.INSTALL_HELPER_LEVEL) {
5170
+ const levelsWithContent = /* @__PURE__ */ new Set();
5171
+ for (const key of relevantKeys) {
5172
+ const [t2, l] = key.split(":");
5173
+ if (t2 === tool) {
5174
+ levelsWithContent.add(l);
5175
+ }
5176
+ }
5177
+ if (levelsWithContent.size === 1) {
5178
+ level = [...levelsWithContent][0];
5179
+ } else if (!process.env.INSTALL_HELPER_LEVEL) {
5080
5180
  const { stepLevel: stepLevel2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
5081
5181
  const levelResult = await stepLevel2();
5082
5182
  if (levelResult === "__back__" || levelResult === "__cancel__") {
@@ -5114,12 +5214,12 @@ async function interactivePluginUninstall(tool, level) {
5114
5214
  ...installed.map((inst) => ({
5115
5215
  name: `${chalk11.cyan(inst.displayName)} ${chalk11.dim(`(${inst.id})`)}`,
5116
5216
  value: inst.id,
5117
- checked: true,
5217
+ checked: false,
5118
5218
  description: `${inst.skillsCount} skills, ${inst.agentsCount} agents`
5119
5219
  }))
5120
5220
  ];
5121
5221
  printBoxTitle(t("uninstall_interactive_title"));
5122
- logger.info(chalk11.dim(` ${t("uninstall_checkbox_hint")}`));
5222
+ logger.info(chalk11.dim(` ${t("uninstall_checkbox_hint_select")}`));
5123
5223
  logger.blank();
5124
5224
  showOperationHints(true);
5125
5225
  const selected = await checkbox2({
@@ -5130,13 +5230,13 @@ async function interactivePluginUninstall(tool, level) {
5130
5230
  theme: checkboxTheme,
5131
5231
  pageSize: 15
5132
5232
  });
5133
- const toUninstall = installed.filter((inst) => !selected.includes(inst.id));
5233
+ const toUninstall = installed.filter((inst) => selected.includes(inst.id));
5134
5234
  if (toUninstall.length === 0) {
5135
5235
  logger.info(t("uninstall_nothing_to_uninstall"));
5136
5236
  return;
5137
5237
  }
5138
5238
  const confirmed = await confirm3({
5139
- message: t("uninstall_confirm_count").replace("{count}", chalk11.bold(String(toUninstall.length))),
5239
+ message: t("uninstall_confirm_prompt").replace("{count}", chalk11.bold(String(toUninstall.length))),
5140
5240
  default: false
5141
5241
  });
5142
5242
  if (!confirmed) {