bip-skills 1.4.9 → 1.4.11
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 +220 -100
- package/package.json +19 -21
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";
|
|
@@ -103,7 +103,12 @@ function isInternalSkillSourceUrl(sourceUrl) {
|
|
|
103
103
|
return hostname ? isInternalSkillSourceHost(hostname) : false;
|
|
104
104
|
}
|
|
105
105
|
function isLocalPath(input) {
|
|
106
|
-
return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
106
|
+
return isAbsolute(input) || input === "~" || input.startsWith("~/") || input.startsWith("~\\") || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
107
|
+
}
|
|
108
|
+
function expandLocalPath(input) {
|
|
109
|
+
if (input === "~") return homedir();
|
|
110
|
+
if (input.startsWith("~/") || input.startsWith("~\\")) return resolve(homedir(), input.slice(2));
|
|
111
|
+
return input;
|
|
107
112
|
}
|
|
108
113
|
const SOURCE_ALIASES = { "coinbase/agentWallet": "coinbase/agentic-wallet-skills" };
|
|
109
114
|
function buildDefaultGitUrl(repoPath) {
|
|
@@ -113,7 +118,7 @@ function parseSource(input) {
|
|
|
113
118
|
const alias = SOURCE_ALIASES[input];
|
|
114
119
|
if (alias) input = alias;
|
|
115
120
|
if (isLocalPath(input)) {
|
|
116
|
-
const resolvedPath = resolve(input);
|
|
121
|
+
const resolvedPath = resolve(expandLocalPath(input));
|
|
117
122
|
return {
|
|
118
123
|
type: "local",
|
|
119
124
|
url: resolvedPath,
|
|
@@ -2070,7 +2075,7 @@ function createEmptyLocalLock() {
|
|
|
2070
2075
|
skills: {}
|
|
2071
2076
|
};
|
|
2072
2077
|
}
|
|
2073
|
-
var version$1 = "1.4.
|
|
2078
|
+
var version$1 = "1.4.11";
|
|
2074
2079
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
2075
2080
|
async function isSourcePrivate(source) {
|
|
2076
2081
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2083,6 +2088,14 @@ function initTelemetry(version) {
|
|
|
2083
2088
|
function getWellKnownFileCount(skill) {
|
|
2084
2089
|
return skill.declaredFiles.length > 0 ? skill.declaredFiles.length : skill.files.size;
|
|
2085
2090
|
}
|
|
2091
|
+
function getWellKnownSkillHash(skill) {
|
|
2092
|
+
return skill.indexEntry.hash || skill.indexEntry.contentHash || skill.indexEntry.skillFolderHash || "";
|
|
2093
|
+
}
|
|
2094
|
+
function getWellKnownSkillPath(skill) {
|
|
2095
|
+
if (skill.indexEntry.entry) return skill.indexEntry.entry;
|
|
2096
|
+
if (skill.installTarget.type === "inline") return skill.installTarget.skillRoot ? posix.join(skill.installTarget.skillRoot, "SKILL.md") : "SKILL.md";
|
|
2097
|
+
return skill.installTarget.subpath ? posix.join(skill.installTarget.subpath, "SKILL.md") : "SKILL.md";
|
|
2098
|
+
}
|
|
2086
2099
|
function getWellKnownEmptyStateMessage(status, totalSkillCount, invalidSkillCount) {
|
|
2087
2100
|
switch (status) {
|
|
2088
2101
|
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.";
|
|
@@ -2304,8 +2317,11 @@ function reportInstallToSunIfNeeded(params) {
|
|
|
2304
2317
|
function isBareSkillNameSource(source) {
|
|
2305
2318
|
return /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/.test(source);
|
|
2306
2319
|
}
|
|
2320
|
+
function isFilesystemPathLike(source) {
|
|
2321
|
+
return isAbsolute(source) || source === "~" || source.startsWith("~/") || source.startsWith("~\\") || source.startsWith("./") || source.startsWith("../") || source === "." || source === ".." || /^[a-zA-Z]:[/\\]/.test(source);
|
|
2322
|
+
}
|
|
2307
2323
|
function shouldProbeDefaultWellKnownPath(source) {
|
|
2308
|
-
return source.includes("/") && !source.includes("@") && !source.startsWith("http://") && !source.startsWith("https://") && !source.startsWith("git@") && !source.startsWith("ssh://") && !
|
|
2324
|
+
return source.includes("/") && !source.includes("@") && !source.startsWith("http://") && !source.startsWith("https://") && !source.startsWith("git@") && !source.startsWith("ssh://") && !isFilesystemPathLike(source);
|
|
2309
2325
|
}
|
|
2310
2326
|
function buildFallbackGitSshUrl(source) {
|
|
2311
2327
|
return `git@${DEFAULT_GIT_FALLBACK_SSH_HOST}:${source.replace(/\.git$/, "")}.git`;
|
|
@@ -2590,7 +2606,8 @@ async function handleWellKnownSkills(source, url, options, spinner, allowFallbac
|
|
|
2590
2606
|
source: sourceIdentifier,
|
|
2591
2607
|
sourceType: "well-known",
|
|
2592
2608
|
sourceUrl: skill.sourceUrl,
|
|
2593
|
-
|
|
2609
|
+
skillPath: getWellKnownSkillPath(skill),
|
|
2610
|
+
skillFolderHash: getWellKnownSkillHash(skill)
|
|
2594
2611
|
});
|
|
2595
2612
|
} catch {}
|
|
2596
2613
|
}
|
|
@@ -4106,6 +4123,146 @@ function parseRemoveOptions(args) {
|
|
|
4106
4123
|
options
|
|
4107
4124
|
};
|
|
4108
4125
|
}
|
|
4126
|
+
function getUpdateCheckApiBase() {
|
|
4127
|
+
return process.env.SKILLS_API_URL || DEFAULT_SEARCH_API_BASE;
|
|
4128
|
+
}
|
|
4129
|
+
function canCheckWithServer(skill) {
|
|
4130
|
+
return skill.entry.sourceType !== "github";
|
|
4131
|
+
}
|
|
4132
|
+
function canCheckWithGitHub(skill) {
|
|
4133
|
+
return skill.entry.sourceType === "github" && Boolean(skill.entry.skillFolderHash) && Boolean(skill.entry.skillPath);
|
|
4134
|
+
}
|
|
4135
|
+
function buildUpdateCheckRequest(skills) {
|
|
4136
|
+
return {
|
|
4137
|
+
forceRefresh: true,
|
|
4138
|
+
skills: skills.map(({ name, entry }) => ({
|
|
4139
|
+
name,
|
|
4140
|
+
source: entry.source,
|
|
4141
|
+
sourceType: entry.sourceType,
|
|
4142
|
+
sourceUrl: entry.sourceUrl,
|
|
4143
|
+
skillPath: entry.skillPath,
|
|
4144
|
+
skillFolderHash: entry.skillFolderHash
|
|
4145
|
+
}))
|
|
4146
|
+
};
|
|
4147
|
+
}
|
|
4148
|
+
async function checkServerUpdates(skills, apiBaseUrl) {
|
|
4149
|
+
if (skills.length === 0) return {
|
|
4150
|
+
checkedCount: 0,
|
|
4151
|
+
skippedCount: 0,
|
|
4152
|
+
updates: [],
|
|
4153
|
+
errors: []
|
|
4154
|
+
};
|
|
4155
|
+
const byName = new Map(skills.map((skill) => [skill.name, skill]));
|
|
4156
|
+
const url = `${apiBaseUrl.replace(/\/$/, "")}/api/check-updates`;
|
|
4157
|
+
const request = buildUpdateCheckRequest(skills);
|
|
4158
|
+
debugLog(`[update] requesting update check: ${url}`);
|
|
4159
|
+
debugLog(`[update] update check request: ${JSON.stringify(request)}`);
|
|
4160
|
+
const response = await fetchWithSelectiveTls(url, {
|
|
4161
|
+
method: "POST",
|
|
4162
|
+
headers: {
|
|
4163
|
+
"Content-Type": "application/json",
|
|
4164
|
+
Accept: "application/json"
|
|
4165
|
+
},
|
|
4166
|
+
body: JSON.stringify(request)
|
|
4167
|
+
});
|
|
4168
|
+
debugLog(`[update] update check response status: ${response.status} ${response.statusText}`);
|
|
4169
|
+
if (!response.ok) throw new Error(`Update check failed with status ${response.status}`);
|
|
4170
|
+
const responseText = await response.text();
|
|
4171
|
+
debugLog(`[update] update check response body: ${responseText}`);
|
|
4172
|
+
const data = JSON.parse(responseText);
|
|
4173
|
+
return {
|
|
4174
|
+
checkedCount: data.checked ?? skills.length,
|
|
4175
|
+
skippedCount: data.skipped ?? 0,
|
|
4176
|
+
updates: (data.updates || []).flatMap((update) => {
|
|
4177
|
+
const skill = byName.get(update.name);
|
|
4178
|
+
if (!skill) return [];
|
|
4179
|
+
return [{
|
|
4180
|
+
name: update.name,
|
|
4181
|
+
source: update.source,
|
|
4182
|
+
entry: skill.entry,
|
|
4183
|
+
currentHash: update.currentHash,
|
|
4184
|
+
latestHash: update.latestHash
|
|
4185
|
+
}];
|
|
4186
|
+
}),
|
|
4187
|
+
errors: data.errors || []
|
|
4188
|
+
};
|
|
4189
|
+
}
|
|
4190
|
+
async function checkGitHubUpdates(skills, token) {
|
|
4191
|
+
const updates = [];
|
|
4192
|
+
const errors = [];
|
|
4193
|
+
for (const { name, entry } of skills) try {
|
|
4194
|
+
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
|
|
4195
|
+
if (!latestHash) {
|
|
4196
|
+
errors.push({
|
|
4197
|
+
name,
|
|
4198
|
+
source: entry.source,
|
|
4199
|
+
error: "Could not fetch from GitHub"
|
|
4200
|
+
});
|
|
4201
|
+
continue;
|
|
4202
|
+
}
|
|
4203
|
+
if (latestHash !== entry.skillFolderHash) updates.push({
|
|
4204
|
+
name,
|
|
4205
|
+
source: entry.source,
|
|
4206
|
+
entry,
|
|
4207
|
+
currentHash: entry.skillFolderHash,
|
|
4208
|
+
latestHash
|
|
4209
|
+
});
|
|
4210
|
+
} catch (err) {
|
|
4211
|
+
errors.push({
|
|
4212
|
+
name,
|
|
4213
|
+
source: entry.source,
|
|
4214
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
4215
|
+
});
|
|
4216
|
+
}
|
|
4217
|
+
return {
|
|
4218
|
+
checkedCount: skills.length,
|
|
4219
|
+
skippedCount: 0,
|
|
4220
|
+
updates,
|
|
4221
|
+
errors
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4224
|
+
async function checkSkillUpdates(skills, options = {}) {
|
|
4225
|
+
const serverSkills = skills.filter(canCheckWithServer);
|
|
4226
|
+
const githubSkills = skills.filter(canCheckWithGitHub);
|
|
4227
|
+
let checkedCount = 0;
|
|
4228
|
+
let skippedCount = skills.length - serverSkills.length - githubSkills.length;
|
|
4229
|
+
const updates = [];
|
|
4230
|
+
const errors = [];
|
|
4231
|
+
debugLog(`[update] prepared ${serverSkills.length} server skill(s), ${githubSkills.length} github skill(s), ${skippedCount} skipped`);
|
|
4232
|
+
for (const skill of skills) {
|
|
4233
|
+
if (serverSkills.includes(skill)) {
|
|
4234
|
+
debugLog(`[update] server check ${skill.name}: sourceType=${skill.entry.sourceType} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4235
|
+
continue;
|
|
4236
|
+
}
|
|
4237
|
+
if (githubSkills.includes(skill)) {
|
|
4238
|
+
debugLog(`[update] github check ${skill.name}: path=${skill.entry.skillPath || "(missing)"} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4239
|
+
continue;
|
|
4240
|
+
}
|
|
4241
|
+
debugLog(`[update] skipped ${skill.name}: sourceType=${skill.entry.sourceType} path=${skill.entry.skillPath || "(missing)"} hash=${skill.entry.skillFolderHash || "(empty)"}`);
|
|
4242
|
+
}
|
|
4243
|
+
if (serverSkills.length > 0) try {
|
|
4244
|
+
const serverResult = await checkServerUpdates(serverSkills, options.apiBaseUrl || getUpdateCheckApiBase());
|
|
4245
|
+
checkedCount += serverResult.checkedCount;
|
|
4246
|
+
skippedCount += serverResult.skippedCount;
|
|
4247
|
+
updates.push(...serverResult.updates);
|
|
4248
|
+
errors.push(...serverResult.errors);
|
|
4249
|
+
} catch (err) {
|
|
4250
|
+
debugLog(`[update] server update check failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
4251
|
+
}
|
|
4252
|
+
if (githubSkills.length > 0) {
|
|
4253
|
+
const githubResult = await checkGitHubUpdates(githubSkills, options.githubToken);
|
|
4254
|
+
checkedCount += githubResult.checkedCount;
|
|
4255
|
+
skippedCount += githubResult.skippedCount;
|
|
4256
|
+
updates.push(...githubResult.updates);
|
|
4257
|
+
errors.push(...githubResult.errors);
|
|
4258
|
+
}
|
|
4259
|
+
return {
|
|
4260
|
+
checkedCount,
|
|
4261
|
+
skippedCount,
|
|
4262
|
+
updates,
|
|
4263
|
+
errors
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4109
4266
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
4110
4267
|
function getVersion() {
|
|
4111
4268
|
try {
|
|
@@ -4122,12 +4279,12 @@ const BOLD = "\x1B[1m";
|
|
|
4122
4279
|
const DIM = "\x1B[38;5;102m";
|
|
4123
4280
|
const TEXT = "\x1B[38;5;145m";
|
|
4124
4281
|
const LOGO_LINES = [
|
|
4125
|
-
"███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
4126
|
-
"██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
4127
|
-
"
|
|
4128
|
-
"
|
|
4129
|
-
"███████║██║ ██╗██║███████╗███████╗███████║",
|
|
4130
|
-
"╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
4282
|
+
"██████╗ ██╗ ██████╗ ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
4283
|
+
"██╔══██╗ ██║ ██╔══██╗ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
4284
|
+
"██████╔╝ ██║ ██████╔╝█████╗███████╗█████╔╝ ██║██║ ██║ ███████╗",
|
|
4285
|
+
"██╔══██╗ ██║ ██╔═══╝ ╚════╝╚════██║██╔═██╗ ██║██║ ██║ ╚════██║",
|
|
4286
|
+
"██████╔╝ ██║ ██║ ███████║██║ ██╗██║███████╗███████╗███████║",
|
|
4287
|
+
"╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
4131
4288
|
];
|
|
4132
4289
|
const GRAYS = [
|
|
4133
4290
|
"\x1B[38;5;250m",
|
|
@@ -4146,6 +4303,8 @@ function showLogo() {
|
|
|
4146
4303
|
function showBanner() {
|
|
4147
4304
|
showLogo();
|
|
4148
4305
|
console.log();
|
|
4306
|
+
console.log(`${BOLD}${TEXT}BIP-SKILLS${RESET}`);
|
|
4307
|
+
console.log();
|
|
4149
4308
|
console.log(`${DIM}The open agent skills ecosystem${RESET}`);
|
|
4150
4309
|
console.log();
|
|
4151
4310
|
console.log(` ${DIM}$${RESET} ${TEXT}${CLI_NPX_COMMAND} add ${DIM}<package>${RESET} ${DIM}Add a new skill${RESET}`);
|
|
@@ -4343,82 +4502,69 @@ function readSkillLock() {
|
|
|
4343
4502
|
};
|
|
4344
4503
|
}
|
|
4345
4504
|
}
|
|
4505
|
+
function getLockedSkillsForUpdate(lock) {
|
|
4506
|
+
return Object.entries(lock.skills).map(([name, entry]) => ({
|
|
4507
|
+
name,
|
|
4508
|
+
entry
|
|
4509
|
+
}));
|
|
4510
|
+
}
|
|
4511
|
+
function buildWellKnownUpdateUrl(name, entry) {
|
|
4512
|
+
try {
|
|
4513
|
+
if (entry.sourceUrl.startsWith("http://") || entry.sourceUrl.startsWith("https://")) {
|
|
4514
|
+
const parsed = new URL(entry.sourceUrl);
|
|
4515
|
+
const markerIndex = parsed.pathname.indexOf("/.well-known/skills");
|
|
4516
|
+
const basePath = markerIndex >= 0 ? parsed.pathname.slice(0, markerIndex) : "";
|
|
4517
|
+
return `${parsed.origin}${basePath}@${name}`;
|
|
4518
|
+
}
|
|
4519
|
+
} catch {}
|
|
4520
|
+
if (entry.source.startsWith("http://") || entry.source.startsWith("https://")) return `${entry.source.replace(/\/$/, "")}@${name}`;
|
|
4521
|
+
if (entry.source.includes(".")) return `https://${entry.source.replace(/\/$/, "")}@${name}`;
|
|
4522
|
+
return entry.sourceUrl;
|
|
4523
|
+
}
|
|
4524
|
+
function buildUpdateInstallUrl(name, entry) {
|
|
4525
|
+
if (entry.sourceType === "well-known") return buildWellKnownUpdateUrl(name, entry);
|
|
4526
|
+
if (entry.sourceType !== "github" || !entry.skillPath) return entry.sourceUrl;
|
|
4527
|
+
let skillFolder = entry.skillPath;
|
|
4528
|
+
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
4529
|
+
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
4530
|
+
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
4531
|
+
return `${entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "")}/tree/main/${skillFolder}`;
|
|
4532
|
+
}
|
|
4346
4533
|
async function runCheck(args = []) {
|
|
4347
4534
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4348
4535
|
console.log();
|
|
4349
4536
|
const lock = readSkillLock();
|
|
4350
|
-
|
|
4351
|
-
if (skillNames.length === 0) {
|
|
4537
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4352
4538
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4353
4539
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4354
4540
|
return;
|
|
4355
4541
|
}
|
|
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}`);
|
|
4542
|
+
const result = await checkSkillUpdates(getLockedSkillsForUpdate(lock), { githubToken: getGitHubToken() });
|
|
4543
|
+
if (result.checkedCount === 0) {
|
|
4544
|
+
console.log(`${DIM}No skills to check.${RESET}`);
|
|
4376
4545
|
return;
|
|
4377
4546
|
}
|
|
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
|
-
}
|
|
4547
|
+
console.log(`${DIM}Checking ${result.checkedCount} skill(s) for updates...${RESET}`);
|
|
4402
4548
|
console.log();
|
|
4403
|
-
if (updates.length === 0) console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4549
|
+
if (result.updates.length === 0) console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4404
4550
|
else {
|
|
4405
|
-
console.log(`${TEXT}${updates.length} update(s) available:${RESET}`);
|
|
4551
|
+
console.log(`${TEXT}${result.updates.length} update(s) available:${RESET}`);
|
|
4406
4552
|
console.log();
|
|
4407
|
-
for (const update of updates) {
|
|
4553
|
+
for (const update of result.updates) {
|
|
4408
4554
|
console.log(` ${TEXT}↑${RESET} ${update.name}`);
|
|
4409
4555
|
console.log(` ${DIM}source: ${update.source}${RESET}`);
|
|
4410
4556
|
}
|
|
4411
4557
|
console.log();
|
|
4412
4558
|
console.log(`${DIM}Run${RESET} ${TEXT}${CLI_NPX_COMMAND} update${RESET} ${DIM}to update all skills${RESET}`);
|
|
4413
4559
|
}
|
|
4414
|
-
if (errors.length > 0) {
|
|
4560
|
+
if (result.errors.length > 0) {
|
|
4415
4561
|
console.log();
|
|
4416
|
-
console.log(`${DIM}Could not check ${errors.length} skill(s) (may need reinstall)${RESET}`);
|
|
4562
|
+
console.log(`${DIM}Could not check ${result.errors.length} skill(s) (may need reinstall)${RESET}`);
|
|
4417
4563
|
}
|
|
4418
4564
|
track({
|
|
4419
4565
|
event: "check",
|
|
4420
|
-
skillCount: String(
|
|
4421
|
-
updatesAvailable: String(updates.length)
|
|
4566
|
+
skillCount: String(result.checkedCount),
|
|
4567
|
+
updatesAvailable: String(result.updates.length)
|
|
4422
4568
|
});
|
|
4423
4569
|
console.log();
|
|
4424
4570
|
}
|
|
@@ -4426,58 +4572,32 @@ async function runUpdate() {
|
|
|
4426
4572
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4427
4573
|
console.log();
|
|
4428
4574
|
const lock = readSkillLock();
|
|
4429
|
-
|
|
4430
|
-
if (skillNames.length === 0) {
|
|
4575
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4431
4576
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4432
4577
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4433
4578
|
return;
|
|
4434
4579
|
}
|
|
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) {
|
|
4580
|
+
const result = await checkSkillUpdates(getLockedSkillsForUpdate(lock), { githubToken: getGitHubToken() });
|
|
4581
|
+
if (result.checkedCount === 0) {
|
|
4453
4582
|
console.log(`${DIM}No skills to check.${RESET}`);
|
|
4454
4583
|
return;
|
|
4455
4584
|
}
|
|
4456
|
-
if (updates.length === 0) {
|
|
4585
|
+
if (result.updates.length === 0) {
|
|
4457
4586
|
console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4458
4587
|
console.log();
|
|
4459
4588
|
return;
|
|
4460
4589
|
}
|
|
4461
|
-
console.log(`${TEXT}Found ${updates.length} update(s)${RESET}`);
|
|
4590
|
+
console.log(`${TEXT}Found ${result.updates.length} update(s)${RESET}`);
|
|
4462
4591
|
console.log();
|
|
4463
4592
|
let successCount = 0;
|
|
4464
4593
|
let failCount = 0;
|
|
4465
|
-
for (const update of updates) {
|
|
4594
|
+
for (const update of result.updates) {
|
|
4466
4595
|
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
4596
|
if (spawnSync("npx", [
|
|
4477
4597
|
"-y",
|
|
4478
4598
|
CLI_PACKAGE_NAME,
|
|
4479
4599
|
"add",
|
|
4480
|
-
|
|
4600
|
+
buildUpdateInstallUrl(update.name, update.entry),
|
|
4481
4601
|
"-g",
|
|
4482
4602
|
"-y"
|
|
4483
4603
|
], { stdio: [
|
|
@@ -4497,7 +4617,7 @@ async function runUpdate() {
|
|
|
4497
4617
|
if (failCount > 0) console.log(`${DIM}Failed to update ${failCount} skill(s)${RESET}`);
|
|
4498
4618
|
track({
|
|
4499
4619
|
event: "update",
|
|
4500
|
-
skillCount: String(updates.length),
|
|
4620
|
+
skillCount: String(result.updates.length),
|
|
4501
4621
|
successCount: String(successCount),
|
|
4502
4622
|
failCount: String(failCount)
|
|
4503
4623
|
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bip-skills",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.11",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"bip-skills": "
|
|
8
|
-
"skills": "
|
|
9
|
-
"add-skill": "
|
|
7
|
+
"bip-skills": "bin/cli.mjs",
|
|
8
|
+
"skills": "bin/cli.mjs",
|
|
9
|
+
"add-skill": "bin/cli.mjs"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
@@ -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
|
+
}
|