@cannbot-ai/install-helper 0.0.2-beta.37 → 0.0.2-beta.39

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
@@ -195,8 +195,19 @@ function isDirectory(path) {
195
195
  // src/core/registry.ts
196
196
  var __filename2 = fileURLToPath2(import.meta.url);
197
197
  var __dirname2 = dirname2(__filename2);
198
+ function findPluginsDir() {
199
+ const candidates = [
200
+ join2(__dirname2, "plugins.d"),
201
+ join2(__dirname2, "..", "plugins.d"),
202
+ join2(__dirname2, "..", "..", "plugins.d")
203
+ ];
204
+ for (const dir of candidates) {
205
+ if (existsSync(dir)) return dir;
206
+ }
207
+ return candidates[0];
208
+ }
198
209
  function loadPluginsFromYaml() {
199
- const pluginsDir = join2(__dirname2, "plugins.d");
210
+ const pluginsDir = findPluginsDir();
200
211
  const defaultsPath = join2(pluginsDir, "_defaults.yml");
201
212
  let defaults = {};
202
213
  try {
@@ -388,6 +399,9 @@ function getConfigRoot(tool, level, base) {
388
399
  function getConfigFileName(tool) {
389
400
  return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
390
401
  }
402
+ function getAgentsFileName(tool) {
403
+ return getConfigFileName(tool);
404
+ }
391
405
  function getSkillsDir(configRoot) {
392
406
  return join3(configRoot, "skills");
393
407
  }
@@ -1502,9 +1516,9 @@ function createRepositoryManager(customPath) {
1502
1516
  }
1503
1517
 
1504
1518
  // src/core/installer.ts
1505
- import { existsSync as existsSync11 } from "fs";
1506
- import { join as join11 } from "path";
1507
- import { execa as execa3 } from "execa";
1519
+ import { existsSync as existsSync12 } from "fs";
1520
+ import { join as join12 } from "path";
1521
+ import { execa as execa4 } from "execa";
1508
1522
 
1509
1523
  // src/core/record.ts
1510
1524
  import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
@@ -1836,39 +1850,211 @@ async function showRestorePrompt(backups) {
1836
1850
  return choice;
1837
1851
  }
1838
1852
 
1839
- // src/core/installer.ts
1840
- async function installPlugin(opts) {
1841
- const plugin = getPluginById(opts.pluginId);
1842
- if (!plugin) {
1853
+ // src/core/plugin-installer.ts
1854
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, realpathSync, copyFileSync as copyFileSync2, cpSync, writeFileSync as writeFileSync3, readFileSync as readFileSync8 } from "fs";
1855
+ import { join as join11 } from "path";
1856
+ import { execa as execa3 } from "execa";
1857
+ function readPluginManifest(pluginDir) {
1858
+ const manifestPath = join11(pluginDir, "plugin-manifest.json");
1859
+ if (!existsSync11(manifestPath)) return null;
1860
+ try {
1861
+ const content = JSON.parse(readFileSync8(manifestPath, "utf-8"));
1862
+ if (!content || !content.id) return null;
1863
+ return content;
1864
+ } catch {
1865
+ return null;
1866
+ }
1867
+ }
1868
+ function installLink(source, target) {
1869
+ try {
1870
+ const resolved = realpathSync(source);
1871
+ if (existsSync11(target) || isSymlink(target)) {
1872
+ unlinkSync4(target);
1873
+ }
1874
+ try {
1875
+ symlinkSync(resolved, target);
1876
+ return "symlink";
1877
+ } catch (e) {
1878
+ if (e.code === "EPERM") {
1879
+ cpSync(resolved, target, { recursive: true });
1880
+ return "copy";
1881
+ }
1882
+ throw e;
1883
+ }
1884
+ } catch {
1885
+ return "failed";
1886
+ }
1887
+ }
1888
+ function installConfigFile(pluginDir, configFile, tool, level, configRoot, installPath) {
1889
+ const sourcePath = join11(pluginDir, configFile);
1890
+ if (!existsSync11(sourcePath)) return;
1891
+ const agentsFileName = getAgentsFileName(tool);
1892
+ const isProjectLevel = level === "project";
1893
+ let primaryTarget;
1894
+ if (isProjectLevel) {
1895
+ primaryTarget = join11(installPath, agentsFileName);
1896
+ } else {
1897
+ primaryTarget = join11(configRoot, agentsFileName);
1898
+ }
1899
+ if (existsSync11(primaryTarget) || isSymlink(primaryTarget)) {
1900
+ unlinkSync4(primaryTarget);
1901
+ }
1902
+ try {
1903
+ symlinkSync(realpathSync(sourcePath), primaryTarget);
1904
+ } catch (e) {
1905
+ if (e.code === "EPERM") {
1906
+ copyFileSync2(sourcePath, primaryTarget);
1907
+ } else {
1908
+ throw e;
1909
+ }
1910
+ }
1911
+ if (isProjectLevel && primaryTarget !== join11(configRoot, agentsFileName)) {
1912
+ const configRootTarget = join11(configRoot, agentsFileName);
1913
+ if (existsSync11(configRootTarget) || isSymlink(configRootTarget)) {
1914
+ unlinkSync4(configRootTarget);
1915
+ }
1916
+ try {
1917
+ symlinkSync(realpathSync(sourcePath), configRootTarget);
1918
+ } catch (e) {
1919
+ if (e.code === "EPERM") {
1920
+ copyFileSync2(sourcePath, configRootTarget);
1921
+ }
1922
+ }
1923
+ }
1924
+ }
1925
+ async function installExternalRepos(repos, repoPath) {
1926
+ if (!repos || repos.length === 0) return;
1927
+ for (const repo of repos) {
1928
+ const targetDir = join11(repoPath, repo.dir);
1929
+ if (existsSync11(targetDir)) {
1930
+ logger.info(` ${repo.dir} already exists, skipping clone`);
1931
+ continue;
1932
+ }
1933
+ const args = ["clone"];
1934
+ if (repo.depth) {
1935
+ args.push("--depth", String(repo.depth));
1936
+ }
1937
+ if (repo.recursive) {
1938
+ args.push("--recursive");
1939
+ }
1940
+ args.push(repo.url, targetDir);
1941
+ try {
1942
+ await execa3("git", args, { timeout: 12e4 });
1943
+ } catch {
1944
+ logger.warn(` git clone failed: ${repo.url}, clone manually: git clone ${repo.url} ${repo.dir}`);
1945
+ }
1946
+ }
1947
+ }
1948
+ function writeCannbotManifest(configRoot, pluginId, version, level, tool, skills, agents) {
1949
+ const manifest = {
1950
+ brand: "CANNBot",
1951
+ version,
1952
+ team: pluginId,
1953
+ level,
1954
+ tool,
1955
+ installed_skills: skills,
1956
+ installed_agents: agents,
1957
+ brand_dir: configRoot,
1958
+ install_time: (/* @__PURE__ */ new Date()).toISOString()
1959
+ };
1960
+ const manifestPath = join11(configRoot, "cannbot-manifest.json");
1961
+ writeFileSync3(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
1962
+ return manifest;
1963
+ }
1964
+ async function installViaManifest(manifest, pluginDir, repoPath, tool, level, installPath) {
1965
+ const cwd = installPath || process.cwd();
1966
+ const configRoot = getConfigRoot(tool, level, installPath);
1967
+ try {
1968
+ const skillsDir = join11(configRoot, "skills");
1969
+ const agentsDir = join11(configRoot, "agents");
1970
+ mkdirSync5(skillsDir, { recursive: true });
1971
+ mkdirSync5(agentsDir, { recursive: true });
1972
+ const installedSkills = [];
1973
+ const installedAgents = [];
1974
+ for (const source of manifest.skills) {
1975
+ const sourceDir = join11(repoPath, source.dir);
1976
+ if (!existsSync11(sourceDir)) {
1977
+ logger.warn(` Skill source not found: ${source.dir}`);
1978
+ continue;
1979
+ }
1980
+ for (const skillName of source.skills) {
1981
+ const skillPath = join11(sourceDir, skillName);
1982
+ if (!existsSync11(skillPath)) {
1983
+ logger.warn(` Skill not found: ${skillName} in ${source.dir}`);
1984
+ continue;
1985
+ }
1986
+ const targetPath = join11(skillsDir, skillName);
1987
+ const result = installLink(skillPath, targetPath);
1988
+ if (result !== "failed") {
1989
+ installedSkills.push(skillName);
1990
+ } else {
1991
+ logger.warn(` Failed to install skill: ${skillName}`);
1992
+ }
1993
+ }
1994
+ }
1995
+ for (const agentName of manifest.agents) {
1996
+ const agentFile = agentName.endsWith(".md") ? agentName : `${agentName}.md`;
1997
+ const agentPath = join11(pluginDir, "agents", agentFile);
1998
+ if (!existsSync11(agentPath)) {
1999
+ logger.warn(` Agent not found: ${agentFile}`);
2000
+ continue;
2001
+ }
2002
+ const targetPath = join11(agentsDir, agentFile);
2003
+ const result = installLink(agentPath, targetPath);
2004
+ if (result !== "failed") {
2005
+ installedAgents.push(agentFile);
2006
+ } else {
2007
+ logger.warn(` Failed to install agent: ${agentFile}`);
2008
+ }
2009
+ }
2010
+ installConfigFile(pluginDir, manifest.configFile, tool, level, configRoot, cwd);
2011
+ await installExternalRepos(manifest.externalRepos, repoPath);
2012
+ const cannbotManifest = writeCannbotManifest(
2013
+ configRoot,
2014
+ manifest.id,
2015
+ manifest.version || "1.0.0",
2016
+ level,
2017
+ tool,
2018
+ installedSkills,
2019
+ installedAgents
2020
+ );
2021
+ return {
2022
+ success: true,
2023
+ skillsCount: installedSkills.length,
2024
+ agentsCount: installedAgents.length,
2025
+ errors: [],
2026
+ manifest: cannbotManifest
2027
+ };
2028
+ } catch (error) {
1843
2029
  return {
1844
2030
  success: false,
1845
- pluginId: opts.pluginId,
1846
2031
  skillsCount: 0,
1847
2032
  agentsCount: 0,
1848
- errors: [t("error_plugin_not_found") + ": " + opts.pluginId],
1849
- warnings: []
2033
+ errors: [error instanceof Error ? error.message : t("error_unknown")],
2034
+ manifest: null
1850
2035
  };
1851
2036
  }
1852
- const scriptPath = join11(opts.repoPath, plugin.dir, plugin.script);
1853
- if (!existsSync11(scriptPath)) {
2037
+ }
2038
+
2039
+ // src/core/installer.ts
2040
+ async function installPlugin(opts) {
2041
+ const plugin = getPluginById(opts.pluginId);
2042
+ if (!plugin) {
1854
2043
  return {
1855
2044
  success: false,
1856
2045
  pluginId: opts.pluginId,
1857
2046
  skillsCount: 0,
1858
2047
  agentsCount: 0,
1859
- errors: [t("error_script_not_found").replace("{path}", scriptPath)],
2048
+ errors: [t("error_plugin_not_found") + ": " + opts.pluginId],
1860
2049
  warnings: []
1861
2050
  };
1862
2051
  }
1863
- const args = [opts.level, opts.tool];
1864
- if (opts.installPath) {
1865
- args.push(opts.installPath);
1866
- }
2052
+ const pluginDir = join12(opts.repoPath, plugin.dir);
1867
2053
  const cwd = opts.installPath || process.cwd();
1868
2054
  const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
1869
- const agentsFile = join11(configRoot, getAgentsFileName2(opts.tool));
2055
+ const agentsFile = join12(configRoot, getAgentsFileName(opts.tool));
1870
2056
  let backupInfo = null;
1871
- if (existsSync11(agentsFile)) {
2057
+ if (existsSync12(agentsFile)) {
1872
2058
  const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
1873
2059
  if (currentPlugin && currentPlugin.pluginId !== opts.pluginId) {
1874
2060
  let choice = "overwrite";
@@ -1909,6 +2095,73 @@ async function installPlugin(opts) {
1909
2095
  logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
1910
2096
  }
1911
2097
  }
2098
+ const pluginManifest = readPluginManifest(pluginDir);
2099
+ if (pluginManifest) {
2100
+ const result = await installViaManifest(
2101
+ pluginManifest,
2102
+ pluginDir,
2103
+ opts.repoPath,
2104
+ opts.tool,
2105
+ opts.level,
2106
+ opts.installPath
2107
+ );
2108
+ if (result.success) {
2109
+ try {
2110
+ const record = scanInstalledFiles(
2111
+ opts.pluginId,
2112
+ plugin.displayName,
2113
+ opts.tool,
2114
+ opts.level,
2115
+ cwd,
2116
+ configRoot,
2117
+ result.manifest
2118
+ );
2119
+ if (backupInfo) {
2120
+ record.backup = {
2121
+ filePath: backupInfo.filePath,
2122
+ fromPluginId: backupInfo.pluginId,
2123
+ fromPluginName: backupInfo.pluginName,
2124
+ backupTime: backupInfo.backupTime
2125
+ };
2126
+ }
2127
+ writeRecord(record);
2128
+ } catch {
2129
+ logger.warn(t("record_write_failed"));
2130
+ }
2131
+ return {
2132
+ success: true,
2133
+ pluginId: opts.pluginId,
2134
+ skillsCount: result.skillsCount,
2135
+ agentsCount: result.agentsCount,
2136
+ errors: result.errors,
2137
+ warnings: []
2138
+ };
2139
+ } else {
2140
+ return {
2141
+ success: false,
2142
+ pluginId: opts.pluginId,
2143
+ skillsCount: 0,
2144
+ agentsCount: 0,
2145
+ errors: result.errors,
2146
+ warnings: []
2147
+ };
2148
+ }
2149
+ }
2150
+ const scriptPath = join12(pluginDir, plugin.script);
2151
+ if (!existsSync12(scriptPath)) {
2152
+ return {
2153
+ success: false,
2154
+ pluginId: opts.pluginId,
2155
+ skillsCount: 0,
2156
+ agentsCount: 0,
2157
+ errors: [t("error_script_not_found").replace("{path}", scriptPath)],
2158
+ warnings: []
2159
+ };
2160
+ }
2161
+ const args = [opts.level, opts.tool];
2162
+ if (opts.installPath) {
2163
+ args.push(opts.installPath);
2164
+ }
1912
2165
  try {
1913
2166
  const shell = process.platform === "win32" ? "sh" : "bash";
1914
2167
  const execOptions = {
@@ -1917,7 +2170,7 @@ async function installPlugin(opts) {
1917
2170
  stdio: "pipe",
1918
2171
  input: opts.yes ? "y\n" : void 0
1919
2172
  };
1920
- await execa3(shell, [scriptPath, ...args], execOptions);
2173
+ await execa4(shell, [scriptPath, ...args], execOptions);
1921
2174
  const manifest = readManifest(configRoot);
1922
2175
  let skillsCount = 0;
1923
2176
  let agentsCount = 0;
@@ -1972,17 +2225,17 @@ async function installPlugin(opts) {
1972
2225
  }
1973
2226
 
1974
2227
  // src/core/skill-installer.ts
1975
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmdirSync, realpathSync } from "fs";
1976
- import { join as join12, dirname as dirname6 } from "path";
2228
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readdirSync as readdirSync4, rmdirSync, realpathSync as realpathSync2 } from "fs";
2229
+ import { join as join13, dirname as dirname7 } from "path";
1977
2230
  import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
1978
2231
  import chalk5 from "chalk";
1979
2232
  import Table from "cli-table3";
1980
2233
  async function installSkills(skillIds, tool, level, repoPath) {
1981
2234
  const configRoot = getConfigRoot(tool, level);
1982
- const skillsDir = join12(configRoot, "skills");
2235
+ const skillsDir = join13(configRoot, "skills");
1983
2236
  const installPath = level === "project" ? process.cwd() : configRoot;
1984
- if (!existsSync12(skillsDir)) {
1985
- mkdirSync5(skillsDir, { recursive: true });
2237
+ if (!existsSync13(skillsDir)) {
2238
+ mkdirSync6(skillsDir, { recursive: true });
1986
2239
  }
1987
2240
  const results = [];
1988
2241
  const installedIds = [];
@@ -1993,17 +2246,17 @@ async function installSkills(skillIds, tool, level, repoPath) {
1993
2246
  continue;
1994
2247
  }
1995
2248
  const sourcePath = resolveSkillSourcePath(skill, repoPath);
1996
- const targetPath = join12(skillsDir, skillId);
1997
- if (!existsSync12(sourcePath)) {
2249
+ const targetPath = join13(skillsDir, skillId);
2250
+ if (!existsSync13(sourcePath)) {
1998
2251
  results.push({ skillId, success: false, error: t("error_source_not_found").replace("{path}", sourcePath) });
1999
2252
  continue;
2000
2253
  }
2001
2254
  try {
2002
- const resolvedSource = realpathSync(sourcePath);
2003
- if (existsSync12(targetPath) || isSymlink(targetPath)) {
2004
- unlinkSync4(targetPath);
2255
+ const resolvedSource = realpathSync2(sourcePath);
2256
+ if (existsSync13(targetPath) || isSymlink(targetPath)) {
2257
+ unlinkSync5(targetPath);
2005
2258
  }
2006
- symlinkSync(resolvedSource, targetPath);
2259
+ symlinkSync2(resolvedSource, targetPath);
2007
2260
  results.push({ skillId, success: true });
2008
2261
  installedIds.push(skillId);
2009
2262
  } catch (error) {
@@ -2021,15 +2274,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
2021
2274
  }
2022
2275
  async function uninstallSkills(skillIds, tool, level) {
2023
2276
  const configRoot = getConfigRoot(tool, level);
2024
- const skillsDir = join12(configRoot, "skills");
2277
+ const skillsDir = join13(configRoot, "skills");
2025
2278
  const installPath = level === "project" ? process.cwd() : configRoot;
2026
2279
  const results = [];
2027
2280
  const removedIds = [];
2028
2281
  for (const skillId of skillIds) {
2029
- const targetPath = join12(skillsDir, skillId);
2282
+ const targetPath = join13(skillsDir, skillId);
2030
2283
  try {
2031
- if (existsSync12(targetPath) || isSymlink(targetPath)) {
2032
- unlinkSync4(targetPath);
2284
+ if (existsSync13(targetPath) || isSymlink(targetPath)) {
2285
+ unlinkSync5(targetPath);
2033
2286
  results.push({ skillId, success: true });
2034
2287
  removedIds.push(skillId);
2035
2288
  logger.step(` ${t("uninstall_remove_label")}: ${skillId}`);
@@ -2044,7 +2297,7 @@ async function uninstallSkills(skillIds, tool, level) {
2044
2297
  if (removedIds.length > 0) {
2045
2298
  removeSkillsFromRecord(removedIds, tool, level, installPath);
2046
2299
  }
2047
- if (existsSync12(skillsDir)) {
2300
+ if (existsSync13(skillsDir)) {
2048
2301
  try {
2049
2302
  const entries = readdirSync4(skillsDir);
2050
2303
  if (entries.length === 0) {
@@ -2227,12 +2480,12 @@ function listAllSkills() {
2227
2480
  }
2228
2481
  function resolveSkillSourcePath(skill, repoPath) {
2229
2482
  if (skill.filePath) {
2230
- const absPath = skill.filePath.startsWith("/") ? skill.filePath : join12(repoPath, skill.filePath);
2231
- if (existsSync12(absPath)) {
2232
- return dirname6(absPath);
2483
+ const absPath = skill.filePath.startsWith("/") ? skill.filePath : join13(repoPath, skill.filePath);
2484
+ if (existsSync13(absPath)) {
2485
+ return dirname7(absPath);
2233
2486
  }
2234
2487
  }
2235
- return join12(repoPath, skill.source, skill.id);
2488
+ return join13(repoPath, skill.source, skill.id);
2236
2489
  }
2237
2490
 
2238
2491
  // src/ui/display.ts
@@ -2324,13 +2577,13 @@ function printEnhancedSummary(results, tool, configRoot) {
2324
2577
  }
2325
2578
 
2326
2579
  // src/commands/init.ts
2327
- import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
2328
- import { join as join13 } from "path";
2580
+ import { existsSync as existsSync14, readFileSync as readFileSync9 } from "fs";
2581
+ import { join as join14 } from "path";
2329
2582
  async function initCommand() {
2330
2583
  const cwd = process.cwd();
2331
- if (existsSync13(join13(cwd, "package.json")) && (() => {
2584
+ if (existsSync14(join14(cwd, "package.json")) && (() => {
2332
2585
  try {
2333
- const pkg = JSON.parse(readFileSync8(join13(cwd, "package.json"), "utf-8"));
2586
+ const pkg = JSON.parse(readFileSync9(join14(cwd, "package.json"), "utf-8"));
2334
2587
  return pkg.name === "@cannbot-ai/install-helper";
2335
2588
  } catch {
2336
2589
  return false;
@@ -2555,8 +2808,8 @@ async function listCommand() {
2555
2808
 
2556
2809
  // src/commands/doctor.ts
2557
2810
  import chalk8 from "chalk";
2558
- import { existsSync as existsSync14, readdirSync as readdirSync5, lstatSync as lstatSync2, unlinkSync as unlinkSync5, mkdirSync as mkdirSync6 } from "fs";
2559
- import { join as join14 } from "path";
2811
+ import { existsSync as existsSync15, readdirSync as readdirSync5, lstatSync as lstatSync2, unlinkSync as unlinkSync6, mkdirSync as mkdirSync7 } from "fs";
2812
+ import { join as join15 } from "path";
2560
2813
  async function doctorCommand(options = {}) {
2561
2814
  console.log();
2562
2815
  console.log(chalk8.bold(` ${t("doctor_title")}`));
@@ -2598,7 +2851,7 @@ async function doctorCommand(options = {}) {
2598
2851
  const configRoot = getConfigRoot(primaryTool, "project");
2599
2852
  const skillsDir = getSkillsDir(configRoot);
2600
2853
  const agentsDir = getAgentsDir(configRoot);
2601
- if (existsSync14(skillsDir)) {
2854
+ if (existsSync15(skillsDir)) {
2602
2855
  const brokenLinks = checkBrokenLinks(skillsDir);
2603
2856
  if (brokenLinks === 0) {
2604
2857
  const count = readdirSync5(skillsDir).length;
@@ -2615,12 +2868,12 @@ async function doctorCommand(options = {}) {
2615
2868
  } else {
2616
2869
  console.log(chalk8.dim(" \u2014") + ` ${skillsDir} \u2014 ${t("doctor_not_exist")}`);
2617
2870
  if (options.fix) {
2618
- mkdirSync6(skillsDir, { recursive: true });
2871
+ mkdirSync7(skillsDir, { recursive: true });
2619
2872
  fixes++;
2620
2873
  console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", skillsDir)}`);
2621
2874
  }
2622
2875
  }
2623
- if (existsSync14(agentsDir)) {
2876
+ if (existsSync15(agentsDir)) {
2624
2877
  const brokenLinks = checkBrokenLinks(agentsDir);
2625
2878
  if (brokenLinks === 0) {
2626
2879
  const count = readdirSync5(agentsDir).length;
@@ -2637,7 +2890,7 @@ async function doctorCommand(options = {}) {
2637
2890
  } else {
2638
2891
  console.log(chalk8.dim(" \u2014") + ` ${agentsDir} \u2014 ${t("doctor_not_exist")}`);
2639
2892
  if (options.fix) {
2640
- mkdirSync6(agentsDir, { recursive: true });
2893
+ mkdirSync7(agentsDir, { recursive: true });
2641
2894
  fixes++;
2642
2895
  console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", agentsDir)}`);
2643
2896
  }
@@ -2645,8 +2898,8 @@ async function doctorCommand(options = {}) {
2645
2898
  console.log();
2646
2899
  console.log(chalk8.bold(` ${t("doctor_config")}`));
2647
2900
  const configFile = getConfigFileName(primaryTool);
2648
- const configPath = join14(process.cwd(), configFile);
2649
- if (existsSync14(configPath)) {
2901
+ const configPath = join15(process.cwd(), configFile);
2902
+ if (existsSync15(configPath)) {
2650
2903
  console.log(chalk8.green(" \u2713") + ` ${configFile} ${t("doctor_config_exists")}`);
2651
2904
  } else {
2652
2905
  console.log(chalk8.dim(" \u2014") + ` ${configFile} ${t("doctor_config_not_exist")}`);
@@ -2669,11 +2922,11 @@ function checkBrokenLinks(dir) {
2669
2922
  try {
2670
2923
  const entries = readdirSync5(dir);
2671
2924
  for (const entry of entries) {
2672
- const fullPath = join14(dir, entry);
2925
+ const fullPath = join15(dir, entry);
2673
2926
  try {
2674
2927
  const stats = lstatSync2(fullPath);
2675
2928
  if (stats.isSymbolicLink()) {
2676
- if (!existsSync14(fullPath)) {
2929
+ if (!existsSync15(fullPath)) {
2677
2930
  broken++;
2678
2931
  }
2679
2932
  }
@@ -2690,12 +2943,12 @@ function fixBrokenLinks(dir) {
2690
2943
  try {
2691
2944
  const entries = readdirSync5(dir);
2692
2945
  for (const entry of entries) {
2693
- const fullPath = join14(dir, entry);
2946
+ const fullPath = join15(dir, entry);
2694
2947
  try {
2695
2948
  const stats = lstatSync2(fullPath);
2696
2949
  if (stats.isSymbolicLink()) {
2697
- if (!existsSync14(fullPath)) {
2698
- unlinkSync5(fullPath);
2950
+ if (!existsSync15(fullPath)) {
2951
+ unlinkSync6(fullPath);
2699
2952
  fixed++;
2700
2953
  }
2701
2954
  }
@@ -3040,8 +3293,8 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
3040
3293
  }
3041
3294
 
3042
3295
  // src/commands/uninstall.ts
3043
- import { existsSync as existsSync15, unlinkSync as unlinkSync6, rmdirSync as rmdirSync2, readdirSync as readdirSync6 } from "fs";
3044
- import { resolve, basename } from "path";
3296
+ import { existsSync as existsSync16, unlinkSync as unlinkSync7, rmdirSync as rmdirSync2, readdirSync as readdirSync6 } from "fs";
3297
+ import { resolve, basename as basename2 } from "path";
3045
3298
  import chalk11 from "chalk";
3046
3299
  async function uninstallCommand(names, options) {
3047
3300
  const tool = options.tool ? validateTool(options.tool) : "opencode";
@@ -3082,9 +3335,9 @@ async function uninstallCommand(names, options) {
3082
3335
  for (const filePath of record.files) {
3083
3336
  if (!isSafePath(filePath)) continue;
3084
3337
  try {
3085
- if (existsSync15(filePath) || isSymlink(filePath)) {
3086
- unlinkSync6(filePath);
3087
- const name = basename(filePath);
3338
+ if (existsSync16(filePath) || isSymlink(filePath)) {
3339
+ unlinkSync7(filePath);
3340
+ const name = basename2(filePath);
3088
3341
  logger.step(` ${t("uninstall_remove_label")}: ${name}`);
3089
3342
  removedFiles++;
3090
3343
  }
@@ -3097,11 +3350,11 @@ async function uninstallCommand(names, options) {
3097
3350
  if (resolve(dirPath) === resolve(configRoot)) {
3098
3351
  continue;
3099
3352
  }
3100
- if (existsSync15(dirPath)) {
3353
+ if (existsSync16(dirPath)) {
3101
3354
  const entries = readdirSync6(dirPath);
3102
3355
  if (entries.length === 0) {
3103
3356
  rmdirSync2(dirPath);
3104
- const name = basename(dirPath);
3357
+ const name = basename2(dirPath);
3105
3358
  logger.step(` ${t("uninstall_clean_empty_dir")}: ${name}/`);
3106
3359
  removedDirs++;
3107
3360
  }
@@ -3236,8 +3489,8 @@ async function updateCommand(pluginNames, options) {
3236
3489
 
3237
3490
  // src/commands/info.ts
3238
3491
  import chalk13 from "chalk";
3239
- import { existsSync as existsSync16, readdirSync as readdirSync7 } from "fs";
3240
- import { join as join15 } from "path";
3492
+ import { existsSync as existsSync17, readdirSync as readdirSync7 } from "fs";
3493
+ import { join as join16 } from "path";
3241
3494
  async function infoCommand(pluginName) {
3242
3495
  const plugin = findPlugin(pluginName);
3243
3496
  if (!plugin) {
@@ -3262,12 +3515,12 @@ async function infoCommand(pluginName) {
3262
3515
  try {
3263
3516
  const repoManager = createRepositoryManager();
3264
3517
  const repoPath = await repoManager.ensureRepo();
3265
- const quickstartPath = join15(repoPath, plugin.dir, "quickstart.md");
3266
- if (existsSync16(quickstartPath)) {
3518
+ const quickstartPath = join16(repoPath, plugin.dir, "quickstart.md");
3519
+ if (existsSync17(quickstartPath)) {
3267
3520
  console.log(` ${chalk13.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
3268
3521
  }
3269
- const agentsDir = join15(repoPath, plugin.dir, "agents");
3270
- if (existsSync16(agentsDir)) {
3522
+ const agentsDir = join16(repoPath, plugin.dir, "agents");
3523
+ if (existsSync17(agentsDir)) {
3271
3524
  const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
3272
3525
  if (agentFiles.length > 0) {
3273
3526
  console.log();
@@ -3319,15 +3572,15 @@ async function langCommand(action, value) {
3319
3572
  }
3320
3573
 
3321
3574
  // src/cli.ts
3322
- import { readFileSync as readFileSync9 } from "fs";
3575
+ import { readFileSync as readFileSync10 } from "fs";
3323
3576
  import { fileURLToPath as fileURLToPath5 } from "url";
3324
- import { dirname as dirname7, join as join16 } from "path";
3577
+ import { dirname as dirname8, join as join17 } from "path";
3325
3578
  function readVersion() {
3326
3579
  try {
3327
3580
  const __filename5 = fileURLToPath5(import.meta.url);
3328
- const __dirname5 = dirname7(__filename5);
3329
- const pkgPath = join16(__dirname5, "..", "package.json");
3330
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
3581
+ const __dirname5 = dirname8(__filename5);
3582
+ const pkgPath = join17(__dirname5, "..", "package.json");
3583
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
3331
3584
  return pkg.version || "0.0.0";
3332
3585
  } catch {
3333
3586
  return "0.0.0";