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.
Files changed (2) hide show
  1. package/dist/cli.mjs +220 -100
  2. 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, spawn, spawnSync } from "child_process";
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.9";
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://") && !source.startsWith("./") && !source.startsWith("../") && source !== "." && source !== "..";
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
- skillFolderHash: ""
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
- const skillNames = Object.keys(lock.skills);
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 token = getGitHubToken();
4357
- const skillsBySource = /* @__PURE__ */ new Map();
4358
- let skippedCount = 0;
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 ${totalSkills} skill(s) for updates...${RESET}`);
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(totalSkills),
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
- const skillNames = Object.keys(lock.skills);
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 token = getGitHubToken();
4436
- const updates = [];
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
- installUrl,
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.9",
3
+ "version": "1.4.11",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
7
- "bip-skills": "./bin/cli.mjs",
8
- "skills": "./bin/cli.mjs",
9
- "add-skill": "./bin/cli.mjs"
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
- "packageManager": "pnpm@10.17.1"
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
+ }