@cannbot-ai/install-helper 0.0.2-beta.38 → 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 +314 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1516,9 +1516,9 @@ function createRepositoryManager(customPath) {
|
|
|
1516
1516
|
}
|
|
1517
1517
|
|
|
1518
1518
|
// src/core/installer.ts
|
|
1519
|
-
import { existsSync as
|
|
1520
|
-
import { join as
|
|
1521
|
-
import { execa as
|
|
1519
|
+
import { existsSync as existsSync12 } from "fs";
|
|
1520
|
+
import { join as join12 } from "path";
|
|
1521
|
+
import { execa as execa4 } from "execa";
|
|
1522
1522
|
|
|
1523
1523
|
// src/core/record.ts
|
|
1524
1524
|
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
|
|
@@ -1850,39 +1850,211 @@ async function showRestorePrompt(backups) {
|
|
|
1850
1850
|
return choice;
|
|
1851
1851
|
}
|
|
1852
1852
|
|
|
1853
|
-
// src/core/installer.ts
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
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) {
|
|
1857
2029
|
return {
|
|
1858
2030
|
success: false,
|
|
1859
|
-
pluginId: opts.pluginId,
|
|
1860
2031
|
skillsCount: 0,
|
|
1861
2032
|
agentsCount: 0,
|
|
1862
|
-
errors: [t("
|
|
1863
|
-
|
|
2033
|
+
errors: [error instanceof Error ? error.message : t("error_unknown")],
|
|
2034
|
+
manifest: null
|
|
1864
2035
|
};
|
|
1865
2036
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// src/core/installer.ts
|
|
2040
|
+
async function installPlugin(opts) {
|
|
2041
|
+
const plugin = getPluginById(opts.pluginId);
|
|
2042
|
+
if (!plugin) {
|
|
1868
2043
|
return {
|
|
1869
2044
|
success: false,
|
|
1870
2045
|
pluginId: opts.pluginId,
|
|
1871
2046
|
skillsCount: 0,
|
|
1872
2047
|
agentsCount: 0,
|
|
1873
|
-
errors: [t("
|
|
2048
|
+
errors: [t("error_plugin_not_found") + ": " + opts.pluginId],
|
|
1874
2049
|
warnings: []
|
|
1875
2050
|
};
|
|
1876
2051
|
}
|
|
1877
|
-
const
|
|
1878
|
-
if (opts.installPath) {
|
|
1879
|
-
args.push(opts.installPath);
|
|
1880
|
-
}
|
|
2052
|
+
const pluginDir = join12(opts.repoPath, plugin.dir);
|
|
1881
2053
|
const cwd = opts.installPath || process.cwd();
|
|
1882
2054
|
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
1883
|
-
const agentsFile =
|
|
2055
|
+
const agentsFile = join12(configRoot, getAgentsFileName(opts.tool));
|
|
1884
2056
|
let backupInfo = null;
|
|
1885
|
-
if (
|
|
2057
|
+
if (existsSync12(agentsFile)) {
|
|
1886
2058
|
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
1887
2059
|
if (currentPlugin && currentPlugin.pluginId !== opts.pluginId) {
|
|
1888
2060
|
let choice = "overwrite";
|
|
@@ -1923,6 +2095,73 @@ async function installPlugin(opts) {
|
|
|
1923
2095
|
logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
|
|
1924
2096
|
}
|
|
1925
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
|
+
}
|
|
1926
2165
|
try {
|
|
1927
2166
|
const shell = process.platform === "win32" ? "sh" : "bash";
|
|
1928
2167
|
const execOptions = {
|
|
@@ -1931,7 +2170,7 @@ async function installPlugin(opts) {
|
|
|
1931
2170
|
stdio: "pipe",
|
|
1932
2171
|
input: opts.yes ? "y\n" : void 0
|
|
1933
2172
|
};
|
|
1934
|
-
await
|
|
2173
|
+
await execa4(shell, [scriptPath, ...args], execOptions);
|
|
1935
2174
|
const manifest = readManifest(configRoot);
|
|
1936
2175
|
let skillsCount = 0;
|
|
1937
2176
|
let agentsCount = 0;
|
|
@@ -1986,17 +2225,17 @@ async function installPlugin(opts) {
|
|
|
1986
2225
|
}
|
|
1987
2226
|
|
|
1988
2227
|
// src/core/skill-installer.ts
|
|
1989
|
-
import { existsSync as
|
|
1990
|
-
import { join as
|
|
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";
|
|
1991
2230
|
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
1992
2231
|
import chalk5 from "chalk";
|
|
1993
2232
|
import Table from "cli-table3";
|
|
1994
2233
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
1995
2234
|
const configRoot = getConfigRoot(tool, level);
|
|
1996
|
-
const skillsDir =
|
|
2235
|
+
const skillsDir = join13(configRoot, "skills");
|
|
1997
2236
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1998
|
-
if (!
|
|
1999
|
-
|
|
2237
|
+
if (!existsSync13(skillsDir)) {
|
|
2238
|
+
mkdirSync6(skillsDir, { recursive: true });
|
|
2000
2239
|
}
|
|
2001
2240
|
const results = [];
|
|
2002
2241
|
const installedIds = [];
|
|
@@ -2007,17 +2246,17 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2007
2246
|
continue;
|
|
2008
2247
|
}
|
|
2009
2248
|
const sourcePath = resolveSkillSourcePath(skill, repoPath);
|
|
2010
|
-
const targetPath =
|
|
2011
|
-
if (!
|
|
2249
|
+
const targetPath = join13(skillsDir, skillId);
|
|
2250
|
+
if (!existsSync13(sourcePath)) {
|
|
2012
2251
|
results.push({ skillId, success: false, error: t("error_source_not_found").replace("{path}", sourcePath) });
|
|
2013
2252
|
continue;
|
|
2014
2253
|
}
|
|
2015
2254
|
try {
|
|
2016
|
-
const resolvedSource =
|
|
2017
|
-
if (
|
|
2018
|
-
|
|
2255
|
+
const resolvedSource = realpathSync2(sourcePath);
|
|
2256
|
+
if (existsSync13(targetPath) || isSymlink(targetPath)) {
|
|
2257
|
+
unlinkSync5(targetPath);
|
|
2019
2258
|
}
|
|
2020
|
-
|
|
2259
|
+
symlinkSync2(resolvedSource, targetPath);
|
|
2021
2260
|
results.push({ skillId, success: true });
|
|
2022
2261
|
installedIds.push(skillId);
|
|
2023
2262
|
} catch (error) {
|
|
@@ -2035,15 +2274,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2035
2274
|
}
|
|
2036
2275
|
async function uninstallSkills(skillIds, tool, level) {
|
|
2037
2276
|
const configRoot = getConfigRoot(tool, level);
|
|
2038
|
-
const skillsDir =
|
|
2277
|
+
const skillsDir = join13(configRoot, "skills");
|
|
2039
2278
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
2040
2279
|
const results = [];
|
|
2041
2280
|
const removedIds = [];
|
|
2042
2281
|
for (const skillId of skillIds) {
|
|
2043
|
-
const targetPath =
|
|
2282
|
+
const targetPath = join13(skillsDir, skillId);
|
|
2044
2283
|
try {
|
|
2045
|
-
if (
|
|
2046
|
-
|
|
2284
|
+
if (existsSync13(targetPath) || isSymlink(targetPath)) {
|
|
2285
|
+
unlinkSync5(targetPath);
|
|
2047
2286
|
results.push({ skillId, success: true });
|
|
2048
2287
|
removedIds.push(skillId);
|
|
2049
2288
|
logger.step(` ${t("uninstall_remove_label")}: ${skillId}`);
|
|
@@ -2058,7 +2297,7 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
2058
2297
|
if (removedIds.length > 0) {
|
|
2059
2298
|
removeSkillsFromRecord(removedIds, tool, level, installPath);
|
|
2060
2299
|
}
|
|
2061
|
-
if (
|
|
2300
|
+
if (existsSync13(skillsDir)) {
|
|
2062
2301
|
try {
|
|
2063
2302
|
const entries = readdirSync4(skillsDir);
|
|
2064
2303
|
if (entries.length === 0) {
|
|
@@ -2241,12 +2480,12 @@ function listAllSkills() {
|
|
|
2241
2480
|
}
|
|
2242
2481
|
function resolveSkillSourcePath(skill, repoPath) {
|
|
2243
2482
|
if (skill.filePath) {
|
|
2244
|
-
const absPath = skill.filePath.startsWith("/") ? skill.filePath :
|
|
2245
|
-
if (
|
|
2246
|
-
return
|
|
2483
|
+
const absPath = skill.filePath.startsWith("/") ? skill.filePath : join13(repoPath, skill.filePath);
|
|
2484
|
+
if (existsSync13(absPath)) {
|
|
2485
|
+
return dirname7(absPath);
|
|
2247
2486
|
}
|
|
2248
2487
|
}
|
|
2249
|
-
return
|
|
2488
|
+
return join13(repoPath, skill.source, skill.id);
|
|
2250
2489
|
}
|
|
2251
2490
|
|
|
2252
2491
|
// src/ui/display.ts
|
|
@@ -2338,13 +2577,13 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2338
2577
|
}
|
|
2339
2578
|
|
|
2340
2579
|
// src/commands/init.ts
|
|
2341
|
-
import { existsSync as
|
|
2342
|
-
import { join as
|
|
2580
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9 } from "fs";
|
|
2581
|
+
import { join as join14 } from "path";
|
|
2343
2582
|
async function initCommand() {
|
|
2344
2583
|
const cwd = process.cwd();
|
|
2345
|
-
if (
|
|
2584
|
+
if (existsSync14(join14(cwd, "package.json")) && (() => {
|
|
2346
2585
|
try {
|
|
2347
|
-
const pkg = JSON.parse(
|
|
2586
|
+
const pkg = JSON.parse(readFileSync9(join14(cwd, "package.json"), "utf-8"));
|
|
2348
2587
|
return pkg.name === "@cannbot-ai/install-helper";
|
|
2349
2588
|
} catch {
|
|
2350
2589
|
return false;
|
|
@@ -2569,8 +2808,8 @@ async function listCommand() {
|
|
|
2569
2808
|
|
|
2570
2809
|
// src/commands/doctor.ts
|
|
2571
2810
|
import chalk8 from "chalk";
|
|
2572
|
-
import { existsSync as
|
|
2573
|
-
import { join as
|
|
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";
|
|
2574
2813
|
async function doctorCommand(options = {}) {
|
|
2575
2814
|
console.log();
|
|
2576
2815
|
console.log(chalk8.bold(` ${t("doctor_title")}`));
|
|
@@ -2612,7 +2851,7 @@ async function doctorCommand(options = {}) {
|
|
|
2612
2851
|
const configRoot = getConfigRoot(primaryTool, "project");
|
|
2613
2852
|
const skillsDir = getSkillsDir(configRoot);
|
|
2614
2853
|
const agentsDir = getAgentsDir(configRoot);
|
|
2615
|
-
if (
|
|
2854
|
+
if (existsSync15(skillsDir)) {
|
|
2616
2855
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2617
2856
|
if (brokenLinks === 0) {
|
|
2618
2857
|
const count = readdirSync5(skillsDir).length;
|
|
@@ -2629,12 +2868,12 @@ async function doctorCommand(options = {}) {
|
|
|
2629
2868
|
} else {
|
|
2630
2869
|
console.log(chalk8.dim(" \u2014") + ` ${skillsDir} \u2014 ${t("doctor_not_exist")}`);
|
|
2631
2870
|
if (options.fix) {
|
|
2632
|
-
|
|
2871
|
+
mkdirSync7(skillsDir, { recursive: true });
|
|
2633
2872
|
fixes++;
|
|
2634
2873
|
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", skillsDir)}`);
|
|
2635
2874
|
}
|
|
2636
2875
|
}
|
|
2637
|
-
if (
|
|
2876
|
+
if (existsSync15(agentsDir)) {
|
|
2638
2877
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2639
2878
|
if (brokenLinks === 0) {
|
|
2640
2879
|
const count = readdirSync5(agentsDir).length;
|
|
@@ -2651,7 +2890,7 @@ async function doctorCommand(options = {}) {
|
|
|
2651
2890
|
} else {
|
|
2652
2891
|
console.log(chalk8.dim(" \u2014") + ` ${agentsDir} \u2014 ${t("doctor_not_exist")}`);
|
|
2653
2892
|
if (options.fix) {
|
|
2654
|
-
|
|
2893
|
+
mkdirSync7(agentsDir, { recursive: true });
|
|
2655
2894
|
fixes++;
|
|
2656
2895
|
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", agentsDir)}`);
|
|
2657
2896
|
}
|
|
@@ -2659,8 +2898,8 @@ async function doctorCommand(options = {}) {
|
|
|
2659
2898
|
console.log();
|
|
2660
2899
|
console.log(chalk8.bold(` ${t("doctor_config")}`));
|
|
2661
2900
|
const configFile = getConfigFileName(primaryTool);
|
|
2662
|
-
const configPath =
|
|
2663
|
-
if (
|
|
2901
|
+
const configPath = join15(process.cwd(), configFile);
|
|
2902
|
+
if (existsSync15(configPath)) {
|
|
2664
2903
|
console.log(chalk8.green(" \u2713") + ` ${configFile} ${t("doctor_config_exists")}`);
|
|
2665
2904
|
} else {
|
|
2666
2905
|
console.log(chalk8.dim(" \u2014") + ` ${configFile} ${t("doctor_config_not_exist")}`);
|
|
@@ -2683,11 +2922,11 @@ function checkBrokenLinks(dir) {
|
|
|
2683
2922
|
try {
|
|
2684
2923
|
const entries = readdirSync5(dir);
|
|
2685
2924
|
for (const entry of entries) {
|
|
2686
|
-
const fullPath =
|
|
2925
|
+
const fullPath = join15(dir, entry);
|
|
2687
2926
|
try {
|
|
2688
2927
|
const stats = lstatSync2(fullPath);
|
|
2689
2928
|
if (stats.isSymbolicLink()) {
|
|
2690
|
-
if (!
|
|
2929
|
+
if (!existsSync15(fullPath)) {
|
|
2691
2930
|
broken++;
|
|
2692
2931
|
}
|
|
2693
2932
|
}
|
|
@@ -2704,12 +2943,12 @@ function fixBrokenLinks(dir) {
|
|
|
2704
2943
|
try {
|
|
2705
2944
|
const entries = readdirSync5(dir);
|
|
2706
2945
|
for (const entry of entries) {
|
|
2707
|
-
const fullPath =
|
|
2946
|
+
const fullPath = join15(dir, entry);
|
|
2708
2947
|
try {
|
|
2709
2948
|
const stats = lstatSync2(fullPath);
|
|
2710
2949
|
if (stats.isSymbolicLink()) {
|
|
2711
|
-
if (!
|
|
2712
|
-
|
|
2950
|
+
if (!existsSync15(fullPath)) {
|
|
2951
|
+
unlinkSync6(fullPath);
|
|
2713
2952
|
fixed++;
|
|
2714
2953
|
}
|
|
2715
2954
|
}
|
|
@@ -3054,8 +3293,8 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
|
|
|
3054
3293
|
}
|
|
3055
3294
|
|
|
3056
3295
|
// src/commands/uninstall.ts
|
|
3057
|
-
import { existsSync as
|
|
3058
|
-
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";
|
|
3059
3298
|
import chalk11 from "chalk";
|
|
3060
3299
|
async function uninstallCommand(names, options) {
|
|
3061
3300
|
const tool = options.tool ? validateTool(options.tool) : "opencode";
|
|
@@ -3096,9 +3335,9 @@ async function uninstallCommand(names, options) {
|
|
|
3096
3335
|
for (const filePath of record.files) {
|
|
3097
3336
|
if (!isSafePath(filePath)) continue;
|
|
3098
3337
|
try {
|
|
3099
|
-
if (
|
|
3100
|
-
|
|
3101
|
-
const name =
|
|
3338
|
+
if (existsSync16(filePath) || isSymlink(filePath)) {
|
|
3339
|
+
unlinkSync7(filePath);
|
|
3340
|
+
const name = basename2(filePath);
|
|
3102
3341
|
logger.step(` ${t("uninstall_remove_label")}: ${name}`);
|
|
3103
3342
|
removedFiles++;
|
|
3104
3343
|
}
|
|
@@ -3111,11 +3350,11 @@ async function uninstallCommand(names, options) {
|
|
|
3111
3350
|
if (resolve(dirPath) === resolve(configRoot)) {
|
|
3112
3351
|
continue;
|
|
3113
3352
|
}
|
|
3114
|
-
if (
|
|
3353
|
+
if (existsSync16(dirPath)) {
|
|
3115
3354
|
const entries = readdirSync6(dirPath);
|
|
3116
3355
|
if (entries.length === 0) {
|
|
3117
3356
|
rmdirSync2(dirPath);
|
|
3118
|
-
const name =
|
|
3357
|
+
const name = basename2(dirPath);
|
|
3119
3358
|
logger.step(` ${t("uninstall_clean_empty_dir")}: ${name}/`);
|
|
3120
3359
|
removedDirs++;
|
|
3121
3360
|
}
|
|
@@ -3250,8 +3489,8 @@ async function updateCommand(pluginNames, options) {
|
|
|
3250
3489
|
|
|
3251
3490
|
// src/commands/info.ts
|
|
3252
3491
|
import chalk13 from "chalk";
|
|
3253
|
-
import { existsSync as
|
|
3254
|
-
import { join as
|
|
3492
|
+
import { existsSync as existsSync17, readdirSync as readdirSync7 } from "fs";
|
|
3493
|
+
import { join as join16 } from "path";
|
|
3255
3494
|
async function infoCommand(pluginName) {
|
|
3256
3495
|
const plugin = findPlugin(pluginName);
|
|
3257
3496
|
if (!plugin) {
|
|
@@ -3276,12 +3515,12 @@ async function infoCommand(pluginName) {
|
|
|
3276
3515
|
try {
|
|
3277
3516
|
const repoManager = createRepositoryManager();
|
|
3278
3517
|
const repoPath = await repoManager.ensureRepo();
|
|
3279
|
-
const quickstartPath =
|
|
3280
|
-
if (
|
|
3518
|
+
const quickstartPath = join16(repoPath, plugin.dir, "quickstart.md");
|
|
3519
|
+
if (existsSync17(quickstartPath)) {
|
|
3281
3520
|
console.log(` ${chalk13.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
3282
3521
|
}
|
|
3283
|
-
const agentsDir =
|
|
3284
|
-
if (
|
|
3522
|
+
const agentsDir = join16(repoPath, plugin.dir, "agents");
|
|
3523
|
+
if (existsSync17(agentsDir)) {
|
|
3285
3524
|
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
|
|
3286
3525
|
if (agentFiles.length > 0) {
|
|
3287
3526
|
console.log();
|
|
@@ -3333,15 +3572,15 @@ async function langCommand(action, value) {
|
|
|
3333
3572
|
}
|
|
3334
3573
|
|
|
3335
3574
|
// src/cli.ts
|
|
3336
|
-
import { readFileSync as
|
|
3575
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
3337
3576
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
3338
|
-
import { dirname as
|
|
3577
|
+
import { dirname as dirname8, join as join17 } from "path";
|
|
3339
3578
|
function readVersion() {
|
|
3340
3579
|
try {
|
|
3341
3580
|
const __filename5 = fileURLToPath5(import.meta.url);
|
|
3342
|
-
const __dirname5 =
|
|
3343
|
-
const pkgPath =
|
|
3344
|
-
const pkg = JSON.parse(
|
|
3581
|
+
const __dirname5 = dirname8(__filename5);
|
|
3582
|
+
const pkgPath = join17(__dirname5, "..", "package.json");
|
|
3583
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
3345
3584
|
return pkg.version || "0.0.0";
|
|
3346
3585
|
} catch {
|
|
3347
3586
|
return "0.0.0";
|