skilld 0.15.1 → 0.15.3
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 +77 -28
- package/dist/cli.mjs.map +1 -1
- package/dist/retriv/index.d.mts.map +1 -1
- package/dist/retriv/index.mjs +12 -3
- package/dist/retriv/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -776,15 +776,26 @@ function highlightTerms(content, terms) {
|
|
|
776
776
|
const pattern = new RegExp(`(${sorted.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})`, "gi");
|
|
777
777
|
return content.replace(pattern, "\x1B[33m$1\x1B[0m");
|
|
778
778
|
}
|
|
779
|
-
function
|
|
779
|
+
function scoreLabel(pct) {
|
|
780
|
+
return `${pct >= 70 ? "\x1B[32m" : pct >= 40 ? "\x1B[33m" : "\x1B[90m"}${pct}%\x1B[0m`;
|
|
781
|
+
}
|
|
782
|
+
function normalizeScores(results) {
|
|
783
|
+
const map = /* @__PURE__ */ new Map();
|
|
784
|
+
const max = results.reduce((m, r) => Math.max(m, r.score), 0);
|
|
785
|
+
for (const r of results) map.set(r, max > 0 ? Math.round(r.score / max * 100) : 0);
|
|
786
|
+
return map;
|
|
787
|
+
}
|
|
788
|
+
function formatSnippet(r, versions, pct) {
|
|
780
789
|
const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`;
|
|
781
790
|
const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`;
|
|
782
|
-
const score = `\x1B[90m${r.score.toFixed(2)}\x1B[0m`;
|
|
791
|
+
const score = pct != null ? scoreLabel(pct) : `\x1B[90m${r.score.toFixed(2)}\x1B[0m`;
|
|
792
|
+
const version = versions?.get(r.package);
|
|
793
|
+
const pkgLabel = version ? `${r.package}@${version}` : r.package;
|
|
783
794
|
const scopeStr = r.scope?.length ? `${r.scope.map((e) => e.name).join(".")} → ` : "";
|
|
784
795
|
const entityStr = r.entities?.map((e) => e.signature || `${e.type} ${e.name}`).join(", ");
|
|
785
796
|
const highlighted = highlightTerms(r.content, r.highlights);
|
|
786
797
|
return [
|
|
787
|
-
`${
|
|
798
|
+
`${pkgLabel} ${score}${entityStr ? ` \x1B[36m${scopeStr}${entityStr}\x1B[0m` : ""}`,
|
|
788
799
|
`\x1B[90m${refPath}:${lineRange}\x1B[0m`,
|
|
789
800
|
` ${highlighted.replace(/\n/g, "\n ")}`
|
|
790
801
|
].join("\n");
|
|
@@ -3428,35 +3439,56 @@ const removeCommandDef = defineCommand({
|
|
|
3428
3439
|
});
|
|
3429
3440
|
var search_exports = /* @__PURE__ */ __exportAll({
|
|
3430
3441
|
findPackageDbs: () => findPackageDbs,
|
|
3442
|
+
getPackageVersions: () => getPackageVersions,
|
|
3443
|
+
listLockPackages: () => listLockPackages,
|
|
3431
3444
|
parseFilterPrefix: () => parseFilterPrefix,
|
|
3432
3445
|
searchCommand: () => searchCommand,
|
|
3433
3446
|
searchCommandDef: () => searchCommandDef
|
|
3434
3447
|
});
|
|
3435
3448
|
function findPackageDbs(packageFilter) {
|
|
3436
|
-
const
|
|
3449
|
+
const lock = readProjectLock(process.cwd());
|
|
3450
|
+
if (!lock) return [];
|
|
3451
|
+
return filterLockDbs(lock, packageFilter);
|
|
3452
|
+
}
|
|
3453
|
+
function getPackageVersions(cwd = process.cwd()) {
|
|
3454
|
+
const lock = readProjectLock(cwd);
|
|
3455
|
+
const map = /* @__PURE__ */ new Map();
|
|
3456
|
+
if (!lock) return map;
|
|
3457
|
+
for (const s of Object.values(lock.skills)) if (s.packageName && s.version) map.set(s.packageName, s.version);
|
|
3458
|
+
return map;
|
|
3459
|
+
}
|
|
3460
|
+
function readProjectLock(cwd) {
|
|
3437
3461
|
const shared = getSharedSkillsDir(cwd);
|
|
3438
3462
|
if (shared) {
|
|
3439
3463
|
const lock = readLock(shared);
|
|
3440
|
-
if (lock) return
|
|
3464
|
+
if (lock) return lock;
|
|
3441
3465
|
}
|
|
3442
3466
|
const agent = detectTargetAgent();
|
|
3443
|
-
if (!agent) return
|
|
3444
|
-
|
|
3467
|
+
if (!agent) return null;
|
|
3468
|
+
return readLock(`${cwd}/${targets[agent].skillsDir}`);
|
|
3469
|
+
}
|
|
3470
|
+
function listLockPackages(cwd = process.cwd()) {
|
|
3471
|
+
const lock = readProjectLock(cwd);
|
|
3445
3472
|
if (!lock) return [];
|
|
3446
|
-
|
|
3473
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3474
|
+
for (const s of Object.values(lock.skills)) if (s.packageName && s.version) seen.set(s.packageName, s.version);
|
|
3475
|
+
return [...seen].map(([name, version]) => `${name}@${version}`);
|
|
3447
3476
|
}
|
|
3448
3477
|
function filterLockDbs(lock, packageFilter) {
|
|
3449
3478
|
if (!lock) return [];
|
|
3450
|
-
const
|
|
3479
|
+
const tokenize = (s) => s.toLowerCase().replace(/@/g, "").split(/[-_/]+/).filter(Boolean);
|
|
3451
3480
|
return Object.values(lock.skills).filter((info) => {
|
|
3452
3481
|
if (!info.packageName || !info.version) return false;
|
|
3453
3482
|
if (!packageFilter) return true;
|
|
3454
|
-
const
|
|
3455
|
-
|
|
3483
|
+
const filterTokens = tokenize(packageFilter);
|
|
3484
|
+
const nameTokens = tokenize(info.packageName);
|
|
3485
|
+
return filterTokens.every((ft) => nameTokens.some((nt) => nt.includes(ft) || ft.includes(nt)));
|
|
3456
3486
|
}).map((info) => {
|
|
3457
3487
|
const exact = getPackageDbPath(info.packageName, info.version);
|
|
3458
3488
|
if (existsSync(exact)) return exact;
|
|
3459
|
-
|
|
3489
|
+
const fallback = findAnyPackageDb(info.packageName);
|
|
3490
|
+
if (fallback) p.log.warn(`Using cached search index for ${info.packageName} (v${info.version} not indexed). Run \`skilld update ${info.packageName}\` to re-index.`);
|
|
3491
|
+
return fallback;
|
|
3460
3492
|
}).filter((db) => !!db);
|
|
3461
3493
|
}
|
|
3462
3494
|
function findAnyPackageDb(name) {
|
|
@@ -3499,23 +3531,36 @@ function parseFilterPrefix(rawQuery) {
|
|
|
3499
3531
|
}
|
|
3500
3532
|
async function searchCommand(rawQuery, packageFilter) {
|
|
3501
3533
|
const dbs = findPackageDbs(packageFilter);
|
|
3534
|
+
const versions = getPackageVersions();
|
|
3502
3535
|
if (dbs.length === 0) {
|
|
3503
|
-
if (packageFilter)
|
|
3504
|
-
|
|
3536
|
+
if (packageFilter) {
|
|
3537
|
+
const available = listLockPackages();
|
|
3538
|
+
if (available.length > 0) p.log.warn(`No docs indexed for "${packageFilter}". Available: ${available.join(", ")}`);
|
|
3539
|
+
else p.log.warn(`No docs indexed for "${packageFilter}". Run \`skilld add ${packageFilter}\` first.`);
|
|
3540
|
+
} else p.log.warn("No docs indexed yet. Run `skilld add <package>` first.");
|
|
3505
3541
|
return;
|
|
3506
3542
|
}
|
|
3507
3543
|
const { query, filter } = parseFilterPrefix(rawQuery);
|
|
3508
3544
|
const start = performance.now();
|
|
3509
|
-
const
|
|
3510
|
-
limit: filter ?
|
|
3545
|
+
const allResults = await Promise.all(dbs.map((dbPath) => searchSnippets(query, { dbPath }, {
|
|
3546
|
+
limit: filter ? 20 : 10,
|
|
3511
3547
|
filter
|
|
3512
|
-
})))
|
|
3548
|
+
})));
|
|
3549
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3550
|
+
const merged = allResults.flat().sort((a, b) => b.score - a.score).filter((r) => {
|
|
3551
|
+
const key = `${r.source}:${r.lineStart}-${r.lineEnd}`;
|
|
3552
|
+
if (seen.has(key)) return false;
|
|
3553
|
+
seen.add(key);
|
|
3554
|
+
return true;
|
|
3555
|
+
}).slice(0, 5);
|
|
3513
3556
|
const elapsed = ((performance.now() - start) / 1e3).toFixed(2);
|
|
3514
3557
|
if (merged.length === 0) {
|
|
3515
3558
|
p.log.warn(`No results for "${query}"`);
|
|
3516
3559
|
return;
|
|
3517
3560
|
}
|
|
3518
|
-
const
|
|
3561
|
+
for (const r of merged) r.content = sanitizeMarkdown(r.content);
|
|
3562
|
+
const scores = normalizeScores(merged);
|
|
3563
|
+
const output = merged.map((r) => formatSnippet(r, versions, scores.get(r))).join("\n\n");
|
|
3519
3564
|
const summary = `${merged.length} results (${elapsed}s)`;
|
|
3520
3565
|
if (!!detectCurrentAgent()) {
|
|
3521
3566
|
const sanitized = output.replace(/<\/search-results>/gi, "</search-results>");
|
|
@@ -3563,11 +3608,6 @@ function filterToSearchFilter(label) {
|
|
|
3563
3608
|
if (label === "releases") return { type: "release" };
|
|
3564
3609
|
return { type: { $in: ["doc", "docs"] } };
|
|
3565
3610
|
}
|
|
3566
|
-
function scoreColor(score) {
|
|
3567
|
-
if (score >= .7) return "\x1B[32m";
|
|
3568
|
-
if (score >= .4) return "\x1B[33m";
|
|
3569
|
-
return "\x1B[90m";
|
|
3570
|
-
}
|
|
3571
3611
|
const SPINNER_FRAMES = [
|
|
3572
3612
|
"◐",
|
|
3573
3613
|
"◓",
|
|
@@ -3576,8 +3616,13 @@ const SPINNER_FRAMES = [
|
|
|
3576
3616
|
];
|
|
3577
3617
|
async function interactiveSearch(packageFilter) {
|
|
3578
3618
|
const dbs = findPackageDbs(packageFilter);
|
|
3619
|
+
const versions = getPackageVersions();
|
|
3579
3620
|
if (dbs.length === 0) {
|
|
3580
|
-
|
|
3621
|
+
let msg;
|
|
3622
|
+
if (packageFilter) {
|
|
3623
|
+
const available = listLockPackages();
|
|
3624
|
+
msg = available.length > 0 ? `No docs indexed for "${packageFilter}". Available: ${available.join(", ")}` : `No docs indexed for "${packageFilter}". Run \`skilld add ${packageFilter}\` first.`;
|
|
3625
|
+
} else msg = "No docs indexed yet. Run `skilld add <package>` first.";
|
|
3581
3626
|
process.stderr.write(`\x1B[33m${msg}\x1B[0m\n`);
|
|
3582
3627
|
return;
|
|
3583
3628
|
}
|
|
@@ -3628,18 +3673,21 @@ async function interactiveSearch(packageFilter) {
|
|
|
3628
3673
|
} else {
|
|
3629
3674
|
lines.push("");
|
|
3630
3675
|
const shown = results.slice(0, maxResults);
|
|
3676
|
+
const scores = normalizeScores(results);
|
|
3631
3677
|
for (let i = 0; i < shown.length; i++) {
|
|
3632
3678
|
const r = shown[i];
|
|
3633
3679
|
const selected = i === selectedIndex;
|
|
3634
3680
|
const bullet = selected ? "\x1B[36m●\x1B[0m" : "\x1B[90m○\x1B[0m";
|
|
3635
|
-
const sc =
|
|
3681
|
+
const sc = scoreLabel(scores.get(r) ?? 0);
|
|
3636
3682
|
const { title, path, preview } = formatCompactSnippet(r, cols);
|
|
3637
3683
|
const highlighted = highlightTerms(preview, r.highlights);
|
|
3684
|
+
const ver = versions.get(r.package);
|
|
3685
|
+
const pkgLabel = ver ? `${r.package}@${ver}` : r.package;
|
|
3638
3686
|
if (selected) {
|
|
3639
|
-
lines.push(` ${bullet} \x1B[1m${
|
|
3687
|
+
lines.push(` ${bullet} \x1B[1m${pkgLabel}\x1B[0m ${sc} \x1B[36m${title}\x1B[0m`);
|
|
3640
3688
|
lines.push(` \x1B[90m${path}\x1B[0m`);
|
|
3641
3689
|
lines.push(` ${highlighted}`);
|
|
3642
|
-
} else lines.push(` ${bullet} \x1B[90m${
|
|
3690
|
+
} else lines.push(` ${bullet} \x1B[90m${pkgLabel}\x1B[0m ${sc} \x1B[90m${title}\x1B[0m`);
|
|
3643
3691
|
}
|
|
3644
3692
|
}
|
|
3645
3693
|
lines.push("");
|
|
@@ -3715,9 +3763,10 @@ async function interactiveSearch(packageFilter) {
|
|
|
3715
3763
|
const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`;
|
|
3716
3764
|
const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`;
|
|
3717
3765
|
const highlighted = highlightTerms(sanitizeMarkdown(r.content), r.highlights);
|
|
3766
|
+
const rVer = versions.get(r.package);
|
|
3718
3767
|
const out = [
|
|
3719
3768
|
"",
|
|
3720
|
-
` \x1B[1m${r.package}\x1B[0m ${
|
|
3769
|
+
` \x1B[1m${rVer ? `${r.package}@${rVer}` : r.package}\x1B[0m ${scoreLabel(normalizeScores(results).get(r) ?? 0)}`,
|
|
3721
3770
|
` \x1B[90m${refPath}:${lineRange}\x1B[0m`,
|
|
3722
3771
|
"",
|
|
3723
3772
|
` ${highlighted.replace(/\n/g, "\n ")}`,
|