@synity/bitrix-skills 1.3.7 → 1.3.8
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/CHANGELOG.md +8 -0
- package/dist/cli.js +89 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix(list): global features now show correct [installed] status by checking ~/.claude/skills/<name>/ on disk instead of project manifest
|
|
8
|
+
|
|
9
|
+
fix(install): add --all flag + generic install handler for bx, bx-crm, bx-calendar global skills
|
|
10
|
+
|
|
3
11
|
## 1.3.7
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/cli.js
CHANGED
|
@@ -944,11 +944,15 @@ import { createRequire } from "module";
|
|
|
944
944
|
|
|
945
945
|
// src/commands/install.ts
|
|
946
946
|
init_esm_shims();
|
|
947
|
+
init_fs_safety();
|
|
947
948
|
import { Command, Option } from "clipanion";
|
|
948
949
|
import chalk from "chalk";
|
|
949
950
|
import { existsSync as existsSync4 } from "fs";
|
|
951
|
+
import { access as access4, copyFile as copyFile3, mkdir as mkdir4, readdir as readdir2 } from "fs/promises";
|
|
950
952
|
import { createInterface } from "readline";
|
|
951
|
-
import { join as join4, relative as relative2 } from "path";
|
|
953
|
+
import { dirname as dirname3, join as join4, relative as relative2, resolve as resolve2 } from "path";
|
|
954
|
+
import { homedir as homedir2 } from "os";
|
|
955
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
952
956
|
|
|
953
957
|
// src/lib/feature-registry.ts
|
|
954
958
|
init_esm_shims();
|
|
@@ -1046,11 +1050,11 @@ function computeChecksum(filepath) {
|
|
|
1046
1050
|
|
|
1047
1051
|
// src/commands/install.ts
|
|
1048
1052
|
function promptKey() {
|
|
1049
|
-
return new Promise((
|
|
1053
|
+
return new Promise((resolve4) => {
|
|
1050
1054
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1051
1055
|
rl.question(chalk.cyan("License key (Enter to skip \u2014 free tier only): "), (answer) => {
|
|
1052
1056
|
rl.close();
|
|
1053
|
-
|
|
1057
|
+
resolve4(answer.trim());
|
|
1054
1058
|
});
|
|
1055
1059
|
});
|
|
1056
1060
|
}
|
|
@@ -1096,6 +1100,63 @@ async function installBxTask(cwd) {
|
|
|
1096
1100
|
return { ok: false, message: `bx-task: ${err.message}` };
|
|
1097
1101
|
}
|
|
1098
1102
|
}
|
|
1103
|
+
async function getFeatureAssetsDir(featureName) {
|
|
1104
|
+
const here = dirname3(fileURLToPath5(import.meta.url));
|
|
1105
|
+
const candidates = [
|
|
1106
|
+
// dist/cli.js context (inlined): ../src/features/<name>/assets
|
|
1107
|
+
resolve2(here, `../src/features/${featureName}/assets`),
|
|
1108
|
+
// dist/features/<name>/ context: ../../../src/features/<name>/assets
|
|
1109
|
+
resolve2(here, `../../../src/features/${featureName}/assets`),
|
|
1110
|
+
// dev (running from src/)
|
|
1111
|
+
resolve2(here, `../features/${featureName}/assets`)
|
|
1112
|
+
];
|
|
1113
|
+
for (const c of candidates) {
|
|
1114
|
+
try {
|
|
1115
|
+
await access4(c);
|
|
1116
|
+
return c;
|
|
1117
|
+
} catch {
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return candidates[0];
|
|
1121
|
+
}
|
|
1122
|
+
async function copyDirRecursive(srcDir, destDir, skillBase, installedFiles, onConflict) {
|
|
1123
|
+
await mkdir4(destDir, { recursive: true });
|
|
1124
|
+
const entries = await readdir2(srcDir, { withFileTypes: true });
|
|
1125
|
+
for (const entry of entries) {
|
|
1126
|
+
const src = join4(srcDir, entry.name);
|
|
1127
|
+
const dest = join4(destDir, entry.name);
|
|
1128
|
+
if (entry.isDirectory()) {
|
|
1129
|
+
await copyDirRecursive(src, dest, skillBase, installedFiles, onConflict);
|
|
1130
|
+
continue;
|
|
1131
|
+
}
|
|
1132
|
+
assertContainedIn(dest, skillBase, dest);
|
|
1133
|
+
await assertNotSymlink(dest);
|
|
1134
|
+
try {
|
|
1135
|
+
await access4(dest);
|
|
1136
|
+
if (onConflict === "skip") continue;
|
|
1137
|
+
} catch {
|
|
1138
|
+
}
|
|
1139
|
+
await copyFile3(src, dest);
|
|
1140
|
+
installedFiles.push(dest);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
async function installGlobalSkill(featureName) {
|
|
1144
|
+
try {
|
|
1145
|
+
const skillBase = resolve2(homedir2(), ".claude", "skills");
|
|
1146
|
+
const dest = resolve2(skillBase, featureName);
|
|
1147
|
+
const assetsDir = await getFeatureAssetsDir(featureName);
|
|
1148
|
+
const installedFiles = [];
|
|
1149
|
+
await copyDirRecursive(assetsDir, dest, skillBase, installedFiles, "overwrite");
|
|
1150
|
+
return {
|
|
1151
|
+
ok: true,
|
|
1152
|
+
message: `${featureName}: ${installedFiles.length} files installed`,
|
|
1153
|
+
installPath: dest,
|
|
1154
|
+
installedAbsPaths: installedFiles
|
|
1155
|
+
};
|
|
1156
|
+
} catch (err) {
|
|
1157
|
+
return { ok: false, message: `${featureName}: ${err.message}` };
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1099
1160
|
function upsertFeature(manifest, entry) {
|
|
1100
1161
|
const idx = manifest.features.findIndex((f) => f.name === entry.name);
|
|
1101
1162
|
const features = [...manifest.features];
|
|
@@ -1122,6 +1183,7 @@ var InstallCommand = class extends Command {
|
|
|
1122
1183
|
]
|
|
1123
1184
|
});
|
|
1124
1185
|
key = Option.String("--key", { description: "License key to unlock paid tier features" });
|
|
1186
|
+
all = Option.Boolean("--all", false, { description: "Install all available features" });
|
|
1125
1187
|
featuresFlag = Option.String("--features", { description: "Comma-separated feature names" });
|
|
1126
1188
|
featureArgs = Option.Rest({ required: 0 });
|
|
1127
1189
|
async execute() {
|
|
@@ -1207,10 +1269,15 @@ Installing ${chalk.bold(name)}...
|
|
|
1207
1269
|
ok = r.ok;
|
|
1208
1270
|
message = r.message;
|
|
1209
1271
|
if (r.installPath) {
|
|
1210
|
-
const { homedir: homedir2 } = await import("os");
|
|
1211
1272
|
installPath = join4(homedir2(), ".claude", "skills", "bx-task");
|
|
1212
1273
|
}
|
|
1213
1274
|
installedAbsPaths = r.installedAbsPaths ?? [];
|
|
1275
|
+
} else if (featureInfo.target === "global") {
|
|
1276
|
+
const r = await installGlobalSkill(name);
|
|
1277
|
+
ok = r.ok;
|
|
1278
|
+
message = r.message;
|
|
1279
|
+
if (r.installPath) installPath = r.installPath;
|
|
1280
|
+
installedAbsPaths = r.installedAbsPaths ?? [];
|
|
1214
1281
|
} else {
|
|
1215
1282
|
this.context.stderr.write(chalk.yellow(` ! No install handler for feature: ${name}
|
|
1216
1283
|
`));
|
|
@@ -1321,6 +1388,15 @@ Uninstalling ${chalk2.bold(name)}...
|
|
|
1321
1388
|
init_esm_shims();
|
|
1322
1389
|
import { Command as Command3 } from "clipanion";
|
|
1323
1390
|
import chalk3 from "chalk";
|
|
1391
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1392
|
+
import { resolve as resolve3 } from "path";
|
|
1393
|
+
import { homedir as homedir3 } from "os";
|
|
1394
|
+
function isInstalled(f, manifest) {
|
|
1395
|
+
if (f.target === "global") {
|
|
1396
|
+
return existsSync5(resolve3(homedir3(), ".claude", "skills", f.name));
|
|
1397
|
+
}
|
|
1398
|
+
return !!manifest?.features.find((e) => e.name === f.name);
|
|
1399
|
+
}
|
|
1324
1400
|
var ListCommand = class extends Command3 {
|
|
1325
1401
|
static paths = [["list"]];
|
|
1326
1402
|
static usage = Command3.Usage({
|
|
@@ -1329,20 +1405,19 @@ var ListCommand = class extends Command3 {
|
|
|
1329
1405
|
async execute() {
|
|
1330
1406
|
const features = listFeatures();
|
|
1331
1407
|
const manifest = readManifest(process.cwd());
|
|
1332
|
-
const installed = new Map(manifest?.features.map((f) => [f.name, f]) ?? []);
|
|
1333
1408
|
if (features.length === 0) {
|
|
1334
1409
|
this.context.stdout.write(chalk3.yellow("No features found.\n"));
|
|
1335
1410
|
return 0;
|
|
1336
1411
|
}
|
|
1337
1412
|
this.context.stdout.write("\nAvailable features:\n");
|
|
1338
1413
|
for (const f of features) {
|
|
1339
|
-
const
|
|
1340
|
-
const check =
|
|
1414
|
+
const installed = isInstalled(f, manifest);
|
|
1415
|
+
const check = installed ? chalk3.green("\u2713") : chalk3.gray("\u25CB");
|
|
1341
1416
|
const name = chalk3.bold(f.name.padEnd(12));
|
|
1342
1417
|
const ver = chalk3.cyan(f.version.padEnd(14));
|
|
1343
1418
|
const target = chalk3.gray(f.target.padEnd(8));
|
|
1344
1419
|
const desc = f.description;
|
|
1345
|
-
const status =
|
|
1420
|
+
const status = installed ? chalk3.green("[installed]") : chalk3.gray("[not installed]");
|
|
1346
1421
|
this.context.stdout.write(` ${check} ${name} ${ver} ${target} ${desc} ${status}
|
|
1347
1422
|
`);
|
|
1348
1423
|
}
|
|
@@ -1354,7 +1429,7 @@ var ListCommand = class extends Command3 {
|
|
|
1354
1429
|
init_esm_shims();
|
|
1355
1430
|
import { Command as Command4 } from "clipanion";
|
|
1356
1431
|
import chalk4 from "chalk";
|
|
1357
|
-
import { existsSync as
|
|
1432
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1358
1433
|
import { join as join5 } from "path";
|
|
1359
1434
|
var VerifyCommand = class extends Command4 {
|
|
1360
1435
|
static paths = [["verify"]];
|
|
@@ -1378,7 +1453,7 @@ var VerifyCommand = class extends Command4 {
|
|
|
1378
1453
|
`);
|
|
1379
1454
|
this.context.stdout.write(chalk4.gray(` install path: ${feature.installPath}
|
|
1380
1455
|
`));
|
|
1381
|
-
if (!
|
|
1456
|
+
if (!existsSync6(feature.installPath)) {
|
|
1382
1457
|
this.context.stderr.write(chalk4.red(` \u2717 install path missing: ${feature.installPath}
|
|
1383
1458
|
`));
|
|
1384
1459
|
anyMismatch = true;
|
|
@@ -1391,7 +1466,7 @@ var VerifyCommand = class extends Command4 {
|
|
|
1391
1466
|
}
|
|
1392
1467
|
for (const [rel, expectedHash] of Object.entries(stored)) {
|
|
1393
1468
|
const absPath = join5(feature.installPath, rel);
|
|
1394
|
-
if (!
|
|
1469
|
+
if (!existsSync6(absPath)) {
|
|
1395
1470
|
this.context.stderr.write(chalk4.red(` \u2717 missing: ${rel}
|
|
1396
1471
|
`));
|
|
1397
1472
|
anyMismatch = true;
|
|
@@ -1430,7 +1505,7 @@ var VerifyCommand = class extends Command4 {
|
|
|
1430
1505
|
init_esm_shims();
|
|
1431
1506
|
import { Command as Command5 } from "clipanion";
|
|
1432
1507
|
import chalk5 from "chalk";
|
|
1433
|
-
import { existsSync as
|
|
1508
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1434
1509
|
import { relative as relative3 } from "path";
|
|
1435
1510
|
var UpdateCommand = class extends Command5 {
|
|
1436
1511
|
static paths = [["update"]];
|
|
@@ -1478,7 +1553,7 @@ var UpdateCommand = class extends Command5 {
|
|
|
1478
1553
|
const { buildDestMap: buildDestMap2 } = await Promise.resolve().then(() => (init_dest_map(), dest_map_exports));
|
|
1479
1554
|
const assetManifest = await loadManifest2();
|
|
1480
1555
|
const dests = buildDestMap2(assetManifest, cwd);
|
|
1481
|
-
installedAbsPaths = dests.map((d) => d.destAbs).filter((p) =>
|
|
1556
|
+
installedAbsPaths = dests.map((d) => d.destAbs).filter((p) => existsSync7(p));
|
|
1482
1557
|
} catch {
|
|
1483
1558
|
}
|
|
1484
1559
|
} else if (feature.name === "bx-task") {
|
|
@@ -1507,7 +1582,7 @@ var UpdateCommand = class extends Command5 {
|
|
|
1507
1582
|
const checksums = {};
|
|
1508
1583
|
for (const absPath of installedAbsPaths) {
|
|
1509
1584
|
try {
|
|
1510
|
-
if (
|
|
1585
|
+
if (existsSync7(absPath)) {
|
|
1511
1586
|
const rel = relative3(feature.installPath, absPath);
|
|
1512
1587
|
checksums[rel] = computeChecksum(absPath);
|
|
1513
1588
|
}
|