bip-skills 1.4.8 → 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 +368 -111
- package/package.json +16 -18
package/dist/cli.mjs
CHANGED
|
@@ -9,15 +9,18 @@ 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";
|
|
19
|
+
import { Buffer } from "node:buffer";
|
|
20
20
|
import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
|
|
21
|
+
import http from "node:http";
|
|
22
|
+
import https from "node:https";
|
|
23
|
+
import { createHash } from "crypto";
|
|
21
24
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
22
25
|
const AGENTS_DIR$2 = ".agents";
|
|
23
26
|
const SKILLS_SUBDIR = "skills";
|
|
@@ -31,9 +34,13 @@ const DEFAULT_GIT_HOST = "git.yyrd.com";
|
|
|
31
34
|
const DEFAULT_GIT_BASE_URL = `https://${DEFAULT_GIT_HOST}`;
|
|
32
35
|
const DEFAULT_GIT_FALLBACK_SSH_HOST = "git.yyrd.com";
|
|
33
36
|
const DEFAULT_INSTALL_REPORT_URL = "https://sun.yyuap.com/api/install-report";
|
|
37
|
+
const TLS_RELAXED_HOSTS = ["sun.yyuap.com"];
|
|
34
38
|
function isYyuapHost(hostname) {
|
|
35
39
|
return hostname === "yyuap.com" || hostname.endsWith(".yyuap.com");
|
|
36
40
|
}
|
|
41
|
+
function shouldRelaxTlsForHost(hostname) {
|
|
42
|
+
return TLS_RELAXED_HOSTS.includes(hostname);
|
|
43
|
+
}
|
|
37
44
|
function isYyrdHost(hostname) {
|
|
38
45
|
return hostname === "yyrd.com" || hostname.endsWith(".yyrd.com");
|
|
39
46
|
}
|
|
@@ -515,13 +522,41 @@ async function hasSkillMd(dir) {
|
|
|
515
522
|
return false;
|
|
516
523
|
}
|
|
517
524
|
}
|
|
525
|
+
function getYamlHeuristicHint(content, frontmatterKeys) {
|
|
526
|
+
if (frontmatterKeys.length > 0 || !content.startsWith("---\n")) return null;
|
|
527
|
+
const closingMarkerIndex = content.indexOf("\n---", 4);
|
|
528
|
+
if (closingMarkerIndex === -1) return "frontmatter start marker was found, but the closing --- marker may be missing or malformed";
|
|
529
|
+
const suspiciousLine = content.slice(4, closingMarkerIndex).split(/\r?\n/).find((line) => /^[A-Za-z0-9_-]+:\s.+:\s/.test(line) && !/^[A-Za-z0-9_-]+:\s*["'|>]/.test(line));
|
|
530
|
+
if (suspiciousLine) return `frontmatter looks present but YAML may be invalid; this line contains an unquoted ": " inside a scalar value: ${JSON.stringify(suspiciousLine)}`;
|
|
531
|
+
return "frontmatter looks present but YAML parsing produced no keys; check for hidden characters, invalid YAML syntax, or unquoted \": \" inside values";
|
|
532
|
+
}
|
|
518
533
|
async function parseSkillMd(skillMdPath, options) {
|
|
519
534
|
try {
|
|
520
535
|
const content = await readFile(skillMdPath, "utf-8");
|
|
521
536
|
const { data } = (0, import_gray_matter.default)(content);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
537
|
+
const frontmatterKeys = Object.keys(data);
|
|
538
|
+
const frontmatterSummary = frontmatterKeys.length === 0 ? "(none)" : frontmatterKeys.map((key) => {
|
|
539
|
+
const value = data[key];
|
|
540
|
+
return `${key}:${Array.isArray(value) ? "array" : typeof value}`;
|
|
541
|
+
}).join(", ");
|
|
542
|
+
const leadingPreview = JSON.stringify(content.slice(0, 80));
|
|
543
|
+
const firstLine = JSON.stringify(content.split(/\r?\n/, 1)[0] ?? "");
|
|
544
|
+
const leadingCharCodes = Array.from(content.slice(0, 8)).map((char) => `U+${char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0")}`).join(", ");
|
|
545
|
+
const heuristicHint = getYamlHeuristicHint(content, frontmatterKeys);
|
|
546
|
+
if (!data.name || !data.description) {
|
|
547
|
+
debugLog(`[discover] skipped ${skillMdPath}: missing required frontmatter fields "name" and/or "description" (parsed keys: ${frontmatterSummary}, firstLine: ${firstLine}, leadingChars: ${leadingCharCodes}, leadingPreview: ${leadingPreview})`);
|
|
548
|
+
if (heuristicHint) debugLog(`[discover] hint ${skillMdPath}: ${heuristicHint}`);
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
if (typeof data.name !== "string" || typeof data.description !== "string") {
|
|
552
|
+
debugLog(`[discover] skipped ${skillMdPath}: frontmatter "name" and "description" must be strings (name=${typeof data.name}, description=${typeof data.description}, parsed keys: ${frontmatterSummary})`);
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
if (data.metadata?.internal === true && !shouldInstallInternalSkills() && !options?.includeInternal) {
|
|
556
|
+
debugLog(`[discover] skipped ${skillMdPath}: internal skill hidden (set INSTALL_INTERNAL_SKILLS=1 or request it explicitly)`);
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
debugLog(`[discover] accepted ${skillMdPath}: name="${data.name}" (parsed keys: ${frontmatterSummary})`);
|
|
525
560
|
return {
|
|
526
561
|
name: data.name,
|
|
527
562
|
description: data.description,
|
|
@@ -529,7 +564,8 @@ async function parseSkillMd(skillMdPath, options) {
|
|
|
529
564
|
rawContent: content,
|
|
530
565
|
metadata: data.metadata
|
|
531
566
|
};
|
|
532
|
-
} catch {
|
|
567
|
+
} catch (error) {
|
|
568
|
+
debugLog(`[discover] failed to read ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
533
569
|
return null;
|
|
534
570
|
}
|
|
535
571
|
}
|
|
@@ -548,6 +584,7 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
548
584
|
const skills = [];
|
|
549
585
|
const seenNames = /* @__PURE__ */ new Set();
|
|
550
586
|
const searchPath = subpath ? join(basePath, subpath) : basePath;
|
|
587
|
+
debugLog(`[discover] start basePath=${basePath} searchPath=${searchPath} includeInternal=${options?.includeInternal === true} fullDepth=${options?.fullDepth === true}`);
|
|
551
588
|
const pluginGroupings = await getPluginGroupings(searchPath);
|
|
552
589
|
const enhanceSkill = (skill) => {
|
|
553
590
|
const resolvedPath = resolve(skill.path);
|
|
@@ -555,6 +592,7 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
555
592
|
return skill;
|
|
556
593
|
};
|
|
557
594
|
if (await hasSkillMd(searchPath)) {
|
|
595
|
+
debugLog(`[discover] found root SKILL.md at ${join(searchPath, "SKILL.md")}`);
|
|
558
596
|
let skill = await parseSkillMd(join(searchPath, "SKILL.md"), options);
|
|
559
597
|
if (skill) {
|
|
560
598
|
skill = enhanceSkill(skill);
|
|
@@ -595,31 +633,38 @@ async function discoverSkills(basePath, subpath, options) {
|
|
|
595
633
|
join(searchPath, ".zencoder/skills")
|
|
596
634
|
];
|
|
597
635
|
prioritySearchDirs.push(...await getPluginSkillPaths(searchPath));
|
|
636
|
+
debugLog(`[discover] scanning priority directories (${prioritySearchDirs.length}): ${prioritySearchDirs.join(", ")}`);
|
|
598
637
|
for (const dir of prioritySearchDirs) try {
|
|
599
638
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
600
639
|
for (const entry of entries) if (entry.isDirectory()) {
|
|
601
640
|
const skillDir = join(dir, entry.name);
|
|
602
641
|
if (await hasSkillMd(skillDir)) {
|
|
642
|
+
debugLog(`[discover] candidate skill directory ${skillDir}`);
|
|
603
643
|
let skill = await parseSkillMd(join(skillDir, "SKILL.md"), options);
|
|
604
644
|
if (skill && !seenNames.has(skill.name)) {
|
|
605
645
|
skill = enhanceSkill(skill);
|
|
606
646
|
skills.push(skill);
|
|
607
647
|
seenNames.add(skill.name);
|
|
608
|
-
}
|
|
648
|
+
} else if (skill) debugLog(`[discover] skipped ${join(skillDir, "SKILL.md")}: duplicate skill name "${skill.name}"`);
|
|
609
649
|
}
|
|
610
650
|
}
|
|
611
|
-
} catch {
|
|
651
|
+
} catch (error) {
|
|
652
|
+
debugLog(`[discover] unable to scan ${dir}: ${error instanceof Error ? error.message : String(error)}`);
|
|
653
|
+
}
|
|
612
654
|
if (skills.length === 0 || options?.fullDepth) {
|
|
655
|
+
debugLog(`[discover] ${skills.length === 0 ? "no skills from priority scan" : "fullDepth enabled"}; starting recursive search from ${searchPath}`);
|
|
613
656
|
const allSkillDirs = await findSkillDirs(searchPath);
|
|
657
|
+
debugLog(`[discover] recursive candidates (${allSkillDirs.length}): ${allSkillDirs.join(", ") || "(none)"}`);
|
|
614
658
|
for (const skillDir of allSkillDirs) {
|
|
615
659
|
let skill = await parseSkillMd(join(skillDir, "SKILL.md"), options);
|
|
616
660
|
if (skill && !seenNames.has(skill.name)) {
|
|
617
661
|
skill = enhanceSkill(skill);
|
|
618
662
|
skills.push(skill);
|
|
619
663
|
seenNames.add(skill.name);
|
|
620
|
-
}
|
|
664
|
+
} else if (skill) debugLog(`[discover] skipped ${join(skillDir, "SKILL.md")}: duplicate skill name "${skill.name}"`);
|
|
621
665
|
}
|
|
622
666
|
}
|
|
667
|
+
debugLog(`[discover] completed searchPath=${searchPath}; found ${skills.length} skill${skills.length === 1 ? "" : "s"}`);
|
|
623
668
|
return skills;
|
|
624
669
|
}
|
|
625
670
|
function getSkillDisplayName(skill) {
|
|
@@ -1411,6 +1456,106 @@ async function listInstalledSkills(options = {}) {
|
|
|
1411
1456
|
} catch {}
|
|
1412
1457
|
return Array.from(skillsMap.values());
|
|
1413
1458
|
}
|
|
1459
|
+
function getRequestUrl(input) {
|
|
1460
|
+
if (input instanceof URL) return input;
|
|
1461
|
+
if (typeof input === "string") return new URL(input);
|
|
1462
|
+
return new URL(input.url);
|
|
1463
|
+
}
|
|
1464
|
+
function shouldUseRelaxedTls(input) {
|
|
1465
|
+
try {
|
|
1466
|
+
const url = getRequestUrl(input);
|
|
1467
|
+
return url.protocol === "https:" && shouldRelaxTlsForHost(url.hostname);
|
|
1468
|
+
} catch {
|
|
1469
|
+
return false;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
function normalizeRequestMethod(input, init) {
|
|
1473
|
+
if (init?.method) return init.method.toUpperCase();
|
|
1474
|
+
if (typeof Request !== "undefined" && input instanceof Request) return input.method.toUpperCase();
|
|
1475
|
+
return "GET";
|
|
1476
|
+
}
|
|
1477
|
+
function buildHeaders(input, init) {
|
|
1478
|
+
const headers = new Headers(typeof Request !== "undefined" && input instanceof Request ? input.headers : void 0);
|
|
1479
|
+
if (init?.headers) new Headers(init.headers).forEach((value, key) => {
|
|
1480
|
+
headers.set(key, value);
|
|
1481
|
+
});
|
|
1482
|
+
return headers;
|
|
1483
|
+
}
|
|
1484
|
+
async function readRequestBody(init) {
|
|
1485
|
+
const body = init?.body;
|
|
1486
|
+
if (body == null) return;
|
|
1487
|
+
if (typeof body === "string") return Buffer.from(body);
|
|
1488
|
+
if (body instanceof URLSearchParams) return Buffer.from(body.toString());
|
|
1489
|
+
if (body instanceof ArrayBuffer) return Buffer.from(body);
|
|
1490
|
+
if (ArrayBuffer.isView(body)) return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
|
|
1491
|
+
if (body instanceof Blob) return Buffer.from(await body.arrayBuffer());
|
|
1492
|
+
throw new TypeError("Unsupported request body for relaxed TLS fetch");
|
|
1493
|
+
}
|
|
1494
|
+
async function relaxedTlsFetch(input, init, redirectCount = 0) {
|
|
1495
|
+
if (redirectCount > 5) throw new Error("Too many redirects");
|
|
1496
|
+
const url = getRequestUrl(input);
|
|
1497
|
+
const method = normalizeRequestMethod(input, init);
|
|
1498
|
+
const headers = buildHeaders(input, init);
|
|
1499
|
+
const body = await readRequestBody(init);
|
|
1500
|
+
const transport = url.protocol === "https:" ? https : http;
|
|
1501
|
+
return await new Promise((resolve, reject) => {
|
|
1502
|
+
const request = transport.request(url, {
|
|
1503
|
+
method,
|
|
1504
|
+
headers: Object.fromEntries(headers.entries()),
|
|
1505
|
+
rejectUnauthorized: url.protocol === "https:" ? false : void 0
|
|
1506
|
+
}, (response) => {
|
|
1507
|
+
const status = response.statusCode ?? 500;
|
|
1508
|
+
const location = response.headers.location;
|
|
1509
|
+
if (location && [
|
|
1510
|
+
301,
|
|
1511
|
+
302,
|
|
1512
|
+
303,
|
|
1513
|
+
307,
|
|
1514
|
+
308
|
|
1515
|
+
].includes(status) && init?.redirect !== "manual") {
|
|
1516
|
+
response.resume();
|
|
1517
|
+
const nextUrl = new URL(location, url);
|
|
1518
|
+
const nextInit = {
|
|
1519
|
+
...init,
|
|
1520
|
+
method: status === 303 ? "GET" : method
|
|
1521
|
+
};
|
|
1522
|
+
delete nextInit.body;
|
|
1523
|
+
relaxedTlsFetch(nextUrl, nextInit, redirectCount + 1).then(resolve).catch(reject);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
const chunks = [];
|
|
1527
|
+
response.on("data", (chunk) => {
|
|
1528
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1529
|
+
});
|
|
1530
|
+
response.on("end", () => {
|
|
1531
|
+
const responseHeaders = Object.entries(response.headers).flatMap(([key, value]) => value == null ? [] : Array.isArray(value) ? value.map((item) => [key, item]) : [[key, value]]);
|
|
1532
|
+
resolve(new Response(method === "HEAD" ? null : Buffer.concat(chunks), {
|
|
1533
|
+
status,
|
|
1534
|
+
statusText: response.statusMessage ?? "",
|
|
1535
|
+
headers: new Headers(responseHeaders)
|
|
1536
|
+
}));
|
|
1537
|
+
});
|
|
1538
|
+
});
|
|
1539
|
+
request.on("error", reject);
|
|
1540
|
+
if (init?.signal) {
|
|
1541
|
+
const abort = () => {
|
|
1542
|
+
request.destroy(new DOMException("The operation was aborted.", "AbortError"));
|
|
1543
|
+
};
|
|
1544
|
+
if (init.signal.aborted) {
|
|
1545
|
+
abort();
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
init.signal.addEventListener("abort", abort, { once: true });
|
|
1549
|
+
request.on("close", () => init.signal?.removeEventListener("abort", abort));
|
|
1550
|
+
}
|
|
1551
|
+
if (body) request.write(body);
|
|
1552
|
+
request.end();
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
async function fetchWithSelectiveTls(input, init) {
|
|
1556
|
+
if (!shouldUseRelaxedTls(input)) return fetch(input, init);
|
|
1557
|
+
return relaxedTlsFetch(input, init);
|
|
1558
|
+
}
|
|
1414
1559
|
function getAllowedReportingUrl(envVarName) {
|
|
1415
1560
|
const value = process.env[envVarName];
|
|
1416
1561
|
if (!value) return null;
|
|
@@ -1439,7 +1584,7 @@ async function fetchAuditData(source, skillSlugs, timeoutMs = 3e3) {
|
|
|
1439
1584
|
});
|
|
1440
1585
|
const controller = new AbortController();
|
|
1441
1586
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
1442
|
-
const response = await
|
|
1587
|
+
const response = await fetchWithSelectiveTls(`${AUDIT_URL}?${params.toString()}`, { signal: controller.signal });
|
|
1443
1588
|
clearTimeout(timeout);
|
|
1444
1589
|
if (!response.ok) return null;
|
|
1445
1590
|
return await response.json();
|
|
@@ -1454,7 +1599,7 @@ function sendTelemetry(url, data) {
|
|
|
1454
1599
|
if (cliVersion) params.set("v", cliVersion);
|
|
1455
1600
|
if (isCI()) params.set("ci", "1");
|
|
1456
1601
|
for (const [key, value] of Object.entries(data)) if (value !== void 0 && value !== null) params.set(key, String(value));
|
|
1457
|
-
|
|
1602
|
+
fetchWithSelectiveTls(`${url}?${params.toString()}`).catch(() => {});
|
|
1458
1603
|
} catch {}
|
|
1459
1604
|
}
|
|
1460
1605
|
function track(data) {
|
|
@@ -1566,7 +1711,7 @@ var WellKnownProvider = class {
|
|
|
1566
1711
|
});
|
|
1567
1712
|
for (const { indexUrl, baseUrl: resolvedBase } of urlsToTry) try {
|
|
1568
1713
|
debugLog(`[well-known] requesting index: ${indexUrl}`);
|
|
1569
|
-
const response = await
|
|
1714
|
+
const response = await fetchWithSelectiveTls(indexUrl);
|
|
1570
1715
|
if (!response.ok) {
|
|
1571
1716
|
debugLog(`[well-known] index response status: ${response.status} ${response.statusText}`);
|
|
1572
1717
|
continue;
|
|
@@ -1650,7 +1795,7 @@ var WellKnownProvider = class {
|
|
|
1650
1795
|
indexEntry: entry,
|
|
1651
1796
|
installTarget
|
|
1652
1797
|
};
|
|
1653
|
-
const response = await
|
|
1798
|
+
const response = await fetchWithSelectiveTls(installTarget.skillMdUrl);
|
|
1654
1799
|
if (!response.ok) return null;
|
|
1655
1800
|
const content = await response.text();
|
|
1656
1801
|
const { data } = (0, import_gray_matter.default)(content);
|
|
@@ -1660,8 +1805,7 @@ var WellKnownProvider = class {
|
|
|
1660
1805
|
try {
|
|
1661
1806
|
const normalizedFilePath = filePath.replace(/^\/+/, "");
|
|
1662
1807
|
const fileRelativePath = installTarget.skillRoot ? posix.join(installTarget.skillRoot, normalizedFilePath) : normalizedFilePath;
|
|
1663
|
-
const
|
|
1664
|
-
const fileResponse = await fetch(fileUrl);
|
|
1808
|
+
const fileResponse = await fetchWithSelectiveTls(this.buildUrl(this.resolveInlineBaseUrl(installTarget.repositoryUrl) || baseUrl, fileRelativePath));
|
|
1665
1809
|
if (fileResponse.ok) return {
|
|
1666
1810
|
path: normalizedFilePath,
|
|
1667
1811
|
content: await fileResponse.text()
|
|
@@ -1926,7 +2070,7 @@ function createEmptyLocalLock() {
|
|
|
1926
2070
|
skills: {}
|
|
1927
2071
|
};
|
|
1928
2072
|
}
|
|
1929
|
-
var version$1 = "1.4.
|
|
2073
|
+
var version$1 = "1.4.10";
|
|
1930
2074
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
1931
2075
|
async function isSourcePrivate(source) {
|
|
1932
2076
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -1939,6 +2083,14 @@ function initTelemetry(version) {
|
|
|
1939
2083
|
function getWellKnownFileCount(skill) {
|
|
1940
2084
|
return skill.declaredFiles.length > 0 ? skill.declaredFiles.length : skill.files.size;
|
|
1941
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
|
+
}
|
|
1942
2094
|
function getWellKnownEmptyStateMessage(status, totalSkillCount, invalidSkillCount) {
|
|
1943
2095
|
switch (status) {
|
|
1944
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.";
|
|
@@ -2446,7 +2598,8 @@ async function handleWellKnownSkills(source, url, options, spinner, allowFallbac
|
|
|
2446
2598
|
source: sourceIdentifier,
|
|
2447
2599
|
sourceType: "well-known",
|
|
2448
2600
|
sourceUrl: skill.sourceUrl,
|
|
2449
|
-
|
|
2601
|
+
skillPath: getWellKnownSkillPath(skill),
|
|
2602
|
+
skillFolderHash: getWellKnownSkillHash(skill)
|
|
2450
2603
|
});
|
|
2451
2604
|
} catch {}
|
|
2452
2605
|
}
|
|
@@ -2590,6 +2743,7 @@ async function runAdd(args, options = {}) {
|
|
|
2590
2743
|
fullDepth: options.fullDepth
|
|
2591
2744
|
});
|
|
2592
2745
|
if (skills.length === 0) {
|
|
2746
|
+
debugLog(`[add] discoverSkills returned 0 skills for source=${parsed.type === "local" ? parsed.localPath : parsed.url} searchSubpath=${parsed.subpath ?? "(root)"} includeInternal=${includeInternal} fullDepth=${options.fullDepth === true}`);
|
|
2593
2747
|
spinner.stop(import_picocolors.default.red("No skills found"));
|
|
2594
2748
|
Se(import_picocolors.default.red("No valid skills found. Skills require a SKILL.md with name and description."));
|
|
2595
2749
|
await cleanup(tempDir);
|
|
@@ -3145,7 +3299,7 @@ async function searchSkillsAPI(query) {
|
|
|
3145
3299
|
try {
|
|
3146
3300
|
const url = `${SEARCH_API_BASE}/api/search?q=${encodeURIComponent(query)}&limit=10`;
|
|
3147
3301
|
debugLog(`[find] requesting search: ${url}`);
|
|
3148
|
-
const res = await
|
|
3302
|
+
const res = await fetchWithSelectiveTls(url);
|
|
3149
3303
|
debugLog(`[find] search response status: ${res.status} ${res.statusText}`);
|
|
3150
3304
|
const responseText = await res.text();
|
|
3151
3305
|
debugLog(`[find] search response body: ${responseText}`);
|
|
@@ -3961,6 +4115,146 @@ function parseRemoveOptions(args) {
|
|
|
3961
4115
|
options
|
|
3962
4116
|
};
|
|
3963
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
|
+
}
|
|
3964
4258
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
3965
4259
|
function getVersion() {
|
|
3966
4260
|
try {
|
|
@@ -3977,12 +4271,12 @@ const BOLD = "\x1B[1m";
|
|
|
3977
4271
|
const DIM = "\x1B[38;5;102m";
|
|
3978
4272
|
const TEXT = "\x1B[38;5;145m";
|
|
3979
4273
|
const LOGO_LINES = [
|
|
3980
|
-
"███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
3981
|
-
"██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
3982
|
-
"
|
|
3983
|
-
"
|
|
3984
|
-
"███████║██║ ██╗██║███████╗███████╗███████║",
|
|
3985
|
-
"╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
4274
|
+
"██████╗ ██╗ ██████╗ ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
4275
|
+
"██╔══██╗ ██║ ██╔══██╗ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
4276
|
+
"██████╔╝ ██║ ██████╔╝█████╗███████╗█████╔╝ ██║██║ ██║ ███████╗",
|
|
4277
|
+
"██╔══██╗ ██║ ██╔═══╝ ╚════╝╚════██║██╔═██╗ ██║██║ ██║ ╚════██║",
|
|
4278
|
+
"██████╔╝ ██║ ██║ ███████║██║ ██╗██║███████╗███████╗███████║",
|
|
4279
|
+
"╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝"
|
|
3986
4280
|
];
|
|
3987
4281
|
const GRAYS = [
|
|
3988
4282
|
"\x1B[38;5;250m",
|
|
@@ -4001,6 +4295,8 @@ function showLogo() {
|
|
|
4001
4295
|
function showBanner() {
|
|
4002
4296
|
showLogo();
|
|
4003
4297
|
console.log();
|
|
4298
|
+
console.log(`${BOLD}${TEXT}BIP-SKILLS${RESET}`);
|
|
4299
|
+
console.log();
|
|
4004
4300
|
console.log(`${DIM}The open agent skills ecosystem${RESET}`);
|
|
4005
4301
|
console.log();
|
|
4006
4302
|
console.log(` ${DIM}$${RESET} ${TEXT}${CLI_NPX_COMMAND} add ${DIM}<package>${RESET} ${DIM}Add a new skill${RESET}`);
|
|
@@ -4198,82 +4494,69 @@ function readSkillLock() {
|
|
|
4198
4494
|
};
|
|
4199
4495
|
}
|
|
4200
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
|
+
}
|
|
4201
4525
|
async function runCheck(args = []) {
|
|
4202
4526
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4203
4527
|
console.log();
|
|
4204
4528
|
const lock = readSkillLock();
|
|
4205
|
-
|
|
4206
|
-
if (skillNames.length === 0) {
|
|
4529
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4207
4530
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4208
4531
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4209
4532
|
return;
|
|
4210
4533
|
}
|
|
4211
|
-
const
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
for (const skillName of skillNames) {
|
|
4215
|
-
const entry = lock.skills[skillName];
|
|
4216
|
-
if (!entry) continue;
|
|
4217
|
-
if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) {
|
|
4218
|
-
skippedCount++;
|
|
4219
|
-
continue;
|
|
4220
|
-
}
|
|
4221
|
-
const existing = skillsBySource.get(entry.source) || [];
|
|
4222
|
-
existing.push({
|
|
4223
|
-
name: skillName,
|
|
4224
|
-
entry
|
|
4225
|
-
});
|
|
4226
|
-
skillsBySource.set(entry.source, existing);
|
|
4227
|
-
}
|
|
4228
|
-
const totalSkills = skillNames.length - skippedCount;
|
|
4229
|
-
if (totalSkills === 0) {
|
|
4230
|
-
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}`);
|
|
4231
4537
|
return;
|
|
4232
4538
|
}
|
|
4233
|
-
console.log(`${DIM}Checking ${
|
|
4234
|
-
const updates = [];
|
|
4235
|
-
const errors = [];
|
|
4236
|
-
for (const [source, skills] of skillsBySource) for (const { name, entry } of skills) try {
|
|
4237
|
-
const latestHash = await fetchSkillFolderHash(source, entry.skillPath, token);
|
|
4238
|
-
if (!latestHash) {
|
|
4239
|
-
errors.push({
|
|
4240
|
-
name,
|
|
4241
|
-
source,
|
|
4242
|
-
error: "Could not fetch from GitHub"
|
|
4243
|
-
});
|
|
4244
|
-
continue;
|
|
4245
|
-
}
|
|
4246
|
-
if (latestHash !== entry.skillFolderHash) updates.push({
|
|
4247
|
-
name,
|
|
4248
|
-
source
|
|
4249
|
-
});
|
|
4250
|
-
} catch (err) {
|
|
4251
|
-
errors.push({
|
|
4252
|
-
name,
|
|
4253
|
-
source,
|
|
4254
|
-
error: err instanceof Error ? err.message : "Unknown error"
|
|
4255
|
-
});
|
|
4256
|
-
}
|
|
4539
|
+
console.log(`${DIM}Checking ${result.checkedCount} skill(s) for updates...${RESET}`);
|
|
4257
4540
|
console.log();
|
|
4258
|
-
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}`);
|
|
4259
4542
|
else {
|
|
4260
|
-
console.log(`${TEXT}${updates.length} update(s) available:${RESET}`);
|
|
4543
|
+
console.log(`${TEXT}${result.updates.length} update(s) available:${RESET}`);
|
|
4261
4544
|
console.log();
|
|
4262
|
-
for (const update of updates) {
|
|
4545
|
+
for (const update of result.updates) {
|
|
4263
4546
|
console.log(` ${TEXT}↑${RESET} ${update.name}`);
|
|
4264
4547
|
console.log(` ${DIM}source: ${update.source}${RESET}`);
|
|
4265
4548
|
}
|
|
4266
4549
|
console.log();
|
|
4267
4550
|
console.log(`${DIM}Run${RESET} ${TEXT}${CLI_NPX_COMMAND} update${RESET} ${DIM}to update all skills${RESET}`);
|
|
4268
4551
|
}
|
|
4269
|
-
if (errors.length > 0) {
|
|
4552
|
+
if (result.errors.length > 0) {
|
|
4270
4553
|
console.log();
|
|
4271
|
-
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}`);
|
|
4272
4555
|
}
|
|
4273
4556
|
track({
|
|
4274
4557
|
event: "check",
|
|
4275
|
-
skillCount: String(
|
|
4276
|
-
updatesAvailable: String(updates.length)
|
|
4558
|
+
skillCount: String(result.checkedCount),
|
|
4559
|
+
updatesAvailable: String(result.updates.length)
|
|
4277
4560
|
});
|
|
4278
4561
|
console.log();
|
|
4279
4562
|
}
|
|
@@ -4281,58 +4564,32 @@ async function runUpdate() {
|
|
|
4281
4564
|
console.log(`${TEXT}Checking for skill updates...${RESET}`);
|
|
4282
4565
|
console.log();
|
|
4283
4566
|
const lock = readSkillLock();
|
|
4284
|
-
|
|
4285
|
-
if (skillNames.length === 0) {
|
|
4567
|
+
if (Object.keys(lock.skills).length === 0) {
|
|
4286
4568
|
console.log(`${DIM}No skills tracked in lock file.${RESET}`);
|
|
4287
4569
|
console.log(`${DIM}Install skills with${RESET} ${TEXT}${CLI_NPX_COMMAND} add <package>${RESET}`);
|
|
4288
4570
|
return;
|
|
4289
4571
|
}
|
|
4290
|
-
const
|
|
4291
|
-
|
|
4292
|
-
let checkedCount = 0;
|
|
4293
|
-
for (const skillName of skillNames) {
|
|
4294
|
-
const entry = lock.skills[skillName];
|
|
4295
|
-
if (!entry) continue;
|
|
4296
|
-
if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) continue;
|
|
4297
|
-
checkedCount++;
|
|
4298
|
-
try {
|
|
4299
|
-
const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
|
|
4300
|
-
if (latestHash && latestHash !== entry.skillFolderHash) updates.push({
|
|
4301
|
-
name: skillName,
|
|
4302
|
-
source: entry.source,
|
|
4303
|
-
entry
|
|
4304
|
-
});
|
|
4305
|
-
} catch {}
|
|
4306
|
-
}
|
|
4307
|
-
if (checkedCount === 0) {
|
|
4572
|
+
const result = await checkSkillUpdates(getLockedSkillsForUpdate(lock), { githubToken: getGitHubToken() });
|
|
4573
|
+
if (result.checkedCount === 0) {
|
|
4308
4574
|
console.log(`${DIM}No skills to check.${RESET}`);
|
|
4309
4575
|
return;
|
|
4310
4576
|
}
|
|
4311
|
-
if (updates.length === 0) {
|
|
4577
|
+
if (result.updates.length === 0) {
|
|
4312
4578
|
console.log(`${TEXT}✓ All skills are up to date${RESET}`);
|
|
4313
4579
|
console.log();
|
|
4314
4580
|
return;
|
|
4315
4581
|
}
|
|
4316
|
-
console.log(`${TEXT}Found ${updates.length} update(s)${RESET}`);
|
|
4582
|
+
console.log(`${TEXT}Found ${result.updates.length} update(s)${RESET}`);
|
|
4317
4583
|
console.log();
|
|
4318
4584
|
let successCount = 0;
|
|
4319
4585
|
let failCount = 0;
|
|
4320
|
-
for (const update of updates) {
|
|
4586
|
+
for (const update of result.updates) {
|
|
4321
4587
|
console.log(`${TEXT}Updating ${update.name}...${RESET}`);
|
|
4322
|
-
let installUrl = update.entry.sourceUrl;
|
|
4323
|
-
if (update.entry.skillPath) {
|
|
4324
|
-
let skillFolder = update.entry.skillPath;
|
|
4325
|
-
if (skillFolder.endsWith("/SKILL.md")) skillFolder = skillFolder.slice(0, -9);
|
|
4326
|
-
else if (skillFolder.endsWith("SKILL.md")) skillFolder = skillFolder.slice(0, -8);
|
|
4327
|
-
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
4328
|
-
installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
|
|
4329
|
-
installUrl = `${installUrl}/tree/main/${skillFolder}`;
|
|
4330
|
-
}
|
|
4331
4588
|
if (spawnSync("npx", [
|
|
4332
4589
|
"-y",
|
|
4333
4590
|
CLI_PACKAGE_NAME,
|
|
4334
4591
|
"add",
|
|
4335
|
-
|
|
4592
|
+
buildUpdateInstallUrl(update.name, update.entry),
|
|
4336
4593
|
"-g",
|
|
4337
4594
|
"-y"
|
|
4338
4595
|
], { stdio: [
|
|
@@ -4352,7 +4609,7 @@ async function runUpdate() {
|
|
|
4352
4609
|
if (failCount > 0) console.log(`${DIM}Failed to update ${failCount} skill(s)${RESET}`);
|
|
4353
4610
|
track({
|
|
4354
4611
|
event: "update",
|
|
4355
|
-
skillCount: String(updates.length),
|
|
4612
|
+
skillCount: String(result.updates.length),
|
|
4356
4613
|
successCount: String(successCount),
|
|
4357
4614
|
failCount: String(failCount)
|
|
4358
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
|
+
}
|