@cannbot-ai/install-helper 1.1.4 → 1.1.5-beta.1

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
@@ -16,7 +16,7 @@ import { readdirSync, existsSync } from "fs";
16
16
  import { join } from "path";
17
17
 
18
18
  // src/utils/fs-helpers.ts
19
- import { lstatSync, statSync } from "fs";
19
+ import { lstatSync, statSync, unlinkSync, rmSync } from "fs";
20
20
  function isSymlink(path) {
21
21
  try {
22
22
  return lstatSync(path).isSymbolicLink();
@@ -31,6 +31,17 @@ function isDirectory(path) {
31
31
  return false;
32
32
  }
33
33
  }
34
+ function removePath(p) {
35
+ try {
36
+ const stat = lstatSync(p);
37
+ if (stat.isDirectory()) {
38
+ rmSync(p, { recursive: true, force: true });
39
+ } else {
40
+ unlinkSync(p);
41
+ }
42
+ } catch {
43
+ }
44
+ }
34
45
 
35
46
  // src/embedded-plugins.json
36
47
  var embedded_plugins_default = [
@@ -616,8 +627,8 @@ function findPlugin(query) {
616
627
  (p) => p.aliases.some((a) => a === normalized)
617
628
  );
618
629
  if (aliasMatch) return aliasMatch;
619
- const prefixMatch = PLUGIN_REGISTRY.find((p) => p.id.startsWith(normalized));
620
- if (prefixMatch) return prefixMatch;
630
+ const prefixMatches = PLUGIN_REGISTRY.filter((p) => p.id.startsWith(normalized));
631
+ if (prefixMatches.length === 1) return prefixMatches[0];
621
632
  return void 0;
622
633
  }
623
634
  function getAllPlugins() {
@@ -780,7 +791,6 @@ var zh_CN_default = {
780
791
  config_corrupted: "\u914D\u7F6E\u6587\u4EF6\u5DF2\u635F\u574F\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E",
781
792
  record_corrupted: "\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F\uFF1A{file}",
782
793
  skill_record_corrupted: "Skill \u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
783
- plugin_yaml_error: "\u63D2\u4EF6\u914D\u7F6E\u89E3\u6790\u5931\u8D25\uFF1A{file}",
784
794
  record_write_failed: "\u5B89\u88C5\u8BB0\u5F55\u5199\u5165\u5931\u8D25\uFF0C\u5378\u8F7D\u65F6\u53EF\u80FD\u65E0\u6CD5\u81EA\u52A8\u6E05\u7406",
785
795
  install_config_failed: "\u914D\u7F6E\u6587\u4EF6\u5B89\u88C5\u5931\u8D25: {error}",
786
796
  install_clone_failed: "git clone \u5931\u8D25: {url}\uFF0C\u8BF7\u624B\u52A8\u514B\u9686: git clone {url} {dir}",
@@ -972,7 +982,6 @@ var en_US_default = {
972
982
  config_corrupted: "Config file corrupted, using defaults",
973
983
  record_corrupted: "Install record corrupted: {file}",
974
984
  skill_record_corrupted: "Skill install record corrupted",
975
- plugin_yaml_error: "Plugin config parse error: {file}",
976
985
  record_write_failed: "Install record write failed, uninstall may not work properly",
977
986
  install_config_failed: "Failed to install config file: {error}",
978
987
  install_clone_failed: "git clone failed: {url}, clone manually: git clone {url} {dir}",
@@ -1514,7 +1523,7 @@ import { join as join6 } from "path";
1514
1523
  import { parse, stringify } from "yaml";
1515
1524
 
1516
1525
  // src/utils/fs.ts
1517
- import { writeFileSync, renameSync, existsSync as existsSync6 } from "fs";
1526
+ import { writeFileSync, renameSync, existsSync as existsSync6, unlinkSync as unlinkSync2 } from "fs";
1518
1527
  import { dirname as dirname2 } from "path";
1519
1528
  function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
1520
1529
  const dir = dirname2(filePath);
@@ -1523,7 +1532,15 @@ function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
1523
1532
  }
1524
1533
  const tmpPath = `${filePath}.tmp`;
1525
1534
  writeFileSync(tmpPath, data, encoding);
1526
- renameSync(tmpPath, filePath);
1535
+ try {
1536
+ renameSync(tmpPath, filePath);
1537
+ } catch (e) {
1538
+ try {
1539
+ unlinkSync2(tmpPath);
1540
+ } catch {
1541
+ }
1542
+ throw e;
1543
+ }
1527
1544
  }
1528
1545
 
1529
1546
  // src/utils/config.ts
@@ -1827,7 +1844,7 @@ async function stepConfirm(tool, level, plugins) {
1827
1844
  }
1828
1845
 
1829
1846
  // src/core/repository.ts
1830
- import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync } from "fs";
1847
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs";
1831
1848
  import { join as join9, dirname as dirname4 } from "path";
1832
1849
  import { fileURLToPath as fileURLToPath3 } from "url";
1833
1850
  import { execa as execa2 } from "execa";
@@ -2477,7 +2494,7 @@ var RepositoryManager = class {
2477
2494
  this.repoPath = targetPath;
2478
2495
  return targetPath;
2479
2496
  }
2480
- rmSync(targetPath, { recursive: true, force: true });
2497
+ rmSync2(targetPath, { recursive: true, force: true });
2481
2498
  }
2482
2499
  try {
2483
2500
  logger.info(t("repo_cloning"));
@@ -2505,7 +2522,7 @@ import { join as join13, basename as basename2 } from "path";
2505
2522
  import { execa as execa4, execaSync } from "execa";
2506
2523
 
2507
2524
  // src/core/record.ts
2508
- import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync } from "fs";
2525
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync3 } from "fs";
2509
2526
  import { join as join10 } from "path";
2510
2527
  function getInstallsDir() {
2511
2528
  return join10(getCannbotConfigDir(), "installs");
@@ -2537,7 +2554,7 @@ function writeRecord(record) {
2537
2554
  function deleteRecord(pluginId) {
2538
2555
  const recordPath = getRecordPath(pluginId);
2539
2556
  if (existsSync11(recordPath)) {
2540
- unlinkSync(recordPath);
2557
+ unlinkSync3(recordPath);
2541
2558
  }
2542
2559
  }
2543
2560
  function scanInstalledFiles(pluginId, displayName, tool, level, installPath, configRoot, manifest, externalRepoNames) {
@@ -2676,7 +2693,7 @@ function getInstalledSkills(tool, level, installPath) {
2676
2693
  }
2677
2694
 
2678
2695
  // src/core/backup.ts
2679
- import { existsSync as existsSync12, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
2696
+ import { existsSync as existsSync12, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
2680
2697
  import { join as join11 } from "path";
2681
2698
  function detectCurrentPlugin(configRoot, tool, installPath) {
2682
2699
  const manifests = readAllManifests(configRoot);
@@ -2775,7 +2792,7 @@ function restoreBackup(backupPath, configRoot, tool) {
2775
2792
  function deleteBackup(backupPath) {
2776
2793
  try {
2777
2794
  if (existsSync12(backupPath)) {
2778
- unlinkSync2(backupPath);
2795
+ unlinkSync4(backupPath);
2779
2796
  return true;
2780
2797
  }
2781
2798
  return false;
@@ -2843,7 +2860,7 @@ async function showRestorePrompt(backups) {
2843
2860
  }
2844
2861
 
2845
2862
  // src/core/plugin-installer.ts
2846
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, realpathSync, readlinkSync, copyFileSync as copyFileSync2, cpSync, writeFileSync as writeFileSync2, rmSync as rmSync2 } from "fs";
2863
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, symlinkSync, realpathSync, readlinkSync, copyFileSync as copyFileSync2, cpSync, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "fs";
2847
2864
  import { join as join12, basename } from "path";
2848
2865
  import { execa as execa3 } from "execa";
2849
2866
  function installLink(source, target) {
@@ -2862,7 +2879,7 @@ function installLink(source, target) {
2862
2879
  }
2863
2880
  }
2864
2881
  if (existsSync13(target) || isSymlink(target)) {
2865
- unlinkSync3(target);
2882
+ removePath(target);
2866
2883
  }
2867
2884
  try {
2868
2885
  symlinkSync(resolved, target);
@@ -2892,7 +2909,7 @@ function installConfigFile(pluginDir, configFile, tool, level, configRoot, insta
2892
2909
  try {
2893
2910
  const resolvedSource = realpathSync(sourcePath);
2894
2911
  if (existsSync13(primaryTarget) || isSymlink(primaryTarget)) {
2895
- unlinkSync3(primaryTarget);
2912
+ removePath(primaryTarget);
2896
2913
  }
2897
2914
  try {
2898
2915
  symlinkSync(resolvedSource, primaryTarget);
@@ -2910,7 +2927,7 @@ function installConfigFile(pluginDir, configFile, tool, level, configRoot, insta
2910
2927
  if (configRootConfigLink === false) return;
2911
2928
  const configRootTarget = join12(configRoot, agentsFileName);
2912
2929
  if (existsSync13(configRootTarget) || isSymlink(configRootTarget)) {
2913
- unlinkSync3(configRootTarget);
2930
+ removePath(configRootTarget);
2914
2931
  }
2915
2932
  try {
2916
2933
  symlinkSync(realpathSync(sourcePath), configRootTarget);
@@ -2931,6 +2948,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2931
2948
  await execa3("git", ["pull", "--quiet"], { cwd: targetDir, timeout: 12e4 });
2932
2949
  } catch {
2933
2950
  logger.warn(t("external_repo_update_failed").replace("{dir}", repo.dir));
2951
+ continue;
2934
2952
  }
2935
2953
  } else if (!existsSync13(targetDir)) {
2936
2954
  const args = ["clone"];
@@ -2946,7 +2964,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2946
2964
  } catch {
2947
2965
  logger.warn(t("install_clone_failed").replace("{url}", repo.url).replace("{dir}", repo.dir));
2948
2966
  try {
2949
- rmSync2(targetDir, { recursive: true, force: true });
2967
+ rmSync3(targetDir, { recursive: true, force: true });
2950
2968
  } catch {
2951
2969
  }
2952
2970
  continue;
@@ -2959,7 +2977,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2959
2977
  const configRootLink = join12(configRoot, linkName);
2960
2978
  try {
2961
2979
  if (existsSync13(configRootLink) || isSymlink(configRootLink)) {
2962
- unlinkSync3(configRootLink);
2980
+ removePath(configRootLink);
2963
2981
  }
2964
2982
  try {
2965
2983
  symlinkSync(resolved, configRootLink);
@@ -2976,7 +2994,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2976
2994
  const projectLink = join12(installPath, linkName);
2977
2995
  try {
2978
2996
  if (existsSync13(projectLink) || isSymlink(projectLink)) {
2979
- unlinkSync3(projectLink);
2997
+ removePath(projectLink);
2980
2998
  }
2981
2999
  try {
2982
3000
  symlinkSync(resolved, projectLink);
@@ -2998,7 +3016,7 @@ function installWorkflows(pluginDir, configRoot) {
2998
3016
  try {
2999
3017
  const resolved = realpathSync(workflowsDir);
3000
3018
  if (existsSync13(targetPath) || isSymlink(targetPath)) {
3001
- unlinkSync3(targetPath);
3019
+ removePath(targetPath);
3002
3020
  }
3003
3021
  try {
3004
3022
  symlinkSync(resolved, targetPath);
@@ -3319,7 +3337,7 @@ async function installPlugin(opts) {
3319
3337
  }
3320
3338
 
3321
3339
  // src/core/skill-installer.ts
3322
- import { existsSync as existsSync15, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmSync as rmSync3, realpathSync as realpathSync2, readlinkSync as readlinkSync2, cpSync as cpSync2 } from "fs";
3340
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, readdirSync as readdirSync4, rmSync as rmSync4, realpathSync as realpathSync2, readlinkSync as readlinkSync2, cpSync as cpSync2 } from "fs";
3323
3341
  import { join as join14, dirname as dirname5, isAbsolute } from "path";
3324
3342
  import { select as select3, checkbox, Separator as Separator2 } from "@inquirer/prompts";
3325
3343
  import chalk5 from "chalk";
@@ -3364,7 +3382,7 @@ async function installSkills(skillIds, tool, level, repoPath) {
3364
3382
  }
3365
3383
  }
3366
3384
  if (existsSync15(targetPath) || isSymlink(targetPath)) {
3367
- unlinkSync4(targetPath);
3385
+ removePath(targetPath);
3368
3386
  }
3369
3387
  try {
3370
3388
  symlinkSync2(resolvedSource, targetPath);
@@ -3400,7 +3418,7 @@ async function uninstallSkills(skillIds, tool, level) {
3400
3418
  const targetPath = join14(skillsDir, skillId);
3401
3419
  try {
3402
3420
  if (existsSync15(targetPath) || isSymlink(targetPath)) {
3403
- unlinkSync4(targetPath);
3421
+ removePath(targetPath);
3404
3422
  results.push({ skillId, success: true });
3405
3423
  removedIds.push(skillId);
3406
3424
  logger.step(` ${t("uninstall_remove_label")}: ${skillId}`);
@@ -3419,7 +3437,7 @@ async function uninstallSkills(skillIds, tool, level) {
3419
3437
  try {
3420
3438
  const entries = readdirSync4(skillsDir);
3421
3439
  if (entries.length === 0) {
3422
- rmSync3(skillsDir, { recursive: true });
3440
+ rmSync4(skillsDir, { recursive: true });
3423
3441
  logger.step(` ${t("uninstall_clean_empty_dir")}: skills/`);
3424
3442
  }
3425
3443
  } catch {
@@ -4580,17 +4598,21 @@ async function uninstallCommand(names, options) {
4580
4598
  // src/commands/update.ts
4581
4599
  import chalk12 from "chalk";
4582
4600
  async function updateCommand(pluginNames, options) {
4601
+ const repoManager = createRepositoryManager();
4602
+ const updateSpinner = createSpinner(t("update_updating") + "...");
4603
+ updateSpinner.start();
4604
+ let repoPath;
4605
+ try {
4606
+ repoPath = await repoManager.ensureRepoAndScan();
4607
+ updateSpinner.succeed(t("install_repo_ready"));
4608
+ } catch (error) {
4609
+ updateSpinner.fail(t("repo_clone_failed").replace("{error}", error instanceof Error ? error.message : t("error_unknown")).replace("{url}", "").replace("{dir}", ""));
4610
+ return;
4611
+ }
4583
4612
  const installed = scanInstalled();
4584
4613
  let targets = [];
4585
4614
  if (pluginNames.length === 0) {
4586
4615
  if (installed.length === 0) {
4587
- if (!options.tool) {
4588
- const detected = await selectToolWithDetection();
4589
- if (detected === "back" || detected === "cancel") {
4590
- logger.info(t("init_cancelled"));
4591
- return;
4592
- }
4593
- }
4594
4616
  logger.info(t("update_no_plugins"));
4595
4617
  logger.info(t("update_install_hint").replace("{cmd}", chalk12.cyan("install-helper install <plugin>")));
4596
4618
  return;
@@ -4627,17 +4649,6 @@ async function updateCommand(pluginNames, options) {
4627
4649
  logger.info(t("update_no_plugins"));
4628
4650
  return;
4629
4651
  }
4630
- const repoManager = createRepositoryManager();
4631
- const updateSpinner = createSpinner(t("update_updating") + "...");
4632
- updateSpinner.start();
4633
- let repoPath;
4634
- try {
4635
- repoPath = await repoManager.ensureRepoAndScan();
4636
- updateSpinner.succeed(t("install_repo_ready"));
4637
- } catch (error) {
4638
- updateSpinner.fail(t("repo_clone_failed").replace("{error}", error instanceof Error ? error.message : t("error_unknown")).replace("{url}", "").replace("{dir}", ""));
4639
- return;
4640
- }
4641
4652
  const allPlugins = getAllPlugins();
4642
4653
  const results = [];
4643
4654
  const total = targets.length;