@cannbot-ai/install-helper 0.0.2-beta.66 → 0.0.2-beta.68

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
@@ -32,7 +32,6 @@ var zh_CN_default = {
32
32
  wizard_detect: "\u6B63\u5728\u68C0\u6D4B\u5DF2\u5B89\u88C5\u7684 AI \u7F16\u7A0B\u5DE5\u5177...",
33
33
  wizard_select_tool: "\u9009\u62E9 AI \u7F16\u7A0B\u5DE5\u5177",
34
34
  wizard_select_level: "\u9009\u62E9\u5B89\u88C5\u4F4D\u7F6E",
35
- wizard_select_plugins: "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
36
35
  wizard_select_plugin: "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
37
36
  wizard_confirm: "\u786E\u8BA4\u5B89\u88C5",
38
37
  wizard_detected_tool: "\u68C0\u6D4B\u5230",
@@ -91,8 +90,6 @@ var zh_CN_default = {
91
90
  error_not_installed: "\u672A\u5B89\u88C5",
92
91
  error_no_shell: "\u672A\u627E\u5230 bash \u6216 sh\uFF0C\u65E0\u6CD5\u6267\u884C\u5B89\u88C5\u811A\u672C\u3002\u8BF7\u5B89\u88C5 Git Bash \u6216 WSL",
93
92
  error_symlink_windows: "\u521B\u5EFA\u7B26\u53F7\u94FE\u63A5\u5931\u8D25\uFF0C\u8BF7\u4EE5\u7BA1\u7406\u5458\u8EAB\u4EFD\u8FD0\u884C\u6216\u5F00\u542F Windows \u5F00\u53D1\u8005\u6A21\u5F0F",
94
- quick_start: "\u542F\u52A8\u547D\u4EE4",
95
- quick_start_hint: "\u8BD5\u8BD5\u8F93\u5165: \u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50",
96
93
  skill_select_category: "\u9009\u62E9 Skill \u7C7B\u522B",
97
94
  skill_select_items: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills",
98
95
  skill_already_installed: "\u5DF2\u5B89\u88C5",
@@ -132,7 +129,6 @@ var zh_CN_default = {
132
129
  uninstall_no_record: "\u672A\u627E\u5230\u5B89\u88C5\u8BB0\u5F55\uFF0C\u53EF\u80FD\u672A\u5B89\u88C5\u6216\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
133
130
  uninstall_no_record_hint: "\u5982\u9700\u5F3A\u5236\u6E05\u7406\uFF0C\u8BF7\u624B\u52A8\u5220\u9664 .opencode/ \u6216 .claude/ \u76EE\u5F55\u4E2D\u7684\u76F8\u5173\u6587\u4EF6",
134
131
  uninstall_in_progress: "\u6B63\u5728\u5378\u8F7D",
135
- uninstall_removed: "\u5DF2\u5378\u8F7D",
136
132
  uninstall_summary_format: "{name}\uFF08\u79FB\u9664 {files} \u4E2A\u6587\u4EF6\uFF0C{dirs} \u4E2A\u76EE\u5F55\uFF09",
137
133
  uninstall_files_gone: "\u7684\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF0C\u5DF2\u6E05\u7406\u5B89\u88C5\u8BB0\u5F55",
138
134
  uninstall_skills_in_progress: "\u6B63\u5728\u5378\u8F7D",
@@ -166,6 +162,16 @@ var zh_CN_default = {
166
162
  skill_record_corrupted: "Skill \u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
167
163
  plugin_yaml_error: "\u63D2\u4EF6\u914D\u7F6E\u89E3\u6790\u5931\u8D25\uFF1A{file}",
168
164
  record_write_failed: "\u5B89\u88C5\u8BB0\u5F55\u5199\u5165\u5931\u8D25\uFF0C\u5378\u8F7D\u65F6\u53EF\u80FD\u65E0\u6CD5\u81EA\u52A8\u6E05\u7406",
165
+ install_config_failed: "\u914D\u7F6E\u6587\u4EF6\u5B89\u88C5\u5931\u8D25: {error}",
166
+ install_clone_failed: "git clone \u5931\u8D25: {url}\uFF0C\u8BF7\u624B\u52A8\u514B\u9686: git clone {url} {dir}",
167
+ install_link_config_failed: "\u94FE\u63A5 {name} \u5230\u914D\u7F6E\u76EE\u5F55\u5931\u8D25",
168
+ install_link_project_failed: "\u94FE\u63A5 {name} \u5230\u9879\u76EE\u76EE\u5F55\u5931\u8D25",
169
+ install_link_workflows_failed: "\u94FE\u63A5 workflows \u5230\u914D\u7F6E\u76EE\u5F55\u5931\u8D25",
170
+ install_skill_source_not_found: "Skill \u6E90\u76EE\u5F55\u672A\u627E\u5230: {dir}",
171
+ install_skill_not_found: "Skill \u672A\u627E\u5230: {name} (\u5728 {dir})",
172
+ install_skill_failed: "Skill \u5B89\u88C5\u5931\u8D25: {name}",
173
+ install_agent_not_found: "Agent \u672A\u627E\u5230: {name}",
174
+ install_agent_failed: "Agent \u5B89\u88C5\u5931\u8D25: {name}",
169
175
  install_no_skill_selected: "\u672A\u9009\u62E9\u4EFB\u4F55 Skill",
170
176
  install_to: "\u5B89\u88C5\u5230",
171
177
  start_to_use: "\u542F\u52A8 {tool} \u5373\u53EF\u4F7F\u7528",
@@ -182,8 +188,6 @@ var zh_CN_default = {
182
188
  result_success_format: "{count} \u6210\u529F",
183
189
  result_failed_format: "{count} \u5931\u8D25",
184
190
  uninstall_remove_label: "\u79FB\u9664",
185
- uninstall_remove_file_format: "\u79FB\u9664 {count} \u4E2A\u6587\u4EF6",
186
- uninstall_remove_dir_format: "{count} \u4E2A\u76EE\u5F55",
187
191
  uninstall_clean_empty_dir: "\u6E05\u7406\u7A7A\u76EE\u5F55",
188
192
  uninstall_skill_not_installed: "\u672A\u5B89\u88C5",
189
193
  available_plugins: "\u53EF\u7528\u63D2\u4EF6",
@@ -217,7 +221,6 @@ var en_US_default = {
217
221
  wizard_detect: "Detecting installed AI coding tools...",
218
222
  wizard_select_tool: "Select AI coding tool",
219
223
  wizard_select_level: "Select install level",
220
- wizard_select_plugins: "Select scenarios to install",
221
224
  wizard_select_plugin: "Select a scenario to install",
222
225
  wizard_confirm: "Confirm installation",
223
226
  wizard_detected_tool: "Detected",
@@ -276,8 +279,6 @@ var en_US_default = {
276
279
  error_not_installed: "Not installed",
277
280
  error_no_shell: "bash or sh not found, cannot execute install script. Please install Git Bash or WSL",
278
281
  error_symlink_windows: "Failed to create symlink, please run as administrator or enable Windows Developer Mode",
279
- quick_start: "Launch command",
280
- quick_start_hint: "Try: help me develop an Abs operator",
281
282
  skill_select_category: "Select Skill category",
282
283
  skill_select_items: "Select Skills to install (space to toggle, enter to confirm)",
283
284
  skill_already_installed: "installed",
@@ -317,7 +318,6 @@ var en_US_default = {
317
318
  uninstall_no_record: "No install record found, may not be installed or record is corrupted",
318
319
  uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
319
320
  uninstall_in_progress: "Uninstalling",
320
- uninstall_removed: "Uninstalled",
321
321
  uninstall_summary_format: "{name} (removed {files} files, {dirs} directories)",
322
322
  uninstall_files_gone: " files no longer exist, install record cleaned",
323
323
  uninstall_skills_in_progress: "Uninstalling",
@@ -351,6 +351,16 @@ var en_US_default = {
351
351
  skill_record_corrupted: "Skill install record corrupted",
352
352
  plugin_yaml_error: "Plugin config parse error: {file}",
353
353
  record_write_failed: "Install record write failed, uninstall may not work properly",
354
+ install_config_failed: "Failed to install config file: {error}",
355
+ install_clone_failed: "git clone failed: {url}, clone manually: git clone {url} {dir}",
356
+ install_link_config_failed: "Failed to link {name} to config directory",
357
+ install_link_project_failed: "Failed to link {name} to project directory",
358
+ install_link_workflows_failed: "Failed to link workflows to config directory",
359
+ install_skill_source_not_found: "Skill source not found: {dir}",
360
+ install_skill_not_found: "Skill not found: {name} in {dir}",
361
+ install_skill_failed: "Failed to install skill: {name}",
362
+ install_agent_not_found: "Agent not found: {name}",
363
+ install_agent_failed: "Failed to install agent: {name}",
354
364
  install_no_skill_selected: "No Skill selected",
355
365
  install_to: "Install to",
356
366
  start_to_use: "Start {tool} to use",
@@ -367,8 +377,6 @@ var en_US_default = {
367
377
  result_success_format: "{count} succeeded",
368
378
  result_failed_format: "{count} failed",
369
379
  uninstall_remove_label: "Removed",
370
- uninstall_remove_file_format: "Removed {count} files",
371
- uninstall_remove_dir_format: "{count} directories",
372
380
  uninstall_clean_empty_dir: "Cleaned empty directory",
373
381
  uninstall_skill_not_installed: "Not installed",
374
382
  available_plugins: "Available plugins",
@@ -587,8 +595,8 @@ var embedded_plugins_default = [
587
595
  "direct",
588
596
  "kernel"
589
597
  ],
590
- skills: 16,
591
- agents: 3,
598
+ skills: 19,
599
+ agents: 4,
592
600
  description: "Ascend C \u76F4\u8C03\u5168\u6D41\u7A0B\uFF1A\u73AF\u5883\u2192\u8BBE\u8BA1\u2192\u5F00\u53D1\u2192\u5BA1\u67E5\u2192\u6027\u80FD\u9A8C\u6536",
593
601
  version: "1.2.2",
594
602
  configFile: "AGENTS.md",
@@ -647,7 +655,7 @@ var embedded_plugins_default = [
647
655
  "flash",
648
656
  "kernel-flash"
649
657
  ],
650
- skills: 1,
658
+ skills: 7,
651
659
  agents: 1,
652
660
  description: "\u4ECE\u6570\u5B66\u516C\u5F0F\u6216\u4EE3\u7801\u7247\u6BB5\u5FEB\u901F\u6784\u5EFA\u5E76\u9A8C\u8BC1 Ascend NPU \u6838\u51FD\u6570",
653
661
  version: "1.2.2",
@@ -691,8 +699,8 @@ var embedded_plugins_default = [
691
699
  "ascendc-registry",
692
700
  "registry"
693
701
  ],
694
- skills: 12,
695
- agents: 4,
702
+ skills: 26,
703
+ agents: 3,
696
704
  description: "\u751F\u4EA7\u7EA7 ACLNN \u6CE8\u518C\u7B97\u5B50\u5168\u6D41\u7A0B\uFF1A\u4EE3\u7801\u2192UT/ST\u2192\u4E0A\u5E93",
697
705
  version: "1.2.2",
698
706
  configFile: "AGENTS.md",
@@ -764,7 +772,7 @@ var embedded_plugins_default = [
764
772
  aliases: [
765
773
  "catlass"
766
774
  ],
767
- skills: 10,
775
+ skills: 14,
768
776
  agents: 3,
769
777
  description: "Catlass \u6A21\u677F\u62FC\u88C5 GEMM/Matmul/Epilogue \u7B97\u5B50\u5F00\u53D1",
770
778
  version: "1.2.2",
@@ -814,7 +822,7 @@ var embedded_plugins_default = [
814
822
  "infer",
815
823
  "inference"
816
824
  ],
817
- skills: 11,
825
+ skills: 12,
818
826
  agents: 3,
819
827
  description: "NPU \u6A21\u578B\u63A8\u7406\u7AEF\u5230\u7AEF\u4F18\u5316\uFF08\u5E76\u884C/KVCache/\u878D\u5408/\u91CF\u5316/\u56FE\u6A21\u5F0F/\u591A\u6D41/SuperKernel\uFF09",
820
828
  version: "1.2.2",
@@ -950,7 +958,7 @@ var embedded_plugins_default = [
950
958
  "triton"
951
959
  ],
952
960
  skills: 6,
953
- agents: 1,
961
+ agents: 0,
954
962
  description: "Triton-Ascend \u7B97\u5B50 6 \u9636\u6BB5\u81EA\u52A8\u751F\u6210\u4E0E\u4F18\u5316\uFF08\u63CF\u8FF0\u2192\u4EE3\u7801\u2192\u9A8C\u8BC1\u2192\u4F18\u5316\uFF09",
955
963
  version: "1.2.2",
956
964
  configFile: "AGENTS.md",
@@ -1014,7 +1022,7 @@ var embedded_plugins_default = [
1014
1022
  "review"
1015
1023
  ],
1016
1024
  skills: 5,
1017
- agents: 1,
1025
+ agents: 2,
1018
1026
  description: "Ascend C \u7B97\u5B50\u4EE3\u7801 4 \u9636\u6BB5\u5168\u91CF\u68C0\u89C6\uFF08\u4E3B Agent \u7F16\u6392 + \u5B50 Agent \u5E76\u884C\u68C0\u89C6\uFF09",
1019
1027
  version: "1.2.2",
1020
1028
  configFile: "AGENTS.md",
@@ -1142,14 +1150,14 @@ function mergeDynamicPlugins(repoPath) {
1142
1150
  function findPlugin(query) {
1143
1151
  const normalized = query.toLowerCase().trim();
1144
1152
  const exactMatch = PLUGIN_REGISTRY.find(
1145
- (p) => p.id === normalized || p.id === query.trim()
1153
+ (p) => p.id.toLowerCase() === normalized || p.id === query.trim()
1146
1154
  );
1147
1155
  if (exactMatch) return exactMatch;
1148
1156
  const aliasMatch = PLUGIN_REGISTRY.find(
1149
- (p) => p.aliases.some((a) => a === normalized)
1157
+ (p) => p.aliases.some((a) => a.toLowerCase() === normalized)
1150
1158
  );
1151
1159
  if (aliasMatch) return aliasMatch;
1152
- const prefixMatch = PLUGIN_REGISTRY.find((p) => p.id.startsWith(normalized));
1160
+ const prefixMatch = PLUGIN_REGISTRY.find((p) => p.id.toLowerCase().startsWith(normalized));
1153
1161
  if (prefixMatch) return prefixMatch;
1154
1162
  return void 0;
1155
1163
  }
@@ -1393,7 +1401,6 @@ function readManifest(configRoot) {
1393
1401
  }
1394
1402
  function readAllManifests(configRoot) {
1395
1403
  const manifests = [];
1396
- const plugins = getAllPlugins();
1397
1404
  const standardPath = getManifestPath(configRoot);
1398
1405
  if (existsSync5(standardPath)) {
1399
1406
  try {
@@ -1402,16 +1409,6 @@ function readAllManifests(configRoot) {
1402
1409
  } catch {
1403
1410
  }
1404
1411
  }
1405
- for (const plugin of plugins) {
1406
- const pluginManifestPath = join5(configRoot, `${plugin.id}-manifest.json`);
1407
- if (existsSync5(pluginManifestPath)) {
1408
- try {
1409
- const content = readFileSync3(pluginManifestPath, "utf-8");
1410
- manifests.push(JSON.parse(content));
1411
- } catch {
1412
- }
1413
- }
1414
- }
1415
1412
  return manifests;
1416
1413
  }
1417
1414
  function scanInstalled() {
@@ -1465,13 +1462,9 @@ function verifyPluginFilesExist(configRoot, manifest, tool, level) {
1465
1462
  });
1466
1463
  if (!hasAnyAgent) return false;
1467
1464
  }
1468
- let agentsMdPath;
1469
- if (tool === "opencode" && level === "project") {
1470
- agentsMdPath = join5(configRoot, "..", "AGENTS.md");
1471
- } else {
1472
- agentsMdPath = join5(configRoot, "AGENTS.md");
1473
- }
1474
- if (!existsSync5(agentsMdPath)) return false;
1465
+ const agentsFileName = getAgentsFileName(tool);
1466
+ const configFilePath = level === "project" ? join5(configRoot, "..", agentsFileName) : join5(configRoot, agentsFileName);
1467
+ if (!existsSync5(configFilePath)) return false;
1475
1468
  return true;
1476
1469
  }
1477
1470
 
@@ -2226,7 +2219,7 @@ function deduplicate(skills) {
2226
2219
  function findSkill(query) {
2227
2220
  const normalized = query.toLowerCase().trim();
2228
2221
  const pool = getActiveSkills();
2229
- return pool.find((s) => s.id === normalized);
2222
+ return pool.find((s) => s.id.toLowerCase() === normalized);
2230
2223
  }
2231
2224
  function getAllSkills() {
2232
2225
  return getActiveSkills();
@@ -2255,9 +2248,9 @@ function loadRepoUrl() {
2255
2248
  const configPath = join8(__dirname4, "config", "repository.yaml");
2256
2249
  try {
2257
2250
  const config = parseYaml3(readFileSync6(configPath, "utf-8"));
2258
- return config.repository?.url || "https://gitcode.com/yanhf/cann_skills.git";
2251
+ return config.repository?.url || "https://gitcode.com/cann/cannbot-skills.git";
2259
2252
  } catch {
2260
- return "https://gitcode.com/yanhf/cann_skills.git";
2253
+ return "https://gitcode.com/cann/cannbot-skills.git";
2261
2254
  }
2262
2255
  }
2263
2256
  var REPO_URL = loadRepoUrl();
@@ -2355,7 +2348,7 @@ var RepositoryManager = class {
2355
2348
  return targetPath;
2356
2349
  } catch (error) {
2357
2350
  throw new Error(
2358
- `Failed to clone repository: ${error instanceof Error ? error.message : "Unknown error"}`
2351
+ `Failed to clone repository: ${error instanceof Error ? error.message : t("error_unknown")}`
2359
2352
  );
2360
2353
  }
2361
2354
  }
@@ -2424,11 +2417,13 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
2424
2417
  directories.push(agentsDir);
2425
2418
  for (const agentName of manifest.installed_agents || []) {
2426
2419
  const agentPath = join9(agentsDir, agentName);
2427
- const agentPathMd = join9(agentsDir, agentName + ".md");
2428
2420
  if (existsSync10(agentPath) || isSymlink(agentPath)) {
2429
2421
  files.push(agentPath);
2430
- } else if (existsSync10(agentPathMd) || isSymlink(agentPathMd)) {
2431
- files.push(agentPathMd);
2422
+ } else if (!agentName.endsWith(".md")) {
2423
+ const agentPathMd = join9(agentsDir, agentName + ".md");
2424
+ if (existsSync10(agentPathMd) || isSymlink(agentPathMd)) {
2425
+ files.push(agentPathMd);
2426
+ }
2432
2427
  }
2433
2428
  }
2434
2429
  }
@@ -2441,10 +2436,6 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
2441
2436
  if (existsSync10(manifestPath)) {
2442
2437
  files.push(manifestPath);
2443
2438
  }
2444
- const pluginManifestPath = join9(configRoot, `${pluginId}-manifest.json`);
2445
- if (existsSync10(pluginManifestPath)) {
2446
- files.push(pluginManifestPath);
2447
- }
2448
2439
  const configFileName = tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
2449
2440
  const configFilePath = level === "project" ? join9(installPath, configFileName) : join9(configRoot, configFileName);
2450
2441
  if (existsSync10(configFilePath)) {
@@ -2700,7 +2691,7 @@ async function showRestorePrompt(backups) {
2700
2691
  }
2701
2692
 
2702
2693
  // src/core/plugin-installer.ts
2703
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, realpathSync, copyFileSync as copyFileSync2, cpSync, writeFileSync as writeFileSync3, rmSync } from "fs";
2694
+ import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, realpathSync, copyFileSync as copyFileSync2, cpSync, writeFileSync as writeFileSync2, rmSync } from "fs";
2704
2695
  import { join as join11, basename } from "path";
2705
2696
  import { execa as execa3 } from "execa";
2706
2697
  function installLink(source, target) {
@@ -2749,7 +2740,7 @@ function installConfigFile(pluginDir, configFile, tool, level, configRoot, insta
2749
2740
  }
2750
2741
  }
2751
2742
  } catch (e) {
2752
- logger.warn(` Failed to install config file: ${e.message}`);
2743
+ logger.warn(t("install_config_failed").replace("{error}", e.message));
2753
2744
  }
2754
2745
  if (isProjectLevel && primaryTarget !== join11(configRoot, agentsFileName)) {
2755
2746
  if (configRootConfigLink === false) return;
@@ -2782,7 +2773,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2782
2773
  try {
2783
2774
  await execa3("git", args, { timeout: 12e4 });
2784
2775
  } catch {
2785
- logger.warn(` git clone failed: ${repo.url}, clone manually: git clone ${repo.url} ${repo.dir}`);
2776
+ logger.warn(t("install_clone_failed").replace("{url}", repo.url).replace("{dir}", repo.dir));
2786
2777
  try {
2787
2778
  rmSync(targetDir, { recursive: true, force: true });
2788
2779
  } catch {
@@ -2807,7 +2798,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2807
2798
  }
2808
2799
  }
2809
2800
  } catch {
2810
- logger.warn(` Failed to link ${linkName} to config directory`);
2801
+ logger.warn(t("install_link_config_failed").replace("{name}", linkName));
2811
2802
  }
2812
2803
  }
2813
2804
  if (level === "project") {
@@ -2824,7 +2815,7 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
2824
2815
  }
2825
2816
  }
2826
2817
  } catch {
2827
- logger.warn(` Failed to link ${linkName} to project directory`);
2818
+ logger.warn(t("install_link_project_failed").replace("{name}", linkName));
2828
2819
  }
2829
2820
  }
2830
2821
  }
@@ -2846,7 +2837,7 @@ function installWorkflows(pluginDir, configRoot) {
2846
2837
  }
2847
2838
  }
2848
2839
  } catch {
2849
- logger.warn(` Failed to link workflows to config directory`);
2840
+ logger.warn(t("install_link_workflows_failed"));
2850
2841
  }
2851
2842
  }
2852
2843
  function writeCannbotManifest(configRoot, pluginId, version, level, tool, skills, agents) {
@@ -2862,7 +2853,7 @@ function writeCannbotManifest(configRoot, pluginId, version, level, tool, skills
2862
2853
  install_time: (/* @__PURE__ */ new Date()).toISOString()
2863
2854
  };
2864
2855
  const manifestPath = join11(configRoot, "cannbot-manifest.json");
2865
- writeFileSync3(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
2856
+ writeFileSync2(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
2866
2857
  return manifest;
2867
2858
  }
2868
2859
  async function installViaManifest(plugin, repoPath, tool, level, installPath) {
@@ -2879,7 +2870,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2879
2870
  for (const source of plugin.installSkills || []) {
2880
2871
  const sourceDir = join11(repoPath, source.dir);
2881
2872
  if (!existsSync12(sourceDir)) {
2882
- logger.warn(` Skill source not found: ${source.dir}`);
2873
+ logger.warn(t("install_skill_source_not_found").replace("{dir}", source.dir));
2883
2874
  continue;
2884
2875
  }
2885
2876
  for (const skillEntry of source.skills) {
@@ -2887,7 +2878,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2887
2878
  const skillAlias = typeof skillEntry === "string" ? skillName : skillEntry.as || skillName;
2888
2879
  const skillPath = join11(sourceDir, skillName);
2889
2880
  if (!existsSync12(skillPath)) {
2890
- logger.warn(` Skill not found: ${skillName} in ${source.dir}`);
2881
+ logger.warn(t("install_skill_not_found").replace("{name}", skillName).replace("{dir}", source.dir));
2891
2882
  continue;
2892
2883
  }
2893
2884
  const targetPath = join11(skillsDir, skillAlias);
@@ -2895,7 +2886,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2895
2886
  if (result !== "failed") {
2896
2887
  installedSkills.push(skillAlias);
2897
2888
  } else {
2898
- logger.warn(` Failed to install skill: ${skillAlias}`);
2889
+ logger.warn(t("install_skill_failed").replace("{name}", skillAlias));
2899
2890
  }
2900
2891
  }
2901
2892
  }
@@ -2903,7 +2894,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2903
2894
  const agentFile = agentName.endsWith(".md") ? agentName : `${agentName}.md`;
2904
2895
  const agentPath = join11(pluginDir, "agents", agentFile);
2905
2896
  if (!existsSync12(agentPath)) {
2906
- logger.warn(` Agent not found: ${agentFile}`);
2897
+ logger.warn(t("install_agent_not_found").replace("{name}", agentFile));
2907
2898
  continue;
2908
2899
  }
2909
2900
  const targetPath = join11(agentsDir, agentFile);
@@ -2911,7 +2902,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2911
2902
  if (result !== "failed") {
2912
2903
  installedAgents.push(agentFile);
2913
2904
  } else {
2914
- logger.warn(` Failed to install agent: ${agentFile}`);
2905
+ logger.warn(t("install_agent_failed").replace("{name}", agentFile));
2915
2906
  }
2916
2907
  }
2917
2908
  installConfigFile(pluginDir, plugin.configFile || "AGENTS.md", tool, level, configRoot, cwd, plugin.configRootConfigLink);
@@ -2946,7 +2937,7 @@ async function installViaManifest(plugin, repoPath, tool, level, installPath) {
2946
2937
 
2947
2938
  // src/core/installer.ts
2948
2939
  function findShell() {
2949
- const candidates = process.platform === "win32" ? ["bash", "sh"] : ["bash", "sh"];
2940
+ const candidates = ["bash", "sh"];
2950
2941
  for (const cmd of candidates) {
2951
2942
  try {
2952
2943
  const detectCmd = process.platform === "win32" ? "where" : "which";
@@ -3155,8 +3146,8 @@ async function installPlugin(opts) {
3155
3146
  }
3156
3147
 
3157
3148
  // src/core/skill-installer.ts
3158
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readdirSync as readdirSync4, rmdirSync, realpathSync as realpathSync2 } from "fs";
3159
- import { join as join13, dirname as dirname6 } from "path";
3149
+ import { existsSync as existsSync14, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readdirSync as readdirSync4, rmSync as rmSync2, realpathSync as realpathSync2, copyFileSync as copyFileSync3 } from "fs";
3150
+ import { join as join13, dirname as dirname6, isAbsolute } from "path";
3160
3151
  import { select as select3, checkbox, Separator as Separator2 } from "@inquirer/prompts";
3161
3152
  import chalk5 from "chalk";
3162
3153
  import Table from "cli-table3";
@@ -3186,7 +3177,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
3186
3177
  if (existsSync14(targetPath) || isSymlink(targetPath)) {
3187
3178
  unlinkSync5(targetPath);
3188
3179
  }
3189
- symlinkSync2(resolvedSource, targetPath);
3180
+ try {
3181
+ symlinkSync2(resolvedSource, targetPath);
3182
+ } catch (e) {
3183
+ if (e instanceof Error && e.message.includes("EPERM")) {
3184
+ copyFileSync3(resolvedSource, targetPath);
3185
+ } else {
3186
+ throw e;
3187
+ }
3188
+ }
3190
3189
  results.push({ skillId, success: true });
3191
3190
  installedIds.push(skillId);
3192
3191
  } catch (error) {
@@ -3231,7 +3230,7 @@ async function uninstallSkills(skillIds, tool, level) {
3231
3230
  try {
3232
3231
  const entries = readdirSync4(skillsDir);
3233
3232
  if (entries.length === 0) {
3234
- rmdirSync(skillsDir);
3233
+ rmSync2(skillsDir, { recursive: true });
3235
3234
  logger.step(` ${t("uninstall_clean_empty_dir")}: skills/`);
3236
3235
  }
3237
3236
  } catch {
@@ -3410,7 +3409,7 @@ function listAllSkills() {
3410
3409
  }
3411
3410
  function resolveSkillSourcePath(skill, repoPath) {
3412
3411
  if (skill.filePath) {
3413
- const absPath = skill.filePath.startsWith("/") ? skill.filePath : join13(repoPath, skill.filePath);
3412
+ const absPath = isAbsolute(skill.filePath) ? skill.filePath : join13(repoPath, skill.filePath);
3414
3413
  if (existsSync14(absPath)) {
3415
3414
  return dirname6(absPath);
3416
3415
  }
@@ -4224,7 +4223,7 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
4224
4223
  }
4225
4224
 
4226
4225
  // src/commands/uninstall.ts
4227
- import { existsSync as existsSync17, unlinkSync as unlinkSync7, rmdirSync as rmdirSync2, readdirSync as readdirSync6 } from "fs";
4226
+ import { existsSync as existsSync17, unlinkSync as unlinkSync7, rmdirSync, readdirSync as readdirSync6 } from "fs";
4228
4227
  import { resolve, basename as basename3, sep } from "path";
4229
4228
  import chalk11 from "chalk";
4230
4229
  async function uninstallCommand(names, options) {
@@ -4284,7 +4283,7 @@ async function uninstallCommand(names, options) {
4284
4283
  if (existsSync17(dirPath)) {
4285
4284
  const entries = readdirSync6(dirPath);
4286
4285
  if (entries.length === 0) {
4287
- rmdirSync2(dirPath);
4286
+ rmdirSync(dirPath);
4288
4287
  const name = basename3(dirPath);
4289
4288
  logger.step(` ${t("uninstall_clean_empty_dir")}: ${name}/`);
4290
4289
  removedDirs++;