bip-skills 1.4.9 → 1.4.10
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/cli.mjs +209 -97
- package/package.json +16 -18
package/dist/cli.mjs
CHANGED
|
@@ -9,11 +9,10 @@ import { t as require_gray_matter } from "./_chunks/libs/gray-matter.mjs";
|
|
|
9
9
|
import "./_chunks/libs/extend-shallow.mjs";
|
|
10
10
|
import "./_chunks/libs/esprima.mjs";
|
|
11
11
|
import { t as xdgConfig } from "./_chunks/libs/xdg-basedir.mjs";
|
|
12
|
-
import { execSync,
|
|
12
|
+
import { execSync, spawnSync } from "child_process";
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
14
14
|
import { basename, dirname, isAbsolute, join, normalize, posix, relative, resolve, sep } from "path";
|
|
15
15
|
import { homedir, platform, tmpdir } from "os";
|
|
16
|
-
import { createHash } from "crypto";
|
|
17
16
|
import { fileURLToPath } from "url";
|
|
18
17
|
import * as readline from "readline";
|
|
19
18
|
import { Writable } from "stream";
|
|
@@ -21,6 +20,7 @@ import { Buffer } from "node:buffer";
|
|
|
21
20
|
import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
|
|
22
21
|
import http from "node:http";
|
|
23
22
|
import https from "node:https";
|
|
23
|
+
import { createHash } from "crypto";
|
|
24
24
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
25
25
|
const AGENTS_DIR$2 = ".agents";
|
|
26
26
|
const SKILLS_SUBDIR = "skills";
|
|
@@ -2070,7 +2070,7 @@ function createEmptyLocalLock() {
|
|
|
2070
2070
|
skills: {}
|
|
2071
2071
|
};
|
|
2072
2072
|
}
|
|
2073
|
-
var version$1 = "1.4.
|
|
2073
|
+
var version$1 = "1.4.10";
|
|
2074
2074
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
2075
2075
|
async function isSourcePrivate(source) {
|
|
2076
2076
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2083,6 +2083,14 @@ function initTelemetry(version) {
|
|
|
2083
2083
|
function getWellKnownFileCount(skill) {
|
|
2084
2084
|
return skill.declaredFiles.length > 0 ? skill.declaredFiles.length : skill.files.size;
|
|
2085
2085
|
}
|
|
2086
|
+
function getWellKnownSkillHash(skill) {
|
|
2087
|
+
return skill.indexEntry.hash || skill.indexEntry.contentHash || skill.indexEntry.skillFolderHash || "";
|
|
2088
|
+
}
|
|
2089
|
+
function getWellKnownSkillPath(skill) {
|
|
2090
|
+
if (skill.indexEntry.entry) return skill.indexEntry.entry;
|
|
2091
|
+
if (skill.installTarget.type === "inline") return skill.installTarget.skillRoot ? posix.join(skill.installTarget.skillRoot, "SKILL.md") : "SKILL.md";
|
|
2092
|
+
return skill.installTarget.subpath ? posix.join(skill.installTarget.subpath, "SKILL.md") : "SKILL.md";
|
|
2093
|
+
}
|
|
2086
2094
|
function getWellKnownEmptyStateMessage(status, totalSkillCount, invalidSkillCount) {
|
|
2087
2095
|
switch (status) {
|
|
2088
2096
|
case "no-valid-entries": return totalSkillCount > 0 ? `Found a skills index, but all ${totalSkillCount} entr${totalSkillCount === 1 ? "y is" : "ies are"} invalid. Check that each entry has a top-level SKILL.md in files[].` : "Found a skills index, but it does not contain any valid skill entries.";
|
|
@@ -2590,7 +2598,8 @@ async function handleWellKnownSkills(source, url, options, spinner, allowFallbac
|
|
|
2590
2598
|
source: sourceIdentifier,
|
|
2591
2599
|
sourceType: "well-known",
|
|
2592
2600
|
sourceUrl: skill.sourceUrl,
|
|
2593
|
-
|
|
2601
|
+
skillPath: getWellKnownSkillPath(skill),
|
|
2602
|
+
skillFolderHash: getWellKnownSkillHash(skill)
|
|
2594
2603
|
});
|
|
2595
2604
|
} catch {}
|
|
2596
2605
|
}
|
|
@@ -4106,6 +4115,146 @@ function parseRemoveOptions(args) {
|
|
|
4106
4115
|
options
|
|
4107
4116
|
};
|
|
4108
4117
|
}
|
|
4118
|
+
function getUpdateCheckApiBase() {
|
|
4119
|
+
return process.env.SKILLS_API_URL || DEFAULT_SEARCH_API_BASE;
|
|
4120
|
+
}
|
|
4121
|
+
function canCheckWithServer(skill) {
|
|
4122
|
+
return skill.entry.sourceType !== "github";
|
|
4123
|
+
}
|
|
4124
|
+
function canCheckWithGitHub(skill) {
|
|
4125
|
+
return skill.entry.sourceType === "github" && Boolean(skill.entry.skillFolderHash) && Boolean(skill.entry.skillPath);
|
|
4126
|
+
}
|
|
4127
|
+
function buildUpdateCheckRequest(skills) {
|
|
4128
|
+
return {
|
|
4129
|
+
forceRefresh: true,
|
|
4130
|
+
skills: skills.map(({ name, entry }) => ({
|
|
4131
|
+
name,
|
|
4132
|
+
source: entry.source,
|
|
4133
|
+
sourceType: entry.sourceType,
|
|
4134
|
+
sourceUrl: entry.sourceUrl,
|
|
4135
|
+
skillPath: entry.skillPath,
|
|
4136
|
+
skillFolderHash: entry.skillFolderHash
|
|
4137
|
+
}))
|
|
4138
|
+
};
|
|
4139
|
+
}
|
|
4140
|
+
async function checkServerUpdates(skills, apiBaseUrl) {
|
|
4141
|
+
if (skills.length === 0) return {
|
|
4142
|
+
checkedCount: 0,
|
|
4143
|
+
skippedCount: 0,
|
|
4144
|
+
updates: [],
|
|
4145
|
+
errors: []
|
|
4146
|
+
};
|
|
4147
|
+
const byName = new Map(skills.map((skill) => [skill.name, skill]));
|
|
4148
|
+
const url = `${apiBaseUrl.replace(/\/$/, "")}/api/check-updates`;
|
|
4149
|
+
const request = buildUpdateCheckRequest(skills);
|
|
4150
|
+
debugLog(`[update] requesting update check: ${url}`);
|
|
4151
|
+
debugLog(`[update] update check request: ${JSON.stringify(request)}`);
|
|
4152
|
+
const response = await fetchWithSelectiveTls(url, {
|
|
4153
|
+
method: "POST",
|
|
4154
|
+
headers: {
|
|
4155
|
+
"Content-Type": "application/json",
|
|
4156
|
+
Accept: "application/json"
|
|
4157
|
+
},
|
|
4158
|
+
body: JSON.stringify(request)
|
|
4159
|
+
});
|
|
4160
|
+
debugLog(`[update] update check response status: ${response.status} ${response.statusText}`);
|
|
4161
|
+
if (!response.ok) throw new Error(`Update check failed with status ${response.status}`);
|
|
4162
|
+
const responseText = await response.text();
|
|
4163
|
+
debugLog(`[update] update check response body: ${responseText}`);
|
|
4164
|
+
const data = JSON.parse(responseText);
|
|
4165
|
+
return {
|
|
4166
|
+
checkedCount: data.checked ?? skills.length,
|
|
4167
|
+
skippedCount: data.skipped ?? 0,
|
|
4168
|
+
updates: (data.updates || []).flatMap((update) => {
|
|
4169
|
+
const skill = byName.get(update.name);
|
|
4170
|
+
if (!skill) return [];
|
|
4171
|
+
return [{
|
|
4172
|
+
name: update.name,
|
|
4173
|
+
source: update.source,
|
|
4174
|
+
entry: skill.entry,
|
|
4175
|
+
currentHash: update.currentHash,
|
|
4176
|
+
latestHash: update.latestHash
|
|
4177
|
+
}];
|
|
4178
|
+
}),
|
|
4179
|
+
errors: data.errors || []
|
|
4180
|
+
};
|
|
4181
|
+
}
|
|
4182
|
+
async function checkGitHubUpdates(skills, token) {
|
|
4183
|
+
const updates = [];
|
|
4184
|
+
const errors = [];
|
|
4185
|
+
for (const { name, entry } of skills) try {
|
|
4186
|
+
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
|
|
4187
|
+
if (!latestHash) {
|
|
4188
|
+
errors.push({
|
|
4189
|
+
name,
|
|
4190
|
+
source: entry.source,
|
|
4191
|
+
error: "Could not fetch from GitHub"
|
|
4192
|
+
});
|
|
4193
|
+
continue;
|
|
4194
|
+
}
|
|
4195
|
+
if (latestHash !== entry.skillFolderHash) updates.push({
|
|
4196
|
+
name,
|
|
4197
|
+
source: entry.source,
|
|
4198
|
+
entry,
|
|
4199
|
+
currentHash: entry.skillFolderHash,
|
|
4200
|
+
latestHash
|
|
4201
|
+
});
|
|
4202
|
+
} catch (err) {
|
|
4203
|
+
errors.push({
|
|
4204
|
+
name,
|
|
4205
|
+
source: entry.source,
|
|
4206
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
4207
|
+
});
|
|
4208
|
+
}
|
|
4209
|
+
return {
|
|
4210
|
+
checkedCount: skills.length,
|
|
4211
|
+
skippedCount: 0,
|
|
4212
|
+
updates,
|
|
4213
|
+
errors
|
|
4214
|
+
};
|
|
4215
|
+
}
|
|
4216
|
+
async function checkSkillUpdates(skills, options = {}) {
|
|
4217
|
+
const serverSkills = skills.filter(canCheckWithServer);
|
|
4218
|
+
const githubSkills = skills.filter(canCheckWithGitHub);
|
|
4219
|
+
let checkedCount = 0;
|
|
4220
|
+
let skippedCount = skills.length - serverSkills.length - githubSkills.length;
|
|
4221
|
+
const updates = [];
|
|
4222
|
+
const errors = [];
|
|
4223
|
+
debugLog(`[update] prepared ${serverSkills.length} server skill(s), ${githubSkills.length} github skill(s), ${skippedCount} skipped`);
|
|
4224
|
+
for (const skill of skills) {
|
|
4225
|
+
if (serverSkills.includes(skill)) {
|
|
4226
|
+
debugLog(`[update] server check ${skill.name}: sourceType=${skill.entry.sourceType} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4227
|
+
continue;
|
|
4228
|
+
}
|
|
4229
|
+
if (githubSkills.includes(skill)) {
|
|
4230
|
+
debugLog(`[update] github check ${skill.name}: path=${skill.entry.skillPath || "(missing)"} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4231
|
+
continue;
|
|
4232
|
+
}
|
|
4233
|
+
debugLog(`[update] skipped ${skill.name}: sourceType=${skill.entry.sourceType} path=${skill.entry.skillPath || "(missing)"} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4234
|
+
}
|
|
4235
|
+
if (serverSkills.length > 0) try {
|
|
4236
|
+
const serverResult = await checkServerUpdates(serverSkills, options.apiBaseUrl || getUpdateCheckApiBase());
|
|
4237
|
+
checkedCount += serverResult.checkedCount;
|
|
4238
|
+
skippedCount += serverResult.skippedCount;
|
|
4239
|
+
updates.push(...serverResult.updates);
|
|
4240
|
+
errors.push(...serverResult.errors);
|
|
4241
|
+
} catch (err) {
|
|
4242
|
+
debugLog(`[update] server update check failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
4243
|
+
}
|
|
4244
|
+
if (githubSkills.length > 0) {
|
|
4245
|
+
const githubResult = await checkGitHubUpdates(githubSkills, options.githubToken);
|
|
4246
|
+
checkedCount += githubResult.checkedCount;
|
|
4247
|
+
skippedCount += githubResult.skippedCount;
|
|
4248
|
+
updates.push(...githubResult.updates);
|
|
4249
|
+
errors.push(...githubResult.errors);
|
|
4250
|
+
}
|
|
4251
|
+
return {
|
|
4252
|
+
checkedCount,
|
|
4253
|
+
skippedCount,
|
|
4254
|
+
updates,
|
|
4255
|
+
errors
|
|
4256
|
+
};
|
|
4257
|
+
}
|
|
4109
4258
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
4110
4259
|
function getVersion() {
|
|
4111
4260
|
try {
|
|
@@ -4122,12 +4271,12 @@ const BOLD = "\x1B[1m";
|
|
|
4122
4271
|
const DIM = "\x1B[38;5;102m";
|
|
4123
4272
|
const TEXT = "\x1B[38;5;145m";
|
|
4124
4273
|
const LOGO_LINES = [
|
|
4125
|
-
"███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
4126
|
-
"██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
4127
|
-
"
|
|
4128
|
-
"
|
|
4129
|
-
"███████║██║ ██╗██║███████╗███████╗███████║",
|
|
4130
|
-
"╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
4274
|
+
"██████╗ ██╗ ██████╗ ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
4275
|
+
"██╔══██╗ ██║ ██╔══██╗ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
4276
|
+
"██████╔╝ ██║ ██████╔╝█████╗███████╗█████╔╝ ██║██║ ██║ ███████╗",
|
|
4277
|
+
"██╔══██╗ ██║ ██╔═══╝ ╚════╝╚════██║██╔═██╗ ██║██║ ██║ ╚════██║",
|
|
4278
|
+
"██████╔╝ ██║ ██║ ███████║██║ ██╗██║███████╗███████╗███████║",
|
|
4279
|
+
"╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
4131
4280
|
];
|
|
4132
4281
|
const GRAYS = [
|
|
4133
4282
|
"\x1B[38;5;250m",
|
|
@@ -4146,6 +4295,8 @@ function showLogo() {
|
|
|
4146
4295
|
function showBanner() {
|
|
4147
4296
|
showLogo();
|
|
4148
4297
|
console.log();
|
|
4298
|
+
console.log(`${BOLD}${TEXT}BIP-SKILLS${RESET}`);
|
|
4299
|
+
console.log();
|
|
4149
4300
|
console.log(`${DIM}The open agent skills ecosystem${RESET}`);
|
|
4150
4301
|
console.log();
|
|
4151
4302
|
console.log(` ${DIM}$${RESET} ${TEXT}${CLI_NPX_COMMAND} add ${DIM}<package>${RESET} ${DIM}Add a new skill${RESET}`);
|
|
@@ -4343,82 +4494,69 @@ function readSkillLock() {
|
|
|
4343
4494
|
};
|
|
4344
4495
|
}
|
|
4345
4496
|
}
|
|
4497
|
+
function getLockedSkillsForUpdate(lock) {
|
|
4498
|
+
return Object.entries(lock.skills).map(([name, entry]) => ({
|
|
4499
|
+
name,
|
|
4500
|
+
entry
|
|
4501
|
+
}));
|
|
4502
|
+
}
|
|
4503
|
+
function buildWellKnownUpdateUrl(name, entry) {
|
|
4504
|
+
try {
|
|
4505
|
+
if (entry.sourceUrl.startsWith("http://") || entry.sourceUrl.startsWith("https://")) {
|
|
4506
|
+
const parsed = new URL(entry.sourceUrl);
|
|
4507
|
+
const markerIndex = parsed.pathname.indexOf("/.well-known/skills");
|
|
4508
|
+
const basePath = markerIndex >= 0 ? parsed.pathname.slice(0, markerIndex) : "";
|
|
4509
|
+
return `${parsed.origin}${basePath}@${name}`;
|
|
4510
|
+
}
|
|
4511
|
+
} catch {}
|
|
4512
|
+
if (entry.source.startsWith("http://") || entry.source.startsWith("https://")) return `${entry.source.replace(/\/$/, "")}@${name}`;
|
|
4513
|
+
if (entry.source.includes(".")) return `https://${entry.source.replace(/\/$/, "")}@${name}`;
|
|
4514
|
+
return entry.sourceUrl;
|
|
4515
|
+
}
|
|
4516
|
+
function buildUpdateInstallUrl(name, entry) {
|
|
4517
|
+
if (entry.sourceType === "well-known") return buildWellKnownUpdateUrl(name, entry);
|
|
4518
|
+
if (entry.sourceType !== "github" || !entry.skillPath) return entry.sourceUrl;
|
|
4519
|
+
let skillFolder = entry.skillPath;
|
|
4520
|
+
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
4521
|
+
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
4522
|
+
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
4523
|
+
return `${entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "")}/tree/main/${skillFolder}`;
|
|
4524
|
+
}
|
|
4346
4525
|
async function runCheck(args = []) {
|
|
4347
4526
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4348
4527
|
console.log();
|
|
4349
4528
|
const lock = readSkillLock();
|
|
4350
|
-
|
|
4351
|
-
if (skillNames.length === 0) {
|
|
4529
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4352
4530
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4353
4531
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4354
4532
|
return;
|
|
4355
4533
|
}
|
|
4356
|
-
const
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
for (const skillName of skillNames) {
|
|
4360
|
-
const entry = lock.skills[skillName];
|
|
4361
|
-
if (!entry) continue;
|
|
4362
|
-
if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) {
|
|
4363
|
-
skippedCount++;
|
|
4364
|
-
continue;
|
|
4365
|
-
}
|
|
4366
|
-
const existing = skillsBySource.get(entry.source) || [];
|
|
4367
|
-
existing.push({
|
|
4368
|
-
name: skillName,
|
|
4369
|
-
entry
|
|
4370
|
-
});
|
|
4371
|
-
skillsBySource.set(entry.source, existing);
|
|
4372
|
-
}
|
|
4373
|
-
const totalSkills = skillNames.length - skippedCount;
|
|
4374
|
-
if (totalSkills === 0) {
|
|
4375
|
-
console.log(`${DIM}No GitHub skills to check.${RESET}`);
|
|
4534
|
+
const result = await checkSkillUpdates(getLockedSkillsForUpdate(lock), { githubToken: getGitHubToken() });
|
|
4535
|
+
if (result.checkedCount === 0) {
|
|
4536
|
+
console.log(`${DIM}No skills to check.${RESET}`);
|
|
4376
4537
|
return;
|
|
4377
4538
|
}
|
|
4378
|
-
console.log(`${DIM}Checking ${
|
|
4379
|
-
const updates = [];
|
|
4380
|
-
const errors = [];
|
|
4381
|
-
for (const [source, skills] of skillsBySource) for (const { name, entry } of skills) try {
|
|
4382
|
-
const latestHash = await fetchSkillFolderHash(source, entry.skillPath, token);
|
|
4383
|
-
if (!latestHash) {
|
|
4384
|
-
errors.push({
|
|
4385
|
-
name,
|
|
4386
|
-
source,
|
|
4387
|
-
error: "Could not fetch from GitHub"
|
|
4388
|
-
});
|
|
4389
|
-
continue;
|
|
4390
|
-
}
|
|
4391
|
-
if (latestHash !== entry.skillFolderHash) updates.push({
|
|
4392
|
-
name,
|
|
4393
|
-
source
|
|
4394
|
-
});
|
|
4395
|
-
} catch (err) {
|
|
4396
|
-
errors.push({
|
|
4397
|
-
name,
|
|
4398
|
-
source,
|
|
4399
|
-
error: err instanceof Error ? err.message : "Unknown error"
|
|
4400
|
-
});
|
|
4401
|
-
}
|
|
4539
|
+
console.log(`${DIM}Checking ${result.checkedCount} skill(s) for updates...${RESET}`);
|
|
4402
4540
|
console.log();
|
|
4403
|
-
if (updates.length === 0) console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4541
|
+
if (result.updates.length === 0) console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4404
4542
|
else {
|
|
4405
|
-
console.log(`${TEXT}${updates.length} update(s) available:${RESET}`);
|
|
4543
|
+
console.log(`${TEXT}${result.updates.length} update(s) available:${RESET}`);
|
|
4406
4544
|
console.log();
|
|
4407
|
-
for (const update of updates) {
|
|
4545
|
+
for (const update of result.updates) {
|
|
4408
4546
|
console.log(` ${TEXT}↑${RESET} ${update.name}`);
|
|
4409
4547
|
console.log(` ${DIM}source: ${update.source}${RESET}`);
|
|
4410
4548
|
}
|
|
4411
4549
|
console.log();
|
|
4412
4550
|
console.log(`${DIM}Run${RESET} ${TEXT}${CLI_NPX_COMMAND} update${RESET} ${DIM}to update all skills${RESET}`);
|
|
4413
4551
|
}
|
|
4414
|
-
if (errors.length > 0) {
|
|
4552
|
+
if (result.errors.length > 0) {
|
|
4415
4553
|
console.log();
|
|
4416
|
-
console.log(`${DIM}Could not check ${errors.length} skill(s) (may need reinstall)${RESET}`);
|
|
4554
|
+
console.log(`${DIM}Could not check ${result.errors.length} skill(s) (may need reinstall)${RESET}`);
|
|
4417
4555
|
}
|
|
4418
4556
|
track({
|
|
4419
4557
|
event: "check",
|
|
4420
|
-
skillCount: String(
|
|
4421
|
-
updatesAvailable: String(updates.length)
|
|
4558
|
+
skillCount: String(result.checkedCount),
|
|
4559
|
+
updatesAvailable: String(result.updates.length)
|
|
4422
4560
|
});
|
|
4423
4561
|
console.log();
|
|
4424
4562
|
}
|
|
@@ -4426,58 +4564,32 @@ async function runUpdate() {
|
|
|
4426
4564
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4427
4565
|
console.log();
|
|
4428
4566
|
const lock = readSkillLock();
|
|
4429
|
-
|
|
4430
|
-
if (skillNames.length === 0) {
|
|
4567
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4431
4568
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4432
4569
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4433
4570
|
return;
|
|
4434
4571
|
}
|
|
4435
|
-
const
|
|
4436
|
-
|
|
4437
|
-
let checkedCount = 0;
|
|
4438
|
-
for (const skillName of skillNames) {
|
|
4439
|
-
const entry = lock.skills[skillName];
|
|
4440
|
-
if (!entry) continue;
|
|
4441
|
-
if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) continue;
|
|
4442
|
-
checkedCount++;
|
|
4443
|
-
try {
|
|
4444
|
-
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
|
|
4445
|
-
if (latestHash && latestHash !== entry.skillFolderHash) updates.push({
|
|
4446
|
-
name: skillName,
|
|
4447
|
-
source: entry.source,
|
|
4448
|
-
entry
|
|
4449
|
-
});
|
|
4450
|
-
} catch {}
|
|
4451
|
-
}
|
|
4452
|
-
if (checkedCount === 0) {
|
|
4572
|
+
const result = await checkSkillUpdates(getLockedSkillsForUpdate(lock), { githubToken: getGitHubToken() });
|
|
4573
|
+
if (result.checkedCount === 0) {
|
|
4453
4574
|
console.log(`${DIM}No skills to check.${RESET}`);
|
|
4454
4575
|
return;
|
|
4455
4576
|
}
|
|
4456
|
-
if (updates.length === 0) {
|
|
4577
|
+
if (result.updates.length === 0) {
|
|
4457
4578
|
console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4458
4579
|
console.log();
|
|
4459
4580
|
return;
|
|
4460
4581
|
}
|
|
4461
|
-
console.log(`${TEXT}Found ${updates.length} update(s)${RESET}`);
|
|
4582
|
+
console.log(`${TEXT}Found ${result.updates.length} update(s)${RESET}`);
|
|
4462
4583
|
console.log();
|
|
4463
4584
|
let successCount = 0;
|
|
4464
4585
|
let failCount = 0;
|
|
4465
|
-
for (const update of updates) {
|
|
4586
|
+
for (const update of result.updates) {
|
|
4466
4587
|
console.log(`${TEXT}Updating ${update.name}...${RESET}`);
|
|
4467
|
-
let installUrl = update.entry.sourceUrl;
|
|
4468
|
-
if (update.entry.skillPath) {
|
|
4469
|
-
let skillFolder = update.entry.skillPath;
|
|
4470
|
-
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
4471
|
-
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
4472
|
-
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
4473
|
-
installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
|
|
4474
|
-
installUrl = `${installUrl}/tree/main/${skillFolder}`;
|
|
4475
|
-
}
|
|
4476
4588
|
if (spawnSync("npx", [
|
|
4477
4589
|
"-y",
|
|
4478
4590
|
CLI_PACKAGE_NAME,
|
|
4479
4591
|
"add",
|
|
4480
|
-
|
|
4592
|
+
buildUpdateInstallUrl(update.name, update.entry),
|
|
4481
4593
|
"-g",
|
|
4482
4594
|
"-y"
|
|
4483
4595
|
], { stdio: [
|
|
@@ -4497,7 +4609,7 @@ async function runUpdate() {
|
|
|
4497
4609
|
if (failCount > 0) console.log(`${DIM}Failed to update ${failCount} skill(s)${RESET}`);
|
|
4498
4610
|
track({
|
|
4499
4611
|
event: "update",
|
|
4500
|
-
skillCount: String(updates.length),
|
|
4612
|
+
skillCount: String(result.updates.length),
|
|
4501
4613
|
successCount: String(successCount),
|
|
4502
4614
|
failCount: String(failCount)
|
|
4503
4615
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bip-skills",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.10",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,20 +14,6 @@
|
|
|
14
14
|
"README.md",
|
|
15
15
|
"ThirdPartyNoticeText.txt"
|
|
16
16
|
],
|
|
17
|
-
"scripts": {
|
|
18
|
-
"build": "obuild && node scripts/generate-licenses.ts",
|
|
19
|
-
"generate-licenses": "node scripts/generate-licenses.ts",
|
|
20
|
-
"dev": "node src/cli.ts",
|
|
21
|
-
"exec:test": "node scripts/execute-tests.ts",
|
|
22
|
-
"pack:check": "npm pack --dry-run --ignore-scripts --cache .npm-cache",
|
|
23
|
-
"prepublishOnly": "npm run build",
|
|
24
|
-
"format": "prettier --write 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
25
|
-
"format:check": "prettier --check 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
26
|
-
"prepare": "husky",
|
|
27
|
-
"test": "vitest",
|
|
28
|
-
"type-check": "tsc --noEmit",
|
|
29
|
-
"publish:snapshot": "npm version prerelease --preid=snapshot --no-git-tag-version && npm publish --tag snapshot"
|
|
30
|
-
},
|
|
31
17
|
"lint-staged": {
|
|
32
18
|
"src/**/*.ts": "prettier --write",
|
|
33
19
|
"scripts/**/*.ts": "prettier --write",
|
|
@@ -88,7 +74,8 @@
|
|
|
88
74
|
"author": "",
|
|
89
75
|
"license": "MIT",
|
|
90
76
|
"publishConfig": {
|
|
91
|
-
"access": "public"
|
|
77
|
+
"access": "public",
|
|
78
|
+
"registry": "https://registry.npmjs.org/"
|
|
92
79
|
},
|
|
93
80
|
"devDependencies": {
|
|
94
81
|
"@clack/prompts": "^0.11.0",
|
|
@@ -108,5 +95,16 @@
|
|
|
108
95
|
"engines": {
|
|
109
96
|
"node": ">=18"
|
|
110
97
|
},
|
|
111
|
-
"
|
|
112
|
-
|
|
98
|
+
"scripts": {
|
|
99
|
+
"build": "obuild && node scripts/generate-licenses.ts",
|
|
100
|
+
"generate-licenses": "node scripts/generate-licenses.ts",
|
|
101
|
+
"dev": "node src/cli.ts",
|
|
102
|
+
"exec:test": "node scripts/execute-tests.ts",
|
|
103
|
+
"pack:check": "npm pack --dry-run --ignore-scripts --cache .npm-cache",
|
|
104
|
+
"format": "prettier --write 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
105
|
+
"format:check": "prettier --check 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
106
|
+
"test": "vitest",
|
|
107
|
+
"type-check": "tsc --noEmit",
|
|
108
|
+
"publish:snapshot": "npm version prerelease --preid=snapshot --no-git-tag-version && npm publish --tag snapshot"
|
|
109
|
+
}
|
|
110
|
+
}
|