bip-skills 1.4.7 → 1.4.9
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/README.md +5 -5
- package/dist/cli.mjs +161 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,20 +33,20 @@ npx bip-skills add yonyou/agent-skills
|
|
|
33
33
|
### Source Formats
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
# Default repo shorthand (owner/repo -> git.
|
|
36
|
+
# Default repo shorthand (owner/repo -> git.yyrd.com)
|
|
37
37
|
npx bip-skills add yonyou/agent-skills
|
|
38
38
|
|
|
39
39
|
# Full default Git URL
|
|
40
|
-
npx bip-skills add https://git.
|
|
40
|
+
npx bip-skills add https://git.yyrd.com/yonyou/agent-skills
|
|
41
41
|
|
|
42
42
|
# Direct path to a skill in a repo
|
|
43
|
-
npx bip-skills add https://git.
|
|
43
|
+
npx bip-skills add https://git.yyrd.com/yonyou/agent-skills/tree/main/skills/web-design-guidelines
|
|
44
44
|
|
|
45
45
|
# GitLab URL
|
|
46
46
|
npx bip-skills add https://gitlab.com/org/repo
|
|
47
47
|
|
|
48
48
|
# Any git URL
|
|
49
|
-
npx bip-skills add https://git.
|
|
49
|
+
npx bip-skills add https://git.yyrd.com/yonyou/agent-skills.git
|
|
50
50
|
|
|
51
51
|
# Local path
|
|
52
52
|
npx bip-skills add ./my-local-skills
|
|
@@ -485,7 +485,7 @@ The repository also includes [`.github/workflows/publish.yml`](.github/workflows
|
|
|
485
485
|
- [Replit Skills Documentation](https://docs.replit.com/replitai/skills)
|
|
486
486
|
- [Roo Code Skills Documentation](https://docs.roocode.com/features/skills)
|
|
487
487
|
- [Trae Skills Documentation](https://docs.trae.ai/ide/skills)
|
|
488
|
-
- [YonYou Agent Skills Repository](https://git.
|
|
488
|
+
- [YonYou Agent Skills Repository](https://git.yyrd.com/yonyou/agent-skills)
|
|
489
489
|
|
|
490
490
|
## License
|
|
491
491
|
|
package/dist/cli.mjs
CHANGED
|
@@ -17,7 +17,10 @@ import { createHash } from "crypto";
|
|
|
17
17
|
import { fileURLToPath } from "url";
|
|
18
18
|
import * as readline from "readline";
|
|
19
19
|
import { Writable } from "stream";
|
|
20
|
+
import { Buffer } from "node:buffer";
|
|
20
21
|
import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
|
|
22
|
+
import http from "node:http";
|
|
23
|
+
import https from "node:https";
|
|
21
24
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
22
25
|
const AGENTS_DIR$2 = ".agents";
|
|
23
26
|
const SKILLS_SUBDIR = "skills";
|
|
@@ -27,13 +30,17 @@ const CLI_NPX_COMMAND = `npx ${CLI_PACKAGE_NAME}`;
|
|
|
27
30
|
const DEFAULT_WELL_KNOWN_BASE_URL = "https://sun.yyuap.com";
|
|
28
31
|
const DEFAULT_DISCOVERY_SITE_URL = DEFAULT_WELL_KNOWN_BASE_URL;
|
|
29
32
|
const DEFAULT_SEARCH_API_BASE = DEFAULT_WELL_KNOWN_BASE_URL;
|
|
30
|
-
const DEFAULT_GIT_HOST = "git.
|
|
33
|
+
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.9";
|
|
1930
2074
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
1931
2075
|
async function isSourcePrivate(source) {
|
|
1932
2076
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2590,6 +2734,7 @@ async function runAdd(args, options = {}) {
|
|
|
2590
2734
|
fullDepth: options.fullDepth
|
|
2591
2735
|
});
|
|
2592
2736
|
if (skills.length === 0) {
|
|
2737
|
+
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
2738
|
spinner.stop(import_picocolors.default.red("No skills found"));
|
|
2594
2739
|
Se(import_picocolors.default.red("No valid skills found. Skills require a SKILL.md with name and description."));
|
|
2595
2740
|
await cleanup(tempDir);
|
|
@@ -3145,7 +3290,7 @@ async function searchSkillsAPI(query) {
|
|
|
3145
3290
|
try {
|
|
3146
3291
|
const url = `${SEARCH_API_BASE}/api/search?q=${encodeURIComponent(query)}&limit=10`;
|
|
3147
3292
|
debugLog(`[find] requesting search: ${url}`);
|
|
3148
|
-
const res = await
|
|
3293
|
+
const res = await fetchWithSelectiveTls(url);
|
|
3149
3294
|
debugLog(`[find] search response status: ${res.status} ${res.statusText}`);
|
|
3150
3295
|
const responseText = await res.text();
|
|
3151
3296
|
debugLog(`[find] search response body: ${responseText}`);
|