@cannbot-ai/install-helper 1.2.0 → 1.2.1-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/README.md +5 -5
- package/dist/config/repository.yaml +1 -1
- package/dist/index.js +126 -45
- package/dist/index.js.map +1 -1
- package/dist/locales/en_US.json +1 -0
- package/dist/locales/zh_CN.json +1 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -101,18 +101,18 @@ install-helper install --list # 查看所有可用 Sk
|
|
|
101
101
|
|------|------|
|
|
102
102
|
| `--tool <tool>` | 指定 AI 工具(opencode, claude, trae, cursor, codex, copilot, codearts) |
|
|
103
103
|
| `--level <level>` | 安装级别(project, global),默认 project |
|
|
104
|
-
| `--source <source>` | 同名插件的安装来源(cannbot, skills):默认 cannbot
|
|
104
|
+
| `--source <source>` | 同名插件的安装来源(cannbot, skills):默认 cannbot 仓插件优先,`--source skills` 强制安装 cannbot-skills 仓旧版 |
|
|
105
105
|
| `--all` `-a` | 安装全部 Skills |
|
|
106
106
|
| `--list` | 按类别列出所有可用 Skills |
|
|
107
107
|
| `--yes` `-y` | 跳过所有确认提示 |
|
|
108
108
|
|
|
109
|
-
### 安装 cannbot
|
|
109
|
+
### 安装 cannbot 仓插件(双源)
|
|
110
110
|
|
|
111
|
-
插件编排已拆分至 [cannbot 仓](https://gitcode.com/cann/cannbot)(`ops-direct-invoke` v3、`ascendc-st-design`、`model-infer-optimize`、`ops-registry-invoke`
|
|
111
|
+
插件编排已拆分至 [cannbot 仓](https://gitcode.com/cann/cannbot)(`ops-direct-invoke` v3、`ascendc-st-design`、`model-infer-optimize`、`ops-registry-invoke` 等 cannbot 仓插件)。install-helper 以**委托转发**方式兼容其安装方式:自动托管 `@cannbot-plugin/cannbot` 安装器(npm 拉取到 `~/.cannbot/installers/cannbot`,按通道 + TTL 自动刷新),安装时委托其执行,产物布局(`.agents/skills`、标记块 AGENTS.md、`.cannbot/plugins/` 资产、`cannbot-plugin.json` 注册表)与 `npx @cannbot-plugin/cannbot install` 直装**完全一致**。
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
install-helper install ops-direct-invoke --tool opencode # cannbot
|
|
115
|
-
install-helper install ops-direct-invoke --source skills --tool opencode #
|
|
114
|
+
install-helper install ops-direct-invoke --tool opencode # cannbot 仓插件(默认)
|
|
115
|
+
install-helper install ops-direct-invoke --source skills --tool opencode # cannbot-skills 仓旧版
|
|
116
116
|
install-helper update ops-direct-invoke # 更新 = 重新委托安装
|
|
117
117
|
install-helper uninstall ops-direct-invoke # 按 cannbot-plugin.json 注册表精确卸载
|
|
118
118
|
```
|
|
@@ -28,7 +28,7 @@ pluginDirs:
|
|
|
28
28
|
|
|
29
29
|
scanCacheTtlHours: 24
|
|
30
30
|
|
|
31
|
-
# cannbot 仓(https://gitcode.com/cann/cannbot
|
|
31
|
+
# cannbot 仓(https://gitcode.com/cann/cannbot)插件的安装器托管配置。
|
|
32
32
|
# install-helper 以委托转发方式安装 cannbot 型插件:按通道将
|
|
33
33
|
# @cannbot-plugin/cannbot 安装到 ~/.cannbot/installers/cannbot,
|
|
34
34
|
# 超过 ttlHours 后自动按通道刷新。
|
package/dist/index.js
CHANGED
|
@@ -112,6 +112,7 @@ var init_zh_CN = __esm({
|
|
|
112
112
|
error_skill_not_found: "\u672A\u5728\u6CE8\u518C\u8868\u4E2D\u627E\u5230 Skill",
|
|
113
113
|
error_source_not_found: "\u672A\u627E\u5230\u6E90\u6587\u4EF6: {path}",
|
|
114
114
|
error_script_not_found: "\u672A\u627E\u5230\u5B89\u88C5\u811A\u672C: {path}",
|
|
115
|
+
error_cannbot_requires_delegation: "\u63D2\u4EF6 {plugin} \u4E3A cannbot \u4ED3\u59D4\u6258\u5B89\u88C5\u6E90\uFF0C\u987B\u7ECF installPluginRouted \u8DEF\u7531\u5B89\u88C5\uFF08\u5185\u90E8\u8DEF\u7531\u9519\u8BEF\uFF0C\u8BF7\u63D0 Issue \u53CD\u9988\uFF09",
|
|
115
116
|
error_unknown: "\u672A\u77E5\u9519\u8BEF",
|
|
116
117
|
error_not_installed: "\u672A\u5B89\u88C5",
|
|
117
118
|
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",
|
|
@@ -363,6 +364,7 @@ var init_en_US = __esm({
|
|
|
363
364
|
error_skill_not_found: "Skill not found in registry",
|
|
364
365
|
error_source_not_found: "Source not found: {path}",
|
|
365
366
|
error_script_not_found: "Script not found: {path}",
|
|
367
|
+
error_cannbot_requires_delegation: "Plugin {plugin} is a cannbot-source entry and must be installed via installPluginRouted delegation (internal routing error \u2014 please report an issue)",
|
|
366
368
|
error_unknown: "Unknown error",
|
|
367
369
|
error_not_installed: "Not installed",
|
|
368
370
|
error_no_shell: "bash or sh not found, cannot execute install script. Please install Git Bash or WSL",
|
|
@@ -2911,7 +2913,7 @@ function createRepositoryManager(customPath) {
|
|
|
2911
2913
|
|
|
2912
2914
|
// src/core/cannbot-delegate.ts
|
|
2913
2915
|
import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync5, copyFileSync as copyFileSync3, unlinkSync as unlinkSync6, readdirSync as readdirSync8 } from "fs";
|
|
2914
|
-
import { join as join16, resolve as
|
|
2916
|
+
import { join as join16, resolve as resolve3 } from "path";
|
|
2915
2917
|
import { execa as execa6 } from "execa";
|
|
2916
2918
|
|
|
2917
2919
|
// src/core/cannbot-installer.ts
|
|
@@ -3152,7 +3154,7 @@ async function ensureCannbotDiscovery() {
|
|
|
3152
3154
|
|
|
3153
3155
|
// src/core/cannbot-registry.ts
|
|
3154
3156
|
import { existsSync as existsSync13, readFileSync as readFileSync9, readdirSync as readdirSync6, rmSync as rmSync3, rmdirSync, unlinkSync as unlinkSync4, lstatSync as lstatSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
3155
|
-
import { join as join12, resolve, sep as sep2, dirname as dirname6 } from "path";
|
|
3157
|
+
import { join as join12, resolve as resolve2, sep as sep2, dirname as dirname6 } from "path";
|
|
3156
3158
|
|
|
3157
3159
|
// src/core/record.ts
|
|
3158
3160
|
init_paths();
|
|
@@ -3161,38 +3163,88 @@ init_fs_helpers();
|
|
|
3161
3163
|
init_logger();
|
|
3162
3164
|
init_i18n();
|
|
3163
3165
|
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync8, unlinkSync as unlinkSync3, readdirSync as readdirSync5 } from "fs";
|
|
3164
|
-
import { join as join11 } from "path";
|
|
3166
|
+
import { join as join11, resolve } from "path";
|
|
3167
|
+
var LEGACY_LOCATION_KEY = "__legacy__";
|
|
3165
3168
|
function getInstallsDir() {
|
|
3166
3169
|
return join11(getCannbotConfigDir(), "installs");
|
|
3167
3170
|
}
|
|
3168
3171
|
function getRecordPath(pluginId) {
|
|
3169
3172
|
return join11(getInstallsDir(), `${pluginId}.json`);
|
|
3170
3173
|
}
|
|
3171
|
-
function
|
|
3174
|
+
function locationKey(loc) {
|
|
3175
|
+
return `${loc.tool}:${loc.level}:${resolve(loc.installPath)}`;
|
|
3176
|
+
}
|
|
3177
|
+
function readStore(pluginId) {
|
|
3172
3178
|
const recordPath = getRecordPath(pluginId);
|
|
3173
3179
|
if (!existsSync12(recordPath)) {
|
|
3174
3180
|
return null;
|
|
3175
3181
|
}
|
|
3182
|
+
let parsed;
|
|
3176
3183
|
try {
|
|
3177
|
-
|
|
3178
|
-
return JSON.parse(content);
|
|
3184
|
+
parsed = JSON.parse(readFileSync8(recordPath, "utf-8"));
|
|
3179
3185
|
} catch {
|
|
3180
3186
|
logger.warn(t("record_corrupted").replace("{file}", recordPath));
|
|
3181
3187
|
return null;
|
|
3182
3188
|
}
|
|
3189
|
+
const store = parsed;
|
|
3190
|
+
if (store && typeof store === "object" && "locations" in store && store.locations) {
|
|
3191
|
+
return { version: 2, locations: store.locations };
|
|
3192
|
+
}
|
|
3193
|
+
const legacy = parsed;
|
|
3194
|
+
if (legacy && typeof legacy === "object" && typeof legacy.pluginId === "string") {
|
|
3195
|
+
const key = legacy.tool && legacy.level && legacy.installPath ? locationKey(legacy) : LEGACY_LOCATION_KEY;
|
|
3196
|
+
return { version: 2, locations: { [key]: legacy } };
|
|
3197
|
+
}
|
|
3198
|
+
logger.warn(t("record_corrupted").replace("{file}", recordPath));
|
|
3199
|
+
return null;
|
|
3183
3200
|
}
|
|
3184
|
-
function
|
|
3201
|
+
function writeStore(pluginId, store) {
|
|
3185
3202
|
const installsDir = getInstallsDir();
|
|
3186
3203
|
if (!existsSync12(installsDir)) {
|
|
3187
3204
|
mkdirSync5(installsDir, { recursive: true });
|
|
3188
3205
|
}
|
|
3189
|
-
|
|
3190
|
-
atomicWriteFileSync(recordPath, JSON.stringify(record, null, 2));
|
|
3206
|
+
atomicWriteFileSync(getRecordPath(pluginId), JSON.stringify(store, null, 2));
|
|
3191
3207
|
}
|
|
3192
|
-
function
|
|
3208
|
+
function readRecords(pluginId) {
|
|
3209
|
+
const store = readStore(pluginId);
|
|
3210
|
+
return store ? Object.values(store.locations) : [];
|
|
3211
|
+
}
|
|
3212
|
+
var byLatest = (a, b) => (b.installTime || "").localeCompare(a.installTime || "");
|
|
3213
|
+
function readRecord(pluginId) {
|
|
3214
|
+
const records = readRecords(pluginId);
|
|
3215
|
+
if (records.length === 0) {
|
|
3216
|
+
return null;
|
|
3217
|
+
}
|
|
3218
|
+
const cwd = resolve(process.cwd());
|
|
3219
|
+
const localMatch = records.filter((r) => r.level === "project" && resolve(r.installPath) === cwd).sort(byLatest);
|
|
3220
|
+
if (localMatch.length > 0) return localMatch[0];
|
|
3221
|
+
const globalMatch = records.filter((r) => r.level === "global").sort(byLatest);
|
|
3222
|
+
if (globalMatch.length > 0) return globalMatch[0];
|
|
3223
|
+
return [...records].sort(byLatest)[0];
|
|
3224
|
+
}
|
|
3225
|
+
function writeRecord(record) {
|
|
3226
|
+
const store = readStore(record.pluginId) ?? { version: 2, locations: {} };
|
|
3227
|
+
store.locations[locationKey(record)] = record;
|
|
3228
|
+
writeStore(record.pluginId, store);
|
|
3229
|
+
}
|
|
3230
|
+
function deleteRecord(pluginId, where) {
|
|
3193
3231
|
const recordPath = getRecordPath(pluginId);
|
|
3194
|
-
if (existsSync12(recordPath)) {
|
|
3232
|
+
if (!existsSync12(recordPath)) {
|
|
3233
|
+
return;
|
|
3234
|
+
}
|
|
3235
|
+
if (!where) {
|
|
3236
|
+
unlinkSync3(recordPath);
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3239
|
+
const store = readStore(pluginId);
|
|
3240
|
+
if (!store) {
|
|
3241
|
+
return;
|
|
3242
|
+
}
|
|
3243
|
+
delete store.locations[locationKey(where)];
|
|
3244
|
+
if (Object.keys(store.locations).length === 0) {
|
|
3195
3245
|
unlinkSync3(recordPath);
|
|
3246
|
+
} else {
|
|
3247
|
+
writeStore(pluginId, store);
|
|
3196
3248
|
}
|
|
3197
3249
|
}
|
|
3198
3250
|
function scanInstalledFiles(pluginId, displayName, tool, level, installPath, configRoot, manifest, externalRepoNames, configRootConfigLink) {
|
|
@@ -3443,7 +3495,7 @@ function toInstalledEntry(target, registryPath, record) {
|
|
|
3443
3495
|
};
|
|
3444
3496
|
}
|
|
3445
3497
|
function scanCannbotInstalled(target) {
|
|
3446
|
-
const root =
|
|
3498
|
+
const root = resolve2(target || process.cwd());
|
|
3447
3499
|
const installed = [];
|
|
3448
3500
|
for (const tool of CANNBOT_SUPPORTED_TOOLS) {
|
|
3449
3501
|
const result = readCannbotRegistry(root, tool);
|
|
@@ -3469,7 +3521,7 @@ function countMarkerBlocks(content, pluginName) {
|
|
|
3469
3521
|
return content.split(start).length - 1;
|
|
3470
3522
|
}
|
|
3471
3523
|
function removeIfSafe(pathToRemove, allowedBase) {
|
|
3472
|
-
const resolved =
|
|
3524
|
+
const resolved = resolve2(pathToRemove);
|
|
3473
3525
|
if (resolved !== allowedBase && !resolved.startsWith(allowedBase + sep2)) {
|
|
3474
3526
|
return "skipped";
|
|
3475
3527
|
}
|
|
@@ -3486,8 +3538,8 @@ function removeIfSafe(pathToRemove, allowedBase) {
|
|
|
3486
3538
|
}
|
|
3487
3539
|
}
|
|
3488
3540
|
function removeEmptyDirUpward(dirPath, stopAt) {
|
|
3489
|
-
let current =
|
|
3490
|
-
const stop =
|
|
3541
|
+
let current = resolve2(dirPath);
|
|
3542
|
+
const stop = resolve2(stopAt);
|
|
3491
3543
|
let removedAny = false;
|
|
3492
3544
|
while (current.startsWith(stop + sep2)) {
|
|
3493
3545
|
try {
|
|
@@ -3503,7 +3555,7 @@ function removeEmptyDirUpward(dirPath, stopAt) {
|
|
|
3503
3555
|
return removedAny;
|
|
3504
3556
|
}
|
|
3505
3557
|
function cleanHookSettings(hookSettingsPath, target, pluginId) {
|
|
3506
|
-
const resolved =
|
|
3558
|
+
const resolved = resolve2(target, hookSettingsPath);
|
|
3507
3559
|
if (!existsSync13(resolved)) return;
|
|
3508
3560
|
let settings;
|
|
3509
3561
|
try {
|
|
@@ -3616,7 +3668,7 @@ function uninstallCannbotPlugin(pluginId, target) {
|
|
|
3616
3668
|
removedDirs: 0,
|
|
3617
3669
|
errors: []
|
|
3618
3670
|
};
|
|
3619
|
-
const root =
|
|
3671
|
+
const root = resolve2(target || process.cwd());
|
|
3620
3672
|
let read = null;
|
|
3621
3673
|
let record;
|
|
3622
3674
|
for (const tool of CANNBOT_SUPPORTED_TOOLS) {
|
|
@@ -3650,7 +3702,7 @@ function uninstallCannbotPlugin(pluginId, target) {
|
|
|
3650
3702
|
}
|
|
3651
3703
|
if (record.instructions) {
|
|
3652
3704
|
const instructionsPath = join12(root, record.instructions);
|
|
3653
|
-
const resolved =
|
|
3705
|
+
const resolved = resolve2(instructionsPath);
|
|
3654
3706
|
if (resolved.startsWith(allowedBase + sep2) && existsSync13(resolved)) {
|
|
3655
3707
|
try {
|
|
3656
3708
|
const content = readFileSync9(resolved, "utf-8");
|
|
@@ -3734,16 +3786,21 @@ function uninstallCannbotPlugin(pluginId, target) {
|
|
|
3734
3786
|
}
|
|
3735
3787
|
function findOrphanedDelegatedRecords(target) {
|
|
3736
3788
|
const orphans = [];
|
|
3737
|
-
const installed = new Set(scanCannbotInstalled(target).map((e) => e.id));
|
|
3738
3789
|
const installsDir = join12(getCannbotConfigDir(), "installs");
|
|
3739
3790
|
if (!existsSync13(installsDir)) return orphans;
|
|
3740
3791
|
for (const file of readdirSync6(installsDir)) {
|
|
3741
3792
|
if (!file.endsWith(".json") || file === "skills.json") continue;
|
|
3742
3793
|
const pluginId = file.replace(/\.json$/, "");
|
|
3743
3794
|
try {
|
|
3744
|
-
const
|
|
3745
|
-
|
|
3746
|
-
if (
|
|
3795
|
+
const records = readRecords(pluginId);
|
|
3796
|
+
const delegated = records.filter((r) => r?.kind === "delegated");
|
|
3797
|
+
if (delegated.length === 0) continue;
|
|
3798
|
+
const isOrphan = delegated.some((rec) => {
|
|
3799
|
+
const recTarget = rec.installPath || target;
|
|
3800
|
+
const installedThere = new Set(scanCannbotInstalled(recTarget).map((e) => e.id));
|
|
3801
|
+
return !installedThere.has(pluginId);
|
|
3802
|
+
});
|
|
3803
|
+
if (isOrphan) {
|
|
3747
3804
|
orphans.push(pluginId);
|
|
3748
3805
|
}
|
|
3749
3806
|
} catch {
|
|
@@ -3757,7 +3814,7 @@ init_registry();
|
|
|
3757
3814
|
init_manifest();
|
|
3758
3815
|
init_paths();
|
|
3759
3816
|
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
3760
|
-
import { join as join15, basename as basename2 } from "path";
|
|
3817
|
+
import { join as join15, basename as basename2, isAbsolute } from "path";
|
|
3761
3818
|
import { execa as execa5, execaSync as execaSync2 } from "execa";
|
|
3762
3819
|
|
|
3763
3820
|
// src/core/backup.ts
|
|
@@ -3884,10 +3941,7 @@ function readAllRecords() {
|
|
|
3884
3941
|
const records = [];
|
|
3885
3942
|
const plugins = getAllPlugins();
|
|
3886
3943
|
for (const plugin of plugins) {
|
|
3887
|
-
|
|
3888
|
-
if (record) {
|
|
3889
|
-
records.push(record);
|
|
3890
|
-
}
|
|
3944
|
+
records.push(...readRecords(plugin.id));
|
|
3891
3945
|
}
|
|
3892
3946
|
return records;
|
|
3893
3947
|
}
|
|
@@ -4281,7 +4335,7 @@ function scriptSupportsTool(scriptPath, tool) {
|
|
|
4281
4335
|
}
|
|
4282
4336
|
}
|
|
4283
4337
|
async function installPlugin(opts) {
|
|
4284
|
-
const plugin = getPluginById(opts.pluginId);
|
|
4338
|
+
const plugin = opts.plugin ?? getPluginById(opts.pluginId);
|
|
4285
4339
|
if (!plugin) {
|
|
4286
4340
|
return {
|
|
4287
4341
|
success: false,
|
|
@@ -4292,7 +4346,17 @@ async function installPlugin(opts) {
|
|
|
4292
4346
|
warnings: []
|
|
4293
4347
|
};
|
|
4294
4348
|
}
|
|
4295
|
-
|
|
4349
|
+
if (plugin.source === "cannbot") {
|
|
4350
|
+
return {
|
|
4351
|
+
success: false,
|
|
4352
|
+
pluginId: opts.pluginId,
|
|
4353
|
+
skillsCount: 0,
|
|
4354
|
+
agentsCount: 0,
|
|
4355
|
+
errors: [t("error_cannbot_requires_delegation").replace("{plugin}", plugin.displayName)],
|
|
4356
|
+
warnings: []
|
|
4357
|
+
};
|
|
4358
|
+
}
|
|
4359
|
+
const pluginDir = isAbsolute(plugin.dir) ? plugin.dir : join15(opts.repoPath, plugin.dir);
|
|
4296
4360
|
const cwd = opts.installPath || process.cwd();
|
|
4297
4361
|
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
4298
4362
|
const agentsFile = join15(configRoot, getAgentsFileName(opts.tool));
|
|
@@ -4586,7 +4650,7 @@ function installerSupportsBundledFlag() {
|
|
|
4586
4650
|
}
|
|
4587
4651
|
async function delegateInstall(options) {
|
|
4588
4652
|
const { pluginId, tool, level } = options;
|
|
4589
|
-
const target =
|
|
4653
|
+
const target = resolve3(options.target || process.cwd());
|
|
4590
4654
|
const displayName = options.displayName || pluginId;
|
|
4591
4655
|
const result = {
|
|
4592
4656
|
success: false,
|
|
@@ -4713,7 +4777,7 @@ init_constants();
|
|
|
4713
4777
|
init_logger();
|
|
4714
4778
|
init_i18n();
|
|
4715
4779
|
import { existsSync as existsSync18, mkdirSync as mkdirSync7, symlinkSync as symlinkSync2, readdirSync as readdirSync9, rmSync as rmSync5, realpathSync as realpathSync2, readlinkSync as readlinkSync2, cpSync as cpSync2 } from "fs";
|
|
4716
|
-
import { join as join17, dirname as dirname7, basename as basename3, isAbsolute } from "path";
|
|
4780
|
+
import { join as join17, dirname as dirname7, basename as basename3, isAbsolute as isAbsolute2 } from "path";
|
|
4717
4781
|
import { select as select3, checkbox, Separator as Separator2 } from "@inquirer/prompts";
|
|
4718
4782
|
import chalk5 from "chalk";
|
|
4719
4783
|
import Table from "cli-table3";
|
|
@@ -5232,7 +5296,7 @@ function listAllSkills() {
|
|
|
5232
5296
|
}
|
|
5233
5297
|
function resolveSkillSourcePath(skill, repoPath) {
|
|
5234
5298
|
if (skill.filePath) {
|
|
5235
|
-
const absPath =
|
|
5299
|
+
const absPath = isAbsolute2(skill.filePath) ? skill.filePath : join17(repoPath, skill.filePath);
|
|
5236
5300
|
if (existsSync18(absPath)) {
|
|
5237
5301
|
return dirname7(absPath);
|
|
5238
5302
|
}
|
|
@@ -5319,7 +5383,9 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
5319
5383
|
""
|
|
5320
5384
|
];
|
|
5321
5385
|
if (successResults.length === 1) {
|
|
5322
|
-
const plugin = findPlugin(successResults[0].pluginId
|
|
5386
|
+
const plugin = findPlugin(successResults[0].pluginId, {
|
|
5387
|
+
source: successResults[0].source
|
|
5388
|
+
});
|
|
5323
5389
|
const docsPath = plugin ? `${plugin.dir}/quickstart.md` : `${successResults[0].pluginId}/quickstart.md`;
|
|
5324
5390
|
lines.push(
|
|
5325
5391
|
` ${chalk6.dim(t("install_enhanced_docs"))}: ${chalk6.dim(docsPath)}`
|
|
@@ -5487,7 +5553,8 @@ async function pluginInstallFlow() {
|
|
|
5487
5553
|
displayName: selected[index]?.plugin?.displayName || result.pluginId,
|
|
5488
5554
|
success: result.success,
|
|
5489
5555
|
skillsCount: result.skillsCount,
|
|
5490
|
-
agentsCount: result.agentsCount
|
|
5556
|
+
agentsCount: result.agentsCount,
|
|
5557
|
+
source: selected[index]?.source
|
|
5491
5558
|
}));
|
|
5492
5559
|
printInstallSummary(summary);
|
|
5493
5560
|
const configRoot = getConfigRoot(answers.tool, answers.level);
|
|
@@ -6087,6 +6154,9 @@ async function installCommand(names, options) {
|
|
|
6087
6154
|
logger.info(`${t("install_to")}: ${chalk10.cyan(getSkillsRoot(tool2, level2))}`);
|
|
6088
6155
|
logger.info(`${t("start_to_use").replace("{tool}", chalk10.green(tool2))}`);
|
|
6089
6156
|
logger.blank();
|
|
6157
|
+
if (failCount > 0) {
|
|
6158
|
+
process.exitCode = 1;
|
|
6159
|
+
}
|
|
6090
6160
|
return;
|
|
6091
6161
|
}
|
|
6092
6162
|
}
|
|
@@ -6123,6 +6193,7 @@ async function installCommand(names, options) {
|
|
|
6123
6193
|
logger.step(` ${p.id}${badge} (${p.aliases.join(", ")})`);
|
|
6124
6194
|
}
|
|
6125
6195
|
logger.info(`${t("available_skills")}: ${chalk10.cyan("install-helper install --list")}`);
|
|
6196
|
+
process.exitCode = 1;
|
|
6126
6197
|
return;
|
|
6127
6198
|
}
|
|
6128
6199
|
let tool;
|
|
@@ -6176,7 +6247,6 @@ async function installCommand(names, options) {
|
|
|
6176
6247
|
spinner.fail(t("repo_clone_failed").replace("{error}", error instanceof Error ? error.message : t("error_unknown")).replace("{url}", "").replace("{dir}", ""));
|
|
6177
6248
|
return;
|
|
6178
6249
|
}
|
|
6179
|
-
const allPlugins = getAllPlugins();
|
|
6180
6250
|
const results = await installPlugins(
|
|
6181
6251
|
pluginsToInstall,
|
|
6182
6252
|
tool,
|
|
@@ -6187,17 +6257,21 @@ async function installCommand(names, options) {
|
|
|
6187
6257
|
source
|
|
6188
6258
|
);
|
|
6189
6259
|
const summary = results.map((result) => {
|
|
6190
|
-
const plugin =
|
|
6260
|
+
const plugin = findPlugin(result.pluginId, { source });
|
|
6191
6261
|
return {
|
|
6192
6262
|
pluginId: result.pluginId,
|
|
6193
6263
|
displayName: plugin?.displayName || result.pluginId,
|
|
6194
6264
|
success: result.success,
|
|
6195
6265
|
skillsCount: result.skillsCount,
|
|
6196
|
-
agentsCount: result.agentsCount
|
|
6266
|
+
agentsCount: result.agentsCount,
|
|
6267
|
+
source: plugin?.source
|
|
6197
6268
|
};
|
|
6198
6269
|
});
|
|
6199
6270
|
printInstallSummary(summary);
|
|
6200
6271
|
printEnhancedSummary(summary, tool, configRoot);
|
|
6272
|
+
if (results.some((r) => !r.success)) {
|
|
6273
|
+
process.exitCode = 1;
|
|
6274
|
+
}
|
|
6201
6275
|
}
|
|
6202
6276
|
}
|
|
6203
6277
|
if (skills.length > 0) {
|
|
@@ -6234,6 +6308,9 @@ async function installCommand(names, options) {
|
|
|
6234
6308
|
logger.info(`${t("install_to")}: ${chalk10.cyan(getSkillsRoot(tool, level))}`);
|
|
6235
6309
|
logger.info(`${t("start_to_use").replace("{tool}", chalk10.green(tool))}`);
|
|
6236
6310
|
logger.blank();
|
|
6311
|
+
if (failCount > 0) {
|
|
6312
|
+
process.exitCode = 1;
|
|
6313
|
+
}
|
|
6237
6314
|
}
|
|
6238
6315
|
}
|
|
6239
6316
|
async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes, source) {
|
|
@@ -6274,7 +6351,7 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
|
|
|
6274
6351
|
// src/commands/uninstall.ts
|
|
6275
6352
|
init_registry();
|
|
6276
6353
|
import { existsSync as existsSync21, unlinkSync as unlinkSync8, rmdirSync as rmdirSync2, readdirSync as readdirSync11, readFileSync as readFileSync15 } from "fs";
|
|
6277
|
-
import { resolve as
|
|
6354
|
+
import { resolve as resolve4, basename as basename4, sep as sep3, join as join20 } from "path";
|
|
6278
6355
|
import chalk11 from "chalk";
|
|
6279
6356
|
import { select as select5, checkbox as checkbox2, Separator as Separator4, confirm as confirm3 } from "@inquirer/prompts";
|
|
6280
6357
|
init_config();
|
|
@@ -6674,13 +6751,13 @@ async function uninstallPluginById(pluginId, batchMode) {
|
|
|
6674
6751
|
return;
|
|
6675
6752
|
}
|
|
6676
6753
|
logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
|
|
6677
|
-
const configRoot =
|
|
6678
|
-
const allowedBases = [
|
|
6754
|
+
const configRoot = record.configRoot;
|
|
6755
|
+
const allowedBases = [resolve4(configRoot), resolve4(record.installPath)];
|
|
6679
6756
|
if (record.tool === "codex") {
|
|
6680
|
-
allowedBases.push(
|
|
6757
|
+
allowedBases.push(resolve4(getSkillsRoot(record.tool, record.level, record.installPath)));
|
|
6681
6758
|
}
|
|
6682
6759
|
const isSafePath = (p) => {
|
|
6683
|
-
const resolved =
|
|
6760
|
+
const resolved = resolve4(p);
|
|
6684
6761
|
return allowedBases.some((base) => resolved === base || resolved.startsWith(base + sep3));
|
|
6685
6762
|
};
|
|
6686
6763
|
let removedFiles = 0;
|
|
@@ -6708,7 +6785,7 @@ async function uninstallPluginById(pluginId, batchMode) {
|
|
|
6708
6785
|
const sortedDirs = [...record.directories].filter(isSafePath).sort((a, b) => b.length - a.length);
|
|
6709
6786
|
for (const dirPath of sortedDirs) {
|
|
6710
6787
|
try {
|
|
6711
|
-
if (
|
|
6788
|
+
if (resolve4(dirPath) === resolve4(configRoot)) {
|
|
6712
6789
|
continue;
|
|
6713
6790
|
}
|
|
6714
6791
|
if (existsSync21(dirPath)) {
|
|
@@ -6725,7 +6802,7 @@ async function uninstallPluginById(pluginId, batchMode) {
|
|
|
6725
6802
|
}
|
|
6726
6803
|
if (record.tool === "codex") {
|
|
6727
6804
|
try {
|
|
6728
|
-
const agentsRoot =
|
|
6805
|
+
const agentsRoot = resolve4(getSkillsRoot(record.tool, record.level, record.installPath), "..");
|
|
6729
6806
|
if (existsSync21(agentsRoot) && readdirSync11(agentsRoot).length === 0) {
|
|
6730
6807
|
rmdirSync2(agentsRoot);
|
|
6731
6808
|
logger.step(` ${t("uninstall_clean_empty_dir")}: ${basename4(agentsRoot)}/`);
|
|
@@ -6734,7 +6811,11 @@ async function uninstallPluginById(pluginId, batchMode) {
|
|
|
6734
6811
|
} catch {
|
|
6735
6812
|
}
|
|
6736
6813
|
}
|
|
6737
|
-
deleteRecord(plugin.id
|
|
6814
|
+
deleteRecord(plugin.id, {
|
|
6815
|
+
tool: record.tool,
|
|
6816
|
+
level: record.level,
|
|
6817
|
+
installPath: record.installPath
|
|
6818
|
+
});
|
|
6738
6819
|
removeInstalledPlugin(plugin.id);
|
|
6739
6820
|
const backups = findBackups(configRoot);
|
|
6740
6821
|
const otherBackups = backups.filter((b) => b.pluginId !== pluginId);
|